MSP430: Allow interrupt handlers to be static
authorJozef Lawrynowicz <jozef.l@mittosystems.com>
Wed, 6 Jun 2018 11:49:20 +0000 (11:49 +0000)
committerJozef Lawrynowicz <jozefl@gcc.gnu.org>
Wed, 6 Jun 2018 11:49:20 +0000 (11:49 +0000)
* gcc/config/msp430/msp430.c (msp430_attr): Allow interrupt handlers
to be static and remove check on interrupt attribute name.

gcc/testsuite/gcc.target/msp430/
* function-attributes-4.c: New test.
* static-interrupts.c: New test.

From-SVN: r261229

gcc/ChangeLog
gcc/config/msp430/msp430.c
gcc/testsuite/gcc.target/msp430/function-attributes-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/msp430/static-interrupts.c [new file with mode: 0644]

index e7be00833098357ab0d7cf6e4389dc56ae608645..85515d98f98ee1292ccb1681a93e81e7dcba14ea 100644 (file)
@@ -1,3 +1,12 @@
+2018-06-06  Jozef Lawrynowicz  <jozef.l@mittosystems.com>
+
+       * gcc/config/msp430/msp430.c (msp430_attr): Allow interrupt handlers
+       to be static and remove check on interrupt attribute name.
+
+       gcc/testsuite/gcc.target/msp430/
+       * function-attributes-4.c: New test.
+       * static-interrupts.c: New test.
+
 2018-06-05  Kelvin Nilsen  <kelvin@gcc.gnu.org>
 
        * doc/extend.texi (PowerPC AltiVec Built-in Functions): Remove
