authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-24 04:29:42+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-26 13:20:45+00:00
log59447e53056d8fb6682b79accccffa176d0b44d1
treefef7809520fc67d519150592ea479576c9b289ca
parent031f23117dadd84b1e7189ee5b0f712eeb23ca1e
signaturelock-open Commit is signed but in an unrecognized format.

compiler: decide dbg_var scoping based on AIR blocks

This commit eliminates the `dbg_block_{begin,end}` instructions from both ZIR and AIR. Instead, lexical scoping of `dbg_var_{ptr,val}` instructions is decided based on the AIR block they exist within. This is a much more robust system, and also results in a huge drop in ZIR bytes - around 7% for Sema.zig. This required some enhancements to Sema to prevent elision of blocks when they are required for debug variable scoping. This can be observed by looking at the AIR for the following simple test program with and without `-fstrip`: ```zig export fn f() void { { var a: u32 = 0; _ = &a; } { var a: u32 = 0; _ = &a; } } ``` When `-fstrip` is passed, no AIR blocks are generated. When `-fno-strip` is passed, the ZIR blocks are lowered to true AIR blocks to give correct lexical scoping to the debug vars. The changes here incidentally reolve #19060. A corresponding behavior test has been added. Resolves: #19060

18 files changed, 187 insertions(+), 287 deletions(-)

