Skip to main content

lower_ir_utils/
macros.rs

1/// Build a Cranelift `Signature` from Rust types.
2///
3/// The first argument is an expression evaluating to a `&impl cranelift_module::Module`
4/// (the module supplies both the call convention and the target pointer type).
5///
6/// # Example
7///
8/// ```ignore
9/// let sig = jit_signature!(&module; fn(*const HashMap<String, i64>, &str) -> i64);
10/// ```
11#[macro_export]
12macro_rules! jit_signature {
13    ($module:expr; fn($($pty:ty),* $(,)?) $(-> $ret:ty)?) => {{
14        let __m = $module;
15        let mut __sig = $crate::__reexport::cranelift_module::Module::make_signature(__m);
16        let __ptr = $crate::__reexport::cranelift_module::Module::target_config(__m).pointer_type();
17        $(
18            <$pty as $crate::JitParam>::push_params(&mut __sig.params, __ptr);
19        )*
20        $(
21            <$ret as $crate::JitParam>::push_params(&mut __sig.returns, __ptr);
22        )?
23        __sig
24    }};
25}
26
27/// Declare and define a Cranelift function in one call, with the signature
28/// expressed as Rust types.
29///
30/// Combines [`jit_signature!`] with [`crate::define_function`]: the signature
31/// is derived from the `fn(T1, T2) -> R` shape, then the body closure is
32/// invoked with `&mut FunctionBuilder`, `&mut Module`, and the entry-block
33/// parameter slice. Whatever the closure returns is funneled through
34/// [`crate::IntoReturns`] and emitted as `return_`.
35///
36/// # Example
37///
38/// ```ignore
39/// let id = define_jit_fn!(
40///     &mut module, "wrap", Linkage::Export, fn(i64) -> i64,
41///     |bcx, module, params| {
42///         double_i64_jit::call(bcx, module, ext_id, params[0])
43///     },
44/// )?;
45/// ```
46#[macro_export]
47macro_rules! define_jit_fn {
48    (
49        $module:expr,
50        $name:expr,
51        $linkage:expr,
52        fn($($pty:ty),* $(,)?) $(-> $ret:ty)?,
53        $body:expr $(,)?
54    ) => {{
55        let __module: &mut _ = $module;
56        let __sig = $crate::jit_signature!(&*__module; fn($($pty),*) $(-> $ret)?);
57        $crate::define_function(__module, $name, $linkage, __sig, $body)
58    }};
59}
60
61/// Emit a Cranelift `call` instruction, lowering each Rust argument via [`JitArg`].
62///
63/// Each argument expression must implement [`JitArg`]. Already-lowered IR `Value`s
64/// pass through unchanged; Rust constants (integers, floats, `&'static str`, raw
65/// pointers) are emitted as IR constants on the spot.
66///
67/// Returns the `Inst` produced by `bcx.ins().call(...)` so the caller can extract
68/// return values via `bcx.inst_results(inst)`.
69///
70/// # Example
71///
72/// ```ignore
73/// // map_v: Value from a function param; "foo": &'static str literal.
74/// let call = jit_call!(&mut bcx, ptr_ty, local_callee; map_v, "foo");
75/// let result = bcx.inst_results(call)[0];
76/// ```
77///
78/// [`JitArg`]: crate::JitArg
79#[macro_export]
80macro_rules! jit_call {
81    ($bcx:expr, $ptr_ty:expr, $callee:expr $(; $($arg:expr),* $(,)?)?) => {{
82        let __bcx = &mut *$bcx;
83        let __ptr_ty = $ptr_ty;
84        let mut __args: $crate::__reexport::smallvec::SmallVec<
85            [$crate::__reexport::cranelift_codegen::ir::Value; 8]
86        > = $crate::__reexport::smallvec::SmallVec::new();
87        $($(
88            <_ as $crate::JitArg>::lower($arg, __bcx, __ptr_ty, &mut __args);
89        )*)?
90        __bcx.ins().call($callee, &__args)
91    }};
92}