Commit 82e7f23c49

Travis Lange <travislange12@gmail.com>
2025-01-03 17:04:40
Added support for thin lto
1 parent da1ffae
src/codegen/llvm.zig
@@ -1056,7 +1056,7 @@ pub const Object = struct {
         time_report: bool,
         sanitize_thread: bool,
         fuzz: bool,
-        lto: bool,
+        lto: Compilation.Config.LtoMode,
     };
 
     pub fn emit(o: *Object, options: EmitOptions) !void {
@@ -1338,7 +1338,7 @@ pub const Object = struct {
             .time_report = options.time_report,
             .tsan = options.sanitize_thread,
             .sancov = options.fuzz,
-            .lto = options.lto,
+            .lto = options.lto != .none,
             // https://github.com/ziglang/zig/issues/21215
             .allow_fast_isel = !comp.root_mod.resolved_target.result.cpu.arch.isMIPS(),
             .asm_filename = null,
src/Compilation/Config.zig
@@ -48,7 +48,7 @@ use_lib_llvm: bool,
 /// and updates the final binary.
 use_lld: bool,
 c_frontend: CFrontend,
-lto: bool,
+lto: LtoMode,
 /// WASI-only. Type of WASI execution model ("command" or "reactor").
 /// Always set to `command` for non-WASI targets.
 wasi_exec_model: std.builtin.WasiExecModel,
@@ -65,6 +65,8 @@ san_cov_trace_pc_guard: bool,
 
 pub const CFrontend = enum { clang, aro };
 
+pub const LtoMode = enum { none, full, thin };
+
 pub const DebugFormat = union(enum) {
     strip,
     dwarf: std.dwarf.Format,
@@ -101,7 +103,7 @@ pub const Options = struct {
     use_lib_llvm: ?bool = null,
     use_lld: ?bool = null,
     use_clang: ?bool = null,
-    lto: ?bool = null,
+    lto: ?LtoMode = null,
     /// WASI-only. Type of WASI execution model ("command" or "reactor").
     wasi_exec_model: ?std.builtin.WasiExecModel = null,
     import_memory: ?bool = null,
@@ -258,7 +260,7 @@ pub fn resolve(options: Options) ResolveError!Config {
             break :b false;
         }
 
-        if (options.lto == true) {
+        if (options.lto != null and options.lto != .none) {
             if (options.use_lld == false) return error.LtoRequiresLld;
             break :b true;
         }
@@ -284,16 +286,16 @@ pub fn resolve(options: Options) ResolveError!Config {
         break :b .clang;
     };
 
-    const lto = b: {
+    const lto: LtoMode = b: {
         if (!use_lld) {
             // zig ld LTO support is tracked by
             // https://github.com/ziglang/zig/issues/8680
-            if (options.lto == true) return error.LtoRequiresLld;
-            break :b false;
+            if (options.lto != null and options.lto != .none) return error.LtoRequiresLld;
+            break :b .none;
         }
 
         if (options.lto) |x| break :b x;
-        if (!options.any_c_source_files) break :b false;
+        if (!options.any_c_source_files) break :b .none;
 
         // https://github.com/llvm/llvm-project/pull/116537
         switch (target.abi) {
@@ -303,15 +305,15 @@ pub fn resolve(options: Options) ResolveError!Config {
             .ilp32,
             .muslabin32,
             .muslx32,
-            => break :b false,
+            => break :b .none,
             else => {},
         }
 
         break :b switch (options.output_mode) {
-            .Lib, .Obj => false,
+            .Lib, .Obj => .none,
             .Exe => switch (root_optimize_mode) {
-                .Debug => false,
-                .ReleaseSafe, .ReleaseFast, .ReleaseSmall => true,
+                .Debug => .none,
+                .ReleaseSafe, .ReleaseFast, .ReleaseSmall => .full,
             },
         };
     };
src/link/Coff.zig
@@ -1859,7 +1859,7 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
         if (comp.version) |version| {
             try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor }));
         }
-        if (comp.config.lto) {
+        if (comp.config.lto != .none) {
             switch (optimize_mode) {
                 .Debug => {},
                 .ReleaseSmall => try argv.append("-OPT:lldlto=2"),
src/link/Elf.zig
@@ -1640,7 +1640,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
     // copy when generating relocatables. Normally, we would expect `lld -r` to work.
     // However, because LLD wants to resolve BPF relocations which it shouldn't, it fails
     // before even generating the relocatable.
-    if (output_mode == .Obj and (comp.config.lto or target.cpu.arch.isBpf())) {
+    if (output_mode == .Obj and (comp.config.lto != .none or target.cpu.arch.isBpf())) {
         // In this case we must do a simple file copy
         // here. TODO: think carefully about how we can avoid this redundant operation when doing
         // build-obj. See also the corresponding TODO in linkAsArchive.
@@ -1683,7 +1683,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
             try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot}));
         }
 
-        if (comp.config.lto) {
+        if (comp.config.lto != .none) {
             switch (comp.root_mod.optimize_mode) {
                 .Debug => {},
                 .ReleaseSmall => try argv.append("--lto-O2"),
src/link/Wasm.zig
@@ -3537,7 +3537,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
         try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
         try argv.append("--error-limit=0");
 
-        if (comp.config.lto) {
+        if (comp.config.lto != .none) {
             switch (comp.root_mod.optimize_mode) {
                 .Debug => {},
                 .ReleaseSmall => try argv.append("-O2"),
src/Compilation.zig
@@ -5399,8 +5399,10 @@ pub fn addCCArgs(
         },
     }
 
-    if (comp.config.lto) {
-        try argv.append("-flto");
+    switch (comp.config.lto) {
+        .none => try argv.append("-fno-lto"),
+        .full => try argv.append("-flto=full"),
+        .thin => try argv.append("-flto=thin"),
     }
 
     // This only works for preprocessed files. Guarded by `FileExt.clangSupportsDepFile`.
@@ -6450,7 +6452,7 @@ pub fn build_crt_file(
         .link_libc = false,
         .lto = switch (output_mode) {
             .Lib => comp.config.lto,
-            .Obj, .Exe => false,
+            .Obj, .Exe => .none,
         },
     });
     const root_mod = try Package.Module.create(arena, .{
src/libunwind.zig
@@ -37,7 +37,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
         .root_strip = comp.compilerRtStrip(),
         .link_libc = true,
         // Disable LTO to avoid https://github.com/llvm/llvm-project/issues/56825
-        .lto = false,
+        .lto = .none,
     }) catch |err| {
         comp.setMiscFailure(
             .libunwind,
src/main.zig
@@ -1386,9 +1386,18 @@ fn buildOutputType(
                     } else if (mem.eql(u8, arg, "-fno-PIE")) {
                         create_module.opts.pie = false;
                     } else if (mem.eql(u8, arg, "-flto")) {
-                        create_module.opts.lto = true;
+                        create_module.opts.lto = .full;
+                    } else if (mem.startsWith(u8, arg, "-flto=")) {
+                        const mode = arg["-flto=".len..];
+                        if (mem.eql(u8, mode, "full")) {
+                            create_module.opts.lto = .full;
+                        } else if (mem.eql(u8, mode, "thin")) {
+                            create_module.opts.lto = .thin;
+                        } else {
+                            fatal("Invalid -flto mode: '{s}'. Must be 'full'or 'thin'.", .{mode});
+                        }
                     } else if (mem.eql(u8, arg, "-fno-lto")) {
-                        create_module.opts.lto = false;
+                        create_module.opts.lto = .none;
                     } else if (mem.eql(u8, arg, "-funwind-tables")) {
                         mod_opts.unwind_tables = .sync;
                     } else if (mem.eql(u8, arg, "-fasync-unwind-tables")) {
@@ -1958,8 +1967,20 @@ fn buildOutputType(
                     .no_pic => mod_opts.pic = false,
                     .pie => create_module.opts.pie = true,
                     .no_pie => create_module.opts.pie = false,
-                    .lto => create_module.opts.lto = true,
-                    .no_lto => create_module.opts.lto = false,
+                    .lto => {
+                        if (mem.eql(u8, it.only_arg, "flto") or
+                            mem.eql(u8, it.only_arg, "auto") or
+                            mem.eql(u8, it.only_arg, "full") or
+                            mem.eql(u8, it.only_arg, "jobserver"))
+                        {
+                            create_module.opts.lto = .full;
+                        } else if (mem.eql(u8, it.only_arg, "thin")) {
+                            create_module.opts.lto = .thin;
+                        } else {
+                            fatal("Invalid -flto mode: '{s}'. Must be 'auto', 'full', 'thin', or 'jobserver'.", .{it.only_arg});
+                        }
+                    },
+                    .no_lto => create_module.opts.lto = .none,
                     .red_zone => mod_opts.red_zone = true,
                     .no_red_zone => mod_opts.red_zone = false,
                     .omit_frame_pointer => mod_opts.omit_frame_pointer = true,