authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-27 03:25:04+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-02-27 03:25:04+00:00
log8775d8bbcef347640c6ae7e73da02ca6eff1d669
tree3f04f80b042d7baf10074b6f88fabb5693b2b71e
parentf803761e13a65ccbc6a5508f2dc2d7723b010dab
parent59447e53056d8fb6682b79accccffa176d0b44d1
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #19062 from mlugg/dbg-var-blocks

compiler: decide dbg_var scoping based on AIR blocks

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;
...@@ -5762,7 +5742,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError...@@ -5762,7 +5742,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
5762 );5742 );
5763 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(loop_block.instructions.items));5743 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(loop_block.instructions.items));
5764 }5744 }
5765 return sema.analyzeBlockBody(parent_block, src, &child_block, merges);5745 return sema.analyzeBlockBody(parent_block, src, &child_block, merges, false);
5766}5746}
57675747
5768fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5748fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -5950,13 +5930,31 @@ fn resolveBlockBody(...@@ -5950,13 +5930,31 @@ fn resolveBlockBody(
5950 if (child_block.is_comptime) {5930 if (child_block.is_comptime) {
5951 return sema.resolveBody(child_block, body, body_inst);5931 return sema.resolveBody(child_block, body, body_inst);
5952 } else {5932 } else {
5933 var need_debug_scope = false;
5934 child_block.need_debug_scope = &need_debug_scope;
5953 if (sema.analyzeBodyInner(child_block, body)) |_| {5935 if (sema.analyzeBodyInner(child_block, body)) |_| {
5954 return sema.analyzeBlockBody(parent_block, src, child_block, merges);5936 return sema.analyzeBlockBody(parent_block, src, child_block, merges, need_debug_scope);
5955 } else |err| switch (err) {5937 } else |err| switch (err) {
5956 error.ComptimeBreak => {5938 error.ComptimeBreak => {
5957 // Comptime control flow is happening, however child_block may still contain5939 // Comptime control flow is happening, however child_block may still contain
5958 // runtime instructions which need to be copied to the parent block.5940 // runtime instructions which need to be copied to the parent block.
5959 try parent_block.instructions.appendSlice(sema.gpa, child_block.instructions.items);5941 if (need_debug_scope and child_block.instructions.items.len > 0) {
5942 // We need a runtime block for scoping reasons.
5943 _ = try child_block.addBr(merges.block_inst, .void_value);
5944 try parent_block.instructions.append(sema.gpa, merges.block_inst);
5945 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Block).Struct.fields.len +
5946 child_block.instructions.items.len);
5947 sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{
5948 .ty = .void_type,
5949 .payload = sema.addExtraAssumeCapacity(Air.Block{
5950 .body_len = @intCast(child_block.instructions.items.len),
5951 }),
5952 } };
5953 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items));
5954 } else {
5955 // We can copy instructions directly to the parent block.
5956 try parent_block.instructions.appendSlice(sema.gpa, child_block.instructions.items);
5957 }
59605958
5961 const break_inst = sema.comptime_break_inst;5959 const break_inst = sema.comptime_break_inst;
5962 const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break";5960 const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break";
...@@ -5978,6 +5976,7 @@ fn analyzeBlockBody(...@@ -5978,6 +5976,7 @@ fn analyzeBlockBody(
5978 src: LazySrcLoc,5976 src: LazySrcLoc,
5979 child_block: *Block,5977 child_block: *Block,
5980 merges: *Block.Merges,5978 merges: *Block.Merges,
5979 need_debug_scope: bool,
5981) CompileError!Air.Inst.Ref {5980) CompileError!Air.Inst.Ref {
5982 const tracy = trace(@src());5981 const tracy = trace(@src());
5983 defer tracy.end();5982 defer tracy.end();
...@@ -5992,25 +5991,57 @@ fn analyzeBlockBody(...@@ -5992,25 +5991,57 @@ fn analyzeBlockBody(
5992 if (merges.results.items.len == 0) {5991 if (merges.results.items.len == 0) {
5993 // No need for a block instruction. We can put the new instructions5992 // No need for a block instruction. We can put the new instructions
5994 // directly into the parent block.5993 // directly into the parent block.
5994 if (need_debug_scope) {
5995 // The code following this block is unreachable, as the block has no
5996 // merges, so we don't necessarily need to emit this as an AIR block.
5997 // However, we need a block *somewhere* to make the scoping correct,
5998 // so forward this request to the parent block.
5999 if (parent_block.need_debug_scope) |ptr| ptr.* = true;
6000 }
5995 try parent_block.instructions.appendSlice(gpa, child_block.instructions.items);6001 try parent_block.instructions.appendSlice(gpa, child_block.instructions.items);
5996 return child_block.instructions.items[child_block.instructions.items.len - 1].toRef();6002 return child_block.instructions.items[child_block.instructions.items.len - 1].toRef();
5997 }6003 }
5998 if (merges.results.items.len == 1) {6004 if (merges.results.items.len == 1) {
5999 const last_inst_index = child_block.instructions.items.len - 1;6005 // If the `break` is trailing, we may be able to elide the AIR block here
6000 const last_inst = child_block.instructions.items[last_inst_index];6006 // by appending the new instructions directly to the parent block.
6001 if (sema.getBreakBlock(last_inst)) |br_block| {6007 if (!need_debug_scope) {
6002 if (br_block == merges.block_inst) {6008 const last_inst_index = child_block.instructions.items.len - 1;
6003 // No need for a block instruction. We can put the new instructions directly6009 const last_inst = child_block.instructions.items[last_inst_index];
6004 // into the parent block. Here we omit the break instruction.6010 if (sema.getBreakBlock(last_inst)) |br_block| {
6005 const without_break = child_block.instructions.items[0..last_inst_index];6011 if (br_block == merges.block_inst) {
6006 try parent_block.instructions.appendSlice(gpa, without_break);6012 // Great, the last instruction is the break! Put the instructions
6007 return merges.results.items[0];6013 // directly into the parent block.
6008 }6014 try parent_block.instructions.appendSlice(gpa, child_block.instructions.items[0..last_inst_index]);
6015 return merges.results.items[0];
6016 }
6017 }
6018 }
6019 // Okay, we need a runtime block. If the value is comptime-known, the
6020 // block should just return void, and we return the merge result
6021 // directly. Otherwise, we can defer to the logic below.
6022 if (try sema.resolveValue(merges.results.items[0])) |result_val| {
6023 // Create a block containing all instruction from the body.
6024 try parent_block.instructions.append(gpa, merges.block_inst);
6025 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
6026 child_block.instructions.items.len);
6027 sema.air_instructions.items(.data)[@intFromEnum(merges.block_inst)] = .{ .ty_pl = .{
6028 .ty = .void_type,
6029 .payload = sema.addExtraAssumeCapacity(Air.Block{
6030 .body_len = @intCast(child_block.instructions.items.len),
6031 }),
6032 } };
6033 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items));
6034 // Rewrite the break to just give value {}; the value is
6035 // comptime-known and will be returned directly.
6036 sema.air_instructions.items(.data)[@intFromEnum(merges.br_list.items[0])].br.operand = .void_value;
6037 return Air.internedToRef(result_val.toIntern());
6009 }6038 }
6010 }6039 }
6011 // It is impossible to have the number of results be > 1 in a comptime scope.6040 // It is impossible to have the number of results be > 1 in a comptime scope.
6012 assert(!child_block.is_comptime); // Should already got a compile error in the condbr condition.6041 assert(!child_block.is_comptime); // Should already got a compile error in the condbr condition.
60136042
6043 // Note that we'll always create an AIR block here, so `need_debug_scope` is irrelevant.
6044
6014 // Need to set the type and emit the Block instruction. This allows machine code generation6045 // Need to set the type and emit the Block instruction. This allows machine code generation
6015 // to emit a jump instruction to after the block when it encounters the break.6046 // to emit a jump instruction to after the block when it encounters the break.
6016 try parent_block.instructions.append(gpa, merges.block_inst);6047 try parent_block.instructions.append(gpa, merges.block_inst);
...@@ -6388,24 +6419,6 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi...@@ -6388,24 +6419,6 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi
6388 });6419 });
6389}6420}
63906421
6391fn zirDbgBlockBegin(block: *Block) CompileError!void {
6392 if (block.is_comptime or block.ownerModule().strip) return;
6393
6394 _ = try block.addInst(.{
6395 .tag = .dbg_block_begin,
6396 .data = undefined,
6397 });
6398}
6399
6400fn zirDbgBlockEnd(block: *Block) CompileError!void {
6401 if (block.is_comptime or block.ownerModule().strip) return;
6402
6403 _ = try block.addInst(.{
6404 .tag = .dbg_block_end,
6405 .data = undefined,
6406 });
6407}
6408
6409fn zirDbgVar(6422fn zirDbgVar(
6410 sema: *Sema,6423 sema: *Sema,
6411 block: *Block,6424 block: *Block,
...@@ -6437,6 +6450,15 @@ fn addDbgVar(...@@ -6437,6 +6450,15 @@ fn addDbgVar(
6437 if (try sema.typeRequiresComptime(val_ty)) return;6450 if (try sema.typeRequiresComptime(val_ty)) return;
6438 if (!(try sema.typeHasRuntimeBits(val_ty))) return;6451 if (!(try sema.typeHasRuntimeBits(val_ty))) return;
64396452
6453 // To ensure the lexical scoping is known to backends, this alloc must be
6454 // within a real runtime block. We set a flag which communicates information
6455 // to the closest lexically enclosing block:
6456 // * If it is a `block_inline`, communicates to logic in `analyzeBodyInner`
6457 // to create a post-hoc block.
6458 // * Otherwise, communicates to logic in `resolveBlockBody` to create a
6459 // real `block` instruction.
6460 if (block.need_debug_scope) |ptr| ptr.* = true;
6461
6440 try sema.queueFullTypeResolution(operand_ty);6462 try sema.queueFullTypeResolution(operand_ty);
64416463
6442 // Add the name to the AIR.6464 // Add the name to the AIR.
...@@ -7590,7 +7612,7 @@ fn analyzeCall(...@@ -7590,7 +7612,7 @@ fn analyzeCall(
7590 error.ComptimeReturn => break :result inlining.comptime_result,7612 error.ComptimeReturn => break :result inlining.comptime_result,
7591 else => |e| return e,7613 else => |e| return e,
7592 };7614 };
7593 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges);7615 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges, false);
7594 };7616 };
75957617
7596 if (!is_comptime_call and !block.is_typeof and7618 if (!is_comptime_call and !block.is_typeof and
...@@ -11534,7 +11556,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -11534,7 +11556,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
11534 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(true_instructions));11556 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(true_instructions));
11535 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items));11557 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items));
1153611558
11537 return sema.analyzeBlockBody(block, main_src, &child_block, merges);11559 return sema.analyzeBlockBody(block, main_src, &child_block, merges, false);
11538}11560}
1153911561
11540fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_ref: bool) CompileError!Air.Inst.Ref {11562fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_ref: bool) CompileError!Air.Inst.Ref {
...@@ -12156,7 +12178,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -12156,7 +12178,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
12156 false,12178 false,
12157 );12179 );
1215812180
12159 return sema.analyzeBlockBody(block, src, &child_block, merges);12181 return sema.analyzeBlockBody(block, src, &child_block, merges, false);
12160}12182}
1216112183
12162const SpecialProng = struct {12184const SpecialProng = struct {
...@@ -13169,8 +13191,6 @@ fn validateErrSetSwitch(...@@ -13169,8 +13191,6 @@ fn validateErrSetSwitch(
13169 const tags = sema.code.instructions.items(.tag);13191 const tags = sema.code.instructions.items(.tag);
13170 const datas = sema.code.instructions.items(.data);13192 const datas = sema.code.instructions.items(.data);
13171 for (else_case.body) |else_inst| switch (tags[@intFromEnum(else_inst)]) {13193 for (else_case.body) |else_inst| switch (tags[@intFromEnum(else_inst)]) {
13172 .dbg_block_begin,
13173 .dbg_block_end,
13174 .dbg_stmt,13194 .dbg_stmt,
13175 .dbg_var_val,13195 .dbg_var_val,
13176 .ret_type,13196 .ret_type,
...@@ -13422,8 +13442,6 @@ fn maybeErrorUnwrap(...@@ -13422,8 +13442,6 @@ fn maybeErrorUnwrap(
13422 .@"unreachable" => if (!block.wantSafety()) return false,13442 .@"unreachable" => if (!block.wantSafety()) return false,
13423 .err_union_code => if (!allow_err_code_inst) return false,13443 .err_union_code => if (!allow_err_code_inst) return false,
13424 .save_err_ret_index,13444 .save_err_ret_index,
13425 .dbg_block_begin,
13426 .dbg_block_end,
13427 .dbg_stmt,13445 .dbg_stmt,
13428 .str,13446 .str,
13429 .as_node,13447 .as_node,
...@@ -13436,10 +13454,7 @@ fn maybeErrorUnwrap(...@@ -13436,10 +13454,7 @@ fn maybeErrorUnwrap(
1343613454
13437 for (body) |inst| {13455 for (body) |inst| {
13438 const air_inst = switch (tags[@intFromEnum(inst)]) {13456 const air_inst = switch (tags[@intFromEnum(inst)]) {
13439 .dbg_block_begin,13457 .err_union_code => continue,
13440 .dbg_block_end,
13441 .err_union_code,
13442 => continue,
13443 .dbg_stmt => {13458 .dbg_stmt => {
13444 try sema.zirDbgStmt(block, inst);13459 try sema.zirDbgStmt(block, inst);
13445 continue;13460 continue;
...@@ -13505,8 +13520,6 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I...@@ -13505,8 +13520,6 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I
13505 const tags = sema.code.instructions.items(.tag);13520 const tags = sema.code.instructions.items(.tag);
13506 const inst = for (body) |inst| {13521 const inst = for (body) |inst| {
13507 switch (tags[@intFromEnum(inst)]) {13522 switch (tags[@intFromEnum(inst)]) {
13508 .dbg_block_begin,
13509 .dbg_block_end,
13510 .dbg_stmt,13523 .dbg_stmt,
13511 .save_err_ret_index,13524 .save_err_ret_index,
13512 => {},13525 => {},
...@@ -19098,55 +19111,64 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -19098,55 +19111,64 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
19098 return try_inst;19111 return try_inst;
19099}19112}
1910019113
19114fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*LabeledBlock {
19115 const gop = sema.inst_map.getOrPutAssumeCapacity(dest_block);
19116 if (gop.found_existing) existing: {
19117 // This may be a *result* from an earlier iteration of an inline loop.
19118 // In this case, there will not be a post-hoc block entry, and we can
19119 // continue with the logic below.
19120 const new_block_inst = gop.value_ptr.*.toIndex() orelse break :existing;
19121 return sema.post_hoc_blocks.get(new_block_inst) orelse break :existing;
19122 }
19123
19124 try sema.post_hoc_blocks.ensureUnusedCapacity(sema.gpa, 1);
19125
19126 const new_block_inst: Air.Inst.Index = @enumFromInt(sema.air_instructions.len);
19127 gop.value_ptr.* = new_block_inst.toRef();
19128 try sema.air_instructions.append(sema.gpa, .{
19129 .tag = .block,
19130 .data = undefined,
19131 });
19132 const labeled_block = try sema.gpa.create(LabeledBlock);
19133 labeled_block.* = .{
19134 .label = .{
19135 .zir_block = dest_block,
19136 .merges = .{
19137 .src_locs = .{},
19138 .results = .{},
19139 .br_list = .{},
19140 .block_inst = new_block_inst,
19141 },
19142 },
19143 .block = .{
19144 .parent = block,
19145 .sema = sema,
19146 .src_decl = block.src_decl,
19147 .namespace = block.namespace,
19148 .wip_capture_scope = block.wip_capture_scope,
19149 .instructions = .{},
19150 .label = &labeled_block.label,
19151 .inlining = block.inlining,
19152 .is_comptime = block.is_comptime,
19153 },
19154 };
19155 sema.post_hoc_blocks.putAssumeCapacityNoClobber(new_block_inst, labeled_block);
19156 return labeled_block;
19157}
19158
19101// A `break` statement is inside a runtime condition, but trying to19159// A `break` statement is inside a runtime condition, but trying to
19102// break from an inline loop. In such case we must convert it to19160// break from an inline loop. In such case we must convert it to
19103// a runtime break.19161// a runtime break.
19104fn addRuntimeBreak(sema: *Sema, child_block: *Block, break_data: BreakData) !void {19162fn addRuntimeBreak(sema: *Sema, child_block: *Block, break_data: BreakData) !void {
19105 const gop = sema.inst_map.getOrPutAssumeCapacity(break_data.block_inst);19163 const labeled_block = try sema.ensurePostHoc(child_block, break_data.block_inst);
19106 const labeled_block = if (!gop.found_existing) blk: {
19107 try sema.post_hoc_blocks.ensureUnusedCapacity(sema.gpa, 1);
19108
19109 const new_block_inst: Air.Inst.Index = @enumFromInt(sema.air_instructions.len);
19110 gop.value_ptr.* = new_block_inst.toRef();
19111 try sema.air_instructions.append(sema.gpa, .{
19112 .tag = .block,
19113 .data = undefined,
19114 });
19115 const labeled_block = try sema.gpa.create(LabeledBlock);
19116 labeled_block.* = .{
19117 .label = .{
19118 .zir_block = break_data.block_inst,
19119 .merges = .{
19120 .src_locs = .{},
19121 .results = .{},
19122 .br_list = .{},
19123 .block_inst = new_block_inst,
19124 },
19125 },
19126 .block = .{
19127 .parent = child_block,
19128 .sema = sema,
19129 .src_decl = child_block.src_decl,
19130 .namespace = child_block.namespace,
19131 .wip_capture_scope = child_block.wip_capture_scope,
19132 .instructions = .{},
19133 .label = &labeled_block.label,
19134 .inlining = child_block.inlining,
19135 .is_comptime = child_block.is_comptime,
19136 },
19137 };
19138 sema.post_hoc_blocks.putAssumeCapacityNoClobber(new_block_inst, labeled_block);
19139 break :blk labeled_block;
19140 } else blk: {
19141 const new_block_inst = gop.value_ptr.*.toIndex().?;
19142 const labeled_block = sema.post_hoc_blocks.get(new_block_inst).?;
19143 break :blk labeled_block;
19144 };
1914519164
19146 const operand = try sema.resolveInst(break_data.operand);19165 const operand = try sema.resolveInst(break_data.operand);
19147 const br_ref = try child_block.addBr(labeled_block.label.merges.block_inst, operand);19166 const br_ref = try child_block.addBr(labeled_block.label.merges.block_inst, operand);
19167
19148 try labeled_block.label.merges.results.append(sema.gpa, operand);19168 try labeled_block.label.merges.results.append(sema.gpa, operand);
19149 try labeled_block.label.merges.br_list.append(sema.gpa, br_ref.toIndex().?);19169 try labeled_block.label.merges.br_list.append(sema.gpa, br_ref.toIndex().?);
19170 try labeled_block.label.merges.src_locs.append(sema.gpa, null);
19171
19150 labeled_block.block.runtime_index.increment();19172 labeled_block.block.runtime_index.increment();
19151 if (labeled_block.block.runtime_cond == null and labeled_block.block.runtime_loop == null) {19173 if (labeled_block.block.runtime_cond == null and labeled_block.block.runtime_loop == null) {
19152 labeled_block.block.runtime_cond = child_block.runtime_cond orelse child_block.runtime_loop;19174 labeled_block.block.runtime_cond = child_block.runtime_cond orelse child_block.runtime_loop;
...@@ -19487,8 +19509,10 @@ fn analyzeRet(...@@ -19487,8 +19509,10 @@ fn analyzeRet(
19487 return error.ComptimeReturn;19509 return error.ComptimeReturn;
19488 }19510 }
19489 // We are inlining a function call; rewrite the `ret` as a `break`.19511 // We are inlining a function call; rewrite the `ret` as a `break`.
19512 const br_inst = try block.addBr(inlining.merges.block_inst, operand);
19490 try inlining.merges.results.append(sema.gpa, operand);19513 try inlining.merges.results.append(sema.gpa, operand);
19491 _ = try block.addBr(inlining.merges.block_inst, operand);19514 try inlining.merges.br_list.append(sema.gpa, br_inst.toIndex().?);
19515 try inlining.merges.src_locs.append(sema.gpa, operand_src);
19492 return always_noreturn;19516 return always_noreturn;
19493 } else if (block.is_comptime) {19517 } else if (block.is_comptime) {
19494 return sema.fail(block, src, "function called at runtime cannot return value at comptime", .{});19518 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}