
[clang][ARM] Fix warning for using VFP from interrupts. This warning has three issues: - The interrupt attribute causes the function to return using an exception return instruction. This warning allows calls from one function with the interrupt attribute to another, and the diagnostic text suggests that not having the attribute on the callee is a problem. Actually making such a call will lead to a double exception return, which is unpredictable according to the ARM architecture manual section B9.1.1, "Restrictions on exception return instructions". Even on machines where an exception return from user/system mode is tolerated, if the callee's interrupt type is anything other than a supervisor call or secure monitor call, it will also return to a different address than a normal function would. For example, returning from an "IRQ" handler will return to lr - 4, which will generally result in calling the same function again. - The interrupt attribute currently does not cause caller-saved VFP registers to be saved and restored if they are used, so putting __attribute__((interrupt)) on a called function doesn't prevent it from clobbering VFP state. - It is part of the -Wextra diagnostic group and can't be individually disabled when using -Wextra, which also means the diagnostic text of this specific warning appears in the documentation of -Wextra. This change addresses all three issues by instead generating a warning for any interrupt handler where the vfp feature is enabled. The warning is also given its own diagnostic group. Closes #34876. [clang][ARM] Emit an error when an interrupt handler is called. Closes #95359.
27 lines
1.3 KiB
C
27 lines
1.3 KiB
C
// RUN: %clang_cc1 %s -triple arm-none-eabi -verify -fsyntax-only
|
|
// RUN: %clang_cc1 %s -triple arm-none-eabi -target-feature +vfp2 -verify -fsyntax-only
|
|
|
|
|
|
#ifdef __ARM_FP
|
|
__attribute__((interrupt("IRQ"))) void float_irq(void); // expected-warning {{interrupt service routine with vfp enabled may clobber the interruptee's vfp state}}
|
|
#else // !defined(__ARM_FP)
|
|
__attribute__((interrupt("irq"))) void foo1(void) {} // expected-warning {{'interrupt' attribute argument not supported: irq}}
|
|
__attribute__((interrupt(IRQ))) void foo(void) {} // expected-error {{'interrupt' attribute requires a string}}
|
|
__attribute__((interrupt("IRQ", 1))) void foo2(void) {} // expected-error {{'interrupt' attribute takes no more than 1 argument}}
|
|
__attribute__((interrupt("IRQ"))) void foo3(void) {}
|
|
__attribute__((interrupt("FIQ"))) void foo4(void) {}
|
|
__attribute__((interrupt("SWI"))) void foo5(void) {}
|
|
__attribute__((interrupt("ABORT"))) void foo6(void) {}
|
|
__attribute__((interrupt("UNDEF"))) void foo7(void) {}
|
|
__attribute__((interrupt)) void foo8(void) {}
|
|
__attribute__((interrupt())) void foo9(void) {}
|
|
__attribute__((interrupt(""))) void foo10(void) {}
|
|
|
|
__attribute__((interrupt("IRQ"))) void callee(void) {}
|
|
|
|
void caller(void)
|
|
{
|
|
callee(); // expected-error {{interrupt service routine cannot be called directly}}
|
|
}
|
|
#endif // __ARM_FP
|