[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