mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
Compilation: fix compiler_rt and ubsan_rt strategy logic
It doesn't really make sense for `target_util.canBuildLibCompilerRt`
(and its ubsan-rt friend) to take in `use_llvm`, because the caller
doesn't control that: they're just going to queue a sub-compilation for
the runtime. The only exception to that is the ZCU strategy, where we
effectively embed `_ = @import("compiler_rt")` into the Zig compilation:
there, the question does matter. Rather than trying to do multiple weird
calls to model this, just have `canBuildLibCompilerRt` return not just a
boolean, but also differentiate the self-hosted backend being capable of
building the library vs only LLVM being capable. Logic in `Compilation`
uses that difference to decide whether to use the ZCU strategy, and also
to disable the library if the compiler does not support LLVM and it is
required.
Also, remove a redundant check later on, when actually queuing jobs.
We've already checked that we can build `compiler_rt`, and
`compiler_rt_strat` is set accordingly. I'm guessing this was there to
work around a bug I saw in the old strategy assignment, where support
was ignored in some cases.
Resolves: #24623
This commit is contained in:
parent
2f422372b5
commit
c1483eb05c
@ -1983,13 +1983,21 @@ pub fn create(gpa: Allocator, arena: Allocator, diag: *CreateDiagnostic, options
|
|||||||
if (options.skip_linker_dependencies) break :s .none;
|
if (options.skip_linker_dependencies) break :s .none;
|
||||||
const want = options.want_compiler_rt orelse is_exe_or_dyn_lib;
|
const want = options.want_compiler_rt orelse is_exe_or_dyn_lib;
|
||||||
if (!want) break :s .none;
|
if (!want) break :s .none;
|
||||||
if (have_zcu and target_util.canBuildLibCompilerRt(target, use_llvm, build_options.have_llvm and use_llvm)) {
|
const need_llvm = switch (target_util.canBuildLibCompilerRt(target)) {
|
||||||
|
.no => break :s .none, // impossible to build
|
||||||
|
.yes => false,
|
||||||
|
.llvm_only => true,
|
||||||
|
};
|
||||||
|
if (have_zcu and (!need_llvm or use_llvm)) {
|
||||||
if (output_mode == .Obj) break :s .zcu;
|
if (output_mode == .Obj) break :s .zcu;
|
||||||
if (switch (target_util.zigBackend(target, use_llvm)) {
|
switch (target_util.zigBackend(target, use_llvm)) {
|
||||||
else => false,
|
else => {},
|
||||||
.stage2_aarch64, .stage2_x86_64 => target.ofmt == .coff,
|
.stage2_aarch64, .stage2_x86_64 => if (target.ofmt == .coff) {
|
||||||
}) break :s if (is_exe_or_dyn_lib) .dyn_lib else .zcu;
|
break :s if (is_exe_or_dyn_lib) .dyn_lib else .zcu;
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (need_llvm and !build_options.have_llvm) break :s .none; // impossible to build without llvm
|
||||||
if (is_exe_or_dyn_lib) break :s .lib;
|
if (is_exe_or_dyn_lib) break :s .lib;
|
||||||
break :s .obj;
|
break :s .obj;
|
||||||
};
|
};
|
||||||
@ -2031,14 +2039,22 @@ pub fn create(gpa: Allocator, arena: Allocator, diag: *CreateDiagnostic, options
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unlike compiler_rt, we always want to go through the `_ = @import("ubsan-rt")`
|
// unlike compiler_rt, we always want to go through the `_ = @import("ubsan-rt")`
|
||||||
// approach, since the ubsan runtime uses quite a lot of the standard library
|
// approach if possible, since the ubsan runtime uses quite a lot of the standard
|
||||||
// and this reduces unnecessary bloat.
|
// library and this reduces unnecessary bloat.
|
||||||
const ubsan_rt_strat: RtStrat = s: {
|
const ubsan_rt_strat: RtStrat = s: {
|
||||||
const can_build_ubsan_rt = target_util.canBuildLibUbsanRt(target, use_llvm, build_options.have_llvm);
|
|
||||||
const want_ubsan_rt = options.want_ubsan_rt orelse (can_build_ubsan_rt and any_sanitize_c == .full and is_exe_or_dyn_lib);
|
|
||||||
if (!want_ubsan_rt) break :s .none;
|
|
||||||
if (options.skip_linker_dependencies) break :s .none;
|
if (options.skip_linker_dependencies) break :s .none;
|
||||||
if (have_zcu and target_util.canBuildLibUbsanRt(target, use_llvm, build_options.have_llvm and use_llvm)) break :s .zcu;
|
const want = options.want_ubsan_rt orelse (any_sanitize_c == .full and is_exe_or_dyn_lib);
|
||||||
|
if (!want) break :s .none;
|
||||||
|
const need_llvm = switch (target_util.canBuildLibUbsanRt(target)) {
|
||||||
|
.no => break :s .none, // impossible to build
|
||||||
|
.yes => false,
|
||||||
|
.llvm_only => true,
|
||||||
|
.llvm_lld_only => if (!options.config.use_lld) {
|
||||||
|
break :s .none; // only LLD can handle ubsan-rt for this target
|
||||||
|
} else true,
|
||||||
|
};
|
||||||
|
if (have_zcu and (!need_llvm or use_llvm)) break :s .zcu;
|
||||||
|
if (need_llvm and !build_options.have_llvm) break :s .none; // impossible to build without llvm
|
||||||
if (is_exe_or_dyn_lib) break :s .lib;
|
if (is_exe_or_dyn_lib) break :s .lib;
|
||||||
break :s .obj;
|
break :s .obj;
|
||||||
};
|
};
|
||||||
@ -2476,8 +2492,6 @@ pub fn create(gpa: Allocator, arena: Allocator, diag: *CreateDiagnostic, options
|
|||||||
};
|
};
|
||||||
errdefer comp.destroy();
|
errdefer comp.destroy();
|
||||||
|
|
||||||
const can_build_compiler_rt = target_util.canBuildLibCompilerRt(target, use_llvm, build_options.have_llvm);
|
|
||||||
|
|
||||||
// Add a `CObject` for each `c_source_files`.
|
// Add a `CObject` for each `c_source_files`.
|
||||||
try comp.c_object_table.ensureTotalCapacity(gpa, options.c_source_files.len);
|
try comp.c_object_table.ensureTotalCapacity(gpa, options.c_source_files.len);
|
||||||
for (options.c_source_files) |c_source_file| {
|
for (options.c_source_files) |c_source_file| {
|
||||||
@ -2637,33 +2651,39 @@ pub fn create(gpa: Allocator, arena: Allocator, diag: *CreateDiagnostic, options
|
|||||||
comp.queued_jobs.libtsan = true;
|
comp.queued_jobs.libtsan = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (can_build_compiler_rt) {
|
switch (comp.compiler_rt_strat) {
|
||||||
if (comp.compiler_rt_strat == .lib) {
|
.none, .zcu => {},
|
||||||
|
.lib => {
|
||||||
log.debug("queuing a job to build compiler_rt_lib", .{});
|
log.debug("queuing a job to build compiler_rt_lib", .{});
|
||||||
comp.queued_jobs.compiler_rt_lib = true;
|
comp.queued_jobs.compiler_rt_lib = true;
|
||||||
} else if (comp.compiler_rt_strat == .obj) {
|
},
|
||||||
|
.obj => {
|
||||||
log.debug("queuing a job to build compiler_rt_obj", .{});
|
log.debug("queuing a job to build compiler_rt_obj", .{});
|
||||||
// In this case we are making a static library, so we ask
|
|
||||||
// for a compiler-rt object to put in it.
|
|
||||||
comp.queued_jobs.compiler_rt_obj = true;
|
comp.queued_jobs.compiler_rt_obj = true;
|
||||||
} else if (comp.compiler_rt_strat == .dyn_lib) {
|
},
|
||||||
|
.dyn_lib => {
|
||||||
// hack for stage2_x86_64 + coff
|
// hack for stage2_x86_64 + coff
|
||||||
log.debug("queuing a job to build compiler_rt_dyn_lib", .{});
|
log.debug("queuing a job to build compiler_rt_dyn_lib", .{});
|
||||||
comp.queued_jobs.compiler_rt_dyn_lib = true;
|
comp.queued_jobs.compiler_rt_dyn_lib = true;
|
||||||
}
|
},
|
||||||
|
}
|
||||||
|
|
||||||
if (comp.ubsan_rt_strat == .lib) {
|
switch (comp.ubsan_rt_strat) {
|
||||||
|
.none, .zcu => {},
|
||||||
|
.lib => {
|
||||||
log.debug("queuing a job to build ubsan_rt_lib", .{});
|
log.debug("queuing a job to build ubsan_rt_lib", .{});
|
||||||
comp.queued_jobs.ubsan_rt_lib = true;
|
comp.queued_jobs.ubsan_rt_lib = true;
|
||||||
} else if (comp.ubsan_rt_strat == .obj) {
|
},
|
||||||
|
.obj => {
|
||||||
log.debug("queuing a job to build ubsan_rt_obj", .{});
|
log.debug("queuing a job to build ubsan_rt_obj", .{});
|
||||||
comp.queued_jobs.ubsan_rt_obj = true;
|
comp.queued_jobs.ubsan_rt_obj = true;
|
||||||
}
|
},
|
||||||
|
.dyn_lib => unreachable, // hack for compiler_rt only
|
||||||
|
}
|
||||||
|
|
||||||
if (is_exe_or_dyn_lib and comp.config.any_fuzz) {
|
if (is_exe_or_dyn_lib and comp.config.any_fuzz) {
|
||||||
log.debug("queuing a job to build libfuzzer", .{});
|
log.debug("queuing a job to build libfuzzer", .{});
|
||||||
comp.queued_jobs.fuzzer_lib = true;
|
comp.queued_jobs.fuzzer_lib = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7638,11 +7658,11 @@ pub fn dump_argv(argv: []const []const u8) void {
|
|||||||
const stderr = std.debug.lockStderrWriter(&buffer);
|
const stderr = std.debug.lockStderrWriter(&buffer);
|
||||||
defer std.debug.unlockStderrWriter();
|
defer std.debug.unlockStderrWriter();
|
||||||
nosuspend {
|
nosuspend {
|
||||||
for (argv) |arg| {
|
for (argv, 0..) |arg, i| {
|
||||||
|
if (i != 0) stderr.writeByte(' ') catch return;
|
||||||
stderr.writeAll(arg) catch return;
|
stderr.writeAll(arg) catch return;
|
||||||
(stderr.writableArray(1) catch return)[0] = ' ';
|
|
||||||
}
|
}
|
||||||
stderr.buffer[stderr.end - 1] = '\n';
|
stderr.writeByte('\n') catch return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -351,43 +351,41 @@ pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.builtin.Opti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, have_llvm: bool) bool {
|
pub fn canBuildLibCompilerRt(target: *const std.Target) enum { no, yes, llvm_only } {
|
||||||
switch (target.os.tag) {
|
switch (target.os.tag) {
|
||||||
.plan9 => return false,
|
.plan9 => return .no,
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
switch (target.cpu.arch) {
|
switch (target.cpu.arch) {
|
||||||
.spirv32, .spirv64 => return false,
|
.spirv32, .spirv64 => return .no,
|
||||||
// Remove this once https://github.com/ziglang/zig/issues/23714 is fixed
|
// Remove this once https://github.com/ziglang/zig/issues/23714 is fixed
|
||||||
.amdgcn => return false,
|
.amdgcn => return .no,
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
return switch (zigBackend(target, use_llvm)) {
|
return switch (zigBackend(target, false)) {
|
||||||
.stage2_aarch64 => true,
|
.stage2_aarch64 => .yes,
|
||||||
.stage2_llvm => true,
|
|
||||||
.stage2_x86_64 => switch (target.ofmt) {
|
.stage2_x86_64 => switch (target.ofmt) {
|
||||||
.elf, .macho => true,
|
.elf, .macho => .yes,
|
||||||
else => have_llvm,
|
else => .llvm_only,
|
||||||
},
|
},
|
||||||
else => have_llvm,
|
else => .llvm_only,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, have_llvm: bool) bool {
|
pub fn canBuildLibUbsanRt(target: *const std.Target) enum { no, yes, llvm_only, llvm_lld_only } {
|
||||||
switch (target.cpu.arch) {
|
switch (target.cpu.arch) {
|
||||||
.spirv32, .spirv64 => return false,
|
.spirv32, .spirv64 => return .no,
|
||||||
// Remove this once https://github.com/ziglang/zig/issues/23715 is fixed
|
// Remove this once https://github.com/ziglang/zig/issues/23715 is fixed
|
||||||
.nvptx, .nvptx64 => return false,
|
.nvptx, .nvptx64 => return .no,
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
return switch (zigBackend(target, use_llvm)) {
|
return switch (zigBackend(target, false)) {
|
||||||
.stage2_llvm => true,
|
.stage2_wasm => .llvm_lld_only,
|
||||||
.stage2_wasm => false,
|
|
||||||
.stage2_x86_64 => switch (target.ofmt) {
|
.stage2_x86_64 => switch (target.ofmt) {
|
||||||
.elf, .macho => true,
|
.elf, .macho => .yes,
|
||||||
else => have_llvm,
|
else => .llvm_only,
|
||||||
},
|
},
|
||||||
else => have_llvm,
|
else => .llvm_only,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user