| ... | @@ -49,11 +49,8 @@ imports_count_dirty: bool = true, | ... | @@ -49,11 +49,8 @@ imports_count_dirty: bool = true, |
| 49 | /// Virtual address of the entry point procedure relative to image base. | 49 | /// Virtual address of the entry point procedure relative to image base. |
| 50 | entry_addr: ?u32 = null, | 50 | entry_addr: ?u32 = null, |
| 51 | | 51 | |
| 52 | /// Table of Decls that are currently alive. | 52 | /// Table of tracked Decls. |
| 53 | /// We store them here so that we can properly dispose of any allocated | 53 | decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{}, |
| 54 | /// memory within the atom in the incremental linker. | | |
| 55 | /// TODO consolidate this. | | |
| 56 | decls: std.AutoHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{}, | | |
| 57 | | 54 | |
| 58 | /// List of atoms that are either synthetic or map directly to the Zig source program. | 55 | /// List of atoms that are either synthetic or map directly to the Zig source program. |
| 59 | atoms: std.ArrayListUnmanaged(Atom) = .{}, | 56 | atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| ... | @@ -98,9 +95,9 @@ const Entry = struct { | ... | @@ -98,9 +95,9 @@ const Entry = struct { |
| 98 | sym_index: u32, | 95 | sym_index: u32, |
| 99 | }; | 96 | }; |
| 100 | | 97 | |
| 101 | const RelocTable = std.AutoHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation)); | 98 | const RelocTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation)); |
| 102 | const BaseRelocationTable = std.AutoHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); | 99 | const BaseRelocationTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); |
| 103 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); | 100 | const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); |
| 104 | | 101 | |
| 105 | const default_file_alignment: u16 = 0x200; | 102 | const default_file_alignment: u16 = 0x200; |
| 106 | const default_size_of_stack_reserve: u32 = 0x1000000; | 103 | const default_size_of_stack_reserve: u32 = 0x1000000; |
| ... | @@ -137,6 +134,10 @@ const DeclMetadata = struct { | ... | @@ -137,6 +134,10 @@ const DeclMetadata = struct { |
| 137 | /// A list of all exports aliases of this Decl. | 134 | /// A list of all exports aliases of this Decl. |
| 138 | exports: std.ArrayListUnmanaged(u32) = .{}, | 135 | exports: std.ArrayListUnmanaged(u32) = .{}, |
| 139 | | 136 | |
| | 137 | fn deinit(m: *DeclMetadata, allocator: Allocator) void { |
| | 138 | m.exports.deinit(allocator); |
| | 139 | } |
| | 140 | |
| 140 | fn getExport(m: DeclMetadata, coff_file: *const Coff, name: []const u8) ?u32 { | 141 | fn getExport(m: DeclMetadata, coff_file: *const Coff, name: []const u8) ?u32 { |
| 141 | for (m.exports.items) |exp| { | 142 | for (m.exports.items) |exp| { |
| 142 | if (mem.eql(u8, name, coff_file.getSymbolName(.{ | 143 | if (mem.eql(u8, name, coff_file.getSymbolName(.{ |
| ... | @@ -293,39 +294,27 @@ pub fn deinit(self: *Coff) void { | ... | @@ -293,39 +294,27 @@ pub fn deinit(self: *Coff) void { |
| 293 | } | 294 | } |
| 294 | self.import_tables.deinit(gpa); | 295 | self.import_tables.deinit(gpa); |
| 295 | | 296 | |
| 296 | { | 297 | for (self.decls.values()) |*metadata| { |
| 297 | var it = self.decls.iterator(); | 298 | metadata.deinit(gpa); |
| 298 | while (it.next()) |entry| { | | |
| 299 | entry.value_ptr.exports.deinit(gpa); | | |
| 300 | } | | |
| 301 | self.decls.deinit(gpa); | | |
| 302 | } | 299 | } |
| | 300 | self.decls.deinit(gpa); |
| 303 | | 301 | |
| 304 | self.atom_by_index_table.deinit(gpa); | 302 | self.atom_by_index_table.deinit(gpa); |
| 305 | | 303 | |
| 306 | { | 304 | for (self.unnamed_const_atoms.values()) |*atoms| { |
| 307 | var it = self.unnamed_const_atoms.valueIterator(); | 305 | atoms.deinit(gpa); |
| 308 | while (it.next()) |atoms| { | | |
| 309 | atoms.deinit(gpa); | | |
| 310 | } | | |
| 311 | self.unnamed_const_atoms.deinit(gpa); | | |
| 312 | } | 306 | } |
| | 307 | self.unnamed_const_atoms.deinit(gpa); |
| 313 | | 308 | |
| 314 | { | 309 | for (self.relocs.values()) |*relocs| { |
| 315 | var it = self.relocs.valueIterator(); | 310 | relocs.deinit(gpa); |
| 316 | while (it.next()) |relocs| { | | |
| 317 | relocs.deinit(gpa); | | |
| 318 | } | | |
| 319 | self.relocs.deinit(gpa); | | |
| 320 | } | 311 | } |
| | 312 | self.relocs.deinit(gpa); |
| 321 | | 313 | |
| 322 | { | 314 | for (self.base_relocs.values()) |*relocs| { |
| 323 | var it = self.base_relocs.valueIterator(); | 315 | relocs.deinit(gpa); |
| 324 | while (it.next()) |relocs| { | | |
| 325 | relocs.deinit(gpa); | | |
| 326 | } | | |
| 327 | self.base_relocs.deinit(gpa); | | |
| 328 | } | 316 | } |
| | 317 | self.base_relocs.deinit(gpa); |
| 329 | } | 318 | } |
| 330 | | 319 | |
| 331 | fn populateMissingMetadata(self: *Coff) !void { | 320 | fn populateMissingMetadata(self: *Coff) !void { |
| ... | @@ -800,8 +789,7 @@ fn writePtrWidthAtom(self: *Coff, atom_index: Atom.Index) !void { | ... | @@ -800,8 +789,7 @@ fn writePtrWidthAtom(self: *Coff, atom_index: Atom.Index) !void { |
| 800 | | 789 | |
| 801 | fn markRelocsDirtyByTarget(self: *Coff, target: SymbolWithLoc) void { | 790 | fn markRelocsDirtyByTarget(self: *Coff, target: SymbolWithLoc) void { |
| 802 | // TODO: reverse-lookup might come in handy here | 791 | // TODO: reverse-lookup might come in handy here |
| 803 | var it = self.relocs.valueIterator(); | 792 | for (self.relocs.values()) |*relocs| { |
| 804 | while (it.next()) |relocs| { | | |
| 805 | for (relocs.items) |*reloc| { | 793 | for (relocs.items) |*reloc| { |
| 806 | if (!reloc.target.eql(target)) continue; | 794 | if (!reloc.target.eql(target)) continue; |
| 807 | reloc.dirty = true; | 795 | reloc.dirty = true; |
| ... | @@ -810,8 +798,7 @@ fn markRelocsDirtyByTarget(self: *Coff, target: SymbolWithLoc) void { | ... | @@ -810,8 +798,7 @@ fn markRelocsDirtyByTarget(self: *Coff, target: SymbolWithLoc) void { |
| 810 | } | 798 | } |
| 811 | | 799 | |
| 812 | fn markRelocsDirtyByAddress(self: *Coff, addr: u32) void { | 800 | fn markRelocsDirtyByAddress(self: *Coff, addr: u32) void { |
| 813 | var it = self.relocs.valueIterator(); | 801 | for (self.relocs.values()) |*relocs| { |
| 814 | while (it.next()) |relocs| { | | |
| 815 | for (relocs.items) |*reloc| { | 802 | for (relocs.items) |*reloc| { |
| 816 | const target_vaddr = reloc.getTargetAddress(self) orelse continue; | 803 | const target_vaddr = reloc.getTargetAddress(self) orelse continue; |
| 817 | if (target_vaddr < addr) continue; | 804 | if (target_vaddr < addr) continue; |
| ... | @@ -821,7 +808,7 @@ fn markRelocsDirtyByAddress(self: *Coff, addr: u32) void { | ... | @@ -821,7 +808,7 @@ fn markRelocsDirtyByAddress(self: *Coff, addr: u32) void { |
| 821 | } | 808 | } |
| 822 | | 809 | |
| 823 | fn resolveRelocs(self: *Coff, atom_index: Atom.Index, code: []u8) void { | 810 | fn resolveRelocs(self: *Coff, atom_index: Atom.Index, code: []u8) void { |
| 824 | const relocs = self.relocs.get(atom_index) orelse return; | 811 | const relocs = self.relocs.getPtr(atom_index) orelse return; |
| 825 | | 812 | |
| 826 | log.debug("relocating '{s}'", .{self.getAtom(atom_index).getName(self)}); | 813 | log.debug("relocating '{s}'", .{self.getAtom(atom_index).getName(self)}); |
| 827 | | 814 | |
| ... | @@ -1196,7 +1183,7 @@ pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void { | ... | @@ -1196,7 +1183,7 @@ pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void { |
| 1196 | | 1183 | |
| 1197 | log.debug("freeDecl {*}", .{decl}); | 1184 | log.debug("freeDecl {*}", .{decl}); |
| 1198 | | 1185 | |
| 1199 | if (self.decls.fetchRemove(decl_index)) |const_kv| { | 1186 | if (self.decls.fetchOrderedRemove(decl_index)) |const_kv| { |
| 1200 | var kv = const_kv; | 1187 | var kv = const_kv; |
| 1201 | self.freeAtom(kv.value.atom); | 1188 | self.freeAtom(kv.value.atom); |
| 1202 | self.freeUnnamedConsts(decl_index); | 1189 | self.freeUnnamedConsts(decl_index); |
| ... | @@ -1423,32 +1410,29 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -1423,32 +1410,29 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod |
| 1423 | } | 1410 | } |
| 1424 | | 1411 | |
| 1425 | try self.writeImportTables(); | 1412 | try self.writeImportTables(); |
| 1426 | { | | |
| 1427 | var it = self.relocs.keyIterator(); | | |
| 1428 | while (it.next()) |atom_index_ptr| { | | |
| 1429 | const atom_index = atom_index_ptr.*; | | |
| 1430 | const relocs = self.relocs.get(atom_index).?; | | |
| 1431 | const needs_update = for (relocs.items) |reloc| { | | |
| 1432 | if (reloc.dirty) break true; | | |
| 1433 | } else false; | | |
| 1434 | | 1413 | |
| 1435 | if (!needs_update) continue; | 1414 | for (self.relocs.keys(), self.relocs.values()) |atom_index, relocs| { |
| | 1415 | const needs_update = for (relocs.items) |reloc| { |
| | 1416 | if (reloc.dirty) break true; |
| | 1417 | } else false; |
| 1436 | | 1418 | |
| 1437 | const atom = self.getAtom(atom_index); | 1419 | if (!needs_update) continue; |
| 1438 | const sym = atom.getSymbol(self); | | |
| 1439 | const section = self.sections.get(@enumToInt(sym.section_number) - 1).header; | | |
| 1440 | const file_offset = section.pointer_to_raw_data + sym.value - section.virtual_address; | | |
| 1441 | | 1420 | |
| 1442 | var code = std.ArrayList(u8).init(gpa); | 1421 | const atom = self.getAtom(atom_index); |
| 1443 | defer code.deinit(); | 1422 | const sym = atom.getSymbol(self); |
| 1444 | try code.resize(math.cast(usize, atom.size) orelse return error.Overflow); | 1423 | const section = self.sections.get(@enumToInt(sym.section_number) - 1).header; |
| | 1424 | const file_offset = section.pointer_to_raw_data + sym.value - section.virtual_address; |
| 1445 | | 1425 | |
| 1446 | const amt = try self.base.file.?.preadAll(code.items, file_offset); | 1426 | var code = std.ArrayList(u8).init(gpa); |
| 1447 | if (amt != code.items.len) return error.InputOutput; | 1427 | defer code.deinit(); |
| | 1428 | try code.resize(math.cast(usize, atom.size) orelse return error.Overflow); |
| 1448 | | 1429 | |
| 1449 | try self.writeAtom(atom_index, code.items); | 1430 | const amt = try self.base.file.?.preadAll(code.items, file_offset); |
| 1450 | } | 1431 | if (amt != code.items.len) return error.InputOutput; |
| | 1432 | |
| | 1433 | try self.writeAtom(atom_index, code.items); |
| 1451 | } | 1434 | } |
| | 1435 | |
| 1452 | try self.writeBaseRelocations(); | 1436 | try self.writeBaseRelocations(); |
| 1453 | | 1437 | |
| 1454 | if (self.getEntryPoint()) |entry_sym_loc| { | 1438 | if (self.getEntryPoint()) |entry_sym_loc| { |