From 4c610b8a80ecc4927a25242796a072be4f99edc4 Mon Sep 17 00:00:00 2001 From: dimgigov Date: Tue, 2 Jun 2026 13:32:41 +0300 Subject: [PATCH] fix(qbe): improved if-else label handling, QBE_IsTerminator for hIf --- _selfhost/src/qbe_backend.bux | 32 +++++++++++++++++++++++--------- src_bux/qbe_backend.bux | 32 +++++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/_selfhost/src/qbe_backend.bux b/_selfhost/src/qbe_backend.bux index 7e7d505..32e9404 100644 --- a/_selfhost/src/qbe_backend.bux +++ b/_selfhost/src/qbe_backend.bux @@ -261,6 +261,10 @@ func QBE_IsTerminator(node: *HirNode) -> bool { if node.kind == hReturn { return true; } if node.kind == hBreak { return true; } if node.kind == hContinue { return true; } + if node.kind == hIf { + // Both branches must terminate for the if to be a terminator + return QBE_IsTerminator(node.child2) && QBE_IsTerminator(node.child3); + } if node.kind == hBlock { var last: *HirNode = node.child1; if last == null as *HirNode { return false; } @@ -684,25 +688,35 @@ func QBE_EmitStmt(qbe: *QbeEmitter, node: *HirNode) { QBE_Emit(qbe, ", "); QBE_Emit(qbe, lThen); QBE_Emit(qbe, ", "); - QBE_EmitLine(qbe, lElse); + var hasElse: bool = node.child3 != null as *HirNode; + if hasElse { + QBE_EmitLine(qbe, lElse); + } else { + QBE_EmitLine(qbe, lEnd); + } QBE_EmitLine(qbe, lThen); QBE_EmitStmt(qbe, node.child2); - if !QBE_IsTerminator(node.child2) { + let thenTerm: bool = QBE_IsTerminator(node.child2); + if !thenTerm { QBE_EmitIndent(qbe); QBE_Emit(qbe, "jmp "); QBE_EmitLine(qbe, lEnd); } - QBE_EmitLine(qbe, lElse); - QBE_EmitStmt(qbe, node.child3); - if !QBE_IsTerminator(node.child3) { - QBE_EmitIndent(qbe); - QBE_Emit(qbe, "jmp "); - QBE_EmitLine(qbe, lEnd); + if hasElse { + QBE_EmitLine(qbe, lElse); + QBE_EmitStmt(qbe, node.child3); + if !QBE_IsTerminator(node.child3) { + QBE_EmitIndent(qbe); + QBE_Emit(qbe, "jmp "); + QBE_EmitLine(qbe, lEnd); + } } - QBE_EmitLine(qbe, lEnd); + if (!thenTerm || hasElse) { + QBE_EmitLine(qbe, lEnd); + } return; } diff --git a/src_bux/qbe_backend.bux b/src_bux/qbe_backend.bux index 7e7d505..32e9404 100644 --- a/src_bux/qbe_backend.bux +++ b/src_bux/qbe_backend.bux @@ -261,6 +261,10 @@ func QBE_IsTerminator(node: *HirNode) -> bool { if node.kind == hReturn { return true; } if node.kind == hBreak { return true; } if node.kind == hContinue { return true; } + if node.kind == hIf { + // Both branches must terminate for the if to be a terminator + return QBE_IsTerminator(node.child2) && QBE_IsTerminator(node.child3); + } if node.kind == hBlock { var last: *HirNode = node.child1; if last == null as *HirNode { return false; } @@ -684,25 +688,35 @@ func QBE_EmitStmt(qbe: *QbeEmitter, node: *HirNode) { QBE_Emit(qbe, ", "); QBE_Emit(qbe, lThen); QBE_Emit(qbe, ", "); - QBE_EmitLine(qbe, lElse); + var hasElse: bool = node.child3 != null as *HirNode; + if hasElse { + QBE_EmitLine(qbe, lElse); + } else { + QBE_EmitLine(qbe, lEnd); + } QBE_EmitLine(qbe, lThen); QBE_EmitStmt(qbe, node.child2); - if !QBE_IsTerminator(node.child2) { + let thenTerm: bool = QBE_IsTerminator(node.child2); + if !thenTerm { QBE_EmitIndent(qbe); QBE_Emit(qbe, "jmp "); QBE_EmitLine(qbe, lEnd); } - QBE_EmitLine(qbe, lElse); - QBE_EmitStmt(qbe, node.child3); - if !QBE_IsTerminator(node.child3) { - QBE_EmitIndent(qbe); - QBE_Emit(qbe, "jmp "); - QBE_EmitLine(qbe, lEnd); + if hasElse { + QBE_EmitLine(qbe, lElse); + QBE_EmitStmt(qbe, node.child3); + if !QBE_IsTerminator(node.child3) { + QBE_EmitIndent(qbe); + QBE_Emit(qbe, "jmp "); + QBE_EmitLine(qbe, lEnd); + } } - QBE_EmitLine(qbe, lEnd); + if (!thenTerm || hasElse) { + QBE_EmitLine(qbe, lEnd); + } return; }