| ... | @@ -6608,14 +6608,43 @@ pub fn addTranslateCCArgs( | ... | @@ -6608,14 +6608,43 @@ pub fn addTranslateCCArgs( |
| 6608 | out_dep_path: ?[]const u8, | 6608 | out_dep_path: ?[]const u8, |
| 6609 | owner_mod: *Package.Module, | 6609 | owner_mod: *Package.Module, |
| 6610 | ) !void { | 6610 | ) !void { |
| | 6611 | const target = &owner_mod.resolved_target.result; |
| | 6612 | |
| 6611 | try argv.appendSlice(&.{ "-x", "c" }); | 6613 | try argv.appendSlice(&.{ "-x", "c" }); |
| 6612 | try comp.addCCArgs(arena, argv, ext, out_dep_path, owner_mod); | 6614 | |
| 6613 | // This gives us access to preprocessing entities, presumably at the cost of performance. | 6615 | const resource_path = try comp.dirs.zig_lib.join(arena, &.{"compiler/aro/include"}); |
| 6614 | try argv.appendSlice(&.{ "-Xclang", "-detailed-preprocessing-record" }); | 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 | /// Add common C compiler args between translate-c and C object compilation. | 6646 | /// Add common C compiler args between translate-c and C object compilation. |
| 6618 | pub fn addCCArgs( | 6647 | fn addCommonCCArgs( |
| 6619 | comp: *const Compilation, | 6648 | comp: *const Compilation, |
| 6620 | arena: Allocator, | 6649 | arena: Allocator, |
| 6621 | argv: *std.array_list.Managed([]const u8), | 6650 | argv: *std.array_list.Managed([]const u8), |
| ... | @@ -6625,32 +6654,13 @@ pub fn addCCArgs( | ... | @@ -6625,32 +6654,13 @@ pub fn addCCArgs( |
| 6625 | ) !void { | 6654 | ) !void { |
| 6626 | const target = &mod.resolved_target.result; | 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. | 6657 | if (target_util.supports_fpic(target)) { |
| 6629 | // I'm sure the person who implemented this means well, but they have a lot | 6658 | // PIE needs to go before PIC because Clang interprets `-fno-PIE` to imply `-fno-PIC`, which |
| 6630 | // to learn about abstractions and where the appropriate boundaries between | 6659 | // we don't necessarily want. |
| 6631 | // them are. The road to hell is paved with good intentions. Fortunately it | 6660 | try argv.append(if (comp.config.pie) "-fPIE" else "-fno-PIE"); |
| 6632 | // can be disabled. | 6661 | try argv.append(if (mod.pic) "-fPIC" else "-fno-PIC"); |
| 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"); | | |
| 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 | switch (target.os.tag) { | 6664 | switch (target.os.tag) { |
| 6655 | .ios, .macos, .tvos, .watchos => |os| { | 6665 | .ios, .macos, .tvos, .watchos => |os| { |
| 6656 | try argv.ensureUnusedCapacity(2); | 6666 | try argv.ensureUnusedCapacity(2); |
| ... | @@ -6676,78 +6686,6 @@ pub fn addCCArgs( | ... | @@ -6676,78 +6686,6 @@ pub fn addCCArgs( |
| 6676 | else => {}, | 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 | if (comp.mingw_unicode_entry_point) { | 6689 | if (comp.mingw_unicode_entry_point) { |
| 6752 | try argv.append("-municode"); | 6690 | try argv.append("-municode"); |
| 6753 | } | 6691 | } |
| ... | @@ -6784,45 +6722,6 @@ pub fn addCCArgs( | ... | @@ -6784,45 +6722,6 @@ pub fn addCCArgs( |
| 6784 | if (ext != .assembly) { | 6722 | if (ext != .assembly) { |
| 6785 | try argv.append(if (target.os.tag == .freestanding) "-ffreestanding" else "-fhosted"); | 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 | try argv.append("-nostdinc"); | 6725 | try argv.append("-nostdinc"); |
| 6827 | | 6726 | |
| 6828 | if (ext == .cpp or ext == .hpp) { | 6727 | if (ext == .cpp or ext == .hpp) { |
| ... | @@ -6961,80 +6860,6 @@ pub fn addCCArgs( | ... | @@ -6961,80 +6860,6 @@ pub fn addCCArgs( |
| 6961 | else => {}, | 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 | // Only compiled files support these flags. | 6863 | // Only compiled files support these flags. |
| 7039 | switch (ext) { | 6864 | switch (ext) { |
| 7040 | .c, | 6865 | .c, |
| ... | @@ -7133,6 +6958,243 @@ pub fn addCCArgs( | ... | @@ -7133,6 +6958,243 @@ pub fn addCCArgs( |
| 7133 | }, | 6958 | }, |
| 7134 | else => {}, | 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 | try argv.appendSlice(comp.global_cc_argv); | 7199 | try argv.appendSlice(comp.global_cc_argv); |
| 7138 | try argv.appendSlice(mod.cc_argv); | 7200 | try argv.appendSlice(mod.cc_argv); |