mir/
interp.rs

1use std::fmt;
2
3use paste::paste;
4
5use crate::{FuncItemRef, ImportResolver, MirContext, ffi};
6
7/// Untagged value for MIR interpreter.
8#[derive(Clone, Copy)]
9#[repr(transparent)]
10pub struct Val(pub(crate) ffi::MIR_val_t);
11
12impl Default for Val {
13    fn default() -> Self {
14        Self(unsafe { std::mem::zeroed::<ffi::MIR_val_t>() })
15    }
16}
17
18impl fmt::Debug for Val {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        f.debug_struct("Val")
21            .field("i64", &self.as_i64())
22            .field("u64", &self.as_u64())
23            .field("f32", &self.as_f32())
24            .field("f64", &self.as_f64())
25            .finish()
26    }
27}
28
29macro_rules! impl_val_variant {
30    ($($name:ident: $ty:ident;)*) => {
31        $(
32            impl From<$ty> for Val {
33                #[inline]
34                fn from(v: $ty) -> Self {
35                    // Fully initialize it.
36                    let mut ret = Self::default();
37                    ret.0.$name = v;
38                    ret
39                }
40            }
41        )*
42        impl Val {
43            paste! {
44                $(
45                    /// Get the value as a
46                    #[doc = concat!("`", stringify!($ty), "`.")]
47                    #[must_use]
48                    #[inline]
49                    pub fn [<as_ $ty>](self) -> $ty {
50                        unsafe { self.0.$name }
51                    }
52                )*
53            }
54        }
55    };
56}
57
58impl_val_variant! {
59    i: i64;
60    u: u64;
61    f: f32;
62    d: f64;
63}
64
65impl MirContext {
66    /// Link loaded modules and external names, preparing to be interpreted.
67    ///
68    /// # Panics
69    ///
70    /// Panic from C on unresolved names.
71    pub fn link_modules_for_interpret(&self) {
72        unsafe { self.link_modules_raw(Some(ffi::MIR_set_interp_interface), None) }
73    }
74
75    /// Link loaded modules and external names with custom resolver, preparing to be interpreted.
76    ///
77    /// # Safety
78    ///
79    /// `resolver` must return valid function pointers with prototype expected by generated code,
80    /// or `NULL` if unresolved.
81    ///
82    /// # Panics
83    ///
84    /// Panic from C on unresolved names.
85    pub unsafe fn link_modules_for_interpret_with_resolver(&self, resolver: &ImportResolver) {
86        unsafe { self.link_modules_raw(Some(ffi::MIR_set_interp_interface), Some(resolver)) }
87    }
88
89    /// Execute a function using the interpreter.
90    ///
91    /// # Safety
92    ///
93    /// The types and lengths of arguments and results must match the function signature.
94    ///
95    /// # Panics
96    ///
97    /// Panic from C on (detectable) interpretation errors.
98    pub unsafe fn interpret_unchecked(
99        &self,
100        func: FuncItemRef<'_>,
101        results: &mut [Val],
102        args: &[Val],
103    ) {
104        let data = unsafe { func.data() };
105        debug_assert_eq!(data.nres as usize, results.len());
106        debug_assert_eq!(data.nargs as usize, args.len());
107        unsafe {
108            ffi::MIR_interp_arr(
109                self.as_raw(),
110                func.as_raw(),
111                results.as_mut_ptr().cast::<ffi::MIR_val_t>(),
112                args.len(),
113                args.as_ptr().cast::<ffi::MIR_val_t>().cast_mut(),
114            );
115        }
116    }
117}