mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-31 06:51:04 +00:00
Start running spectests
Additional info: - Execution is turned off, this is just to make sure the backend can compile the entire specsuite. - That being said, trampolines are implemented and protected call works (just doesn't protect).
This commit is contained in:
parent
3717c5720d
commit
f0ac76517a
@ -117,6 +117,8 @@ private:
|
|||||||
|
|
||||||
struct SymbolLookup : llvm::JITSymbolResolver {
|
struct SymbolLookup : llvm::JITSymbolResolver {
|
||||||
public:
|
public:
|
||||||
|
SymbolLookup(callbacks_t callbacks) : callbacks(callbacks) {}
|
||||||
|
|
||||||
virtual llvm::Expected<LookupResult> lookup(const LookupSet& symbols) override {
|
virtual llvm::Expected<LookupResult> lookup(const LookupSet& symbols) override {
|
||||||
LookupResult result;
|
LookupResult result;
|
||||||
|
|
||||||
@ -140,10 +142,12 @@ public:
|
|||||||
private:
|
private:
|
||||||
llvm::JITEvaluatedSymbol symbol_lookup(llvm::StringRef name) {
|
llvm::JITEvaluatedSymbol symbol_lookup(llvm::StringRef name) {
|
||||||
std::cout << "symbol name: " << (std::string)name << std::endl;
|
std::cout << "symbol name: " << (std::string)name << std::endl;
|
||||||
uint64_t addr = 0;
|
uint64_t addr = callbacks.lookup_vm_symbol(name.data(), name.size());
|
||||||
|
|
||||||
return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None);
|
return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callbacks_t callbacks;
|
||||||
};
|
};
|
||||||
|
|
||||||
WasmModule::WasmModule(
|
WasmModule::WasmModule(
|
||||||
@ -156,7 +160,7 @@ WasmModule::WasmModule(
|
|||||||
llvm::StringRef((const char *)object_start, object_size), "object"
|
llvm::StringRef((const char *)object_start, object_size), "object"
|
||||||
)));
|
)));
|
||||||
|
|
||||||
SymbolLookup symbol_resolver;
|
SymbolLookup symbol_resolver(callbacks);
|
||||||
runtime_dyld = std::unique_ptr<llvm::RuntimeDyld>(new llvm::RuntimeDyld(*memory_manager, symbol_resolver));
|
runtime_dyld = std::unique_ptr<llvm::RuntimeDyld>(new llvm::RuntimeDyld(*memory_manager, symbol_resolver));
|
||||||
|
|
||||||
runtime_dyld->setProcessAllSections(true);
|
runtime_dyld->setProcessAllSections(true);
|
||||||
|
@ -20,7 +20,7 @@ typedef enum {
|
|||||||
typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t** ptr_out, size_t* size_out);
|
typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t** ptr_out, size_t* size_out);
|
||||||
typedef result_t (*protect_memory_t)(uint8_t* ptr, size_t size, mem_protect_t protect);
|
typedef result_t (*protect_memory_t)(uint8_t* ptr, size_t size, mem_protect_t protect);
|
||||||
typedef result_t (*dealloc_memory_t)(uint8_t* ptr, size_t size);
|
typedef result_t (*dealloc_memory_t)(uint8_t* ptr, size_t size);
|
||||||
typedef uintptr_t (*lookup_vm_symbol_t)(char* name_ptr);
|
typedef uintptr_t (*lookup_vm_symbol_t)(const char* name_ptr, size_t length);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* Memory management. */
|
/* Memory management. */
|
||||||
|
@ -13,6 +13,7 @@ use std::{
|
|||||||
ffi::CString,
|
ffi::CString,
|
||||||
mem,
|
mem,
|
||||||
ptr::{self, NonNull},
|
ptr::{self, NonNull},
|
||||||
|
slice, str,
|
||||||
};
|
};
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
backend::{FuncResolver, ProtectedCaller, Token, UserTrapper},
|
backend::{FuncResolver, ProtectedCaller, Token, UserTrapper},
|
||||||
@ -22,6 +23,7 @@ use wasmer_runtime_core::{
|
|||||||
structures::TypedIndex,
|
structures::TypedIndex,
|
||||||
types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, Value},
|
types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, Value},
|
||||||
vm::{self, ImportBacking},
|
vm::{self, ImportBacking},
|
||||||
|
vmcalls,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -56,7 +58,7 @@ struct Callbacks {
|
|||||||
protect_memory: extern "C" fn(*mut u8, usize, MemProtect) -> LLVMResult,
|
protect_memory: extern "C" fn(*mut u8, usize, MemProtect) -> LLVMResult,
|
||||||
dealloc_memory: extern "C" fn(*mut u8, usize) -> LLVMResult,
|
dealloc_memory: extern "C" fn(*mut u8, usize) -> LLVMResult,
|
||||||
|
|
||||||
lookup_vm_symbol: extern "C" fn(*const c_char) -> *const vm::Func,
|
lookup_vm_symbol: extern "C" fn(*const c_char, usize) -> *const vm::Func,
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -136,8 +138,31 @@ fn get_callbacks() -> Callbacks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn lookup_vm_symbol(_name_ptr: *const c_char) -> *const vm::Func {
|
extern "C" fn lookup_vm_symbol(name_ptr: *const c_char, length: usize) -> *const vm::Func {
|
||||||
ptr::null()
|
#[cfg(target_os = "macos")]
|
||||||
|
macro_rules! fn_name {
|
||||||
|
($s:literal) => {
|
||||||
|
concat!("_", $s)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
macro_rules! fn_name {
|
||||||
|
($s:literal) => {
|
||||||
|
$s
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let name_slice = unsafe { slice::from_raw_parts(name_ptr as *const u8, length) };
|
||||||
|
let name = str::from_utf8(name_slice).unwrap();
|
||||||
|
|
||||||
|
match name {
|
||||||
|
fn_name!("vm.memory.grow.dynamic.local") => vmcalls::local_dynamic_memory_grow as _,
|
||||||
|
fn_name!("vm.memory.size.dynamic.local") => vmcalls::local_dynamic_memory_size as _,
|
||||||
|
fn_name!("vm.memory.grow.static.local") => vmcalls::local_static_memory_grow as _,
|
||||||
|
fn_name!("vm.memory.size.static.local") => vmcalls::local_static_memory_size as _,
|
||||||
|
_ => ptr::null(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Callbacks {
|
Callbacks {
|
||||||
@ -241,6 +266,7 @@ impl FuncResolver for LLVMBackend {
|
|||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
local_func_index: LocalFuncIndex,
|
local_func_index: LocalFuncIndex,
|
||||||
) -> Option<NonNull<vm::Func>> {
|
) -> Option<NonNull<vm::Func>> {
|
||||||
|
unimplemented!();
|
||||||
self.get_func(&module.info, local_func_index)
|
self.get_func(&module.info, local_func_index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,6 +290,7 @@ impl ProtectedCaller for LLVMProtectedCaller {
|
|||||||
vmctx: *mut vm::Ctx,
|
vmctx: *mut vm::Ctx,
|
||||||
_: Token,
|
_: Token,
|
||||||
) -> RuntimeResult<Vec<Value>> {
|
) -> RuntimeResult<Vec<Value>> {
|
||||||
|
unimplemented!();
|
||||||
let (func_ptr, ctx, signature, sig_index) =
|
let (func_ptr, ctx, signature, sig_index) =
|
||||||
get_func_from_index(&module, import_backing, func_index);
|
get_func_from_index(&module, import_backing, func_index);
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ pub fn parse_function_bodies(
|
|||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// module.print_to_stderr();
|
module.print_to_stderr();
|
||||||
|
|
||||||
generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics);
|
generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics);
|
||||||
|
|
||||||
@ -475,22 +475,8 @@ fn parse_function(
|
|||||||
builder.build_unconditional_branch(frame.code_after());
|
builder.build_unconditional_branch(frame.code_after());
|
||||||
|
|
||||||
for phi in frame.phis().iter().rev() {
|
for phi in frame.phis().iter().rev() {
|
||||||
if phi.count_incoming() != 0 {
|
let value = state.pop1()?;
|
||||||
let value = state.pop1()?;
|
phi.add_incoming(&[(&value, ¤t_block)]);
|
||||||
phi.add_incoming(&[(&value, ¤t_block)])
|
|
||||||
} else {
|
|
||||||
let basic_ty = phi.as_basic_value().get_type();
|
|
||||||
let placeholder_value = match basic_ty {
|
|
||||||
BasicTypeEnum::IntType(int_ty) => {
|
|
||||||
int_ty.const_int(0, false).as_basic_value_enum()
|
|
||||||
}
|
|
||||||
BasicTypeEnum::FloatType(float_ty) => {
|
|
||||||
float_ty.const_float(0.0).as_basic_value_enum()
|
|
||||||
}
|
|
||||||
_ => unimplemented!(),
|
|
||||||
};
|
|
||||||
phi.add_incoming(&[(&placeholder_value, ¤t_block)]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,6 +544,7 @@ fn parse_function(
|
|||||||
// it will emit a `ud2` instruction on x86_64 arches.
|
// it will emit a `ud2` instruction on x86_64 arches.
|
||||||
ctx.build_trap();
|
ctx.build_trap();
|
||||||
builder.build_unreachable();
|
builder.build_unreachable();
|
||||||
|
|
||||||
state.reachable = false;
|
state.reachable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -747,12 +734,13 @@ fn parse_function(
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let sigindices_equal = builder.build_int_compare(
|
// let sigindices_equal = builder.build_int_compare(
|
||||||
IntPredicate::EQ,
|
// IntPredicate::EQ,
|
||||||
expected_dynamic_sigindex,
|
// expected_dynamic_sigindex,
|
||||||
found_dynamic_sigindex,
|
// found_dynamic_sigindex,
|
||||||
"sigindices_equal",
|
// "sigindices_equal",
|
||||||
);
|
// );
|
||||||
|
let sigindices_equal = intrinsics.i1_ty.const_int(1, false);
|
||||||
|
|
||||||
// Tell llvm that `expected_dynamic_sigindex` should equal `found_dynamic_sigindex`.
|
// Tell llvm that `expected_dynamic_sigindex` should equal `found_dynamic_sigindex`.
|
||||||
let sigindices_equal = builder
|
let sigindices_equal = builder
|
||||||
@ -1227,18 +1215,18 @@ fn parse_function(
|
|||||||
state.push1(res);
|
state.push1(res);
|
||||||
}
|
}
|
||||||
Operator::F32Copysign => {
|
Operator::F32Copysign => {
|
||||||
let input = state.pop1()?;
|
let (mag, sgn) = state.pop2()?;
|
||||||
let res = builder
|
let res = builder
|
||||||
.build_call(intrinsics.copysign_f32, &[input], &state.var_name())
|
.build_call(intrinsics.copysign_f32, &[mag, sgn], &state.var_name())
|
||||||
.try_as_basic_value()
|
.try_as_basic_value()
|
||||||
.left()
|
.left()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
state.push1(res);
|
state.push1(res);
|
||||||
}
|
}
|
||||||
Operator::F64Copysign => {
|
Operator::F64Copysign => {
|
||||||
let input = state.pop1()?;
|
let (msg, sgn) = state.pop2()?;
|
||||||
let res = builder
|
let res = builder
|
||||||
.build_call(intrinsics.copysign_f64, &[input], &state.var_name())
|
.build_call(intrinsics.copysign_f64, &[msg, sgn], &state.var_name())
|
||||||
.try_as_basic_value()
|
.try_as_basic_value()
|
||||||
.left()
|
.left()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -1549,7 +1537,7 @@ fn parse_function(
|
|||||||
&mut state,
|
&mut state,
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
memarg,
|
memarg,
|
||||||
intrinsics.i32_ptr_ty,
|
intrinsics.f32_ptr_ty,
|
||||||
)?;
|
)?;
|
||||||
let result = builder.build_load(effective_address, &state.var_name());
|
let result = builder.build_load(effective_address, &state.var_name());
|
||||||
state.push1(result);
|
state.push1(result);
|
||||||
|
@ -231,11 +231,11 @@ impl Intrinsics {
|
|||||||
sqrt_f32: module.add_function("llvm.sqrt.f32", ret_f32_take_f32, None),
|
sqrt_f32: module.add_function("llvm.sqrt.f32", ret_f32_take_f32, None),
|
||||||
sqrt_f64: module.add_function("llvm.sqrt.f64", ret_f64_take_f64, None),
|
sqrt_f64: module.add_function("llvm.sqrt.f64", ret_f64_take_f64, None),
|
||||||
|
|
||||||
minimum_f32: module.add_function("llvm.minimum.f32", ret_f32_take_f32_f32, None),
|
minimum_f32: module.add_function("llvm.minnum.f32", ret_f32_take_f32_f32, None),
|
||||||
minimum_f64: module.add_function("llvm.minimum.f64", ret_f64_take_f64_f64, None),
|
minimum_f64: module.add_function("llvm.minnum.f64", ret_f64_take_f64_f64, None),
|
||||||
|
|
||||||
maximum_f32: module.add_function("llvm.maximum.f32", ret_f32_take_f32_f32, None),
|
maximum_f32: module.add_function("llvm.maxnum.f32", ret_f32_take_f32_f32, None),
|
||||||
maximum_f64: module.add_function("llvm.maximum.f64", ret_f64_take_f64_f64, None),
|
maximum_f64: module.add_function("llvm.maxnum.f64", ret_f64_take_f64_f64, None),
|
||||||
|
|
||||||
ceil_f32: module.add_function("llvm.ceil.f32", ret_f32_take_f32, 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),
|
ceil_f64: module.add_function("llvm.ceil.f64", ret_f64_take_f64, None),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user