diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 8c3d89d74..4981fd0ad 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -8,6 +8,7 @@ use inkwell::{ AddressSpace, FloatPredicate, IntPredicate, }; use smallvec::SmallVec; +use std::ops::{Deref, DerefMut}; use std::sync::Arc; use wasmer_runtime_core::{ backend::{Backend, CacheGen, Token}, @@ -292,7 +293,7 @@ fn resolve_memory_ptr( let var_offset = builder.build_int_z_extend(var_offset_i32, intrinsics.i64_ty, &state.var_name()); let effective_offset = builder.build_int_add(var_offset, imm_offset, &state.var_name()); - let memory_cache = ctx.memory(MemoryIndex::new(0)); + let memory_cache = ctx.memory(MemoryIndex::new(0), intrinsics); let mem_base_int = match memory_cache { MemoryCache::Dynamic { @@ -363,25 +364,25 @@ pub struct CodegenError { } pub struct LLVMModuleCodeGenerator { - context: Context, - builder: Builder, + context: Option, + builder: Option, + intrinsics: Option, functions: Vec, signatures: Map, signatures_raw: Map, function_signatures: Option>>, func_import_count: usize, - intrinsics: Intrinsics, personality_func: FunctionValue, module: Module, } pub struct LLVMFunctionCodeGenerator { + context: Option, + builder: Option, + intrinsics: Option, state: State, - builder: &'static Builder, - context: &'static Context, function: FunctionValue, func_sig: FuncSig, - intrinsics: &'static Intrinsics, signatures: Map, locals: Vec, // Contains params and locals num_params: usize, @@ -405,21 +406,23 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { // let (count, ty) = local?; let count = n; let wasmer_ty = type_to_type(ty)?; - let ty = type_to_llvm(self.intrinsics, wasmer_ty); + + let intrinsics = self.intrinsics.as_ref().unwrap(); + let ty = type_to_llvm(intrinsics, wasmer_ty); let default_value = match wasmer_ty { - Type::I32 => self.intrinsics.i32_zero.as_basic_value_enum(), - Type::I64 => self.intrinsics.i64_zero.as_basic_value_enum(), - Type::F32 => self.intrinsics.f32_zero.as_basic_value_enum(), - Type::F64 => self.intrinsics.f64_zero.as_basic_value_enum(), + Type::I32 => intrinsics.i32_zero.as_basic_value_enum(), + Type::I64 => intrinsics.i64_zero.as_basic_value_enum(), + Type::F32 => intrinsics.f32_zero.as_basic_value_enum(), + Type::F64 => intrinsics.f64_zero.as_basic_value_enum(), }; - for _ in 0..count { - let alloca = self - .builder - .build_alloca(ty, &format!("local{}", param_len + local_idx)); + let builder = self.builder.as_ref().unwrap(); - self.builder.build_store(alloca, default_value); + for _ in 0..count { + let alloca = builder.build_alloca(ty, &format!("local{}", param_len + local_idx)); + + builder.build_store(alloca, default_value); self.locals.push(alloca); local_idx += 1; @@ -430,22 +433,27 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { fn begin_body(&mut self, module_info: &ModuleInfo) -> Result<(), CodegenError> { let start_of_code_block = self .context + .as_ref() + .unwrap() .append_basic_block(&self.function, "start_of_code"); let entry_end_inst = self .builder + .as_ref() + .unwrap() .build_unconditional_branch(&start_of_code_block); - self.builder.position_at_end(&start_of_code_block); + self.builder + .as_ref() + .unwrap() + .position_at_end(&start_of_code_block); - let cache_builder = self.context.create_builder(); + let cache_builder = self.context.as_ref().unwrap().create_builder(); cache_builder.position_before(&entry_end_inst); let module_info = unsafe { ::std::mem::transmute::<&ModuleInfo, &'static ModuleInfo>(module_info) }; let function = unsafe { ::std::mem::transmute::<&FunctionValue, &'static FunctionValue>(&self.function) }; - let ctx = self - .intrinsics - .ctx(module_info, self.builder, function, cache_builder); + let ctx = CtxType::new(module_info, function, cache_builder); self.ctx = Some(ctx); Ok(()) @@ -460,10 +468,10 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { }; let mut state = &mut self.state; - let builder = self.builder; - let context = self.context; + let builder = self.builder.as_ref().unwrap(); + let context = self.context.as_ref().unwrap(); let function = self.function; - let intrinsics = self.intrinsics; + let intrinsics = self.intrinsics.as_ref().unwrap(); let locals = &self.locals; let info = module_info; let signatures = &self.signatures; @@ -868,7 +876,7 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { Operator::GetGlobal { global_index } => { let index = GlobalIndex::new(global_index as usize); - let global_cache = ctx.global_cache(index); + let global_cache = ctx.global_cache(index, intrinsics); match global_cache { GlobalCache::Const { value } => { state.push1(value); @@ -882,7 +890,7 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { Operator::SetGlobal { global_index } => { let value = state.pop1()?; let index = GlobalIndex::new(global_index as usize); - let global_cache = ctx.global_cache(index); + let global_cache = ctx.global_cache(index, intrinsics); match global_cache { GlobalCache::Mut { ptr_to_value } => { builder.build_store(ptr_to_value, value); @@ -918,12 +926,14 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { .map(|v| *v) .collect(); - let func_ptr = ctx.local_func(local_func_index, llvm_sig); + let func_ptr = + ctx.local_func(local_func_index, llvm_sig, intrinsics, builder); builder.build_call(func_ptr, ¶ms, &state.var_name()) } LocalOrImport::Import(import_func_index) => { - let (func_ptr_untyped, ctx_ptr) = ctx.imported_func(import_func_index); + let (func_ptr_untyped, ctx_ptr) = + ctx.imported_func(import_func_index, intrinsics); let params: Vec<_> = [ctx_ptr.as_basic_value_enum()] .iter() .chain(state.peekn(func_sig.params().len())?.iter()) @@ -962,8 +972,9 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { } Operator::CallIndirect { index, table_index } => { let sig_index = SigIndex::new(index as usize); - let expected_dynamic_sigindex = ctx.dynamic_sigindex(sig_index); - let (table_base, table_bound) = ctx.table(TableIndex::new(table_index as usize)); + let expected_dynamic_sigindex = ctx.dynamic_sigindex(sig_index, intrinsics); + let (table_base, table_bound) = + ctx.table(TableIndex::new(table_index as usize), intrinsics, builder); let func_index = state.pop1()?.into_int_value(); // We assume the table has the `anyfunc` element type. @@ -2404,10 +2415,10 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { match results.as_slice() { [] => { - self.builder.build_return(None); + self.builder.as_ref().unwrap().build_return(None); } [one_value] => { - self.builder.build_return(Some(one_value)); + self.builder.as_ref().unwrap().build_return(Some(one_value)); } _ => { // let struct_ty = llvm_sig.get_return_type().as_struct_type(); @@ -2446,15 +2457,15 @@ impl ModuleCodeGenerator let signatures = Map::new(); LLVMModuleCodeGenerator { - context, - builder, + context: Some(context), + builder: Some(builder), + intrinsics: Some(intrinsics), module, functions: vec![], signatures, signatures_raw: Map::new(), function_signatures: None, func_import_count: 0, - intrinsics, personality_func, } } @@ -2469,6 +2480,18 @@ impl ModuleCodeGenerator fn next_function(&mut self) -> Result<&mut LLVMFunctionCodeGenerator, CodegenError> { // Creates a new function and returns the function-scope code generator for it. + let (context, builder, intrinsics) = match self.functions.last_mut() { + Some(x) => ( + x.context.take().unwrap(), + x.builder.take().unwrap(), + x.intrinsics.take().unwrap(), + ), + None => ( + self.context.take().unwrap(), + self.builder.take().unwrap(), + self.intrinsics.take().unwrap(), + ), + }; let sig_id = self.function_signatures.as_ref().unwrap() [FuncIndex::new(self.func_import_count + self.functions.len())]; @@ -2482,20 +2505,20 @@ impl ModuleCodeGenerator function.set_personality_function(self.personality_func); let mut state = State::new(); - let entry_block = self.context.append_basic_block(&function, "entry"); + let entry_block = context.append_basic_block(&function, "entry"); - let return_block = self.context.append_basic_block(&function, "return"); - self.builder.position_at_end(&return_block); + let return_block = context.append_basic_block(&function, "return"); + builder.position_at_end(&return_block); let phis: SmallVec<[PhiValue; 1]> = func_sig .returns() .iter() - .map(|&wasmer_ty| type_to_llvm(&self.intrinsics, wasmer_ty)) - .map(|ty| self.builder.build_phi(ty, &state.var_name())) + .map(|&wasmer_ty| type_to_llvm(&intrinsics, wasmer_ty)) + .map(|ty| builder.build_phi(ty, &state.var_name())) .collect(); state.push_block(return_block, phis); - self.builder.position_at_end(&entry_block); + builder.position_at_end(&entry_block); let mut locals = Vec::new(); locals.extend( @@ -2506,8 +2529,8 @@ impl ModuleCodeGenerator .map(|(index, param)| { let ty = param.get_type(); - let alloca = self.builder.build_alloca(ty, &format!("local{}", index)); - self.builder.build_store(alloca, param); + let alloca = builder.build_alloca(ty, &format!("local{}", index)); + builder.build_store(alloca, param); alloca }), ); @@ -2515,16 +2538,14 @@ impl ModuleCodeGenerator let code = LLVMFunctionCodeGenerator { state, - builder: unsafe { ::std::mem::transmute::<&Builder, &'static Builder>(&self.builder) }, - context: unsafe { ::std::mem::transmute::<&Context, &'static Context>(&self.context) }, + context: Some(context), + builder: Some(builder), + intrinsics: Some(intrinsics), function, func_sig: func_sig, locals, signatures: self.signatures.clone(), num_params, - intrinsics: unsafe { - ::std::mem::transmute::<&Intrinsics, &'static Intrinsics>(&self.intrinsics) - }, ctx: None, unreachable_depth: 0, }; @@ -2533,18 +2554,33 @@ impl ModuleCodeGenerator } fn finalize( - self, + mut self, module_info: &ModuleInfo, ) -> Result<(LLVMBackend, Box), CodegenError> { // self.module.print_to_stderr(); + let (context, builder, intrinsics) = match self.functions.last_mut() { + Some(x) => ( + x.context.take().unwrap(), + x.builder.take().unwrap(), + x.intrinsics.take().unwrap(), + ), + None => ( + self.context.take().unwrap(), + self.builder.take().unwrap(), + self.intrinsics.take().unwrap(), + ), + }; + self.context = Some(context); + self.builder = Some(builder); + self.intrinsics = Some(intrinsics); generate_trampolines( module_info, &self.signatures, &self.module, - &self.context, - &self.builder, - &self.intrinsics, + self.context.as_ref().unwrap(), + self.builder.as_ref().unwrap(), + self.intrinsics.as_ref().unwrap(), ); let pass_manager = PassManager::create_for_module(); @@ -2563,14 +2599,20 @@ impl ModuleCodeGenerator // self.module.print_to_stderr(); - let (backend, cache_gen) = LLVMBackend::new(self.module, self.intrinsics); + let (backend, cache_gen) = LLVMBackend::new(self.module, self.intrinsics.take().unwrap()); Ok((backend, Box::new(cache_gen))) } fn feed_signatures(&mut self, signatures: Map) -> Result<(), CodegenError> { self.signatures = signatures .iter() - .map(|(_, sig)| func_sig_to_llvm(&self.context, &self.intrinsics, sig)) + .map(|(_, sig)| { + func_sig_to_llvm( + self.context.as_ref().unwrap(), + self.intrinsics.as_ref().unwrap(), + sig, + ) + }) .collect(); self.signatures_raw = signatures.clone(); Ok(()) diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index 1b367f5d4..6250fd4fd 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -369,31 +369,6 @@ impl Intrinsics { ctx_ptr_ty, } } - - pub fn ctx<'a>( - &'a self, - info: &'a ModuleInfo, - builder: &'a Builder, - func_value: &'a FunctionValue, - cache_builder: Builder, - ) -> CtxType<'a> { - CtxType { - ctx_ptr_value: func_value.get_nth_param(0).unwrap().into_pointer_value(), - - builder, - intrinsics: self, - info, - cache_builder, - - cached_memories: HashMap::new(), - cached_tables: HashMap::new(), - cached_sigindices: HashMap::new(), - cached_globals: HashMap::new(), - cached_imported_functions: HashMap::new(), - - _phantom: PhantomData, - } - } } #[derive(Clone, Copy)] @@ -429,8 +404,6 @@ struct ImportedFuncCache { pub struct CtxType<'a> { ctx_ptr_value: PointerValue, - builder: &'a Builder, - intrinsics: &'a Intrinsics, info: &'a ModuleInfo, cache_builder: Builder, @@ -444,16 +417,36 @@ pub struct CtxType<'a> { } impl<'a> CtxType<'a> { + pub fn new( + info: &'a ModuleInfo, + func_value: &'a FunctionValue, + cache_builder: Builder, + ) -> CtxType<'a> { + CtxType { + ctx_ptr_value: func_value.get_nth_param(0).unwrap().into_pointer_value(), + + info, + cache_builder, + + cached_memories: HashMap::new(), + cached_tables: HashMap::new(), + cached_sigindices: HashMap::new(), + cached_globals: HashMap::new(), + cached_imported_functions: HashMap::new(), + + _phantom: PhantomData, + } + } + pub fn basic(&self) -> BasicValueEnum { self.ctx_ptr_value.as_basic_value_enum() } - pub fn memory(&mut self, index: MemoryIndex) -> MemoryCache { - let (cached_memories, info, ctx_ptr_value, intrinsics, cache_builder) = ( + pub fn memory(&mut self, index: MemoryIndex, intrinsics: &Intrinsics) -> MemoryCache { + let (cached_memories, info, ctx_ptr_value, cache_builder) = ( &mut self.cached_memories, self.info, self.ctx_ptr_value, - self.intrinsics, &self.cache_builder, ); @@ -514,13 +507,16 @@ impl<'a> CtxType<'a> { }) } - pub fn table(&mut self, index: TableIndex) -> (PointerValue, IntValue) { - let (cached_tables, builder, info, ctx_ptr_value, intrinsics, cache_builder) = ( + pub fn table( + &mut self, + index: TableIndex, + intrinsics: &Intrinsics, + builder: &Builder, + ) -> (PointerValue, IntValue) { + let (cached_tables, info, ctx_ptr_value, cache_builder) = ( &mut self.cached_tables, - self.builder, self.info, self.ctx_ptr_value, - self.intrinsics, &self.cache_builder, ); @@ -575,41 +571,39 @@ impl<'a> CtxType<'a> { ) } - pub fn local_func(&mut self, index: LocalFuncIndex, fn_ty: FunctionType) -> PointerValue { - let local_func_array_ptr_ptr = unsafe { - self.builder - .build_struct_gep(self.ctx_ptr_value, 8, "local_func_array_ptr_ptr") - }; - let local_func_array_ptr = self - .builder + pub fn local_func( + &mut self, + index: LocalFuncIndex, + fn_ty: FunctionType, + intrinsics: &Intrinsics, + builder: &Builder, + ) -> PointerValue { + let local_func_array_ptr_ptr = + unsafe { builder.build_struct_gep(self.ctx_ptr_value, 8, "local_func_array_ptr_ptr") }; + let local_func_array_ptr = builder .build_load(local_func_array_ptr_ptr, "local_func_array_ptr") .into_pointer_value(); let local_func_ptr_ptr = unsafe { - self.builder.build_in_bounds_gep( + builder.build_in_bounds_gep( local_func_array_ptr, - &[self - .intrinsics - .i32_ty - .const_int(index.index() as u64, false)], + &[intrinsics.i32_ty.const_int(index.index() as u64, false)], "local_func_ptr_ptr", ) }; - let local_func_ptr = self - .builder + let local_func_ptr = builder .build_load(local_func_ptr_ptr, "local_func_ptr") .into_pointer_value(); - self.builder.build_pointer_cast( + builder.build_pointer_cast( local_func_ptr, fn_ty.ptr_type(AddressSpace::Generic), "local_func_ptr", ) } - pub fn dynamic_sigindex(&mut self, index: SigIndex) -> IntValue { - let (cached_sigindices, ctx_ptr_value, intrinsics, cache_builder) = ( + pub fn dynamic_sigindex(&mut self, index: SigIndex, intrinsics: &Intrinsics) -> IntValue { + let (cached_sigindices, ctx_ptr_value, cache_builder) = ( &mut self.cached_sigindices, self.ctx_ptr_value, - self.intrinsics, &self.cache_builder, ); @@ -636,12 +630,11 @@ impl<'a> CtxType<'a> { }) } - pub fn global_cache(&mut self, index: GlobalIndex) -> GlobalCache { - let (cached_globals, ctx_ptr_value, info, intrinsics, cache_builder) = ( + pub fn global_cache(&mut self, index: GlobalIndex, intrinsics: &Intrinsics) -> GlobalCache { + let (cached_globals, ctx_ptr_value, info, cache_builder) = ( &mut self.cached_globals, self.ctx_ptr_value, self.info, - self.intrinsics, &self.cache_builder, ); @@ -712,11 +705,14 @@ impl<'a> CtxType<'a> { }) } - pub fn imported_func(&mut self, index: ImportedFuncIndex) -> (PointerValue, PointerValue) { - let (cached_imported_functions, ctx_ptr_value, intrinsics, cache_builder) = ( + pub fn imported_func( + &mut self, + index: ImportedFuncIndex, + intrinsics: &Intrinsics, + ) -> (PointerValue, PointerValue) { + let (cached_imported_functions, ctx_ptr_value, cache_builder) = ( &mut self.cached_imported_functions, self.ctx_ptr_value, - self.intrinsics, &self.cache_builder, );