Fix WasmTy/WasmRet on big-endian hosts (#2384)
When invoking a WebAssembly routine from Rust code, arguments are stored into an array of u128, and read from a piece of generated trampoline code before calling the compiled target function using the platform ABI calling convention. The WasmTy/WasmRet routines handle the conversion between Rust data types and those u128 buffers. This currently works by in effect converting the Rust object to a u128 and then storing this u128 into the buffer. The generated trampoline code will then read an object of appropriate type from the beginning of that buffer. This does not work on big-endian platforms, since the above approach causes the value to be stored into the rightmost bytes of the u128 buffer, while the trampoline code reads the leftmost bytes. This patch fixes the problem by changing WasmTy/WasmRet to use the leftmost bytes as well, by casting the u128 pointer to a pointer of the correct type before storing to it (or reading from it). (Note that it is not necessary to actually byte-swap the values since the trampoline code will not treat them like WebAssembly little-endian memory, but simply access them in native byte order.)
This commit is contained in:
@@ -1001,14 +1001,14 @@ unsafe impl WasmTy for i32 {
|
||||
|
||||
#[inline]
|
||||
unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
|
||||
let ret = **ptr as Self;
|
||||
let ret = *(*ptr).cast::<Self>();
|
||||
*ptr = (*ptr).add(1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
|
||||
*ptr = abi as u128;
|
||||
*ptr.cast::<Self>() = abi;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1083,14 +1083,14 @@ unsafe impl WasmTy for i64 {
|
||||
|
||||
#[inline]
|
||||
unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
|
||||
let ret = **ptr as Self;
|
||||
let ret = *(*ptr).cast::<Self>();
|
||||
*ptr = (*ptr).add(1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
|
||||
*ptr = abi as u128;
|
||||
*ptr.cast::<Self>() = abi;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1165,14 +1165,14 @@ unsafe impl WasmTy for f32 {
|
||||
|
||||
#[inline]
|
||||
unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
|
||||
let ret = f32::from_bits(**ptr as u32);
|
||||
let ret = f32::from_bits(*(*ptr).cast::<u32>());
|
||||
*ptr = (*ptr).add(1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
|
||||
*ptr = abi.to_bits() as u128;
|
||||
*ptr.cast::<u32>() = abi.to_bits();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1210,14 +1210,14 @@ unsafe impl WasmTy for f64 {
|
||||
|
||||
#[inline]
|
||||
unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
|
||||
let ret = f64::from_bits(**ptr as u64);
|
||||
let ret = f64::from_bits(*(*ptr).cast::<u64>());
|
||||
*ptr = (*ptr).add(1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
|
||||
*ptr = abi.to_bits() as u128;
|
||||
*ptr.cast::<u64>() = abi.to_bits();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1271,13 +1271,13 @@ unsafe impl WasmTy for Option<ExternRef> {
|
||||
}
|
||||
|
||||
unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
|
||||
let ret = **ptr as usize as *mut u8;
|
||||
let ret = *(*ptr).cast::<usize>() as *mut u8;
|
||||
*ptr = (*ptr).add(1);
|
||||
ret
|
||||
}
|
||||
|
||||
unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
|
||||
ptr::write(ptr, abi as usize as u128);
|
||||
ptr::write(ptr.cast::<usize>(), abi as usize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1324,13 +1324,13 @@ unsafe impl WasmTy for Option<Func> {
|
||||
}
|
||||
|
||||
unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
|
||||
let ret = **ptr as usize as *mut wasmtime_runtime::VMCallerCheckedAnyfunc;
|
||||
let ret = *(*ptr).cast::<usize>() as *mut wasmtime_runtime::VMCallerCheckedAnyfunc;
|
||||
*ptr = (*ptr).add(1);
|
||||
ret
|
||||
}
|
||||
|
||||
unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
|
||||
ptr::write(ptr, abi as usize as u128);
|
||||
ptr::write(ptr.cast::<usize>(), abi as usize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user