Applied with the addendum below. Am 23.07.24 um 22:19 schrieb Georg-Johann Lay:
This patch adds support for arguments to the signal and interrupt function attributes. It allows to specify the ISR by means of the associated IRQ number, in extension to the current attributes that require to specify the ISR name like "__vector_1" as (assembly) name for the function. The new feature is more convenient, e.g. when the ISR is implemented by a class method or in a namespace. There is no requirement that the ISR is externally visible. The syntax is like:__attribute__((signal(1, 2, ...), signal(3, 4, ...))) [static] void isr_function (void) { // Code } Ok for trunk? Johann -- AVR target 116056 - Support attribute signal(n) and interrupt(n). This patch adds support for arguments to the signal and interrupt function attributes. It allows to specify the ISR by means of the associated IRQ number, in extension to the current attributes that require to specify the ISR name like "__vector_1" as (assembly) name for the function. The new feature is more convenient, e.g. when the ISR is implemented by a class method or in a namespace. There is no requirement that the ISR is externally visible. The syntax is like: __attribute__((signal(1, 2, ...), signal(3, 4, ...))) [static] void isr_function (void) { // Code } PR target/116056 gcc/ * config/avr/avr.h (ASM_DECLARE_FUNCTION_NAME): New define. * config/avr/avr-protos.h (avr_declare_function_name): New proto. * config/avr/avr-c.cc (avr_cpu_cpp_builtins) <__HAVE_SIGNAL_N__>: New built-in macro. * config/avr/avr.cc (avr_declare_function_name): New function. (avr_attribute_table) <signal,interrupt>: Allow any number of args. (avr_insert_attributes): Check validity of "signal" and "interrupt" arguments. (avr_foreach_function_attribute, avr_interrupt_signal_function) (avr_isr_number, avr_asm_isr_alias, avr_handle_isr_attribute): New static functions. (avr_interrupt_function): New from avr_interrupt_function_p. Adjust callers. (avr_signal_function): New from avr_signal_function_p. Adjust callers. (avr_set_current_function): Only diagnose non-__vector ISR names when "signal" or "interrupt" attribute has no args. (struct avr_fun_cookie): New. * doc/extend.texi (AVR Function Attributes): Document signal(num) and interrupt(num). * doc/invoke.texi (AVR Built-in Macros) <__HAVE_SIGNAL_N__>: Document. gcc/testsuite/ * gcc.target/avr/torture/signal_n-1.c: New test. * gcc.target/avr/torture/signal_n-2.c: New test. * gcc.target/avr/torture/signal_n-3.c: New test. * gcc.target/avr/torture/signal_n-4.cpp: New test.
diff --git a/gcc/config/avr/avr-c.cc b/gcc/config/avr/avr-c.cc index 2c5cfb34df6..ca484f26132 100644 --- a/gcc/config/avr/avr-c.cc +++ b/gcc/config/avr/avr-c.cc @@ -391,9 +391,10 @@ avr_cpu_cpp_builtins (struct cpp_reader *pfile) cpp_define (pfile, "__WITH_AVRLIBC__"); #endif /* WITH_AVRLIBC */ - // We support __attribute__((signal (n1, n2, ...))). + // We support __attribute__((signal/interrupt (n1, n2, ...)[, noblock])) cpp_define (pfile, "__HAVE_SIGNAL_N__"); + // From configure --with-libf7={|libgcc|math|math-symbols|yes|no} #ifdef WITH_LIBF7_LIBGCC diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 63643b24cbd..dffb7e056be 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -1391,6 +1391,14 @@ avr_naked_function_p (tree func) return avr_lookup_function_attribute1 (func, "naked"); } +/* Return nonzero if FUNC is a noblock function. */ + +static bool +avr_noblock_function_p (tree func) +{ + return avr_lookup_function_attribute1 (func, "noblock"); +} + /* Return 1 if FUNC is a function that has a "ATTR_NAME" attribute (and perhaps also "ATTR_NAME(num)" attributes. Return -1 if FUNC has "ATTR_NAME(num)" attribute(s) but no "ATTR_NAME" attribute. @@ -1492,6 +1500,7 @@ avr_set_current_function (tree decl) cfun->machine->is_naked = avr_naked_function_p (decl); cfun->machine->is_signal = avr_signal_function (decl); cfun->machine->is_interrupt = avr_interrupt_function (decl); + cfun->machine->is_noblock = avr_noblock_function_p (decl); cfun->machine->is_OS_task = avr_OS_task_function_p (decl); cfun->machine->is_OS_main = avr_OS_main_function_p (decl); cfun->machine->is_no_gccisr = avr_no_gccisr_function_p (decl); @@ -1551,6 +1560,11 @@ avr_set_current_function (tree decl) "%qs handler, missing %<__vector%> prefix", name, isr); #endif // AVR-LibC naming conventions } + else if (cfun->machine->is_noblock) + { + warning (OPT_Wattributes, "%qs attribute ignored on non-ISR function", + "noblock"); + } #if defined WITH_AVRLIBC // Common problem is using "ISR" without first including avr/interrupt.h. @@ -2848,11 +2862,14 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) Always move through unspec, see PR50063. For meaning of irq_state see movhi_sp_r insn. */ - if (cfun->machine->is_interrupt) + if (cfun->machine->is_interrupt + || (cfun->machine->is_signal + && cfun->machine->is_noblock)) irq_state = 1; if (TARGET_NO_INTERRUPTS - || cfun->machine->is_signal + || (cfun->machine->is_signal + && ! cfun->machine->is_noblock) || cfun->machine->is_OS_main) irq_state = 0; @@ -2947,7 +2964,8 @@ avr_expand_prologue (void) { int treg = AVR_TMP_REGNO; /* Enable interrupts. */ - if (cfun->machine->is_interrupt) + if (cfun->machine->is_interrupt + || cfun->machine->is_noblock) emit_insn (gen_enable_interrupt ()); if (cfun->machine->gasisr.maybe) @@ -3105,7 +3123,9 @@ avr_asm_function_end_prologue (FILE *file) } else { - if (cfun->machine->is_interrupt) + if (cfun->machine->is_interrupt + || (cfun->machine->is_signal + && cfun->machine->is_noblock)) { fputs ("/* prologue: Interrupt */\n", file); } @@ -11502,6 +11522,7 @@ avr_class_likely_spilled_p (reg_class_t c) After function prologue interrupts remain disabled. interrupt - Make a function to be hardware interrupt. Before function prologue interrupts are enabled by means of SEI. + noblock - The function is an ISR that starts with a SEI instruction. naked - Don't generate function prologue/epilogue and RET instruction. */ @@ -11704,6 +11725,8 @@ TARGET_GNU_ATTRIBUTES (avr_attribute_table, avr_handle_fndecl_attribute, NULL }, { "interrupt", 0, -1, true, false, false, false, avr_handle_fndecl_attribute, NULL }, + { "noblock", 0, 0, true, false, false, false, + avr_handle_fndecl_attribute, NULL }, { "no_gccisr", 0, 0, true, false, false, false, avr_handle_fndecl_attribute, NULL }, { "naked", 0, 0, false, true, true, false, diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index 06984cd82b4..56b7f39b834 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -562,6 +562,10 @@ struct GTY(()) machine_function without argument. */ int is_signal; + /* 'true' - if current function is a non-blocking interrupt service + routine as specified by the "isr_noblock" attribute. */ + int is_noblock; + /* 'true' - if current function is a 'task' function as specified by the "OS_task" attribute. */ int is_OS_task; diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 3936f469d21..36b8c181611 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -5164,6 +5164,16 @@ static void my_pcint0_1_handler (void) Notice that the handler function needs not to be externally visible. +@cindex @code{noblock} function attribute, AVR +@item noblock + +This attribute can be used together with the @code{signal} attribute +to indicate that an interrupt service routine should start with a @code{SEI} +instruction to globally re-enable interrupts. Using attributes @code{signal} +and @code{noblock} together has the same effect like using the @code{interrupt} +attribute. Using the @code{noblock} attribute without @code{signal} has no +effect. + @cindex @code{naked} function attribute, AVR @item naked This attribute allows the compiler to construct the diff --git a/gcc/testsuite/gcc.target/avr/torture/signal_n-1.c b/gcc/testsuite/gcc.target/avr/torture/signal_n-1.c index 0e4c109fe9e..d5f422d2d99 100644 --- a/gcc/testsuite/gcc.target/avr/torture/signal_n-1.c +++ b/gcc/testsuite/gcc.target/avr/torture/signal_n-1.c @@ -13,8 +13,20 @@ static void fun12 (void) __asm ("%~jmp abort" ::: "memory"); } +__attribute__((signal(3),noblock)) +static void fun3 (void) +{ + __asm goto ("brid %x0" ::: "memory" : l_abort); + i += 333; + return; + + l_abort: + __asm ("%~jmp abort" ::: "memory"); +} + extern void isr1 (void) __asm("__vector_1"); extern void isr2 (void) __asm("__vector_2"); +extern void isr3 (void) __asm("__vector_3"); int main (void) { @@ -28,5 +40,10 @@ int main (void) if (i != 2468) __builtin_abort (); + __asm ("cli" ::: "memory"); + isr3(); + if (i != 2468 + 333) + __builtin_abort (); + return 0; } diff --git a/gcc/testsuite/gcc.target/avr/torture/signal_n-3.c b/gcc/testsuite/gcc.target/avr/torture/signal_n-3.c index 379056a110f..55f7d14543d 100644 --- a/gcc/testsuite/gcc.target/avr/torture/signal_n-3.c +++ b/gcc/testsuite/gcc.target/avr/torture/signal_n-3.c @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-additional-options "-Wattributes" } */ __attribute__((signal(0))) static void fun1 (void); /* { dg-error "expects a constant positive integer" } */ @@ -8,3 +9,5 @@ __attribute__((interrupt(-1))) void fun3 (void); /* { dg-error "expects a consta __attribute__((interrupt("2"))) void fun4 (void); /* { dg-error "expects a constant positive integer" } */ +__attribute__((noblock)) void fun5 (void) { } /* { dg-warning "attribute ignored on non-ISR" } */ +