Skip to content

Commit 4fba733

Browse files
authored
Merge pull request #21269 from alexrp/soft-float
Fix soft float support, split musl triples by float ABI, and enable CI
2 parents 218cf05 + f164577 commit 4fba733

File tree

13 files changed

+251
-43
lines changed

13 files changed

+251
-43
lines changed

lib/compiler_rt/truncdfhf2.zig

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ pub const panic = common.panic;
66
comptime {
77
if (common.want_aeabi) {
88
@export(&__aeabi_d2h, .{ .name = "__aeabi_d2h", .linkage = common.linkage, .visibility = common.visibility });
9-
} else {
10-
@export(&__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = common.linkage, .visibility = common.visibility });
119
}
10+
@export(&__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = common.linkage, .visibility = common.visibility });
1211
}
1312

1413
pub fn __truncdfhf2(a: f64) callconv(.C) common.F16T(f64) {

lib/std/Target.zig

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -765,12 +765,13 @@ pub const Abi = enum {
765765

766766
pub inline fn floatAbi(abi: Abi) FloatAbi {
767767
return switch (abi) {
768-
.gnueabihf,
769-
.eabihf,
770-
.musleabihf,
771-
=> .hard,
772-
.ohos => .soft,
773-
else => .soft,
768+
.eabi,
769+
.gnueabi,
770+
.musleabi,
771+
.gnusf,
772+
.ohos,
773+
=> .soft,
774+
else => .hard,
774775
};
775776
}
776777
};
@@ -1645,7 +1646,7 @@ pub const FloatAbi = enum {
16451646
soft,
16461647
};
16471648

1648-
pub inline fn getFloatAbi(target: Target) FloatAbi {
1649+
pub inline fn floatAbi(target: Target) FloatAbi {
16491650
return target.abi.floatAbi();
16501651
}
16511652

lib/std/math/gamma.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//
44
// https://git.musl-libc.org/cgit/musl/tree/src/math/tgamma.c
55

6+
const builtin = @import("builtin");
67
const std = @import("../std.zig");
78

89
/// Returns the gamma function of x,
@@ -262,6 +263,8 @@ test gamma {
262263
}
263264

264265
test "gamma.special" {
266+
if (builtin.cpu.arch.isArmOrThumb() and builtin.target.floatAbi() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
267+
265268
inline for (&.{ f32, f64 }) |T| {
266269
try expect(std.math.isNan(gamma(T, -std.math.nan(T))));
267270
try expect(std.math.isNan(gamma(T, std.math.nan(T))));

lib/std/zig/system.zig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,12 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
384384
query.cpu_features_add,
385385
query.cpu_features_sub,
386386
);
387+
388+
// https://github.com/llvm/llvm-project/issues/105978
389+
if (result.cpu.arch.isArmOrThumb() and result.floatAbi() == .soft) {
390+
result.cpu.features.removeFeature(@intFromEnum(Target.arm.Feature.vfp2));
391+
}
392+
387393
return result;
388394
}
389395

lib/std/zig/target.zig

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,20 @@ pub const available_libcs = [_]ArchOsAbi{
4646
.{ .arch = .mips64, .os = .linux, .abi = .musl },
4747
.{ .arch = .mipsel, .os = .linux, .abi = .gnueabi },
4848
.{ .arch = .mipsel, .os = .linux, .abi = .gnueabihf },
49-
.{ .arch = .mipsel, .os = .linux, .abi = .musl },
49+
.{ .arch = .mipsel, .os = .linux, .abi = .musleabi },
50+
.{ .arch = .mipsel, .os = .linux, .abi = .musleabihf },
5051
.{ .arch = .mips, .os = .linux, .abi = .gnueabi },
5152
.{ .arch = .mips, .os = .linux, .abi = .gnueabihf },
52-
.{ .arch = .mips, .os = .linux, .abi = .musl },
53+
.{ .arch = .mips, .os = .linux, .abi = .musleabi },
54+
.{ .arch = .mips, .os = .linux, .abi = .musleabihf },
5355
.{ .arch = .powerpc64le, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 19, .patch = 0 } },
5456
.{ .arch = .powerpc64le, .os = .linux, .abi = .musl },
5557
.{ .arch = .powerpc64, .os = .linux, .abi = .gnu },
5658
.{ .arch = .powerpc64, .os = .linux, .abi = .musl },
5759
.{ .arch = .powerpc, .os = .linux, .abi = .gnueabi },
5860
.{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf },
59-
.{ .arch = .powerpc, .os = .linux, .abi = .musl },
61+
.{ .arch = .powerpc, .os = .linux, .abi = .musleabi },
62+
.{ .arch = .powerpc, .os = .linux, .abi = .musleabihf },
6063
.{ .arch = .riscv32, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 33, .patch = 0 } },
6164
.{ .arch = .riscv32, .os = .linux, .abi = .musl },
6265
.{ .arch = .riscv64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 } },

src/Compilation.zig

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5484,6 +5484,9 @@ pub fn addCCArgs(
54845484
const is_enabled = target.cpu.features.isEnabled(index);
54855485

54865486
if (feature.llvm_name) |llvm_name| {
5487+
// We communicate float ABI to Clang through the dedicated options further down.
5488+
if (std.mem.eql(u8, llvm_name, "soft-float")) continue;
5489+
54875490
argv.appendSliceAssumeCapacity(&[_][]const u8{ "-Xclang", "-target-feature", "-Xclang" });
54885491
const plus_or_minus = "-+"[@intFromBool(is_enabled)];
54895492
const arg = try std.fmt.allocPrint(arena, "{c}{s}", .{ plus_or_minus, llvm_name });
@@ -5705,10 +5708,6 @@ pub fn addCCArgs(
57055708
if (target.cpu.model.llvm_name) |llvm_name| {
57065709
try argv.append(try std.fmt.allocPrint(arena, "-march={s}", .{llvm_name}));
57075710
}
5708-
5709-
if (std.Target.mips.featureSetHas(target.cpu.features, .soft_float)) {
5710-
try argv.append("-msoft-float");
5711-
}
57125711
},
57135712
else => {
57145713
// TODO
@@ -5751,6 +5750,28 @@ pub fn addCCArgs(
57515750
try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{mabi}));
57525751
}
57535752

5753+
// We might want to support -mfloat-abi=softfp for Arm and CSKY here in the future.
5754+
if (target_util.clangSupportsFloatAbiArg(target)) {
5755+
const fabi = @tagName(target.floatAbi());
5756+
5757+
try argv.append(switch (target.cpu.arch) {
5758+
// For whatever reason, Clang doesn't support `-mfloat-abi` for s390x.
5759+
.s390x => try std.fmt.allocPrint(arena, "-m{s}-float", .{fabi}),
5760+
else => try std.fmt.allocPrint(arena, "-mfloat-abi={s}", .{fabi}),
5761+
});
5762+
}
5763+
5764+
if (target_util.clangSupportsNoImplicitFloatArg(target) and target.floatAbi() == .soft) {
5765+
try argv.append("-mno-implicit-float");
5766+
}
5767+
5768+
// https://github.com/llvm/llvm-project/issues/105972
5769+
if (target.cpu.arch.isPowerPC() and target.floatAbi() == .soft) {
5770+
try argv.append("-D__NO_FPRS__");
5771+
try argv.append("-D_SOFT_FLOAT");
5772+
try argv.append("-D_SOFT_DOUBLE");
5773+
}
5774+
57545775
if (out_dep_path) |p| {
57555776
try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p });
57565777
}

