Merge branch 'main' into intrinsicts

This commit is contained in:
Sofia 2025-07-24 11:18:33 +03:00
commit 4f1dc5e59d
10 changed files with 287 additions and 29 deletions

View File

@ -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

11
examples/for_loops.reid Normal file
View File

@ -0,0 +1,11 @@
import std::print;
import std::from_str;
fn main() {
for i in 0..1 {
print(from_str("Hello!"));
}
for i in 0..1 {
print(from_str("Hello!"));
}
}

27
examples/loop_hard.reid Normal file
View 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;
}

9
examples/ptr_hard.reid Normal file
View File

@ -0,0 +1,9 @@
fn main() -> u8 {
let mut a = 5;
inner(&mut a);
return 0;
}
fn inner(a: &mut i32) {
*a = *a + 1;
}

View File

@ -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);

183
reid/src/allocator.rs Normal file
View 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
}
}

View File

@ -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 {

View File

@ -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<SourceModuleId, ModuleCodegen<'ctx>>,
tokens: &'ctx Vec<FullToken>,
module: &'ctx Module<'ctx>,
module_id: SourceModuleId,
pub(super) module_id: SourceModuleId,
function: &'ctx StackFunction<'ctx>,
block: Block<'ctx>,
types: &'scope HashMap<TypeValue, TypeDefinition>,
type_values: &'scope HashMap<CustomTypeKey, TypeValue>,
pub(super) block: Block<'ctx>,
pub(super) types: &'scope HashMap<TypeValue, TypeDefinition>,
pub(super) type_values: &'scope HashMap<CustomTypeKey, TypeValue>,
functions: &'scope HashMap<String, StackFunction<'ctx>>,
stack_values: HashMap<String, StackValue>,
debug: Option<Debug<'ctx>>,
allocator: Rc<RefCell<Allocator>>,
}
#[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<InstructionValue> {
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
@ -1179,7 +1189,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
@ -1428,7 +1438,7 @@ impl mir::Literal {
}
impl TypeKind {
fn get_type(
pub(super) fn get_type(
&self,
type_vals: &HashMap<CustomTypeKey, TypeValue>,
typedefs: &HashMap<TypeValue, TypeDefinition>,

View File

@ -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;

View File

@ -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 loop_hard_compiles_well() {
test(include_str!("../../examples/loop_hard.reid"), "test", 0);
}