authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-12-15 04:53:24+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-12-15 04:53:24+01:00
logaf89bb05d392b34a9ac257d166df1c794542f2e8
treed982dc1d7db94c3e35f5d55550c03425cf27100a
parentd5c2f527b488a17e20b0698ff02c9b67f1148210
parent39c4efa2a75e1e369a5d39b32d91d376fbd2257a
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #22224 from alexrp/cc-args

`Compilation`: Clean up `addCCArgs()` + some minor improvements

1 files changed, 337 insertions(+), 279 deletions(-)

src/Compilation.zig+337-279
......@@ -4687,19 +4687,19 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
46874687
46884688 try argv.appendSlice(&[_][]const u8{ self_exe_path, "clang" });
46894689 // if "ext" is explicit, add "-x <lang>". Otherwise let clang do its thing.
4690 if (c_object.src.ext != null) {
4690 if (c_object.src.ext != null or ext.clangNeedsLanguageOverride()) {
46914691 try argv.appendSlice(&[_][]const u8{ "-x", switch (ext) {
46924692 .assembly => "assembler",
46934693 .assembly_with_cpp => "assembler-with-cpp",
46944694 .c => "c",
4695 .cpp => "c++",
46964695 .h => "c-header",
4696 .cpp => "c++",
46974697 .hpp => "c++-header",
4698 .m => "objective-c",
46984699 .hm => "objective-c-header",
4700 .mm => "objective-c++",
46994701 .hmm => "objective-c++-header",
47004702 .cu => "cuda",
4701 .m => "objective-c",
4702 .mm => "objective-c++",
47034703 else => fatal("language '{s}' is unsupported in this context", .{@tagName(ext)}),
47044704 } });
47054705 }
......@@ -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,117 +5281,312 @@ 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 },
53975565 }
53985566
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 }
5571 }
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");
5589
53995590 if (target_util.clangSupportsTargetCpuArg(target)) {
54005591 if (target.cpu.model.llvm_name) |llvm_name| {
54015592 try argv.appendSlice(&[_][]const u8{
......@@ -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 }
5572 },
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 }
56795730 },
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);
......@@ -5840,6 +5842,36 @@ pub const FileExt = enum {
58405842 manifest,
58415843 unknown,
58425844
5845 pub fn clangNeedsLanguageOverride(ext: FileExt) bool {
5846 return switch (ext) {
5847 .h,
5848 .hpp,
5849 .hm,
5850 .hmm,
5851 => true,
5852
5853 .c,
5854 .cpp,
5855 .cu,
5856 .m,
5857 .mm,
5858 .ll,
5859 .bc,
5860 .assembly,
5861 .assembly_with_cpp,
5862 .shared_library,
5863 .object,
5864 .static_library,
5865 .zig,
5866 .def,
5867 .rc,
5868 .res,
5869 .manifest,
5870 .unknown,
5871 => false,
5872 };
5873 }
5874
58435875 pub fn clangSupportsDiagnostics(ext: FileExt) bool {
58445876 return switch (ext) {
58455877 .c, .cpp, .h, .hpp, .hm, .hmm, .m, .mm, .cu, .ll, .bc => true,
......@@ -5861,12 +5893,11 @@ pub const FileExt = enum {
58615893
58625894 pub fn clangSupportsDepFile(ext: FileExt) bool {
58635895 return switch (ext) {
5864 .c, .cpp, .h, .hpp, .hm, .hmm, .m, .mm, .cu => true,
5896 .assembly_with_cpp, .c, .cpp, .h, .hpp, .hm, .hmm, .m, .mm, .cu => true,
58655897
58665898 .ll,
58675899 .bc,
58685900 .assembly,
5869 .assembly_with_cpp,
58705901 .shared_library,
58715902 .object,
58725903 .static_library,
......@@ -5886,9 +5917,9 @@ pub const FileExt = enum {
58865917 .cpp => ".cpp",
58875918 .cu => ".cu",
58885919 .h => ".h",
5889 .hpp => ".h",
5890 .hm => ".h",
5891 .hmm => ".h",
5920 .hpp => ".hpp",
5921 .hm => ".hm",
5922 .hmm => ".hmm",
58925923 .m => ".m",
58935924 .mm => ".mm",
58945925 .ll => ".ll",
......@@ -5925,21 +5956,42 @@ pub fn hasCExt(filename: []const u8) bool {
59255956 return mem.endsWith(u8, filename, ".c");
59265957}
59275958
5959pub fn hasCHExt(filename: []const u8) bool {
5960 return mem.endsWith(u8, filename, ".h");
5961}
5962
59285963pub fn hasCppExt(filename: []const u8) bool {
59295964 return mem.endsWith(u8, filename, ".C") or
59305965 mem.endsWith(u8, filename, ".cc") or
5966 mem.endsWith(u8, filename, ".cp") or
5967 mem.endsWith(u8, filename, ".CPP") or
59315968 mem.endsWith(u8, filename, ".cpp") or
59325969 mem.endsWith(u8, filename, ".cxx") or
59335970 mem.endsWith(u8, filename, ".c++") or
59345971 mem.endsWith(u8, filename, ".stub");
59355972}
59365973
5974pub fn hasCppHExt(filename: []const u8) bool {
5975 return mem.endsWith(u8, filename, ".hh") or
5976 mem.endsWith(u8, filename, ".hpp") or
5977 mem.endsWith(u8, filename, ".hxx");
5978}
5979
59375980pub fn hasObjCExt(filename: []const u8) bool {
59385981 return mem.endsWith(u8, filename, ".m");
59395982}
59405983
5984pub fn hasObjCHExt(filename: []const u8) bool {
5985 return mem.endsWith(u8, filename, ".hm");
5986}
5987
59415988pub fn hasObjCppExt(filename: []const u8) bool {
5942 return mem.endsWith(u8, filename, ".mm");
5989 return mem.endsWith(u8, filename, ".M") or
5990 mem.endsWith(u8, filename, ".mm");
5991}
5992
5993pub fn hasObjCppHExt(filename: []const u8) bool {
5994 return mem.endsWith(u8, filename, ".hmm");
59435995}
59445996
59455997pub fn hasSharedLibraryExt(filename: []const u8) bool {
......@@ -5972,12 +6024,20 @@ pub fn hasSharedLibraryExt(filename: []const u8) bool {
59726024pub fn classifyFileExt(filename: []const u8) FileExt {
59736025 if (hasCExt(filename)) {
59746026 return .c;
6027 } else if (hasCHExt(filename)) {
6028 return .h;
59756029 } else if (hasCppExt(filename)) {
59766030 return .cpp;
6031 } else if (hasCppHExt(filename)) {
6032 return .hpp;
59776033 } else if (hasObjCExt(filename)) {
59786034 return .m;
6035 } else if (hasObjCHExt(filename)) {
6036 return .hm;
59796037 } else if (hasObjCppExt(filename)) {
59806038 return .mm;
6039 } else if (hasObjCppHExt(filename)) {
6040 return .hmm;
59816041 } else if (mem.endsWith(u8, filename, ".ll")) {
59826042 return .ll;
59836043 } else if (mem.endsWith(u8, filename, ".bc")) {
......@@ -5986,8 +6046,6 @@ pub fn classifyFileExt(filename: []const u8) FileExt {
59866046 return .assembly;
59876047 } else if (mem.endsWith(u8, filename, ".S")) {
59886048 return .assembly_with_cpp;
5989 } else if (mem.endsWith(u8, filename, ".h")) {
5990 return .h;
59916049 } else if (mem.endsWith(u8, filename, ".zig")) {
59926050 return .zig;
59936051 } else if (hasSharedLibraryExt(filename)) {