Merge pull request #21269 from alexrp/soft-float

Fix soft float support, split musl triples by float ABI, and enable CI
This commit is contained in:
Andrew Kelley 2024-09-11 17:41:55 -07:00 committed by GitHub
commit 4fba7336a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 251 additions and 43 deletions

View File

@ -6,9 +6,8 @@ pub const panic = common.panic;
comptime {
if (common.want_aeabi) {
@export(&__aeabi_d2h, .{ .name = "__aeabi_d2h", .linkage = common.linkage, .visibility = common.visibility });
} else {
@export(&__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = common.linkage, .visibility = common.visibility });
}
@export(&__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = common.linkage, .visibility = common.visibility });
}
pub fn __truncdfhf2(a: f64) callconv(.C) common.F16T(f64) {

View File

@ -765,12 +765,13 @@ pub const Abi = enum {
pub inline fn floatAbi(abi: Abi) FloatAbi {
return switch (abi) {
.gnueabihf,
.eabihf,
.musleabihf,
=> .hard,
.ohos => .soft,
else => .soft,
.eabi,
.gnueabi,
.musleabi,
.gnusf,
.ohos,
=> .soft,
else => .hard,
};
}
};
@ -1645,7 +1646,7 @@ pub const FloatAbi = enum {
soft,
};
pub inline fn getFloatAbi(target: Target) FloatAbi {
pub inline fn floatAbi(target: Target) FloatAbi {
return target.abi.floatAbi();
}

View File

@ -3,6 +3,7 @@
//
// https://git.musl-libc.org/cgit/musl/tree/src/math/tgamma.c
const builtin = @import("builtin");
const std = @import("../std.zig");
/// Returns the gamma function of x,
@ -262,6 +263,8 @@ test gamma {
}
test "gamma.special" {
if (builtin.cpu.arch.isArmOrThumb() and builtin.target.floatAbi() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
inline for (&.{ f32, f64 }) |T| {
try expect(std.math.isNan(gamma(T, -std.math.nan(T))));
try expect(std.math.isNan(gamma(T, std.math.nan(T))));

View File

@ -384,6 +384,12 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
query.cpu_features_add,
query.cpu_features_sub,
);
// https://github.com/llvm/llvm-project/issues/105978
if (result.cpu.arch.isArmOrThumb() and result.floatAbi() == .soft) {
result.cpu.features.removeFeature(@intFromEnum(Target.arm.Feature.vfp2));
}
return result;
}

View File

@ -46,17 +46,20 @@ pub const available_libcs = [_]ArchOsAbi{
.{ .arch = .mips64, .os = .linux, .abi = .musl },
.{ .arch = .mipsel, .os = .linux, .abi = .gnueabi },
.{ .arch = .mipsel, .os = .linux, .abi = .gnueabihf },
.{ .arch = .mipsel, .os = .linux, .abi = .musl },
.{ .arch = .mipsel, .os = .linux, .abi = .musleabi },
.{ .arch = .mipsel, .os = .linux, .abi = .musleabihf },
.{ .arch = .mips, .os = .linux, .abi = .gnueabi },
.{ .arch = .mips, .os = .linux, .abi = .gnueabihf },
.{ .arch = .mips, .os = .linux, .abi = .musl },
.{ .arch = .mips, .os = .linux, .abi = .musleabi },
.{ .arch = .mips, .os = .linux, .abi = .musleabihf },
.{ .arch = .powerpc64le, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 19, .patch = 0 } },
.{ .arch = .powerpc64le, .os = .linux, .abi = .musl },
.{ .arch = .powerpc64, .os = .linux, .abi = .gnu },
.{ .arch = .powerpc64, .os = .linux, .abi = .musl },
.{ .arch = .powerpc, .os = .linux, .abi = .gnueabi },
.{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf },
.{ .arch = .powerpc, .os = .linux, .abi = .musl },
.{ .arch = .powerpc, .os = .linux, .abi = .musleabi },
.{ .arch = .powerpc, .os = .linux, .abi = .musleabihf },
.{ .arch = .riscv32, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 33, .patch = 0 } },
.{ .arch = .riscv32, .os = .linux, .abi = .musl },
.{ .arch = .riscv64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 } },

View File

@ -5484,6 +5484,9 @@ pub fn addCCArgs(
const is_enabled = target.cpu.features.isEnabled(index);
if (feature.llvm_name) |llvm_name| {
// We communicate float ABI to Clang through the dedicated options further down.
if (std.mem.eql(u8, llvm_name, "soft-float")) continue;
argv.appendSliceAssumeCapacity(&[_][]const u8{ "-Xclang", "-target-feature", "-Xclang" });
const plus_or_minus = "-+"[@intFromBool(is_enabled)];
const arg = try std.fmt.allocPrint(arena, "{c}{s}", .{ plus_or_minus, llvm_name });
@ -5705,10 +5708,6 @@ pub fn addCCArgs(
if (target.cpu.model.llvm_name) |llvm_name| {
try argv.append(try std.fmt.allocPrint(arena, "-march={s}", .{llvm_name}));
}
if (std.Target.mips.featureSetHas(target.cpu.features, .soft_float)) {
try argv.append("-msoft-float");
}
},
else => {
// TODO
@ -5751,6 +5750,28 @@ pub fn addCCArgs(
try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{mabi}));
}
// We might want to support -mfloat-abi=softfp for Arm and CSKY here in the future.
if (target_util.clangSupportsFloatAbiArg(target)) {
const fabi = @tagName(target.floatAbi());
try argv.append(switch (target.cpu.arch) {
// For whatever reason, Clang doesn't support `-mfloat-abi` for s390x.
.s390x => try std.fmt.allocPrint(arena, "-m{s}-float", .{fabi}),
else => try std.fmt.allocPrint(arena, "-mfloat-abi={s}", .{fabi}),
});
}
if (target_util.clangSupportsNoImplicitFloatArg(target) and target.floatAbi() == .soft) {
try argv.append("-mno-implicit-float");
}
// https://github.com/llvm/llvm-project/issues/105972
if (target.cpu.arch.isPowerPC() and target.floatAbi() == .soft) {
try argv.append("-D__NO_FPRS__");
try argv.append("-D_SOFT_FLOAT");
try argv.append("-D_SOFT_DOUBLE");
}
if (out_dep_path) |p| {
try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p });
}

