#![allow(missing_docs)] use crate::probestack::PROBESTACK;
use crate::table::{RawTableElement, TableElement};
use crate::trap::{raise_lib_trap, Trap, TrapCode};
use crate::vmcontext::VMContext;
use crate::{on_host_stack, VMFuncRef};
pub use wasmer_types::LibCall;
use wasmer_types::{
DataIndex, ElemIndex, FunctionIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex,
TableIndex, Type,
};
#[no_mangle]
pub extern "C" fn wasmer_vm_f32_ceil(x: f32) -> f32 {
x.ceil()
}
#[no_mangle]
pub extern "C" fn wasmer_vm_f32_floor(x: f32) -> f32 {
x.floor()
}
#[no_mangle]
pub extern "C" fn wasmer_vm_f32_trunc(x: f32) -> f32 {
x.trunc()
}
#[allow(clippy::float_arithmetic, clippy::float_cmp)]
#[no_mangle]
pub extern "C" fn wasmer_vm_f32_nearest(x: f32) -> f32 {
if x == 0.0 {
x
} else {
let u = x.ceil();
let d = x.floor();
let um = (x - u).abs();
let dm = (x - d).abs();
if um < dm
|| (um == dm && {
let h = u / 2.;
h.floor() == h
})
{
u
} else {
d
}
}
}
#[no_mangle]
pub extern "C" fn wasmer_vm_f64_ceil(x: f64) -> f64 {
x.ceil()
}
#[no_mangle]
pub extern "C" fn wasmer_vm_f64_floor(x: f64) -> f64 {
x.floor()
}
#[no_mangle]
pub extern "C" fn wasmer_vm_f64_trunc(x: f64) -> f64 {
x.trunc()
}
#[allow(clippy::float_arithmetic, clippy::float_cmp)]
#[no_mangle]
pub extern "C" fn wasmer_vm_f64_nearest(x: f64) -> f64 {
if x == 0.0 {
x
} else {
let u = x.ceil();
let d = x.floor();
let um = (x - u).abs();
let dm = (x - d).abs();
if um < dm
|| (um == dm && {
let h = u / 2.;
h.floor() == h
})
{
u
} else {
d
}
}
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_memory32_grow(
vmctx: *mut VMContext,
delta: u32,
memory_index: u32,
) -> u32 {
on_host_stack(|| {
let instance = (*vmctx).instance_mut();
let memory_index = LocalMemoryIndex::from_u32(memory_index);
instance
.memory_grow(memory_index, delta)
.map(|pages| pages.0)
.unwrap_or(u32::MAX)
})
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_imported_memory32_grow(
vmctx: *mut VMContext,
delta: u32,
memory_index: u32,
) -> u32 {
on_host_stack(|| {
let instance = (*vmctx).instance_mut();
let memory_index = MemoryIndex::from_u32(memory_index);
instance
.imported_memory_grow(memory_index, delta)
.map(|pages| pages.0)
.unwrap_or(u32::MAX)
})
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_memory32_size(vmctx: *mut VMContext, memory_index: u32) -> u32 {
let instance = (*vmctx).instance();
let memory_index = LocalMemoryIndex::from_u32(memory_index);
instance.memory_size(memory_index).0
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_imported_memory32_size(
vmctx: *mut VMContext,
memory_index: u32,
) -> u32 {
let instance = (*vmctx).instance();
let memory_index = MemoryIndex::from_u32(memory_index);
instance.imported_memory_size(memory_index).0
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_table_copy(
vmctx: *mut VMContext,
dst_table_index: u32,
src_table_index: u32,
dst: u32,
src: u32,
len: u32,
) {
let result = {
let dst_table_index = TableIndex::from_u32(dst_table_index);
let src_table_index = TableIndex::from_u32(src_table_index);
if dst_table_index == src_table_index {
let table = (*vmctx).instance_mut().get_table(dst_table_index);
table.copy_within(dst, src, len)
} else {
let dst_table = (*vmctx).instance_mut().get_table(dst_table_index);
let src_table = (*vmctx).instance_mut().get_table(src_table_index);
dst_table.copy(src_table, dst, src, len)
}
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_table_init(
vmctx: *mut VMContext,
table_index: u32,
elem_index: u32,
dst: u32,
src: u32,
len: u32,
) {
let result = {
let table_index = TableIndex::from_u32(table_index);
let elem_index = ElemIndex::from_u32(elem_index);
let instance = (*vmctx).instance_mut();
instance.table_init(table_index, elem_index, dst, src, len)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_table_fill(
vmctx: *mut VMContext,
table_index: u32,
start_idx: u32,
item: RawTableElement,
len: u32,
) {
let result = {
let table_index = TableIndex::from_u32(table_index);
let instance = (*vmctx).instance_mut();
let elem = match instance.get_table(table_index).ty().ty {
Type::ExternRef => TableElement::ExternRef(item.extern_ref),
Type::FuncRef => TableElement::FuncRef(item.func_ref),
_ => panic!("Unrecognized table type: does not contain references"),
};
instance.table_fill(table_index, start_idx, elem, len)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_table_size(vmctx: *mut VMContext, table_index: u32) -> u32 {
let instance = (*vmctx).instance();
let table_index = LocalTableIndex::from_u32(table_index);
instance.table_size(table_index)
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_imported_table_size(
vmctx: *mut VMContext,
table_index: u32,
) -> u32 {
let instance = (*vmctx).instance();
let table_index = TableIndex::from_u32(table_index);
instance.imported_table_size(table_index)
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_table_get(
vmctx: *mut VMContext,
table_index: u32,
elem_index: u32,
) -> RawTableElement {
let instance = (*vmctx).instance();
let table_index = LocalTableIndex::from_u32(table_index);
match instance.table_get(table_index, elem_index) {
Some(table_ref) => table_ref.into(),
None => raise_lib_trap(Trap::lib(TrapCode::TableAccessOutOfBounds)),
}
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_imported_table_get(
vmctx: *mut VMContext,
table_index: u32,
elem_index: u32,
) -> RawTableElement {
let instance = (*vmctx).instance_mut();
let table_index = TableIndex::from_u32(table_index);
match instance.imported_table_get(table_index, elem_index) {
Some(table_ref) => table_ref.into(),
None => raise_lib_trap(Trap::lib(TrapCode::TableAccessOutOfBounds)),
}
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_table_set(
vmctx: *mut VMContext,
table_index: u32,
elem_index: u32,
value: RawTableElement,
) {
let instance = (*vmctx).instance_mut();
let table_index = TableIndex::from_u32(table_index);
let table_index = instance
.module_ref()
.local_table_index(table_index)
.unwrap();
let elem = match instance.get_local_table(table_index).ty().ty {
Type::ExternRef => TableElement::ExternRef(value.extern_ref),
Type::FuncRef => TableElement::FuncRef(value.func_ref),
_ => panic!("Unrecognized table type: does not contain references"),
};
let result = instance.table_set(table_index, elem_index, elem);
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_imported_table_set(
vmctx: *mut VMContext,
table_index: u32,
elem_index: u32,
value: RawTableElement,
) {
let instance = (*vmctx).instance_mut();
let table_index = TableIndex::from_u32(table_index);
let elem = match instance.get_table(table_index).ty().ty {
Type::ExternRef => TableElement::ExternRef(value.extern_ref),
Type::FuncRef => TableElement::FuncRef(value.func_ref),
_ => panic!("Unrecognized table type: does not contain references"),
};
let result = instance.imported_table_set(table_index, elem_index, elem);
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_table_grow(
vmctx: *mut VMContext,
init_value: RawTableElement,
delta: u32,
table_index: u32,
) -> u32 {
on_host_stack(|| {
let instance = (*vmctx).instance_mut();
let table_index = LocalTableIndex::from_u32(table_index);
let init_value = match instance.get_local_table(table_index).ty().ty {
Type::ExternRef => TableElement::ExternRef(init_value.extern_ref),
Type::FuncRef => TableElement::FuncRef(init_value.func_ref),
_ => panic!("Unrecognized table type: does not contain references"),
};
instance
.table_grow(table_index, delta, init_value)
.unwrap_or(u32::MAX)
})
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_imported_table_grow(
vmctx: *mut VMContext,
init_value: RawTableElement,
delta: u32,
table_index: u32,
) -> u32 {
on_host_stack(|| {
let instance = (*vmctx).instance_mut();
let table_index = TableIndex::from_u32(table_index);
let init_value = match instance.get_table(table_index).ty().ty {
Type::ExternRef => TableElement::ExternRef(init_value.extern_ref),
Type::FuncRef => TableElement::FuncRef(init_value.func_ref),
_ => panic!("Unrecognized table type: does not contain references"),
};
instance
.imported_table_grow(table_index, delta, init_value)
.unwrap_or(u32::MAX)
})
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_func_ref(
vmctx: *mut VMContext,
function_index: u32,
) -> VMFuncRef {
let instance = (*vmctx).instance();
let function_index = FunctionIndex::from_u32(function_index);
instance.func_ref(function_index).unwrap()
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_elem_drop(vmctx: *mut VMContext, elem_index: u32) {
on_host_stack(|| {
let elem_index = ElemIndex::from_u32(elem_index);
let instance = (*vmctx).instance();
instance.elem_drop(elem_index);
})
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_memory32_copy(
vmctx: *mut VMContext,
memory_index: u32,
dst: u32,
src: u32,
len: u32,
) {
let result = {
let memory_index = LocalMemoryIndex::from_u32(memory_index);
let instance = (*vmctx).instance();
instance.local_memory_copy(memory_index, dst, src, len)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_imported_memory32_copy(
vmctx: *mut VMContext,
memory_index: u32,
dst: u32,
src: u32,
len: u32,
) {
let result = {
let memory_index = MemoryIndex::from_u32(memory_index);
let instance = (*vmctx).instance();
instance.imported_memory_copy(memory_index, dst, src, len)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_memory32_fill(
vmctx: *mut VMContext,
memory_index: u32,
dst: u32,
val: u32,
len: u32,
) {
let result = {
let memory_index = LocalMemoryIndex::from_u32(memory_index);
let instance = (*vmctx).instance();
instance.local_memory_fill(memory_index, dst, val, len)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_imported_memory32_fill(
vmctx: *mut VMContext,
memory_index: u32,
dst: u32,
val: u32,
len: u32,
) {
let result = {
let memory_index = MemoryIndex::from_u32(memory_index);
let instance = (*vmctx).instance();
instance.imported_memory_fill(memory_index, dst, val, len)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_memory32_init(
vmctx: *mut VMContext,
memory_index: u32,
data_index: u32,
dst: u32,
src: u32,
len: u32,
) {
let result = {
let memory_index = MemoryIndex::from_u32(memory_index);
let data_index = DataIndex::from_u32(data_index);
let instance = (*vmctx).instance();
instance.memory_init(memory_index, data_index, dst, src, len)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_data_drop(vmctx: *mut VMContext, data_index: u32) {
on_host_stack(|| {
let data_index = DataIndex::from_u32(data_index);
let instance = (*vmctx).instance();
instance.data_drop(data_index)
})
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_raise_trap(trap_code: TrapCode) -> ! {
let trap = Trap::lib(trap_code);
raise_lib_trap(trap)
}
#[no_mangle]
pub static wasmer_vm_probestack: unsafe extern "C" fn() = PROBESTACK;
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_memory32_atomic_wait32(
vmctx: *mut VMContext,
memory_index: u32,
dst: u32,
val: u32,
timeout: i64,
) -> u32 {
let result = {
let instance = (*vmctx).instance_mut();
let memory_index = LocalMemoryIndex::from_u32(memory_index);
instance.local_memory_wait32(memory_index, dst, val, timeout)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
result.unwrap()
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_imported_memory32_atomic_wait32(
vmctx: *mut VMContext,
memory_index: u32,
dst: u32,
val: u32,
timeout: i64,
) -> u32 {
let result = {
let instance = (*vmctx).instance_mut();
let memory_index = MemoryIndex::from_u32(memory_index);
instance.imported_memory_wait32(memory_index, dst, val, timeout)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
result.unwrap()
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_memory32_atomic_wait64(
vmctx: *mut VMContext,
memory_index: u32,
dst: u32,
val: u64,
timeout: i64,
) -> u32 {
let result = {
let instance = (*vmctx).instance_mut();
let memory_index = LocalMemoryIndex::from_u32(memory_index);
instance.local_memory_wait64(memory_index, dst, val, timeout)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
result.unwrap()
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_imported_memory32_atomic_wait64(
vmctx: *mut VMContext,
memory_index: u32,
dst: u32,
val: u64,
timeout: i64,
) -> u32 {
let result = {
let instance = (*vmctx).instance_mut();
let memory_index = MemoryIndex::from_u32(memory_index);
instance.imported_memory_wait64(memory_index, dst, val, timeout)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
result.unwrap()
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_memory32_atomic_notify(
vmctx: *mut VMContext,
memory_index: u32,
dst: u32,
cnt: u32,
) -> u32 {
let result = {
let instance = (*vmctx).instance_mut();
let memory_index = LocalMemoryIndex::from_u32(memory_index);
instance.local_memory_notify(memory_index, dst, cnt)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
result.unwrap()
}
#[no_mangle]
pub unsafe extern "C" fn wasmer_vm_imported_memory32_atomic_notify(
vmctx: *mut VMContext,
memory_index: u32,
dst: u32,
cnt: u32,
) -> u32 {
let result = {
let instance = (*vmctx).instance_mut();
let memory_index = MemoryIndex::from_u32(memory_index);
instance.imported_memory_notify(memory_index, dst, cnt)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
result.unwrap()
}
pub fn function_pointer(libcall: LibCall) -> usize {
match libcall {
LibCall::CeilF32 => wasmer_vm_f32_ceil as usize,
LibCall::CeilF64 => wasmer_vm_f64_ceil as usize,
LibCall::FloorF32 => wasmer_vm_f32_floor as usize,
LibCall::FloorF64 => wasmer_vm_f64_floor as usize,
LibCall::NearestF32 => wasmer_vm_f32_nearest as usize,
LibCall::NearestF64 => wasmer_vm_f64_nearest as usize,
LibCall::TruncF32 => wasmer_vm_f32_trunc as usize,
LibCall::TruncF64 => wasmer_vm_f64_trunc as usize,
LibCall::Memory32Size => wasmer_vm_memory32_size as usize,
LibCall::ImportedMemory32Size => wasmer_vm_imported_memory32_size as usize,
LibCall::TableCopy => wasmer_vm_table_copy as usize,
LibCall::TableInit => wasmer_vm_table_init as usize,
LibCall::TableFill => wasmer_vm_table_fill as usize,
LibCall::TableSize => wasmer_vm_table_size as usize,
LibCall::ImportedTableSize => wasmer_vm_imported_table_size as usize,
LibCall::TableGet => wasmer_vm_table_get as usize,
LibCall::ImportedTableGet => wasmer_vm_imported_table_get as usize,
LibCall::TableSet => wasmer_vm_table_set as usize,
LibCall::ImportedTableSet => wasmer_vm_imported_table_set as usize,
LibCall::TableGrow => wasmer_vm_table_grow as usize,
LibCall::ImportedTableGrow => wasmer_vm_imported_table_grow as usize,
LibCall::FuncRef => wasmer_vm_func_ref as usize,
LibCall::ElemDrop => wasmer_vm_elem_drop as usize,
LibCall::Memory32Copy => wasmer_vm_memory32_copy as usize,
LibCall::ImportedMemory32Copy => wasmer_vm_imported_memory32_copy as usize,
LibCall::Memory32Fill => wasmer_vm_memory32_fill as usize,
LibCall::ImportedMemory32Fill => wasmer_vm_imported_memory32_fill as usize,
LibCall::Memory32Init => wasmer_vm_memory32_init as usize,
LibCall::DataDrop => wasmer_vm_data_drop as usize,
LibCall::Probestack => wasmer_vm_probestack as usize,
LibCall::RaiseTrap => wasmer_vm_raise_trap as usize,
LibCall::Memory32AtomicWait32 => wasmer_vm_memory32_atomic_wait32 as usize,
LibCall::ImportedMemory32AtomicWait32 => wasmer_vm_imported_memory32_atomic_wait32 as usize,
LibCall::Memory32AtomicWait64 => wasmer_vm_memory32_atomic_wait64 as usize,
LibCall::ImportedMemory32AtomicWait64 => wasmer_vm_imported_memory32_atomic_wait64 as usize,
LibCall::Memory32AtomicNotify => wasmer_vm_memory32_atomic_notify as usize,
LibCall::ImportedMemory32AtomicNotify => wasmer_vm_imported_memory32_atomic_notify as usize,
}
}