use crate::probestack::PROBESTACK;
use crate::trap::{raise_lib_trap, Trap, TrapCode};
use crate::vmcontext::VMContext;
use serde::{Deserialize, Serialize};
use std::fmt;
use wasmer_types::{DataIndex, ElemIndex, LocalMemoryIndex, MemoryIndex, TableIndex};
#[no_mangle]
pub extern "C" fn wasmer_f32_ceil(x: f32) -> f32 {
x.ceil()
}
#[no_mangle]
pub extern "C" fn wasmer_f32_floor(x: f32) -> f32 {
x.floor()
}
#[no_mangle]
pub extern "C" fn wasmer_f32_trunc(x: f32) -> f32 {
x.trunc()
}
#[allow(clippy::float_arithmetic, clippy::float_cmp)]
#[no_mangle]
pub extern "C" fn wasmer_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_f64_ceil(x: f64) -> f64 {
x.ceil()
}
#[no_mangle]
pub extern "C" fn wasmer_f64_floor(x: f64) -> f64 {
x.floor()
}
#[no_mangle]
pub extern "C" fn wasmer_f64_trunc(x: f64) -> f64 {
x.trunc()
}
#[allow(clippy::float_arithmetic, clippy::float_cmp)]
#[no_mangle]
pub extern "C" fn wasmer_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
}
}
}
pub unsafe extern "C" fn wasmer_memory32_grow(
vmctx: *mut VMContext,
delta: u32,
memory_index: u32,
) -> u32 {
let instance = (&*vmctx).instance();
let memory_index = LocalMemoryIndex::from_u32(memory_index);
instance
.memory_grow(memory_index, delta)
.map(|pages| pages.0)
.unwrap_or(u32::max_value())
}
pub unsafe extern "C" fn wasmer_imported_memory32_grow(
vmctx: *mut VMContext,
delta: u32,
memory_index: u32,
) -> u32 {
let instance = (&*vmctx).instance();
let memory_index = MemoryIndex::from_u32(memory_index);
instance
.imported_memory_grow(memory_index, delta)
.map(|pages| pages.0)
.unwrap_or(u32::max_value())
}
pub unsafe extern "C" fn wasmer_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
}
pub unsafe extern "C" fn wasmer_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
}
pub unsafe extern "C" fn wasmer_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);
let instance = (&*vmctx).instance();
let dst_table = instance.get_table(dst_table_index);
let src_table = instance.get_table(src_table_index);
dst_table.copy(src_table, dst, src, len)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
pub unsafe extern "C" fn wasmer_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();
instance.table_init(table_index, elem_index, dst, src, len)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
pub unsafe extern "C" fn wasmer_elem_drop(vmctx: *mut VMContext, elem_index: u32) {
let elem_index = ElemIndex::from_u32(elem_index);
let instance = (&*vmctx).instance();
instance.elem_drop(elem_index);
}
pub unsafe extern "C" fn wasmer_local_memory_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);
}
}
pub unsafe extern "C" fn wasmer_imported_memory_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);
}
}
pub unsafe extern "C" fn wasmer_memory_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);
}
}
pub unsafe extern "C" fn wasmer_imported_memory_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);
}
}
pub unsafe extern "C" fn wasmer_memory_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);
}
}
pub unsafe extern "C" fn wasmer_data_drop(vmctx: *mut VMContext, data_index: u32) {
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_raise_trap(trap_code: TrapCode) -> ! {
let trap = Trap::new_from_runtime(trap_code);
raise_lib_trap(trap)
}
#[no_mangle]
pub static wasmer_probestack: unsafe extern "C" fn() = PROBESTACK;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum LibCall {
CeilF32,
CeilF64,
FloorF32,
FloorF64,
NearestF32,
NearestF64,
Probestack,
RaiseTrap,
TruncF32,
TruncF64,
}
impl LibCall {
pub fn function_pointer(self) -> usize {
match self {
Self::CeilF32 => wasmer_f32_ceil as usize,
Self::CeilF64 => wasmer_f64_ceil as usize,
Self::FloorF32 => wasmer_f32_floor as usize,
Self::FloorF64 => wasmer_f64_floor as usize,
Self::NearestF32 => wasmer_f32_nearest as usize,
Self::NearestF64 => wasmer_f64_nearest as usize,
Self::Probestack => wasmer_probestack as usize,
Self::RaiseTrap => wasmer_raise_trap as usize,
Self::TruncF32 => wasmer_f32_trunc as usize,
Self::TruncF64 => wasmer_f64_trunc as usize,
}
}
pub fn to_function_name(&self) -> &str {
match self {
Self::CeilF32 => "wasmer_f32_ceil",
Self::CeilF64 => "wasmer_f64_ceil",
Self::FloorF32 => "wasmer_f32_floor",
Self::FloorF64 => "wasmer_f64_floor",
Self::NearestF32 => "wasmer_f32_nearest",
Self::NearestF64 => "wasmer_f64_nearest",
Self::Probestack => "wasmer_probestack",
Self::RaiseTrap => "wasmer_raise_trap",
Self::TruncF32 => "wasmer_f32_trunc",
Self::TruncF64 => "wasmer_f64_trunc",
}
}
}
impl fmt::Display for LibCall {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}