Skip to content

Figure out which target features are required/incompatible for which ABI #131799

@RalfJung

Description

@RalfJung
Member

The context for this is #116344: some target features change the way floats are passed between functions. Changing those target features is unsound as code compiled for the same target may now use different ABIs.

In #134794, I am adding the infrastructure to have the compiler recognize this. But this infrastructure needs to be fed with information about which ABIs exist (e.g. softfloat/hardfloat), and which target features they require or are incompatible with. This will have to be done for each architecture we support.

  • x86 (32bit and 64bit):
    • soft-float can be set to swap the ABI; if unset, a hardfloat ABI is used
    • 32bit: uses float registers if !soft-float && x87 (see here). IOW, hardfloat ABI requires x87.
    • 64bit: floats are passed via SSE registers, so likely !soft-float && sse is the relevant check -- IOW, hardfloat ABI requires sse/sse2.
  • arm
    • soft-float can be set to swap the ABI; if unset, a hardfloat ABI is used
    • uses float registers if !soft-float && fpregs (see here), so hardfloat ABI requires fpregs
  • aarch64
  • riscv
    • "RISC-V has a similar ABI split. -F/-D/-Q is your softfloat/nofloat, but it also comes with the Zfinx/Zdinx/Zqinx variants where floating-point values are carried in the regular registers and the floating-point register file is deleted. Your float-function-features would be +F,-Zfinx, +D,-Zdinx for riscv64gc-unknown-linux (linux does not permit finx). Although I don't think this is as much of a problem because the platform states that +F,+Zfinx is illegal?" (from here)
    • For RISC-V targets, the float ABI can be specified by the llvm_abiname target option. As long as this happens, f/d can be enabled without changing the ABI (LLVM doesn't support q yet). Disabling target features required by the requested ABI will cause LLVM to ignore the ABI. The zfinx/zdinx features don't affect the ABI.
  • loongarch: see here
    powerpc
    s390x
    wasm
    sparc
    bpf
    csky
    hexagon
    mips
    m68k
    more?

Activity

added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Oct 16, 2024
RalfJung

RalfJung commented on Oct 16, 2024

@RalfJung
MemberAuthor

@rust-lang/wg-llvm @bjorn3 @chorman0773 if you happen to know anything that needs to be added to the list, please let me know, or edit the issue. :) I'm mostly focusing on float ABI here; if it turns out there's a ton of architecture-specific ABI-affecting non-float features we might want to split this up into float and non-float.

changed the title [-]Figure out which target features affect ABI[/-] [+]Figure out which target features affect float ABI[/+] on Oct 16, 2024
added
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
A-floating-pointArea: Floating point numbers and arithmetic
A-ABIArea: Concerning the application binary interface (ABI)
A-target-featureArea: Enabling/disabling target features like AVX, Neon, etc.
on Oct 16, 2024
chorman0773

chorman0773 commented on Oct 16, 2024

@chorman0773
Contributor

sse should be included for x86-64 and x87 should not be. Floats on 64-bit x86 use xmm registers rather than the x87 stack.

RalfJung

RalfJung commented on Oct 16, 2024

@RalfJung
MemberAuthor

Does -x87 not also disable SSE?

chorman0773

chorman0773 commented on Oct 16, 2024

@chorman0773
Contributor

I would assume not, they're entirely separate instruction sets and units.
In regardless, sse still affects float abi on x86_64.

beetrees

beetrees commented on Oct 16, 2024

@beetrees
Contributor
RalfJung

RalfJung commented on Oct 17, 2024

@RalfJung
MemberAuthor

On x86 (32-bit and 64-bit), f16 will get passed in an integer register instead of an SSE register if the sse2 feature is disabled.

What is the default register for f16 on x86-32? I would have expected it matches f32 and f64, i.e., it uses an x87 register for returns and gets passed on the stack for arguments? Why is SSE involved at all?

15 remaining items

changed the title [-]Figure out which target features affect float ABI[/-] [+]Figure out which target features are required/incompatible for which ABI[/+] on Dec 26, 2024
RalfJung

RalfJung commented on Dec 26, 2024

