From c894ac09a31380319ba9cfdc82025fcc614a8cc0 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Sun, 24 Nov 2024 04:11:52 -0500 Subject: [PATCH] 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. --- lib/std/zig/AstGen.zig | 33 ++- lib/std/zig/Zir.zig | 3 + src/Air.zig | 4 + src/Air/types_resolved.zig | 1 + src/Liveness.zig | 2 + src/Liveness/Verify.zig | 1 + src/Sema.zig | 10 + src/arch/aarch64/CodeGen.zig | 1 + src/arch/arm/CodeGen.zig | 1 + src/arch/riscv64/CodeGen.zig | 1 + src/arch/sparc64/CodeGen.zig | 1 + src/arch/wasm/CodeGen.zig | 1 + src/arch/x86_64/CodeGen.zig | 41 ++-- src/arch/x86_64/Emit.zig | 392 ++++++++++++++++---------------- src/arch/x86_64/Lower.zig | 1 + src/arch/x86_64/Mir.zig | 5 +- src/codegen/c.zig | 6 + src/codegen/llvm.zig | 7 + src/dev.zig | 2 + src/link/Dwarf.zig | 5 + src/link/Elf/ZigObject.zig | 2 +- src/main.zig | 1 + src/print_air.zig | 1 + src/print_zir.zig | 2 + test/src/Debugger.zig | 418 +++++++++++++++++++++++++++++++++++ 25 files changed, 721 insertions(+), 221 deletions(-) diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index abec1f354ac238707e96ebf23850f91d6a561abf..a9b518357bfcfc7f696ffdc59ea40cdf441b34f1 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -6024,7 +6024,7 @@ fn tryExpr( if (!parent_gz.is_comptime) { try emitDbgNode(parent_gz, node); } - const try_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column }; + const try_lc: LineColumn = .{ astgen.source_line - parent_gz.decl_line, astgen.source_column }; const operand_rl: ResultInfo.Loc, const block_tag: Zir.Inst.Tag = switch (ri.rl) { .ref => .{ .ref, .try_ptr }, @@ -6577,6 +6577,7 @@ fn whileExpr( const astgen = parent_gz.astgen; const tree = astgen.tree; const token_tags = tree.tokens.items(.tag); + const token_starts = tree.tokens.items(.start); const need_rl = astgen.nodes_need_rl.contains(node); const block_ri: ResultInfo = if (need_rl) ri else .{ @@ -6774,6 +6775,16 @@ fn whileExpr( try checkUsed(parent_gz, &then_scope.base, then_sub_scope); const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; if (!continue_scope.endsWithNoReturn()) { + astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]); + try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column }); + _ = try parent_gz.add(.{ + .tag = .extended, + .data = .{ .extended = .{ + .opcode = .dbg_empty_stmt, + .small = undefined, + .operand = undefined, + } }, + }); _ = try continue_scope.addBreak(break_tag, continue_block, .void_value); } try continue_scope.setBlockBody(continue_block); @@ -6882,6 +6893,7 @@ fn forExpr( } const tree = astgen.tree; const token_tags = tree.tokens.items(.tag); + const token_starts = tree.tokens.items(.start); const node_tags = tree.nodes.items(.tag); const node_data = tree.nodes.items(.data); const gpa = astgen.gpa; @@ -7087,8 +7099,18 @@ fn forExpr( try checkUsed(parent_gz, &then_scope.base, then_sub_scope); - const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; + astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]); + try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column }); + _ = try parent_gz.add(.{ + .tag = .extended, + .data = .{ .extended = .{ + .opcode = .dbg_empty_stmt, + .small = undefined, + .operand = undefined, + } }, + }); + const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; _ = try then_scope.addBreak(break_tag, cond_block, .void_value); var else_scope = parent_gz.makeSubBlock(&cond_scope.base); @@ -7135,6 +7157,7 @@ fn forExpr( .lhs = index_ptr, .rhs = index_plus_one, }); + const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat; _ = try loop_scope.addNode(repeat_tag, node); @@ -7279,7 +7302,7 @@ fn switchExprErrUnion( }; astgen.advanceSourceCursorToNode(operand_node); - const operand_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column }; + const operand_lc: LineColumn = .{ astgen.source_line - parent_gz.decl_line, astgen.source_column }; const raw_operand = try reachableExpr(parent_gz, scope, operand_ri, operand_node, switch_node); const item_ri: ResultInfo = .{ .rl = .none }; @@ -7868,7 +7891,7 @@ fn switchExpr( const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none }; astgen.advanceSourceCursorToNode(operand_node); - const operand_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column }; + const operand_lc: LineColumn = .{ astgen.source_line - parent_gz.decl_line, astgen.source_column }; const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node); const item_ri: ResultInfo = .{ .rl = .none }; @@ -8214,7 +8237,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref if (!gz.is_comptime) { try emitDbgNode(gz, node); } - const ret_lc = LineColumn{ astgen.source_line - gz.decl_line, astgen.source_column }; + const ret_lc: LineColumn = .{ astgen.source_line - gz.decl_line, astgen.source_column }; const defer_outer = &astgen.fn_block.?.base; diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 00a48e21f7c435662025daf71a0282bd878c023f..f2c103f8358d47703cc8a80b9154ff75a302a48c 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -2088,6 +2088,8 @@ pub const Inst = struct { /// `operand` is `Zir.Inst.Ref` of the loaded LHS (*not* its type). /// `small` is an `Inst.InplaceOp`. inplace_arith_result_ty, + /// Marks a statement that can be stepped to but produces no code. + dbg_empty_stmt, pub const InstData = struct { opcode: Extended, @@ -4062,6 +4064,7 @@ fn findDeclsInner( .branch_hint, .inplace_arith_result_ty, .tuple_decl, + .dbg_empty_stmt, => return, // `@TypeOf` has a body. diff --git a/src/Air.zig b/src/Air.zig index 3aa5f317c06d7daca25f91490a271260dffd9567..4589bb1557cfac20daa63ad504c0eda54904efbb 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -460,6 +460,8 @@ pub const Inst = struct { /// Result type is always void. /// Uses the `dbg_stmt` field. dbg_stmt, + /// Marks a statement that can be stepped to but produces no code. + dbg_empty_stmt, /// A block that represents an inlined function call. /// Uses the `ty_pl` field. Payload is `DbgInlineBlock`. dbg_inline_block, @@ -1468,6 +1470,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) .breakpoint, .dbg_stmt, + .dbg_empty_stmt, .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline, @@ -1629,6 +1632,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { .try_ptr, .try_ptr_cold, .dbg_stmt, + .dbg_empty_stmt, .dbg_inline_block, .dbg_var_ptr, .dbg_var_val, diff --git a/src/Air/types_resolved.zig b/src/Air/types_resolved.zig index 098cb29b2282a7a82aec0d03fedadc8b84cbd172..cc866184e475e6dafbdf01556607f6f25a3397a0 100644 --- a/src/Air/types_resolved.zig +++ b/src/Air/types_resolved.zig @@ -417,6 +417,7 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool { .work_group_size, .work_group_id, .dbg_stmt, + .dbg_empty_stmt, .err_return_trace, .save_err_return_trace_index, .repeat, diff --git a/src/Liveness.zig b/src/Liveness.zig index b5bffc6a480f7b4cd19136b5b39736b3d5d8e904..709844c0ac0a8cd8e805b49b4861bb680c6032b5 100644 --- a/src/Liveness.zig +++ b/src/Liveness.zig @@ -334,6 +334,7 @@ pub fn categorizeOperand( .repeat, .switch_dispatch, .dbg_stmt, + .dbg_empty_stmt, .unreach, .ret_addr, .frame_addr, @@ -973,6 +974,7 @@ fn analyzeInst( .ret_ptr, .breakpoint, .dbg_stmt, + .dbg_empty_stmt, .ret_addr, .frame_addr, .wasm_memory_size, diff --git a/src/Liveness/Verify.zig b/src/Liveness/Verify.zig index aa2239793a1dea783c0722597744469b9efc6e6c..01e0842dedf38207bd8a81606989cf120b80f0ac 100644 --- a/src/Liveness/Verify.zig +++ b/src/Liveness/Verify.zig @@ -56,6 +56,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { .ret_ptr, .breakpoint, .dbg_stmt, + .dbg_empty_stmt, .ret_addr, .frame_addr, .wasm_memory_size, diff --git a/src/Sema.zig b/src/Sema.zig index 25fb54dab81c292731b8200935bacd791f947050..5acd2012d5cba2a64977f3e75647577e303d0558 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1355,6 +1355,11 @@ fn analyzeBodyInner( .field_parent_ptr => try sema.zirFieldParentPtr(block, extended), .builtin_value => try sema.zirBuiltinValue(block, extended), .inplace_arith_result_ty => try sema.zirInplaceArithResultTy(extended), + .dbg_empty_stmt => { + try sema.zirDbgEmptyStmt(block, inst); + i += 1; + continue; + }, }; }, @@ -6671,6 +6676,11 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi }); } +fn zirDbgEmptyStmt(_: *Sema, block: *Block, _: Zir.Inst.Index) CompileError!void { + if (block.is_comptime or block.ownerModule().strip) return; + _ = try block.addNoOp(.dbg_empty_stmt); +} + fn zirDbgVar( sema: *Sema, block: *Block, diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 6371cf92f37b8441482ed7e74dba08c2444580f2..8fd27d4bb7967ff7a5db0691bd28fb6479183251 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -800,6 +800,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .try_ptr_cold => try self.airTryPtr(inst), .dbg_stmt => try self.airDbgStmt(inst), + .dbg_empty_stmt => self.finishAirBookkeeping(), .dbg_inline_block => try self.airDbgInlineBlock(inst), .dbg_var_ptr, .dbg_var_val, diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 99666487598dd1062dc6e6d453122066ca3e47ba..065f4a047de615a1360bc026cc0e5f543be2db9f 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -787,6 +787,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .try_ptr_cold => try self.airTryPtr(inst), .dbg_stmt => try self.airDbgStmt(inst), + .dbg_empty_stmt => self.finishAirBookkeeping(), .dbg_inline_block => try self.airDbgInlineBlock(inst), .dbg_var_ptr, .dbg_var_val, diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 24497defa2e773223dbba79c310008e4e933beca..29a0a8b8b5b4e36e9f39890a0f0117620b4536ea 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -1593,6 +1593,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { .frame_addr => try func.airFrameAddress(inst), .cond_br => try func.airCondBr(inst), .dbg_stmt => try func.airDbgStmt(inst), + .dbg_empty_stmt => func.finishAirBookkeeping(), .fptrunc => try func.airFptrunc(inst), .fpext => try func.airFpext(inst), .intcast => try func.airIntCast(inst), diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig index a1bef1f4cd3ac4f818e24732ef42aa9fd1f836e2..7bbed29d8fabe140329e318cc1196bdd21e36e4b 100644 --- a/src/arch/sparc64/CodeGen.zig +++ b/src/arch/sparc64/CodeGen.zig @@ -642,6 +642,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .try_ptr_cold => @panic("TODO try self.airTryPtrCold(inst)"), .dbg_stmt => try self.airDbgStmt(inst), + .dbg_empty_stmt => self.finishAirBookkeeping(), .dbg_inline_block => try self.airDbgInlineBlock(inst), .dbg_var_ptr, .dbg_var_val, diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 50a8869282bc8309fedf73718c64e6b503adeb99..ccdf38a4741e390e9d7adbb6d161d5234366cdbb 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1924,6 +1924,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { .try_ptr_cold => func.airTryPtr(inst), .dbg_stmt => func.airDbgStmt(inst), + .dbg_empty_stmt => try func.finishAir(inst, .none, &.{}), .dbg_inline_block => func.airDbgInlineBlock(inst), .dbg_var_ptr => func.airDbgVar(inst, .local_var, true), .dbg_var_val => func.airDbgVar(inst, .local_var, false), diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 06ae399f25acd6429bb9a6b074dda856563d2978..298b2e11e0ec2115cec78c6091a3f16171644d4c 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -961,9 +961,16 @@ pub fn generate( }, .debug_output = debug_output, .code = code, + .prev_di_loc = .{ + .line = func.lbrace_line, + .column = func.lbrace_column, + .is_stmt = switch (debug_output) { + .dwarf => |dwarf| dwarf.dwarf.debug_line.header.default_is_stmt, + .plan9 => undefined, + .none => undefined, + }, + }, .prev_di_pc = 0, - .prev_di_line = func.lbrace_line, - .prev_di_column = func.lbrace_column, }; defer emit.deinit(); emit.emitMir() catch |err| switch (err) { @@ -1066,9 +1073,8 @@ pub fn generateLazy( }, .debug_output = debug_output, .code = code, + .prev_di_loc = undefined, // no debug info yet .prev_di_pc = undefined, // no debug info yet - .prev_di_line = undefined, // no debug info yet - .prev_di_column = undefined, // no debug info yet }; defer emit.deinit(); emit.emitMir() catch |err| switch (err) { @@ -1194,13 +1200,16 @@ fn formatWipMir( switch (mir_inst.ops) { else => unreachable, .pseudo_dbg_prologue_end_none, - .pseudo_dbg_line_line_column, .pseudo_dbg_epilogue_begin_none, .pseudo_dbg_enter_block_none, .pseudo_dbg_leave_block_none, .pseudo_dbg_var_args_none, .pseudo_dead_none, => {}, + .pseudo_dbg_line_stmt_line_column, .pseudo_dbg_line_line_column => try writer.print( + " {[line]d}, {[column]d}", + mir_inst.data.line_column, + ), .pseudo_dbg_enter_inline_func, .pseudo_dbg_leave_inline_func => try writer.print(" {}", .{ ip.getNav(ip.indexToKey(mir_inst.data.func).func.owner_nav).name.fmt(ip), }), @@ -1281,14 +1290,7 @@ fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { try self.mir_instructions.ensureUnusedCapacity(gpa, 1); const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len); self.mir_instructions.appendAssumeCapacity(inst); - if (inst.tag != .pseudo or switch (inst.ops) { - else => true, - .pseudo_dbg_prologue_end_none, - .pseudo_dbg_line_line_column, - .pseudo_dbg_epilogue_begin_none, - .pseudo_dead_none, - => false, - }) wip_mir_log.debug("{}", .{self.fmtWipMir(result_index)}); + wip_mir_log.debug("{}", .{self.fmtWipMir(result_index)}); return result_index; } @@ -2218,7 +2220,7 @@ fn gen(self: *Self) InnerError!void { // Drop them off at the rbrace. _ = try self.addInst(.{ .tag = .pseudo, - .ops = .pseudo_dbg_line_line_column, + .ops = .pseudo_dbg_line_stmt_line_column, .data = .{ .line_column = .{ .line = self.end_di_line, .column = self.end_di_column, @@ -2426,6 +2428,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .try_ptr_cold => try self.airTryPtr(inst), // TODO .dbg_stmt => try self.airDbgStmt(inst), + .dbg_empty_stmt => try self.airDbgEmptyStmt(), .dbg_inline_block => try self.airDbgInlineBlock(inst), .dbg_var_ptr, .dbg_var_val, @@ -13281,7 +13284,7 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; _ = try self.addInst(.{ .tag = .pseudo, - .ops = .pseudo_dbg_line_line_column, + .ops = .pseudo_dbg_line_stmt_line_column, .data = .{ .line_column = .{ .line = dbg_stmt.line, .column = dbg_stmt.column, @@ -13290,6 +13293,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void { self.finishAirBookkeeping(); } +fn airDbgEmptyStmt(self: *Self) !void { + if (self.mir_instructions.len > 0 and + self.mir_instructions.items(.ops)[self.mir_instructions.len - 1] == .pseudo_dbg_line_stmt_line_column) + self.mir_instructions.items(.ops)[self.mir_instructions.len - 1] = .pseudo_dbg_line_line_column; + try self.asmOpOnly(.{ ._, .nop }); + self.finishAirBookkeeping(); +} + fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void { const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload); diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index 0395b7a43bcfa90d9e93a2917007b4b8d007838a..f744eb3fc4d7077728a3a2d937183e6b2346e0ed 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -6,8 +6,7 @@ atom_index: u32, debug_output: link.File.DebugInfoOutput, code: *std.ArrayList(u8), -prev_di_line: u32, -prev_di_column: u32, +prev_di_loc: Loc, /// Relative to the beginning of `code`. prev_di_pc: usize, @@ -263,77 +262,71 @@ pub fn emitMir(emit: *Emit) Error!void { else => unreachable, .pseudo => switch (mir_inst.ops) { else => unreachable, - .pseudo_dbg_prologue_end_none => { - switch (emit.debug_output) { - .dwarf => |dw| try dw.setPrologueEnd(), - .plan9 => {}, - .none => {}, - } + .pseudo_dbg_prologue_end_none => switch (emit.debug_output) { + .dwarf => |dwarf| try dwarf.setPrologueEnd(), + .plan9 => {}, + .none => {}, }, - .pseudo_dbg_line_line_column => try emit.dbgAdvancePCAndLine( - mir_inst.data.line_column.line, - mir_inst.data.line_column.column, - ), - .pseudo_dbg_epilogue_begin_none => { - switch (emit.debug_output) { - .dwarf => |dw| { - try dw.setEpilogueBegin(); - log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ - emit.prev_di_line, emit.prev_di_column, - }); - try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); - }, - .plan9 => {}, - .none => {}, - } + .pseudo_dbg_line_stmt_line_column => try emit.dbgAdvancePCAndLine(.{ + .line = mir_inst.data.line_column.line, + .column = mir_inst.data.line_column.column, + .is_stmt = true, + }), + .pseudo_dbg_line_line_column => try emit.dbgAdvancePCAndLine(.{ + .line = mir_inst.data.line_column.line, + .column = mir_inst.data.line_column.column, + .is_stmt = false, + }), + .pseudo_dbg_epilogue_begin_none => switch (emit.debug_output) { + .dwarf => |dwarf| { + try dwarf.setEpilogueBegin(); + log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ + emit.prev_di_loc.line, emit.prev_di_loc.column, + }); + try emit.dbgAdvancePCAndLine(emit.prev_di_loc); + }, + .plan9 => {}, + .none => {}, }, - .pseudo_dbg_enter_block_none => { - switch (emit.debug_output) { - .dwarf => |dw| { - log.debug("mirDbgEnterBlock (line={d}, col={d})", .{ - emit.prev_di_line, emit.prev_di_column, - }); - try dw.enterBlock(emit.code.items.len); - }, - .plan9 => {}, - .none => {}, - } + .pseudo_dbg_enter_block_none => switch (emit.debug_output) { + .dwarf => |dwarf| { + log.debug("mirDbgEnterBlock (line={d}, col={d})", .{ + emit.prev_di_loc.line, emit.prev_di_loc.column, + }); + try dwarf.enterBlock(emit.code.items.len); + }, + .plan9 => {}, + .none => {}, }, - .pseudo_dbg_leave_block_none => { - switch (emit.debug_output) { - .dwarf => |dw| { - log.debug("mirDbgLeaveBlock (line={d}, col={d})", .{ - emit.prev_di_line, emit.prev_di_column, - }); - try dw.leaveBlock(emit.code.items.len); - }, - .plan9 => {}, - .none => {}, - } + .pseudo_dbg_leave_block_none => switch (emit.debug_output) { + .dwarf => |dwarf| { + log.debug("mirDbgLeaveBlock (line={d}, col={d})", .{ + emit.prev_di_loc.line, emit.prev_di_loc.column, + }); + try dwarf.leaveBlock(emit.code.items.len); + }, + .plan9 => {}, + .none => {}, }, - .pseudo_dbg_enter_inline_func => { - switch (emit.debug_output) { - .dwarf => |dw| { - log.debug("mirDbgEnterInline (line={d}, col={d})", .{ - emit.prev_di_line, emit.prev_di_column, - }); - try dw.enterInlineFunc(mir_inst.data.func, emit.code.items.len, emit.prev_di_line, emit.prev_di_column); - }, - .plan9 => {}, - .none => {}, - } + .pseudo_dbg_enter_inline_func => switch (emit.debug_output) { + .dwarf => |dwarf| { + log.debug("mirDbgEnterInline (line={d}, col={d})", .{ + emit.prev_di_loc.line, emit.prev_di_loc.column, + }); + try dwarf.enterInlineFunc(mir_inst.data.func, emit.code.items.len, emit.prev_di_loc.line, emit.prev_di_loc.column); + }, + .plan9 => {}, + .none => {}, }, - .pseudo_dbg_leave_inline_func => { - switch (emit.debug_output) { - .dwarf => |dw| { - log.debug("mirDbgLeaveInline (line={d}, col={d})", .{ - emit.prev_di_line, emit.prev_di_column, - }); - try dw.leaveInlineFunc(mir_inst.data.func, emit.code.items.len); - }, - .plan9 => {}, - .none => {}, - } + .pseudo_dbg_leave_inline_func => switch (emit.debug_output) { + .dwarf => |dwarf| { + log.debug("mirDbgLeaveInline (line={d}, col={d})", .{ + emit.prev_di_loc.line, emit.prev_di_loc.column, + }); + try dwarf.leaveInlineFunc(mir_inst.data.func, emit.code.items.len); + }, + .plan9 => {}, + .none => {}, }, .pseudo_dbg_local_a, .pseudo_dbg_local_ai_s, @@ -344,129 +337,125 @@ pub fn emitMir(emit: *Emit) Error!void { .pseudo_dbg_local_aro, .pseudo_dbg_local_af, .pseudo_dbg_local_am, - => { - switch (emit.debug_output) { - .dwarf => |dw| { - var loc_buf: [2]link.File.Dwarf.Loc = undefined; - const air_inst_index, const loc: link.File.Dwarf.Loc = switch (mir_inst.ops) { + => switch (emit.debug_output) { + .dwarf => |dwarf| { + var loc_buf: [2]link.File.Dwarf.Loc = undefined; + const air_inst_index, const loc: link.File.Dwarf.Loc = switch (mir_inst.ops) { + else => unreachable, + .pseudo_dbg_local_a => .{ mir_inst.data.a.air_inst, .empty }, + .pseudo_dbg_local_ai_s, + .pseudo_dbg_local_ai_u, + .pseudo_dbg_local_ai_64, + => .{ mir_inst.data.ai.air_inst, .{ .stack_value = stack_value: { + loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.ai.i)) { + .signed => |s| .{ .consts = s }, + .unsigned => |u| .{ .constu = u }, + }; + break :stack_value &loc_buf[0]; + } } }, + .pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{ .addr = .{ + .sym = mir_inst.data.as.sym_index, + } } }, + .pseudo_dbg_local_aso => loc: { + const sym_off = emit.lower.mir.extraData( + bits.SymbolOffset, + mir_inst.data.ax.payload, + ).data; + break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{ + sym: { + loc_buf[0] = .{ .addr = .{ .sym = sym_off.sym_index } }; + break :sym &loc_buf[0]; + }, + off: { + loc_buf[1] = .{ .consts = sym_off.off }; + break :off &loc_buf[1]; + }, + } } }; + }, + .pseudo_dbg_local_aro => loc: { + const air_off = emit.lower.mir.extraData( + Mir.AirOffset, + mir_inst.data.rx.payload, + ).data; + break :loc .{ air_off.air_inst, .{ .plus = .{ + reg: { + loc_buf[0] = .{ .breg = mir_inst.data.rx.r1.dwarfNum() }; + break :reg &loc_buf[0]; + }, + off: { + loc_buf[1] = .{ .consts = air_off.off }; + break :off &loc_buf[1]; + }, + } } }; + }, + .pseudo_dbg_local_af => loc: { + const reg_off = emit.lower.mir.resolveFrameAddr(emit.lower.mir.extraData( + bits.FrameAddr, + mir_inst.data.ax.payload, + ).data); + break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{ + reg: { + loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() }; + break :reg &loc_buf[0]; + }, + off: { + loc_buf[1] = .{ .consts = reg_off.off }; + break :off &loc_buf[1]; + }, + } } }; + }, + .pseudo_dbg_local_am => loc: { + const mem = emit.lower.mem(mir_inst.data.ax.payload); + break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{ + base: { + loc_buf[0] = switch (mem.base()) { + .none => .{ .constu = 0 }, + .reg => |reg| .{ .breg = reg.dwarfNum() }, + .frame => unreachable, + .reloc => |sym_index| .{ .addr = .{ .sym = sym_index } }, + }; + break :base &loc_buf[0]; + }, + disp: { + loc_buf[1] = switch (mem.disp()) { + .signed => |s| .{ .consts = s }, + .unsigned => |u| .{ .constu = u }, + }; + break :disp &loc_buf[1]; + }, + } } }; + }, + }; + const ip = &emit.lower.bin_file.comp.zcu.?.intern_pool; + const air_inst = emit.air.instructions.get(@intFromEnum(air_inst_index)); + const name: Air.NullTerminatedString = switch (air_inst.tag) { + else => unreachable, + .arg => air_inst.data.arg.name, + .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => @enumFromInt(air_inst.data.pl_op.payload), + }; + try dwarf.genLocalDebugInfo( + switch (air_inst.tag) { else => unreachable, - .pseudo_dbg_local_a => .{ mir_inst.data.a.air_inst, .empty }, - .pseudo_dbg_local_ai_s, - .pseudo_dbg_local_ai_u, - .pseudo_dbg_local_ai_64, - => .{ mir_inst.data.ai.air_inst, .{ .stack_value = stack_value: { - loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.ai.i)) { - .signed => |s| .{ .consts = s }, - .unsigned => |u| .{ .constu = u }, - }; - break :stack_value &loc_buf[0]; - } } }, - .pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{ .addr = .{ - .sym = mir_inst.data.as.sym_index, - } } }, - .pseudo_dbg_local_aso => loc: { - const sym_off = emit.lower.mir.extraData( - bits.SymbolOffset, - mir_inst.data.ax.payload, - ).data; - break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{ - sym: { - loc_buf[0] = .{ .addr = .{ .sym = sym_off.sym_index } }; - break :sym &loc_buf[0]; - }, - off: { - loc_buf[1] = .{ .consts = sym_off.off }; - break :off &loc_buf[1]; - }, - } } }; - }, - .pseudo_dbg_local_aro => loc: { - const air_off = emit.lower.mir.extraData( - Mir.AirOffset, - mir_inst.data.rx.payload, - ).data; - break :loc .{ air_off.air_inst, .{ .plus = .{ - reg: { - loc_buf[0] = .{ .breg = mir_inst.data.rx.r1.dwarfNum() }; - break :reg &loc_buf[0]; - }, - off: { - loc_buf[1] = .{ .consts = air_off.off }; - break :off &loc_buf[1]; - }, - } } }; - }, - .pseudo_dbg_local_af => loc: { - const reg_off = emit.lower.mir.resolveFrameAddr(emit.lower.mir.extraData( - bits.FrameAddr, - mir_inst.data.ax.payload, - ).data); - break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{ - reg: { - loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() }; - break :reg &loc_buf[0]; - }, - off: { - loc_buf[1] = .{ .consts = reg_off.off }; - break :off &loc_buf[1]; - }, - } } }; - }, - .pseudo_dbg_local_am => loc: { - const mem = emit.lower.mem(mir_inst.data.ax.payload); - break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{ - base: { - loc_buf[0] = switch (mem.base()) { - .none => .{ .constu = 0 }, - .reg => |reg| .{ .breg = reg.dwarfNum() }, - .frame => unreachable, - .reloc => |sym_index| .{ .addr = .{ .sym = sym_index } }, - }; - break :base &loc_buf[0]; - }, - disp: { - loc_buf[1] = switch (mem.disp()) { - .signed => |s| .{ .consts = s }, - .unsigned => |u| .{ .constu = u }, - }; - break :disp &loc_buf[1]; - }, - } } }; - }, - }; - const ip = &emit.lower.bin_file.comp.zcu.?.intern_pool; - const air_inst = emit.air.instructions.get(@intFromEnum(air_inst_index)); - const name: Air.NullTerminatedString = switch (air_inst.tag) { + .arg, .dbg_arg_inline => .local_arg, + .dbg_var_ptr, .dbg_var_val => .local_var, + }, + name.toSlice(emit.air), + switch (air_inst.tag) { else => unreachable, - .arg => air_inst.data.arg.name, - .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => @enumFromInt(air_inst.data.pl_op.payload), - }; - try dw.genLocalDebugInfo( - switch (air_inst.tag) { - else => unreachable, - .arg, .dbg_arg_inline => .local_arg, - .dbg_var_ptr, .dbg_var_val => .local_var, - }, - name.toSlice(emit.air), - switch (air_inst.tag) { - else => unreachable, - .arg => emit.air.typeOfIndex(air_inst_index, ip), - .dbg_var_ptr => emit.air.typeOf(air_inst.data.pl_op.operand, ip).childTypeIp(ip), - .dbg_var_val, .dbg_arg_inline => emit.air.typeOf(air_inst.data.pl_op.operand, ip), - }, - loc, - ); - }, - .plan9 => {}, - .none => {}, - } + .arg => emit.air.typeOfIndex(air_inst_index, ip), + .dbg_var_ptr => emit.air.typeOf(air_inst.data.pl_op.operand, ip).childTypeIp(ip), + .dbg_var_val, .dbg_arg_inline => emit.air.typeOf(air_inst.data.pl_op.operand, ip), + }, + loc, + ); + }, + .plan9 => {}, + .none => {}, }, - .pseudo_dbg_var_args_none => { - switch (emit.debug_output) { - .dwarf => |dw| try dw.genVarArgsDebugInfo(), - .plan9 => {}, - .none => {}, - } + .pseudo_dbg_var_args_none => switch (emit.debug_output) { + .dwarf => |dwarf| try dwarf.genVarArgsDebugInfo(), + .plan9 => {}, + .none => {}, }, .pseudo_dead_none => {}, }, @@ -515,16 +504,22 @@ fn fixupRelocs(emit: *Emit) Error!void { } } -fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void { - const delta_line = @as(i33, line) - @as(i33, emit.prev_di_line); +const Loc = struct { + line: u32, + column: u32, + is_stmt: bool, +}; + +fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void { + const delta_line = @as(i33, loc.line) - @as(i33, emit.prev_di_loc.line); const delta_pc: usize = emit.code.items.len - emit.prev_di_pc; log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line }); switch (emit.debug_output) { - .dwarf => |dw| { - if (column != emit.prev_di_column) try dw.setColumn(column); - try dw.advancePCAndLine(delta_line, delta_pc); - emit.prev_di_line = line; - emit.prev_di_column = column; + .dwarf => |dwarf| { + if (loc.is_stmt != emit.prev_di_loc.is_stmt) try dwarf.negateStmt(); + if (loc.column != emit.prev_di_loc.column) try dwarf.setColumn(loc.column); + try dwarf.advancePCAndLine(delta_line, delta_pc); + emit.prev_di_loc = loc; emit.prev_di_pc = emit.code.items.len; }, .plan9 => |dbg_out| { @@ -553,11 +548,10 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void { // we don't need to do anything, because adding the pc quanta does it for us } else unreachable; if (dbg_out.start_line == null) - dbg_out.start_line = emit.prev_di_line; - dbg_out.end_line = line; + dbg_out.start_line = emit.prev_di_loc.line; + dbg_out.end_line = loc.line; // only do this if the pc changed - emit.prev_di_line = line; - emit.prev_di_column = column; + emit.prev_di_loc = loc; emit.prev_di_pc = emit.code.items.len; }, .none => {}, diff --git a/src/arch/x86_64/Lower.zig b/src/arch/x86_64/Lower.zig index 6ac79378c1ce27252a76ad44b848f21406eaae36..015b3ba12ec74d669a8d1d3c3dc77295044ab1a3 100644 --- a/src/arch/x86_64/Lower.zig +++ b/src/arch/x86_64/Lower.zig @@ -310,6 +310,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { }), .pseudo_dbg_prologue_end_none, + .pseudo_dbg_line_stmt_line_column, .pseudo_dbg_line_line_column, .pseudo_dbg_epilogue_begin_none, .pseudo_dbg_enter_block_none, diff --git a/src/arch/x86_64/Mir.zig b/src/arch/x86_64/Mir.zig index 0e9d01075860af6cfc00ac8a1707c406aafd59f0..a7f308b7b44459198fa21fb8fa6f0f29892eabf1 100644 --- a/src/arch/x86_64/Mir.zig +++ b/src/arch/x86_64/Mir.zig @@ -930,7 +930,10 @@ pub const Inst = struct { /// End of prologue pseudo_dbg_prologue_end_none, - /// Update debug line + /// Update debug line with is_stmt register set + /// Uses `line_column` payload. + pseudo_dbg_line_stmt_line_column, + /// Update debug line with is_stmt register clear /// Uses `line_column` payload. pseudo_dbg_line_line_column, /// Start of epilogue diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 0410023588d7bd6c3695014186c1227451b41bb2..56466b4395978c64f9a2a43f330d68835bf42449 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -3289,6 +3289,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, .try_ptr_cold => try airTryPtr(f, inst), .dbg_stmt => try airDbgStmt(f, inst), + .dbg_empty_stmt => try airDbgEmptyStmt(f, inst), .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => try airDbgVar(f, inst), .float_from_int, @@ -4601,6 +4602,11 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { return .none; } +fn airDbgEmptyStmt(f: *Function, _: Air.Inst.Index) !CValue { + try f.object.writer().writeAll("(void)0;\n"); + return .none; +} + fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue { const pt = f.object.dg.pt; const zcu = pt.zcu; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index fb20d4d622dff625a73749ab97c5edd5000c8ef6..d0b12350c0988939e399f19eace3e2d4cf048dad 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5391,6 +5391,7 @@ pub const FuncGen = struct { .inferred_alloc, .inferred_alloc_comptime => unreachable, .dbg_stmt => try self.airDbgStmt(inst), + .dbg_empty_stmt => try self.airDbgEmptyStmt(inst), .dbg_var_ptr => try self.airDbgVarPtr(inst), .dbg_var_val => try self.airDbgVarVal(inst, false), .dbg_arg_inline => try self.airDbgVarVal(inst, true), @@ -7433,6 +7434,12 @@ pub const FuncGen = struct { return .none; } + fn airDbgEmptyStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { + _ = self; + _ = inst; + return .none; + } + fn airDbgInlineBlock(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload); diff --git a/src/dev.zig b/src/dev.zig index 0d365c3e19f28f685154b2797d889094fe742297..d623a708e77a8081a3d9056f4014bf3ed2f9f4c0 100644 --- a/src/dev.zig +++ b/src/dev.zig @@ -81,6 +81,7 @@ pub const Env = enum { => true, .cc_command, .translate_c_command, + .fmt_command, .jit_command, .fetch_command, .init_command, @@ -168,6 +169,7 @@ pub const Feature = enum { clang_command, cc_command, translate_c_command, + fmt_command, jit_command, fetch_command, init_command, diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 6653a8309a6f61cab6fead88664e5b8f2d2407e1..afdc5d1d4802ee15e0e383bfe1b98c49d109dc2a 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1474,6 +1474,11 @@ pub const WipNav = struct { try uleb128(dlw, column + 1); } + pub fn negateStmt(wip_nav: *WipNav) error{OutOfMemory}!void { + const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa); + try dlw.writeByte(DW.LNS.negate_stmt); + } + pub fn setPrologueEnd(wip_nav: *WipNav) error{OutOfMemory}!void { const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa); try dlw.writeByte(DW.LNS.set_prologue_end); diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 1e29ab8bf60604d6cabee1810686699b73a30a31..effe12539ce84d79b95ccb82f06aa10d0c1c26f0 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -1496,7 +1496,7 @@ pub fn updateFunc( }); defer gpa.free(name); const osec = if (self.text_index) |sect_sym_index| - self.symbol(sect_sym_index).output_section_index + self.symbol(sect_sym_index).outputShndx(elf_file).? else osec: { const osec = try elf_file.addSection(.{ .name = try elf_file.insertShString(".text"), diff --git a/src/main.zig b/src/main.zig index 291820cb75233a4da504fb43c3d009cad9b39000..13e24d8c25932f6fa76622511d7ddf19fa43ad08 100644 --- a/src/main.zig +++ b/src/main.zig @@ -309,6 +309,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { .server = use_server, }); } else if (mem.eql(u8, cmd, "fmt")) { + dev.check(.fmt_command); return @import("fmt.zig").run(gpa, arena, cmd_args); } else if (mem.eql(u8, cmd, "objcopy")) { return jitCmd(gpa, arena, cmd_args, .{ diff --git a/src/print_air.zig b/src/print_air.zig index 6a3f31a27c2ce513bdb8fdec00f99047ba07197c..280d05edfa7d63793930032e33a3f1dbd262f208 100644 --- a/src/print_air.zig +++ b/src/print_air.zig @@ -202,6 +202,7 @@ const Writer = struct { .trap, .breakpoint, + .dbg_empty_stmt, .unreach, .ret_addr, .frame_addr, diff --git a/src/print_zir.zig b/src/print_zir.zig index b8f4432e72a5441505160f6c8d5f8b215caeeb15..808ead0e7991ed9e5b9e1212fa8c631628b364f4 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -621,6 +621,8 @@ const Writer = struct { .field_parent_ptr => try self.writeFieldParentPtr(stream, extended), .builtin_value => try self.writeBuiltinValue(stream, extended), .inplace_arith_result_ty => try self.writeInplaceArithResultTy(stream, extended), + + .dbg_empty_stmt => try stream.writeAll("))"), } } diff --git a/test/src/Debugger.zig b/test/src/Debugger.zig index b4b453700d254531e9ded4d732f959e56aca84bf..1e2289eb11bfcfff6339cdaf906b39ab7cf4c81a 100644 --- a/test/src/Debugger.zig +++ b/test/src/Debugger.zig @@ -808,6 +808,424 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void { \\1 breakpoints deleted; 0 breakpoint locations disabled. }, ); + db.addLldbTest( + "step_single_stmt_loops", + target, + &.{ + .{ + .path = "step_single_stmt_loops.zig", + .source = + \\pub fn main() void { + \\ var x: u32 = 0; + \\ for (0..3) |_| { + \\ x +%= 1; + \\ } + \\ { + \\ var i: u32 = 0; + \\ while (i < 3) : (i +%= 1) { + \\ x +%= 1; + \\ } + \\ } + \\ { + \\ var i: u32 = 0; + \\ while (i < 3) { + \\ i +%= 1; + \\ } + \\ } + \\ inline for (0..3) |_| { + \\ x +%= 1; + \\ } + \\ { + \\ comptime var i: u32 = 0; + \\ inline while (i < 3) : (i +%= 1) { + \\ x +%= 1; + \\ } + \\ } + \\ { + \\ comptime var i: u32 = 0; + \\ inline while (i < 3) { + \\ i +%= 1; + \\ } + \\ } + \\ x +%= 1; + \\} + \\ + , + }, + }, + \\breakpoint set --name step_single_stmt_loops.main + \\process launch + \\thread step-in + \\#00 + \\frame variable x + \\thread step-in + \\#01 + \\frame variable x + \\thread step-in + \\#02 + \\frame variable x + \\thread step-in + \\#03 + \\frame variable x + \\thread step-in + \\#04 + \\frame variable x + \\thread step-in + \\#05 + \\frame variable x + \\thread step-in + \\#06 + \\frame variable x + \\thread step-in + \\#07 + \\frame variable x + \\thread step-in + \\#08 + \\frame variable x + \\thread step-in + \\#09 + \\frame variable x + \\thread step-in + \\#10 + \\frame variable x + \\thread step-in + \\#11 + \\frame variable x + \\thread step-in + \\#12 + \\frame variable x + \\thread step-in + \\#13 + \\frame variable x + \\thread step-in + \\#14 + \\frame variable x + \\thread step-in + \\#15 + \\frame variable x + \\thread step-in + \\#16 + \\frame variable x + \\thread step-in + \\#17 + \\frame variable x + \\thread step-in + \\#18 + \\frame variable x + \\thread step-in + \\#19 + \\frame variable x + \\thread step-in + \\#20 + \\frame variable x + \\thread step-in + \\#21 + \\frame variable x + \\thread step-in + \\#22 + \\frame variable x + \\thread step-in + \\#23 + \\frame variable x + \\thread step-in + \\#24 + \\frame variable x + \\thread step-in + \\#25 + \\frame variable x + \\thread step-in + \\#26 + \\frame variable x + \\thread step-in + \\#27 + \\frame variable x + \\thread step-in + \\#28 + \\frame variable x + \\thread step-in + \\#29 + \\frame variable x + \\thread step-in + \\#30 + \\frame variable x + \\thread step-in + \\#31 + \\frame variable x + \\thread step-in + \\#32 + \\frame variable x + \\thread step-in + \\#33 + \\frame variable x + \\thread step-in + \\#34 + \\frame variable x + \\thread step-in + \\#35 + \\frame variable x + \\thread step-in + \\#36 + \\frame variable x + \\thread step-in + \\#37 + \\frame variable x + \\thread step-in + \\#38 + \\frame variable x + \\thread step-in + \\#39 + \\frame variable x + \\thread step-in + \\#40 + \\frame variable x + \\thread step-in + \\#41 + \\frame variable x + \\thread step-in + \\#42 + \\frame variable x + \\thread step-in + \\#43 + \\frame variable x + \\thread step-in + \\#44 + \\frame variable x + \\thread step-in + \\#45 + \\frame variable x + \\ + , + &.{ + \\(lldb) #00 + \\(lldb) frame variable x + \\(u32) x = 0 + \\(lldb) thread step-in + , + \\(lldb) #01 + \\(lldb) frame variable x + \\(u32) x = 0 + \\(lldb) thread step-in + , + \\(lldb) #02 + \\(lldb) frame variable x + \\(u32) x = 1 + \\(lldb) thread step-in + , + \\(lldb) #03 + \\(lldb) frame variable x + \\(u32) x = 1 + \\(lldb) thread step-in + , + \\(lldb) #04 + \\(lldb) frame variable x + \\(u32) x = 1 + \\(lldb) thread step-in + , + \\(lldb) #05 + \\(lldb) frame variable x + \\(u32) x = 2 + \\(lldb) thread step-in + , + \\(lldb) #06 + \\(lldb) frame variable x + \\(u32) x = 2 + \\(lldb) thread step-in + , + \\(lldb) #07 + \\(lldb) frame variable x + \\(u32) x = 2 + \\(lldb) thread step-in + , + \\(lldb) #08 + \\(lldb) frame variable x + \\(u32) x = 3 + \\(lldb) thread step-in + , + \\(lldb) #09 + \\(lldb) frame variable x + \\(u32) x = 3 + \\(lldb) thread step-in + , + \\(lldb) #10 + \\(lldb) frame variable x + \\(u32) x = 3 + \\(lldb) thread step-in + , + \\(lldb) #11 + \\(lldb) frame variable x + \\(u32) x = 3 + \\(lldb) thread step-in + , + \\(lldb) #12 + \\(lldb) frame variable x + \\(u32) x = 3 + \\(lldb) thread step-in + , + \\(lldb) #13 + \\(lldb) frame variable x + \\(u32) x = 4 + \\(lldb) thread step-in + , + \\(lldb) #14 + \\(lldb) frame variable x + \\(u32) x = 4 + \\(lldb) thread step-in + , + \\(lldb) #15 + \\(lldb) frame variable x + \\(u32) x = 4 + \\(lldb) thread step-in + , + \\(lldb) #16 + \\(lldb) frame variable x + \\(u32) x = 5 + \\(lldb) thread step-in + , + \\(lldb) #17 + \\(lldb) frame variable x + \\(u32) x = 5 + \\(lldb) thread step-in + , + \\(lldb) #18 + \\(lldb) frame variable x + \\(u32) x = 5 + \\(lldb) thread step-in + , + \\(lldb) #19 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #20 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #21 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #22 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #23 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #24 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #25 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #26 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #27 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #28 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #29 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #30 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #31 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #32 + \\(lldb) frame variable x + \\(u32) x = 6 + \\(lldb) thread step-in + , + \\(lldb) #33 + \\(lldb) frame variable x + \\(u32) x = 7 + \\(lldb) thread step-in + , + \\(lldb) #34 + \\(lldb) frame variable x + \\(u32) x = 7 + \\(lldb) thread step-in + , + \\(lldb) #35 + \\(lldb) frame variable x + \\(u32) x = 8 + \\(lldb) thread step-in + , + \\(lldb) #36 + \\(lldb) frame variable x + \\(u32) x = 8 + \\(lldb) thread step-in + , + \\(lldb) #37 + \\(lldb) frame variable x + \\(u32) x = 9 + \\(lldb) thread step-in + , + \\(lldb) #38 + \\(lldb) frame variable x + \\(u32) x = 9 + \\(lldb) thread step-in + , + \\(lldb) #39 + \\(lldb) frame variable x + \\(u32) x = 10 + \\(lldb) thread step-in + , + \\(lldb) #40 + \\(lldb) frame variable x + \\(u32) x = 10 + \\(lldb) thread step-in + , + \\(lldb) #41 + \\(lldb) frame variable x + \\(u32) x = 11 + \\(lldb) thread step-in + , + \\(lldb) #42 + \\(lldb) frame variable x + \\(u32) x = 11 + \\(lldb) thread step-in + , + \\(lldb) #43 + \\(lldb) frame variable x + \\(u32) x = 12 + \\(lldb) thread step-in + , + \\(lldb) #44 + \\(lldb) frame variable x + \\(u32) x = 12 + \\(lldb) thread step-in + , + \\(lldb) #45 + \\(lldb) frame variable x + \\(u32) x = 12 + }, + ); db.addLldbTest( "inline_call", target, -- 2.54.0