sprite-rs/src/jit/translate.rs

93 lines
3.0 KiB
Rust
Raw Normal View History

2022-03-26 03:21:24 +00:00
// Copyright (c) 2022 Marceline Cramer
// SPDX-License-Identifier: GPL-3.0-or-later
use crate::parse::ast;
2022-03-26 15:42:59 +00:00
use cranelift::prelude::*;
2022-03-26 03:21:24 +00:00
pub struct FunctionTranslator<'a> {
pub int: types::Type,
pub builder: FunctionBuilder<'a>,
}
impl<'a> FunctionTranslator<'a> {
2022-03-26 15:42:59 +00:00
pub fn translate(mut self, fn_impl: &ast::FnImpl) {
let signature = &fn_impl.def.signature;
let return_info = if let Some(tail_expr) = &fn_impl.body.tail_expr {
match signature.return_type {
Some(t) => Some((tail_expr, t)),
None => panic!("Function has tail expression but no return type"),
}
} else if let Some(_) = signature.return_type {
panic!("Function has return type but no tail expression");
} else {
None
};
for _ in signature.args.iter() {
self.builder
.func
.signature
.params
.push(AbiParam::new(self.int));
}
if let Some((_, _return_type)) = return_info {
self.builder
.func
.signature
.returns
.push(AbiParam::new(self.int));
}
let entry_block = self.builder.create_block();
self.builder
.append_block_params_for_function_params(entry_block);
self.builder.switch_to_block(entry_block);
self.builder.seal_block(entry_block);
if fn_impl.body.statements.len() > 0 {
unimplemented!("Function body statements are unimplemented");
}
if let Some((tail_expr, _)) = return_info {
let return_value = self.translate_expr(tail_expr);
self.builder.ins().return_(&[return_value]);
}
println!("{}", self.builder.func.display());
self.builder.finalize();
}
2022-03-26 03:21:24 +00:00
pub fn translate_expr(&mut self, expr: &ast::Expr) -> Value {
use ast::Expr::*;
match expr {
Literal(ast::Literal::DecimalInteger(literal)) => {
// TODO parse integers while building ast so that codegen doesn't have to
let val: i64 = literal.parse().unwrap();
self.builder.ins().iconst(self.int, val)
}
BinaryOp(op, terms) => {
let lhs = self.translate_expr(&terms.0);
let rhs = self.translate_expr(&terms.1);
self.translate_binary_op(op, lhs, rhs)
}
// TODO the AST doesn't need this either
Group(expr) => self.translate_expr(expr),
_ => unimplemented!("Expression: {:#?}", expr),
}
}
pub fn translate_binary_op(&mut self, op: &ast::BinaryOp, lhs: Value, rhs: Value) -> Value {
use ast::BinaryOp::*;
let ins = self.builder.ins();
match op {
Add => ins.iadd(lhs, rhs),
Sub => ins.isub(lhs, rhs),
Mul => ins.imul(lhs, rhs),
Div => ins.udiv(lhs, rhs),
_ => unimplemented!("Binary operation: {:#?}", op),
}
}
}