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

Code generation for basic block

parent 97ec6d48
No related branches found
No related tags found
No related merge requests found
#![allow(unused_imports)]
#![allow(dead_code)]
use crust::{ use crust::{
ast::{Block, Cmd, Expr, Func, Op, Span, SpanExpr}, ast::{Block, Cmd, Expr, Func, Op, Span, SpanExpr},
parse::{parse_block, parse_expr}, parse::{parse_block, parse_expr},
...@@ -10,10 +13,7 @@ use inkwell::{ ...@@ -10,10 +13,7 @@ use inkwell::{
module::Module, module::Module,
passes::PassManager, passes::PassManager,
types::BasicTypeEnum, types::BasicTypeEnum,
values::{ values::{BasicValueEnum, FloatValue, FunctionValue, InstructionValue, IntValue, PointerValue},
BasicValueEnum, FloatValue, FunctionValue, InstructionValue, IntValue,
PointerValue,
},
FloatPredicate, OptimizationLevel, FloatPredicate, OptimizationLevel,
}; };
use std::collections::HashMap; use std::collections::HashMap;
...@@ -23,23 +23,23 @@ type ExprFunc = unsafe extern "C" fn() -> i32; ...@@ -23,23 +23,23 @@ type ExprFunc = unsafe extern "C" fn() -> i32;
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
let context = Context::create(); let context = Context::create();
let mut module = context.create_module("expr"); let module = context.create_module("expr");
let builder = context.create_builder(); let builder = context.create_builder();
let fpm = PassManager::create(&module); let fpm = PassManager::create(&module);
fpm.initialize(); fpm.initialize();
let execution_engine = let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None)?;
module.create_jit_execution_engine(OptimizationLevel::None)?;
match parse_block(Span::new( match parse_block(Span::new(
" "
{ {
let abba : i32 = 7; let abba : mut i32 = 7;
abba = 5;
return 2 + abba return 2 + abba
} }
", ",
)) { )) {
Ok((_, prog)) => { Ok((_, prog)) => {
println!("{:?}", &prog); println!("ast : {:?}", &prog);
let u32_type = context.i32_type(); let u32_type = context.i32_type();
let fn_type = u32_type.fn_type(&[], false); let fn_type = u32_type.fn_type(&[], false);
let function = module.add_function("expr", fn_type, None); let function = module.add_function("expr", fn_type, None);
...@@ -54,18 +54,17 @@ fn main() -> Result<(), Box<dyn Error>> { ...@@ -54,18 +54,17 @@ fn main() -> Result<(), Box<dyn Error>> {
variables: HashMap::new(), variables: HashMap::new(),
//&fpm, //&fpm,
}; };
let res = compiler.compile_block(prog); compiler.compile_block(prog);
// builder.build_return(Some(&res));
let fun_expr: JitFunction<ExprFunc> = let fun_expr: JitFunction<ExprFunc> =
unsafe { execution_engine.get_function("expr").ok().unwrap() }; unsafe { execution_engine.get_function("expr").ok().unwrap() };
unsafe { unsafe {
println!("{}", fun_expr.call()); println!("\nexecution result : {}", fun_expr.call());
} }
} }
_ => panic!(), _ => panic!(),
} }
println!("module: {}", module.print_to_string()); module.print_to_stderr();
Ok(()) Ok(())
} }
...@@ -87,24 +86,33 @@ impl<'a> Compiler<'a> { ...@@ -87,24 +86,33 @@ impl<'a> Compiler<'a> {
self.module.get_function(name) self.module.get_function(name)
} }
/// Returns the `PointerValue` representing the variable `id`.
#[inline]
fn get_variable(&self, id: &str) -> &PointerValue {
match self.variables.get(id) {
Some(var) => var,
None => panic!(
"Could not find a matching variable, {} in {:?}",
id, self.variables
),
}
}
/// Returns the `FunctionValue` representing the function being compiled. /// Returns the `FunctionValue` representing the function being compiled.
#[inline] #[inline]
fn fn_value(&self) -> FunctionValue { fn fn_value(&self) -> FunctionValue {
self.fn_value_opt.unwrap() self.fn_value_opt.unwrap()
} }
/// For now, returns an IntValue
/// Boolean is i1, single bit integers in LLVM
/// However we might to choose to store them as i8 or i32
fn compile_expr(&self, expr: &SpanExpr) -> IntValue { fn compile_expr(&self, expr: &SpanExpr) -> IntValue {
match expr.1.clone() { match expr.1.clone() {
Expr::Id(id) => match self.variables.get(&id) { Expr::Id(id) => {
Some(var) => { let var = self.get_variable(&id);
self.builder.build_load(*var, &id).into_int_value() self.builder.build_load(*var, &id).into_int_value()
} }
None => panic!(
"Could not find a matching variable.
{} in {:?}",
id, self.variables
),
},
Expr::Num(i) => self.context.i32_type().const_int(i as u64, false), Expr::Num(i) => self.context.i32_type().const_int(i as u64, false),
Expr::BinOp(op, l, r) => { Expr::BinOp(op, l, r) => {
...@@ -115,6 +123,7 @@ impl<'a> Compiler<'a> { ...@@ -115,6 +123,7 @@ impl<'a> Compiler<'a> {
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
// Todo: Binop, Unop, Booleans, Function calls
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
...@@ -134,19 +143,20 @@ impl<'a> Compiler<'a> { ...@@ -134,19 +143,20 @@ impl<'a> Compiler<'a> {
alloca alloca
} }
/// Compiles a command into (InstructionValue, b:bool)
/// `b` indicates that its a return value of the basic block
fn compile_cmd(&mut self, cmd: &Cmd) -> (InstructionValue, bool) { fn compile_cmd(&mut self, cmd: &Cmd) -> (InstructionValue, bool) {
// println!("{:?}", cmd);
match cmd { match cmd {
// Cmd::Assign(lexp, rexp) => { Cmd::Assign((_, lexp), rexp) => match lexp {
// let rval = eval_expr(rexp, mem, venv, fenv); Expr::Id(id) => {
// println!("val {:?}", rval); let var = self.get_variable(id);
// let addr = eval_lvalue(lexp, mem, venv, fenv); let rexp = self.compile_expr(rexp);
// // println!("lval {:?}", lval); (self.builder.build_store(*var, rexp), false)
// // let addr = venv.get(&lval).unwrap(); }
_ => panic!("we are bad"),
// mem.Menv.insert(addr, rval); },
// None
// } // -- TODO: This is code from my `old` interpreter
// Cmd::If(exp, then_block, opt_else) => { // Cmd::If(exp, then_block, opt_else) => {
// if get_bool(eval_expr(exp, mem, venv, fenv)) { // if get_bool(eval_expr(exp, mem, venv, fenv)) {
// eval_body(then_block.to_vec(), mem, venv, fenv) // eval_body(then_block.to_vec(), mem, venv, fenv)
...@@ -158,10 +168,12 @@ impl<'a> Compiler<'a> { ...@@ -158,10 +168,12 @@ impl<'a> Compiler<'a> {
// } // }
// } // }
// } // }
// -- TODO: While
Cmd::Let(_, id, _, exp) => { Cmd::Let(_, id, _, exp) => {
let exp = self.compile_expr(exp); let exp = self.compile_expr(exp);
println!("\n-- let id.fragment {}\n", id.fragment); // allocate a local variable (on the stack)
let alloca = self.create_entry_block_alloca(id.fragment); let alloca = self.create_entry_block_alloca(id.fragment);
// store the (initial) value
let store = self.builder.build_store(alloca, exp); let store = self.builder.build_store(alloca, exp);
(store, false) (store, false)
} }
...@@ -176,28 +188,18 @@ impl<'a> Compiler<'a> { ...@@ -176,28 +188,18 @@ impl<'a> Compiler<'a> {
pub fn compile_block(&mut self, cmds: Vec<Cmd>) -> InstructionValue { pub fn compile_block(&mut self, cmds: Vec<Cmd>) -> InstructionValue {
for c in &cmds { for c in &cmds {
let (cmd, ret) = self.compile_cmd(c); let (cmd, ret) = self.compile_cmd(c);
// early return (e.g., inside a loop/conditional)
if ret { if ret {
return cmd; return cmd;
} }
} }
panic!(); panic!();
} }
}
// fn main() { // TODO, function declarations
// let p = parse_prog(Span::new( }
// "
// fn main() -> i32
// {
// let a : i32 = 1 + 2;
// a = a + 1;
// return a
// }
// ",
// ));
// println!("{:?}", &p);
// }
// SHAMELESSLY STOLEN FROM inkwell!!!!
// // ====================================================================================== // // ======================================================================================
// // COMPILER ============================================================================= // // COMPILER =============================================================================
// // ====================================================================================== // // ======================================================================================
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment