Add a block garbage-collector that will delete an unused block at end
This commit is contained in:
		
							parent
							
								
									d757ac4eb3
								
							
						
					
					
						commit
						94c4ec0613
					
				| @ -143,6 +143,17 @@ impl Builder { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub(crate) unsafe fn delete_block(&self, block: &BlockValue) -> Result<(), ()> { | ||||
|         unsafe { | ||||
|             let mut modules = self.modules.borrow_mut(); | ||||
|             let module = modules.get_unchecked_mut(block.0.0.0); | ||||
|             let function = module.functions.get_unchecked_mut(block.0.1); | ||||
|             let block = function.blocks.get_unchecked_mut(block.1); | ||||
|             block.data.deleted = true; | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[allow(dead_code)] | ||||
|     pub(crate) unsafe fn module_data(&self, value: &ModuleValue) -> ModuleData { | ||||
|         unsafe { self.modules.borrow().get_unchecked(value.0).data.clone() } | ||||
| @ -242,6 +253,39 @@ impl Builder { | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn is_block_used(&self, block_v: BlockValue) -> bool { | ||||
|         unsafe { | ||||
|             let modules = self.modules.borrow(); | ||||
|             let module = modules.get_unchecked(block_v.0.0.0); | ||||
|             let function = module.functions.get_unchecked(block_v.0.1); | ||||
|             let block = function.blocks.get_unchecked(block_v.1); | ||||
| 
 | ||||
|             if block.instructions.len() > 0 || block.data.terminator.is_some() { | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             for other in &function.blocks { | ||||
|                 if let Some(term) = &other.data.terminator { | ||||
|                     match term { | ||||
|                         TerminatorKind::Ret(_) => {} | ||||
|                         TerminatorKind::Br(other_val) => { | ||||
|                             if other_val == &block_v { | ||||
|                                 return true; | ||||
|                             } | ||||
|                         } | ||||
|                         TerminatorKind::CondBr(_, then_other_v, else_other_v) => { | ||||
|                             if then_other_v == &block_v || else_other_v == &block_v { | ||||
|                                 return true; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             false | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl InstructionValue { | ||||
|  | ||||
| @ -205,6 +205,10 @@ impl FunctionHolder { | ||||
|             let own_function = *module.functions.get(&self.value).unwrap(); | ||||
| 
 | ||||
|             for block in &self.blocks { | ||||
|                 if block.data.deleted { | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 let block_ref = LLVMCreateBasicBlockInContext( | ||||
|                     module.context_ref, | ||||
|                     into_cstring(&self.data.name).as_ptr(), | ||||
| @ -223,6 +227,10 @@ impl FunctionHolder { | ||||
| impl BlockHolder { | ||||
|     unsafe fn compile(&self, module: &mut LLVMModule, function: &LLVMFunction) { | ||||
|         unsafe { | ||||
|             if self.data.deleted { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             let block_ref = *module.blocks.get(&self.value).unwrap(); | ||||
|             LLVMPositionBuilderAtEnd(module.builder_ref, block_ref); | ||||
| 
 | ||||
|  | ||||
| @ -32,10 +32,14 @@ impl Debug for FunctionHolder { | ||||
| 
 | ||||
| impl Debug for BlockHolder { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_tuple(&format!("{}[{:?}]", &self.data.name, &self.value)) | ||||
|             .field(&self.instructions) | ||||
|             .field(&self.data.terminator) | ||||
|             .finish() | ||||
|         let deleted = if self.data.deleted { " (deleted)" } else { "" }; | ||||
|         f.debug_tuple(&format!( | ||||
|             "{}[{:?}]{} ", | ||||
|             &self.data.name, &self.value, deleted | ||||
|         )) | ||||
|         .field(&self.instructions) | ||||
|         .field(&self.data.terminator) | ||||
|         .finish() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -95,6 +95,7 @@ impl<'ctx> Function<'ctx> { | ||||
|                     BlockData { | ||||
|                         name: name.to_owned(), | ||||
|                         terminator: None, | ||||
|                         deleted: false, | ||||
|                     }, | ||||
|                 ), | ||||
|             } | ||||
| @ -110,6 +111,7 @@ impl<'ctx> Function<'ctx> { | ||||
| pub struct BlockData { | ||||
|     name: String, | ||||
|     terminator: Option<TerminatorKind>, | ||||
|     deleted: bool, | ||||
| } | ||||
| 
 | ||||
| pub struct Block<'builder> { | ||||
| @ -130,6 +132,16 @@ impl<'builder> Block<'builder> { | ||||
|         unsafe { self.builder.terminate(&self.value, instruction) } | ||||
|     } | ||||
| 
 | ||||
|     pub fn delete_if_unused(&mut self) -> Result<(), ()> { | ||||
|         unsafe { | ||||
|             if !self.builder.is_block_used(self.value()) { | ||||
|                 self.builder.delete_block(&self.value) | ||||
|             } else { | ||||
|                 Ok(()) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn value(&self) -> BlockValue { | ||||
|         self.value | ||||
|     } | ||||
|  | ||||
| @ -1,14 +1,13 @@ | ||||
| // Main | ||||
| fn main() -> bool { | ||||
|     return (5 == fibonacci(5)) && false; | ||||
|     return 5 == fibonacci(5); | ||||
| } | ||||
| 
 | ||||
| // Fibonacci | ||||
| fn fibonacci(value: u16) -> u16 { | ||||
|     let ret = if value <= 2 { | ||||
|         1 | ||||
|     if value <= 2 { | ||||
|         return 1; | ||||
|     } else { | ||||
|         fibonacci(value - 1) + fibonacci(value - 2) | ||||
|     }; | ||||
|     ret | ||||
|         return fibonacci(value - 1) + fibonacci(value - 2); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -89,6 +89,8 @@ impl mir::Module { | ||||
|                 mir::FunctionDefinitionKind::Local(block, _) => { | ||||
|                     if let Some(ret) = block.codegen(&mut scope) { | ||||
|                         scope.block.terminate(Term::Ret(ret)).unwrap(); | ||||
|                     } else { | ||||
|                         scope.block.delete_if_unused().unwrap(); | ||||
|                     } | ||||
|                 } | ||||
|                 mir::FunctionDefinitionKind::Extern => {} | ||||
| @ -298,13 +300,16 @@ impl mir::Block { | ||||
|         } | ||||
| 
 | ||||
|         if let Some((kind, expr)) = &self.return_expression { | ||||
|             let ret = expr.codegen(&mut scope).unwrap(); | ||||
|             match kind { | ||||
|                 mir::ReturnKind::Hard => { | ||||
|                     scope.block.terminate(Term::Ret(ret)).unwrap(); | ||||
|                     None | ||||
|             if let Some(ret) = expr.codegen(&mut scope) { | ||||
|                 match kind { | ||||
|                     mir::ReturnKind::Hard => { | ||||
|                         scope.block.terminate(Term::Ret(ret)).unwrap(); | ||||
|                         None | ||||
|                     } | ||||
|                     mir::ReturnKind::Soft => Some(ret), | ||||
|                 } | ||||
|                 mir::ReturnKind::Soft => Some(ret), | ||||
|             } else { | ||||
|                 None | ||||
|             } | ||||
|         } else { | ||||
|             None | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user