src/codegen/llvm.zig

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,8 +1285,7 @@ pub const Object = struct {
12851285
.large => .Large,
12861286
};
12871287

1288-
// TODO handle float ABI better- it should depend on the ABI portion of std.Target
1289-
const float_abi: llvm.ABIType = .Default;
1288+
const float_abi: llvm.ABIType = if (comp.root_mod.resolved_target.result.floatAbi() == .hard) .Hard else .Soft;
12901289

12911290
var target_machine = llvm.TargetMachine.create(
12921291
target,
@@ -3110,6 +3109,30 @@ pub const Object = struct {
31103109
.value = .empty,
31113110
} }, &o.builder);
31123111
}
3112+
if (target.floatAbi() == .soft) {
3113+
// `use-soft-float` means "use software routines for floating point computations". In
3114+
// other words, it configures how LLVM lowers basic float instructions like `fcmp`,
3115+
// `fadd`, etc. The float calling convention is configured on `TargetMachine` and is
3116+
// mostly an orthogonal concept, although obviously we do need hardware float operations
3117+
// to actually be able to pass float values in float registers.
3118+
//
3119+
// Ideally, we would support something akin to the `-mfloat-abi=softfp` option that GCC
3120+
// and Clang support for Arm32 and CSKY. We don't currently expose such an option in
3121+
// Zig, and using CPU features as the source of truth for this makes for a miserable
3122+
// user experience since people expect e.g. `arm-linux-gnueabi` to mean full soft float
3123+
// unless the compiler has explicitly been told otherwise. (And note that our baseline
3124+
// CPU models almost all include FPU features!)
3125+
//
3126+
// Revisit this at some point.
3127+
try attributes.addFnAttr(.{ .string = .{
3128+
.kind = try o.builder.string("use-soft-float"),
3129+
.value = try o.builder.string("true"),
3130+
} }, &o.builder);
3131+
3132+
// This prevents LLVM from using FPU/SIMD code for things like `memcpy`. As for the
3133+
// above, this should be revisited if `softfp` support is added.
3134+
try attributes.addFnAttr(.noimplicitfloat, &o.builder);
3135+
}
31133136
}
31143137

