Remove transmutes.

This commit is contained in:
losfair 2019-05-07 19:20:18 +08:00
parent 9c0cbc9775
commit e53d5a91ca
2 changed files with 151 additions and 113 deletions

View File

@ -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<Context>,
builder: Option<Builder>,
intrinsics: Option<Intrinsics>,
functions: Vec<LLVMFunctionCodeGenerator>,
signatures: Map<SigIndex, FunctionType>,
signatures_raw: Map<SigIndex, FuncSig>,
function_signatures: Option<Arc<Map<FuncIndex, SigIndex>>>,
func_import_count: usize,
intrinsics: Intrinsics,
personality_func: FunctionValue,
module: Module,
}
pub struct LLVMFunctionCodeGenerator {
context: Option<Context>,
builder: Option<Builder>,
intrinsics: Option<Intrinsics>,
state: State,
builder: &'static Builder,
context: &'static Context,
function: FunctionValue,
func_sig: FuncSig,
intrinsics: &'static Intrinsics,
signatures: Map<SigIndex, FunctionType>,
locals: Vec<PointerValue>, // Contains params and locals
num_params: usize,
@ -405,21 +406,23 @@ impl FunctionCodeGenerator<CodegenError> 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<CodegenError> 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<CodegenError> 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<CodegenError> 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<CodegenError> 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<CodegenError> 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, &params, &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<CodegenError> 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<CodegenError> 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<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
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<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
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<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
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<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
.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<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
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<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
}
fn finalize(
self,
mut self,
module_info: &ModuleInfo,
) -> Result<(LLVMBackend, Box<dyn CacheGen>), 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<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
// 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<SigIndex, FuncSig>) -> 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(())

View File

@ -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,
);