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( | ||||
|                     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 | ||||
|     } | ||||
| } | ||||
| @ -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 | ||||
| @ -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; | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user