31153138
fn resolveGlobalUav(
@@ -12423,6 +12446,11 @@ fn backendSupportsF16(target: std.Target) bool {
1242312446
.riscv32,
1242412447
.s390x,
1242512448
=> false,
12449+
.arm,
12450+
.armeb,
12451+
.thumb,
12452+
.thumbeb,
12453+
=> target.floatAbi() == .soft or std.Target.arm.featureSetHas(target.cpu.features, .fp_armv8),
1242612454
.aarch64,
1242712455
.aarch64_be,
1242812456
=> std.Target.aarch64.featureSetHas(target.cpu.features, .fp_armv8),
@@ -12445,6 +12473,11 @@ fn backendSupportsF128(target: std.Target) bool {
1244512473
.powerpc64,
1244612474
.powerpc64le,
1244712475
=> target.os.tag != .aix,
12476+
.arm,
12477+
.armeb,
12478+
.thumb,
12479+
.thumbeb,
12480+
=> target.floatAbi() == .soft or std.Target.arm.featureSetHas(target.cpu.features, .fp_armv8),
1244812481
.aarch64,
1244912482
.aarch64_be,
1245012483
=> std.Target.aarch64.featureSetHas(target.cpu.features, .fp_armv8),

src/musl.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ fn addCcArgs(
387387
"-fno-builtin",
388388
"-fexcess-precision=standard",
389389
"-frounding-math",
390+
"-ffp-contract=off",
390391
"-fno-strict-aliasing",
391392
"-Wa,--noexecstack",
392393
"-D_XOPEN_SOURCE=700",

src/target.zig

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,48 @@ pub fn clangAssemblerSupportsMcpuArg(target: std.Target) bool {
339339
};
340340
}
341341

342+
pub fn clangSupportsFloatAbiArg(target: std.Target) bool {
343+
return switch (target.cpu.arch) {
344+
.arm,
345+
.armeb,
346+
.thumb,
347+
.thumbeb,
348+
.csky,
349+
.mips,
350+
.mipsel,
351+
.mips64,
352+
.mips64el,
353+
.powerpc,
354+
.powerpcle,
355+
.powerpc64,
356+
.powerpc64le,
357+
.s390x,
358+
.sparc,
359+
.sparc64,
360+
=> true,
361+
// We use the target triple for LoongArch.
362+
.loongarch32, .loongarch64 => false,
363+
else => false,
364+
};
365+
}
366+
367+
pub fn clangSupportsNoImplicitFloatArg(target: std.Target) bool {
368+
return switch (target.cpu.arch) {
369+
.aarch64,
370+
.aarch64_be,
371+
.arm,
372+
.armeb,
373+
.thumb,
374+
.thumbeb,
375+
.riscv32,
376+
.riscv64,
377+
.x86,
378+
.x86_64,
379+
=> true,
380+
else => false,
381+
};
382+
}
383+
342384
pub fn needUnwindTables(target: std.Target) bool {
343385
return target.os.tag == .windows or target.isDarwin() or std.debug.Dwarf.abi.supportsUnwinding(target);
344386
}

test/behavior/floatop.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ test "cmp f16" {
126126
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
127127
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
128128
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
129+
if (builtin.cpu.arch.isArmOrThumb() and builtin.target.floatAbi() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
129130

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

138140
try testCmp(f32);
139141
try comptime testCmp(f32);

test/behavior/math.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,6 +1597,7 @@ test "NaN comparison" {
15971597
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
15981598
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
15991599
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1600+
if (builtin.cpu.arch.isArmOrThumb() and builtin.target.floatAbi() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
16001601

16011602
try testNanEqNan(f16);
16021603
try testNanEqNan(f32);

test/behavior/vector.zig

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,7 +1409,14 @@ test "store vector with memset" {
14091409
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14101410

14111411
if (builtin.zig_backend == .stage2_llvm) {
1412+
// LLVM 16 ERROR: "Converting bits to bytes lost precision"
1413+
// https://github.com/ziglang/zig/issues/16177
14121414
switch (builtin.target.cpu.arch) {
1415+
.arm,
1416+
.armeb,
1417+
.thumb,
1418+
.thumbeb,
1419+
=> if (builtin.target.floatAbi() == .soft) return error.SkipZigTest,
14131420
.wasm32,
14141421
.mips,
14151422
.mipsel,
@@ -1418,11 +1425,7 @@ test "store vector with memset" {
14181425
.riscv64,
14191426
.powerpc,
14201427
.powerpc64,
1421-
=> {
1422-
// LLVM 16 ERROR: "Converting bits to bytes lost precision"
1423-
// https://github.com/ziglang/zig/issues/16177
1424-
return error.SkipZigTest;
1425-
},
1428+
=> return error.SkipZigTest,
14261429
else => {},
14271430
}
14281431
}

0 commit comments

Comments
 (0)