add noreturn and unreachable
This commit is contained in:
@@ -716,6 +716,13 @@ lower_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instruction_Id {
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
_ = pop(&stack)
|
||||
case .Unreachable:
|
||||
last = append_instruction(state, ir.Instruction{
|
||||
op=.Trap, span=expr.span, type=types.NORETURN, integer=1,
|
||||
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
_ = pop(&stack)
|
||||
case .String, .Array, .Struct, .Range, .Null, .Optional_Some, .Address, .Deref,
|
||||
.Index, .Slice, .Field, .Union_Tag, .Length, .Slice_Ptr, .Unwrap, .Orelse,
|
||||
.Try, .Catch, .Not, .Eq, .Ne, .Lt, .Le, .Gt, .Ge, .And, .Or:
|
||||
@@ -1037,6 +1044,9 @@ lower_statements :: proc(state: ^State, statements: []hir.Stmt_Id) {
|
||||
})
|
||||
} else {
|
||||
value := lower_expr(state, statement.expr)
|
||||
if types.is_noreturn(state.hir_module.exprs[statement.expr].type) {
|
||||
continue
|
||||
}
|
||||
append_instruction(state, ir.Instruction{
|
||||
op=.Return,
|
||||
span=statement.span,
|
||||
@@ -1680,11 +1690,22 @@ lower_body :: proc(hir_module: ^hir.Module, function: hir.Function, allocator: m
|
||||
}
|
||||
|
||||
lower_statements(&state, function.body)
|
||||
if len(state.instructions) == 0 ||
|
||||
(state.instructions[len(state.instructions)-1].op != .Return &&
|
||||
state.instructions[len(state.instructions)-1].op != .Return_Void) {
|
||||
last_terminates := false
|
||||
if len(state.instructions) > 0 {
|
||||
last_instruction := state.instructions[len(state.instructions)-1]
|
||||
last_terminates = last_instruction.op == .Return || last_instruction.op == .Return_Void ||
|
||||
last_instruction.op == .Trap ||
|
||||
last_instruction.op == .Call && types.is_noreturn(last_instruction.type)
|
||||
}
|
||||
if !last_terminates {
|
||||
if types.is_void(function.result) {
|
||||
append_instruction(&state, ir.Instruction{op=.Return_Void, type=types.VOID, target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC})
|
||||
} else if types.is_noreturn(function.result) {
|
||||
append_instruction(&state, ir.Instruction{
|
||||
op=.Trap, type=types.NORETURN, integer=1,
|
||||
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
} else {
|
||||
value := append_instruction(&state, ir.Instruction{
|
||||
op=.Const,
|
||||
|
||||
Reference in New Issue
Block a user