statham-arm wrote:
Hi @chrisnc,
This new diagnostic caused some build failures in our Arm embedded toolchain.
We build some embedded C/C++ libraries intended to run on a platform with
hardware FP, but because they're embedded, the code begins running when the FPU
is not enabled in hardware yet. So we tagged one of our initial setup functions
with the `target("no-fpregs")` attribute to make sure it didn't accidentally
use the FP registers:
```c++
[[gnu::target("no-fpregs")]] void setup() { ... }
```
But now this causes a compile error, because the compiler is running with
`-mfloat-abi=hard`, and `setup()` isn't allowed to have the hard-float ABI and
also not use the FP registers.
However, its function type is `void(void)`, which works the same with or
without the hard-float ABI! The diagnostic is complaining that it doesn't have
the same _formal_ ABI, even though it makes no difference in this case. We have
to work around it by tagging the function with the `pcs("aapcs")` attribute too.
Another case of this occurs when the setup function calls a subroutine to write
a system register. That subroutine must also be formally marked as
`pcs("aapcs")` to avoid this new diagnostic. Again that function has no
floating-point values in its signature. But not only that: it's also marked
`[[clang::always_inline]]`, which ought to mean that its PCS _does not matter_,
because no function call to it is ever emitted in output code!
What do you think? Would it make sense to suppress this diagnostic in one or
both of the cases where
* the function's type is such that the two ABIs would agree anyway
* the function is marked always-inline, so that its ABI is irrelevant?
Separately, here's an oddity in the error reporting. Consider this input code:
```c++
__attribute__((target("no-fpregs"), pcs("aapcs"))) int f(void) {
extern int g(void);
return g() + 1;
}
```
Here, `f` is fine: it's not using the FP registers, but that's OK, it's also
marked with the soft-float ABI. But `g` isn't, so the call to `g` provokes your
new diagnostic. However, the diagnostic is localised to the start of `f`:
```
$ clang --target=armv8a-none-eabi -mfloat-abi=hard -c zz.c
zz.c:1:56: error: call to 'g' expects a hard-float calling convention, but
floating-point registers are unavailable
1 | __attribute__((target("no-fpregs"), pcs("aapcs"))) int f(void) {
| ^
1 error generated.
```
If `f` is a long function, it might not be easy to track down _where_ in it
I've accidentally called `g`. Shouldn't the error message point at the
objectionable function call, not the start of the containing function?
https://github.com/llvm/llvm-project/pull/111334
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits