add noreturn and unreachable

This commit is contained in:
2026-07-22 00:27:13 +02:00
parent 402871ef7a
commit 17508ff751
21 changed files with 286673 additions and 279245 deletions
+36 -6
View File
@@ -142,6 +142,11 @@ llvm_type :: proc(value: types.Type, store: ^types.Store = nil) -> string {
if types.is_void(resolved) {
return "void"
}
// `noreturn` has no value representation. Keep malformed storage recoverable with
// a byte carrier; function and call result positions map it to LLVM `void` below.
if types.is_noreturn(resolved) {
return "i8"
}
if types.is_bool(resolved) {
return "i1"
}
@@ -183,6 +188,9 @@ function_result_type :: proc(function: ir.Function, store: ^types.Store) -> stri
if function.is_main {
return "i32"
}
if types.is_noreturn(function.result) {
return "void"
}
if function.calling_convention == .C {
return c_abi_result_type(function.result, store)
}
@@ -2121,7 +2129,7 @@ emit_instruction_stream :: proc(
strings.write_string(&emitter.builder, " ")
} else if result_abi.kind != .None && result_abi.kind != .Homogeneous_Float {
fmt.sbprintf(&emitter.builder, " %%abi_result%d = ", instruction_index)
} else if !types.is_void(instruction.type) {
} else if !types.is_void(instruction.type) && !types.is_noreturn(instruction.type) {
fmt.sbprintf(&emitter.builder, " %%v%d = ", instruction_index)
} else {
strings.write_string(&emitter.builder, " ")
@@ -2137,7 +2145,10 @@ emit_instruction_stream :: proc(
}
strings.write_string(&emitter.builder, c_abi_result_type(function_item.child, &emitter.module.types))
} else {
strings.write_string(&emitter.builder, llvm_type(function_item.child, &emitter.module.types))
strings.write_string(
&emitter.builder,
"void" if types.is_noreturn(function_item.child) else llvm_type(function_item.child, &emitter.module.types),
)
}
if function_item.variadic {
strings.write_string(&emitter.builder, " (")
@@ -2187,6 +2198,10 @@ emit_instruction_stream :: proc(
wrote_arg = true
}
strings.write_string(&emitter.builder, ")\n")
if types.is_noreturn(instruction.type) {
strings.write_string(&emitter.builder, " unreachable\n")
after_terminator = true
}
if result_abi.kind == .Indirect {
fmt.sbprintf(&emitter.builder, " %%v%d = load %s, ptr %%abi_result_slot%d\n", instruction_index, llvm_type(function_item.child, &emitter.module.types), instruction_index)
} else if result_abi.kind != .None && result_abi.kind != .Homogeneous_Float {
@@ -2248,7 +2263,7 @@ emit_instruction_stream :: proc(
strings.write_string(&emitter.builder, " ")
} else if result_abi.kind != .None && result_abi.kind != .Homogeneous_Float {
fmt.sbprintf(&emitter.builder, " %%abi_result%d = ", instruction_index)
} else if !types.is_void(instruction.type) {
} else if !types.is_void(instruction.type) && !types.is_noreturn(instruction.type) {
fmt.sbprintf(&emitter.builder, " %%v%d = ", instruction_index)
} else {
strings.write_string(&emitter.builder, " ")
@@ -2304,6 +2319,10 @@ emit_instruction_stream :: proc(
wrote_arg = true
}
strings.write_string(&emitter.builder, ")\n")
if types.is_noreturn(instruction.type) {
strings.write_string(&emitter.builder, " unreachable\n")
after_terminator = true
}
if result_abi.kind == .Indirect {
fmt.sbprintf(&emitter.builder, " %%v%d = load %s, ptr %%abi_result_slot%d\n", instruction_index, llvm_type(target.result, &emitter.module.types), instruction_index)
} else if result_abi.kind != .None && result_abi.kind != .Homogeneous_Float {
@@ -2355,8 +2374,11 @@ emit_instruction_stream :: proc(
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")
fallback := "reached unreachable code" if instruction.integer != 0 else "invalid recovered source"
message := diagnostic_message(emitter, instruction.diagnostic, instruction.span, fallback)
emit_trap_call(emitter, message)
strings.write_string(&emitter.builder, " unreachable\n")
after_terminator = true
case .Return:
if global_initializer {
return_value = instruction.a
@@ -2681,10 +2703,18 @@ emit_functions :: proc(emitter: ^Emitter) {
strings.write_string(&emitter.builder, "...")
}
if function.implementation == .Declaration {
strings.write_string(&emitter.builder, ")\n\n")
strings.write_string(&emitter.builder, ")")
if types.is_noreturn(function.result) {
strings.write_string(&emitter.builder, " noreturn")
}
strings.write_string(&emitter.builder, "\n\n")
continue
}
strings.write_string(&emitter.builder, ") {\nentry:\n")
strings.write_string(&emitter.builder, ")")
if types.is_noreturn(function.result) {
strings.write_string(&emitter.builder, " noreturn")
}
strings.write_string(&emitter.builder, " {\nentry:\n")
emit_entry_allocas(emitter, function.instructions)
if function.calling_convention == .C {
for param_type, index in function.param_types {