Dwarf: implement new incremental line number update API

This commit is contained in:
Jacob Young 2025-01-04 00:32:28 -05:00 committed by mlugg
parent 065e10c95c
commit dde3116e50
No known key found for this signature in database
GPG key ID: 3F5B7DCCBF4AF02E
10 changed files with 851 additions and 466 deletions

View file

@ -64,7 +64,7 @@ stage3-debug/bin/zig build \
stage3-debug/bin/zig build test docs \
--maxrss 21000000000 \
-Dlldb=$HOME/deps/lldb-zig/Debug-bfeada333/bin/lldb \
-Dlldb=$HOME/deps/lldb-zig/Debug-e0a42bb34/bin/lldb \
-fqemu \
-fwasmtime \
-Dstatic-llvm \

View file

@ -64,7 +64,7 @@ stage3-release/bin/zig build \
stage3-release/bin/zig build test docs \
--maxrss 21000000000 \
-Dlldb=$HOME/deps/lldb-zig/Release-bfeada333/bin/lldb \
-Dlldb=$HOME/deps/lldb-zig/Release-e0a42bb34/bin/lldb \
-fqemu \
-fwasmtime \
-Dstatic-llvm \

View file

@ -168,6 +168,8 @@ pub const TrackedInst = extern struct {
_ => @enumFromInt(@intFromEnum(opt)),
};
}
const debug_state = InternPool.debug_state;
};
pub const Unwrapped = struct {
@ -187,6 +189,8 @@ pub const TrackedInst = extern struct {
.index = @intFromEnum(tracked_inst_index) & ip.getIndexMask(u32),
};
}
const debug_state = InternPool.debug_state;
};
};
@ -508,7 +512,7 @@ pub const Nav = struct {
/// The fully-qualified name of this `Nav`.
fqn: NullTerminatedString,
/// This field is populated iff this `Nav` is resolved by semantic analysis.
/// If this is `null`, then `status == .resolved` always.
/// If this is `null`, then `status == .fully_resolved` always.
analysis: ?struct {
namespace: NamespaceIndex,
zir_index: TrackedInst.Index,
@ -6631,6 +6635,8 @@ pub fn activate(ip: *const InternPool) void {
_ = OptionalString.debug_state;
_ = NullTerminatedString.debug_state;
_ = OptionalNullTerminatedString.debug_state;
_ = TrackedInst.Index.debug_state;
_ = TrackedInst.Index.Optional.debug_state;
_ = Nav.Index.debug_state;
_ = Nav.Index.Optional.debug_state;
std.debug.assert(debug_state.intern_pool == null);

File diff suppressed because it is too large Load diff

View file

@ -1463,19 +1463,7 @@ pub fn updateFunc(
break :blk .{ atom_ptr.value, atom_ptr.alignment };
};
if (debug_wip_nav) |*wip_nav| {
const sym = self.symbol(sym_index);
try self.dwarf.?.finishWipNav(
pt,
func.owner_nav,
.{
.index = sym_index,
.addr = @intCast(sym.address(.{}, elf_file)),
.size = self.atom(sym.ref.index).?.size,
},
wip_nav,
);
}
if (debug_wip_nav) |*wip_nav| try self.dwarf.?.finishWipNavFunc(pt, func.owner_nav, code.len, wip_nav);
// Exports will be updated by `Zcu.processExports` after the update.
@ -1546,13 +1534,21 @@ pub fn updateNav(
.func => .none,
.variable => |variable| variable.init,
.@"extern" => |@"extern"| {
if (ip.isFunctionType(@"extern".ty)) return;
const sym_index = try self.getGlobalSymbol(
elf_file,
nav.name.toSlice(ip),
@"extern".lib_name.toSlice(ip),
);
self.symbol(sym_index).flags.is_extern_ptr = true;
if (!ip.isFunctionType(@"extern".ty)) {
const sym = self.symbol(sym_index);
sym.flags.is_extern_ptr = true;
if (@"extern".is_threadlocal) sym.flags.is_tls = true;
}
if (self.dwarf) |*dwarf| dwarf: {
var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf;
defer debug_wip_nav.deinit();
try dwarf.finishWipNav(pt, nav_index, &debug_wip_nav);
}
return;
},
else => nav.status.fully_resolved.val,
@ -1596,19 +1592,7 @@ pub fn updateNav(
else
try self.updateNavCode(elf_file, pt, nav_index, sym_index, shndx, code, elf.STT_OBJECT);
if (debug_wip_nav) |*wip_nav| {
const sym = self.symbol(sym_index);
try self.dwarf.?.finishWipNav(
pt,
nav_index,
.{
.index = sym_index,
.addr = @intCast(sym.address(.{}, elf_file)),
.size = sym.atom(elf_file).?.size,
},
wip_nav,
);
}
if (debug_wip_nav) |*wip_nav| try self.dwarf.?.finishWipNav(pt, nav_index, wip_nav);
} else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index);
// Exports will be updated by `Zcu.processExports` after the update.

View file

@ -780,8 +780,8 @@ pub fn updateFunc(
var code_buffer = std.ArrayList(u8).init(gpa);
defer code_buffer.deinit();
var dwarf_wip_nav = if (self.dwarf) |*dwarf| try dwarf.initWipNav(pt, func.owner_nav, sym_index) else null;
defer if (dwarf_wip_nav) |*wip_nav| wip_nav.deinit();
var debug_wip_nav = if (self.dwarf) |*dwarf| try dwarf.initWipNav(pt, func.owner_nav, sym_index) else null;
defer if (debug_wip_nav) |*wip_nav| wip_nav.deinit();
const res = try codegen.generateFunction(
&macho_file.base,
@ -791,7 +791,7 @@ pub fn updateFunc(
air,
liveness,
&code_buffer,
if (dwarf_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,
if (debug_wip_nav) |*wip_nav| .{ .dwarf = wip_nav } else .none,
);
const code = switch (res) {
@ -813,19 +813,7 @@ pub fn updateFunc(
break :blk .{ atom.value, atom.alignment };
};
if (dwarf_wip_nav) |*wip_nav| {
const sym = self.symbols.items[sym_index];
try self.dwarf.?.finishWipNav(
pt,
func.owner_nav,
.{
.index = sym_index,
.addr = sym.getAddress(.{}, macho_file),
.size = sym.getAtom(macho_file).?.size,
},
wip_nav,
);
}
if (debug_wip_nav) |*wip_nav| try self.dwarf.?.finishWipNavFunc(pt, func.owner_nav, code.len, wip_nav);
// Exports will be updated by `Zcu.processExports` after the update.
if (old_rva != new_rva and old_rva > 0) {
@ -883,13 +871,20 @@ pub fn updateNav(
.func => .none,
.variable => |variable| variable.init,
.@"extern" => |@"extern"| {
if (ip.isFunctionType(@"extern".ty)) return;
// Extern variable gets a __got entry only
const name = @"extern".name.toSlice(ip);
const lib_name = @"extern".lib_name.toSlice(ip);
const index = try self.getGlobalSymbol(macho_file, name, lib_name);
const sym = &self.symbols.items[index];
sym.flags.is_extern_ptr = true;
const sym_index = try self.getGlobalSymbol(macho_file, name, lib_name);
if (!ip.isFunctionType(@"extern".ty)) {
const sym = &self.symbols.items[sym_index];
sym.flags.is_extern_ptr = true;
if (@"extern".is_threadlocal) sym.flags.tlv = true;
}
if (self.dwarf) |*dwarf| dwarf: {
var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index) orelse break :dwarf;
defer debug_wip_nav.deinit();
try dwarf.finishWipNav(pt, nav_index, &debug_wip_nav);
}
return;
},
else => nav.status.fully_resolved.val,
@ -927,19 +922,7 @@ pub fn updateNav(
else
try self.updateNavCode(macho_file, pt, nav_index, sym_index, sect_index, code);
if (debug_wip_nav) |*wip_nav| {
const sym = self.symbols.items[sym_index];
try self.dwarf.?.finishWipNav(
pt,
nav_index,
.{
.index = sym_index,
.addr = sym.getAddress(.{}, macho_file),
.size = sym.getAtom(macho_file).?.size,
},
wip_nav,
);
}
if (debug_wip_nav) |*wip_nav| try self.dwarf.?.finishWipNav(pt, nav_index, wip_nav);
} else if (self.dwarf) |*dwarf| try dwarf.updateComptimeNav(pt, nav_index);
// Exports will be updated by `Zcu.processExports` after the update.

View file

@ -0,0 +1,32 @@
#target=x86_64-linux-selfhosted
#update=initial version
#file=main.zig
const std = @import("std");
fn Printer(message: []const u8) type {
return struct {
fn print() !void {
try std.io.getStdOut().writeAll(message);
}
};
}
pub fn main() !void {
try Printer("foo\n").print();
try Printer("bar\n").print();
}
#expect_stdout="foo\nbar\n"
#update=change line number
#file=main.zig
const std = @import("std");
fn Printer(message: []const u8) type {
return struct {
fn print() !void {
try std.io.getStdOut().writeAll(message);
}
};
}
pub fn main() !void {
try Printer("foo\n").print();
try Printer("bar\n").print();
}
#expect_stdout="foo\nbar\n"

View file

@ -2,7 +2,7 @@ const std = @import("std");
const Allocator = std.mem.Allocator;
const Cache = std.Build.Cache;
const usage = "usage: incr-check <zig binary path> <input file> [--zig-lib-dir lib] [--debug-zcu] [--debug-link] [--preserve-tmp] [--zig-cc-binary /path/to/zig]";
const usage = "usage: incr-check <zig binary path> <input file> [--zig-lib-dir lib] [--debug-zcu] [--debug-dwarf] [--debug-link] [--preserve-tmp] [--zig-cc-binary /path/to/zig]";
pub fn main() !void {
const fatal = std.process.fatal;
@ -16,6 +16,7 @@ pub fn main() !void {
var opt_lib_dir: ?[]const u8 = null;
var opt_cc_zig: ?[]const u8 = null;
var debug_zcu = false;
var debug_dwarf = false;
var debug_link = false;
var preserve_tmp = false;
@ -27,6 +28,8 @@ pub fn main() !void {
opt_lib_dir = arg_it.next() orelse fatal("expected arg after '--zig-lib-dir'\n{s}", .{usage});
} else if (std.mem.eql(u8, arg, "--debug-zcu")) {
debug_zcu = true;
} else if (std.mem.eql(u8, arg, "--debug-dwarf")) {
debug_dwarf = true;
} else if (std.mem.eql(u8, arg, "--debug-link")) {
debug_link = true;
} else if (std.mem.eql(u8, arg, "--preserve-tmp")) {
@ -85,7 +88,7 @@ pub fn main() !void {
const host = try std.zig.system.resolveTargetQuery(.{});
const debug_log_verbose = debug_zcu or debug_link;
const debug_log_verbose = debug_zcu or debug_dwarf or debug_link;
for (case.targets) |target| {
const target_prog_node = node: {
@ -125,6 +128,9 @@ pub fn main() !void {
if (debug_zcu) {
try child_args.appendSlice(arena, &.{ "--debug-log", "zcu" });
}
if (debug_dwarf) {
try child_args.appendSlice(arena, &.{ "--debug-log", "dwarf" });
}
if (debug_link) {
try child_args.appendSlice(arena, &.{ "--debug-log", "link", "--debug-log", "link_state", "--debug-log", "link_relocs" });
}

View file

@ -25,7 +25,7 @@ def create_struct(parent, name, struct_type, inits):
case lldb.eByteOrderBig:
byte_order = 'big'
field_bytes = field_init.to_bytes(field_size, byte_order, signed=field.type.GetTypeFlags() & lldb.eTypeIsSigned != 0)
elif isinstance(field_init_type, lldb.SBValue):
elif isinstance(field_init, lldb.SBValue):
field_bytes = field_init.data.uint8
else: return
match struct_data.byte_order:
@ -731,7 +731,7 @@ def root_InternPool_Index_SummaryProvider(value, _=None):
if not unwrapped: return '' # .none
tag = unwrapped.GetChildMemberWithName('tag')
tag_value = tag.value
summary = tag.CreateValueFromType(tag.type).GetChildMemberWithName('encodings').GetChildMemberWithName(tag_value.removeprefix('.')).GetChildMemberWithName('summary')
summary = tag.CreateValueFromType(tag.type).GetChildMemberWithName('encodings').GetChildMemberWithName(tag_value.removeprefix('.').removeprefix('@"').removesuffix('"').replace(r'\"', '"')).GetChildMemberWithName('summary')
if not summary: return tag_value
return re.sub(
expr_path_re,
@ -767,7 +767,7 @@ class root_InternPool_Index_Unwrapped_SynthProvider:
shared = ip.GetChildMemberWithName('locals').GetSyntheticValue().child[self.value.GetChildMemberWithName('tid').unsigned].GetChildMemberWithName('shared')
item = shared.GetChildMemberWithName('items').GetChildMemberWithName('view').child[index.unsigned]
self.tag, item_data = item.GetChildMemberWithName('tag'), item.GetChildMemberWithName('data')
encoding = self.tag.CreateValueFromType(self.tag.type).GetChildMemberWithName('encodings').GetChildMemberWithName(self.tag.value.removeprefix('.'))
encoding = self.tag.CreateValueFromType(self.tag.type).GetChildMemberWithName('encodings').GetChildMemberWithName(self.tag.value.removeprefix('.').removeprefix('@"').removesuffix('"').replace(r'\"', '"'))
encoding_index, encoding_data, encoding_payload, encoding_trailing, encoding_config = encoding.GetChildMemberWithName('index'), encoding.GetChildMemberWithName('data'), encoding.GetChildMemberWithName('payload'), encoding.GetChildMemberWithName('trailing'), encoding.GetChildMemberWithName('config')
if encoding_index:
index_type = encoding_index.GetValueAsType()
@ -869,6 +869,7 @@ class root_InternPool_Index_Unwrapped_SynthProvider:
def root_InternPool_String_SummaryProvider(value, _=None):
wrapped = value.unsigned
if wrapped == (1 << 32) - 1: return ''
ip = value.CreateValueFromType(value.type).GetChildMemberWithName('debug_state').GetChildMemberWithName('intern_pool').GetNonSyntheticValue().GetChildMemberWithName('?')
tid_shift_32 = ip.GetChildMemberWithName('tid_shift_32').unsigned
locals_value = ip.GetChildMemberWithName('locals').GetSyntheticValue()
@ -880,24 +881,24 @@ def root_InternPool_String_SummaryProvider(value, _=None):
string.format = lldb.eFormatCString
return string.value
class root_InternPool_Cau_Index_SynthProvider:
class root_InternPool_TrackedInst_Index_SynthProvider:
def __init__(self, value, _=None): self.value = value
def update(self):
self.cau = None
self.tracked_inst = None
wrapped = self.value.unsigned
if wrapped == (1 << 32) - 1: return
ip = self.value.CreateValueFromType(self.value.type).GetChildMemberWithName('debug_state').GetChildMemberWithName('intern_pool').GetNonSyntheticValue().GetChildMemberWithName('?')
tid_shift_31 = ip.GetChildMemberWithName('tid_shift_31').unsigned
tid_shift_32 = ip.GetChildMemberWithName('tid_shift_32').unsigned
locals_value = ip.GetChildMemberWithName('locals').GetSyntheticValue()
local_value = locals_value.child[wrapped >> tid_shift_31]
local_value = locals_value.child[wrapped >> tid_shift_32]
if local_value is None:
wrapped = 0
local_value = locals_value.child[0]
self.cau = local_value.GetChildMemberWithName('shared').GetChildMemberWithName('caus').GetChildMemberWithName('view').GetChildMemberWithName('0').child[wrapped & (1 << tid_shift_31) - 1]
def has_children(self): return self.cau.GetNumChildren(1) > 0
def num_children(self): return self.cau.GetNumChildren()
def get_child_index(self, name): return self.cau.GetIndexOfChildWithName(name)
def get_child_at_index(self, index): return self.cau.GetChildAtIndex(index)
self.tracked_inst = local_value.GetChildMemberWithName('shared').GetChildMemberWithName('tracked_insts').GetChildMemberWithName('view').GetChildMemberWithName('0').child[wrapped & (1 << tid_shift_32) - 1]
def has_children(self): return False if self.tracked_inst is None else self.tracked_inst.GetNumChildren(1) > 0
def num_children(self): return 0 if self.tracked_inst is None else self.tracked_inst.GetNumChildren()
def get_child_index(self, name): return -1 if self.tracked_inst is None else self.tracked_inst.GetIndexOfChildWithName(name)
def get_child_at_index(self, index): return None if self.tracked_inst is None else self.tracked_inst.GetChildAtIndex(index)
class root_InternPool_Nav_Index_SynthProvider:
def __init__(self, value, _=None): self.value = value
@ -913,10 +914,10 @@ class root_InternPool_Nav_Index_SynthProvider:
wrapped = 0
local_value = locals_value.child[0]
self.nav = local_value.GetChildMemberWithName('shared').GetChildMemberWithName('navs').GetChildMemberWithName('view').child[wrapped & (1 << tid_shift_32) - 1]
def has_children(self): return self.nav.GetNumChildren(1) > 0
def num_children(self): return self.nav.GetNumChildren()
def get_child_index(self, name): return self.nav.GetIndexOfChildWithName(name)
def get_child_at_index(self, index): return self.nav.GetChildAtIndex(index)
def has_children(self): return False if self.nav is None else self.nav.GetNumChildren(1) > 0
def num_children(self): return 0 if self.nav is None else self.nav.GetNumChildren()
def get_child_index(self, name): return -1 if self.nav is None else self.nav.GetIndexOfChildWithName(name)
def get_child_at_index(self, index): return None if self.nav is None else self.nav.GetChildAtIndex(index)
# Initialize
@ -973,5 +974,5 @@ def __lldb_init_module(debugger, _=None):
add(debugger, category='zig', type='root.InternPool.Index', synth=True, summary=True)
add(debugger, category='zig', type='root.InternPool.Index.Unwrapped', synth=True)
add(debugger, category='zig', regex=True, type=r'^root\.InternPool\.(Optional)?(NullTerminated)?String$', identifier='root_InternPool_String', summary=True)
add(debugger, category='zig', regex=True, type=r'^root\.InternPool\.Cau\.Index(\.Optional)?$', identifier='root_InternPool_Cau_Index', synth=True)
add(debugger, category='zig', regex=True, type=r'^root\.InternPool\.TrackedInst\.Index(\.Optional)?$', identifier='root_InternPool_TrackedInst_Index', synth=True)
add(debugger, category='zig', regex=True, type=r'^root\.InternPool\.Nav\.Index(\.Optional)?$', identifier='root_InternPool_Nav_Index', synth=True)