aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-02-10 14:41:07 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-02-11 10:52:13 +0100
commitb9b1ab024063105a9adfe3828692867c91015dc6 (patch)
treeae0c2e67953f9fbb308ecb17d5bdd8438747cca9 /src
parent08e2f5d08390d41b58c92707693385e5e2968fc8 (diff)
downloadzig-b9b1ab024063105a9adfe3828692867c91015dc6.tar.gz
zig-b9b1ab024063105a9adfe3828692867c91015dc6.zip
elf: store pointer relocations indexed by containing atom
In `getDeclVAddr`, it may happen that the target `Decl` has not been allocated space in virtual memory. In this case, we store a relocation in the linker-global table which we will iterate over when flushing the module, and fill in any missing address in the final binary. Note that for optimisation, if the address was resolved at the time of a call to `getDeclVAddr`, we skip relocating this atom. This commit also adds the glue code for lowering const slices in the ARM backend.
Diffstat (limited to 'src')
-rw-r--r--src/arch/arm/CodeGen.zig25
-rw-r--r--src/codegen.zig30
-rw-r--r--src/link.zig14
-rw-r--r--src/link/Coff.zig8
-rw-r--r--src/link/Elf.zig113
-rw-r--r--src/link/MachO.zig53
-rw-r--r--src/link/Plan9.zig6
7 files changed, 163 insertions, 86 deletions
diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig
index 711e2a96f0..2c60027d97 100644
--- a/src/arch/arm/CodeGen.zig
+++ b/src/arch/arm/CodeGen.zig
@@ -3931,23 +3931,20 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
switch (typed_value.ty.zigTypeTag()) {
.Pointer => switch (typed_value.ty.ptrSize()) {
.Slice => {
- var buf: Type.SlicePtrFieldTypeBuffer = undefined;
- const ptr_type = typed_value.ty.slicePtrFieldType(&buf);
- const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val });
- const slice_len = typed_value.val.sliceLen();
- // Codegen can't handle some kinds of indirection. If the wrong union field is accessed here it may mean
- // the Sema code needs to use anonymous Decls or alloca instructions to store data.
- const ptr_imm = ptr_mcv.memory;
- _ = slice_len;
- _ = ptr_imm;
- // We need more general support for const data being stored in memory to make this work.
- return self.fail("TODO codegen for const slices", .{});
+ return self.lowerUnnamedConst(typed_value);
},
else => {
- if (typed_value.val.tag() == .int_u64) {
- return MCValue{ .immediate = @intCast(u32, typed_value.val.toUnsignedInt()) };
+ switch (typed_value.val.tag()) {
+ .int_u64 => {
+ return MCValue{ .immediate = @intCast(u32, typed_value.val.toUnsignedInt()) };
+ },
+ .slice => {
+ return self.lowerUnnamedConst(typed_value);
+ },
+ else => {
+ return self.fail("TODO codegen more kinds of const pointers", .{});
+ },
}
- return self.fail("TODO codegen more kinds of const pointers", .{});
},
},
.Int => {
diff --git a/src/codegen.zig b/src/codegen.zig
index 389f38a020..fd4321fee9 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -142,6 +142,7 @@ pub fn generateFunction(
pub fn generateSymbol(
bin_file: *link.File,
+ parent_atom_index: u32,
src_loc: Module.SrcLoc,
typed_value: TypedValue,
code: *std.ArrayList(u8),
@@ -177,7 +178,7 @@ pub fn generateSymbol(
if (typed_value.ty.sentinel()) |sentinel| {
try code.ensureUnusedCapacity(payload.data.len + 1);
code.appendSliceAssumeCapacity(payload.data);
- switch (try generateSymbol(bin_file, src_loc, .{
+ switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
.ty = typed_value.ty.elemType(),
.val = sentinel,
}, code, debug_output)) {
@@ -197,7 +198,7 @@ pub fn generateSymbol(
const elem_vals = typed_value.val.castTag(.array).?.data;
const elem_ty = typed_value.ty.elemType();
for (elem_vals) |elem_val| {
- switch (try generateSymbol(bin_file, src_loc, .{
+ switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
.ty = elem_ty,
.val = elem_val,
}, code, debug_output)) {
@@ -223,11 +224,11 @@ pub fn generateSymbol(
.Pointer => switch (typed_value.val.tag()) {
.variable => {
const decl = typed_value.val.castTag(.variable).?.data.owner_decl;
- return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output);
+ return lowerDeclRef(bin_file, parent_atom_index, src_loc, typed_value, decl, code, debug_output);
},
.decl_ref => {
const decl = typed_value.val.castTag(.decl_ref).?.data;
- return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output);
+ return lowerDeclRef(bin_file, parent_atom_index, src_loc, typed_value, decl, code, debug_output);
},
.slice => {
const slice = typed_value.val.castTag(.slice).?.data;
@@ -235,7 +236,7 @@ pub fn generateSymbol(
// generate ptr
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);
- switch (try generateSymbol(bin_file, src_loc, .{
+ switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
.ty = slice_ptr_field_type,
.val = slice.ptr,
}, code, debug_output)) {
@@ -247,7 +248,7 @@ pub fn generateSymbol(
}
// generate length
- switch (try generateSymbol(bin_file, src_loc, .{
+ switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
.ty = Type.initTag(.usize),
.val = slice.len,
}, code, debug_output)) {
@@ -391,7 +392,7 @@ pub fn generateSymbol(
const field_ty = typed_value.ty.structFieldType(index);
if (!field_ty.hasRuntimeBits()) continue;
- switch (try generateSymbol(bin_file, src_loc, .{
+ switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
.ty = field_ty,
.val = field_val,
}, code, debug_output)) {
@@ -446,6 +447,7 @@ pub fn generateSymbol(
fn lowerDeclRef(
bin_file: *link.File,
+ parent_atom_index: u32,
src_loc: Module.SrcLoc,
typed_value: TypedValue,
decl: *Module.Decl,
@@ -456,7 +458,7 @@ fn lowerDeclRef(
// generate ptr
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);
- switch (try generateSymbol(bin_file, src_loc, .{
+ switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
.ty = slice_ptr_field_type,
.val = typed_value.val,
}, code, debug_output)) {
@@ -472,7 +474,7 @@ fn lowerDeclRef(
.base = .{ .tag = .int_u64 },
.data = typed_value.val.sliceLen(),
};
- switch (try generateSymbol(bin_file, src_loc, .{
+ switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
.ty = Type.initTag(.usize),
.val = Value.initPayload(&slice_len.base),
}, code, debug_output)) {
@@ -495,15 +497,7 @@ fn lowerDeclRef(
}
decl.markAlive();
- const vaddr = vaddr: {
- if (bin_file.cast(link.File.MachO)) |macho_file| {
- break :vaddr try macho_file.getDeclVAddrWithReloc(decl, code.items.len);
- }
- // TODO handle the dependency of this symbol on the decl's vaddr.
- // If the decl changes vaddr, then this symbol needs to get regenerated.
- break :vaddr bin_file.getDeclVAddr(decl);
- };
-
+ const vaddr = try bin_file.getDeclVAddr(decl, parent_atom_index, code.items.len);
const endian = target.cpu.arch.endian();
switch (ptr_width) {
16 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(u16, vaddr), endian),
diff --git a/src/link.zig b/src/link.zig
index 56b88bffef..c5d14eb75a 100644
--- a/src/link.zig
+++ b/src/link.zig
@@ -684,12 +684,16 @@ pub const File = struct {
}
}
- pub fn getDeclVAddr(base: *File, decl: *const Module.Decl) u64 {
+ /// Get allocated `Decl`'s address in virtual memory.
+ /// The linker is passed information about the containing atom, `parent_atom_index`, and offset within it's
+ /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the
+ /// `Decl`'s address was not yet resolved, or the containing atom gets moved in virtual memory.
+ pub fn getDeclVAddr(base: *File, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {
switch (base.tag) {
- .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl),
- .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl),
- .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl),
- .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl),
+ .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl, parent_atom_index, offset),
+ .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl, parent_atom_index, offset),
+ .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl, parent_atom_index, offset),
+ .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl, parent_atom_index, offset),
.c => unreachable,
.wasm => unreachable,
.spirv => unreachable,
diff --git a/src/link/Coff.zig b/src/link/Coff.zig
index 2f500e6b91..32d4d38235 100644
--- a/src/link/Coff.zig
+++ b/src/link/Coff.zig
@@ -726,7 +726,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
defer code_buffer.deinit();
- const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
+ const res = try codegen.generateSymbol(&self.base, 0, decl.srcLoc(), .{
.ty = decl.ty,
.val = decl.val,
}, &code_buffer, .none);
@@ -751,7 +751,7 @@ fn finishUpdateDecl(self: *Coff, module: *Module, decl: *Module.Decl, code: []co
const need_realloc = code.len > capacity or
!mem.isAlignedGeneric(u32, decl.link.coff.text_offset, required_alignment);
if (need_realloc) {
- const curr_vaddr = self.getDeclVAddr(decl);
+ const curr_vaddr = self.text_section_virtual_address + decl.link.coff.text_offset;
const vaddr = try self.growTextBlock(&decl.link.coff, code.len, required_alignment);
log.debug("growing {s} from 0x{x} to 0x{x}\n", .{ decl.name, curr_vaddr, vaddr });
if (vaddr != curr_vaddr) {
@@ -1465,7 +1465,9 @@ fn findLib(self: *Coff, arena: Allocator, name: []const u8) !?[]const u8 {
return null;
}
-pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl) u64 {
+pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {
+ _ = parent_atom_index;
+ _ = offset;
assert(self.llvm_object == null);
return self.text_section_virtual_address + decl.link.coff.text_offset;
}
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index 23bd5bb2dd..467bbeee54 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -145,6 +145,7 @@ decls: std.AutoHashMapUnmanaged(*Module.Decl, ?u16) = .{},
/// at present owned by Module.Decl.
/// TODO consolidate this.
managed_atoms: std.ArrayListUnmanaged(*TextBlock) = .{},
+atom_by_index_table: std.AutoHashMapUnmanaged(u32, *TextBlock) = .{},
/// Table of unnamed constants associated with a parent `Decl`.
/// We store them here so that we can free the constants whenever the `Decl`
@@ -179,6 +180,18 @@ dbg_info_decl_free_list: std.AutoHashMapUnmanaged(*TextBlock, void) = .{},
dbg_info_decl_first: ?*TextBlock = null,
dbg_info_decl_last: ?*TextBlock = null,
+/// A table of relocations indexed by the owning them `TextBlock`.
+/// Note that once we refactor `TextBlock`'s lifetime and ownership rules,
+/// this will be a table indexed by index into the list of Atoms.
+relocs: RelocTable = .{},
+
+const Reloc = struct {
+ target: u32,
+ offset: u64,
+ prev_vaddr: u64,
+};
+
+const RelocTable = std.AutoHashMapUnmanaged(*TextBlock, std.ArrayListUnmanaged(Reloc));
const UnnamedConstTable = std.AutoHashMapUnmanaged(*Module.Decl, std.ArrayListUnmanaged(*TextBlock));
/// When allocating, the ideal_capacity is calculated by
@@ -397,12 +410,36 @@ pub fn deinit(self: *Elf) void {
}
self.unnamed_const_atoms.deinit(self.base.allocator);
}
+
+ {
+ var it = self.relocs.valueIterator();
+ while (it.next()) |relocs| {
+ relocs.deinit(self.base.allocator);
+ }
+ self.relocs.deinit(self.base.allocator);
+ }
+
+ self.atom_by_index_table.deinit(self.base.allocator);
}
-pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl) u64 {
+pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {
assert(self.llvm_object == null);
assert(decl.link.elf.local_sym_index != 0);
- return self.local_symbols.items[decl.link.elf.local_sym_index].st_value;
+
+ const target = decl.link.elf.local_sym_index;
+ const vaddr = self.local_symbols.items[target].st_value;
+ const atom = self.atom_by_index_table.get(parent_atom_index).?;
+ const gop = try self.relocs.getOrPut(self.base.allocator, atom);
+ if (!gop.found_existing) {
+ gop.value_ptr.* = .{};
+ }
+ try gop.value_ptr.append(self.base.allocator, .{
+ .target = target,
+ .offset = offset,
+ .prev_vaddr = vaddr,
+ });
+
+ return vaddr;
}
fn getDebugLineProgramOff(self: Elf) u32 {
@@ -991,6 +1028,41 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
.p64 => 12,
};
+ {
+ var it = self.relocs.iterator();
+ 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_shdr = self.sections.items[source_sym.st_shndx];
+
+ log.debug("relocating '{s}'", .{self.getString(source_sym.st_name)});
+
+ for (relocs.items) |*reloc| {
+ const target_sym = self.local_symbols.items[reloc.target];
+ const target_vaddr = target_sym.st_value;
+
+ if (target_vaddr == reloc.prev_vaddr) continue;
+
+ const section_offset = (source_sym.st_value + reloc.offset) - source_shdr.sh_addr;
+ const file_offset = source_shdr.sh_offset + section_offset;
+
+ log.debug(" ({x}: [() => 0x{x}] ({s}))", .{
+ reloc.offset,
+ target_vaddr,
+ self.getString(target_sym.st_name),
+ });
+
+ switch (self.ptr_width) {
+ .p32 => try self.base.file.?.pwriteAll(mem.asBytes(&@intCast(u32, target_vaddr)), file_offset),
+ .p64 => try self.base.file.?.pwriteAll(mem.asBytes(&target_vaddr), file_offset),
+ }
+
+ reloc.prev_vaddr = target_vaddr;
+ }
+ }
+ }
+
// Unfortunately these have to be buffered and done at the end because ELF does not allow
// mixing local and global symbols within a symbol table.
try self.writeAllGlobalSymbols();
@@ -2508,6 +2580,7 @@ pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {
log.debug("allocating symbol indexes for {s}", .{decl.name});
decl.link.elf.local_sym_index = try self.allocateLocalSymbol();
+ try self.atom_by_index_table.putNoClobber(self.base.allocator, decl.link.elf.local_sym_index, &decl.link.elf);
if (self.offset_table_free_list.popOrNull()) |i| {
decl.link.elf.offset_table_index = i;
@@ -2525,6 +2598,7 @@ fn freeUnnamedConsts(self: *Elf, decl: *Module.Decl) void {
self.freeTextBlock(atom, self.phdr_load_ro_index.?);
self.local_symbol_free_list.append(self.base.allocator, atom.local_sym_index) catch {};
self.local_symbols.items[atom.local_sym_index].st_info = 0;
+ _ = self.atom_by_index_table.remove(atom.local_sym_index);
}
unnamed_consts.clearAndFree(self.base.allocator);
}
@@ -2543,11 +2617,11 @@ pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {
// Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
if (decl.link.elf.local_sym_index != 0) {
self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {};
- self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {};
-
self.local_symbols.items[decl.link.elf.local_sym_index].st_info = 0;
-
+ _ = self.atom_by_index_table.remove(decl.link.elf.local_sym_index);
decl.link.elf.local_sym_index = 0;
+
+ self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {};
}
// TODO make this logic match freeTextBlock. Maybe abstract the logic out since the same thing
// is desired for both.
@@ -2993,7 +3067,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
// TODO implement .debug_info for global variables
const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
- const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
+ const res = try codegen.generateSymbol(&self.base, decl.link.elf.local_sym_index, decl.srcLoc(), .{
.ty = decl.ty,
.val = decl_val,
}, &code_buffer, .{
@@ -3028,19 +3102,6 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl
}
const unnamed_consts = gop.value_ptr;
- const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{
- .none = .{},
- });
- const code = switch (res) {
- .externally_managed => |x| x,
- .appended => code_buffer.items,
- .fail => |em| {
- decl.analysis = .codegen_failure;
- try module.failed_decls.put(module.gpa, decl, em);
- return error.AnalysisFail;
- },
- };
-
const atom = try self.base.allocator.create(TextBlock);
errdefer self.base.allocator.destroy(atom);
atom.* = TextBlock.empty;
@@ -3056,6 +3117,20 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl
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, atom.local_sym_index, decl.srcLoc(), typed_value, &code_buffer, .{
+ .none = .{},
+ });
+ const code = switch (res) {
+ .externally_managed => |x| x,
+ .appended => code_buffer.items,
+ .fail => |em| {
+ decl.analysis = .codegen_failure;
+ try module.failed_decls.put(module.gpa, decl, em);
+ return error.AnalysisFail;
+ },
+ };
const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);
const phdr_index = self.phdr_load_ro_index.?;
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 065145cdc8..37040f267f 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -3745,19 +3745,6 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De
}
const unnamed_consts = gop.value_ptr;
- const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{
- .none = .{},
- });
- const code = switch (res) {
- .externally_managed => |x| x,
- .appended => code_buffer.items,
- .fail => |em| {
- decl.analysis = .codegen_failure;
- try module.failed_decls.put(module.gpa, decl, em);
- return error.AnalysisFail;
- },
- };
-
const name_str_index = blk: {
const index = unnamed_consts.items.len;
const name = try std.fmt.allocPrint(self.base.allocator, "__unnamed_{s}_{d}", .{ decl.name, index });
@@ -3772,12 +3759,27 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De
const match = (try self.getMatchingSection(.{
.segname = makeStaticString("__TEXT"),
.sectname = makeStaticString("__const"),
- .size = code.len,
+ .size = @sizeOf(u64),
.@"align" = math.log2(required_alignment),
})).?;
const local_sym_index = try self.allocateLocalSymbol();
- const atom = try self.createEmptyAtom(local_sym_index, code.len, math.log2(required_alignment));
- mem.copy(u8, atom.code.items, code);
+ const atom = try self.createEmptyAtom(local_sym_index, @sizeOf(u64), math.log2(required_alignment));
+
+ const res = try codegen.generateSymbol(&self.base, local_sym_index, decl.srcLoc(), typed_value, &code_buffer, .{
+ .none = .{},
+ });
+ const code = switch (res) {
+ .externally_managed => |x| x,
+ .appended => code_buffer.items,
+ .fail => |em| {
+ decl.analysis = .codegen_failure;
+ try module.failed_decls.put(module.gpa, decl, em);
+ return error.AnalysisFail;
+ },
+ };
+
+ atom.code.clearRetainingCapacity();
+ try atom.code.appendSlice(self.base.allocator, code);
const addr = try self.allocateAtom(atom, code.len, required_alignment, match);
log.debug("allocated atom for {s} at 0x{x}", .{ name, addr });
@@ -3841,7 +3843,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
const res = if (debug_buffers) |dbg|
- try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
+ try codegen.generateSymbol(&self.base, decl.link.elf.local_sym_index, decl.srcLoc(), .{
.ty = decl.ty,
.val = decl_val,
}, &code_buffer, .{
@@ -3852,7 +3854,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
},
})
else
- try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
+ try codegen.generateSymbol(&self.base, decl.link.elf.local_sym_index, decl.srcLoc(), .{
.ty = decl.ty,
.val = decl_val,
}, &code_buffer, .none);
@@ -4341,16 +4343,17 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {
}
}
-pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 {
+pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {
+ assert(self.llvm_object == null);
assert(decl.link.macho.local_sym_index != 0);
- return self.locals.items[decl.link.macho.local_sym_index].n_value;
-}
-pub fn getDeclVAddrWithReloc(self: *MachO, decl: *const Module.Decl, offset: u64) !u64 {
- assert(decl.link.macho.local_sym_index != 0);
- assert(self.active_decl != null);
+ // TODO cache local_sym_index => atom!!!
+ const atom: *Atom = blk: for (self.managed_atoms.items) |atom| {
+ if (atom.local_sym_index == parent_atom_index) {
+ break :blk atom;
+ }
+ } else unreachable;
- const atom = &self.active_decl.?.link.macho;
try atom.relocs.append(self.base.allocator, .{
.offset = @intCast(u32, offset),
.target = .{ .local = decl.link.macho.local_sym_index },
diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig
index c2d6d61066..ee7272ca8d 100644
--- a/src/link/Plan9.zig
+++ b/src/link/Plan9.zig
@@ -302,7 +302,7 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl: *Module.Decl) !void {
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
defer code_buffer.deinit();
const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
- const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
+ const res = try codegen.generateSymbol(&self.base, @intCast(u32, decl.link.plan9.sym_index.?), decl.srcLoc(), .{
.ty = decl.ty,
.val = decl_val,
}, &code_buffer, .{ .none = .{} });
@@ -749,7 +749,9 @@ pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void {
_ = self;
_ = decl;
}
-pub fn getDeclVAddr(self: *Plan9, decl: *const Module.Decl) u64 {
+pub fn getDeclVAddr(self: *Plan9, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {
+ _ = parent_atom_index;
+ _ = offset;
if (decl.ty.zigTypeTag() == .Fn) {
var start = self.bases.text;
var it_file = self.fn_decl_table.iterator();