Skip to content

Commit 6e203cf

Browse files
committed
fix: Handle nested Block expressions in While loops and void function returns
This fixes two issues with Haxe/Reflaxe compilation: 1. CFG builder: Handle Expression(Block) in while loop bodies - Haxe generates While body as Expression(Block(...)) instead of direct statements - Added flattening logic in typed_cfg.rs to recursively process inner Block statements 2. Cranelift backend: Void functions now return instead of trap - Functions with Void return type that fall through without explicit return now emit `return_(&[])` instead of `trap unreachable` - This fixes Haxe main() functions which return Void Tested with SimpleWhileTest.hx which computes sum 0+1+2+3+4 = 10 using a while loop - generates correct Cranelift IR with proper phi nodes.
1 parent 2dfb421 commit 6e203cf

8 files changed

Lines changed: 526 additions & 1181 deletions

File tree

crates/compiler/src/cranelift_backend.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1737,7 +1737,14 @@ impl CraneliftBackend {
17371737
}
17381738

17391739
HirTerminator::Unreachable => {
1740-
builder.ins().trap(cranelift_codegen::ir::TrapCode::UnreachableCodeReached);
1740+
// For void-returning functions, emit a return instead of trap
1741+
// This handles Haxe/other languages where main() returns Void and has no explicit return
1742+
if function.signature.returns.is_empty() ||
1743+
function.signature.returns.iter().all(|r| matches!(r, HirType::Void)) {
1744+
builder.ins().return_(&[]);
1745+
} else {
1746+
builder.ins().trap(cranelift_codegen::ir::TrapCode::UnreachableCodeReached);
1747+
}
17411748
}
17421749

17431750
_ => {

crates/compiler/src/typed_cfg.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,22 @@ impl TypedCfgBuilder {
782782
exit_id = block_exit;
783783
}
784784

785+
TypedStatement::Expression(expr) => {
786+
// Check if expression is a Block - if so, flatten it
787+
if let TypedExpression::Block(block) = &expr.node {
788+
log::debug!("[CFG] Expression(Block): flattening block with {} statements", block.statements.len());
789+
// Recursively process the block's statements
790+
let (block_blocks, _block_entry, block_exit) = self.split_at_control_flow(block, current_block_id)?;
791+
all_blocks.extend(block_blocks);
792+
current_statements = Vec::new();
793+
current_block_id = block_exit;
794+
exit_id = block_exit;
795+
} else {
796+
// Regular expression - add as statement
797+
current_statements.push(stmt.clone());
798+
}
799+
}
800+
785801
TypedStatement::Break(value_opt) => {
786802
// Break jumps to loop exit
787803
if let Some(&(_header_id, exit_id)) = self.loop_stack.last() {

reflaxe.zyntax/extraParams.hxml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
# Define Zyntax target for conditional compilation
88
-D zyntax
99

10+
# Enable Zyntax runtime transformers (StringOperatorTransformer, TraceTransformer)
11+
-D zyntax_runtime
12+
1013
# Initialize the Zyntax compiler
1114
--macro zyntax.ZyntaxCompilerInit.Start()
1215

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class SimpleWhileTest {
2+
public static function calculate():Int {
3+
// Simple while loop that returns a value
4+
var sum = 0;
5+
var i = 0;
6+
while (i < 5) {
7+
sum = sum + i;
8+
i = i + 1;
9+
}
10+
return sum; // Should return 0+1+2+3+4 = 10
11+
}
12+
13+
public static function main():Void {
14+
var result = calculate();
15+
// result is 10
16+
}
17+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-lib reflaxe.zyntax
2+
-main SimpleWhileTest
3+
-D zyntax-output=output
4+
--macro exclude('haxe.Log')

0 commit comments

Comments
 (0)