authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-12-13 04:59:17+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-12-14 06:49:45+01:00
log39c4efa2a75e1e369a5d39b32d91d376fbd2257a
tree099aecff69a15dab74ad2f8d58648f8c7a74b02e
parentd74e87aab1a59102643cc8c2b0a650cba71cccfc
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

Compilation: Clean up addCCArgs().

The goal of this commit is to get rid of some "unused command line argument" warnings that Clang would give for various file types previously. This cleanup also has the side effect of making the order of flags more understandable, especially as it pertains to include paths. Since a lot of code was shuffled around in this commit, I recommend reviewing the old and new versions of the function side-by-side rather than trying to make sense of the diff.

1 files changed, 269 insertions(+), 267 deletions(-)

src/Compilation.zig+269-267
......@@ -5273,10 +5273,6 @@ pub fn addCCArgs(
52735273 // can be disabled.
52745274 try argv.append("--no-default-config");
52755275
5276 if (ext == .cpp) {
5277 try argv.append("-nostdinc++");
5278 }
5279
52805276 // We don't ever put `-fcolor-diagnostics` or `-fno-color-diagnostics` because in passthrough mode
52815277 // we want Clang to infer it, and in normal mode we always want it off, which will be true since
52825278 // clang will detect stderr as a pipe rather than a terminal.
......@@ -5285,116 +5281,311 @@ pub fn addCCArgs(
52855281 try argv.append("-fno-caret-diagnostics");
52865282 }
52875283
5288 try argv.append(if (comp.function_sections) "-ffunction-sections" else "-fno-function-sections");
5289 try argv.append(if (comp.data_sections) "-fdata-sections" else "-fno-data-sections");
5284 // We never want clang to invoke the system assembler for anything. So we would want
5285 // this option always enabled. However, it only matters for some targets. To avoid
5286 // "unused parameter" warnings, and to keep CLI spam to a minimum, we only put this
5287 // flag on the command line if it is necessary.
5288 if (target_util.clangMightShellOutForAssembly(target)) {
5289 try argv.append("-integrated-as");
5290 }
52905291
5291 try argv.append(if (mod.no_builtin) "-fno-builtin" else "-fbuiltin");
5292 const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target);
5293 try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple });
52925294
5293 if (comp.config.link_libcpp) {
5294 const libcxx_include_path = try std.fs.path.join(arena, &[_][]const u8{
5295 comp.zig_lib_directory.path.?, "libcxx", "include",
5296 });
5297 const libcxxabi_include_path = try std.fs.path.join(arena, &[_][]const u8{
5298 comp.zig_lib_directory.path.?, "libcxxabi", "include",
5299 });
5295 if (target.cpu.arch.isArm()) {
5296 try argv.append(if (target.cpu.arch.isThumb()) "-mthumb" else "-mno-thumb");
5297 }
53005298
5301 try argv.append("-isystem");
5302 try argv.append(libcxx_include_path);
5299 if (target_util.llvmMachineAbi(target)) |mabi| {
5300 try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{mabi}));
5301 }
53035302
5304 try argv.append("-isystem");
5305 try argv.append(libcxxabi_include_path);
5303 // We might want to support -mfloat-abi=softfp for Arm and CSKY here in the future.
5304 if (target_util.clangSupportsFloatAbiArg(target)) {
5305 const fabi = @tagName(target.floatAbi());
53065306
5307 if (target.abi.isMusl()) {
5308 try argv.append("-D_LIBCPP_HAS_MUSL_LIBC");
5309 }
5310 try argv.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");
5311 try argv.append("-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS");
5312 try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
5307 try argv.append(switch (target.cpu.arch) {
5308 // For whatever reason, Clang doesn't support `-mfloat-abi` for s390x.
5309 .s390x => try std.fmt.allocPrint(arena, "-m{s}-float", .{fabi}),
5310 else => try std.fmt.allocPrint(arena, "-mfloat-abi={s}", .{fabi}),
5311 });
5312 }
53135313
5314 if (!comp.config.any_non_single_threaded) {
5315 try argv.append("-D_LIBCPP_HAS_NO_THREADS");
5316 }
5314 if (target_util.supports_fpic(target)) {
5315 try argv.append(if (mod.pic) "-fPIC" else "-fno-PIC");
5316 }
53175317
5318 // See the comment in libcxx.zig for more details about this.
5319 try argv.append("-D_LIBCPP_PSTL_BACKEND_SERIAL");
5318 if (comp.mingw_unicode_entry_point) {
5319 try argv.append("-municode");
5320 }
53205321
5321 try argv.append(try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_VERSION={d}", .{
5322 @intFromEnum(comp.libcxx_abi_version),
5323 }));
5324 try argv.append(try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_NAMESPACE=__{d}", .{
5325 @intFromEnum(comp.libcxx_abi_version),
5326 }));
5322 if (mod.code_model != .default) {
5323 try argv.append(try std.fmt.allocPrint(arena, "-mcmodel={s}", .{@tagName(mod.code_model)}));
5324 }
53275325
5328 try argv.append(libcxx.hardeningModeFlag(mod.optimize_mode));
5326 try argv.ensureUnusedCapacity(2);
5327 switch (comp.config.debug_format) {
5328 .strip => {},
5329 .code_view => {
5330 // -g is required here because -gcodeview doesn't trigger debug info
5331 // generation, it only changes the type of information generated.
5332 argv.appendSliceAssumeCapacity(&.{ "-g", "-gcodeview" });
5333 },
5334 .dwarf => |f| {
5335 argv.appendAssumeCapacity("-gdwarf-4");
5336 switch (f) {
5337 .@"32" => argv.appendAssumeCapacity("-gdwarf32"),
5338 .@"64" => argv.appendAssumeCapacity("-gdwarf64"),
5339 }
5340 },
53295341 }
53305342
5331 if (comp.config.link_libunwind) {
5332 const libunwind_include_path = try std.fs.path.join(arena, &[_][]const u8{
5333 comp.zig_lib_directory.path.?, "libunwind", "include",
5334 });
5343 if (comp.config.lto) {
5344 try argv.append("-flto");
5345 }
53355346
5336 try argv.append("-isystem");
5337 try argv.append(libunwind_include_path);
5347 // This only works for preprocessed files. Guarded by `FileExt.clangSupportsDepFile`.
5348 if (out_dep_path) |p| {
5349 try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p });
53385350 }
53395351
5340 if (comp.config.link_libc) {
5341 if (target.isGnuLibC()) {
5342 const target_version = target.os.versionRange().gnuLibCVersion().?;
5343 const glibc_minor_define = try std.fmt.allocPrint(arena, "-D__GLIBC_MINOR__={d}", .{
5344 target_version.minor,
5352 // Non-preprocessed assembly files don't support these flags.
5353 if (ext != .assembly) {
5354 try argv.append(if (target.os.tag == .freestanding) "-ffreestanding" else "-fhosted");
5355
5356 if (target_util.clangSupportsNoImplicitFloatArg(target) and target.floatAbi() == .soft) {
5357 try argv.append("-mno-implicit-float");
5358 }
5359
5360 if (target_util.hasRedZone(target)) {
5361 try argv.append(if (mod.red_zone) "-mred-zone" else "-mno-red-zone");
5362 }
5363
5364 try argv.append(if (mod.omit_frame_pointer) "-fomit-frame-pointer" else "-fno-omit-frame-pointer");
5365
5366 const ssp_buf_size = mod.stack_protector;
5367 if (ssp_buf_size != 0) {
5368 try argv.appendSlice(&[_][]const u8{
5369 "-fstack-protector-strong",
5370 "--param",
5371 try std.fmt.allocPrint(arena, "ssp-buffer-size={d}", .{ssp_buf_size}),
53455372 });
5346 try argv.append(glibc_minor_define);
5347 } else if (target.isMinGW()) {
5348 try argv.append("-D__MSVCRT_VERSION__=0xE00"); // use ucrt
5373 } else {
5374 try argv.append("-fno-stack-protector");
5375 }
5376
5377 try argv.append(if (mod.no_builtin) "-fno-builtin" else "-fbuiltin");
5378
5379 try argv.append(if (comp.function_sections) "-ffunction-sections" else "-fno-function-sections");
5380 try argv.append(if (comp.data_sections) "-fdata-sections" else "-fno-data-sections");
5381
5382 switch (mod.unwind_tables) {
5383 .none => {
5384 try argv.append("-fno-unwind-tables");
5385 try argv.append("-fno-asynchronous-unwind-tables");
5386 },
5387 .sync => {
5388 // Need to override Clang's convoluted default logic.
5389 try argv.append("-fno-asynchronous-unwind-tables");
5390 try argv.append("-funwind-tables");
5391 },
5392 .@"async" => try argv.append("-fasynchronous-unwind-tables"),
5393 }
5394
5395 try argv.append("-nostdinc");
5396
5397 if (ext == .cpp or ext == .hpp) {
5398 try argv.append("-nostdinc++");
5399 }
5400
5401 // LLVM IR files don't support these flags.
5402 if (ext != .ll and ext != .bc) {
5403 // https://github.com/llvm/llvm-project/issues/105972
5404 if (target.cpu.arch.isPowerPC() and target.floatAbi() == .soft) {
5405 try argv.append("-D__NO_FPRS__");
5406 try argv.append("-D_SOFT_FLOAT");
5407 try argv.append("-D_SOFT_DOUBLE");
5408 }
5409
5410 if (comp.config.link_libc) {
5411 if (target.isGnuLibC()) {
5412 const target_version = target.os.versionRange().gnuLibCVersion().?;
5413 const glibc_minor_define = try std.fmt.allocPrint(arena, "-D__GLIBC_MINOR__={d}", .{
5414 target_version.minor,
5415 });
5416 try argv.append(glibc_minor_define);
5417 } else if (target.isMinGW()) {
5418 try argv.append("-D__MSVCRT_VERSION__=0xE00"); // use ucrt
53495419
5350 switch (ext) {
5351 .c, .cpp, .m, .mm, .h, .hpp, .hm, .hmm, .cu, .rc, .assembly, .assembly_with_cpp => {
53525420 const minver: u16 = @truncate(@intFromEnum(target.os.versionRange().windows.min) >> 16);
53535421 try argv.append(
53545422 try std.fmt.allocPrint(arena, "-D_WIN32_WINNT=0x{x:0>4}", .{minver}),
53555423 );
5356 },
5357 else => {},
5424 }
53585425 }
5359 }
5360 }
53615426
5362 const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target);
5363 try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple });
5427 if (comp.config.link_libcpp) {
5428 try argv.append("-isystem");
5429 try argv.append(try std.fs.path.join(arena, &[_][]const u8{
5430 comp.zig_lib_directory.path.?, "libcxx", "include",
5431 }));
53645432
5365 switch (ext) {
5366 .c, .cpp, .m, .mm, .h, .hpp, .hm, .hmm, .cu, .rc => {
5367 try argv.appendSlice(&[_][]const u8{
5368 "-nostdinc",
5369 "-fno-spell-checking",
5370 });
5371 if (comp.config.lto) {
5372 try argv.append("-flto");
5433 try argv.append("-isystem");
5434 try argv.append(try std.fs.path.join(arena, &[_][]const u8{
5435 comp.zig_lib_directory.path.?, "libcxxabi", "include",
5436 }));
5437
5438 if (target.abi.isMusl()) {
5439 try argv.append("-D_LIBCPP_HAS_MUSL_LIBC");
5440 }
5441
5442 try argv.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");
5443 try argv.append("-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS");
5444 try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
5445
5446 if (!comp.config.any_non_single_threaded) {
5447 try argv.append("-D_LIBCPP_HAS_NO_THREADS");
5448 }
5449
5450 // See the comment in libcxx.zig for more details about this.
5451 try argv.append("-D_LIBCPP_PSTL_BACKEND_SERIAL");
5452
5453 try argv.append(try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_VERSION={d}", .{
5454 @intFromEnum(comp.libcxx_abi_version),
5455 }));
5456 try argv.append(try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_NAMESPACE=__{d}", .{
5457 @intFromEnum(comp.libcxx_abi_version),
5458 }));
5459
5460 try argv.append(libcxx.hardeningModeFlag(mod.optimize_mode));
5461 }
5462
5463 // According to Rich Felker libc headers are supposed to go before C language headers.
5464 // However as noted by @dimenus, appending libc headers before compiler headers breaks
5465 // intrinsics and other compiler specific items.
5466 try argv.append("-isystem");
5467 try argv.append(try std.fs.path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, "include" }));
5468
5469 try argv.ensureUnusedCapacity(comp.libc_include_dir_list.len * 2);
5470 for (comp.libc_include_dir_list) |include_dir| {
5471 try argv.append("-isystem");
5472 try argv.append(include_dir);
53735473 }
53745474
5375 if (ext == .mm) {
5376 try argv.append("-ObjC++");
5475 if (mod.resolved_target.is_native_os and mod.resolved_target.is_native_abi) {
5476 try argv.ensureUnusedCapacity(comp.native_system_include_paths.len * 2);
5477 for (comp.native_system_include_paths) |include_path| {
5478 argv.appendAssumeCapacity("-isystem");
5479 argv.appendAssumeCapacity(include_path);
5480 }
53775481 }
53785482
5483 if (comp.config.link_libunwind) {
5484 try argv.append("-isystem");
5485 try argv.append(try std.fs.path.join(arena, &[_][]const u8{
5486 comp.zig_lib_directory.path.?, "libunwind", "include",
5487 }));
5488 }
5489
5490 try argv.ensureUnusedCapacity(comp.libc_framework_dir_list.len * 2);
53795491 for (comp.libc_framework_dir_list) |framework_dir| {
53805492 try argv.appendSlice(&.{ "-iframework", framework_dir });
53815493 }
53825494
5495 try argv.ensureUnusedCapacity(comp.framework_dirs.len * 2);
53835496 for (comp.framework_dirs) |framework_dir| {
53845497 try argv.appendSlice(&.{ "-F", framework_dir });
53855498 }
5499 }
5500 }
53865501
5387 // According to Rich Felker libc headers are supposed to go before C language headers.
5388 // However as noted by @dimenus, appending libc headers before c_headers breaks intrinsics
5389 // and other compiler specific items.
5390 const c_headers_dir = try std.fs.path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, "include" });
5391 try argv.append("-isystem");
5392 try argv.append(c_headers_dir);
5502 // Only assembly files support these flags.
5503 switch (ext) {
5504 .assembly,
5505 .assembly_with_cpp,
5506 => {
5507 // The Clang assembler does not accept the list of CPU features like the
5508 // compiler frontend does. Therefore we must hard-code the -m flags for
5509 // all CPU features here.
5510 switch (target.cpu.arch) {
5511 .riscv32, .riscv64 => {
5512 const RvArchFeat = struct { char: u8, feat: std.Target.riscv.Feature };
5513 const letters = [_]RvArchFeat{
5514 .{ .char = 'm', .feat = .m },
5515 .{ .char = 'a', .feat = .a },
5516 .{ .char = 'f', .feat = .f },
5517 .{ .char = 'd', .feat = .d },
5518 .{ .char = 'c', .feat = .c },
5519 };
5520 const prefix: []const u8 = if (target.cpu.arch == .riscv64) "rv64" else "rv32";
5521 const prefix_len = 4;
5522 assert(prefix.len == prefix_len);
5523 var march_buf: [prefix_len + letters.len + 1]u8 = undefined;
5524 var march_index: usize = prefix_len;
5525 @memcpy(march_buf[0..prefix.len], prefix);
53935526
5394 for (comp.libc_include_dir_list) |include_dir| {
5395 try argv.append("-isystem");
5396 try argv.append(include_dir);
5527 if (std.Target.riscv.featureSetHas(target.cpu.features, .e)) {
5528 march_buf[march_index] = 'e';
5529 } else {
5530 march_buf[march_index] = 'i';
5531 }
5532 march_index += 1;
5533
5534 for (letters) |letter| {
5535 if (std.Target.riscv.featureSetHas(target.cpu.features, letter.feat)) {
5536 march_buf[march_index] = letter.char;
5537 march_index += 1;
5538 }
5539 }
5540
5541 const march_arg = try std.fmt.allocPrint(arena, "-march={s}", .{
5542 march_buf[0..march_index],
5543 });
5544 try argv.append(march_arg);
5545
5546 if (std.Target.riscv.featureSetHas(target.cpu.features, .relax)) {
5547 try argv.append("-mrelax");
5548 } else {
5549 try argv.append("-mno-relax");
5550 }
5551 if (std.Target.riscv.featureSetHas(target.cpu.features, .save_restore)) {
5552 try argv.append("-msave-restore");
5553 } else {
5554 try argv.append("-mno-save-restore");
5555 }
5556 },
5557 .mips, .mipsel, .mips64, .mips64el => {
5558 if (target.cpu.model.llvm_name) |llvm_name| {
5559 try argv.append(try std.fmt.allocPrint(arena, "-march={s}", .{llvm_name}));
5560 }
5561 },
5562 else => {
5563 // TODO
5564 },
5565 }
5566
5567 if (target_util.clangAssemblerSupportsMcpuArg(target)) {
5568 if (target.cpu.model.llvm_name) |llvm_name| {
5569 try argv.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{llvm_name}));
5570 }
53975571 }
5572 },
5573 else => {},
5574 }
5575
5576 // Only C-family files support these flags.
5577 switch (ext) {
5578 .c,
5579 .h,
5580 .cpp,
5581 .hpp,
5582 .m,
5583 .hm,
5584 .mm,
5585 .hmm,
5586 .cu,
5587 => {
5588 try argv.append("-fno-spell-checking");
53985589
53995590 if (target_util.clangSupportsTargetCpuArg(target)) {
54005591 if (target.cpu.model.llvm_name) |llvm_name| {
......@@ -5421,9 +5612,6 @@ pub fn addCCArgs(
54215612 argv.appendAssumeCapacity(arg);
54225613 }
54235614 }
5424 if (mod.code_model != .default) {
5425 try argv.append(try std.fmt.allocPrint(arena, "-mcmodel={s}", .{@tagName(mod.code_model)}));
5426 }
54275615
54285616 switch (target.os.tag) {
54295617 .windows => {
......@@ -5506,23 +5694,6 @@ pub fn addCCArgs(
55065694 }
55075695 }
55085696
5509 if (target_util.hasRedZone(target)) {
5510 try argv.append(if (mod.red_zone) "-mred-zone" else "-mno-red-zone");
5511 }
5512
5513 try argv.append(if (mod.omit_frame_pointer) "-fomit-frame-pointer" else "-fno-omit-frame-pointer");
5514
5515 const ssp_buf_size = mod.stack_protector;
5516 if (ssp_buf_size != 0) {
5517 try argv.appendSlice(&[_][]const u8{
5518 "-fstack-protector-strong",
5519 "--param",
5520 try std.fmt.allocPrint(arena, "ssp-buffer-size={d}", .{ssp_buf_size}),
5521 });
5522 } else {
5523 try argv.append("-fno-stack-protector");
5524 }
5525
55265697 switch (mod.optimize_mode) {
55275698 .Debug => {
55285699 // windows c runtime requires -D_DEBUG if using debug libraries
......@@ -5556,177 +5727,8 @@ pub fn addCCArgs(
55565727 if (mod.optimize_mode != .Debug) {
55575728 try argv.append("-Werror=date-time");
55585729 }
5559
5560 switch (mod.unwind_tables) {
5561 .none => {
5562 try argv.append("-fno-unwind-tables");
5563 try argv.append("-fno-asynchronous-unwind-tables");
5564 },
5565 .sync => {
5566 // Need to override Clang's convoluted default logic.
5567 try argv.append("-fno-asynchronous-unwind-tables");
5568 try argv.append("-funwind-tables");
5569 },
5570 .@"async" => try argv.append("-fasynchronous-unwind-tables"),
5571 }
55725730 },
5573 .shared_library, .ll, .bc, .unknown, .static_library, .object, .def, .zig, .res, .manifest => {},
5574 .assembly, .assembly_with_cpp => {
5575 if (ext == .assembly_with_cpp) {
5576 const c_headers_dir = try std.fs.path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, "include" });
5577 try argv.append("-isystem");
5578 try argv.append(c_headers_dir);
5579
5580 for (comp.libc_include_dir_list) |include_dir| {
5581 try argv.append("-isystem");
5582 try argv.append(include_dir);
5583 }
5584 }
5585
5586 // The Clang assembler does not accept the list of CPU features like the
5587 // compiler frontend does. Therefore we must hard-code the -m flags for
5588 // all CPU features here.
5589 switch (target.cpu.arch) {
5590 .riscv32, .riscv64 => {
5591 const RvArchFeat = struct { char: u8, feat: std.Target.riscv.Feature };
5592 const letters = [_]RvArchFeat{
5593 .{ .char = 'm', .feat = .m },
5594 .{ .char = 'a', .feat = .a },
5595 .{ .char = 'f', .feat = .f },
5596 .{ .char = 'd', .feat = .d },
5597 .{ .char = 'c', .feat = .c },
5598 };
5599 const prefix: []const u8 = if (target.cpu.arch == .riscv64) "rv64" else "rv32";
5600 const prefix_len = 4;
5601 assert(prefix.len == prefix_len);
5602 var march_buf: [prefix_len + letters.len + 1]u8 = undefined;
5603 var march_index: usize = prefix_len;
5604 @memcpy(march_buf[0..prefix.len], prefix);
5605
5606 if (std.Target.riscv.featureSetHas(target.cpu.features, .e)) {
5607 march_buf[march_index] = 'e';
5608 } else {
5609 march_buf[march_index] = 'i';
5610 }
5611 march_index += 1;
5612
5613 for (letters) |letter| {
5614 if (std.Target.riscv.featureSetHas(target.cpu.features, letter.feat)) {
5615 march_buf[march_index] = letter.char;
5616 march_index += 1;
5617 }
5618 }
5619
5620 const march_arg = try std.fmt.allocPrint(arena, "-march={s}", .{
5621 march_buf[0..march_index],
5622 });
5623 try argv.append(march_arg);
5624
5625 if (std.Target.riscv.featureSetHas(target.cpu.features, .relax)) {
5626 try argv.append("-mrelax");
5627 } else {
5628 try argv.append("-mno-relax");
5629 }
5630 if (std.Target.riscv.featureSetHas(target.cpu.features, .save_restore)) {
5631 try argv.append("-msave-restore");
5632 } else {
5633 try argv.append("-mno-save-restore");
5634 }
5635 },
5636 .mips, .mipsel, .mips64, .mips64el => {
5637 if (target.cpu.model.llvm_name) |llvm_name| {
5638 try argv.append(try std.fmt.allocPrint(arena, "-march={s}", .{llvm_name}));
5639 }
5640 },
5641 else => {
5642 // TODO
5643 },
5644 }
5645 if (target_util.clangAssemblerSupportsMcpuArg(target)) {
5646 if (target.cpu.model.llvm_name) |llvm_name| {
5647 try argv.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{llvm_name}));
5648 }
5649 }
5650 },
5651 }
5652
5653 if (comp.mingw_unicode_entry_point) {
5654 try argv.append("-municode");
5655 }
5656
5657 if (target.cpu.arch.isArm()) {
5658 try argv.append(if (target.cpu.arch.isThumb()) "-mthumb" else "-mno-thumb");
5659 }
5660
5661 if (target_util.supports_fpic(target)) {
5662 try argv.append(if (mod.pic) "-fPIC" else "-fno-PIC");
5663 }
5664
5665 try argv.ensureUnusedCapacity(2);
5666 switch (comp.config.debug_format) {
5667 .strip => {},
5668 .code_view => {
5669 // -g is required here because -gcodeview doesn't trigger debug info
5670 // generation, it only changes the type of information generated.
5671 argv.appendSliceAssumeCapacity(&.{ "-g", "-gcodeview" });
5672 },
5673 .dwarf => |f| {
5674 argv.appendAssumeCapacity("-gdwarf-4");
5675 switch (f) {
5676 .@"32" => argv.appendAssumeCapacity("-gdwarf32"),
5677 .@"64" => argv.appendAssumeCapacity("-gdwarf64"),
5678 }
5679 },
5680 }
5681
5682 if (target_util.llvmMachineAbi(target)) |mabi| {
5683 try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{mabi}));
5684 }
5685
5686 // We might want to support -mfloat-abi=softfp for Arm and CSKY here in the future.
5687 if (target_util.clangSupportsFloatAbiArg(target)) {
5688 const fabi = @tagName(target.floatAbi());
5689
5690 try argv.append(switch (target.cpu.arch) {
5691 // For whatever reason, Clang doesn't support `-mfloat-abi` for s390x.
5692 .s390x => try std.fmt.allocPrint(arena, "-m{s}-float", .{fabi}),
5693 else => try std.fmt.allocPrint(arena, "-mfloat-abi={s}", .{fabi}),
5694 });
5695 }
5696
5697 if (target_util.clangSupportsNoImplicitFloatArg(target) and target.floatAbi() == .soft) {
5698 try argv.append("-mno-implicit-float");
5699 }
5700
5701 // https://github.com/llvm/llvm-project/issues/105972
5702 if (target.cpu.arch.isPowerPC() and target.floatAbi() == .soft) {
5703 try argv.append("-D__NO_FPRS__");
5704 try argv.append("-D_SOFT_FLOAT");
5705 try argv.append("-D_SOFT_DOUBLE");
5706 }
5707
5708 if (out_dep_path) |p| {
5709 try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p });
5710 }
5711
5712 // We never want clang to invoke the system assembler for anything. So we would want
5713 // this option always enabled. However, it only matters for some targets. To avoid
5714 // "unused parameter" warnings, and to keep CLI spam to a minimum, we only put this
5715 // flag on the command line if it is necessary.
5716 if (target_util.clangMightShellOutForAssembly(target)) {
5717 try argv.append("-integrated-as");
5718 }
5719
5720 if (target.os.tag == .freestanding) {
5721 try argv.append("-ffreestanding");
5722 }
5723
5724 if (mod.resolved_target.is_native_os and mod.resolved_target.is_native_abi) {
5725 try argv.ensureUnusedCapacity(comp.native_system_include_paths.len * 2);
5726 for (comp.native_system_include_paths) |include_path| {
5727 argv.appendAssumeCapacity("-isystem");
5728 argv.appendAssumeCapacity(include_path);
5729 }
5731 else => {},
57305732 }
57315733
57325734 try argv.appendSlice(comp.global_cc_argv);