Skip to content
Snippets Groups Projects
Commit d69cc691 authored by Per Lindgren's avatar Per Lindgren
Browse files

Code generation for expr (const and add)

parent dfbdcd33
No related branches found
No related tags found
No related merge requests found
......@@ -62,6 +62,18 @@
"kind": "build",
"isDefault": true
}
},
{
"type": "shell",
"label": "cargo run --example crust",
"command": "cargo run --example crust",
"problemMatcher": [
"$rustc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
\ No newline at end of file
use crust::{
ast::{Expr, Func, Sig, Span},
ast::{Expr, Func, Op, Span, SpanExpr},
parse::parse_expr,
};
use inkwell::{
builder::Builder,
context::Context,
......@@ -9,7 +10,7 @@ use inkwell::{
module::Module,
passes::PassManager,
types::BasicTypeEnum,
values::{BasicValueEnum, FloatValue, FunctionValue, PointerValue},
values::{BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue},
FloatPredicate, OptimizationLevel,
};
use std::collections::HashMap;
......@@ -18,7 +19,42 @@ use std::error::Error;
type ExprFunc = unsafe extern "C" fn() -> i32;
fn compile_expr(
expr: &SpanExpr,
context: &Context,
module: &Module,
builder: &Builder,
) -> IntValue {
match expr.1.clone() {
Expr::Num(i) => context.i32_type().const_int(i as u64, false),
Expr::BinOp(op, l, r) => {
let lv = compile_expr(&l, context, module, builder);
let rv = compile_expr(&r, context, module, builder);
match op {
Op::Add => builder.build_int_add(lv, rv, "sum")
,
// Op::Sub => lv - rv,
// Op::Mul => lv * rv,
// Op::Div => lv / rv,
// Op::Pow => lv.pow(rv as u32),
_ => unimplemented!(),
}
}
// Expr::UnaryOp(op, e) => {
// let e = eval_expr(&e);
// match op {
// Op::Add => e,
// Op::Sub => -e,
// _ => unimplemented!(),
// }
// }
_ => unimplemented!(),
}
}
fn jit_compile_sum(
expr: &SpanExpr,
context: &Context,
module: &Module,
builder: &Builder,
......@@ -32,14 +68,15 @@ fn jit_compile_sum(
builder.position_at_end(&basic_block);
let x = context.i32_type().const_int(1, false);
let y = context.i32_type().const_int(2, false);
let z = context.i32_type().const_int(3, false);
// let x = context.i32_type().const_int(1, false);
// let y = context.i32_type().const_int(42, false);
// let z = context.i32_type().const_int(3, false);
let sum = builder.build_int_add(x, y, "sum");
let sum = builder.build_int_add(sum, z, "sum");
builder.build_return(Some(&sum));
// let sum = builder.build_int_add(x, y, "sum");
// let sum = builder.build_int_add(sum, z, "sum");
// builder.build_return(Some(&sum));
let res = compile_expr(expr, context, module, builder);
builder.build_return(Some(&res));
unsafe { execution_engine.get_function("expr").ok() }
}
......@@ -48,27 +85,55 @@ fn main() -> Result<(), Box<dyn Error>> {
let context = Context::create();
let module = context.create_module("expr");
let builder = context.create_builder();
let execution_engine =
module.create_jit_execution_engine(OptimizationLevel::None)?;
let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None)?;
let p = parse_expr(Span::new(
match parse_expr(Span::new(
"
1 + 2 + 3
2 + 3
",
));
println!("{:?}", &p);
let fun_expr =
jit_compile_sum(&context, &module, &builder, &execution_engine)
)) {
Ok((_, e)) => {
println!("{:?}", &e);
let fun_expr = jit_compile_sum(&e, &context, &module, &builder, &execution_engine)
.ok_or("Unable to JIT compile `expr`")?;
unsafe {
println!("{}", fun_expr.call());
}
}
_ => panic!(),
}
Ok(())
}
pub fn eval_expr(e: &SpanExpr) -> i32 {
match e.1.clone() {
Expr::Num(i) => i,
Expr::BinOp(op, l, r) => {
let lv = eval_expr(&l);
let rv = eval_expr(&r);
match op {
Op::Add => lv + rv,
Op::Sub => lv - rv,
Op::Mul => lv * rv,
Op::Div => lv / rv,
Op::Pow => lv.pow(rv as u32),
_ => unimplemented!(),
}
}
Expr::UnaryOp(op, e) => {
let e = eval_expr(&e);
match op {
Op::Add => e,
Op::Sub => -e,
_ => unimplemented!(),
}
}
_ => unimplemented!(),
}
}
// fn main() {
// let p = parse_prog(Span::new(
// "
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment