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( |                 let block_ref = LLVMCreateBasicBlockInContext( | ||||||
|                     module.context_ref, |                     module.context_ref, | ||||||
|                     into_cstring(&self.data.name).as_ptr(), |                     into_cstring(&block.data.name).as_ptr(), | ||||||
|                 ); |                 ); | ||||||
|                 LLVMAppendExistingBasicBlock(own_function.value_ref, block_ref); |                 LLVMAppendExistingBasicBlock(own_function.value_ref, block_ref); | ||||||
|                 module.blocks.insert(block.value, 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::{ | use reid_lib::{ | ||||||
|     builder::{InstructionValue, TypeValue}, |     builder::{InstructionValue, TypeValue}, | ||||||
| @ -15,6 +15,7 @@ use reid_lib::{ | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|  |     allocator::{Allocator, AllocatorScope}, | ||||||
|     lexer::{FullToken, Position}, |     lexer::{FullToken, Position}, | ||||||
|     mir::{ |     mir::{ | ||||||
|         self, implement::TypeCategory, CustomTypeKey, Metadata, NamedVariableRef, SourceModuleId, |         self, implement::TypeCategory, CustomTypeKey, Metadata, NamedVariableRef, SourceModuleId, | ||||||
| @ -76,14 +77,15 @@ pub struct Scope<'ctx, 'scope> { | |||||||
|     modules: &'scope HashMap<SourceModuleId, ModuleCodegen<'ctx>>, |     modules: &'scope HashMap<SourceModuleId, ModuleCodegen<'ctx>>, | ||||||
|     tokens: &'ctx Vec<FullToken>, |     tokens: &'ctx Vec<FullToken>, | ||||||
|     module: &'ctx Module<'ctx>, |     module: &'ctx Module<'ctx>, | ||||||
|     module_id: SourceModuleId, |     pub(super) module_id: SourceModuleId, | ||||||
|     function: &'ctx StackFunction<'ctx>, |     function: &'ctx StackFunction<'ctx>, | ||||||
|     block: Block<'ctx>, |     pub(super) block: Block<'ctx>, | ||||||
|     types: &'scope HashMap<TypeValue, TypeDefinition>, |     pub(super) types: &'scope HashMap<TypeValue, TypeDefinition>, | ||||||
|     type_values: &'scope HashMap<CustomTypeKey, TypeValue>, |     pub(super) type_values: &'scope HashMap<CustomTypeKey, TypeValue>, | ||||||
|     functions: &'scope HashMap<String, StackFunction<'ctx>>, |     functions: &'scope HashMap<String, StackFunction<'ctx>>, | ||||||
|     stack_values: HashMap<String, StackValue>, |     stack_values: HashMap<String, StackValue>, | ||||||
|     debug: Option<Debug<'ctx>>, |     debug: Option<Debug<'ctx>>, | ||||||
|  |     allocator: Rc<RefCell<Allocator>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone)] | #[derive(Debug, Clone)] | ||||||
| @ -161,6 +163,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { | |||||||
|             type_values: self.type_values, |             type_values: self.type_values, | ||||||
|             stack_values: self.stack_values.clone(), |             stack_values: self.stack_values.clone(), | ||||||
|             debug: self.debug.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> { |     fn get_typedef(&self, key: &CustomTypeKey) -> Option<&TypeDefinition> { | ||||||
|         self.type_values.get(key).and_then(|v| self.types.get(v)) |         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)] | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] | ||||||
| @ -321,6 +328,15 @@ impl mir::Module { | |||||||
|             match &mir_function.kind { |             match &mir_function.kind { | ||||||
|                 mir::FunctionDefinitionKind::Local(block, _) => { |                 mir::FunctionDefinitionKind::Local(block, _) => { | ||||||
|                     let mut entry = function.ir.block("entry"); |                     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
 |                     // Insert debug information
 | ||||||
|                     let debug_scope = if let Some(location) = |                     let debug_scope = if let Some(location) = | ||||||
| @ -372,12 +388,9 @@ impl mir::Module { | |||||||
|                         let param = entry |                         let param = entry | ||||||
|                             .build_named(format!("{}.get", arg_name), Instr::Param(i)) |                             .build_named(format!("{}.get", arg_name), Instr::Param(i)) | ||||||
|                             .unwrap(); |                             .unwrap(); | ||||||
|                         let alloca = entry | 
 | ||||||
|                             .build_named( |                         let alloca = allocator.allocate(&p_name, &p_ty).unwrap(); | ||||||
|                                 &arg_name, | 
 | ||||||
|                                 Instr::Alloca(p_ty.get_type(&type_values, &types)), |  | ||||||
|                             ) |  | ||||||
|                             .unwrap(); |  | ||||||
|                         entry |                         entry | ||||||
|                             .build_named(format!("{}.store", arg_name), Instr::Store(alloca, param)) |                             .build_named(format!("{}.store", arg_name), Instr::Store(alloca, param)) | ||||||
|                             .unwrap(); |                             .unwrap(); | ||||||
| @ -435,6 +448,7 @@ impl mir::Module { | |||||||
|                                 types: &debug_types, |                                 types: &debug_types, | ||||||
|                             }) |                             }) | ||||||
|                         }), |                         }), | ||||||
|  |                         allocator: Rc::new(RefCell::new(allocator)), | ||||||
|                     }; |                     }; | ||||||
| 
 | 
 | ||||||
|                     let state = State::default(); |                     let state = State::default(); | ||||||
| @ -514,15 +528,11 @@ impl mir::Statement { | |||||||
|                 let value = expression.codegen(scope, &state)?.unwrap(); |                 let value = expression.codegen(scope, &state)?.unwrap(); | ||||||
| 
 | 
 | ||||||
|                 let alloca = scope |                 let alloca = scope | ||||||
|                     .block |                     .allocate(name, &value.1) | ||||||
|                     .build_named( |  | ||||||
|                         name, |  | ||||||
|                         Instr::Alloca(value.1.get_type(scope.type_values, scope.types)), |  | ||||||
|                     ) |  | ||||||
|                     .unwrap() |                     .unwrap() | ||||||
|                     .maybe_location(&mut scope.block, location); |                     .maybe_location(&mut scope.block, location); | ||||||
| 
 | 
 | ||||||
|                 scope |                 let store = scope | ||||||
|                     .block |                     .block | ||||||
|                     .build_named( |                     .build_named( | ||||||
|                         format!("{}.store", name), |                         format!("{}.store", name), | ||||||
| @ -551,7 +561,7 @@ impl mir::Statement { | |||||||
|                             flags: DwarfFlags, |                             flags: DwarfFlags, | ||||||
|                         }), |                         }), | ||||||
|                     ); |                     ); | ||||||
|                     alloca.add_record( |                     store.add_record( | ||||||
|                         &mut scope.block, |                         &mut scope.block, | ||||||
|                         InstructionDebugRecordData { |                         InstructionDebugRecordData { | ||||||
|                             variable: var, |                             variable: var, | ||||||
| @ -602,9 +612,9 @@ impl mir::Statement { | |||||||
|             mir::StmtKind::While(WhileStatement { |             mir::StmtKind::While(WhileStatement { | ||||||
|                 condition, block, .. |                 condition, block, .. | ||||||
|             }) => { |             }) => { | ||||||
|                 let condition_block = scope.function.ir.block("condition_block"); |                 let condition_block = scope.function.ir.block("while.cond"); | ||||||
|                 let condition_true_block = scope.function.ir.block("condition_true"); |                 let condition_true_block = scope.function.ir.block("while.body"); | ||||||
|                 let condition_failed_block = scope.function.ir.block("condition_failed"); |                 let condition_failed_block = scope.function.ir.block("while.end"); | ||||||
| 
 | 
 | ||||||
|                 scope |                 scope | ||||||
|                     .block |                     .block | ||||||
| @ -1428,7 +1438,7 @@ impl mir::Literal { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl TypeKind { | impl TypeKind { | ||||||
|     fn get_type( |     pub(super) fn get_type( | ||||||
|         &self, |         &self, | ||||||
|         type_vals: &HashMap<CustomTypeKey, TypeValue>, |         type_vals: &HashMap<CustomTypeKey, TypeValue>, | ||||||
|         typedefs: &HashMap<TypeValue, TypeDefinition>, |         typedefs: &HashMap<TypeValue, TypeDefinition>, | ||||||
|  | |||||||
| @ -52,6 +52,7 @@ use reid_lib::{compile::CompileOutput, Context}; | |||||||
| 
 | 
 | ||||||
| use crate::{ast::TopLevelStatement, lexer::Token, token_stream::TokenStream}; | use crate::{ast::TopLevelStatement, lexer::Token, token_stream::TokenStream}; | ||||||
| 
 | 
 | ||||||
|  | mod allocator; | ||||||
| mod ast; | mod ast; | ||||||
| mod codegen; | mod codegen; | ||||||
| pub mod error_raporting; | pub mod error_raporting; | ||||||
|  | |||||||
| @ -129,6 +129,6 @@ fn ptr_hard_compiles_well() { | |||||||
|     test(include_str!("../../examples/ptr_hard.reid"), "test", 0); |     test(include_str!("../../examples/ptr_hard.reid"), "test", 0); | ||||||
| } | } | ||||||
| #[test] | #[test] | ||||||
| fn list_hard_compiles_well() { | fn loop_hard_compiles_well() { | ||||||
|     test(include_str!("../../examples/list_hard.reid"), "test", 0); |     test(include_str!("../../examples/loop_hard.reid"), "test", 0); | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user