Am 11.05.26 um 08:09 schrieb Richard Biener:
On Fri, May 8, 2026 at 4:56 PM Georg-Johann Lay <[email protected]> wrote:
Am 08.05.26 um 11:53 schrieb Richard Biener:
On Thu, May 7, 2026 at 2:36 PM Georg-Johann Lay <[email protected]> wrote:

This patch fixes -mno-call-main which did not work with LTO.

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.

In the patch the avr.opt and the avr_insert_attributes hunk shouldn't
be necessary?

The avr.opt change is according to
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125194#c1

Some avr_insert_attributes hunk is needed because avr_no_call_main_p
has been removed, since it is no more needed.

And I added "used" to main because otherwise, LTO optimized out main.

That said, even w/o the patch the LTRANS invocations with -flto
should see -mno-call-main, but avr_insert_attributes might not
be called at LTO time.

That's not a problem imho.  The hook just adds section(".init9")
and used, and they will survive as attributes.

So if in avr_file_end you check
avropt_call_main instead of avr_no_call_main_p you should
get the .global emitted.  Of course in every LTRANS object,
but I suppose the linker should merge multiple defs?

Like mentioned, I am getting multiple symbol definitions error
from ld when emitting .global __call_main=0.  Therefore, I
switched to --defsym __call_main=0 which works fine.

OK.  Another solution might have been to make the symbol
weak?

I've tried that before, and it doesn't work:

When a C module does .weak __call_main, then it will be
overridden by the .global __call_main in libmcu.a.
When libmcu.a has a .weak __call_main, then ld won't pull
in the associated code because crtmcu.o references it
per .global __call_main.  And .weak __call_main in
crtmcu.o doesn't work for obvious reasons.

I applied the version that does --defsym __call_main=0 which
works in all situations, including when the user already has
a --defsym __call_main=0, e.g. as a work-around for PR125194.

Having a testcase in the testsuite would be nice btw.

Richard.

Johann

This is for trunk.  If you agree, I would also packport it.

Johann

--

AVR: target/125194 - Make -mno-call-main work with -flto.

Instead of emitting  .global __call_main + __call_main=0  in some module,
use 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/avr.opt (-mcall-main): Add Save option flag.
          * 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).


Reply via email to