https://gcc.gnu.org/g:51cf758d720fe55e71484fcfc62e11981b4883ad
commit r15-11156-g51cf758d720fe55e71484fcfc62e11981b4883ad Author: Georg-Johann Lay <[email protected]> Date: Thu May 14 10:21:28 2026 +0200 AVR: target/125194 - Make -mno-call-main work with -flto. Instead of emitting .global __call_main + __call_main=0 in some module, it uses a %{mno-call-main: --defsym __call_main=0} spec. The problem with the old implementation is that avr_no_call_main_p was set by cc1[plus] (in avr_insert_attributes) but used by lto1 (in avr_file_end). The new approach uses --defsym __call_main=0 in order to avoid link fails due to multiple definitions of __call_main in *.o and lib<mcu>.a. PR target/125194 gcc/ * config/avr/avr.cc (avr_no_call_main_p): Remove variable... (avr_file_end): ...and code that uses it. (avr_insert_attributes): Same. Add "used" to main attributes when -mno-call-main. * config/avr/gen-avr-mmcu-specs.cc (print_mcu): Emit code for link_no_call_main specs. * config/avr/specs.h (LINK_SPEC): Add %(link_no_call_main). (cherry picked from commit 701c41191413fdcfeea33b8f49cfebf62b8a6135) Diff: --- gcc/config/avr/avr.cc | 16 +++------------- gcc/config/avr/gen-avr-mmcu-specs.cc | 2 ++ gcc/config/avr/specs.h | 1 + 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 16da67325c56..fb0e8292fef1 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -230,9 +230,6 @@ bool avr_need_clear_bss_p = false; bool avr_need_copy_data_p = false; bool avr_has_rodata_p = false; -/* To track if we satisfy __call_main from AVR-LibC. */ -bool avr_no_call_main_p = false; - /* Counts how often pass avr-fuse-add has been executed. Is is kept in sync with cfun->machine->n_avr_fuse_add_executed and serves as an insn condition for shift insn splitters. */ @@ -11889,7 +11886,9 @@ avr_insert_attributes (tree node, tree *attributes) *attributes = tree_cons (get_identifier ("section"), arg, *attributes); } - avr_no_call_main_p = true; + if (!lookup_attribute ("used", *attributes)) + *attributes = tree_cons (get_identifier ("used"), + NULL_TREE, *attributes); } } // -mno-call-main #endif // AVR-LibC @@ -12493,15 +12492,6 @@ avr_file_end (void) if (avr_need_clear_bss_p) fputs (".global __do_clear_bss\n", asm_out_file); - - /* Don't let __call_main call main() and exit(). - Defining this symbol will keep the code from being pulled - in from lib<mcu>.a as requested by AVR-LibC's gcrt1.S. - We invoke main() by other means: putting it in .init9. */ - - if (avr_no_call_main_p) - fputs (".global __call_main\n" - "__call_main = 0\n", asm_out_file); } diff --git a/gcc/config/avr/gen-avr-mmcu-specs.cc b/gcc/config/avr/gen-avr-mmcu-specs.cc index 05f2d0e1d4ac..cf318ea640b7 100644 --- a/gcc/config/avr/gen-avr-mmcu-specs.cc +++ b/gcc/config/avr/gen-avr-mmcu-specs.cc @@ -355,6 +355,8 @@ print_mcu (const avr_mcu_t *mcu, const McuInfo &mi) fprintf (f, "*link_relax:\n\t%s\n\n", LINK_RELAX_SPEC); + fprintf (f, "*link_no_call_main:\n\t%s\n\n", "%{mno-call-main: --defsym __call_main=0}"); + fprintf (f, "*link_arch:\n\t%s", link_arch_spec); if (mi.is_device && rodata_pm_offset) diff --git a/gcc/config/avr/specs.h b/gcc/config/avr/specs.h index c95c75856cb0..38e3e502b65b 100644 --- a/gcc/config/avr/specs.h +++ b/gcc/config/avr/specs.h @@ -67,6 +67,7 @@ along with GCC; see the file COPYING3. If not see "%(link_relax) " \ "%(link_pmem_wrap) " \ "%(link_rodata_in_ram) " \ + "%(link_no_call_main) " \ "%{shared:%eshared is not supported} " #undef LIB_SPEC
