Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix soft float support, split musl triples by float ABI, and enable CI #21269

Merged
merged 15 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions lib/compiler_rt/truncdfhf2.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
15 changes: 8 additions & 7 deletions lib/std/Target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
}
};
Expand Down Expand Up @@ -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();
}

Expand Down
3 changes: 3 additions & 0 deletions lib/std/math/gamma.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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))));
Expand Down
6 changes: 6 additions & 0 deletions lib/std/zig/system.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
9 changes: 6 additions & 3 deletions lib/std/zig/target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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 } },
Expand Down
29 changes: 25 additions & 4 deletions src/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 });
}
Expand Down
37 changes: 35 additions & 2 deletions src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1284,8 +1284,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,
Expand Down Expand Up @@ -3109,6 +3108,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.
Comment on lines +3112 to +3125
Copy link
Member

@andrewrk andrewrk Sep 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What makes sense to me is:

  • float ABI in the target triple
  • whether hard float instructions can be used in the CPU featureset

Furthermore, baseline for soft float ABI target triples can default to not using float instructions in the CPU features.

it's unclear to me if this comment is in agreement with this or not.

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(
Expand Down Expand Up @@ -12400,6 +12423,11 @@ fn backendSupportsF16(target: std.Target) bool {
.mips64el,
.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),
Expand All @@ -12422,6 +12450,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),
Expand Down
1 change: 1 addition & 0 deletions src/musl.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
42 changes: 42 additions & 0 deletions src/target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 2 additions & 0 deletions test/behavior/floatop.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions test/behavior/math.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 8 additions & 5 deletions test/behavior/vector.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1442,7 +1442,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"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this test is being re-enabled for all targets in #21183.

// 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,
Expand All @@ -1451,11 +1458,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 => {},
}
}
Expand Down
Loading