From d69cc69101c47a49b8915b3c0f16bc45ac84f6b2 Mon Sep 17 00:00:00 2001 From: Per Lindgren <per.lindgren@ltu.se> Date: Thu, 3 Oct 2019 14:03:44 +0200 Subject: [PATCH] Code generation for expr (const and add) --- .vscode/tasks.json | 12 +++++ examples/crust.rs | 109 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 99 insertions(+), 22 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index b890df0..4d7ce4c 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -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 diff --git a/examples/crust.rs b/examples/crust.rs index b9e8077..7f92b9a 100644 --- a/examples/crust.rs +++ b/examples/crust.rs @@ -1,7 +1,8 @@ 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_or("Unable to JIT compile `expr`")?; - - unsafe { - println!("{}", fun_expr.call()); + )) { + 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( // " -- GitLab