use wamrx_sys as sys;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ValType {
I32,
I64,
F32,
F64,
}
impl core::fmt::Display for ValType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let s = match self {
ValType::I32 => "i32",
ValType::I64 => "i64",
ValType::F32 => "f32",
ValType::F64 => "f64",
};
f.write_str(s)
}
}
impl ValType {
pub(crate) fn signature_char(self) -> u8 {
match self {
ValType::I32 => b'i',
ValType::I64 => b'I',
ValType::F32 => b'f',
ValType::F64 => b'F',
}
}
pub fn default_value(self) -> Val {
match self {
ValType::I32 => Val::I32(0),
ValType::I64 => Val::I64(0),
ValType::F32 => Val::F32(0.0),
ValType::F64 => Val::F64(0.0),
}
}
pub(crate) fn from_valkind(kind: sys::wasm_valkind_t) -> Option<ValType> {
match kind as u32 {
k if k == sys::WASM_I32 => Some(ValType::I32),
k if k == sys::WASM_I64 => Some(ValType::I64),
k if k == sys::WASM_F32 => Some(ValType::F32),
k if k == sys::WASM_F64 => Some(ValType::F64),
_ => None,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Val {
I32(i32),
I64(i64),
F32(f32),
F64(f64),
}
impl Val {
pub fn ty(self) -> ValType {
match self {
Val::I32(_) => ValType::I32,
Val::I64(_) => ValType::I64,
Val::F32(_) => ValType::F32,
Val::F64(_) => ValType::F64,
}
}
pub(crate) fn to_raw_slot(self) -> u64 {
match self {
Val::I32(v) => v as u32 as u64,
Val::I64(v) => v as u64,
Val::F32(v) => v.to_bits() as u64,
Val::F64(v) => v.to_bits(),
}
}
pub(crate) fn from_raw_slot(ty: ValType, slot: u64) -> Val {
match ty {
ValType::I32 => Val::I32(slot as u32 as i32),
ValType::I64 => Val::I64(slot as i64),
ValType::F32 => Val::F32(f32::from_bits(slot as u32)),
ValType::F64 => Val::F64(f64::from_bits(slot)),
}
}
pub(crate) fn to_wasm_val(self) -> sys::wasm_val_t {
let mut raw: sys::wasm_val_t = unsafe { core::mem::zeroed() };
match self {
Val::I32(v) => {
raw.kind = sys::WASM_I32 as sys::wasm_valkind_t;
raw.of.i32_ = v;
}
Val::I64(v) => {
raw.kind = sys::WASM_I64 as sys::wasm_valkind_t;
raw.of.i64_ = v;
}
Val::F32(v) => {
raw.kind = sys::WASM_F32 as sys::wasm_valkind_t;
raw.of.f32_ = v;
}
Val::F64(v) => {
raw.kind = sys::WASM_F64 as sys::wasm_valkind_t;
raw.of.f64_ = v;
}
}
raw
}
pub(crate) fn from_wasm_val(raw: &sys::wasm_val_t) -> Val {
let kind = raw.kind as u32;
unsafe {
if kind == sys::WASM_I32 {
Val::I32(raw.of.i32_)
} else if kind == sys::WASM_I64 {
Val::I64(raw.of.i64_)
} else if kind == sys::WASM_F32 {
Val::F32(raw.of.f32_)
} else {
Val::F64(raw.of.f64_)
}
}
}
}
impl From<i32> for Val {
fn from(v: i32) -> Self {
Val::I32(v)
}
}
impl From<i64> for Val {
fn from(v: i64) -> Self {
Val::I64(v)
}
}
impl From<f32> for Val {
fn from(v: f32) -> Self {
Val::F32(v)
}
}
impl From<f64> for Val {
fn from(v: f64) -> Self {
Val::F64(v)
}
}
impl core::fmt::Display for Val {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Val::I32(v) => write!(f, "{v}"),
Val::I64(v) => write!(f, "{v}"),
Val::F32(v) => write!(f, "{v}"),
Val::F64(v) => write!(f, "{v}"),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Mutability {
Const,
Mutable,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct GlobalType {
content: ValType,
mutability: Mutability,
}
impl GlobalType {
pub fn new(content: ValType, mutability: Mutability) -> Self {
Self {
content,
mutability,
}
}
pub fn content(&self) -> ValType {
self.content
}
pub fn mutable(&self) -> Mutability {
self.mutability
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FuncType {
params: Box<[ValType]>,
results: Box<[ValType]>,
}
impl FuncType {
pub fn new(
params: impl IntoIterator<Item = ValType>,
results: impl IntoIterator<Item = ValType>,
) -> Self {
Self {
params: params.into_iter().collect(),
results: results.into_iter().collect(),
}
}
pub fn params(&self) -> &[ValType] {
&self.params
}
pub fn results(&self) -> &[ValType] {
&self.results
}
pub(crate) fn signature_cstring(&self) -> std::ffi::CString {
let mut s = Vec::with_capacity(self.params.len() + self.results.len() + 2);
s.push(b'(');
s.extend(self.params.iter().map(|t| t.signature_char()));
s.push(b')');
s.extend(self.results.iter().map(|t| t.signature_char()));
std::ffi::CString::new(s).expect("signature contains no NUL bytes")
}
}