Re: lto: from insert_attributes to file_end?

Georg-Johann Lay via Gcc <[email protected]>
Newsgroups gmane.comp.gcc.devel
Message-ID <[email protected]>
Am 06.05.26 um 09:51 schrieb Richard Biener:
> On Tue, May 5, 2026 at 8:16 PM Georg-Johann Lay <[email protected]> wrote:
>> Am 05.05.26 um 19:05 schrieb Richard Biener:
>>> On Tue, May 5, 2026 at 5:41 PM Georg-Johann Lay via Gcc <[email protected]> wrote:
>>>>
>>>> In the avr backend there is a static variable avr_no_call_main_p that
>>>> is set in TARGET_INSERT_ATTRIBUTES and used in TARGET_ASM_FILE_END.
>>>>
>>>> This works as expected in non-LTO compilations, with LTO however,
>>>> TARGET_INSERT_ATTRIBUTES runs in cc1[plus] but TARGET_ASM_FILE_END
>>>> is run by lto1, hence the variable is not set as expected.
>>>>
>>>> What's the recommended way to handle such a situation?
>>>
>>> Without looking too closely I assume there's an actual attribute somewhere
>>> (on the main function decl?).  Instead of using a global variable you'd
>>> check for the presence of the attribute.  Now - the question is whether
>>> the TARGET_ASM_FILE_END behavior is only required in the TU with
>>> the main() definition?  In that case this should work.
>>
>> What works is to attach a new attribute to main when the conditions are
>> right, then check for that attribute in, say,
>> TARGET_DECLARE_FUNCTION_NAME and set a variable accordingly, and then
>> check for that var in TARGET_ASM_FILE_END.
> 
> It's not technically required to be handled from TARGET_ASM_FILE_END,
> correct?

Exactly.  Background: main is called by __call_main which is provided
by some default lib*.a.  It is referenced by crt*.o to pull it in.

With -mno-call-main, main is effectively a part of the startup-code.
The application emits
    .global __call_main
    __call_main = 0
so __call_main it is no more pulled in since it is no more needed.

 > It should work to emit the symbol from ASM_OUTPUT_FUNCTION_LABEL?> 
(not sure if there's sth more appropriate for 'before function' or
> 'after function')  You'd at least have access to the functions decl there.

Using a new attribute and emit .global __call_main + __call_main=0 in
ASM_OUTPUT_FUNCTION_LABEL (or TARGET_ASM_FILE END) generates code as
expected, however I am getting an error from the linker because
__call_main is defined in lib*.a and also in some app module.

What works fine is adding  %{mno-call-main: --defsym __call_main=0}
to the link specs, and skip messing with __call_main in avr.cc
altogether.  See attached delta.

When the user sets -mcall-main as well as -mno-call-main in the same
app, then it's fine for me it that doesn't work.

Johann

>> What's a bit ugly is that it requires a new target attribute that's only
>> for internal usage and should not to be set by the user.  Maybe not
>> document it is okay then.
> 
> As Sam says, an attribute with a space cannot be used by users.  Like
> "avr no_call_main".
> 
> But also see the PR iff the only way for the user to get the behavior
> with -mno-call-main
pr125194-v2.diff (text/x-patch, 2.9 KB)
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index b0e9d9000e..25cb518b0f 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/avr.opt b/gcc/config/avr/avr.opt
index 8bc2f5f173..56264ee6d1 100644
--- a/gcc/config/avr/avr.opt
+++ b/gcc/config/avr/avr.opt
@@ -39,7 +39,7 @@ Target RejectNegative Joined Var(avropt_n_flash) UInteger Init(-1)
 This option is used internally. Set the number of 64 KiB flash segments.
 
 mcall-main
-Target Var(avropt_call_main) UInteger Init(1)
+Target Var(avropt_call_main) UInteger Init(1) Save
 Call main and exit (default).
 
 mskip-bug
diff --git a/gcc/config/avr/gen-avr-mmcu-specs.cc b/gcc/config/avr/gen-avr-mmcu-specs.cc
index 42623d7e87..470d40538e 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 4f71f8a657..1fca4a1d6e 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.