index 8c8e676b73e1d2800542775dbb5dc01245f6aa9f..90517615bba9b69cea731cd8bef871907b386ece 100644 (file)
@@ -1878,11 +1878,9 @@ msp430_attr (tree * node,
 {
   gcc_assert (DECL_P (* node));
 
+  /* Only the interrupt attribute takes an argument.  */
   if (args != NULL)
     {
-      /* Only the interrupt attribute takes an argument.  */
-      gcc_assert (TREE_NAME_EQ (name, ATTR_INTR));
-
       tree value = TREE_VALUE (args);
 
       switch (TREE_CODE (value))
@@ -1927,13 +1925,12 @@ msp430_attr (tree * node,
       if (TREE_CODE (TREE_TYPE (* node)) == FUNCTION_TYPE
          && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node))))
        message = "interrupt handlers must be void";
-
-      if (! TREE_PUBLIC (* node))
-       message = "interrupt handlers cannot be static";
-
-      /* Ensure interrupt handlers never get optimised out.  */
-      TREE_USED (* node) = 1;
-      DECL_PRESERVE_P (* node) = 1;
+      else
+       {
+         /* Ensure interrupt handlers never get optimised out.  */
+         TREE_USED (* node) = 1;
+         DECL_PRESERVE_P (* node) = 1;
+       }
     }
   else if (TREE_NAME_EQ (name, ATTR_REENT))
     {
diff --git a/gcc/testsuite/gcc.target/msp430/function-attributes-4.c b/gcc/testsuite/gcc.target/msp430/function-attributes-4.c
new file mode 100644 (file)
index 0000000..07d13c9
--- /dev/null
@@ -0,0 +1,111 @@
+/* { dg-do compile } */
+/* Check that the foo interrupt vectors aren't actually removed.  */
+/* { dg-final { scan-assembler-times "__interrupt_vector_foo" 2 } } */
+
+/* Check that warnings are emitted when attributes are used incorrectly and
+   that attributes are interpreted correctly whether leading and trailing
+   underscores are used or not.  */
+
+void __attribute__((__naked__,__reentrant__))
+fn1(void)
+{ /* { dg-warning "naked functions cannot be reentrant" } */
+}
+
+void __attribute__((naked,reentrant))
+fn2(void)
+{ /* { dg-warning "naked functions cannot be reentrant" } */
+}
+
+void __attribute__((__reentrant__,__naked__))
+fn3(void)
+{ /* { dg-warning "reentrant functions cannot be naked" } */
+}
+
+void __attribute__((reentrant,naked))
+fn4(void)
+{ /* { dg-warning "reentrant functions cannot be naked" } */
+}
+
+void __attribute__((__critical__,__reentrant__))
+fn5(void)
+{ /* { dg-warning "critical functions cannot be reentrant" } */
+}
+
+void __attribute__((critical,reentrant))
+fn6(void)
+{ /* { dg-warning "critical functions cannot be reentrant" } */
+}
+
+void __attribute__((__reentrant__,__critical__))
+fn7(void)
+{ /* { dg-warning "reentrant functions cannot be critical" } */
+}
+
+void __attribute__((reentrant,critical))
+fn8(void)
+{ /* { dg-warning "reentrant functions cannot be critical" } */
+}
+
+void __attribute__((__critical__,__naked__))
+fn9(void)
+{ /* { dg-warning "critical functions cannot be naked" } */
+}
+
+void __attribute__((critical,naked))
+fn10(void)
+{ /* { dg-warning "critical functions cannot be naked" } */
+}
+
+void __attribute__((__naked__,__critical__))
+fn11(void)
+{ /* { dg-warning "naked functions cannot be critical" } */
+}
+
+void __attribute__((naked,critical))
+fn12(void)
+{ /* { dg-warning "naked functions cannot be critical" } */
+}
+
+int __attribute__((interrupt))
+isr1 (void)
+{ /* { dg-warning "interrupt handlers must be void" } */
+}
+
+int __attribute__((__interrupt__))
+isr2 (void)
+{ /* { dg-warning "interrupt handlers must be void" } */
+}
+
+void __attribute__((interrupt("foo1")))
+isr3 (void)
+{ /* { dg-warning "unrecognized interrupt vector argument" } */
+}
+
+void __attribute__((__interrupt__("foo2")))
+isr4 (void)
+{ /* { dg-warning "unrecognized.*interrupt vector argument" } */
+}
+
+void __attribute__((interrupt(65)))
+isr5 (void)
+{ /* { dg-warning "numeric argument of 'interrupt' attribute must be in range 0..63" } */
+}
+
+void __attribute__((__interrupt__(100)))
+isr6 (void)
+{ /* { dg-warning "numeric argument of 'interrupt' attribute must be in range 0..63" } */
+}
+
+void __attribute__((interrupt(0.5)))
+isr7 (void)
+{ /* { dg-warning "argument of 'interrupt' attribute is not a string constant or number" } */
+  volatile int __attribute__((__naked__))
+    a; /* { dg-warning "'naked' attribute only applies to functions" } */
+}
+
+void __attribute__((__interrupt__(1.5)))
+isr8 (void)
+{ /* { dg-warning "argument of 'interrupt' attribute is not a string constant or number" } */
+  volatile int __attribute__((naked))
+    a; /* { dg-warning "'naked' attribute only applies to functions" } */
+}
diff --git a/gcc/testsuite/gcc.target/msp430/static-interrupts.c b/gcc/testsuite/gcc.target/msp430/static-interrupts.c
new file mode 100644 (file)
index 0000000..06d9ea6
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+/* { dg-final { scan-assembler-times "__interrupt_vector_" 4 } } */
+
+/* Test that interrupts aren't optimised out and that "__interrupt__" and
+   "interrupt" can be used interchangeably.  */
+
+static void __attribute__((interrupt(1)))
+isr_static (void)
+{
+}
+
+static void __attribute__((__interrupt__(2)))
+isr_static_alt (void)
+{
+}
+
+void __attribute__((interrupt(3)))
+isr_global (void)
+{
+}
+
+void __attribute__((__interrupt__(4)))
+isr_global_alt (void)
+{
+}