home

How To Call Rust Functions From Cranelift

May 2021

Here I’ll explain how to resolve that issue and in the process explain how you can call a Rust function that you’ve written from Cranelift code.

By the end of this you’ll be able to write a simple little print function in your compiled programming language.

(print "that's right")

To start, let’s assume you have a Rust function you’d like to call. Mine is pretty simple and just prints a value from my Lust programming language to standard out:

pub fn print_lustc_word(word: Word) -> Word {
    let expr = Expr::from_immediate(word);
    println!("{}", expr);
    Expr::Nil.immediate_rep()
}

I’ve been using this to debug my programs by printing the last value that they evaluate. This morning the thought came to me that if I could call lustc_print_word from Lust code I’d have a print function. Very cool.

To start, navigate in your code to where you construct your Cranelift JIT and add the following lines:

// Register the print function.
let print_addr = print_lustc_word as *const u8;
builder.symbol("print_lustc_word", print_addr);

Now my JIT building looks something like this:

let mut builder = JITBuilder::new(cranelift_module::default_libcall_names());

// Register the print function.
let print_addr = print_lustc_word as *const u8;
builder.symbol("print_lustc_word", print_addr);

Once you’ve done that it’s smooth sailing. Here’s how you can call that function from Cranelift code:

let mut sig = ctx.module.make_signature();
sig.params.push(AbiParam::new(ctx.word));
sig.returns.push(AbiParam::new(ctx.word));

let callee = ctx
    .module
    .declare_function("print_lustc_word", cranelift_module::Linkage::Import, &sig)
    .map_err(|e| e.to_string())?;

let local_callee = ctx
    .module
    .declare_func_in_func(callee, &mut ctx.builder.func);

let call = ctx.builder.ins().call(local_callee, &args);
let res = ctx.builder.inst_results(call)[0]

Cool. You’re done. It is actually that easy. Here’s the complete code if you’re interested.

If you liked this consider giving Lust a GitHub star to make me feel better about spending my free time working on it.