add noreturn and unreachable
This commit is contained in:
+36
-6
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user