Compare commits

...

6 Commits

Author SHA1 Message Date
a3642f127c Verify before printing 2024-09-12 20:41:23 +03:00
7f3a3ac1f8 modify how block is codegenerated 2024-08-25 23:28:01 +03:00
e21f47e34b Implement some kind of if/else 2024-08-25 23:17:52 +03:00
8defa39b31 Restructure a bit 2024-08-25 22:29:45 +03:00
6a4c30e49e Add scope.inner 2024-08-22 00:34:58 +03:00
8b8cd2c464 Add comments to easy.reid 2024-08-21 23:31:31 +03:00
6 changed files with 137 additions and 46 deletions

View File

@ -1,9 +1,9 @@
use reid::compile; use reid::compile;
pub static EASY: &str = include_str!("./reid/easy.reid"); pub static ARITHMETIC: &str = include_str!("./reid/arithmetic.reid");
fn main() { fn main() {
let text = match compile(EASY) { let text = match compile(ARITHMETIC) {
Ok(t) => t, Ok(t) => t,
Err(e) => panic!("{}", e), Err(e) => panic!("{}", e),
}; };

View File

@ -3,8 +3,12 @@
fn main() { fn main() {
let test = 9; let test = 9;
let simpleAdd = 2 + 2; let simpleAdd = 2 + 2;
let simpleMult = 7 * 2; let simpleMult = 7 * 2; // 14
let arithmetic = 3 + 2 * 5 + 1 * 2; let arithmetic = 3 + 2 * 5 + 1 * 2; // 15
if simpleAdd < test {
return 3;
}
return arithmetic + simpleMult * arithmetic; return arithmetic + simpleMult * arithmetic;
} }

View File

@ -1,17 +1,9 @@
// Hello, comment here! // Main
import std::print;
fn main() { fn main() {
let hello = 32 + { return fibonacci(10);
2 + 3
};
let beep = hello + fibonacci();
return beep;
} }
// Fibonacci // Fibonacci
fn fibonacci(value: i32) -> i32 { fn fibonacci(value: i32) -> i32 {
if value < 3 { if value < 3 {
return 1; return 1;

View File

@ -214,7 +214,7 @@ impl Parse for FunctionCallExpression {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct IfExpression(Expression, pub Block, pub TokenRange); pub struct IfExpression(pub Expression, pub Block, pub TokenRange);
impl Parse for IfExpression { impl Parse for IfExpression {
fn parse(mut stream: TokenStream) -> Result<Self, Error> { fn parse(mut stream: TokenStream) -> Result<Self, Error> {

View File

@ -1,6 +1,9 @@
use std::borrow::BorrowMut;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::mem; use std::mem;
use std::ptr::null_mut;
use llvm_sys::analysis::LLVMVerifyModule;
use llvm_sys::{ use llvm_sys::{
core::*, prelude::*, LLVMBasicBlock, LLVMBuilder, LLVMContext, LLVMModule, LLVMType, LLVMValue, core::*, prelude::*, LLVMBasicBlock, LLVMBuilder, LLVMContext, LLVMModule, LLVMType, LLVMValue,
}; };
@ -21,14 +24,16 @@ pub enum Error {
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub enum IRType { pub enum IRType {
I32, I32,
Boolean,
} }
impl IRType { impl IRType {
fn in_context(&self, context: &mut IRContext) -> *mut LLVMType { fn in_context(&self, context: &IRContext) -> *mut LLVMType {
use IRType::*; use IRType::*;
unsafe { unsafe {
return match self { return match self {
I32 => LLVMInt32TypeInContext(context.context), I32 => LLVMInt32TypeInContext(context.context),
Boolean => LLVMInt1TypeInContext(context.context),
}; };
} }
} }
@ -38,14 +43,14 @@ impl IRType {
pub struct IRValue(pub IRType, *mut LLVMValue); pub struct IRValue(pub IRType, *mut LLVMValue);
impl IRValue { impl IRValue {
pub fn from_literal(literal: &ast::Literal, block: &mut IRBlock) -> Self { pub fn from_literal(literal: &ast::Literal, module: &IRModule) -> Self {
use ast::Literal; use ast::Literal;
match literal { match literal {
Literal::I32(v) => { Literal::I32(v) => {
let ir_type = IRType::I32; let ir_type = IRType::I32;
unsafe { unsafe {
let ir_value = LLVMConstInt( let ir_value = LLVMConstInt(
ir_type.in_context(block.function.module.context), ir_type.in_context(module.context),
mem::transmute(*v as i64), mem::transmute(*v as i64),
1, 1,
); );
@ -102,7 +107,14 @@ impl<'a> IRModule<'a> {
} }
pub fn print_to_string(&mut self) -> Result<&str, std::str::Utf8Error> { pub fn print_to_string(&mut self) -> Result<&str, std::str::Utf8Error> {
unsafe { CStr::from_ptr(LLVMPrintModuleToString(self.module)).to_str() } unsafe {
LLVMVerifyModule(
self.module,
llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction,
null_mut(),
);
CStr::from_ptr(LLVMPrintModuleToString(self.module)).to_str()
}
} }
} }
@ -116,18 +128,17 @@ impl<'a> Drop for IRModule<'a> {
} }
pub struct IRFunction<'a, 'b> { pub struct IRFunction<'a, 'b> {
module: &'b mut IRModule<'a>, pub module: &'b IRModule<'a>,
/// The actual function /// The actual function
value: *mut LLVMValue, value: *mut LLVMValue,
} }
impl<'a, 'b> IRFunction<'a, 'b> { impl<'a, 'b> IRFunction<'a, 'b> {
pub fn new(name: &String, module: &'b mut IRModule<'a>) -> IRFunction<'a, 'b> { pub fn new(name: &String, module: &'b IRModule<'a>) -> IRFunction<'a, 'b> {
unsafe { unsafe {
// TODO, fix later! // TODO, fix later!
let return_type = LLVMInt32TypeInContext(module.context.context); let return_type = LLVMInt32TypeInContext(module.context.context);
let mut argts = []; let mut argts = [];
let func_type = let func_type =
LLVMFunctionType(return_type, argts.as_mut_ptr(), argts.len() as u32, 0); LLVMFunctionType(return_type, argts.as_mut_ptr(), argts.len() as u32, 0);
@ -143,18 +154,15 @@ impl<'a, 'b> IRFunction<'a, 'b> {
} }
pub struct IRBlock<'a, 'b, 'c> { pub struct IRBlock<'a, 'b, 'c> {
function: &'a mut IRFunction<'b, 'c>, pub function: &'c IRFunction<'a, 'b>,
blockref: *mut LLVMBasicBlock, blockref: *mut LLVMBasicBlock,
} }
impl<'a, 'b, 'c> IRBlock<'a, 'b, 'c> { impl<'a, 'b, 'c> IRBlock<'a, 'b, 'c> {
pub fn new(function: &'a mut IRFunction<'b, 'c>) -> IRBlock<'a, 'b, 'c> { pub fn new(function: &'c IRFunction<'a, 'b>, name: &CStr) -> IRBlock<'a, 'b, 'c> {
unsafe { unsafe {
let blockref = LLVMCreateBasicBlockInContext( let blockref =
function.module.context.context, LLVMCreateBasicBlockInContext(function.module.context.context, name.as_ptr());
into_cstring("entryblock").as_ptr(),
);
LLVMPositionBuilderAtEnd(function.module.context.builder, blockref);
IRBlock { function, blockref } IRBlock { function, blockref }
} }
@ -166,6 +174,7 @@ impl<'a, 'b, 'c> IRBlock<'a, 'b, 'c> {
IRValue(rhs_t, rhs_v): IRValue, IRValue(rhs_t, rhs_v): IRValue,
) -> Result<IRValue, Error> { ) -> Result<IRValue, Error> {
unsafe { unsafe {
LLVMPositionBuilderAtEnd(self.function.module.context.builder, self.blockref);
if lhs_t == rhs_t { if lhs_t == rhs_t {
Ok(IRValue( Ok(IRValue(
lhs_t, lhs_t,
@ -188,6 +197,7 @@ impl<'a, 'b, 'c> IRBlock<'a, 'b, 'c> {
IRValue(rhs_t, rhs_v): IRValue, IRValue(rhs_t, rhs_v): IRValue,
) -> Result<IRValue, Error> { ) -> Result<IRValue, Error> {
unsafe { unsafe {
LLVMPositionBuilderAtEnd(self.function.module.context.builder, self.blockref);
if lhs_t == rhs_t { if lhs_t == rhs_t {
Ok(IRValue( Ok(IRValue(
lhs_t, lhs_t,
@ -204,8 +214,33 @@ impl<'a, 'b, 'c> IRBlock<'a, 'b, 'c> {
} }
} }
pub fn add_return(self, value: Option<IRValue>) { pub fn less_than(
&mut self,
IRValue(lhs_t, lhs_v): IRValue,
IRValue(rhs_t, rhs_v): IRValue,
) -> Result<IRValue, Error> {
unsafe { unsafe {
LLVMPositionBuilderAtEnd(self.function.module.context.builder, self.blockref);
if lhs_t == rhs_t {
Ok(IRValue(
IRType::Boolean,
LLVMBuildICmp(
self.function.module.context.builder,
llvm_sys::LLVMIntPredicate::LLVMIntULT,
lhs_v,
rhs_v,
c"IntULT".as_ptr(),
),
))
} else {
Err(Error::TypeMismatch(lhs_t, rhs_t))
}
}
}
pub fn add_return(&mut self, value: Option<IRValue>) {
unsafe {
LLVMPositionBuilderAtEnd(self.function.module.context.builder, self.blockref);
if let Some(IRValue(_, value)) = value { if let Some(IRValue(_, value)) = value {
LLVMBuildRet(self.function.module.context.builder, value); LLVMBuildRet(self.function.module.context.builder, value);
} else { } else {
@ -213,6 +248,30 @@ impl<'a, 'b, 'c> IRBlock<'a, 'b, 'c> {
} }
} }
} }
pub fn branch(
&mut self,
IRValue(_, condition): IRValue,
then_block: &mut IRBlock,
else_block: &mut IRBlock,
) {
unsafe {
LLVMPositionBuilderAtEnd(self.function.module.context.builder, self.blockref);
LLVMBuildCondBr(
self.function.module.context.builder,
condition,
then_block.blockref,
else_block.blockref,
);
}
}
pub fn move_into(&mut self, block: &mut IRBlock) {
unsafe {
LLVMPositionBuilderAtEnd(self.function.module.context.builder, self.blockref);
LLVMBuildBr(self.function.module.context.builder, block.blockref);
}
}
} }
impl<'a, 'b, 'c> Drop for IRBlock<'a, 'b, 'c> { impl<'a, 'b, 'c> Drop for IRBlock<'a, 'b, 'c> {

View File

@ -6,7 +6,7 @@ use llvm::{Error, IRBlock, IRContext, IRFunction, IRModule, IRValue};
use crate::{ use crate::{
ast::{ ast::{
BinaryOperator, Block, BlockLevelStatement, Expression, ExpressionKind, FunctionDefinition, Block, BlockLevelStatement, Expression, ExpressionKind, FunctionDefinition, IfExpression,
LetStatement, ReturnType, LetStatement, ReturnType,
}, },
TopLevelStatement, TopLevelStatement,
@ -41,21 +41,30 @@ impl TopLevelStatement {
impl FunctionDefinition { impl FunctionDefinition {
fn codegen(&self, scope: &mut ScopeData, module: &mut IRModule) { fn codegen(&self, scope: &mut ScopeData, module: &mut IRModule) {
let FunctionDefinition(signature, block, _) = self; let FunctionDefinition(signature, block, _) = self;
let mut ir_function = IRFunction::new(&signature.name, module); let ir_function = IRFunction::new(&signature.name, module);
let ir_block = IRBlock::new(&mut ir_function);
block.codegen(scope.with_block(ir_block)); let ir_block = IRBlock::new(&ir_function, c"entry");
let mut scope = scope.inner(ir_block);
if let Some((_, val)) = block.codegen(&mut scope) {
scope.block.add_return(Some(val));
} else {
scope.block.add_return(None);
}
} }
} }
impl Block { impl Block {
fn codegen(&self, mut scope: Scope) { #[must_use]
fn codegen(&self, scope: &mut Scope) -> Option<(ReturnType, IRValue)> {
for statement in &self.0 { for statement in &self.0 {
statement.codegen(&mut scope); statement.codegen(scope);
} }
if let Some((_, return_exp)) = &self.1 { if let Some((ret_type, return_exp)) = &self.1 {
let value = return_exp.codegen(&mut scope); let value = return_exp.codegen(scope);
scope.block.add_return(Some(value)); Some((*ret_type, value))
} else {
None
} }
} }
} }
@ -83,7 +92,7 @@ impl Expression {
use ExpressionKind::*; use ExpressionKind::*;
match kind { match kind {
Literal(lit) => IRValue::from_literal(lit, &mut scope.block), Literal(lit) => IRValue::from_literal(lit, &scope.block.function.module),
VariableName(v) => scope.data.fetch(v), VariableName(v) => scope.data.fetch(v),
Binop(op, lhs, rhs) => { Binop(op, lhs, rhs) => {
let lhs = lhs.codegen(scope); let lhs = lhs.codegen(scope);
@ -92,10 +101,30 @@ impl Expression {
match op { match op {
Add => scope.block.add(lhs, rhs).unwrap(), Add => scope.block.add(lhs, rhs).unwrap(),
Mult => scope.block.mult(lhs, rhs).unwrap(), Mult => scope.block.mult(lhs, rhs).unwrap(),
LessThan => scope.block.less_than(lhs, rhs).unwrap(),
_ => panic!("operator not supported: {:?}", op), _ => panic!("operator not supported: {:?}", op),
} }
} }
_ => panic!("expression type not supported"), IfExpr(ifx) => {
let IfExpression(expr, block, _) = ifx.as_ref();
let condition = expr.codegen(scope);
let mut thenb = IRBlock::new(scope.block.function, c"then");
let mut afterb = IRBlock::new(scope.block.function, c"merge");
scope.block.branch(condition, &mut thenb, &mut afterb);
scope.block = afterb;
let mut then = scope.inner(thenb);
match block.codegen(&mut then) {
Some((ReturnType::Hard, v)) => then.block.add_return(Some(v)),
_ => then.block.move_into(&mut scope.block),
}
IRValue::from_literal(&crate::ast::Literal::I32(1), scope.block.function.module)
}
BlockExpr(_) => panic!("block expr not supported"),
FunctionCall(_) => panic!("function call expr not supported"),
} }
} }
} }
@ -112,11 +141,12 @@ impl ScopeData {
} }
} }
fn with_block<'a, 'b, 'c>(&self, block: IRBlock<'a, 'b, 'c>) -> Scope<'a, 'b, 'c> { fn with_block<'a, 'b, 'c>(self, block: IRBlock<'a, 'b, 'c>) -> Scope<'a, 'b, 'c> {
Scope { Scope { data: self, block }
data: self.clone(), }
block,
} fn inner<'a, 'b, 'c>(&self, block: IRBlock<'a, 'b, 'c>) -> Scope<'a, 'b, 'c> {
self.clone().with_block(block)
} }
fn fetch(&self, name: &String) -> IRValue { fn fetch(&self, name: &String) -> IRValue {
@ -138,3 +168,9 @@ struct Scope<'a, 'b, 'c> {
data: ScopeData, data: ScopeData,
block: IRBlock<'a, 'b, 'c>, block: IRBlock<'a, 'b, 'c>,
} }
impl<'a, 'b, 'c> Scope<'a, 'b, 'c> {
fn inner(&self, block: IRBlock<'a, 'b, 'c>) -> Scope<'a, 'b, 'c> {
self.data.clone().with_block(block)
}
}