Skip to main content

Jit

Struct Jit 

Source
pub struct Jit { /* private fields */ }
Expand description

A just-in-time compiler for the host machine.

A Jit holds a code generator configured for the CPU it is running on, built once in new. Each call to compile validates an ir_lang::Function, lowers it to native machine code, and places that code in executable memory, returning a Compiled that can be called. The engine carries no per-function state, so one Jit compiles many functions, and it is Send and Sync, so it can be shared across threads.

For a one-off compile where reuse does not matter, the free function compile builds a Jit and compiles in a single call.

§Examples

Build the engine once, compile two functions, and run them:

use jit_lang::Jit;
use ir_lang::{Builder, BinOp, Type};

let jit = Jit::new().expect("the host is supported");

// fn inc(x: int) -> int { x + 1 }
let mut b = Builder::new("inc", &[Type::Int], Type::Int);
let x = b.block_params(b.entry())[0];
let one = b.iconst(1);
let sum = b.bin(BinOp::Add, x, one);
b.ret(Some(sum));
let inc = jit.compile(&b.finish()).expect("inc is well-formed");

// fn neg(x: int) -> int { 0 - x }
let mut b = Builder::new("neg", &[Type::Int], Type::Int);
let x = b.block_params(b.entry())[0];
let zero = b.iconst(0);
let r = b.bin(BinOp::Sub, zero, x);
b.ret(Some(r));
let neg = jit.compile(&b.finish()).expect("neg is well-formed");

// SAFETY: both signatures are `fn(int) -> int`, and each handle outlives its call.
let inc_fn: extern "C" fn(i64) -> i64 = unsafe { inc.entry() };
let neg_fn: extern "C" fn(i64) -> i64 = unsafe { neg.entry() };
assert_eq!(inc_fn(41), 42);
assert_eq!(neg_fn(42), -42);

Implementations§

Source§

impl Jit

Source

pub fn new() -> Result<Self, JitError>

Builds an engine targeting the host CPU, with its native instruction-set features enabled and the optimizing code path selected.

§Errors
§Examples
use jit_lang::Jit;

let jit = Jit::new().expect("the host is supported");
let _ = jit; // ready to compile
Source

pub fn compile(&self, func: &Function) -> Result<Compiled, JitError>

Compiles a function to native machine code and makes it runnable.

The function is validated, translated to Cranelift IR, compiled for the host, and copied into a guard-flanked, read-execute memory region that the returned Compiled owns. The emitted code is self-contained — a leaf function with no outgoing calls — so it needs no runtime relocation; a function that somehow required one is refused rather than run wrong.

§Errors
§Examples
use jit_lang::Jit;
use ir_lang::{Builder, BinOp, Type};

// fn mul(a: int, b: int) -> int { a * b }
let mut b = Builder::new("mul", &[Type::Int, Type::Int], Type::Int);
let a = b.block_params(b.entry())[0];
let c = b.block_params(b.entry())[1];
let p = b.bin(BinOp::Mul, a, c);
b.ret(Some(p));

let jit = Jit::new().unwrap();
let mul = jit.compile(&b.finish()).expect("mul is well-formed");

// SAFETY: the signature is `fn(int, int) -> int`, and `mul` outlives the call.
let mul_fn: extern "C" fn(i64, i64) -> i64 = unsafe { mul.entry() };
assert_eq!(mul_fn(6, 7), 42);

Trait Implementations§

Source§

impl Debug for Jit

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for Jit

§

impl !UnwindSafe for Jit

§

impl Freeze for Jit

§

impl Send for Jit

§

impl Sync for Jit

§

impl Unpin for Jit

§

impl UnsafeUnpin for Jit

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.