I added support for reduced code size printf and puts functions to Newlib for MSP430 a while ago [1]. By removing support for reentrancy, streams and buffering we can greatly reduce code size, which is always often a limitation when using printf on microcontrollers.
This patch adds an interface to enable these reduced code size implementations from GCC by using the -mtiny-printf option. The tiny printf and puts implementations require GCC to be configured with --enable-newlib-nano-formatted-io, so there are some modifications to configure scripts to support the checking of that. -mtiny-printf is merely an alias for passing "--wrap printf --wrap puts" to the linker. This will replace references to "printf" and "puts" in user code with "__wrap_printf" and "__wrap_puts" respectively. If there is no implementation of these __wrap* functions in user code, these "tiny" printf and puts implementations will be linked into the final executable. The wrapping mechanism is supposed to be invisible to the user since even if they are unaware of the "tiny" implementation, and implement their own __wrap_printf and __wrap_puts, their own implementation will be automatically chosen over the "tiny" printf and puts from the library. Successfully regtested on trunk by comparing results with -mtiny-printf with a set of testresults without the option. The new test "gcc.target/msp430/tiny-printf.c" verifies the option behaves as expected when GCC is configured with and without --enable-newlib-nano-formatted-io. Ok to apply? [1] https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=commit;h=1e6c561d48f
>From 4d4e2b6bb92317b2b4db1d99c3f43a167a1e3288 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz <joze...@mittosystems.com> Date: Thu, 24 Oct 2019 13:30:21 +0100 Subject: [PATCH] MSP430: Add -mtiny-printf option gcc/ChangeLog: 2019-10-24 Jozef Lawrynowicz <joze...@mittosystems.com> * config.in: Regenerate. * config/msp430/msp430.c (msp430_option_override): Emit an error if -mtiny-printf is used without GCC being configured with --enable-newlib-nano-formatted-io. * config/msp430/msp430.h (LINK_SPEC): Pass "--wrap puts --wrap printf" when -mtiny-printf is used. * config/msp430/msp430.opt: Document -mtiny-printf. * configure: Regenerate. * configure.ac: Enable --enable-newlib-nano-formatted-io flag. Define HAVE_NEWLIB_NANO_FORMATTED_IO if --enable-newlib-nano-formatted-io is passed. * doc/invoke.texi: Document -mtiny-printf. gcc/testsuite/ChangeLog: 2019-10-24 Jozef Lawrynowicz <joze...@mittosystems.com> * gcc.target/msp430/tiny-printf.c: New test. --- gcc/config.in | 7 ++++++ gcc/config/msp430/msp430.c | 6 +++++ gcc/config/msp430/msp430.h | 1 + gcc/config/msp430/msp430.opt | 4 +++ gcc/configure | 25 +++++++++++++++++-- gcc/configure.ac | 16 ++++++++++++ gcc/doc/invoke.texi | 15 ++++++++++- gcc/testsuite/gcc.target/msp430/tiny-printf.c | 3 +++ 8 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.target/msp430/tiny-printf.c diff --git a/gcc/config.in b/gcc/config.in index 9b54a4715db..7925d892cce 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -1675,6 +1675,13 @@ #endif +/* Define if GCC has been configured with --enable-newlib-nano-formatted-io. + */ +#ifndef USED_FOR_TARGET +#undef HAVE_NEWLIB_NANO_FORMATTED_IO +#endif + + /* Define to 1 if you have the `nl_langinfo' function. */ #ifndef USED_FOR_TARGET #undef HAVE_NL_LANGINFO diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c index 31029395c3d..dbbff4a6863 100644 --- a/gcc/config/msp430/msp430.c +++ b/gcc/config/msp430/msp430.c @@ -284,6 +284,12 @@ msp430_option_override (void) possible to build newlib with -Os enabled. Until now... */ if (TARGET_OPT_SPACE && optimize < 3) optimize_size = 1; + +#ifndef HAVE_NEWLIB_NANO_FORMATTED_IO + if (TARGET_TINY_PRINTF) + error ("GCC must be configured with %<--enable-newlib-nano-formatted-io%> " + "to use %<-mtiny-printf%>"); +#endif } #undef TARGET_SCALAR_MODE_SUPPORTED_P diff --git a/gcc/config/msp430/msp430.h b/gcc/config/msp430/msp430.h index 73afe2e2d16..4a89f03a35e 100644 --- a/gcc/config/msp430/msp430.h +++ b/gcc/config/msp430/msp430.h @@ -75,6 +75,7 @@ extern bool msp430x; "msp430_propagate_region_opt(%* %{muse-lower-region-prefix})} " \ "%{mdata-region=*:--data-region=%:" \ "msp430_propagate_region_opt(%* %{muse-lower-region-prefix})} " \ + "%{mtiny-printf:--wrap puts --wrap printf} " #define DRIVER_SELF_SPECS \ " %{!mlarge:%{mcode-region=*:%{mdata-region=*:%e-mcode-region and " \ diff --git a/gcc/config/msp430/msp430.opt b/gcc/config/msp430/msp430.opt index 2db2906ca11..b451174c3d1 100644 --- a/gcc/config/msp430/msp430.opt +++ b/gcc/config/msp430/msp430.opt @@ -2,6 +2,10 @@ msim Target Use simulator runtime. +mtiny-printf +Target Report Mask(TINY_PRINTF) +Use a lightweight configuration of printf and puts to reduce code size. For single-threaded applications, not requiring reentrant I/O only. Requires Newlib Nano IO. + masm-hex Target Mask(ASM_HEX) Force assembly output to always use hex constants. diff --git a/gcc/configure b/gcc/configure index 9de9ef85f24..29e3074dc48 100755 --- a/gcc/configure +++ b/gcc/configure @@ -988,6 +988,7 @@ with_plugin_ld enable_gnu_indirect_function enable_initfini_array enable_comdat +enable_newlib_nano_formatted_io enable_standard_branch_protection enable_fix_cortex_a53_835769 enable_fix_cortex_a53_843419 @@ -1716,6 +1717,8 @@ Optional Features: glibc systems --enable-initfini-array use .init_array/.fini_array sections --enable-comdat enable COMDAT group support + --enable-newlib-nano-formatted-io + Use nano version formatted IO --enable-standard-branch-protection enable Branch Target Identification Mechanism and @@ -18851,7 +18854,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18854 "configure" +#line 18857 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -18957,7 +18960,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18960 "configure" +#line 18963 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -24477,6 +24480,19 @@ $as_echo "#define HAVE_GAS_DISCRIMINATOR 1" >>confdefs.h fi +# Catch the newlib flag of the same name so we can gate GCC features on it. +# Check whether --enable-newlib-nano-formatted-io was given. +if test "${enable_newlib_nano_formatted_io+set}" = set; then : + enableval=$enable_newlib_nano_formatted_io; case "${enableval}" in + yes|no) + ;; + *) + as_fn_error $? "unknown newlib-nano-formatted-io setting $enableval" "$LINENO" 5 + ;; +esac +fi + + # Thread-local storage - the check is heavily parameterized. conftest_s= tls_first_major= @@ -27867,6 +27883,11 @@ $as_echo "#define HAVE_AS_MSPABI_ATTRIBUTE 1" >>confdefs.h fi + if test x$enable_newlib_nano_formatted_io = xyes; then + +$as_echo "#define HAVE_NEWLIB_NANO_FORMATTED_IO 1" >>confdefs.h + + fi ;; riscv*-*-*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .attribute support" >&5 diff --git a/gcc/configure.ac b/gcc/configure.ac index 62f4b2651cc..9a7e95ea504 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -3336,6 +3336,18 @@ gcc_GAS_CHECK_FEATURE([line table discriminator support], [AC_DEFINE(HAVE_GAS_DISCRIMINATOR, 1, [Define if your assembler supports the .loc discriminator sub-directive.])]) +# Catch the newlib flag of the same name so we can gate GCC features on it. +AC_ARG_ENABLE(newlib-nano-formatted-io, +[AS_HELP_STRING([--enable-newlib-nano-formatted-io], [Use nano version + formatted IO])], +[case "${enableval}" in + yes|no) + ;; + *) + AC_MSG_ERROR([unknown newlib-nano-formatted-io setting $enableval]) + ;; +esac], []) + # Thread-local storage - the check is heavily parameterized. conftest_s= tls_first_major= @@ -4976,6 +4988,10 @@ pointers into PC-relative form.]) [.mspabi_attribute 4,1],, [AC_DEFINE(HAVE_AS_MSPABI_ATTRIBUTE, 1, [Define if your assembler supports .mspabi_attribute.])]) + if test x$enable_newlib_nano_formatted_io = xyes; then + AC_DEFINE(HAVE_NEWLIB_NANO_FORMATTED_IO, 1, [Define if GCC has been +configured with --enable-newlib-nano-formatted-io.]) + fi ;; riscv*-*-*) gcc_GAS_CHECK_FEATURE([.attribute support], diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 1407d019d14..6e55738322f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1009,7 +1009,7 @@ Objective-C and Objective-C++ Dialects}. -mwarn-mcu @gol -mcode-region= -mdata-region= @gol -msilicon-errata= -msilicon-errata-warn= @gol --mhwmult= -minrt} +-mhwmult= -minrt -mtiny-printf} @emph{NDS32 Options} @gccoptlist{-mbig-endian -mlittle-endian @gol @@ -23267,6 +23267,19 @@ initializers or constructors. This is intended for memory-constrained devices. The compiler includes special symbols in some objects that tell the linker and runtime which code fragments are required. +@item -mtiny-printf +@opindex mtiny-printf +Enable reduced code size @code{printf} and @code{puts} library functions. +The @samp{tiny} implementations of these functions are not reentrant, so +must be used with caution in multi-threaded applications. + +Support for streams has been removed and the string to be printed will +always be sent to stdout via the @code{write} syscall. The string is not +buffered before it is sent to write. + +This option requires Newlib Nano IO, so GCC must be configured with +@samp{--enable-newlib-nano-formatted-io}. + @item -mcode-region= @itemx -mdata-region= @opindex mcode-region diff --git a/gcc/testsuite/gcc.target/msp430/tiny-printf.c b/gcc/testsuite/gcc.target/msp430/tiny-printf.c new file mode 100644 index 00000000000..55ef5f76ca4 --- /dev/null +++ b/gcc/testsuite/gcc.target/msp430/tiny-printf.c @@ -0,0 +1,3 @@ +/* { dg-do compile } */ +/* { dg-options "-mtiny-printf" } */ +/* { dg-error "GCC must be configured with --enable-newlib-nano-formatted-io to use -mtiny-printf" "" { target { ! newlib_nano_io } } 0 } */ -- 2.17.1