Merge branch 'main' into intrinsicts
This commit is contained in:
commit
4f1dc5e59d
@ -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
11
examples/for_loops.reid
Normal 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
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;
|
||||
}
|
9
examples/ptr_hard.reid
Normal file
9
examples/ptr_hard.reid
Normal 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;
|
||||
}
|
@ -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
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
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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>,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user