Skip to content

Commit

Permalink
Remove FunctionBuilderContext from API, and change FunctionBuilder API
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron Power committed Mar 21, 2019
1 parent 894cecc commit 0c98256
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 155 deletions.
146 changes: 71 additions & 75 deletions cranelift-frontend/src/frontend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,22 @@ use std::vec::Vec;
/// In order to reduce memory reallocations when compiling multiple functions,
/// `FunctionBuilderContext` holds various data structures which are cleared between
/// functions, rather than dropped, preserving the underlying allocations.
pub struct FunctionBuilderContext {
struct FunctionBuilderContext {
ssa: SSABuilder,
ebbs: SecondaryMap<Ebb, EbbData>,
types: SecondaryMap<Variable, Type>,
}

/// Temporary object used to build a single Cranelift IR `Function`.
pub struct FunctionBuilder<'a> {
pub struct FunctionBuilder {
/// The function currently being built.
/// This field is public so the function can be re-borrowed.
pub func: &'a mut Function,
pub func: Function,

/// Source location to assign to all new instructions.
srcloc: ir::SourceLoc,

func_ctx: &'a mut FunctionBuilderContext,
func_ctx: FunctionBuilderContext,
position: Position,
}

Expand Down Expand Up @@ -95,18 +95,18 @@ impl FunctionBuilderContext {

/// Implementation of the [`InstBuilder`](../codegen/ir/builder/trait.InstBuilder.html) that has
/// one convenience method per Cranelift IR instruction.
pub struct FuncInstBuilder<'short, 'long: 'short> {
builder: &'short mut FunctionBuilder<'long>,
pub struct FuncInstBuilder<'short> {
builder: &'short mut FunctionBuilder,
ebb: Ebb,
}

impl<'short, 'long> FuncInstBuilder<'short, 'long> {
fn new(builder: &'short mut FunctionBuilder<'long>, ebb: Ebb) -> Self {
impl<'short> FuncInstBuilder<'short> {
fn new(builder: &'short mut FunctionBuilder, ebb: Ebb) -> Self {
Self { builder, ebb }
}
}

impl<'short, 'long> InstBuilderBase<'short> for FuncInstBuilder<'short, 'long> {
impl<'short> InstBuilderBase<'short> for FuncInstBuilder<'short> {
fn data_flow_graph(&self) -> &DataFlowGraph {
&self.builder.func.dfg
}
Expand Down Expand Up @@ -200,28 +200,23 @@ impl<'short, 'long> InstBuilderBase<'short> for FuncInstBuilder<'short, 'long> {
/// The first block for which you call `switch_to_block` will be assumed to be the beginning of
/// the function.
///
/// At creation, a `FunctionBuilder` instance borrows an already allocated `Function` which it
/// modifies with the information stored in the mutable borrowed
/// [`FunctionBuilderContext`](struct.FunctionBuilderContext.html). The function passed in
/// argument should be newly created with
/// [`Function::with_name_signature()`](../function/struct.Function.html), whereas the
/// `FunctionBuilderContext` can be kept as is between two function translations.
/// At creation, a `FunctionBuilder` instance borrows an already allocated `Function`. The
/// function passed in argument should be newly created with
/// [`Function::with_name_signature()`](../function/struct.Function.html).
///
/// # Errors
///
/// The functions below will panic in debug mode whenever you try to modify the Cranelift IR
/// function in a way that violate the coherence of the code. For instance: switching to a new
/// `Ebb` when you haven't filled the current one with a terminator instruction, inserting a
/// return instruction with arguments that don't match the function's signature.
impl<'a> FunctionBuilder<'a> {
/// Creates a new FunctionBuilder structure that will operate on a `Function` using a
/// `FunctionBuilderContext`.
pub fn new(func: &'a mut Function, func_ctx: &'a mut FunctionBuilderContext) -> Self {
debug_assert!(func_ctx.is_empty());
impl FunctionBuilder {
/// Creates a new FunctionBuilder structure that will operate on a `Function`.
pub fn new(func: Function) -> Self {
Self {
func,
srcloc: Default::default(),
func_ctx,
func_ctx: FunctionBuilderContext::new(),
position: Position::default(),
}
}
Expand Down Expand Up @@ -276,7 +271,7 @@ impl<'a> FunctionBuilder<'a> {
/// created. Forgetting to call this method on every block will cause inconsistencies in the
/// produced functions.
pub fn seal_block(&mut self, ebb: Ebb) {
let side_effects = self.func_ctx.ssa.seal_ebb_header_block(ebb, self.func);
let side_effects = self.func_ctx.ssa.seal_ebb_header_block(ebb, &mut self.func);
self.handle_ssa_side_effects(side_effects);
}

Expand All @@ -287,7 +282,7 @@ impl<'a> FunctionBuilder<'a> {
/// function can be used at the end of translating all blocks to ensure
/// that everything is sealed.
pub fn seal_all_blocks(&mut self) {
let side_effects = self.func_ctx.ssa.seal_all_ebb_header_blocks(self.func);
let side_effects = self.func_ctx.ssa.seal_all_ebb_header_blocks(&mut self.func);
self.handle_ssa_side_effects(side_effects);
}

Expand All @@ -308,7 +303,7 @@ impl<'a> FunctionBuilder<'a> {
});
self.func_ctx
.ssa
.use_var(self.func, var, ty, self.position.basic_block.unwrap())
.use_var(&mut self.func, var, ty, self.position.basic_block.unwrap())
};
self.handle_ssa_side_effects(side_effects);
val
Expand Down Expand Up @@ -366,7 +361,7 @@ impl<'a> FunctionBuilder<'a> {

/// Returns an object with the [`InstBuilder`](../codegen/ir/builder/trait.InstBuilder.html)
/// trait that allows to conveniently append an instruction to the current `Ebb` being built.
pub fn ins<'short>(&'short mut self) -> FuncInstBuilder<'short, 'a> {
pub fn ins<'short>(&'short mut self) -> FuncInstBuilder<'short> {
let ebb = self
.position
.ebb
Expand Down Expand Up @@ -396,7 +391,7 @@ impl<'a> FunctionBuilder<'a> {
/// need to know about `FunctionBuilder` at all.
pub fn cursor(&mut self) -> FuncCursor {
self.ensure_inserted_ebb();
FuncCursor::new(self.func)
FuncCursor::new(&mut self.func)
.with_srcloc(self.srcloc)
.at_bottom(self.position.ebb.unwrap())
}
Expand Down Expand Up @@ -432,10 +427,21 @@ impl<'a> FunctionBuilder<'a> {
}
}

/// Declare that translation of the current function is complete. This
/// resets the state of the `FunctionBuilder` in preparation to be used
/// Clears the current state of the `FunctionBuilder` while preserving
/// allocations for reuse in translating another function.
pub fn clear(&mut self) {
// Clear the state (but preserve the allocated buffers) in preparation
// for translation another function.
self.func_ctx.clear();
// Reset srcloc and position to initial states.
self.srcloc = Default::default();
self.position = Position::default();
}

/// Declare that translation of the current function is complete, and return the completed
/// function. This resets the state of the `FunctionBuilder` in preparation to be used
/// for another function.
pub fn finalize(&mut self) {
pub fn finalize(&mut self) -> ir::Function {
// Check that all the `Ebb`s are filled and sealed.
debug_assert!(
self.func_ctx
Expand All @@ -452,13 +458,9 @@ impl<'a> FunctionBuilder<'a> {
"all blocks should be filled before dropping a FunctionBuilder"
);

// Clear the state (but preserve the allocated buffers) in preparation
// for translation another function.
self.func_ctx.clear();
self.clear();

// Reset srcloc and position to initial states.
self.srcloc = Default::default();
self.position = Position::default();
std::mem::replace(&mut self.func, Function::new())
}
}

Expand All @@ -467,7 +469,7 @@ impl<'a> FunctionBuilder<'a> {
/// performance of your translation perform more complex transformations to your Cranelift IR
/// function. The functions below help you inspect the function you're creating and modify it
/// in ways that can be unsafe if used incorrectly.
impl<'a> FunctionBuilder<'a> {
impl FunctionBuilder {
/// Retrieves all the parameters for an `Ebb` currently inferred from the jump instructions
/// inserted that target it and the SSA construction.
pub fn ebb_params(&self, ebb: Ebb) -> &[Value] {
Expand Down Expand Up @@ -553,7 +555,7 @@ impl<'a> FunctionBuilder<'a> {
}

/// Helper functions
impl<'a> FunctionBuilder<'a> {
impl FunctionBuilder {
/// Calls libc.memcpy
///
/// Copies the `size` bytes from `src` to `dest`, assumes that `src + size`
Expand Down Expand Up @@ -813,7 +815,7 @@ fn greatest_divisible_power_of_two(size: u64) -> u64 {
}

// Helper functions
impl<'a> FunctionBuilder<'a> {
impl FunctionBuilder {
fn move_to_next_basic_block(&mut self) {
self.position.basic_block = PackedOption::from(
self.func_ctx
Expand Down Expand Up @@ -847,7 +849,7 @@ impl<'a> FunctionBuilder<'a> {
#[cfg(test)]
mod tests {
use super::greatest_divisible_power_of_two;
use crate::frontend::{FunctionBuilder, FunctionBuilderContext};
use crate::frontend::FunctionBuilder;
use crate::Variable;
use cranelift_codegen::entity::EntityRef;
use cranelift_codegen::ir::types::*;
Expand All @@ -862,10 +864,9 @@ mod tests {
sig.returns.push(AbiParam::new(I32));
sig.params.push(AbiParam::new(I32));

let mut fn_ctx = FunctionBuilderContext::new();
let mut func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
{
let mut builder = FunctionBuilder::new(&mut func, &mut fn_ctx);
let func = {
let func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
let mut builder = FunctionBuilder::new(func);

let block0 = builder.create_ebb();
let block1 = builder.create_ebb();
Expand Down Expand Up @@ -940,8 +941,8 @@ mod tests {
builder.seal_all_blocks();
}

builder.finalize();
}
builder.finalize()
};

let flags = settings::Flags::new(settings::builder());
// println!("{}", func.display(None));
Expand Down Expand Up @@ -978,10 +979,9 @@ mod tests {
let mut sig = Signature::new(target.default_call_conv());
sig.returns.push(AbiParam::new(I32));

let mut fn_ctx = FunctionBuilderContext::new();
let mut func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
{
let mut builder = FunctionBuilder::new(&mut func, &mut fn_ctx);
let func = {
let func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
let mut builder = FunctionBuilder::new(func);

let block0 = builder.create_ebb();
let x = Variable::new(0);
Expand All @@ -1000,8 +1000,8 @@ mod tests {
builder.ins().return_(&[size]);

builder.seal_all_blocks();
builder.finalize();
}
builder.finalize()
};

assert_eq!(
func.display(None).to_string(),
Expand Down Expand Up @@ -1039,10 +1039,9 @@ ebb0:
let mut sig = Signature::new(target.default_call_conv());
sig.returns.push(AbiParam::new(I32));

let mut fn_ctx = FunctionBuilderContext::new();
let mut func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
{
let mut builder = FunctionBuilder::new(&mut func, &mut fn_ctx);
let func = {
let func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
let mut builder = FunctionBuilder::new(func);

let block0 = builder.create_ebb();
let x = Variable::new(0);
Expand All @@ -1059,8 +1058,8 @@ ebb0:
builder.ins().return_(&[dest]);

builder.seal_all_blocks();
builder.finalize();
}
builder.finalize()
};

assert_eq!(
func.display(None).to_string(),
Expand Down Expand Up @@ -1096,10 +1095,9 @@ ebb0:
let mut sig = Signature::new(target.default_call_conv());
sig.returns.push(AbiParam::new(I32));

let mut fn_ctx = FunctionBuilderContext::new();
let mut func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
{
let mut builder = FunctionBuilder::new(&mut func, &mut fn_ctx);
let func = {
let func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
let mut builder = FunctionBuilder::new(func);

let block0 = builder.create_ebb();
let x = Variable::new(0);
Expand All @@ -1116,8 +1114,8 @@ ebb0:
builder.ins().return_(&[dest]);

builder.seal_all_blocks();
builder.finalize();
}
builder.finalize()
};

assert_eq!(
func.display(None).to_string(),
Expand Down Expand Up @@ -1156,10 +1154,9 @@ ebb0:
let mut sig = Signature::new(target.default_call_conv());
sig.returns.push(AbiParam::new(I32));

let mut fn_ctx = FunctionBuilderContext::new();
let mut func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
{
let mut builder = FunctionBuilder::new(&mut func, &mut fn_ctx);
let func = {
let func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
let mut builder = FunctionBuilder::new(func);

let block0 = builder.create_ebb();
let y = Variable::new(16);
Expand All @@ -1173,8 +1170,8 @@ ebb0:
builder.ins().return_(&[dest]);

builder.seal_all_blocks();
builder.finalize();
}
builder.finalize()
};

assert_eq!(
func.display(None).to_string(),
Expand Down Expand Up @@ -1208,10 +1205,9 @@ ebb0:
let mut sig = Signature::new(target.default_call_conv());
sig.returns.push(AbiParam::new(I32));

let mut fn_ctx = FunctionBuilderContext::new();
let mut func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
{
let mut builder = FunctionBuilder::new(&mut func, &mut fn_ctx);
let func = {
let func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
let mut builder = FunctionBuilder::new(func);

let block0 = builder.create_ebb();
let y = Variable::new(16);
Expand All @@ -1225,8 +1221,8 @@ ebb0:
builder.ins().return_(&[dest]);

builder.seal_all_blocks();
builder.finalize();
}
builder.finalize()
};

assert_eq!(
func.display(None).to_string(),
Expand Down
Loading

0 comments on commit 0c98256

Please sign in to comment.