authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-20 09:12:26+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-20 09:12:26+02:00
log153e2317748cff7d59d2709f72fe8b22c14f2a7b
tree0b51fed3f45eb424f417b4777f81c1e35d3e54ee
parent30247fbb6a46231154f051119228829c6a0dfd90

macho: track unresolved externs globally

this way we share state between incremental and traditional paths.

1 files changed, 17 insertions(+), 19 deletions(-)

src/link/MachO.zig+17-19
...@@ -138,6 +138,7 @@ locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},...@@ -138,6 +138,7 @@ locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
138globals: std.ArrayListUnmanaged(macho.nlist_64) = .{},138globals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
139undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{},139undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{},
140symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{},140symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{},
141unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
141142
142locals_free_list: std.ArrayListUnmanaged(u32) = .{},143locals_free_list: std.ArrayListUnmanaged(u32) = .{},
143globals_free_list: std.ArrayListUnmanaged(u32) = .{},144globals_free_list: std.ArrayListUnmanaged(u32) = .{},
...@@ -2082,7 +2083,6 @@ fn resolveSymbolsInObject(...@@ -2082,7 +2083,6 @@ fn resolveSymbolsInObject(
2082 self: *MachO,2083 self: *MachO,
2083 object_id: u16,2084 object_id: u16,
2084 tentatives: *std.AutoArrayHashMap(u32, void),2085 tentatives: *std.AutoArrayHashMap(u32, void),
2085 unresolved: *std.AutoArrayHashMap(u32, void),
2086) !void {2086) !void {
2087 const object = &self.objects.items[object_id];2087 const object = &self.objects.items[object_id];
20882088
...@@ -2181,7 +2181,7 @@ fn resolveSymbolsInObject(...@@ -2181,7 +2181,7 @@ fn resolveSymbolsInObject(
2181 .n_desc = 0,2181 .n_desc = 0,
2182 .n_value = 0,2182 .n_value = 0,
2183 };2183 };
2184 _ = unresolved.fetchSwapRemove(resolv.where_index);2184 _ = self.unresolved.fetchSwapRemove(resolv.where_index);
2185 },2185 },
2186 }2186 }
21872187
...@@ -2252,7 +2252,7 @@ fn resolveSymbolsInObject(...@@ -2252,7 +2252,7 @@ fn resolveSymbolsInObject(
2252 .n_desc = 0,2252 .n_desc = 0,
2253 .n_value = 0,2253 .n_value = 0,
2254 };2254 };
2255 _ = unresolved.fetchSwapRemove(resolv.where_index);2255 _ = self.unresolved.fetchSwapRemove(resolv.where_index);
2256 },2256 },
2257 }2257 }
2258 } else {2258 } else {
...@@ -2272,7 +2272,7 @@ fn resolveSymbolsInObject(...@@ -2272,7 +2272,7 @@ fn resolveSymbolsInObject(
2272 .where_index = undef_sym_index,2272 .where_index = undef_sym_index,
2273 .file = object_id,2273 .file = object_id,
2274 });2274 });
2275 _ = try unresolved.getOrPut(undef_sym_index);2275 _ = try self.unresolved.getOrPut(self.base.allocator, undef_sym_index);
2276 }2276 }
2277 }2277 }
2278}2278}
...@@ -2281,18 +2281,15 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2281,18 +2281,15 @@ fn resolveSymbols(self: *MachO) !void {
2281 var tentatives = std.AutoArrayHashMap(u32, void).init(self.base.allocator);2281 var tentatives = std.AutoArrayHashMap(u32, void).init(self.base.allocator);
2282 defer tentatives.deinit();2282 defer tentatives.deinit();
22832283
2284 var unresolved = std.AutoArrayHashMap(u32, void).init(self.base.allocator);
2285 defer unresolved.deinit();
2286
2287 // First pass, resolve symbols in provided objects.2284 // First pass, resolve symbols in provided objects.
2288 for (self.objects.items) |_, object_id| {2285 for (self.objects.items) |_, object_id| {
2289 try self.resolveSymbolsInObject(@intCast(u16, object_id), &tentatives, &unresolved);2286 try self.resolveSymbolsInObject(@intCast(u16, object_id), &tentatives);
2290 }2287 }
22912288
2292 // Second pass, resolve symbols in static libraries.2289 // Second pass, resolve symbols in static libraries.
2293 var next_sym: usize = 0;2290 var next_sym: usize = 0;
2294 loop: while (next_sym < unresolved.count()) {2291 loop: while (next_sym < self.unresolved.count()) {
2295 const sym = self.undefs.items[unresolved.keys()[next_sym]];2292 const sym = self.undefs.items[self.unresolved.keys()[next_sym]];
2296 const sym_name = self.getString(sym.n_strx);2293 const sym_name = self.getString(sym.n_strx);
22972294
2298 for (self.archives.items) |archive| {2295 for (self.archives.items) |archive| {
...@@ -2306,7 +2303,7 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2306,7 +2303,7 @@ fn resolveSymbols(self: *MachO) !void {
2306 const object_id = @intCast(u16, self.objects.items.len);2303 const object_id = @intCast(u16, self.objects.items.len);
2307 const object = try self.objects.addOne(self.base.allocator);2304 const object = try self.objects.addOne(self.base.allocator);
2308 object.* = try archive.parseObject(self.base.allocator, self.base.options.target, offsets.items[0]);2305 object.* = try archive.parseObject(self.base.allocator, self.base.options.target, offsets.items[0]);
2309 try self.resolveSymbolsInObject(object_id, &tentatives, &unresolved);2306 try self.resolveSymbolsInObject(object_id, &tentatives);
23102307
2311 continue :loop;2308 continue :loop;
2312 }2309 }
...@@ -2382,8 +2379,8 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2382,8 +2379,8 @@ fn resolveSymbols(self: *MachO) !void {
23822379
2383 // Third pass, resolve symbols in dynamic libraries.2380 // Third pass, resolve symbols in dynamic libraries.
2384 next_sym = 0;2381 next_sym = 0;
2385 loop: while (next_sym < unresolved.count()) {2382 loop: while (next_sym < self.unresolved.count()) {
2386 const sym = self.undefs.items[unresolved.keys()[next_sym]];2383 const sym = self.undefs.items[self.unresolved.keys()[next_sym]];
2387 const sym_name = self.getString(sym.n_strx);2384 const sym_name = self.getString(sym.n_strx);
23882385
2389 for (self.dylibs.items) |dylib, id| {2386 for (self.dylibs.items) |dylib, id| {
...@@ -2400,7 +2397,7 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2400,7 +2397,7 @@ fn resolveSymbols(self: *MachO) !void {
2400 undef.n_type |= macho.N_EXT;2397 undef.n_type |= macho.N_EXT;
2401 undef.n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER;2398 undef.n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER;
24022399
2403 _ = unresolved.fetchSwapRemove(resolv.where_index);2400 _ = self.unresolved.fetchSwapRemove(resolv.where_index);
24042401
2405 continue :loop;2402 continue :loop;
2406 }2403 }
...@@ -2434,7 +2431,7 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2434,7 +2431,7 @@ fn resolveSymbols(self: *MachO) !void {
2434 nlist.n_desc = macho.N_WEAK_DEF;2431 nlist.n_desc = macho.N_WEAK_DEF;
2435 try self.globals.append(self.base.allocator, nlist);2432 try self.globals.append(self.base.allocator, nlist);
24362433
2437 _ = unresolved.fetchSwapRemove(resolv.where_index);2434 _ = self.unresolved.fetchSwapRemove(resolv.where_index);
24382435
2439 undef.* = .{2436 undef.* = .{
2440 .n_strx = 0,2437 .n_strx = 0,
...@@ -2468,7 +2465,7 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2468,7 +2465,7 @@ fn resolveSymbols(self: *MachO) !void {
2468 }2465 }
2469 }2466 }
24702467
2471 for (unresolved.keys()) |index| {2468 for (self.unresolved.keys()) |index| {
2472 const sym = self.undefs.items[index];2469 const sym = self.undefs.items[index];
2473 const sym_name = self.getString(sym.n_strx);2470 const sym_name = self.getString(sym.n_strx);
2474 const resolv = self.symbol_resolver.get(sym.n_strx) orelse unreachable;2471 const resolv = self.symbol_resolver.get(sym.n_strx) orelse unreachable;
...@@ -2477,7 +2474,7 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2477,7 +2474,7 @@ fn resolveSymbols(self: *MachO) !void {
2477 log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name});2474 log.err(" first referenced in '{s}'", .{self.objects.items[resolv.file].name});
2478 }2475 }
24792476
2480 if (unresolved.count() > 0)2477 if (self.unresolved.count() > 0)
2481 return error.UndefinedSymbolReference;2478 return error.UndefinedSymbolReference;
2482}2479}
24832480
...@@ -3122,6 +3119,7 @@ pub fn deinit(self: *MachO) void {...@@ -3122,6 +3119,7 @@ pub fn deinit(self: *MachO) void {
3122 self.locals.deinit(self.base.allocator);3119 self.locals.deinit(self.base.allocator);
3123 self.locals_free_list.deinit(self.base.allocator);3120 self.locals_free_list.deinit(self.base.allocator);
3124 self.symbol_resolver.deinit(self.base.allocator);3121 self.symbol_resolver.deinit(self.base.allocator);
3122 self.unresolved.deinit(self.base.allocator);
31253123
3126 for (self.objects.items) |*object| {3124 for (self.objects.items) |*object| {
3127 object.deinit(self.base.allocator);3125 object.deinit(self.base.allocator);
...@@ -4332,6 +4330,7 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {...@@ -4332,6 +4330,7 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
4332 .where = .undef,4330 .where = .undef,
4333 .where_index = sym_index,4331 .where_index = sym_index,
4334 });4332 });
4333 _ = try self.unresolved.getOrPut(self.base.allocator, sym_index);
43354334
4336 const stubs_index = @intCast(u32, self.stubs.items.len);4335 const stubs_index = @intCast(u32, self.stubs.items.len);
4337 try self.stubs.append(self.base.allocator, sym_index);4336 try self.stubs.append(self.base.allocator, sym_index);
...@@ -4340,8 +4339,7 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {...@@ -4340,8 +4339,7 @@ pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
4340 // TODO discuss this. The caller context expects codegen.InnerError{ OutOfMemory, CodegenFail },4339 // TODO discuss this. The caller context expects codegen.InnerError{ OutOfMemory, CodegenFail },
4341 // which obviously doesn't include file writing op errors. So instead of trying to write the stub4340 // which obviously doesn't include file writing op errors. So instead of trying to write the stub
4342 // entry right here and now, queue it up and dispose of when updating decl.4341 // entry right here and now, queue it up and dispose of when updating decl.
4343 try self.pending_updates.ensureUnusedCapacity(self.base.allocator, 2);4342 try self.pending_updates.ensureUnusedCapacity(self.base.allocator, 1);
4344 self.pending_updates.appendAssumeCapacity(.{ .resolve_undef = sym_index });
4345 self.pending_updates.appendAssumeCapacity(.{ .add_stub_entry = stubs_index });4343 self.pending_updates.appendAssumeCapacity(.{ .add_stub_entry = stubs_index });
43464344
4347 return sym_index;4345 return sym_index;