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 Program { pub fn into_cranelift(&self, module: &mut M, print_func_id: FuncId) -> Result { 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 SimpleExpression { 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)), } } }