Add static allocator, fix loop_hard
This commit is contained in:
parent
6664b25932
commit
3404f0fb6e
@ -1,12 +0,0 @@
|
|||||||
fn main() {
|
|
||||||
let mut a = 5;
|
|
||||||
for i in 0..1000 {
|
|
||||||
for j in 0..1000 {
|
|
||||||
for k in 0..1000 {
|
|
||||||
inner(&mut a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inner(a: &mut i32) {}
|
|
27
examples/loop_hard.reid
Normal file
27
examples/loop_hard.reid
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import std::print;
|
||||||
|
import std::new_string;
|
||||||
|
import std::add_num_to_str;
|
||||||
|
import std::add_char;
|
||||||
|
|
||||||
|
fn main() -> u8 {
|
||||||
|
for i in 0..5 {
|
||||||
|
for j in 0..5 {
|
||||||
|
for k in 0..5 {
|
||||||
|
let mut test = new_string();
|
||||||
|
add_num_to_str(&mut test, i);
|
||||||
|
add_char(&mut test, ',');
|
||||||
|
add_num_to_str(&mut test, j);
|
||||||
|
add_char(&mut test, ',');
|
||||||
|
add_num_to_str(&mut test, k);
|
||||||
|
print(test);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i in 0..1000 {
|
||||||
|
for j in 0..1000 {
|
||||||
|
for k in 0..1000 {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
@ -676,7 +676,7 @@ impl FunctionHolder {
|
|||||||
|
|
||||||
let block_ref = LLVMCreateBasicBlockInContext(
|
let block_ref = LLVMCreateBasicBlockInContext(
|
||||||
module.context_ref,
|
module.context_ref,
|
||||||
into_cstring(&self.data.name).as_ptr(),
|
into_cstring(&block.data.name).as_ptr(),
|
||||||
);
|
);
|
||||||
LLVMAppendExistingBasicBlock(own_function.value_ref, block_ref);
|
LLVMAppendExistingBasicBlock(own_function.value_ref, block_ref);
|
||||||
module.blocks.insert(block.value, block_ref);
|
module.blocks.insert(block.value, block_ref);
|
||||||
|
183
reid/src/allocator.rs
Normal file
183
reid/src/allocator.rs
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use reid_lib::{
|
||||||
|
builder::{InstructionValue, TypeValue},
|
||||||
|
Block,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::mir::{
|
||||||
|
self, CustomTypeKey, FunctionCall, FunctionDefinition, IfExpression, SourceModuleId,
|
||||||
|
TypeDefinition, TypeKind, WhileStatement,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Allocator {
|
||||||
|
allocations: Vec<Allocation>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AllocatorScope<'ctx, 'a> {
|
||||||
|
pub(super) block: &'a mut Block<'ctx>,
|
||||||
|
pub(super) module_id: SourceModuleId,
|
||||||
|
pub(super) types: &'a HashMap<TypeValue, TypeDefinition>,
|
||||||
|
pub(super) type_values: &'a HashMap<CustomTypeKey, TypeValue>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Allocator {
|
||||||
|
pub fn from(func: &FunctionDefinition, scope: &mut AllocatorScope) -> Allocator {
|
||||||
|
func.allocate(scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocate(&mut self, name: &String, ty: &TypeKind) -> Option<InstructionValue> {
|
||||||
|
let mut allocs = self.allocations.iter().cloned().enumerate();
|
||||||
|
let val = allocs.find(|a| a.1 .0 == *name && a.1 .1 == *ty);
|
||||||
|
if let Some((i, _)) = val {
|
||||||
|
self.allocations.remove(i);
|
||||||
|
}
|
||||||
|
val.map(|v| v.1 .2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Allocation(String, TypeKind, InstructionValue);
|
||||||
|
|
||||||
|
impl mir::FunctionDefinition {
|
||||||
|
fn allocate<'ctx, 'a>(&self, scope: &mut AllocatorScope<'ctx, 'a>) -> Allocator {
|
||||||
|
let mut allocated = Vec::new();
|
||||||
|
match &self.kind {
|
||||||
|
crate::mir::FunctionDefinitionKind::Local(block, _) => {
|
||||||
|
for param in &self.parameters {
|
||||||
|
let allocation = scope
|
||||||
|
.block
|
||||||
|
.build_named(
|
||||||
|
param.0.clone(),
|
||||||
|
reid_lib::Instr::Alloca(
|
||||||
|
param.1.get_type(scope.type_values, scope.types),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
allocated.push(Allocation(param.0.clone(), param.1.clone(), allocation));
|
||||||
|
}
|
||||||
|
allocated.extend(block.allocate(scope));
|
||||||
|
}
|
||||||
|
crate::mir::FunctionDefinitionKind::Extern(_) => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Allocator {
|
||||||
|
allocations: allocated,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl mir::Block {
|
||||||
|
fn allocate<'ctx, 'a>(&self, scope: &mut AllocatorScope<'ctx, 'a>) -> Vec<Allocation> {
|
||||||
|
let mut allocated = Vec::new();
|
||||||
|
|
||||||
|
for statement in &self.statements {
|
||||||
|
allocated.extend(statement.allocate(scope));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((_, ret_expr)) = &self.return_expression {
|
||||||
|
allocated.extend(ret_expr.allocate(scope));
|
||||||
|
}
|
||||||
|
|
||||||
|
allocated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl mir::Statement {
|
||||||
|
fn allocate<'ctx, 'a>(&self, scope: &mut AllocatorScope<'ctx, 'a>) -> Vec<Allocation> {
|
||||||
|
let mut allocated = Vec::new();
|
||||||
|
|
||||||
|
match &self.0 {
|
||||||
|
crate::mir::StmtKind::Let(named_variable_ref, _, expression) => {
|
||||||
|
allocated.extend(expression.allocate(scope));
|
||||||
|
let allocation = scope
|
||||||
|
.block
|
||||||
|
.build_named(
|
||||||
|
named_variable_ref.1.clone(),
|
||||||
|
reid_lib::Instr::Alloca(
|
||||||
|
named_variable_ref
|
||||||
|
.0
|
||||||
|
.get_type(scope.type_values, scope.types),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
allocated.push(Allocation(
|
||||||
|
named_variable_ref.1.clone(),
|
||||||
|
named_variable_ref.0.clone(),
|
||||||
|
allocation,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
crate::mir::StmtKind::Set(lhs, rhs) => {
|
||||||
|
allocated.extend(lhs.allocate(scope));
|
||||||
|
allocated.extend(rhs.allocate(scope));
|
||||||
|
}
|
||||||
|
crate::mir::StmtKind::Import(_) => {}
|
||||||
|
crate::mir::StmtKind::Expression(expression) => {
|
||||||
|
allocated.extend(expression.allocate(scope));
|
||||||
|
}
|
||||||
|
crate::mir::StmtKind::While(WhileStatement {
|
||||||
|
condition, block, ..
|
||||||
|
}) => {
|
||||||
|
allocated.extend(condition.allocate(scope));
|
||||||
|
allocated.extend(block.allocate(scope));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allocated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl mir::Expression {
|
||||||
|
fn allocate<'ctx, 'a>(&self, scope: &mut AllocatorScope<'ctx, 'a>) -> Vec<Allocation> {
|
||||||
|
let mut allocated = Vec::new();
|
||||||
|
|
||||||
|
match &self.0 {
|
||||||
|
crate::mir::ExprKind::Variable(_) => {}
|
||||||
|
crate::mir::ExprKind::Indexed(expr, _, idx) => {
|
||||||
|
allocated.extend(expr.allocate(scope));
|
||||||
|
allocated.extend(idx.allocate(scope));
|
||||||
|
}
|
||||||
|
crate::mir::ExprKind::Accessed(expression, _, _) => {
|
||||||
|
allocated.extend(expression.allocate(scope));
|
||||||
|
}
|
||||||
|
crate::mir::ExprKind::Array(expressions) => {
|
||||||
|
for expression in expressions {
|
||||||
|
allocated.extend(expression.allocate(scope));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crate::mir::ExprKind::Struct(_, items) => {
|
||||||
|
for (_, expression) in items {
|
||||||
|
allocated.extend(expression.allocate(scope));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crate::mir::ExprKind::Literal(_) => {}
|
||||||
|
crate::mir::ExprKind::BinOp(_, lhs, rhs) => {
|
||||||
|
allocated.extend(lhs.allocate(scope));
|
||||||
|
allocated.extend(rhs.allocate(scope));
|
||||||
|
}
|
||||||
|
crate::mir::ExprKind::FunctionCall(FunctionCall { parameters, .. }) => {
|
||||||
|
for param in parameters {
|
||||||
|
allocated.extend(param.allocate(scope));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crate::mir::ExprKind::If(IfExpression(cond, then_ex, else_ex)) => {
|
||||||
|
allocated.extend(cond.allocate(scope));
|
||||||
|
allocated.extend(then_ex.allocate(scope));
|
||||||
|
if let Some(else_ex) = else_ex.as_ref() {
|
||||||
|
allocated.extend(else_ex.allocate(scope));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crate::mir::ExprKind::Block(block) => {
|
||||||
|
allocated.extend(block.allocate(scope));
|
||||||
|
}
|
||||||
|
crate::mir::ExprKind::Borrow(_, _) => {}
|
||||||
|
crate::mir::ExprKind::Deref(_) => {}
|
||||||
|
crate::mir::ExprKind::CastTo(expression, _) => {
|
||||||
|
allocated.extend(expression.allocate(scope));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allocated
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
use std::{collections::HashMap, mem};
|
use std::{cell::RefCell, collections::HashMap, mem, rc::Rc};
|
||||||
|
|
||||||
use reid_lib::{
|
use reid_lib::{
|
||||||
builder::{InstructionValue, TypeValue},
|
builder::{InstructionValue, TypeValue},
|
||||||
@ -15,6 +15,7 @@ use reid_lib::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
allocator::{Allocator, AllocatorScope},
|
||||||
lexer::{FullToken, Position},
|
lexer::{FullToken, Position},
|
||||||
mir::{
|
mir::{
|
||||||
self, implement::TypeCategory, CustomTypeKey, Metadata, NamedVariableRef, SourceModuleId,
|
self, implement::TypeCategory, CustomTypeKey, Metadata, NamedVariableRef, SourceModuleId,
|
||||||
@ -76,14 +77,15 @@ pub struct Scope<'ctx, 'scope> {
|
|||||||
modules: &'scope HashMap<SourceModuleId, ModuleCodegen<'ctx>>,
|
modules: &'scope HashMap<SourceModuleId, ModuleCodegen<'ctx>>,
|
||||||
tokens: &'ctx Vec<FullToken>,
|
tokens: &'ctx Vec<FullToken>,
|
||||||
module: &'ctx Module<'ctx>,
|
module: &'ctx Module<'ctx>,
|
||||||
module_id: SourceModuleId,
|
pub(super) module_id: SourceModuleId,
|
||||||
function: &'ctx StackFunction<'ctx>,
|
function: &'ctx StackFunction<'ctx>,
|
||||||
block: Block<'ctx>,
|
pub(super) block: Block<'ctx>,
|
||||||
types: &'scope HashMap<TypeValue, TypeDefinition>,
|
pub(super) types: &'scope HashMap<TypeValue, TypeDefinition>,
|
||||||
type_values: &'scope HashMap<CustomTypeKey, TypeValue>,
|
pub(super) type_values: &'scope HashMap<CustomTypeKey, TypeValue>,
|
||||||
functions: &'scope HashMap<String, StackFunction<'ctx>>,
|
functions: &'scope HashMap<String, StackFunction<'ctx>>,
|
||||||
stack_values: HashMap<String, StackValue>,
|
stack_values: HashMap<String, StackValue>,
|
||||||
debug: Option<Debug<'ctx>>,
|
debug: Option<Debug<'ctx>>,
|
||||||
|
allocator: Rc<RefCell<Allocator>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -161,6 +163,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
|
|||||||
type_values: self.type_values,
|
type_values: self.type_values,
|
||||||
stack_values: self.stack_values.clone(),
|
stack_values: self.stack_values.clone(),
|
||||||
debug: self.debug.clone(),
|
debug: self.debug.clone(),
|
||||||
|
allocator: self.allocator.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +178,10 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
|
|||||||
fn get_typedef(&self, key: &CustomTypeKey) -> Option<&TypeDefinition> {
|
fn get_typedef(&self, key: &CustomTypeKey) -> Option<&TypeDefinition> {
|
||||||
self.type_values.get(key).and_then(|v| self.types.get(v))
|
self.type_values.get(key).and_then(|v| self.types.get(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn allocate(&self, name: &String, ty: &TypeKind) -> Option<InstructionValue> {
|
||||||
|
self.allocator.borrow_mut().allocate(name, ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
||||||
@ -321,6 +328,15 @@ impl mir::Module {
|
|||||||
match &mir_function.kind {
|
match &mir_function.kind {
|
||||||
mir::FunctionDefinitionKind::Local(block, _) => {
|
mir::FunctionDefinitionKind::Local(block, _) => {
|
||||||
let mut entry = function.ir.block("entry");
|
let mut entry = function.ir.block("entry");
|
||||||
|
let mut allocator = Allocator::from(
|
||||||
|
mir_function,
|
||||||
|
&mut AllocatorScope {
|
||||||
|
block: &mut entry,
|
||||||
|
module_id: self.module_id,
|
||||||
|
types: &types,
|
||||||
|
type_values: &type_values,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// Insert debug information
|
// Insert debug information
|
||||||
let debug_scope = if let Some(location) =
|
let debug_scope = if let Some(location) =
|
||||||
@ -372,12 +388,9 @@ impl mir::Module {
|
|||||||
let param = entry
|
let param = entry
|
||||||
.build_named(format!("{}.get", arg_name), Instr::Param(i))
|
.build_named(format!("{}.get", arg_name), Instr::Param(i))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let alloca = entry
|
|
||||||
.build_named(
|
let alloca = allocator.allocate(&p_name, &p_ty).unwrap();
|
||||||
&arg_name,
|
|
||||||
Instr::Alloca(p_ty.get_type(&type_values, &types)),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
entry
|
entry
|
||||||
.build_named(format!("{}.store", arg_name), Instr::Store(alloca, param))
|
.build_named(format!("{}.store", arg_name), Instr::Store(alloca, param))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -435,6 +448,7 @@ impl mir::Module {
|
|||||||
types: &debug_types,
|
types: &debug_types,
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
allocator: Rc::new(RefCell::new(allocator)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let state = State::default();
|
let state = State::default();
|
||||||
@ -514,15 +528,11 @@ impl mir::Statement {
|
|||||||
let value = expression.codegen(scope, &state)?.unwrap();
|
let value = expression.codegen(scope, &state)?.unwrap();
|
||||||
|
|
||||||
let alloca = scope
|
let alloca = scope
|
||||||
.block
|
.allocate(name, &value.1)
|
||||||
.build_named(
|
|
||||||
name,
|
|
||||||
Instr::Alloca(value.1.get_type(scope.type_values, scope.types)),
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
|
|
||||||
scope
|
let store = scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build_named(
|
||||||
format!("{}.store", name),
|
format!("{}.store", name),
|
||||||
@ -551,7 +561,7 @@ impl mir::Statement {
|
|||||||
flags: DwarfFlags,
|
flags: DwarfFlags,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
alloca.add_record(
|
store.add_record(
|
||||||
&mut scope.block,
|
&mut scope.block,
|
||||||
InstructionDebugRecordData {
|
InstructionDebugRecordData {
|
||||||
variable: var,
|
variable: var,
|
||||||
@ -602,9 +612,9 @@ impl mir::Statement {
|
|||||||
mir::StmtKind::While(WhileStatement {
|
mir::StmtKind::While(WhileStatement {
|
||||||
condition, block, ..
|
condition, block, ..
|
||||||
}) => {
|
}) => {
|
||||||
let condition_block = scope.function.ir.block("condition_block");
|
let condition_block = scope.function.ir.block("while.cond");
|
||||||
let condition_true_block = scope.function.ir.block("condition_true");
|
let condition_true_block = scope.function.ir.block("while.body");
|
||||||
let condition_failed_block = scope.function.ir.block("condition_failed");
|
let condition_failed_block = scope.function.ir.block("while.end");
|
||||||
|
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
@ -1428,7 +1438,7 @@ impl mir::Literal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TypeKind {
|
impl TypeKind {
|
||||||
fn get_type(
|
pub(super) fn get_type(
|
||||||
&self,
|
&self,
|
||||||
type_vals: &HashMap<CustomTypeKey, TypeValue>,
|
type_vals: &HashMap<CustomTypeKey, TypeValue>,
|
||||||
typedefs: &HashMap<TypeValue, TypeDefinition>,
|
typedefs: &HashMap<TypeValue, TypeDefinition>,
|
||||||
|
@ -52,6 +52,7 @@ use reid_lib::{compile::CompileOutput, Context};
|
|||||||
|
|
||||||
use crate::{ast::TopLevelStatement, lexer::Token, token_stream::TokenStream};
|
use crate::{ast::TopLevelStatement, lexer::Token, token_stream::TokenStream};
|
||||||
|
|
||||||
|
mod allocator;
|
||||||
mod ast;
|
mod ast;
|
||||||
mod codegen;
|
mod codegen;
|
||||||
pub mod error_raporting;
|
pub mod error_raporting;
|
||||||
|
@ -129,6 +129,6 @@ fn ptr_hard_compiles_well() {
|
|||||||
test(include_str!("../../examples/ptr_hard.reid"), "test", 0);
|
test(include_str!("../../examples/ptr_hard.reid"), "test", 0);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn list_hard_compiles_well() {
|
fn loop_hard_compiles_well() {
|
||||||
test(include_str!("../../examples/list_hard.reid"), "test", 0);
|
test(include_str!("../../examples/loop_hard.reid"), "test", 0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user