authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-06-23 18:19:17-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-02 13:26:50-07:00
log125b85d7375b96b4847f6ead51c853cdc0567506
tree34a947e48f84ce6455d3ff133828a8e0e5614ce8
parentd84b386f6034278c8a9e8c3d2b0975ac541584aa

move "unreachable code" error from stage1 to stage2

* AstGen: implement "unreachable code" error for blocks. This works at the statement level. * stage1: remove the "unreachable code" error implementation, which means removing the `is_gen` field from IrInstSrc. This is one small step towards a smaller memory footprint for stage1. The benefits won't be realized until a future commit because this flag took advantage of padding. There may be a regression here with "union has no associated enum" error, and there is a regression with the following code: ```zig const a = noreturn; ``` A future commit will address these regressions.

6 files changed, 109 insertions(+), 105 deletions(-)

lib/std/unicode.zig-1
......@@ -247,7 +247,6 @@ pub const Utf8View = struct {
247247 } else |err| switch (err) {
248248 error.InvalidUtf8 => {
249249 @compileError("invalid utf8");
250 unreachable;
251250 },
252251 }
253252 }
src/AstGen.zig+49-21
......@@ -1570,7 +1570,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index) Inn
15701570 const defer_scope = scope.cast(Scope.Defer).?;
15711571 scope = defer_scope.parent;
15721572 const expr_node = node_datas[defer_scope.defer_node].rhs;
1573 try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);
1573 _ = try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);
15741574 },
15751575 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
15761576 .top => unreachable,
......@@ -1623,7 +1623,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: ast.Node.Index)
16231623 const defer_scope = scope.cast(Scope.Defer).?;
16241624 scope = defer_scope.parent;
16251625 const expr_node = node_datas[defer_scope.defer_node].rhs;
1626 try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);
1626 _ = try unusedResultExpr(parent_gz, defer_scope.parent, expr_node);
16271627 },
16281628 .defer_error => scope = scope.cast(Scope.Defer).?.parent,
16291629 .namespace => break,
......@@ -1785,8 +1785,23 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const ast.Nod
17851785 var block_arena = std.heap.ArenaAllocator.init(gz.astgen.gpa);
17861786 defer block_arena.deinit();
17871787
1788 var noreturn_src_node: ast.Node.Index = 0;
17881789 var scope = parent_scope;
17891790 for (statements) |statement| {
1791 if (noreturn_src_node != 0) {
1792 return astgen.failNodeNotes(
1793 statement,
1794 "unreachable code",
1795 .{},
1796 &[_]u32{
1797 try astgen.errNoteNode(
1798 noreturn_src_node,
1799 "control flow is diverted here",
1800 .{},
1801 ),
1802 },
1803 );
1804 }
17901805 switch (node_tags[statement]) {
17911806 // zig fmt: off
17921807 .global_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.globalVarDecl(statement)),
......@@ -1814,7 +1829,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const ast.Nod
18141829 .assign_mul => try assignOp(gz, scope, statement, .mul),
18151830 .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap),
18161831
1817 else => try unusedResultExpr(gz, scope, statement),
1832 else => noreturn_src_node = try unusedResultExpr(gz, scope, statement),
18181833 // zig fmt: on
18191834 }
18201835 }
......@@ -1823,11 +1838,14 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const ast.Nod
18231838 try checkUsed(gz, parent_scope, scope);
18241839}
18251840
1826fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) InnerError!void {
1841/// Returns AST source node of the thing that is noreturn if the statement is definitely `noreturn`.
1842/// Otherwise returns 0.
1843fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) InnerError!ast.Node.Index {
18271844 try emitDbgNode(gz, statement);
18281845 // We need to emit an error if the result is not `noreturn` or `void`, but
18291846 // we want to avoid adding the ZIR instruction if possible for performance.
18301847 const maybe_unused_result = try expr(gz, scope, .none, statement);
1848 var noreturn_src_node: ast.Node.Index = 0;
18311849 const elide_check = if (gz.refToIndex(maybe_unused_result)) |inst| b: {
18321850 // Note that this array becomes invalid after appending more items to it
18331851 // in the above while loop.
......@@ -2061,15 +2079,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
20612079 .extended,
20622080 => break :b false,
20632081
2064 // ZIR instructions that are always either `noreturn` or `void`.
2065 .breakpoint,
2066 .fence,
2067 .dbg_stmt,
2068 .ensure_result_used,
2069 .ensure_result_non_error,
2070 .@"export",
2071 .set_eval_branch_quota,
2072 .ensure_err_payload_void,
2082 // ZIR instructions that are always `noreturn`.
20732083 .@"break",
20742084 .break_inline,
20752085 .condbr,
......@@ -2078,16 +2088,30 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
20782088 .ret_node,
20792089 .ret_coerce,
20802090 .@"unreachable",
2091 .repeat,
2092 .repeat_inline,
2093 .panic,
2094 => {
2095 noreturn_src_node = statement;
2096 break :b true;
2097 },
2098
2099 // ZIR instructions that are always `void`.
2100 .breakpoint,
2101 .fence,
2102 .dbg_stmt,
2103 .ensure_result_used,
2104 .ensure_result_non_error,
2105 .@"export",
2106 .set_eval_branch_quota,
2107 .ensure_err_payload_void,
20812108 .store,
20822109 .store_node,
20832110 .store_to_block_ptr,
20842111 .store_to_inferred_ptr,
20852112 .resolve_inferred_alloc,
2086 .repeat,
2087 .repeat_inline,
20882113 .validate_struct_init_ptr,
20892114 .validate_array_init_ptr,
2090 .panic,
20912115 .set_align_stack,
20922116 .set_cold,
20932117 .set_float_mode,
......@@ -2097,15 +2121,19 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
20972121 } else switch (maybe_unused_result) {
20982122 .none => unreachable,
20992123
2100 .void_value,
2101 .unreachable_value,
2102 => true,
2124 .unreachable_value => b: {
2125 noreturn_src_node = statement;
2126 break :b true;
2127 },
2128
2129 .void_value => true,
21032130
21042131 else => false,
21052132 };
21062133 if (!elide_check) {
21072134 _ = try gz.addUnNode(.ensure_result_used, maybe_unused_result, statement);
21082135 }
2136 return noreturn_src_node;
21092137}
21102138
21112139fn genDefers(
......@@ -2132,7 +2160,7 @@ fn genDefers(
21322160 const prev_in_defer = gz.in_defer;
21332161 gz.in_defer = true;
21342162 defer gz.in_defer = prev_in_defer;
2135 try unusedResultExpr(gz, defer_scope.parent, expr_node);
2163 _ = try unusedResultExpr(gz, defer_scope.parent, expr_node);
21362164 },
21372165 .defer_error => {
21382166 const defer_scope = scope.cast(Scope.Defer).?;
......@@ -2142,7 +2170,7 @@ fn genDefers(
21422170 const prev_in_defer = gz.in_defer;
21432171 gz.in_defer = true;
21442172 defer gz.in_defer = prev_in_defer;
2145 try unusedResultExpr(gz, defer_scope.parent, expr_node);
2173 _ = try unusedResultExpr(gz, defer_scope.parent, expr_node);
21462174 },
21472175 .namespace => unreachable,
21482176 .top => unreachable,
src/stage1/all_types.hpp-3
......@@ -2733,9 +2733,6 @@ struct IrInstSrc {
27332733 IrInst base;
27342734
27352735 IrInstSrcId id;
2736 // true if this instruction was generated by zig and not from user code
2737 // this matters for the "unreachable code" compile error
2738 bool is_gen;
27392736 bool is_noreturn;
27402737
27412738 // When analyzing IR, instructions that point to this instruction in the "old ir"
src/stage1/astgen.cpp+55-66
......@@ -2557,7 +2557,6 @@ static IrInstSrc *ir_build_reset_result(Stage1AstGen *ag, Scope *scope, AstNode
25572557{
25582558 IrInstSrcResetResult *instruction = ir_build_instruction<IrInstSrcResetResult>(ag, scope, source_node);
25592559 instruction->result_loc = result_loc;
2560 instruction->base.is_gen = true;
25612560
25622561 return &instruction->base;
25632562}
......@@ -2737,7 +2736,6 @@ static IrInstSrc *ir_build_alloca_src(Stage1AstGen *ag, Scope *scope, AstNode *s
27372736 IrInstSrc *align, const char *name_hint, IrInstSrc *is_comptime)
27382737{
27392738 IrInstSrcAlloca *instruction = ir_build_instruction<IrInstSrcAlloca>(ag, scope, source_node);
2740 instruction->base.is_gen = true;
27412739 instruction->align = align;
27422740 instruction->name_hint = name_hint;
27432741 instruction->is_comptime = is_comptime;
......@@ -2752,7 +2750,6 @@ static IrInstSrc *ir_build_end_expr(Stage1AstGen *ag, Scope *scope, AstNode *sou
27522750 IrInstSrc *value, ResultLoc *result_loc)
27532751{
27542752 IrInstSrcEndExpr *instruction = ir_build_instruction<IrInstSrcEndExpr>(ag, scope, source_node);
2755 instruction->base.is_gen = true;
27562753 instruction->value = value;
27572754 instruction->result_loc = result_loc;
27582755
......@@ -2885,11 +2882,6 @@ static void ir_count_defers(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_s
28852882 }
28862883}
28872884
2888static IrInstSrc *ir_mark_gen(IrInstSrc *instruction) {
2889 instruction->is_gen = true;
2890 return instruction;
2891}
2892
28932885static bool astgen_defers_for_block(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_scope, bool *is_noreturn, IrInstSrc *err_value) {
28942886 Scope *scope = inner_scope;
28952887 if (is_noreturn != nullptr) *is_noreturn = false;
......@@ -2948,8 +2940,8 @@ static bool astgen_defers_for_block(Stage1AstGen *ag, Scope *inner_scope, Scope
29482940 if (defer_expr_value->is_noreturn) {
29492941 if (is_noreturn != nullptr) *is_noreturn = true;
29502942 } else {
2951 ir_mark_gen(ir_build_check_statement_is_void(ag, defer_expr_scope, defer_expr_node,
2952 defer_expr_value));
2943 ir_build_check_statement_is_void(ag, defer_expr_scope, defer_expr_node,
2944 defer_expr_value);
29532945 }
29542946 scope = scope->parent;
29552947 continue;
......@@ -3047,7 +3039,7 @@ static IrInstSrc *astgen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, L
30473039 ir_build_end_expr(ag, scope, node, return_value, &result_loc_ret->base);
30483040 }
30493041
3050 ir_mark_gen(ir_build_add_implicit_return_type(ag, scope, node, return_value, result_loc_ret));
3042 ir_build_add_implicit_return_type(ag, scope, node, return_value, result_loc_ret);
30513043
30523044 size_t defer_counts[2];
30533045 ir_count_defers(ag, scope, outer_scope, defer_counts);
......@@ -3074,7 +3066,7 @@ static IrInstSrc *astgen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, L
30743066 is_comptime = ir_build_test_comptime(ag, scope, node, is_err);
30753067 }
30763068
3077 ir_mark_gen(ir_build_cond_br(ag, scope, node, is_err, err_block, ok_block, is_comptime));
3069 ir_build_cond_br(ag, scope, node, is_err, err_block, ok_block, is_comptime);
30783070 Stage1ZirBasicBlock *ret_stmt_block = ir_create_basic_block(ag, scope, "RetStmt");
30793071
30803072 ir_set_cursor_at_end_and_append_block(ag, err_block);
......@@ -3112,12 +3104,12 @@ static IrInstSrc *astgen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, L
31123104 } else {
31133105 is_comptime = ir_build_test_comptime(ag, scope, node, is_err_val);
31143106 }
3115 ir_mark_gen(ir_build_cond_br(ag, scope, node, is_err_val, return_block, continue_block, is_comptime));
3107 ir_build_cond_br(ag, scope, node, is_err_val, return_block, continue_block, is_comptime);
31163108
31173109 ir_set_cursor_at_end_and_append_block(ag, return_block);
31183110 IrInstSrc *err_val_ptr = ir_build_unwrap_err_code_src(ag, scope, node, err_union_ptr);
31193111 IrInstSrc *err_val = ir_build_load_ptr(ag, scope, node, err_val_ptr);
3120 ir_mark_gen(ir_build_add_implicit_return_type(ag, scope, node, err_val, nullptr));
3112 ir_build_add_implicit_return_type(ag, scope, node, err_val, nullptr);
31213113 IrInstSrcSpillBegin *spill_begin = ir_build_spill_begin_src(ag, scope, node, err_val,
31223114 SpillIdRetErrCode);
31233115 ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>();
......@@ -3338,7 +3330,7 @@ static IrInstSrc *astgen_block(Stage1AstGen *ag, Scope *parent_scope, AstNode *b
33383330 child_scope = decl_var_instruction->var->child_scope;
33393331 } else if (!is_continuation_unreachable) {
33403332 // this statement's value must be void
3341 ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, statement_node, statement_value));
3333 ir_build_check_statement_is_void(ag, child_scope, statement_node, statement_value);
33423334 }
33433335 }
33443336
......@@ -3364,7 +3356,7 @@ static IrInstSrc *astgen_block(Stage1AstGen *ag, Scope *parent_scope, AstNode *b
33643356 return ir_expr_wrap(ag, parent_scope, phi, result_loc);
33653357 } else {
33663358 incoming_blocks.append(ag->current_basic_block);
3367 IrInstSrc *else_expr_result = ir_mark_gen(ir_build_const_void(ag, parent_scope, block_node));
3359 IrInstSrc *else_expr_result = ir_build_const_void(ag, parent_scope, block_node);
33683360
33693361 if (scope_block->peer_parent != nullptr) {
33703362 ResultLocPeer *peer_result = create_peer_result(scope_block->peer_parent);
......@@ -3387,13 +3379,13 @@ static IrInstSrc *astgen_block(Stage1AstGen *ag, Scope *parent_scope, AstNode *b
33873379
33883380 IrInstSrc *result;
33893381 if (block_node->data.block.name != nullptr) {
3390 ir_mark_gen(ir_build_br(ag, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime));
3382 ir_build_br(ag, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime);
33913383 ir_set_cursor_at_end_and_append_block(ag, scope_block->end_block);
33923384 IrInstSrc *phi = ir_build_phi(ag, parent_scope, block_node, incoming_blocks.length,
33933385 incoming_blocks.items, incoming_values.items, scope_block->peer_parent);
33943386 result = ir_expr_wrap(ag, parent_scope, phi, result_loc);
33953387 } else {
3396 IrInstSrc *void_inst = ir_mark_gen(ir_build_const_void(ag, child_scope, block_node));
3388 IrInstSrc *void_inst = ir_build_const_void(ag, child_scope, block_node);
33973389 result = ir_lval_wrap(ag, parent_scope, void_inst, lval, result_loc);
33983390 }
33993391 if (!is_return_from_fn)
......@@ -3402,14 +3394,14 @@ static IrInstSrc *astgen_block(Stage1AstGen *ag, Scope *parent_scope, AstNode *b
34023394 // no need for save_err_ret_addr because this cannot return error
34033395 // only generate unconditional defers
34043396
3405 ir_mark_gen(ir_build_add_implicit_return_type(ag, child_scope, block_node, result, nullptr));
3397 ir_build_add_implicit_return_type(ag, child_scope, block_node, result, nullptr);
34063398 ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>();
34073399 result_loc_ret->base.id = ResultLocIdReturn;
34083400 ir_build_reset_result(ag, parent_scope, block_node, &result_loc_ret->base);
3409 ir_mark_gen(ir_build_end_expr(ag, parent_scope, block_node, result, &result_loc_ret->base));
3401 ir_build_end_expr(ag, parent_scope, block_node, result, &result_loc_ret->base);
34103402 if (!astgen_defers_for_block(ag, child_scope, outer_block_scope, nullptr, nullptr))
34113403 return ag->codegen->invalid_inst_src;
3412 return ir_mark_gen(ir_build_return_src(ag, child_scope, result->base.source_node, result));
3404 return ir_build_return_src(ag, child_scope, result->base.source_node, result);
34133405}
34143406
34153407static IrInstSrc *astgen_bin_op_id(Stage1AstGen *ag, Scope *scope, AstNode *node, IrBinOp op_id) {
......@@ -3628,7 +3620,7 @@ static IrInstSrc *astgen_orelse(Stage1AstGen *ag, Scope *parent_scope, AstNode *
36283620 return ag->codegen->invalid_inst_src;
36293621 Stage1ZirBasicBlock *after_null_block = ag->current_basic_block;
36303622 if (!instr_is_unreachable(null_result))
3631 ir_mark_gen(ir_build_br(ag, parent_scope, node, end_block, is_comptime));
3623 ir_build_br(ag, parent_scope, node, end_block, is_comptime);
36323624
36333625 ir_set_cursor_at_end_and_append_block(ag, ok_block);
36343626 IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(ag, parent_scope, node, maybe_ptr, false);
......@@ -5395,7 +5387,7 @@ static IrInstSrc *astgen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *n
53955387 return ag->codegen->invalid_inst_src;
53965388 Stage1ZirBasicBlock *after_then_block = ag->current_basic_block;
53975389 if (!instr_is_unreachable(then_expr_result))
5398 ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime));
5390 ir_build_br(ag, scope, node, endif_block, is_comptime);
53995391
54005392 ir_set_cursor_at_end_and_append_block(ag, else_block);
54015393 IrInstSrc *else_expr_result;
......@@ -5409,7 +5401,7 @@ static IrInstSrc *astgen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *n
54095401 }
54105402 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
54115403 if (!instr_is_unreachable(else_expr_result))
5412 ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime));
5404 ir_build_br(ag, scope, node, endif_block, is_comptime);
54135405
54145406 ir_set_cursor_at_end_and_append_block(ag, endif_block);
54155407 IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2);
......@@ -5954,12 +5946,11 @@ static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod
59545946 IrInstSrc *is_err = ir_build_test_err_src(ag, scope, node->data.while_expr.condition, err_val_ptr,
59555947 true, false);
59565948 Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block;
5957 IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, scope, node));
5949 IrInstSrc *void_else_result = else_node ? nullptr : ir_build_const_void(ag, scope, node);
59585950 IrInstSrc *cond_br_inst;
59595951 if (!instr_is_unreachable(is_err)) {
59605952 cond_br_inst = ir_build_cond_br(ag, scope, node->data.while_expr.condition, is_err,
59615953 else_block, body_block, is_comptime);
5962 cond_br_inst->is_gen = true;
59635954 } else {
59645955 // for the purposes of the source instruction to ir_build_result_peers
59655956 cond_br_inst = ag->current_basic_block->instruction_list.last();
......@@ -6005,8 +5996,8 @@ static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod
60055996 }
60065997
60075998 if (!instr_is_unreachable(body_result)) {
6008 ir_mark_gen(ir_build_check_statement_is_void(ag, payload_scope, node->data.while_expr.body, body_result));
6009 ir_mark_gen(ir_build_br(ag, payload_scope, node, continue_block, is_comptime));
5999 ir_build_check_statement_is_void(ag, payload_scope, node->data.while_expr.body, body_result);
6000 ir_build_br(ag, payload_scope, node, continue_block, is_comptime);
60106001 }
60116002
60126003 if (continue_expr_node) {
......@@ -6015,8 +6006,8 @@ static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod
60156006 if (expr_result == ag->codegen->invalid_inst_src)
60166007 return expr_result;
60176008 if (!instr_is_unreachable(expr_result)) {
6018 ir_mark_gen(ir_build_check_statement_is_void(ag, payload_scope, continue_expr_node, expr_result));
6019 ir_mark_gen(ir_build_br(ag, payload_scope, node, cond_block, is_comptime));
6009 ir_build_check_statement_is_void(ag, payload_scope, continue_expr_node, expr_result);
6010 ir_build_br(ag, payload_scope, node, cond_block, is_comptime);
60206011 }
60216012 }
60226013
......@@ -6041,7 +6032,7 @@ static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod
60416032 if (else_result == ag->codegen->invalid_inst_src)
60426033 return else_result;
60436034 if (!instr_is_unreachable(else_result))
6044 ir_mark_gen(ir_build_br(ag, scope, node, end_block, is_comptime));
6035 ir_build_br(ag, scope, node, end_block, is_comptime);
60456036 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
60466037 ir_set_cursor_at_end_and_append_block(ag, end_block);
60476038 if (else_result) {
......@@ -6075,12 +6066,11 @@ static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod
60756066 IrInstSrc *maybe_val = ir_build_load_ptr(ag, scope, node->data.while_expr.condition, maybe_val_ptr);
60766067 IrInstSrc *is_non_null = ir_build_test_non_null_src(ag, scope, node->data.while_expr.condition, maybe_val);
60776068 Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block;
6078 IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, scope, node));
6069 IrInstSrc *void_else_result = else_node ? nullptr : ir_build_const_void(ag, scope, node);
60796070 IrInstSrc *cond_br_inst;
60806071 if (!instr_is_unreachable(is_non_null)) {
60816072 cond_br_inst = ir_build_cond_br(ag, scope, node->data.while_expr.condition, is_non_null,
60826073 body_block, else_block, is_comptime);
6083 cond_br_inst->is_gen = true;
60846074 } else {
60856075 // for the purposes of the source instruction to ir_build_result_peers
60866076 cond_br_inst = ag->current_basic_block->instruction_list.last();
......@@ -6123,8 +6113,8 @@ static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod
61236113 }
61246114
61256115 if (!instr_is_unreachable(body_result)) {
6126 ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, node->data.while_expr.body, body_result));
6127 ir_mark_gen(ir_build_br(ag, child_scope, node, continue_block, is_comptime));
6116 ir_build_check_statement_is_void(ag, child_scope, node->data.while_expr.body, body_result);
6117 ir_build_br(ag, child_scope, node, continue_block, is_comptime);
61286118 }
61296119
61306120 if (continue_expr_node) {
......@@ -6133,8 +6123,8 @@ static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod
61336123 if (expr_result == ag->codegen->invalid_inst_src)
61346124 return expr_result;
61356125 if (!instr_is_unreachable(expr_result)) {
6136 ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, continue_expr_node, expr_result));
6137 ir_mark_gen(ir_build_br(ag, child_scope, node, cond_block, is_comptime));
6126 ir_build_check_statement_is_void(ag, child_scope, continue_expr_node, expr_result);
6127 ir_build_br(ag, child_scope, node, cond_block, is_comptime);
61386128 }
61396129 }
61406130
......@@ -6151,7 +6141,7 @@ static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod
61516141 if (else_result == ag->codegen->invalid_inst_src)
61526142 return else_result;
61536143 if (!instr_is_unreachable(else_result))
6154 ir_mark_gen(ir_build_br(ag, scope, node, end_block, is_comptime));
6144 ir_build_br(ag, scope, node, end_block, is_comptime);
61556145 }
61566146 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
61576147 ir_set_cursor_at_end_and_append_block(ag, end_block);
......@@ -6175,12 +6165,11 @@ static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod
61756165 if (cond_val == ag->codegen->invalid_inst_src)
61766166 return cond_val;
61776167 Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block;
6178 IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, scope, node));
6168 IrInstSrc *void_else_result = else_node ? nullptr : ir_build_const_void(ag, scope, node);
61796169 IrInstSrc *cond_br_inst;
61806170 if (!instr_is_unreachable(cond_val)) {
61816171 cond_br_inst = ir_build_cond_br(ag, scope, node->data.while_expr.condition, cond_val,
61826172 body_block, else_block, is_comptime);
6183 cond_br_inst->is_gen = true;
61846173 } else {
61856174 // for the purposes of the source instruction to ir_build_result_peers
61866175 cond_br_inst = ag->current_basic_block->instruction_list.last();
......@@ -6219,8 +6208,8 @@ static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod
62196208 }
62206209
62216210 if (!instr_is_unreachable(body_result)) {
6222 ir_mark_gen(ir_build_check_statement_is_void(ag, scope, node->data.while_expr.body, body_result));
6223 ir_mark_gen(ir_build_br(ag, scope, node, continue_block, is_comptime));
6211 ir_build_check_statement_is_void(ag, scope, node->data.while_expr.body, body_result);
6212 ir_build_br(ag, scope, node, continue_block, is_comptime);
62246213 }
62256214
62266215 if (continue_expr_node) {
......@@ -6229,8 +6218,8 @@ static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod
62296218 if (expr_result == ag->codegen->invalid_inst_src)
62306219 return expr_result;
62316220 if (!instr_is_unreachable(expr_result)) {
6232 ir_mark_gen(ir_build_check_statement_is_void(ag, scope, continue_expr_node, expr_result));
6233 ir_mark_gen(ir_build_br(ag, scope, node, cond_block, is_comptime));
6221 ir_build_check_statement_is_void(ag, scope, continue_expr_node, expr_result);
6222 ir_build_br(ag, scope, node, cond_block, is_comptime);
62346223 }
62356224 }
62366225
......@@ -6248,7 +6237,7 @@ static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *nod
62486237 if (else_result == ag->codegen->invalid_inst_src)
62496238 return else_result;
62506239 if (!instr_is_unreachable(else_result))
6251 ir_mark_gen(ir_build_br(ag, scope, node, end_block, is_comptime));
6240 ir_build_br(ag, scope, node, end_block, is_comptime);
62526241 }
62536242 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
62546243 ir_set_cursor_at_end_and_append_block(ag, end_block);
......@@ -6332,9 +6321,9 @@ static IrInstSrc *astgen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode
63326321 IrInstSrc *index_val = ir_build_load_ptr(ag, &spill_scope->base, node, index_ptr);
63336322 IrInstSrc *cond = ir_build_bin_op(ag, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false);
63346323 Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block;
6335 IrInstSrc *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, parent_scope, node));
6336 IrInstSrc *cond_br_inst = ir_mark_gen(ir_build_cond_br(ag, parent_scope, node, cond,
6337 body_block, else_block, is_comptime));
6324 IrInstSrc *void_else_value = else_node ? nullptr : ir_build_const_void(ag, parent_scope, node);
6325 IrInstSrc *cond_br_inst = ir_build_cond_br(ag, parent_scope, node, cond,
6326 body_block, else_block, is_comptime);
63386327
63396328 ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, result_loc, is_comptime);
63406329
......@@ -6377,8 +6366,8 @@ static IrInstSrc *astgen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode
63776366 }
63786367
63796368 if (!instr_is_unreachable(body_result)) {
6380 ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, node->data.for_expr.body, body_result));
6381 ir_mark_gen(ir_build_br(ag, child_scope, node, continue_block, is_comptime));
6369 ir_build_check_statement_is_void(ag, child_scope, node->data.for_expr.body, body_result);
6370 ir_build_br(ag, child_scope, node, continue_block, is_comptime);
63826371 }
63836372
63846373 ir_set_cursor_at_end_and_append_block(ag, continue_block);
......@@ -6399,7 +6388,7 @@ static IrInstSrc *astgen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode
63996388 if (else_result == ag->codegen->invalid_inst_src)
64006389 return else_result;
64016390 if (!instr_is_unreachable(else_result))
6402 ir_mark_gen(ir_build_br(ag, parent_scope, node, end_block, is_comptime));
6391 ir_build_br(ag, parent_scope, node, end_block, is_comptime);
64036392 }
64046393 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
64056394 ir_set_cursor_at_end_and_append_block(ag, end_block);
......@@ -6719,7 +6708,7 @@ static IrInstSrc *astgen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNod
67196708 return then_expr_result;
67206709 Stage1ZirBasicBlock *after_then_block = ag->current_basic_block;
67216710 if (!instr_is_unreachable(then_expr_result))
6722 ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime));
6711 ir_build_br(ag, scope, node, endif_block, is_comptime);
67236712
67246713 ir_set_cursor_at_end_and_append_block(ag, else_block);
67256714 IrInstSrc *else_expr_result;
......@@ -6733,7 +6722,7 @@ static IrInstSrc *astgen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNod
67336722 }
67346723 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
67356724 if (!instr_is_unreachable(else_expr_result))
6736 ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime));
6725 ir_build_br(ag, scope, node, endif_block, is_comptime);
67376726
67386727 ir_set_cursor_at_end_and_append_block(ag, endif_block);
67396728 IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2);
......@@ -6802,7 +6791,7 @@ static IrInstSrc *astgen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *no
68026791 return then_expr_result;
68036792 Stage1ZirBasicBlock *after_then_block = ag->current_basic_block;
68046793 if (!instr_is_unreachable(then_expr_result))
6805 ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime));
6794 ir_build_br(ag, scope, node, endif_block, is_comptime);
68066795
68076796 ir_set_cursor_at_end_and_append_block(ag, else_block);
68086797
......@@ -6831,7 +6820,7 @@ static IrInstSrc *astgen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *no
68316820 }
68326821 Stage1ZirBasicBlock *after_else_block = ag->current_basic_block;
68336822 if (!instr_is_unreachable(else_expr_result))
6834 ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime));
6823 ir_build_br(ag, scope, node, endif_block, is_comptime);
68356824
68366825 ir_set_cursor_at_end_and_append_block(ag, endif_block);
68376826 IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2);
......@@ -6893,7 +6882,7 @@ static bool astgen_switch_prong_expr(Stage1AstGen *ag, Scope *scope, AstNode *sw
68936882 if (expr_result == ag->codegen->invalid_inst_src)
68946883 return false;
68956884 if (!instr_is_unreachable(expr_result))
6896 ir_mark_gen(ir_build_br(ag, scope, switch_node, end_block, is_comptime));
6885 ir_build_br(ag, scope, switch_node, end_block, is_comptime);
68976886 incoming_blocks->append(ag->current_basic_block);
68986887 incoming_values->append(expr_result);
68996888 return true;
......@@ -7008,8 +6997,8 @@ static IrInstSrc *astgen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *no
70086997
70096998 assert(ok_bit);
70106999 assert(last_item_node);
7011 IrInstSrc *br_inst = ir_mark_gen(ir_build_cond_br(ag, scope, last_item_node, ok_bit,
7012 range_block_yes, range_block_no, is_comptime));
7000 IrInstSrc *br_inst = ir_build_cond_br(ag, scope, last_item_node, ok_bit,
7001 range_block_yes, range_block_no, is_comptime);
70137002 if (peer_parent->base.source_instruction == nullptr) {
70147003 peer_parent->base.source_instruction = br_inst;
70157004 }
......@@ -7349,14 +7338,14 @@ static IrInstSrc *astgen_continue(Stage1AstGen *ag, Scope *continue_scope, AstNo
73497338
73507339 for (size_t i = 0; i < runtime_scopes.length; i += 1) {
73517340 ScopeRuntime *scope_runtime = runtime_scopes.at(i);
7352 ir_mark_gen(ir_build_check_runtime_scope(ag, continue_scope, node, scope_runtime->is_comptime, is_comptime));
7341 ir_build_check_runtime_scope(ag, continue_scope, node, scope_runtime->is_comptime, is_comptime);
73537342 }
73547343 runtime_scopes.deinit();
73557344
73567345 Stage1ZirBasicBlock *dest_block = loop_scope->continue_block;
73577346 if (!astgen_defers_for_block(ag, continue_scope, dest_block->scope, nullptr, nullptr))
73587347 return ag->codegen->invalid_inst_src;
7359 return ir_mark_gen(ir_build_br(ag, continue_scope, node, dest_block, is_comptime));
7348 return ir_build_br(ag, continue_scope, node, dest_block, is_comptime);
73607349}
73617350
73627351static IrInstSrc *astgen_error_type(Stage1AstGen *ag, Scope *scope, AstNode *node) {
......@@ -7482,7 +7471,7 @@ static IrInstSrc *astgen_catch(Stage1AstGen *ag, Scope *parent_scope, AstNode *n
74827471 return ag->codegen->invalid_inst_src;
74837472 Stage1ZirBasicBlock *after_err_block = ag->current_basic_block;
74847473 if (!instr_is_unreachable(err_result))
7485 ir_mark_gen(ir_build_br(ag, parent_scope, node, end_block, is_comptime));
7474 ir_build_br(ag, parent_scope, node, end_block, is_comptime);
74867475
74877476 ir_set_cursor_at_end_and_append_block(ag, ok_block);
74887477 IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(ag, parent_scope, node, err_union_ptr, false, false);
......@@ -7757,9 +7746,9 @@ static IrInstSrc *astgen_suspend(Stage1AstGen *ag, Scope *parent_scope, AstNode
77577746 IrInstSrc *susp_res = astgen_node(ag, node->data.suspend.block, child_scope);
77587747 if (susp_res == ag->codegen->invalid_inst_src)
77597748 return ag->codegen->invalid_inst_src;
7760 ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, node->data.suspend.block, susp_res));
7749 ir_build_check_statement_is_void(ag, child_scope, node->data.suspend.block, susp_res);
77617750
7762 return ir_mark_gen(ir_build_suspend_finish_src(ag, parent_scope, node, begin));
7751 return ir_build_suspend_finish_src(ag, parent_scope, node, begin);
77637752}
77647753
77657754static IrInstSrc *astgen_node_raw(Stage1AstGen *ag, AstNode *node, Scope *scope,
......@@ -8073,13 +8062,13 @@ bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *sta
80738062 }
80748063
80758064 if (!instr_is_unreachable(result)) {
8076 ir_mark_gen(ir_build_add_implicit_return_type(ag, scope, result->base.source_node, result, nullptr));
8065 ir_build_add_implicit_return_type(ag, scope, result->base.source_node, result, nullptr);
80778066 // no need for save_err_ret_addr because this cannot return error
80788067 ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>();
80798068 result_loc_ret->base.id = ResultLocIdReturn;
80808069 ir_build_reset_result(ag, scope, node, &result_loc_ret->base);
8081 ir_mark_gen(ir_build_end_expr(ag, scope, node, result, &result_loc_ret->base));
8082 ir_mark_gen(ir_build_return_src(ag, scope, result->base.source_node, result));
8070 ir_build_end_expr(ag, scope, node, result, &result_loc_ret->base);
8071 ir_build_return_src(ag, scope, result->base.source_node, result);
80838072 }
80848073
80858074 return true;
src/stage1/ir.cpp+3-13
......@@ -5407,16 +5407,6 @@ static void ir_finish_bb(IrAnalyze *ira) {
54075407 ira->new_irb.current_basic_block->debug_id);
54085408 }
54095409 }
5410 ira->instruction_index += 1;
5411 while (ira->instruction_index < ira->zir_current_basic_block->instruction_list.length) {
5412 IrInstSrc *next_instruction = ira->zir_current_basic_block->instruction_list.at(ira->instruction_index);
5413 if (!next_instruction->is_gen) {
5414 ir_add_error(ira, &next_instruction->base, buf_sprintf("unreachable code"));
5415 break;
5416 }
5417 ira->instruction_index += 1;
5418 }
5419
54205410 ir_start_next_bb(ira);
54215411}
54225412
......@@ -15934,7 +15924,7 @@ static IrInstGen *ir_analyze_instruction_pop_count(IrAnalyze *ira, IrInstSrcPopC
1593415924 return ir_build_pop_count_gen(ira, &instruction->base.base, return_type, op);
1593515925}
1593615926
15937static IrInstGen *ir_analyze_union_tag(IrAnalyze *ira, IrInst* source_instr, IrInstGen *value, bool is_gen) {
15927static IrInstGen *ir_analyze_union_tag(IrAnalyze *ira, IrInst* source_instr, IrInstGen *value) {
1593815928 if (type_is_invalid(value->value->type))
1593915929 return ira->codegen->invalid_inst_gen;
1594015930
......@@ -15943,7 +15933,7 @@ static IrInstGen *ir_analyze_union_tag(IrAnalyze *ira, IrInst* source_instr, IrI
1594315933 buf_sprintf("expected enum or union type, found '%s'", buf_ptr(&value->value->type->name)));
1594415934 return ira->codegen->invalid_inst_gen;
1594515935 }
15946 if (!value->value->type->data.unionation.have_explicit_tag_type && !is_gen) {
15936 if (!value->value->type->data.unionation.have_explicit_tag_type) {
1594715937 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("union has no associated enum"));
1594815938 if (value->value->type->data.unionation.decl_node != nullptr) {
1594915939 add_error_note(ira->codegen, msg, value->value->type->data.unionation.decl_node,
......@@ -16906,7 +16896,7 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc
1690616896 }
1690716897
1690816898 if (target_type->id == ZigTypeIdUnion) {
16909 target = ir_analyze_union_tag(ira, &instruction->base.base, target, instruction->base.is_gen);
16899 target = ir_analyze_union_tag(ira, &instruction->base.base, target);
1691016900 if (type_is_invalid(target->value->type))
1691116901 return ira->codegen->invalid_inst_gen;
1691216902 target_type = target->value->type;
test/compile_errors.zig+2-1
......@@ -4762,7 +4762,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
47624762 \\
47634763 \\fn b() void {}
47644764 , &[_][]const u8{
4765 "tmp.zig:3:5: error: unreachable code",
4765 "tmp.zig:3:6: error: unreachable code",
4766 "tmp.zig:2:5: note: control flow is diverted here",
47664767 });
47674768
47684769 cases.add("bad import",