[clang] cc3d25b - [clang][patch] To solve PR26413, x86 interrupt routines may only call routines with no_saved_reg

Melanie Blower via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 3 07:12:03 PST 2021


Author: Melanie Blower
Date: 2021-03-03T10:11:13-05:00
New Revision: cc3d25be0116fc3cc41a08f8bf9eef73d6dc5d62

URL: https://github.com/llvm/llvm-project/commit/cc3d25be0116fc3cc41a08f8bf9eef73d6dc5d62
DIFF: https://github.com/llvm/llvm-project/commit/cc3d25be0116fc3cc41a08f8bf9eef73d6dc5d62.diff

LOG: [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

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaExpr.cpp
    clang/test/Sema/arm-interrupt-attr.c
    clang/test/Sema/attr-x86-interrupt.c

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 481ed57c0b58..1ffc9884013d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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>;

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 98097b6fb381..79dd3c0c1184 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -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

diff  --git a/clang/test/Sema/arm-interrupt-attr.c b/clang/test/Sema/arm-interrupt-attr.c
index 60691ab7f8e8..5a844d0e2d79 100644
--- a/clang/test/Sema/arm-interrupt-attr.c
+++ b/clang/test/Sema/arm-interrupt-attr.c
@@ -19,6 +19,9 @@ __attribute__((interrupt)) void foo8() {}
 __attribute__((interrupt())) void foo9() {}
 __attribute__((interrupt(""))) void foo10() {}
 
+#ifndef SOFT
+// expected-note at +2 {{'callee1' declared here}}
+#endif
 void callee1();
 __attribute__((interrupt("IRQ"))) void callee2();
 void caller1() {

diff  --git a/clang/test/Sema/attr-x86-interrupt.c b/clang/test/Sema/attr-x86-interrupt.c
index 0785fdfcb1b3..952433e2cb8a 100644
--- a/clang/test/Sema/attr-x86-interrupt.c
+++ b/clang/test/Sema/attr-x86-interrupt.c
@@ -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 at +3 {{'foo9' declared here}}
+// expected-error at +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;


        


More information about the cfe-commits mailing list