View File

@ -1285,8 +1285,7 @@ pub const Object = struct {
.large => .Large,
};
// TODO handle float ABI better- it should depend on the ABI portion of std.Target
const float_abi: llvm.ABIType = .Default;
const float_abi: llvm.ABIType = if (comp.root_mod.resolved_target.result.floatAbi() == .hard) .Hard else .Soft;
var target_machine = llvm.TargetMachine.create(
target,
@ -3110,6 +3109,30 @@ pub const Object = struct {
.value = .empty,
} }, &o.builder);
}
if (target.floatAbi() == .soft) {
// `use-soft-float` means "use software routines for floating point computations". In
// other words, it configures how LLVM lowers basic float instructions like `fcmp`,
// `fadd`, etc. The float calling convention is configured on `TargetMachine` and is
// mostly an orthogonal concept, although obviously we do need hardware float operations
// to actually be able to pass float values in float registers.
//
// Ideally, we would support something akin to the `-mfloat-abi=softfp` option that GCC
// and Clang support for Arm32 and CSKY. We don't currently expose such an option in
// Zig, and using CPU features as the source of truth for this makes for a miserable
// user experience since people expect e.g. `arm-linux-gnueabi` to mean full soft float
// unless the compiler has explicitly been told otherwise. (And note that our baseline
// CPU models almost all include FPU features!)
//
// Revisit this at some point.
try attributes.addFnAttr(.{ .string = .{
.kind = try o.builder.string("use-soft-float"),
.value = try o.builder.string("true"),
} }, &o.builder);
// This prevents LLVM from using FPU/SIMD code for things like `memcpy`. As for the
// above, this should be revisited if `softfp` support is added.
try attributes.addFnAttr(.noimplicitfloat, &o.builder);
}
}
fn resolveGlobalUav(
@ -12423,6 +12446,11 @@ fn backendSupportsF16(target: std.Target) bool {
.riscv32,
.s390x,
=> false,
.arm,
.armeb,
.thumb,
.thumbeb,
=> target.floatAbi() == .soft or std.Target.arm.featureSetHas(target.cpu.features, .fp_armv8),
.aarch64,
.aarch64_be,
=> std.Target.aarch64.featureSetHas(target.cpu.features, .fp_armv8),
@ -12445,6 +12473,11 @@ fn backendSupportsF128(target: std.Target) bool {
.powerpc64,
.powerpc64le,
=> target.os.tag != .aix,
.arm,
.armeb,
.thumb,
.thumbeb,
=> target.floatAbi() == .soft or std.Target.arm.featureSetHas(target.cpu.features, .fp_armv8),
.aarch64,
.aarch64_be,
=> std.Target.aarch64.featureSetHas(target.cpu.features, .fp_armv8),

View File

@ -387,6 +387,7 @@ fn addCcArgs(
"-fno-builtin",
"-fexcess-precision=standard",
"-frounding-math",
"-ffp-contract=off",
"-fno-strict-aliasing",
"-Wa,--noexecstack",
"-D_XOPEN_SOURCE=700",

View File

@ -339,6 +339,48 @@ pub fn clangAssemblerSupportsMcpuArg(target: std.Target) bool {
};
}
pub fn clangSupportsFloatAbiArg(target: std.Target) bool {
return switch (target.cpu.arch) {
.arm,
.armeb,
.thumb,
.thumbeb,
.csky,
.mips,
.mipsel,
.mips64,
.mips64el,
.powerpc,
.powerpcle,
.powerpc64,
.powerpc64le,
.s390x,
.sparc,
.sparc64,
=> true,
// We use the target triple for LoongArch.
.loongarch32, .loongarch64 => false,
else => false,
};
}
pub fn clangSupportsNoImplicitFloatArg(target: std.Target) bool {
return switch (target.cpu.arch) {
.aarch64,
.aarch64_be,
.arm,
.armeb,
.thumb,
.thumbeb,
.riscv32,
.riscv64,
.x86,
.x86_64,
=> true,
else => false,
};
}
pub fn needUnwindTables(target: std.Target) bool {
return target.os.tag == .windows or target.isDarwin() or std.debug.Dwarf.abi.supportsUnwinding(target);
}

View File

@ -126,6 +126,7 @@ test "cmp f16" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
if (builtin.cpu.arch.isArmOrThumb() and builtin.target.floatAbi() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
try testCmp(f16);
try comptime testCmp(f16);
@ -134,6 +135,7 @@ test "cmp f16" {
test "cmp f32/f64" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
if (builtin.cpu.arch.isArmOrThumb() and builtin.target.floatAbi() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
try testCmp(f32);
try comptime testCmp(f32);

View File

@ -1597,6 +1597,7 @@ test "NaN comparison" {
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
if (builtin.cpu.arch.isArmOrThumb() and builtin.target.floatAbi() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
try testNanEqNan(f16);
try testNanEqNan(f32);

View File

@ -1409,7 +1409,14 @@ test "store vector with memset" {
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_llvm) {
// LLVM 16 ERROR: "Converting bits to bytes lost precision"
// https://github.com/ziglang/zig/issues/16177
switch (builtin.target.cpu.arch) {
.arm,
.armeb,
.thumb,
.thumbeb,
=> if (builtin.target.floatAbi() == .soft) return error.SkipZigTest,
.wasm32,
.mips,
.mipsel,
@ -1418,11 +1425,7 @@ test "store vector with memset" {
.riscv64,
.powerpc,
.powerpc64,
=> {
// LLVM 16 ERROR: "Converting bits to bytes lost precision"
// https://github.com/ziglang/zig/issues/16177
return error.SkipZigTest;
},
=> return error.SkipZigTest,
else => {},
}
}

View File

@ -291,23 +291,49 @@ const test_targets = blk: {
},
.{
.target = std.Target.Query.parse(.{
.arch_os_abi = "arm-linux-none",
.cpu_features = "generic+v8a",
}) catch unreachable,
.target = .{
.cpu_arch = .arm,
.os_tag = .linux,
.abi = .eabi,
},
},
.{
.target = std.Target.Query.parse(.{
.arch_os_abi = "arm-linux-musleabihf",
.cpu_features = "generic+v8a",
}) catch unreachable,
.target = .{
.cpu_arch = .arm,
.os_tag = .linux,
.abi = .eabihf,
},
},
.{
.target = .{
.cpu_arch = .arm,
.os_tag = .linux,
.abi = .musleabi,
},
.link_libc = true,
},
.{
.target = std.Target.Query.parse(.{
.arch_os_abi = "arm-linux-gnueabihf",
.cpu_features = "generic+v8a",
}) catch unreachable,
.target = .{
.cpu_arch = .arm,
.os_tag = .linux,
.abi = .musleabihf,
},
.link_libc = true,
},
.{
.target = .{
.cpu_arch = .arm,
.os_tag = .linux,
.abi = .gnueabi,
},
.link_libc = true,
},
.{
.target = .{
.cpu_arch = .arm,
.os_tag = .linux,
.abi = .gnueabihf,
},
.link_libc = true,
},
@ -315,7 +341,7 @@ const test_targets = blk: {
.target = .{
.cpu_arch = .mips,
.os_tag = .linux,
.abi = .none,
.abi = .eabi,
},
.slow_backend = true,
},
@ -323,7 +349,33 @@ const test_targets = blk: {
.target = .{
.cpu_arch = .mips,
.os_tag = .linux,
.abi = .musl,
.abi = .eabihf,
},
.slow_backend = true,
},
.{
.target = .{
.cpu_arch = .mips,
.os_tag = .linux,
.abi = .musleabi,
},
.link_libc = true,
.slow_backend = true,
},
.{
.target = .{
.cpu_arch = .mips,
.os_tag = .linux,
.abi = .musleabihf,
},
.link_libc = true,
.slow_backend = true,
},
.{
.target = .{
.cpu_arch = .mips,
.os_tag = .linux,
.abi = .gnueabi,
},
.link_libc = true,
.slow_backend = true,
@ -342,7 +394,7 @@ const test_targets = blk: {
.target = .{
.cpu_arch = .mipsel,
.os_tag = .linux,
.abi = .none,
.abi = .eabi,
},
.slow_backend = true,
},
@ -350,7 +402,33 @@ const test_targets = blk: {
.target = .{
.cpu_arch = .mipsel,
.os_tag = .linux,
.abi = .musl,
.abi = .eabihf,
},
.slow_backend = true,
},
.{
.target = .{
.cpu_arch = .mipsel,
.os_tag = .linux,
.abi = .musleabi,
},
.link_libc = true,
.slow_backend = true,
},
.{
.target = .{
.cpu_arch = .mipsel,
.os_tag = .linux,
.abi = .musleabihf,
},
.link_libc = true,
.slow_backend = true,
},
.{
.target = .{
.cpu_arch = .mipsel,
.os_tag = .linux,
.abi = .gnueabi,
},
.link_libc = true,
.slow_backend = true,
@ -417,14 +495,29 @@ const test_targets = blk: {
.target = .{
.cpu_arch = .powerpc,
.os_tag = .linux,
.abi = .none,
.abi = .eabi,
},
},
.{
.target = .{
.cpu_arch = .powerpc,
.os_tag = .linux,
.abi = .musl,
.abi = .eabihf,
},
},
.{
.target = .{
.cpu_arch = .powerpc,
.os_tag = .linux,
.abi = .musleabi,
},
.link_libc = true,
},
.{
.target = .{
.cpu_arch = .powerpc,
.os_tag = .linux,
.abi = .musleabihf,
},
.link_libc = true,
},
@ -661,7 +754,7 @@ const c_abi_targets = [_]CAbiTarget{
.target = .{
.cpu_arch = .mips,
.os_tag = .linux,
.abi = .musl,
.abi = .musleabihf,
},
},
.{
@ -682,7 +775,7 @@ const c_abi_targets = [_]CAbiTarget{
.target = .{
.cpu_arch = .powerpc,
.os_tag = .linux,
.abi = .musl,
.abi = .musleabihf,
},
},
.{