Expand description
Bridges Rust types to Cranelift
Signature values, lowers values at JIT call
sites, and trims Module /
FunctionBuilder boilerplate while leaving the
underlying APIs in your hands.
Cranelift / crate versions. This crate targets Cranelift 0.131 (see
dependencies in Cargo.toml). Use matching cranelift-* versions in your
project to avoid subtle ABI or API skew.
#[jit_export] is implemented in the companion crate
lower-ir-utils-macros and re-exported
here; see that crate’s docs for details on the generated <fn>_jit module.
§Platform and ABI notes
JitParam / JitArg model &str and slices as two machine words
(data pointer and length), matching how separate (ptr, len) arguments look in
Cranelift. That matches common 64-bit C ABIs (e.g. separate scalar args).
#[jit_export] injects extern "C" when none is specified and allows
improper_ctypes_definitions so you can write &str in Rust signatures on targets
that pass fat pointers compatibly with that layout—on platforms where that does
not hold, flatten parameters to scalars explicitly.
§Example (end-to-end JIT)
Flow (register host symbol → declare import → wrap with define_jit_fn! →
finalize → call), adapted from tests/external_consumer/tests/smoke.rs in this
repository. Add cranelift-jit, cranelift-module, cranelift-codegen, and
cranelift-native alongside lower-ir-utils for this shape; or import the
Cranelift crates through [__reexport] and keep only lower-ir-utils as a normal
dependency, as that test crate does.
use cranelift_jit::{JITBuilder, JITModule};
use cranelift_module::{default_libcall_names, Linkage};
use cranelift_codegen::settings::{self, Configurable};
use lower_ir_utils::{define_jit_fn, jit_export};
#[jit_export]
fn add(a: i64, b: i64) -> i64 {
a + b
}
let mut flag_builder = settings::builder();
flag_builder.set("use_colocated_libcalls", "false").unwrap();
flag_builder.set("is_pic", "false").unwrap();
let isa = cranelift_native::builder()
.unwrap()
.finish(settings::Flags::new(flag_builder))
.unwrap();
let mut jb = JITBuilder::with_isa(isa, default_libcall_names());
add_jit::register(&mut jb);
let mut module = JITModule::new(jb);
let ext_id = add_jit::declare(&mut module);
let wrap_id = define_jit_fn!(
&mut module, "wrap", Linkage::Export, fn(i64, i64) -> i64,
|bcx, module, params| add_jit::call(bcx, module, ext_id, params[0], params[1]),
)
.unwrap();
module.finalize_definitions().unwrap();
let f: extern "C" fn(i64, i64) -> i64 =
unsafe { std::mem::transmute(module.get_finalized_function(wrap_id)) };
assert_eq!(f(2, 3), 5);§Main items
- Traits:
JitParam(Rust type →AbiParams),JitArg(Rust value →Valueresults viaInstBuilder). - Macros:
jit_signature!,jit_call!,define_jit_fn!(exported at the crate root). define_function,IntoReturns: declare and define a function in one step.- Attribute macro:
jit_export(re-export fromlower_ir_utils_macros).
The crate README (also on docs.rs) adds another runnable sketch and links to more integration tests.
Re-exports§
pub use abi::JitArg;pub use abi::JitParam;pub use builder::define_function;pub use builder::IntoReturns;
Modules§
- abi
- Traits describing how Rust types map onto Cranelift’s ABI.
- builder
- High-level helper to define a Cranelift function: declares the function,
creates the
FunctionBuilderContext+ entry block, runs the user-supplied body closure to populate the IR, emits the return, and finalizes.
Macros§
- define_
jit_ fn - Declare and define a Cranelift function in one call, with the signature expressed as Rust types.
- jit_
call - Emit a Cranelift
callinstruction, lowering each Rust argument viaJitArg. - jit_
signature - Build a Cranelift
Signaturefrom Rust types.
Attribute Macros§
- jit_
export - Annotate a Rust function so it can be called from JIT-compiled Cranelift IR.