Refactor
This commit is contained in:
parent
08909d76ee
commit
2ced45eb40
@ -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 {
|
||||||
|
@ -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")),
|
||||||
))
|
))
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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> {
|
||||||
|
Loading…
Reference in New Issue
Block a user