Commit 153e231774

Jakub Konka <kubkon@jakubkonka.com>
2021-08-20 09:12:26
macho: track unresolved externs globally
this way we share state between incremental and traditional paths.
1 parent 30247fb
Changed files (1)
src
src/link/MachO.zig
@@ -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;