#ir #cretonne #builder #variables #construction #cranelift #language

yanked cretonne-frontend

Cretonne IR builder helper

Uses old Rust 2015

0.13.2 Jul 14, 2018
0.12.0 Jun 16, 2018
0.4.1 Mar 18, 2018

#1 in #cretonne


Used in 2 crates

Apache-2.0

2MB
35K SLoC

Rust 26K SLoC // 0.1% comments Python 9K SLoC // 0.4% comments Shell 15 SLoC // 0.3% comments INI 4 SLoC

Cretonne has been renamed to Cranelift! For future versions, see the cranelift-frontend crate.

This crate provides a straightforward way to create a Cretonne IR function and fill it with instructions translated from another language. It contains an SSA construction module that provides convenient methods for translating non-SSA variables into SSA Cretonne IR values via use_var and def_var calls.


lib.rs:

Cretonne IR builder library.

Provides a straightforward way to create a Cretonne IR function and fill it with instructions translated from another language. Contains an SSA construction module that lets you translate your non-SSA variables into SSA Cretonne IR values via use_var and def_var calls.

To get started, create an FunctionBuilderContext and pass it as an argument to a FunctionBuilder.

Example

Here is a pseudo-program we want to transform into Cretonne IR:

function(x) {
x, y, z : i32
block0:
   y = 2;
   z = x + y;
   jump block1
block1:
   z = z + y;
   brnz y, block2;
   z = z - x;
   return y
block2:
   y = y - x
   jump block1
}

Here is how you build the corresponding Cretonne IR function using FunctionBuilderContext:

extern crate cretonne_codegen;
extern crate cretonne_frontend;

use cretonne_codegen::entity::EntityRef;
use cretonne_codegen::ir::{ExternalName, Function, Signature, AbiParam, InstBuilder};
use cretonne_codegen::ir::types::*;
use cretonne_codegen::settings::{self, CallConv};
use cretonne_frontend::{FunctionBuilderContext, FunctionBuilder, Variable};
use cretonne_codegen::verifier::verify_function;

fn main() {
    let mut sig = Signature::new(CallConv::SystemV);
    sig.returns.push(AbiParam::new(I32));
    sig.params.push(AbiParam::new(I32));
    let mut fn_builder_ctx = FunctionBuilderContext::<Variable>::new();
    let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);
    {
        let mut builder = FunctionBuilder::<Variable>::new(&mut func, &mut fn_builder_ctx);

        let block0 = builder.create_ebb();
        let block1 = builder.create_ebb();
        let block2 = builder.create_ebb();
        let x = Variable::new(0);
        let y = Variable::new(1);
        let z = Variable::new(2);
        builder.declare_var(x, I32);
        builder.declare_var(y, I32);
        builder.declare_var(z, I32);
        builder.append_ebb_params_for_function_params(block0);

        builder.switch_to_block(block0);
        builder.seal_block(block0);
        {
            let tmp = builder.ebb_params(block0)[0]; // the first function parameter
            builder.def_var(x, tmp);
        }
        {
            let tmp = builder.ins().iconst(I32, 2);
            builder.def_var(y, tmp);
        }
        {
            let arg1 = builder.use_var(x);
            let arg2 = builder.use_var(y);
            let tmp = builder.ins().iadd(arg1, arg2);
            builder.def_var(z, tmp);
        }
        builder.ins().jump(block1, &[]);

        builder.switch_to_block(block1);
        {
            let arg1 = builder.use_var(y);
            let arg2 = builder.use_var(z);
            let tmp = builder.ins().iadd(arg1, arg2);
            builder.def_var(z, tmp);
        }
        {
            let arg = builder.use_var(y);
            builder.ins().brnz(arg, block2, &[]);
        }
        {
            let arg1 = builder.use_var(z);
            let arg2 = builder.use_var(x);
            let tmp = builder.ins().isub(arg1, arg2);
            builder.def_var(z, tmp);
        }
        {
            let arg = builder.use_var(y);
            builder.ins().return_(&[arg]);
        }

        builder.switch_to_block(block2);
        builder.seal_block(block2);

        {
            let arg1 = builder.use_var(y);
            let arg2 = builder.use_var(x);
            let tmp = builder.ins().isub(arg1, arg2);
            builder.def_var(y, tmp);
        }
        builder.ins().jump(block1, &[]);
        builder.seal_block(block1);

        builder.finalize();
    }

    let flags = settings::Flags::new(settings::builder());
    let res = verify_function(&func, &flags);
    println!("{}", func.display(None));
    match res {
        Ok(_) => {}
        Err(err) => panic!("{}", err),
    }
}

Dependencies

~2MB
~47K SLoC