| ... | ... | @@ -79,13 +79,13 @@ entry_addr: ?u32 = null, |
| 79 | 79 | /// We store them here so that we can properly dispose of any allocated |
| 80 | 80 | /// memory within the atom in the incremental linker. |
| 81 | 81 | /// TODO consolidate this. |
| 82 | | decls: std.AutoHashMapUnmanaged(Module.Decl.Index, ?u16) = .{}, |
| 82 | decls: std.AutoHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{}, |
| 83 | 83 | |
| 84 | 84 | /// List of atoms that are either synthetic or map directly to the Zig source program. |
| 85 | | managed_atoms: std.ArrayListUnmanaged(*Atom) = .{}, |
| 85 | atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| 86 | 86 | |
| 87 | 87 | /// Table of atoms indexed by the symbol index. |
| 88 | | atom_by_index_table: std.AutoHashMapUnmanaged(u32, *Atom) = .{}, |
| 88 | atom_by_index_table: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{}, |
| 89 | 89 | |
| 90 | 90 | /// Table of unnamed constants associated with a parent `Decl`. |
| 91 | 91 | /// We store them here so that we can free the constants whenever the `Decl` |
| ... | ... | @@ -124,9 +124,9 @@ const Entry = struct { |
| 124 | 124 | sym_index: u32, |
| 125 | 125 | }; |
| 126 | 126 | |
| 127 | | const RelocTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Relocation)); |
| 128 | | const BaseRelocationTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(u32)); |
| 129 | | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom)); |
| 127 | const RelocTable = std.AutoHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation)); |
| 128 | const BaseRelocationTable = std.AutoHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); |
| 129 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); |
| 130 | 130 | |
| 131 | 131 | const default_file_alignment: u16 = 0x200; |
| 132 | 132 | const default_size_of_stack_reserve: u32 = 0x1000000; |
| ... | ... | @@ -137,7 +137,7 @@ const default_size_of_heap_commit: u32 = 0x1000; |
| 137 | 137 | const Section = struct { |
| 138 | 138 | header: coff.SectionHeader, |
| 139 | 139 | |
| 140 | | last_atom: ?*Atom = null, |
| 140 | last_atom_index: ?Atom.Index = null, |
| 141 | 141 | |
| 142 | 142 | /// A list of atoms that have surplus capacity. This list can have false |
| 143 | 143 | /// positives, as functions grow and shrink over time, only sometimes being added |
| ... | ... | @@ -154,7 +154,34 @@ const Section = struct { |
| 154 | 154 | /// overcapacity can be negative. A simple way to have negative overcapacity is to |
| 155 | 155 | /// allocate a fresh atom, which will have ideal capacity, and then grow it |
| 156 | 156 | /// by 1 byte. It will then have -1 overcapacity. |
| 157 | | free_list: std.ArrayListUnmanaged(*Atom) = .{}, |
| 157 | free_list: std.ArrayListUnmanaged(Atom.Index) = .{}, |
| 158 | }; |
| 159 | |
| 160 | const DeclMetadata = struct { |
| 161 | atom: Atom.Index, |
| 162 | section: u16, |
| 163 | /// A list of all exports aliases of this Decl. |
| 164 | exports: std.ArrayListUnmanaged(u32) = .{}, |
| 165 | |
| 166 | fn getExport(m: DeclMetadata, coff_file: *const Coff, name: []const u8) ?u32 { |
| 167 | for (m.exports.items) |exp| { |
| 168 | if (mem.eql(u8, name, coff_file.getSymbolName(.{ |
| 169 | .sym_index = exp, |
| 170 | .file = null, |
| 171 | }))) return exp; |
| 172 | } |
| 173 | return null; |
| 174 | } |
| 175 | |
| 176 | fn getExportPtr(m: *DeclMetadata, coff_file: *Coff, name: []const u8) ?*u32 { |
| 177 | for (m.exports.items) |*exp| { |
| 178 | if (mem.eql(u8, name, coff_file.getSymbolName(.{ |
| 179 | .sym_index = exp.*, |
| 180 | .file = null, |
| 181 | }))) return exp; |
| 182 | } |
| 183 | return null; |
| 184 | } |
| 158 | 185 | }; |
| 159 | 186 | |
| 160 | 187 | pub const PtrWidth = enum { |
| ... | ... | @@ -170,10 +197,6 @@ pub const PtrWidth = enum { |
| 170 | 197 | }; |
| 171 | 198 | pub const SrcFn = void; |
| 172 | 199 | |
| 173 | | pub const Export = struct { |
| 174 | | sym_index: ?u32 = null, |
| 175 | | }; |
| 176 | | |
| 177 | 200 | pub const SymbolWithLoc = struct { |
| 178 | 201 | // Index into the respective symbol table. |
| 179 | 202 | sym_index: u32, |
| ... | ... | @@ -271,11 +294,7 @@ pub fn deinit(self: *Coff) void { |
| 271 | 294 | } |
| 272 | 295 | self.sections.deinit(gpa); |
| 273 | 296 | |
| 274 | | for (self.managed_atoms.items) |atom| { |
| 275 | | gpa.destroy(atom); |
| 276 | | } |
| 277 | | self.managed_atoms.deinit(gpa); |
| 278 | | |
| 297 | self.atoms.deinit(gpa); |
| 279 | 298 | self.locals.deinit(gpa); |
| 280 | 299 | self.globals.deinit(gpa); |
| 281 | 300 | |
| ... | ... | @@ -297,7 +316,15 @@ pub fn deinit(self: *Coff) void { |
| 297 | 316 | self.imports.deinit(gpa); |
| 298 | 317 | self.imports_free_list.deinit(gpa); |
| 299 | 318 | self.imports_table.deinit(gpa); |
| 300 | | self.decls.deinit(gpa); |
| 319 | |
| 320 | { |
| 321 | var it = self.decls.iterator(); |
| 322 | while (it.next()) |entry| { |
| 323 | entry.value_ptr.exports.deinit(gpa); |
| 324 | } |
| 325 | self.decls.deinit(gpa); |
| 326 | } |
| 327 | |
| 301 | 328 | self.atom_by_index_table.deinit(gpa); |
| 302 | 329 | |
| 303 | 330 | { |
| ... | ... | @@ -461,17 +488,18 @@ fn growSectionVM(self: *Coff, sect_id: u32, needed_size: u32) !void { |
| 461 | 488 | // TODO: enforce order by increasing VM addresses in self.sections container. |
| 462 | 489 | // This is required by the loader anyhow as far as I can tell. |
| 463 | 490 | for (self.sections.items(.header)[sect_id + 1 ..]) |*next_header, next_sect_id| { |
| 464 | | const maybe_last_atom = &self.sections.items(.last_atom)[sect_id + 1 + next_sect_id]; |
| 491 | const maybe_last_atom_index = self.sections.items(.last_atom_index)[sect_id + 1 + next_sect_id]; |
| 465 | 492 | next_header.virtual_address += diff; |
| 466 | 493 | |
| 467 | | if (maybe_last_atom.*) |last_atom| { |
| 468 | | var atom = last_atom; |
| 494 | if (maybe_last_atom_index) |last_atom_index| { |
| 495 | var atom_index = last_atom_index; |
| 469 | 496 | while (true) { |
| 497 | const atom = self.getAtom(atom_index); |
| 470 | 498 | const sym = atom.getSymbolPtr(self); |
| 471 | 499 | sym.value += diff; |
| 472 | 500 | |
| 473 | | if (atom.prev) |prev| { |
| 474 | | atom = prev; |
| 501 | if (atom.prev_index) |prev_index| { |
| 502 | atom_index = prev_index; |
| 475 | 503 | } else break; |
| 476 | 504 | } |
| 477 | 505 | } |
| ... | ... | @@ -480,14 +508,15 @@ fn growSectionVM(self: *Coff, sect_id: u32, needed_size: u32) !void { |
| 480 | 508 | header.virtual_size = increased_size; |
| 481 | 509 | } |
| 482 | 510 | |
| 483 | | fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u32 { |
| 511 | fn allocateAtom(self: *Coff, atom_index: Atom.Index, new_atom_size: u32, alignment: u32) !u32 { |
| 484 | 512 | const tracy = trace(@src()); |
| 485 | 513 | defer tracy.end(); |
| 486 | 514 | |
| 515 | const atom = self.getAtom(atom_index); |
| 487 | 516 | const sect_id = @enumToInt(atom.getSymbol(self).section_number) - 1; |
| 488 | 517 | const header = &self.sections.items(.header)[sect_id]; |
| 489 | 518 | const free_list = &self.sections.items(.free_list)[sect_id]; |
| 490 | | const maybe_last_atom = &self.sections.items(.last_atom)[sect_id]; |
| 519 | const maybe_last_atom_index = &self.sections.items(.last_atom_index)[sect_id]; |
| 491 | 520 | const new_atom_ideal_capacity = if (header.isCode()) padToIdeal(new_atom_size) else new_atom_size; |
| 492 | 521 | |
| 493 | 522 | // We use these to indicate our intention to update metadata, placing the new atom, |
| ... | ... | @@ -495,7 +524,7 @@ fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u |
| 495 | 524 | // It would be simpler to do it inside the for loop below, but that would cause a |
| 496 | 525 | // problem if an error was returned later in the function. So this action |
| 497 | 526 | // is actually carried out at the end of the function, when errors are no longer possible. |
| 498 | | var atom_placement: ?*Atom = null; |
| 527 | var atom_placement: ?Atom.Index = null; |
| 499 | 528 | var free_list_removal: ?usize = null; |
| 500 | 529 | |
| 501 | 530 | // First we look for an appropriately sized free list node. |
| ... | ... | @@ -503,7 +532,8 @@ fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u |
| 503 | 532 | var vaddr = blk: { |
| 504 | 533 | var i: usize = 0; |
| 505 | 534 | while (i < free_list.items.len) { |
| 506 | | const big_atom = free_list.items[i]; |
| 535 | const big_atom_index = free_list.items[i]; |
| 536 | const big_atom = self.getAtom(big_atom_index); |
| 507 | 537 | // We now have a pointer to a live atom that has too much capacity. |
| 508 | 538 | // Is it enough that we could fit this new atom? |
| 509 | 539 | const sym = big_atom.getSymbol(self); |
| ... | ... | @@ -531,34 +561,43 @@ fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u |
| 531 | 561 | const keep_free_list_node = remaining_capacity >= min_text_capacity; |
| 532 | 562 | |
| 533 | 563 | // Set up the metadata to be updated, after errors are no longer possible. |
| 534 | | atom_placement = big_atom; |
| 564 | atom_placement = big_atom_index; |
| 535 | 565 | if (!keep_free_list_node) { |
| 536 | 566 | free_list_removal = i; |
| 537 | 567 | } |
| 538 | 568 | break :blk new_start_vaddr; |
| 539 | | } else if (maybe_last_atom.*) |last| { |
| 569 | } else if (maybe_last_atom_index.*) |last_index| { |
| 570 | const last = self.getAtom(last_index); |
| 540 | 571 | const last_symbol = last.getSymbol(self); |
| 541 | 572 | const ideal_capacity = if (header.isCode()) padToIdeal(last.size) else last.size; |
| 542 | 573 | const ideal_capacity_end_vaddr = last_symbol.value + ideal_capacity; |
| 543 | 574 | const new_start_vaddr = mem.alignForwardGeneric(u32, ideal_capacity_end_vaddr, alignment); |
| 544 | | atom_placement = last; |
| 575 | atom_placement = last_index; |
| 545 | 576 | break :blk new_start_vaddr; |
| 546 | 577 | } else { |
| 547 | 578 | break :blk mem.alignForwardGeneric(u32, header.virtual_address, alignment); |
| 548 | 579 | } |
| 549 | 580 | }; |
| 550 | 581 | |
| 551 | | const expand_section = atom_placement == null or atom_placement.?.next == null; |
| 582 | const expand_section = if (atom_placement) |placement_index| |
| 583 | self.getAtom(placement_index).next_index == null |
| 584 | else |
| 585 | true; |
| 552 | 586 | if (expand_section) { |
| 553 | 587 | const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); |
| 554 | 588 | const needed_size: u32 = (vaddr + new_atom_size) - header.virtual_address; |
| 555 | 589 | if (needed_size > sect_capacity) { |
| 556 | 590 | const new_offset = self.findFreeSpace(needed_size, default_file_alignment); |
| 557 | | const current_size = if (maybe_last_atom.*) |last_atom| blk: { |
| 591 | const current_size = if (maybe_last_atom_index.*) |last_atom_index| blk: { |
| 592 | const last_atom = self.getAtom(last_atom_index); |
| 558 | 593 | const sym = last_atom.getSymbol(self); |
| 559 | 594 | break :blk (sym.value + last_atom.size) - header.virtual_address; |
| 560 | 595 | } else 0; |
| 561 | | log.debug("moving {s} from 0x{x} to 0x{x}", .{ self.getSectionName(header), header.pointer_to_raw_data, new_offset }); |
| 596 | log.debug("moving {s} from 0x{x} to 0x{x}", .{ |
| 597 | self.getSectionName(header), |
| 598 | header.pointer_to_raw_data, |
| 599 | new_offset, |
| 600 | }); |
| 562 | 601 | const amt = try self.base.file.?.copyRangeAll( |
| 563 | 602 | header.pointer_to_raw_data, |
| 564 | 603 | self.base.file.?, |
| ... | ... | @@ -577,26 +616,34 @@ fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u |
| 577 | 616 | |
| 578 | 617 | header.virtual_size = @max(header.virtual_size, needed_size); |
| 579 | 618 | header.size_of_raw_data = needed_size; |
| 580 | | maybe_last_atom.* = atom; |
| 619 | maybe_last_atom_index.* = atom_index; |
| 581 | 620 | } |
| 582 | 621 | |
| 583 | | atom.size = new_atom_size; |
| 584 | | atom.alignment = alignment; |
| 622 | { |
| 623 | const atom_ptr = self.getAtomPtr(atom_index); |
| 624 | atom_ptr.size = new_atom_size; |
| 625 | atom_ptr.alignment = alignment; |
| 626 | } |
| 585 | 627 | |
| 586 | | if (atom.prev) |prev| { |
| 587 | | prev.next = atom.next; |
| 628 | if (atom.prev_index) |prev_index| { |
| 629 | const prev = self.getAtomPtr(prev_index); |
| 630 | prev.next_index = atom.next_index; |
| 588 | 631 | } |
| 589 | | if (atom.next) |next| { |
| 590 | | next.prev = atom.prev; |
| 632 | if (atom.next_index) |next_index| { |
| 633 | const next = self.getAtomPtr(next_index); |
| 634 | next.prev_index = atom.prev_index; |
| 591 | 635 | } |
| 592 | 636 | |
| 593 | | if (atom_placement) |big_atom| { |
| 594 | | atom.prev = big_atom; |
| 595 | | atom.next = big_atom.next; |
| 596 | | big_atom.next = atom; |
| 637 | if (atom_placement) |big_atom_index| { |
| 638 | const big_atom = self.getAtomPtr(big_atom_index); |
| 639 | const atom_ptr = self.getAtomPtr(atom_index); |
| 640 | atom_ptr.prev_index = big_atom_index; |
| 641 | atom_ptr.next_index = big_atom.next_index; |
| 642 | big_atom.next_index = atom_index; |
| 597 | 643 | } else { |
| 598 | | atom.prev = null; |
| 599 | | atom.next = null; |
| 644 | const atom_ptr = self.getAtomPtr(atom_index); |
| 645 | atom_ptr.prev_index = null; |
| 646 | atom_ptr.next_index = null; |
| 600 | 647 | } |
| 601 | 648 | if (free_list_removal) |i| { |
| 602 | 649 | _ = free_list.swapRemove(i); |
| ... | ... | @@ -701,24 +748,37 @@ pub fn allocateImportEntry(self: *Coff, target: SymbolWithLoc) !u32 { |
| 701 | 748 | return index; |
| 702 | 749 | } |
| 703 | 750 | |
| 704 | | fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom { |
| 751 | pub fn createAtom(self: *Coff) !Atom.Index { |
| 705 | 752 | const gpa = self.base.allocator; |
| 706 | | const atom = try gpa.create(Atom); |
| 707 | | errdefer gpa.destroy(atom); |
| 708 | | atom.* = Atom.empty; |
| 709 | | try atom.ensureInitialized(self); |
| 753 | const atom_index = @intCast(Atom.Index, self.atoms.items.len); |
| 754 | const atom = try self.atoms.addOne(gpa); |
| 755 | const sym_index = try self.allocateSymbol(); |
| 756 | try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index); |
| 757 | atom.* = .{ |
| 758 | .sym_index = sym_index, |
| 759 | .file = null, |
| 760 | .size = 0, |
| 761 | .alignment = 0, |
| 762 | .prev_index = null, |
| 763 | .next_index = null, |
| 764 | }; |
| 765 | log.debug("creating ATOM(%{d}) at index {d}", .{ sym_index, atom_index }); |
| 766 | return atom_index; |
| 767 | } |
| 768 | |
| 769 | fn createGotAtom(self: *Coff, target: SymbolWithLoc) !Atom.Index { |
| 770 | const atom_index = try self.createAtom(); |
| 771 | const atom = self.getAtomPtr(atom_index); |
| 710 | 772 | atom.size = @sizeOf(u64); |
| 711 | 773 | atom.alignment = @alignOf(u64); |
| 712 | 774 | |
| 713 | | try self.managed_atoms.append(gpa, atom); |
| 714 | | |
| 715 | 775 | const sym = atom.getSymbolPtr(self); |
| 716 | 776 | sym.section_number = @intToEnum(coff.SectionNumber, self.got_section_index.? + 1); |
| 717 | | sym.value = try self.allocateAtom(atom, atom.size, atom.alignment); |
| 777 | sym.value = try self.allocateAtom(atom_index, atom.size, atom.alignment); |
| 718 | 778 | |
| 719 | 779 | log.debug("allocated GOT atom at 0x{x}", .{sym.value}); |
| 720 | 780 | |
| 721 | | try atom.addRelocation(self, .{ |
| 781 | try Atom.addRelocation(self, atom_index, .{ |
| 722 | 782 | .type = .direct, |
| 723 | 783 | .target = target, |
| 724 | 784 | .offset = 0, |
| ... | ... | @@ -732,49 +792,46 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom { |
| 732 | 792 | .UNDEFINED => @panic("TODO generate a binding for undefined GOT target"), |
| 733 | 793 | .ABSOLUTE => {}, |
| 734 | 794 | .DEBUG => unreachable, // not possible |
| 735 | | else => try atom.addBaseRelocation(self, 0), |
| 795 | else => try Atom.addBaseRelocation(self, atom_index, 0), |
| 736 | 796 | } |
| 737 | 797 | |
| 738 | | return atom; |
| 798 | return atom_index; |
| 739 | 799 | } |
| 740 | 800 | |
| 741 | | fn createImportAtom(self: *Coff) !*Atom { |
| 742 | | const gpa = self.base.allocator; |
| 743 | | const atom = try gpa.create(Atom); |
| 744 | | errdefer gpa.destroy(atom); |
| 745 | | atom.* = Atom.empty; |
| 746 | | try atom.ensureInitialized(self); |
| 801 | fn createImportAtom(self: *Coff) !Atom.Index { |
| 802 | const atom_index = try self.createAtom(); |
| 803 | const atom = self.getAtomPtr(atom_index); |
| 747 | 804 | atom.size = @sizeOf(u64); |
| 748 | 805 | atom.alignment = @alignOf(u64); |
| 749 | 806 | |
| 750 | | try self.managed_atoms.append(gpa, atom); |
| 751 | | |
| 752 | 807 | const sym = atom.getSymbolPtr(self); |
| 753 | 808 | sym.section_number = @intToEnum(coff.SectionNumber, self.idata_section_index.? + 1); |
| 754 | | sym.value = try self.allocateAtom(atom, atom.size, atom.alignment); |
| 809 | sym.value = try self.allocateAtom(atom_index, atom.size, atom.alignment); |
| 755 | 810 | |
| 756 | 811 | log.debug("allocated import atom at 0x{x}", .{sym.value}); |
| 757 | 812 | |
| 758 | | return atom; |
| 813 | return atom_index; |
| 759 | 814 | } |
| 760 | 815 | |
| 761 | | fn growAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u32 { |
| 816 | fn growAtom(self: *Coff, atom_index: Atom.Index, new_atom_size: u32, alignment: u32) !u32 { |
| 817 | const atom = self.getAtom(atom_index); |
| 762 | 818 | const sym = atom.getSymbol(self); |
| 763 | 819 | const align_ok = mem.alignBackwardGeneric(u32, sym.value, alignment) == sym.value; |
| 764 | 820 | const need_realloc = !align_ok or new_atom_size > atom.capacity(self); |
| 765 | 821 | if (!need_realloc) return sym.value; |
| 766 | | return self.allocateAtom(atom, new_atom_size, alignment); |
| 822 | return self.allocateAtom(atom_index, new_atom_size, alignment); |
| 767 | 823 | } |
| 768 | 824 | |
| 769 | | fn shrinkAtom(self: *Coff, atom: *Atom, new_block_size: u32) void { |
| 825 | fn shrinkAtom(self: *Coff, atom_index: Atom.Index, new_block_size: u32) void { |
| 770 | 826 | _ = self; |
| 771 | | _ = atom; |
| 827 | _ = atom_index; |
| 772 | 828 | _ = new_block_size; |
| 773 | 829 | // TODO check the new capacity, and if it crosses the size threshold into a big enough |
| 774 | 830 | // capacity, insert a free list node for it. |
| 775 | 831 | } |
| 776 | 832 | |
| 777 | | fn writeAtom(self: *Coff, atom: *Atom, code: []const u8) !void { |
| 833 | fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []const u8) !void { |
| 834 | const atom = self.getAtom(atom_index); |
| 778 | 835 | const sym = atom.getSymbol(self); |
| 779 | 836 | const section = self.sections.get(@enumToInt(sym.section_number) - 1); |
| 780 | 837 | const file_offset = section.header.pointer_to_raw_data + sym.value - section.header.virtual_address; |
| ... | ... | @@ -784,18 +841,18 @@ fn writeAtom(self: *Coff, atom: *Atom, code: []const u8) !void { |
| 784 | 841 | file_offset + code.len, |
| 785 | 842 | }); |
| 786 | 843 | try self.base.file.?.pwriteAll(code, file_offset); |
| 787 | | try self.resolveRelocs(atom); |
| 844 | try self.resolveRelocs(atom_index); |
| 788 | 845 | } |
| 789 | 846 | |
| 790 | | fn writePtrWidthAtom(self: *Coff, atom: *Atom) !void { |
| 847 | fn writePtrWidthAtom(self: *Coff, atom_index: Atom.Index) !void { |
| 791 | 848 | switch (self.ptr_width) { |
| 792 | 849 | .p32 => { |
| 793 | 850 | var buffer: [@sizeOf(u32)]u8 = [_]u8{0} ** @sizeOf(u32); |
| 794 | | try self.writeAtom(atom, &buffer); |
| 851 | try self.writeAtom(atom_index, &buffer); |
| 795 | 852 | }, |
| 796 | 853 | .p64 => { |
| 797 | 854 | var buffer: [@sizeOf(u64)]u8 = [_]u8{0} ** @sizeOf(u64); |
| 798 | | try self.writeAtom(atom, &buffer); |
| 855 | try self.writeAtom(atom_index, &buffer); |
| 799 | 856 | }, |
| 800 | 857 | } |
| 801 | 858 | } |
| ... | ... | @@ -815,7 +872,8 @@ fn markRelocsDirtyByAddress(self: *Coff, addr: u32) void { |
| 815 | 872 | var it = self.relocs.valueIterator(); |
| 816 | 873 | while (it.next()) |relocs| { |
| 817 | 874 | for (relocs.items) |*reloc| { |
| 818 | | const target_atom = reloc.getTargetAtom(self) orelse continue; |
| 875 | const target_atom_index = reloc.getTargetAtomIndex(self) orelse continue; |
| 876 | const target_atom = self.getAtom(target_atom_index); |
| 819 | 877 | const target_sym = target_atom.getSymbol(self); |
| 820 | 878 | if (target_sym.value < addr) continue; |
| 821 | 879 | reloc.dirty = true; |
| ... | ... | @@ -823,24 +881,26 @@ fn markRelocsDirtyByAddress(self: *Coff, addr: u32) void { |
| 823 | 881 | } |
| 824 | 882 | } |
| 825 | 883 | |
| 826 | | fn resolveRelocs(self: *Coff, atom: *Atom) !void { |
| 827 | | const relocs = self.relocs.get(atom) orelse return; |
| 884 | fn resolveRelocs(self: *Coff, atom_index: Atom.Index) !void { |
| 885 | const relocs = self.relocs.get(atom_index) orelse return; |
| 828 | 886 | |
| 829 | | log.debug("relocating '{s}'", .{atom.getName(self)}); |
| 887 | log.debug("relocating '{s}'", .{self.getAtom(atom_index).getName(self)}); |
| 830 | 888 | |
| 831 | 889 | for (relocs.items) |*reloc| { |
| 832 | 890 | if (!reloc.dirty) continue; |
| 833 | | try reloc.resolve(atom, self); |
| 891 | try reloc.resolve(atom_index, self); |
| 834 | 892 | } |
| 835 | 893 | } |
| 836 | 894 | |
| 837 | | fn freeAtom(self: *Coff, atom: *Atom) void { |
| 838 | | log.debug("freeAtom {*}", .{atom}); |
| 895 | fn freeAtom(self: *Coff, atom_index: Atom.Index) void { |
| 896 | log.debug("freeAtom {d}", .{atom_index}); |
| 897 | |
| 898 | const gpa = self.base.allocator; |
| 839 | 899 | |
| 840 | 900 | // Remove any relocs and base relocs associated with this Atom |
| 841 | | self.freeRelocationsForAtom(atom); |
| 901 | Atom.freeRelocations(self, atom_index); |
| 842 | 902 | |
| 843 | | const gpa = self.base.allocator; |
| 903 | const atom = self.getAtom(atom_index); |
| 844 | 904 | const sym = atom.getSymbol(self); |
| 845 | 905 | const sect_id = @enumToInt(sym.section_number) - 1; |
| 846 | 906 | const free_list = &self.sections.items(.free_list)[sect_id]; |
| ... | ... | @@ -849,45 +909,46 @@ fn freeAtom(self: *Coff, atom: *Atom) void { |
| 849 | 909 | var i: usize = 0; |
| 850 | 910 | // TODO turn free_list into a hash map |
| 851 | 911 | while (i < free_list.items.len) { |
| 852 | | if (free_list.items[i] == atom) { |
| 912 | if (free_list.items[i] == atom_index) { |
| 853 | 913 | _ = free_list.swapRemove(i); |
| 854 | 914 | continue; |
| 855 | 915 | } |
| 856 | | if (free_list.items[i] == atom.prev) { |
| 916 | if (free_list.items[i] == atom.prev_index) { |
| 857 | 917 | already_have_free_list_node = true; |
| 858 | 918 | } |
| 859 | 919 | i += 1; |
| 860 | 920 | } |
| 861 | 921 | } |
| 862 | 922 | |
| 863 | | const maybe_last_atom = &self.sections.items(.last_atom)[sect_id]; |
| 864 | | if (maybe_last_atom.*) |last_atom| { |
| 865 | | if (last_atom == atom) { |
| 866 | | if (atom.prev) |prev| { |
| 923 | const maybe_last_atom_index = &self.sections.items(.last_atom_index)[sect_id]; |
| 924 | if (maybe_last_atom_index.*) |last_atom_index| { |
| 925 | if (last_atom_index == atom_index) { |
| 926 | if (atom.prev_index) |prev_index| { |
| 867 | 927 | // TODO shrink the section size here |
| 868 | | maybe_last_atom.* = prev; |
| 928 | maybe_last_atom_index.* = prev_index; |
| 869 | 929 | } else { |
| 870 | | maybe_last_atom.* = null; |
| 930 | maybe_last_atom_index.* = null; |
| 871 | 931 | } |
| 872 | 932 | } |
| 873 | 933 | } |
| 874 | 934 | |
| 875 | | if (atom.prev) |prev| { |
| 876 | | prev.next = atom.next; |
| 935 | if (atom.prev_index) |prev_index| { |
| 936 | const prev = self.getAtomPtr(prev_index); |
| 937 | prev.next_index = atom.next_index; |
| 877 | 938 | |
| 878 | | if (!already_have_free_list_node and prev.freeListEligible(self)) { |
| 939 | if (!already_have_free_list_node and prev.*.freeListEligible(self)) { |
| 879 | 940 | // The free list is heuristics, it doesn't have to be perfect, so we can |
| 880 | 941 | // ignore the OOM here. |
| 881 | | free_list.append(gpa, prev) catch {}; |
| 942 | free_list.append(gpa, prev_index) catch {}; |
| 882 | 943 | } |
| 883 | 944 | } else { |
| 884 | | atom.prev = null; |
| 945 | self.getAtomPtr(atom_index).prev_index = null; |
| 885 | 946 | } |
| 886 | 947 | |
| 887 | | if (atom.next) |next| { |
| 888 | | next.prev = atom.prev; |
| 948 | if (atom.next_index) |next_index| { |
| 949 | self.getAtomPtr(next_index).prev_index = atom.prev_index; |
| 889 | 950 | } else { |
| 890 | | atom.next = null; |
| 951 | self.getAtomPtr(atom_index).next_index = null; |
| 891 | 952 | } |
| 892 | 953 | |
| 893 | 954 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| ... | ... | @@ -910,7 +971,7 @@ fn freeAtom(self: *Coff, atom: *Atom) void { |
| 910 | 971 | self.locals.items[sym_index].section_number = .UNDEFINED; |
| 911 | 972 | _ = self.atom_by_index_table.remove(sym_index); |
| 912 | 973 | log.debug(" adding local symbol index {d} to free list", .{sym_index}); |
| 913 | | atom.sym_index = 0; |
| 974 | self.getAtomPtr(atom_index).sym_index = 0; |
| 914 | 975 | } |
| 915 | 976 | |
| 916 | 977 | pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { |
| ... | ... | @@ -927,15 +988,10 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live |
| 927 | 988 | |
| 928 | 989 | const decl_index = func.owner_decl; |
| 929 | 990 | const decl = module.declPtr(decl_index); |
| 930 | | const atom = &decl.link.coff; |
| 931 | | try atom.ensureInitialized(self); |
| 932 | | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); |
| 933 | | if (gop.found_existing) { |
| 934 | | self.freeUnnamedConsts(decl_index); |
| 935 | | self.freeRelocationsForAtom(&decl.link.coff); |
| 936 | | } else { |
| 937 | | gop.value_ptr.* = null; |
| 938 | | } |
| 991 | |
| 992 | const atom_index = try self.getOrCreateAtomForDecl(decl_index); |
| 993 | self.freeUnnamedConsts(decl_index); |
| 994 | Atom.freeRelocations(self, atom_index); |
| 939 | 995 | |
| 940 | 996 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 941 | 997 | defer code_buffer.deinit(); |
| ... | ... | @@ -979,11 +1035,8 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In |
| 979 | 1035 | } |
| 980 | 1036 | const unnamed_consts = gop.value_ptr; |
| 981 | 1037 | |
| 982 | | const atom = try gpa.create(Atom); |
| 983 | | errdefer gpa.destroy(atom); |
| 984 | | atom.* = Atom.empty; |
| 985 | | try atom.ensureInitialized(self); |
| 986 | | try self.managed_atoms.append(gpa, atom); |
| 1038 | const atom_index = try self.createAtom(); |
| 1039 | const atom = self.getAtomPtr(atom_index); |
| 987 | 1040 | |
| 988 | 1041 | const sym_name = blk: { |
| 989 | 1042 | const decl_name = try decl.getFullyQualifiedName(mod); |
| ... | ... | @@ -1012,15 +1065,15 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In |
| 1012 | 1065 | const required_alignment = tv.ty.abiAlignment(self.base.options.target); |
| 1013 | 1066 | atom.alignment = required_alignment; |
| 1014 | 1067 | atom.size = @intCast(u32, code.len); |
| 1015 | | atom.getSymbolPtr(self).value = try self.allocateAtom(atom, atom.size, atom.alignment); |
| 1016 | | errdefer self.freeAtom(atom); |
| 1068 | atom.getSymbolPtr(self).value = try self.allocateAtom(atom_index, atom.size, atom.alignment); |
| 1069 | errdefer self.freeAtom(atom_index); |
| 1017 | 1070 | |
| 1018 | | try unnamed_consts.append(gpa, atom); |
| 1071 | try unnamed_consts.append(gpa, atom_index); |
| 1019 | 1072 | |
| 1020 | 1073 | log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, atom.getSymbol(self).value }); |
| 1021 | 1074 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 1022 | 1075 | |
| 1023 | | try self.writeAtom(atom, code); |
| 1076 | try self.writeAtom(atom_index, code); |
| 1024 | 1077 | |
| 1025 | 1078 | return atom.getSymbolIndex().?; |
| 1026 | 1079 | } |
| ... | ... | @@ -1047,14 +1100,9 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) ! |
| 1047 | 1100 | } |
| 1048 | 1101 | } |
| 1049 | 1102 | |
| 1050 | | const atom = &decl.link.coff; |
| 1051 | | try atom.ensureInitialized(self); |
| 1052 | | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); |
| 1053 | | if (gop.found_existing) { |
| 1054 | | self.freeRelocationsForAtom(atom); |
| 1055 | | } else { |
| 1056 | | gop.value_ptr.* = null; |
| 1057 | | } |
| 1103 | const atom_index = try self.getOrCreateAtomForDecl(decl_index); |
| 1104 | Atom.freeRelocations(self, atom_index); |
| 1105 | const atom = self.getAtom(atom_index); |
| 1058 | 1106 | |
| 1059 | 1107 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 1060 | 1108 | defer code_buffer.deinit(); |
| ... | ... | @@ -1064,7 +1112,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) ! |
| 1064 | 1112 | .ty = decl.ty, |
| 1065 | 1113 | .val = decl_val, |
| 1066 | 1114 | }, &code_buffer, .none, .{ |
| 1067 | | .parent_atom_index = decl.link.coff.getSymbolIndex().?, |
| 1115 | .parent_atom_index = atom.getSymbolIndex().?, |
| 1068 | 1116 | }); |
| 1069 | 1117 | const code = switch (res) { |
| 1070 | 1118 | .ok => code_buffer.items, |
| ... | ... | @@ -1082,7 +1130,20 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) ! |
| 1082 | 1130 | return self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index)); |
| 1083 | 1131 | } |
| 1084 | 1132 | |
| 1085 | | fn getDeclOutputSection(self: *Coff, decl: *Module.Decl) u16 { |
| 1133 | pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: Module.Decl.Index) !Atom.Index { |
| 1134 | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); |
| 1135 | if (!gop.found_existing) { |
| 1136 | gop.value_ptr.* = .{ |
| 1137 | .atom = try self.createAtom(), |
| 1138 | .section = self.getDeclOutputSection(decl_index), |
| 1139 | .exports = .{}, |
| 1140 | }; |
| 1141 | } |
| 1142 | return gop.value_ptr.atom; |
| 1143 | } |
| 1144 | |
| 1145 | fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 { |
| 1146 | const decl = self.base.options.module.?.declPtr(decl_index); |
| 1086 | 1147 | const ty = decl.ty; |
| 1087 | 1148 | const zig_ty = ty.zigTypeTag(); |
| 1088 | 1149 | const val = decl.val; |
| ... | ... | @@ -1117,14 +1178,11 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, |
| 1117 | 1178 | log.debug("updateDeclCode {s}{*}", .{ decl_name, decl }); |
| 1118 | 1179 | const required_alignment = decl.getAlignment(self.base.options.target); |
| 1119 | 1180 | |
| 1120 | | const decl_ptr = self.decls.getPtr(decl_index).?; |
| 1121 | | if (decl_ptr.* == null) { |
| 1122 | | decl_ptr.* = self.getDeclOutputSection(decl); |
| 1123 | | } |
| 1124 | | const sect_index = decl_ptr.*.?; |
| 1125 | | |
| 1181 | const decl_metadata = self.decls.get(decl_index).?; |
| 1182 | const atom_index = decl_metadata.atom; |
| 1183 | const atom = self.getAtom(atom_index); |
| 1184 | const sect_index = decl_metadata.section; |
| 1126 | 1185 | const code_len = @intCast(u32, code.len); |
| 1127 | | const atom = &decl.link.coff; |
| 1128 | 1186 | |
| 1129 | 1187 | if (atom.size != 0) { |
| 1130 | 1188 | const sym = atom.getSymbolPtr(self); |
| ... | ... | @@ -1135,7 +1193,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, |
| 1135 | 1193 | const capacity = atom.capacity(self); |
| 1136 | 1194 | const need_realloc = code.len > capacity or !mem.isAlignedGeneric(u64, sym.value, required_alignment); |
| 1137 | 1195 | if (need_realloc) { |
| 1138 | | const vaddr = try self.growAtom(atom, code_len, required_alignment); |
| 1196 | const vaddr = try self.growAtom(atom_index, code_len, required_alignment); |
| 1139 | 1197 | log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, sym.value, vaddr }); |
| 1140 | 1198 | log.debug(" (required alignment 0x{x}", .{required_alignment}); |
| 1141 | 1199 | |
| ... | ... | @@ -1143,49 +1201,43 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, |
| 1143 | 1201 | sym.value = vaddr; |
| 1144 | 1202 | log.debug(" (updating GOT entry)", .{}); |
| 1145 | 1203 | const got_target = SymbolWithLoc{ .sym_index = atom.getSymbolIndex().?, .file = null }; |
| 1146 | | const got_atom = self.getGotAtomForSymbol(got_target).?; |
| 1204 | const got_atom_index = self.getGotAtomIndexForSymbol(got_target).?; |
| 1147 | 1205 | self.markRelocsDirtyByTarget(got_target); |
| 1148 | | try self.writePtrWidthAtom(got_atom); |
| 1206 | try self.writePtrWidthAtom(got_atom_index); |
| 1149 | 1207 | } |
| 1150 | 1208 | } else if (code_len < atom.size) { |
| 1151 | | self.shrinkAtom(atom, code_len); |
| 1209 | self.shrinkAtom(atom_index, code_len); |
| 1152 | 1210 | } |
| 1153 | | atom.size = code_len; |
| 1211 | self.getAtomPtr(atom_index).size = code_len; |
| 1154 | 1212 | } else { |
| 1155 | 1213 | const sym = atom.getSymbolPtr(self); |
| 1156 | 1214 | try self.setSymbolName(sym, decl_name); |
| 1157 | 1215 | sym.section_number = @intToEnum(coff.SectionNumber, sect_index + 1); |
| 1158 | 1216 | sym.type = .{ .complex_type = complex_type, .base_type = .NULL }; |
| 1159 | 1217 | |
| 1160 | | const vaddr = try self.allocateAtom(atom, code_len, required_alignment); |
| 1161 | | errdefer self.freeAtom(atom); |
| 1218 | const vaddr = try self.allocateAtom(atom_index, code_len, required_alignment); |
| 1219 | errdefer self.freeAtom(atom_index); |
| 1162 | 1220 | log.debug("allocated atom for {s} at 0x{x}", .{ decl_name, vaddr }); |
| 1163 | | atom.size = code_len; |
| 1221 | self.getAtomPtr(atom_index).size = code_len; |
| 1164 | 1222 | sym.value = vaddr; |
| 1165 | 1223 | |
| 1166 | 1224 | const got_target = SymbolWithLoc{ .sym_index = atom.getSymbolIndex().?, .file = null }; |
| 1167 | 1225 | const got_index = try self.allocateGotEntry(got_target); |
| 1168 | | const got_atom = try self.createGotAtom(got_target); |
| 1226 | const got_atom_index = try self.createGotAtom(got_target); |
| 1227 | const got_atom = self.getAtom(got_atom_index); |
| 1169 | 1228 | self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?; |
| 1170 | | try self.writePtrWidthAtom(got_atom); |
| 1229 | try self.writePtrWidthAtom(got_atom_index); |
| 1171 | 1230 | } |
| 1172 | 1231 | |
| 1173 | 1232 | self.markRelocsDirtyByTarget(atom.getSymbolWithLoc()); |
| 1174 | | try self.writeAtom(atom, code); |
| 1175 | | } |
| 1176 | | |
| 1177 | | fn freeRelocationsForAtom(self: *Coff, atom: *Atom) void { |
| 1178 | | var removed_relocs = self.relocs.fetchRemove(atom); |
| 1179 | | if (removed_relocs) |*relocs| relocs.value.deinit(self.base.allocator); |
| 1180 | | var removed_base_relocs = self.base_relocs.fetchRemove(atom); |
| 1181 | | if (removed_base_relocs) |*base_relocs| base_relocs.value.deinit(self.base.allocator); |
| 1233 | try self.writeAtom(atom_index, code); |
| 1182 | 1234 | } |
| 1183 | 1235 | |
| 1184 | 1236 | fn freeUnnamedConsts(self: *Coff, decl_index: Module.Decl.Index) void { |
| 1185 | 1237 | const gpa = self.base.allocator; |
| 1186 | 1238 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; |
| 1187 | | for (unnamed_consts.items) |atom| { |
| 1188 | | self.freeAtom(atom); |
| 1239 | for (unnamed_consts.items) |atom_index| { |
| 1240 | self.freeAtom(atom_index); |
| 1189 | 1241 | } |
| 1190 | 1242 | unnamed_consts.clearAndFree(gpa); |
| 1191 | 1243 | } |
| ... | ... | @@ -1200,11 +1252,11 @@ pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void { |
| 1200 | 1252 | |
| 1201 | 1253 | log.debug("freeDecl {*}", .{decl}); |
| 1202 | 1254 | |
| 1203 | | if (self.decls.fetchRemove(decl_index)) |kv| { |
| 1204 | | if (kv.value) |_| { |
| 1205 | | self.freeAtom(&decl.link.coff); |
| 1206 | | self.freeUnnamedConsts(decl_index); |
| 1207 | | } |
| 1255 | if (self.decls.fetchRemove(decl_index)) |const_kv| { |
| 1256 | var kv = const_kv; |
| 1257 | self.freeAtom(kv.value.atom); |
| 1258 | self.freeUnnamedConsts(decl_index); |
| 1259 | kv.value.exports.deinit(self.base.allocator); |
| 1208 | 1260 | } |
| 1209 | 1261 | } |
| 1210 | 1262 | |
| ... | ... | @@ -1257,16 +1309,10 @@ pub fn updateDeclExports( |
| 1257 | 1309 | const gpa = self.base.allocator; |
| 1258 | 1310 | |
| 1259 | 1311 | const decl = module.declPtr(decl_index); |
| 1260 | | const atom = &decl.link.coff; |
| 1261 | | |
| 1262 | | if (atom.getSymbolIndex() == null) return; |
| 1263 | | |
| 1264 | | const gop = try self.decls.getOrPut(gpa, decl_index); |
| 1265 | | if (!gop.found_existing) { |
| 1266 | | gop.value_ptr.* = self.getDeclOutputSection(decl); |
| 1267 | | } |
| 1268 | | |
| 1312 | const atom_index = try self.getOrCreateAtomForDecl(decl_index); |
| 1313 | const atom = self.getAtom(atom_index); |
| 1269 | 1314 | const decl_sym = atom.getSymbol(self); |
| 1315 | const decl_metadata = self.decls.getPtr(decl_index).?; |
| 1270 | 1316 | |
| 1271 | 1317 | for (exports) |exp| { |
| 1272 | 1318 | log.debug("adding new export '{s}'", .{exp.options.name}); |
| ... | ... | @@ -1301,9 +1347,9 @@ pub fn updateDeclExports( |
| 1301 | 1347 | continue; |
| 1302 | 1348 | } |
| 1303 | 1349 | |
| 1304 | | const sym_index = exp.link.coff.sym_index orelse blk: { |
| 1350 | const sym_index = decl_metadata.getExport(self, exp.options.name) orelse blk: { |
| 1305 | 1351 | const sym_index = try self.allocateSymbol(); |
| 1306 | | exp.link.coff.sym_index = sym_index; |
| 1352 | try decl_metadata.exports.append(gpa, sym_index); |
| 1307 | 1353 | break :blk sym_index; |
| 1308 | 1354 | }; |
| 1309 | 1355 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null }; |
| ... | ... | @@ -1326,16 +1372,15 @@ pub fn updateDeclExports( |
| 1326 | 1372 | } |
| 1327 | 1373 | } |
| 1328 | 1374 | |
| 1329 | | pub fn deleteExport(self: *Coff, exp: Export) void { |
| 1375 | pub fn deleteDeclExport(self: *Coff, decl_index: Module.Decl.Index, name: []const u8) void { |
| 1330 | 1376 | if (self.llvm_object) |_| return; |
| 1331 | | const sym_index = exp.sym_index orelse return; |
| 1377 | const metadata = self.decls.getPtr(decl_index) orelse return; |
| 1378 | const sym_index = metadata.getExportPtr(self, name) orelse return; |
| 1332 | 1379 | |
| 1333 | 1380 | const gpa = self.base.allocator; |
| 1334 | | |
| 1335 | | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null }; |
| 1381 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index.*, .file = null }; |
| 1336 | 1382 | const sym = self.getSymbolPtr(sym_loc); |
| 1337 | | const sym_name = self.getSymbolName(sym_loc); |
| 1338 | | log.debug("deleting export '{s}'", .{sym_name}); |
| 1383 | log.debug("deleting export '{s}'", .{name}); |
| 1339 | 1384 | assert(sym.storage_class == .EXTERNAL and sym.section_number != .UNDEFINED); |
| 1340 | 1385 | sym.* = .{ |
| 1341 | 1386 | .name = [_]u8{0} ** 8, |
| ... | ... | @@ -1345,9 +1390,9 @@ pub fn deleteExport(self: *Coff, exp: Export) void { |
| 1345 | 1390 | .storage_class = .NULL, |
| 1346 | 1391 | .number_of_aux_symbols = 0, |
| 1347 | 1392 | }; |
| 1348 | | self.locals_free_list.append(gpa, sym_index) catch {}; |
| 1393 | self.locals_free_list.append(gpa, sym_index.*) catch {}; |
| 1349 | 1394 | |
| 1350 | | if (self.resolver.fetchRemove(sym_name)) |entry| { |
| 1395 | if (self.resolver.fetchRemove(name)) |entry| { |
| 1351 | 1396 | defer gpa.free(entry.key); |
| 1352 | 1397 | self.globals_free_list.append(gpa, entry.value) catch {}; |
| 1353 | 1398 | self.globals.items[entry.value] = .{ |
| ... | ... | @@ -1355,6 +1400,8 @@ pub fn deleteExport(self: *Coff, exp: Export) void { |
| 1355 | 1400 | .file = null, |
| 1356 | 1401 | }; |
| 1357 | 1402 | } |
| 1403 | |
| 1404 | sym_index.* = 0; |
| 1358 | 1405 | } |
| 1359 | 1406 | |
| 1360 | 1407 | fn resolveGlobalSymbol(self: *Coff, current: SymbolWithLoc) !void { |
| ... | ... | @@ -1419,9 +1466,10 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod |
| 1419 | 1466 | if (self.imports_table.contains(global)) continue; |
| 1420 | 1467 | |
| 1421 | 1468 | const import_index = try self.allocateImportEntry(global); |
| 1422 | | const import_atom = try self.createImportAtom(); |
| 1469 | const import_atom_index = try self.createImportAtom(); |
| 1470 | const import_atom = self.getAtom(import_atom_index); |
| 1423 | 1471 | self.imports.items[import_index].sym_index = import_atom.getSymbolIndex().?; |
| 1424 | | try self.writePtrWidthAtom(import_atom); |
| 1472 | try self.writePtrWidthAtom(import_atom_index); |
| 1425 | 1473 | } |
| 1426 | 1474 | |
| 1427 | 1475 | if (build_options.enable_logging) { |
| ... | ... | @@ -1455,22 +1503,14 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod |
| 1455 | 1503 | } |
| 1456 | 1504 | } |
| 1457 | 1505 | |
| 1458 | | pub fn getDeclVAddr( |
| 1459 | | self: *Coff, |
| 1460 | | decl_index: Module.Decl.Index, |
| 1461 | | reloc_info: link.File.RelocInfo, |
| 1462 | | ) !u64 { |
| 1463 | | const mod = self.base.options.module.?; |
| 1464 | | const decl = mod.declPtr(decl_index); |
| 1465 | | |
| 1506 | pub fn getDeclVAddr(self: *Coff, decl_index: Module.Decl.Index, reloc_info: link.File.RelocInfo) !u64 { |
| 1466 | 1507 | assert(self.llvm_object == null); |
| 1467 | 1508 | |
| 1468 | | try decl.link.coff.ensureInitialized(self); |
| 1469 | | const sym_index = decl.link.coff.getSymbolIndex().?; |
| 1470 | | |
| 1471 | | const atom = self.getAtomForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?; |
| 1509 | const this_atom_index = try self.getOrCreateAtomForDecl(decl_index); |
| 1510 | const sym_index = self.getAtom(this_atom_index).getSymbolIndex().?; |
| 1511 | const atom_index = self.getAtomIndexForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?; |
| 1472 | 1512 | const target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; |
| 1473 | | try atom.addRelocation(self, .{ |
| 1513 | try Atom.addRelocation(self, atom_index, .{ |
| 1474 | 1514 | .type = .direct, |
| 1475 | 1515 | .target = target, |
| 1476 | 1516 | .offset = @intCast(u32, reloc_info.offset), |
| ... | ... | @@ -1478,7 +1518,7 @@ pub fn getDeclVAddr( |
| 1478 | 1518 | .pcrel = false, |
| 1479 | 1519 | .length = 3, |
| 1480 | 1520 | }); |
| 1481 | | try atom.addBaseRelocation(self, @intCast(u32, reloc_info.offset)); |
| 1521 | try Atom.addBaseRelocation(self, atom_index, @intCast(u32, reloc_info.offset)); |
| 1482 | 1522 | |
| 1483 | 1523 | return 0; |
| 1484 | 1524 | } |
| ... | ... | @@ -1529,7 +1569,8 @@ fn writeBaseRelocations(self: *Coff) !void { |
| 1529 | 1569 | |
| 1530 | 1570 | var it = self.base_relocs.iterator(); |
| 1531 | 1571 | while (it.next()) |entry| { |
| 1532 | | const atom = entry.key_ptr.*; |
| 1572 | const atom_index = entry.key_ptr.*; |
| 1573 | const atom = self.getAtom(atom_index); |
| 1533 | 1574 | const offsets = entry.value_ptr.*; |
| 1534 | 1575 | |
| 1535 | 1576 | for (offsets.items) |offset| { |
| ... | ... | @@ -1613,7 +1654,8 @@ fn writeImportTable(self: *Coff) !void { |
| 1613 | 1654 | const gpa = self.base.allocator; |
| 1614 | 1655 | |
| 1615 | 1656 | const section = self.sections.get(self.idata_section_index.?); |
| 1616 | | const last_atom = section.last_atom orelse return; |
| 1657 | const last_atom_index = section.last_atom_index orelse return; |
| 1658 | const last_atom = self.getAtom(last_atom_index); |
| 1617 | 1659 | |
| 1618 | 1660 | const iat_rva = section.header.virtual_address; |
| 1619 | 1661 | const iat_size = last_atom.getSymbol(self).value + last_atom.size * 2 - iat_rva; // account for sentinel zero pointer |
| ... | ... | @@ -2051,27 +2093,37 @@ pub fn getOrPutGlobalPtr(self: *Coff, name: []const u8) !GetOrPutGlobalPtrResult |
| 2051 | 2093 | return GetOrPutGlobalPtrResult{ .found_existing = false, .value_ptr = ptr }; |
| 2052 | 2094 | } |
| 2053 | 2095 | |
| 2096 | pub fn getAtom(self: *const Coff, atom_index: Atom.Index) Atom { |
| 2097 | assert(atom_index < self.atoms.items.len); |
| 2098 | return self.atoms.items[atom_index]; |
| 2099 | } |
| 2100 | |
| 2101 | pub fn getAtomPtr(self: *Coff, atom_index: Atom.Index) *Atom { |
| 2102 | assert(atom_index < self.atoms.items.len); |
| 2103 | return &self.atoms.items[atom_index]; |
| 2104 | } |
| 2105 | |
| 2054 | 2106 | /// Returns atom if there is an atom referenced by the symbol described by `sym_loc` descriptor. |
| 2055 | 2107 | /// Returns null on failure. |
| 2056 | | pub fn getAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom { |
| 2108 | pub fn getAtomIndexForSymbol(self: *const Coff, sym_loc: SymbolWithLoc) ?Atom.Index { |
| 2057 | 2109 | assert(sym_loc.file == null); // TODO linking with object files |
| 2058 | 2110 | return self.atom_by_index_table.get(sym_loc.sym_index); |
| 2059 | 2111 | } |
| 2060 | 2112 | |
| 2061 | 2113 | /// Returns GOT atom that references `sym_loc` if one exists. |
| 2062 | 2114 | /// Returns null otherwise. |
| 2063 | | pub fn getGotAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom { |
| 2115 | pub fn getGotAtomIndexForSymbol(self: *const Coff, sym_loc: SymbolWithLoc) ?Atom.Index { |
| 2064 | 2116 | const got_index = self.got_entries_table.get(sym_loc) orelse return null; |
| 2065 | 2117 | const got_entry = self.got_entries.items[got_index]; |
| 2066 | | return self.getAtomForSymbol(.{ .sym_index = got_entry.sym_index, .file = null }); |
| 2118 | return self.getAtomIndexForSymbol(.{ .sym_index = got_entry.sym_index, .file = null }); |
| 2067 | 2119 | } |
| 2068 | 2120 | |
| 2069 | 2121 | /// Returns import atom that references `sym_loc` if one exists. |
| 2070 | 2122 | /// Returns null otherwise. |
| 2071 | | pub fn getImportAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom { |
| 2123 | pub fn getImportAtomIndexForSymbol(self: *const Coff, sym_loc: SymbolWithLoc) ?Atom.Index { |
| 2072 | 2124 | const imports_index = self.imports_table.get(sym_loc) orelse return null; |
| 2073 | 2125 | const imports_entry = self.imports.items[imports_index]; |
| 2074 | | return self.getAtomForSymbol(.{ .sym_index = imports_entry.sym_index, .file = null }); |
| 2126 | return self.getAtomIndexForSymbol(.{ .sym_index = imports_entry.sym_index, .file = null }); |
| 2075 | 2127 | } |
| 2076 | 2128 | |
| 2077 | 2129 | fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !void { |