The msp430 target supports an "interrupt" attribute, which can take an optional argument specifying the interrupt number. If this argument is provided then the compiler will output an __interrupt_vector_<number> section that the linker script can use to create a vector table.
PR target/70713 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70713) reports that if an __interrupt_vector section is generated for a weak function, this section won't be discarded when the linker discards the weak function, which results in multiple __interrupt_vector sections that the linker is unable to choose between. This patch seeks to avoid the issue by not generating __interrupt_vector sections for weak functions, instead emitting a warning. I considered implementing the warning in msp430_attr(), but that only works if the weak attribute is specified before the interrupt attribute. Instead I've implemented the whole patch in msp430_start_function (aside: there are two functions named msp430_start_function). I've moved part of msp430_start_function into a new helper function, largely to keep line length down. I haven't tried to keep the line that calls warning under 79 characters, as other parts of msp430.c don't. Built and tested msp430-elf-gcc without regressions. I haven't done any c++ testing because that doesn't build for msp430-elf at the moment: https://gcc.gnu.org/ml/gcc-patches/2016-08/msg01256.html Note that I don't have commit access. If this patch (or some future version of it) is OK, I'd appreciate it if someone could commit it for me. Thanks, 2016-08-XX Joe Seymour <jo...@somniumtech.com> gcc/ PR target/70713 * config/msp430/msp430.c (msp430_start_function): Don't output interrupt vectors for weak functions. Issue a warning. (msp430_output_interrupt_vector): New helper function. gcc/testsuite/ PR target/70713 * gcc.target/msp430/function-attributes.c: New test. --- gcc/config/msp430/msp430.c | 58 +++++++++++++------- .../gcc.target/msp430/function-attributes.c | 17 ++++++ 2 files changed, 55 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/gcc.target/msp430/function-attributes.c diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c index dba4d19..ee9cdf9 100644 --- a/gcc/config/msp430/msp430.c +++ b/gcc/config/msp430/msp430.c @@ -2094,6 +2094,32 @@ increment_stack (HOST_WIDE_INT amount) } } +static void +msp430_output_interrupt_vector (FILE *file, const char *name, + tree decl, tree intr_vector) +{ + char buf[101]; + + intr_vector = TREE_VALUE (intr_vector); + + /* The interrupt attribute has a vector value. Turn this into a + section name, switch to that section and put the address of + the current function into that vector slot. Note msp430_attr() + has already verified the vector name for us. */ + if (TREE_CODE (intr_vector) == STRING_CST) + sprintf (buf, "__interrupt_vector_%.80s", + TREE_STRING_POINTER (intr_vector)); + else /* TREE_CODE (intr_vector) == INTEGER_CST */ + sprintf (buf, "__interrupt_vector_%u", + (unsigned int) TREE_INT_CST_LOW (intr_vector)); + + switch_to_section (get_section (buf, SECTION_CODE, decl)); + fputs ("\t.word\t", file); + assemble_name (file, name); + fputc ('\n', file); + fputc ('\t', file); +} + void msp430_start_function (FILE *file, const char *name, tree decl) { @@ -2106,26 +2132,18 @@ msp430_start_function (FILE *file, const char *name, tree decl) if (intr_vector != NULL_TREE) { - char buf[101]; - - intr_vector = TREE_VALUE (intr_vector); - - /* The interrupt attribute has a vector value. Turn this into a - section name, switch to that section and put the address of - the current function into that vector slot. Note msp430_attr() - has already verified the vector name for us. */ - if (TREE_CODE (intr_vector) == STRING_CST) - sprintf (buf, "__interrupt_vector_%.80s", - TREE_STRING_POINTER (intr_vector)); - else /* TREE_CODE (intr_vector) == INTEGER_CST */ - sprintf (buf, "__interrupt_vector_%u", - (unsigned int) TREE_INT_CST_LOW (intr_vector)); - - switch_to_section (get_section (buf, SECTION_CODE, decl)); - fputs ("\t.word\t", file); - assemble_name (file, name); - fputc ('\n', file); - fputc ('\t', file); + /* Interrupt vector sections should be unique, use of weak functions + implies multiple definitions, so don't generate vector table + entries for weak functions. */ + if (DECL_WEAK (decl)) + { + warning (OPT_Wattributes, + "argument to interrupt attribute is ignored for weak functions"); + } + else + { + msp430_output_interrupt_vector (file, name, decl, intr_vector); + } } } diff --git a/gcc/testsuite/gcc.target/msp430/function-attributes.c b/gcc/testsuite/gcc.target/msp430/function-attributes.c new file mode 100644 index 0000000..1c166af --- /dev/null +++ b/gcc/testsuite/gcc.target/msp430/function-attributes.c @@ -0,0 +1,17 @@ +void __attribute__((weak, interrupt(10))) +weak_interrupt_number (void) { +} /* { dg-warning "argument to interrupt attribute is ignored for weak functions" } */ + +void __attribute__((interrupt("nmi"))) __attribute__((weak)) +interrupt_name_weak (void) { +} /* { dg-warning "argument to interrupt attribute is ignored for weak functions" } */ + +void __attribute__((weak, interrupt)) +weak_interrupt (void) { +} + +void __attribute__((interrupt(11))) +interrupt_number (void) { +} + +/* { dg-final { scan-assembler-times "__interrupt_vector_" 1 } } */ -- 1.7.1