mirror of
https://github.com/ziglang/zig.git
synced 2026-01-13 10:55:11 +00:00
macho: track unresolved externs globally
this way we share state between incremental and traditional paths.
This commit is contained in:
parent
30247fbb6a
commit
153e231774
@ -138,6 +138,7 @@ locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
|
||||
globals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
|
||||
undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{},
|
||||
symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{},
|
||||
unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
|
||||
|
||||
locals_free_list: std.ArrayListUnmanaged(u32) = .{},
|
||||
globals_free_list: std.ArrayListUnmanaged(u32) = .{},
|
||||
@ -2082,7 +2083,6 @@ fn resolveSymbolsInObject(
|
||||
self: *MachO,
|
||||
object_id: u16,
|
||||
tentatives: *std.AutoArrayHashMap(u32, void),
|
||||
unresolved: *std.AutoArrayHashMap(u32, void),
|
||||
) !void {
|
||||
const object = &self.objects.items[object_id];
|
||||
|
||||
@ -2181,7 +2181,7 @@ fn resolveSymbolsInObject(
|
||||
.n_desc = 0,
|
||||
.n_value = 0,
|
||||
};
|
||||
_ = unresolved.fetchSwapRemove(resolv.where_index);
|
||||
_ = self.unresolved.fetchSwapRemove(resolv.where_index);
|
||||
},
|
||||
}
|
||||
|
||||
@ -2252,7 +2252,7 @@ fn resolveSymbolsInObject(
|
||||
.n_desc = 0,
|
||||
.n_value = 0,
|
||||
};
|
||||
_ = unresolved.fetchSwapRemove(resolv.where_index);
|
||||
_ = self.unresolved.fetchSwapRemove(resolv.where_index);
|
||||
},
|
||||
}
|
||||
} else {
|
||||
@ -2272,7 +2272,7 @@ fn resolveSymbolsInObject(
|
||||
.where_index = undef_sym_index,
|
||||
.file = object_id,
|
||||
});
|
||||
_ = try unresolved.getOrPut(undef_sym_index);
|
||||
_ = try self.unresolved.getOrPut(self.base.allocator, undef_sym_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2281,18 +2281,15 @@ fn resolveSymbols(self: *MachO) !void {
|
||||
var tentatives = std.AutoArrayHashMap(u32, void).init(self.base.allocator);
|
||||
defer tentatives.deinit();
|
||||
|
||||
var unresolved = std.AutoArrayHashMap(u32, void).init(self.base.allocator);
|
||||
defer unresolved.deinit();
|
||||
|
||||
// First pass, resolve symbols in provided objects.
|
||||
for (self.objects.items) |_, object_id| {
|
||||
try self.resolveSymbolsInObject(@intCast(u16, object_id), &tentatives, &unresolved);
|
||||
try self.resolveSymbolsInObject(@intCast(u16, object_id), &tentatives);
|
||||
}
|
||||
|
||||
// Second pass, resolve symbols in static libraries.
|
||||
var next_sym: usize = 0;
|
||||
loop: while (next_sym < unresolved.count()) {
|
||||
const sym = self.undefs.items[unresolved.keys()[next_sym]];
|
||||
loop: while (next_sym < self.unresolved.count()) {
|
||||
const sym = self.undefs.items[self.unresolved.keys()[next_sym]];
|
||||
const sym_name = self.getString(sym.n_strx);
|
||||
|
||||
for (self.archives.items) |archive| {
|
||||
@ -2306,7 +2303,7 @@ fn resolveSymbols(self: *MachO) !void {
|
||||
const object_id = @intCast(u16, self.objects.items.len);
|
||||
const object = try self.objects.addOne(self.base.allocator);
|
||||
object.* = try archive.parseObject(self.base.allocator, self.base.options.target, offsets.items[0]);
|
||||
try self.resolveSymbolsInObject(object_id, &tentatives, &unresolved);
|
||||
try self.resolveSymbolsInObject(object_id, &tentatives);
|
||||
|
||||
continue :loop;
|
||||
}
|
||||
@ -2382,8 +2379,8 @@ fn resolveSymbols(self: *MachO) !void {
|
||||
|
||||
// Third pass, resolve symbols in dynamic libraries.
|
||||
next_sym = 0;
|
||||
loop: while (next_sym < unresolved.count()) {
|
||||
const sym = self.undefs.items[unresolved.keys()[next_sym]];
|
||||
loop: while (next_sym < self.unresolved.count()) {
|
||||
const sym = self.undefs.items[self.unresolved.keys()[next_sym]];
|
||||
const sym_name = self.getString(sym.n_strx);
|
||||
|
||||
for (self.dylibs.items) |dylib, id| {
|
||||
@ -2400,7 +2397,7 @@ fn resolveSymbols(self: *MachO) !void {
|
||||
undef.n_type |= macho.N_EXT;
|
||||
undef.n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER;
|
||||
|
||||
_ = unresolved.fetchSwapRemove(resolv.where_index);
|
||||
_ = self.unresolved.fetchSwapRemove(resolv.where_index);
|
||||
|
||||
continue :loop;
|
||||
}
|
||||
@ -2434,7 +2431,7 @@ fn resolveSymbols(self: *MachO) !void {
|
||||
nlist.n_desc = macho.N_WEAK_DEF;
|
||||
try self.globals.append(self.base.allocator, nlist);
|
||||
|
||||
_ = unresolved.fetchSwapRemove(resolv.where_index);
|
||||
_ = self.unresolved.fetchSwapRemove(resolv.where_index);
|
||||
|
||||
undef.* = .{
|
||||
.n_strx = 0,
|
||||
@ -2468,7 +2465,7 @@ fn resolveSymbols(self: *MachO) !void {
|
||||
}
|
||||
}
|
||||
|
||||
for (unresolved.keys()) |index| {
|
||||
for (self.unresolved.keys()) |index| {
|
||||
const sym = self.undefs.items[index];
|
||||
const sym_name = self.getString(sym.n_strx);
|
||||
const resolv = self.symbol_resolver.get(sym.n_strx) orelse unreachable;
|
||||
@ -2477,7 +2474,7 @@ fn resolveSymbols(self: *MachO) !void {
|
||||
log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name});
|
||||
}
|
||||
|
||||
if (unresolved.count() > 0)
|
||||
if (self.unresolved.count() > 0)
|
||||
return error.UndefinedSymbolReference;
|
||||
}
|
||||
|
||||
@ -3122,6 +3119,7 @@ pub fn deinit(self: *MachO) void {
|
||||
self.locals.deinit(self.base.allocator);
|
||||
self.locals_free_list.deinit(self.base.allocator);
|
||||
self.symbol_resolver.deinit(self.base.allocator);
|
||||
self.unresolved.deinit(self.base.allocator);
|
||||
|
||||
for (self.objects.items) |*object| {
|
||||
object.deinit(self.base.allocator);
|
||||
@ -4332,6 +4330,7 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
|
||||
.where = .undef,
|
||||
.where_index = sym_index,
|
||||
});
|
||||
_ = try self.unresolved.getOrPut(self.base.allocator, sym_index);
|
||||
|
||||
const stubs_index = @intCast(u32, self.stubs.items.len);
|
||||
try self.stubs.append(self.base.allocator, sym_index);
|
||||
@ -4340,8 +4339,7 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
|
||||
// TODO discuss this. The caller context expects codegen.InnerError{ OutOfMemory, CodegenFail },
|
||||
// which obviously doesn't include file writing op errors. So instead of trying to write the stub
|
||||
// entry right here and now, queue it up and dispose of when updating decl.
|
||||
try self.pending_updates.ensureUnusedCapacity(self.base.allocator, 2);
|
||||
self.pending_updates.appendAssumeCapacity(.{ .resolve_undef = sym_index });
|
||||
try self.pending_updates.ensureUnusedCapacity(self.base.allocator, 1);
|
||||
self.pending_updates.appendAssumeCapacity(.{ .add_stub_entry = stubs_index });
|
||||
|
||||
return sym_index;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user