diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-03-01 22:03:18 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-03-01 22:03:18 +0100 |
| commit | e8eb9778cccd2f2d23027d9e0d73d7053bf92efe (patch) | |
| tree | a658c7381f29593222e059ad541d006afd9e310c /src/link | |
| parent | 543bee0adf2d3b036654fa0983c16ff7023f504c (diff) | |
| download | zig-e8eb9778cccd2f2d23027d9e0d73d7053bf92efe.tar.gz zig-e8eb9778cccd2f2d23027d9e0d73d7053bf92efe.zip | |
codegen: lower field_ptr to memory across linking backends
This requires generating an addend for the target relocation as
the field pointer might point at a field inner to the container.
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/Coff.zig | 11 | ||||
| -rw-r--r-- | src/link/Elf.zig | 18 | ||||
| -rw-r--r-- | src/link/MachO.zig | 25 | ||||
| -rw-r--r-- | src/link/Plan9.zig | 11 |
4 files changed, 40 insertions, 25 deletions
diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 3ee34682e9..3293cf2dfc 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -724,10 +724,12 @@ 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, 0, decl.srcLoc(), .{ + const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ .ty = decl.ty, .val = decl.val, - }, &code_buffer, .none); + }, &code_buffer, .none, .{ + .parent_atom_index = 0, + }); const code = switch (res) { .externally_managed => |x| x, .appended => code_buffer.items, @@ -1463,9 +1465,8 @@ fn findLib(self: *Coff, arena: Allocator, name: []const u8) !?[]const u8 { return null; } -pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 { - _ = parent_atom_index; - _ = offset; +pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl, reloc_info: link.File.RelocInfo) !u64 { + _ = reloc_info; 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 2b063dd1d2..1424a521b9 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -188,6 +188,7 @@ relocs: RelocTable = .{}, const Reloc = struct { target: u32, offset: u64, + addend: u32, prev_vaddr: u64, }; @@ -421,20 +422,21 @@ pub fn deinit(self: *Elf) void { self.atom_by_index_table.deinit(self.base.allocator); } -pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 { +pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl, reloc_info: File.RelocInfo) !u64 { assert(self.llvm_object == null); assert(decl.link.elf.local_sym_index != 0); 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 atom = self.atom_by_index_table.get(reloc_info.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, + .offset = reloc_info.offset, + .addend = reloc_info.addend, .prev_vaddr = vaddr, }); @@ -1039,7 +1041,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { for (relocs.items) |*reloc| { const target_sym = self.local_symbols.items[reloc.target]; - const target_vaddr = target_sym.st_value; + const target_vaddr = target_sym.st_value + reloc.addend; if (target_vaddr == reloc.prev_vaddr) continue; @@ -3074,7 +3076,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.link.elf.local_sym_index, decl.srcLoc(), .{ + const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ .ty = decl.ty, .val = decl_val, }, &code_buffer, .{ @@ -3083,6 +3085,8 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { .dbg_info = &dbg_info_buffer, .dbg_info_type_relocs = &dbg_info_type_relocs, }, + }, .{ + .parent_atom_index = decl.link.elf.local_sym_index, }); const code = switch (res) { .externally_managed => |x| x, @@ -3130,8 +3134,10 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl 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, .{ + const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{ .none = .{}, + }, .{ + .parent_atom_index = atom.local_sym_index, }); const code = switch (res) { .externally_managed => |x| x, diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 9f038d9b9f..2f55c69b3a 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3781,8 +3781,10 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De const atom = try self.createEmptyAtom(local_sym_index, @sizeOf(u64), math.log2(required_alignment)); try self.atom_by_index_table.putNoClobber(self.base.allocator, local_sym_index, atom); - const res = try codegen.generateSymbol(&self.base, local_sym_index, decl.srcLoc(), typed_value, &code_buffer, .{ + const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{ .none = .{}, + }, .{ + .parent_atom_index = local_sym_index, }); const code = switch (res) { .externally_managed => |x| x, @@ -3790,6 +3792,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De .fail => |em| { decl.analysis = .codegen_failure; try module.failed_decls.put(module.gpa, decl, em); + log.err("{s}", .{em.msg}); return error.AnalysisFail; }, }; @@ -3860,7 +3863,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.link.macho.local_sym_index, decl.srcLoc(), .{ + try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ .ty = decl.ty, .val = decl_val, }, &code_buffer, .{ @@ -3869,12 +3872,16 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { .dbg_info = &dbg.dbg_info_buffer, .dbg_info_type_relocs = &dbg.dbg_info_type_relocs, }, + }, .{ + .parent_atom_index = decl.link.macho.local_sym_index, }) else - try codegen.generateSymbol(&self.base, decl.link.macho.local_sym_index, decl.srcLoc(), .{ + try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ .ty = decl.ty, .val = decl_val, - }, &code_buffer, .none); + }, &code_buffer, .none, .{ + .parent_atom_index = decl.link.macho.local_sym_index, + }); const code = blk: { switch (res) { @@ -4357,15 +4364,15 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { } } -pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 { +pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl, reloc_info: File.RelocInfo) !u64 { assert(self.llvm_object == null); assert(decl.link.macho.local_sym_index != 0); - const atom = self.atom_by_index_table.get(parent_atom_index).?; + const atom = self.atom_by_index_table.get(reloc_info.parent_atom_index).?; try atom.relocs.append(self.base.allocator, .{ - .offset = @intCast(u32, offset), + .offset = @intCast(u32, reloc_info.offset), .target = .{ .local = decl.link.macho.local_sym_index }, - .addend = 0, + .addend = reloc_info.addend, .subtractor = null, .pcrel = false, .length = 3, @@ -4375,7 +4382,7 @@ pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl, parent_atom_index: u else => unreachable, }, }); - try atom.rebases.append(self.base.allocator, offset); + try atom.rebases.append(self.base.allocator, reloc_info.offset); return 0; } diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index 4648a6a673..8096b2d38c 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -304,10 +304,12 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl: *Module.Decl) !void { const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; // TODO we need the symbol index for symbol in the table of locals for the containing atom const sym_index = decl.link.plan9.sym_index orelse 0; - const res = try codegen.generateSymbol(&self.base, @intCast(u32, sym_index), decl.srcLoc(), .{ + const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ .ty = decl.ty, .val = decl_val, - }, &code_buffer, .{ .none = .{} }); + }, &code_buffer, .{ .none = .{} }, .{ + .parent_atom_index = @intCast(u32, sym_index), + }); const code = switch (res) { .externally_managed => |x| x, .appended => code_buffer.items, @@ -752,9 +754,8 @@ pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void { _ = self; _ = decl; } -pub fn getDeclVAddr(self: *Plan9, decl: *const Module.Decl, parent_atom_index: u32, offset: u64) !u64 { - _ = parent_atom_index; - _ = offset; +pub fn getDeclVAddr(self: *Plan9, decl: *const Module.Decl, reloc_info: link.File.RelocInfo) !u64 { + _ = reloc_info; if (decl.ty.zigTypeTag() == .Fn) { var start = self.bases.text; var it_file = self.fn_decl_table.iterator(); |
