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}