authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-30 11:03:50+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-30 14:21:13-04:00
logf5d9160f1b9fcf7b459c6746e8256d349f0c6873
tree36c800efa12843c80f3544e3ca06f89bc7076954
parentb73cf97c93bb23150475ac0c23aadf86dbd71bc4

dwarf: pass DeclState around instead of storing a temp global in Dwarf

Avoids many pitfalls connected with premature/early return in case there are errors with Decl, etc. This is effectively bringing back the old design however in a much nicer packaging, where every mechanism related to tracking Decl's debug info is now nicely wrapped in a single struct (aka the `DeclState`). This includes relocation table, type arena, etc. It is now the caller's responsibility to deinit the state (so that no memory is leaked) after `Decl` has been analysed (or errored out). The caller here is typically a linker such as `Elf` or `MachO`.

9 files changed, 566 insertions(+), 530 deletions(-)

src/arch/aarch64/Emit.zig+3-3
...@@ -390,7 +390,7 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {...@@ -390,7 +390,7 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
390 // TODO Look into using the DWARF special opcodes to compress this data.390 // TODO Look into using the DWARF special opcodes to compress this data.
391 // It lets you emit single-byte opcodes that add different numbers to391 // It lets you emit single-byte opcodes that add different numbers to
392 // both the PC and the line number at the same time.392 // both the PC and the line number at the same time.
393 const dbg_line = dw.getDeclDebugLineBuffer();393 const dbg_line = &dw.dbg_line;
394 try dbg_line.ensureUnusedCapacity(11);394 try dbg_line.ensureUnusedCapacity(11);
395 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);395 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
396 leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;396 leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;
...@@ -588,7 +588,7 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -588,7 +588,7 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {
588fn mirDebugPrologueEnd(self: *Emit) !void {588fn mirDebugPrologueEnd(self: *Emit) !void {
589 switch (self.debug_output) {589 switch (self.debug_output) {
590 .dwarf => |dw| {590 .dwarf => |dw| {
591 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end);591 try dw.dbg_line.append(DW.LNS.set_prologue_end);
592 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);592 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
593 },593 },
594 .plan9 => {},594 .plan9 => {},
...@@ -599,7 +599,7 @@ fn mirDebugPrologueEnd(self: *Emit) !void {...@@ -599,7 +599,7 @@ fn mirDebugPrologueEnd(self: *Emit) !void {
599fn mirDebugEpilogueBegin(self: *Emit) !void {599fn mirDebugEpilogueBegin(self: *Emit) !void {
600 switch (self.debug_output) {600 switch (self.debug_output) {
601 .dwarf => |dw| {601 .dwarf => |dw| {
602 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin);602 try dw.dbg_line.append(DW.LNS.set_epilogue_begin);
603 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);603 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
604 },604 },
605 .plan9 => {},605 .plan9 => {},
src/arch/arm/Emit.zig+6-6
...@@ -332,7 +332,7 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {...@@ -332,7 +332,7 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
332 // TODO Look into using the DWARF special opcodes to compress this data.332 // TODO Look into using the DWARF special opcodes to compress this data.
333 // It lets you emit single-byte opcodes that add different numbers to333 // It lets you emit single-byte opcodes that add different numbers to
334 // both the PC and the line number at the same time.334 // both the PC and the line number at the same time.
335 const dbg_line = dw.getDeclDebugLineBuffer();335 const dbg_line = &dw.dbg_line;
336 try dbg_line.ensureUnusedCapacity(11);336 try dbg_line.ensureUnusedCapacity(11);
337 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);337 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
338 leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;338 leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;
...@@ -382,7 +382,7 @@ fn addDbgInfoTypeReloc(self: *Emit, ty: Type) !void {...@@ -382,7 +382,7 @@ fn addDbgInfoTypeReloc(self: *Emit, ty: Type) !void {
382 switch (self.debug_output) {382 switch (self.debug_output) {
383 .dwarf => |dw| {383 .dwarf => |dw| {
384 assert(ty.hasRuntimeBits());384 assert(ty.hasRuntimeBits());
385 const dbg_info = dw.getDeclDebugInfoBuffer();385 const dbg_info = &dw.dbg_info;
386 const index = dbg_info.items.len;386 const index = dbg_info.items.len;
387 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4387 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
388 const atom = switch (self.bin_file.tag) {388 const atom = switch (self.bin_file.tag) {
...@@ -409,7 +409,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {...@@ -409,7 +409,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
409 .register => |reg| {409 .register => |reg| {
410 switch (self.debug_output) {410 switch (self.debug_output) {
411 .dwarf => |dw| {411 .dwarf => |dw| {
412 const dbg_info = dw.getDeclDebugInfoBuffer();412 const dbg_info = &dw.dbg_info;
413 try dbg_info.ensureUnusedCapacity(3);413 try dbg_info.ensureUnusedCapacity(3);
414 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);414 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
415 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc415 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
...@@ -442,7 +442,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {...@@ -442,7 +442,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
442 else => unreachable,442 else => unreachable,
443 };443 };
444444
445 const dbg_info = dw.getDeclDebugInfoBuffer();445 const dbg_info = &dw.dbg_info;
446 try dbg_info.append(link.File.Dwarf.abbrev_parameter);446 try dbg_info.append(link.File.Dwarf.abbrev_parameter);
447447
448 // Get length of the LEB128 stack offset448 // Get length of the LEB128 stack offset
...@@ -560,7 +560,7 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -560,7 +560,7 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {
560fn mirDebugPrologueEnd(emit: *Emit) !void {560fn mirDebugPrologueEnd(emit: *Emit) !void {
561 switch (emit.debug_output) {561 switch (emit.debug_output) {
562 .dwarf => |dw| {562 .dwarf => |dw| {
563 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end);563 try dw.dbg_line.append(DW.LNS.set_prologue_end);
564 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);564 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
565 },565 },
566 .plan9 => {},566 .plan9 => {},
...@@ -571,7 +571,7 @@ fn mirDebugPrologueEnd(emit: *Emit) !void {...@@ -571,7 +571,7 @@ fn mirDebugPrologueEnd(emit: *Emit) !void {
571fn mirDebugEpilogueBegin(emit: *Emit) !void {571fn mirDebugEpilogueBegin(emit: *Emit) !void {
572 switch (emit.debug_output) {572 switch (emit.debug_output) {
573 .dwarf => |dw| {573 .dwarf => |dw| {
574 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin);574 try dw.dbg_line.append(DW.LNS.set_epilogue_begin);
575 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);575 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
576 },576 },
577 .plan9 => {},577 .plan9 => {},
src/arch/riscv64/CodeGen.zig+2-2
...@@ -749,7 +749,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {...@@ -749,7 +749,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
749 switch (self.debug_output) {749 switch (self.debug_output) {
750 .dwarf => |dw| {750 .dwarf => |dw| {
751 assert(ty.hasRuntimeBits());751 assert(ty.hasRuntimeBits());
752 const dbg_info = dw.getDeclDebugInfoBuffer();752 const dbg_info = &dw.dbg_info;
753 const index = dbg_info.items.len;753 const index = dbg_info.items.len;
754 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4754 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
755 const atom = switch (self.bin_file.tag) {755 const atom = switch (self.bin_file.tag) {
...@@ -1572,7 +1572,7 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32...@@ -1572,7 +1572,7 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32
1572 .register => |reg| {1572 .register => |reg| {
1573 switch (self.debug_output) {1573 switch (self.debug_output) {
1574 .dwarf => |dw| {1574 .dwarf => |dw| {
1575 const dbg_info = dw.getDeclDebugInfoBuffer();1575 const dbg_info = &dw.dbg_info;
1576 try dbg_info.ensureUnusedCapacity(3);1576 try dbg_info.ensureUnusedCapacity(3);
1577 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);1577 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
1578 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc1578 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
src/arch/riscv64/Emit.zig+3-3
...@@ -93,7 +93,7 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {...@@ -93,7 +93,7 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
93 // TODO Look into using the DWARF special opcodes to compress this data.93 // TODO Look into using the DWARF special opcodes to compress this data.
94 // It lets you emit single-byte opcodes that add different numbers to94 // It lets you emit single-byte opcodes that add different numbers to
95 // both the PC and the line number at the same time.95 // both the PC and the line number at the same time.
96 const dbg_line = dw.getDeclDebugLineBuffer();96 const dbg_line = &dw.dbg_line;
97 try dbg_line.ensureUnusedCapacity(11);97 try dbg_line.ensureUnusedCapacity(11);
98 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);98 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
99 leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;99 leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;
...@@ -184,7 +184,7 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -184,7 +184,7 @@ fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {
184fn mirDebugPrologueEnd(self: *Emit) !void {184fn mirDebugPrologueEnd(self: *Emit) !void {
185 switch (self.debug_output) {185 switch (self.debug_output) {
186 .dwarf => |dw| {186 .dwarf => |dw| {
187 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end);187 try dw.dbg_line.append(DW.LNS.set_prologue_end);
188 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);188 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
189 },189 },
190 .plan9 => {},190 .plan9 => {},
...@@ -195,7 +195,7 @@ fn mirDebugPrologueEnd(self: *Emit) !void {...@@ -195,7 +195,7 @@ fn mirDebugPrologueEnd(self: *Emit) !void {
195fn mirDebugEpilogueBegin(self: *Emit) !void {195fn mirDebugEpilogueBegin(self: *Emit) !void {
196 switch (self.debug_output) {196 switch (self.debug_output) {
197 .dwarf => |dw| {197 .dwarf => |dw| {
198 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin);198 try dw.dbg_line.append(DW.LNS.set_epilogue_begin);
199 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);199 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
200 },200 },
201 .plan9 => {},201 .plan9 => {},
src/arch/x86_64/Emit.zig+6-6
...@@ -977,7 +977,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {...@@ -977,7 +977,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {
977 // TODO Look into using the DWARF special opcodes to compress this data.977 // TODO Look into using the DWARF special opcodes to compress this data.
978 // It lets you emit single-byte opcodes that add different numbers to978 // It lets you emit single-byte opcodes that add different numbers to
979 // both the PC and the line number at the same time.979 // both the PC and the line number at the same time.
980 const dbg_line = dw.getDeclDebugLineBuffer();980 const dbg_line = &dw.dbg_line;
981 try dbg_line.ensureUnusedCapacity(11);981 try dbg_line.ensureUnusedCapacity(11);
982 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);982 dbg_line.appendAssumeCapacity(DW.LNS.advance_pc);
983 leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;983 leb128.writeULEB128(dbg_line.writer(), delta_pc) catch unreachable;
...@@ -1034,7 +1034,7 @@ fn mirDbgPrologueEnd(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -1034,7 +1034,7 @@ fn mirDbgPrologueEnd(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
1034 assert(tag == .dbg_prologue_end);1034 assert(tag == .dbg_prologue_end);
1035 switch (emit.debug_output) {1035 switch (emit.debug_output) {
1036 .dwarf => |dw| {1036 .dwarf => |dw| {
1037 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_prologue_end);1037 try dw.dbg_line.append(DW.LNS.set_prologue_end);
1038 log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column });1038 log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column });
1039 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);1039 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
1040 },1040 },
...@@ -1048,7 +1048,7 @@ fn mirDbgEpilogueBegin(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -1048,7 +1048,7 @@ fn mirDbgEpilogueBegin(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
1048 assert(tag == .dbg_epilogue_begin);1048 assert(tag == .dbg_epilogue_begin);
1049 switch (emit.debug_output) {1049 switch (emit.debug_output) {
1050 .dwarf => |dw| {1050 .dwarf => |dw| {
1051 try dw.getDeclDebugLineBuffer().append(DW.LNS.set_epilogue_begin);1051 try dw.dbg_line.append(DW.LNS.set_epilogue_begin);
1052 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column });1052 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ emit.prev_di_line, emit.prev_di_column });
1053 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);1053 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
1054 },1054 },
...@@ -1075,7 +1075,7 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32...@@ -1075,7 +1075,7 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32
1075 .register => |reg| {1075 .register => |reg| {
1076 switch (emit.debug_output) {1076 switch (emit.debug_output) {
1077 .dwarf => |dw| {1077 .dwarf => |dw| {
1078 const dbg_info = dw.getDeclDebugInfoBuffer();1078 const dbg_info = &dw.dbg_info;
1079 try dbg_info.ensureUnusedCapacity(3);1079 try dbg_info.ensureUnusedCapacity(3);
1080 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);1080 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
1081 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc1081 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
...@@ -1099,7 +1099,7 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32...@@ -1099,7 +1099,7 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32
1099 // TODO we need to make this more generic if we don't use rbp as the frame pointer1099 // TODO we need to make this more generic if we don't use rbp as the frame pointer
1100 // for example when -fomit-frame-pointer is set.1100 // for example when -fomit-frame-pointer is set.
1101 const disp = @intCast(i32, max_stack) - off + 16;1101 const disp = @intCast(i32, max_stack) - off + 16;
1102 const dbg_info = dw.getDeclDebugInfoBuffer();1102 const dbg_info = &dw.dbg_info;
1103 try dbg_info.ensureUnusedCapacity(8);1103 try dbg_info.ensureUnusedCapacity(8);
1104 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);1104 dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
1105 const fixup = dbg_info.items.len;1105 const fixup = dbg_info.items.len;
...@@ -1128,7 +1128,7 @@ fn addDbgInfoTypeReloc(emit: *Emit, ty: Type) !void {...@@ -1128,7 +1128,7 @@ fn addDbgInfoTypeReloc(emit: *Emit, ty: Type) !void {
1128 switch (emit.debug_output) {1128 switch (emit.debug_output) {
1129 .dwarf => |dw| {1129 .dwarf => |dw| {
1130 assert(ty.hasRuntimeBits());1130 assert(ty.hasRuntimeBits());
1131 const dbg_info = dw.getDeclDebugInfoBuffer();1131 const dbg_info = &dw.dbg_info;
1132 const index = dbg_info.items.len;1132 const index = dbg_info.items.len;
1133 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref41133 try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4
1134 const atom = switch (emit.bin_file.tag) {1134 const atom = switch (emit.bin_file.tag) {
src/codegen.zig+1-1
...@@ -42,7 +42,7 @@ pub const GenerateSymbolError = error{...@@ -42,7 +42,7 @@ pub const GenerateSymbolError = error{
42};42};
4343
44pub const DebugInfoOutput = union(enum) {44pub const DebugInfoOutput = union(enum) {
45 dwarf: *link.File.Dwarf,45 dwarf: *link.File.Dwarf.DeclState,
46 /// the plan9 debuginfo output is a bytecode with 4 opcodes46 /// the plan9 debuginfo output is a bytecode with 4 opcodes
47 /// assume all numbers/variables are bytes47 /// assume all numbers/variables are bytes
48 /// 0 w x y z -> interpret w x y z as a big-endian i32, and add it to the line offset48 /// 0 w x y z -> interpret w x y z as a big-endian i32, and add it to the line offset
src/link/Dwarf.zig+486-475
...@@ -43,11 +43,6 @@ abbrev_table_offset: ?u64 = null,...@@ -43,11 +43,6 @@ abbrev_table_offset: ?u64 = null,
43/// Table of debug symbol names.43/// Table of debug symbol names.
44strtab: std.ArrayListUnmanaged(u8) = .{},44strtab: std.ArrayListUnmanaged(u8) = .{},
4545
46/// Lives only as long as the analysed Decl.
47/// Allocated with `initDeclState`.
48/// Freed with `commitDeclState`.
49decl_state: ?DeclState = null,
50
51/// List of atoms that are owned directly by the DWARF module.46/// List of atoms that are owned directly by the DWARF module.
52/// TODO convert links in DebugInfoAtom into indices and make47/// TODO convert links in DebugInfoAtom into indices and make
53/// sure every atom is owned by this module.48/// sure every atom is owned by this module.
...@@ -71,6 +66,8 @@ pub const Atom = struct {...@@ -71,6 +66,8 @@ pub const Atom = struct {
71/// and a set of relocations that will be resolved once this66/// and a set of relocations that will be resolved once this
72/// Decl's inner Atom is assigned an offset within the DWARF section.67/// Decl's inner Atom is assigned an offset within the DWARF section.
73pub const DeclState = struct {68pub const DeclState = struct {
69 gpa: Allocator,
70 target: std.Target,
74 dbg_line: std.ArrayList(u8),71 dbg_line: std.ArrayList(u8),
75 dbg_info: std.ArrayList(u8),72 dbg_info: std.ArrayList(u8),
76 abbrev_type_arena: std.heap.ArenaAllocator,73 abbrev_type_arena: std.heap.ArenaAllocator,
...@@ -83,21 +80,438 @@ pub const DeclState = struct {...@@ -83,21 +80,438 @@ pub const DeclState = struct {
83 ) = .{},80 ) = .{},
84 abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{},81 abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{},
8582
86 fn init(gpa: Allocator) DeclState {83 fn init(gpa: Allocator, target: std.Target) DeclState {
87 return .{84 return .{
85 .gpa = gpa,
86 .target = target,
88 .dbg_line = std.ArrayList(u8).init(gpa),87 .dbg_line = std.ArrayList(u8).init(gpa),
89 .dbg_info = std.ArrayList(u8).init(gpa),88 .dbg_info = std.ArrayList(u8).init(gpa),
90 .abbrev_type_arena = std.heap.ArenaAllocator.init(gpa),89 .abbrev_type_arena = std.heap.ArenaAllocator.init(gpa),
91 };90 };
92 }91 }
9392
94 pub fn deinit(self: *DeclState, gpa: Allocator) void {93 pub fn deinit(self: *DeclState) void {
95 self.dbg_line.deinit();94 self.dbg_line.deinit();
96 self.dbg_info.deinit();95 self.dbg_info.deinit();
97 self.abbrev_type_arena.deinit();96 self.abbrev_type_arena.deinit();
98 self.abbrev_table.deinit(gpa);97 self.abbrev_table.deinit(self.gpa);
99 self.abbrev_resolver.deinit(gpa);98 self.abbrev_resolver.deinit(self.gpa);
100 self.abbrev_relocs.deinit(gpa);99 self.abbrev_relocs.deinit(self.gpa);
100 }
101
102 pub fn addTypeReloc(
103 self: *DeclState,
104 atom: *const Atom,
105 ty: Type,
106 offset: u32,
107 addend: ?u32,
108 ) !void {
109 const resolv = self.abbrev_resolver.getContext(ty, .{
110 .target = self.target,
111 }) orelse blk: {
112 const sym_index = @intCast(u32, self.abbrev_table.items.len);
113 try self.abbrev_table.append(self.gpa, .{
114 .atom = atom,
115 .@"type" = ty,
116 .offset = undefined,
117 });
118 log.debug("@{d}: {}", .{ sym_index, ty.fmtDebug() });
119 try self.abbrev_resolver.putNoClobberContext(self.gpa, ty, sym_index, .{
120 .target = self.target,
121 });
122 break :blk self.abbrev_resolver.getContext(ty, .{
123 .target = self.target,
124 }).?;
125 };
126 const add: u32 = addend orelse 0;
127
128 log.debug("{x}: @{d} + {x}", .{ offset, resolv, add });
129 try self.abbrev_relocs.append(self.gpa, .{
130 .target = resolv,
131 .atom = atom,
132 .offset = offset,
133 .addend = add,
134 });
135 }
136
137 fn addDbgInfoType(
138 self: *DeclState,
139 module: *Module,
140 atom: *Atom,
141 ty: Type,
142 ) error{OutOfMemory}!void {
143 const arena = self.abbrev_type_arena.allocator();
144 const dbg_info_buffer = &self.dbg_info;
145 const target = self.target;
146 const target_endian = self.target.cpu.arch.endian();
147
148 switch (ty.zigTypeTag()) {
149 .NoReturn => unreachable,
150 .Void => {
151 try dbg_info_buffer.append(abbrev_pad1);
152 },
153 .Bool => {
154 try dbg_info_buffer.appendSlice(&[_]u8{
155 abbrev_base_type,
156 DW.ATE.boolean, // DW.AT.encoding , DW.FORM.data1
157 1, // DW.AT.byte_size, DW.FORM.data1
158 'b', 'o', 'o', 'l', 0, // DW.AT.name, DW.FORM.string
159 });
160 },
161 .Int => {
162 const info = ty.intInfo(target);
163 try dbg_info_buffer.ensureUnusedCapacity(12);
164 dbg_info_buffer.appendAssumeCapacity(abbrev_base_type);
165 // DW.AT.encoding, DW.FORM.data1
166 dbg_info_buffer.appendAssumeCapacity(switch (info.signedness) {
167 .signed => DW.ATE.signed,
168 .unsigned => DW.ATE.unsigned,
169 });
170 // DW.AT.byte_size, DW.FORM.data1
171 dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(target)));
172 // DW.AT.name, DW.FORM.string
173 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)});
174 },
175 .Optional => {
176 if (ty.isPtrLikeOptional()) {
177 try dbg_info_buffer.ensureUnusedCapacity(12);
178 dbg_info_buffer.appendAssumeCapacity(abbrev_base_type);
179 // DW.AT.encoding, DW.FORM.data1
180 dbg_info_buffer.appendAssumeCapacity(DW.ATE.address);
181 // DW.AT.byte_size, DW.FORM.data1
182 dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(target)));
183 // DW.AT.name, DW.FORM.string
184 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)});
185 } else {
186 // Non-pointer optionals are structs: struct { .maybe = *, .val = * }
187 var buf = try arena.create(Type.Payload.ElemType);
188 const payload_ty = ty.optionalChild(buf);
189 // DW.AT.structure_type
190 try dbg_info_buffer.append(abbrev_struct_type);
191 // DW.AT.byte_size, DW.FORM.sdata
192 const abi_size = ty.abiSize(target);
193 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
194 // DW.AT.name, DW.FORM.string
195 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)});
196 // DW.AT.member
197 try dbg_info_buffer.ensureUnusedCapacity(7);
198 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
199 // DW.AT.name, DW.FORM.string
200 dbg_info_buffer.appendSliceAssumeCapacity("maybe");
201 dbg_info_buffer.appendAssumeCapacity(0);
202 // DW.AT.type, DW.FORM.ref4
203 var index = dbg_info_buffer.items.len;
204 try dbg_info_buffer.resize(index + 4);
205 try self.addTypeReloc(atom, Type.bool, @intCast(u32, index), null);
206 // DW.AT.data_member_location, DW.FORM.sdata
207 try dbg_info_buffer.ensureUnusedCapacity(6);
208 dbg_info_buffer.appendAssumeCapacity(0);
209 // DW.AT.member
210 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
211 // DW.AT.name, DW.FORM.string
212 dbg_info_buffer.appendSliceAssumeCapacity("val");
213 dbg_info_buffer.appendAssumeCapacity(0);
214 // DW.AT.type, DW.FORM.ref4
215 index = dbg_info_buffer.items.len;
216 try dbg_info_buffer.resize(index + 4);
217 try self.addTypeReloc(atom, payload_ty, @intCast(u32, index), null);
218 // DW.AT.data_member_location, DW.FORM.sdata
219 const offset = abi_size - payload_ty.abiSize(target);
220 try leb128.writeULEB128(dbg_info_buffer.writer(), offset);
221 // DW.AT.structure_type delimit children
222 try dbg_info_buffer.append(0);
223 }
224 },
225 .Pointer => {
226 if (ty.isSlice()) {
227 // Slices are structs: struct { .ptr = *, .len = N }
228 // DW.AT.structure_type
229 try dbg_info_buffer.ensureUnusedCapacity(2);
230 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_type);
231 // DW.AT.byte_size, DW.FORM.sdata
232 dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize) * 2);
233 // DW.AT.name, DW.FORM.string
234 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)});
235 // DW.AT.member
236 try dbg_info_buffer.ensureUnusedCapacity(5);
237 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
238 // DW.AT.name, DW.FORM.string
239 dbg_info_buffer.appendSliceAssumeCapacity("ptr");
240 dbg_info_buffer.appendAssumeCapacity(0);
241 // DW.AT.type, DW.FORM.ref4
242 var index = dbg_info_buffer.items.len;
243 try dbg_info_buffer.resize(index + 4);
244 var buf = try arena.create(Type.SlicePtrFieldTypeBuffer);
245 const ptr_ty = ty.slicePtrFieldType(buf);
246 try self.addTypeReloc(atom, ptr_ty, @intCast(u32, index), null);
247 // DW.AT.data_member_location, DW.FORM.sdata
248 try dbg_info_buffer.ensureUnusedCapacity(6);
249 dbg_info_buffer.appendAssumeCapacity(0);
250 // DW.AT.member
251 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
252 // DW.AT.name, DW.FORM.string
253 dbg_info_buffer.appendSliceAssumeCapacity("len");
254 dbg_info_buffer.appendAssumeCapacity(0);
255 // DW.AT.type, DW.FORM.ref4
256 index = dbg_info_buffer.items.len;
257 try dbg_info_buffer.resize(index + 4);
258 try self.addTypeReloc(atom, Type.usize, @intCast(u32, index), null);
259 // DW.AT.data_member_location, DW.FORM.sdata
260 try dbg_info_buffer.ensureUnusedCapacity(2);
261 dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize));
262 // DW.AT.structure_type delimit children
263 dbg_info_buffer.appendAssumeCapacity(0);
264 } else {
265 try dbg_info_buffer.ensureUnusedCapacity(5);
266 dbg_info_buffer.appendAssumeCapacity(abbrev_ptr_type);
267 // DW.AT.type, DW.FORM.ref4
268 const index = dbg_info_buffer.items.len;
269 try dbg_info_buffer.resize(index + 4);
270 try self.addTypeReloc(atom, ty.childType(), @intCast(u32, index), null);
271 }
272 },
273 .Struct => blk: {
274 // DW.AT.structure_type
275 try dbg_info_buffer.append(abbrev_struct_type);
276 // DW.AT.byte_size, DW.FORM.sdata
277 const abi_size = ty.abiSize(target);
278 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
279
280 switch (ty.tag()) {
281 .tuple, .anon_struct => {
282 // DW.AT.name, DW.FORM.string
283 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)});
284
285 const fields = ty.tupleFields();
286 for (fields.types) |field, field_index| {
287 // DW.AT.member
288 try dbg_info_buffer.append(abbrev_struct_member);
289 // DW.AT.name, DW.FORM.string
290 try dbg_info_buffer.writer().print("{d}\x00", .{field_index});
291 // DW.AT.type, DW.FORM.ref4
292 var index = dbg_info_buffer.items.len;
293 try dbg_info_buffer.resize(index + 4);
294 try self.addTypeReloc(atom, field, @intCast(u32, index), null);
295 // DW.AT.data_member_location, DW.FORM.sdata
296 const field_off = ty.structFieldOffset(field_index, target);
297 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
298 }
299 },
300 else => {
301 // DW.AT.name, DW.FORM.string
302 const struct_name = try ty.nameAllocArena(arena, target);
303 try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1);
304 dbg_info_buffer.appendSliceAssumeCapacity(struct_name);
305 dbg_info_buffer.appendAssumeCapacity(0);
306
307 const struct_obj = ty.castTag(.@"struct").?.data;
308 if (struct_obj.layout == .Packed) {
309 log.debug("TODO implement .debug_info for packed structs", .{});
310 break :blk;
311 }
312
313 const fields = ty.structFields();
314 for (fields.keys()) |field_name, field_index| {
315 const field = fields.get(field_name).?;
316 // DW.AT.member
317 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);
318 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
319 // DW.AT.name, DW.FORM.string
320 dbg_info_buffer.appendSliceAssumeCapacity(field_name);
321 dbg_info_buffer.appendAssumeCapacity(0);
322 // DW.AT.type, DW.FORM.ref4
323 var index = dbg_info_buffer.items.len;
324 try dbg_info_buffer.resize(index + 4);
325 try self.addTypeReloc(atom, field.ty, @intCast(u32, index), null);
326 // DW.AT.data_member_location, DW.FORM.sdata
327 const field_off = ty.structFieldOffset(field_index, target);
328 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
329 }
330 },
331 }
332
333 // DW.AT.structure_type delimit children
334 try dbg_info_buffer.append(0);
335 },
336 .Enum => {
337 // DW.AT.enumeration_type
338 try dbg_info_buffer.append(abbrev_enum_type);
339 // DW.AT.byte_size, DW.FORM.sdata
340 const abi_size = ty.abiSize(target);
341 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
342 // DW.AT.name, DW.FORM.string
343 const enum_name = try ty.nameAllocArena(arena, target);
344 try dbg_info_buffer.ensureUnusedCapacity(enum_name.len + 1);
345 dbg_info_buffer.appendSliceAssumeCapacity(enum_name);
346 dbg_info_buffer.appendAssumeCapacity(0);
347
348 const fields = ty.enumFields();
349 const values: ?Module.EnumFull.ValueMap = switch (ty.tag()) {
350 .enum_full, .enum_nonexhaustive => ty.cast(Type.Payload.EnumFull).?.data.values,
351 .enum_simple => null,
352 .enum_numbered => ty.castTag(.enum_numbered).?.data.values,
353 else => unreachable,
354 };
355 for (fields.keys()) |field_name, field_i| {
356 // DW.AT.enumerator
357 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64));
358 dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant);
359 // DW.AT.name, DW.FORM.string
360 dbg_info_buffer.appendSliceAssumeCapacity(field_name);
361 dbg_info_buffer.appendAssumeCapacity(0);
362 // DW.AT.const_value, DW.FORM.data8
363 const value: u64 = if (values) |vals| value: {
364 if (vals.count() == 0) break :value @intCast(u64, field_i); // auto-numbered
365 const value = vals.keys()[field_i];
366 var int_buffer: Value.Payload.U64 = undefined;
367 break :value value.enumToInt(ty, &int_buffer).toUnsignedInt(target);
368 } else @intCast(u64, field_i);
369 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian);
370 }
371
372 // DW.AT.enumeration_type delimit children
373 try dbg_info_buffer.append(0);
374 },
375 .Union => {
376 const layout = ty.unionGetLayout(target);
377 const union_obj = ty.cast(Type.Payload.Union).?.data;
378 const payload_offset = if (layout.tag_align >= layout.payload_align) layout.tag_size else 0;
379 const tag_offset = if (layout.tag_align >= layout.payload_align) 0 else layout.payload_size;
380 const is_tagged = layout.tag_size > 0;
381 const union_name = try ty.nameAllocArena(arena, target);
382
383 // TODO this is temporary to match current state of unions in Zig - we don't yet have
384 // safety checks implemented meaning the implicit tag is not yet stored and generated
385 // for untagged unions.
386 if (is_tagged) {
387 // DW.AT.structure_type
388 try dbg_info_buffer.append(abbrev_struct_type);
389 // DW.AT.byte_size, DW.FORM.sdata
390 try leb128.writeULEB128(dbg_info_buffer.writer(), layout.abi_size);
391 // DW.AT.name, DW.FORM.string
392 try dbg_info_buffer.ensureUnusedCapacity(union_name.len + 1);
393 dbg_info_buffer.appendSliceAssumeCapacity(union_name);
394 dbg_info_buffer.appendAssumeCapacity(0);
395
396 // DW.AT.member
397 try dbg_info_buffer.ensureUnusedCapacity(9);
398 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
399 // DW.AT.name, DW.FORM.string
400 dbg_info_buffer.appendSliceAssumeCapacity("payload");
401 dbg_info_buffer.appendAssumeCapacity(0);
402 // DW.AT.type, DW.FORM.ref4
403 const inner_union_index = dbg_info_buffer.items.len;
404 try dbg_info_buffer.resize(inner_union_index + 4);
405 try self.addTypeReloc(atom, ty, @intCast(u32, inner_union_index), 5);
406 // DW.AT.data_member_location, DW.FORM.sdata
407 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset);
408 }
409
410 // DW.AT.union_type
411 try dbg_info_buffer.append(abbrev_union_type);
412 // DW.AT.byte_size, DW.FORM.sdata,
413 try leb128.writeULEB128(dbg_info_buffer.writer(), layout.payload_size);
414 // DW.AT.name, DW.FORM.string
415 if (is_tagged) {
416 try dbg_info_buffer.writer().print("AnonUnion\x00", .{});
417 } else {
418 try dbg_info_buffer.writer().print("{s}\x00", .{union_name});
419 }
420
421 const fields = ty.unionFields();
422 for (fields.keys()) |field_name| {
423 const field = fields.get(field_name).?;
424 if (!field.ty.hasRuntimeBits()) continue;
425 // DW.AT.member
426 try dbg_info_buffer.append(abbrev_struct_member);
427 // DW.AT.name, DW.FORM.string
428 try dbg_info_buffer.writer().print("{s}\x00", .{field_name});
429 // DW.AT.type, DW.FORM.ref4
430 const index = dbg_info_buffer.items.len;
431 try dbg_info_buffer.resize(index + 4);
432 try self.addTypeReloc(atom, field.ty, @intCast(u32, index), null);
433 // DW.AT.data_member_location, DW.FORM.sdata
434 try dbg_info_buffer.append(0);
435 }
436 // DW.AT.union_type delimit children
437 try dbg_info_buffer.append(0);
438
439 if (is_tagged) {
440 // DW.AT.member
441 try dbg_info_buffer.ensureUnusedCapacity(5);
442 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
443 // DW.AT.name, DW.FORM.string
444 dbg_info_buffer.appendSliceAssumeCapacity("tag");
445 dbg_info_buffer.appendAssumeCapacity(0);
446 // DW.AT.type, DW.FORM.ref4
447 const index = dbg_info_buffer.items.len;
448 try dbg_info_buffer.resize(index + 4);
449 try self.addTypeReloc(atom, union_obj.tag_ty, @intCast(u32, index), null);
450 // DW.AT.data_member_location, DW.FORM.sdata
451 try leb128.writeULEB128(dbg_info_buffer.writer(), tag_offset);
452
453 // DW.AT.structure_type delimit children
454 try dbg_info_buffer.append(0);
455 }
456 },
457 .ErrorSet => {
458 try addDbgInfoErrorSet(
459 self.abbrev_type_arena.allocator(),
460 module,
461 ty,
462 self.target,
463 &self.dbg_info,
464 );
465 },
466 .ErrorUnion => {
467 const error_ty = ty.errorUnionSet();
468 const payload_ty = ty.errorUnionPayload();
469 const abi_size = ty.abiSize(target);
470 const abi_align = ty.abiAlignment(target);
471 const payload_off = mem.alignForwardGeneric(u64, error_ty.abiSize(target), abi_align);
472
473 // DW.AT.structure_type
474 try dbg_info_buffer.append(abbrev_struct_type);
475 // DW.AT.byte_size, DW.FORM.sdata
476 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
477 // DW.AT.name, DW.FORM.string
478 const name = try ty.nameAllocArena(arena, target);
479 try dbg_info_buffer.writer().print("{s}\x00", .{name});
480
481 // DW.AT.member
482 try dbg_info_buffer.ensureUnusedCapacity(7);
483 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
484 // DW.AT.name, DW.FORM.string
485 dbg_info_buffer.appendSliceAssumeCapacity("value");
486 dbg_info_buffer.appendAssumeCapacity(0);
487 // DW.AT.type, DW.FORM.ref4
488 var index = dbg_info_buffer.items.len;
489 try dbg_info_buffer.resize(index + 4);
490 try self.addTypeReloc(atom, payload_ty, @intCast(u32, index), null);
491 // DW.AT.data_member_location, DW.FORM.sdata
492 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_off);
493
494 // DW.AT.member
495 try dbg_info_buffer.ensureUnusedCapacity(5);
496 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
497 // DW.AT.name, DW.FORM.string
498 dbg_info_buffer.appendSliceAssumeCapacity("err");
499 dbg_info_buffer.appendAssumeCapacity(0);
500 // DW.AT.type, DW.FORM.ref4
501 index = dbg_info_buffer.items.len;
502 try dbg_info_buffer.resize(index + 4);
503 try self.addTypeReloc(atom, error_ty, @intCast(u32, index), null);
504 // DW.AT.data_member_location, DW.FORM.sdata
505 try dbg_info_buffer.append(0);
506
507 // DW.AT.structure_type delimit children
508 try dbg_info_buffer.append(0);
509 },
510 else => {
511 log.debug("TODO implement .debug_info for type '{}'", .{ty.fmtDebug()});
512 try dbg_info_buffer.append(abbrev_pad1);
513 },
514 }
101 }515 }
102};516};
103517
...@@ -191,7 +605,7 @@ pub fn deinit(self: *Dwarf) void {...@@ -191,7 +605,7 @@ pub fn deinit(self: *Dwarf) void {
191605
192/// Initializes Decl's state and its matching output buffers.606/// Initializes Decl's state and its matching output buffers.
193/// Call this before `commitDeclState`.607/// Call this before `commitDeclState`.
194pub fn initDeclState(self: *Dwarf, decl: *Module.Decl) !void {608pub fn initDeclState(self: *Dwarf, decl: *Module.Decl) !DeclState {
195 const tracy = trace(@src());609 const tracy = trace(@src());
196 defer tracy.end();610 defer tracy.end();
197611
...@@ -201,10 +615,10 @@ pub fn initDeclState(self: *Dwarf, decl: *Module.Decl) !void {...@@ -201,10 +615,10 @@ pub fn initDeclState(self: *Dwarf, decl: *Module.Decl) !void {
201 log.debug("initDeclState {s}{*}", .{ decl_name, decl });615 log.debug("initDeclState {s}{*}", .{ decl_name, decl });
202616
203 const gpa = self.allocator;617 const gpa = self.allocator;
204 assert(self.decl_state == null);618 var decl_state = DeclState.init(gpa, self.target);
205 self.decl_state = DeclState.init(gpa);619 errdefer decl_state.deinit();
206 const dbg_line_buffer = &self.decl_state.?.dbg_line;620 const dbg_line_buffer = &decl_state.dbg_line;
207 const dbg_info_buffer = &self.decl_state.?.dbg_info;621 const dbg_info_buffer = &decl_state.dbg_info;
208622
209 assert(decl.has_tv);623 assert(decl.has_tv);
210624
...@@ -274,7 +688,12 @@ pub fn initDeclState(self: *Dwarf, decl: *Module.Decl) !void {...@@ -274,7 +688,12 @@ pub fn initDeclState(self: *Dwarf, decl: *Module.Decl) !void {
274 .macho => &decl.link.macho.dbg_info_atom,688 .macho => &decl.link.macho.dbg_info_atom,
275 else => unreachable,689 else => unreachable,
276 };690 };
277 try self.addTypeReloc(atom, fn_ret_type, @intCast(u32, dbg_info_buffer.items.len), null);691 try decl_state.addTypeReloc(
692 atom,
693 fn_ret_type,
694 @intCast(u32, dbg_info_buffer.items.len),
695 null,
696 );
278 dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4697 dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4
279 }698 }
280699
...@@ -285,6 +704,8 @@ pub fn initDeclState(self: *Dwarf, decl: *Module.Decl) !void {...@@ -285,6 +704,8 @@ pub fn initDeclState(self: *Dwarf, decl: *Module.Decl) !void {
285 // TODO implement .debug_info for global variables704 // TODO implement .debug_info for global variables
286 },705 },
287 }706 }
707
708 return decl_state;
288}709}
289710
290pub fn commitDeclState(711pub fn commitDeclState(
...@@ -294,19 +715,14 @@ pub fn commitDeclState(...@@ -294,19 +715,14 @@ pub fn commitDeclState(
294 decl: *Module.Decl,715 decl: *Module.Decl,
295 sym_addr: u64,716 sym_addr: u64,
296 sym_size: u64,717 sym_size: u64,
718 decl_state: *DeclState,
297) !void {719) !void {
298 const tracy = trace(@src());720 const tracy = trace(@src());
299 defer tracy.end();721 defer tracy.end();
300722
301 assert(self.decl_state != null); // Caller forgot to call `initDeclState`
302 defer {
303 self.decl_state.?.deinit(self.allocator);
304 self.decl_state = null;
305 }
306
307 const gpa = self.allocator;723 const gpa = self.allocator;
308 var dbg_line_buffer = &self.decl_state.?.dbg_line;724 var dbg_line_buffer = &decl_state.dbg_line;
309 var dbg_info_buffer = &self.decl_state.?.dbg_info;725 var dbg_info_buffer = &decl_state.dbg_info;
310726
311 const target_endian = self.target.cpu.arch.endian();727 const target_endian = self.target.cpu.arch.endian();
312728
...@@ -509,7 +925,6 @@ pub fn commitDeclState(...@@ -509,7 +925,6 @@ pub fn commitDeclState(
509 .macho => &decl.link.macho.dbg_info_atom,925 .macho => &decl.link.macho.dbg_info_atom,
510 else => unreachable,926 else => unreachable,
511 };927 };
512 const decl_state = &self.decl_state.?;
513928
514 {929 {
515 // Now we emit the .debug_info types of the Decl. These will count towards the size of930 // Now we emit the .debug_info types of the Decl. These will count towards the size of
...@@ -532,7 +947,7 @@ pub fn commitDeclState(...@@ -532,7 +947,7 @@ pub fn commitDeclState(
532 if (deferred) continue;947 if (deferred) continue;
533948
534 symbol.offset = @intCast(u32, dbg_info_buffer.items.len);949 symbol.offset = @intCast(u32, dbg_info_buffer.items.len);
535 try self.addDbgInfoType(decl_state.abbrev_type_arena.allocator(), module, atom, ty, dbg_info_buffer);950 try decl_state.addDbgInfoType(module, atom, ty);
536 }951 }
537 }952 }
538953
...@@ -825,414 +1240,6 @@ pub fn freeDecl(self: *Dwarf, decl: *Module.Decl) void {...@@ -825,414 +1240,6 @@ pub fn freeDecl(self: *Dwarf, decl: *Module.Decl) void {
825 }1240 }
826}1241}
8271242
828/// Asserts the type has codegen bits.
829fn addDbgInfoType(
830 self: *Dwarf,
831 arena: Allocator,
832 module: *Module,
833 atom: *Atom,
834 ty: Type,
835 dbg_info_buffer: *std.ArrayList(u8),
836) error{OutOfMemory}!void {
837 const target = self.target;
838 const target_endian = self.target.cpu.arch.endian();
839
840 switch (ty.zigTypeTag()) {
841 .NoReturn => unreachable,
842 .Void => {
843 try dbg_info_buffer.append(abbrev_pad1);
844 },
845 .Bool => {
846 try dbg_info_buffer.appendSlice(&[_]u8{
847 abbrev_base_type,
848 DW.ATE.boolean, // DW.AT.encoding , DW.FORM.data1
849 1, // DW.AT.byte_size, DW.FORM.data1
850 'b', 'o', 'o', 'l', 0, // DW.AT.name, DW.FORM.string
851 });
852 },
853 .Int => {
854 const info = ty.intInfo(target);
855 try dbg_info_buffer.ensureUnusedCapacity(12);
856 dbg_info_buffer.appendAssumeCapacity(abbrev_base_type);
857 // DW.AT.encoding, DW.FORM.data1
858 dbg_info_buffer.appendAssumeCapacity(switch (info.signedness) {
859 .signed => DW.ATE.signed,
860 .unsigned => DW.ATE.unsigned,
861 });
862 // DW.AT.byte_size, DW.FORM.data1
863 dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(target)));
864 // DW.AT.name, DW.FORM.string
865 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)});
866 },
867 .Optional => {
868 if (ty.isPtrLikeOptional()) {
869 try dbg_info_buffer.ensureUnusedCapacity(12);
870 dbg_info_buffer.appendAssumeCapacity(abbrev_base_type);
871 // DW.AT.encoding, DW.FORM.data1
872 dbg_info_buffer.appendAssumeCapacity(DW.ATE.address);
873 // DW.AT.byte_size, DW.FORM.data1
874 dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(target)));
875 // DW.AT.name, DW.FORM.string
876 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)});
877 } else {
878 // Non-pointer optionals are structs: struct { .maybe = *, .val = * }
879 var buf = try arena.create(Type.Payload.ElemType);
880 const payload_ty = ty.optionalChild(buf);
881 // DW.AT.structure_type
882 try dbg_info_buffer.append(abbrev_struct_type);
883 // DW.AT.byte_size, DW.FORM.sdata
884 const abi_size = ty.abiSize(target);
885 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
886 // DW.AT.name, DW.FORM.string
887 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)});
888 // DW.AT.member
889 try dbg_info_buffer.ensureUnusedCapacity(7);
890 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
891 // DW.AT.name, DW.FORM.string
892 dbg_info_buffer.appendSliceAssumeCapacity("maybe");
893 dbg_info_buffer.appendAssumeCapacity(0);
894 // DW.AT.type, DW.FORM.ref4
895 var index = dbg_info_buffer.items.len;
896 try dbg_info_buffer.resize(index + 4);
897 try self.addTypeReloc(atom, Type.bool, @intCast(u32, index), null);
898 // DW.AT.data_member_location, DW.FORM.sdata
899 try dbg_info_buffer.ensureUnusedCapacity(6);
900 dbg_info_buffer.appendAssumeCapacity(0);
901 // DW.AT.member
902 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
903 // DW.AT.name, DW.FORM.string
904 dbg_info_buffer.appendSliceAssumeCapacity("val");
905 dbg_info_buffer.appendAssumeCapacity(0);
906 // DW.AT.type, DW.FORM.ref4
907 index = dbg_info_buffer.items.len;
908 try dbg_info_buffer.resize(index + 4);
909 try self.addTypeReloc(atom, payload_ty, @intCast(u32, index), null);
910 // DW.AT.data_member_location, DW.FORM.sdata
911 const offset = abi_size - payload_ty.abiSize(target);
912 try leb128.writeULEB128(dbg_info_buffer.writer(), offset);
913 // DW.AT.structure_type delimit children
914 try dbg_info_buffer.append(0);
915 }
916 },
917 .Pointer => {
918 if (ty.isSlice()) {
919 // Slices are structs: struct { .ptr = *, .len = N }
920 // DW.AT.structure_type
921 try dbg_info_buffer.ensureUnusedCapacity(2);
922 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_type);
923 // DW.AT.byte_size, DW.FORM.sdata
924 dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize) * 2);
925 // DW.AT.name, DW.FORM.string
926 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)});
927 // DW.AT.member
928 try dbg_info_buffer.ensureUnusedCapacity(5);
929 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
930 // DW.AT.name, DW.FORM.string
931 dbg_info_buffer.appendSliceAssumeCapacity("ptr");
932 dbg_info_buffer.appendAssumeCapacity(0);
933 // DW.AT.type, DW.FORM.ref4
934 var index = dbg_info_buffer.items.len;
935 try dbg_info_buffer.resize(index + 4);
936 var buf = try arena.create(Type.SlicePtrFieldTypeBuffer);
937 const ptr_ty = ty.slicePtrFieldType(buf);
938 try self.addTypeReloc(atom, ptr_ty, @intCast(u32, index), null);
939 // DW.AT.data_member_location, DW.FORM.sdata
940 try dbg_info_buffer.ensureUnusedCapacity(6);
941 dbg_info_buffer.appendAssumeCapacity(0);
942 // DW.AT.member
943 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
944 // DW.AT.name, DW.FORM.string
945 dbg_info_buffer.appendSliceAssumeCapacity("len");
946 dbg_info_buffer.appendAssumeCapacity(0);
947 // DW.AT.type, DW.FORM.ref4
948 index = dbg_info_buffer.items.len;
949 try dbg_info_buffer.resize(index + 4);
950 try self.addTypeReloc(atom, Type.usize, @intCast(u32, index), null);
951 // DW.AT.data_member_location, DW.FORM.sdata
952 try dbg_info_buffer.ensureUnusedCapacity(2);
953 dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize));
954 // DW.AT.structure_type delimit children
955 dbg_info_buffer.appendAssumeCapacity(0);
956 } else {
957 try dbg_info_buffer.ensureUnusedCapacity(5);
958 dbg_info_buffer.appendAssumeCapacity(abbrev_ptr_type);
959 // DW.AT.type, DW.FORM.ref4
960 const index = dbg_info_buffer.items.len;
961 try dbg_info_buffer.resize(index + 4);
962 try self.addTypeReloc(atom, ty.childType(), @intCast(u32, index), null);
963 }
964 },
965 .Struct => blk: {
966 // DW.AT.structure_type
967 try dbg_info_buffer.append(abbrev_struct_type);
968 // DW.AT.byte_size, DW.FORM.sdata
969 const abi_size = ty.abiSize(target);
970 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
971
972 switch (ty.tag()) {
973 .tuple, .anon_struct => {
974 // DW.AT.name, DW.FORM.string
975 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)});
976
977 const fields = ty.tupleFields();
978 for (fields.types) |field, field_index| {
979 // DW.AT.member
980 try dbg_info_buffer.append(abbrev_struct_member);
981 // DW.AT.name, DW.FORM.string
982 try dbg_info_buffer.writer().print("{d}\x00", .{field_index});
983 // DW.AT.type, DW.FORM.ref4
984 var index = dbg_info_buffer.items.len;
985 try dbg_info_buffer.resize(index + 4);
986 try self.addTypeReloc(atom, field, @intCast(u32, index), null);
987 // DW.AT.data_member_location, DW.FORM.sdata
988 const field_off = ty.structFieldOffset(field_index, target);
989 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
990 }
991 },
992 else => {
993 // DW.AT.name, DW.FORM.string
994 const struct_name = try ty.nameAllocArena(arena, target);
995 try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1);
996 dbg_info_buffer.appendSliceAssumeCapacity(struct_name);
997 dbg_info_buffer.appendAssumeCapacity(0);
998
999 const struct_obj = ty.castTag(.@"struct").?.data;
1000 if (struct_obj.layout == .Packed) {
1001 log.debug("TODO implement .debug_info for packed structs", .{});
1002 break :blk;
1003 }
1004
1005 const fields = ty.structFields();
1006 for (fields.keys()) |field_name, field_index| {
1007 const field = fields.get(field_name).?;
1008 // DW.AT.member
1009 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);
1010 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
1011 // DW.AT.name, DW.FORM.string
1012 dbg_info_buffer.appendSliceAssumeCapacity(field_name);
1013 dbg_info_buffer.appendAssumeCapacity(0);
1014 // DW.AT.type, DW.FORM.ref4
1015 var index = dbg_info_buffer.items.len;
1016 try dbg_info_buffer.resize(index + 4);
1017 try self.addTypeReloc(atom, field.ty, @intCast(u32, index), null);
1018 // DW.AT.data_member_location, DW.FORM.sdata
1019 const field_off = ty.structFieldOffset(field_index, target);
1020 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
1021 }
1022 },
1023 }
1024
1025 // DW.AT.structure_type delimit children
1026 try dbg_info_buffer.append(0);
1027 },
1028 .Enum => {
1029 // DW.AT.enumeration_type
1030 try dbg_info_buffer.append(abbrev_enum_type);
1031 // DW.AT.byte_size, DW.FORM.sdata
1032 const abi_size = ty.abiSize(target);
1033 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
1034 // DW.AT.name, DW.FORM.string
1035 const enum_name = try ty.nameAllocArena(arena, target);
1036 try dbg_info_buffer.ensureUnusedCapacity(enum_name.len + 1);
1037 dbg_info_buffer.appendSliceAssumeCapacity(enum_name);
1038 dbg_info_buffer.appendAssumeCapacity(0);
1039
1040 const fields = ty.enumFields();
1041 const values: ?Module.EnumFull.ValueMap = switch (ty.tag()) {
1042 .enum_full, .enum_nonexhaustive => ty.cast(Type.Payload.EnumFull).?.data.values,
1043 .enum_simple => null,
1044 .enum_numbered => ty.castTag(.enum_numbered).?.data.values,
1045 else => unreachable,
1046 };
1047 for (fields.keys()) |field_name, field_i| {
1048 // DW.AT.enumerator
1049 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64));
1050 dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant);
1051 // DW.AT.name, DW.FORM.string
1052 dbg_info_buffer.appendSliceAssumeCapacity(field_name);
1053 dbg_info_buffer.appendAssumeCapacity(0);
1054 // DW.AT.const_value, DW.FORM.data8
1055 const value: u64 = if (values) |vals| value: {
1056 if (vals.count() == 0) break :value @intCast(u64, field_i); // auto-numbered
1057 const value = vals.keys()[field_i];
1058 var int_buffer: Value.Payload.U64 = undefined;
1059 break :value value.enumToInt(ty, &int_buffer).toUnsignedInt(target);
1060 } else @intCast(u64, field_i);
1061 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian);
1062 }
1063
1064 // DW.AT.enumeration_type delimit children
1065 try dbg_info_buffer.append(0);
1066 },
1067 .Union => {
1068 const layout = ty.unionGetLayout(target);
1069 const union_obj = ty.cast(Type.Payload.Union).?.data;
1070 const payload_offset = if (layout.tag_align >= layout.payload_align) layout.tag_size else 0;
1071 const tag_offset = if (layout.tag_align >= layout.payload_align) 0 else layout.payload_size;
1072 const is_tagged = layout.tag_size > 0;
1073 const union_name = try ty.nameAllocArena(arena, target);
1074
1075 // TODO this is temporary to match current state of unions in Zig - we don't yet have
1076 // safety checks implemented meaning the implicit tag is not yet stored and generated
1077 // for untagged unions.
1078 if (is_tagged) {
1079 // DW.AT.structure_type
1080 try dbg_info_buffer.append(abbrev_struct_type);
1081 // DW.AT.byte_size, DW.FORM.sdata
1082 try leb128.writeULEB128(dbg_info_buffer.writer(), layout.abi_size);
1083 // DW.AT.name, DW.FORM.string
1084 try dbg_info_buffer.ensureUnusedCapacity(union_name.len + 1);
1085 dbg_info_buffer.appendSliceAssumeCapacity(union_name);
1086 dbg_info_buffer.appendAssumeCapacity(0);
1087
1088 // DW.AT.member
1089 try dbg_info_buffer.ensureUnusedCapacity(9);
1090 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
1091 // DW.AT.name, DW.FORM.string
1092 dbg_info_buffer.appendSliceAssumeCapacity("payload");
1093 dbg_info_buffer.appendAssumeCapacity(0);
1094 // DW.AT.type, DW.FORM.ref4
1095 const inner_union_index = dbg_info_buffer.items.len;
1096 try dbg_info_buffer.resize(inner_union_index + 4);
1097 try self.addTypeReloc(atom, ty, @intCast(u32, inner_union_index), 5);
1098 // DW.AT.data_member_location, DW.FORM.sdata
1099 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset);
1100 }
1101
1102 // DW.AT.union_type
1103 try dbg_info_buffer.append(abbrev_union_type);
1104 // DW.AT.byte_size, DW.FORM.sdata,
1105 try leb128.writeULEB128(dbg_info_buffer.writer(), layout.payload_size);
1106 // DW.AT.name, DW.FORM.string
1107 if (is_tagged) {
1108 try dbg_info_buffer.writer().print("AnonUnion\x00", .{});
1109 } else {
1110 try dbg_info_buffer.writer().print("{s}\x00", .{union_name});
1111 }
1112
1113 const fields = ty.unionFields();
1114 for (fields.keys()) |field_name| {
1115 const field = fields.get(field_name).?;
1116 if (!field.ty.hasRuntimeBits()) continue;
1117 // DW.AT.member
1118 try dbg_info_buffer.append(abbrev_struct_member);
1119 // DW.AT.name, DW.FORM.string
1120 try dbg_info_buffer.writer().print("{s}\x00", .{field_name});
1121 // DW.AT.type, DW.FORM.ref4
1122 const index = dbg_info_buffer.items.len;
1123 try dbg_info_buffer.resize(index + 4);
1124 try self.addTypeReloc(atom, field.ty, @intCast(u32, index), null);
1125 // DW.AT.data_member_location, DW.FORM.sdata
1126 try dbg_info_buffer.append(0);
1127 }
1128 // DW.AT.union_type delimit children
1129 try dbg_info_buffer.append(0);
1130
1131 if (is_tagged) {
1132 // DW.AT.member
1133 try dbg_info_buffer.ensureUnusedCapacity(5);
1134 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
1135 // DW.AT.name, DW.FORM.string
1136 dbg_info_buffer.appendSliceAssumeCapacity("tag");
1137 dbg_info_buffer.appendAssumeCapacity(0);
1138 // DW.AT.type, DW.FORM.ref4
1139 const index = dbg_info_buffer.items.len;
1140 try dbg_info_buffer.resize(index + 4);
1141 try self.addTypeReloc(atom, union_obj.tag_ty, @intCast(u32, index), null);
1142 // DW.AT.data_member_location, DW.FORM.sdata
1143 try leb128.writeULEB128(dbg_info_buffer.writer(), tag_offset);
1144
1145 // DW.AT.structure_type delimit children
1146 try dbg_info_buffer.append(0);
1147 }
1148 },
1149 .ErrorSet => {
1150 // DW.AT.enumeration_type
1151 try dbg_info_buffer.append(abbrev_enum_type);
1152 // DW.AT.byte_size, DW.FORM.sdata
1153 const abi_size = ty.abiSize(target);
1154 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
1155 // DW.AT.name, DW.FORM.string
1156 const name = try ty.nameAllocArena(arena, target);
1157 try dbg_info_buffer.writer().print("{s}\x00", .{name});
1158
1159 // DW.AT.enumerator
1160 const no_error = "(no error)";
1161 try dbg_info_buffer.ensureUnusedCapacity(no_error.len + 2 + @sizeOf(u64));
1162 dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant);
1163 // DW.AT.name, DW.FORM.string
1164 dbg_info_buffer.appendSliceAssumeCapacity(no_error);
1165 dbg_info_buffer.appendAssumeCapacity(0);
1166 // DW.AT.const_value, DW.FORM.data8
1167 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);
1168
1169 const error_names = ty.errorSetNames();
1170 for (error_names) |error_name| {
1171 const kv = module.getErrorValue(error_name) catch unreachable;
1172 // DW.AT.enumerator
1173 try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64));
1174 dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant);
1175 // DW.AT.name, DW.FORM.string
1176 dbg_info_buffer.appendSliceAssumeCapacity(error_name);
1177 dbg_info_buffer.appendAssumeCapacity(0);
1178 // DW.AT.const_value, DW.FORM.data8
1179 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), kv.value, target_endian);
1180 }
1181
1182 // DW.AT.enumeration_type delimit children
1183 try dbg_info_buffer.append(0);
1184 },
1185 .ErrorUnion => {
1186 const error_ty = ty.errorUnionSet();
1187 const payload_ty = ty.errorUnionPayload();
1188 const abi_size = ty.abiSize(target);
1189 const abi_align = ty.abiAlignment(target);
1190 const payload_off = mem.alignForwardGeneric(u64, error_ty.abiSize(target), abi_align);
1191
1192 // DW.AT.structure_type
1193 try dbg_info_buffer.append(abbrev_struct_type);
1194 // DW.AT.byte_size, DW.FORM.sdata
1195 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
1196 // DW.AT.name, DW.FORM.string
1197 const name = try ty.nameAllocArena(arena, target);
1198 try dbg_info_buffer.writer().print("{s}\x00", .{name});
1199
1200 // DW.AT.member
1201 try dbg_info_buffer.ensureUnusedCapacity(7);
1202 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
1203 // DW.AT.name, DW.FORM.string
1204 dbg_info_buffer.appendSliceAssumeCapacity("value");
1205 dbg_info_buffer.appendAssumeCapacity(0);
1206 // DW.AT.type, DW.FORM.ref4
1207 var index = dbg_info_buffer.items.len;
1208 try dbg_info_buffer.resize(index + 4);
1209 try self.addTypeReloc(atom, payload_ty, @intCast(u32, index), null);
1210 // DW.AT.data_member_location, DW.FORM.sdata
1211 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_off);
1212
1213 // DW.AT.member
1214 try dbg_info_buffer.ensureUnusedCapacity(5);
1215 dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
1216 // DW.AT.name, DW.FORM.string
1217 dbg_info_buffer.appendSliceAssumeCapacity("err");
1218 dbg_info_buffer.appendAssumeCapacity(0);
1219 // DW.AT.type, DW.FORM.ref4
1220 index = dbg_info_buffer.items.len;
1221 try dbg_info_buffer.resize(index + 4);
1222 try self.addTypeReloc(atom, error_ty, @intCast(u32, index), null);
1223 // DW.AT.data_member_location, DW.FORM.sdata
1224 try dbg_info_buffer.append(0);
1225
1226 // DW.AT.structure_type delimit children
1227 try dbg_info_buffer.append(0);
1228 },
1229 else => {
1230 log.debug("TODO implement .debug_info for type '{}'", .{ty.fmtDebug()});
1231 try dbg_info_buffer.append(abbrev_pad1);
1232 },
1233 }
1234}
1235
1236pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {1243pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
1237 // These are LEB encoded but since the values are all less than 1271244 // These are LEB encoded but since the values are all less than 127
1238 // we can simply append these bytes.1245 // we can simply append these bytes.
...@@ -1952,45 +1959,6 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {...@@ -1952,45 +1959,6 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
1952 std.math.maxInt(@TypeOf(actual_size));1959 std.math.maxInt(@TypeOf(actual_size));
1953}1960}
19541961
1955pub fn addTypeReloc(self: *Dwarf, atom: *const Atom, ty: Type, offset: u32, addend: ?u32) !void {
1956 const decl_state = &self.decl_state.?;
1957 const gpa = self.allocator;
1958 const resolv = decl_state.abbrev_resolver.getContext(ty, .{
1959 .target = self.target,
1960 }) orelse blk: {
1961 const sym_index = @intCast(u32, decl_state.abbrev_table.items.len);
1962 try decl_state.abbrev_table.append(gpa, .{
1963 .atom = atom,
1964 .@"type" = ty,
1965 .offset = undefined,
1966 });
1967 log.debug("@{d}: {}", .{ sym_index, ty.fmtDebug() });
1968 try decl_state.abbrev_resolver.putNoClobberContext(gpa, ty, sym_index, .{
1969 .target = self.target,
1970 });
1971 break :blk decl_state.abbrev_resolver.getContext(ty, .{
1972 .target = self.target,
1973 }).?;
1974 };
1975 const add: u32 = addend orelse 0;
1976
1977 log.debug("{x}: @{d} + {x}", .{ offset, resolv, add });
1978 try decl_state.abbrev_relocs.append(gpa, .{
1979 .target = resolv,
1980 .atom = atom,
1981 .offset = offset,
1982 .addend = add,
1983 });
1984}
1985
1986pub fn getDeclDebugLineBuffer(self: *Dwarf) *std.ArrayList(u8) {
1987 return &self.decl_state.?.dbg_line;
1988}
1989
1990pub fn getDeclDebugInfoBuffer(self: *Dwarf) *std.ArrayList(u8) {
1991 return &self.decl_state.?.dbg_info;
1992}
1993
1994pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {1962pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {
1995 if (self.global_abbrev_relocs.items.len > 0) {1963 if (self.global_abbrev_relocs.items.len > 0) {
1996 const gpa = self.allocator;1964 const gpa = self.allocator;
...@@ -2018,7 +1986,7 @@ pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {...@@ -2018,7 +1986,7 @@ pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {
2018 };1986 };
20191987
2020 var dbg_info_buffer = std.ArrayList(u8).init(arena);1988 var dbg_info_buffer = std.ArrayList(u8).init(arena);
2021 try self.addDbgInfoType(arena, module, atom, error_ty, &dbg_info_buffer);1989 try addDbgInfoErrorSet(arena, module, error_ty, self.target, &dbg_info_buffer);
20221990
2023 try self.managed_atoms.append(gpa, atom);1991 try self.managed_atoms.append(gpa, atom);
2024 try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len));1992 try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len));
...@@ -2060,6 +2028,49 @@ pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {...@@ -2060,6 +2028,49 @@ pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {
2060 }2028 }
2061 }2029 }
2062 }2030 }
2031}
2032
2033fn addDbgInfoErrorSet(
2034 arena: Allocator,
2035 module: *Module,
2036 ty: Type,
2037 target: std.Target,
2038 dbg_info_buffer: *std.ArrayList(u8),
2039) !void {
2040 const target_endian = target.cpu.arch.endian();
2041
2042 // DW.AT.enumeration_type
2043 try dbg_info_buffer.append(abbrev_enum_type);
2044 // DW.AT.byte_size, DW.FORM.sdata
2045 const abi_size = ty.abiSize(target);
2046 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
2047 // DW.AT.name, DW.FORM.string
2048 const name = try ty.nameAllocArena(arena, target);
2049 try dbg_info_buffer.writer().print("{s}\x00", .{name});
2050
2051 // DW.AT.enumerator
2052 const no_error = "(no error)";
2053 try dbg_info_buffer.ensureUnusedCapacity(no_error.len + 2 + @sizeOf(u64));
2054 dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant);
2055 // DW.AT.name, DW.FORM.string
2056 dbg_info_buffer.appendSliceAssumeCapacity(no_error);
2057 dbg_info_buffer.appendAssumeCapacity(0);
2058 // DW.AT.const_value, DW.FORM.data8
2059 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);
2060
2061 const error_names = ty.errorSetNames();
2062 for (error_names) |error_name| {
2063 const kv = module.getErrorValue(error_name) catch unreachable;
2064 // DW.AT.enumerator
2065 try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64));
2066 dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant);
2067 // DW.AT.name, DW.FORM.string
2068 dbg_info_buffer.appendSliceAssumeCapacity(error_name);
2069 dbg_info_buffer.appendAssumeCapacity(0);
2070 // DW.AT.const_value, DW.FORM.data8
2071 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), kv.value, target_endian);
2072 }
20632073
2064 assert(self.decl_state == null);2074 // DW.AT.enumeration_type delimit children
2075 try dbg_info_buffer.append(0);
2065}2076}
src/link/Elf.zig+26-20
...@@ -2339,19 +2339,12 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven...@@ -2339,19 +2339,12 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
2339 const decl = func.owner_decl;2339 const decl = func.owner_decl;
2340 self.freeUnnamedConsts(decl);2340 self.freeUnnamedConsts(decl);
23412341
2342 if (self.dwarf) |*dw| {2342 var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(decl) else null;
2343 try dw.initDeclState(decl);2343 defer if (decl_state) |*ds| ds.deinit();
2344 }
2345 defer if (self.dwarf) |*dw| {
2346 if (dw.decl_state) |*ds| {
2347 ds.deinit(dw.allocator);
2348 dw.decl_state = null;
2349 }
2350 };
23512344
2352 const res = if (self.dwarf) |*dw|2345 const res = if (decl_state) |*ds|
2353 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{2346 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{
2354 .dwarf = dw,2347 .dwarf = ds,
2355 })2348 })
2356 else2349 else
2357 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);2350 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);
...@@ -2365,8 +2358,15 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven...@@ -2365,8 +2358,15 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
2365 },2358 },
2366 };2359 };
2367 const local_sym = try self.updateDeclCode(decl, code, elf.STT_FUNC);2360 const local_sym = try self.updateDeclCode(decl, code, elf.STT_FUNC);
2368 if (self.dwarf) |*dw| {2361 if (decl_state) |*ds| {
2369 try dw.commitDeclState(&self.base, module, decl, local_sym.st_value, local_sym.st_size);2362 try self.dwarf.?.commitDeclState(
2363 &self.base,
2364 module,
2365 decl,
2366 local_sym.st_value,
2367 local_sym.st_size,
2368 ds,
2369 );
2370 }2370 }
23712371
2372 // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated.2372 // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated.
...@@ -2400,18 +2400,17 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2400,18 +2400,17 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2400 var code_buffer = std.ArrayList(u8).init(self.base.allocator);2400 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
2401 defer code_buffer.deinit();2401 defer code_buffer.deinit();
24022402
2403 if (self.dwarf) |*dw| {2403 var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(decl) else null;
2404 try dw.initDeclState(decl);2404 defer if (decl_state) |*ds| ds.deinit();
2405 }
24062405
2407 // TODO implement .debug_info for global variables2406 // TODO implement .debug_info for global variables
2408 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;2407 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
2409 const res = if (self.dwarf) |*dw|2408 const res = if (decl_state) |*ds|
2410 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{2409 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2411 .ty = decl.ty,2410 .ty = decl.ty,
2412 .val = decl_val,2411 .val = decl_val,
2413 }, &code_buffer, .{2412 }, &code_buffer, .{
2414 .dwarf = dw,2413 .dwarf = ds,
2415 }, .{2414 }, .{
2416 .parent_atom_index = decl.link.elf.local_sym_index,2415 .parent_atom_index = decl.link.elf.local_sym_index,
2417 })2416 })
...@@ -2434,8 +2433,15 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2434,8 +2433,15 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2434 };2433 };
24352434
2436 const local_sym = try self.updateDeclCode(decl, code, elf.STT_OBJECT);2435 const local_sym = try self.updateDeclCode(decl, code, elf.STT_OBJECT);
2437 if (self.dwarf) |*dw| {2436 if (decl_state) |*ds| {
2438 try dw.commitDeclState(&self.base, module, decl, local_sym.st_value, local_sym.st_size);2437 try self.dwarf.?.commitDeclState(
2438 &self.base,
2439 module,
2440 decl,
2441 local_sym.st_value,
2442 local_sym.st_size,
2443 ds,
2444 );
2439 }2445 }
24402446
2441 // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated.2447 // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated.
src/link/MachO.zig+33-14
...@@ -27,6 +27,7 @@ const Atom = @import("MachO/Atom.zig");...@@ -27,6 +27,7 @@ const Atom = @import("MachO/Atom.zig");
27const Cache = @import("../Cache.zig");27const Cache = @import("../Cache.zig");
28const CodeSignature = @import("MachO/CodeSignature.zig");28const CodeSignature = @import("MachO/CodeSignature.zig");
29const Compilation = @import("../Compilation.zig");29const Compilation = @import("../Compilation.zig");
30const Dwarf = File.Dwarf;
30const Dylib = @import("MachO/Dylib.zig");31const Dylib = @import("MachO/Dylib.zig");
31const File = link.File;32const File = link.File;
32const Object = @import("MachO/Object.zig");33const Object = @import("MachO/Object.zig");
...@@ -3676,13 +3677,15 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv...@@ -3676,13 +3677,15 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
3676 var code_buffer = std.ArrayList(u8).init(self.base.allocator);3677 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
3677 defer code_buffer.deinit();3678 defer code_buffer.deinit();
36783679
3679 if (self.d_sym) |*d_sym| {3680 var decl_state = if (self.d_sym) |*d_sym|
3680 try d_sym.dwarf.initDeclState(decl);3681 try d_sym.dwarf.initDeclState(decl)
3681 }3682 else
3683 null;
3684 defer if (decl_state) |*ds| ds.deinit();
36823685
3683 const res = if (self.d_sym) |*d_sym|3686 const res = if (decl_state) |*ds|
3684 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{3687 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{
3685 .dwarf = &d_sym.dwarf,3688 .dwarf = ds,
3686 })3689 })
3687 else3690 else
3688 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);3691 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);
...@@ -3700,8 +3703,15 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv...@@ -3700,8 +3703,15 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
37003703
3701 const symbol = try self.placeDecl(decl, decl.link.macho.code.items.len);3704 const symbol = try self.placeDecl(decl, decl.link.macho.code.items.len);
37023705
3703 if (self.d_sym) |*d_sym| {3706 if (decl_state) |*ds| {
3704 try d_sym.dwarf.commitDeclState(&self.base, module, decl, symbol.n_value, decl.link.macho.size);3707 try self.d_sym.?.dwarf.commitDeclState(
3708 &self.base,
3709 module,
3710 decl,
3711 symbol.n_value,
3712 decl.link.macho.size,
3713 ds,
3714 );
3705 }3715 }
37063716
3707 // Since we updated the vaddr and the size, each corresponding export symbol also3717 // Since we updated the vaddr and the size, each corresponding export symbol also
...@@ -3801,17 +3811,19 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -3801,17 +3811,19 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
3801 var code_buffer = std.ArrayList(u8).init(self.base.allocator);3811 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
3802 defer code_buffer.deinit();3812 defer code_buffer.deinit();
38033813
3804 if (self.d_sym) |*d_sym| {3814 var decl_state: ?Dwarf.DeclState = if (self.d_sym) |*d_sym|
3805 try d_sym.dwarf.initDeclState(decl);3815 try d_sym.dwarf.initDeclState(decl)
3806 }3816 else
3817 null;
3818 defer if (decl_state) |*ds| ds.deinit();
38073819
3808 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;3820 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
3809 const res = if (self.d_sym) |*d_sym|3821 const res = if (decl_state) |*ds|
3810 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{3822 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
3811 .ty = decl.ty,3823 .ty = decl.ty,
3812 .val = decl_val,3824 .val = decl_val,
3813 }, &code_buffer, .{3825 }, &code_buffer, .{
3814 .dwarf = &d_sym.dwarf,3826 .dwarf = ds,
3815 }, .{3827 }, .{
3816 .parent_atom_index = decl.link.macho.local_sym_index,3828 .parent_atom_index = decl.link.macho.local_sym_index,
3817 })3829 })
...@@ -3845,8 +3857,15 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -3845,8 +3857,15 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
3845 };3857 };
3846 const symbol = try self.placeDecl(decl, code.len);3858 const symbol = try self.placeDecl(decl, code.len);
38473859
3848 if (self.d_sym) |*d_sym| {3860 if (decl_state) |*ds| {
3849 try d_sym.dwarf.commitDeclState(&self.base, module, decl, symbol.n_value, decl.link.macho.size);3861 try self.d_sym.?.dwarf.commitDeclState(
3862 &self.base,
3863 module,
3864 decl,
3865 symbol.n_value,
3866 decl.link.macho.size,
3867 ds,
3868 );
3850 }3869 }
38513870
3852 // Since we updated the vaddr and the size, each corresponding export symbol also3871 // Since we updated the vaddr and the size, each corresponding export symbol also