From 3404f0fb6ee848211991e3fb3c116f70e38cc298 Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 03:28:48 +0300 Subject: [PATCH] Add static allocator, fix loop_hard --- examples/list_hard.reid | 12 --- examples/loop_hard.reid | 27 ++++++ reid-llvm-lib/src/compile.rs | 2 +- reid/src/allocator.rs | 183 +++++++++++++++++++++++++++++++++++ reid/src/codegen.rs | 54 ++++++----- reid/src/lib.rs | 1 + reid/tests/e2e.rs | 4 +- 7 files changed, 246 insertions(+), 37 deletions(-) delete mode 100644 examples/list_hard.reid create mode 100644 examples/loop_hard.reid create mode 100644 reid/src/allocator.rs diff --git a/examples/list_hard.reid b/examples/list_hard.reid deleted file mode 100644 index 634e198..0000000 --- a/examples/list_hard.reid +++ /dev/null @@ -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) {} \ No newline at end of file diff --git a/examples/loop_hard.reid b/examples/loop_hard.reid new file mode 100644 index 0000000..73a17f4 --- /dev/null +++ b/examples/loop_hard.reid @@ -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; +} diff --git a/reid-llvm-lib/src/compile.rs b/reid-llvm-lib/src/compile.rs index 8c3a3ee..3629914 100644 --- a/reid-llvm-lib/src/compile.rs +++ b/reid-llvm-lib/src/compile.rs @@ -676,7 +676,7 @@ impl FunctionHolder { let block_ref = LLVMCreateBasicBlockInContext( module.context_ref, - into_cstring(&self.data.name).as_ptr(), + into_cstring(&block.data.name).as_ptr(), ); LLVMAppendExistingBasicBlock(own_function.value_ref, block_ref); module.blocks.insert(block.value, block_ref); diff --git a/reid/src/allocator.rs b/reid/src/allocator.rs new file mode 100644 index 0000000..4ea09bb --- /dev/null +++ b/reid/src/allocator.rs @@ -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, +} + +pub struct AllocatorScope<'ctx, 'a> { + pub(super) block: &'a mut Block<'ctx>, + pub(super) module_id: SourceModuleId, + pub(super) types: &'a HashMap, + pub(super) type_values: &'a HashMap, +} + +impl Allocator { + pub fn from(func: &FunctionDefinition, scope: &mut AllocatorScope) -> Allocator { + func.allocate(scope) + } + + pub fn allocate(&mut self, name: &String, ty: &TypeKind) -> Option { + 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 { + 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 { + 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 { + 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 + } +} diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index ccd3ec7..deb27da 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, mem}; +use std::{cell::RefCell, collections::HashMap, mem, rc::Rc}; use reid_lib::{ builder::{InstructionValue, TypeValue}, @@ -15,6 +15,7 @@ use reid_lib::{ }; use crate::{ + allocator::{Allocator, AllocatorScope}, lexer::{FullToken, Position}, mir::{ self, implement::TypeCategory, CustomTypeKey, Metadata, NamedVariableRef, SourceModuleId, @@ -76,14 +77,15 @@ pub struct Scope<'ctx, 'scope> { modules: &'scope HashMap>, tokens: &'ctx Vec, module: &'ctx Module<'ctx>, - module_id: SourceModuleId, + pub(super) module_id: SourceModuleId, function: &'ctx StackFunction<'ctx>, - block: Block<'ctx>, - types: &'scope HashMap, - type_values: &'scope HashMap, + pub(super) block: Block<'ctx>, + pub(super) types: &'scope HashMap, + pub(super) type_values: &'scope HashMap, functions: &'scope HashMap>, stack_values: HashMap, debug: Option>, + allocator: Rc>, } #[derive(Debug, Clone)] @@ -161,6 +163,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { type_values: self.type_values, stack_values: self.stack_values.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> { self.type_values.get(key).and_then(|v| self.types.get(v)) } + + fn allocate(&self, name: &String, ty: &TypeKind) -> Option { + self.allocator.borrow_mut().allocate(name, ty) + } } #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] @@ -321,6 +328,15 @@ impl mir::Module { match &mir_function.kind { mir::FunctionDefinitionKind::Local(block, _) => { 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 let debug_scope = if let Some(location) = @@ -372,12 +388,9 @@ impl mir::Module { let param = entry .build_named(format!("{}.get", arg_name), Instr::Param(i)) .unwrap(); - let alloca = entry - .build_named( - &arg_name, - Instr::Alloca(p_ty.get_type(&type_values, &types)), - ) - .unwrap(); + + let alloca = allocator.allocate(&p_name, &p_ty).unwrap(); + entry .build_named(format!("{}.store", arg_name), Instr::Store(alloca, param)) .unwrap(); @@ -435,6 +448,7 @@ impl mir::Module { types: &debug_types, }) }), + allocator: Rc::new(RefCell::new(allocator)), }; let state = State::default(); @@ -514,15 +528,11 @@ impl mir::Statement { let value = expression.codegen(scope, &state)?.unwrap(); let alloca = scope - .block - .build_named( - name, - Instr::Alloca(value.1.get_type(scope.type_values, scope.types)), - ) + .allocate(name, &value.1) .unwrap() .maybe_location(&mut scope.block, location); - scope + let store = scope .block .build_named( format!("{}.store", name), @@ -551,7 +561,7 @@ impl mir::Statement { flags: DwarfFlags, }), ); - alloca.add_record( + store.add_record( &mut scope.block, InstructionDebugRecordData { variable: var, @@ -602,9 +612,9 @@ impl mir::Statement { mir::StmtKind::While(WhileStatement { condition, block, .. }) => { - let condition_block = scope.function.ir.block("condition_block"); - let condition_true_block = scope.function.ir.block("condition_true"); - let condition_failed_block = scope.function.ir.block("condition_failed"); + let condition_block = scope.function.ir.block("while.cond"); + let condition_true_block = scope.function.ir.block("while.body"); + let condition_failed_block = scope.function.ir.block("while.end"); scope .block @@ -1428,7 +1438,7 @@ impl mir::Literal { } impl TypeKind { - fn get_type( + pub(super) fn get_type( &self, type_vals: &HashMap, typedefs: &HashMap, diff --git a/reid/src/lib.rs b/reid/src/lib.rs index 81e07fa..9d8ac7c 100644 --- a/reid/src/lib.rs +++ b/reid/src/lib.rs @@ -52,6 +52,7 @@ use reid_lib::{compile::CompileOutput, Context}; use crate::{ast::TopLevelStatement, lexer::Token, token_stream::TokenStream}; +mod allocator; mod ast; mod codegen; pub mod error_raporting; diff --git a/reid/tests/e2e.rs b/reid/tests/e2e.rs index 7d37782..fbf738c 100644 --- a/reid/tests/e2e.rs +++ b/reid/tests/e2e.rs @@ -129,6 +129,6 @@ fn ptr_hard_compiles_well() { test(include_str!("../../examples/ptr_hard.reid"), "test", 0); } #[test] -fn list_hard_compiles_well() { - test(include_str!("../../examples/list_hard.reid"), "test", 0); +fn loop_hard_compiles_well() { + test(include_str!("../../examples/loop_hard.reid"), "test", 0); }