forked from OSchip/llvm-project
[clang][patch] To solve PR26413, x86 interrupt routines may only call routines with no_saved_reg
Reviewed By: Aaron Ballman Differential Revision: https://reviews.llvm.org/D97764
This commit is contained in:
parent
b2bc0a3254
commit
cc3d25be01
|
@ -293,6 +293,9 @@ def err_anyx86_interrupt_attribute : Error<
|
|||
"a pointer as the first parameter|a %2 type as the second parameter}1">;
|
||||
def err_anyx86_interrupt_called : Error<
|
||||
"interrupt service routine cannot be called directly">;
|
||||
def err_anyx86_interrupt_regsave : Error<
|
||||
"interrupt service routine may only call a function"
|
||||
" with attribute 'no_caller_saved_registers'">;
|
||||
def warn_arm_interrupt_calling_convention : Warning<
|
||||
"call to function without interrupt attribute could clobber interruptee's VFP registers">,
|
||||
InGroup<Extra>;
|
||||
|
|
|
@ -6552,12 +6552,25 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
|
|||
// so there's some risk when calling out to non-interrupt handler functions
|
||||
// that the callee might not preserve them. This is easy to diagnose here,
|
||||
// but can be very challenging to debug.
|
||||
if (auto *Caller = getCurFunctionDecl())
|
||||
// Likewise, X86 interrupt handlers may only call routines with attribute
|
||||
// no_caller_saved_registers since there is no efficient way to
|
||||
// save and restore the non-GPR state.
|
||||
if (auto *Caller = getCurFunctionDecl()) {
|
||||
if (Caller->hasAttr<ARMInterruptAttr>()) {
|
||||
bool VFP = Context.getTargetInfo().hasFeature("vfp");
|
||||
if (VFP && (!FDecl || !FDecl->hasAttr<ARMInterruptAttr>()))
|
||||
if (VFP && (!FDecl || !FDecl->hasAttr<ARMInterruptAttr>())) {
|
||||
Diag(Fn->getExprLoc(), diag::warn_arm_interrupt_calling_convention);
|
||||
if (FDecl)
|
||||
Diag(FDecl->getLocation(), diag::note_callee_decl) << FDecl;
|
||||
}
|
||||
}
|
||||
if (Caller->hasAttr<AnyX86InterruptAttr>() &&
|
||||
((!FDecl || !FDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>()))) {
|
||||
Diag(Fn->getExprLoc(), diag::err_anyx86_interrupt_regsave);
|
||||
if (FDecl)
|
||||
Diag(FDecl->getLocation(), diag::note_callee_decl) << FDecl;
|
||||
}
|
||||
}
|
||||
|
||||
// Promote the function operand.
|
||||
// We special-case function promotion here because we only allow promoting
|
||||
|
|
|
@ -19,6 +19,9 @@ __attribute__((interrupt)) void foo8() {}
|
|||
__attribute__((interrupt())) void foo9() {}
|
||||
__attribute__((interrupt(""))) void foo10() {}
|
||||
|
||||
#ifndef SOFT
|
||||
// expected-note@+2 {{'callee1' declared here}}
|
||||
#endif
|
||||
void callee1();
|
||||
__attribute__((interrupt("IRQ"))) void callee2();
|
||||
void caller1() {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-pc-win32 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -triple i386-pc-win32 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnux32 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s -DNOCALLERSAVE=1
|
||||
|
||||
struct a {
|
||||
int b;
|
||||
|
@ -39,6 +40,23 @@ __attribute__((interrupt)) void foo6(float *a, int b) {}
|
|||
__attribute__((interrupt)) void foo7(int *a, unsigned b) {}
|
||||
__attribute__((interrupt)) void foo8(int *a) {}
|
||||
|
||||
#ifdef _LP64
|
||||
typedef unsigned long Arg2Type;
|
||||
#elif defined(__x86_64__)
|
||||
typedef unsigned long long Arg2Type;
|
||||
#else
|
||||
typedef unsigned int Arg2Type;
|
||||
#endif
|
||||
#ifndef NOCALLERSAVE
|
||||
__attribute__((no_caller_saved_registers))
|
||||
#else
|
||||
// expected-note@+3 {{'foo9' declared here}}
|
||||
// expected-error@+4 {{interrupt service routine may only call a function with attribute 'no_caller_saved_registers'}}
|
||||
#endif
|
||||
void foo9(int *a, Arg2Type b) {}
|
||||
__attribute__((interrupt)) void fooA(int *a, Arg2Type b) {
|
||||
foo9(a, b);
|
||||
}
|
||||
void g(void (*fp)(int *));
|
||||
int main(int argc, char **argv) {
|
||||
void *ptr = (void *)&foo7;
|
||||
|
|
Loading…
Reference in New Issue