aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-01-25 13:17:25 -0800
committerGitHub <noreply@github.com>2025-01-25 13:17:25 -0800
commit8fa47bb904c888dadf20af5eb72b9643eed2bfea (patch)
tree47fcc20146a7358b4216668d91c78d3bb712511d /src
parent015a5e198246f782415586235e0da7085867eb22 (diff)
parentb60e39fe8f50783509e3cfe7a3888e1611b063c1 (diff)
downloadzig-8fa47bb904c888dadf20af5eb72b9643eed2bfea.tar.gz
zig-8fa47bb904c888dadf20af5eb72b9643eed2bfea.zip
Merge pull request #22230 from alexrp/lto-stuff
Disable LTO by default + some LTO fixes
Diffstat (limited to 'src')
-rw-r--r--src/Compilation.zig31
-rw-r--r--src/Compilation/Config.zig21
-rw-r--r--src/libtsan.zig6
-rw-r--r--src/link/Coff.zig7
-rw-r--r--src/link/Elf.zig12
-rw-r--r--src/mingw.zig2
-rw-r--r--src/target.zig80
7 files changed, 90 insertions, 69 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 1a056c1c04..75b7f5e602 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -1881,18 +1881,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
comp.remaining_prelink_tasks += 1;
}
- if (target.isMinGW() and comp.config.any_non_single_threaded) {
- // LLD might drop some symbols as unused during LTO and GCing, therefore,
- // we force mark them for resolution here.
-
- const tls_index_sym = switch (target.cpu.arch) {
- .x86 => "__tls_index",
- else => "_tls_index",
- };
-
- try comp.force_undefined_symbols.put(comp.gpa, tls_index_sym, {});
- }
-
if (comp.include_compiler_rt and capable_of_building_compiler_rt) {
if (is_exe_or_dyn_lib) {
log.debug("queuing a job to build compiler_rt_lib", .{});
@@ -3695,15 +3683,19 @@ fn performAllTheWorkInner(
// In case it failed last time, try again. `clearMiscFailures` was already
// called at the start of `update`.
if (comp.queued_jobs.compiler_rt_lib and comp.compiler_rt_lib == null) {
- comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "compiler_rt.zig", .compiler_rt, .Lib, &comp.compiler_rt_lib, main_progress_node });
+ // LLVM disables LTO for its compiler-rt and we've had various issues with LTO of our
+ // compiler-rt due to LLD bugs as well, e.g.:
+ //
+ // https://github.com/llvm/llvm-project/issues/43698#issuecomment-2542660611
+ comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "compiler_rt.zig", .compiler_rt, .Lib, false, &comp.compiler_rt_lib, main_progress_node });
}
if (comp.queued_jobs.compiler_rt_obj and comp.compiler_rt_obj == null) {
- comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "compiler_rt.zig", .compiler_rt, .Obj, &comp.compiler_rt_obj, main_progress_node });
+ comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "compiler_rt.zig", .compiler_rt, .Obj, false, &comp.compiler_rt_obj, main_progress_node });
}
if (comp.queued_jobs.fuzzer_lib and comp.fuzzer_lib == null) {
- comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "fuzzer.zig", .libfuzzer, .Lib, &comp.fuzzer_lib, main_progress_node });
+ comp.link_task_wait_group.spawnManager(buildRt, .{ comp, "fuzzer.zig", .libfuzzer, .Lib, true, &comp.fuzzer_lib, main_progress_node });
}
if (comp.queued_jobs.glibc_shared_objects) {
@@ -4635,12 +4627,14 @@ fn buildRt(
root_source_name: []const u8,
misc_task: MiscTask,
output_mode: std.builtin.OutputMode,
+ allow_lto: bool,
out: *?CrtFile,
prog_node: std.Progress.Node,
) void {
comp.buildOutputFromZig(
root_source_name,
output_mode,
+ allow_lto,
out,
misc_task,
prog_node,
@@ -4748,6 +4742,7 @@ fn buildZigLibc(comp: *Compilation, prog_node: std.Progress.Node) void {
comp.buildOutputFromZig(
"c.zig",
.Lib,
+ true,
&comp.libc_static_lib,
.zig_libc,
prog_node,
@@ -6453,6 +6448,7 @@ fn buildOutputFromZig(
comp: *Compilation,
src_basename: []const u8,
output_mode: std.builtin.OutputMode,
+ allow_lto: bool,
out: *?CrtFile,
misc_task_tag: MiscTask,
prog_node: std.Progress.Node,
@@ -6481,6 +6477,7 @@ fn buildOutputFromZig(
.root_strip = strip,
.link_libc = comp.config.link_libc,
.any_unwind_tables = comp.root_mod.unwind_tables != .none,
+ .lto = if (allow_lto) comp.config.lto else .none,
});
const root_mod = try Package.Module.create(arena, .{
@@ -6581,6 +6578,8 @@ pub const CrtFileOptions = struct {
unwind_tables: ?std.builtin.UnwindTables = null,
pic: ?bool = null,
no_builtin: ?bool = null,
+
+ allow_lto: bool = true,
};
pub fn build_crt_file(
@@ -6619,7 +6618,7 @@ pub fn build_crt_file(
.link_libc = false,
.any_unwind_tables = options.unwind_tables != .none,
.lto = switch (output_mode) {
- .Lib => comp.config.lto,
+ .Lib => if (options.allow_lto) comp.config.lto else .none,
.Obj, .Exe => .none,
},
});
diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig
index 41a8077203..ee175cce11 100644
--- a/src/Compilation/Config.zig
+++ b/src/Compilation/Config.zig
@@ -295,27 +295,8 @@ pub fn resolve(options: Options) ResolveError!Config {
}
if (options.lto) |x| break :b x;
- if (!options.any_c_source_files) break :b .none;
-
- // https://github.com/llvm/llvm-project/pull/116537
- switch (target.abi) {
- .gnuabin32,
- .gnuilp32,
- .gnux32,
- .ilp32,
- .muslabin32,
- .muslx32,
- => break :b .none,
- else => {},
- }
- break :b switch (options.output_mode) {
- .Lib, .Obj => .none,
- .Exe => switch (root_optimize_mode) {
- .Debug => .none,
- .ReleaseSafe, .ReleaseFast, .ReleaseSmall => .full,
- },
- };
+ break :b .none;
};
const link_libcpp = b: {
diff --git a/src/libtsan.zig b/src/libtsan.zig
index 8b2427df1b..cd28b8694a 100644
--- a/src/libtsan.zig
+++ b/src/libtsan.zig
@@ -53,6 +53,8 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
const optimize_mode = comp.compilerRtOptMode();
const strip = comp.compilerRtStrip();
const link_libcpp = target.isDarwin();
+ const unwind_tables: std.builtin.UnwindTables =
+ if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .@"async";
const config = Compilation.Config.resolve(.{
.output_mode = output_mode,
@@ -65,6 +67,9 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
.root_strip = strip,
.link_libc = true,
.link_libcpp = link_libcpp,
+ .any_unwind_tables = unwind_tables != .none,
+ // LLVM disables LTO for its libtsan.
+ .lto = .none,
}) catch |err| {
comp.setMiscFailure(
.libtsan,
@@ -95,6 +100,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
.red_zone = comp.root_mod.red_zone,
.omit_frame_pointer = optimize_mode != .Debug and !target.os.tag.isDarwin(),
.valgrind = false,
+ .unwind_tables = unwind_tables,
.optimize_mode = optimize_mode,
.structured_cfg = comp.root_mod.structured_cfg,
.pic = true,
diff --git a/src/link/Coff.zig b/src/link/Coff.zig
index 9bd3bd76e9..3b239246ca 100644
--- a/src/link/Coff.zig
+++ b/src/link/Coff.zig
@@ -1876,6 +1876,13 @@ 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 (target_util.llvmMachineAbi(target)) |mabi| {
+ try argv.append(try allocPrint(arena, "-MLLVM:-target-abi={s}", .{mabi}));
+ }
+
+ try argv.append(try allocPrint(arena, "-MLLVM:-float-abi={s}", .{if (target.abi.floatAbi() == .hard) "hard" else "soft"}));
+
if (comp.config.lto != .none) {
switch (optimize_mode) {
.Debug => {},
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index ea2fa56a5d..edd45f65ee 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -1700,6 +1700,18 @@ 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 (target_util.llvmMachineAbi(target)) |mabi| {
+ try argv.appendSlice(&.{
+ "-mllvm",
+ try std.fmt.allocPrint(arena, "-target-abi={s}", .{mabi}),
+ });
+ }
+
+ try argv.appendSlice(&.{
+ "-mllvm",
+ try std.fmt.allocPrint(arena, "-float-abi={s}", .{if (target.abi.floatAbi() == .hard) "hard" else "soft"}),
+ });
+
if (comp.config.lto != .none) {
switch (comp.root_mod.optimize_mode) {
.Debug => {},
diff --git a/src/mingw.zig b/src/mingw.zig
index 47aff05133..17c0a49b11 100644
--- a/src/mingw.zig
+++ b/src/mingw.zig
@@ -175,6 +175,8 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
return comp.build_crt_file("mingw32", .Lib, .@"mingw-w64 mingw32.lib", prog_node, c_source_files.items, .{
.unwind_tables = unwind_tables,
+ // https://github.com/llvm/llvm-project/issues/43698#issuecomment-2542660611
+ .allow_lto = false,
});
},
}
diff --git a/src/target.zig b/src/target.zig
index 99e0fd1faa..546d10b0bc 100644
--- a/src/target.zig
+++ b/src/target.zig
@@ -482,16 +482,6 @@ pub fn arePointersLogical(target: std.Target, as: AddressSpace) bool {
}
pub fn llvmMachineAbi(target: std.Target) ?[:0]const u8 {
- // This special-casing should be removed with LLVM 20.
- switch (target.cpu.arch) {
- .mips, .mipsel => return "o32",
- .mips64, .mips64el => return switch (target.abi) {
- .gnuabin32, .muslabin32 => "n32",
- else => "n64",
- },
- else => {},
- }
-
// LLD does not support ELFv1. Rather than having LLVM produce ELFv1 code and then linking it
// into a broken ELFv2 binary, just force LLVM to use ELFv2 as well. This will break when glibc
// is linked as glibc only supports ELFv2 for little endian, but there's nothing we can do about
@@ -500,33 +490,57 @@ pub fn llvmMachineAbi(target: std.Target) ?[:0]const u8 {
// Once our self-hosted linker can handle both ABIs, this hack should go away.
if (target.cpu.arch == .powerpc64) return "elfv2";
- switch (target.cpu.arch) {
- .riscv64 => {
+ return switch (target.cpu.arch) {
+ .arm, .armeb, .thumb, .thumbeb => "aapcs",
+ // TODO: `muslsf` and `muslf32` in LLVM 20.
+ .loongarch64 => switch (target.abi) {
+ .gnusf => "lp64s",
+ .gnuf32 => "lp64f",
+ else => "lp64d",
+ },
+ .loongarch32 => switch (target.abi) {
+ .gnusf => "ilp32s",
+ .gnuf32 => "ilp32f",
+ else => "ilp32d",
+ },
+ .mips, .mipsel => "o32",
+ .mips64, .mips64el => switch (target.abi) {
+ .gnuabin32, .muslabin32 => "n32",
+ else => "n64",
+ },
+ .powerpc64 => switch (target.os.tag) {
+ .freebsd => if (target.os.version_range.semver.isAtLeast(.{ .major = 13, .minor = 0, .patch = 0 }) orelse false)
+ "elfv2"
+ else
+ "elfv1",
+ .openbsd => "elfv2",
+ else => if (target.abi.isMusl()) "elfv2" else "elfv1",
+ },
+ .powerpc64le => "elfv2",
+ .riscv64 => b: {
const featureSetHas = std.Target.riscv.featureSetHas;
- if (featureSetHas(target.cpu.features, .e)) {
- return "lp64e";
- } else if (featureSetHas(target.cpu.features, .d)) {
- return "lp64d";
- } else if (featureSetHas(target.cpu.features, .f)) {
- return "lp64f";
- } else {
- return "lp64";
- }
+ break :b if (featureSetHas(target.cpu.features, .e))
+ "lp64e"
+ else if (featureSetHas(target.cpu.features, .d))
+ "lp64d"
+ else if (featureSetHas(target.cpu.features, .f))
+ "lp64f"
+ else
+ "lp64";
},
- .riscv32 => {
+ .riscv32 => b: {
const featureSetHas = std.Target.riscv.featureSetHas;
- if (featureSetHas(target.cpu.features, .e)) {
- return "ilp32e";
- } else if (featureSetHas(target.cpu.features, .d)) {
- return "ilp32d";
- } else if (featureSetHas(target.cpu.features, .f)) {
- return "ilp32f";
- } else {
- return "ilp32";
- }
+ break :b if (featureSetHas(target.cpu.features, .e))
+ "ilp32e"
+ else if (featureSetHas(target.cpu.features, .d))
+ "ilp32d"
+ else if (featureSetHas(target.cpu.features, .f))
+ "ilp32f"
+ else
+ "ilp32";
},
- else => return null,
- }
+ else => null,
+ };
}
/// This function returns 1 if function alignment is not observable or settable. Note that this