Commit 642cd730c8

Alex Rønne Petersen <alex@alexrp.com>
2024-07-26 21:05:40
link: Accept `-Brepro` linker option and pass it to LLD.
Enable it by default when building Zig code in release modes. Contributes to #9432.
1 parent 91c1797
src/link/Coff/lld.zig
@@ -71,7 +71,7 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no
         man = comp.cache_parent.obtain();
         self.base.releaseLock();
 
-        comptime assert(Compilation.link_hash_implementation_version == 13);
+        comptime assert(Compilation.link_hash_implementation_version == 14);
 
         for (comp.objects) |obj| {
             _ = try man.addFile(obj.path, null);
@@ -110,6 +110,7 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no
         // strip does not need to go into the linker hash because it is part of the hash namespace
         man.hash.add(self.major_subsystem_version);
         man.hash.add(self.minor_subsystem_version);
+        man.hash.add(self.repro);
         man.hash.addOptional(comp.version);
         try man.addOptionalFile(self.module_definition_file);
 
@@ -227,6 +228,10 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no
             try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{name}));
         }
 
+        if (self.repro) {
+            try argv.append("-BREPRO");
+        }
+
         if (self.tsaware) {
             try argv.append("-tsaware");
         }
src/link/Coff.zig
@@ -21,6 +21,7 @@ entry: link.File.OpenOptions.Entry,
 entry_addr: ?u32,
 module_definition_file: ?[]const u8,
 pdb_out_path: ?[]const u8,
+repro: bool,
 
 ptr_width: PtrWidth,
 page_size: u32,
@@ -319,6 +320,7 @@ pub fn createEmpty(
             return error.EntryAddressTooBig,
         .module_definition_file = options.module_definition_file,
         .pdb_out_path = options.pdb_out_path,
+        .repro = options.repro,
     };
     if (use_llvm and comp.config.have_zcu) {
         self.llvm_object = try LlvmObject.create(arena, comp);
src/link/Elf.zig
@@ -2270,7 +2270,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
         // We are about to obtain this lock, so here we give other processes a chance first.
         self.base.releaseLock();
 
-        comptime assert(Compilation.link_hash_implementation_version == 13);
+        comptime assert(Compilation.link_hash_implementation_version == 14);
 
         try man.addOptionalFile(self.linker_script);
         try man.addOptionalFile(self.version_script);
src/link/Wasm.zig
@@ -3393,7 +3393,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
         // We are about to obtain this lock, so here we give other processes a chance first.
         wasm.base.releaseLock();
 
-        comptime assert(Compilation.link_hash_implementation_version == 13);
+        comptime assert(Compilation.link_hash_implementation_version == 14);
 
         for (comp.objects) |obj| {
             _ = try man.addFile(obj.path, null);
src/Compilation.zig
@@ -1122,6 +1122,7 @@ pub const CreateOptions = struct {
     linker_enable_new_dtags: ?bool = null,
     soname: ?[]const u8 = null,
     linker_gc_sections: ?bool = null,
+    linker_repro: ?bool = null,
     linker_allow_shlib_undefined: ?bool = null,
     linker_bind_global_refs_locally: ?bool = null,
     linker_import_symbols: bool = false,
@@ -1602,6 +1603,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
             .framework_dirs = options.framework_dirs,
             .rpath_list = options.rpath_list,
             .symbol_wrap_set = options.symbol_wrap_set,
+            .repro = options.linker_repro orelse (options.root_mod.optimize_mode != .Debug),
             .allow_shlib_undefined = options.linker_allow_shlib_undefined,
             .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
             .compress_debug_sections = options.linker_compress_debug_sections orelse .none,
@@ -2560,7 +2562,7 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo
 /// to remind the programmer to update multiple related pieces of code that
 /// are in different locations. Bump this number when adding or deleting
 /// anything from the link cache manifest.
-pub const link_hash_implementation_version = 13;
+pub const link_hash_implementation_version = 14;
 
 fn addNonIncrementalStuffToCacheManifest(
     comp: *Compilation,
@@ -2569,7 +2571,7 @@ fn addNonIncrementalStuffToCacheManifest(
 ) !void {
     const gpa = comp.gpa;
 
-    comptime assert(link_hash_implementation_version == 13);
+    comptime assert(link_hash_implementation_version == 14);
 
     if (comp.module) |mod| {
         try addModuleTableToCacheHash(gpa, arena, &man.hash, mod.root_mod, mod.main_mod, .{ .files = man });
@@ -2660,6 +2662,7 @@ fn addNonIncrementalStuffToCacheManifest(
         }
         man.hash.addOptionalBytes(target.dynamic_linker.get());
     }
+    man.hash.add(opts.repro);
     man.hash.addOptional(opts.allow_shlib_undefined);
     man.hash.add(opts.bind_global_refs_locally);
 
src/link.zig
@@ -114,6 +114,7 @@ pub const File = struct {
         major_subsystem_version: ?u16,
         minor_subsystem_version: ?u16,
         gc_sections: ?bool,
+        repro: bool,
         allow_shlib_undefined: ?bool,
         allow_undefined_version: bool,
         enable_new_dtags: ?bool,
src/main.zig
@@ -860,6 +860,7 @@ fn buildOutputType(
     var want_compiler_rt: ?bool = null;
     var linker_script: ?[]const u8 = null;
     var version_script: ?[]const u8 = null;
+    var linker_repro: ?bool = null;
     var linker_allow_undefined_version: bool = false;
     var linker_enable_new_dtags: ?bool = null;
     var disable_c_depfile = false;
@@ -2481,6 +2482,8 @@ fn buildOutputType(
                 {
                     emit_implib = .{ .yes = linker_args_it.nextOrFatal() };
                     emit_implib_arg_provided = true;
+                } else if (mem.eql(u8, arg, "-Brepro") or mem.eql(u8, arg, "/Brepro")) {
+                    linker_repro = true;
                 } else if (mem.eql(u8, arg, "-undefined")) {
                     const lookup_type = linker_args_it.nextOrFatal();
                     if (mem.eql(u8, "dynamic_lookup", lookup_type)) {
@@ -3315,6 +3318,7 @@ fn buildOutputType(
         .soname = resolved_soname,
         .linker_sort_section = linker_sort_section,
         .linker_gc_sections = linker_gc_sections,
+        .linker_repro = linker_repro,
         .linker_allow_shlib_undefined = linker_allow_shlib_undefined,
         .linker_bind_global_refs_locally = linker_bind_global_refs_locally,
         .linker_import_symbols = linker_import_symbols,