Compare commits
No commits in common. "a3642f127c859ad6de3e1386c59a6e20279ceca6" and "6448b0c438643d5c1a6abe7bb3a0dbac663786a6" have entirely different histories.
a3642f127c
...
6448b0c438
@ -1,9 +1,9 @@
|
|||||||
use reid::compile;
|
use reid::compile;
|
||||||
|
|
||||||
pub static ARITHMETIC: &str = include_str!("./reid/arithmetic.reid");
|
pub static EASY: &str = include_str!("./reid/easy.reid");
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let text = match compile(ARITHMETIC) {
|
let text = match compile(EASY) {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) => panic!("{}", e),
|
Err(e) => panic!("{}", e),
|
||||||
};
|
};
|
@ -3,12 +3,8 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
let test = 9;
|
let test = 9;
|
||||||
let simpleAdd = 2 + 2;
|
let simpleAdd = 2 + 2;
|
||||||
let simpleMult = 7 * 2; // 14
|
let simpleMult = 7 * 2;
|
||||||
let arithmetic = 3 + 2 * 5 + 1 * 2; // 15
|
let arithmetic = 3 + 2 * 5 + 1 * 2;
|
||||||
|
|
||||||
if simpleAdd < test {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
return arithmetic + simpleMult * arithmetic;
|
return arithmetic + simpleMult * arithmetic;
|
||||||
}
|
}
|
@ -1,9 +1,17 @@
|
|||||||
// Main
|
// Hello, comment here!
|
||||||
|
|
||||||
|
import std::print;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
return fibonacci(10);
|
let hello = 32 + {
|
||||||
|
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;
|
||||||
|
@ -214,7 +214,7 @@ impl Parse for FunctionCallExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct IfExpression(pub Expression, pub Block, pub TokenRange);
|
pub struct IfExpression(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> {
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
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,
|
||||||
};
|
};
|
||||||
@ -24,16 +21,14 @@ 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: &IRContext) -> *mut LLVMType {
|
fn in_context(&self, context: &mut 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),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,14 +38,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, module: &IRModule) -> Self {
|
pub fn from_literal(literal: &ast::Literal, block: &mut IRBlock) -> 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(module.context),
|
ir_type.in_context(block.function.module.context),
|
||||||
mem::transmute(*v as i64),
|
mem::transmute(*v as i64),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
@ -107,14 +102,7 @@ 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 {
|
unsafe { CStr::from_ptr(LLVMPrintModuleToString(self.module)).to_str() }
|
||||||
LLVMVerifyModule(
|
|
||||||
self.module,
|
|
||||||
llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction,
|
|
||||||
null_mut(),
|
|
||||||
);
|
|
||||||
CStr::from_ptr(LLVMPrintModuleToString(self.module)).to_str()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,17 +116,18 @@ impl<'a> Drop for IRModule<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct IRFunction<'a, 'b> {
|
pub struct IRFunction<'a, 'b> {
|
||||||
pub module: &'b IRModule<'a>,
|
module: &'b mut 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 IRModule<'a>) -> IRFunction<'a, 'b> {
|
pub fn new(name: &String, module: &'b mut 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);
|
||||||
@ -154,15 +143,18 @@ impl<'a, 'b> IRFunction<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct IRBlock<'a, 'b, 'c> {
|
pub struct IRBlock<'a, 'b, 'c> {
|
||||||
pub function: &'c IRFunction<'a, 'b>,
|
function: &'a mut IRFunction<'b, 'c>,
|
||||||
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: &'c IRFunction<'a, 'b>, name: &CStr) -> IRBlock<'a, 'b, 'c> {
|
pub fn new(function: &'a mut IRFunction<'b, 'c>) -> IRBlock<'a, 'b, 'c> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let blockref =
|
let blockref = LLVMCreateBasicBlockInContext(
|
||||||
LLVMCreateBasicBlockInContext(function.module.context.context, name.as_ptr());
|
function.module.context.context,
|
||||||
|
into_cstring("entryblock").as_ptr(),
|
||||||
|
);
|
||||||
|
LLVMPositionBuilderAtEnd(function.module.context.builder, blockref);
|
||||||
|
|
||||||
IRBlock { function, blockref }
|
IRBlock { function, blockref }
|
||||||
}
|
}
|
||||||
@ -174,7 +166,6 @@ 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,
|
||||||
@ -197,7 +188,6 @@ 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,
|
||||||
@ -214,33 +204,8 @@ impl<'a, 'b, 'c> IRBlock<'a, 'b, 'c> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_than(
|
pub fn add_return(self, value: Option<IRValue>) {
|
||||||
&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 {
|
||||||
@ -248,30 +213,6 @@ 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> {
|
||||||
|
@ -6,7 +6,7 @@ use llvm::{Error, IRBlock, IRContext, IRFunction, IRModule, IRValue};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
Block, BlockLevelStatement, Expression, ExpressionKind, FunctionDefinition, IfExpression,
|
BinaryOperator, Block, BlockLevelStatement, Expression, ExpressionKind, FunctionDefinition,
|
||||||
LetStatement, ReturnType,
|
LetStatement, ReturnType,
|
||||||
},
|
},
|
||||||
TopLevelStatement,
|
TopLevelStatement,
|
||||||
@ -41,30 +41,21 @@ 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 ir_function = IRFunction::new(&signature.name, module);
|
let mut ir_function = IRFunction::new(&signature.name, module);
|
||||||
|
let ir_block = IRBlock::new(&mut ir_function);
|
||||||
let ir_block = IRBlock::new(&ir_function, c"entry");
|
block.codegen(scope.with_block(ir_block));
|
||||||
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 {
|
||||||
#[must_use]
|
fn codegen(&self, mut scope: Scope) {
|
||||||
fn codegen(&self, scope: &mut Scope) -> Option<(ReturnType, IRValue)> {
|
|
||||||
for statement in &self.0 {
|
for statement in &self.0 {
|
||||||
statement.codegen(scope);
|
statement.codegen(&mut scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((ret_type, return_exp)) = &self.1 {
|
if let Some((_, return_exp)) = &self.1 {
|
||||||
let value = return_exp.codegen(scope);
|
let value = return_exp.codegen(&mut scope);
|
||||||
Some((*ret_type, value))
|
scope.block.add_return(Some(value));
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,7 +83,7 @@ impl Expression {
|
|||||||
|
|
||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
match kind {
|
match kind {
|
||||||
Literal(lit) => IRValue::from_literal(lit, &scope.block.function.module),
|
Literal(lit) => IRValue::from_literal(lit, &mut scope.block),
|
||||||
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);
|
||||||
@ -101,30 +92,10 @@ 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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IfExpr(ifx) => {
|
_ => panic!("expression type not supported"),
|
||||||
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"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,12 +112,11 @@ 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 { data: self, block }
|
Scope {
|
||||||
|
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 {
|
||||||
@ -168,9 +138,3 @@ 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user