diff options
| -rw-r--r-- | patio-to-cranelift/src/codegen/context.rs | 11 | ||||
| -rw-r--r-- | patio-to-cranelift/src/codegen/mod.rs | 54 |
2 files changed, 40 insertions, 25 deletions
diff --git a/patio-to-cranelift/src/codegen/context.rs b/patio-to-cranelift/src/codegen/context.rs index a9333e26..bc551944 100644 --- a/patio-to-cranelift/src/codegen/context.rs +++ b/patio-to-cranelift/src/codegen/context.rs @@ -103,6 +103,7 @@ impl CompilerContext { local_name_to_type: Default::default(), var_name_to_variable: Default::default(), loop_blocks: Default::default(), + unreachable: false, }; generate_function_body(&mut context); @@ -161,6 +162,7 @@ pub(crate) struct CompilerFunctionContext<'a> { local_name_to_type: HashMap<String, cranelift_codegen::ir::Type>, var_name_to_variable: HashMap<String, cranelift::prelude::Variable>, loop_blocks: Vec<Loop>, + unreachable: bool, } impl<'a> CompilerFunctionContext<'a> { @@ -217,6 +219,7 @@ impl<'a> CompilerFunctionContext<'a> { pub(crate) fn switch_to_block(&mut self, block: cranelift_codegen::ir::Block) { self.function_builder.switch_to_block(block); + self.unreachable = false; } pub(crate) fn seal_block(&mut self, block: cranelift_codegen::ir::Block) { @@ -245,6 +248,14 @@ impl<'a> CompilerFunctionContext<'a> { pub(crate) fn exit_loop(&mut self) { self.loop_blocks.pop(); } + + pub(crate) fn mark_unreachable(&mut self) { + self.unreachable = true + } + + pub(crate) fn is_reachable(&self) -> bool { + !self.unreachable + } } pub(crate) enum Mutability { diff --git a/patio-to-cranelift/src/codegen/mod.rs b/patio-to-cranelift/src/codegen/mod.rs index 438a0893..1e898123 100644 --- a/patio-to-cranelift/src/codegen/mod.rs +++ b/patio-to-cranelift/src/codegen/mod.rs @@ -494,17 +494,21 @@ fn compile_if(if_: &PatioIf, context: &mut CompilerFunctionContext<'_>) { context.switch_to_block(cranelift_then_block); let cranelift_then_results = compile_block(&if_.true_body, context); - context.function_builder.ins().jump( - cranelift_end_block, - cranelift_block_args(cranelift_then_results).iter(), - ); + if context.is_reachable() { + context.function_builder.ins().jump( + cranelift_end_block, + cranelift_block_args(cranelift_then_results).iter(), + ); + } context.switch_to_block(cranelift_else_block); let cranelift_else_results = compile_block(&if_.false_body, context); - context.function_builder.ins().jump( - cranelift_end_block, - cranelift_block_args(cranelift_else_results).iter(), - ); + if context.is_reachable() { + context.function_builder.ins().jump( + cranelift_end_block, + cranelift_block_args(cranelift_else_results).iter(), + ); + } context.seal_block(cranelift_end_block); context.switch_to_block(cranelift_end_block); @@ -603,7 +607,9 @@ fn compile_loop(loop_: &PatioLoop, context: &mut CompilerFunctionContext<'_>) { } context.exit_loop(); context.seal_block(cranelift_loop_block); - context.function_builder.ins().jump(cranelift_end_block, []); + if context.is_reachable() { + context.function_builder.ins().jump(cranelift_end_block, []); + } context.seal_block(cranelift_end_block); context.switch_to_block(cranelift_end_block); @@ -615,10 +621,7 @@ fn compile_loop_break(_: &PatioLoopBreak, context: &mut CompilerFunctionContext< .function_builder .ins() .jump(cranelift_loop_end_block, []); - - // TODO: avoid creating orphaned blocks - let cranelift_unreachable_block = context.create_block(); - context.switch_to_block(cranelift_unreachable_block); + context.mark_unreachable(); } fn compile_loop_continue(_: &PatioLoopContinue, context: &mut CompilerFunctionContext<'_>) { @@ -627,10 +630,7 @@ fn compile_loop_continue(_: &PatioLoopContinue, context: &mut CompilerFunctionCo .function_builder .ins() .jump(cranelift_loop_start_block, []); - - // TODO: avoid creating orphaned blocks - let cranelift_unreachable_block = context.create_block(); - context.switch_to_block(cranelift_unreachable_block); + context.mark_unreachable(); } fn compile_memory_load(memory_load: &PatioMemoryLoad, context: &mut CompilerFunctionContext<'_>) { @@ -738,19 +738,23 @@ fn compile_switch(switch: &PatioSwitch, context: &mut CompilerFunctionContext<'_ for (case, case_block) in switch.cases.iter().zip(&case_blocks) { context.switch_to_block(*case_block); let end_args = compile_block(&case.body, context); - context - .function_builder - .ins() - .jump(end_block, &cranelift_block_args(end_args)); + if context.is_reachable() { + context + .function_builder + .ins() + .jump(end_block, &cranelift_block_args(end_args)); + } } { context.switch_to_block(default_block); let end_args = compile_block(&switch.default_body, context); - context - .function_builder - .ins() - .jump(end_block, &cranelift_block_args(end_args)); + if context.is_reachable() { + context + .function_builder + .ins() + .jump(end_block, &cranelift_block_args(end_args)); + } } context.seal_block(end_block); |