src/Air.zig-8
...@@ -443,10 +443,6 @@ pub const Inst = struct {...@@ -443,10 +443,6 @@ pub const Inst = struct {
443 /// Result type is always void.443 /// Result type is always void.
444 /// Uses the `dbg_stmt` field.444 /// Uses the `dbg_stmt` field.
445 dbg_stmt,445 dbg_stmt,
446 /// Marks the beginning of a semantic scope for debug info variables.
447 dbg_block_begin,
448 /// Marks the end of a semantic scope for debug info variables.
449 dbg_block_end,
450 /// Marks the start of an inline call.446 /// Marks the start of an inline call.
451 /// Uses the `ty_fn` field.447 /// Uses the `ty_fn` field.
452 dbg_inline_begin,448 dbg_inline_begin,
...@@ -1454,8 +1450,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)...@@ -1454,8 +1450,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
1454 .dbg_stmt,1450 .dbg_stmt,
1455 .dbg_inline_begin,1451 .dbg_inline_begin,
1456 .dbg_inline_end,1452 .dbg_inline_end,
1457 .dbg_block_begin,
1458 .dbg_block_end,
1459 .dbg_var_ptr,1453 .dbg_var_ptr,
1460 .dbg_var_val,1454 .dbg_var_val,
1461 .store,1455 .store,
...@@ -1612,8 +1606,6 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {...@@ -1612,8 +1606,6 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
1612 .@"try",1606 .@"try",
1613 .try_ptr,1607 .try_ptr,
1614 .dbg_stmt,1608 .dbg_stmt,
1615 .dbg_block_begin,
1616 .dbg_block_end,
1617 .dbg_inline_begin,1609 .dbg_inline_begin,
1618 .dbg_inline_end,1610 .dbg_inline_end,
1619 .dbg_var_ptr,1611 .dbg_var_ptr,
src/AstGen.zig-51
...@@ -2445,8 +2445,6 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2445,8 +2445,6 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
24452445
2446 if (statements.len == 0) return;2446 if (statements.len == 0) return;
24472447
2448 try gz.addDbgBlockBegin();
2449
2450 var block_arena = std.heap.ArenaAllocator.init(gz.astgen.gpa);2448 var block_arena = std.heap.ArenaAllocator.init(gz.astgen.gpa);
2451 defer block_arena.deinit();2449 defer block_arena.deinit();
2452 const block_arena_allocator = block_arena.allocator();2450 const block_arena_allocator = block_arena.allocator();
...@@ -2518,8 +2516,6 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2518,8 +2516,6 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
2518 }2516 }
2519 }2517 }
25202518
2521 try gz.addDbgBlockEnd();
2522
2523 try genDefers(gz, parent_scope, scope, .normal_only);2519 try genDefers(gz, parent_scope, scope, .normal_only);
2524 try checkUsed(gz, parent_scope, scope);2520 try checkUsed(gz, parent_scope, scope);
2525}2521}
...@@ -2804,8 +2800,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2804,8 +2800,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2804 .dbg_stmt,2800 .dbg_stmt,
2805 .dbg_var_ptr,2801 .dbg_var_ptr,
2806 .dbg_var_val,2802 .dbg_var_val,
2807 .dbg_block_begin,
2808 .dbg_block_end,
2809 .ensure_result_used,2803 .ensure_result_used,
2810 .ensure_result_non_error,2804 .ensure_result_non_error,
2811 .ensure_err_union_payload_void,2805 .ensure_err_union_payload_void,
...@@ -3026,7 +3020,6 @@ fn deferStmt(...@@ -3026,7 +3020,6 @@ fn deferStmt(
3026 var opt_remapped_err_code: Zir.Inst.OptionalIndex = .none;3020 var opt_remapped_err_code: Zir.Inst.OptionalIndex = .none;
3027 const have_err_code = scope_tag == .defer_error and payload_token != 0;3021 const have_err_code = scope_tag == .defer_error and payload_token != 0;
3028 const sub_scope = if (!have_err_code) &defer_gen.base else blk: {3022 const sub_scope = if (!have_err_code) &defer_gen.base else blk: {
3029 try gz.addDbgBlockBegin();
3030 const ident_name = try gz.astgen.identAsString(payload_token);3023 const ident_name = try gz.astgen.identAsString(payload_token);
3031 const remapped_err_code: Zir.Inst.Index = @enumFromInt(gz.astgen.instructions.len);3024 const remapped_err_code: Zir.Inst.Index = @enumFromInt(gz.astgen.instructions.len);
3032 opt_remapped_err_code = remapped_err_code.toOptional();3025 opt_remapped_err_code = remapped_err_code.toOptional();
...@@ -3052,7 +3045,6 @@ fn deferStmt(...@@ -3052,7 +3045,6 @@ fn deferStmt(
3052 };3045 };
3053 _ = try unusedResultExpr(&defer_gen, sub_scope, expr_node);3046 _ = try unusedResultExpr(&defer_gen, sub_scope, expr_node);
3054 try checkUsed(gz, scope, sub_scope);3047 try checkUsed(gz, scope, sub_scope);
3055 if (have_err_code) try gz.addDbgBlockEnd();
3056 _ = try defer_gen.addBreak(.break_inline, @enumFromInt(0), .void_value);3048 _ = try defer_gen.addBreak(.break_inline, @enumFromInt(0), .void_value);
30573049
3058 // We must handle ref_table for remapped_err_code manually.3050 // We must handle ref_table for remapped_err_code manually.
...@@ -6245,7 +6237,6 @@ fn ifExpr(...@@ -6245,7 +6237,6 @@ fn ifExpr(
62456237
6246 var payload_val_scope: Scope.LocalVal = undefined;6238 var payload_val_scope: Scope.LocalVal = undefined;
62476239
6248 try then_scope.addDbgBlockBegin();
6249 const then_node = if_full.ast.then_expr;6240 const then_node = if_full.ast.then_expr;
6250 const then_sub_scope = s: {6241 const then_sub_scope = s: {
6251 if (if_full.error_token != null) {6242 if (if_full.error_token != null) {
...@@ -6305,7 +6296,6 @@ fn ifExpr(...@@ -6305,7 +6296,6 @@ fn ifExpr(
6305 const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_info, then_node);6296 const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_info, then_node);
6306 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);6297 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
6307 if (!then_scope.endsWithNoReturn()) {6298 if (!then_scope.endsWithNoReturn()) {
6308 try then_scope.addDbgBlockEnd();
6309 _ = try then_scope.addBreakWithSrcNode(.@"break", block, then_result, then_node);6299 _ = try then_scope.addBreakWithSrcNode(.@"break", block, then_result, then_node);
6310 }6300 }
63116301
...@@ -6319,7 +6309,6 @@ fn ifExpr(...@@ -6319,7 +6309,6 @@ fn ifExpr(
63196309
6320 const else_node = if_full.ast.else_expr;6310 const else_node = if_full.ast.else_expr;
6321 if (else_node != 0) {6311 if (else_node != 0) {
6322 try else_scope.addDbgBlockBegin();
6323 const sub_scope = s: {6312 const sub_scope = s: {
6324 if (if_full.error_token) |error_token| {6313 if (if_full.error_token) |error_token| {
6325 const tag: Zir.Inst.Tag = if (payload_is_ref)6314 const tag: Zir.Inst.Tag = if (payload_is_ref)
...@@ -6347,7 +6336,6 @@ fn ifExpr(...@@ -6347,7 +6336,6 @@ fn ifExpr(
6347 }6336 }
6348 };6337 };
6349 const else_result = try expr(&else_scope, sub_scope, block_scope.break_result_info, else_node);6338 const else_result = try expr(&else_scope, sub_scope, block_scope.break_result_info, else_node);
6350 try else_scope.addDbgBlockEnd();
6351 if (!else_scope.endsWithNoReturn()) {6339 if (!else_scope.endsWithNoReturn()) {
6352 // As our last action before the break, "pop" the error trace if needed6340 // As our last action before the break, "pop" the error trace if needed
6353 if (do_err_trace)6341 if (do_err_trace)
...@@ -6579,7 +6567,6 @@ fn whileExpr(...@@ -6579,7 +6567,6 @@ fn whileExpr(
6579 // done adding instructions to loop_scope, can now stack then_scope6567 // done adding instructions to loop_scope, can now stack then_scope
6580 then_scope.instructions_top = then_scope.instructions.items.len;6568 then_scope.instructions_top = then_scope.instructions.items.len;
65816569
6582 try then_scope.addDbgBlockBegin();
6583 const then_node = while_full.ast.then_expr;6570 const then_node = while_full.ast.then_expr;
6584 if (opt_payload_inst.unwrap()) |payload_inst| {6571 if (opt_payload_inst.unwrap()) |payload_inst| {
6585 try then_scope.instructions.append(astgen.gpa, payload_inst);6572 try then_scope.instructions.append(astgen.gpa, payload_inst);
...@@ -6593,7 +6580,6 @@ fn whileExpr(...@@ -6593,7 +6580,6 @@ fn whileExpr(
6593 if (while_full.ast.cont_expr != 0) {6580 if (while_full.ast.cont_expr != 0) {
6594 _ = try unusedResultExpr(&then_scope, then_sub_scope, while_full.ast.cont_expr);6581 _ = try unusedResultExpr(&then_scope, then_sub_scope, while_full.ast.cont_expr);
6595 }6582 }
6596 try then_scope.addDbgBlockEnd();
65976583
6598 continue_scope.instructions_top = continue_scope.instructions.items.len;6584 continue_scope.instructions_top = continue_scope.instructions.items.len;
6599 _ = try unusedResultExpr(&continue_scope, &continue_scope.base, then_node);6585 _ = try unusedResultExpr(&continue_scope, &continue_scope.base, then_node);
...@@ -6610,7 +6596,6 @@ fn whileExpr(...@@ -6610,7 +6596,6 @@ fn whileExpr(
66106596
6611 const else_node = while_full.ast.else_expr;6597 const else_node = while_full.ast.else_expr;
6612 if (else_node != 0) {6598 if (else_node != 0) {
6613 try else_scope.addDbgBlockBegin();
6614 const sub_scope = s: {6599 const sub_scope = s: {
6615 if (while_full.error_token) |error_token| {6600 if (while_full.error_token) |error_token| {
6616 const tag: Zir.Inst.Tag = if (payload_is_ref)6601 const tag: Zir.Inst.Tag = if (payload_is_ref)
...@@ -6647,7 +6632,6 @@ fn whileExpr(...@@ -6647,7 +6632,6 @@ fn whileExpr(
6647 }6632 }
66486633
6649 try checkUsed(parent_gz, &else_scope.base, sub_scope);6634 try checkUsed(parent_gz, &else_scope.base, sub_scope);
6650 try else_scope.addDbgBlockEnd();
6651 if (!else_scope.endsWithNoReturn()) {6635 if (!else_scope.endsWithNoReturn()) {
6652 _ = try else_scope.addBreakWithSrcNode(break_tag, loop_block, else_result, else_node);6636 _ = try else_scope.addBreakWithSrcNode(break_tag, loop_block, else_result, else_node);
6653 }6637 }
...@@ -6849,8 +6833,6 @@ fn forExpr(...@@ -6849,8 +6833,6 @@ fn forExpr(
6849 var then_scope = parent_gz.makeSubBlock(&cond_scope.base);6833 var then_scope = parent_gz.makeSubBlock(&cond_scope.base);
6850 defer then_scope.unstack();6834 defer then_scope.unstack();
68516835
6852 try then_scope.addDbgBlockBegin();
6853
6854 const capture_scopes = try gpa.alloc(Scope.LocalVal, for_full.ast.inputs.len);6836 const capture_scopes = try gpa.alloc(Scope.LocalVal, for_full.ast.inputs.len);
6855 defer gpa.free(capture_scopes);6837 defer gpa.free(capture_scopes);
68566838
...@@ -6916,7 +6898,6 @@ fn forExpr(...@@ -6916,7 +6898,6 @@ fn forExpr(
6916 _ = try addEnsureResult(&then_scope, then_result, then_node);6898 _ = try addEnsureResult(&then_scope, then_result, then_node);
69176899
6918 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);6900 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
6919 try then_scope.addDbgBlockEnd();
69206901
6921 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";6902 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
69226903
...@@ -7149,8 +7130,6 @@ fn switchExprErrUnion(...@@ -7149,8 +7130,6 @@ fn switchExprErrUnion(
7149 case_scope.instructions_top = parent_gz.instructions.items.len;7130 case_scope.instructions_top = parent_gz.instructions.items.len;
7150 defer case_scope.unstack();7131 defer case_scope.unstack();
71517132
7152 try case_scope.addDbgBlockBegin();
7153
7154 const unwrap_payload_tag: Zir.Inst.Tag = if (payload_is_ref)7133 const unwrap_payload_tag: Zir.Inst.Tag = if (payload_is_ref)
7155 .err_union_payload_unsafe_ptr7134 .err_union_payload_unsafe_ptr
7156 else7135 else
...@@ -7173,7 +7152,6 @@ fn switchExprErrUnion(...@@ -7173,7 +7152,6 @@ fn switchExprErrUnion(
7173 catch_or_if_node,7152 catch_or_if_node,
7174 ),7153 ),
7175 };7154 };
7176 try case_scope.addDbgBlockEnd();
7177 _ = try case_scope.addBreakWithSrcNode(7155 _ = try case_scope.addBreakWithSrcNode(
7178 .@"break",7156 .@"break",
7179 switch_block,7157 switch_block,
...@@ -7184,7 +7162,6 @@ fn switchExprErrUnion(...@@ -7184,7 +7162,6 @@ fn switchExprErrUnion(
7184 .@"if" => {7162 .@"if" => {
7185 var payload_val_scope: Scope.LocalVal = undefined;7163 var payload_val_scope: Scope.LocalVal = undefined;
71867164
7187 try case_scope.addDbgBlockBegin();
7188 const then_node = if_full.ast.then_expr;7165 const then_node = if_full.ast.then_expr;
7189 const then_sub_scope = s: {7166 const then_sub_scope = s: {
7190 assert(if_full.error_token != null);7167 assert(if_full.error_token != null);
...@@ -7228,7 +7205,6 @@ fn switchExprErrUnion(...@@ -7228,7 +7205,6 @@ fn switchExprErrUnion(
7228 );7205 );
7229 try checkUsed(parent_gz, &case_scope.base, then_sub_scope);7206 try checkUsed(parent_gz, &case_scope.base, then_sub_scope);
7230 if (!case_scope.endsWithNoReturn()) {7207 if (!case_scope.endsWithNoReturn()) {
7231 try case_scope.addDbgBlockEnd();
7232 _ = try case_scope.addBreakWithSrcNode(7208 _ = try case_scope.addBreakWithSrcNode(
7233 .@"break",7209 .@"break",
7234 switch_block,7210 switch_block,
...@@ -7407,7 +7383,6 @@ fn switchExprErrUnion(...@@ -7407,7 +7383,6 @@ fn switchExprErrUnion(
7407 if (do_err_trace and nodeMayAppendToErrorTrace(tree, operand_node))7383 if (do_err_trace and nodeMayAppendToErrorTrace(tree, operand_node))
7408 _ = try case_scope.addSaveErrRetIndex(.always);7384 _ = try case_scope.addSaveErrRetIndex(.always);
74097385
7410 try case_scope.addDbgBlockBegin();
7411 if (dbg_var_name != .empty) {7386 if (dbg_var_name != .empty) {
7412 try case_scope.addDbgVar(.dbg_var_val, dbg_var_name, dbg_var_inst);7387 try case_scope.addDbgVar(.dbg_var_val, dbg_var_name, dbg_var_inst);
7413 }7388 }
...@@ -7421,7 +7396,6 @@ fn switchExprErrUnion(...@@ -7421,7 +7396,6 @@ fn switchExprErrUnion(
7421 try case_scope.addDbgVar(.dbg_var_val, err_name, err_inst.toRef());7396 try case_scope.addDbgVar(.dbg_var_val, err_name, err_inst.toRef());
7422 any_uses_err_capture = true;7397 any_uses_err_capture = true;
7423 }7398 }
7424 try case_scope.addDbgBlockEnd();
74257399
7426 if (!parent_gz.refIsNoReturn(case_result)) {7400 if (!parent_gz.refIsNoReturn(case_result)) {
7427 if (do_err_trace)7401 if (do_err_trace)
...@@ -7868,7 +7842,6 @@ fn switchExpr(...@@ -7868,7 +7842,6 @@ fn switchExpr(
7868 case_scope.instructions_top = parent_gz.instructions.items.len;7842 case_scope.instructions_top = parent_gz.instructions.items.len;
7869 defer case_scope.unstack();7843 defer case_scope.unstack();
78707844
7871 try case_scope.addDbgBlockBegin();
7872 if (dbg_var_name != .empty) {7845 if (dbg_var_name != .empty) {
7873 try case_scope.addDbgVar(.dbg_var_val, dbg_var_name, dbg_var_inst);7846 try case_scope.addDbgVar(.dbg_var_val, dbg_var_name, dbg_var_inst);
7874 }7847 }
...@@ -7878,7 +7851,6 @@ fn switchExpr(...@@ -7878,7 +7851,6 @@ fn switchExpr(
7878 const target_expr_node = case.ast.target_expr;7851 const target_expr_node = case.ast.target_expr;
7879 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node);7852 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node);
7880 try checkUsed(parent_gz, &case_scope.base, sub_scope);7853 try checkUsed(parent_gz, &case_scope.base, sub_scope);
7881 try case_scope.addDbgBlockEnd();
7882 if (!parent_gz.refIsNoReturn(case_result)) {7854 if (!parent_gz.refIsNoReturn(case_result)) {
7883 _ = try case_scope.addBreakWithSrcNode(.@"break", switch_block, case_result, target_expr_node);7855 _ = try case_scope.addBreakWithSrcNode(.@"break", switch_block, case_result, target_expr_node);
7884 }7856 }
...@@ -13165,29 +13137,6 @@ const GenZir = struct {...@@ -13165,29 +13137,6 @@ const GenZir = struct {
13165 },13137 },
13166 } });13138 } });
13167 }13139 }
13168
13169 fn addDbgBlockBegin(gz: *GenZir) !void {
13170 if (gz.is_comptime) return;
13171
13172 _ = try gz.add(.{ .tag = .dbg_block_begin, .data = undefined });
13173 }
13174
13175 fn addDbgBlockEnd(gz: *GenZir) !void {
13176 if (gz.is_comptime) return;
13177 const gpa = gz.astgen.gpa;
13178
13179 const tags = gz.astgen.instructions.items(.tag);
13180 const last_inst = gz.instructions.items[gz.instructions.items.len - 1];
13181 // remove dbg_block_begin immediately followed by dbg_block_end
13182 if (tags[@intFromEnum(last_inst)] == .dbg_block_begin) {
13183 _ = gz.instructions.pop();
13184 return;
13185 }
13186
13187 const new_index: Zir.Inst.Index = @enumFromInt(gz.astgen.instructions.len);
13188 try gz.astgen.instructions.append(gpa, .{ .tag = .dbg_block_end, .data = undefined });
13189 try gz.instructions.append(gpa, new_index);
13190 }
13191};13140};
1319213141
13193/// This can only be for short-lived references; the memory becomes invalidated13142/// This can only be for short-lived references; the memory becomes invalidated
src/Liveness.zig-4
...@@ -329,8 +329,6 @@ pub fn categorizeOperand(...@@ -329,8 +329,6 @@ pub fn categorizeOperand(
329 .dbg_stmt,329 .dbg_stmt,
330 .dbg_inline_begin,330 .dbg_inline_begin,
331 .dbg_inline_end,331 .dbg_inline_end,
332 .dbg_block_begin,
333 .dbg_block_end,
334 .unreach,332 .unreach,
335 .ret_addr,333 .ret_addr,
336 .frame_addr,334 .frame_addr,
...@@ -967,8 +965,6 @@ fn analyzeInst(...@@ -967,8 +965,6 @@ fn analyzeInst(
967 .dbg_stmt,965 .dbg_stmt,
968 .dbg_inline_begin,966 .dbg_inline_begin,
969 .dbg_inline_end,967 .dbg_inline_end,
970 .dbg_block_begin,
971 .dbg_block_end,
972 .fence,968 .fence,
973 .ret_addr,969 .ret_addr,
974 .frame_addr,970 .frame_addr,
src/Liveness/Verify.zig-2
...@@ -48,8 +48,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -48,8 +48,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
48 .dbg_stmt,48 .dbg_stmt,
49 .dbg_inline_begin,49 .dbg_inline_begin,
50 .dbg_inline_end,50 .dbg_inline_end,
51 .dbg_block_begin,
52 .dbg_block_end,
53 .fence,51 .fence,
54 .ret_addr,52 .ret_addr,
55 .frame_addr,53 .frame_addr,
src/Sema.zig+148-124
...@@ -364,6 +364,12 @@ pub const Block = struct {...@@ -364,6 +364,12 @@ pub const Block = struct {
364364
365 c_import_buf: ?*std.ArrayList(u8) = null,365 c_import_buf: ?*std.ArrayList(u8) = null,
366366
367 /// If not `null`, this boolean is set when a `dbg_var_ptr` or `dbg_var_val`
368 /// instruction is emitted. It signals that the innermost lexically
369 /// enclosing `block`/`block_inline` should be translated into a real AIR
370 /// `block` in order for codegen to match lexical scoping for debug vars.
371 need_debug_scope: ?*bool = null,
372
367 const ComptimeReason = union(enum) {373 const ComptimeReason = union(enum) {
368 c_import: struct {374 c_import: struct {
369 block: *Block,375 block: *Block,
...@@ -482,6 +488,7 @@ pub const Block = struct {...@@ -482,6 +488,7 @@ pub const Block = struct {
482 .float_mode = parent.float_mode,488 .float_mode = parent.float_mode,
483 .c_import_buf = parent.c_import_buf,489 .c_import_buf = parent.c_import_buf,
484 .error_return_trace_index = parent.error_return_trace_index,490 .error_return_trace_index = parent.error_return_trace_index,
491 .need_debug_scope = parent.need_debug_scope,
485 };492 };
486 }493 }
487494
...@@ -986,8 +993,6 @@ fn analyzeBodyInner(...@@ -986,8 +993,6 @@ fn analyzeBodyInner(
986 crash_info.push();993 crash_info.push();
987 defer crash_info.pop();994 defer crash_info.pop();
988995
989 var dbg_block_begins: u32 = 0;
990
991 // We use a while (true) loop here to avoid a redundant way of breaking out of996 // We use a while (true) loop here to avoid a redundant way of breaking out of
992 // the loop. The only way to break out of the loop is with a `noreturn`997 // the loop. The only way to break out of the loop is with a `noreturn`
993 // instruction.998 // instruction.
...@@ -1332,18 +1337,6 @@ fn analyzeBodyInner(...@@ -1332,18 +1337,6 @@ fn analyzeBodyInner(
1332 i += 1;1337 i += 1;
1333 continue;1338 continue;
1334 },1339 },
1335 .dbg_block_begin => {
1336 dbg_block_begins += 1;
1337 try zirDbgBlockBegin(block);
1338 i += 1;
1339 continue;
1340 },
1341 .dbg_block_end => {
1342 dbg_block_begins -= 1;
1343 try zirDbgBlockEnd(block);
1344 i += 1;
1345 continue;
1346 },
1347 .ensure_err_union_payload_void => {1340 .ensure_err_union_payload_void => {
1348 try sema.zirEnsureErrUnionPayloadVoid(block, inst);1341 try sema.zirEnsureErrUnionPayloadVoid(block, inst);
1349 i += 1;1342 i += 1;
...@@ -1641,10 +1634,12 @@ fn analyzeBodyInner(...@@ -1641,10 +1634,12 @@ fn analyzeBodyInner(
1641 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);1634 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);
1642 const gpa = sema.gpa;1635 const gpa = sema.gpa;
16431636
1644 const opt_break_data = b: {1637 const opt_break_data, const need_debug_scope = b: {
1645 // Create a temporary child block so that this inline block is properly1638 // Create a temporary child block so that this inline block is properly
1646 // labeled for any .restore_err_ret_index instructions1639 // labeled for any .restore_err_ret_index instructions
1647 var child_block = block.makeSubBlock();1640 var child_block = block.makeSubBlock();
1641 var need_debug_scope = false;
1642 child_block.need_debug_scope = &need_debug_scope;
16481643
1649 // If this block contains a function prototype, we need to reset the1644 // If this block contains a function prototype, we need to reset the
1650 // current list of parameters and restore it later.1645 // current list of parameters and restore it later.
...@@ -1665,7 +1660,11 @@ fn analyzeBodyInner(...@@ -1665,7 +1660,11 @@ fn analyzeBodyInner(
1665 child_block.instructions = block.instructions;1660 child_block.instructions = block.instructions;
1666 defer block.instructions = child_block.instructions;1661 defer block.instructions = child_block.instructions;
16671662
1668 break :b try sema.analyzeBodyBreak(&child_block, inline_body);1663 const result = try sema.analyzeBodyBreak(&child_block, inline_body);
1664 if (need_debug_scope) {
1665 _ = try sema.ensurePostHoc(block, inst);
1666 }
1667 break :b .{ result, need_debug_scope };
1669 };1668 };
16701669
1671 // A runtime conditional branch that needs a post-hoc block to be1670 // A runtime conditional branch that needs a post-hoc block to be
...@@ -1686,28 +1685,22 @@ fn analyzeBodyInner(...@@ -1686,28 +1685,22 @@ fn analyzeBodyInner(
1686 // since it crosses a runtime branch.1685 // since it crosses a runtime branch.
1687 // It may pass through our currently being analyzed block_inline or it1686 // It may pass through our currently being analyzed block_inline or it
1688 // may point directly to it. In the latter case, this modifies the1687 // may point directly to it. In the latter case, this modifies the
1689 // block that we are about to look up in the post_hoc_blocks map below.1688 // block that we looked up in the post_hoc_blocks map above.
1690 try sema.addRuntimeBreak(block, break_data);1689 try sema.addRuntimeBreak(block, break_data);
1691 } else {
1692 // Here the comptime control flow ends with noreturn; however
1693 // we have runtime control flow continuing after this block.
1694 // This branch is therefore handled by the `i += 1; continue;`
1695 // logic below.
1696 }1690 }
16971691
1698 try labeled_block.block.instructions.appendSlice(gpa, block.instructions.items[block_index..]);1692 try labeled_block.block.instructions.appendSlice(gpa, block.instructions.items[block_index..]);
1699 block.instructions.items.len = block_index;1693 block.instructions.items.len = block_index;
17001694
1701 const block_result = try sema.analyzeBlockBody(block, inst_data.src(), &labeled_block.block, &labeled_block.label.merges);1695 const block_result = try sema.analyzeBlockBody(block, inst_data.src(), &labeled_block.block, &labeled_block.label.merges, need_debug_scope);
1702 {1696 {
1703 // Destroy the ad-hoc block entry so that it does not interfere with1697 // Destroy the ad-hoc block entry so that it does not interfere with
1704 // the next iteration of comptime control flow, if any.1698 // the next iteration of comptime control flow, if any.
1705 labeled_block.destroy(gpa);1699 labeled_block.destroy(gpa);
1706 assert(sema.post_hoc_blocks.remove(new_block_inst));1700 assert(sema.post_hoc_blocks.remove(new_block_inst));
1707 }1701 }
1708 map.putAssumeCapacity(inst, block_result);1702
1709 i += 1;1703 break :blk block_result;
1710 continue;
1711 }1704 }
17121705
1713 const break_data = opt_break_data orelse break always_noreturn;1706 const break_data = opt_break_data orelse break always_noreturn;
...@@ -1860,19 +1853,6 @@ fn analyzeBodyInner(...@@ -1860,19 +1853,6 @@ fn analyzeBodyInner(
1860 i += 1;1853 i += 1;
1861 };1854 };
18621855
1863 // balance out dbg_block_begins in case of early noreturn
1864 if (!block.is_comptime and !block.ownerModule().strip) {
1865 const noreturn_inst = block.instructions.popOrNull();
1866 while (dbg_block_begins > 0) {
1867 dbg_block_begins -= 1;
1868 _ = try block.addInst(.{
1869 .tag = .dbg_block_end,
1870 .data = undefined,
1871 });
1872 }
1873 if (noreturn_inst) |some| try block.instructions.append(sema.gpa, some);
1874 }
1875
1876 // We may have overwritten the capture scope due to a `repeat` instruction where1856 // We may have overwritten the capture scope due to a `repeat` instruction where
1877 // the body had a capture; restore it now.1857 // the body had a capture; restore it now.
1878 block.wip_capture_scope = parent_capture_scope;1858 block.wip_capture_scope = parent_capture_scope;
...@@ -5757,7 +5737,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError...@@ -5757,7 +5737,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
5757 );5737 );
5758 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(loop_block.instructions.items));5738 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(loop_block.instructions.items));
5759 }5739 }
5760 return sema.analyzeBlockBody(parent_block, src, &child_block, merges);5740 return sema.analyzeBlockBody(parent_block, src, &child_block, merges, false);
5761}5741}
57625742
5763fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5743fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -5945,13 +5925,31 @@ fn resolveBlockBody(...@@ -5945,13 +5925,31 @@ fn resolveBlockBody(
5945 if (child_block.is_comptime) {5925 if (child_block.is_comptime) {
5946 return sema.resolveBody(child_block, body, body_inst);5926 return sema.resolveBody(child_block, body, body_inst);
5947 } else {5927 } else {
5928 var need_debug_scope = false;
5929 child_block.need_debug_scope = &need_debug_scope;
5948 if (sema.analyzeBodyInner(child_block, body)) |_| {5930 if (sema.analyzeBodyInner(child_block, body)) |_| {
5949 return sema.analyzeBlockBody(parent_block, src, child_block, merges);5931 return sema.analyzeBlockBody(parent_block, src, child_block, merges, need_debug_scope);
5950 } else |err| switch (err) {5932 } else |err| switch (err) {
5951 error.ComptimeBreak => {5933 error.ComptimeBreak => {
5952 // Comptime control flow is happening, however child_block may still contain5934 // Comptime control flow is happening, however child_block may still contain
5953 // runtime instructions which need to be copied to the parent block.5935 // runtime instructions which need to be copied to the parent block.
5954 try parent_block.instructions.appendSlice(sema.gpa, child_block.instructions.items);5936 if (need_debug_scope and child_block.instructions.items.len > 0) {
5937 // We need a runtime block for scoping reasons.
5938 _ = try child_block.addBr(merges.block_inst, .void_value);
5939 try parent_block.instructions.append(sema.gpa, merges.block_inst);
5940 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Block).Struct.fields.len +
5941 child_block.instructions.items.len);
5942 sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{
5943 .ty = .void_type,
5944 .payload = sema.addExtraAssumeCapacity(Air.Block{
5945 .body_len = @intCast(child_block.instructions.items.len),
5946 }),
5947 } };
5948 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items));
5949 } else {
5950 // We can copy instructions directly to the parent block.
5951 try parent_block.instructions.appendSlice(sema.gpa, child_block.instructions.items);
5952 }
59555953
5956 const break_inst = sema.comptime_break_inst;5954 const break_inst = sema.comptime_break_inst;
5957 const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break";5955 const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break";
...@@ -5973,6 +5971,7 @@ fn analyzeBlockBody(...@@ -5973,6 +5971,7 @@ fn analyzeBlockBody(
5973 src: LazySrcLoc,5971 src: LazySrcLoc,
5974 child_block: *Block,5972 child_block: *Block,
5975 merges: *Block.Merges,5973 merges: *Block.Merges,
5974 need_debug_scope: bool,
5976) CompileError!Air.Inst.Ref {5975) CompileError!Air.Inst.Ref {
5977 const tracy = trace(@src());5976 const tracy = trace(@src());
5978 defer tracy.end();5977 defer tracy.end();
...@@ -5987,25 +5986,57 @@ fn analyzeBlockBody(...@@ -5987,25 +5986,57 @@ fn analyzeBlockBody(
5987 if (merges.results.items.len == 0) {5986 if (merges.results.items.len == 0) {
5988 // No need for a block instruction. We can put the new instructions5987 // No need for a block instruction. We can put the new instructions
5989 // directly into the parent block.5988 // directly into the parent block.
5989 if (need_debug_scope) {
5990 // The code following this block is unreachable, as the block has no
5991 // merges, so we don't necessarily need to emit this as an AIR block.
5992 // However, we need a block *somewhere* to make the scoping correct,
5993 // so forward this request to the parent block.
5994 if (parent_block.need_debug_scope) |ptr| ptr.* = true;
5995 }
5990 try parent_block.instructions.appendSlice(gpa, child_block.instructions.items);5996 try parent_block.instructions.appendSlice(gpa, child_block.instructions.items);
5991 return child_block.instructions.items[child_block.instructions.items.len - 1].toRef();5997 return child_block.instructions.items[child_block.instructions.items.len - 1].toRef();
5992 }5998 }
5993 if (merges.results.items.len == 1) {5999 if (merges.results.items.len == 1) {
5994 const last_inst_index = child_block.instructions.items.len - 1;6000 // If the `break` is trailing, we may be able to elide the AIR block here
5995 const last_inst = child_block.instructions.items[last_inst_index];6001 // by appending the new instructions directly to the parent block.
5996 if (sema.getBreakBlock(last_inst)) |br_block| {6002 if (!need_debug_scope) {
5997 if (br_block == merges.block_inst) {6003 const last_inst_index = child_block.instructions.items.len - 1;
5998 // No need for a block instruction. We can put the new instructions directly6004 const last_inst = child_block.instructions.items[last_inst_index];
5999 // into the parent block. Here we omit the break instruction.6005 if (sema.getBreakBlock(last_inst)) |br_block| {
6000 const without_break = child_block.instructions.items[0..last_inst_index];6006 if (br_block == merges.block_inst) {
6001 try parent_block.instructions.appendSlice(gpa, without_break);6007 // Great, the last instruction is the break! Put the instructions
6002 return merges.results.items[0];6008 // directly into the parent block.
6003 }6009 try parent_block.instructions.appendSlice(gpa, child_block.instructions.items[0..last_inst_index]);
6010 return merges.results.items[0];
6011 }
6012 }
6013 }
6014 // Okay, we need a runtime block. If the value is comptime-known, the
6015 // block should just return void, and we return the merge result
6016 // directly. Otherwise, we can defer to the logic below.
6017 if (try sema.resolveValue(merges.results.items[0])) |result_val| {
6018 // Create a block containing all instruction from the body.
6019 try parent_block.instructions.append(gpa, merges.block_inst);
6020 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
6021 child_block.instructions.items.len);
6022 sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{
6023 .ty = .void_type,
6024 .payload = sema.addExtraAssumeCapacity(Air.Block{
6025 .body_len = @intCast(child_block.instructions.items.len),
6026 }),
6027 } };
6028 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items));
6029 // Rewrite the break to just give value {}; the value is
6030 // comptime-known and will be returned directly.
6031 sema.air_instructions.items(.data)[@intFromEnum(merges.br_list.items[0])].br.operand = .void_value;
6032 return Air.internedToRef(result_val.toIntern());
6004 }6033 }
6005 }6034 }
6006 // It is impossible to have the number of results be > 1 in a comptime scope.6035 // It is impossible to have the number of results be > 1 in a comptime scope.
6007 assert(!child_block.is_comptime); // Should already got a compile error in the condbr condition.6036 assert(!child_block.is_comptime); // Should already got a compile error in the condbr condition.
60086037
6038 // Note that we'll always create an AIR block here, so `need_debug_scope` is irrelevant.
6039
6009 // Need to set the type and emit the Block instruction. This allows machine code generation6040 // Need to set the type and emit the Block instruction. This allows machine code generation
6010 // to emit a jump instruction to after the block when it encounters the break.6041 // to emit a jump instruction to after the block when it encounters the break.
6011 try parent_block.instructions.append(gpa, merges.block_inst);6042 try parent_block.instructions.append(gpa, merges.block_inst);
...@@ -6383,24 +6414,6 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi...@@ -6383,24 +6414,6 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi
6383 });6414 });
6384}6415}
63856416
6386fn zirDbgBlockBegin(block: *Block) CompileError!void {
6387 if (block.is_comptime or block.ownerModule().strip) return;
6388
6389 _ = try block.addInst(.{
6390 .tag = .dbg_block_begin,
6391 .data = undefined,
6392 });
6393}
6394
6395fn zirDbgBlockEnd(block: *Block) CompileError!void {
6396 if (block.is_comptime or block.ownerModule().strip) return;
6397
6398 _ = try block.addInst(.{
6399 .tag = .dbg_block_end,
6400 .data = undefined,
6401 });
6402}
6403
6404fn zirDbgVar(6417fn zirDbgVar(
6405 sema: *Sema,6418 sema: *Sema,
6406 block: *Block,6419 block: *Block,
...@@ -6432,6 +6445,15 @@ fn addDbgVar(...@@ -6432,6 +6445,15 @@ fn addDbgVar(
6432 if (try sema.typeRequiresComptime(val_ty)) return;6445 if (try sema.typeRequiresComptime(val_ty)) return;
6433 if (!(try sema.typeHasRuntimeBits(val_ty))) return;6446 if (!(try sema.typeHasRuntimeBits(val_ty))) return;
64346447
6448 // To ensure the lexical scoping is known to backends, this alloc must be
6449 // within a real runtime block. We set a flag which communicates information
6450 // to the closest lexically enclosing block:
6451 // * If it is a `block_inline`, communicates to logic in `analyzeBodyInner`
6452 // to create a post-hoc block.
6453 // * Otherwise, communicates to logic in `resolveBlockBody` to create a
6454 // real `block` instruction.
6455 if (block.need_debug_scope) |ptr| ptr.* = true;
6456
6435 try sema.queueFullTypeResolution(operand_ty);6457 try sema.queueFullTypeResolution(operand_ty);
64366458
6437 // Add the name to the AIR.6459 // Add the name to the AIR.
...@@ -7585,7 +7607,7 @@ fn analyzeCall(...@@ -7585,7 +7607,7 @@ fn analyzeCall(
7585 error.ComptimeReturn => break :result inlining.comptime_result,7607 error.ComptimeReturn => break :result inlining.comptime_result,
7586 else => |e| return e,7608 else => |e| return e,
7587 };7609 };
7588 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges);7610 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges, false);
7589 };7611 };
75907612
7591 if (!is_comptime_call and !block.is_typeof and7613 if (!is_comptime_call and !block.is_typeof and
...@@ -11528,7 +11550,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11528,7 +11550,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11528 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(true_instructions));11550 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(true_instructions));
11529 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items));11551 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items));
1153011552
11531 return sema.analyzeBlockBody(block, main_src, &child_block, merges);11553 return sema.analyzeBlockBody(block, main_src, &child_block, merges, false);
11532}11554}
1153311555
11534fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_ref: bool) CompileError!Air.Inst.Ref {11556fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_ref: bool) CompileError!Air.Inst.Ref {
...@@ -12150,7 +12172,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -12150,7 +12172,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
12150 false,12172 false,
12151 );12173 );
1215212174
12153 return sema.analyzeBlockBody(block, src, &child_block, merges);12175 return sema.analyzeBlockBody(block, src, &child_block, merges, false);
12154}12176}
1215512177
12156const SpecialProng = struct {12178const SpecialProng = struct {
...@@ -13163,8 +13185,6 @@ fn validateErrSetSwitch(...@@ -13163,8 +13185,6 @@ fn validateErrSetSwitch(
13163 const tags = sema.code.instructions.items(.tag);13185 const tags = sema.code.instructions.items(.tag);
13164 const datas = sema.code.instructions.items(.data);13186 const datas = sema.code.instructions.items(.data);
13165 for (else_case.body) |else_inst| switch (tags[@intFromEnum(else_inst)]) {13187 for (else_case.body) |else_inst| switch (tags[@intFromEnum(else_inst)]) {
13166 .dbg_block_begin,
13167 .dbg_block_end,
13168 .dbg_stmt,13188 .dbg_stmt,
13169 .dbg_var_val,13189 .dbg_var_val,
13170 .ret_type,13190 .ret_type,
...@@ -13416,8 +13436,6 @@ fn maybeErrorUnwrap(...@@ -13416,8 +13436,6 @@ fn maybeErrorUnwrap(
13416 .@"unreachable" => if (!block.wantSafety()) return false,13436 .@"unreachable" => if (!block.wantSafety()) return false,
13417 .err_union_code => if (!allow_err_code_inst) return false,13437 .err_union_code => if (!allow_err_code_inst) return false,
13418 .save_err_ret_index,13438 .save_err_ret_index,
13419 .dbg_block_begin,
13420 .dbg_block_end,
13421 .dbg_stmt,13439 .dbg_stmt,
13422 .str,13440 .str,
13423 .as_node,13441 .as_node,
...@@ -13430,10 +13448,7 @@ fn maybeErrorUnwrap(...@@ -13430,10 +13448,7 @@ fn maybeErrorUnwrap(
1343013448
13431 for (body) |inst| {13449 for (body) |inst| {
13432 const air_inst = switch (tags[@intFromEnum(inst)]) {13450 const air_inst = switch (tags[@intFromEnum(inst)]) {
13433 .dbg_block_begin,13451 .err_union_code => continue,
13434 .dbg_block_end,
13435 .err_union_code,
13436 => continue,
13437 .dbg_stmt => {13452 .dbg_stmt => {
13438 try sema.zirDbgStmt(block, inst);13453 try sema.zirDbgStmt(block, inst);
13439 continue;13454 continue;
...@@ -13499,8 +13514,6 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I...@@ -13499,8 +13514,6 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I
13499 const tags = sema.code.instructions.items(.tag);13514 const tags = sema.code.instructions.items(.tag);
13500 const inst = for (body) |inst| {13515 const inst = for (body) |inst| {
13501 switch (tags[@intFromEnum(inst)]) {13516 switch (tags[@intFromEnum(inst)]) {
13502 .dbg_block_begin,
13503 .dbg_block_end,
13504 .dbg_stmt,13517 .dbg_stmt,
13505 .save_err_ret_index,13518 .save_err_ret_index,
13506 => {},13519 => {},
...@@ -19092,55 +19105,64 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -19092,55 +19105,64 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
19092 return try_inst;19105 return try_inst;
19093}19106}
1909419107
19108fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*LabeledBlock {
19109 const gop = sema.inst_map.getOrPutAssumeCapacity(dest_block);
19110 if (gop.found_existing) existing: {
19111 // This may be a *result* from an earlier iteration of an inline loop.
19112 // In this case, there will not be a post-hoc block entry, and we can
19113 // continue with the logic below.
19114 const new_block_inst = gop.value_ptr.*.toIndex() orelse break :existing;
19115 return sema.post_hoc_blocks.get(new_block_inst) orelse break :existing;
19116 }
19117
19118 try sema.post_hoc_blocks.ensureUnusedCapacity(sema.gpa, 1);
19119
19120 const new_block_inst: Air.Inst.Index = @enumFromInt(sema.air_instructions.len);
19121 gop.value_ptr.* = new_block_inst.toRef();
19122 try sema.air_instructions.append(sema.gpa, .{
19123 .tag = .block,
19124 .data = undefined,
19125 });
19126 const labeled_block = try sema.gpa.create(LabeledBlock);
19127 labeled_block.* = .{
19128 .label = .{
19129 .zir_block = dest_block,
19130 .merges = .{
19131 .src_locs = .{},
19132 .results = .{},
19133 .br_list = .{},
19134 .block_inst = new_block_inst,
19135 },
19136 },
19137 .block = .{
19138 .parent = block,
19139 .sema = sema,
19140 .src_decl = block.src_decl,
19141 .namespace = block.namespace,
19142 .wip_capture_scope = block.wip_capture_scope,
19143 .instructions = .{},
19144 .label = &labeled_block.label,
19145 .inlining = block.inlining,
19146 .is_comptime = block.is_comptime,
19147 },
19148 };
19149 sema.post_hoc_blocks.putAssumeCapacityNoClobber(new_block_inst, labeled_block);
19150 return labeled_block;
19151}
19152
19095// A `break` statement is inside a runtime condition, but trying to19153// A `break` statement is inside a runtime condition, but trying to
19096// break from an inline loop. In such case we must convert it to19154// break from an inline loop. In such case we must convert it to
19097// a runtime break.19155// a runtime break.
19098fn addRuntimeBreak(sema: *Sema, child_block: *Block, break_data: BreakData) !void {19156fn addRuntimeBreak(sema: *Sema, child_block: *Block, break_data: BreakData) !void {
19099 const gop = sema.inst_map.getOrPutAssumeCapacity(break_data.block_inst);19157 const labeled_block = try sema.ensurePostHoc(child_block, break_data.block_inst);
19100 const labeled_block = if (!gop.found_existing) blk: {
19101 try sema.post_hoc_blocks.ensureUnusedCapacity(sema.gpa, 1);
19102
19103 const new_block_inst: Air.Inst.Index = @enumFromInt(sema.air_instructions.len);
19104 gop.value_ptr.* = new_block_inst.toRef();
19105 try sema.air_instructions.append(sema.gpa, .{
19106 .tag = .block,
19107 .data = undefined,
19108 });
19109 const labeled_block = try sema.gpa.create(LabeledBlock);
19110 labeled_block.* = .{
19111 .label = .{
19112 .zir_block = break_data.block_inst,
19113 .merges = .{
19114 .src_locs = .{},
19115 .results = .{},
19116 .br_list = .{},
19117 .block_inst = new_block_inst,
19118 },
19119 },
19120 .block = .{
19121 .parent = child_block,
19122 .sema = sema,
19123 .src_decl = child_block.src_decl,
19124 .namespace = child_block.namespace,
19125 .wip_capture_scope = child_block.wip_capture_scope,
19126 .instructions = .{},
19127 .label = &labeled_block.label,
19128 .inlining = child_block.inlining,
19129 .is_comptime = child_block.is_comptime,
19130 },
19131 };
19132 sema.post_hoc_blocks.putAssumeCapacityNoClobber(new_block_inst, labeled_block);
19133 break :blk labeled_block;
19134 } else blk: {
19135 const new_block_inst = gop.value_ptr.*.toIndex().?;
19136 const labeled_block = sema.post_hoc_blocks.get(new_block_inst).?;
19137 break :blk labeled_block;
19138 };
1913919158
19140 const operand = try sema.resolveInst(break_data.operand);19159 const operand = try sema.resolveInst(break_data.operand);
19141 const br_ref = try child_block.addBr(labeled_block.label.merges.block_inst, operand);19160 const br_ref = try child_block.addBr(labeled_block.label.merges.block_inst, operand);
19161
19142 try labeled_block.label.merges.results.append(sema.gpa, operand);19162 try labeled_block.label.merges.results.append(sema.gpa, operand);
19143 try labeled_block.label.merges.br_list.append(sema.gpa, br_ref.toIndex().?);19163 try labeled_block.label.merges.br_list.append(sema.gpa, br_ref.toIndex().?);
19164 try labeled_block.label.merges.src_locs.append(sema.gpa, null);
19165
19144 labeled_block.block.runtime_index.increment();19166 labeled_block.block.runtime_index.increment();
19145 if (labeled_block.block.runtime_cond == null and labeled_block.block.runtime_loop == null) {19167 if (labeled_block.block.runtime_cond == null and labeled_block.block.runtime_loop == null) {
19146 labeled_block.block.runtime_cond = child_block.runtime_cond orelse child_block.runtime_loop;19168 labeled_block.block.runtime_cond = child_block.runtime_cond orelse child_block.runtime_loop;
...@@ -19481,8 +19503,10 @@ fn analyzeRet(...@@ -19481,8 +19503,10 @@ fn analyzeRet(
19481 return error.ComptimeReturn;19503 return error.ComptimeReturn;
19482 }19504 }
19483 // We are inlining a function call; rewrite the `ret` as a `break`.19505 // We are inlining a function call; rewrite the `ret` as a `break`.
19506 const br_inst = try block.addBr(inlining.merges.block_inst, operand);
19484 try inlining.merges.results.append(sema.gpa, operand);19507 try inlining.merges.results.append(sema.gpa, operand);
19485 _ = try block.addBr(inlining.merges.block_inst, operand);19508 try inlining.merges.br_list.append(sema.gpa, br_inst.toIndex().?);
19509 try inlining.merges.src_locs.append(sema.gpa, operand_src);
19486 return always_noreturn;19510 return always_noreturn;
19487 } else if (block.is_comptime) {19511 } else if (block.is_comptime) {
19488 return sema.fail(block, src, "function called at runtime cannot return value at comptime", .{});19512 return sema.fail(block, src, "function called at runtime cannot return value at comptime", .{});
src/Zir.zig-10
...@@ -392,10 +392,6 @@ pub const Inst = struct {...@@ -392,10 +392,6 @@ pub const Inst = struct {
392 /// Same as `dbg_var_ptr` but the local is always a const and the operand392 /// Same as `dbg_var_ptr` but the local is always a const and the operand
393 /// is the local's value.393 /// is the local's value.
394 dbg_var_val,394 dbg_var_val,
395 /// Marks the beginning of a semantic scope for debug info variables.
396 dbg_block_begin,
397 /// Marks the end of a semantic scope for debug info variables.
398 dbg_block_end,
399 /// Uses a name to identify a Decl and takes a pointer to it.395 /// Uses a name to identify a Decl and takes a pointer to it.
400 /// Uses the `str_tok` union field.396 /// Uses the `str_tok` union field.
401 decl_ref,397 decl_ref,
...@@ -1107,8 +1103,6 @@ pub const Inst = struct {...@@ -1107,8 +1103,6 @@ pub const Inst = struct {
1107 .dbg_stmt,1103 .dbg_stmt,
1108 .dbg_var_ptr,1104 .dbg_var_ptr,
1109 .dbg_var_val,1105 .dbg_var_val,
1110 .dbg_block_begin,
1111 .dbg_block_end,
1112 .decl_ref,1106 .decl_ref,
1113 .decl_val,1107 .decl_val,
1114 .load,1108 .load,
...@@ -1335,8 +1329,6 @@ pub const Inst = struct {...@@ -1335,8 +1329,6 @@ pub const Inst = struct {
1335 .dbg_stmt,1329 .dbg_stmt,
1336 .dbg_var_ptr,1330 .dbg_var_ptr,
1337 .dbg_var_val,1331 .dbg_var_val,
1338 .dbg_block_begin,
1339 .dbg_block_end,
1340 .ensure_result_used,1332 .ensure_result_used,
1341 .ensure_result_non_error,1333 .ensure_result_non_error,
1342 .ensure_err_union_payload_void,1334 .ensure_err_union_payload_void,
...@@ -1663,8 +1655,6 @@ pub const Inst = struct {...@@ -1663,8 +1655,6 @@ pub const Inst = struct {
1663 .dbg_stmt = .dbg_stmt,1655 .dbg_stmt = .dbg_stmt,
1664 .dbg_var_ptr = .str_op,1656 .dbg_var_ptr = .str_op,
1665 .dbg_var_val = .str_op,1657 .dbg_var_val = .str_op,
1666 .dbg_block_begin = .tok,
1667 .dbg_block_end = .tok,
1668 .decl_ref = .str_tok,1658 .decl_ref = .str_tok,
1669 .decl_val = .str_tok,1659 .decl_val = .str_tok,
1670 .load = .un_node,1660 .load = .un_node,
src/arch/aarch64/CodeGen.zig+1-9
...@@ -813,10 +813,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -813,10 +813,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
813 .dbg_inline_end,813 .dbg_inline_end,
814 => try self.airDbgInline(inst),814 => try self.airDbgInline(inst),
815815
816 .dbg_block_begin,
817 .dbg_block_end,
818 => try self.airDbgBlock(inst),
819
820 .call => try self.airCall(inst, .auto),816 .call => try self.airCall(inst, .auto),
821 .call_always_tail => try self.airCall(inst, .always_tail),817 .call_always_tail => try self.airCall(inst, .always_tail),
822 .call_never_tail => try self.airCall(inst, .never_tail),818 .call_never_tail => try self.airCall(inst, .never_tail),
...@@ -4634,11 +4630,6 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {...@@ -4634,11 +4630,6 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
4634 return self.finishAir(inst, .dead, .{ .none, .none, .none });4630 return self.finishAir(inst, .dead, .{ .none, .none, .none });
4635}4631}
46364632
4637fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
4638 // TODO emit debug info lexical block
4639 return self.finishAir(inst, .dead, .{ .none, .none, .none });
4640}
4641
4642fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {4633fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
4643 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;4634 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
4644 const operand = pl_op.operand;4635 const operand = pl_op.operand;
...@@ -5066,6 +5057,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -5066,6 +5057,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
5066 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;5057 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
5067 const extra = self.air.extraData(Air.Block, ty_pl.payload);5058 const extra = self.air.extraData(Air.Block, ty_pl.payload);
5068 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);5059 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);
5060 // TODO emit debug info lexical block
5069 try self.genBody(body);5061 try self.genBody(body);
50705062
5071 // relocations for `br` instructions5063 // relocations for `br` instructions
src/arch/arm/CodeGen.zig+1-9
...@@ -799,10 +799,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -799,10 +799,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
799 .dbg_inline_end,799 .dbg_inline_end,
800 => try self.airDbgInline(inst),800 => try self.airDbgInline(inst),
801801
802 .dbg_block_begin,
803 .dbg_block_end,
804 => try self.airDbgBlock(inst),
805
806 .call => try self.airCall(inst, .auto),802 .call => try self.airCall(inst, .auto),
807 .call_always_tail => try self.airCall(inst, .always_tail),803 .call_always_tail => try self.airCall(inst, .always_tail),
808 .call_never_tail => try self.airCall(inst, .never_tail),804 .call_never_tail => try self.airCall(inst, .never_tail),
...@@ -4587,11 +4583,6 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {...@@ -4587,11 +4583,6 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
4587 return self.finishAir(inst, .dead, .{ .none, .none, .none });4583 return self.finishAir(inst, .dead, .{ .none, .none, .none });
4588}4584}
45894585
4590fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
4591 // TODO emit debug info lexical block
4592 return self.finishAir(inst, .dead, .{ .none, .none, .none });
4593}
4594
4595fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {4586fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
4596 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;4587 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
4597 const operand = pl_op.operand;4588 const operand = pl_op.operand;
...@@ -4997,6 +4988,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -4997,6 +4988,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
4997 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;4988 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
4998 const extra = self.air.extraData(Air.Block, ty_pl.payload);4989 const extra = self.air.extraData(Air.Block, ty_pl.payload);
4999 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);4990 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);
4991 // TODO emit debug info lexical block
5000 try self.genBody(body);4992 try self.genBody(body);
50014993
5002 // relocations for `br` instructions4994 // relocations for `br` instructions
src/arch/riscv64/CodeGen.zig+1-9
...@@ -632,10 +632,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -632,10 +632,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
632 .dbg_inline_end,632 .dbg_inline_end,
633 => try self.airDbgInline(inst),633 => try self.airDbgInline(inst),
634634
635 .dbg_block_begin,
636 .dbg_block_end,
637 => try self.airDbgBlock(inst),
638
639 .call => try self.airCall(inst, .auto),635 .call => try self.airCall(inst, .auto),
640 .call_always_tail => try self.airCall(inst, .always_tail),636 .call_always_tail => try self.airCall(inst, .always_tail),
641 .call_never_tail => try self.airCall(inst, .never_tail),637 .call_never_tail => try self.airCall(inst, .never_tail),
...@@ -1894,11 +1890,6 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {...@@ -1894,11 +1890,6 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
1894 return self.finishAir(inst, .dead, .{ .none, .none, .none });1890 return self.finishAir(inst, .dead, .{ .none, .none, .none });
1895}1891}
18961892
1897fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
1898 // TODO emit debug info lexical block
1899 return self.finishAir(inst, .dead, .{ .none, .none, .none });
1900}
1901
1902fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {1893fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
1903 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;1894 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
1904 const name = self.air.nullTerminatedString(pl_op.payload);1895 const name = self.air.nullTerminatedString(pl_op.payload);
...@@ -2084,6 +2075,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -2084,6 +2075,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
2084 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;2075 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
2085 const extra = self.air.extraData(Air.Block, ty_pl.payload);2076 const extra = self.air.extraData(Air.Block, ty_pl.payload);
2086 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);2077 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);
2078 // TODO emit debug info lexical block
2087 try self.genBody(body);2079 try self.genBody(body);
20882080
2089 for (self.blocks.getPtr(inst).?.relocs.items) |reloc| try self.performReloc(reloc);2081 for (self.blocks.getPtr(inst).?.relocs.items) |reloc| try self.performReloc(reloc);
src/arch/sparc64/CodeGen.zig+1-9
...@@ -645,10 +645,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -645,10 +645,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
645 .dbg_inline_end,645 .dbg_inline_end,
646 => try self.airDbgInline(inst),646 => try self.airDbgInline(inst),
647647
648 .dbg_block_begin,
649 .dbg_block_end,
650 => try self.airDbgBlock(inst),
651
652 .call => try self.airCall(inst, .auto),648 .call => try self.airCall(inst, .auto),
653 .call_always_tail => try self.airCall(inst, .always_tail),649 .call_always_tail => try self.airCall(inst, .always_tail),
654 .call_never_tail => try self.airCall(inst, .never_tail),650 .call_never_tail => try self.airCall(inst, .never_tail),
...@@ -1146,6 +1142,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -1146,6 +1142,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
1146 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;1142 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
1147 const extra = self.air.extraData(Air.Block, ty_pl.payload);1143 const extra = self.air.extraData(Air.Block, ty_pl.payload);
1148 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);1144 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);
1145 // TODO emit debug info lexical block
1149 try self.genBody(body);1146 try self.genBody(body);
11501147
1151 // relocations for `bpcc` instructions1148 // relocations for `bpcc` instructions
...@@ -1655,11 +1652,6 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {...@@ -1655,11 +1652,6 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
1655 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1652 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1656}1653}
16571654
1658fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
1659 // TODO emit debug info lexical block
1660 return self.finishAir(inst, .dead, .{ .none, .none, .none });
1661}
1662
1663fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {1655fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
1664 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;1656 const ty_fn = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_fn;
1665 const mod = self.bin_file.comp.module.?;1657 const mod = self.bin_file.comp.module.?;
src/arch/wasm/CodeGen.zig-2
...@@ -1913,8 +1913,6 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1913,8 +1913,6 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1913 // TODO1913 // TODO
1914 .dbg_inline_begin,1914 .dbg_inline_begin,
1915 .dbg_inline_end,1915 .dbg_inline_end,
1916 .dbg_block_begin,
1917 .dbg_block_end,
1918 => func.finishAir(inst, .none, &.{}),1916 => func.finishAir(inst, .none, &.{}),
19191917
1920 .dbg_var_ptr => func.airDbgVar(inst, true),1918 .dbg_var_ptr => func.airDbgVar(inst, true),
src/arch/x86_64/CodeGen.zig+1-10
...@@ -2106,10 +2106,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -2106,10 +2106,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
2106 .dbg_inline_end,2106 .dbg_inline_end,
2107 => try self.airDbgInline(inst),2107 => try self.airDbgInline(inst),
21082108
2109 .dbg_block_begin,
2110 .dbg_block_end,
2111 => try self.airDbgBlock(inst),
2112
2113 .call => try self.airCall(inst, .auto),2109 .call => try self.airCall(inst, .auto),
2114 .call_always_tail => try self.airCall(inst, .always_tail),2110 .call_always_tail => try self.airCall(inst, .always_tail),
2115 .call_never_tail => try self.airCall(inst, .never_tail),2111 .call_never_tail => try self.airCall(inst, .never_tail),
...@@ -12976,12 +12972,6 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {...@@ -12976,12 +12972,6 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
12976 self.finishAirBookkeeping();12972 self.finishAirBookkeeping();
12977}12973}
1297812974
12979fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
12980 _ = inst;
12981 // TODO emit debug info lexical block
12982 self.finishAirBookkeeping();
12983}
12984
12985fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {12975fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
12986 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;12976 const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
12987 const operand = pl_op.operand;12977 const operand = pl_op.operand;
...@@ -13428,6 +13418,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -13428,6 +13418,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
13428 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;13418 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
13429 const extra = self.air.extraData(Air.Block, ty_pl.payload);13419 const extra = self.air.extraData(Air.Block, ty_pl.payload);
13430 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);13420 const body: []const Air.Inst.Index = @ptrCast(self.air.extra[extra.end..][0..extra.data.body_len]);
13421 // TODO emit debug info lexical block
13431 try self.genBody(body);13422 try self.genBody(body);
1343213423
13433 var block_data = self.blocks.fetchRemove(inst).?;13424 var block_data = self.blocks.fetchRemove(inst).?;
src/codegen/c.zig-4
...@@ -3268,10 +3268,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3268,10 +3268,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3268 .dbg_inline_end,3268 .dbg_inline_end,
3269 => try airDbgInline(f, inst),3269 => try airDbgInline(f, inst),
32703270
3271 .dbg_block_begin,
3272 .dbg_block_end,
3273 => .none,
3274
3275 .call => try airCall(f, inst, .auto),3271 .call => try airCall(f, inst, .auto),
3276 .call_always_tail => .none,3272 .call_always_tail => .none,
3277 .call_never_tail => try airCall(f, inst, .never_tail),3273 .call_never_tail => try airCall(f, inst, .never_tail),
src/codegen/llvm.zig+16-28
...@@ -4768,8 +4768,6 @@ pub const FuncGen = struct {...@@ -4768,8 +4768,6 @@ pub const FuncGen = struct {
4768 scope: Builder.Metadata,4768 scope: Builder.Metadata,
4769 }) = .{},4769 }) = .{},
47704770
4771 scope_stack: std.ArrayListUnmanaged(Builder.Metadata) = .{},
4772
4773 base_line: u32,4771 base_line: u32,
4774 prev_dbg_line: c_uint,4772 prev_dbg_line: c_uint,
4775 prev_dbg_column: c_uint,4773 prev_dbg_column: c_uint,
...@@ -4813,7 +4811,6 @@ pub const FuncGen = struct {...@@ -4813,7 +4811,6 @@ pub const FuncGen = struct {
48134811
4814 fn deinit(self: *FuncGen) void {4812 fn deinit(self: *FuncGen) void {
4815 self.wip.deinit();4813 self.wip.deinit();
4816 self.scope_stack.deinit(self.gpa);
4817 self.inlined.deinit(self.gpa);4814 self.inlined.deinit(self.gpa);
4818 self.func_inst_table.deinit(self.gpa);4815 self.func_inst_table.deinit(self.gpa);
4819 self.blocks.deinit(self.gpa);4816 self.blocks.deinit(self.gpa);
...@@ -5112,8 +5109,6 @@ pub const FuncGen = struct {...@@ -5112,8 +5109,6 @@ pub const FuncGen = struct {
5112 .dbg_stmt => try self.airDbgStmt(inst),5109 .dbg_stmt => try self.airDbgStmt(inst),
5113 .dbg_inline_begin => try self.airDbgInlineBegin(inst),5110 .dbg_inline_begin => try self.airDbgInlineBegin(inst),
5114 .dbg_inline_end => try self.airDbgInlineEnd(inst),5111 .dbg_inline_end => try self.airDbgInlineEnd(inst),
5115 .dbg_block_begin => try self.airDbgBlockBegin(),
5116 .dbg_block_end => try self.airDbgBlockEnd(),
5117 .dbg_var_ptr => try self.airDbgVarPtr(inst),5112 .dbg_var_ptr => try self.airDbgVarPtr(inst),
5118 .dbg_var_val => try self.airDbgVarVal(inst),5113 .dbg_var_val => try self.airDbgVarVal(inst),
51195114
...@@ -5131,6 +5126,19 @@ pub const FuncGen = struct {...@@ -5131,6 +5126,19 @@ pub const FuncGen = struct {
5131 }5126 }
5132 }5127 }
51335128
5129 fn genBodyDebugScope(self: *FuncGen, body: []const Air.Inst.Index) Error!void {
5130 if (self.wip.strip) return self.genBody(body);
5131 const old_scope = self.scope;
5132 self.scope = try self.dg.object.builder.debugLexicalBlock(
5133 old_scope,
5134 self.file,
5135 self.prev_dbg_line,
5136 self.prev_dbg_column,
5137 );
5138 try self.genBody(body);
5139 self.scope = old_scope;
5140 }
5141
5134 pub const CallAttr = enum {5142 pub const CallAttr = enum {
5135 Auto,5143 Auto,
5136 NeverTail,5144 NeverTail,
...@@ -5820,7 +5828,7 @@ pub const FuncGen = struct {...@@ -5820,7 +5828,7 @@ pub const FuncGen = struct {
5820 const inst_ty = self.typeOfIndex(inst);5828 const inst_ty = self.typeOfIndex(inst);
58215829
5822 if (inst_ty.isNoReturn(mod)) {5830 if (inst_ty.isNoReturn(mod)) {
5823 try self.genBody(body);5831 try self.genBodyDebugScope(body);
5824 return .none;5832 return .none;
5825 }5833 }
58265834
...@@ -5836,7 +5844,7 @@ pub const FuncGen = struct {...@@ -5836,7 +5844,7 @@ pub const FuncGen = struct {
5836 });5844 });
5837 defer assert(self.blocks.remove(inst));5845 defer assert(self.blocks.remove(inst));
58385846
5839 try self.genBody(body);5847 try self.genBodyDebugScope(body);
58405848
5841 self.wip.cursor = .{ .block = parent_bb };5849 self.wip.cursor = .{ .block = parent_bb };
58425850
...@@ -6683,26 +6691,6 @@ pub const FuncGen = struct {...@@ -6683,26 +6691,6 @@ pub const FuncGen = struct {
6683 return .none;6691 return .none;
6684 }6692 }
66856693
6686 fn airDbgBlockBegin(self: *FuncGen) Allocator.Error!Builder.Value {
6687 const o = self.dg.object;
6688
6689 try self.scope_stack.append(self.gpa, self.scope);
6690
6691 const old = self.scope;
6692 self.scope = try o.builder.debugLexicalBlock(
6693 old,
6694 self.file,
6695 self.prev_dbg_line,
6696 self.prev_dbg_column,
6697 );
6698 return .none;
6699 }
6700
6701 fn airDbgBlockEnd(self: *FuncGen) !Builder.Value {
6702 self.scope = self.scope_stack.pop();
6703 return .none;
6704 }
6705
6706 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6694 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
6707 const o = self.dg.object;6695 const o = self.dg.object;
6708 const mod = o.module;6696 const mod = o.module;
...@@ -7488,7 +7476,7 @@ pub const FuncGen = struct {...@@ -7488,7 +7476,7 @@ pub const FuncGen = struct {
7488 for (body_tail[1..]) |body_inst| {7476 for (body_tail[1..]) |body_inst| {
7489 switch (air_tags[@intFromEnum(body_inst)]) {7477 switch (air_tags[@intFromEnum(body_inst)]) {
7490 .ret => return true,7478 .ret => return true,
7491 .dbg_stmt, .dbg_block_end => continue,7479 .dbg_stmt => continue,
7492 else => return false,7480 else => return false,
7493 }7481 }
7494 }7482 }
src/codegen/spirv.zig-2
...@@ -2322,8 +2322,6 @@ const DeclGen = struct {...@@ -2322,8 +2322,6 @@ const DeclGen = struct {
2322 .dbg_inline_begin => return self.airDbgInlineBegin(inst),2322 .dbg_inline_begin => return self.airDbgInlineBegin(inst),
2323 .dbg_inline_end => return self.airDbgInlineEnd(inst),2323 .dbg_inline_end => return self.airDbgInlineEnd(inst),
2324 .dbg_var_ptr, .dbg_var_val => return self.airDbgVar(inst),2324 .dbg_var_ptr, .dbg_var_val => return self.airDbgVar(inst),
2325 .dbg_block_begin => return,
2326 .dbg_block_end => return,
23272325
2328 .unwrap_errunion_err => try self.airErrUnionErr(inst),2326 .unwrap_errunion_err => try self.airErrUnionErr(inst),
2329 .unwrap_errunion_payload => try self.airErrUnionPayload(inst),2327 .unwrap_errunion_payload => try self.airErrUnionPayload(inst),
src/print_air.zig-2
...@@ -319,8 +319,6 @@ const Writer = struct {...@@ -319,8 +319,6 @@ const Writer = struct {
319 .cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst),319 .cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst),
320 .vector_store_elem => try w.writeVectorStoreElem(s, inst),320 .vector_store_elem => try w.writeVectorStoreElem(s, inst),
321321
322 .dbg_block_begin, .dbg_block_end => {},
323
324 .work_item_id,322 .work_item_id,
325 .work_group_size,323 .work_group_size,
326 .work_group_id,324 .work_group_id,
src/print_zir.zig-4
...@@ -510,10 +510,6 @@ const Writer = struct {...@@ -510,10 +510,6 @@ const Writer = struct {
510510
511 .dbg_stmt => try self.writeDbgStmt(stream, inst),511 .dbg_stmt => try self.writeDbgStmt(stream, inst),
512512
513 .dbg_block_begin,
514 .dbg_block_end,
515 => try stream.writeAll(")"),
516
517 .closure_get => try self.writeInstNode(stream, inst),513 .closure_get => try self.writeInstNode(stream, inst),
518514
519 .@"defer" => try self.writeDefer(stream, inst),515 .@"defer" => try self.writeDefer(stream, inst),
test/behavior/eval.zig+18
...@@ -1714,3 +1714,21 @@ test "const with specified type initialized with typed array is comptime-known"...@@ -1714,3 +1714,21 @@ test "const with specified type initialized with typed array is comptime-known"
1714 comptime assert(x[1] == 2);1714 comptime assert(x[1] == 2);
1715 comptime assert(x[2] == 3);1715 comptime assert(x[2] == 3);
1716}1716}
1717
1718test "block with comptime-known result but possible runtime exit is comptime-known" {
1719 var t: bool = true;
1720 _ = &t;
1721
1722 const a: comptime_int = a: {
1723 if (!t) return error.TestFailed;
1724 break :a 123;
1725 };
1726
1727 const b: comptime_int = b: {
1728 if (t) break :b 456;
1729 return error.TestFailed;
1730 };
1731
1732 comptime assert(a == 123);
1733 comptime assert(b == 456);
1734}