| ... | @@ -31,10 +31,11 @@ dbg_line_fn_free_list: std.AutoHashMapUnmanaged(*SrcFn, void) = .{}, | ... | @@ -31,10 +31,11 @@ dbg_line_fn_free_list: std.AutoHashMapUnmanaged(*SrcFn, void) = .{}, |
| 31 | dbg_line_fn_first: ?*SrcFn = null, | 31 | dbg_line_fn_first: ?*SrcFn = null, |
| 32 | dbg_line_fn_last: ?*SrcFn = null, | 32 | dbg_line_fn_last: ?*SrcFn = null, |
| 33 | | 33 | |
| 34 | /// A list of `TextBlock` whose corresponding .debug_info tags have surplus capacity. /// This is the same concept as `text_block_free_list`; see those doc comments. | 34 | /// A list of `Atom`s whose corresponding .debug_info tags have surplus capacity. |
| 35 | dbg_info_decl_free_list: std.AutoHashMapUnmanaged(*DebugInfoAtom, void) = .{}, | 35 | /// This is the same concept as `text_block_free_list`; see those doc comments. |
| 36 | dbg_info_decl_first: ?*DebugInfoAtom = null, | 36 | atom_free_list: std.AutoHashMapUnmanaged(*Atom, void) = .{}, |
| 37 | dbg_info_decl_last: ?*DebugInfoAtom = null, | 37 | atom_first: ?*Atom = null, |
| | 38 | atom_last: ?*Atom = null, |
| 38 | | 39 | |
| 39 | abbrev_table_offset: ?u64 = null, | 40 | abbrev_table_offset: ?u64 = null, |
| 40 | | 41 | |
| ... | @@ -43,11 +44,16 @@ strtab: std.ArrayListUnmanaged(u8) = .{}, | ... | @@ -43,11 +44,16 @@ strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 43 | | 44 | |
| 44 | deferred_error_sets_relocs: std.ArrayListUnmanaged(u32) = .{}, | 45 | deferred_error_sets_relocs: std.ArrayListUnmanaged(u32) = .{}, |
| 45 | | 46 | |
| 46 | pub const DebugInfoAtom = struct { | 47 | /// List of atoms that are owned directly by the DWARF module. |
| | 48 | /// TODO convert links in DebugInfoAtom into indices and make |
| | 49 | /// sure every atom is owned by this module. |
| | 50 | managed_atoms: std.ArrayListUnmanaged(*Atom) = .{}, |
| | 51 | |
| | 52 | pub const Atom = struct { |
| 47 | /// Previous/next linked list pointers. | 53 | /// Previous/next linked list pointers. |
| 48 | /// This is the linked list node for this Decl's corresponding .debug_info tag. | 54 | /// This is the linked list node for this Decl's corresponding .debug_info tag. |
| 49 | prev: ?*DebugInfoAtom, | 55 | prev: ?*Atom, |
| 50 | next: ?*DebugInfoAtom, | 56 | next: ?*Atom, |
| 51 | /// Offset into .debug_info pointing to the tag for this Decl. | 57 | /// Offset into .debug_info pointing to the tag for this Decl. |
| 52 | off: u32, | 58 | off: u32, |
| 53 | /// Size of the .debug_info tag for this Decl, not including padding. | 59 | /// Size of the .debug_info tag for this Decl, not including padding. |
| ... | @@ -119,9 +125,14 @@ pub fn init(allocator: Allocator, tag: File.Tag, target: std.Target) Dwarf { | ... | @@ -119,9 +125,14 @@ pub fn init(allocator: Allocator, tag: File.Tag, target: std.Target) Dwarf { |
| 119 | pub fn deinit(self: *Dwarf) void { | 125 | pub fn deinit(self: *Dwarf) void { |
| 120 | const gpa = self.allocator; | 126 | const gpa = self.allocator; |
| 121 | self.dbg_line_fn_free_list.deinit(gpa); | 127 | self.dbg_line_fn_free_list.deinit(gpa); |
| 122 | self.dbg_info_decl_free_list.deinit(gpa); | 128 | self.atom_free_list.deinit(gpa); |
| 123 | self.strtab.deinit(gpa); | 129 | self.strtab.deinit(gpa); |
| 124 | self.deferred_error_sets_relocs.deinit(gpa); | 130 | self.deferred_error_sets_relocs.deinit(gpa); |
| | 131 | |
| | 132 | for (self.managed_atoms.items) |atom| { |
| | 133 | gpa.destroy(atom); |
| | 134 | } |
| | 135 | self.managed_atoms.deinit(gpa); |
| 125 | } | 136 | } |
| 126 | | 137 | |
| 127 | pub const DeclDebugBuffers = struct { | 138 | pub const DeclDebugBuffers = struct { |
| ... | @@ -568,10 +579,7 @@ pub fn commitErrorSetDebugInfo(self: *Dwarf, file: *File, module: *Module) !void | ... | @@ -568,10 +579,7 @@ pub fn commitErrorSetDebugInfo(self: *Dwarf, file: *File, module: *Module) !void |
| 568 | var dbg_info_buffer = std.ArrayList(u8).init(arena); | 579 | var dbg_info_buffer = std.ArrayList(u8).init(arena); |
| 569 | try self.addDbgInfoErrorSet(arena, module, ty, &dbg_info_buffer); | 580 | try self.addDbgInfoErrorSet(arena, module, ty, &dbg_info_buffer); |
| 570 | | 581 | |
| 571 | // TODO seems like we need to store DebugInfoAtoms in Dwarf object | 582 | const atom = try gpa.create(Atom); |
| 572 | // In other words, I have turned Dwarf into a linker... | | |
| 573 | // FIXME memory leak!!! | | |
| 574 | const atom = try gpa.create(DebugInfoAtom); | | |
| 575 | errdefer gpa.destroy(atom); | 583 | errdefer gpa.destroy(atom); |
| 576 | atom.* = .{ | 584 | atom.* = .{ |
| 577 | .prev = null, | 585 | .prev = null, |
| ... | @@ -579,6 +587,7 @@ pub fn commitErrorSetDebugInfo(self: *Dwarf, file: *File, module: *Module) !void | ... | @@ -579,6 +587,7 @@ pub fn commitErrorSetDebugInfo(self: *Dwarf, file: *File, module: *Module) !void |
| 579 | .off = 0, | 587 | .off = 0, |
| 580 | .len = 0, | 588 | .len = 0, |
| 581 | }; | 589 | }; |
| | 590 | try self.managed_atoms.append(gpa, atom); |
| 582 | try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len)); | 591 | try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len)); |
| 583 | try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items); | 592 | try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items); |
| 584 | | 593 | |
| ... | @@ -620,7 +629,7 @@ pub fn commitErrorSetDebugInfo(self: *Dwarf, file: *File, module: *Module) !void | ... | @@ -620,7 +629,7 @@ pub fn commitErrorSetDebugInfo(self: *Dwarf, file: *File, module: *Module) !void |
| 620 | } | 629 | } |
| 621 | } | 630 | } |
| 622 | | 631 | |
| 623 | fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *DebugInfoAtom, len: u32) !void { | 632 | fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u32) !void { |
| 624 | const tracy = trace(@src()); | 633 | const tracy = trace(@src()); |
| 625 | defer tracy.end(); | 634 | defer tracy.end(); |
| 626 | | 635 | |
| ... | @@ -630,14 +639,14 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *DebugInfoAtom | ... | @@ -630,14 +639,14 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *DebugInfoAtom |
| 630 | const gpa = self.allocator; | 639 | const gpa = self.allocator; |
| 631 | | 640 | |
| 632 | atom.len = len; | 641 | atom.len = len; |
| 633 | if (self.dbg_info_decl_last) |last| blk: { | 642 | if (self.atom_last) |last| blk: { |
| 634 | if (atom == last) break :blk; | 643 | if (atom == last) break :blk; |
| 635 | if (atom.next) |next| { | 644 | if (atom.next) |next| { |
| 636 | // Update existing Decl - non-last item. | 645 | // Update existing Decl - non-last item. |
| 637 | if (atom.off + atom.len + min_nop_size > next.off) { | 646 | if (atom.off + atom.len + min_nop_size > next.off) { |
| 638 | // It grew too big, so we move it to a new location. | 647 | // It grew too big, so we move it to a new location. |
| 639 | if (atom.prev) |prev| { | 648 | if (atom.prev) |prev| { |
| 640 | self.dbg_info_decl_free_list.put(gpa, prev, {}) catch {}; | 649 | self.atom_free_list.put(gpa, prev, {}) catch {}; |
| 641 | prev.next = atom.next; | 650 | prev.next = atom.next; |
| 642 | } | 651 | } |
| 643 | next.prev = atom.prev; | 652 | next.prev = atom.prev; |
| ... | @@ -663,7 +672,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *DebugInfoAtom | ... | @@ -663,7 +672,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *DebugInfoAtom |
| 663 | // TODO Look at the free list before appending at the end. | 672 | // TODO Look at the free list before appending at the end. |
| 664 | atom.prev = last; | 673 | atom.prev = last; |
| 665 | last.next = atom; | 674 | last.next = atom; |
| 666 | self.dbg_info_decl_last = atom; | 675 | self.atom_last = atom; |
| 667 | | 676 | |
| 668 | atom.off = last.off + padToIdeal(last.len); | 677 | atom.off = last.off + padToIdeal(last.len); |
| 669 | } | 678 | } |
| ... | @@ -672,20 +681,20 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *DebugInfoAtom | ... | @@ -672,20 +681,20 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *DebugInfoAtom |
| 672 | // TODO Look at the free list before appending at the end. | 681 | // TODO Look at the free list before appending at the end. |
| 673 | atom.prev = last; | 682 | atom.prev = last; |
| 674 | last.next = atom; | 683 | last.next = atom; |
| 675 | self.dbg_info_decl_last = atom; | 684 | self.atom_last = atom; |
| 676 | | 685 | |
| 677 | atom.off = last.off + padToIdeal(last.len); | 686 | atom.off = last.off + padToIdeal(last.len); |
| 678 | } | 687 | } |
| 679 | } else { | 688 | } else { |
| 680 | // This is the first Decl of the .debug_info | 689 | // This is the first Decl of the .debug_info |
| 681 | self.dbg_info_decl_first = atom; | 690 | self.atom_first = atom; |
| 682 | self.dbg_info_decl_last = atom; | 691 | self.atom_last = atom; |
| 683 | | 692 | |
| 684 | atom.off = @intCast(u32, padToIdeal(self.dbgInfoHeaderBytes())); | 693 | atom.off = @intCast(u32, padToIdeal(self.dbgInfoHeaderBytes())); |
| 685 | } | 694 | } |
| 686 | } | 695 | } |
| 687 | | 696 | |
| 688 | fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *DebugInfoAtom, dbg_info_buf: []const u8) !void { | 697 | fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []const u8) !void { |
| 689 | const tracy = trace(@src()); | 698 | const tracy = trace(@src()); |
| 690 | defer tracy.end(); | 699 | defer tracy.end(); |
| 691 | | 700 | |
| ... | @@ -694,7 +703,7 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *DebugInfoAtom, dbg_info_ | ... | @@ -694,7 +703,7 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *DebugInfoAtom, dbg_info_ |
| 694 | // probably need to edit that logic too. | 703 | // probably need to edit that logic too. |
| 695 | const gpa = self.allocator; | 704 | const gpa = self.allocator; |
| 696 | | 705 | |
| 697 | const last_decl = self.dbg_info_decl_last.?; | 706 | const last_decl = self.atom_last.?; |
| 698 | // +1 for a trailing zero to end the children of the decl tag. | 707 | // +1 for a trailing zero to end the children of the decl tag. |
| 699 | const needed_size = last_decl.off + last_decl.len + 1; | 708 | const needed_size = last_decl.off + last_decl.len + 1; |
| 700 | const prev_padding_size: u32 = if (atom.prev) |prev| atom.off - (prev.off + prev.len) else 0; | 709 | const prev_padding_size: u32 = if (atom.prev) |prev| atom.off - (prev.off + prev.len) else 0; |
| ... | @@ -819,13 +828,13 @@ pub fn updateDeclLineNumber(self: *Dwarf, file: *File, decl: *const Module.Decl) | ... | @@ -819,13 +828,13 @@ pub fn updateDeclLineNumber(self: *Dwarf, file: *File, decl: *const Module.Decl) |
| 819 | } | 828 | } |
| 820 | } | 829 | } |
| 821 | | 830 | |
| 822 | pub fn freeAtom(self: *Dwarf, atom: *DebugInfoAtom) void { | 831 | pub fn freeAtom(self: *Dwarf, atom: *Atom) void { |
| 823 | if (self.dbg_info_decl_first == atom) { | 832 | if (self.atom_first == atom) { |
| 824 | self.dbg_info_decl_first = atom.next; | 833 | self.atom_first = atom.next; |
| 825 | } | 834 | } |
| 826 | if (self.dbg_info_decl_last == atom) { | 835 | if (self.atom_last == atom) { |
| 827 | // TODO shrink the .debug_info section size here | 836 | // TODO shrink the .debug_info section size here |
| 828 | self.dbg_info_decl_last = atom.prev; | 837 | self.atom_last = atom.prev; |
| 829 | } | 838 | } |
| 830 | | 839 | |
| 831 | if (atom.prev) |prev| { | 840 | if (atom.prev) |prev| { |
| ... | @@ -1964,12 +1973,12 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void { | ... | @@ -1964,12 +1973,12 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void { |
| 1964 | } | 1973 | } |
| 1965 | | 1974 | |
| 1966 | fn getDebugInfoOff(self: Dwarf) ?u32 { | 1975 | fn getDebugInfoOff(self: Dwarf) ?u32 { |
| 1967 | const first = self.dbg_info_decl_first orelse return null; | 1976 | const first = self.atom_first orelse return null; |
| 1968 | return first.off; | 1977 | return first.off; |
| 1969 | } | 1978 | } |
| 1970 | | 1979 | |
| 1971 | fn getDebugInfoEnd(self: Dwarf) ?u32 { | 1980 | fn getDebugInfoEnd(self: Dwarf) ?u32 { |
| 1972 | const last = self.dbg_info_decl_last orelse return null; | 1981 | const last = self.atom_last orelse return null; |
| 1973 | return last.off + last.len; | 1982 | return last.off + last.len; |
| 1974 | } | 1983 | } |
| 1975 | | 1984 | |