authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-11-24 04:11:52-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-11-24 17:28:12-05:00
logc894ac09a31380319ba9cfdc82025fcc614a8cc0
tree5f1b32932432f1c414fbe20aa3288ead4fbc2b44
parent6d781e0955e7dd2b6cc17a5bb43c790e19a07ac0

dwarf: fix stepping through an inline loop containing one statement

Previously, stepping from the single statement within the loop would always exit the loop because all of the code unrolled from the loop is associated with the same line and treated by the debugger as one line.

25 files changed, 721 insertions(+), 221 deletions(-)

lib/std/zig/AstGen.zig+28-5
...@@ -6024,7 +6024,7 @@ fn tryExpr(...@@ -6024,7 +6024,7 @@ fn tryExpr(
6024 if (!parent_gz.is_comptime) {6024 if (!parent_gz.is_comptime) {
6025 try emitDbgNode(parent_gz, node);6025 try emitDbgNode(parent_gz, node);
6026 }6026 }
6027 const try_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };6027 const try_lc: LineColumn = .{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
60286028
6029 const operand_rl: ResultInfo.Loc, const block_tag: Zir.Inst.Tag = switch (ri.rl) {6029 const operand_rl: ResultInfo.Loc, const block_tag: Zir.Inst.Tag = switch (ri.rl) {
6030 .ref => .{ .ref, .try_ptr },6030 .ref => .{ .ref, .try_ptr },
...@@ -6577,6 +6577,7 @@ fn whileExpr(...@@ -6577,6 +6577,7 @@ fn whileExpr(
6577 const astgen = parent_gz.astgen;6577 const astgen = parent_gz.astgen;
6578 const tree = astgen.tree;6578 const tree = astgen.tree;
6579 const token_tags = tree.tokens.items(.tag);6579 const token_tags = tree.tokens.items(.tag);
6580 const token_starts = tree.tokens.items(.start);
65806581
6581 const need_rl = astgen.nodes_need_rl.contains(node);6582 const need_rl = astgen.nodes_need_rl.contains(node);
6582 const block_ri: ResultInfo = if (need_rl) ri else .{6583 const block_ri: ResultInfo = if (need_rl) ri else .{
...@@ -6774,6 +6775,16 @@ fn whileExpr(...@@ -6774,6 +6775,16 @@ fn whileExpr(
6774 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);6775 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
6775 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";6776 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
6776 if (!continue_scope.endsWithNoReturn()) {6777 if (!continue_scope.endsWithNoReturn()) {
6778 astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]);
6779 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });
6780 _ = try parent_gz.add(.{
6781 .tag = .extended,
6782 .data = .{ .extended = .{
6783 .opcode = .dbg_empty_stmt,
6784 .small = undefined,
6785 .operand = undefined,
6786 } },
6787 });
6777 _ = try continue_scope.addBreak(break_tag, continue_block, .void_value);6788 _ = try continue_scope.addBreak(break_tag, continue_block, .void_value);
6778 }6789 }
6779 try continue_scope.setBlockBody(continue_block);6790 try continue_scope.setBlockBody(continue_block);
...@@ -6882,6 +6893,7 @@ fn forExpr(...@@ -6882,6 +6893,7 @@ fn forExpr(
6882 }6893 }
6883 const tree = astgen.tree;6894 const tree = astgen.tree;
6884 const token_tags = tree.tokens.items(.tag);6895 const token_tags = tree.tokens.items(.tag);
6896 const token_starts = tree.tokens.items(.start);
6885 const node_tags = tree.nodes.items(.tag);6897 const node_tags = tree.nodes.items(.tag);
6886 const node_data = tree.nodes.items(.data);6898 const node_data = tree.nodes.items(.data);
6887 const gpa = astgen.gpa;6899 const gpa = astgen.gpa;
...@@ -7087,8 +7099,18 @@ fn forExpr(...@@ -7087,8 +7099,18 @@ fn forExpr(
70877099
7088 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);7100 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
70897101
7090 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";7102 astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]);
7103 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });
7104 _ = try parent_gz.add(.{
7105 .tag = .extended,
7106 .data = .{ .extended = .{
7107 .opcode = .dbg_empty_stmt,
7108 .small = undefined,
7109 .operand = undefined,
7110 } },
7111 });
70917112
7113 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
7092 _ = try then_scope.addBreak(break_tag, cond_block, .void_value);7114 _ = try then_scope.addBreak(break_tag, cond_block, .void_value);
70937115
7094 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);7116 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
...@@ -7135,6 +7157,7 @@ fn forExpr(...@@ -7135,6 +7157,7 @@ fn forExpr(
7135 .lhs = index_ptr,7157 .lhs = index_ptr,
7136 .rhs = index_plus_one,7158 .rhs = index_plus_one,
7137 });7159 });
7160
7138 const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;7161 const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
7139 _ = try loop_scope.addNode(repeat_tag, node);7162 _ = try loop_scope.addNode(repeat_tag, node);
71407163
...@@ -7279,7 +7302,7 @@ fn switchExprErrUnion(...@@ -7279,7 +7302,7 @@ fn switchExprErrUnion(
7279 };7302 };
72807303
7281 astgen.advanceSourceCursorToNode(operand_node);7304 astgen.advanceSourceCursorToNode(operand_node);
7282 const operand_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };7305 const operand_lc: LineColumn = .{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
72837306
7284 const raw_operand = try reachableExpr(parent_gz, scope, operand_ri, operand_node, switch_node);7307 const raw_operand = try reachableExpr(parent_gz, scope, operand_ri, operand_node, switch_node);
7285 const item_ri: ResultInfo = .{ .rl = .none };7308 const item_ri: ResultInfo = .{ .rl = .none };
...@@ -7868,7 +7891,7 @@ fn switchExpr(...@@ -7868,7 +7891,7 @@ fn switchExpr(
7868 const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none };7891 const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none };
78697892
7870 astgen.advanceSourceCursorToNode(operand_node);7893 astgen.advanceSourceCursorToNode(operand_node);
7871 const operand_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };7894 const operand_lc: LineColumn = .{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
78727895
7873 const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);7896 const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);
7874 const item_ri: ResultInfo = .{ .rl = .none };7897 const item_ri: ResultInfo = .{ .rl = .none };
...@@ -8214,7 +8237,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -8214,7 +8237,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
8214 if (!gz.is_comptime) {8237 if (!gz.is_comptime) {
8215 try emitDbgNode(gz, node);8238 try emitDbgNode(gz, node);
8216 }8239 }
8217 const ret_lc = LineColumn{ astgen.source_line - gz.decl_line, astgen.source_column };8240 const ret_lc: LineColumn = .{ astgen.source_line - gz.decl_line, astgen.source_column };
82188241
8219 const defer_outer = &astgen.fn_block.?.base;8242 const defer_outer = &astgen.fn_block.?.base;
82208243
lib/std/zig/Zir.zig+3
...@@ -2088,6 +2088,8 @@ pub const Inst = struct {...@@ -2088,6 +2088,8 @@ pub const Inst = struct {
2088 /// `operand` is `Zir.Inst.Ref` of the loaded LHS (*not* its type).2088 /// `operand` is `Zir.Inst.Ref` of the loaded LHS (*not* its type).
2089 /// `small` is an `Inst.InplaceOp`.2089 /// `small` is an `Inst.InplaceOp`.
2090 inplace_arith_result_ty,2090 inplace_arith_result_ty,
2091 /// Marks a statement that can be stepped to but produces no code.
2092 dbg_empty_stmt,
20912093
2092 pub const InstData = struct {2094 pub const InstData = struct {
2093 opcode: Extended,2095 opcode: Extended,
...@@ -4062,6 +4064,7 @@ fn findDeclsInner(...@@ -4062,6 +4064,7 @@ fn findDeclsInner(
4062 .branch_hint,4064 .branch_hint,
4063 .inplace_arith_result_ty,4065 .inplace_arith_result_ty,
4064 .tuple_decl,4066 .tuple_decl,
4067 .dbg_empty_stmt,
4065 => return,4068 => return,
40664069
4067 // `@TypeOf` has a body.4070 // `@TypeOf` has a body.
src/Air.zig+4
...@@ -460,6 +460,8 @@ pub const Inst = struct {...@@ -460,6 +460,8 @@ pub const Inst = struct {
460 /// Result type is always void.460 /// Result type is always void.
461 /// Uses the `dbg_stmt` field.461 /// Uses the `dbg_stmt` field.
462 dbg_stmt,462 dbg_stmt,
463 /// Marks a statement that can be stepped to but produces no code.
464 dbg_empty_stmt,
463 /// A block that represents an inlined function call.465 /// A block that represents an inlined function call.
464 /// Uses the `ty_pl` field. Payload is `DbgInlineBlock`.466 /// Uses the `ty_pl` field. Payload is `DbgInlineBlock`.
465 dbg_inline_block,467 dbg_inline_block,
...@@ -1468,6 +1470,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)...@@ -1468,6 +1470,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
14681470
1469 .breakpoint,1471 .breakpoint,
1470 .dbg_stmt,1472 .dbg_stmt,
1473 .dbg_empty_stmt,
1471 .dbg_var_ptr,1474 .dbg_var_ptr,
1472 .dbg_var_val,1475 .dbg_var_val,
1473 .dbg_arg_inline,1476 .dbg_arg_inline,
...@@ -1629,6 +1632,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {...@@ -1629,6 +1632,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
1629 .try_ptr,1632 .try_ptr,
1630 .try_ptr_cold,1633 .try_ptr_cold,
1631 .dbg_stmt,1634 .dbg_stmt,
1635 .dbg_empty_stmt,
1632 .dbg_inline_block,1636 .dbg_inline_block,
1633 .dbg_var_ptr,1637 .dbg_var_ptr,
1634 .dbg_var_val,1638 .dbg_var_val,
src/Air/types_resolved.zig+1
...@@ -417,6 +417,7 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool {...@@ -417,6 +417,7 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool {
417 .work_group_size,417 .work_group_size,
418 .work_group_id,418 .work_group_id,
419 .dbg_stmt,419 .dbg_stmt,
420 .dbg_empty_stmt,
420 .err_return_trace,421 .err_return_trace,
421 .save_err_return_trace_index,422 .save_err_return_trace_index,
422 .repeat,423 .repeat,
src/Liveness.zig+2
...@@ -334,6 +334,7 @@ pub fn categorizeOperand(...@@ -334,6 +334,7 @@ pub fn categorizeOperand(
334 .repeat,334 .repeat,
335 .switch_dispatch,335 .switch_dispatch,
336 .dbg_stmt,336 .dbg_stmt,
337 .dbg_empty_stmt,
337 .unreach,338 .unreach,
338 .ret_addr,339 .ret_addr,
339 .frame_addr,340 .frame_addr,
...@@ -973,6 +974,7 @@ fn analyzeInst(...@@ -973,6 +974,7 @@ fn analyzeInst(
973 .ret_ptr,974 .ret_ptr,
974 .breakpoint,975 .breakpoint,
975 .dbg_stmt,976 .dbg_stmt,
977 .dbg_empty_stmt,
976 .ret_addr,978 .ret_addr,
977 .frame_addr,979 .frame_addr,
978 .wasm_memory_size,980 .wasm_memory_size,
src/Liveness/Verify.zig+1
...@@ -56,6 +56,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -56,6 +56,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
56 .ret_ptr,56 .ret_ptr,
57 .breakpoint,57 .breakpoint,
58 .dbg_stmt,58 .dbg_stmt,
59 .dbg_empty_stmt,
59 .ret_addr,60 .ret_addr,
60 .frame_addr,61 .frame_addr,
61 .wasm_memory_size,62 .wasm_memory_size,
src/Sema.zig+10
...@@ -1355,6 +1355,11 @@ fn analyzeBodyInner(...@@ -1355,6 +1355,11 @@ fn analyzeBodyInner(
1355 .field_parent_ptr => try sema.zirFieldParentPtr(block, extended),1355 .field_parent_ptr => try sema.zirFieldParentPtr(block, extended),
1356 .builtin_value => try sema.zirBuiltinValue(block, extended),1356 .builtin_value => try sema.zirBuiltinValue(block, extended),
1357 .inplace_arith_result_ty => try sema.zirInplaceArithResultTy(extended),1357 .inplace_arith_result_ty => try sema.zirInplaceArithResultTy(extended),
1358 .dbg_empty_stmt => {
1359 try sema.zirDbgEmptyStmt(block, inst);
1360 i += 1;
1361 continue;
1362 },
1358 };1363 };
1359 },1364 },
13601365
...@@ -6671,6 +6676,11 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi...@@ -6671,6 +6676,11 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi
6671 });6676 });
6672}6677}
66736678
6679fn zirDbgEmptyStmt(_: *Sema, block: *Block, _: Zir.Inst.Index) CompileError!void {
6680 if (block.is_comptime or block.ownerModule().strip) return;
6681 _ = try block.addNoOp(.dbg_empty_stmt);
6682}
6683
6674fn zirDbgVar(6684fn zirDbgVar(
6675 sema: *Sema,6685 sema: *Sema,
6676 block: *Block,6686 block: *Block,
src/arch/aarch64/CodeGen.zig+1
...@@ -800,6 +800,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -800,6 +800,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
800 .try_ptr_cold => try self.airTryPtr(inst),800 .try_ptr_cold => try self.airTryPtr(inst),
801801
802 .dbg_stmt => try self.airDbgStmt(inst),802 .dbg_stmt => try self.airDbgStmt(inst),
803 .dbg_empty_stmt => self.finishAirBookkeeping(),
803 .dbg_inline_block => try self.airDbgInlineBlock(inst),804 .dbg_inline_block => try self.airDbgInlineBlock(inst),
804 .dbg_var_ptr,805 .dbg_var_ptr,
805 .dbg_var_val,806 .dbg_var_val,
src/arch/arm/CodeGen.zig+1
...@@ -787,6 +787,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -787,6 +787,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
787 .try_ptr_cold => try self.airTryPtr(inst),787 .try_ptr_cold => try self.airTryPtr(inst),
788788
789 .dbg_stmt => try self.airDbgStmt(inst),789 .dbg_stmt => try self.airDbgStmt(inst),
790 .dbg_empty_stmt => self.finishAirBookkeeping(),
790 .dbg_inline_block => try self.airDbgInlineBlock(inst),791 .dbg_inline_block => try self.airDbgInlineBlock(inst),
791 .dbg_var_ptr,792 .dbg_var_ptr,
792 .dbg_var_val,793 .dbg_var_val,
src/arch/riscv64/CodeGen.zig+1
...@@ -1593,6 +1593,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {...@@ -1593,6 +1593,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
1593 .frame_addr => try func.airFrameAddress(inst),1593 .frame_addr => try func.airFrameAddress(inst),
1594 .cond_br => try func.airCondBr(inst),1594 .cond_br => try func.airCondBr(inst),
1595 .dbg_stmt => try func.airDbgStmt(inst),1595 .dbg_stmt => try func.airDbgStmt(inst),
1596 .dbg_empty_stmt => func.finishAirBookkeeping(),
1596 .fptrunc => try func.airFptrunc(inst),1597 .fptrunc => try func.airFptrunc(inst),
1597 .fpext => try func.airFpext(inst),1598 .fpext => try func.airFpext(inst),
1598 .intcast => try func.airIntCast(inst),1599 .intcast => try func.airIntCast(inst),
src/arch/sparc64/CodeGen.zig+1
...@@ -642,6 +642,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -642,6 +642,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
642 .try_ptr_cold => @panic("TODO try self.airTryPtrCold(inst)"),642 .try_ptr_cold => @panic("TODO try self.airTryPtrCold(inst)"),
643643
644 .dbg_stmt => try self.airDbgStmt(inst),644 .dbg_stmt => try self.airDbgStmt(inst),
645 .dbg_empty_stmt => self.finishAirBookkeeping(),
645 .dbg_inline_block => try self.airDbgInlineBlock(inst),646 .dbg_inline_block => try self.airDbgInlineBlock(inst),
646 .dbg_var_ptr,647 .dbg_var_ptr,
647 .dbg_var_val,648 .dbg_var_val,
src/arch/wasm/CodeGen.zig+1
...@@ -1924,6 +1924,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1924,6 +1924,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1924 .try_ptr_cold => func.airTryPtr(inst),1924 .try_ptr_cold => func.airTryPtr(inst),
19251925
1926 .dbg_stmt => func.airDbgStmt(inst),1926 .dbg_stmt => func.airDbgStmt(inst),
1927 .dbg_empty_stmt => try func.finishAir(inst, .none, &.{}),
1927 .dbg_inline_block => func.airDbgInlineBlock(inst),1928 .dbg_inline_block => func.airDbgInlineBlock(inst),
1928 .dbg_var_ptr => func.airDbgVar(inst, .local_var, true),1929 .dbg_var_ptr => func.airDbgVar(inst, .local_var, true),
1929 .dbg_var_val => func.airDbgVar(inst, .local_var, false),1930 .dbg_var_val => func.airDbgVar(inst, .local_var, false),
src/arch/x86_64/CodeGen.zig+26-15
...@@ -961,9 +961,16 @@ pub fn generate(...@@ -961,9 +961,16 @@ pub fn generate(
961 },961 },
962 .debug_output = debug_output,962 .debug_output = debug_output,
963 .code = code,963 .code = code,
964 .prev_di_loc = .{
965 .line = func.lbrace_line,
966 .column = func.lbrace_column,
967 .is_stmt = switch (debug_output) {
968 .dwarf => |dwarf| dwarf.dwarf.debug_line.header.default_is_stmt,
969 .plan9 => undefined,
970 .none => undefined,
971 },
972 },
964 .prev_di_pc = 0,973 .prev_di_pc = 0,
965 .prev_di_line = func.lbrace_line,
966 .prev_di_column = func.lbrace_column,
967 };974 };
968 defer emit.deinit();975 defer emit.deinit();
969 emit.emitMir() catch |err| switch (err) {976 emit.emitMir() catch |err| switch (err) {
...@@ -1066,9 +1073,8 @@ pub fn generateLazy(...@@ -1066,9 +1073,8 @@ pub fn generateLazy(
1066 },1073 },
1067 .debug_output = debug_output,1074 .debug_output = debug_output,
1068 .code = code,1075 .code = code,
1076 .prev_di_loc = undefined, // no debug info yet
1069 .prev_di_pc = undefined, // no debug info yet1077 .prev_di_pc = undefined, // no debug info yet
1070 .prev_di_line = undefined, // no debug info yet
1071 .prev_di_column = undefined, // no debug info yet
1072 };1078 };
1073 defer emit.deinit();1079 defer emit.deinit();
1074 emit.emitMir() catch |err| switch (err) {1080 emit.emitMir() catch |err| switch (err) {
...@@ -1194,13 +1200,16 @@ fn formatWipMir(...@@ -1194,13 +1200,16 @@ fn formatWipMir(
1194 switch (mir_inst.ops) {1200 switch (mir_inst.ops) {
1195 else => unreachable,1201 else => unreachable,
1196 .pseudo_dbg_prologue_end_none,1202 .pseudo_dbg_prologue_end_none,
1197 .pseudo_dbg_line_line_column,
1198 .pseudo_dbg_epilogue_begin_none,1203 .pseudo_dbg_epilogue_begin_none,
1199 .pseudo_dbg_enter_block_none,1204 .pseudo_dbg_enter_block_none,
1200 .pseudo_dbg_leave_block_none,1205 .pseudo_dbg_leave_block_none,
1201 .pseudo_dbg_var_args_none,1206 .pseudo_dbg_var_args_none,
1202 .pseudo_dead_none,1207 .pseudo_dead_none,
1203 => {},1208 => {},
1209 .pseudo_dbg_line_stmt_line_column, .pseudo_dbg_line_line_column => try writer.print(
1210 " {[line]d}, {[column]d}",
1211 mir_inst.data.line_column,
1212 ),
1204 .pseudo_dbg_enter_inline_func, .pseudo_dbg_leave_inline_func => try writer.print(" {}", .{1213 .pseudo_dbg_enter_inline_func, .pseudo_dbg_leave_inline_func => try writer.print(" {}", .{
1205 ip.getNav(ip.indexToKey(mir_inst.data.func).func.owner_nav).name.fmt(ip),1214 ip.getNav(ip.indexToKey(mir_inst.data.func).func.owner_nav).name.fmt(ip),
1206 }),1215 }),
...@@ -1281,14 +1290,7 @@ fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {...@@ -1281,14 +1290,7 @@ fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
1281 try self.mir_instructions.ensureUnusedCapacity(gpa, 1);1290 try self.mir_instructions.ensureUnusedCapacity(gpa, 1);
1282 const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len);1291 const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len);
1283 self.mir_instructions.appendAssumeCapacity(inst);1292 self.mir_instructions.appendAssumeCapacity(inst);
1284 if (inst.tag != .pseudo or switch (inst.ops) {1293 wip_mir_log.debug("{}", .{self.fmtWipMir(result_index)});
1285 else => true,
1286 .pseudo_dbg_prologue_end_none,
1287 .pseudo_dbg_line_line_column,
1288 .pseudo_dbg_epilogue_begin_none,
1289 .pseudo_dead_none,
1290 => false,
1291 }) wip_mir_log.debug("{}", .{self.fmtWipMir(result_index)});
1292 return result_index;1294 return result_index;
1293}1295}
12941296
...@@ -2218,7 +2220,7 @@ fn gen(self: *Self) InnerError!void {...@@ -2218,7 +2220,7 @@ fn gen(self: *Self) InnerError!void {
2218 // Drop them off at the rbrace.2220 // Drop them off at the rbrace.
2219 _ = try self.addInst(.{2221 _ = try self.addInst(.{
2220 .tag = .pseudo,2222 .tag = .pseudo,
2221 .ops = .pseudo_dbg_line_line_column,2223 .ops = .pseudo_dbg_line_stmt_line_column,
2222 .data = .{ .line_column = .{2224 .data = .{ .line_column = .{
2223 .line = self.end_di_line,2225 .line = self.end_di_line,
2224 .column = self.end_di_column,2226 .column = self.end_di_column,
...@@ -2426,6 +2428,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -2426,6 +2428,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
2426 .try_ptr_cold => try self.airTryPtr(inst), // TODO2428 .try_ptr_cold => try self.airTryPtr(inst), // TODO
24272429
2428 .dbg_stmt => try self.airDbgStmt(inst),2430 .dbg_stmt => try self.airDbgStmt(inst),
2431 .dbg_empty_stmt => try self.airDbgEmptyStmt(),
2429 .dbg_inline_block => try self.airDbgInlineBlock(inst),2432 .dbg_inline_block => try self.airDbgInlineBlock(inst),
2430 .dbg_var_ptr,2433 .dbg_var_ptr,
2431 .dbg_var_val,2434 .dbg_var_val,
...@@ -13281,7 +13284,7 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -13281,7 +13284,7 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
13281 const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;13284 const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
13282 _ = try self.addInst(.{13285 _ = try self.addInst(.{
13283 .tag = .pseudo,13286 .tag = .pseudo,
13284 .ops = .pseudo_dbg_line_line_column,13287 .ops = .pseudo_dbg_line_stmt_line_column,
13285 .data = .{ .line_column = .{13288 .data = .{ .line_column = .{
13286 .line = dbg_stmt.line,13289 .line = dbg_stmt.line,
13287 .column = dbg_stmt.column,13290 .column = dbg_stmt.column,
...@@ -13290,6 +13293,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -13290,6 +13293,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
13290 self.finishAirBookkeeping();13293 self.finishAirBookkeeping();
13291}13294}
1329213295
13296fn airDbgEmptyStmt(self: *Self) !void {
13297 if (self.mir_instructions.len > 0 and
13298 self.mir_instructions.items(.ops)[self.mir_instructions.len - 1] == .pseudo_dbg_line_stmt_line_column)
13299 self.mir_instructions.items(.ops)[self.mir_instructions.len - 1] = .pseudo_dbg_line_line_column;
13300 try self.asmOpOnly(.{ ._, .nop });
13301 self.finishAirBookkeeping();
13302}
13303
13293fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {13304fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {
13294 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;13305 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
13295 const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);13306 const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
src/arch/x86_64/Emit.zig+193-199
...@@ -6,8 +6,7 @@ atom_index: u32,...@@ -6,8 +6,7 @@ atom_index: u32,
6debug_output: link.File.DebugInfoOutput,6debug_output: link.File.DebugInfoOutput,
7code: *std.ArrayList(u8),7code: *std.ArrayList(u8),
88
9prev_di_line: u32,9prev_di_loc: Loc,
10prev_di_column: u32,
11/// Relative to the beginning of `code`.10/// Relative to the beginning of `code`.
12prev_di_pc: usize,11prev_di_pc: usize,
1312
...@@ -263,77 +262,71 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -263,77 +262,71 @@ pub fn emitMir(emit: *Emit) Error!void {
263 else => unreachable,262 else => unreachable,
264 .pseudo => switch (mir_inst.ops) {263 .pseudo => switch (mir_inst.ops) {
265 else => unreachable,264 else => unreachable,
266 .pseudo_dbg_prologue_end_none => {265 .pseudo_dbg_prologue_end_none => switch (emit.debug_output) {
267 switch (emit.debug_output) {266 .dwarf => |dwarf| try dwarf.setPrologueEnd(),
268 .dwarf => |dw| try dw.setPrologueEnd(),267 .plan9 => {},
269 .plan9 => {},268 .none => {},
270 .none => {},
271 }
272 },269 },
273 .pseudo_dbg_line_line_column => try emit.dbgAdvancePCAndLine(270 .pseudo_dbg_line_stmt_line_column => try emit.dbgAdvancePCAndLine(.{
274 mir_inst.data.line_column.line,271 .line = mir_inst.data.line_column.line,
275 mir_inst.data.line_column.column,272 .column = mir_inst.data.line_column.column,
276 ),273 .is_stmt = true,
277 .pseudo_dbg_epilogue_begin_none => {274 }),
278 switch (emit.debug_output) {275 .pseudo_dbg_line_line_column => try emit.dbgAdvancePCAndLine(.{
279 .dwarf => |dw| {276 .line = mir_inst.data.line_column.line,
280 try dw.setEpilogueBegin();277 .column = mir_inst.data.line_column.column,
281 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{278 .is_stmt = false,
282 emit.prev_di_line, emit.prev_di_column,279 }),
283 });280 .pseudo_dbg_epilogue_begin_none => switch (emit.debug_output) {
284 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);281 .dwarf => |dwarf| {
285 },282 try dwarf.setEpilogueBegin();
286 .plan9 => {},283 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
287 .none => {},284 emit.prev_di_loc.line, emit.prev_di_loc.column,
288 }285 });
286 try emit.dbgAdvancePCAndLine(emit.prev_di_loc);
287 },
288 .plan9 => {},
289 .none => {},
289 },290 },
290 .pseudo_dbg_enter_block_none => {291 .pseudo_dbg_enter_block_none => switch (emit.debug_output) {
291 switch (emit.debug_output) {292 .dwarf => |dwarf| {
292 .dwarf => |dw| {293 log.debug("mirDbgEnterBlock (line={d}, col={d})", .{
293 log.debug("mirDbgEnterBlock (line={d}, col={d})", .{294 emit.prev_di_loc.line, emit.prev_di_loc.column,
294 emit.prev_di_line, emit.prev_di_column,295 });
295 });296 try dwarf.enterBlock(emit.code.items.len);
296 try dw.enterBlock(emit.code.items.len);297 },
297 },298 .plan9 => {},
298 .plan9 => {},299 .none => {},
299 .none => {},
300 }
301 },300 },
302 .pseudo_dbg_leave_block_none => {301 .pseudo_dbg_leave_block_none => switch (emit.debug_output) {
303 switch (emit.debug_output) {302 .dwarf => |dwarf| {
304 .dwarf => |dw| {303 log.debug("mirDbgLeaveBlock (line={d}, col={d})", .{
305 log.debug("mirDbgLeaveBlock (line={d}, col={d})", .{304 emit.prev_di_loc.line, emit.prev_di_loc.column,
306 emit.prev_di_line, emit.prev_di_column,305 });
307 });306 try dwarf.leaveBlock(emit.code.items.len);
308 try dw.leaveBlock(emit.code.items.len);307 },
309 },308 .plan9 => {},
310 .plan9 => {},309 .none => {},
311 .none => {},
312 }
313 },310 },
314 .pseudo_dbg_enter_inline_func => {311 .pseudo_dbg_enter_inline_func => switch (emit.debug_output) {
315 switch (emit.debug_output) {312 .dwarf => |dwarf| {
316 .dwarf => |dw| {313 log.debug("mirDbgEnterInline (line={d}, col={d})", .{
317 log.debug("mirDbgEnterInline (line={d}, col={d})", .{314 emit.prev_di_loc.line, emit.prev_di_loc.column,
318 emit.prev_di_line, emit.prev_di_column,315 });
319 });316 try dwarf.enterInlineFunc(mir_inst.data.func, emit.code.items.len, emit.prev_di_loc.line, emit.prev_di_loc.column);
320 try dw.enterInlineFunc(mir_inst.data.func, emit.code.items.len, emit.prev_di_line, emit.prev_di_column);317 },
321 },318 .plan9 => {},
322 .plan9 => {},319 .none => {},
323 .none => {},
324 }
325 },320 },
326 .pseudo_dbg_leave_inline_func => {321 .pseudo_dbg_leave_inline_func => switch (emit.debug_output) {
327 switch (emit.debug_output) {322 .dwarf => |dwarf| {
328 .dwarf => |dw| {323 log.debug("mirDbgLeaveInline (line={d}, col={d})", .{
329 log.debug("mirDbgLeaveInline (line={d}, col={d})", .{324 emit.prev_di_loc.line, emit.prev_di_loc.column,
330 emit.prev_di_line, emit.prev_di_column,325 });
331 });326 try dwarf.leaveInlineFunc(mir_inst.data.func, emit.code.items.len);
332 try dw.leaveInlineFunc(mir_inst.data.func, emit.code.items.len);327 },
333 },328 .plan9 => {},
334 .plan9 => {},329 .none => {},
335 .none => {},
336 }
337 },330 },
338 .pseudo_dbg_local_a,331 .pseudo_dbg_local_a,
339 .pseudo_dbg_local_ai_s,332 .pseudo_dbg_local_ai_s,
...@@ -344,129 +337,125 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -344,129 +337,125 @@ pub fn emitMir(emit: *Emit) Error!void {
344 .pseudo_dbg_local_aro,337 .pseudo_dbg_local_aro,
345 .pseudo_dbg_local_af,338 .pseudo_dbg_local_af,
346 .pseudo_dbg_local_am,339 .pseudo_dbg_local_am,
347 => {340 => switch (emit.debug_output) {
348 switch (emit.debug_output) {341 .dwarf => |dwarf| {
349 .dwarf => |dw| {342 var loc_buf: [2]link.File.Dwarf.Loc = undefined;
350 var loc_buf: [2]link.File.Dwarf.Loc = undefined;343 const air_inst_index, const loc: link.File.Dwarf.Loc = switch (mir_inst.ops) {
351 const air_inst_index, const loc: link.File.Dwarf.Loc = switch (mir_inst.ops) {344 else => unreachable,
345 .pseudo_dbg_local_a => .{ mir_inst.data.a.air_inst, .empty },
346 .pseudo_dbg_local_ai_s,
347 .pseudo_dbg_local_ai_u,
348 .pseudo_dbg_local_ai_64,
349 => .{ mir_inst.data.ai.air_inst, .{ .stack_value = stack_value: {
350 loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.ai.i)) {
351 .signed => |s| .{ .consts = s },
352 .unsigned => |u| .{ .constu = u },
353 };
354 break :stack_value &loc_buf[0];
355 } } },
356 .pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{ .addr = .{
357 .sym = mir_inst.data.as.sym_index,
358 } } },
359 .pseudo_dbg_local_aso => loc: {
360 const sym_off = emit.lower.mir.extraData(
361 bits.SymbolOffset,
362 mir_inst.data.ax.payload,
363 ).data;
364 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
365 sym: {
366 loc_buf[0] = .{ .addr = .{ .sym = sym_off.sym_index } };
367 break :sym &loc_buf[0];
368 },
369 off: {
370 loc_buf[1] = .{ .consts = sym_off.off };
371 break :off &loc_buf[1];
372 },
373 } } };
374 },
375 .pseudo_dbg_local_aro => loc: {
376 const air_off = emit.lower.mir.extraData(
377 Mir.AirOffset,
378 mir_inst.data.rx.payload,
379 ).data;
380 break :loc .{ air_off.air_inst, .{ .plus = .{
381 reg: {
382 loc_buf[0] = .{ .breg = mir_inst.data.rx.r1.dwarfNum() };
383 break :reg &loc_buf[0];
384 },
385 off: {
386 loc_buf[1] = .{ .consts = air_off.off };
387 break :off &loc_buf[1];
388 },
389 } } };
390 },
391 .pseudo_dbg_local_af => loc: {
392 const reg_off = emit.lower.mir.resolveFrameAddr(emit.lower.mir.extraData(
393 bits.FrameAddr,
394 mir_inst.data.ax.payload,
395 ).data);
396 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
397 reg: {
398 loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() };
399 break :reg &loc_buf[0];
400 },
401 off: {
402 loc_buf[1] = .{ .consts = reg_off.off };
403 break :off &loc_buf[1];
404 },
405 } } };
406 },
407 .pseudo_dbg_local_am => loc: {
408 const mem = emit.lower.mem(mir_inst.data.ax.payload);
409 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
410 base: {
411 loc_buf[0] = switch (mem.base()) {
412 .none => .{ .constu = 0 },
413 .reg => |reg| .{ .breg = reg.dwarfNum() },
414 .frame => unreachable,
415 .reloc => |sym_index| .{ .addr = .{ .sym = sym_index } },
416 };
417 break :base &loc_buf[0];
418 },
419 disp: {
420 loc_buf[1] = switch (mem.disp()) {
421 .signed => |s| .{ .consts = s },
422 .unsigned => |u| .{ .constu = u },
423 };
424 break :disp &loc_buf[1];
425 },
426 } } };
427 },
428 };
429 const ip = &emit.lower.bin_file.comp.zcu.?.intern_pool;
430 const air_inst = emit.air.instructions.get(@intFromEnum(air_inst_index));
431 const name: Air.NullTerminatedString = switch (air_inst.tag) {
432 else => unreachable,
433 .arg => air_inst.data.arg.name,
434 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => @enumFromInt(air_inst.data.pl_op.payload),
435 };
436 try dwarf.genLocalDebugInfo(
437 switch (air_inst.tag) {
352 else => unreachable,438 else => unreachable,
353 .pseudo_dbg_local_a => .{ mir_inst.data.a.air_inst, .empty },439 .arg, .dbg_arg_inline => .local_arg,
354 .pseudo_dbg_local_ai_s,440 .dbg_var_ptr, .dbg_var_val => .local_var,
355 .pseudo_dbg_local_ai_u,441 },
356 .pseudo_dbg_local_ai_64,442 name.toSlice(emit.air),
357 => .{ mir_inst.data.ai.air_inst, .{ .stack_value = stack_value: {443 switch (air_inst.tag) {
358 loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.ai.i)) {
359 .signed => |s| .{ .consts = s },
360 .unsigned => |u| .{ .constu = u },
361 };
362 break :stack_value &loc_buf[0];
363 } } },
364 .pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{ .addr = .{
365 .sym = mir_inst.data.as.sym_index,
366 } } },
367 .pseudo_dbg_local_aso => loc: {
368 const sym_off = emit.lower.mir.extraData(
369 bits.SymbolOffset,
370 mir_inst.data.ax.payload,
371 ).data;
372 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
373 sym: {
374 loc_buf[0] = .{ .addr = .{ .sym = sym_off.sym_index } };
375 break :sym &loc_buf[0];
376 },
377 off: {
378 loc_buf[1] = .{ .consts = sym_off.off };
379 break :off &loc_buf[1];
380 },
381 } } };
382 },
383 .pseudo_dbg_local_aro => loc: {
384 const air_off = emit.lower.mir.extraData(
385 Mir.AirOffset,
386 mir_inst.data.rx.payload,
387 ).data;
388 break :loc .{ air_off.air_inst, .{ .plus = .{
389 reg: {
390 loc_buf[0] = .{ .breg = mir_inst.data.rx.r1.dwarfNum() };
391 break :reg &loc_buf[0];
392 },
393 off: {
394 loc_buf[1] = .{ .consts = air_off.off };
395 break :off &loc_buf[1];
396 },
397 } } };
398 },
399 .pseudo_dbg_local_af => loc: {
400 const reg_off = emit.lower.mir.resolveFrameAddr(emit.lower.mir.extraData(
401 bits.FrameAddr,
402 mir_inst.data.ax.payload,
403 ).data);
404 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
405 reg: {
406 loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() };
407 break :reg &loc_buf[0];
408 },
409 off: {
410 loc_buf[1] = .{ .consts = reg_off.off };
411 break :off &loc_buf[1];
412 },
413 } } };
414 },
415 .pseudo_dbg_local_am => loc: {
416 const mem = emit.lower.mem(mir_inst.data.ax.payload);
417 break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
418 base: {
419 loc_buf[0] = switch (mem.base()) {
420 .none => .{ .constu = 0 },
421 .reg => |reg| .{ .breg = reg.dwarfNum() },
422 .frame => unreachable,
423 .reloc => |sym_index| .{ .addr = .{ .sym = sym_index } },
424 };
425 break :base &loc_buf[0];
426 },
427 disp: {
428 loc_buf[1] = switch (mem.disp()) {
429 .signed => |s| .{ .consts = s },
430 .unsigned => |u| .{ .constu = u },
431 };
432 break :disp &loc_buf[1];
433 },
434 } } };
435 },
436 };
437 const ip = &emit.lower.bin_file.comp.zcu.?.intern_pool;
438 const air_inst = emit.air.instructions.get(@intFromEnum(air_inst_index));
439 const name: Air.NullTerminatedString = switch (air_inst.tag) {
440 else => unreachable,444 else => unreachable,
441 .arg => air_inst.data.arg.name,445 .arg => emit.air.typeOfIndex(air_inst_index, ip),
442 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => @enumFromInt(air_inst.data.pl_op.payload),446 .dbg_var_ptr => emit.air.typeOf(air_inst.data.pl_op.operand, ip).childTypeIp(ip),
443 };447 .dbg_var_val, .dbg_arg_inline => emit.air.typeOf(air_inst.data.pl_op.operand, ip),
444 try dw.genLocalDebugInfo(448 },
445 switch (air_inst.tag) {449 loc,
446 else => unreachable,450 );
447 .arg, .dbg_arg_inline => .local_arg,451 },
448 .dbg_var_ptr, .dbg_var_val => .local_var,452 .plan9 => {},
449 },453 .none => {},
450 name.toSlice(emit.air),
451 switch (air_inst.tag) {
452 else => unreachable,
453 .arg => emit.air.typeOfIndex(air_inst_index, ip),
454 .dbg_var_ptr => emit.air.typeOf(air_inst.data.pl_op.operand, ip).childTypeIp(ip),
455 .dbg_var_val, .dbg_arg_inline => emit.air.typeOf(air_inst.data.pl_op.operand, ip),
456 },
457 loc,
458 );
459 },
460 .plan9 => {},
461 .none => {},
462 }
463 },454 },
464 .pseudo_dbg_var_args_none => {455 .pseudo_dbg_var_args_none => switch (emit.debug_output) {
465 switch (emit.debug_output) {456 .dwarf => |dwarf| try dwarf.genVarArgsDebugInfo(),
466 .dwarf => |dw| try dw.genVarArgsDebugInfo(),457 .plan9 => {},
467 .plan9 => {},458 .none => {},
468 .none => {},
469 }
470 },459 },
471 .pseudo_dead_none => {},460 .pseudo_dead_none => {},
472 },461 },
...@@ -515,16 +504,22 @@ fn fixupRelocs(emit: *Emit) Error!void {...@@ -515,16 +504,22 @@ fn fixupRelocs(emit: *Emit) Error!void {
515 }504 }
516}505}
517506
518fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {507const Loc = struct {
519 const delta_line = @as(i33, line) - @as(i33, emit.prev_di_line);508 line: u32,
509 column: u32,
510 is_stmt: bool,
511};
512
513fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void {
514 const delta_line = @as(i33, loc.line) - @as(i33, emit.prev_di_loc.line);
520 const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;515 const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;
521 log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line });516 log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line });
522 switch (emit.debug_output) {517 switch (emit.debug_output) {
523 .dwarf => |dw| {518 .dwarf => |dwarf| {
524 if (column != emit.prev_di_column) try dw.setColumn(column);519 if (loc.is_stmt != emit.prev_di_loc.is_stmt) try dwarf.negateStmt();
525 try dw.advancePCAndLine(delta_line, delta_pc);520 if (loc.column != emit.prev_di_loc.column) try dwarf.setColumn(loc.column);
526 emit.prev_di_line = line;521 try dwarf.advancePCAndLine(delta_line, delta_pc);
527 emit.prev_di_column = column;522 emit.prev_di_loc = loc;
528 emit.prev_di_pc = emit.code.items.len;523 emit.prev_di_pc = emit.code.items.len;
529 },524 },
530 .plan9 => |dbg_out| {525 .plan9 => |dbg_out| {
...@@ -553,11 +548,10 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {...@@ -553,11 +548,10 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
553 // we don't need to do anything, because adding the pc quanta does it for us548 // we don't need to do anything, because adding the pc quanta does it for us
554 } else unreachable;549 } else unreachable;
555 if (dbg_out.start_line == null)550 if (dbg_out.start_line == null)
556 dbg_out.start_line = emit.prev_di_line;551 dbg_out.start_line = emit.prev_di_loc.line;
557 dbg_out.end_line = line;552 dbg_out.end_line = loc.line;
558 // only do this if the pc changed553 // only do this if the pc changed
559 emit.prev_di_line = line;554 emit.prev_di_loc = loc;
560 emit.prev_di_column = column;
561 emit.prev_di_pc = emit.code.items.len;555 emit.prev_di_pc = emit.code.items.len;
562 },556 },
563 .none => {},557 .none => {},
src/arch/x86_64/Lower.zig+1
...@@ -310,6 +310,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {...@@ -310,6 +310,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
310 }),310 }),
311311
312 .pseudo_dbg_prologue_end_none,312 .pseudo_dbg_prologue_end_none,
313 .pseudo_dbg_line_stmt_line_column,
313 .pseudo_dbg_line_line_column,314 .pseudo_dbg_line_line_column,
314 .pseudo_dbg_epilogue_begin_none,315 .pseudo_dbg_epilogue_begin_none,
315 .pseudo_dbg_enter_block_none,316 .pseudo_dbg_enter_block_none,
src/arch/x86_64/Mir.zig+4-1
...@@ -930,7 +930,10 @@ pub const Inst = struct {...@@ -930,7 +930,10 @@ pub const Inst = struct {
930930
931 /// End of prologue931 /// End of prologue
932 pseudo_dbg_prologue_end_none,932 pseudo_dbg_prologue_end_none,
933 /// Update debug line933 /// Update debug line with is_stmt register set
934 /// Uses `line_column` payload.
935 pseudo_dbg_line_stmt_line_column,
936 /// Update debug line with is_stmt register clear
934 /// Uses `line_column` payload.937 /// Uses `line_column` payload.
935 pseudo_dbg_line_line_column,938 pseudo_dbg_line_line_column,
936 /// Start of epilogue939 /// Start of epilogue
src/codegen/c.zig+6
...@@ -3289,6 +3289,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3289,6 +3289,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3289 .try_ptr_cold => try airTryPtr(f, inst),3289 .try_ptr_cold => try airTryPtr(f, inst),
32903290
3291 .dbg_stmt => try airDbgStmt(f, inst),3291 .dbg_stmt => try airDbgStmt(f, inst),
3292 .dbg_empty_stmt => try airDbgEmptyStmt(f, inst),
3292 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => try airDbgVar(f, inst),3293 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => try airDbgVar(f, inst),
32933294
3294 .float_from_int,3295 .float_from_int,
...@@ -4601,6 +4602,11 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4601,6 +4602,11 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
4601 return .none;4602 return .none;
4602}4603}
46034604
4605fn airDbgEmptyStmt(f: *Function, _: Air.Inst.Index) !CValue {
4606 try f.object.writer().writeAll("(void)0;\n");
4607 return .none;
4608}
4609
4604fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {4610fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
4605 const pt = f.object.dg.pt;4611 const pt = f.object.dg.pt;
4606 const zcu = pt.zcu;4612 const zcu = pt.zcu;
src/codegen/llvm.zig+7
...@@ -5391,6 +5391,7 @@ pub const FuncGen = struct {...@@ -5391,6 +5391,7 @@ pub const FuncGen = struct {
5391 .inferred_alloc, .inferred_alloc_comptime => unreachable,5391 .inferred_alloc, .inferred_alloc_comptime => unreachable,
53925392
5393 .dbg_stmt => try self.airDbgStmt(inst),5393 .dbg_stmt => try self.airDbgStmt(inst),
5394 .dbg_empty_stmt => try self.airDbgEmptyStmt(inst),
5394 .dbg_var_ptr => try self.airDbgVarPtr(inst),5395 .dbg_var_ptr => try self.airDbgVarPtr(inst),
5395 .dbg_var_val => try self.airDbgVarVal(inst, false),5396 .dbg_var_val => try self.airDbgVarVal(inst, false),
5396 .dbg_arg_inline => try self.airDbgVarVal(inst, true),5397 .dbg_arg_inline => try self.airDbgVarVal(inst, true),
...@@ -7433,6 +7434,12 @@ pub const FuncGen = struct {...@@ -7433,6 +7434,12 @@ pub const FuncGen = struct {
7433 return .none;7434 return .none;
7434 }7435 }
74357436
7437 fn airDbgEmptyStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
7438 _ = self;
7439 _ = inst;
7440 return .none;
7441 }
7442
7436 fn airDbgInlineBlock(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {7443 fn airDbgInlineBlock(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
7437 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;7444 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
7438 const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);7445 const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
src/dev.zig+2
...@@ -81,6 +81,7 @@ pub const Env = enum {...@@ -81,6 +81,7 @@ pub const Env = enum {
81 => true,81 => true,
82 .cc_command,82 .cc_command,
83 .translate_c_command,83 .translate_c_command,
84 .fmt_command,
84 .jit_command,85 .jit_command,
85 .fetch_command,86 .fetch_command,
86 .init_command,87 .init_command,
...@@ -168,6 +169,7 @@ pub const Feature = enum {...@@ -168,6 +169,7 @@ pub const Feature = enum {
168 clang_command,169 clang_command,
169 cc_command,170 cc_command,
170 translate_c_command,171 translate_c_command,
172 fmt_command,
171 jit_command,173 jit_command,
172 fetch_command,174 fetch_command,
173 init_command,175 init_command,
src/link/Dwarf.zig+5
...@@ -1474,6 +1474,11 @@ pub const WipNav = struct {...@@ -1474,6 +1474,11 @@ pub const WipNav = struct {
1474 try uleb128(dlw, column + 1);1474 try uleb128(dlw, column + 1);
1475 }1475 }
14761476
1477 pub fn negateStmt(wip_nav: *WipNav) error{OutOfMemory}!void {
1478 const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa);
1479 try dlw.writeByte(DW.LNS.negate_stmt);
1480 }
1481
1477 pub fn setPrologueEnd(wip_nav: *WipNav) error{OutOfMemory}!void {1482 pub fn setPrologueEnd(wip_nav: *WipNav) error{OutOfMemory}!void {
1478 const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa);1483 const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa);
1479 try dlw.writeByte(DW.LNS.set_prologue_end);1484 try dlw.writeByte(DW.LNS.set_prologue_end);
src/link/Elf/ZigObject.zig+1-1
...@@ -1496,7 +1496,7 @@ pub fn updateFunc(...@@ -1496,7 +1496,7 @@ pub fn updateFunc(
1496 });1496 });
1497 defer gpa.free(name);1497 defer gpa.free(name);
1498 const osec = if (self.text_index) |sect_sym_index|1498 const osec = if (self.text_index) |sect_sym_index|
1499 self.symbol(sect_sym_index).output_section_index1499 self.symbol(sect_sym_index).outputShndx(elf_file).?
1500 else osec: {1500 else osec: {
1501 const osec = try elf_file.addSection(.{1501 const osec = try elf_file.addSection(.{
1502 .name = try elf_file.insertShString(".text"),1502 .name = try elf_file.insertShString(".text"),
src/main.zig+1
...@@ -309,6 +309,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -309,6 +309,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
309 .server = use_server,309 .server = use_server,
310 });310 });
311 } else if (mem.eql(u8, cmd, "fmt")) {311 } else if (mem.eql(u8, cmd, "fmt")) {
312 dev.check(.fmt_command);
312 return @import("fmt.zig").run(gpa, arena, cmd_args);313 return @import("fmt.zig").run(gpa, arena, cmd_args);
313 } else if (mem.eql(u8, cmd, "objcopy")) {314 } else if (mem.eql(u8, cmd, "objcopy")) {
314 return jitCmd(gpa, arena, cmd_args, .{315 return jitCmd(gpa, arena, cmd_args, .{
src/print_air.zig+1
...@@ -202,6 +202,7 @@ const Writer = struct {...@@ -202,6 +202,7 @@ const Writer = struct {
202202
203 .trap,203 .trap,
204 .breakpoint,204 .breakpoint,
205 .dbg_empty_stmt,
205 .unreach,206 .unreach,
206 .ret_addr,207 .ret_addr,
207 .frame_addr,208 .frame_addr,
src/print_zir.zig+2
...@@ -621,6 +621,8 @@ const Writer = struct {...@@ -621,6 +621,8 @@ const Writer = struct {
621 .field_parent_ptr => try self.writeFieldParentPtr(stream, extended),621 .field_parent_ptr => try self.writeFieldParentPtr(stream, extended),
622 .builtin_value => try self.writeBuiltinValue(stream, extended),622 .builtin_value => try self.writeBuiltinValue(stream, extended),
623 .inplace_arith_result_ty => try self.writeInplaceArithResultTy(stream, extended),623 .inplace_arith_result_ty => try self.writeInplaceArithResultTy(stream, extended),
624
625 .dbg_empty_stmt => try stream.writeAll("))"),
624 }626 }
625 }627 }
626628
test/src/Debugger.zig+418
...@@ -808,6 +808,424 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {...@@ -808,6 +808,424 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
808 \\1 breakpoints deleted; 0 breakpoint locations disabled.808 \\1 breakpoints deleted; 0 breakpoint locations disabled.
809 },809 },
810 );810 );
811 db.addLldbTest(
812 "step_single_stmt_loops",
813 target,
814 &.{
815 .{
816 .path = "step_single_stmt_loops.zig",
817 .source =
818 \\pub fn main() void {
819 \\ var x: u32 = 0;
820 \\ for (0..3) |_| {
821 \\ x +%= 1;
822 \\ }
823 \\ {
824 \\ var i: u32 = 0;
825 \\ while (i < 3) : (i +%= 1) {
826 \\ x +%= 1;
827 \\ }
828 \\ }
829 \\ {
830 \\ var i: u32 = 0;
831 \\ while (i < 3) {
832 \\ i +%= 1;
833 \\ }
834 \\ }
835 \\ inline for (0..3) |_| {
836 \\ x +%= 1;
837 \\ }
838 \\ {
839 \\ comptime var i: u32 = 0;
840 \\ inline while (i < 3) : (i +%= 1) {
841 \\ x +%= 1;
842 \\ }
843 \\ }
844 \\ {
845 \\ comptime var i: u32 = 0;
846 \\ inline while (i < 3) {
847 \\ i +%= 1;
848 \\ }
849 \\ }
850 \\ x +%= 1;
851 \\}
852 \\
853 ,
854 },
855 },
856 \\breakpoint set --name step_single_stmt_loops.main
857 \\process launch
858 \\thread step-in
859 \\#00
860 \\frame variable x
861 \\thread step-in
862 \\#01
863 \\frame variable x
864 \\thread step-in
865 \\#02
866 \\frame variable x
867 \\thread step-in
868 \\#03
869 \\frame variable x
870 \\thread step-in
871 \\#04
872 \\frame variable x
873 \\thread step-in
874 \\#05
875 \\frame variable x
876 \\thread step-in
877 \\#06
878 \\frame variable x
879 \\thread step-in
880 \\#07
881 \\frame variable x
882 \\thread step-in
883 \\#08
884 \\frame variable x
885 \\thread step-in
886 \\#09
887 \\frame variable x
888 \\thread step-in
889 \\#10
890 \\frame variable x
891 \\thread step-in
892 \\#11
893 \\frame variable x
894 \\thread step-in
895 \\#12
896 \\frame variable x
897 \\thread step-in
898 \\#13
899 \\frame variable x
900 \\thread step-in
901 \\#14
902 \\frame variable x
903 \\thread step-in
904 \\#15
905 \\frame variable x
906 \\thread step-in
907 \\#16
908 \\frame variable x
909 \\thread step-in
910 \\#17
911 \\frame variable x
912 \\thread step-in
913 \\#18
914 \\frame variable x
915 \\thread step-in
916 \\#19
917 \\frame variable x
918 \\thread step-in
919 \\#20
920 \\frame variable x
921 \\thread step-in
922 \\#21
923 \\frame variable x
924 \\thread step-in
925 \\#22
926 \\frame variable x
927 \\thread step-in
928 \\#23
929 \\frame variable x
930 \\thread step-in
931 \\#24
932 \\frame variable x
933 \\thread step-in
934 \\#25
935 \\frame variable x
936 \\thread step-in
937 \\#26
938 \\frame variable x
939 \\thread step-in
940 \\#27
941 \\frame variable x
942 \\thread step-in
943 \\#28
944 \\frame variable x
945 \\thread step-in
946 \\#29
947 \\frame variable x
948 \\thread step-in
949 \\#30
950 \\frame variable x
951 \\thread step-in
952 \\#31
953 \\frame variable x
954 \\thread step-in
955 \\#32
956 \\frame variable x
957 \\thread step-in
958 \\#33
959 \\frame variable x
960 \\thread step-in
961 \\#34
962 \\frame variable x
963 \\thread step-in
964 \\#35
965 \\frame variable x
966 \\thread step-in
967 \\#36
968 \\frame variable x
969 \\thread step-in
970 \\#37
971 \\frame variable x
972 \\thread step-in
973 \\#38
974 \\frame variable x
975 \\thread step-in
976 \\#39
977 \\frame variable x
978 \\thread step-in
979 \\#40
980 \\frame variable x
981 \\thread step-in
982 \\#41
983 \\frame variable x
984 \\thread step-in
985 \\#42
986 \\frame variable x
987 \\thread step-in
988 \\#43
989 \\frame variable x
990 \\thread step-in
991 \\#44
992 \\frame variable x
993 \\thread step-in
994 \\#45
995 \\frame variable x
996 \\
997 ,
998 &.{
999 \\(lldb) #00
1000 \\(lldb) frame variable x
1001 \\(u32) x = 0
1002 \\(lldb) thread step-in
1003 ,
1004 \\(lldb) #01
1005 \\(lldb) frame variable x
1006 \\(u32) x = 0
1007 \\(lldb) thread step-in
1008 ,
1009 \\(lldb) #02
1010 \\(lldb) frame variable x
1011 \\(u32) x = 1
1012 \\(lldb) thread step-in
1013 ,
1014 \\(lldb) #03
1015 \\(lldb) frame variable x
1016 \\(u32) x = 1
1017 \\(lldb) thread step-in
1018 ,
1019 \\(lldb) #04
1020 \\(lldb) frame variable x
1021 \\(u32) x = 1
1022 \\(lldb) thread step-in
1023 ,
1024 \\(lldb) #05
1025 \\(lldb) frame variable x
1026 \\(u32) x = 2
1027 \\(lldb) thread step-in
1028 ,
1029 \\(lldb) #06
1030 \\(lldb) frame variable x
1031 \\(u32) x = 2
1032 \\(lldb) thread step-in
1033 ,
1034 \\(lldb) #07
1035 \\(lldb) frame variable x
1036 \\(u32) x = 2
1037 \\(lldb) thread step-in
1038 ,
1039 \\(lldb) #08
1040 \\(lldb) frame variable x
1041 \\(u32) x = 3
1042 \\(lldb) thread step-in
1043 ,
1044 \\(lldb) #09
1045 \\(lldb) frame variable x
1046 \\(u32) x = 3
1047 \\(lldb) thread step-in
1048 ,
1049 \\(lldb) #10
1050 \\(lldb) frame variable x
1051 \\(u32) x = 3
1052 \\(lldb) thread step-in
1053 ,
1054 \\(lldb) #11
1055 \\(lldb) frame variable x
1056 \\(u32) x = 3
1057 \\(lldb) thread step-in
1058 ,
1059 \\(lldb) #12
1060 \\(lldb) frame variable x
1061 \\(u32) x = 3
1062 \\(lldb) thread step-in
1063 ,
1064 \\(lldb) #13
1065 \\(lldb) frame variable x
1066 \\(u32) x = 4
1067 \\(lldb) thread step-in
1068 ,
1069 \\(lldb) #14
1070 \\(lldb) frame variable x
1071 \\(u32) x = 4
1072 \\(lldb) thread step-in
1073 ,
1074 \\(lldb) #15
1075 \\(lldb) frame variable x
1076 \\(u32) x = 4
1077 \\(lldb) thread step-in
1078 ,
1079 \\(lldb) #16
1080 \\(lldb) frame variable x
1081 \\(u32) x = 5
1082 \\(lldb) thread step-in
1083 ,
1084 \\(lldb) #17
1085 \\(lldb) frame variable x
1086 \\(u32) x = 5
1087 \\(lldb) thread step-in
1088 ,
1089 \\(lldb) #18
1090 \\(lldb) frame variable x
1091 \\(u32) x = 5
1092 \\(lldb) thread step-in
1093 ,
1094 \\(lldb) #19
1095 \\(lldb) frame variable x
1096 \\(u32) x = 6
1097 \\(lldb) thread step-in
1098 ,
1099 \\(lldb) #20
1100 \\(lldb) frame variable x
1101 \\(u32) x = 6
1102 \\(lldb) thread step-in
1103 ,
1104 \\(lldb) #21
1105 \\(lldb) frame variable x
1106 \\(u32) x = 6
1107 \\(lldb) thread step-in
1108 ,
1109 \\(lldb) #22
1110 \\(lldb) frame variable x
1111 \\(u32) x = 6
1112 \\(lldb) thread step-in
1113 ,
1114 \\(lldb) #23
1115 \\(lldb) frame variable x
1116 \\(u32) x = 6
1117 \\(lldb) thread step-in
1118 ,
1119 \\(lldb) #24
1120 \\(lldb) frame variable x
1121 \\(u32) x = 6
1122 \\(lldb) thread step-in
1123 ,
1124 \\(lldb) #25
1125 \\(lldb) frame variable x
1126 \\(u32) x = 6
1127 \\(lldb) thread step-in
1128 ,
1129 \\(lldb) #26
1130 \\(lldb) frame variable x
1131 \\(u32) x = 6
1132 \\(lldb) thread step-in
1133 ,
1134 \\(lldb) #27
1135 \\(lldb) frame variable x
1136 \\(u32) x = 6
1137 \\(lldb) thread step-in
1138 ,
1139 \\(lldb) #28
1140 \\(lldb) frame variable x
1141 \\(u32) x = 6
1142 \\(lldb) thread step-in
1143 ,
1144 \\(lldb) #29
1145 \\(lldb) frame variable x
1146 \\(u32) x = 6
1147 \\(lldb) thread step-in
1148 ,
1149 \\(lldb) #30
1150 \\(lldb) frame variable x
1151 \\(u32) x = 6
1152 \\(lldb) thread step-in
1153 ,
1154 \\(lldb) #31
1155 \\(lldb) frame variable x
1156 \\(u32) x = 6
1157 \\(lldb) thread step-in
1158 ,
1159 \\(lldb) #32
1160 \\(lldb) frame variable x
1161 \\(u32) x = 6
1162 \\(lldb) thread step-in
1163 ,
1164 \\(lldb) #33
1165 \\(lldb) frame variable x
1166 \\(u32) x = 7
1167 \\(lldb) thread step-in
1168 ,
1169 \\(lldb) #34
1170 \\(lldb) frame variable x
1171 \\(u32) x = 7
1172 \\(lldb) thread step-in
1173 ,
1174 \\(lldb) #35
1175 \\(lldb) frame variable x
1176 \\(u32) x = 8
1177 \\(lldb) thread step-in
1178 ,
1179 \\(lldb) #36
1180 \\(lldb) frame variable x
1181 \\(u32) x = 8
1182 \\(lldb) thread step-in
1183 ,
1184 \\(lldb) #37
1185 \\(lldb) frame variable x
1186 \\(u32) x = 9
1187 \\(lldb) thread step-in
1188 ,
1189 \\(lldb) #38
1190 \\(lldb) frame variable x
1191 \\(u32) x = 9
1192 \\(lldb) thread step-in
1193 ,
1194 \\(lldb) #39
1195 \\(lldb) frame variable x
1196 \\(u32) x = 10
1197 \\(lldb) thread step-in
1198 ,
1199 \\(lldb) #40
1200 \\(lldb) frame variable x
1201 \\(u32) x = 10
1202 \\(lldb) thread step-in
1203 ,
1204 \\(lldb) #41
1205 \\(lldb) frame variable x
1206 \\(u32) x = 11
1207 \\(lldb) thread step-in
1208 ,
1209 \\(lldb) #42
1210 \\(lldb) frame variable x
1211 \\(u32) x = 11
1212 \\(lldb) thread step-in
1213 ,
1214 \\(lldb) #43
1215 \\(lldb) frame variable x
1216 \\(u32) x = 12
1217 \\(lldb) thread step-in
1218 ,
1219 \\(lldb) #44
1220 \\(lldb) frame variable x
1221 \\(u32) x = 12
1222 \\(lldb) thread step-in
1223 ,
1224 \\(lldb) #45
1225 \\(lldb) frame variable x
1226 \\(u32) x = 12
1227 },
1228 );
811 db.addLldbTest(1229 db.addLldbTest(
812 "inline_call",1230 "inline_call",
813 target,1231 target,