authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-19 16:05:22-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-19 16:05:22-04:00
loga318aeed9b8ccec453e9f15415ea3fd20cb13c8d
tree12c7de4eb436130491aefa1a4e8ef517cd20491e
parent67665286575d406769000b3f3e80d4d03d2cab2b
parentd56e3c988f0707e996be8eeb7a55f8a90c497a26
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11222 from Vexu/dbg_block

stage2: add debug info for payload captures + inline function parameters

16 files changed, 296 insertions(+), 74 deletions(-)

src/Air.zig+6
...@@ -326,6 +326,10 @@ pub const Inst = struct {...@@ -326,6 +326,10 @@ pub const Inst = struct {
326 /// Result type is always void.326 /// Result type is always void.
327 /// Uses the `dbg_stmt` field.327 /// Uses the `dbg_stmt` field.
328 dbg_stmt,328 dbg_stmt,
329 /// Marks the beginning of a semantic scope for debug info variables.
330 dbg_block_begin,
331 /// Marks the end of a semantic scope for debug info variables.
332 dbg_block_end,
329 /// Marks the start of an inline call.333 /// Marks the start of an inline call.
330 /// Uses `ty_pl` with the payload being the index of a Value.Function in air.values.334 /// Uses `ty_pl` with the payload being the index of a Value.Function in air.values.
331 dbg_inline_begin,335 dbg_inline_begin,
...@@ -990,6 +994,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -990,6 +994,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
990 .dbg_stmt,994 .dbg_stmt,
991 .dbg_inline_begin,995 .dbg_inline_begin,
992 .dbg_inline_end,996 .dbg_inline_end,
997 .dbg_block_begin,
998 .dbg_block_end,
993 .dbg_var_ptr,999 .dbg_var_ptr,
994 .dbg_var_val,1000 .dbg_var_val,
995 .store,1001 .store,
src/AstGen.zig+92-32
...@@ -2052,6 +2052,10 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2052,6 +2052,10 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
2052 const tree = astgen.tree;2052 const tree = astgen.tree;
2053 const node_tags = tree.nodes.items(.tag);2053 const node_tags = tree.nodes.items(.tag);
20542054
2055 if (statements.len == 0) return;
2056
2057 try gz.addDbgBlockBegin();
2058
2055 var block_arena = std.heap.ArenaAllocator.init(gz.astgen.gpa);2059 var block_arena = std.heap.ArenaAllocator.init(gz.astgen.gpa);
2056 defer block_arena.deinit();2060 defer block_arena.deinit();
2057 const block_arena_allocator = block_arena.allocator();2061 const block_arena_allocator = block_arena.allocator();
...@@ -2105,6 +2109,8 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2105,6 +2109,8 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
2105 }2109 }
2106 }2110 }
21072111
2112 try gz.addDbgBlockEnd();
2113
2108 try genDefers(gz, parent_scope, scope, .normal_only);2114 try genDefers(gz, parent_scope, scope, .normal_only);
2109 try checkUsed(gz, parent_scope, scope);2115 try checkUsed(gz, parent_scope, scope);
2110}2116}
...@@ -2527,6 +2533,7 @@ fn genDefers(...@@ -2527,6 +2533,7 @@ fn genDefers(
2527 gz.in_defer = true;2533 gz.in_defer = true;
2528 defer gz.in_defer = prev_in_defer;2534 defer gz.in_defer = prev_in_defer;
2529 var local_val_scope: Scope.LocalVal = undefined;2535 var local_val_scope: Scope.LocalVal = undefined;
2536 try gz.addDbgBlockBegin();
2530 const sub_scope = if (payload_token == 0) defer_scope.parent else blk: {2537 const sub_scope = if (payload_token == 0) defer_scope.parent else blk: {
2531 const ident_name = try astgen.identAsString(payload_token);2538 const ident_name = try astgen.identAsString(payload_token);
2532 local_val_scope = .{2539 local_val_scope = .{
...@@ -2537,9 +2544,11 @@ fn genDefers(...@@ -2537,9 +2544,11 @@ fn genDefers(
2537 .token_src = payload_token,2544 .token_src = payload_token,
2538 .id_cat = .@"capture",2545 .id_cat = .@"capture",
2539 };2546 };
2547 try gz.addDbgVar(.dbg_var_val, ident_name, err_code);
2540 break :blk &local_val_scope.base;2548 break :blk &local_val_scope.base;
2541 };2549 };
2542 try unusedResultDeferExpr(gz, defer_scope, sub_scope, expr_node);2550 try unusedResultDeferExpr(gz, defer_scope, sub_scope, expr_node);
2551 try gz.addDbgBlockEnd();
2543 },2552 },
2544 .normal_only => continue,2553 .normal_only => continue,
2545 }2554 }
...@@ -2665,14 +2674,7 @@ fn varDecl(...@@ -2665,14 +2674,7 @@ fn varDecl(
2665 } else .none;2674 } else .none;
2666 const init_inst = try reachableExpr(gz, scope, result_loc, var_decl.ast.init_node, node);2675 const init_inst = try reachableExpr(gz, scope, result_loc, var_decl.ast.init_node, node);
26672676
2668 if (!gz.force_comptime) {2677 try gz.addDbgVar(.dbg_var_val, ident_name, init_inst);
2669 _ = try gz.add(.{ .tag = .dbg_var_val, .data = .{
2670 .str_op = .{
2671 .str = ident_name,
2672 .operand = init_inst,
2673 },
2674 } });
2675 }
26762678
2677 const sub_scope = try block_arena.create(Scope.LocalVal);2679 const sub_scope = try block_arena.create(Scope.LocalVal);
2678 sub_scope.* = .{2680 sub_scope.* = .{
...@@ -2766,14 +2768,7 @@ fn varDecl(...@@ -2766,14 +2768,7 @@ fn varDecl(
2766 else2768 else
2767 init_inst;2769 init_inst;
27682770
2769 if (!gz.force_comptime) {2771 try gz.addDbgVar(.dbg_var_val, ident_name, coerced_init);
2770 _ = try gz.add(.{ .tag = .dbg_var_val, .data = .{
2771 .str_op = .{
2772 .str = ident_name,
2773 .operand = coerced_init,
2774 },
2775 } });
2776 }
27772772
2778 const sub_scope = try block_arena.create(Scope.LocalVal);2773 const sub_scope = try block_arena.create(Scope.LocalVal);
2779 sub_scope.* = .{2774 sub_scope.* = .{
...@@ -2810,14 +2805,7 @@ fn varDecl(...@@ -2810,14 +2805,7 @@ fn varDecl(
2810 }2805 }
2811 const const_ptr = try gz.addUnNode(.make_ptr_const, init_scope.rl_ptr, node);2806 const const_ptr = try gz.addUnNode(.make_ptr_const, init_scope.rl_ptr, node);
28122807
2813 if (!gz.force_comptime) {2808 try gz.addDbgVar(.dbg_var_ptr, ident_name, const_ptr);
2814 _ = try gz.add(.{ .tag = .dbg_var_ptr, .data = .{
2815 .str_op = .{
2816 .str = ident_name,
2817 .operand = const_ptr,
2818 },
2819 } });
2820 }
28212809
2822 const sub_scope = try block_arena.create(Scope.LocalPtr);2810 const sub_scope = try block_arena.create(Scope.LocalPtr);
2823 sub_scope.* = .{2811 sub_scope.* = .{
...@@ -2883,14 +2871,7 @@ fn varDecl(...@@ -2883,14 +2871,7 @@ fn varDecl(
2883 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);2871 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);
2884 }2872 }
28852873
2886 if (!gz.force_comptime) {2874 try gz.addDbgVar(.dbg_var_ptr, ident_name, var_data.alloc);
2887 _ = try gz.add(.{ .tag = .dbg_var_ptr, .data = .{
2888 .str_op = .{
2889 .str = ident_name,
2890 .operand = var_data.alloc,
2891 },
2892 } });
2893 }
28942875
2895 const sub_scope = try block_arena.create(Scope.LocalPtr);2876 const sub_scope = try block_arena.create(Scope.LocalPtr);
2896 sub_scope.* = .{2877 sub_scope.* = .{
...@@ -5187,6 +5168,7 @@ fn ifExpr(...@@ -5187,6 +5168,7 @@ fn ifExpr(
51875168
5188 var payload_val_scope: Scope.LocalVal = undefined;5169 var payload_val_scope: Scope.LocalVal = undefined;
51895170
5171 try then_scope.addDbgBlockBegin();
5190 const then_sub_scope = s: {5172 const then_sub_scope = s: {
5191 if (if_full.error_token != null) {5173 if (if_full.error_token != null) {
5192 if (if_full.payload_token) |payload_token| {5174 if (if_full.payload_token) |payload_token| {
...@@ -5209,6 +5191,7 @@ fn ifExpr(...@@ -5209,6 +5191,7 @@ fn ifExpr(
5209 .token_src = payload_token,5191 .token_src = payload_token,
5210 .id_cat = .@"capture",5192 .id_cat = .@"capture",
5211 };5193 };
5194 try then_scope.addDbgVar(.dbg_var_val, ident_name, payload_inst);
5212 break :s &payload_val_scope.base;5195 break :s &payload_val_scope.base;
5213 } else {5196 } else {
5214 break :s &then_scope.base;5197 break :s &then_scope.base;
...@@ -5233,6 +5216,7 @@ fn ifExpr(...@@ -5233,6 +5216,7 @@ fn ifExpr(
5233 .token_src = ident_token,5216 .token_src = ident_token,
5234 .id_cat = .@"capture",5217 .id_cat = .@"capture",
5235 };5218 };
5219 try then_scope.addDbgVar(.dbg_var_val, ident_name, payload_inst);
5236 break :s &payload_val_scope.base;5220 break :s &payload_val_scope.base;
5237 } else {5221 } else {
5238 break :s &then_scope.base;5222 break :s &then_scope.base;
...@@ -5244,6 +5228,7 @@ fn ifExpr(...@@ -5244,6 +5228,7 @@ fn ifExpr(
5244 block_scope.break_count += 1;5228 block_scope.break_count += 1;
5245 }5229 }
5246 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);5230 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
5231 try then_scope.addDbgBlockEnd();
5247 // We hold off on the break instructions as well as copying the then/else5232 // We hold off on the break instructions as well as copying the then/else
5248 // instructions into place until we know whether to keep store_to_block_ptr5233 // instructions into place until we know whether to keep store_to_block_ptr
5249 // instructions or not.5234 // instructions or not.
...@@ -5256,6 +5241,7 @@ fn ifExpr(...@@ -5256,6 +5241,7 @@ fn ifExpr(
5256 src: Ast.Node.Index,5241 src: Ast.Node.Index,
5257 result: Zir.Inst.Ref,5242 result: Zir.Inst.Ref,
5258 } = if (else_node != 0) blk: {5243 } = if (else_node != 0) blk: {
5244 try else_scope.addDbgBlockBegin();
5259 const sub_scope = s: {5245 const sub_scope = s: {
5260 if (if_full.error_token) |error_token| {5246 if (if_full.error_token) |error_token| {
5261 const tag: Zir.Inst.Tag = if (payload_is_ref)5247 const tag: Zir.Inst.Tag = if (payload_is_ref)
...@@ -5276,6 +5262,7 @@ fn ifExpr(...@@ -5276,6 +5262,7 @@ fn ifExpr(
5276 .token_src = error_token,5262 .token_src = error_token,
5277 .id_cat = .@"capture",5263 .id_cat = .@"capture",
5278 };5264 };
5265 try else_scope.addDbgVar(.dbg_var_val, ident_name, payload_inst);
5279 break :s &payload_val_scope.base;5266 break :s &payload_val_scope.base;
5280 } else {5267 } else {
5281 break :s &else_scope.base;5268 break :s &else_scope.base;
...@@ -5286,6 +5273,7 @@ fn ifExpr(...@@ -5286,6 +5273,7 @@ fn ifExpr(
5286 block_scope.break_count += 1;5273 block_scope.break_count += 1;
5287 }5274 }
5288 try checkUsed(parent_gz, &else_scope.base, sub_scope);5275 try checkUsed(parent_gz, &else_scope.base, sub_scope);
5276 try else_scope.addDbgBlockEnd();
5289 break :blk .{5277 break :blk .{
5290 .src = else_node,5278 .src = else_node,
5291 .result = e,5279 .result = e,
...@@ -5501,6 +5489,8 @@ fn whileExpr(...@@ -5501,6 +5489,8 @@ fn whileExpr(
5501 then_scope.instructions_top = GenZir.unstacked_top;5489 then_scope.instructions_top = GenZir.unstacked_top;
5502 defer then_scope.unstack();5490 defer then_scope.unstack();
55035491
5492 var dbg_var_name: ?u32 = null;
5493 var dbg_var_inst: Zir.Inst.Ref = undefined;
5504 var payload_inst: Zir.Inst.Index = 0;5494 var payload_inst: Zir.Inst.Index = 0;
5505 var payload_val_scope: Scope.LocalVal = undefined;5495 var payload_val_scope: Scope.LocalVal = undefined;
5506 const then_sub_scope = s: {5496 const then_sub_scope = s: {
...@@ -5527,6 +5517,8 @@ fn whileExpr(...@@ -5527,6 +5517,8 @@ fn whileExpr(
5527 .token_src = payload_token,5517 .token_src = payload_token,
5528 .id_cat = .@"capture",5518 .id_cat = .@"capture",
5529 };5519 };
5520 dbg_var_name = ident_name;
5521 dbg_var_inst = indexToRef(payload_inst);
5530 break :s &payload_val_scope.base;5522 break :s &payload_val_scope.base;
5531 } else {5523 } else {
5532 break :s &then_scope.base;5524 break :s &then_scope.base;
...@@ -5552,6 +5544,8 @@ fn whileExpr(...@@ -5552,6 +5544,8 @@ fn whileExpr(
5552 .token_src = ident_token,5544 .token_src = ident_token,
5553 .id_cat = .@"capture",5545 .id_cat = .@"capture",
5554 };5546 };
5547 dbg_var_name = ident_name;
5548 dbg_var_inst = indexToRef(payload_inst);
5555 break :s &payload_val_scope.base;5549 break :s &payload_val_scope.base;
5556 } else {5550 } else {
5557 break :s &then_scope.base;5551 break :s &then_scope.base;
...@@ -5562,9 +5556,14 @@ fn whileExpr(...@@ -5562,9 +5556,14 @@ fn whileExpr(
5562 // are no jumps to it. This happens when the last statement of a while body is noreturn5556 // are no jumps to it. This happens when the last statement of a while body is noreturn
5563 // and there are no `continue` statements.5557 // and there are no `continue` statements.
5564 // Tracking issue: https://github.com/ziglang/zig/issues/91855558 // Tracking issue: https://github.com/ziglang/zig/issues/9185
5559 try then_scope.addDbgBlockBegin();
5560 if (dbg_var_name) |some| {
5561 try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst);
5562 }
5565 if (while_full.ast.cont_expr != 0) {5563 if (while_full.ast.cont_expr != 0) {
5566 _ = try expr(&loop_scope, then_sub_scope, .{ .ty = .void_type }, while_full.ast.cont_expr);5564 _ = try expr(&loop_scope, then_sub_scope, .{ .ty = .void_type }, while_full.ast.cont_expr);
5567 }5565 }
5566 try then_scope.addDbgBlockEnd();
5568 const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;5567 const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
5569 _ = try loop_scope.addNode(repeat_tag, node);5568 _ = try loop_scope.addNode(repeat_tag, node);
55705569
...@@ -5580,9 +5579,15 @@ fn whileExpr(...@@ -5580,9 +5579,15 @@ fn whileExpr(
55805579
5581 // done adding instructions to loop_scope, can now stack then_scope5580 // done adding instructions to loop_scope, can now stack then_scope
5582 then_scope.instructions_top = then_scope.instructions.items.len;5581 then_scope.instructions_top = then_scope.instructions.items.len;
5582
5583 if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst);5583 if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst);
5584 try then_scope.addDbgBlockBegin();
5585 if (dbg_var_name) |some| {
5586 try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst);
5587 }
5584 const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr);5588 const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr);
5585 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);5589 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
5590 try then_scope.addDbgBlockEnd();
55865591
5587 var else_scope = parent_gz.makeSubBlock(&continue_scope.base);5592 var else_scope = parent_gz.makeSubBlock(&continue_scope.base);
5588 defer else_scope.unstack();5593 defer else_scope.unstack();
...@@ -5592,6 +5597,7 @@ fn whileExpr(...@@ -5592,6 +5597,7 @@ fn whileExpr(
5592 src: Ast.Node.Index,5597 src: Ast.Node.Index,
5593 result: Zir.Inst.Ref,5598 result: Zir.Inst.Ref,
5594 } = if (else_node != 0) blk: {5599 } = if (else_node != 0) blk: {
5600 try else_scope.addDbgBlockBegin();
5595 const sub_scope = s: {5601 const sub_scope = s: {
5596 if (while_full.error_token) |error_token| {5602 if (while_full.error_token) |error_token| {
5597 const tag: Zir.Inst.Tag = if (payload_is_ref)5603 const tag: Zir.Inst.Tag = if (payload_is_ref)
...@@ -5612,6 +5618,7 @@ fn whileExpr(...@@ -5612,6 +5618,7 @@ fn whileExpr(
5612 .token_src = error_token,5618 .token_src = error_token,
5613 .id_cat = .@"capture",5619 .id_cat = .@"capture",
5614 };5620 };
5621 try else_scope.addDbgVar(.dbg_var_val, ident_name, else_payload_inst);
5615 break :s &payload_val_scope.base;5622 break :s &payload_val_scope.base;
5616 } else {5623 } else {
5617 break :s &else_scope.base;5624 break :s &else_scope.base;
...@@ -5622,6 +5629,7 @@ fn whileExpr(...@@ -5622,6 +5629,7 @@ fn whileExpr(
5622 loop_scope.break_count += 1;5629 loop_scope.break_count += 1;
5623 }5630 }
5624 try checkUsed(parent_gz, &else_scope.base, sub_scope);5631 try checkUsed(parent_gz, &else_scope.base, sub_scope);
5632 try else_scope.addDbgBlockEnd();
5625 break :blk .{5633 break :blk .{
5626 .src = else_node,5634 .src = else_node,
5627 .result = e,5635 .result = e,
...@@ -5743,6 +5751,7 @@ fn forExpr(...@@ -5743,6 +5751,7 @@ fn forExpr(
5743 then_scope.markAsLoopBody(loop_scope);5751 then_scope.markAsLoopBody(loop_scope);
5744 defer then_scope.unstack();5752 defer then_scope.unstack();
57455753
5754 try then_scope.addDbgBlockBegin();
5746 var payload_val_scope: Scope.LocalVal = undefined;5755 var payload_val_scope: Scope.LocalVal = undefined;
5747 var index_scope: Scope.LocalPtr = undefined;5756 var index_scope: Scope.LocalPtr = undefined;
5748 const then_sub_scope = blk: {5757 const then_sub_scope = blk: {
...@@ -5767,6 +5776,7 @@ fn forExpr(...@@ -5767,6 +5776,7 @@ fn forExpr(
5767 .token_src = ident,5776 .token_src = ident,
5768 .id_cat = .@"capture",5777 .id_cat = .@"capture",
5769 };5778 };
5779 try then_scope.addDbgVar(.dbg_var_val, name_str_index, payload_inst);
5770 payload_sub_scope = &payload_val_scope.base;5780 payload_sub_scope = &payload_val_scope.base;
5771 } else if (is_ptr) {5781 } else if (is_ptr) {
5772 return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{});5782 return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{});
...@@ -5793,11 +5803,13 @@ fn forExpr(...@@ -5793,11 +5803,13 @@ fn forExpr(
5793 .maybe_comptime = is_inline,5803 .maybe_comptime = is_inline,
5794 .id_cat = .@"loop index capture",5804 .id_cat = .@"loop index capture",
5795 };5805 };
5806 try then_scope.addDbgVar(.dbg_var_val, index_name, index_ptr);
5796 break :blk &index_scope.base;5807 break :blk &index_scope.base;
5797 };5808 };
57985809
5799 const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr);5810 const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr);
5800 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);5811 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
5812 try then_scope.addDbgBlockEnd();
58015813
5802 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);5814 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
5803 defer else_scope.unstack();5815 defer else_scope.unstack();
...@@ -6016,6 +6028,8 @@ fn switchExpr(...@@ -6016,6 +6028,8 @@ fn switchExpr(
6016 const is_multi_case = case.ast.values.len > 1 or6028 const is_multi_case = case.ast.values.len > 1 or
6017 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);6029 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);
60186030
6031 var dbg_var_name: ?u32 = null;
6032 var dbg_var_inst: Zir.Inst.Ref = undefined;
6019 var capture_inst: Zir.Inst.Index = 0;6033 var capture_inst: Zir.Inst.Index = 0;
6020 var capture_val_scope: Scope.LocalVal = undefined;6034 var capture_val_scope: Scope.LocalVal = undefined;
6021 const sub_scope = blk: {6035 const sub_scope = blk: {
...@@ -6075,6 +6089,8 @@ fn switchExpr(...@@ -6075,6 +6089,8 @@ fn switchExpr(
6075 .token_src = payload_token,6089 .token_src = payload_token,
6076 .id_cat = .@"capture",6090 .id_cat = .@"capture",
6077 };6091 };
6092 dbg_var_name = capture_name;
6093 dbg_var_inst = indexToRef(capture_inst);
6078 break :blk &capture_val_scope.base;6094 break :blk &capture_val_scope.base;
6079 };6095 };
60806096
...@@ -6130,8 +6146,13 @@ fn switchExpr(...@@ -6130,8 +6146,13 @@ fn switchExpr(
6130 defer case_scope.unstack();6146 defer case_scope.unstack();
61316147
6132 if (capture_inst != 0) try case_scope.instructions.append(gpa, capture_inst);6148 if (capture_inst != 0) try case_scope.instructions.append(gpa, capture_inst);
6149 try case_scope.addDbgBlockBegin();
6150 if (dbg_var_name) |some| {
6151 try case_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst);
6152 }
6133 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);6153 const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr);
6134 try checkUsed(parent_gz, &case_scope.base, sub_scope);6154 try checkUsed(parent_gz, &case_scope.base, sub_scope);
6155 try case_scope.addDbgBlockEnd();
6135 if (!parent_gz.refIsNoReturn(case_result)) {6156 if (!parent_gz.refIsNoReturn(case_result)) {
6136 block_scope.break_count += 1;6157 block_scope.break_count += 1;
6137 _ = try case_scope.addBreak(.@"break", switch_block, case_result);6158 _ = try case_scope.addBreak(.@"break", switch_block, case_result);
...@@ -10829,6 +10850,45 @@ const GenZir = struct {...@@ -10829,6 +10850,45 @@ const GenZir = struct {
10829 }10850 }
10830 }10851 }
1083110852
10853 fn addDbgVar(gz: *GenZir, tag: Zir.Inst.Tag, name: u32, inst: Zir.Inst.Ref) !void {
10854 if (gz.force_comptime) return;
10855
10856 _ = try gz.add(.{ .tag = tag, .data = .{
10857 .str_op = .{
10858 .str = name,
10859 .operand = inst,
10860 },
10861 } });
10862 }
10863
10864 fn addDbgBlockBegin(gz: *GenZir) !void {
10865 if (gz.force_comptime) return;
10866
10867 _ = try gz.add(.{ .tag = .extended, .data = .{
10868 .extended = .{ .opcode = .dbg_block_begin, .small = undefined, .operand = undefined },
10869 } });
10870 }
10871
10872 fn addDbgBlockEnd(gz: *GenZir) !void {
10873 if (gz.force_comptime) return;
10874 const gpa = gz.astgen.gpa;
10875
10876 const tags = gz.astgen.instructions.items(.tag);
10877 const data = gz.astgen.instructions.items(.data);
10878 const last_inst = gz.instructions.items[gz.instructions.items.len - 1];
10879 // remove dbg_block_begin immediately followed by dbg_block_end
10880 if (tags[last_inst] == .extended and data[last_inst].extended.opcode == .dbg_block_begin) {
10881 _ = gz.instructions.pop();
10882 return;
10883 }
10884
10885 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
10886 try gz.astgen.instructions.append(gpa, .{ .tag = .extended, .data = .{
10887 .extended = .{ .opcode = .dbg_block_end, .small = undefined, .operand = undefined },
10888 } });
10889 try gz.instructions.insert(gpa, gz.instructions.items.len - 1, new_index);
10890 }
10891
10832 /// Control flow does not fall through the "then" block of a loop; it continues10892 /// Control flow does not fall through the "then" block of a loop; it continues
10833 /// back to the while condition. This prevents `rvalue` from10893 /// back to the while condition. This prevents `rvalue` from
10834 /// adding an invalid store to the result location of `then_scope`.10894 /// adding an invalid store to the result location of `then_scope`.
src/Liveness.zig+2
...@@ -316,6 +316,8 @@ fn analyzeInst(...@@ -316,6 +316,8 @@ fn analyzeInst(
316 .dbg_stmt,316 .dbg_stmt,
317 .dbg_inline_begin,317 .dbg_inline_begin,
318 .dbg_inline_end,318 .dbg_inline_end,
319 .dbg_block_begin,
320 .dbg_block_end,
319 .unreach,321 .unreach,
320 .fence,322 .fence,
321 .ret_addr,323 .ret_addr,
src/Sema.zig+115-40
...@@ -618,6 +618,8 @@ fn analyzeBodyInner(...@@ -618,6 +618,8 @@ fn analyzeBodyInner(
618 crash_info.push();618 crash_info.push();
619 defer crash_info.pop();619 defer crash_info.pop();
620620
621 var dbg_block_begins: u32 = 0;
622
621 // We use a while(true) loop here to avoid a redundant way of breaking out of623 // We use a while(true) loop here to avoid a redundant way of breaking out of
622 // the loop. The only way to break out of the loop is with a `noreturn`624 // the loop. The only way to break out of the loop is with a `noreturn`
623 // instruction.625 // instruction.
...@@ -792,7 +794,6 @@ fn analyzeBodyInner(...@@ -792,7 +794,6 @@ fn analyzeBodyInner(
792 .@"resume" => try sema.zirResume(block, inst),794 .@"resume" => try sema.zirResume(block, inst),
793 .@"await" => try sema.zirAwait(block, inst, false),795 .@"await" => try sema.zirAwait(block, inst, false),
794 .await_nosuspend => try sema.zirAwait(block, inst, true),796 .await_nosuspend => try sema.zirAwait(block, inst, true),
795 .extended => try sema.zirExtended(block, inst),
796 .array_base_ptr => try sema.zirArrayBasePtr(block, inst),797 .array_base_ptr => try sema.zirArrayBasePtr(block, inst),
797 .field_base_ptr => try sema.zirFieldBasePtr(block, inst),798 .field_base_ptr => try sema.zirFieldBasePtr(block, inst),
798799
...@@ -854,6 +855,55 @@ fn analyzeBodyInner(...@@ -854,6 +855,55 @@ fn analyzeBodyInner(
854 .panic => break sema.zirPanic(block, inst),855 .panic => break sema.zirPanic(block, inst),
855 // zig fmt: on856 // zig fmt: on
856857
858 .extended => ext: {
859 const extended = datas[inst].extended;
860 break :ext switch (extended.opcode) {
861 // zig fmt: off
862 .func => try sema.zirFuncExtended( block, extended, inst),
863 .variable => try sema.zirVarExtended( block, extended),
864 .struct_decl => try sema.zirStructDecl( block, extended, inst),
865 .enum_decl => try sema.zirEnumDecl( block, extended),
866 .union_decl => try sema.zirUnionDecl( block, extended, inst),
867 .opaque_decl => try sema.zirOpaqueDecl( block, extended),
868 .ret_ptr => try sema.zirRetPtr( block, extended),
869 .ret_type => try sema.zirRetType( block, extended),
870 .this => try sema.zirThis( block, extended),
871 .ret_addr => try sema.zirRetAddr( block, extended),
872 .builtin_src => try sema.zirBuiltinSrc( block, extended),
873 .error_return_trace => try sema.zirErrorReturnTrace( block, extended),
874 .frame => try sema.zirFrame( block, extended),
875 .frame_address => try sema.zirFrameAddress( block, extended),
876 .alloc => try sema.zirAllocExtended( block, extended),
877 .builtin_extern => try sema.zirBuiltinExtern( block, extended),
878 .@"asm" => try sema.zirAsm( block, extended),
879 .typeof_peer => try sema.zirTypeofPeer( block, extended),
880 .compile_log => try sema.zirCompileLog( block, extended),
881 .add_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode),
882 .sub_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode),
883 .mul_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode),
884 .shl_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode),
885 .c_undef => try sema.zirCUndef( block, extended),
886 .c_include => try sema.zirCInclude( block, extended),
887 .c_define => try sema.zirCDefine( block, extended),
888 .wasm_memory_size => try sema.zirWasmMemorySize( block, extended),
889 .wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended),
890 .prefetch => try sema.zirPrefetch( block, extended),
891 // zig fmt: on
892 .dbg_block_begin => {
893 dbg_block_begins += 1;
894 try sema.zirDbgBlockBegin(block);
895 i += 1;
896 continue;
897 },
898 .dbg_block_end => {
899 dbg_block_begins -= 1;
900 try sema.zirDbgBlockEnd(block);
901 i += 1;
902 continue;
903 },
904 };
905 },
906
857 // Instructions that we know can *never* be noreturn based solely on907 // Instructions that we know can *never* be noreturn based solely on
858 // their tag. We avoid needlessly checking if they are noreturn and908 // their tag. We avoid needlessly checking if they are noreturn and
859 // continue the loop.909 // continue the loop.
...@@ -1179,6 +1229,19 @@ fn analyzeBodyInner(...@@ -1179,6 +1229,19 @@ fn analyzeBodyInner(
1179 i += 1;1229 i += 1;
1180 } else unreachable;1230 } else unreachable;
11811231
1232 // balance out dbg_block_begins in case of early noreturn
1233 const noreturn_inst = block.instructions.popOrNull();
1234 while (dbg_block_begins > 0) {
1235 dbg_block_begins -= 1;
1236 if (block.is_comptime or sema.mod.comp.bin_file.options.strip) continue;
1237
1238 _ = try block.addInst(.{
1239 .tag = .dbg_block_end,
1240 .data = undefined,
1241 });
1242 }
1243 if (noreturn_inst) |some| try block.instructions.append(sema.gpa, some);
1244
1182 if (!wip_captures.finalized) {1245 if (!wip_captures.finalized) {
1183 try wip_captures.finalize();1246 try wip_captures.finalize();
1184 block.wip_capture_scope = parent_capture_scope;1247 block.wip_capture_scope = parent_capture_scope;
...@@ -1187,43 +1250,6 @@ fn analyzeBodyInner(...@@ -1187,43 +1250,6 @@ fn analyzeBodyInner(
1187 return result;1250 return result;
1188}1251}
11891252
1190fn zirExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1191 const extended = sema.code.instructions.items(.data)[inst].extended;
1192 switch (extended.opcode) {
1193 // zig fmt: off
1194 .func => return sema.zirFuncExtended( block, extended, inst),
1195 .variable => return sema.zirVarExtended( block, extended),
1196 .struct_decl => return sema.zirStructDecl( block, extended, inst),
1197 .enum_decl => return sema.zirEnumDecl( block, extended),
1198 .union_decl => return sema.zirUnionDecl( block, extended, inst),
1199 .opaque_decl => return sema.zirOpaqueDecl( block, extended),
1200 .ret_ptr => return sema.zirRetPtr( block, extended),
1201 .ret_type => return sema.zirRetType( block, extended),
1202 .this => return sema.zirThis( block, extended),
1203 .ret_addr => return sema.zirRetAddr( block, extended),
1204 .builtin_src => return sema.zirBuiltinSrc( block, extended),
1205 .error_return_trace => return sema.zirErrorReturnTrace( block, extended),
1206 .frame => return sema.zirFrame( block, extended),
1207 .frame_address => return sema.zirFrameAddress( block, extended),
1208 .alloc => return sema.zirAllocExtended( block, extended),
1209 .builtin_extern => return sema.zirBuiltinExtern( block, extended),
1210 .@"asm" => return sema.zirAsm( block, extended),
1211 .typeof_peer => return sema.zirTypeofPeer( block, extended),
1212 .compile_log => return sema.zirCompileLog( block, extended),
1213 .add_with_overflow => return sema.zirOverflowArithmetic(block, extended, extended.opcode),
1214 .sub_with_overflow => return sema.zirOverflowArithmetic(block, extended, extended.opcode),
1215 .mul_with_overflow => return sema.zirOverflowArithmetic(block, extended, extended.opcode),
1216 .shl_with_overflow => return sema.zirOverflowArithmetic(block, extended, extended.opcode),
1217 .c_undef => return sema.zirCUndef( block, extended),
1218 .c_include => return sema.zirCInclude( block, extended),
1219 .c_define => return sema.zirCDefine( block, extended),
1220 .wasm_memory_size => return sema.zirWasmMemorySize( block, extended),
1221 .wasm_memory_grow => return sema.zirWasmMemoryGrow( block, extended),
1222 .prefetch => return sema.zirPrefetch( block, extended),
1223 // zig fmt: on
1224 }
1225}
1226
1227pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) Air.Inst.Ref {1253pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) Air.Inst.Ref {
1228 var i: usize = @enumToInt(zir_ref);1254 var i: usize = @enumToInt(zir_ref);
12291255
...@@ -4241,6 +4267,24 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi...@@ -4241,6 +4267,24 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi
4241 });4267 });
4242}4268}
42434269
4270fn zirDbgBlockBegin(sema: *Sema, block: *Block) CompileError!void {
4271 if (block.is_comptime or sema.mod.comp.bin_file.options.strip) return;
4272
4273 _ = try block.addInst(.{
4274 .tag = .dbg_block_begin,
4275 .data = undefined,
4276 });
4277}
4278
4279fn zirDbgBlockEnd(sema: *Sema, block: *Block) CompileError!void {
4280 if (block.is_comptime or sema.mod.comp.bin_file.options.strip) return;
4281
4282 _ = try block.addInst(.{
4283 .tag = .dbg_block_end,
4284 .data = undefined,
4285 });
4286}
4287
4244fn zirDbgVar(4288fn zirDbgVar(
4245 sema: *Sema,4289 sema: *Sema,
4246 block: *Block,4290 block: *Block,
...@@ -4251,6 +4295,17 @@ fn zirDbgVar(...@@ -4251,6 +4295,17 @@ fn zirDbgVar(
42514295
4252 const str_op = sema.code.instructions.items(.data)[inst].str_op;4296 const str_op = sema.code.instructions.items(.data)[inst].str_op;
4253 const operand = sema.resolveInst(str_op.operand);4297 const operand = sema.resolveInst(str_op.operand);
4298 const name = str_op.getStr(sema.code);
4299 try sema.addDbgVar(block, operand, air_tag, name);
4300}
4301
4302fn addDbgVar(
4303 sema: *Sema,
4304 block: *Block,
4305 operand: Air.Inst.Ref,
4306 air_tag: Air.Inst.Tag,
4307 name: []const u8,
4308) CompileError!void {
4254 const operand_ty = sema.typeOf(operand);4309 const operand_ty = sema.typeOf(operand);
4255 switch (air_tag) {4310 switch (air_tag) {
4256 .dbg_var_ptr => {4311 .dbg_var_ptr => {
...@@ -4261,7 +4316,6 @@ fn zirDbgVar(...@@ -4261,7 +4316,6 @@ fn zirDbgVar(
4261 },4316 },
4262 else => unreachable,4317 else => unreachable,
4263 }4318 }
4264 const name = str_op.getStr(sema.code);
42654319
4266 // Add the name to the AIR.4320 // Add the name to the AIR.
4267 const name_extra_index = @intCast(u32, sema.air_extra.items.len);4321 const name_extra_index = @intCast(u32, sema.air_extra.items.len);
...@@ -4817,6 +4871,25 @@ fn analyzeCall(...@@ -4817,6 +4871,25 @@ fn analyzeCall(
4817 const new_func_resolved_ty = try Type.Tag.function.create(sema.arena, new_fn_info);4871 const new_func_resolved_ty = try Type.Tag.function.create(sema.arena, new_fn_info);
4818 if (!is_comptime_call) {4872 if (!is_comptime_call) {
4819 try sema.emitDbgInline(block, parent_func.?, module_fn, new_func_resolved_ty, .dbg_inline_begin);4873 try sema.emitDbgInline(block, parent_func.?, module_fn, new_func_resolved_ty, .dbg_inline_begin);
4874
4875 for (fn_info.param_body) |param| switch (zir_tags[param]) {
4876 .param, .param_comptime => {
4877 const inst_data = sema.code.instructions.items(.data)[param].pl_tok;
4878 const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index);
4879 const param_name = sema.code.nullTerminatedString(extra.data.name);
4880 const inst = sema.inst_map.get(param).?;
4881
4882 try sema.addDbgVar(&child_block, inst, .dbg_var_val, param_name);
4883 },
4884 .param_anytype, .param_anytype_comptime => {
4885 const inst_data = sema.code.instructions.items(.data)[param].str_tok;
4886 const param_name = inst_data.get(sema.code);
4887 const inst = sema.inst_map.get(param).?;
4888
4889 try sema.addDbgVar(&child_block, inst, .dbg_var_val, param_name);
4890 },
4891 else => continue,
4892 };
4820 }4893 }
48214894
4822 const result = result: {4895 const result = result: {
...@@ -5250,7 +5323,9 @@ fn emitDbgInline(...@@ -5250,7 +5323,9 @@ fn emitDbgInline(
5250 new_func_ty: Type,5323 new_func_ty: Type,
5251 tag: Air.Inst.Tag,5324 tag: Air.Inst.Tag,
5252) CompileError!void {5325) CompileError!void {
5253 // No change of file; no dbg_inline needed.5326 if (sema.mod.comp.bin_file.options.strip) return;
5327
5328 // Recursive inline call; no dbg_inline needed.
5254 if (old_func == new_func) return;5329 if (old_func == new_func) return;
52555330
5256 try sema.air_values.append(sema.gpa, try Value.Tag.function.create(sema.arena, new_func));5331 try sema.air_values.append(sema.gpa, try Value.Tag.function.create(sema.arena, new_func));
src/Zir.zig+4
...@@ -1646,6 +1646,10 @@ pub const Inst = struct {...@@ -1646,6 +1646,10 @@ pub const Inst = struct {
1646 /// The `@prefetch` builtin.1646 /// The `@prefetch` builtin.
1647 /// `operand` is payload index to `BinNode`.1647 /// `operand` is payload index to `BinNode`.
1648 prefetch,1648 prefetch,
1649 /// Marks the beginning of a semantic scope for debug info variables.
1650 dbg_block_begin,
1651 /// Marks the end of a semantic scope for debug info variables.
1652 dbg_block_end,
16491653
1650 pub const InstData = struct {1654 pub const InstData = struct {
1651 opcode: Extended,1655 opcode: Extended,
src/arch/aarch64/CodeGen.zig+9
...@@ -654,6 +654,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -654,6 +654,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
654 .dbg_inline_end,654 .dbg_inline_end,
655 => try self.airDbgInline(inst),655 => try self.airDbgInline(inst),
656656
657 .dbg_block_begin,
658 .dbg_block_end,
659 => try self.airDbgBlock(inst),
660
657 .call => try self.airCall(inst, .auto),661 .call => try self.airCall(inst, .auto),
658 .call_always_tail => try self.airCall(inst, .always_tail),662 .call_always_tail => try self.airCall(inst, .always_tail),
659 .call_never_tail => try self.airCall(inst, .never_tail),663 .call_never_tail => try self.airCall(inst, .never_tail),
...@@ -2731,6 +2735,11 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {...@@ -2731,6 +2735,11 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
2731 return self.finishAir(inst, .dead, .{ .none, .none, .none });2735 return self.finishAir(inst, .dead, .{ .none, .none, .none });
2732}2736}
27332737
2738fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
2739 // TODO emit debug info lexical block
2740 return self.finishAir(inst, .dead, .{ .none, .none, .none });
2741}
2742
2734fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {2743fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
2735 const pl_op = self.air.instructions.items(.data)[inst].pl_op;2744 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
2736 const name = self.air.nullTerminatedString(pl_op.payload);2745 const name = self.air.nullTerminatedString(pl_op.payload);
src/arch/arm/CodeGen.zig+9
...@@ -644,6 +644,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -644,6 +644,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
644 .dbg_inline_end,644 .dbg_inline_end,
645 => try self.airDbgInline(inst),645 => try self.airDbgInline(inst),
646646
647 .dbg_block_begin,
648 .dbg_block_end,
649 => try self.airDbgBlock(inst),
650
647 .call => try self.airCall(inst, .auto),651 .call => try self.airCall(inst, .auto),
648 .call_always_tail => try self.airCall(inst, .always_tail),652 .call_always_tail => try self.airCall(inst, .always_tail),
649 .call_never_tail => try self.airCall(inst, .never_tail),653 .call_never_tail => try self.airCall(inst, .never_tail),
...@@ -2948,6 +2952,11 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {...@@ -2948,6 +2952,11 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
2948 return self.finishAir(inst, .dead, .{ .none, .none, .none });2952 return self.finishAir(inst, .dead, .{ .none, .none, .none });
2949}2953}
29502954
2955fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
2956 // TODO emit debug info lexical block
2957 return self.finishAir(inst, .dead, .{ .none, .none, .none });
2958}
2959
2951fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {2960fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
2952 const pl_op = self.air.instructions.items(.data)[inst].pl_op;2961 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
2953 const name = self.air.nullTerminatedString(pl_op.payload);2962 const name = self.air.nullTerminatedString(pl_op.payload);
src/arch/riscv64/CodeGen.zig+9
...@@ -618,6 +618,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -618,6 +618,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
618 .dbg_inline_end,618 .dbg_inline_end,
619 => try self.airDbgInline(inst),619 => try self.airDbgInline(inst),
620620
621 .dbg_block_begin,
622 .dbg_block_end,
623 => try self.airDbgBlock(inst),
624
621 .call => try self.airCall(inst, .auto),625 .call => try self.airCall(inst, .auto),
622 .call_always_tail => try self.airCall(inst, .always_tail),626 .call_always_tail => try self.airCall(inst, .always_tail),
623 .call_never_tail => try self.airCall(inst, .never_tail),627 .call_never_tail => try self.airCall(inst, .never_tail),
...@@ -1653,6 +1657,11 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {...@@ -1653,6 +1657,11 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
1653 return self.finishAir(inst, .dead, .{ .none, .none, .none });1657 return self.finishAir(inst, .dead, .{ .none, .none, .none });
1654}1658}
16551659
1660fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
1661 // TODO emit debug info lexical block
1662 return self.finishAir(inst, .dead, .{ .none, .none, .none });
1663}
1664
1656fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {1665fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
1657 const pl_op = self.air.instructions.items(.data)[inst].pl_op;1666 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
1658 const name = self.air.nullTerminatedString(pl_op.payload);1667 const name = self.air.nullTerminatedString(pl_op.payload);
src/arch/wasm/CodeGen.zig+2
...@@ -1330,6 +1330,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {...@@ -1330,6 +1330,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
1330 .dbg_stmt,1330 .dbg_stmt,
1331 .dbg_inline_begin,1331 .dbg_inline_begin,
1332 .dbg_inline_end,1332 .dbg_inline_end,
1333 .dbg_block_begin,
1334 .dbg_block_end,
1333 .dbg_var_ptr,1335 .dbg_var_ptr,
1334 .dbg_var_val,1336 .dbg_var_val,
1335 => WValue.none,1337 => WValue.none,
src/arch/x86_64/CodeGen.zig+9
...@@ -735,6 +735,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -735,6 +735,10 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
735 .dbg_inline_end,735 .dbg_inline_end,
736 => try self.airDbgInline(inst),736 => try self.airDbgInline(inst),
737737
738 .dbg_block_begin,
739 .dbg_block_end,
740 => try self.airDbgBlock(inst),
741
738 .call => try self.airCall(inst, .auto),742 .call => try self.airCall(inst, .auto),
739 .call_always_tail => try self.airCall(inst, .always_tail),743 .call_always_tail => try self.airCall(inst, .always_tail),
740 .call_never_tail => try self.airCall(inst, .never_tail),744 .call_never_tail => try self.airCall(inst, .never_tail),
...@@ -3683,6 +3687,11 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {...@@ -3683,6 +3687,11 @@ fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
3683 return self.finishAir(inst, .dead, .{ .none, .none, .none });3687 return self.finishAir(inst, .dead, .{ .none, .none, .none });
3684}3688}
36853689
3690fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
3691 // TODO emit debug info lexical block
3692 return self.finishAir(inst, .dead, .{ .none, .none, .none });
3693}
3694
3686fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {3695fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
3687 const pl_op = self.air.instructions.items(.data)[inst].pl_op;3696 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3688 const name = self.air.nullTerminatedString(pl_op.payload);3697 const name = self.air.nullTerminatedString(pl_op.payload);
src/codegen/c.zig+4
...@@ -1786,6 +1786,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -1786,6 +1786,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
1786 .dbg_inline_end,1786 .dbg_inline_end,
1787 => try airDbgInline(f, inst),1787 => try airDbgInline(f, inst),
17881788
1789 .dbg_block_begin,
1790 .dbg_block_end,
1791 => CValue{ .none = {} },
1792
1789 .call => try airCall(f, inst, .auto),1793 .call => try airCall(f, inst, .auto),
1790 .call_always_tail => try airCall(f, inst, .always_tail),1794 .call_always_tail => try airCall(f, inst, .always_tail),
1791 .call_never_tail => try airCall(f, inst, .never_tail),1795 .call_never_tail => try airCall(f, inst, .never_tail),
src/codegen/llvm.zig+22
...@@ -3220,6 +3220,10 @@ pub const FuncGen = struct {...@@ -3220,6 +3220,10 @@ pub const FuncGen = struct {
3220 /// Stack of locations where a call was inlined.3220 /// Stack of locations where a call was inlined.
3221 dbg_inlined: std.ArrayListUnmanaged(DbgState) = .{},3221 dbg_inlined: std.ArrayListUnmanaged(DbgState) = .{},
32223222
3223 /// Stack of `DILexicalBlock`s. dbg_block instructions cannot happend accross
3224 /// dbg_inline instructions so no special handling there is required.
3225 dbg_block_stack: std.ArrayListUnmanaged(*llvm.DIScope) = .{},
3226
3223 /// This stores the LLVM values used in a function, such that they can be referred to3227 /// This stores the LLVM values used in a function, such that they can be referred to
3224 /// in other instructions. This table is cleared before every function is generated.3228 /// in other instructions. This table is cleared before every function is generated.
3225 func_inst_table: std.AutoHashMapUnmanaged(Air.Inst.Ref, *const llvm.Value),3229 func_inst_table: std.AutoHashMapUnmanaged(Air.Inst.Ref, *const llvm.Value),
...@@ -3254,6 +3258,7 @@ pub const FuncGen = struct {...@@ -3254,6 +3258,7 @@ pub const FuncGen = struct {
3254 fn deinit(self: *FuncGen) void {3258 fn deinit(self: *FuncGen) void {
3255 self.builder.dispose();3259 self.builder.dispose();
3256 self.dbg_inlined.deinit(self.gpa);3260 self.dbg_inlined.deinit(self.gpa);
3261 self.dbg_block_stack.deinit(self.gpa);
3257 self.func_inst_table.deinit(self.gpa);3262 self.func_inst_table.deinit(self.gpa);
3258 self.blocks.deinit(self.gpa);3263 self.blocks.deinit(self.gpa);
3259 }3264 }
...@@ -3475,6 +3480,8 @@ pub const FuncGen = struct {...@@ -3475,6 +3480,8 @@ pub const FuncGen = struct {
3475 .dbg_stmt => self.airDbgStmt(inst),3480 .dbg_stmt => self.airDbgStmt(inst),
3476 .dbg_inline_begin => try self.airDbgInlineBegin(inst),3481 .dbg_inline_begin => try self.airDbgInlineBegin(inst),
3477 .dbg_inline_end => try self.airDbgInlineEnd(inst),3482 .dbg_inline_end => try self.airDbgInlineEnd(inst),
3483 .dbg_block_begin => try self.airDbgBlockBegin(),
3484 .dbg_block_end => try self.airDbgBlockEnd(),
3478 .dbg_var_ptr => try self.airDbgVarPtr(inst),3485 .dbg_var_ptr => try self.airDbgVarPtr(inst),
3479 .dbg_var_val => try self.airDbgVarVal(inst),3486 .dbg_var_val => try self.airDbgVarVal(inst),
3480 // zig fmt: on3487 // zig fmt: on
...@@ -4256,6 +4263,21 @@ pub const FuncGen = struct {...@@ -4256,6 +4263,21 @@ pub const FuncGen = struct {
4256 return null;4263 return null;
4257 }4264 }
42584265
4266 fn airDbgBlockBegin(self: *FuncGen) !?*const llvm.Value {
4267 const dib = self.dg.object.di_builder orelse return null;
4268 const old_scope = self.di_scope.?;
4269 try self.dbg_block_stack.append(self.gpa, old_scope);
4270 const lexical_block = dib.createLexicalBlock(old_scope, self.di_file.?, self.prev_dbg_line, self.prev_dbg_column);
4271 self.di_scope = lexical_block.toScope();
4272 return null;
4273 }
4274
4275 fn airDbgBlockEnd(self: *FuncGen) !?*const llvm.Value {
4276 if (self.dg.object.di_builder == null) return null;
4277 self.di_scope = self.dbg_block_stack.pop();
4278 return null;
4279 }
4280
4259 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {4281 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
4260 const dib = self.dg.object.di_builder orelse return null;4282 const dib = self.dg.object.di_builder orelse return null;
4261 const pl_op = self.air.instructions.items(.data)[inst].pl_op;4283 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
src/print_air.zig+4-2
...@@ -272,6 +272,8 @@ const Writer = struct {...@@ -272,6 +272,8 @@ const Writer = struct {
272 .mul_with_overflow,272 .mul_with_overflow,
273 .shl_with_overflow,273 .shl_with_overflow,
274 => try w.writeOverflow(s, inst),274 => try w.writeOverflow(s, inst),
275
276 .dbg_block_begin, .dbg_block_end => {},
275 }277 }
276 }278 }
277279
...@@ -384,8 +386,8 @@ const Writer = struct {...@@ -384,8 +386,8 @@ const Writer = struct {
384 }386 }
385387
386 fn writeShuffle(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {388 fn writeShuffle(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
387 const pl_op = w.air.instructions.items(.data)[inst].pl_op;389 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
388 const extra = w.air.extraData(Air.Shuffle, pl_op.payload).data;390 const extra = w.air.extraData(Air.Shuffle, ty_pl.payload).data;
389391
390 try w.writeOperand(s, inst, 0, extra.a);392 try w.writeOperand(s, inst, 0, extra.a);
391 try s.writeAll(", ");393 try s.writeAll(", ");
src/print_zir.zig+4
...@@ -463,6 +463,10 @@ const Writer = struct {...@@ -463,6 +463,10 @@ const Writer = struct {
463 .builtin_src,463 .builtin_src,
464 => try self.writeExtNode(stream, extended),464 => try self.writeExtNode(stream, extended),
465465
466 .dbg_block_begin,
467 .dbg_block_end,
468 => try stream.writeAll("))"),
469
466 .@"asm" => try self.writeAsm(stream, extended),470 .@"asm" => try self.writeAsm(stream, extended),
467 .func => try self.writeFuncExtended(stream, extended),471 .func => try self.writeFuncExtended(stream, extended),
468 .variable => try self.writeVarExtended(stream, extended),472 .variable => try self.writeVarExtended(stream, extended),
test/behavior/struct.zig+2
...@@ -427,6 +427,7 @@ test "packed struct 24bits" {...@@ -427,6 +427,7 @@ test "packed struct 24bits" {
427 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO427 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
428 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO428 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
429 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO429 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO
430 if (builtin.cpu.arch == .arm) return error.SkipZigTest; // TODO
430431
431 comptime {432 comptime {
432 try expect(@sizeOf(Foo24Bits) == 4);433 try expect(@sizeOf(Foo24Bits) == 4);
...@@ -979,6 +980,7 @@ test "tuple assigned to variable" {...@@ -979,6 +980,7 @@ test "tuple assigned to variable" {
979980
980test "comptime struct field" {981test "comptime struct field" {
981 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO982 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
983 if (builtin.stage2_arch == .arm) return error.SkipZigTest; // TODO
982984
983 const T = struct {985 const T = struct {
984 a: i32,986 a: i32,
test/behavior/while.zig+3
...@@ -173,6 +173,7 @@ test "while with optional as condition with else" {...@@ -173,6 +173,7 @@ test "while with optional as condition with else" {
173}173}
174174
175test "while with error union condition" {175test "while with error union condition" {
176 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
176 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;177 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
177 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;178 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
178179
...@@ -289,6 +290,7 @@ test "while bool 2 break statements and an else" {...@@ -289,6 +290,7 @@ test "while bool 2 break statements and an else" {
289}290}
290291
291test "while optional 2 break statements and an else" {292test "while optional 2 break statements and an else" {
293 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
292 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO294 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
293 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO295 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
294296
...@@ -307,6 +309,7 @@ test "while optional 2 break statements and an else" {...@@ -307,6 +309,7 @@ test "while optional 2 break statements and an else" {
307}309}
308310
309test "while error 2 break statements and an else" {311test "while error 2 break statements and an else" {
312 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
310 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO313 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
311 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO314 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
312315