mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
coff: implement enough of extern handling to pass comptime export tests
This commit is contained in:
parent
2e690f5c74
commit
324a93e673
@ -13063,6 +13063,7 @@ fn genExternSymbolRef(
|
||||
} },
|
||||
});
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
const global_index = try coff_file.getGlobalSymbol(callee, lib);
|
||||
_ = try self.addInst(.{
|
||||
.tag = .mov,
|
||||
.ops = .import_reloc,
|
||||
@ -13070,7 +13071,7 @@ fn genExternSymbolRef(
|
||||
.r1 = .rax,
|
||||
.payload = try self.addExtra(bits.Symbol{
|
||||
.atom_index = atom_index,
|
||||
.sym_index = try coff_file.getGlobalSymbol(callee, lib),
|
||||
.sym_index = link.File.Coff.global_symbol_bit | global_index,
|
||||
}),
|
||||
} },
|
||||
});
|
||||
|
||||
@ -69,7 +69,10 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
const atom_index = coff_file.getAtomIndexForSymbol(
|
||||
.{ .sym_index = symbol.atom_index, .file = null },
|
||||
).?;
|
||||
const target = coff_file.getGlobalByIndex(symbol.sym_index);
|
||||
const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)
|
||||
coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)
|
||||
else
|
||||
link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };
|
||||
try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
|
||||
.type = .direct,
|
||||
.target = target,
|
||||
@ -141,6 +144,10 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
.sym_index = symbol.atom_index,
|
||||
.file = null,
|
||||
}).?;
|
||||
const target = if (link.File.Coff.global_symbol_bit & symbol.sym_index != 0)
|
||||
coff_file.getGlobalByIndex(link.File.Coff.global_symbol_mask & symbol.sym_index)
|
||||
else
|
||||
link.File.Coff.SymbolWithLoc{ .sym_index = symbol.sym_index, .file = null };
|
||||
try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
|
||||
.type = switch (lowered_relocs[0].target) {
|
||||
.linker_got => .got,
|
||||
@ -148,13 +155,7 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
.linker_import => .import,
|
||||
else => unreachable,
|
||||
},
|
||||
.target = switch (lowered_relocs[0].target) {
|
||||
.linker_got,
|
||||
.linker_direct,
|
||||
=> .{ .sym_index = symbol.sym_index, .file = null },
|
||||
.linker_import => coff_file.getGlobalByIndex(symbol.sym_index),
|
||||
else => unreachable,
|
||||
},
|
||||
.target = target,
|
||||
.offset = @as(u32, @intCast(end_offset - 4)),
|
||||
.addend = 0,
|
||||
.pcrel = true,
|
||||
|
||||
@ -927,6 +927,17 @@ fn genDeclRef(
|
||||
}
|
||||
return GenResult.mcv(.{ .load_got = sym_index });
|
||||
} else if (bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
if (is_extern) {
|
||||
const name = mod.intern_pool.stringToSlice(decl.name);
|
||||
// TODO audit this
|
||||
const lib_name = if (decl.getOwnedVariable(mod)) |ov|
|
||||
mod.intern_pool.stringToSliceUnwrap(ov.lib_name)
|
||||
else
|
||||
null;
|
||||
const global_index = try coff_file.getGlobalSymbol(name, lib_name);
|
||||
try coff_file.need_got_table.put(bin_file.allocator, global_index, {}); // needs GOT
|
||||
return GenResult.mcv(.{ .load_got = link.File.Coff.global_symbol_bit | global_index });
|
||||
}
|
||||
const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index);
|
||||
const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
|
||||
return GenResult.mcv(.{ .load_got = sym_index });
|
||||
|
||||
@ -28,6 +28,7 @@ locals: std.ArrayListUnmanaged(coff.Symbol) = .{},
|
||||
globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{},
|
||||
resolver: std.StringHashMapUnmanaged(u32) = .{},
|
||||
unresolved: std.AutoArrayHashMapUnmanaged(u32, bool) = .{},
|
||||
need_got_table: std.AutoHashMapUnmanaged(u32, void) = .{},
|
||||
|
||||
locals_free_list: std.ArrayListUnmanaged(u32) = .{},
|
||||
globals_free_list: std.ArrayListUnmanaged(u32) = .{},
|
||||
@ -1168,12 +1169,17 @@ pub fn updateDecl(
|
||||
const decl = mod.declPtr(decl_index);
|
||||
|
||||
if (decl.val.getExternFunc(mod)) |_| {
|
||||
return; // TODO Should we do more when front-end analyzed extern decl?
|
||||
return;
|
||||
}
|
||||
if (decl.val.getVariable(mod)) |variable| {
|
||||
if (variable.is_extern) {
|
||||
return; // TODO Should we do more when front-end analyzed extern decl?
|
||||
}
|
||||
|
||||
if (decl.isExtern(mod)) {
|
||||
// TODO make this part of getGlobalSymbol
|
||||
const variable = decl.getOwnedVariable(mod).?;
|
||||
const name = mod.intern_pool.stringToSlice(decl.name);
|
||||
const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);
|
||||
const global_index = try self.getGlobalSymbol(name, lib_name);
|
||||
try self.need_got_table.put(self.base.allocator, global_index, {});
|
||||
return;
|
||||
}
|
||||
|
||||
const atom_index = try self.getOrCreateAtomForDecl(decl_index);
|
||||
@ -1519,14 +1525,25 @@ pub fn updateExports(
|
||||
continue;
|
||||
}
|
||||
|
||||
const sym_index = metadata.getExport(self, mod.intern_pool.stringToSlice(exp.opts.name)) orelse blk: {
|
||||
const sym_index = try self.allocateSymbol();
|
||||
const exp_name = mod.intern_pool.stringToSlice(exp.opts.name);
|
||||
const sym_index = metadata.getExport(self, exp_name) orelse blk: {
|
||||
const sym_index = if (self.getGlobalIndex(exp_name)) |global_index| ind: {
|
||||
const global = self.globals.items[global_index];
|
||||
// TODO this is just plain wrong as it all should happen in a single `resolveSymbols`
|
||||
// pass. This will go away once we abstact away Zig's incremental compilation into
|
||||
// its own module.
|
||||
if (global.file == null and self.getSymbol(global).section_number == .UNDEFINED) {
|
||||
_ = self.unresolved.swapRemove(global_index);
|
||||
break :ind global.sym_index;
|
||||
}
|
||||
break :ind try self.allocateSymbol();
|
||||
} else try self.allocateSymbol();
|
||||
try metadata.exports.append(gpa, sym_index);
|
||||
break :blk sym_index;
|
||||
};
|
||||
const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
|
||||
const sym = self.getSymbolPtr(sym_loc);
|
||||
try self.setSymbolName(sym, mod.intern_pool.stringToSlice(exp.opts.name));
|
||||
try self.setSymbolName(sym, exp_name);
|
||||
sym.value = atom.getSymbol(self).value;
|
||||
sym.section_number = @as(coff.SectionNumber, @enumFromInt(metadata.section + 1));
|
||||
sym.type = atom.getSymbol(self).type;
|
||||
@ -1663,8 +1680,16 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
if (metadata.rdata_state != .unused) metadata.rdata_state = .flushed;
|
||||
}
|
||||
|
||||
{
|
||||
var it = self.need_got_table.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const global = self.globals.items[entry.key_ptr.*];
|
||||
try self.addGotEntry(global);
|
||||
}
|
||||
}
|
||||
|
||||
while (self.unresolved.popOrNull()) |entry| {
|
||||
assert(entry.value); // We only expect imports generated by the incremental linker for now.
|
||||
assert(entry.value);
|
||||
const global = self.globals.items[entry.key];
|
||||
const sym = self.getSymbol(global);
|
||||
const res = try self.import_tables.getOrPut(gpa, sym.value);
|
||||
@ -2459,6 +2484,11 @@ const GetOrPutGlobalPtrResult = struct {
|
||||
value_ptr: *SymbolWithLoc,
|
||||
};
|
||||
|
||||
/// Used only for disambiguating local from global at relocation level.
|
||||
/// TODO this must go away.
|
||||
pub const global_symbol_bit: u32 = 0x80000000;
|
||||
pub const global_symbol_mask: u32 = 0x7fffffff;
|
||||
|
||||
/// Return pointer to the global entry for `name` if one exists.
|
||||
/// Puts a new global entry for `name` if one doesn't exist, and
|
||||
/// returns a pointer to it.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user