This commit is contained in:
Sofia 2023-08-02 18:43:47 +03:00
parent 08909d76ee
commit 2ced45eb40
5 changed files with 38 additions and 30 deletions

View File

@ -1,16 +1,16 @@
use std::collections::{hash_map, HashMap}; use std::collections::{hash_map, HashMap};
use crate::{ use crate::{
llvm_ir::{IRBlock, IRModule, Value, ValueType}, ast::{
parser::{
BinaryOperator, BlockLevelStatement, Expression, FunctionDefinition, Literal, BinaryOperator, BlockLevelStatement, Expression, FunctionDefinition, Literal,
TopLevelStatement, TopLevelStatement,
}, },
llvm_ir::{IRBlock, IRModule, IRValue, IRValueType},
}; };
pub struct Scope<'a> { pub struct Scope<'a> {
pub block: IRBlock<'a>, pub block: IRBlock<'a>,
named_vars: HashMap<String, Value>, named_vars: HashMap<String, IRValue>,
} }
impl<'a> Scope<'a> { impl<'a> Scope<'a> {
@ -21,11 +21,11 @@ impl<'a> Scope<'a> {
} }
} }
pub fn get(&self, name: &String) -> Option<&Value> { pub fn get(&self, name: &String) -> Option<&IRValue> {
self.named_vars.get(name) self.named_vars.get(name)
} }
pub fn set(&mut self, name: &str, val: Value) -> Result<(), ()> { pub fn set(&mut self, name: &str, val: IRValue) -> Result<(), ()> {
if let hash_map::Entry::Vacant(e) = self.named_vars.entry(name.to_owned()) { if let hash_map::Entry::Vacant(e) = self.named_vars.entry(name.to_owned()) {
e.insert(val); e.insert(val);
Ok(()) Ok(())
@ -39,7 +39,7 @@ impl TopLevelStatement {
pub fn codegen(&self, module: &mut IRModule) { pub fn codegen(&self, module: &mut IRModule) {
match self { match self {
TopLevelStatement::FunctionDefinition(FunctionDefinition(sig, block)) => { TopLevelStatement::FunctionDefinition(FunctionDefinition(sig, block)) => {
let func = module.create_func(&sig.name, ValueType::I32); let func = module.create_func(&sig.name, IRValueType::I32);
let mut scope = Scope::from(module.create_block()); let mut scope = Scope::from(module.create_block());
for statement in &block.0 { for statement in &block.0 {
@ -49,7 +49,7 @@ impl TopLevelStatement {
let value = if let Some(exp) = &block.1 { let value = if let Some(exp) = &block.1 {
exp.codegen(&mut scope) exp.codegen(&mut scope)
} else { } else {
scope.block.get_const(&Literal::I32(0)) panic!("Void-return type function not yet implemented!");
}; };
func.add_definition(value, scope.block); func.add_definition(value, scope.block);
} }
@ -73,7 +73,7 @@ impl BlockLevelStatement {
} }
impl Expression { impl Expression {
pub fn codegen(&self, scope: &mut Scope) -> Value { pub fn codegen(&self, scope: &mut Scope) -> IRValue {
use Expression::*; use Expression::*;
match self { match self {
Binop(op, lhs, rhs) => match op { Binop(op, lhs, rhs) => match op {

View File

@ -3,7 +3,7 @@ use std::mem;
use llvm_sys::{core::*, prelude::*, LLVMBuilder, LLVMContext, LLVMModule}; use llvm_sys::{core::*, prelude::*, LLVMBuilder, LLVMContext, LLVMModule};
use crate::parser::Literal; use crate::ast::Literal;
macro_rules! cstr { macro_rules! cstr {
($string:expr) => { ($string:expr) => {
@ -12,11 +12,11 @@ macro_rules! cstr {
} }
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum ValueType { pub enum IRValueType {
I32, I32,
} }
impl ValueType { impl IRValueType {
unsafe fn get_llvm_type(&self, codegen: &mut IRModule) -> LLVMTypeRef { unsafe fn get_llvm_type(&self, codegen: &mut IRModule) -> LLVMTypeRef {
match *self { match *self {
Self::I32 => LLVMInt32TypeInContext(codegen.context), Self::I32 => LLVMInt32TypeInContext(codegen.context),
@ -26,7 +26,7 @@ impl ValueType {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[must_use = "value contains raw pointer and must be inserted somewhere"] #[must_use = "value contains raw pointer and must be inserted somewhere"]
pub struct Value(ValueType, LLVMValueRef); pub struct IRValue(IRValueType, LLVMValueRef);
fn into_cstring<T: Into<String>>(value: T) -> CString { fn into_cstring<T: Into<String>>(value: T) -> CString {
let string = value.into(); let string = value.into();
@ -40,11 +40,11 @@ pub struct IRModule {
} }
impl IRModule { impl IRModule {
pub fn new() -> IRModule { pub fn new<T: Into<String>>(name: T) -> IRModule {
unsafe { unsafe {
// Set up a context, module and builder in that context. // Set up a context, module and builder in that context.
let context = LLVMContextCreate(); let context = LLVMContextCreate();
let module = LLVMModuleCreateWithNameInContext(cstr!("testmodule"), context); let module = LLVMModuleCreateWithNameInContext(into_cstring(name).as_ptr(), context);
let builder = LLVMCreateBuilderInContext(context); let builder = LLVMCreateBuilderInContext(context);
IRModule { IRModule {
@ -59,7 +59,11 @@ impl IRModule {
IRBlock::create("entry", self) IRBlock::create("entry", self)
} }
pub fn create_func<T: Into<String>>(&mut self, name: T, return_type: ValueType) -> IRFunction { pub fn create_func<T: Into<String>>(
&mut self,
name: T,
return_type: IRValueType,
) -> IRFunction {
unsafe { unsafe {
let mut argts = []; let mut argts = [];
let func_type = LLVMFunctionType( let func_type = LLVMFunctionType(
@ -71,10 +75,16 @@ impl IRModule {
let anon_func = LLVMAddFunction(self.module, into_cstring(name).as_ptr(), func_type); let anon_func = LLVMAddFunction(self.module, into_cstring(name).as_ptr(), func_type);
IRFunction { IRFunction {
value: Value(return_type, anon_func), value: IRValue(return_type, anon_func),
} }
} }
} }
pub fn dump(&mut self) {
unsafe {
LLVMDumpModule(self.module);
}
}
} }
impl Drop for IRModule { impl Drop for IRModule {
@ -82,7 +92,6 @@ impl Drop for IRModule {
// Clean up. Values created in the context mostly get cleaned up there. // Clean up. Values created in the context mostly get cleaned up there.
unsafe { unsafe {
LLVMDisposeBuilder(self.builder); LLVMDisposeBuilder(self.builder);
LLVMDumpModule(self.module);
LLVMDisposeModule(self.module); LLVMDisposeModule(self.module);
LLVMContextDispose(self.context); LLVMContextDispose(self.context);
} }
@ -90,11 +99,11 @@ impl Drop for IRModule {
} }
pub struct IRFunction { pub struct IRFunction {
value: Value, value: IRValue,
} }
impl IRFunction { impl IRFunction {
pub fn add_definition(self, ret: Value, block: IRBlock) { pub fn add_definition(self, ret: IRValue, block: IRBlock) {
unsafe { unsafe {
LLVMAppendExistingBasicBlock(self.value.1, block.blockref); LLVMAppendExistingBasicBlock(self.value.1, block.blockref);
LLVMBuildRet(block.module.builder, ret.1); LLVMBuildRet(block.module.builder, ret.1);
@ -120,11 +129,11 @@ impl<'a> IRBlock<'a> {
} }
} }
pub fn get_const(&mut self, literal_type: &Literal) -> Value { pub fn get_const(&mut self, literal_type: &Literal) -> IRValue {
unsafe { unsafe {
match *literal_type { match *literal_type {
Literal::I32(v) => Value( Literal::I32(v) => IRValue(
ValueType::I32, IRValueType::I32,
LLVMConstInt( LLVMConstInt(
LLVMInt32TypeInContext(self.module.context), LLVMInt32TypeInContext(self.module.context),
mem::transmute(v as i64), mem::transmute(v as i64),
@ -135,10 +144,10 @@ impl<'a> IRBlock<'a> {
} }
} }
pub fn add(&mut self, lhs: Value, rhs: Value) -> Result<Value, ()> { pub fn add(&mut self, lhs: IRValue, rhs: IRValue) -> Result<IRValue, ()> {
unsafe { unsafe {
if lhs.0 == rhs.0 { if lhs.0 == rhs.0 {
Ok(Value( Ok(IRValue(
lhs.0, lhs.0,
LLVMBuildAdd(self.module.builder, lhs.1, rhs.1, cstr!("tmpadd")), LLVMBuildAdd(self.module.builder, lhs.1, rhs.1, cstr!("tmpadd")),
)) ))

View File

@ -1,16 +1,14 @@
use crate::{ use crate::{ast::TopLevelStatement, lexer::Token, llvm_ir::IRModule, token_stream::TokenStream};
lexer::Token, llvm_ir::IRModule, parser::TopLevelStatement, token_stream::TokenStream,
};
pub static EASIEST: &str = include_str!("../reid/easiest.reid"); pub static EASIEST: &str = include_str!("../reid/easiest.reid");
pub static EASY: &str = include_str!("../reid/easy.reid"); pub static EASY: &str = include_str!("../reid/easy.reid");
pub static MEDIUM: &str = include_str!("../reid/medium.reid"); pub static MEDIUM: &str = include_str!("../reid/medium.reid");
pub static HARD: &str = include_str!("../reid/hard.reid"); pub static HARD: &str = include_str!("../reid/hard.reid");
mod ast;
mod codegen; mod codegen;
mod lexer; mod lexer;
mod llvm_ir; mod llvm_ir;
mod parser;
mod token_stream; mod token_stream;
// TODO: // TODO:
@ -34,8 +32,9 @@ fn main() {
statements.push(statement); statements.push(statement);
} }
let mut module = IRModule::new(); let mut module = IRModule::new("testmod");
for statement in statements { for statement in statements {
statement.codegen(&mut module); statement.codegen(&mut module);
} }
module.dump();
} }

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
ast::Parse,
lexer::{FullToken, Token}, lexer::{FullToken, Token},
parser::Parse,
}; };
pub struct TokenStream<'a, 'b> { pub struct TokenStream<'a, 'b> {