From f7500b886a348a05851dd770cb7a1bff1d1f7ff7 Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 01:41:46 +0300 Subject: [PATCH 1/6] Add two failing examples --- examples/list_hard.reid | 12 ++++++++++++ examples/ptr_hard.reid | 8 ++++++++ reid/tests/e2e.rs | 8 ++++++++ 3 files changed, 28 insertions(+) create mode 100644 examples/list_hard.reid create mode 100644 examples/ptr_hard.reid diff --git a/examples/list_hard.reid b/examples/list_hard.reid new file mode 100644 index 0000000..634e198 --- /dev/null +++ b/examples/list_hard.reid @@ -0,0 +1,12 @@ +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/ptr_hard.reid b/examples/ptr_hard.reid new file mode 100644 index 0000000..5f1d9d2 --- /dev/null +++ b/examples/ptr_hard.reid @@ -0,0 +1,8 @@ +fn main() { + let mut a = 5; + inner(&mut a); +} + +fn inner(a: &mut i32) { + *a = *a + 1; +} diff --git a/reid/tests/e2e.rs b/reid/tests/e2e.rs index 5685490..7d37782 100644 --- a/reid/tests/e2e.rs +++ b/reid/tests/e2e.rs @@ -124,3 +124,11 @@ fn struct_compiles_well() { fn loops_compiles_well() { test(include_str!("../../examples/loops.reid"), "test", 10); } +#[test] +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); +} From 5464bba17e481323292c0e803175f6025c94c4e3 Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 01:43:32 +0300 Subject: [PATCH 2/6] Add one more failing test credit to @neon --- examples/for_loops.reid | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 examples/for_loops.reid diff --git a/examples/for_loops.reid b/examples/for_loops.reid new file mode 100644 index 0000000..bac6d85 --- /dev/null +++ b/examples/for_loops.reid @@ -0,0 +1,9 @@ +import std::print; +fn main() { + for i in 0..1 { + print("Hello!"); + } + for i in 0..1 { + print("World!"); + } +} \ No newline at end of file From 87a8eac61b005ffb8a0673c376d2544935ffd26f Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 01:48:25 +0300 Subject: [PATCH 3/6] Fix for loops causing issues together --- examples/for_loops.reid | 6 ++++-- reid/src/ast/process.rs | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/examples/for_loops.reid b/examples/for_loops.reid index bac6d85..979194f 100644 --- a/examples/for_loops.reid +++ b/examples/for_loops.reid @@ -1,9 +1,11 @@ import std::print; +import std::from_str; + fn main() { for i in 0..1 { - print("Hello!"); + print(from_str("Hello!")); } for i in 0..1 { - print("World!"); + print(from_str("Hello!")); } } \ No newline at end of file diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs index 355d323..8b19356 100644 --- a/reid/src/ast/process.rs +++ b/reid/src/ast/process.rs @@ -158,7 +158,6 @@ impl ast::Block { StmtKind::Let(counter_var.clone(), true, start.process(module_id)), counter_range.as_meta(module_id), ); - mir_statements.push(let_statement); let set_new = mir::Statement( StmtKind::Set( @@ -187,7 +186,7 @@ impl ast::Block { ); let mut block = block.into_mir(module_id); block.statements.push(set_new); - ( + let while_statement = mir::Statement( StmtKind::While(WhileStatement { condition: mir::Expression( mir::ExprKind::BinOp( @@ -203,8 +202,18 @@ impl ast::Block { block, meta: self.2.as_meta(module_id), }), - self.2, - ) + self.2.as_meta(module_id), + ); + + let inner_scope = StmtKind::Expression(mir::Expression( + mir::ExprKind::Block(mir::Block { + statements: vec![let_statement, while_statement], + return_expression: None, + meta: counter_range.as_meta(module_id) + end.1.as_meta(module_id), + }), + counter_range.as_meta(module_id) + end.1.as_meta(module_id), + )); + (inner_scope, self.2) } ast::BlockLevelStatement::WhileLoop(expression, block) => ( StmtKind::While(WhileStatement { From 6664b25932feb9ff71f8bec23fdb3c3b1e76e328 Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 01:51:44 +0300 Subject: [PATCH 4/6] Fix deref expecting a codegenptr and not borrow --- examples/ptr_hard.reid | 3 ++- reid/src/codegen.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/ptr_hard.reid b/examples/ptr_hard.reid index 5f1d9d2..a83b06c 100644 --- a/examples/ptr_hard.reid +++ b/examples/ptr_hard.reid @@ -1,6 +1,7 @@ -fn main() { +fn main() -> u8 { let mut a = 5; inner(&mut a); + return 0; } fn inner(a: &mut i32) { diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index 421f2ab..ccd3ec7 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -1179,7 +1179,7 @@ impl mir::Expression { Some({ if state.should_load { - if let TypeKind::CodegenPtr(inner) = *ptr_inner.clone() { + if let TypeKind::Borrow(inner, _) = *ptr_inner.clone() { StackValue( v.0.derive( scope From 3404f0fb6ee848211991e3fb3c116f70e38cc298 Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 03:28:48 +0300 Subject: [PATCH 5/6] 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); } From 9ba091973a32f030eb7b8e7e53fa317156cef4c0 Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 11:18:23 +0300 Subject: [PATCH 6/6] Update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b08702..24dfc19 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Currently missing big features (TODOs) are: - Debug Information (PARTIALLY DONE) - Ability to specify types in literals and variable definitions - Intrinsic functions -- Not-Unary +- Not-Unary and NEQ-binary Big features that I want later but are not necessary: - Associated functions