-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[x86] LLVM silently switches to the soft-float ABI if FPU is disabled on hard-float target #111406
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
Comments
@llvm/issue-subscribers-backend-x86 Author: Ralf Jung (RalfJung)
Here's a godbolt reproducer: https://godbolt.org/z/GGfTEWcPT
This is basically the X86 version of https://github.com//issues/110383.
Strangely, passing just I am a Rust person so I care mostly about the behavior of the backend here, and less about the clang frontend. The underlying issue is that if Rust sets |
GCC has option |
That requires duplicating the ABI logic in the frontend. It is hard to figure out which flags might make LLVM silently change ABI, and this might even change on LLVM updates. So doing this in the frontend is an endless game of wack-a-mole.
|
Silently changing ABI is allowed in some cases, e.g., https://godbolt.org/z/dEs4cjGYr |
That looks like a GCC bug to me, given that it generally strives to clearly tell when the requested ABI cannot be realized. |
It is a feature, see #50840 |
-mno-fp-ret asks for an ABI change. That's very different than -mno-x87 silently changing the ABI.
|
No sure GCC's implementation, but we simply do an alias in Clang. Anyway, the option differentiation is a FE job instead of backend. |
As I already said (but you have not replied to), that requires duplicating a bunch if logic. The backend should at least expose this information to the frontend; it would be silly for every frontend to duplicate that.
|
The frontend has already had a lot of knowledge about ABI information, see clang/lib/CodeGen/Targets/X86.cpp. Sinking them in backend is not efficient or even possible in some cases. So I suggest frontend to check it following the precedent. |
Other frontends have way less ABI information, e.g. the Rust compiler. It would be a huge waste of effort to duplicate this in all frontends.
Yeah backend errors currently do not look great, but that can be fixed by having some way for the backend to give error information to the frontend rather than printing the error itself. Also, even if the frontend has its own checks, it's always good to have a second line of defense -- if something slips through the frontend checks, it's good for the backend to catch that. Right now the same logic is implemented twice and if there's an accidental mismatch it leads to very subtle surprising behavior. It would be much better to instead have a backend error in that case, even if a backend error looks less nice than a frontend error. |
…rget A small step to ABIVerifier proposal disscussed in llvm#100757 (comment) Fixes: llvm#111406
I agree with the idea of second line defense and I actually suggested to do similar work with an ABI verifier, see #100757 (comment) Here you go :) |
@phoebewang thanks for filing that PR. :) Seems like unfortunately reviewers do not agree with the approach. For RISCV, the ABI logic in |
We check the feature when lowering return on X86 . The problem is when both That says, backend doesn't distinguish |
I'm sorry I wasn't able to fully understand this. But given that RISC-V handles this properly, emitting a warning when requesting an invalid combination (hardfloat ABI but no FP unit), I think X86 should do the same. Maybe we have to first introduce a more explicit notion of "requesting hardfloat ABI" for X86 if you are not happy with using "absence of
Where can I find the documentation on UB like this? Clearly it is very important to precisely document all the UB, otherwise how are frontends supposed to know that there is UB here. |
I don't see the concept of hardfloat ABI in LLVM. Here is the code I mentioned that transforms FP into integer type: And X86 checks it here: The check happens after type been transformed, and for an integer type, it's correct to not error out here. As you can see, the framework doesn't care about ABI when target does not have native FP support. I'm not sure it's UB, but ABI related UB seldom been documented. I think one reason is it's always target specific and been handled well by CFE. It's not convenient for other FE to do them all, so I'm in favor of modulize that part as much as possible and share among different FEs. Of course, we can do more strict verifier like I proposed. |
It seems to be something each target has to do on its own. For RISCV, this happens here:
IMO ideally all targets would work something like that: the user explicitly requests an ABI, and then LLVM at least warns if somehow the ABI cannot be implemented. The X86 check you mention approximates this somewhat, though it fails to capture the case of an x87 register return occurring when x87 is disabled. |
Here's a godbolt reproducer: https://godbolt.org/z/GGfTEWcPT
This is basically the X86 version of #110383.
-mno-sse -mno-x87
switches to the softfloat ABI. I would expect this to only happen when I set-msoft-float
. (Though strangely, that flag on its own does not seem to change the ABI at all?)Strangely, passing just
-mno-sse
to clang behaves as expected: it shows an error. But adding-mno-x87
(which does not seem to exist for GCC) makes the error go away.I am a Rust person so I care mostly about the behavior of the backend here, and less about the clang frontend. The underlying issue is that if Rust sets
-x87
for the target features increateTargetMachine
we should get an error since the registers for the ABI are missing;+soft-float,-x87
should work because we requested soft-float and then it's fine for the registers to be missing.The text was updated successfully, but these errors were encountered: