mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-21 20:51:32 +00:00
Merge branch 'master' into feature/llvm-nan-but-fast
This commit is contained in:
@ -1,17 +1,16 @@
|
||||
[package]
|
||||
name = "wasmer-llvm-backend"
|
||||
version = "0.8.0"
|
||||
version = "0.9.0"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
edition = "2018"
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.8.0" }
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.9.0" }
|
||||
wasmparser = "0.39.1"
|
||||
smallvec = "0.6"
|
||||
goblin = "0.0.24"
|
||||
libc = "0.2.60"
|
||||
capstone = { version = "0.6", optional = true }
|
||||
byteorder = "1"
|
||||
|
||||
[dependencies.inkwell]
|
||||
@ -38,4 +37,3 @@ wabt = "0.9.1"
|
||||
|
||||
[features]
|
||||
debug = ["wasmer-runtime-core/debug"]
|
||||
disasm = ["capstone"]
|
||||
|
@ -4,8 +4,7 @@ use crate::structs::{Callbacks, LLVMModule, LLVMResult, MemProtect};
|
||||
use inkwell::{
|
||||
memory_buffer::MemoryBuffer,
|
||||
module::Module,
|
||||
targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine},
|
||||
OptimizationLevel,
|
||||
targets::{FileType, TargetMachine},
|
||||
};
|
||||
use libc::c_char;
|
||||
use std::{
|
||||
@ -172,28 +171,8 @@ impl LLVMBackend {
|
||||
_intrinsics: Intrinsics,
|
||||
_stackmaps: &StackmapRegistry,
|
||||
_module_info: &ModuleInfo,
|
||||
target_machine: &TargetMachine,
|
||||
) -> (Self, LLVMCache) {
|
||||
Target::initialize_x86(&InitializationConfig {
|
||||
asm_parser: true,
|
||||
asm_printer: true,
|
||||
base: true,
|
||||
disassembler: true,
|
||||
info: true,
|
||||
machine_code: true,
|
||||
});
|
||||
let triple = TargetMachine::get_default_triple().to_string();
|
||||
let target = Target::from_triple(&triple).unwrap();
|
||||
let target_machine = target
|
||||
.create_target_machine(
|
||||
&triple,
|
||||
&TargetMachine::get_host_cpu_name().to_string(),
|
||||
&TargetMachine::get_host_cpu_features().to_string(),
|
||||
OptimizationLevel::Aggressive,
|
||||
RelocMode::Static,
|
||||
CodeModel::Large,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let memory_buffer = target_machine
|
||||
.write_to_memory_buffer(&module, FileType::Object)
|
||||
.unwrap();
|
||||
@ -477,33 +456,3 @@ impl CacheGen for LLVMCache {
|
||||
Ok(([].as_ref().into(), memory))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "disasm")]
|
||||
unsafe fn disass_ptr(ptr: *const u8, size: usize, inst_count: usize) {
|
||||
use capstone::arch::BuildsCapstone;
|
||||
let mut cs = capstone::Capstone::new() // Call builder-pattern
|
||||
.x86() // X86 architecture
|
||||
.mode(capstone::arch::x86::ArchMode::Mode64) // 64-bit mode
|
||||
.detail(true) // Generate extra instruction details
|
||||
.build()
|
||||
.expect("Failed to create Capstone object");
|
||||
|
||||
// Get disassembled instructions
|
||||
let insns = cs
|
||||
.disasm_count(
|
||||
std::slice::from_raw_parts(ptr, size),
|
||||
ptr as u64,
|
||||
inst_count,
|
||||
)
|
||||
.expect("Failed to disassemble");
|
||||
|
||||
println!("count = {}", insns.len());
|
||||
for insn in insns.iter() {
|
||||
println!(
|
||||
"0x{:x}: {:6} {}",
|
||||
insn.address(),
|
||||
insn.mnemonic().unwrap_or(""),
|
||||
insn.op_str().unwrap_or("")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -3,19 +3,20 @@ use inkwell::{
|
||||
context::Context,
|
||||
module::{Linkage, Module},
|
||||
passes::PassManager,
|
||||
targets::{CodeModel, InitializationConfig, RelocMode, Target, TargetMachine},
|
||||
types::{BasicType, BasicTypeEnum, FunctionType, PointerType, VectorType},
|
||||
values::{
|
||||
BasicValue, BasicValueEnum, FloatValue, FunctionValue, IntValue, PhiValue, PointerValue,
|
||||
VectorValue,
|
||||
},
|
||||
AddressSpace, AtomicOrdering, AtomicRMWBinOp, FloatPredicate, IntPredicate,
|
||||
AddressSpace, AtomicOrdering, AtomicRMWBinOp, FloatPredicate, IntPredicate, OptimizationLevel,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use wasmer_runtime_core::{
|
||||
backend::{Backend, CacheGen, Token},
|
||||
backend::{Backend, CacheGen, CompilerConfig, Token},
|
||||
cache::{Artifact, Error as CacheError},
|
||||
codegen::*,
|
||||
memory::MemoryType,
|
||||
@ -558,17 +559,9 @@ fn resolve_memory_ptr(
|
||||
ptr_ty: PointerType,
|
||||
value_size: usize,
|
||||
) -> Result<PointerValue, BinaryReaderError> {
|
||||
// Ignore alignment hint for the time being.
|
||||
let imm_offset = intrinsics.i64_ty.const_int(memarg.offset as u64, false);
|
||||
let value_size_v = intrinsics.i64_ty.const_int(value_size as u64, false);
|
||||
let var_offset_i32 = state.pop1()?.into_int_value();
|
||||
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 end_offset = builder.build_int_add(effective_offset, value_size_v, &state.var_name());
|
||||
// Look up the memory base (as pointer) and bounds (as unsigned integer).
|
||||
let memory_cache = ctx.memory(MemoryIndex::new(0), intrinsics);
|
||||
|
||||
let mem_base_int = match memory_cache {
|
||||
let (mem_base, mem_bound) = match memory_cache {
|
||||
MemoryCache::Dynamic {
|
||||
ptr_to_base_ptr,
|
||||
ptr_to_bounds,
|
||||
@ -577,66 +570,71 @@ fn resolve_memory_ptr(
|
||||
.build_load(ptr_to_base_ptr, "base")
|
||||
.into_pointer_value();
|
||||
let bounds = builder.build_load(ptr_to_bounds, "bounds").into_int_value();
|
||||
|
||||
let base_as_int = builder.build_ptr_to_int(base, intrinsics.i64_ty, "base_as_int");
|
||||
|
||||
let base_in_bounds_1 = builder.build_int_compare(
|
||||
IntPredicate::ULE,
|
||||
end_offset,
|
||||
bounds,
|
||||
"base_in_bounds_1",
|
||||
);
|
||||
let base_in_bounds_2 = builder.build_int_compare(
|
||||
IntPredicate::ULT,
|
||||
effective_offset,
|
||||
end_offset,
|
||||
"base_in_bounds_2",
|
||||
);
|
||||
let base_in_bounds =
|
||||
builder.build_and(base_in_bounds_1, base_in_bounds_2, "base_in_bounds");
|
||||
|
||||
let base_in_bounds = builder
|
||||
.build_call(
|
||||
intrinsics.expect_i1,
|
||||
&[
|
||||
base_in_bounds.as_basic_value_enum(),
|
||||
intrinsics.i1_ty.const_int(1, false).as_basic_value_enum(),
|
||||
],
|
||||
"base_in_bounds_expect",
|
||||
)
|
||||
.try_as_basic_value()
|
||||
.left()
|
||||
.unwrap()
|
||||
.into_int_value();
|
||||
|
||||
let in_bounds_continue_block =
|
||||
context.append_basic_block(function, "in_bounds_continue_block");
|
||||
let not_in_bounds_block = context.append_basic_block(function, "not_in_bounds_block");
|
||||
builder.build_conditional_branch(
|
||||
base_in_bounds,
|
||||
&in_bounds_continue_block,
|
||||
¬_in_bounds_block,
|
||||
);
|
||||
builder.position_at_end(¬_in_bounds_block);
|
||||
builder.build_call(
|
||||
intrinsics.throw_trap,
|
||||
&[intrinsics.trap_memory_oob],
|
||||
"throw",
|
||||
);
|
||||
builder.build_unreachable();
|
||||
builder.position_at_end(&in_bounds_continue_block);
|
||||
|
||||
base_as_int
|
||||
(base, bounds)
|
||||
}
|
||||
MemoryCache::Static {
|
||||
base_ptr,
|
||||
bounds: _,
|
||||
} => builder.build_ptr_to_int(base_ptr, intrinsics.i64_ty, "base_as_int"),
|
||||
MemoryCache::Static { base_ptr, bounds } => (base_ptr, bounds),
|
||||
};
|
||||
let mem_base = builder
|
||||
.build_bitcast(mem_base, intrinsics.i8_ptr_ty, &state.var_name())
|
||||
.into_pointer_value();
|
||||
|
||||
let effective_address_int =
|
||||
builder.build_int_add(mem_base_int, effective_offset, &state.var_name());
|
||||
Ok(builder.build_int_to_ptr(effective_address_int, ptr_ty, &state.var_name()))
|
||||
// Compute the offset over the memory_base.
|
||||
let imm_offset = intrinsics.i64_ty.const_int(memarg.offset as u64, false);
|
||||
let var_offset_i32 = state.pop1()?.into_int_value();
|
||||
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());
|
||||
|
||||
if let MemoryCache::Dynamic { .. } = memory_cache {
|
||||
// If the memory is dynamic, do a bounds check. For static we rely on
|
||||
// the size being a multiple of the page size and hitting a reserved
|
||||
// but unreadable memory.
|
||||
let value_size_v = intrinsics.i64_ty.const_int(value_size as u64, false);
|
||||
let load_offset_end =
|
||||
builder.build_int_add(effective_offset, value_size_v, &state.var_name());
|
||||
|
||||
let ptr_in_bounds = builder.build_int_compare(
|
||||
IntPredicate::ULE,
|
||||
load_offset_end,
|
||||
mem_bound,
|
||||
&state.var_name(),
|
||||
);
|
||||
let ptr_in_bounds = builder
|
||||
.build_call(
|
||||
intrinsics.expect_i1,
|
||||
&[
|
||||
ptr_in_bounds.as_basic_value_enum(),
|
||||
intrinsics.i1_ty.const_int(1, false).as_basic_value_enum(),
|
||||
],
|
||||
"ptr_in_bounds_expect",
|
||||
)
|
||||
.try_as_basic_value()
|
||||
.left()
|
||||
.unwrap()
|
||||
.into_int_value();
|
||||
|
||||
let in_bounds_continue_block =
|
||||
context.append_basic_block(function, "in_bounds_continue_block");
|
||||
let not_in_bounds_block = context.append_basic_block(function, "not_in_bounds_block");
|
||||
builder.build_conditional_branch(
|
||||
ptr_in_bounds,
|
||||
&in_bounds_continue_block,
|
||||
¬_in_bounds_block,
|
||||
);
|
||||
builder.position_at_end(¬_in_bounds_block);
|
||||
builder.build_call(
|
||||
intrinsics.throw_trap,
|
||||
&[intrinsics.trap_memory_oob],
|
||||
"throw",
|
||||
);
|
||||
builder.build_unreachable();
|
||||
builder.position_at_end(&in_bounds_continue_block);
|
||||
}
|
||||
|
||||
let ptr = unsafe { builder.build_gep(mem_base, &[effective_offset], &state.var_name()) };
|
||||
Ok(builder
|
||||
.build_bitcast(ptr, ptr_ty, &state.var_name())
|
||||
.into_pointer_value())
|
||||
}
|
||||
|
||||
fn emit_stack_map(
|
||||
@ -808,11 +806,14 @@ pub struct LLVMModuleCodeGenerator {
|
||||
personality_func: FunctionValue,
|
||||
module: Module,
|
||||
stackmaps: Rc<RefCell<StackmapRegistry>>,
|
||||
track_state: bool,
|
||||
target_machine: TargetMachine,
|
||||
}
|
||||
|
||||
pub struct LLVMFunctionCodeGenerator {
|
||||
context: Option<Context>,
|
||||
builder: Option<Builder>,
|
||||
alloca_builder: Option<Builder>,
|
||||
intrinsics: Option<Intrinsics>,
|
||||
state: State,
|
||||
function: FunctionValue,
|
||||
@ -825,6 +826,7 @@ pub struct LLVMFunctionCodeGenerator {
|
||||
stackmaps: Rc<RefCell<StackmapRegistry>>,
|
||||
index: usize,
|
||||
opcode_offset: usize,
|
||||
track_state: bool,
|
||||
}
|
||||
|
||||
impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
|
||||
@ -836,12 +838,9 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), CodegenError> {
|
||||
fn feed_local(&mut self, ty: WpType, count: usize) -> Result<(), CodegenError> {
|
||||
let param_len = self.num_params;
|
||||
|
||||
let mut local_idx = 0;
|
||||
// let (count, ty) = local?;
|
||||
let count = n;
|
||||
let wasmer_ty = type_to_type(ty)?;
|
||||
|
||||
let intrinsics = self.intrinsics.as_ref().unwrap();
|
||||
@ -856,14 +855,22 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
|
||||
};
|
||||
|
||||
let builder = self.builder.as_ref().unwrap();
|
||||
let alloca_builder = self.alloca_builder.as_ref().unwrap();
|
||||
|
||||
for _ in 0..count {
|
||||
let alloca = builder.build_alloca(ty, &format!("local{}", param_len + local_idx));
|
||||
|
||||
for local_idx in 0..count {
|
||||
let alloca =
|
||||
alloca_builder.build_alloca(ty, &format!("local{}", param_len + local_idx));
|
||||
builder.build_store(alloca, default_value);
|
||||
|
||||
if local_idx == 0 {
|
||||
alloca_builder.position_before(
|
||||
&alloca
|
||||
.as_instruction()
|
||||
.unwrap()
|
||||
.get_next_instruction()
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
self.locals.push(alloca);
|
||||
local_idx += 1;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -900,27 +907,29 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
|
||||
let builder = self.builder.as_ref().unwrap();
|
||||
let intrinsics = self.intrinsics.as_ref().unwrap();
|
||||
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
emit_stack_map(
|
||||
&module_info,
|
||||
&intrinsics,
|
||||
&builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::FunctionHeader,
|
||||
&self.locals,
|
||||
&state,
|
||||
self.ctx.as_mut().unwrap(),
|
||||
::std::usize::MAX,
|
||||
);
|
||||
finalize_opcode_stack_map(
|
||||
&intrinsics,
|
||||
&builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::FunctionHeader,
|
||||
::std::usize::MAX,
|
||||
);
|
||||
if self.track_state {
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
emit_stack_map(
|
||||
&module_info,
|
||||
&intrinsics,
|
||||
&builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::FunctionHeader,
|
||||
&self.locals,
|
||||
&state,
|
||||
self.ctx.as_mut().unwrap(),
|
||||
::std::usize::MAX,
|
||||
);
|
||||
finalize_opcode_stack_map(
|
||||
&intrinsics,
|
||||
&builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::FunctionHeader,
|
||||
::std::usize::MAX,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -1050,33 +1059,35 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
|
||||
|
||||
builder.position_at_end(&loop_body);
|
||||
|
||||
if let Some(offset) = opcode_offset {
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
emit_stack_map(
|
||||
&info,
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Loop,
|
||||
&self.locals,
|
||||
state,
|
||||
ctx,
|
||||
offset,
|
||||
);
|
||||
let signal_mem = ctx.signal_mem();
|
||||
let iv = builder
|
||||
.build_store(signal_mem, context.i8_type().const_int(0 as u64, false));
|
||||
// Any 'store' can be made volatile.
|
||||
iv.set_volatile(true).unwrap();
|
||||
finalize_opcode_stack_map(
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Loop,
|
||||
offset,
|
||||
);
|
||||
if self.track_state {
|
||||
if let Some(offset) = opcode_offset {
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
emit_stack_map(
|
||||
&info,
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Loop,
|
||||
&self.locals,
|
||||
state,
|
||||
ctx,
|
||||
offset,
|
||||
);
|
||||
let signal_mem = ctx.signal_mem();
|
||||
let iv = builder
|
||||
.build_store(signal_mem, context.i8_type().const_int(0 as u64, false));
|
||||
// Any 'store' can be made volatile.
|
||||
iv.set_volatile(true).unwrap();
|
||||
finalize_opcode_stack_map(
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Loop,
|
||||
offset,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
state.push_loop(loop_body, loop_next, phis);
|
||||
@ -1358,28 +1369,30 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
|
||||
// Comment out this `if` block to allow spectests to pass.
|
||||
// TODO: fix this
|
||||
if let Some(offset) = opcode_offset {
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
emit_stack_map(
|
||||
&info,
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Trappable,
|
||||
&self.locals,
|
||||
state,
|
||||
ctx,
|
||||
offset,
|
||||
);
|
||||
builder.build_call(intrinsics.trap, &[], "trap");
|
||||
finalize_opcode_stack_map(
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Trappable,
|
||||
offset,
|
||||
);
|
||||
if self.track_state {
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
emit_stack_map(
|
||||
&info,
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Trappable,
|
||||
&self.locals,
|
||||
state,
|
||||
ctx,
|
||||
offset,
|
||||
);
|
||||
builder.build_call(intrinsics.trap, &[], "trap");
|
||||
finalize_opcode_stack_map(
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Trappable,
|
||||
offset,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
builder.build_call(
|
||||
@ -1659,32 +1672,36 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
|
||||
};
|
||||
|
||||
state.popn(func_sig.params().len())?;
|
||||
if let Some(offset) = opcode_offset {
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
emit_stack_map(
|
||||
&info,
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Call,
|
||||
&self.locals,
|
||||
state,
|
||||
ctx,
|
||||
offset,
|
||||
)
|
||||
if self.track_state {
|
||||
if let Some(offset) = opcode_offset {
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
emit_stack_map(
|
||||
&info,
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Call,
|
||||
&self.locals,
|
||||
state,
|
||||
ctx,
|
||||
offset,
|
||||
)
|
||||
}
|
||||
}
|
||||
let call_site = builder.build_call(func_ptr, ¶ms, &state.var_name());
|
||||
if let Some(offset) = opcode_offset {
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
finalize_opcode_stack_map(
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Call,
|
||||
offset,
|
||||
)
|
||||
if self.track_state {
|
||||
if let Some(offset) = opcode_offset {
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
finalize_opcode_stack_map(
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Call,
|
||||
offset,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(basic_value) = call_site.try_as_basic_value().left() {
|
||||
@ -1875,32 +1892,36 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
|
||||
"typed_func_ptr",
|
||||
);
|
||||
|
||||
if let Some(offset) = opcode_offset {
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
emit_stack_map(
|
||||
&info,
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Call,
|
||||
&self.locals,
|
||||
state,
|
||||
ctx,
|
||||
offset,
|
||||
)
|
||||
if self.track_state {
|
||||
if let Some(offset) = opcode_offset {
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
emit_stack_map(
|
||||
&info,
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Call,
|
||||
&self.locals,
|
||||
state,
|
||||
ctx,
|
||||
offset,
|
||||
)
|
||||
}
|
||||
}
|
||||
let call_site = builder.build_call(typed_func_ptr, &args, "indirect_call");
|
||||
if let Some(offset) = opcode_offset {
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
finalize_opcode_stack_map(
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Call,
|
||||
offset,
|
||||
)
|
||||
if self.track_state {
|
||||
if let Some(offset) = opcode_offset {
|
||||
let mut stackmaps = self.stackmaps.borrow_mut();
|
||||
finalize_opcode_stack_map(
|
||||
intrinsics,
|
||||
builder,
|
||||
self.index,
|
||||
&mut *stackmaps,
|
||||
StackmapEntryKind::Call,
|
||||
offset,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
match wasmer_fn_sig.returns() {
|
||||
@ -7260,6 +7281,31 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
fn new() -> LLVMModuleCodeGenerator {
|
||||
let context = Context::create();
|
||||
let module = context.create_module("module");
|
||||
|
||||
Target::initialize_x86(&InitializationConfig {
|
||||
asm_parser: true,
|
||||
asm_printer: true,
|
||||
base: true,
|
||||
disassembler: true,
|
||||
info: true,
|
||||
machine_code: true,
|
||||
});
|
||||
let triple = TargetMachine::get_default_triple().to_string();
|
||||
let target = Target::from_triple(&triple).unwrap();
|
||||
let target_machine = target
|
||||
.create_target_machine(
|
||||
&triple,
|
||||
&TargetMachine::get_host_cpu_name().to_string(),
|
||||
&TargetMachine::get_host_cpu_features().to_string(),
|
||||
OptimizationLevel::Aggressive,
|
||||
RelocMode::Static,
|
||||
CodeModel::Large,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
module.set_target(&target);
|
||||
module.set_data_layout(&target_machine.get_target_data().get_data_layout());
|
||||
|
||||
let builder = context.create_builder();
|
||||
|
||||
let intrinsics = Intrinsics::declare(&module, &context);
|
||||
@ -7284,6 +7330,8 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
func_import_count: 0,
|
||||
personality_func,
|
||||
stackmaps: Rc::new(RefCell::new(StackmapRegistry::default())),
|
||||
track_state: false,
|
||||
target_machine: target_machine,
|
||||
}
|
||||
}
|
||||
|
||||
@ -7326,6 +7374,8 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
|
||||
let mut state = State::new();
|
||||
let entry_block = context.append_basic_block(&function, "entry");
|
||||
let alloca_builder = context.create_builder();
|
||||
alloca_builder.position_at_end(&entry_block);
|
||||
|
||||
let return_block = context.append_basic_block(&function, "return");
|
||||
builder.position_at_end(&return_block);
|
||||
@ -7347,20 +7397,23 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
.skip(1)
|
||||
.enumerate()
|
||||
.map(|(index, param)| {
|
||||
//let ty = param.get_type();
|
||||
let real_ty = func_sig.params()[index];
|
||||
let real_ty_llvm = type_to_llvm(&intrinsics, real_ty);
|
||||
|
||||
let alloca = builder.build_alloca(real_ty_llvm, &format!("local{}", index));
|
||||
|
||||
//if real_ty_llvm != ty {
|
||||
let alloca =
|
||||
alloca_builder.build_alloca(real_ty_llvm, &format!("local{}", index));
|
||||
builder.build_store(
|
||||
alloca,
|
||||
builder.build_bitcast(param, real_ty_llvm, &state.var_name()),
|
||||
);
|
||||
/*} else {
|
||||
builder.build_store(alloca, param);
|
||||
}*/
|
||||
if index == 0 {
|
||||
alloca_builder.position_before(
|
||||
&alloca
|
||||
.as_instruction()
|
||||
.unwrap()
|
||||
.get_next_instruction()
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
alloca
|
||||
}),
|
||||
);
|
||||
@ -7372,6 +7425,7 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
state,
|
||||
context: Some(context),
|
||||
builder: Some(builder),
|
||||
alloca_builder: Some(alloca_builder),
|
||||
intrinsics: Some(intrinsics),
|
||||
function,
|
||||
func_sig: func_sig,
|
||||
@ -7383,6 +7437,7 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
stackmaps: self.stackmaps.clone(),
|
||||
index: local_func_index,
|
||||
opcode_offset: 0,
|
||||
track_state: self.track_state,
|
||||
};
|
||||
self.functions.push(code);
|
||||
Ok(self.functions.last_mut().unwrap())
|
||||
@ -7454,10 +7509,16 @@ impl ModuleCodeGenerator<LLVMFunctionCodeGenerator, LLVMBackend, CodegenError>
|
||||
self.intrinsics.take().unwrap(),
|
||||
&*stackmaps,
|
||||
module_info,
|
||||
&self.target_machine,
|
||||
);
|
||||
Ok((backend, Box::new(cache_gen)))
|
||||
}
|
||||
|
||||
fn feed_compiler_config(&mut self, config: &CompilerConfig) -> Result<(), CodegenError> {
|
||||
self.track_state = config.track_state;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), CodegenError> {
|
||||
self.signatures = signatures
|
||||
.iter()
|
||||
|
@ -49,16 +49,6 @@ pub struct Intrinsics {
|
||||
pub sqrt_f32x4: FunctionValue,
|
||||
pub sqrt_f64x2: FunctionValue,
|
||||
|
||||
pub minimum_f32: FunctionValue,
|
||||
pub minimum_f64: FunctionValue,
|
||||
pub minimum_f32x4: FunctionValue,
|
||||
pub minimum_f64x2: FunctionValue,
|
||||
|
||||
pub maximum_f32: FunctionValue,
|
||||
pub maximum_f64: FunctionValue,
|
||||
pub maximum_f32x4: FunctionValue,
|
||||
pub maximum_f64x2: FunctionValue,
|
||||
|
||||
pub ceil_f32: FunctionValue,
|
||||
pub ceil_f64: FunctionValue,
|
||||
|
||||
@ -309,8 +299,6 @@ impl Intrinsics {
|
||||
|
||||
let ret_f32_take_f32_f32 = f32_ty.fn_type(&[f32_ty_basic, f32_ty_basic], false);
|
||||
let ret_f64_take_f64_f64 = f64_ty.fn_type(&[f64_ty_basic, f64_ty_basic], false);
|
||||
let ret_f32x4_take_f32x4_f32x4 = f32x4_ty.fn_type(&[f32x4_ty_basic, f32x4_ty_basic], false);
|
||||
let ret_f64x2_take_f64x2_f64x2 = f64x2_ty.fn_type(&[f64x2_ty_basic, f64x2_ty_basic], false);
|
||||
|
||||
let ret_i32_take_ctx_i32_i32 = i32_ty.fn_type(
|
||||
&[ctx_ptr_ty.as_basic_type_enum(), i32_ty_basic, i32_ty_basic],
|
||||
@ -335,32 +323,6 @@ impl Intrinsics {
|
||||
sqrt_f32x4: module.add_function("llvm.sqrt.v4f32", ret_f32x4_take_f32x4, None),
|
||||
sqrt_f64x2: module.add_function("llvm.sqrt.v2f64", ret_f64x2_take_f64x2, None),
|
||||
|
||||
minimum_f32: module.add_function("llvm.minnum.f32", ret_f32_take_f32_f32, None),
|
||||
minimum_f64: module.add_function("llvm.minnum.f64", ret_f64_take_f64_f64, None),
|
||||
minimum_f32x4: module.add_function(
|
||||
"llvm.minnum.v4f32",
|
||||
ret_f32x4_take_f32x4_f32x4,
|
||||
None,
|
||||
),
|
||||
minimum_f64x2: module.add_function(
|
||||
"llvm.minnum.v2f64",
|
||||
ret_f64x2_take_f64x2_f64x2,
|
||||
None,
|
||||
),
|
||||
|
||||
maximum_f32: module.add_function("llvm.maxnum.f32", ret_f32_take_f32_f32, None),
|
||||
maximum_f64: module.add_function("llvm.maxnum.f64", ret_f64_take_f64_f64, None),
|
||||
maximum_f32x4: module.add_function(
|
||||
"llvm.maxnum.v4f32",
|
||||
ret_f32x4_take_f32x4_f32x4,
|
||||
None,
|
||||
),
|
||||
maximum_f64x2: module.add_function(
|
||||
"llvm.maxnum.v2f64",
|
||||
ret_f64x2_take_f64x2_f64x2,
|
||||
None,
|
||||
),
|
||||
|
||||
ceil_f32: module.add_function("llvm.ceil.f32", ret_f32_take_f32, None),
|
||||
ceil_f64: module.add_function("llvm.ceil.f64", ret_f64_take_f64, None),
|
||||
|
||||
|
Reference in New Issue
Block a user