Skip to content

Commit c894ac0

Browse files
jacobly0andrewrk
authored andcommitted
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.
1 parent 6d781e0 commit c894ac0

25 files changed

+721
-221
lines changed

lib/std/zig/AstGen.zig

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6024,7 +6024,7 @@ fn tryExpr(
60246024
if (!parent_gz.is_comptime) {
60256025
try emitDbgNode(parent_gz, node);
60266026
}
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

60296029
const operand_rl: ResultInfo.Loc, const block_tag: Zir.Inst.Tag = switch (ri.rl) {
60306030
.ref => .{ .ref, .try_ptr },
@@ -6577,6 +6577,7 @@ fn whileExpr(
65776577
const astgen = parent_gz.astgen;
65786578
const tree = astgen.tree;
65796579
const token_tags = tree.tokens.items(.tag);
6580+
const token_starts = tree.tokens.items(.start);
65806581

65816582
const need_rl = astgen.nodes_need_rl.contains(node);
65826583
const block_ri: ResultInfo = if (need_rl) ri else .{
@@ -6774,6 +6775,16 @@ fn whileExpr(
67746775
try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
67756776
const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
67766777
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+
});
67776788
_ = try continue_scope.addBreak(break_tag, continue_block, .void_value);
67786789
}
67796790
try continue_scope.setBlockBody(continue_block);
@@ -6882,6 +6893,7 @@ fn forExpr(
68826893
}
68836894
const tree = astgen.tree;
68846895
const token_tags = tree.tokens.items(.tag);
6896+
const token_starts = tree.tokens.items(.start);
68856897
const node_tags = tree.nodes.items(.tag);
68866898
const node_data = tree.nodes.items(.data);
68876899
const gpa = astgen.gpa;
@@ -7087,8 +7099,18 @@ fn forExpr(
70877099

70887100
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";
70927114
_ = try then_scope.addBreak(break_tag, cond_block, .void_value);
70937115

70947116
var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
@@ -7135,6 +7157,7 @@ fn forExpr(
71357157
.lhs = index_ptr,
71367158
.rhs = index_plus_one,
71377159
});
7160+
71387161
const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
71397162
_ = try loop_scope.addNode(repeat_tag, node);
71407163

@@ -7279,7 +7302,7 @@ fn switchExprErrUnion(
72797302
};
72807303

72817304
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

72847307
const raw_operand = try reachableExpr(parent_gz, scope, operand_ri, operand_node, switch_node);
72857308
const item_ri: ResultInfo = .{ .rl = .none };
@@ -7868,7 +7891,7 @@ fn switchExpr(
78687891
const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none };
78697892

78707893
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

78737896
const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);
78747897
const item_ri: ResultInfo = .{ .rl = .none };
@@ -8214,7 +8237,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
82148237
if (!gz.is_comptime) {
82158238
try emitDbgNode(gz, node);
82168239
}
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

82198242
const defer_outer = &astgen.fn_block.?.base;
82208243

lib/std/zig/Zir.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,6 +2088,8 @@ pub const Inst = struct {
20882088
/// `operand` is `Zir.Inst.Ref` of the loaded LHS (*not* its type).
20892089
/// `small` is an `Inst.InplaceOp`.
20902090
inplace_arith_result_ty,
2091+
/// Marks a statement that can be stepped to but produces no code.
2092+
dbg_empty_stmt,
20912093

20922094
pub const InstData = struct {
20932095
opcode: Extended,
@@ -4062,6 +4064,7 @@ fn findDeclsInner(
40624064
.branch_hint,
40634065
.inplace_arith_result_ty,
40644066
.tuple_decl,
4067+
.dbg_empty_stmt,
40654068
=> return,
40664069

40674070
// `@TypeOf` has a body.

src/Air.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,8 @@ pub const Inst = struct {
460460
/// Result type is always void.
461461
/// Uses the `dbg_stmt` field.
462462
dbg_stmt,
463+
/// Marks a statement that can be stepped to but produces no code.
464+
dbg_empty_stmt,
463465
/// A block that represents an inlined function call.
464466
/// Uses the `ty_pl` field. Payload is `DbgInlineBlock`.
465467
dbg_inline_block,
@@ -1468,6 +1470,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
14681470

14691471
.breakpoint,
14701472
.dbg_stmt,
1473+
.dbg_empty_stmt,
14711474
.dbg_var_ptr,
14721475
.dbg_var_val,
14731476
.dbg_arg_inline,
@@ -1629,6 +1632,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
16291632
.try_ptr,
16301633
.try_ptr_cold,
16311634
.dbg_stmt,
1635+
.dbg_empty_stmt,
16321636
.dbg_inline_block,
16331637
.dbg_var_ptr,
16341638
.dbg_var_val,

src/Air/types_resolved.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool {
417417
.work_group_size,
418418
.work_group_id,
419419
.dbg_stmt,
420+
.dbg_empty_stmt,
420421
.err_return_trace,
421422
.save_err_return_trace_index,
422423
.repeat,

src/Liveness.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ pub fn categorizeOperand(
334334
.repeat,
335335
.switch_dispatch,
336336
.dbg_stmt,
337+
.dbg_empty_stmt,
337338
.unreach,
338339
.ret_addr,
339340
.frame_addr,
@@ -973,6 +974,7 @@ fn analyzeInst(
973974
.ret_ptr,
974975
.breakpoint,
975976
.dbg_stmt,
977+
.dbg_empty_stmt,
976978
.ret_addr,
977979
.frame_addr,
978980
.wasm_memory_size,

src/Liveness/Verify.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
5656
.ret_ptr,
5757
.breakpoint,
5858
.dbg_stmt,
59+
.dbg_empty_stmt,
5960
.ret_addr,
6061
.frame_addr,
6162
.wasm_memory_size,

src/Sema.zig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,11 @@ fn analyzeBodyInner(
13551355
.field_parent_ptr => try sema.zirFieldParentPtr(block, extended),
13561356
.builtin_value => try sema.zirBuiltinValue(block, extended),
13571357
.inplace_arith_result_ty => try sema.zirInplaceArithResultTy(extended),
1358+
.dbg_empty_stmt => {
1359+
try sema.zirDbgEmptyStmt(block, inst);
1360+
i += 1;
1361+
continue;
1362+
},
13581363
};
13591364
},
13601365

@@ -6671,6 +6676,11 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi
66716676
});
66726677
}
66736678

6679+
fn 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+
66746684
fn zirDbgVar(
66756685
sema: *Sema,
66766686
block: *Block,

src/arch/aarch64/CodeGen.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
800800
.try_ptr_cold => try self.airTryPtr(inst),
801801

802802
.dbg_stmt => try self.airDbgStmt(inst),
803+
.dbg_empty_stmt => self.finishAirBookkeeping(),
803804
.dbg_inline_block => try self.airDbgInlineBlock(inst),
804805
.dbg_var_ptr,
805806
.dbg_var_val,

src/arch/arm/CodeGen.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
787787
.try_ptr_cold => try self.airTryPtr(inst),
788788

789789
.dbg_stmt => try self.airDbgStmt(inst),
790+
.dbg_empty_stmt => self.finishAirBookkeeping(),
790791
.dbg_inline_block => try self.airDbgInlineBlock(inst),
791792
.dbg_var_ptr,
792793
.dbg_var_val,

src/arch/riscv64/CodeGen.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,6 +1593,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
15931593
.frame_addr => try func.airFrameAddress(inst),
15941594
.cond_br => try func.airCondBr(inst),
15951595
.dbg_stmt => try func.airDbgStmt(inst),
1596+
.dbg_empty_stmt => func.finishAirBookkeeping(),
15961597
.fptrunc => try func.airFptrunc(inst),
15971598
.fpext => try func.airFpext(inst),
15981599
.intcast => try func.airIntCast(inst),

src/arch/sparc64/CodeGen.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
642642
.try_ptr_cold => @panic("TODO try self.airTryPtrCold(inst)"),
643643

644644
.dbg_stmt => try self.airDbgStmt(inst),
645+
.dbg_empty_stmt => self.finishAirBookkeeping(),
645646
.dbg_inline_block => try self.airDbgInlineBlock(inst),
646647
.dbg_var_ptr,
647648
.dbg_var_val,

src/arch/wasm/CodeGen.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,6 +1924,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
19241924
.try_ptr_cold => func.airTryPtr(inst),
19251925

19261926
.dbg_stmt => func.airDbgStmt(inst),
1927+
.dbg_empty_stmt => try func.finishAir(inst, .none, &.{}),
19271928
.dbg_inline_block => func.airDbgInlineBlock(inst),
19281929
.dbg_var_ptr => func.airDbgVar(inst, .local_var, true),
19291930
.dbg_var_val => func.airDbgVar(inst, .local_var, false),

src/arch/x86_64/CodeGen.zig

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -961,9 +961,16 @@ pub fn generate(
961961
},
962962
.debug_output = debug_output,
963963
.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+
},
964973
.prev_di_pc = 0,
965-
.prev_di_line = func.lbrace_line,
966-
.prev_di_column = func.lbrace_column,
967974
};
968975
defer emit.deinit();
969976
emit.emitMir() catch |err| switch (err) {
@@ -1066,9 +1073,8 @@ pub fn generateLazy(
10661073
},
10671074
.debug_output = debug_output,
10681075
.code = code,
1076+
.prev_di_loc = undefined, // no debug info yet
10691077
.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
10721078
};
10731079
defer emit.deinit();
10741080
emit.emitMir() catch |err| switch (err) {
@@ -1194,13 +1200,16 @@ fn formatWipMir(
11941200
switch (mir_inst.ops) {
11951201
else => unreachable,
11961202
.pseudo_dbg_prologue_end_none,
1197-
.pseudo_dbg_line_line_column,
11981203
.pseudo_dbg_epilogue_begin_none,
11991204
.pseudo_dbg_enter_block_none,
12001205
.pseudo_dbg_leave_block_none,
12011206
.pseudo_dbg_var_args_none,
12021207
.pseudo_dead_none,
12031208
=> {},
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+
),
12041213
.pseudo_dbg_enter_inline_func, .pseudo_dbg_leave_inline_func => try writer.print(" {}", .{
12051214
ip.getNav(ip.indexToKey(mir_inst.data.func).func.owner_nav).name.fmt(ip),
12061215
}),
@@ -1281,14 +1290,7 @@ fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
12811290
try self.mir_instructions.ensureUnusedCapacity(gpa, 1);
12821291
const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len);
12831292
self.mir_instructions.appendAssumeCapacity(inst);
1284-
if (inst.tag != .pseudo or switch (inst.ops) {
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)});
1293+
wip_mir_log.debug("{}", .{self.fmtWipMir(result_index)});
12921294
return result_index;
12931295
}
12941296

@@ -2218,7 +2220,7 @@ fn gen(self: *Self) InnerError!void {
22182220
// Drop them off at the rbrace.
22192221
_ = try self.addInst(.{
22202222
.tag = .pseudo,
2221-
.ops = .pseudo_dbg_line_line_column,
2223+
.ops = .pseudo_dbg_line_stmt_line_column,
22222224
.data = .{ .line_column = .{
22232225
.line = self.end_di_line,
22242226
.column = self.end_di_column,
@@ -2426,6 +2428,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
24262428
.try_ptr_cold => try self.airTryPtr(inst), // TODO
24272429

24282430
.dbg_stmt => try self.airDbgStmt(inst),
2431+
.dbg_empty_stmt => try self.airDbgEmptyStmt(),
24292432
.dbg_inline_block => try self.airDbgInlineBlock(inst),
24302433
.dbg_var_ptr,
24312434
.dbg_var_val,
@@ -13281,7 +13284,7 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
1328113284
const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
1328213285
_ = try self.addInst(.{
1328313286
.tag = .pseudo,
13284-
.ops = .pseudo_dbg_line_line_column,
13287+
.ops = .pseudo_dbg_line_stmt_line_column,
1328513288
.data = .{ .line_column = .{
1328613289
.line = dbg_stmt.line,
1328713290
.column = dbg_stmt.column,
@@ -13290,6 +13293,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
1329013293
self.finishAirBookkeeping();
1329113294
}
1329213295

13296+
fn 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+
1329313304
fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {
1329413305
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
1329513306
const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);

0 commit comments

Comments
 (0)