diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-01-26 14:28:44 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-01-26 14:29:14 +0100 |
| commit | cc1d7a0e315ba63b0d8c0cd647b4c7e92a571bf2 (patch) | |
| tree | 281b181f5e1bc127ed41e3f7c9e958a57df4cf68 | |
| parent | e1b9800ffa74a637e2b0a6356249c2c37228ec01 (diff) | |
| download | zig-cc1d7a0e315ba63b0d8c0cd647b4c7e92a571bf2.tar.gz zig-cc1d7a0e315ba63b0d8c0cd647b4c7e92a571bf2.zip | |
coff: migrate to new non-allocateDeclIndexes API
| -rw-r--r-- | src/Module.zig | 7 | ||||
| -rw-r--r-- | src/arch/aarch64/CodeGen.zig | 19 | ||||
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 14 | ||||
| -rw-r--r-- | src/link.zig | 12 | ||||
| -rw-r--r-- | src/link/Coff.zig | 152 | ||||
| -rw-r--r-- | src/link/Coff/Atom.zig | 23 | ||||
| -rw-r--r-- | src/link/Elf.zig | 49 | ||||
| -rw-r--r-- | src/link/MachO.zig | 135 |
8 files changed, 209 insertions, 202 deletions
diff --git a/src/Module.zig b/src/Module.zig index 4e1f65aff4..360dd4d1ec 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -5324,7 +5324,12 @@ pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { // Until then, we did call `allocateDeclIndexes` on this anonymous Decl and so we // must call `freeDecl` in the linker backend now. switch (mod.comp.bin_file.tag) { - .elf, .macho, .c => {}, // this linker backend has already migrated to the new API + .coff, + .elf, + .macho, + .c, + => {}, // this linker backend has already migrated to the new API + else => if (decl.has_tv) { if (decl.ty.isFnOrHasRuntimeBits()) { mod.comp.bin_file.freeDecl(decl_index); diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 8c3f3e8168..200bf3b8e0 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -4000,7 +4000,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type const owner_decl = mod.declPtr(self.mod_fn.owner_decl); const atom_index = switch (self.bin_file.tag) { .macho => owner_decl.link.macho.getSymbolIndex().?, - .coff => owner_decl.link.coff.sym_index, + .coff => owner_decl.link.coff.getSymbolIndex().?, else => unreachable, // unsupported target format }; _ = try self.addInst(.{ @@ -4318,11 +4318,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier .sym_index = fn_owner_decl.link.macho.getSymbolIndex().?, }, }); - } else if (self.bin_file.cast(link.File.Coff)) |_| { + } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { + try fn_owner_decl.link.coff.ensureInitialized(coff_file); try self.genSetReg(Type.initTag(.u64), .x30, .{ .linker_load = .{ .type = .got, - .sym_index = fn_owner_decl.link.coff.sym_index, + .sym_index = fn_owner_decl.link.coff.getSymbolIndex().?, }, }); } else if (self.bin_file.cast(link.File.Plan9)) |p9| { @@ -5494,7 +5495,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro const owner_decl = mod.declPtr(self.mod_fn.owner_decl); const atom_index = switch (self.bin_file.tag) { .macho => owner_decl.link.macho.getSymbolIndex().?, - .coff => owner_decl.link.coff.sym_index, + .coff => owner_decl.link.coff.getSymbolIndex().?, else => unreachable, // unsupported target format }; _ = try self.addInst(.{ @@ -5608,7 +5609,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void const owner_decl = mod.declPtr(self.mod_fn.owner_decl); const atom_index = switch (self.bin_file.tag) { .macho => owner_decl.link.macho.getSymbolIndex().?, - .coff => owner_decl.link.coff.sym_index, + .coff => owner_decl.link.coff.getSymbolIndex().?, else => unreachable, // unsupported target format }; _ = try self.addInst(.{ @@ -5802,7 +5803,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I const owner_decl = mod.declPtr(self.mod_fn.owner_decl); const atom_index = switch (self.bin_file.tag) { .macho => owner_decl.link.macho.getSymbolIndex().?, - .coff => owner_decl.link.coff.sym_index, + .coff => owner_decl.link.coff.getSymbolIndex().?, else => unreachable, // unsupported target format }; _ = try self.addInst(.{ @@ -6129,11 +6130,11 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne .type = .got, .sym_index = decl.link.macho.getSymbolIndex().?, } }; - } else if (self.bin_file.cast(link.File.Coff)) |_| { - assert(decl.link.coff.sym_index != 0); + } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { + try decl.link.coff.ensureInitialized(coff_file); return MCValue{ .linker_load = .{ .type = .got, - .sym_index = decl.link.coff.sym_index, + .sym_index = decl.link.coff.getSymbolIndex().?, } }; } else if (self.bin_file.cast(link.File.Plan9)) |p9| { try p9.seeDecl(decl_index); diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 93f1269147..df24fe5e7d 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -2673,7 +2673,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue const atom_index = if (self.bin_file.tag == link.File.MachO.base_tag) fn_owner_decl.link.macho.getSymbolIndex().? else - fn_owner_decl.link.coff.sym_index; + fn_owner_decl.link.coff.getSymbolIndex().?; const flags: u2 = switch (load_struct.type) { .got => 0b00, .direct => 0b01, @@ -4005,11 +4005,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), .data = .{ .imm = got_addr }, }); - } else if (self.bin_file.cast(link.File.Coff)) |_| { + } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { + try fn_owner_decl.link.coff.ensureInitialized(coff_file); + const sym_index = fn_owner_decl.link.coff.getSymbolIndex().?; try self.genSetReg(Type.initTag(.usize), .rax, .{ .linker_load = .{ .type = .got, - .sym_index = fn_owner_decl.link.coff.sym_index, + .sym_index = sym_index, }, }); _ = try self.addInst(.{ @@ -6725,11 +6727,11 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne .type = .got, .sym_index = decl.link.macho.getSymbolIndex().?, } }; - } else if (self.bin_file.cast(link.File.Coff)) |_| { - assert(decl.link.coff.sym_index != 0); + } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { + try decl.link.coff.ensureInitialized(coff_file); return MCValue{ .linker_load = .{ .type = .got, - .sym_index = decl.link.coff.sym_index, + .sym_index = decl.link.coff.getSymbolIndex().?, } }; } else if (self.bin_file.cast(link.File.Plan9)) |p9| { try p9.seeDecl(decl_index); diff --git a/src/link.zig b/src/link.zig index d64c09d199..9be5b9ca3a 100644 --- a/src/link.zig +++ b/src/link.zig @@ -615,12 +615,16 @@ pub const File = struct { return; } switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl_index), - .elf => {}, // no-op - .macho => {}, // no-op .wasm => return @fieldParentPtr(Wasm, "base", base).allocateDeclIndexes(decl_index), .plan9 => return @fieldParentPtr(Plan9, "base", base).allocateDeclIndexes(decl_index), - .c, .spirv, .nvptx => {}, + + .coff, + .elf, + .macho, + .c, + .spirv, + .nvptx, + => {}, } } diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 65aee010fd..dee3c7c381 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -480,16 +480,6 @@ fn growSectionVM(self: *Coff, sect_id: u32, needed_size: u32) !void { header.virtual_size = increased_size; } -pub fn allocateDeclIndexes(self: *Coff, decl_index: Module.Decl.Index) !void { - if (self.llvm_object) |_| return; - const decl = self.base.options.module.?.declPtr(decl_index); - if (decl.link.coff.sym_index != 0) return; - decl.link.coff.sym_index = try self.allocateSymbol(); - const gpa = self.base.allocator; - try self.atom_by_index_table.putNoClobber(gpa, decl.link.coff.sym_index, &decl.link.coff); - try self.decls.putNoClobber(gpa, decl_index, null); -} - fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u32 { const tracy = trace(@src()); defer tracy.end(); @@ -615,7 +605,7 @@ fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u return vaddr; } -fn allocateSymbol(self: *Coff) !u32 { +pub fn allocateSymbol(self: *Coff) !u32 { const gpa = self.base.allocator; try self.locals.ensureUnusedCapacity(gpa, 1); @@ -716,12 +706,11 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom { const atom = try gpa.create(Atom); errdefer gpa.destroy(atom); atom.* = Atom.empty; - atom.sym_index = try self.allocateSymbol(); + try atom.ensureInitialized(self); atom.size = @sizeOf(u64); atom.alignment = @alignOf(u64); try self.managed_atoms.append(gpa, atom); - try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom); const sym = atom.getSymbolPtr(self); sym.section_number = @intToEnum(coff.SectionNumber, self.got_section_index.? + 1); @@ -754,12 +743,11 @@ fn createImportAtom(self: *Coff) !*Atom { const atom = try gpa.create(Atom); errdefer gpa.destroy(atom); atom.* = Atom.empty; - atom.sym_index = try self.allocateSymbol(); + try atom.ensureInitialized(self); atom.size = @sizeOf(u64); atom.alignment = @alignOf(u64); try self.managed_atoms.append(gpa, atom); - try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom); const sym = atom.getSymbolPtr(self); sym.section_number = @intToEnum(coff.SectionNumber, self.idata_section_index.? + 1); @@ -790,7 +778,11 @@ fn writeAtom(self: *Coff, atom: *Atom, code: []const u8) !void { const sym = atom.getSymbol(self); const section = self.sections.get(@enumToInt(sym.section_number) - 1); const file_offset = section.header.pointer_to_raw_data + sym.value - section.header.virtual_address; - log.debug("writing atom for symbol {s} at file offset 0x{x} to 0x{x}", .{ atom.getName(self), file_offset, file_offset + code.len }); + log.debug("writing atom for symbol {s} at file offset 0x{x} to 0x{x}", .{ + atom.getName(self), + file_offset, + file_offset + code.len, + }); try self.base.file.?.pwriteAll(code, file_offset); try self.resolveRelocs(atom); } @@ -848,6 +840,7 @@ fn freeAtom(self: *Coff, atom: *Atom) void { // Remove any relocs and base relocs associated with this Atom self.freeRelocationsForAtom(atom); + const gpa = self.base.allocator; const sym = atom.getSymbol(self); const sect_id = @enumToInt(sym.section_number) - 1; const free_list = &self.sections.items(.free_list)[sect_id]; @@ -885,7 +878,7 @@ fn freeAtom(self: *Coff, atom: *Atom) void { if (!already_have_free_list_node and prev.freeListEligible(self)) { // The free list is heuristics, it doesn't have to be perfect, so we can // ignore the OOM here. - free_list.append(self.base.allocator, prev) catch {}; + free_list.append(gpa, prev) catch {}; } } else { atom.prev = null; @@ -896,6 +889,28 @@ fn freeAtom(self: *Coff, atom: *Atom) void { } else { atom.next = null; } + + // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. + const sym_index = atom.getSymbolIndex().?; + self.locals_free_list.append(gpa, sym_index) catch {}; + + // Try freeing GOT atom if this decl had one + const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; + if (self.got_entries_table.get(got_target)) |got_index| { + self.got_entries_free_list.append(gpa, @intCast(u32, got_index)) catch {}; + self.got_entries.items[got_index] = .{ + .target = .{ .sym_index = 0, .file = null }, + .sym_index = 0, + }; + _ = self.got_entries_table.remove(got_target); + + log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index }); + } + + self.locals.items[sym_index].section_number = .UNDEFINED; + _ = self.atom_by_index_table.remove(sym_index); + log.debug(" adding local symbol index {d} to free list", .{sym_index}); + atom.sym_index = 0; } pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { @@ -912,8 +927,15 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live const decl_index = func.owner_decl; const decl = module.declPtr(decl_index); - self.freeUnnamedConsts(decl_index); - self.freeRelocationsForAtom(&decl.link.coff); + const atom = &decl.link.coff; + try atom.ensureInitialized(self); + const gop = try self.decls.getOrPut(self.base.allocator, decl_index); + if (gop.found_existing) { + self.freeUnnamedConsts(decl_index); + self.freeRelocationsForAtom(&decl.link.coff); + } else { + gop.value_ptr.* = null; + } var code_buffer = std.ArrayList(u8).init(self.base.allocator); defer code_buffer.deinit(); @@ -960,9 +982,9 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In const atom = try gpa.create(Atom); errdefer gpa.destroy(atom); atom.* = Atom.empty; + try atom.ensureInitialized(self); + try self.managed_atoms.append(gpa, atom); - atom.sym_index = try self.allocateSymbol(); - const sym = atom.getSymbolPtr(self); const sym_name = blk: { const decl_name = try decl.getFullyQualifiedName(mod); defer gpa.free(decl_name); @@ -971,14 +993,11 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In break :blk try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); }; defer gpa.free(sym_name); - try self.setSymbolName(sym, sym_name); - sym.section_number = @intToEnum(coff.SectionNumber, self.rdata_section_index.? + 1); - - try self.managed_atoms.append(gpa, atom); - try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom); + try self.setSymbolName(atom.getSymbolPtr(self), sym_name); + atom.getSymbolPtr(self).section_number = @intToEnum(coff.SectionNumber, self.rdata_section_index.? + 1); const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), tv, &code_buffer, .none, .{ - .parent_atom_index = atom.sym_index, + .parent_atom_index = atom.getSymbolIndex().?, }); const code = switch (res) { .ok => code_buffer.items, @@ -993,17 +1012,17 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In const required_alignment = tv.ty.abiAlignment(self.base.options.target); atom.alignment = required_alignment; atom.size = @intCast(u32, code.len); - sym.value = try self.allocateAtom(atom, atom.size, atom.alignment); + atom.getSymbolPtr(self).value = try self.allocateAtom(atom, atom.size, atom.alignment); errdefer self.freeAtom(atom); try unnamed_consts.append(gpa, atom); - log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, sym.value }); + log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, atom.getSymbol(self).value }); log.debug(" (required alignment 0x{x})", .{required_alignment}); try self.writeAtom(atom, code); - return atom.sym_index; + return atom.getSymbolIndex().?; } pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) !void { @@ -1028,7 +1047,14 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) ! } } - self.freeRelocationsForAtom(&decl.link.coff); + const atom = &decl.link.coff; + try atom.ensureInitialized(self); + const gop = try self.decls.getOrPut(self.base.allocator, decl_index); + if (gop.found_existing) { + self.freeRelocationsForAtom(atom); + } else { + gop.value_ptr.* = null; + } var code_buffer = std.ArrayList(u8).init(self.base.allocator); defer code_buffer.deinit(); @@ -1038,7 +1064,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) ! .ty = decl.ty, .val = decl_val, }, &code_buffer, .none, .{ - .parent_atom_index = decl.link.coff.sym_index, + .parent_atom_index = decl.link.coff.getSymbolIndex().?, }); const code = switch (res) { .ok => code_buffer.items, @@ -1099,7 +1125,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, const code_len = @intCast(u32, code.len); const atom = &decl.link.coff; - assert(atom.sym_index != 0); // Caller forgot to allocateDeclIndexes() + if (atom.size != 0) { const sym = atom.getSymbolPtr(self); try self.setSymbolName(sym, decl_name); @@ -1116,7 +1142,7 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, if (vaddr != sym.value) { sym.value = vaddr; log.debug(" (updating GOT entry)", .{}); - const got_target = SymbolWithLoc{ .sym_index = atom.sym_index, .file = null }; + const got_target = SymbolWithLoc{ .sym_index = atom.getSymbolIndex().?, .file = null }; const got_atom = self.getGotAtomForSymbol(got_target).?; self.markRelocsDirtyByTarget(got_target); try self.writePtrWidthAtom(got_atom); @@ -1137,10 +1163,10 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, atom.size = code_len; sym.value = vaddr; - const got_target = SymbolWithLoc{ .sym_index = atom.sym_index, .file = null }; + const got_target = SymbolWithLoc{ .sym_index = atom.getSymbolIndex().?, .file = null }; const got_index = try self.allocateGotEntry(got_target); const got_atom = try self.createGotAtom(got_target); - self.got_entries.items[got_index].sym_index = got_atom.sym_index; + self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?; try self.writePtrWidthAtom(got_atom); } @@ -1160,11 +1186,6 @@ fn freeUnnamedConsts(self: *Coff, decl_index: Module.Decl.Index) void { const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; for (unnamed_consts.items) |atom| { self.freeAtom(atom); - self.locals_free_list.append(gpa, atom.sym_index) catch {}; - self.locals.items[atom.sym_index].section_number = .UNDEFINED; - _ = self.atom_by_index_table.remove(atom.sym_index); - log.debug(" adding local symbol index {d} to free list", .{atom.sym_index}); - atom.sym_index = 0; } unnamed_consts.clearAndFree(gpa); } @@ -1179,35 +1200,11 @@ pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void { log.debug("freeDecl {*}", .{decl}); - const kv = self.decls.fetchRemove(decl_index); - if (kv.?.value) |_| { - self.freeAtom(&decl.link.coff); - self.freeUnnamedConsts(decl_index); - } - - // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. - const gpa = self.base.allocator; - const sym_index = decl.link.coff.sym_index; - if (sym_index != 0) { - self.locals_free_list.append(gpa, sym_index) catch {}; - - // Try freeing GOT atom if this decl had one - const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; - if (self.got_entries_table.get(got_target)) |got_index| { - self.got_entries_free_list.append(gpa, @intCast(u32, got_index)) catch {}; - self.got_entries.items[got_index] = .{ - .target = .{ .sym_index = 0, .file = null }, - .sym_index = 0, - }; - _ = self.got_entries_table.remove(got_target); - - log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index }); + if (self.decls.fetchRemove(decl_index)) |kv| { + if (kv.value) |_| { + self.freeAtom(&decl.link.coff); + self.freeUnnamedConsts(decl_index); } - - self.locals.items[sym_index].section_number = .UNDEFINED; - _ = self.atom_by_index_table.remove(sym_index); - log.debug(" adding local symbol index {d} to free list", .{sym_index}); - decl.link.coff.sym_index = 0; } } @@ -1261,7 +1258,14 @@ pub fn updateDeclExports( const decl = module.declPtr(decl_index); const atom = &decl.link.coff; - if (atom.sym_index == 0) return; + + if (atom.getSymbolIndex() == null) return; + + const gop = try self.decls.getOrPut(gpa, decl_index); + if (!gop.found_existing) { + gop.value_ptr.* = self.getDeclOutputSection(decl); + } + const decl_sym = atom.getSymbol(self); for (exports) |exp| { @@ -1416,7 +1420,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod const import_index = try self.allocateImportEntry(global); const import_atom = try self.createImportAtom(); - self.imports.items[import_index].sym_index = import_atom.sym_index; + self.imports.items[import_index].sym_index = import_atom.getSymbolIndex().?; try self.writePtrWidthAtom(import_atom); } @@ -1460,10 +1464,12 @@ pub fn getDeclVAddr( const decl = mod.declPtr(decl_index); assert(self.llvm_object == null); - assert(decl.link.coff.sym_index != 0); + + try decl.link.coff.ensureInitialized(self); + const sym_index = decl.link.coff.getSymbolIndex().?; const atom = self.getAtomForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?; - const target = SymbolWithLoc{ .sym_index = decl.link.coff.sym_index, .file = null }; + const target = SymbolWithLoc{ .sym_index = sym_index, .file = null }; try atom.addRelocation(self, .{ .type = .direct, .target = target, diff --git a/src/link/Coff/Atom.zig b/src/link/Coff/Atom.zig index b1bb292c62..78824eac1d 100644 --- a/src/link/Coff/Atom.zig +++ b/src/link/Coff/Atom.zig @@ -39,30 +39,45 @@ pub const empty = Atom{ .next = null, }; +pub fn ensureInitialized(self: *Atom, coff_file: *Coff) !void { + if (self.getSymbolIndex() != null) return; // Already initialized + self.sym_index = try coff_file.allocateSymbol(); + try coff_file.atom_by_index_table.putNoClobber(coff_file.base.allocator, self.sym_index, self); +} + +pub fn getSymbolIndex(self: Atom) ?u32 { + if (self.sym_index == 0) return null; + return self.sym_index; +} + /// Returns symbol referencing this atom. pub fn getSymbol(self: Atom, coff_file: *const Coff) *const coff.Symbol { + const sym_index = self.getSymbolIndex().?; return coff_file.getSymbol(.{ - .sym_index = self.sym_index, + .sym_index = sym_index, .file = self.file, }); } /// Returns pointer-to-symbol referencing this atom. pub fn getSymbolPtr(self: Atom, coff_file: *Coff) *coff.Symbol { + const sym_index = self.getSymbolIndex().?; return coff_file.getSymbolPtr(.{ - .sym_index = self.sym_index, + .sym_index = sym_index, .file = self.file, }); } pub fn getSymbolWithLoc(self: Atom) SymbolWithLoc { - return .{ .sym_index = self.sym_index, .file = self.file }; + const sym_index = self.getSymbolIndex().?; + return .{ .sym_index = sym_index, .file = self.file }; } /// Returns the name of this atom. pub fn getName(self: Atom, coff_file: *const Coff) []const u8 { + const sym_index = self.getSymbolIndex().?; return coff_file.getSymbolName(.{ - .sym_index = self.sym_index, + .sym_index = sym_index, .file = self.file, }); } diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 9dbc5e846f..2c55e55f83 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -893,7 +893,7 @@ fn growAllocSection(self: *Elf, shdr_index: u16, phdr_index: u16, needed_size: u // Must move the entire section. const new_offset = self.findFreeSpace(needed_size, self.page_size); const existing_size = if (self.atoms.get(phdr_index)) |last| blk: { - const sym = self.local_symbols.items[last.local_sym_index]; + const sym = last.getSymbol(self); break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr; } else if (shdr_index == self.got_section_index.?) blk: { break :blk shdr.sh_size; @@ -1031,7 +1031,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node while (it.next()) |entry| { const atom = entry.key_ptr.*; const relocs = entry.value_ptr.*; - const source_sym = self.local_symbols.items[atom.local_sym_index]; + const source_sym = atom.getSymbol(self); const source_shdr = self.sections.items[source_sym.st_shndx]; log.debug("relocating '{s}'", .{self.getString(source_sym.st_name)}); @@ -2034,11 +2034,13 @@ fn writeElfHeader(self: *Elf) !void { } fn freeTextBlock(self: *Elf, text_block: *TextBlock, phdr_index: u16) void { - const local_sym = self.local_symbols.items[text_block.local_sym_index]; + const local_sym = text_block.getSymbol(self); const name_str_index = local_sym.st_name; const name = self.getString(name_str_index); log.debug("freeTextBlock {*} ({s})", .{ text_block, name }); + self.freeRelocationsForTextBlock(text_block); + const free_list = self.atom_free_lists.getPtr(phdr_index).?; var already_have_free_list_node = false; { @@ -2107,7 +2109,7 @@ fn shrinkTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, phdr } fn growTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64, phdr_index: u16) !u64 { - const sym = self.local_symbols.items[text_block.local_sym_index]; + const sym = text_block.getSymbol(self); const align_ok = mem.alignBackwardGeneric(u64, sym.st_value, alignment) == sym.st_value; const need_realloc = !align_ok or new_block_size > text_block.capacity(self); if (!need_realloc) return sym.st_value; @@ -2137,7 +2139,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al const big_block = free_list.items[i]; // We now have a pointer to a live text block that has too much capacity. // Is it enough that we could fit this new text block? - const sym = self.local_symbols.items[big_block.local_sym_index]; + const sym = big_block.getSymbol(self); const capacity = big_block.capacity(self); const ideal_capacity = padToIdeal(capacity); const ideal_capacity_end_vaddr = std.math.add(u64, sym.st_value, ideal_capacity) catch ideal_capacity; @@ -2168,7 +2170,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al } break :blk new_start_vaddr; } else if (self.atoms.get(phdr_index)) |last| { - const sym = self.local_symbols.items[last.local_sym_index]; + const sym = last.getSymbol(self); const ideal_capacity = padToIdeal(sym.st_size); const ideal_capacity_end_vaddr = sym.st_value + ideal_capacity; const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, alignment); @@ -2270,6 +2272,11 @@ pub fn allocateGotOffset(self: *Elf) !u32 { return index; } +fn freeRelocationsForTextBlock(self: *Elf, text_block: *TextBlock) void { + var removed_relocs = self.relocs.fetchRemove(text_block); + if (removed_relocs) |*relocs| relocs.value.deinit(self.base.allocator); +} + fn freeUnnamedConsts(self: *Elf, decl_index: Module.Decl.Index) void { const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; for (unnamed_consts.items) |atom| { @@ -2341,8 +2348,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s const phdr_index = decl_ptr.*.?; const shdr_index = self.phdr_shdr_table.get(phdr_index).?; - assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes() - const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index]; + const local_sym = decl.link.elf.getSymbolPtr(self); if (local_sym.st_size != 0) { const capacity = decl.link.elf.capacity(self); const need_realloc = code.len > capacity or @@ -2366,7 +2372,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s local_sym.st_other = 0; local_sym.st_shndx = shdr_index; // TODO this write could be avoided if no fields of the symbol were changed. - try self.writeSymbol(decl.link.elf.local_sym_index); + try self.writeSymbol(decl.link.elf.getSymbolIndex().?); } else { const name_str_index = try self.makeString(decl_name); const vaddr = try self.allocateTextBlock(&decl.link.elf, code.len, required_alignment, phdr_index); @@ -2383,7 +2389,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s }; self.offset_table.items[decl.link.elf.offset_table_index] = vaddr; - try self.writeSymbol(decl.link.elf.local_sym_index); + try self.writeSymbol(decl.link.elf.getSymbolIndex().?); try self.writeOffsetTableEntry(decl.link.elf.offset_table_index); } @@ -2412,6 +2418,7 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven const gop = try self.decls.getOrPut(self.base.allocator, decl_index); if (gop.found_existing) { self.freeUnnamedConsts(decl_index); + self.freeRelocationsForTextBlock(atom); } else { gop.value_ptr.* = null; } @@ -2481,7 +2488,9 @@ pub fn updateDecl(self: *Elf, module: *Module, decl_index: Module.Decl.Index) !v const atom = &decl.link.elf; try atom.ensureInitialized(self); const gop = try self.decls.getOrPut(self.base.allocator, decl_index); - if (!gop.found_existing) { + if (gop.found_existing) { + self.freeRelocationsForTextBlock(atom); + } else { gop.value_ptr.* = null; } @@ -2500,14 +2509,14 @@ pub fn updateDecl(self: *Elf, module: *Module, decl_index: Module.Decl.Index) !v }, &code_buffer, .{ .dwarf = ds, }, .{ - .parent_atom_index = decl.link.elf.local_sym_index, + .parent_atom_index = decl.link.elf.getSymbolIndex().?, }) else try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ .ty = decl.ty, .val = decl_val, }, &code_buffer, .none, .{ - .parent_atom_index = decl.link.elf.local_sym_index, + .parent_atom_index = decl.link.elf.getSymbolIndex().?, }); const code = switch (res) { @@ -2551,6 +2560,8 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module const atom = try self.base.allocator.create(TextBlock); errdefer self.base.allocator.destroy(atom); atom.* = TextBlock.empty; + // TODO for unnamed consts we don't need GOT offset/entry allocated + try atom.ensureInitialized(self); try self.managed_atoms.append(self.base.allocator, atom); const name_str_index = blk: { @@ -2565,14 +2576,10 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module }; const name = self.getString(name_str_index); - log.debug("allocating symbol indexes for {s}", .{name}); - atom.local_sym_index = try self.allocateLocalSymbol(); - try self.atom_by_index_table.putNoClobber(self.base.allocator, atom.local_sym_index, atom); - const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{ .none = {}, }, .{ - .parent_atom_index = atom.local_sym_index, + .parent_atom_index = atom.getSymbolIndex().?, }); const code = switch (res) { .ok => code_buffer.items, @@ -2592,7 +2599,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module log.debug("allocated text block for {s} at 0x{x}", .{ name, vaddr }); - const local_sym = &self.local_symbols.items[atom.local_sym_index]; + const local_sym = atom.getSymbolPtr(self); local_sym.* = .{ .st_name = name_str_index, .st_info = (elf.STB_LOCAL << 4) | elf.STT_OBJECT, @@ -2602,14 +2609,14 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module .st_size = code.len, }; - try self.writeSymbol(atom.local_sym_index); + try self.writeSymbol(atom.getSymbolIndex().?); try unnamed_consts.append(self.base.allocator, atom); const section_offset = local_sym.st_value - self.program_headers.items[phdr_index].p_vaddr; const file_offset = self.sections.items[shdr_index].sh_offset + section_offset; try self.base.file.?.pwriteAll(code, file_offset); - return atom.local_sym_index; + return atom.getSymbolIndex().?; } pub fn updateDeclExports( diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 8fe5a1c712..543cb473d7 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1056,19 +1056,14 @@ pub fn allocateSpecialSymbols(self: *MachO) !void { pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom { const gpa = self.base.allocator; - const sym_index = try self.allocateSymbol(); - const atom = blk: { - const atom = try gpa.create(Atom); - atom.* = Atom.empty; - atom.sym_index = sym_index; - atom.size = @sizeOf(u64); - atom.alignment = @alignOf(u64); - break :blk atom; - }; + const atom = try gpa.create(Atom); + atom.* = Atom.empty; + try atom.ensureInitialized(self); + atom.size = @sizeOf(u64); + atom.alignment = @alignOf(u64); errdefer gpa.destroy(atom); try self.managed_atoms.append(gpa, atom); - try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom); const sym = atom.getSymbolPtr(self); sym.n_type = macho.N_SECT; @@ -1109,15 +1104,11 @@ pub fn createDyldPrivateAtom(self: *MachO) !void { const gpa = self.base.allocator; - const sym_index = try self.allocateSymbol(); - const atom = blk: { - const atom = try gpa.create(Atom); - atom.* = Atom.empty; - atom.sym_index = sym_index; - atom.size = @sizeOf(u64); - atom.alignment = @alignOf(u64); - break :blk atom; - }; + const atom = try gpa.create(Atom); + atom.* = Atom.empty; + try atom.ensureInitialized(self); + atom.size = @sizeOf(u64); + atom.alignment = @alignOf(u64); errdefer gpa.destroy(atom); const sym = atom.getSymbolPtr(self); @@ -1126,7 +1117,6 @@ pub fn createDyldPrivateAtom(self: *MachO) !void { self.dyld_private_atom = atom; try self.managed_atoms.append(gpa, atom); - try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); sym.n_value = try self.allocateAtom(atom, atom.size, @alignOf(u64)); log.debug("allocated dyld_private atom at 0x{x}", .{sym.n_value}); @@ -1144,18 +1134,14 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void { .aarch64 => 6 * @sizeOf(u32), else => unreachable, }; - const sym_index = try self.allocateSymbol(); - const atom = blk: { - const atom = try gpa.create(Atom); - atom.* = Atom.empty; - atom.sym_index = sym_index; - atom.size = size; - atom.alignment = switch (arch) { - .x86_64 => 1, - .aarch64 => @alignOf(u32), - else => unreachable, - }; - break :blk atom; + const atom = try gpa.create(Atom); + atom.* = Atom.empty; + try atom.ensureInitialized(self); + atom.size = size; + atom.alignment = switch (arch) { + .x86_64 => 1, + .aarch64 => @alignOf(u32), + else => unreachable, }; errdefer gpa.destroy(atom); @@ -1163,7 +1149,7 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void { sym.n_type = macho.N_SECT; sym.n_sect = self.stub_helper_section_index.? + 1; - const dyld_private_sym_index = self.dyld_private_atom.?.sym_index; + const dyld_private_sym_index = self.dyld_private_atom.?.getSymbolIndex().?; const code = try gpa.alloc(u8, size); defer gpa.free(code); @@ -1258,7 +1244,6 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void { self.stub_helper_preamble_atom = atom; try self.managed_atoms.append(gpa, atom); - try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); sym.n_value = try self.allocateAtom(atom, size, atom.alignment); log.debug("allocated stub preamble atom at 0x{x}", .{sym.n_value}); @@ -1273,18 +1258,14 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { .aarch64 => 3 * @sizeOf(u32), else => unreachable, }; - const sym_index = try self.allocateSymbol(); - const atom = blk: { - const atom = try gpa.create(Atom); - atom.* = Atom.empty; - atom.sym_index = sym_index; - atom.size = size; - atom.alignment = switch (arch) { - .x86_64 => 1, - .aarch64 => @alignOf(u32), - else => unreachable, - }; - break :blk atom; + const atom = try gpa.create(Atom); + atom.* = Atom.empty; + try atom.ensureInitialized(self); + atom.size = size; + atom.alignment = switch (arch) { + .x86_64 => 1, + .aarch64 => @alignOf(u32), + else => unreachable, }; errdefer gpa.destroy(atom); @@ -1306,7 +1287,7 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { try atom.addRelocation(self, .{ .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH), - .target = .{ .sym_index = self.stub_helper_preamble_atom.?.sym_index, .file = null }, + .target = .{ .sym_index = self.stub_helper_preamble_atom.?.getSymbolIndex().?, .file = null }, .offset = 6, .addend = 0, .pcrel = true, @@ -1329,7 +1310,7 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { try atom.addRelocation(self, .{ .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_BRANCH26), - .target = .{ .sym_index = self.stub_helper_preamble_atom.?.sym_index, .file = null }, + .target = .{ .sym_index = self.stub_helper_preamble_atom.?.getSymbolIndex().?, .file = null }, .offset = 4, .addend = 0, .pcrel = true, @@ -1340,7 +1321,6 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { } try self.managed_atoms.append(gpa, atom); - try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); sym.n_value = try self.allocateAtom(atom, size, atom.alignment); log.debug("allocated stub helper atom at 0x{x}", .{sym.n_value}); @@ -1351,15 +1331,11 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLoc) !*Atom { const gpa = self.base.allocator; - const sym_index = try self.allocateSymbol(); - const atom = blk: { - const atom = try gpa.create(Atom); - atom.* = Atom.empty; - atom.sym_index = sym_index; - atom.size = @sizeOf(u64); - atom.alignment = @alignOf(u64); - break :blk atom; - }; + const atom = try gpa.create(Atom); + atom.* = Atom.empty; + try atom.ensureInitialized(self); + atom.size = @sizeOf(u64); + atom.alignment = @alignOf(u64); errdefer gpa.destroy(atom); const sym = atom.getSymbolPtr(self); @@ -1385,7 +1361,6 @@ pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWi }); try self.managed_atoms.append(gpa, atom); - try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); sym.n_value = try self.allocateAtom(atom, atom.size, @alignOf(u64)); log.debug("allocated lazy pointer atom at 0x{x} ({s})", .{ sym.n_value, self.getSymbolName(target) }); @@ -1402,19 +1377,15 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { .aarch64 => 3 * @sizeOf(u32), else => unreachable, // unhandled architecture type }; - const sym_index = try self.allocateSymbol(); - const atom = blk: { - const atom = try gpa.create(Atom); - atom.* = Atom.empty; - atom.sym_index = sym_index; - atom.size = size; - atom.alignment = switch (arch) { - .x86_64 => 1, - .aarch64 => @alignOf(u32), - else => unreachable, // unhandled architecture type + const atom = try gpa.create(Atom); + atom.* = Atom.empty; + try atom.ensureInitialized(self); + atom.size = size; + atom.alignment = switch (arch) { + .x86_64 => 1, + .aarch64 => @alignOf(u32), + else => unreachable, // unhandled architecture type - }; - break :blk atom; }; errdefer gpa.destroy(atom); @@ -1476,7 +1447,6 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { } try self.managed_atoms.append(gpa, atom); - try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom); sym.n_value = try self.allocateAtom(atom, size, atom.alignment); log.debug("allocated stub atom at 0x{x}", .{sym.n_value}); @@ -1617,9 +1587,9 @@ pub fn resolveSymbolsInDylibs(self: *MachO) !void { const stub_index = try self.allocateStubEntry(global); const stub_helper_atom = try self.createStubHelperAtom(); - const laptr_atom = try self.createLazyPointerAtom(stub_helper_atom.sym_index, global); - const stub_atom = try self.createStubAtom(laptr_atom.sym_index); - self.stubs.items[stub_index].sym_index = stub_atom.sym_index; + const laptr_atom = try self.createLazyPointerAtom(stub_helper_atom.getSymbolIndex().?, global); + const stub_atom = try self.createStubAtom(laptr_atom.getSymbolIndex().?); + self.stubs.items[stub_index].sym_index = stub_atom.getSymbolIndex().?; self.markRelocsDirtyByTarget(global); } @@ -1717,7 +1687,7 @@ pub fn resolveDyldStubBinder(self: *MachO) !void { // Add dyld_stub_binder as the final GOT entry. const got_index = try self.allocateGotEntry(global); const got_atom = try self.createGotAtom(global); - self.got_entries.items[got_index].sym_index = got_atom.sym_index; + self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?; try self.writePtrWidthAtom(got_atom); } @@ -2098,14 +2068,11 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu const atom = try gpa.create(Atom); errdefer gpa.destroy(atom); atom.* = Atom.empty; - - atom.sym_index = try self.allocateSymbol(); - + try atom.ensureInitialized(self); try self.managed_atoms.append(gpa, atom); - try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom); const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none, .{ - .parent_atom_index = atom.sym_index, + .parent_atom_index = atom.getSymbolIndex().?, }); const code = switch (res) { .ok => code_buffer.items, @@ -2137,7 +2104,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu try self.writeAtom(atom, code); - return atom.sym_index; + return atom.getSymbolIndex().?; } pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index) !void { @@ -2188,14 +2155,14 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index) }, &code_buffer, .{ .dwarf = ds, }, .{ - .parent_atom_index = decl.link.macho.sym_index, + .parent_atom_index = decl.link.macho.getSymbolIndex().?, }) else try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ .ty = decl.ty, .val = decl_val, }, &code_buffer, .none, .{ - .parent_atom_index = decl.link.macho.sym_index, + .parent_atom_index = decl.link.macho.getSymbolIndex().?, }); const code = switch (res) { |
