From d440776bc080cd31086ef4779af84b1b0e0081e2 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sat, 25 May 2019 18:06:41 -0500 Subject: [PATCH] Update lifetime of function builder references --- lib/clif-backend/src/code.rs | 97 ++++++++++++++++++--------------- lib/runtime-core/src/codegen.rs | 22 +++++++- lib/runtime-core/src/parse.rs | 5 +- lib/spectests/examples/test.rs | 31 ++++++++++- 4 files changed, 106 insertions(+), 49 deletions(-) diff --git a/lib/clif-backend/src/code.rs b/lib/clif-backend/src/code.rs index d574da43e02..6425415bc30 100644 --- a/lib/clif-backend/src/code.rs +++ b/lib/clif-backend/src/code.rs @@ -13,14 +13,18 @@ use crate::{ }; use cranelift_codegen::entity::EntityRef; +use cranelift_codegen::flowgraph::BasicBlock; use cranelift_codegen::ir::{self, Ebb, Function, InstBuilder, ValueLabel}; +use cranelift_codegen::packed_option::ReservedValue; use cranelift_codegen::timing; use cranelift_codegen::{cursor::FuncCursor, isa}; -use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable}; +use cranelift_entity::packed_option::PackedOption; +use cranelift_frontend::{Block, FunctionBuilder, FunctionBuilderContext, Position, Variable}; use cranelift_wasm::{self, translate_module, FuncTranslator, ModuleEnvironment}; use cranelift_wasm::{get_vmctx_value_label, translate_operator, TranslationState}; use cranelift_wasm::{FuncEnvironment, ReturnMode, WasmError, WasmResult}; use std::mem; +use std::rc::Rc; use std::sync::Arc; use wasmer_runtime_core::error::CompileError; use wasmer_runtime_core::{ @@ -82,12 +86,7 @@ impl ModuleCodeGenerator let mut func_translator = FuncTranslator::new(); - // let func_body = { - - // let mut func_env = FuncEnv::new(self); - - // TODO should func_index come from self.functions? - let func_index = self.func_bodies.next_index(); + let func_index = LocalFuncIndex::new(self.functions.len()); let name = ir::ExternalName::user(0, func_index.index() as u32); let sig = generate_signature( @@ -101,30 +100,25 @@ impl ModuleCodeGenerator let mut func = ir::Function::with_name_signature(name, sig); //func_translator.translate(body_bytes, body_offset, &mut func, &mut func_env)?; - // This clears the `FunctionBuilderContext`. let mut func_env = CraneliftFunctionCodeGenerator { - builder: None, + func, func_translator, next_local: 0, clif_signatures: self.clif_signatures.clone(), module_info: Arc::clone(&module_info), target_config: self.isa.frontend_config().clone(), + position: Position::default(), }; - // Coercing lifetime to accommodate FunctionBuilder new - let func_ref = - unsafe { ::std::mem::transmute::<&mut Function, &'static mut Function>(&mut func) }; - let func_ctx = unsafe { - ::std::mem::transmute::<&mut FunctionBuilderContext, &'static mut FunctionBuilderContext>( - &mut func_env.func_translator.func_ctx, - ) - }; - - let builder = FunctionBuilder::new(func_ref, func_ctx); - func_env.builder = Some(builder); + debug_assert_eq!(func_env.func.dfg.num_ebbs(), 0, "Function must be empty"); + debug_assert_eq!(func_env.func.dfg.num_insts(), 0, "Function must be empty"); - let mut builder = func_env.builder.as_mut().unwrap(); + let mut builder = FunctionBuilder::new( + &mut func_env.func, + &mut func_env.func_translator.func_ctx, + &mut func_env.position, + ); // TODO srcloc //builder.set_srcloc(cur_srcloc(&reader)); @@ -308,12 +302,6 @@ impl ModuleCodeGenerator pos.ins().jump(entry_ebb, new_ebb_params.as_slice()); } - // func - // }; - - // Add function body to list of function bodies. - self.func_bodies.push(func); - self.functions.push(func_env); Ok(self.functions.last_mut().unwrap()) } @@ -322,8 +310,13 @@ impl ModuleCodeGenerator self, module_info: &ModuleInfo, ) -> Result<(Caller, Box), CodegenError> { + let mut func_bodies: Map = Map::new(); + for f in self.functions.into_iter() { + func_bodies.push(f.func); + } + let (func_resolver_builder, handler_data) = - FuncResolverBuilder::new(&*self.isa, self.func_bodies, module_info)?; + FuncResolverBuilder::new(&*self.isa, func_bodies, module_info)?; let trampolines = Arc::new(Trampolines::new(&*self.isa, module_info)); @@ -378,12 +371,13 @@ impl From for CodegenError { } pub struct CraneliftFunctionCodeGenerator { - builder: Option>, + func: Function, func_translator: FuncTranslator, next_local: usize, pub clif_signatures: Map, module_info: Arc, target_config: isa::TargetFrontendConfig, + position: Position, } pub struct FunctionEnvironment { @@ -1088,12 +1082,9 @@ impl FunctionCodeGenerator for CraneliftFunctionCodeGenerator { } fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), CodegenError> { - cranelift_wasm::declare_locals( - self.builder.as_mut().unwrap(), - n as u32, - ty, - &mut self.next_local, - ); + let mut next_local = self.next_local; + cranelift_wasm::declare_locals(&mut self.builder(), n as u32, ty, &mut next_local); + self.next_local = next_local; Ok(()) } @@ -1108,7 +1099,8 @@ impl FunctionCodeGenerator for CraneliftFunctionCodeGenerator { return Ok(()); } }; - let builder = self.builder.as_mut().unwrap(); + + //let builder = self.builder.as_mut().unwrap(); //let func_environment = FuncEnv::new(); //let state = TranslationState::new(); let mut function_environment = FunctionEnvironment { @@ -1116,19 +1108,30 @@ impl FunctionCodeGenerator for CraneliftFunctionCodeGenerator { target_config: self.target_config.clone(), clif_signatures: self.clif_signatures.clone(), }; - translate_operator( - op, - builder, - &mut self.func_translator.state, - &mut function_environment, + + if (self.func_translator.state.control_stack.is_empty()) { + return Ok(()); + } + + let mut builder = FunctionBuilder::new( + &mut self.func, + &mut self.func_translator.func_ctx, + &mut self.position, ); + let state = &mut self.func_translator.state; + translate_operator(op, &mut builder, state, &mut function_environment); Ok(()) } fn finalize(&mut self) -> Result<(), CodegenError> { let return_mode = self.return_mode(); + + let mut builder = FunctionBuilder::new( + &mut self.func, + &mut self.func_translator.func_ctx, + &mut self.position, + ); let state = &mut self.func_translator.state; - let builder = self.builder.as_mut().unwrap(); // The final `End` operator left us in the exit block where we need to manually add a return // instruction. @@ -1149,7 +1152,7 @@ impl FunctionCodeGenerator for CraneliftFunctionCodeGenerator { // or the end of the function is unreachable. state.stack.clear(); - self.builder.as_mut().unwrap().finalize(); + self.builder().finalize(); Ok(()) } } @@ -1172,6 +1175,14 @@ impl CraneliftModuleCodeGenerator { } impl CraneliftFunctionCodeGenerator { + pub fn builder(&mut self) -> FunctionBuilder { + FunctionBuilder::new( + &mut self.func, + &mut self.func_translator.func_ctx, + &mut self.position, + ) + } + pub fn return_mode(&self) -> ReturnMode { ReturnMode::NormalReturns } diff --git a/lib/runtime-core/src/codegen.rs b/lib/runtime-core/src/codegen.rs index 266811422ff..5abfa70ca49 100644 --- a/lib/runtime-core/src/codegen.rs +++ b/lib/runtime-core/src/codegen.rs @@ -12,6 +12,7 @@ use std::fmt; use std::fmt::Debug; use std::marker::PhantomData; use std::sync::Arc; +use wasmparser::{self, WasmDecoder}; use wasmparser::{Operator, Type as WpType}; #[derive(Debug)] @@ -118,6 +119,20 @@ impl< } } +fn validate(bytes: &[u8]) -> CompileResult<()> { + let mut parser = wasmparser::ValidatingParser::new(bytes, None); + loop { + let state = parser.read(); + match *state { + wasmparser::ParserState::EndWasm => break Ok(()), + wasmparser::ParserState::Error(err) => Err(CompileError::ValidationError { + msg: err.message.to_string(), + })?, + _ => {} + } + } +} + impl< MCG: ModuleCodeGenerator, FCG: FunctionCodeGenerator, @@ -132,6 +147,11 @@ impl< compiler_config: CompilerConfig, _: Token, ) -> CompileResult { + let res = validate(wasm); + if let Err(e) = res { + return Err(e); + } + let mut mcg = MCG::new(); let mut chain = (self.middleware_chain_generator)(); let info = crate::parse::read_module( @@ -149,7 +169,7 @@ impl< Ok(ModuleInner { cache_gen, runnable_module: Box::new(exec_context), - info, + info: Arc::try_unwrap(info).unwrap(), }) } diff --git a/lib/runtime-core/src/parse.rs b/lib/runtime-core/src/parse.rs index 04b38bfcfa3..2ab4f33ae0b 100644 --- a/lib/runtime-core/src/parse.rs +++ b/lib/runtime-core/src/parse.rs @@ -53,7 +53,7 @@ pub fn read_module< mcg: &mut MCG, middlewares: &mut MiddlewareChain, compiler_config: &CompilerConfig, -) -> Result { +) -> Result, LoadError> { let mut info = Arc::new(ModuleInfo { memories: Map::new(), globals: Map::new(), @@ -104,7 +104,7 @@ pub fn read_module< use wasmparser::ParserState; let state = parser.read(); match *state { - ParserState::EndWasm => break Ok(Arc::try_unwrap(info).unwrap()), + ParserState::EndWasm => break, ParserState::Error(err) => Err(LoadError::Parse(err))?, ParserState::TypeSectionEntry(ref ty) => { Arc::get_mut(&mut info) @@ -385,6 +385,7 @@ pub fn read_module< _ => {} } } + Ok(info) } pub fn wp_type_to_type(ty: WpType) -> Result { diff --git a/lib/spectests/examples/test.rs b/lib/spectests/examples/test.rs index 6f725e99461..8ce199695fc 100644 --- a/lib/spectests/examples/test.rs +++ b/lib/spectests/examples/test.rs @@ -1,6 +1,6 @@ use wabt::wat2wasm; use wasmer_clif_backend::CraneliftCompiler; -use wasmer_runtime_core::{import::ImportObject, Instance}; +use wasmer_runtime_core::{backend::Compiler, import::ImportObject, Instance}; fn main() { let instance = create_module_1(); @@ -24,13 +24,38 @@ fn create_module_1() -> Instance { (elem (;1;) (i32.const 9) 1)) "#; let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed"); - let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &CraneliftCompiler::new()) + let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &get_compiler()) .expect("WASM can't be compiled"); module .instantiate(&generate_imports()) .expect("WASM can't be instantiated") } +#[cfg(feature = "clif")] +fn get_compiler() -> impl Compiler { + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() +} + +#[cfg(feature = "llvm")] +fn get_compiler() -> impl Compiler { + use wasmer_llvm_backend::LLVMCompiler; + LLVMCompiler::new() +} + +#[cfg(feature = "singlepass")] +fn get_compiler() -> impl Compiler { + use wasmer_singlepass_backend::SinglePassCompiler; + SinglePassCompiler::new() +} + +#[cfg(not(any(feature = "llvm", feature = "clif", feature = "singlepass")))] +fn get_compiler() -> impl Compiler { + panic!("compiler not specified, activate a compiler via features"); + use wasmer_clif_backend::CraneliftCompiler; + CraneliftCompiler::new() +} + static IMPORT_MODULE: &str = r#" (module (type $t0 (func (param i32))) @@ -44,7 +69,7 @@ static IMPORT_MODULE: &str = r#" pub fn generate_imports() -> ImportObject { let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed"); - let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &CraneliftCompiler::new()) + let module = wasmer_runtime_core::compile_with(&wasm_binary[..], &get_compiler()) .expect("WASM can't be compiled"); let instance = module .instantiate(&ImportObject::new())