authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-30 12:44:50+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-30 12:44:50+01:00
log324a93e673afcf1bcaac1163379d385952e52a27
treeec05a05cb590ebc5dcfebce9c92bd8e53db200de
parent2e690f5c74cbfd16757cc301ac0d899caa8b2fb3

coff: implement enough of extern handling to pass comptime export tests


4 files changed, 61 insertions(+), 18 deletions(-)

src/arch/x86_64/CodeGen.zig+2-1
...@@ -13063,6 +13063,7 @@ fn genExternSymbolRef(...@@ -13063,6 +13063,7 @@ fn genExternSymbolRef(
13063 } },13063 } },
13064 });13064 });
13065 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {13065 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
13066 const global_index = try coff_file.getGlobalSymbol(callee, lib);
13066 _ = try self.addInst(.{13067 _ = try self.addInst(.{
13067 .tag = .mov,13068 .tag = .mov,
13068 .ops = .import_reloc,13069 .ops = .import_reloc,
...@@ -13070,7 +13071,7 @@ fn genExternSymbolRef(...@@ -13070,7 +13071,7 @@ fn genExternSymbolRef(
13070 .r1 = .rax,13071 .r1 = .rax,
13071 .payload = try self.addExtra(bits.Symbol{13072 .payload = try self.addExtra(bits.Symbol{
13072 .atom_index = atom_index,13073 .atom_index = atom_index,
13073 .sym_index = try coff_file.getGlobalSymbol(callee, lib),13074 .sym_index = link.File.Coff.global_symbol_bit | global_index,
13074 }),13075 }),
13075 } },13076 } },
13076 });13077 });
src/arch/x86_64/Emit.zig+9-8
...@@ -69,7 +69,10 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -69,7 +69,10 @@ pub fn emitMir(emit: *Emit) Error!void {
69 const atom_index = coff_file.getAtomIndexForSymbol(69 const atom_index = coff_file.getAtomIndexForSymbol(
70 .{ .sym_index = symbol.atom_index, .file = null },70 .{ .sym_index = symbol.atom_index, .file = null },
71 ).?;71 ).?;
72 const target = coff_file.getGlobalByIndex(symbol.sym_index);72 const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)
73 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)
74 else
75 link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };
73 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{76 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
74 .type = .direct,77 .type = .direct,
75 .target = target,78 .target = target,
...@@ -141,6 +144,10 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -141,6 +144,10 @@ pub fn emitMir(emit: *Emit) Error!void {
141 .sym_index = symbol.atom_index,144 .sym_index = symbol.atom_index,
142 .file = null,145 .file = null,
143 }).?;146 }).?;
147 const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)
148 coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)
149 else
150 link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };
144 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{151 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
145 .type = switch (lowered_relocs[0].target) {152 .type = switch (lowered_relocs[0].target) {
146 .linker_got => .got,153 .linker_got => .got,
...@@ -148,13 +155,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -148,13 +155,7 @@ pub fn emitMir(emit: *Emit) Error!void {
148 .linker_import => .import,155 .linker_import => .import,
149 else => unreachable,156 else => unreachable,
150 },157 },
151 .target = switch (lowered_relocs[0].target) {158 .target = target,
152 .linker_got,
153 .linker_direct,
154 => .{ .sym_index = symbol.sym_index, .file = null },
155 .linker_import => coff_file.getGlobalByIndex(symbol.sym_index),
156 else => unreachable,
157 },
158 .offset = @as(u32, @intCast(end_offset - 4)),159 .offset = @as(u32, @intCast(end_offset - 4)),
159 .addend = 0,160 .addend = 0,
160 .pcrel = true,161 .pcrel = true,
src/codegen.zig+11
...@@ -927,6 +927,17 @@ fn genDeclRef(...@@ -927,6 +927,17 @@ fn genDeclRef(
927 }927 }
928 return GenResult.mcv(.{ .load_got = sym_index });928 return GenResult.mcv(.{ .load_got = sym_index });
929 } else if (bin_file.cast(link.File.Coff)) |coff_file| {929 } else if (bin_file.cast(link.File.Coff)) |coff_file| {
930 if (is_extern) {
931 const name = mod.intern_pool.stringToSlice(decl.name);
932 // TODO audit this
933 const lib_name = if (decl.getOwnedVariable(mod)) |ov|
934 mod.intern_pool.stringToSliceUnwrap(ov.lib_name)
935 else
936 null;
937 const global_index = try coff_file.getGlobalSymbol(name, lib_name);
938 try coff_file.need_got_table.put(bin_file.allocator, global_index, {}); // needs GOT
939 return GenResult.mcv(.{ .load_got = link.File.Coff.global_symbol_bit | global_index });
940 }
930 const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index);941 const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index);
931 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;942 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
932 return GenResult.mcv(.{ .load_got = sym_index });943 return GenResult.mcv(.{ .load_got = sym_index });
src/link/Coff.zig+39-9
...@@ -28,6 +28,7 @@ locals: std.ArrayListUnmanaged(coff.Symbol) = .{},...@@ -28,6 +28,7 @@ locals: std.ArrayListUnmanaged(coff.Symbol) = .{},
28globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{},28globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{},
29resolver: std.StringHashMapUnmanaged(u32) = .{},29resolver: std.StringHashMapUnmanaged(u32) = .{},
30unresolved: std.AutoArrayHashMapUnmanaged(u32, bool) = .{},30unresolved: std.AutoArrayHashMapUnmanaged(u32, bool) = .{},
31need_got_table: std.AutoHashMapUnmanaged(u32, void) = .{},
3132
32locals_free_list: std.ArrayListUnmanaged(u32) = .{},33locals_free_list: std.ArrayListUnmanaged(u32) = .{},
33globals_free_list: std.ArrayListUnmanaged(u32) = .{},34globals_free_list: std.ArrayListUnmanaged(u32) = .{},
...@@ -1168,12 +1169,17 @@ pub fn updateDecl(...@@ -1168,12 +1169,17 @@ pub fn updateDecl(
1168 const decl = mod.declPtr(decl_index);1169 const decl = mod.declPtr(decl_index);
11691170
1170 if (decl.val.getExternFunc(mod)) |_| {1171 if (decl.val.getExternFunc(mod)) |_| {
1171 return; // TODO Should we do more when front-end analyzed extern decl?1172 return;
1172 }1173 }
1173 if (decl.val.getVariable(mod)) |variable| {1174
1174 if (variable.is_extern) {1175 if (decl.isExtern(mod)) {
1175 return; // TODO Should we do more when front-end analyzed extern decl?1176 // TODO make this part of getGlobalSymbol
1176 }1177 const variable = decl.getOwnedVariable(mod).?;
1178 const name = mod.intern_pool.stringToSlice(decl.name);
1179 const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);
1180 const global_index = try self.getGlobalSymbol(name, lib_name);
1181 try self.need_got_table.put(self.base.allocator, global_index, {});
1182 return;
1177 }1183 }
11781184
1179 const atom_index = try self.getOrCreateAtomForDecl(decl_index);1185 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
...@@ -1519,14 +1525,25 @@ pub fn updateExports(...@@ -1519,14 +1525,25 @@ pub fn updateExports(
1519 continue;1525 continue;
1520 }1526 }
15211527
1522 const sym_index = metadata.getExport(self, mod.intern_pool.stringToSlice(exp.opts.name)) orelse blk: {1528 const exp_name = mod.intern_pool.stringToSlice(exp.opts.name);
1523 const sym_index = try self.allocateSymbol();1529 const sym_index = metadata.getExport(self, exp_name) orelse blk: {
1530 const sym_index = if (self.getGlobalIndex(exp_name)) |global_index| ind: {
1531 const global = self.globals.items[global_index];
1532 // TODO this is just plain wrong as it all should happen in a single `resolveSymbols`
1533 // pass. This will go away once we abstact away Zig's incremental compilation into
1534 // its own module.
1535 if (global.file == null and self.getSymbol(global).section_number == .UNDEFINED) {
1536 _ = self.unresolved.swapRemove(global_index);
1537 break :ind global.sym_index;
1538 }
1539 break :ind try self.allocateSymbol();
1540 } else try self.allocateSymbol();
1524 try metadata.exports.append(gpa, sym_index);1541 try metadata.exports.append(gpa, sym_index);
1525 break :blk sym_index;1542 break :blk sym_index;
1526 };1543 };
1527 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };1544 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
1528 const sym = self.getSymbolPtr(sym_loc);1545 const sym = self.getSymbolPtr(sym_loc);
1529 try self.setSymbolName(sym, mod.intern_pool.stringToSlice(exp.opts.name));1546 try self.setSymbolName(sym, exp_name);
1530 sym.value = atom.getSymbol(self).value;1547 sym.value = atom.getSymbol(self).value;
1531 sym.section_number = @as(coff.SectionNumber, @enumFromInt(metadata.section + 1));1548 sym.section_number = @as(coff.SectionNumber, @enumFromInt(metadata.section + 1));
1532 sym.type = atom.getSymbol(self).type;1549 sym.type = atom.getSymbol(self).type;
...@@ -1663,8 +1680,16 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -1663,8 +1680,16 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
1663 if (metadata.rdata_state != .unused) metadata.rdata_state = .flushed;1680 if (metadata.rdata_state != .unused) metadata.rdata_state = .flushed;
1664 }1681 }
16651682
1683 {
1684 var it = self.need_got_table.iterator();
1685 while (it.next()) |entry| {
1686 const global = self.globals.items[entry.key_ptr.*];
1687 try self.addGotEntry(global);
1688 }
1689 }
1690
1666 while (self.unresolved.popOrNull()) |entry| {1691 while (self.unresolved.popOrNull()) |entry| {
1667 assert(entry.value); // We only expect imports generated by the incremental linker for now.1692 assert(entry.value);
1668 const global = self.globals.items[entry.key];1693 const global = self.globals.items[entry.key];
1669 const sym = self.getSymbol(global);1694 const sym = self.getSymbol(global);
1670 const res = try self.import_tables.getOrPut(gpa, sym.value);1695 const res = try self.import_tables.getOrPut(gpa, sym.value);
...@@ -2459,6 +2484,11 @@ const GetOrPutGlobalPtrResult = struct {...@@ -2459,6 +2484,11 @@ const GetOrPutGlobalPtrResult = struct {
2459 value_ptr: *SymbolWithLoc,2484 value_ptr: *SymbolWithLoc,
2460};2485};
24612486
2487/// Used only for disambiguating local from global at relocation level.
2488/// TODO this must go away.
2489pub const global_symbol_bit: u32 = 0x80000000;
2490pub const global_symbol_mask: u32 = 0x7fffffff;
2491
2462/// Return pointer to the global entry for `name` if one exists.2492/// Return pointer to the global entry for `name` if one exists.
2463/// Puts a new global entry for `name` if one doesn't exist, and2493/// Puts a new global entry for `name` if one doesn't exist, and
2464/// returns a pointer to it.2494/// returns a pointer to it.