mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 21:08:36 +00:00
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:
commit
4fba7336a9
@ -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) {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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))));
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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 } },
|
||||
|
||||
@ -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 });
|
||||
}
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 => {},
|
||||
}
|
||||
}
|
||||
|
||||
133
test/tests.zig
133
test/tests.zig
@ -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,
|
||||
},
|
||||
},
|
||||
.{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user