authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-25 13:42:01+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-09-25 23:41:40+02:00
log5a263ea6752da8736d00f00af5d2a75e69970259
treec9f21a99a737dd8ed2fbe51b3492983f58fc0e42
parent1e770dbef6f5f34ccb1e61db7edcfb1e705fe1ee

Compilation: for .S files, pass CPU features to both preprocessor and assembler

And delete the old workaround code that's no longer relevant.

1 files changed, 36 insertions(+), 107 deletions(-)

src/Compilation.zig+36-107
......@@ -6672,80 +6672,6 @@ pub fn addCCArgs(
66726672
66736673 try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, mod, comp.config.c_frontend);
66746674
6675 // Only assembly files support these flags.
6676 switch (ext) {
6677 .assembly,
6678 .assembly_with_cpp,
6679 => {
6680 // The Clang assembler does not accept the list of CPU features like the
6681 // compiler frontend does. Therefore we must hard-code the -m flags for
6682 // all CPU features here.
6683 switch (target.cpu.arch) {
6684 .riscv32, .riscv32be, .riscv64, .riscv64be => {
6685 const RvArchFeat = struct { char: u8, feat: std.Target.riscv.Feature };
6686 const letters = [_]RvArchFeat{
6687 .{ .char = 'm', .feat = .m },
6688 .{ .char = 'a', .feat = .a },
6689 .{ .char = 'f', .feat = .f },
6690 .{ .char = 'd', .feat = .d },
6691 .{ .char = 'c', .feat = .c },
6692 };
6693 const prefix: []const u8 = if (target.cpu.arch == .riscv64) "rv64" else "rv32";
6694 const prefix_len = 4;
6695 assert(prefix.len == prefix_len);
6696 var march_buf: [prefix_len + letters.len + 1]u8 = undefined;
6697 var march_index: usize = prefix_len;
6698 @memcpy(march_buf[0..prefix.len], prefix);
6699
6700 if (target.cpu.has(.riscv, .e)) {
6701 march_buf[march_index] = 'e';
6702 } else {
6703 march_buf[march_index] = 'i';
6704 }
6705 march_index += 1;
6706
6707 for (letters) |letter| {
6708 if (target.cpu.has(.riscv, letter.feat)) {
6709 march_buf[march_index] = letter.char;
6710 march_index += 1;
6711 }
6712 }
6713
6714 const march_arg = try std.fmt.allocPrint(arena, "-march={s}", .{
6715 march_buf[0..march_index],
6716 });
6717 try argv.append(march_arg);
6718
6719 if (target.cpu.has(.riscv, .relax)) {
6720 try argv.append("-mrelax");
6721 } else {
6722 try argv.append("-mno-relax");
6723 }
6724 if (target.cpu.has(.riscv, .save_restore)) {
6725 try argv.append("-msave-restore");
6726 } else {
6727 try argv.append("-mno-save-restore");
6728 }
6729 },
6730 .mips, .mipsel, .mips64, .mips64el => {
6731 if (target.cpu.model.llvm_name) |llvm_name| {
6732 try argv.append(try std.fmt.allocPrint(arena, "-march={s}", .{llvm_name}));
6733 }
6734 },
6735 else => {
6736 // TODO
6737 },
6738 }
6739
6740 if (target_util.clangAssemblerSupportsMcpuArg(target)) {
6741 if (target.cpu.model.llvm_name) |llvm_name| {
6742 try argv.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{llvm_name}));
6743 }
6744 }
6745 },
6746 else => {},
6747 }
6748
67496675 // Non-preprocessed assembly files don't support these flags.
67506676 if (ext != .assembly) {
67516677 if (target_util.clangSupportsNoImplicitFloatArg(target) and target.abi.float() == .soft) {
......@@ -6806,43 +6732,46 @@ pub fn addCCArgs(
68066732 .ll,
68076733 .bc,
68086734 => {
6809 const xclang_flag = switch (ext) {
6810 .assembly, .assembly_with_cpp => "-Xclangas",
6811 else => "-Xclang",
6735 const xclang_flags: []const []const u8 = switch (ext) {
6736 .assembly => &.{"-Xclangas"},
6737 .assembly_with_cpp => &.{ "-Xclang", "-Xclangas" }, // preprocessor needs the features too
6738 else => &.{"-Xclang"},
68126739 };
68136740
6814 if (target_util.clangSupportsTargetCpuArg(target)) {
6815 if (target.cpu.model.llvm_name) |llvm_name| {
6816 try argv.appendSlice(&[_][]const u8{
6817 xclang_flag, "-target-cpu", xclang_flag, llvm_name,
6818 });
6741 for (xclang_flags) |xclang| {
6742 if (target_util.clangSupportsTargetCpuArg(target)) {
6743 if (target.cpu.model.llvm_name) |llvm_name| {
6744 try argv.appendSlice(&[_][]const u8{
6745 xclang, "-target-cpu", xclang, llvm_name,
6746 });
6747 }
68196748 }
6820 }
6821
6822 // It would be really nice if there was a more compact way to communicate this info to Clang.
6823 const all_features_list = target.cpu.arch.allFeaturesList();
6824 try argv.ensureUnusedCapacity(all_features_list.len * 4);
6825 for (all_features_list, 0..) |feature, index_usize| {
6826 const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
6827 const is_enabled = target.cpu.features.isEnabled(index);
68286749
6829 if (feature.llvm_name) |llvm_name| {
6830 // We communicate these to Clang through the dedicated options.
6831 if (std.mem.startsWith(u8, llvm_name, "soft-float") or
6832 std.mem.startsWith(u8, llvm_name, "hard-float") or
6833 (target.cpu.arch.isPowerPC() and std.mem.startsWith(u8, llvm_name, "64bit")) or
6834 (target.cpu.arch.isX86() and std.mem.startsWith(u8, llvm_name, "x32")) or
6835 (target.cpu.arch == .s390x and std.mem.eql(u8, llvm_name, "backchain")))
6836 continue;
6837
6838 // Ignore these until we figure out how to handle the concept of omitting features.
6839 // See https://github.com/ziglang/zig/issues/23539
6840 if (target_util.isDynamicAMDGCNFeature(target, feature)) continue;
6841
6842 argv.appendSliceAssumeCapacity(&[_][]const u8{ xclang_flag, "-target-feature", xclang_flag });
6843 const plus_or_minus = "-+"[@intFromBool(is_enabled)];
6844 const arg = try std.fmt.allocPrint(arena, "{c}{s}", .{ plus_or_minus, llvm_name });
6845 argv.appendAssumeCapacity(arg);
6750 // It would be really nice if there was a more compact way to communicate this info to Clang.
6751 const all_features_list = target.cpu.arch.allFeaturesList();
6752 try argv.ensureUnusedCapacity(all_features_list.len * 4);
6753 for (all_features_list, 0..) |feature, index_usize| {
6754 const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
6755 const is_enabled = target.cpu.features.isEnabled(index);
6756
6757 if (feature.llvm_name) |llvm_name| {
6758 // We communicate these to Clang through the dedicated options.
6759 if (std.mem.startsWith(u8, llvm_name, "soft-float") or
6760 std.mem.startsWith(u8, llvm_name, "hard-float") or
6761 (target.cpu.arch.isPowerPC() and std.mem.startsWith(u8, llvm_name, "64bit")) or
6762 (target.cpu.arch.isX86() and std.mem.startsWith(u8, llvm_name, "x32")) or
6763 (target.cpu.arch == .s390x and std.mem.eql(u8, llvm_name, "backchain")))
6764 continue;
6765
6766 // Ignore these until we figure out how to handle the concept of omitting features.
6767 // See https://github.com/ziglang/zig/issues/23539
6768 if (target_util.isDynamicAMDGCNFeature(target, feature)) continue;
6769
6770 argv.appendSliceAssumeCapacity(&[_][]const u8{ xclang, "-target-feature", xclang });
6771 const plus_or_minus = "-+"[@intFromBool(is_enabled)];
6772 const arg = try std.fmt.allocPrint(arena, "{c}{s}", .{ plus_or_minus, llvm_name });
6773 argv.appendAssumeCapacity(arg);
6774 }
68466775 }
68476776 }
68486777 },