diff --git a/cranelift/frontend/src/frontend.rs b/cranelift/frontend/src/frontend.rs index 0961314559..29330a88df 100644 --- a/cranelift/frontend/src/frontend.rs +++ b/cranelift/frontend/src/frontend.rs @@ -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, types: SecondaryMap, } /// 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, } @@ -75,8 +75,9 @@ impl Position { } impl FunctionBuilderContext { - /// Creates a FunctionBuilderContext structure. The structure is automatically cleared after - /// each [`FunctionBuilder`](struct.FunctionBuilder.html) completes translating a function. + /// Creates a FunctionBuilderContext structure. The structure is + /// automatically cleared after each `FunctionBuilder` completes translating + /// a function. pub fn new() -> Self { Self { ssa: SSABuilder::new(), @@ -90,26 +91,22 @@ impl FunctionBuilderContext { self.ebbs.clear(); self.types.clear(); } - - fn is_empty(&self) -> bool { - self.ssa.is_empty() && self.ebbs.is_empty() && self.types.is_empty() - } } /// Implementation of the [`InstBuilder`](cranelift_codegen::ir::InstBuilder) 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 } @@ -203,12 +200,9 @@ 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::with_name_signature), 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 should be newly created with +/// [`Function::with_name_signature()`](Function::with_name_signature). /// /// # Errors /// @@ -216,15 +210,13 @@ impl<'short, 'long> InstBuilderBase<'short> for FuncInstBuilder<'short, 'long> { /// 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(), } } @@ -279,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); } @@ -290,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); } @@ -311,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 @@ -393,7 +385,7 @@ impl<'a> FunctionBuilder<'a> { /// Returns an object with the [`InstBuilder`](cranelift_codegen::ir::InstBuilder) /// 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 @@ -423,7 +415,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()) } @@ -459,10 +451,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 @@ -492,13 +495,8 @@ impl<'a> FunctionBuilder<'a> { } } - // 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(); + self.clear(); + std::mem::replace(&mut self.func, Function::new()) } } @@ -507,7 +505,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] { @@ -593,7 +591,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` @@ -853,7 +851,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 @@ -888,7 +886,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::*; @@ -903,10 +901,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(); @@ -981,8 +978,8 @@ mod tests { builder.seal_all_blocks(); } - builder.finalize(); - } + builder.finalize() + }; let flags = settings::Flags::new(settings::builder()); // println!("{}", func.display(None)); @@ -1019,10 +1016,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); @@ -1041,8 +1037,8 @@ mod tests { builder.ins().return_(&[size]); builder.seal_all_blocks(); - builder.finalize(); - } + builder.finalize() + }; assert_eq!( func.display(None).to_string(), @@ -1080,10 +1076,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); @@ -1100,8 +1095,8 @@ ebb0: builder.ins().return_(&[dest]); builder.seal_all_blocks(); - builder.finalize(); - } + builder.finalize() + }; assert_eq!( func.display(None).to_string(), @@ -1137,10 +1132,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); @@ -1157,8 +1151,8 @@ ebb0: builder.ins().return_(&[dest]); builder.seal_all_blocks(); - builder.finalize(); - } + builder.finalize() + }; assert_eq!( func.display(None).to_string(), @@ -1197,10 +1191,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); @@ -1214,8 +1207,8 @@ ebb0: builder.ins().return_(&[dest]); builder.seal_all_blocks(); - builder.finalize(); - } + builder.finalize() + }; assert_eq!( func.display(None).to_string(), @@ -1249,10 +1242,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); @@ -1266,8 +1258,8 @@ ebb0: builder.ins().return_(&[dest]); builder.seal_all_blocks(); - builder.finalize(); - } + builder.finalize() + }; assert_eq!( func.display(None).to_string(), diff --git a/cranelift/frontend/src/lib.rs b/cranelift/frontend/src/lib.rs index eff5c655fd..14cd7502dc 100644 --- a/cranelift/frontend/src/lib.rs +++ b/cranelift/frontend/src/lib.rs @@ -3,7 +3,7 @@ //! Provides a straightforward way to create a Cranelift IR function and fill it with instructions //! corresponding to your source program written in another language. //! -//! To get started, create an [`FunctionBuilderContext`](struct.FunctionBuilderContext.html) and +//! To get started, create an [`Function`](../cranelift_codegen/ir/function/struct.Function.html) and //! pass it as an argument to a [`FunctionBuilder`](struct.FunctionBuilder.html). //! //! # Mutable variables and Cranelift IR values @@ -61,7 +61,7 @@ //! } //! ``` //! -//! Here is how you build the corresponding Cranelift IR function using `FunctionBuilderContext`: +//! Here is how you build the corresponding Cranelift IR function using `Function`: //! //! ```rust //! extern crate cranelift_codegen; @@ -73,16 +73,15 @@ //! use cranelift_codegen::isa::CallConv; //! use cranelift_codegen::settings; //! use cranelift_codegen::verifier::verify_function; -//! use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable}; +//! use cranelift_frontend::{FunctionBuilder, Variable}; //! //! fn main() { //! let mut sig = Signature::new(CallConv::SystemV); //! sig.returns.push(AbiParam::new(I32)); //! sig.params.push(AbiParam::new(I32)); -//! let mut fn_builder_ctx = FunctionBuilderContext::new(); -//! let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig); -//! { -//! let mut builder = FunctionBuilder::new(&mut func, &mut fn_builder_ctx); +//! let func = { +//! let func = Function::with_name_signature(ExternalName::user(0, 0), sig); +//! let mut builder = FunctionBuilder::new(func); //! //! let block0 = builder.create_ebb(); //! let block1 = builder.create_ebb(); @@ -152,8 +151,8 @@ //! builder.ins().jump(block1, &[]); //! builder.seal_block(block1); //! -//! builder.finalize(); -//! } +//! builder.finalize() +//! }; //! //! let flags = settings::Flags::new(settings::builder()); //! let res = verify_function(&func, &flags); @@ -195,7 +194,7 @@ use hashmap_core::HashMap; #[cfg(feature = "std")] use std::collections::HashMap; -pub use crate::frontend::{FunctionBuilder, FunctionBuilderContext}; +pub use crate::frontend::FunctionBuilder; pub use crate::switch::Switch; pub use crate::variable::Variable; diff --git a/cranelift/frontend/src/ssa.rs b/cranelift/frontend/src/ssa.rs index aa735f7747..2bdd068515 100644 --- a/cranelift/frontend/src/ssa.rs +++ b/cranelift/frontend/src/ssa.rs @@ -173,9 +173,7 @@ impl SSABuilder { self.variables.clear(); self.blocks.clear(); self.ebb_headers.clear(); - debug_assert!(self.calls.is_empty()); - debug_assert!(self.results.is_empty()); - debug_assert!(self.side_effects.is_empty()); + debug_assert!(self.is_empty()); } /// Tests whether an `SSABuilder` is in a cleared state. diff --git a/cranelift/frontend/src/switch.rs b/cranelift/frontend/src/switch.rs index 0b1ca746cb..33b2001655 100644 --- a/cranelift/frontend/src/switch.rs +++ b/cranelift/frontend/src/switch.rs @@ -16,12 +16,11 @@ type EntryIndex = u64; /// # use cranelift_codegen::ir::types::*; /// # use cranelift_codegen::ir::{ExternalName, Function, Signature, InstBuilder}; /// # use cranelift_codegen::isa::CallConv; -/// # use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Switch}; +/// # use cranelift_frontend::{FunctionBuilder, Switch}; /// # /// # let mut sig = Signature::new(CallConv::SystemV); -/// # let mut fn_builder_ctx = FunctionBuilderContext::new(); /// # let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig); -/// # let mut builder = FunctionBuilder::new(&mut func, &mut fn_builder_ctx); +/// # let mut builder = FunctionBuilder::new(func); /// # /// # let entry = builder.create_ebb(); /// # builder.switch_to_block(entry); @@ -289,16 +288,13 @@ impl ContiguousCaseRange { #[cfg(test)] mod tests { use super::*; - use crate::frontend::FunctionBuilderContext; use cranelift_codegen::ir::Function; use std::string::ToString; macro_rules! setup { ($default:expr, [$($index:expr,)*]) => {{ - let mut func = Function::new(); - let mut func_ctx = FunctionBuilderContext::new(); - { - let mut bx = FunctionBuilder::new(&mut func, &mut func_ctx); + let func = { + let mut bx = FunctionBuilder::new(Function::new()); let ebb = bx.create_ebb(); bx.switch_to_block(ebb); let val = bx.ins().iconst(types::I8, 0); @@ -308,7 +304,9 @@ mod tests { switch.set_entry($index, ebb); )* switch.emit(&mut bx, val, Ebb::with_number($default).unwrap()); - } + bx.seal_all_blocks(); + bx.finalize() + }; func .to_string() .trim_start_matches("function u0:0() fast {\n") diff --git a/cranelift/frontend/src/variable.rs b/cranelift/frontend/src/variable.rs index dddcd7490b..1a061beb97 100644 --- a/cranelift/frontend/src/variable.rs +++ b/cranelift/frontend/src/variable.rs @@ -1,6 +1,6 @@ //! A basic `Variable` implementation. //! -//! `FunctionBuilderContext`, `FunctionBuilder`, and related types have a `Variable` +//! `FunctionBuilder` and related types have a `Variable` //! type parameter, to allow frontends that identify variables with //! their own index types to use them directly. Frontends which don't //! can use the `Variable` defined here. diff --git a/cranelift/simplejit/examples/simplejit-minimal.rs b/cranelift/simplejit/examples/simplejit-minimal.rs index 3b8e147830..2fc28367eb 100644 --- a/cranelift/simplejit/examples/simplejit-minimal.rs +++ b/cranelift/simplejit/examples/simplejit-minimal.rs @@ -7,7 +7,6 @@ fn main() { let mut module: Module = Module::new(SimpleJITBuilder::new(default_libcall_names())); let mut ctx = module.make_context(); - let mut func_ctx = FunctionBuilderContext::new(); let mut sig_a = module.make_signature(); sig_a.params.push(AbiParam::new(types::I32)); @@ -25,8 +24,8 @@ fn main() { ctx.func.signature = sig_a; ctx.func.name = ExternalName::user(0, func_a.as_u32()); - { - let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); + ctx.func = { + let mut bcx: FunctionBuilder = FunctionBuilder::new(ctx.func); let ebb = bcx.create_ebb(); bcx.switch_to_block(ebb); @@ -36,15 +35,15 @@ fn main() { let add = bcx.ins().iadd(cst, param); bcx.ins().return_(&[add]); bcx.seal_all_blocks(); - bcx.finalize(); - } + bcx.finalize() + }; module.define_function(func_a, &mut ctx).unwrap(); module.clear_context(&mut ctx); ctx.func.signature = sig_b; ctx.func.name = ExternalName::user(0, func_b.as_u32()); - { - let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); + ctx.func = { + let mut bcx: FunctionBuilder = FunctionBuilder::new(ctx.func); let ebb = bcx.create_ebb(); bcx.switch_to_block(ebb); @@ -58,8 +57,8 @@ fn main() { }; bcx.ins().return_(&[value]); bcx.seal_all_blocks(); - bcx.finalize(); - } + bcx.finalize() + }; module.define_function(func_b, &mut ctx).unwrap(); module.clear_context(&mut ctx); diff --git a/cranelift/simplejit/tests/basic.rs b/cranelift/simplejit/tests/basic.rs index a3932b1d6a..ea3f9cb5fd 100644 --- a/cranelift/simplejit/tests/basic.rs +++ b/cranelift/simplejit/tests/basic.rs @@ -37,14 +37,16 @@ fn define_simple_function(module: &mut Module) -> FuncId { .unwrap(); let mut ctx = Context::new(); - ctx.func = Function::with_name_signature(ExternalName::user(0, func_id.as_u32()), sig); - let mut func_ctx = FunctionBuilderContext::new(); - { - let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); + + ctx.func = { + let func = Function::with_name_signature(ExternalName::user(0, func_id.as_u32()), sig); + let mut bcx: FunctionBuilder = FunctionBuilder::new(func); let ebb = bcx.create_ebb(); bcx.switch_to_block(ebb); bcx.ins().return_(&[]); - } + bcx.seal_all_blocks(); + bcx.finalize() + }; module.define_function(func_id, &mut ctx).unwrap(); @@ -85,11 +87,9 @@ fn switch_error() { call_conv: CallConv::SystemV, }; - let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig); - - let mut func_ctx = FunctionBuilderContext::new(); - { - let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut func, &mut func_ctx); + let func = { + let func = Function::with_name_signature(ExternalName::user(0, 0), sig); + let mut bcx: FunctionBuilder = FunctionBuilder::new(func); let start = bcx.create_ebb(); let bb0 = bcx.create_ebb(); let bb1 = bcx.create_ebb(); @@ -134,8 +134,8 @@ fn switch_error() { bcx.ins().return_(&[r]); bcx.seal_all_blocks(); - bcx.finalize(); - } + bcx.finalize() + }; let flags = settings::Flags::new(settings::builder()); match cranelift_codegen::verify_function(&func, &flags) { @@ -164,10 +164,9 @@ fn libcall_function() { .unwrap(); let mut ctx = Context::new(); - ctx.func = Function::with_name_signature(ExternalName::user(0, func_id.as_u32()), sig); - let mut func_ctx = FunctionBuilderContext::new(); - { - let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx); + ctx.func = { + let func = Function::with_name_signature(ExternalName::user(0, func_id.as_u32()), sig); + let mut bcx: FunctionBuilder = FunctionBuilder::new(func); let ebb = bcx.create_ebb(); bcx.switch_to_block(ebb); @@ -189,7 +188,11 @@ fn libcall_function() { bcx.call_memset(module.target_config(), buffer, zero, size); bcx.ins().return_(&[]); - } + + bcx.seal_all_blocks(); + + bcx.finalize() + }; module.define_function(func_id, &mut ctx).unwrap(); diff --git a/cranelift/umbrella/src/lib.rs b/cranelift/umbrella/src/lib.rs index f97ed443ce..acb0e972d8 100644 --- a/cranelift/umbrella/src/lib.rs +++ b/cranelift/umbrella/src/lib.rs @@ -43,7 +43,7 @@ pub mod prelude { pub use crate::codegen::isa; pub use crate::codegen::settings::{self, Configurable}; - pub use crate::frontend::{FunctionBuilder, FunctionBuilderContext, Variable}; + pub use crate::frontend::{FunctionBuilder, Variable}; } /// Version number of this crate. diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs index b87844bfd4..664d839023 100644 --- a/cranelift/wasm/src/code_translator.rs +++ b/cranelift/wasm/src/code_translator.rs @@ -81,7 +81,7 @@ pub fn translate_operator( * `get_global` and `set_global` are handled by the environment. ***********************************************************************************/ Operator::GetGlobal { global_index } => { - let val = match state.get_global(builder.func, *global_index, environ)? { + let val = match state.get_global(&mut builder.func, *global_index, environ)? { GlobalVariable::Const(val) => val, GlobalVariable::Memory { gv, offset, ty } => { let addr = builder.ins().global_value(environ.pointer_type(), gv); @@ -92,7 +92,7 @@ pub fn translate_operator( state.push1(val); } Operator::SetGlobal { global_index } => { - match state.get_global(builder.func, *global_index, environ)? { + match state.get_global(&mut builder.func, *global_index, environ)? { GlobalVariable::Const(_) => panic!("global #{} is a constant", *global_index), GlobalVariable::Memory { gv, offset, ty } => { let addr = builder.ins().global_value(environ.pointer_type(), gv); @@ -367,7 +367,8 @@ pub fn translate_operator( * argument referring to an index in the external functions table of the module. ************************************************************************************/ Operator::Call { function_index } => { - let (fref, num_args) = state.get_direct_func(builder.func, *function_index, environ)?; + let (fref, num_args) = + state.get_direct_func(&mut builder.func, *function_index, environ)?; let call = environ.translate_call( builder.cursor(), FuncIndex::from_u32(*function_index), @@ -388,8 +389,8 @@ pub fn translate_operator( Operator::CallIndirect { index, table_index } => { // `index` is the index of the function's signature and `table_index` is the index of // the table to search the function in. - let (sigref, num_args) = state.get_indirect_sig(builder.func, *index, environ)?; - let table = state.get_table(builder.func, *table_index, environ)?; + let (sigref, num_args) = state.get_indirect_sig(&mut builder.func, *index, environ)?; + let table = state.get_table(&mut builder.func, *table_index, environ)?; let callee = state.pop1(); let call = environ.translate_call_indirect( builder.cursor(), @@ -417,13 +418,13 @@ pub fn translate_operator( // The WebAssembly MVP only supports one linear memory, but we expect the reserved // argument to be a memory index. let heap_index = MemoryIndex::from_u32(*reserved); - let heap = state.get_heap(builder.func, *reserved, environ)?; + let heap = state.get_heap(&mut builder.func, *reserved, environ)?; let val = state.pop1(); state.push1(environ.translate_memory_grow(builder.cursor(), heap_index, heap, val)?) } Operator::MemorySize { reserved } => { let heap_index = MemoryIndex::from_u32(*reserved); - let heap = state.get_heap(builder.func, *reserved, environ)?; + let heap = state.get_heap(&mut builder.func, *reserved, environ)?; state.push1(environ.translate_memory_size(builder.cursor(), heap_index, heap)?); } /******************************* Load instructions *********************************** @@ -1231,7 +1232,7 @@ fn translate_load( ) -> WasmResult<()> { let addr32 = state.pop1(); // We don't yet support multiple linear memories. - let heap = state.get_heap(builder.func, 0, environ)?; + let heap = state.get_heap(&mut builder.func, 0, environ)?; let (base, offset) = get_heap_addr(heap, addr32, offset, environ.pointer_type(), builder); // Note that we don't set `is_aligned` here, even if the load instruction's // alignment immediate says it's aligned, because WebAssembly's immediate @@ -1256,7 +1257,7 @@ fn translate_store( let val_ty = builder.func.dfg.value_type(val); // We don't yet support multiple linear memories. - let heap = state.get_heap(builder.func, 0, environ)?; + let heap = state.get_heap(&mut builder.func, 0, environ)?; let (base, offset) = get_heap_addr(heap, addr32, offset, environ.pointer_type(), builder); // See the comments in `translate_load` about the flags. let flags = MemFlags::new(); diff --git a/cranelift/wasm/src/environ/dummy.rs b/cranelift/wasm/src/environ/dummy.rs index fcec4e648c..8199cadee6 100644 --- a/cranelift/wasm/src/environ/dummy.rs +++ b/cranelift/wasm/src/environ/dummy.rs @@ -533,8 +533,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { func.collect_debug_info(); } self.trans - .translate(body_bytes, body_offset, &mut func, &mut func_environ)?; - func + .translate(body_bytes, body_offset, func, &mut func_environ)? }; self.func_bytecode_sizes.push(body_bytes.len()); self.info.function_bodies.push(func); diff --git a/cranelift/wasm/src/func_translator.rs b/cranelift/wasm/src/func_translator.rs index b49cffd474..ed5c51e59f 100644 --- a/cranelift/wasm/src/func_translator.rs +++ b/cranelift/wasm/src/func_translator.rs @@ -12,7 +12,7 @@ use crate::wasm_unsupported; use cranelift_codegen::entity::EntityRef; use cranelift_codegen::ir::{self, Ebb, InstBuilder, ValueLabel}; use cranelift_codegen::timing; -use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable}; +use cranelift_frontend::{FunctionBuilder, Variable}; use log::info; use wasmparser::{self, BinaryReader}; @@ -22,7 +22,7 @@ use wasmparser::{self, BinaryReader}; /// by a `FuncEnvironment` object. A single translator instance can be reused to translate multiple /// functions which will reduce heap allocation traffic. pub struct FuncTranslator { - func_ctx: FunctionBuilderContext, + builder: FunctionBuilder, state: TranslationState, } @@ -30,7 +30,7 @@ impl FuncTranslator { /// Create a new translator. pub fn new() -> Self { Self { - func_ctx: FunctionBuilderContext::new(), + builder: FunctionBuilder::new(ir::Function::new()), state: TranslationState::new(), } } @@ -57,9 +57,9 @@ impl FuncTranslator { &mut self, code: &[u8], code_offset: usize, - func: &mut ir::Function, + func: ir::Function, environ: &mut FE, - ) -> WasmResult<()> { + ) -> WasmResult { self.translate_from_reader( BinaryReader::new_with_offset(code, code_offset), func, @@ -71,9 +71,9 @@ impl FuncTranslator { pub fn translate_from_reader( &mut self, mut reader: BinaryReader, - func: &mut ir::Function, + func: ir::Function, environ: &mut FE, - ) -> WasmResult<()> { + ) -> WasmResult { let _tt = timing::wasm_translate_function(); info!( "translate({} bytes, {}{})", @@ -84,31 +84,32 @@ impl FuncTranslator { debug_assert_eq!(func.dfg.num_ebbs(), 0, "Function must be empty"); debug_assert_eq!(func.dfg.num_insts(), 0, "Function must be empty"); - // This clears the `FunctionBuilderContext`. - let mut builder = FunctionBuilder::new(func, &mut self.func_ctx); - builder.set_srcloc(cur_srcloc(&reader)); - let entry_block = builder.create_ebb(); - builder.append_ebb_params_for_function_params(entry_block); - builder.switch_to_block(entry_block); // This also creates values for the arguments. - builder.seal_block(entry_block); // Declare all predecessors known. + self.builder.func = func; + self.builder.set_srcloc(cur_srcloc(&reader)); + let entry_block = self.builder.create_ebb(); + self.builder + .append_ebb_params_for_function_params(entry_block); + self.builder.switch_to_block(entry_block); // This also creates values for the arguments. + self.builder.seal_block(entry_block); // Declare all predecessors known. // Make sure the entry block is inserted in the layout before we make any callbacks to // `environ`. The callback functions may need to insert things in the entry block. - builder.ensure_inserted_ebb(); + self.builder.ensure_inserted_ebb(); - let num_params = declare_wasm_parameters(&mut builder, entry_block); + let num_params = declare_wasm_parameters(&mut self.builder, entry_block); // Set up the translation state with a single pushed control block representing the whole // function and its return values. - let exit_block = builder.create_ebb(); - builder.append_ebb_params_for_function_returns(exit_block); - self.state.initialize(&builder.func.signature, exit_block); + let exit_block = self.builder.create_ebb(); + self.builder + .append_ebb_params_for_function_returns(exit_block); + self.state + .initialize(&self.builder.func.signature, exit_block); - parse_local_decls(&mut reader, &mut builder, num_params, environ)?; - parse_function_body(reader, &mut builder, &mut self.state, environ)?; + parse_local_decls(&mut reader, &mut self.builder, num_params, environ)?; + parse_function_body(reader, &mut self.builder, &mut self.state, environ)?; - builder.finalize(); - Ok(()) + Ok(self.builder.finalize()) } } @@ -288,8 +289,8 @@ mod tests { ctx.func.signature.params.push(ir::AbiParam::new(I32)); ctx.func.signature.returns.push(ir::AbiParam::new(I32)); - trans - .translate(&BODY, 0, &mut ctx.func, &mut runtime.func_env()) + ctx.func = trans + .translate(&BODY, 0, ctx.func, &mut runtime.func_env()) .unwrap(); debug!("{}", ctx.func.display(None)); ctx.verify(&flags).unwrap(); @@ -327,8 +328,8 @@ mod tests { ctx.func.signature.params.push(ir::AbiParam::new(I32)); ctx.func.signature.returns.push(ir::AbiParam::new(I32)); - trans - .translate(&BODY, 0, &mut ctx.func, &mut runtime.func_env()) + ctx.func = trans + .translate(&BODY, 0, ctx.func, &mut runtime.func_env()) .unwrap(); debug!("{}", ctx.func.display(None)); ctx.verify(&flags).unwrap(); @@ -374,8 +375,8 @@ mod tests { ctx.func.name = ir::ExternalName::testcase("infloop"); ctx.func.signature.returns.push(ir::AbiParam::new(I32)); - trans - .translate(&BODY, 0, &mut ctx.func, &mut runtime.func_env()) + ctx.func = trans + .translate(&BODY, 0, ctx.func, &mut runtime.func_env()) .unwrap(); debug!("{}", ctx.func.display(None)); ctx.verify(&flags).unwrap();