aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-03-01 22:03:18 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-03-01 22:03:18 +0100
commite8eb9778cccd2f2d23027d9e0d73d7053bf92efe (patch)
treea658c7381f29593222e059ad541d006afd9e310c /src/link
parent543bee0adf2d3b036654fa0983c16ff7023f504c (diff)
downloadzig-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.zig11
-rw-r--r--src/link/Elf.zig18
-rw-r--r--src/link/MachO.zig25
-rw-r--r--src/link/Plan9.zig11
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();