Commit 2c41c453b6

Andrew Kelley <andrew@ziglang.org>
2024-10-08 23:40:12
link.Elf: avoid converting rpath data in flush()
The goal is to minimize as much as possible how much logic is inside flush(). So let's start by moving out obvious stuff. This data can be preformatted before flush().
1 parent e1e151d
src/link/MachO/load_commands.zig
@@ -63,7 +63,7 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32
     }
     // LC_RPATH
     {
-        for (macho_file.base.rpath_list) |rpath| {
+        for (macho_file.rpath_list) |rpath| {
             sizeofcmds += calcInstallNameLen(
                 @sizeOf(macho.rpath_command),
                 rpath,
src/link/C.zig
@@ -148,7 +148,6 @@ pub fn createEmpty(
             .file = file,
             .disable_lld_caching = options.disable_lld_caching,
             .build_id = options.build_id,
-            .rpath_list = options.rpath_list,
         },
     };
 
src/link/Coff.zig
@@ -263,7 +263,6 @@ pub fn createEmpty(
             .file = null,
             .disable_lld_caching = options.disable_lld_caching,
             .build_id = options.build_id,
-            .rpath_list = options.rpath_list,
         },
         .ptr_width = ptr_width,
         .page_size = page_size,
src/link/Elf.zig
@@ -1,4 +1,5 @@
 base: link.File,
+rpath_table: std.StringArrayHashMapUnmanaged(void),
 image_base: u64,
 emit_relocs: bool,
 z_nodelete: bool,
@@ -239,6 +240,11 @@ pub fn createEmpty(
     else
         try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path});
 
+    var rpath_table: std.StringArrayHashMapUnmanaged(void) = .empty;
+    try rpath_table.entries.resize(arena, options.rpath_list.len);
+    @memcpy(rpath_table.entries.items(.key), options.rpath_list);
+    try rpath_table.reIndex(arena);
+
     const self = try arena.create(Elf);
     self.* = .{
         .base = .{
@@ -253,8 +259,8 @@ pub fn createEmpty(
             .file = null,
             .disable_lld_caching = options.disable_lld_caching,
             .build_id = options.build_id,
-            .rpath_list = options.rpath_list,
         },
+        .rpath_table = rpath_table,
         .ptr_width = ptr_width,
         .page_size = page_size,
         .default_sym_version = default_sym_version,
@@ -829,14 +835,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
 
     if (module_obj_path) |path| try positionals.append(.{ .path = path });
 
-    // rpaths
-    var rpath_table = std.StringArrayHashMap(void).init(gpa);
-    defer rpath_table.deinit();
-
-    for (self.base.rpath_list) |rpath| {
-        _ = try rpath_table.put(rpath, {});
-    }
-
     if (comp.config.any_sanitize_thread) {
         try positionals.append(.{ .path = comp.tsan_lib.?.full_object_path });
     }
@@ -1056,7 +1054,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
     try self.initSpecialPhdrs();
     try self.sortShdrs();
 
-    try self.setDynamicSection(rpath_table.keys());
+    try self.setDynamicSection(self.rpath_table.keys());
     self.sortDynamicSymtab();
     try self.setHashSections();
     try self.setVersionSymtab();
@@ -1207,9 +1205,8 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
             try argv.appendSlice(&.{ "--entry", name });
         }
 
-        for (self.base.rpath_list) |rpath| {
-            try argv.append("-rpath");
-            try argv.append(rpath);
+        for (self.rpath_table.keys()) |rpath| {
+            try argv.appendSlice(&.{ "-rpath", rpath });
         }
 
         try argv.appendSlice(&.{
@@ -1978,7 +1975,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
         man.hash.add(self.emit_relocs);
         man.hash.add(comp.config.rdynamic);
         man.hash.addListOfBytes(self.lib_dirs);
-        man.hash.addListOfBytes(self.base.rpath_list);
+        man.hash.addListOfBytes(self.rpath_table.keys());
         if (output_mode == .Exe) {
             man.hash.add(self.base.stack_size);
             man.hash.add(self.base.build_id);
@@ -2263,14 +2260,8 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
         if (csu.crti) |v| try argv.append(v);
         if (csu.crtbegin) |v| try argv.append(v);
 
-        // rpaths
-        var rpath_table = std.StringHashMap(void).init(gpa);
-        defer rpath_table.deinit();
-        for (self.base.rpath_list) |rpath| {
-            if ((try rpath_table.fetchPut(rpath, {})) == null) {
-                try argv.append("-rpath");
-                try argv.append(rpath);
-            }
+        for (self.rpath_table.keys()) |rpath| {
+            try argv.appendSlice(&.{ "-rpath", rpath });
         }
 
         for (self.symbol_wrap_set.keys()) |symbol_name| {
src/link/MachO.zig
@@ -1,5 +1,7 @@
 base: link.File,
 
+rpath_list: []const []const u8,
+
 /// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
 llvm_object: ?LlvmObject.Ptr = null,
 
@@ -192,8 +194,8 @@ pub fn createEmpty(
             .file = null,
             .disable_lld_caching = options.disable_lld_caching,
             .build_id = options.build_id,
-            .rpath_list = options.rpath_list,
         },
+        .rpath_list = options.rpath_list,
         .pagezero_size = options.pagezero_size,
         .headerpad_size = options.headerpad_size,
         .headerpad_max_install_names = options.headerpad_max_install_names,
@@ -662,9 +664,8 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
             try argv.append(syslibroot);
         }
 
-        for (self.base.rpath_list) |rpath| {
-            try argv.append("-rpath");
-            try argv.append(rpath);
+        for (self.rpath_list) |rpath| {
+            try argv.appendSlice(&.{ "-rpath", rpath });
         }
 
         if (self.pagezero_size) |size| {
@@ -2842,7 +2843,7 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
         ncmds += 1;
     }
 
-    for (self.base.rpath_list) |rpath| {
+    for (self.rpath_list) |rpath| {
         try load_commands.writeRpathLC(rpath, writer);
         ncmds += 1;
     }
src/link/NvPtx.zig
@@ -60,7 +60,6 @@ pub fn createEmpty(
             .file = null,
             .disable_lld_caching = options.disable_lld_caching,
             .build_id = options.build_id,
-            .rpath_list = options.rpath_list,
         },
         .llvm_object = llvm_object,
     };
src/link/Plan9.zig
@@ -304,7 +304,6 @@ pub fn createEmpty(
             .file = null,
             .disable_lld_caching = options.disable_lld_caching,
             .build_id = options.build_id,
-            .rpath_list = options.rpath_list,
         },
         .sixtyfour_bit = sixtyfour_bit,
         .bases = undefined,
src/link/SpirV.zig
@@ -74,7 +74,6 @@ pub fn createEmpty(
             .file = null,
             .disable_lld_caching = options.disable_lld_caching,
             .build_id = options.build_id,
-            .rpath_list = options.rpath_list,
         },
         .object = codegen.Object.init(gpa),
     };
src/link/Wasm.zig
@@ -398,7 +398,6 @@ pub fn createEmpty(
             .file = null,
             .disable_lld_caching = options.disable_lld_caching,
             .build_id = options.build_id,
-            .rpath_list = options.rpath_list,
         },
         .name = undefined,
         .import_table = options.import_table,
src/link.zig
@@ -67,7 +67,6 @@ pub const File = struct {
     gc_sections: bool,
     print_gc_sections: bool,
     build_id: std.zig.BuildId,
-    rpath_list: []const []const u8,
     allow_shlib_undefined: bool,
     stack_size: u64,