aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--patio-to-cranelift/src/codegen/context.rs11
-rw-r--r--patio-to-cranelift/src/codegen/mod.rs54
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);