mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-25 10:22:19 +00:00
Fix floating point return values.
This commit is contained in:
parent
fc114ac671
commit
7e2ede3960
@ -306,16 +306,15 @@ impl<'a> DynamicFunc<'a> {
|
||||
{
|
||||
use crate::trampoline_x64::{CallContext, TrampolineBufferBuilder};
|
||||
use crate::types::Value;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
struct PolymorphicContext {
|
||||
arg_types: Vec<Type>,
|
||||
func: Box<dyn Fn(&mut vm::Ctx, &[Value]) -> Vec<Value>>,
|
||||
}
|
||||
unsafe extern "C" fn enter_host_polymorphic(
|
||||
unsafe fn do_enter_host_polymorphic(
|
||||
ctx: *const CallContext,
|
||||
args: *const u64,
|
||||
) -> u64 {
|
||||
) -> Vec<Value> {
|
||||
let ctx = &*(ctx as *const PolymorphicContext);
|
||||
let vmctx = &mut *(*args.offset(0) as *mut vm::Ctx);
|
||||
let args: Vec<Value> = ctx
|
||||
@ -335,13 +334,40 @@ impl<'a> DynamicFunc<'a> {
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let rets = (ctx.func)(vmctx, &args);
|
||||
(ctx.func)(vmctx, &args)
|
||||
}
|
||||
unsafe extern "C" fn enter_host_polymorphic_i(
|
||||
ctx: *const CallContext,
|
||||
args: *const u64,
|
||||
) -> u64 {
|
||||
let rets = do_enter_host_polymorphic(ctx, args);
|
||||
if rets.len() == 0 {
|
||||
0
|
||||
} else if rets.len() == 1 {
|
||||
u64::try_from(rets[0].to_u128()).expect(
|
||||
"128-bit return value from polymorphic host functions is not yet supported",
|
||||
)
|
||||
match rets[0] {
|
||||
Value::I32(x) => x as u64,
|
||||
Value::I64(x) => x as u64,
|
||||
_ => panic!("enter_host_polymorphic_i: invalid return type"),
|
||||
}
|
||||
} else {
|
||||
panic!(
|
||||
"multiple return values from polymorphic host functions is not yet supported"
|
||||
);
|
||||
}
|
||||
}
|
||||
unsafe extern "C" fn enter_host_polymorphic_f(
|
||||
ctx: *const CallContext,
|
||||
args: *const u64,
|
||||
) -> f64 {
|
||||
let rets = do_enter_host_polymorphic(ctx, args);
|
||||
if rets.len() == 0 {
|
||||
0.0
|
||||
} else if rets.len() == 1 {
|
||||
match rets[0] {
|
||||
Value::F32(x) => f64::from_bits(x.to_bits() as u64),
|
||||
Value::F64(x) => x,
|
||||
_ => panic!("enter_host_polymorphic_f: invalid return type"),
|
||||
}
|
||||
} else {
|
||||
panic!(
|
||||
"multiple return values from polymorphic host functions is not yet supported"
|
||||
@ -364,11 +390,23 @@ impl<'a> DynamicFunc<'a> {
|
||||
let mut native_param_types = vec![Type::I32]; // vm::Ctx is the first parameter.
|
||||
native_param_types.extend_from_slice(signature.params());
|
||||
|
||||
builder.add_callinfo_trampoline(
|
||||
enter_host_polymorphic,
|
||||
ctx as *const _,
|
||||
&native_param_types,
|
||||
);
|
||||
match signature.returns() {
|
||||
[x] if *x == Type::F32 || *x == Type::F64 => {
|
||||
builder.add_callinfo_trampoline(
|
||||
unsafe { std::mem::transmute(enter_host_polymorphic_f as usize) },
|
||||
ctx as *const _,
|
||||
&native_param_types,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
builder.add_callinfo_trampoline(
|
||||
enter_host_polymorphic_i,
|
||||
ctx as *const _,
|
||||
&native_param_types,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let ptr = builder
|
||||
.insert_global()
|
||||
.expect("cannot bump-allocate global trampoline memory");
|
||||
|
@ -205,6 +205,7 @@ pub struct X64FunctionCode {
|
||||
|
||||
signatures: Arc<Map<SigIndex, FuncSig>>,
|
||||
function_signatures: Arc<Map<FuncIndex, SigIndex>>,
|
||||
signature: FuncSig,
|
||||
fsm: FunctionStateMap,
|
||||
offset: usize,
|
||||
|
||||
@ -713,11 +714,22 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
machine.track_state = self.config.as_ref().unwrap().track_state;
|
||||
|
||||
assembler.emit_label(begin_label);
|
||||
|
||||
let signatures = self.signatures.as_ref().unwrap();
|
||||
let function_signatures = self.function_signatures.as_ref().unwrap();
|
||||
let sig_index = function_signatures
|
||||
.get(FuncIndex::new(
|
||||
self.functions.len() + self.func_import_count,
|
||||
))
|
||||
.unwrap()
|
||||
.clone();
|
||||
let sig = signatures.get(sig_index).unwrap().clone();
|
||||
let code = X64FunctionCode {
|
||||
local_function_id: self.functions.len(),
|
||||
|
||||
signatures: self.signatures.as_ref().unwrap().clone(),
|
||||
function_signatures: self.function_signatures.as_ref().unwrap().clone(),
|
||||
signatures: signatures.clone(),
|
||||
function_signatures: function_signatures.clone(),
|
||||
signature: sig,
|
||||
fsm: FunctionStateMap::new(new_machine_state(), self.functions.len(), 32, vec![]), // only a placeholder; this is initialized later in `begin_body`
|
||||
offset: begin_offset.0,
|
||||
|
||||
@ -6347,7 +6359,14 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
false,
|
||||
)[0];
|
||||
self.value_stack.push(ret);
|
||||
a.emit_mov(Size::S64, Location::GPR(GPR::RAX), ret);
|
||||
match return_types[0] {
|
||||
WpType::F32 | WpType::F64 => {
|
||||
a.emit_mov(Size::S64, Location::XMM(XMM::XMM0), ret);
|
||||
}
|
||||
_ => {
|
||||
a.emit_mov(Size::S64, Location::GPR(GPR::RAX), ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Operator::CallIndirect { index, table_index } => {
|
||||
@ -6486,7 +6505,14 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
false,
|
||||
)[0];
|
||||
self.value_stack.push(ret);
|
||||
a.emit_mov(Size::S64, Location::GPR(GPR::RAX), ret);
|
||||
match return_types[0] {
|
||||
WpType::F32 | WpType::F64 => {
|
||||
a.emit_mov(Size::S64, Location::XMM(XMM::XMM0), ret);
|
||||
}
|
||||
_ => {
|
||||
a.emit_mov(Size::S64, Location::GPR(GPR::RAX), ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Operator::If { ty } => {
|
||||
@ -7701,6 +7727,18 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
self.machine.finalize_locals(a, &self.locals);
|
||||
a.emit_mov(Size::S64, Location::GPR(GPR::RBP), Location::GPR(GPR::RSP));
|
||||
a.emit_pop(Size::S64, Location::GPR(GPR::RBP));
|
||||
|
||||
// Make a copy of the return value in XMM0, as required by the SysV CC.
|
||||
match self.signature.returns() {
|
||||
[x] if *x == Type::F32 || *x == Type::F64 => {
|
||||
a.emit_mov(
|
||||
Size::S64,
|
||||
Location::GPR(GPR::RAX),
|
||||
Location::XMM(XMM::XMM0),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
a.emit_ret();
|
||||
} else {
|
||||
let released = &self.value_stack[frame.value_stack_depth..];
|
||||
|
Loading…
x
Reference in New Issue
Block a user