| ... | ... | @@ -6608,14 +6608,43 @@ pub fn addTranslateCCArgs( |
| 6608 | 6608 | out_dep_path: ?[]const u8, |
| 6609 | 6609 | owner_mod: *Package.Module, |
| 6610 | 6610 | ) !void { |
| 6611 | const target = &owner_mod.resolved_target.result; |
| 6612 | |
| 6611 | 6613 | try argv.appendSlice(&.{ "-x", "c" }); |
| 6612 | | try comp.addCCArgs(arena, argv, ext, out_dep_path, owner_mod); |
| 6613 | | // This gives us access to preprocessing entities, presumably at the cost of performance. |
| 6614 | | try argv.appendSlice(&.{ "-Xclang", "-detailed-preprocessing-record" }); |
| 6614 | |
| 6615 | const resource_path = try comp.dirs.zig_lib.join(arena, &.{"compiler/aro/include"}); |
| 6616 | try argv.appendSlice(&.{ "-isystem", resource_path }); |
| 6617 | |
| 6618 | try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, owner_mod); |
| 6619 | |
| 6620 | try argv.appendSlice(&[_][]const u8{ "-target", try target.zigTriple(arena) }); |
| 6621 | |
| 6622 | const mcpu = mcpu: { |
| 6623 | var buf: std.ArrayListUnmanaged(u8) = .empty; |
| 6624 | defer buf.deinit(comp.gpa); |
| 6625 | |
| 6626 | try buf.print(comp.gpa, "-mcpu={s}", .{target.cpu.model.name}); |
| 6627 | |
| 6628 | // TODO better serialization https://github.com/ziglang/zig/issues/4584 |
| 6629 | const all_features_list = target.cpu.arch.allFeaturesList(); |
| 6630 | try argv.ensureUnusedCapacity(all_features_list.len * 4); |
| 6631 | for (all_features_list, 0..) |feature, index_usize| { |
| 6632 | const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); |
| 6633 | const is_enabled = target.cpu.features.isEnabled(index); |
| 6634 | |
| 6635 | const plus_or_minus = "-+"[@intFromBool(is_enabled)]; |
| 6636 | try buf.print(comp.gpa, "{c}{s}", .{ plus_or_minus, feature.name }); |
| 6637 | } |
| 6638 | break :mcpu try buf.toOwnedSlice(arena); |
| 6639 | }; |
| 6640 | try argv.append(mcpu); |
| 6641 | |
| 6642 | try argv.appendSlice(comp.global_cc_argv); |
| 6643 | try argv.appendSlice(owner_mod.cc_argv); |
| 6615 | 6644 | } |
| 6616 | 6645 | |
| 6617 | 6646 | /// Add common C compiler args between translate-c and C object compilation. |
| 6618 | | pub fn addCCArgs( |
| 6647 | fn addCommonCCArgs( |
| 6619 | 6648 | comp: *const Compilation, |
| 6620 | 6649 | arena: Allocator, |
| 6621 | 6650 | argv: *std.array_list.Managed([]const u8), |
| ... | ... | @@ -6625,32 +6654,13 @@ pub fn addCCArgs( |
| 6625 | 6654 | ) !void { |
| 6626 | 6655 | const target = &mod.resolved_target.result; |
| 6627 | 6656 | |
| 6628 | | // As of Clang 16.x, it will by default read extra flags from /etc/clang. |
| 6629 | | // I'm sure the person who implemented this means well, but they have a lot |
| 6630 | | // to learn about abstractions and where the appropriate boundaries between |
| 6631 | | // them are. The road to hell is paved with good intentions. Fortunately it |
| 6632 | | // can be disabled. |
| 6633 | | try argv.append("--no-default-config"); |
| 6634 | | |
| 6635 | | // We don't ever put `-fcolor-diagnostics` or `-fno-color-diagnostics` because in passthrough mode |
| 6636 | | // we want Clang to infer it, and in normal mode we always want it off, which will be true since |
| 6637 | | // clang will detect stderr as a pipe rather than a terminal. |
| 6638 | | if (!comp.clang_passthrough_mode and ext.clangSupportsDiagnostics()) { |
| 6639 | | // Make stderr more easily parseable. |
| 6640 | | try argv.append("-fno-caret-diagnostics"); |
| 6641 | | } |
| 6642 | | |
| 6643 | | // We never want clang to invoke the system assembler for anything. So we would want |
| 6644 | | // this option always enabled. However, it only matters for some targets. To avoid |
| 6645 | | // "unused parameter" warnings, and to keep CLI spam to a minimum, we only put this |
| 6646 | | // flag on the command line if it is necessary. |
| 6647 | | if (target_util.clangMightShellOutForAssembly(target)) { |
| 6648 | | try argv.append("-integrated-as"); |
| 6657 | if (target_util.supports_fpic(target)) { |
| 6658 | // PIE needs to go before PIC because Clang interprets `-fno-PIE` to imply `-fno-PIC`, which |
| 6659 | // we don't necessarily want. |
| 6660 | try argv.append(if (comp.config.pie) "-fPIE" else "-fno-PIE"); |
| 6661 | try argv.append(if (mod.pic) "-fPIC" else "-fno-PIC"); |
| 6649 | 6662 | } |
| 6650 | 6663 | |
| 6651 | | const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target); |
| 6652 | | try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple }); |
| 6653 | | |
| 6654 | 6664 | switch (target.os.tag) { |
| 6655 | 6665 | .ios, .macos, .tvos, .watchos => |os| { |
| 6656 | 6666 | try argv.ensureUnusedCapacity(2); |
| ... | ... | @@ -6676,78 +6686,6 @@ pub fn addCCArgs( |
| 6676 | 6686 | else => {}, |
| 6677 | 6687 | } |
| 6678 | 6688 | |
| 6679 | | const xclang_flag = switch (ext) { |
| 6680 | | .assembly, .assembly_with_cpp => "-Xclangas", |
| 6681 | | else => "-Xclang", |
| 6682 | | }; |
| 6683 | | |
| 6684 | | if (target_util.clangSupportsTargetCpuArg(target)) { |
| 6685 | | if (target.cpu.model.llvm_name) |llvm_name| { |
| 6686 | | try argv.appendSlice(&[_][]const u8{ |
| 6687 | | xclang_flag, "-target-cpu", xclang_flag, llvm_name, |
| 6688 | | }); |
| 6689 | | } |
| 6690 | | } |
| 6691 | | |
| 6692 | | // It would be really nice if there was a more compact way to communicate this info to Clang. |
| 6693 | | const all_features_list = target.cpu.arch.allFeaturesList(); |
| 6694 | | try argv.ensureUnusedCapacity(all_features_list.len * 4); |
| 6695 | | for (all_features_list, 0..) |feature, index_usize| { |
| 6696 | | const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); |
| 6697 | | const is_enabled = target.cpu.features.isEnabled(index); |
| 6698 | | |
| 6699 | | if (feature.llvm_name) |llvm_name| { |
| 6700 | | // We communicate float ABI to Clang through the dedicated options. |
| 6701 | | if (std.mem.startsWith(u8, llvm_name, "soft-float") or |
| 6702 | | std.mem.startsWith(u8, llvm_name, "hard-float")) |
| 6703 | | continue; |
| 6704 | | |
| 6705 | | // Ignore these until we figure out how to handle the concept of omitting features. |
| 6706 | | // See https://github.com/ziglang/zig/issues/23539 |
| 6707 | | if (target_util.isDynamicAMDGCNFeature(target, feature)) continue; |
| 6708 | | |
| 6709 | | argv.appendSliceAssumeCapacity(&[_][]const u8{ xclang_flag, "-target-feature", xclang_flag }); |
| 6710 | | const plus_or_minus = "-+"[@intFromBool(is_enabled)]; |
| 6711 | | const arg = try std.fmt.allocPrint(arena, "{c}{s}", .{ plus_or_minus, llvm_name }); |
| 6712 | | argv.appendAssumeCapacity(arg); |
| 6713 | | } |
| 6714 | | } |
| 6715 | | |
| 6716 | | if (target.cpu.arch.isThumb()) { |
| 6717 | | try argv.append(switch (ext) { |
| 6718 | | .assembly, .assembly_with_cpp => "-Wa,-mthumb", |
| 6719 | | else => "-mthumb", |
| 6720 | | }); |
| 6721 | | } |
| 6722 | | |
| 6723 | | if (target_util.llvmMachineAbi(target)) |mabi| { |
| 6724 | | // Clang's integrated Arm assembler doesn't support `-mabi` yet... |
| 6725 | | // Clang's FreeBSD driver doesn't support `-mabi` on PPC64 (ELFv2 is used anyway). |
| 6726 | | if (!(target.cpu.arch.isArm() and (ext == .assembly or ext == .assembly_with_cpp)) and |
| 6727 | | !(target.cpu.arch.isPowerPC64() and target.os.tag == .freebsd)) |
| 6728 | | { |
| 6729 | | try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{mabi})); |
| 6730 | | } |
| 6731 | | } |
| 6732 | | |
| 6733 | | // We might want to support -mfloat-abi=softfp for Arm and CSKY here in the future. |
| 6734 | | if (target_util.clangSupportsFloatAbiArg(target)) { |
| 6735 | | const fabi = @tagName(target.abi.float()); |
| 6736 | | |
| 6737 | | try argv.append(switch (target.cpu.arch) { |
| 6738 | | // For whatever reason, Clang doesn't support `-mfloat-abi` for s390x. |
| 6739 | | .s390x => try std.fmt.allocPrint(arena, "-m{s}-float", .{fabi}), |
| 6740 | | else => try std.fmt.allocPrint(arena, "-mfloat-abi={s}", .{fabi}), |
| 6741 | | }); |
| 6742 | | } |
| 6743 | | |
| 6744 | | if (target_util.supports_fpic(target)) { |
| 6745 | | // PIE needs to go before PIC because Clang interprets `-fno-PIE` to imply `-fno-PIC`, which |
| 6746 | | // we don't necessarily want. |
| 6747 | | try argv.append(if (comp.config.pie) "-fPIE" else "-fno-PIE"); |
| 6748 | | try argv.append(if (mod.pic) "-fPIC" else "-fno-PIC"); |
| 6749 | | } |
| 6750 | | |
| 6751 | 6689 | if (comp.mingw_unicode_entry_point) { |
| 6752 | 6690 | try argv.append("-municode"); |
| 6753 | 6691 | } |
| ... | ... | @@ -6784,45 +6722,6 @@ pub fn addCCArgs( |
| 6784 | 6722 | if (ext != .assembly) { |
| 6785 | 6723 | try argv.append(if (target.os.tag == .freestanding) "-ffreestanding" else "-fhosted"); |
| 6786 | 6724 | |
| 6787 | | if (target_util.clangSupportsNoImplicitFloatArg(target) and target.abi.float() == .soft) { |
| 6788 | | try argv.append("-mno-implicit-float"); |
| 6789 | | } |
| 6790 | | |
| 6791 | | if (target_util.hasRedZone(target)) { |
| 6792 | | try argv.append(if (mod.red_zone) "-mred-zone" else "-mno-red-zone"); |
| 6793 | | } |
| 6794 | | |
| 6795 | | try argv.append(if (mod.omit_frame_pointer) "-fomit-frame-pointer" else "-fno-omit-frame-pointer"); |
| 6796 | | |
| 6797 | | const ssp_buf_size = mod.stack_protector; |
| 6798 | | if (ssp_buf_size != 0) { |
| 6799 | | try argv.appendSlice(&[_][]const u8{ |
| 6800 | | "-fstack-protector-strong", |
| 6801 | | "--param", |
| 6802 | | try std.fmt.allocPrint(arena, "ssp-buffer-size={d}", .{ssp_buf_size}), |
| 6803 | | }); |
| 6804 | | } else { |
| 6805 | | try argv.append("-fno-stack-protector"); |
| 6806 | | } |
| 6807 | | |
| 6808 | | try argv.append(if (mod.no_builtin) "-fno-builtin" else "-fbuiltin"); |
| 6809 | | |
| 6810 | | try argv.append(if (comp.function_sections) "-ffunction-sections" else "-fno-function-sections"); |
| 6811 | | try argv.append(if (comp.data_sections) "-fdata-sections" else "-fno-data-sections"); |
| 6812 | | |
| 6813 | | switch (mod.unwind_tables) { |
| 6814 | | .none => { |
| 6815 | | try argv.append("-fno-unwind-tables"); |
| 6816 | | try argv.append("-fno-asynchronous-unwind-tables"); |
| 6817 | | }, |
| 6818 | | .sync => { |
| 6819 | | // Need to override Clang's convoluted default logic. |
| 6820 | | try argv.append("-fno-asynchronous-unwind-tables"); |
| 6821 | | try argv.append("-funwind-tables"); |
| 6822 | | }, |
| 6823 | | .async => try argv.append("-fasynchronous-unwind-tables"), |
| 6824 | | } |
| 6825 | | |
| 6826 | 6725 | try argv.append("-nostdinc"); |
| 6827 | 6726 | |
| 6828 | 6727 | if (ext == .cpp or ext == .hpp) { |
| ... | ... | @@ -6961,80 +6860,6 @@ pub fn addCCArgs( |
| 6961 | 6860 | else => {}, |
| 6962 | 6861 | } |
| 6963 | 6862 | |
| 6964 | | // Only assembly files support these flags. |
| 6965 | | switch (ext) { |
| 6966 | | .assembly, |
| 6967 | | .assembly_with_cpp, |
| 6968 | | => { |
| 6969 | | // The Clang assembler does not accept the list of CPU features like the |
| 6970 | | // compiler frontend does. Therefore we must hard-code the -m flags for |
| 6971 | | // all CPU features here. |
| 6972 | | switch (target.cpu.arch) { |
| 6973 | | .riscv32, .riscv32be, .riscv64, .riscv64be => { |
| 6974 | | const RvArchFeat = struct { char: u8, feat: std.Target.riscv.Feature }; |
| 6975 | | const letters = [_]RvArchFeat{ |
| 6976 | | .{ .char = 'm', .feat = .m }, |
| 6977 | | .{ .char = 'a', .feat = .a }, |
| 6978 | | .{ .char = 'f', .feat = .f }, |
| 6979 | | .{ .char = 'd', .feat = .d }, |
| 6980 | | .{ .char = 'c', .feat = .c }, |
| 6981 | | }; |
| 6982 | | const prefix: []const u8 = if (target.cpu.arch == .riscv64) "rv64" else "rv32"; |
| 6983 | | const prefix_len = 4; |
| 6984 | | assert(prefix.len == prefix_len); |
| 6985 | | var march_buf: [prefix_len + letters.len + 1]u8 = undefined; |
| 6986 | | var march_index: usize = prefix_len; |
| 6987 | | @memcpy(march_buf[0..prefix.len], prefix); |
| 6988 | | |
| 6989 | | if (target.cpu.has(.riscv, .e)) { |
| 6990 | | march_buf[march_index] = 'e'; |
| 6991 | | } else { |
| 6992 | | march_buf[march_index] = 'i'; |
| 6993 | | } |
| 6994 | | march_index += 1; |
| 6995 | | |
| 6996 | | for (letters) |letter| { |
| 6997 | | if (target.cpu.has(.riscv, letter.feat)) { |
| 6998 | | march_buf[march_index] = letter.char; |
| 6999 | | march_index += 1; |
| 7000 | | } |
| 7001 | | } |
| 7002 | | |
| 7003 | | const march_arg = try std.fmt.allocPrint(arena, "-march={s}", .{ |
| 7004 | | march_buf[0..march_index], |
| 7005 | | }); |
| 7006 | | try argv.append(march_arg); |
| 7007 | | |
| 7008 | | if (target.cpu.has(.riscv, .relax)) { |
| 7009 | | try argv.append("-mrelax"); |
| 7010 | | } else { |
| 7011 | | try argv.append("-mno-relax"); |
| 7012 | | } |
| 7013 | | if (target.cpu.has(.riscv, .save_restore)) { |
| 7014 | | try argv.append("-msave-restore"); |
| 7015 | | } else { |
| 7016 | | try argv.append("-mno-save-restore"); |
| 7017 | | } |
| 7018 | | }, |
| 7019 | | .mips, .mipsel, .mips64, .mips64el => { |
| 7020 | | if (target.cpu.model.llvm_name) |llvm_name| { |
| 7021 | | try argv.append(try std.fmt.allocPrint(arena, "-march={s}", .{llvm_name})); |
| 7022 | | } |
| 7023 | | }, |
| 7024 | | else => { |
| 7025 | | // TODO |
| 7026 | | }, |
| 7027 | | } |
| 7028 | | |
| 7029 | | if (target_util.clangAssemblerSupportsMcpuArg(target)) { |
| 7030 | | if (target.cpu.model.llvm_name) |llvm_name| { |
| 7031 | | try argv.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{llvm_name})); |
| 7032 | | } |
| 7033 | | } |
| 7034 | | }, |
| 7035 | | else => {}, |
| 7036 | | } |
| 7037 | | |
| 7038 | 6863 | // Only compiled files support these flags. |
| 7039 | 6864 | switch (ext) { |
| 7040 | 6865 | .c, |
| ... | ... | @@ -7133,6 +6958,243 @@ pub fn addCCArgs( |
| 7133 | 6958 | }, |
| 7134 | 6959 | else => {}, |
| 7135 | 6960 | } |
| 6961 | } |
| 6962 | |
| 6963 | /// Add common C compiler args and Clang specific args. |
| 6964 | pub fn addCCArgs( |
| 6965 | comp: *const Compilation, |
| 6966 | arena: Allocator, |
| 6967 | argv: *std.ArrayList([]const u8), |
| 6968 | ext: FileExt, |
| 6969 | out_dep_path: ?[]const u8, |
| 6970 | mod: *Package.Module, |
| 6971 | ) !void { |
| 6972 | const target = &mod.resolved_target.result; |
| 6973 | |
| 6974 | // As of Clang 16.x, it will by default read extra flags from /etc/clang. |
| 6975 | // I'm sure the person who implemented this means well, but they have a lot |
| 6976 | // to learn about abstractions and where the appropriate boundaries between |
| 6977 | // them are. The road to hell is paved with good intentions. Fortunately it |
| 6978 | // can be disabled. |
| 6979 | try argv.append("--no-default-config"); |
| 6980 | |
| 6981 | // We don't ever put `-fcolor-diagnostics` or `-fno-color-diagnostics` because in passthrough mode |
| 6982 | // we want Clang to infer it, and in normal mode we always want it off, which will be true since |
| 6983 | // clang will detect stderr as a pipe rather than a terminal. |
| 6984 | if (!comp.clang_passthrough_mode and ext.clangSupportsDiagnostics()) { |
| 6985 | // Make stderr more easily parseable. |
| 6986 | try argv.append("-fno-caret-diagnostics"); |
| 6987 | } |
| 6988 | |
| 6989 | // We never want clang to invoke the system assembler for anything. So we would want |
| 6990 | // this option always enabled. However, it only matters for some targets. To avoid |
| 6991 | // "unused parameter" warnings, and to keep CLI spam to a minimum, we only put this |
| 6992 | // flag on the command line if it is necessary. |
| 6993 | if (target_util.clangMightShellOutForAssembly(target)) { |
| 6994 | try argv.append("-integrated-as"); |
| 6995 | } |
| 6996 | |
| 6997 | const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target); |
| 6998 | try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple }); |
| 6999 | |
| 7000 | if (target.cpu.arch.isThumb()) { |
| 7001 | try argv.append(switch (ext) { |
| 7002 | .assembly, .assembly_with_cpp => "-Wa,-mthumb", |
| 7003 | else => "-mthumb", |
| 7004 | }); |
| 7005 | } |
| 7006 | |
| 7007 | if (target_util.llvmMachineAbi(target)) |mabi| { |
| 7008 | // Clang's integrated Arm assembler doesn't support `-mabi` yet... |
| 7009 | // Clang's FreeBSD driver doesn't support `-mabi` on PPC64 (ELFv2 is used anyway). |
| 7010 | if (!(target.cpu.arch.isArm() and (ext == .assembly or ext == .assembly_with_cpp)) and |
| 7011 | !(target.cpu.arch.isPowerPC64() and target.os.tag == .freebsd)) |
| 7012 | { |
| 7013 | try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{mabi})); |
| 7014 | } |
| 7015 | } |
| 7016 | |
| 7017 | // We might want to support -mfloat-abi=softfp for Arm and CSKY here in the future. |
| 7018 | if (target_util.clangSupportsFloatAbiArg(target)) { |
| 7019 | const fabi = @tagName(target.abi.float()); |
| 7020 | |
| 7021 | try argv.append(switch (target.cpu.arch) { |
| 7022 | // For whatever reason, Clang doesn't support `-mfloat-abi` for s390x. |
| 7023 | .s390x => try std.fmt.allocPrint(arena, "-m{s}-float", .{fabi}), |
| 7024 | else => try std.fmt.allocPrint(arena, "-mfloat-abi={s}", .{fabi}), |
| 7025 | }); |
| 7026 | } |
| 7027 | |
| 7028 | try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, mod); |
| 7029 | |
| 7030 | // Only assembly files support these flags. |
| 7031 | switch (ext) { |
| 7032 | .assembly, |
| 7033 | .assembly_with_cpp, |
| 7034 | => { |
| 7035 | // The Clang assembler does not accept the list of CPU features like the |
| 7036 | // compiler frontend does. Therefore we must hard-code the -m flags for |
| 7037 | // all CPU features here. |
| 7038 | switch (target.cpu.arch) { |
| 7039 | .riscv32, .riscv32be, .riscv64, .riscv64be => { |
| 7040 | const RvArchFeat = struct { char: u8, feat: std.Target.riscv.Feature }; |
| 7041 | const letters = [_]RvArchFeat{ |
| 7042 | .{ .char = 'm', .feat = .m }, |
| 7043 | .{ .char = 'a', .feat = .a }, |
| 7044 | .{ .char = 'f', .feat = .f }, |
| 7045 | .{ .char = 'd', .feat = .d }, |
| 7046 | .{ .char = 'c', .feat = .c }, |
| 7047 | }; |
| 7048 | const prefix: []const u8 = if (target.cpu.arch == .riscv64) "rv64" else "rv32"; |
| 7049 | const prefix_len = 4; |
| 7050 | assert(prefix.len == prefix_len); |
| 7051 | var march_buf: [prefix_len + letters.len + 1]u8 = undefined; |
| 7052 | var march_index: usize = prefix_len; |
| 7053 | @memcpy(march_buf[0..prefix.len], prefix); |
| 7054 | |
| 7055 | if (target.cpu.has(.riscv, .e)) { |
| 7056 | march_buf[march_index] = 'e'; |
| 7057 | } else { |
| 7058 | march_buf[march_index] = 'i'; |
| 7059 | } |
| 7060 | march_index += 1; |
| 7061 | |
| 7062 | for (letters) |letter| { |
| 7063 | if (target.cpu.has(.riscv, letter.feat)) { |
| 7064 | march_buf[march_index] = letter.char; |
| 7065 | march_index += 1; |
| 7066 | } |
| 7067 | } |
| 7068 | |
| 7069 | const march_arg = try std.fmt.allocPrint(arena, "-march={s}", .{ |
| 7070 | march_buf[0..march_index], |
| 7071 | }); |
| 7072 | try argv.append(march_arg); |
| 7073 | |
| 7074 | if (target.cpu.has(.riscv, .relax)) { |
| 7075 | try argv.append("-mrelax"); |
| 7076 | } else { |
| 7077 | try argv.append("-mno-relax"); |
| 7078 | } |
| 7079 | if (target.cpu.has(.riscv, .save_restore)) { |
| 7080 | try argv.append("-msave-restore"); |
| 7081 | } else { |
| 7082 | try argv.append("-mno-save-restore"); |
| 7083 | } |
| 7084 | }, |
| 7085 | .mips, .mipsel, .mips64, .mips64el => { |
| 7086 | if (target.cpu.model.llvm_name) |llvm_name| { |
| 7087 | try argv.append(try std.fmt.allocPrint(arena, "-march={s}", .{llvm_name})); |
| 7088 | } |
| 7089 | }, |
| 7090 | else => { |
| 7091 | // TODO |
| 7092 | }, |
| 7093 | } |
| 7094 | |
| 7095 | if (target_util.clangAssemblerSupportsMcpuArg(target)) { |
| 7096 | if (target.cpu.model.llvm_name) |llvm_name| { |
| 7097 | try argv.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{llvm_name})); |
| 7098 | } |
| 7099 | } |
| 7100 | }, |
| 7101 | else => {}, |
| 7102 | } |
| 7103 | |
| 7104 | // Non-preprocessed assembly files don't support these flags. |
| 7105 | if (ext != .assembly) { |
| 7106 | if (target_util.clangSupportsNoImplicitFloatArg(target) and target.abi.float() == .soft) { |
| 7107 | try argv.append("-mno-implicit-float"); |
| 7108 | } |
| 7109 | |
| 7110 | if (target_util.hasRedZone(target)) { |
| 7111 | try argv.append(if (mod.red_zone) "-mred-zone" else "-mno-red-zone"); |
| 7112 | } |
| 7113 | |
| 7114 | try argv.append(if (mod.omit_frame_pointer) "-fomit-frame-pointer" else "-fno-omit-frame-pointer"); |
| 7115 | |
| 7116 | const ssp_buf_size = mod.stack_protector; |
| 7117 | if (ssp_buf_size != 0) { |
| 7118 | try argv.appendSlice(&[_][]const u8{ |
| 7119 | "-fstack-protector-strong", |
| 7120 | "--param", |
| 7121 | try std.fmt.allocPrint(arena, "ssp-buffer-size={d}", .{ssp_buf_size}), |
| 7122 | }); |
| 7123 | } else { |
| 7124 | try argv.append("-fno-stack-protector"); |
| 7125 | } |
| 7126 | |
| 7127 | try argv.append(if (mod.no_builtin) "-fno-builtin" else "-fbuiltin"); |
| 7128 | |
| 7129 | try argv.append(if (comp.function_sections) "-ffunction-sections" else "-fno-function-sections"); |
| 7130 | try argv.append(if (comp.data_sections) "-fdata-sections" else "-fno-data-sections"); |
| 7131 | |
| 7132 | switch (mod.unwind_tables) { |
| 7133 | .none => { |
| 7134 | try argv.append("-fno-unwind-tables"); |
| 7135 | try argv.append("-fno-asynchronous-unwind-tables"); |
| 7136 | }, |
| 7137 | .sync => { |
| 7138 | // Need to override Clang's convoluted default logic. |
| 7139 | try argv.append("-fno-asynchronous-unwind-tables"); |
| 7140 | try argv.append("-funwind-tables"); |
| 7141 | }, |
| 7142 | .async => try argv.append("-fasynchronous-unwind-tables"), |
| 7143 | } |
| 7144 | } |
| 7145 | |
| 7146 | // Only compiled files support these flags. |
| 7147 | switch (ext) { |
| 7148 | .c, |
| 7149 | .h, |
| 7150 | .cpp, |
| 7151 | .hpp, |
| 7152 | .m, |
| 7153 | .hm, |
| 7154 | .mm, |
| 7155 | .hmm, |
| 7156 | .ll, |
| 7157 | .bc, |
| 7158 | => { |
| 7159 | const xclang_flag = switch (ext) { |
| 7160 | .assembly, .assembly_with_cpp => "-Xclangas", |
| 7161 | else => "-Xclang", |
| 7162 | }; |
| 7163 | |
| 7164 | if (target_util.clangSupportsTargetCpuArg(target)) { |
| 7165 | if (target.cpu.model.llvm_name) |llvm_name| { |
| 7166 | try argv.appendSlice(&[_][]const u8{ |
| 7167 | xclang_flag, "-target-cpu", xclang_flag, llvm_name, |
| 7168 | }); |
| 7169 | } |
| 7170 | } |
| 7171 | |
| 7172 | // It would be really nice if there was a more compact way to communicate this info to Clang. |
| 7173 | const all_features_list = target.cpu.arch.allFeaturesList(); |
| 7174 | try argv.ensureUnusedCapacity(all_features_list.len * 4); |
| 7175 | for (all_features_list, 0..) |feature, index_usize| { |
| 7176 | const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); |
| 7177 | const is_enabled = target.cpu.features.isEnabled(index); |
| 7178 | |
| 7179 | if (feature.llvm_name) |llvm_name| { |
| 7180 | // We communicate float ABI to Clang through the dedicated options. |
| 7181 | if (std.mem.startsWith(u8, llvm_name, "soft-float") or |
| 7182 | std.mem.startsWith(u8, llvm_name, "hard-float")) |
| 7183 | continue; |
| 7184 | |
| 7185 | // Ignore these until we figure out how to handle the concept of omitting features. |
| 7186 | // See https://github.com/ziglang/zig/issues/23539 |
| 7187 | if (target_util.isDynamicAMDGCNFeature(target, feature)) continue; |
| 7188 | |
| 7189 | argv.appendSliceAssumeCapacity(&[_][]const u8{ xclang_flag, "-target-feature", xclang_flag }); |
| 7190 | const plus_or_minus = "-+"[@intFromBool(is_enabled)]; |
| 7191 | const arg = try std.fmt.allocPrint(arena, "{c}{s}", .{ plus_or_minus, llvm_name }); |
| 7192 | argv.appendAssumeCapacity(arg); |
| 7193 | } |
| 7194 | } |
| 7195 | }, |
| 7196 | else => {}, |
| 7197 | } |
| 7136 | 7198 | |
| 7137 | 7199 | try argv.appendSlice(comp.global_cc_argv); |
| 7138 | 7200 | try argv.appendSlice(mod.cc_argv); |