95 lines
4.0 KiB
Rust
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)),
|
|
}
|
|
}
|
|
} |