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 crate::{
llvm_ir::{IRBlock, IRModule, Value, ValueType},
parser::{
ast::{
BinaryOperator, BlockLevelStatement, Expression, FunctionDefinition, Literal,
TopLevelStatement,
},
llvm_ir::{IRBlock, IRModule, IRValue, IRValueType},
};
pub struct Scope<'a> {
pub block: IRBlock<'a>,
named_vars: HashMap<String, Value>,
named_vars: HashMap<String, IRValue>,
}
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)
}
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()) {
e.insert(val);
Ok(())
@ -39,7 +39,7 @@ impl TopLevelStatement {
pub fn codegen(&self, module: &mut IRModule) {
match self {
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());
for statement in &block.0 {
@ -49,7 +49,7 @@ impl TopLevelStatement {
let value = if let Some(exp) = &block.1 {
exp.codegen(&mut scope)
} else {
scope.block.get_const(&Literal::I32(0))
panic!("Void-return type function not yet implemented!");
};
func.add_definition(value, scope.block);
}
@ -73,7 +73,7 @@ impl BlockLevelStatement {
}
impl Expression {
pub fn codegen(&self, scope: &mut Scope) -> Value {
pub fn codegen(&self, scope: &mut Scope) -> IRValue {
use Expression::*;
match self {
Binop(op, lhs, rhs) => match op {

View File

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

View File

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

View File

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