Files
ngr/src/passes/into_crane.rs

95 lines
4.0 KiB
Rust

use crate::asts::lil::{Program, Statement, Primitive, SimpleExpression, Value};
use cranelift_codegen::entity::EntityRef;
use cranelift_codegen::ir::{Function, UserFuncName, UserExternalName, Signature, types, InstBuilder, entities, ExternalName, ExtFuncData, AbiParam};
use cranelift_codegen::isa::CallConv;
use cranelift_codegen::{Context};
use cranelift_frontend::{FunctionBuilderContext, FunctionBuilder, Variable};
use cranelift_module::{FuncId, Module, Linkage, ModuleError, ModuleCompiledFunction};
impl<Annotation> Program<Annotation> {
pub fn into_cranelift<M: Module>(&self, module: &mut M, print_func_id: FuncId) -> Result<ModuleCompiledFunction, ModuleError> {
let basic_signature = Signature {
params: vec![],
returns: vec![],
call_conv: CallConv::SystemV,
};
let func_id = module.declare_function("gogogo", Linkage::Export, &basic_signature)?;
let mut ctx = Context::new();
ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), basic_signature);
let print_func_ref = module.declare_func_in_func(print_func_id, &mut ctx.func);
let mut fctx = FunctionBuilderContext::new();
let mut builder = FunctionBuilder::new(&mut ctx.func, &mut fctx);
let main_block = builder.create_block();
builder.switch_to_block(main_block);
for stmt in self.statements.iter() {
match stmt {
Statement::Print(ann, var) => {
let var = builder.use_var(Variable::new(*var));
builder.ins().call(print_func_ref, &[var]);
}
Statement::ResultBinding(_, varnum, value) => {
let var = Variable::new(*varnum);
builder.declare_var(var, types::I64);
let val = match value {
Primitive::Plus(left, right) => {
let left = left.into_cranelift(&mut builder);
let right = right.into_cranelift(&mut builder);
builder.ins().iadd(left, right)
}
Primitive::Minus(left, right) => {
let left = left.into_cranelift(&mut builder);
let right = right.into_cranelift(&mut builder);
builder.ins().isub(left, right)
}
Primitive::Times(left, right) => {
let left = left.into_cranelift(&mut builder);
let right = right.into_cranelift(&mut builder);
builder.ins().imul(left, right)
}
Primitive::Divide(left, right) => {
let left = left.into_cranelift(&mut builder);
let right = right.into_cranelift(&mut builder);
builder.ins().sdiv(left, right)
}
};
builder.def_var(var, val);
}
Statement::VariableBinding(_, varnum, exp) => {
let var = Variable::new(*varnum);
builder.declare_var(var, types::I64);
let val = exp.into_cranelift(&mut builder);
builder.def_var(var, val);
}
}
}
builder.ins().return_(&[]);
builder.seal_block(main_block);
builder.finalize();
module.define_function(func_id, &mut ctx)
}
}
impl<Annotation> SimpleExpression<Annotation> {
fn into_cranelift(&self, builder: &mut FunctionBuilder) -> entities::Value {
match self {
SimpleExpression::Constant(_, value) => match value {
Value::Number(_base, numval) => builder.ins().iconst(types::I64, *numval as i64),
}
SimpleExpression::Reference(_, num) => builder.use_var(Variable::new(*num)),
}
}
}