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