lower_ir_utils/lib.rs
1//! Bridges Rust types to [Cranelift](https://cranelift.dev/)
2//! [`Signature`](cranelift_codegen::ir::Signature) values, lowers values at JIT `call`
3//! sites, and trims [`Module`](cranelift_module::Module) /
4//! [`FunctionBuilder`](cranelift_frontend::FunctionBuilder) boilerplate while leaving the
5//! underlying APIs in your hands.
6//!
7//! **Cranelift / crate versions.** This crate targets **Cranelift 0.131** (see
8//! dependencies in `Cargo.toml`). Use matching `cranelift-*` versions in your
9//! project to avoid subtle ABI or API skew.
10//!
11//! **`#[jit_export]`** is implemented in the companion crate
12//! [lower-ir-utils-macros](https://docs.rs/lower-ir-utils-macros) and re-exported
13//! here; see that crate's docs for details on the generated `<fn>_jit` module.
14//!
15//! # Platform and ABI notes
16//!
17//! [`JitParam`] / [`JitArg`] model `&str` and slices as **two machine words**
18//! (data pointer and length), matching how separate `(ptr, len)` arguments look in
19//! Cranelift. That matches common 64-bit C ABIs (e.g. separate scalar args).
20//! **`#[jit_export]`** injects `extern "C"` when none is specified and allows
21//! `improper_ctypes_definitions` so you can write `&str` in Rust signatures on targets
22//! that pass fat pointers compatibly with that layout—on platforms where that does
23//! not hold, flatten parameters to scalars explicitly.
24//!
25//! # Example (end-to-end JIT)
26//!
27//! Flow (register host symbol → declare import → wrap with [`define_jit_fn!`] →
28//! finalize → call), adapted from `tests/external_consumer/tests/smoke.rs` in this
29//! repository. Add `cranelift-jit`, `cranelift-module`, `cranelift-codegen`, and
30//! `cranelift-native` alongside `lower-ir-utils` for this shape; or import the
31//! Cranelift crates through [`__reexport`] and keep only `lower-ir-utils` as a normal
32//! dependency, as that test crate does.
33//!
34//! ```ignore
35//! use cranelift_jit::{JITBuilder, JITModule};
36//! use cranelift_module::{default_libcall_names, Linkage};
37//! use cranelift_codegen::settings::{self, Configurable};
38//! use lower_ir_utils::{define_jit_fn, jit_export};
39//!
40//! #[jit_export]
41//! fn add(a: i64, b: i64) -> i64 {
42//! a + b
43//! }
44//!
45//! let mut flag_builder = settings::builder();
46//! flag_builder.set("use_colocated_libcalls", "false").unwrap();
47//! flag_builder.set("is_pic", "false").unwrap();
48//! let isa = cranelift_native::builder()
49//! .unwrap()
50//! .finish(settings::Flags::new(flag_builder))
51//! .unwrap();
52//!
53//! let mut jb = JITBuilder::with_isa(isa, default_libcall_names());
54//! add_jit::register(&mut jb);
55//! let mut module = JITModule::new(jb);
56//! let ext_id = add_jit::declare(&mut module);
57//!
58//! let wrap_id = define_jit_fn!(
59//! &mut module, "wrap", Linkage::Export, fn(i64, i64) -> i64,
60//! |bcx, module, params| add_jit::call(bcx, module, ext_id, params[0], params[1]),
61//! )
62//! .unwrap();
63//!
64//! module.finalize_definitions().unwrap();
65//! let f: extern "C" fn(i64, i64) -> i64 =
66//! unsafe { std::mem::transmute(module.get_finalized_function(wrap_id)) };
67//! assert_eq!(f(2, 3), 5);
68//! ```
69//!
70//! # Main items
71//!
72//! - Traits: **[`JitParam`]** (Rust type → [`AbiParam`](cranelift_codegen::ir::AbiParam)s), **[`JitArg`]**
73//! (Rust value → [`Value`](cranelift_codegen::ir::Value) results via [`InstBuilder`](cranelift_codegen::ir::InstBuilder)).
74//! - Macros: **`jit_signature!`**, **`jit_call!`**, **`define_jit_fn!`** (exported at
75//! the crate root).
76//! - **`define_function`**, **[`IntoReturns`]**: declare and define a function in one step.
77//! - Attribute macro: **`jit_export`** (re-export from `lower_ir_utils_macros`).
78//!
79//! The crate README (also on docs.rs) adds another runnable sketch and links to more
80//! integration tests.
81
82pub mod abi;
83pub mod builder;
84mod macros;
85
86pub use abi::{JitArg, JitParam};
87pub use builder::{define_function, IntoReturns};
88pub use lower_ir_utils_macros::jit_export;
89
90#[doc(hidden)]
91pub mod __reexport {
92 pub use cranelift_codegen;
93 pub use cranelift_frontend;
94 pub use cranelift_jit;
95 pub use cranelift_module;
96 pub use smallvec;
97}