]> granicus.if.org Git - clang/commitdiff
[MSP430] Improve support of 'interrupt' attribute
authorAnton Korobeynikov <anton@korobeynikov.info>
Wed, 16 Jan 2019 13:44:01 +0000 (13:44 +0000)
committerAnton Korobeynikov <anton@korobeynikov.info>
Wed, 16 Jan 2019 13:44:01 +0000 (13:44 +0000)
* Accept as an argument constants in range 0..63 (aligned with TI headers and linker scripts provided with TI GCC toolchain).
* Emit function attribute 'interrupt'='xx' instead of aliases (used in the backend to create a section for particular interrupt vector).
* Add more diagnostics.

Patch by Kristina Bessonova!

Differential Revision: https://reviews.llvm.org/D56663

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@351344 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/CodeGen/TargetInfo.cpp
lib/Sema/SemaDeclAttr.cpp
test/CodeGen/attr-msp430.c [new file with mode: 0644]
test/Sema/attr-msp430.c

index 5feb877e46c51d3a2966d499b29cdc42a80f7f80..b71f65d146cab53dbb3f69d20e41b6c8492c6f5e 100644 (file)
@@ -274,6 +274,10 @@ def warn_riscv_interrupt_attribute : Warning<
    "RISC-V 'interrupt' attribute only applies to functions that have "
    "%select{no parameters|a 'void' return type}0">,
    InGroup<IgnoredAttributes>;
+def warn_msp430_interrupt_attribute : Warning<
+   "MSP430 'interrupt' attribute only applies to functions that have "
+   "%select{no parameters|a 'void' return type}0">,
+   InGroup<IgnoredAttributes>;
 def warn_unused_parameter : Warning<"unused parameter %0">,
   InGroup<UnusedParameter>, DefaultIgnore;
 def warn_unused_variable : Warning<"unused variable %0">,
index 89ec73670a7350b09ae57b6548cb4339234456a6..f5a770ed9d844466e3558b2abdc4a7b3e4069c5d 100644 (file)
@@ -6774,21 +6774,19 @@ void MSP430TargetCodeGenInfo::setTargetAttributes(
   if (GV->isDeclaration())
     return;
   if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
-    if (const MSP430InterruptAttr *attr = FD->getAttr<MSP430InterruptAttr>()) {
-      // Handle 'interrupt' attribute:
-      llvm::Function *F = cast<llvm::Function>(GV);
+    const auto *InterruptAttr = FD->getAttr<MSP430InterruptAttr>();
+    if (!InterruptAttr)
+      return;
 
-      // Step 1: Set ISR calling convention.
-      F->setCallingConv(llvm::CallingConv::MSP430_INTR);
+    // Handle 'interrupt' attribute:
+    llvm::Function *F = cast<llvm::Function>(GV);
 
-      // Step 2: Add attributes goodness.
-      F->addFnAttr(llvm::Attribute::NoInline);
+    // Step 1: Set ISR calling convention.
+    F->setCallingConv(llvm::CallingConv::MSP430_INTR);
 
-      // Step 3: Emit ISR vector alias.
-      unsigned Num = attr->getNumber() / 2;
-      llvm::GlobalAlias::create(llvm::Function::ExternalLinkage,
-                                "__isr_" + Twine(Num), F);
-    }
+    // Step 2: Add attributes goodness.
+    F->addFnAttr(llvm::Attribute::NoInline);
+    F->addFnAttr("interrupt", llvm::utostr(InterruptAttr->getNumber()));
   }
 }
 
index 0e10804a2ec7613e0f6034813ed23c4b7945ef81..eb95cc748b177ae6813414613122f6667b411ec3 100644 (file)
@@ -5377,6 +5377,27 @@ static void handleARMInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
 }
 
 static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  // MSP430 'interrupt' attribute is applied to
+  // a function with no parameters and void return type.
+  if (!isFunctionOrMethod(D)) {
+    S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
+        << "'interrupt'" << ExpectedFunctionOrMethod;
+    return;
+  }
+
+  if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
+    S.Diag(D->getLocation(), diag::warn_msp430_interrupt_attribute)
+        << 0;
+    return;
+  }
+
+  if (!getFunctionOrMethodResultType(D)->isVoidType()) {
+    S.Diag(D->getLocation(), diag::warn_msp430_interrupt_attribute)
+        << 1;
+    return;
+  }
+
+  // The attribute takes one integer argument.
   if (!checkAttributeNumArgs(S, AL, 1))
     return;
 
@@ -5386,8 +5407,6 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
     return;
   }
 
-  // FIXME: Check for decl - it should be void ()(void).
-
   Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
   llvm::APSInt NumParams(32);
   if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
@@ -5396,9 +5415,9 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
         << NumParamsExpr->getSourceRange();
     return;
   }
-
+  // The argument should be in range 0..63.
   unsigned Num = NumParams.getLimitedValue(255);
-  if ((Num & 1) || Num > 30) {
+  if (Num > 63) {
     S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
         << AL << (int)NumParams.getSExtValue()
         << NumParamsExpr->getSourceRange();
diff --git a/test/CodeGen/attr-msp430.c b/test/CodeGen/attr-msp430.c
new file mode 100644 (file)
index 0000000..e8b6d0d
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple msp430-unknown-unknown -emit-llvm < %s| FileCheck %s
+
+__attribute__((interrupt(1))) void foo(void) {}
+// CHECK: @llvm.used
+// CHECK-SAME: @foo
+
+// CHECK: define msp430_intrcc void @foo() #0
+// CHECK: attributes #0
+// CHECK-SAME: noinline
+// CHECK-SAME: "interrupt"="1"
index 26b2d8fcfd65330238a475ee77345e90847eaa59..4b38d09b86757c37f98f6431cd8f1cf59edf7506 100644 (file)
@@ -1,6 +1,13 @@
 // RUN: %clang_cc1 -triple msp430-unknown-unknown -fsyntax-only -verify %s
 
+__attribute__((interrupt(1))) int t; // expected-warning {{'interrupt' attribute only applies to functions}}
+
 int i;
-void f(void) __attribute__((interrupt(i))); /* expected-error {{'interrupt' attribute requires an integer constant}} */
+__attribute__((interrupt(i))) void f(void); // expected-error {{'interrupt' attribute requires an integer constant}}
+__attribute__((interrupt(1, 2))) void f2(void); // expected-error {{'interrupt' attribute takes one argument}}
+__attribute__((interrupt(1))) int f3(void); // expected-warning {{MSP430 'interrupt' attribute only applies to functions that have a 'void' return type}}
+__attribute__((interrupt(1))) void f4(int a); // expected-warning {{MSP430 'interrupt' attribute only applies to functions that have no parameters}}
+__attribute__((interrupt(64))) void f5(void); // expected-error {{'interrupt' attribute parameter 64 is out of bounds}}
 
-void f2(void) __attribute__((interrupt(12)));
+__attribute__((interrupt(0))) void f6(void);
+__attribute__((interrupt(63))) void f7(void);