authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-10 14:41:07+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-11 10:52:13+01:00
logb9b1ab024063105a9adfe3828692867c91015dc6
treeae0c2e67953f9fbb308ecb17d5bdd8438747cca9
parent08e2f5d08390d41b58c92707693385e5e2968fc8

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.

7 files changed, 163 insertions(+), 86 deletions(-)

src/arch/arm/CodeGen.zig+11-14
......@@ -3931,23 +3931,20 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
39313931 switch (typed_value.ty.zigTypeTag()) {
39323932 .Pointer => switch (typed_value.ty.ptrSize()) {
39333933 .Slice => {
3934 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
3935 const ptr_type = typed_value.ty.slicePtrFieldType(&buf);
3936 const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val });
3937 const slice_len = typed_value.val.sliceLen();
3938 // Codegen can't handle some kinds of indirection. If the wrong union field is accessed here it may mean
3939 // the Sema code needs to use anonymous Decls or alloca instructions to store data.
3940 const ptr_imm = ptr_mcv.memory;
3941 _ = slice_len;
3942 _ = ptr_imm;
3943 // We need more general support for const data being stored in memory to make this work.
3944 return self.fail("TODO codegen for const slices", .{});
3934 return self.lowerUnnamedConst(typed_value);
39453935 },
39463936 else => {
3947 if (typed_value.val.tag() == .int_u64) {
3948 return MCValue{ .immediate = @intCast(u32, typed_value.val.toUnsignedInt()) };
3937 switch (typed_value.val.tag()) {
3938 .int_u64 => {
3939 return MCValue{ .immediate = @intCast(u32, typed_value.val.toUnsignedInt()) };
3940 },
3941 .slice => {
3942 return self.lowerUnnamedConst(typed_value);
3943 },
3944 else => {
3945 return self.fail("TODO codegen more kinds of const pointers", .{});
3946 },
39493947 }
3950 return self.fail("TODO codegen more kinds of const pointers", .{});
39513948 },
39523949 },
39533950 .Int => {
src/codegen.zig+12-18
......@@ -142,6 +142,7 @@ pub fn generateFunction(
142142
143143pub fn generateSymbol(
144144 bin_file: *link.File,
145 parent_atom_index: u32,
145146 src_loc: Module.SrcLoc,
146147 typed_value: TypedValue,
147148 code: *std.ArrayList(u8),
......@@ -177,7 +178,7 @@ pub fn generateSymbol(
177178 if (typed_value.ty.sentinel()) |sentinel| {
178179 try code.ensureUnusedCapacity(payload.data.len + 1);
179180 code.appendSliceAssumeCapacity(payload.data);
180 switch (try generateSymbol(bin_file, src_loc, .{
181 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
181182 .ty = typed_value.ty.elemType(),
182183 .val = sentinel,
183184 }, code, debug_output)) {
......@@ -197,7 +198,7 @@ pub fn generateSymbol(
197198 const elem_vals = typed_value.val.castTag(.array).?.data;
198199 const elem_ty = typed_value.ty.elemType();
199200 for (elem_vals) |elem_val| {
200 switch (try generateSymbol(bin_file, src_loc, .{
201 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
201202 .ty = elem_ty,
202203 .val = elem_val,
203204 }, code, debug_output)) {
......@@ -223,11 +224,11 @@ pub fn generateSymbol(
223224 .Pointer => switch (typed_value.val.tag()) {
224225 .variable => {
225226 const decl = typed_value.val.castTag(.variable).?.data.owner_decl;
226 return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output);
227 return lowerDeclRef(bin_file, parent_atom_index, src_loc, typed_value, decl, code, debug_output);
227228 },
228229 .decl_ref => {
229230 const decl = typed_value.val.castTag(.decl_ref).?.data;
230 return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output);
231 return lowerDeclRef(bin_file, parent_atom_index, src_loc, typed_value, decl, code, debug_output);
231232 },
232233 .slice => {
233234 const slice = typed_value.val.castTag(.slice).?.data;
......@@ -235,7 +236,7 @@ pub fn generateSymbol(
235236 // generate ptr
236237 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
237238 const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);
238 switch (try generateSymbol(bin_file, src_loc, .{
239 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
239240 .ty = slice_ptr_field_type,
240241 .val = slice.ptr,
241242 }, code, debug_output)) {
......@@ -247,7 +248,7 @@ pub fn generateSymbol(
247248 }
248249
249250 // generate length
250 switch (try generateSymbol(bin_file, src_loc, .{
251 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
251252 .ty = Type.initTag(.usize),
252253 .val = slice.len,
253254 }, code, debug_output)) {
......@@ -391,7 +392,7 @@ pub fn generateSymbol(
391392 const field_ty = typed_value.ty.structFieldType(index);
392393 if (!field_ty.hasRuntimeBits()) continue;
393394
394 switch (try generateSymbol(bin_file, src_loc, .{
395 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
395396 .ty = field_ty,
396397 .val = field_val,
397398 }, code, debug_output)) {
......@@ -446,6 +447,7 @@ pub fn generateSymbol(
446447
447448fn lowerDeclRef(
448449 bin_file: *link.File,
450 parent_atom_index: u32,
449451 src_loc: Module.SrcLoc,
450452 typed_value: TypedValue,
451453 decl: *Module.Decl,
......@@ -456,7 +458,7 @@ fn lowerDeclRef(
456458 // generate ptr
457459 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
458460 const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);
459 switch (try generateSymbol(bin_file, src_loc, .{
461 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
460462 .ty = slice_ptr_field_type,
461463 .val = typed_value.val,
462464 }, code, debug_output)) {
......@@ -472,7 +474,7 @@ fn lowerDeclRef(
472474 .base = .{ .tag = .int_u64 },
473475 .data = typed_value.val.sliceLen(),
474476 };
475 switch (try generateSymbol(bin_file, src_loc, .{
477 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
476478 .ty = Type.initTag(.usize),
477479 .val = Value.initPayload(&slice_len.base),
478480 }, code, debug_output)) {
......@@ -495,15 +497,7 @@ fn lowerDeclRef(
495497 }
496498
497499 decl.markAlive();
498 const vaddr = vaddr: {
499 if (bin_file.cast(link.File.MachO)) |macho_file| {
500 break :vaddr try macho_file.getDeclVAddrWithReloc(decl, code.items.len);
501 }
502 // TODO handle the dependency of this symbol on the decl's vaddr.
503 // If the decl changes vaddr, then this symbol needs to get regenerated.
504 break :vaddr bin_file.getDeclVAddr(decl);
505 };
506
500 const vaddr = try bin_file.getDeclVAddr(decl, parent_atom_index, code.items.len);
507501 const endian = target.cpu.arch.endian();
508502 switch (ptr_width) {
509503 16 => mem.writeInt(u16, try code.addManyAsArray(2), @intCast(u16, vaddr), endian),
src/link.zig+9-5
......@@ -684,12 +684,16 @@ pub const File = struct {
684684 }
685685 }
686686
687 pub fn getDeclVAddr(base: *File, decl: *const Module.Decl) u64 {
687 /// Get allocated `Decl`'s address in virtual memory.
688 /// The linker is passed information about the containing atom, `parent_atom_index`, and offset within it's
689 /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the
690 /// `Decl`'s address was not yet resolved, or the containing atom gets moved in virtual memory.
691 pub fn getDeclVAddr(base: *File, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {
688692 switch (base.tag) {
689 .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl),
690 .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl),
691 .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl),
692 .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl),
693 .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl, parent_atom_index, offset),
694 .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl, parent_atom_index, offset),
695 .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl, parent_atom_index, offset),
696 .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl, parent_atom_index, offset),
693697 .c => unreachable,
694698 .wasm => unreachable,
695699 .spirv => unreachable,
src/link/Coff.zig+5-3
......@@ -726,7 +726,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
726726 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
727727 defer code_buffer.deinit();
728728
729 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
729 const res = try codegen.generateSymbol(&self.base, 0, decl.srcLoc(), .{
730730 .ty = decl.ty,
731731 .val = decl.val,
732732 }, &code_buffer, .none);
......@@ -751,7 +751,7 @@ fn finishUpdateDecl(self: *Coff, module: *Module, decl: *Module.Decl, code: []co
751751 const need_realloc = code.len > capacity or
752752 !mem.isAlignedGeneric(u32, decl.link.coff.text_offset, required_alignment);
753753 if (need_realloc) {
754 const curr_vaddr = self.getDeclVAddr(decl);
754 const curr_vaddr = self.text_section_virtual_address + decl.link.coff.text_offset;
755755 const vaddr = try self.growTextBlock(&decl.link.coff, code.len, required_alignment);
756756 log.debug("growing {s} from 0x{x} to 0x{x}\n", .{ decl.name, curr_vaddr, vaddr });
757757 if (vaddr != curr_vaddr) {
......@@ -1465,7 +1465,9 @@ fn findLib(self: *Coff, arena: Allocator, name: []const u8) !?[]const u8 {
14651465 return null;
14661466}
14671467
1468pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl) u64 {
1468pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {
1469 _ = parent_atom_index;
1470 _ = offset;
14691471 assert(self.llvm_object == null);
14701472 return self.text_section_virtual_address + decl.link.coff.text_offset;
14711473}
src/link/Elf.zig+94-19
......@@ -145,6 +145,7 @@ decls: std.AutoHashMapUnmanaged(*Module.Decl, ?u16) = .{},
145145/// at present owned by Module.Decl.
146146/// TODO consolidate this.
147147managed_atoms: std.ArrayListUnmanaged(*TextBlock) = .{},
148atom_by_index_table: std.AutoHashMapUnmanaged(u32, *TextBlock) = .{},
148149
149150/// Table of unnamed constants associated with a parent `Decl`.
150151/// 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) = .{},
179180dbg_info_decl_first: ?*TextBlock = null,
180181dbg_info_decl_last: ?*TextBlock = null,
181182
183/// A table of relocations indexed by the owning them `TextBlock`.
184/// Note that once we refactor `TextBlock`'s lifetime and ownership rules,
185/// this will be a table indexed by index into the list of Atoms.
186relocs: RelocTable = .{},
187
188const Reloc = struct {
189 target: u32,
190 offset: u64,
191 prev_vaddr: u64,
192};
193
194const RelocTable = std.AutoHashMapUnmanaged(*TextBlock, std.ArrayListUnmanaged(Reloc));
182195const UnnamedConstTable = std.AutoHashMapUnmanaged(*Module.Decl, std.ArrayListUnmanaged(*TextBlock));
183196
184197/// When allocating, the ideal_capacity is calculated by
......@@ -397,12 +410,36 @@ pub fn deinit(self: *Elf) void {
397410 }
398411 self.unnamed_const_atoms.deinit(self.base.allocator);
399412 }
413
414 {
415 var it = self.relocs.valueIterator();
416 while (it.next()) |relocs| {
417 relocs.deinit(self.base.allocator);
418 }
419 self.relocs.deinit(self.base.allocator);
420 }
421
422 self.atom_by_index_table.deinit(self.base.allocator);
400423}
401424
402pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl) u64 {
425pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {
403426 assert(self.llvm_object == null);
404427 assert(decl.link.elf.local_sym_index != 0);
405 return self.local_symbols.items[decl.link.elf.local_sym_index].st_value;
428
429 const target = decl.link.elf.local_sym_index;
430 const vaddr = self.local_symbols.items[target].st_value;
431 const atom = self.atom_by_index_table.get(parent_atom_index).?;
432 const gop = try self.relocs.getOrPut(self.base.allocator, atom);
433 if (!gop.found_existing) {
434 gop.value_ptr.* = .{};
435 }
436 try gop.value_ptr.append(self.base.allocator, .{
437 .target = target,
438 .offset = offset,
439 .prev_vaddr = vaddr,
440 });
441
442 return vaddr;
406443}
407444
408445fn getDebugLineProgramOff(self: Elf) u32 {
......@@ -991,6 +1028,41 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
9911028 .p64 => 12,
9921029 };
9931030
1031 {
1032 var it = self.relocs.iterator();
1033 while (it.next()) |entry| {
1034 const atom = entry.key_ptr.*;
1035 const relocs = entry.value_ptr.*;
1036 const source_sym = self.local_symbols.items[atom.local_sym_index];
1037 const source_shdr = self.sections.items[source_sym.st_shndx];
1038
1039 log.debug("relocating '{s}'", .{self.getString(source_sym.st_name)});
1040
1041 for (relocs.items) |*reloc| {
1042 const target_sym = self.local_symbols.items[reloc.target];
1043 const target_vaddr = target_sym.st_value;
1044
1045 if (target_vaddr == reloc.prev_vaddr) continue;
1046
1047 const section_offset = (source_sym.st_value + reloc.offset) - source_shdr.sh_addr;
1048 const file_offset = source_shdr.sh_offset + section_offset;
1049
1050 log.debug(" ({x}: [() => 0x{x}] ({s}))", .{
1051 reloc.offset,
1052 target_vaddr,
1053 self.getString(target_sym.st_name),
1054 });
1055
1056 switch (self.ptr_width) {
1057 .p32 => try self.base.file.?.pwriteAll(mem.asBytes(&@intCast(u32, target_vaddr)), file_offset),
1058 .p64 => try self.base.file.?.pwriteAll(mem.asBytes(&target_vaddr), file_offset),
1059 }
1060
1061 reloc.prev_vaddr = target_vaddr;
1062 }
1063 }
1064 }
1065
9941066 // Unfortunately these have to be buffered and done at the end because ELF does not allow
9951067 // mixing local and global symbols within a symbol table.
9961068 try self.writeAllGlobalSymbols();
......@@ -2508,6 +2580,7 @@ pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {
25082580
25092581 log.debug("allocating symbol indexes for {s}", .{decl.name});
25102582 decl.link.elf.local_sym_index = try self.allocateLocalSymbol();
2583 try self.atom_by_index_table.putNoClobber(self.base.allocator, decl.link.elf.local_sym_index, &decl.link.elf);
25112584
25122585 if (self.offset_table_free_list.popOrNull()) |i| {
25132586 decl.link.elf.offset_table_index = i;
......@@ -2525,6 +2598,7 @@ fn freeUnnamedConsts(self: *Elf, decl: *Module.Decl) void {
25252598 self.freeTextBlock(atom, self.phdr_load_ro_index.?);
25262599 self.local_symbol_free_list.append(self.base.allocator, atom.local_sym_index) catch {};
25272600 self.local_symbols.items[atom.local_sym_index].st_info = 0;
2601 _ = self.atom_by_index_table.remove(atom.local_sym_index);
25282602 }
25292603 unnamed_consts.clearAndFree(self.base.allocator);
25302604}
......@@ -2543,11 +2617,11 @@ pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {
25432617 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
25442618 if (decl.link.elf.local_sym_index != 0) {
25452619 self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {};
2546 self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {};
2547
25482620 self.local_symbols.items[decl.link.elf.local_sym_index].st_info = 0;
2549
2621 _ = self.atom_by_index_table.remove(decl.link.elf.local_sym_index);
25502622 decl.link.elf.local_sym_index = 0;
2623
2624 self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {};
25512625 }
25522626 // TODO make this logic match freeTextBlock. Maybe abstract the logic out since the same thing
25532627 // is desired for both.
......@@ -2993,7 +3067,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
29933067
29943068 // TODO implement .debug_info for global variables
29953069 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
2996 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
3070 const res = try codegen.generateSymbol(&self.base, decl.link.elf.local_sym_index, decl.srcLoc(), .{
29973071 .ty = decl.ty,
29983072 .val = decl_val,
29993073 }, &code_buffer, .{
......@@ -3028,19 +3102,6 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl
30283102 }
30293103 const unnamed_consts = gop.value_ptr;
30303104
3031 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{
3032 .none = .{},
3033 });
3034 const code = switch (res) {
3035 .externally_managed => |x| x,
3036 .appended => code_buffer.items,
3037 .fail => |em| {
3038 decl.analysis = .codegen_failure;
3039 try module.failed_decls.put(module.gpa, decl, em);
3040 return error.AnalysisFail;
3041 },
3042 };
3043
30443105 const atom = try self.base.allocator.create(TextBlock);
30453106 errdefer self.base.allocator.destroy(atom);
30463107 atom.* = TextBlock.empty;
......@@ -3056,6 +3117,20 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl
30563117
30573118 log.debug("allocating symbol indexes for {s}", .{name});
30583119 atom.local_sym_index = try self.allocateLocalSymbol();
3120 try self.atom_by_index_table.putNoClobber(self.base.allocator, atom.local_sym_index, atom);
3121
3122 const res = try codegen.generateSymbol(&self.base, atom.local_sym_index, decl.srcLoc(), typed_value, &code_buffer, .{
3123 .none = .{},
3124 });
3125 const code = switch (res) {
3126 .externally_managed => |x| x,
3127 .appended => code_buffer.items,
3128 .fail => |em| {
3129 decl.analysis = .codegen_failure;
3130 try module.failed_decls.put(module.gpa, decl, em);
3131 return error.AnalysisFail;
3132 },
3133 };
30593134
30603135 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);
30613136 const phdr_index = self.phdr_load_ro_index.?;
src/link/MachO.zig+28-25
......@@ -3745,19 +3745,6 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De
37453745 }
37463746 const unnamed_consts = gop.value_ptr;
37473747
3748 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{
3749 .none = .{},
3750 });
3751 const code = switch (res) {
3752 .externally_managed => |x| x,
3753 .appended => code_buffer.items,
3754 .fail => |em| {
3755 decl.analysis = .codegen_failure;
3756 try module.failed_decls.put(module.gpa, decl, em);
3757 return error.AnalysisFail;
3758 },
3759 };
3760
37613748 const name_str_index = blk: {
37623749 const index = unnamed_consts.items.len;
37633750 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
37723759 const match = (try self.getMatchingSection(.{
37733760 .segname = makeStaticString("__TEXT"),
37743761 .sectname = makeStaticString("__const"),
3775 .size = code.len,
3762 .size = @sizeOf(u64),
37763763 .@"align" = math.log2(required_alignment),
37773764 })).?;
37783765 const local_sym_index = try self.allocateLocalSymbol();
3779 const atom = try self.createEmptyAtom(local_sym_index, code.len, math.log2(required_alignment));
3780 mem.copy(u8, atom.code.items, code);
3766 const atom = try self.createEmptyAtom(local_sym_index, @sizeOf(u64), math.log2(required_alignment));
3767
3768 const res = try codegen.generateSymbol(&self.base, local_sym_index, decl.srcLoc(), typed_value, &code_buffer, .{
3769 .none = .{},
3770 });
3771 const code = switch (res) {
3772 .externally_managed => |x| x,
3773 .appended => code_buffer.items,
3774 .fail => |em| {
3775 decl.analysis = .codegen_failure;
3776 try module.failed_decls.put(module.gpa, decl, em);
3777 return error.AnalysisFail;
3778 },
3779 };
3780
3781 atom.code.clearRetainingCapacity();
3782 try atom.code.appendSlice(self.base.allocator, code);
37813783 const addr = try self.allocateAtom(atom, code.len, required_alignment, match);
37823784
37833785 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 {
38413843
38423844 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
38433845 const res = if (debug_buffers) |dbg|
3844 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
3846 try codegen.generateSymbol(&self.base, decl.link.elf.local_sym_index, decl.srcLoc(), .{
38453847 .ty = decl.ty,
38463848 .val = decl_val,
38473849 }, &code_buffer, .{
......@@ -3852,7 +3854,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
38523854 },
38533855 })
38543856 else
3855 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
3857 try codegen.generateSymbol(&self.base, decl.link.elf.local_sym_index, decl.srcLoc(), .{
38563858 .ty = decl.ty,
38573859 .val = decl_val,
38583860 }, &code_buffer, .none);
......@@ -4341,16 +4343,17 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {
43414343 }
43424344}
43434345
4344pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 {
4346pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {
4347 assert(self.llvm_object == null);
43454348 assert(decl.link.macho.local_sym_index != 0);
4346 return self.locals.items[decl.link.macho.local_sym_index].n_value;
4347}
43484349
4349pub fn getDeclVAddrWithReloc(self: *MachO, decl: *const Module.Decl, offset: u64) !u64 {
4350 assert(decl.link.macho.local_sym_index != 0);
4351 assert(self.active_decl != null);
4350 // TODO cache local_sym_index => atom!!!
4351 const atom: *Atom = blk: for (self.managed_atoms.items) |atom| {
4352 if (atom.local_sym_index == parent_atom_index) {
4353 break :blk atom;
4354 }
4355 } else unreachable;
43524356
4353 const atom = &self.active_decl.?.link.macho;
43544357 try atom.relocs.append(self.base.allocator, .{
43554358 .offset = @intCast(u32, offset),
43564359 .target = .{ .local = decl.link.macho.local_sym_index },
src/link/Plan9.zig+4-2
......@@ -302,7 +302,7 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl: *Module.Decl) !void {
302302 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
303303 defer code_buffer.deinit();
304304 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
305 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
305 const res = try codegen.generateSymbol(&self.base, @intCast(u32, decl.link.plan9.sym_index.?), decl.srcLoc(), .{
306306 .ty = decl.ty,
307307 .val = decl_val,
308308 }, &code_buffer, .{ .none = .{} });
......@@ -749,7 +749,9 @@ pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void {
749749 _ = self;
750750 _ = decl;
751751}
752pub fn getDeclVAddr(self: *Plan9, decl: *const Module.Decl) u64 {
752pub fn getDeclVAddr(self: *Plan9, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 {
753 _ = parent_atom_index;
754 _ = offset;
753755 if (decl.ty.zigTypeTag() == .Fn) {
754756 var start = self.bases.text;
755757 var it_file = self.fn_decl_table.iterator();