mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-08 05:38:19 +00:00
Fix invalid LLVM IR for global.get/set of imported globals.
In passing, refactor global accesses and cache the address computations and values of const globals. Also includes some cargo fmt fixes.
This commit is contained in:
@@ -155,5 +155,4 @@ impl Compiler for LLVMCompiler {
|
||||
Ok(PrimaryMap::new())
|
||||
// unimplemented!("Dynamic funciton trampolines not yet implemented");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2227,96 +2227,34 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
|
||||
|
||||
Operator::GlobalGet { global_index } => {
|
||||
let global_index = GlobalIndex::from_u32(global_index);
|
||||
let global_type = module.globals[global_index];
|
||||
let global_value_type = global_type.ty;
|
||||
|
||||
// TODO: cache loads of const globals.
|
||||
let _global_mutability = global_type.mutability;
|
||||
|
||||
let global_ptr =
|
||||
if let Some(local_global_index) = module.local_global_index(global_index) {
|
||||
let offset = self.vmoffsets.vmctx_vmglobal_definition(local_global_index);
|
||||
let offset = intrinsics.i32_ty.const_int(offset.into(), false);
|
||||
unsafe { builder.build_gep(*vmctx, &[offset], "") }
|
||||
} else {
|
||||
let offset = self.vmoffsets.vmctx_vmglobal_import(global_index);
|
||||
let offset = intrinsics.i32_ty.const_int(offset.into(), false);
|
||||
let global_ptr_ptr = unsafe { builder.build_gep(*vmctx, &[offset], "") };
|
||||
let global_ptr_ptr = builder
|
||||
.build_bitcast(global_ptr_ptr, intrinsics.i8_ptr_ty, "")
|
||||
.into_pointer_value();
|
||||
let global_ptr = builder.build_load(global_ptr_ptr, "");
|
||||
builder
|
||||
.build_bitcast(global_ptr, intrinsics.i8_ptr_ty, "")
|
||||
.into_pointer_value()
|
||||
};
|
||||
let global_ptr = builder
|
||||
.build_bitcast(
|
||||
global_ptr,
|
||||
type_to_llvm_ptr(&intrinsics, global_value_type),
|
||||
"",
|
||||
)
|
||||
.into_pointer_value();
|
||||
let value = builder.build_load(global_ptr, "");
|
||||
// TODO: add TBAA info.
|
||||
self.state.push1(value);
|
||||
match ctx.global(global_index, intrinsics) {
|
||||
GlobalCache::Const { value } => {
|
||||
self.state.push1(value);
|
||||
}
|
||||
GlobalCache::Mut { ptr_to_value } => {
|
||||
let value = builder.build_load(ptr_to_value, "");
|
||||
// TODO: tbaa
|
||||
self.state.push1(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
Operator::GlobalSet { global_index } => {
|
||||
let global_index = GlobalIndex::from_u32(global_index);
|
||||
let global_type = module.globals[global_index];
|
||||
let global_value_type = global_type.ty;
|
||||
|
||||
// Note that we don't check mutability, assuming that's already
|
||||
// been checked by some other verifier.
|
||||
|
||||
let global_ptr =
|
||||
if let Some(local_global_index) = module.local_global_index(global_index) {
|
||||
let offset = self.vmoffsets.vmctx_vmglobal_definition(local_global_index);
|
||||
let offset = intrinsics.i32_ty.const_int(offset.into(), false);
|
||||
unsafe { builder.build_gep(*vmctx, &[offset], "") }
|
||||
} else {
|
||||
let offset = self.vmoffsets.vmctx_vmglobal_import(global_index);
|
||||
let offset = intrinsics.i32_ty.const_int(offset.into(), false);
|
||||
let global_ptr_ptr = unsafe { builder.build_gep(*vmctx, &[offset], "") };
|
||||
let global_ptr_ptr = builder
|
||||
.build_bitcast(global_ptr_ptr, intrinsics.i8_ptr_ty, "")
|
||||
.into_pointer_value();
|
||||
builder.build_load(global_ptr_ptr, "").into_pointer_value()
|
||||
};
|
||||
let global_ptr = builder
|
||||
.build_bitcast(
|
||||
global_ptr,
|
||||
type_to_llvm_ptr(&intrinsics, global_value_type),
|
||||
"",
|
||||
)
|
||||
.into_pointer_value();
|
||||
|
||||
let (value, info) = self.state.pop1_extra()?;
|
||||
let value = apply_pending_canonicalization(builder, intrinsics, value, info);
|
||||
builder.build_store(global_ptr, value);
|
||||
// TODO: add TBAA info
|
||||
|
||||
/*
|
||||
let (value, info) = self.state.pop1_extra()?;
|
||||
let value = apply_pending_canonicalization(builder, intrinsics, value, info);
|
||||
let index = GlobalIndex::from_u32(global_index);
|
||||
let global_cache = ctx.global_cache(index, intrinsics, self.module);
|
||||
match global_cache {
|
||||
GlobalCache::Mut { ptr_to_value } => {
|
||||
let store = builder.build_store(ptr_to_value, value);
|
||||
tbaa_label(
|
||||
&self.module,
|
||||
intrinsics,
|
||||
"global",
|
||||
store,
|
||||
Some(global_index),
|
||||
);
|
||||
}
|
||||
GlobalCache::Const { value: _ } => {
|
||||
return Err(CompileError::Codegen("global is immutable".to_string()));
|
||||
}
|
||||
}
|
||||
*/
|
||||
match ctx.global(global_index, intrinsics) {
|
||||
GlobalCache::Const { value } => {
|
||||
return Err(CompileError::Codegen(format!(
|
||||
"global.set on immutable global index {}",
|
||||
global_index.as_u32()
|
||||
)))
|
||||
}
|
||||
GlobalCache::Mut { ptr_to_value } => {
|
||||
let (value, info) = self.state.pop1_extra()?;
|
||||
let value =
|
||||
apply_pending_canonicalization(builder, intrinsics, value, info);
|
||||
builder.build_store(ptr_to_value, value);
|
||||
// TODO: tbaa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Operator::Select => {
|
||||
|
||||
@@ -910,7 +910,7 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn table_prepare(
|
||||
fn table_prepare(
|
||||
&mut self,
|
||||
table_index: TableIndex,
|
||||
intrinsics: &Intrinsics<'ctx>,
|
||||
@@ -952,7 +952,9 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
|
||||
);
|
||||
let ptr_to_bounds =
|
||||
unsafe { cache_builder.build_gep(ctx_ptr_value, &[offset], "") };
|
||||
let ptr_to_bounds = cache_builder.build_bitcast(ptr_to_bounds, intrinsics.i32_ptr_ty, "").into_pointer_value();
|
||||
let ptr_to_bounds = cache_builder
|
||||
.build_bitcast(ptr_to_bounds, intrinsics.i32_ptr_ty, "")
|
||||
.into_pointer_value();
|
||||
(ptr_to_base_ptr, ptr_to_bounds)
|
||||
} else {
|
||||
let offset = intrinsics.i64_ty.const_int(
|
||||
@@ -990,7 +992,9 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
|
||||
.const_int(offsets.vmtable_definition_current_elements().into(), false);
|
||||
let ptr_to_bounds =
|
||||
unsafe { cache_builder.build_gep(definition_ptr, &[offset], "") };
|
||||
let ptr_to_bounds = cache_builder.build_bitcast(ptr_to_bounds, intrinsics.i32_ptr_ty, "").into_pointer_value();
|
||||
let ptr_to_bounds = cache_builder
|
||||
.build_bitcast(ptr_to_bounds, intrinsics.i32_ptr_ty, "")
|
||||
.into_pointer_value();
|
||||
(ptr_to_base_ptr, ptr_to_bounds)
|
||||
};
|
||||
TableCache {
|
||||
@@ -1010,10 +1014,14 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
|
||||
builder: &Builder<'ctx>,
|
||||
) -> (PointerValue<'ctx>, IntValue<'ctx>) {
|
||||
let (ptr_to_base_ptr, ptr_to_bounds) = self.table_prepare(index, intrinsics, module);
|
||||
let base_ptr = builder
|
||||
let base_ptr = self
|
||||
.cache_builder
|
||||
.build_load(ptr_to_base_ptr, "base_ptr")
|
||||
.into_pointer_value();
|
||||
let bounds = builder.build_load(ptr_to_bounds, "bounds").into_int_value();
|
||||
let bounds = self
|
||||
.cache_builder
|
||||
.build_load(ptr_to_bounds, "bounds")
|
||||
.into_int_value();
|
||||
tbaa_label(
|
||||
module,
|
||||
intrinsics,
|
||||
@@ -1080,106 +1088,59 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn global_cache(
|
||||
pub fn global(
|
||||
&mut self,
|
||||
index: GlobalIndex,
|
||||
intrinsics: &Intrinsics<'ctx>,
|
||||
module: &Module<'ctx>,
|
||||
) -> GlobalCache<'ctx> {
|
||||
let (cached_globals, ctx_ptr_value, wasm_module, cache_builder, offsets) = (
|
||||
let (cached_globals, wasm_module, ctx_ptr_value, cache_builder, offsets) = (
|
||||
&mut self.cached_globals,
|
||||
self.ctx_ptr_value,
|
||||
self.wasm_module,
|
||||
self.ctx_ptr_value,
|
||||
&self.cache_builder,
|
||||
&self.offsets,
|
||||
);
|
||||
*cached_globals.entry(index).or_insert_with(|| {
|
||||
let (globals_array_ptr_ptr, index, mutable, wasmer_ty, field_name) = {
|
||||
let desc = wasm_module.globals.get(index).unwrap();
|
||||
if let Some(_local_global_index) = wasm_module.local_global_index(index) {
|
||||
(
|
||||
unsafe {
|
||||
cache_builder
|
||||
.build_struct_gep(
|
||||
ctx_ptr_value,
|
||||
offset_to_index(offsets.vmctx_globals_begin()),
|
||||
"globals_array_ptr_ptr",
|
||||
)
|
||||
.unwrap()
|
||||
},
|
||||
index.index() as u64,
|
||||
desc.mutability,
|
||||
desc.ty,
|
||||
"context_field_ptr_to_local_globals",
|
||||
)
|
||||
} else {
|
||||
(
|
||||
unsafe {
|
||||
cache_builder
|
||||
.build_struct_gep(
|
||||
ctx_ptr_value,
|
||||
offset_to_index(offsets.vmctx_imported_globals_begin()),
|
||||
"globals_array_ptr_ptr",
|
||||
)
|
||||
.unwrap()
|
||||
},
|
||||
index.index() as u64,
|
||||
desc.mutability,
|
||||
desc.ty,
|
||||
"context_field_ptr_to_imported_globals",
|
||||
)
|
||||
}
|
||||
};
|
||||
let global_type = wasm_module.globals[index];
|
||||
let global_value_type = global_type.ty;
|
||||
|
||||
let llvm_ptr_ty = type_to_llvm_ptr(intrinsics, wasmer_ty);
|
||||
|
||||
let global_array_ptr = cache_builder
|
||||
.build_load(globals_array_ptr_ptr, "global_array_ptr")
|
||||
.into_pointer_value();
|
||||
tbaa_label(
|
||||
module,
|
||||
intrinsics,
|
||||
field_name,
|
||||
global_array_ptr.as_instruction_value().unwrap(),
|
||||
None,
|
||||
);
|
||||
let const_index = intrinsics.i32_ty.const_int(index, false);
|
||||
let global_ptr_ptr = unsafe {
|
||||
cache_builder.build_in_bounds_gep(
|
||||
global_array_ptr,
|
||||
&[const_index],
|
||||
"global_ptr_ptr",
|
||||
)
|
||||
let global_mutability = global_type.mutability;
|
||||
let global_ptr = if let Some(local_global_index) = wasm_module.local_global_index(index)
|
||||
{
|
||||
let offset = offsets.vmctx_vmglobal_definition(local_global_index);
|
||||
let offset = intrinsics.i32_ty.const_int(offset.into(), false);
|
||||
unsafe { cache_builder.build_gep(ctx_ptr_value, &[offset], "") }
|
||||
} else {
|
||||
let offset = offsets.vmctx_vmglobal_import(index);
|
||||
let offset = intrinsics.i32_ty.const_int(offset.into(), false);
|
||||
let global_ptr_ptr =
|
||||
unsafe { cache_builder.build_gep(ctx_ptr_value, &[offset], "") };
|
||||
let global_ptr_ptr = cache_builder
|
||||
.build_bitcast(
|
||||
global_ptr_ptr,
|
||||
intrinsics.i32_ptr_ty.ptr_type(AddressSpace::Generic),
|
||||
"",
|
||||
)
|
||||
.into_pointer_value();
|
||||
cache_builder
|
||||
.build_load(global_ptr_ptr, "")
|
||||
.into_pointer_value()
|
||||
};
|
||||
let global_ptr = cache_builder
|
||||
.build_load(global_ptr_ptr, "global_ptr")
|
||||
.build_bitcast(
|
||||
global_ptr,
|
||||
type_to_llvm_ptr(&intrinsics, global_value_type),
|
||||
"",
|
||||
)
|
||||
.into_pointer_value();
|
||||
tbaa_label(
|
||||
module,
|
||||
intrinsics,
|
||||
"global_ptr",
|
||||
global_ptr.as_instruction_value().unwrap(),
|
||||
Some(index as u32),
|
||||
);
|
||||
|
||||
let global_ptr_typed =
|
||||
cache_builder.build_pointer_cast(global_ptr, llvm_ptr_ty, "global_ptr_typed");
|
||||
|
||||
let mutable = mutable == Mutability::Var;
|
||||
if mutable {
|
||||
GlobalCache::Mut {
|
||||
ptr_to_value: global_ptr_typed,
|
||||
}
|
||||
} else {
|
||||
let value = cache_builder.build_load(global_ptr_typed, "global_value");
|
||||
tbaa_label(
|
||||
module,
|
||||
intrinsics,
|
||||
"global",
|
||||
value.as_instruction_value().unwrap(),
|
||||
Some(index as u32),
|
||||
);
|
||||
GlobalCache::Const { value }
|
||||
match global_mutability {
|
||||
Mutability::Const => GlobalCache::Const {
|
||||
value: cache_builder.build_load(global_ptr, ""),
|
||||
},
|
||||
Mutability::Var => GlobalCache::Mut {
|
||||
ptr_to_value: global_ptr,
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user