[avr] Add -mno-call-main to tweak running main()
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gcc_check--master-arm |
success
|
Test passed
|
| linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Test passed
|
Commit Message
On devices with very limited resources, it may be desirable to run
main in a more efficient way than provided by the startup code
XCALL main
XJMP exit
from section .init9. In AVR-LibC v2.3, that code has been moved to
libmcu.a, hence symbol __call_main can be satisfied so that the
respective code is no more pulled in from that library.
Instead, main can be run by putting it in section .init9.
The patch adds attributes noreturn and section(".init9"), and
sets __call_main=0 when it encounters main().
Ok for trunk?
Johann
--
AVR: target/118806 - Add -mno-call-main to tweak running main().
On devices with very limited resources, it may be desirable to run
main in a more efficient way than provided by the startup code
XCALL main
XJMP exit
from section .init9. In AVR-LibC v2.3, that code has been moved to
libmcu.a, hence symbol __call_main can be satisfied so that the
respective code is no more pulled in from that library.
Instead, main can be run by putting it in section .init9.
The patch adds attributes noreturn and section(".init9"), and
sets __call_main=0 when it encounters main().
gcc/
PR target/118806
* config/avr/avr.opt (-mcall-main): New option and...
(avropt_call_main): ...variable.
* config/avr/avr.cc (avr_no_call_main_p): New variable.
(avr_insert_attributes) [-mno-call-main, main]: Add attributes
noreturn and section(".init9") to main. Set avr_no_call_main_p.
(avr_file_end) [avr_no_call_main_p]: Define symbol __call_main.
* doc/invoke.texi (AVR Options) <-mno-call-main>: Document.
<-mnodevicelib>: Extend explanation.
Comments
...plus, I updated the documentation: -mno-call-main
asserts that main() does not return.
Johann
index 0aef2abf05b..af41d7b9ad3 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -24457,6 +24457,24 @@ Do not save registers in @code{main}. The
effect is the same like
attaching attribute @ref{AVR Function Attributes,,@code{OS_task}}
to @code{main}. It is activated per default if optimization is on.
+@opindex mno-call-main
+@opindex mcall-main
+@item -mno-call-main
+Don't run @code{main} by means of
+@example
+XCALL main
+XJMP exit
+@end example
+Instead, put @code{main} in section
+@w{@uref{https://avrdudes.github.io/avr-libc/avr-libc-user-manual/mem_sections.html#sec_dot_init,@code{.init9}}}
+so that no call is required.
+By setting this options the user asserts that @code{main} will not return.
+
+This option can be used for devices with very limited resources in order
+to save a few bytes of code and stack space. It will work as expected
since
+@w{@uref{https://github.com/avrdudes/avr-libc/issues/1012,AVR-LibC v2.3}}.
+With older versions, there will be no performance gain.
+
@opindex mno-interrupts
@item -mno-interrupts
Generated code is not compatible with hardware interrupts.
@@ -24535,7 +24553,19 @@ Allow to use truncation instead of rounding
towards zero for fractional fixed-po
@opindex nodevicelib
@item -nodevicelib
-Don't link against AVR-LibC's device specific library
Am 09.02.25 um 11:26 schrieb Georg-Johann Lay:
> On devices with very limited resources, it may be desirable to run
> main in a more efficient way than provided by the startup code
>
> XCALL main
> XJMP exit
>
> from section .init9. In AVR-LibC v2.3, that code has been moved to
> libmcu.a, hence symbol __call_main can be satisfied so that the
> respective code is no more pulled in from that library.
> Instead, main can be run by putting it in section .init9.
>
> The patch adds attributes noreturn and section(".init9"), and
> sets __call_main=0 when it encounters main().
>
> Ok for trunk?
>
> Johann
>
> --
>
> AVR: target/118806 - Add -mno-call-main to tweak running main().
>
> On devices with very limited resources, it may be desirable to run
> main in a more efficient way than provided by the startup code
>
> XCALL main
> XJMP exit
>
> from section .init9. In AVR-LibC v2.3, that code has been moved to
> libmcu.a, hence symbol __call_main can be satisfied so that the
> respective code is no more pulled in from that library.
> Instead, main can be run by putting it in section .init9.
>
> The patch adds attributes noreturn and section(".init9"), and
> sets __call_main=0 when it encounters main().
>
> gcc/
> PR target/118806
> * config/avr/avr.opt (-mcall-main): New option and...
> (avropt_call_main): ...variable.
> * config/avr/avr.cc (avr_no_call_main_p): New variable.
> (avr_insert_attributes) [-mno-call-main, main]: Add attributes
> noreturn and section(".init9") to main. Set avr_no_call_main_p.
> (avr_file_end) [avr_no_call_main_p]: Define symbol __call_main.
> * doc/invoke.texi (AVR Options) <-mno-call-main>: Document.
> <-mnodevicelib>: Extend explanation.
Georg-Johann Lay <avr@gjlay.de> writes:
> On devices with very limited resources, it may be desirable to run
> main in a more efficient way than provided by the startup code
>
> XCALL main
> XJMP exit
>
> from section .init9. In AVR-LibC v2.3, that code has been moved to
> libmcu.a, hence symbol __call_main can be satisfied so that the
> respective code is no more pulled in from that library.
> Instead, main can be run by putting it in section .init9.
>
> The patch adds attributes noreturn and section(".init9"), and
> sets __call_main=0 when it encounters main().
>
> Ok for trunk?
Ok.
Please apply.
Denis
AVR: target/118806 - Add -mno-call-main to tweak running main().
On devices with very limited resources, it may be desirable to run
main in a more efficient way than provided by the startup code
XCALL main
XJMP exit
from section .init9. In AVR-LibC v2.3, that code has been moved to
libmcu.a, hence symbol __call_main can be satisfied so that the
respective code is no more pulled in from that library.
Instead, main can be run by putting it in section .init9.
The patch adds attributes noreturn and section(".init9"), and
sets __call_main=0 when it encounters main().
gcc/
PR target/118806
* config/avr/avr.opt (-mcall-main): New option and...
(avropt_call_main): ...variable.
* config/avr/avr.cc (avr_no_call_main_p): New variable.
(avr_insert_attributes) [-mno-call-main, main]: Add attributes
noreturn and section(".init9") to main. Set avr_no_call_main_p.
(avr_file_end) [avr_no_call_main_p]: Define symbol __call_main.
* doc/invoke.texi (AVR Options) <-mno-call-main>: Document.
<-mnodevicelib>: Extend explanation.
@@ -230,6 +230,9 @@ 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. */
@@ -11712,6 +11715,32 @@ avr_insert_attributes (tree node, tree *attributes)
NULL, *attributes);
}
+#if defined WITH_AVRLIBC
+ if (avropt_call_main == 0
+ && TREE_CODE (node) == FUNCTION_DECL
+ && MAIN_NAME_P (DECL_NAME (node)))
+ {
+ if (lookup_attribute ("section", *attributes))
+ {
+ warning (OPT_Wattributes, "%<section%> attribute on main function"
+ " inhibits %<-mno-call-main%>");
+ }
+ else
+ {
+ if (!lookup_attribute ("noreturn", *attributes))
+ *attributes = tree_cons (get_identifier ("noreturn"),
+ NULL_TREE, *attributes);
+ // Put main into section .init9 so that it is executed even
+ // though it's not called.
+ tree init9 = build_string (1 + strlen (".init9"), ".init9");
+ tree arg = build_tree_list (NULL_TREE, init9);
+ *attributes = tree_cons (get_identifier ("section"),
+ arg, *attributes);
+ avr_no_call_main_p = true;
+ }
+ } // -mno-call-main
+#endif // AVR-LibC
+
avr_handle_isr_attribute (node, attributes, "signal");
avr_handle_isr_attribute (node, attributes, "interrupt");
@@ -12311,6 +12340,15 @@ 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);
}
@@ -42,6 +42,10 @@ mn-flash=
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)
+Call main and exit.
+
mskip-bug
Target Mask(SKIP_BUG)
This option is used internally. Indicate presence of a processor erratum. Do not skip 32-bit instructions.
@@ -908,7 +908,7 @@ Objective-C and Objective-C++ Dialects}.
@gccoptlist{-mmcu=@var{mcu} -mabsdata -maccumulate-args -mcvt
-mbranch-cost=@var{cost} -mfuse-add=@var{level} -mfuse-move=@var{level}
-mcall-prologues -mgas-isr-prologues -mint8 -mflmap
--mdouble=@var{bits} -mlong-double=@var{bits}
+-mdouble=@var{bits} -mlong-double=@var{bits} -mno-call-main
-mn_flash=@var{size} -mfract-convert-truncate -mno-interrupts
-mmain-is-OS_task -mrelax -mrmw -mstrict-X -mtiny-stack
-mrodata-in-ram -msplit-bit-shift -msplit-ldst
@@ -24457,6 +24457,18 @@ Do not save registers in @code{main}. The effect is the same like
attaching attribute @ref{AVR Function Attributes,,@code{OS_task}}
to @code{main}. It is activated per default if optimization is on.
+@opindex mno-call-main
+@opindex mcall-main
+@item -mno-call-main
+Don't call @code{main} and @code{exit}.
+Instead, put @code{main} in section
+@w{@uref{https://avrdudes.github.io/avr-libc/avr-libc-user-manual/mem_sections.html#sec_dot_init,@code{.init9}}}.
+
+This option can be used for devices with very limited resources in order
+to save a few bytes of code and stack space. It will work as expected since
+@w{@uref{https://github.com/avrdudes/avr-libc/issues/1012,AVR-LibC v2.3}}.
+With older versions, there will be no performance gain.
+
@opindex mno-interrupts
@item -mno-interrupts
Generated code is not compatible with hardware interrupts.
@@ -24535,7 +24547,19 @@ Allow to use truncation instead of rounding towards zero for fractional fixed-po
@opindex nodevicelib
@item -nodevicelib
-Don't link against AVR-LibC's device specific library @code{lib<mcu>.a}.
+Don't link against AVR-LibC's device specific library @code{lib@var{mcu}.a}.
+
+Notice that since AVR-LibC v2.3, that library contains code that is
+essential for the correct functioning of a program. In particular,
+it contains parts of the startup code like:
+@w{@uref{https://github.com/avrdudes/avr-libc/issues/1011,@code{__init_sp}}}
+to initialize the stack pointer with symbol @code{__stack},
+@w{@uref{https://github.com/avrdudes/avr-libc/issues/1010,@code{__init_cvt}}}
+to set up the hardware to use a compact vector table with @option{-mcvt},
+@w{@uref{https://github.com/avrdudes/avr-libc/issues/1012,@code{__call_main}}}
+to call @code{main} and @code{exit}, and
+@w{@uref{https://github.com/avrdudes/avr-libc/issues/931,@code{__do_flmap_init}}}
+to set up FLMAP according to symbol @code{__flmap}.
@opindex nodevicespecs
@item -nodevicespecs