llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Chris Copeland (chrisnc)

<details>
<summary>Changes</summary>

This warning has two issues:
 - The interrupt attribute doesn't only change how volatile registers
   are treated; it also 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 the 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.
 - 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 both issues. Rather than check that the callee has
the interrupt attribute, check that it uses the soft-float feature,
which will prevent use of VFP state. The warning is also given its own
diagnostic group.


---
Full diff: https://github.com/llvm/llvm-project/pull/91870.diff


5 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+11) 
- (modified) clang/include/clang/Basic/Attr.td (+7) 
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4-3) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+10-9) 
- (modified) clang/test/Sema/arm-interrupt-attr.c (+3-3) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7c5dcc59c7016..3f9f81bc2bfac 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -352,6 +352,10 @@ Modified Compiler Flags
   evaluating to ``true`` and an empty body such as ``while(1);``)
   are considered infinite, even when the ``-ffinite-loop`` flag is set.
 
+- Removed "arm interrupt calling convention" warning that was included in
+  ``-Wextra`` but did not have its own flag. Added
+  ``-Warm-interrupt-vfp-clobber`` that enables the modified warning.
+
 Removed Compiler Flags
 -------------------------
 
@@ -484,6 +488,13 @@ Improvements to Clang's diagnostics
        }
      };
 
+- On ARM, Clang no longer suggests adding ``__attribute__((interrupt))`` to 
normal
+  functions that are called from interrupt handlers to prevent clobbering VFP
+  registers as part of ``-Wextra``. Following this suggestion leads to
+  unpredictable behavior. Instead, ``-Warm-interrupt-vfp-clobber`` can now be
+  used to detect calling functions that don't have VFP disabled with
+  ``__attribute((target("soft-float")))`` from an interrupt handler.
+
 Improvements to Clang's time-trace
 ----------------------------------
 
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 52552ba488560..04e3b8f949992 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3090,6 +3090,13 @@ def Target : InheritableAttr {
       }
     }
 
+    bool hasFeature(StringRef Feature) const {
+      StringRef Features = getFeaturesStr();
+      SmallVector<StringRef, 1> AttrFeatures;
+      Features.split(AttrFeatures, ",");
+      return Features.contains(Feature);
+    }
+
     bool isDefaultVersion() const { return getFeaturesStr() == "default"; }
   }];
 }
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d6863f90edb6e..1c5f5ffb03dc5 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -336,9 +336,10 @@ def warn_anyx86_excessive_regsave : Warning<
   " with attribute 'no_caller_saved_registers'"
   " or be compiled with '-mgeneral-regs-only'">,
   InGroup<DiagGroup<"excessive-regsave">>;
-def warn_arm_interrupt_calling_convention : Warning<
-   "call to function without interrupt attribute could clobber interruptee's 
VFP registers">,
-   InGroup<Extra>;
+def warn_arm_interrupt_vfp_clobber : Warning<
+   "calling a VFP-enabled function from an interrupt could clobber the "
+   "interruptee's VFP registers">,
+   InGroup<DiagGroup<"arm-interrupt-vfp-clobber">>;
 def warn_interrupt_attribute_invalid : Warning<
    "%select{MIPS|MSP430|RISC-V}0 'interrupt' attribute only applies to "
    "functions that have %select{no parameters|a 'void' return type}1">,
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c688cb21f2364..c514820bd899c 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6942,22 +6942,23 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, 
NamedDecl *NDecl,
     return ExprError();
   }
 
-  // Interrupt handlers don't save off the VFP regs automatically on ARM,
-  // 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.
-  // 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()) {
+    // Interrupt handlers don't save volatile VFP registers automatically on
+    // ARM, so calling other functions that use VFP will likely cause the
+    // interruptee's VFP state to be clobbered. This is easy to diagnose here,
+    // but can be very challenging to debug.
     if (Caller->hasAttr<ARMInterruptAttr>()) {
       bool VFP = Context.getTargetInfo().hasFeature("vfp");
-      if (VFP && (!FDecl || !FDecl->hasAttr<ARMInterruptAttr>())) {
-        Diag(Fn->getExprLoc(), diag::warn_arm_interrupt_calling_convention);
+      if (VFP && (!FDecl || !FDecl->hasAttr<TargetAttr>() ||
+                  !FDecl->getAttr<TargetAttr>()->hasFeature("soft-float"))) {
+        Diag(Fn->getExprLoc(), diag::warn_arm_interrupt_vfp_clobber);
         if (FDecl)
           Diag(FDecl->getLocation(), diag::note_callee_decl) << FDecl;
       }
     }
+    // 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 (Caller->hasAttr<AnyX86InterruptAttr>() ||
         Caller->hasAttr<AnyX86NoCallerSavedRegistersAttr>()) {
       const TargetInfo &TI = Context.getTargetInfo();
diff --git a/clang/test/Sema/arm-interrupt-attr.c 
b/clang/test/Sema/arm-interrupt-attr.c
index 3537fba8521ad..112e5b5e8ad1e 100644
--- a/clang/test/Sema/arm-interrupt-attr.c
+++ b/clang/test/Sema/arm-interrupt-attr.c
@@ -23,7 +23,7 @@ __attribute__((interrupt(""))) void foo10(void) {}
 // expected-note@+2 {{'callee1' declared here}}
 #endif
 void callee1(void);
-__attribute__((interrupt("IRQ"))) void callee2(void);
+__attribute__((target("soft-float"))) void callee2(void);
 void caller1(void) {
   callee1();
   callee2();
@@ -31,13 +31,13 @@ void caller1(void) {
 
 #ifndef SOFT
 __attribute__((interrupt("IRQ"))) void caller2(void) {
-  callee1(); // expected-warning {{call to function without interrupt 
attribute could clobber interruptee's VFP registers}}
+  callee1(); // expected-warning {{calling a VFP-enabled function from an 
interrupt could clobber the interruptee's VFP registers}}
   callee2();
 }
 
 void (*callee3)(void);
 __attribute__((interrupt("IRQ"))) void caller3(void) {
-  callee3(); // expected-warning {{call to function without interrupt 
attribute could clobber interruptee's VFP registers}}
+  callee3(); // expected-warning {{calling a VFP-enabled function from an 
interrupt could clobber the interruptee's VFP registers}}
 }
 #else
 __attribute__((interrupt("IRQ"))) void caller2(void) {

``````````

</details>


https://github.com/llvm/llvm-project/pull/91870
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to