Skip to content

Commit

Permalink
Update lifetime of function builder references
Browse files Browse the repository at this point in the history
  • Loading branch information
bjfish committed May 25, 2019
1 parent 9f2e068 commit d440776
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 49 deletions.
97 changes: 54 additions & 43 deletions lib/clif-backend/src/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -82,12 +86,7 @@ impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>

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(
Expand All @@ -101,30 +100,25 @@ impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>
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));
Expand Down Expand Up @@ -308,12 +302,6 @@ impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>
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())
}
Expand All @@ -322,8 +310,13 @@ impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>
self,
module_info: &ModuleInfo,
) -> Result<(Caller, Box<dyn CacheGen>), CodegenError> {
let mut func_bodies: Map<LocalFuncIndex, ir::Function> = 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));

Expand Down Expand Up @@ -378,12 +371,13 @@ impl From<CompileError> for CodegenError {
}

pub struct CraneliftFunctionCodeGenerator {
builder: Option<FunctionBuilder<'static>>,
func: Function,
func_translator: FuncTranslator,
next_local: usize,
pub clif_signatures: Map<SigIndex, ir::Signature>,
module_info: Arc<ModuleInfo>,
target_config: isa::TargetFrontendConfig,
position: Position,
}

pub struct FunctionEnvironment {
Expand Down Expand Up @@ -1088,12 +1082,9 @@ impl FunctionCodeGenerator<CodegenError> 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(())
}

Expand All @@ -1108,27 +1099,39 @@ impl FunctionCodeGenerator<CodegenError> 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 {
module_info: Arc::clone(&self.module_info),
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.
Expand All @@ -1149,7 +1152,7 @@ impl FunctionCodeGenerator<CodegenError> for CraneliftFunctionCodeGenerator {
// or the end of the function is unreachable.
state.stack.clear();

self.builder.as_mut().unwrap().finalize();
self.builder().finalize();
Ok(())
}
}
Expand All @@ -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
}
Expand Down
22 changes: 21 additions & 1 deletion lib/runtime-core/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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, RM, E>,
FCG: FunctionCodeGenerator<E>,
Expand All @@ -132,6 +147,11 @@ impl<
compiler_config: CompilerConfig,
_: Token,
) -> CompileResult<ModuleInner> {
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(
Expand All @@ -149,7 +169,7 @@ impl<
Ok(ModuleInner {
cache_gen,
runnable_module: Box::new(exec_context),
info,
info: Arc::try_unwrap(info).unwrap(),
})
}

Expand Down
5 changes: 3 additions & 2 deletions lib/runtime-core/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub fn read_module<
mcg: &mut MCG,
middlewares: &mut MiddlewareChain,
compiler_config: &CompilerConfig,
) -> Result<ModuleInfo, LoadError> {
) -> Result<Arc<ModuleInfo>, LoadError> {
let mut info = Arc::new(ModuleInfo {
memories: Map::new(),
globals: Map::new(),
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -385,6 +385,7 @@ pub fn read_module<
_ => {}
}
}
Ok(info)
}

pub fn wp_type_to_type(ty: WpType) -> Result<Type, BinaryReaderError> {
Expand Down
31 changes: 28 additions & 3 deletions lib/spectests/examples/test.rs
Original file line number Diff line number Diff line change
@@ -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();
Expand All @@ -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)))
Expand All @@ -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())
Expand Down

0 comments on commit d440776

Please sign in to comment.