break and continue in loops

This commit is contained in:
2026-06-26 23:43:57 +02:00
parent f926bbc605
commit 81ae939bf0
11 changed files with 314 additions and 12 deletions
+15 -6
View File
@@ -652,12 +652,18 @@ emit_instruction_stream :: proc(
sret_name := "",
) -> ir.Instruction_Id {
return_value := ir.INVALID_INSTRUCTION
after_return := false
// Set after any terminator (`ret`, `br`, conditional `br`). Code reachable
// only by falling off a terminator is dead; it needs a fresh label to form a
// well-formed basic block — unless the next instruction is already a `.Label`,
// which opens its own block (the normal terminator-then-label sequence).
after_terminator := false
for instruction, instruction_index in instructions {
instruction_id := ir.instruction_id(instruction_index)
if after_return {
fmt.sbprintf(&emitter.builder, "recover_after_return_%d:\n", instruction_index)
after_return = false
if after_terminator {
if instruction.op != .Label {
fmt.sbprintf(&emitter.builder, "recover_after_return_%d:\n", instruction_index)
}
after_terminator = false
}
switch instruction.op {
case .Param, .Const:
@@ -1662,14 +1668,17 @@ emit_instruction_stream :: proc(
fmt.sbprintf(&emitter.builder, "bro_block_%d:\n", instruction.integer)
case .Br:
fmt.sbprintf(&emitter.builder, " br label %%bro_block_%d\n", instruction.integer)
after_terminator = true
case .Cond_Br:
if !valid_value(instructions, instruction.a, types.BOOL, &emitter.module.types) {
fmt.sbprintf(&emitter.builder, " br label %%bro_block_%d\n", u32(instruction.target))
after_terminator = true
continue
}
strings.write_string(&emitter.builder, " br i1 ")
write_operand(&emitter.builder, instructions, instruction.a, types.BOOL, &emitter.module.types)
fmt.sbprintf(&emitter.builder, ", label %%bro_block_%d, label %%bro_block_%d\n", instruction.integer, u32(instruction.target))
after_terminator = true
case .Trap:
message := diagnostic_message(emitter, instruction.diagnostic, instruction.span, "invalid recovered source")
emit_trap_call(emitter, message)
@@ -1703,7 +1712,7 @@ emit_instruction_stream :: proc(
write_operand(&emitter.builder, instructions, instruction.a, function.result, &emitter.module.types)
strings.write_string(&emitter.builder, "\n")
}
after_return = true
after_terminator = true
case .Return_Void:
if global_initializer {
continue
@@ -1713,7 +1722,7 @@ emit_instruction_stream :: proc(
} else {
strings.write_string(&emitter.builder, " ret void\n")
}
after_return = true
after_terminator = true
}
}
return return_value