| ... | ... | @@ -31,10 +31,11 @@ dbg_line_fn_free_list: std.AutoHashMapUnmanaged(*SrcFn, void) = .{}, |
| 31 | 31 | dbg_line_fn_first: ?*SrcFn = null, |
| 32 | 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. |
| 35 | | dbg_info_decl_free_list: std.AutoHashMapUnmanaged(*DebugInfoAtom, void) = .{}, |
| 36 | | dbg_info_decl_first: ?*DebugInfoAtom = null, |
| 37 | | dbg_info_decl_last: ?*DebugInfoAtom = null, |
| 34 | /// A list of `Atom`s whose corresponding .debug_info tags have surplus capacity. |
| 35 | /// This is the same concept as `text_block_free_list`; see those doc comments. |
| 36 | atom_free_list: std.AutoHashMapUnmanaged(*Atom, void) = .{}, |
| 37 | atom_first: ?*Atom = null, |
| 38 | atom_last: ?*Atom = null, |
| 38 | 39 | |
| 39 | 40 | abbrev_table_offset: ?u64 = null, |
| 40 | 41 | |
| ... | ... | @@ -43,11 +44,16 @@ strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 43 | 44 | |
| 44 | 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 | 53 | /// Previous/next linked list pointers. |
| 48 | 54 | /// This is the linked list node for this Decl's corresponding .debug_info tag. |
| 49 | | prev: ?*DebugInfoAtom, |
| 50 | | next: ?*DebugInfoAtom, |
| 55 | prev: ?*Atom, |
| 56 | next: ?*Atom, |
| 51 | 57 | /// Offset into .debug_info pointing to the tag for this Decl. |
| 52 | 58 | off: u32, |
| 53 | 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 | 125 | pub fn deinit(self: *Dwarf) void { |
| 120 | 126 | const gpa = self.allocator; |
| 121 | 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 | 129 | self.strtab.deinit(gpa); |
| 124 | 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 | 138 | pub const DeclDebugBuffers = struct { |
| ... | ... | @@ -568,10 +579,7 @@ pub fn commitErrorSetDebugInfo(self: *Dwarf, file: *File, module: *Module) !void |
| 568 | 579 | var dbg_info_buffer = std.ArrayList(u8).init(arena); |
| 569 | 580 | try self.addDbgInfoErrorSet(arena, module, ty, &dbg_info_buffer); |
| 570 | 581 | |
| 571 | | // TODO seems like we need to store DebugInfoAtoms in Dwarf object |
| 572 | | // In other words, I have turned Dwarf into a linker... |
| 573 | | // FIXME memory leak!!! |
| 574 | | const atom = try gpa.create(DebugInfoAtom); |
| 582 | const atom = try gpa.create(Atom); |
| 575 | 583 | errdefer gpa.destroy(atom); |
| 576 | 584 | atom.* = .{ |
| 577 | 585 | .prev = null, |
| ... | ... | @@ -579,6 +587,7 @@ pub fn commitErrorSetDebugInfo(self: *Dwarf, file: *File, module: *Module) !void |
| 579 | 587 | .off = 0, |
| 580 | 588 | .len = 0, |
| 581 | 589 | }; |
| 590 | try self.managed_atoms.append(gpa, atom); |
| 582 | 591 | try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len)); |
| 583 | 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 | 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 | 633 | const tracy = trace(@src()); |
| 625 | 634 | defer tracy.end(); |
| 626 | 635 | |
| ... | ... | @@ -630,14 +639,14 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *DebugInfoAtom |
| 630 | 639 | const gpa = self.allocator; |
| 631 | 640 | |
| 632 | 641 | atom.len = len; |
| 633 | | if (self.dbg_info_decl_last) |last| blk: { |
| 642 | if (self.atom_last) |last| blk: { |
| 634 | 643 | if (atom == last) break :blk; |
| 635 | 644 | if (atom.next) |next| { |
| 636 | 645 | // Update existing Decl - non-last item. |
| 637 | 646 | if (atom.off + atom.len + min_nop_size > next.off) { |
| 638 | 647 | // It grew too big, so we move it to a new location. |
| 639 | 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 | 650 | prev.next = atom.next; |
| 642 | 651 | } |
| 643 | 652 | next.prev = atom.prev; |
| ... | ... | @@ -663,7 +672,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *DebugInfoAtom |
| 663 | 672 | // TODO Look at the free list before appending at the end. |
| 664 | 673 | atom.prev = last; |
| 665 | 674 | last.next = atom; |
| 666 | | self.dbg_info_decl_last = atom; |
| 675 | self.atom_last = atom; |
| 667 | 676 | |
| 668 | 677 | atom.off = last.off + padToIdeal(last.len); |
| 669 | 678 | } |
| ... | ... | @@ -672,20 +681,20 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *DebugInfoAtom |
| 672 | 681 | // TODO Look at the free list before appending at the end. |
| 673 | 682 | atom.prev = last; |
| 674 | 683 | last.next = atom; |
| 675 | | self.dbg_info_decl_last = atom; |
| 684 | self.atom_last = atom; |
| 676 | 685 | |
| 677 | 686 | atom.off = last.off + padToIdeal(last.len); |
| 678 | 687 | } |
| 679 | 688 | } else { |
| 680 | 689 | // This is the first Decl of the .debug_info |
| 681 | | self.dbg_info_decl_first = atom; |
| 682 | | self.dbg_info_decl_last = atom; |
| 690 | self.atom_first = atom; |
| 691 | self.atom_last = atom; |
| 683 | 692 | |
| 684 | 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 | 698 | const tracy = trace(@src()); |
| 690 | 699 | defer tracy.end(); |
| 691 | 700 | |
| ... | ... | @@ -694,7 +703,7 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *DebugInfoAtom, dbg_info_ |
| 694 | 703 | // probably need to edit that logic too. |
| 695 | 704 | const gpa = self.allocator; |
| 696 | 705 | |
| 697 | | const last_decl = self.dbg_info_decl_last.?; |
| 706 | const last_decl = self.atom_last.?; |
| 698 | 707 | // +1 for a trailing zero to end the children of the decl tag. |
| 699 | 708 | const needed_size = last_decl.off + last_decl.len + 1; |
| 700 | 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 | 828 | } |
| 820 | 829 | } |
| 821 | 830 | |
| 822 | | pub fn freeAtom(self: *Dwarf, atom: *DebugInfoAtom) void { |
| 823 | | if (self.dbg_info_decl_first == atom) { |
| 824 | | self.dbg_info_decl_first = atom.next; |
| 831 | pub fn freeAtom(self: *Dwarf, atom: *Atom) void { |
| 832 | if (self.atom_first == atom) { |
| 833 | self.atom_first = atom.next; |
| 825 | 834 | } |
| 826 | | if (self.dbg_info_decl_last == atom) { |
| 835 | if (self.atom_last == atom) { |
| 827 | 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 | 840 | if (atom.prev) |prev| { |
| ... | ... | @@ -1964,12 +1973,12 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void { |
| 1964 | 1973 | } |
| 1965 | 1974 | |
| 1966 | 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 | 1977 | return first.off; |
| 1969 | 1978 | } |
| 1970 | 1979 | |
| 1971 | 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 | 1982 | return last.off + last.len; |
| 1974 | 1983 | } |
| 1975 | 1984 | |