@RalfJung
MemberAuthor

With #134794, the framing for this is changing: all we need now is a full list of

  • what are the ABIs on each target (often just softfloat/hardfloat, but e.g. RISC-V has more than that)
  • which target features are required for which ABI

for all our architectures.

added
C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
on Jan 2, 2025
ketsuban

ketsuban commented on Mar 3, 2025

@ketsuban
Contributor

For m68k, built-in hardware floating-point support was added with the 68040, but it was reasonably common to use a 68020 or 68030 in conjunction with a discrete Motorola FPU. As a result GCC defaults to -msoft-float for the 68000 and 68010 and -mhard-float for the 68020 and above. I see no pressing reason not to follow suit.

heiher

heiher commented on Mar 17, 2025

@heiher
Contributor

For LoongArch targets:

  • ilp32d | lp64d: Requires d (which implies f), incompatible with nothing.
  • ilp32f | lp64f: Requires f, incompatible with nothing.
  • ilp32s | lp64s: The soft-float ABI does not require any features and is also not incompatible with any features. Rust targets explicitly specify the LLVM ABI names, which allows for enabling hard-float support even on soft-float targets, and ensures that the ABI behavior is as expected.
RalfJung

RalfJung commented on Mar 17, 2025

@RalfJung
MemberAuthor

Okay, so as usual LoongArch works basically exactly like RISC-V, thanks.

RalfJung

RalfJung commented on Mar 17, 2025

@RalfJung
MemberAuthor

@beetrees For powerpc, I found no trace of a softlfoat target. So it seems like right now, we should just assume a hardfloat ABI and mark the hard-float target feature as required for that ABI? Is there some other target feature we need to be worried about, like x87 on x86, that controls access to basic FP registers? Is it a problem that this makes it impossible to build softfloat code?
f128 adds extra complications, not the first time. Let's discuss that separately, I opened #138616 for this.

@taiki-e same for s390x: we could just mark soft-float as incompatible with the ABI. Without a dedicated softfloat target, that makes it impossible to build softfloat code for that target with Rust. Also, is there some other target feature that disables the FPU (or any other parts relevant for the ABI)?

beetrees

beetrees commented on Mar 17, 2025

@beetrees
Contributor

For PowerPC, glancing through the LLVM source code the only other feature I can spot that affects the ABI of f32 and f64 is spe (Signal Processing Engine): when spe is enabled, floats are passed in general-purpose registers.

RalfJung

RalfJung commented on Mar 18, 2025

@RalfJung
MemberAuthor

So we'd have to reject enabling spe or disabling hard-float on our powerpc targets, and currently there'd be no replacement.

tgross35

tgross35 commented on Mar 18, 2025

@tgross35
Contributor

@taiki-e same for s390x: we could just mark soft-float as incompatible with the ABI. Without a dedicated softfloat target, that makes it impossible to build softfloat code for that target with Rust. Also, is there some other target feature that disables the FPU (or any other parts relevant for the ABI)?

For s390x in particular, I think there may be a softfloat target at some point. See llvm/llvm-project#109164 (comment), my comment below it, and the last paragraph of Ulrich's comment after that.

RalfJung

RalfJung commented on Mar 18, 2025

@RalfJung
MemberAuthor

For s390x in particular, I think there may be a softfloat target at some point. See llvm/llvm-project#109164 (comment), my comment below it, and the last paragraph of Ulrich's comment after that.

I was about to say that having a soft-float target is mostly our decision and not clang's / LLVM, but ofc if there's not even softfloat support in libm or wherever that would go, then yeah there's not a lot we can do.^^

The question is whether we can just make +soft-float an error in rustc, or whether there's someone relying on it so we need to add a softfloat target of some sort first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ABIArea: Concerning the application binary interface (ABI)A-floating-pointArea: Floating point numbers and arithmeticA-target-featureArea: Enabling/disabling target features like AVX, Neon, etc.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Development

    No branches or pull requests

      Participants

      @RalfJung@heiher@chorman0773@ketsuban@tgross35

      Issue actions

        Figure out which target features are required/incompatible for which ABI · Issue #131799 · rust-lang/rust