mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-22 13:11:32 +00:00
Merge branch 'master' into feat-runtime-core-clos-host-function
This commit is contained in:
@ -11,12 +11,14 @@ use inkwell::{
|
||||
use libc::c_char;
|
||||
use std::{
|
||||
any::Any,
|
||||
cell::RefCell,
|
||||
ffi::{c_void, CString},
|
||||
fs::File,
|
||||
io::Write,
|
||||
mem,
|
||||
ops::Deref,
|
||||
ptr::{self, NonNull},
|
||||
rc::Rc,
|
||||
slice, str,
|
||||
sync::{Arc, Once},
|
||||
};
|
||||
@ -169,14 +171,14 @@ pub struct LLVMBackend {
|
||||
|
||||
impl LLVMBackend {
|
||||
pub fn new(
|
||||
module: Module,
|
||||
module: Rc<RefCell<Module>>,
|
||||
_intrinsics: Intrinsics,
|
||||
_stackmaps: &StackmapRegistry,
|
||||
_module_info: &ModuleInfo,
|
||||
target_machine: &TargetMachine,
|
||||
) -> (Self, LLVMCache) {
|
||||
let memory_buffer = target_machine
|
||||
.write_to_memory_buffer(&module, FileType::Object)
|
||||
.write_to_memory_buffer(&module.borrow_mut(), FileType::Object)
|
||||
.unwrap();
|
||||
let mem_buf_slice = memory_buffer.as_slice();
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,12 +7,15 @@ use inkwell::{
|
||||
BasicType, FloatType, FunctionType, IntType, PointerType, StructType, VectorType, VoidType,
|
||||
},
|
||||
values::{
|
||||
BasicValue, BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue, VectorValue,
|
||||
BasicValue, BasicValueEnum, FloatValue, FunctionValue, InstructionValue, IntValue,
|
||||
MetadataValue, PointerValue, VectorValue,
|
||||
},
|
||||
AddressSpace,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
use wasmer_runtime_core::{
|
||||
memory::MemoryType,
|
||||
module::ModuleInfo,
|
||||
@ -21,6 +24,7 @@ use wasmer_runtime_core::{
|
||||
GlobalIndex, ImportedFuncIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex,
|
||||
TableIndex, Type,
|
||||
},
|
||||
units::Pages,
|
||||
vm::{Ctx, INTERNALS_SIZE},
|
||||
};
|
||||
|
||||
@ -559,11 +563,15 @@ pub enum MemoryCache {
|
||||
Dynamic {
|
||||
ptr_to_base_ptr: PointerValue,
|
||||
ptr_to_bounds: PointerValue,
|
||||
minimum: Pages,
|
||||
maximum: Option<Pages>,
|
||||
},
|
||||
/// The memory is always in the same place.
|
||||
Static {
|
||||
base_ptr: PointerValue,
|
||||
bounds: IntValue,
|
||||
minimum: Pages,
|
||||
maximum: Option<Pages>,
|
||||
},
|
||||
}
|
||||
|
||||
@ -653,7 +661,12 @@ impl<'a> CtxType<'a> {
|
||||
ptr
|
||||
}
|
||||
|
||||
pub fn memory(&mut self, index: MemoryIndex, intrinsics: &Intrinsics) -> MemoryCache {
|
||||
pub fn memory(
|
||||
&mut self,
|
||||
index: MemoryIndex,
|
||||
intrinsics: &Intrinsics,
|
||||
module: Rc<RefCell<Module>>,
|
||||
) -> MemoryCache {
|
||||
let (cached_memories, info, ctx_ptr_value, cache_builder) = (
|
||||
&mut self.cached_memories,
|
||||
self.info,
|
||||
@ -662,34 +675,48 @@ impl<'a> CtxType<'a> {
|
||||
);
|
||||
|
||||
*cached_memories.entry(index).or_insert_with(|| {
|
||||
let (memory_array_ptr_ptr, index, memory_type) = match index.local_or_import(info) {
|
||||
LocalOrImport::Local(local_mem_index) => (
|
||||
unsafe {
|
||||
cache_builder.build_struct_gep(
|
||||
ctx_ptr_value,
|
||||
offset_to_index(Ctx::offset_memories()),
|
||||
"memory_array_ptr_ptr",
|
||||
)
|
||||
},
|
||||
local_mem_index.index() as u64,
|
||||
info.memories[local_mem_index].memory_type(),
|
||||
),
|
||||
LocalOrImport::Import(import_mem_index) => (
|
||||
unsafe {
|
||||
cache_builder.build_struct_gep(
|
||||
ctx_ptr_value,
|
||||
offset_to_index(Ctx::offset_imported_memories()),
|
||||
"memory_array_ptr_ptr",
|
||||
)
|
||||
},
|
||||
import_mem_index.index() as u64,
|
||||
info.imported_memories[import_mem_index].1.memory_type(),
|
||||
),
|
||||
};
|
||||
let (memory_array_ptr_ptr, index, memory_type, minimum, maximum, field_name) =
|
||||
match index.local_or_import(info) {
|
||||
LocalOrImport::Local(local_mem_index) => (
|
||||
unsafe {
|
||||
cache_builder.build_struct_gep(
|
||||
ctx_ptr_value,
|
||||
offset_to_index(Ctx::offset_memories()),
|
||||
"memory_array_ptr_ptr",
|
||||
)
|
||||
},
|
||||
local_mem_index.index() as u64,
|
||||
info.memories[local_mem_index].memory_type(),
|
||||
info.memories[local_mem_index].minimum,
|
||||
info.memories[local_mem_index].maximum,
|
||||
"context_field_ptr_to_local_memory",
|
||||
),
|
||||
LocalOrImport::Import(import_mem_index) => (
|
||||
unsafe {
|
||||
cache_builder.build_struct_gep(
|
||||
ctx_ptr_value,
|
||||
offset_to_index(Ctx::offset_imported_memories()),
|
||||
"memory_array_ptr_ptr",
|
||||
)
|
||||
},
|
||||
import_mem_index.index() as u64,
|
||||
info.imported_memories[import_mem_index].1.memory_type(),
|
||||
info.imported_memories[import_mem_index].1.minimum,
|
||||
info.imported_memories[import_mem_index].1.maximum,
|
||||
"context_field_ptr_to_imported_memory",
|
||||
),
|
||||
};
|
||||
|
||||
let memory_array_ptr = cache_builder
|
||||
.build_load(memory_array_ptr_ptr, "memory_array_ptr")
|
||||
.into_pointer_value();
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
field_name,
|
||||
memory_array_ptr.as_instruction_value().unwrap(),
|
||||
None,
|
||||
);
|
||||
let const_index = intrinsics.i32_ty.const_int(index, false);
|
||||
let memory_ptr_ptr = unsafe {
|
||||
cache_builder.build_in_bounds_gep(
|
||||
@ -701,6 +728,13 @@ impl<'a> CtxType<'a> {
|
||||
let memory_ptr = cache_builder
|
||||
.build_load(memory_ptr_ptr, "memory_ptr")
|
||||
.into_pointer_value();
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"memory_ptr",
|
||||
memory_ptr.as_instruction_value().unwrap(),
|
||||
Some(index as u32),
|
||||
);
|
||||
|
||||
let (ptr_to_base_ptr, ptr_to_bounds) = unsafe {
|
||||
(
|
||||
@ -713,15 +747,37 @@ impl<'a> CtxType<'a> {
|
||||
MemoryType::Dynamic => MemoryCache::Dynamic {
|
||||
ptr_to_base_ptr,
|
||||
ptr_to_bounds,
|
||||
minimum,
|
||||
maximum,
|
||||
},
|
||||
MemoryType::Static | MemoryType::SharedStatic => MemoryCache::Static {
|
||||
base_ptr: cache_builder
|
||||
MemoryType::Static | MemoryType::SharedStatic => {
|
||||
let base_ptr = cache_builder
|
||||
.build_load(ptr_to_base_ptr, "base")
|
||||
.into_pointer_value(),
|
||||
bounds: cache_builder
|
||||
.into_pointer_value();
|
||||
let bounds = cache_builder
|
||||
.build_load(ptr_to_bounds, "bounds")
|
||||
.into_int_value(),
|
||||
},
|
||||
.into_int_value();
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"static_memory_base",
|
||||
base_ptr.as_instruction_value().unwrap(),
|
||||
Some(index as u32),
|
||||
);
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"static_memory_bounds",
|
||||
bounds.as_instruction_value().unwrap(),
|
||||
Some(index as u32),
|
||||
);
|
||||
MemoryCache::Static {
|
||||
base_ptr,
|
||||
bounds,
|
||||
minimum,
|
||||
maximum,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -730,6 +786,7 @@ impl<'a> CtxType<'a> {
|
||||
&mut self,
|
||||
index: TableIndex,
|
||||
intrinsics: &Intrinsics,
|
||||
module: Rc<RefCell<Module>>,
|
||||
) -> (PointerValue, PointerValue) {
|
||||
let (cached_tables, info, ctx_ptr_value, cache_builder) = (
|
||||
&mut self.cached_tables,
|
||||
@ -742,7 +799,7 @@ impl<'a> CtxType<'a> {
|
||||
ptr_to_base_ptr,
|
||||
ptr_to_bounds,
|
||||
} = *cached_tables.entry(index).or_insert_with(|| {
|
||||
let (table_array_ptr_ptr, index) = match index.local_or_import(info) {
|
||||
let (table_array_ptr_ptr, index, field_name) = match index.local_or_import(info) {
|
||||
LocalOrImport::Local(local_table_index) => (
|
||||
unsafe {
|
||||
cache_builder.build_struct_gep(
|
||||
@ -752,6 +809,7 @@ impl<'a> CtxType<'a> {
|
||||
)
|
||||
},
|
||||
local_table_index.index() as u64,
|
||||
"context_field_ptr_to_local_table",
|
||||
),
|
||||
LocalOrImport::Import(import_table_index) => (
|
||||
unsafe {
|
||||
@ -762,12 +820,20 @@ impl<'a> CtxType<'a> {
|
||||
)
|
||||
},
|
||||
import_table_index.index() as u64,
|
||||
"context_field_ptr_to_import_table",
|
||||
),
|
||||
};
|
||||
|
||||
let table_array_ptr = cache_builder
|
||||
.build_load(table_array_ptr_ptr, "table_array_ptr")
|
||||
.into_pointer_value();
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
field_name,
|
||||
table_array_ptr.as_instruction_value().unwrap(),
|
||||
None,
|
||||
);
|
||||
let const_index = intrinsics.i32_ty.const_int(index, false);
|
||||
let table_ptr_ptr = unsafe {
|
||||
cache_builder.build_in_bounds_gep(table_array_ptr, &[const_index], "table_ptr_ptr")
|
||||
@ -775,6 +841,13 @@ impl<'a> CtxType<'a> {
|
||||
let table_ptr = cache_builder
|
||||
.build_load(table_ptr_ptr, "table_ptr")
|
||||
.into_pointer_value();
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"table_ptr",
|
||||
table_array_ptr.as_instruction_value().unwrap(),
|
||||
Some(index as u32),
|
||||
);
|
||||
|
||||
let (ptr_to_base_ptr, ptr_to_bounds) = unsafe {
|
||||
(
|
||||
@ -796,15 +869,30 @@ impl<'a> CtxType<'a> {
|
||||
&mut self,
|
||||
index: TableIndex,
|
||||
intrinsics: &Intrinsics,
|
||||
module: Rc<RefCell<Module>>,
|
||||
builder: &Builder,
|
||||
) -> (PointerValue, IntValue) {
|
||||
let (ptr_to_base_ptr, ptr_to_bounds) = self.table_prepare(index, intrinsics);
|
||||
(
|
||||
builder
|
||||
.build_load(ptr_to_base_ptr, "base_ptr")
|
||||
.into_pointer_value(),
|
||||
builder.build_load(ptr_to_bounds, "bounds").into_int_value(),
|
||||
)
|
||||
let (ptr_to_base_ptr, ptr_to_bounds) =
|
||||
self.table_prepare(index, intrinsics, module.clone());
|
||||
let base_ptr = builder
|
||||
.build_load(ptr_to_base_ptr, "base_ptr")
|
||||
.into_pointer_value();
|
||||
let bounds = builder.build_load(ptr_to_bounds, "bounds").into_int_value();
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"table_base_ptr",
|
||||
base_ptr.as_instruction_value().unwrap(),
|
||||
Some(index.index() as u32),
|
||||
);
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"table_bounds",
|
||||
bounds.as_instruction_value().unwrap(),
|
||||
Some(index.index() as u32),
|
||||
);
|
||||
(base_ptr, bounds)
|
||||
}
|
||||
|
||||
pub fn local_func(
|
||||
@ -812,6 +900,7 @@ impl<'a> CtxType<'a> {
|
||||
index: LocalFuncIndex,
|
||||
fn_ty: FunctionType,
|
||||
intrinsics: &Intrinsics,
|
||||
module: Rc<RefCell<Module>>,
|
||||
builder: &Builder,
|
||||
) -> PointerValue {
|
||||
let local_func_array_ptr_ptr = unsafe {
|
||||
@ -824,6 +913,13 @@ impl<'a> CtxType<'a> {
|
||||
let local_func_array_ptr = builder
|
||||
.build_load(local_func_array_ptr_ptr, "local_func_array_ptr")
|
||||
.into_pointer_value();
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"context_field_ptr_to_local_funcs",
|
||||
local_func_array_ptr.as_instruction_value().unwrap(),
|
||||
None,
|
||||
);
|
||||
let local_func_ptr_ptr = unsafe {
|
||||
builder.build_in_bounds_gep(
|
||||
local_func_array_ptr,
|
||||
@ -834,6 +930,13 @@ impl<'a> CtxType<'a> {
|
||||
let local_func_ptr = builder
|
||||
.build_load(local_func_ptr_ptr, "local_func_ptr")
|
||||
.into_pointer_value();
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"local_func_ptr",
|
||||
local_func_ptr.as_instruction_value().unwrap(),
|
||||
Some(index.index() as u32),
|
||||
);
|
||||
builder.build_pointer_cast(
|
||||
local_func_ptr,
|
||||
fn_ty.ptr_type(AddressSpace::Generic),
|
||||
@ -875,7 +978,12 @@ impl<'a> CtxType<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn global_cache(&mut self, index: GlobalIndex, intrinsics: &Intrinsics) -> GlobalCache {
|
||||
pub fn global_cache(
|
||||
&mut self,
|
||||
index: GlobalIndex,
|
||||
intrinsics: &Intrinsics,
|
||||
module: Rc<RefCell<Module>>,
|
||||
) -> GlobalCache {
|
||||
let (cached_globals, ctx_ptr_value, info, cache_builder) = (
|
||||
&mut self.cached_globals,
|
||||
self.ctx_ptr_value,
|
||||
@ -884,7 +992,7 @@ impl<'a> CtxType<'a> {
|
||||
);
|
||||
|
||||
*cached_globals.entry(index).or_insert_with(|| {
|
||||
let (globals_array_ptr_ptr, index, mutable, wasmer_ty) =
|
||||
let (globals_array_ptr_ptr, index, mutable, wasmer_ty, field_name) =
|
||||
match index.local_or_import(info) {
|
||||
LocalOrImport::Local(local_global_index) => {
|
||||
let desc = info.globals[local_global_index].desc;
|
||||
@ -899,6 +1007,7 @@ impl<'a> CtxType<'a> {
|
||||
local_global_index.index() as u64,
|
||||
desc.mutable,
|
||||
desc.ty,
|
||||
"context_field_ptr_to_local_globals",
|
||||
)
|
||||
}
|
||||
LocalOrImport::Import(import_global_index) => {
|
||||
@ -914,6 +1023,7 @@ impl<'a> CtxType<'a> {
|
||||
import_global_index.index() as u64,
|
||||
desc.mutable,
|
||||
desc.ty,
|
||||
"context_field_ptr_to_imported_globals",
|
||||
)
|
||||
}
|
||||
};
|
||||
@ -923,6 +1033,13 @@ impl<'a> CtxType<'a> {
|
||||
let global_array_ptr = cache_builder
|
||||
.build_load(globals_array_ptr_ptr, "global_array_ptr")
|
||||
.into_pointer_value();
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
field_name,
|
||||
globals_array_ptr_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(
|
||||
@ -934,6 +1051,13 @@ impl<'a> CtxType<'a> {
|
||||
let global_ptr = cache_builder
|
||||
.build_load(global_ptr_ptr, "global_ptr")
|
||||
.into_pointer_value();
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"global_ptr",
|
||||
globals_array_ptr_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");
|
||||
@ -943,9 +1067,15 @@ impl<'a> CtxType<'a> {
|
||||
ptr_to_value: global_ptr_typed,
|
||||
}
|
||||
} else {
|
||||
GlobalCache::Const {
|
||||
value: cache_builder.build_load(global_ptr_typed, "global_value"),
|
||||
}
|
||||
let value = cache_builder.build_load(global_ptr_typed, "global_value");
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"global",
|
||||
value.as_instruction_value().unwrap(),
|
||||
Some(index as u32),
|
||||
);
|
||||
GlobalCache::Const { value }
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -954,6 +1084,7 @@ impl<'a> CtxType<'a> {
|
||||
&mut self,
|
||||
index: ImportedFuncIndex,
|
||||
intrinsics: &Intrinsics,
|
||||
module: Rc<RefCell<Module>>,
|
||||
) -> (PointerValue, PointerValue) {
|
||||
let (cached_imported_functions, ctx_ptr_value, cache_builder) = (
|
||||
&mut self.cached_imported_functions,
|
||||
@ -972,6 +1103,13 @@ impl<'a> CtxType<'a> {
|
||||
let func_array_ptr = cache_builder
|
||||
.build_load(func_array_ptr_ptr, "func_array_ptr")
|
||||
.into_pointer_value();
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"context_field_ptr_to_imported_funcs",
|
||||
func_array_ptr.as_instruction_value().unwrap(),
|
||||
None,
|
||||
);
|
||||
let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false);
|
||||
let imported_func_ptr = unsafe {
|
||||
cache_builder.build_in_bounds_gep(
|
||||
@ -993,6 +1131,20 @@ impl<'a> CtxType<'a> {
|
||||
let ctx_ptr = cache_builder
|
||||
.build_load(ctx_ptr_ptr, "ctx_ptr")
|
||||
.into_pointer_value();
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"imported_func_ptr",
|
||||
func_ptr.as_instruction_value().unwrap(),
|
||||
Some(index.index() as u32),
|
||||
);
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"imported_func_ctx_ptr",
|
||||
ctx_ptr.as_instruction_value().unwrap(),
|
||||
Some(index.index() as u32),
|
||||
);
|
||||
|
||||
ImportedFuncCache { func_ptr, ctx_ptr }
|
||||
});
|
||||
@ -1004,6 +1156,7 @@ impl<'a> CtxType<'a> {
|
||||
&mut self,
|
||||
index: usize,
|
||||
intrinsics: &Intrinsics,
|
||||
module: Rc<RefCell<Module>>,
|
||||
builder: &Builder,
|
||||
) -> PointerValue {
|
||||
assert!(index < INTERNALS_SIZE);
|
||||
@ -1018,6 +1171,13 @@ impl<'a> CtxType<'a> {
|
||||
let local_internals_ptr = builder
|
||||
.build_load(local_internals_ptr_ptr, "local_internals_ptr")
|
||||
.into_pointer_value();
|
||||
tbaa_label(
|
||||
module.clone(),
|
||||
intrinsics,
|
||||
"context_field_ptr_to_internals",
|
||||
local_internals_ptr_ptr.as_instruction_value().unwrap(),
|
||||
None,
|
||||
);
|
||||
unsafe {
|
||||
builder.build_in_bounds_gep(
|
||||
local_internals_ptr,
|
||||
@ -1027,3 +1187,83 @@ impl<'a> CtxType<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Given an instruction that operates on memory, mark the access as not aliasing
|
||||
// other memory accesses which have a different (label, index) pair.
|
||||
pub fn tbaa_label(
|
||||
module: Rc<RefCell<Module>>,
|
||||
intrinsics: &Intrinsics,
|
||||
label: &str,
|
||||
instruction: InstructionValue,
|
||||
index: Option<u32>,
|
||||
) {
|
||||
// To convey to LLVM that two pointers must be pointing to distinct memory,
|
||||
// we use LLVM's Type Based Aliasing Analysis, or TBAA, to mark the memory
|
||||
// operations as having different types whose pointers may not alias.
|
||||
//
|
||||
// See the LLVM documentation at
|
||||
// https://llvm.org/docs/LangRef.html#tbaa-metadata
|
||||
//
|
||||
// LLVM TBAA supports many features, but we use it in a simple way, with
|
||||
// only scalar types that are children of the root node. Every TBAA type we
|
||||
// declare is NoAlias with the others. See NoAlias, PartialAlias,
|
||||
// MayAlias and MustAlias in the LLVM documentation:
|
||||
// https://llvm.org/docs/AliasAnalysis.html#must-may-and-no-alias-responses
|
||||
|
||||
let module = module.borrow_mut();
|
||||
let context = module.get_context();
|
||||
|
||||
// `!wasmer_tbaa_root = {}`, the TBAA root node for wasmer.
|
||||
let tbaa_root = module
|
||||
.get_global_metadata("wasmer_tbaa_root")
|
||||
.pop()
|
||||
.unwrap_or_else(|| {
|
||||
module.add_global_metadata("wasmer_tbaa_root", &MetadataValue::create_node(&[]));
|
||||
module.get_global_metadata("wasmer_tbaa_root")[0]
|
||||
});
|
||||
|
||||
// Construct (or look up) the type descriptor, for example
|
||||
// `!"local 0" = !{!"local 0", !wasmer_tbaa_root}`.
|
||||
let label = if let Some(idx) = index {
|
||||
format!("{}{}", label, idx)
|
||||
} else {
|
||||
label.to_string()
|
||||
};
|
||||
let type_label = context.metadata_string(label.as_str());
|
||||
let type_tbaa = module
|
||||
.get_global_metadata(label.as_str())
|
||||
.pop()
|
||||
.unwrap_or_else(|| {
|
||||
module.add_global_metadata(
|
||||
label.as_str(),
|
||||
&MetadataValue::create_node(&[type_label.into(), tbaa_root.into()]),
|
||||
);
|
||||
module.get_global_metadata(label.as_str())[0]
|
||||
});
|
||||
|
||||
// Construct (or look up) the access tag, which is a struct of the form
|
||||
// (base type, access type, offset).
|
||||
//
|
||||
// "If BaseTy is a scalar type, Offset must be 0 and BaseTy and AccessTy
|
||||
// must be the same".
|
||||
// -- https://llvm.org/docs/LangRef.html#tbaa-metadata
|
||||
let label = label + "_memop";
|
||||
let type_tbaa = module
|
||||
.get_global_metadata(label.as_str())
|
||||
.pop()
|
||||
.unwrap_or_else(|| {
|
||||
module.add_global_metadata(
|
||||
label.as_str(),
|
||||
&MetadataValue::create_node(&[
|
||||
type_tbaa.into(),
|
||||
type_tbaa.into(),
|
||||
intrinsics.i64_zero.into(),
|
||||
]),
|
||||
);
|
||||
module.get_global_metadata(label.as_str())[0]
|
||||
});
|
||||
|
||||
// Attach the access tag to the instruction.
|
||||
let tbaa_kind = context.get_kind_id("tbaa");
|
||||
instruction.set_metadata(type_tbaa, tbaa_kind);
|
||||
}
|
||||
|
Reference in New Issue
Block a user