use std::fmt;
use paste::paste;
use crate::{FuncItemRef, ImportResolver, MirContext, ffi};
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct Val(pub(crate) ffi::MIR_val_t);
impl Default for Val {
fn default() -> Self {
Self(unsafe { std::mem::zeroed::<ffi::MIR_val_t>() })
}
}
impl fmt::Debug for Val {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Val")
.field("i64", &self.as_i64())
.field("u64", &self.as_u64())
.field("f32", &self.as_f32())
.field("f64", &self.as_f64())
.finish()
}
}
macro_rules! impl_val_variant {
($($name:ident: $ty:ident;)*) => {
$(
impl From<$ty> for Val {
#[inline]
fn from(v: $ty) -> Self {
let mut ret = Self::default();
ret.0.$name = v;
ret
}
}
)*
impl Val {
paste! {
$(
#[doc = concat!("`", stringify!($ty), "`.")]
#[must_use]
#[inline]
pub fn [<as_ $ty>](self) -> $ty {
unsafe { self.0.$name }
}
)*
}
}
};
}
impl_val_variant! {
i: i64;
u: u64;
f: f32;
d: f64;
}
impl MirContext {
pub fn link_modules_for_interpret(&self) {
unsafe { self.link_modules_raw(Some(ffi::MIR_set_interp_interface), None) }
}
pub unsafe fn link_modules_for_interpret_with_resolver(&self, resolver: &ImportResolver) {
unsafe { self.link_modules_raw(Some(ffi::MIR_set_interp_interface), Some(resolver)) }
}
pub unsafe fn interpret_unchecked(
&self,
func: FuncItemRef<'_>,
results: &mut [Val],
args: &[Val],
) {
let data = unsafe { func.data() };
debug_assert_eq!(data.nres as usize, results.len());
debug_assert_eq!(data.nargs as usize, args.len());
unsafe {
ffi::MIR_interp_arr(
self.as_raw(),
func.as_raw(),
results.as_mut_ptr().cast::<ffi::MIR_val_t>(),
args.len(),
args.as_ptr().cast::<ffi::MIR_val_t>().cast_mut(),
);
}
}
}