Commit 39c4efa2a7
Changed files (1)
src/Compilation.zig
@@ -5273,10 +5273,6 @@ pub fn addCCArgs(
// can be disabled.
try argv.append("--no-default-config");
- if (ext == .cpp) {
- try argv.append("-nostdinc++");
- }
-
// We don't ever put `-fcolor-diagnostics` or `-fno-color-diagnostics` because in passthrough mode
// we want Clang to infer it, and in normal mode we always want it off, which will be true since
// clang will detect stderr as a pipe rather than a terminal.
@@ -5285,116 +5281,311 @@ pub fn addCCArgs(
try argv.append("-fno-caret-diagnostics");
}
- try argv.append(if (comp.function_sections) "-ffunction-sections" else "-fno-function-sections");
- try argv.append(if (comp.data_sections) "-fdata-sections" else "-fno-data-sections");
+ // We never want clang to invoke the system assembler for anything. So we would want
+ // this option always enabled. However, it only matters for some targets. To avoid
+ // "unused parameter" warnings, and to keep CLI spam to a minimum, we only put this
+ // flag on the command line if it is necessary.
+ if (target_util.clangMightShellOutForAssembly(target)) {
+ try argv.append("-integrated-as");
+ }
- try argv.append(if (mod.no_builtin) "-fno-builtin" else "-fbuiltin");
+ const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target);
+ try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple });
- if (comp.config.link_libcpp) {
- const libcxx_include_path = try std.fs.path.join(arena, &[_][]const u8{
- comp.zig_lib_directory.path.?, "libcxx", "include",
- });
- const libcxxabi_include_path = try std.fs.path.join(arena, &[_][]const u8{
- comp.zig_lib_directory.path.?, "libcxxabi", "include",
- });
+ if (target.cpu.arch.isArm()) {
+ try argv.append(if (target.cpu.arch.isThumb()) "-mthumb" else "-mno-thumb");
+ }
- try argv.append("-isystem");
- try argv.append(libcxx_include_path);
+ if (target_util.llvmMachineAbi(target)) |mabi| {
+ try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{mabi}));
+ }
- try argv.append("-isystem");
- try argv.append(libcxxabi_include_path);
+ // We might want to support -mfloat-abi=softfp for Arm and CSKY here in the future.
+ if (target_util.clangSupportsFloatAbiArg(target)) {
+ const fabi = @tagName(target.floatAbi());
- if (target.abi.isMusl()) {
- try argv.append("-D_LIBCPP_HAS_MUSL_LIBC");
- }
- try argv.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");
- try argv.append("-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS");
- try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
+ try argv.append(switch (target.cpu.arch) {
+ // For whatever reason, Clang doesn't support `-mfloat-abi` for s390x.
+ .s390x => try std.fmt.allocPrint(arena, "-m{s}-float", .{fabi}),
+ else => try std.fmt.allocPrint(arena, "-mfloat-abi={s}", .{fabi}),
+ });
+ }
- if (!comp.config.any_non_single_threaded) {
- try argv.append("-D_LIBCPP_HAS_NO_THREADS");
- }
+ if (target_util.supports_fpic(target)) {
+ try argv.append(if (mod.pic) "-fPIC" else "-fno-PIC");
+ }
- // See the comment in libcxx.zig for more details about this.
- try argv.append("-D_LIBCPP_PSTL_BACKEND_SERIAL");
+ if (comp.mingw_unicode_entry_point) {
+ try argv.append("-municode");
+ }
- try argv.append(try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_VERSION={d}", .{
- @intFromEnum(comp.libcxx_abi_version),
- }));
- try argv.append(try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_NAMESPACE=__{d}", .{
- @intFromEnum(comp.libcxx_abi_version),
- }));
+ if (mod.code_model != .default) {
+ try argv.append(try std.fmt.allocPrint(arena, "-mcmodel={s}", .{@tagName(mod.code_model)}));
+ }
- try argv.append(libcxx.hardeningModeFlag(mod.optimize_mode));
+ try argv.ensureUnusedCapacity(2);
+ switch (comp.config.debug_format) {
+ .strip => {},
+ .code_view => {
+ // -g is required here because -gcodeview doesn't trigger debug info
+ // generation, it only changes the type of information generated.
+ argv.appendSliceAssumeCapacity(&.{ "-g", "-gcodeview" });
+ },
+ .dwarf => |f| {
+ argv.appendAssumeCapacity("-gdwarf-4");
+ switch (f) {
+ .@"32" => argv.appendAssumeCapacity("-gdwarf32"),
+ .@"64" => argv.appendAssumeCapacity("-gdwarf64"),
+ }
+ },
}
- if (comp.config.link_libunwind) {
- const libunwind_include_path = try std.fs.path.join(arena, &[_][]const u8{
- comp.zig_lib_directory.path.?, "libunwind", "include",
- });
+ if (comp.config.lto) {
+ try argv.append("-flto");
+ }
- try argv.append("-isystem");
- try argv.append(libunwind_include_path);
+ // This only works for preprocessed files. Guarded by `FileExt.clangSupportsDepFile`.
+ if (out_dep_path) |p| {
+ try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p });
}
- if (comp.config.link_libc) {
- if (target.isGnuLibC()) {
- const target_version = target.os.versionRange().gnuLibCVersion().?;
- const glibc_minor_define = try std.fmt.allocPrint(arena, "-D__GLIBC_MINOR__={d}", .{
- target_version.minor,
+ // Non-preprocessed assembly files don't support these flags.
+ if (ext != .assembly) {
+ try argv.append(if (target.os.tag == .freestanding) "-ffreestanding" else "-fhosted");
+
+ if (target_util.clangSupportsNoImplicitFloatArg(target) and target.floatAbi() == .soft) {
+ try argv.append("-mno-implicit-float");
+ }
+
+ if (target_util.hasRedZone(target)) {
+ try argv.append(if (mod.red_zone) "-mred-zone" else "-mno-red-zone");
+ }
+
+ try argv.append(if (mod.omit_frame_pointer) "-fomit-frame-pointer" else "-fno-omit-frame-pointer");
+
+ const ssp_buf_size = mod.stack_protector;
+ if (ssp_buf_size != 0) {
+ try argv.appendSlice(&[_][]const u8{
+ "-fstack-protector-strong",
+ "--param",
+ try std.fmt.allocPrint(arena, "ssp-buffer-size={d}", .{ssp_buf_size}),
});
- try argv.append(glibc_minor_define);
- } else if (target.isMinGW()) {
- try argv.append("-D__MSVCRT_VERSION__=0xE00"); // use ucrt
+ } else {
+ try argv.append("-fno-stack-protector");
+ }
+
+ try argv.append(if (mod.no_builtin) "-fno-builtin" else "-fbuiltin");
+
+ try argv.append(if (comp.function_sections) "-ffunction-sections" else "-fno-function-sections");
+ try argv.append(if (comp.data_sections) "-fdata-sections" else "-fno-data-sections");
+
+ switch (mod.unwind_tables) {
+ .none => {
+ try argv.append("-fno-unwind-tables");
+ try argv.append("-fno-asynchronous-unwind-tables");
+ },
+ .sync => {
+ // Need to override Clang's convoluted default logic.
+ try argv.append("-fno-asynchronous-unwind-tables");
+ try argv.append("-funwind-tables");
+ },
+ .@"async" => try argv.append("-fasynchronous-unwind-tables"),
+ }
+
+ try argv.append("-nostdinc");
+
+ if (ext == .cpp or ext == .hpp) {
+ try argv.append("-nostdinc++");
+ }
+
+ // LLVM IR files don't support these flags.
+ if (ext != .ll and ext != .bc) {
+ // https://github.com/llvm/llvm-project/issues/105972
+ if (target.cpu.arch.isPowerPC() and target.floatAbi() == .soft) {
+ try argv.append("-D__NO_FPRS__");
+ try argv.append("-D_SOFT_FLOAT");
+ try argv.append("-D_SOFT_DOUBLE");
+ }
+
+ if (comp.config.link_libc) {
+ if (target.isGnuLibC()) {
+ const target_version = target.os.versionRange().gnuLibCVersion().?;
+ const glibc_minor_define = try std.fmt.allocPrint(arena, "-D__GLIBC_MINOR__={d}", .{
+ target_version.minor,
+ });
+ try argv.append(glibc_minor_define);
+ } else if (target.isMinGW()) {
+ try argv.append("-D__MSVCRT_VERSION__=0xE00"); // use ucrt
- switch (ext) {
- .c, .cpp, .m, .mm, .h, .hpp, .hm, .hmm, .cu, .rc, .assembly, .assembly_with_cpp => {
const minver: u16 = @truncate(@intFromEnum(target.os.versionRange().windows.min) >> 16);
try argv.append(
try std.fmt.allocPrint(arena, "-D_WIN32_WINNT=0x{x:0>4}", .{minver}),
);
- },
- else => {},
+ }
}
- }
- }
- const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target);
- try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple });
+ if (comp.config.link_libcpp) {
+ try argv.append("-isystem");
+ try argv.append(try std.fs.path.join(arena, &[_][]const u8{
+ comp.zig_lib_directory.path.?, "libcxx", "include",
+ }));
- switch (ext) {
- .c, .cpp, .m, .mm, .h, .hpp, .hm, .hmm, .cu, .rc => {
- try argv.appendSlice(&[_][]const u8{
- "-nostdinc",
- "-fno-spell-checking",
- });
- if (comp.config.lto) {
- try argv.append("-flto");
+ try argv.append("-isystem");
+ try argv.append(try std.fs.path.join(arena, &[_][]const u8{
+ comp.zig_lib_directory.path.?, "libcxxabi", "include",
+ }));
+
+ if (target.abi.isMusl()) {
+ try argv.append("-D_LIBCPP_HAS_MUSL_LIBC");
+ }
+
+ try argv.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");
+ try argv.append("-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS");
+ try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
+
+ if (!comp.config.any_non_single_threaded) {
+ try argv.append("-D_LIBCPP_HAS_NO_THREADS");
+ }
+
+ // See the comment in libcxx.zig for more details about this.
+ try argv.append("-D_LIBCPP_PSTL_BACKEND_SERIAL");
+
+ try argv.append(try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_VERSION={d}", .{
+ @intFromEnum(comp.libcxx_abi_version),
+ }));
+ try argv.append(try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_NAMESPACE=__{d}", .{
+ @intFromEnum(comp.libcxx_abi_version),
+ }));
+
+ try argv.append(libcxx.hardeningModeFlag(mod.optimize_mode));
+ }
+
+ // According to Rich Felker libc headers are supposed to go before C language headers.
+ // However as noted by @dimenus, appending libc headers before compiler headers breaks
+ // intrinsics and other compiler specific items.
+ try argv.append("-isystem");
+ try argv.append(try std.fs.path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, "include" }));
+
+ try argv.ensureUnusedCapacity(comp.libc_include_dir_list.len * 2);
+ for (comp.libc_include_dir_list) |include_dir| {
+ try argv.append("-isystem");
+ try argv.append(include_dir);
}
- if (ext == .mm) {
- try argv.append("-ObjC++");
+ if (mod.resolved_target.is_native_os and mod.resolved_target.is_native_abi) {
+ try argv.ensureUnusedCapacity(comp.native_system_include_paths.len * 2);
+ for (comp.native_system_include_paths) |include_path| {
+ argv.appendAssumeCapacity("-isystem");
+ argv.appendAssumeCapacity(include_path);
+ }
}
+ if (comp.config.link_libunwind) {
+ try argv.append("-isystem");
+ try argv.append(try std.fs.path.join(arena, &[_][]const u8{
+ comp.zig_lib_directory.path.?, "libunwind", "include",
+ }));
+ }
+
+ try argv.ensureUnusedCapacity(comp.libc_framework_dir_list.len * 2);
for (comp.libc_framework_dir_list) |framework_dir| {
try argv.appendSlice(&.{ "-iframework", framework_dir });
}
+ try argv.ensureUnusedCapacity(comp.framework_dirs.len * 2);
for (comp.framework_dirs) |framework_dir| {
try argv.appendSlice(&.{ "-F", framework_dir });
}
+ }
+ }
- // According to Rich Felker libc headers are supposed to go before C language headers.
- // However as noted by @dimenus, appending libc headers before c_headers breaks intrinsics
- // and other compiler specific items.
- const c_headers_dir = try std.fs.path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, "include" });
- try argv.append("-isystem");
- try argv.append(c_headers_dir);
+ // Only assembly files support these flags.
+ switch (ext) {
+ .assembly,
+ .assembly_with_cpp,
+ => {
+ // The Clang assembler does not accept the list of CPU features like the
+ // compiler frontend does. Therefore we must hard-code the -m flags for
+ // all CPU features here.
+ switch (target.cpu.arch) {
+ .riscv32, .riscv64 => {
+ const RvArchFeat = struct { char: u8, feat: std.Target.riscv.Feature };
+ const letters = [_]RvArchFeat{
+ .{ .char = 'm', .feat = .m },
+ .{ .char = 'a', .feat = .a },
+ .{ .char = 'f', .feat = .f },
+ .{ .char = 'd', .feat = .d },
+ .{ .char = 'c', .feat = .c },
+ };
+ const prefix: []const u8 = if (target.cpu.arch == .riscv64) "rv64" else "rv32";
+ const prefix_len = 4;
+ assert(prefix.len == prefix_len);
+ var march_buf: [prefix_len + letters.len + 1]u8 = undefined;
+ var march_index: usize = prefix_len;
+ @memcpy(march_buf[0..prefix.len], prefix);
- for (comp.libc_include_dir_list) |include_dir| {
- try argv.append("-isystem");
- try argv.append(include_dir);
+ if (std.Target.riscv.featureSetHas(target.cpu.features, .e)) {
+ march_buf[march_index] = 'e';
+ } else {
+ march_buf[march_index] = 'i';
+ }
+ march_index += 1;
+
+ for (letters) |letter| {
+ if (std.Target.riscv.featureSetHas(target.cpu.features, letter.feat)) {
+ march_buf[march_index] = letter.char;
+ march_index += 1;
+ }
+ }
+
+ const march_arg = try std.fmt.allocPrint(arena, "-march={s}", .{
+ march_buf[0..march_index],
+ });
+ try argv.append(march_arg);
+
+ if (std.Target.riscv.featureSetHas(target.cpu.features, .relax)) {
+ try argv.append("-mrelax");
+ } else {
+ try argv.append("-mno-relax");
+ }
+ if (std.Target.riscv.featureSetHas(target.cpu.features, .save_restore)) {
+ try argv.append("-msave-restore");
+ } else {
+ try argv.append("-mno-save-restore");
+ }
+ },
+ .mips, .mipsel, .mips64, .mips64el => {
+ if (target.cpu.model.llvm_name) |llvm_name| {
+ try argv.append(try std.fmt.allocPrint(arena, "-march={s}", .{llvm_name}));
+ }
+ },
+ else => {
+ // TODO
+ },
+ }
+
+ if (target_util.clangAssemblerSupportsMcpuArg(target)) {
+ if (target.cpu.model.llvm_name) |llvm_name| {
+ try argv.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{llvm_name}));
+ }
}
+ },
+ else => {},
+ }
+
+ // Only C-family files support these flags.
+ switch (ext) {
+ .c,
+ .h,
+ .cpp,
+ .hpp,
+ .m,
+ .hm,
+ .mm,
+ .hmm,
+ .cu,
+ => {
+ try argv.append("-fno-spell-checking");
if (target_util.clangSupportsTargetCpuArg(target)) {
if (target.cpu.model.llvm_name) |llvm_name| {
@@ -5421,9 +5612,6 @@ pub fn addCCArgs(
argv.appendAssumeCapacity(arg);
}
}
- if (mod.code_model != .default) {
- try argv.append(try std.fmt.allocPrint(arena, "-mcmodel={s}", .{@tagName(mod.code_model)}));
- }
switch (target.os.tag) {
.windows => {
@@ -5506,23 +5694,6 @@ pub fn addCCArgs(
}
}
- if (target_util.hasRedZone(target)) {
- try argv.append(if (mod.red_zone) "-mred-zone" else "-mno-red-zone");
- }
-
- try argv.append(if (mod.omit_frame_pointer) "-fomit-frame-pointer" else "-fno-omit-frame-pointer");
-
- const ssp_buf_size = mod.stack_protector;
- if (ssp_buf_size != 0) {
- try argv.appendSlice(&[_][]const u8{
- "-fstack-protector-strong",
- "--param",
- try std.fmt.allocPrint(arena, "ssp-buffer-size={d}", .{ssp_buf_size}),
- });
- } else {
- try argv.append("-fno-stack-protector");
- }
-
switch (mod.optimize_mode) {
.Debug => {
// windows c runtime requires -D_DEBUG if using debug libraries
@@ -5556,177 +5727,8 @@ pub fn addCCArgs(
if (mod.optimize_mode != .Debug) {
try argv.append("-Werror=date-time");
}
-
- switch (mod.unwind_tables) {
- .none => {
- try argv.append("-fno-unwind-tables");
- try argv.append("-fno-asynchronous-unwind-tables");
- },
- .sync => {
- // Need to override Clang's convoluted default logic.
- try argv.append("-fno-asynchronous-unwind-tables");
- try argv.append("-funwind-tables");
- },
- .@"async" => try argv.append("-fasynchronous-unwind-tables"),
- }
},
- .shared_library, .ll, .bc, .unknown, .static_library, .object, .def, .zig, .res, .manifest => {},
- .assembly, .assembly_with_cpp => {
- if (ext == .assembly_with_cpp) {
- const c_headers_dir = try std.fs.path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, "include" });
- try argv.append("-isystem");
- try argv.append(c_headers_dir);
-
- for (comp.libc_include_dir_list) |include_dir| {
- try argv.append("-isystem");
- try argv.append(include_dir);
- }
- }
-
- // The Clang assembler does not accept the list of CPU features like the
- // compiler frontend does. Therefore we must hard-code the -m flags for
- // all CPU features here.
- switch (target.cpu.arch) {
- .riscv32, .riscv64 => {
- const RvArchFeat = struct { char: u8, feat: std.Target.riscv.Feature };
- const letters = [_]RvArchFeat{
- .{ .char = 'm', .feat = .m },
- .{ .char = 'a', .feat = .a },
- .{ .char = 'f', .feat = .f },
- .{ .char = 'd', .feat = .d },
- .{ .char = 'c', .feat = .c },
- };
- const prefix: []const u8 = if (target.cpu.arch == .riscv64) "rv64" else "rv32";
- const prefix_len = 4;
- assert(prefix.len == prefix_len);
- var march_buf: [prefix_len + letters.len + 1]u8 = undefined;
- var march_index: usize = prefix_len;
- @memcpy(march_buf[0..prefix.len], prefix);
-
- if (std.Target.riscv.featureSetHas(target.cpu.features, .e)) {
- march_buf[march_index] = 'e';
- } else {
- march_buf[march_index] = 'i';
- }
- march_index += 1;
-
- for (letters) |letter| {
- if (std.Target.riscv.featureSetHas(target.cpu.features, letter.feat)) {
- march_buf[march_index] = letter.char;
- march_index += 1;
- }
- }
-
- const march_arg = try std.fmt.allocPrint(arena, "-march={s}", .{
- march_buf[0..march_index],
- });
- try argv.append(march_arg);
-
- if (std.Target.riscv.featureSetHas(target.cpu.features, .relax)) {
- try argv.append("-mrelax");
- } else {
- try argv.append("-mno-relax");
- }
- if (std.Target.riscv.featureSetHas(target.cpu.features, .save_restore)) {
- try argv.append("-msave-restore");
- } else {
- try argv.append("-mno-save-restore");
- }
- },
- .mips, .mipsel, .mips64, .mips64el => {
- if (target.cpu.model.llvm_name) |llvm_name| {
- try argv.append(try std.fmt.allocPrint(arena, "-march={s}", .{llvm_name}));
- }
- },
- else => {
- // TODO
- },
- }
- if (target_util.clangAssemblerSupportsMcpuArg(target)) {
- if (target.cpu.model.llvm_name) |llvm_name| {
- try argv.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{llvm_name}));
- }
- }
- },
- }
-
- if (comp.mingw_unicode_entry_point) {
- try argv.append("-municode");
- }
-
- if (target.cpu.arch.isArm()) {
- try argv.append(if (target.cpu.arch.isThumb()) "-mthumb" else "-mno-thumb");
- }
-
- if (target_util.supports_fpic(target)) {
- try argv.append(if (mod.pic) "-fPIC" else "-fno-PIC");
- }
-
- try argv.ensureUnusedCapacity(2);
- switch (comp.config.debug_format) {
- .strip => {},
- .code_view => {
- // -g is required here because -gcodeview doesn't trigger debug info
- // generation, it only changes the type of information generated.
- argv.appendSliceAssumeCapacity(&.{ "-g", "-gcodeview" });
- },
- .dwarf => |f| {
- argv.appendAssumeCapacity("-gdwarf-4");
- switch (f) {
- .@"32" => argv.appendAssumeCapacity("-gdwarf32"),
- .@"64" => argv.appendAssumeCapacity("-gdwarf64"),
- }
- },
- }
-
- if (target_util.llvmMachineAbi(target)) |mabi| {
- try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{mabi}));
- }
-
- // We might want to support -mfloat-abi=softfp for Arm and CSKY here in the future.
- if (target_util.clangSupportsFloatAbiArg(target)) {
- const fabi = @tagName(target.floatAbi());
-
- try argv.append(switch (target.cpu.arch) {
- // For whatever reason, Clang doesn't support `-mfloat-abi` for s390x.
- .s390x => try std.fmt.allocPrint(arena, "-m{s}-float", .{fabi}),
- else => try std.fmt.allocPrint(arena, "-mfloat-abi={s}", .{fabi}),
- });
- }
-
- if (target_util.clangSupportsNoImplicitFloatArg(target) and target.floatAbi() == .soft) {
- try argv.append("-mno-implicit-float");
- }
-
- // https://github.com/llvm/llvm-project/issues/105972
- if (target.cpu.arch.isPowerPC() and target.floatAbi() == .soft) {
- try argv.append("-D__NO_FPRS__");
- try argv.append("-D_SOFT_FLOAT");
- try argv.append("-D_SOFT_DOUBLE");
- }
-
- if (out_dep_path) |p| {
- try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p });
- }
-
- // We never want clang to invoke the system assembler for anything. So we would want
- // this option always enabled. However, it only matters for some targets. To avoid
- // "unused parameter" warnings, and to keep CLI spam to a minimum, we only put this
- // flag on the command line if it is necessary.
- if (target_util.clangMightShellOutForAssembly(target)) {
- try argv.append("-integrated-as");
- }
-
- if (target.os.tag == .freestanding) {
- try argv.append("-ffreestanding");
- }
-
- if (mod.resolved_target.is_native_os and mod.resolved_target.is_native_abi) {
- try argv.ensureUnusedCapacity(comp.native_system_include_paths.len * 2);
- for (comp.native_system_include_paths) |include_path| {
- argv.appendAssumeCapacity("-isystem");
- argv.appendAssumeCapacity(include_path);
- }
+ else => {},
}
try argv.appendSlice(comp.global_cc_argv);