https://gcc.gnu.org/g:30e1fbb1cc71bb0662095e868febeaea79d50064

commit r16-8912-g30e1fbb1cc71bb0662095e868febeaea79d50064
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 b0e9d9000e43..25cb518b0f3e 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -249,9 +249,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.  */
@@ -11906,7 +11903,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
@@ -12467,15 +12466,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 42623d7e87c9..470d40538e53 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 4f71f8a6570f..1fca4a1d6eec 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

Reply via email to