https://gcc.gnu.org/g:72274d0a421785ed38ad704af1192a7578660e7f

commit r16-6489-g72274d0a421785ed38ad704af1192a7578660e7f
Author: Keith Packard <[email protected]>
Date:   Sun Jan 4 11:56:24 2026 -0700

    [PATCH] Add support for using picolibc
    
    Selected for *-picolibc-* targets or when --with-picolibc is
    passed to configure.
    
    Add custom options for use with picolibc:
    
     * '--oslib='. Allows targets to insert an OS library after the C
       library in the LIB_PATH spec file fragment. This library maps a few
       POSIX APIs used by picolibc to underlying system capabilities.
    
     * '--crt0='. Allows targets to use an alternate crt0 in place of the
       usual one as provided by Picolibc. Picolibc provides a range of
       crt0 versions which this can be used to select among.
    
     * '--printf=' and '--scanf='. Allows targets to customize the version
       of printf and scanf linked from the C library.
    
    Adds some new preprocessor variables allowing the C library to adjust
    the specfile generation process without affecting target changes:
    
     * LIBC_CPP_SPEC. A specfile fragment appended to cpp_spec. Picolibc
       uses this to add preprocessor definitions when the --printf and
       --scanf options are provided so that applications can detect the
       available printf and scanf versions.
    
     * LIBC_LINK_SPEC. A specfile fragment appended to link_spec. Picolibc
       uses this to implement the --printf and --scanf options, passing
       suitable --defsym options to the linker.
    
    Documents the new driver options and target macros.
    
    gcc/
            * config.gcc: Add clause for picolibc.
            * config/picolibc-spec.h: New file.
            * config/picolibc.opt: Likewise.
            * config/picolibc.opt.urls: Likewise.
            * configure.ac: Add support for --with-picolibc.
            * configure: Rebuilt.
            * doc/invoke.texi: Document picolibc options.
            * doc/tm.texi.in (LIBC_CPP_SPEC): Document.
            (LIBC_LINK_SPEC): Similarly.
            * doc/tm.texi: Rebuilt.
            * gcc.cc (LIBC_CPP_SPEC): Provide default definition.
            (LIBC_LINK_SPEC): Likewise.
            (cpp_spec): Include LIBC_CPP_SPEC.
            (link_spec): Similarly for LIBC_LINK_SPEC.
    
    Signed-off-by: Keith Packard <[email protected]>

Diff:
---
 gcc/config.gcc               | 18 ++++++++++++
 gcc/config/picolibc-spec.h   | 57 ++++++++++++++++++++++++++++++++++++
 gcc/config/picolibc.opt      | 47 ++++++++++++++++++++++++++++++
 gcc/config/picolibc.opt.urls |  2 ++
 gcc/configure                | 24 ++++++++++-----
 gcc/configure.ac             |  3 ++
 gcc/doc/invoke.texi          | 69 ++++++++++++++++++++++++++++++++++++++++++++
 gcc/doc/tm.texi              | 16 ++++++++++
 gcc/doc/tm.texi.in           | 16 ++++++++++
 gcc/gcc.cc                   | 17 +++++++++--
 10 files changed, 260 insertions(+), 9 deletions(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 939ed109c744..b2a48c02d3be 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -3697,6 +3697,24 @@ case ${target} in
        ;;
 esac
 
+# picolibc systems
+case "${target}_${with_picolibc}" in
+*-picolibc-*|*_yes)
+       default_use_cxa_atexit=yes
+       use_gcc_stdint=none
+       # add newlib-stdint.h if not already present
+       case "${tm_file}" in
+       *newlib-stdint.h*)
+               ;;
+       *)
+               tm_file="${tm_file} newlib-stdint.h"
+               ;;
+       esac
+       tm_file="${tm_file} picolibc-spec.h"
+       extra_options="${extra_options} picolibc.opt"
+       ;;
+esac
+
 # Assume the existence of indirect function support and allow the use of the
 # resolver attribute.
 case ${target} in
diff --git a/gcc/config/picolibc-spec.h b/gcc/config/picolibc-spec.h
new file mode 100644
index 000000000000..d1024ced3e7f
--- /dev/null
+++ b/gcc/config/picolibc-spec.h
@@ -0,0 +1,57 @@
+/* Configuration common to all targets running Picolibc.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define PICOLIBC_LD "picolibc.ld"
+
+/* Default to local-exec TLS model.  */
+#undef OS_CC1_SPEC
+#define OS_CC1_SPEC " %{!ftls-model=*:-ftls-model=local-exec}"
+
+/* Pass along preprocessor definitions when --printf or --scanf are specified 
*/
+#define LIBC_CPP_SPEC                          \
+  " %{-printf=*: -D_PICOLIBC_PRINTF='%*'}"     \
+  " %{-scanf=*: -D_PICOLIBC_SCANF='%*'}"
+
+/*
+ * Add picolibc.ld if not using -shared, -r or -T and we can find it.
+ * Define vfprintf if --printf is set
+ * Define vfscanf if --scanf is set
+ */
+#define LIBC_LINK_SPEC                                                 \
+  " %{!shared:%{!r:%{!T*: %:if-exists-then-else(%:find-file(" PICOLIBC_LD ") 
-T" PICOLIBC_LD ")}}}" \
+  " %{-printf=*:--defsym=" USER_LABEL_PREFIX "vfprintf=" USER_LABEL_PREFIX 
"__%*_vfprintf}" \
+  " %{-scanf=*:--defsym=" USER_LABEL_PREFIX "vfscanf=" USER_LABEL_PREFIX 
"__%*_vfscanf}"
+
+/*
+ * Place the C library, libgcc and any oslib in a link group to resolve
+ * interdependencies
+ */
+#undef LIB_SPEC
+#define LIB_SPEC "--start-group -lc %{-oslib=*:-l%*} %(libgcc) --end-group"
+
+/* Select alternate crt0 version if --crt0 is specified */
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC "%{-crt0=*:crt0-%*%O%s; :crt0%O%s}"
+
+#define EH_TABLES_CAN_BE_READ_ONLY 1
diff --git a/gcc/config/picolibc.opt b/gcc/config/picolibc.opt
new file mode 100644
index 000000000000..e68e5d00016d
--- /dev/null
+++ b/gcc/config/picolibc.opt
@@ -0,0 +1,47 @@
+; Processor-independent options for picolibc.
+;
+; Copyright (C) 2026 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 3, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+-oslib
+Driver Separate Alias(-oslib=)
+
+-oslib=
+Driver Joined
+Specify an OS support library to load after libc.
+
+-crt0
+Driver Separate Alias(-crt0=)
+
+-crt0=
+Driver Joined
+Specify an alternate startup file.
+
+-printf
+Driver Separate Alias(-printf=)
+
+-printf=
+Driver Joined
+Specify the printf version linked from libc.
+
+-scanf
+Driver Separate Alias(-scanf=)
+
+-scanf=
+Driver Joined
+Specify the scanf version linked from libc.
diff --git a/gcc/config/picolibc.opt.urls b/gcc/config/picolibc.opt.urls
new file mode 100644
index 000000000000..b3a57d15a396
--- /dev/null
+++ b/gcc/config/picolibc.opt.urls
@@ -0,0 +1,2 @@
+; Autogenerated by regenerate-opt-urls.py from gcc/config/picolibc.opt and 
generated HTML
+
diff --git a/gcc/configure b/gcc/configure
index 826ac310949f..c975d59a7b20 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -1006,6 +1006,7 @@ with_changes_root_url
 enable_languages
 with_multilib_list
 with_multilib_generator
+with_picolibc
 with_zstd
 with_zstd_include
 with_zstd_lib
@@ -1896,6 +1897,8 @@ Optional Packages:
                           RISC-V, SH and x86-64 only)
   --with-multilib-generator
                           Multi-libs configuration string (RISC-V only)
+  --with-picolibc         Support for picolibc, including command line options
+                          and spec rules
   --with-zstd=PATH        specify prefix directory for installed zstd library.
                           Equivalent to --with-zstd-include=PATH/include plus
                           --with-zstd-lib=PATH/lib
@@ -6291,7 +6294,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -6337,7 +6340,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -6361,7 +6364,7 @@ rm -f core conftest.err conftest.$ac_objext 
conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -6406,7 +6409,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -6430,7 +6433,7 @@ rm -f core conftest.err conftest.$ac_objext 
conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -8405,6 +8408,13 @@ else
 fi
 
 
+
+# Check whether --with-picolibc was given.
+if test "${with_picolibc+set}" = set; then :
+  withval=$with_picolibc;
+fi
+
+
 # -------------------------
 # Checks for other programs
 # -------------------------
@@ -21925,7 +21935,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 21928 "configure"
+#line 21938 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -22031,7 +22041,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 22034 "configure"
+#line 22044 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 9ad611b925bc..458f5c990287 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1221,6 +1221,9 @@ AC_ARG_WITH(multilib-generator,
 :,
 with_multilib_generator=default)
 
+AC_ARG_WITH(picolibc,
+[AS_HELP_STRING([--with-picolibc], [Support for picolibc, including command 
line options and spec rules])])
+
 # -------------------------
 # Checks for other programs
 # -------------------------
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index a25b43b3e85c..79107f2dbcd8 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -164,6 +164,7 @@ listing and explanation of the binary and decimal byte size 
prefixes.
 * Link Options::        Specifying libraries and so on.
 * Directory Options::   Where to find header files and libraries.
                         Where to find the compiler executable files.
+* Picolibc Options::    Select compile and link options when using picolibc.
 * Code Gen Options::    Specifying conventions for function calls, data layout
                         and register usage.
 * Developer Options::   Printing GCC configuration info, statistics, and
@@ -803,6 +804,11 @@ Objective-C and Objective-C++ Dialects}.
 --no-canonical-prefixes  --no-standard-includes
 --prefix=@var{prefix}  --sysroot=@var{dir}}
 
+@item Picolibc Options
+@xref{Picolibc Options,,Options for use with Picolibc}.
+@gccoptlist{--oslib=@var{library} 
--crt0=@r{[}none@r{|}minimal@r{|}hosted@r{|}semihost@r{]}
+--printf=@r{[}d@r{|}f@r{|}l@r{|}i@r{|}m@r{]} 
--scanf=@r{[}d@r{|}f@r{|}l@r{|}i@r{|}m@r{]}}
+
 @item Code Generation Options
 @xref{Code Gen Options,,Options for Code Generation Conventions}.
 @gccoptlist{-fcall-saved-@var{reg}  -fcall-used-@var{reg}
@@ -20264,6 +20270,69 @@ such a suffix.
 
 @end table
 
+@node Picolibc Options
+@section Options for use with Picolibc
+@cindex picolibc options
+@cindex options, picolibc
+
+These options control compilation and linking when using picolibc:
+
+@table @gcctabopt
+@opindex oslib
+@item --oslib=@var{library}
+Search the library named @var{library} after the C library, permitting
+symbols undefined by the C library to be defined by this library. The
+C library, libgcc and this library are placed between
+@option{--start-group} and @option{--end-group} flags so that each can
+refer to symbols in the others. For many targets, picolibc provides a
+@samp{semihost} variant (specified with @option{--oslib=semihost})
+which provides enough basic OS functionality to support console and
+file I/O when run in an emulator or when using an in-circuit debugger.
+
+@opindex crt0
+@item --crt0=@r{[}none@r{|}minimal@r{|}hosted@r{|}semihost@r{]}
+Replace the default @file{crt0.o} name with
+@file{crt0-@var{variant}.o}. The @samp{none} variant provides no
+startup code at all, allowing the user to supply their
+own. @samp{minimal} performs basic memory setup but does not invoke
+any constructors. When no @option{-crt0} option is provided, the
+default initialization code adds calls to all
+constructors. @samp{hosted} adds a call to @code{exit} when
+@code{main} returns. @samp{semihost} accesses a command line parameter
+supplied via the semihosting interface and splits that into arguments
+at whitespace boundaries, passing the resulting array of strings to
+main in @code{argc} and @code{argv}. On some targets, including
+aarch64, arc, arm, loongarch, m68k, riscv, super-h and x86,
+@samp{semihost} also traps hardware exceptions and prints information
+to the console. Note that @option{--crt0=semihost} depends upon APIs
+provided by @option{--oslib=semihost}.
+
+@opindex printf
+@item --printf=@r{[}d@r{|}f@r{|}l@r{|}i@r{|}m@r{]}
+Select the printf variant. Picolibc provides five different printf
+variants which offer decreasing levels of functionality along with
+decreasing code size. @samp{d} is the default level, offering full C17
+and POSIX.1-2024 conformance. @samp{f} provides the same feature set,
+but supports @code{float} values instead of @code{double} which are
+passed using the @code{printf_float} macro. @samp{l} elides all
+floating point and POSIX positional parameter support. @samp{i} limits
+integers to those no larger than @code{long}. @samp{m} removes support
+for most formatting options including width and precision. The formats
+and arguments are still parsed correctly, but output does not respect
+those parameters.
+
+@opindex scanf
+@item --scanf=@r{[}d@r{|}f@r{|}l@r{|}i@r{|}m@r{]}
+Select the scanf variant. Picolibc provides five different scanf
+variants which offer decreasing levels of functionality along with
+decreasing code size. @samp{d} is the default level, offering full C17
+and POSIX.1-2024 conformance. @samp{f} removes support for
+@code{double} values. @samp{l} elides all floating point
+support. @samp{i} limits integers to those no larger than
+@code{long}. @samp{m} removes support for @code{%[} conversion specifiers.
+
+@end table
+
 @node Code Gen Options
 @section Options for Code Generation Conventions
 @cindex code generation conventions
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 19b8907c0d7c..4a6aa7bfa4d0 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -188,6 +188,14 @@ give to GCC into options for GCC to pass to the CPP@.
 Do not define this macro if it does not need to do anything.
 @end defmac
 
+@defmac LIBC_CPP_SPEC
+A C string constant which is appended to the value of
+@code{CPP_SPEC}. @code{LIBC_CPP_SPEC} is intended to depend upon the
+C library in use.
+
+Do not define this macro if it does not need to do anything.
+@end defmac
+
 @defmac CPLUSPLUS_CPP_SPEC
 This macro is just like @code{CPP_SPEC}, but is used for C++, rather
 than C@.  If you do not define this macro, then the value of
@@ -254,6 +262,14 @@ give to GCC into options for GCC to pass to the linker.
 Do not define this macro if it does not need to do anything.
 @end defmac
 
+@defmac LIBC_LINK_SPEC
+A C string constant which is appended to the value of
+@code{LINK_SPEC}. @code{LIBC_LINK_SPEC} is intended to depend upon the
+C library in use.
+
+Do not define this macro if it does not need to do anything.
+@end defmac
+
 @defmac LIB_SPEC
 Another C string constant used much like @code{LINK_SPEC}.  The difference
 between the two is that @code{LIB_SPEC} is used at the end of the
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index b755ee1f6d4c..274bb899d0cb 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -188,6 +188,14 @@ give to GCC into options for GCC to pass to the CPP@.
 Do not define this macro if it does not need to do anything.
 @end defmac
 
+@defmac LIBC_CPP_SPEC
+A C string constant which is appended to the value of
+@code{CPP_SPEC}. @code{LIBC_CPP_SPEC} is intended to depend upon the
+C library in use.
+
+Do not define this macro if it does not need to do anything.
+@end defmac
+
 @defmac CPLUSPLUS_CPP_SPEC
 This macro is just like @code{CPP_SPEC}, but is used for C++, rather
 than C@.  If you do not define this macro, then the value of
@@ -254,6 +262,14 @@ give to GCC into options for GCC to pass to the linker.
 Do not define this macro if it does not need to do anything.
 @end defmac
 
+@defmac LIBC_LINK_SPEC
+A C string constant which is appended to the value of
+@code{LINK_SPEC}. @code{LIBC_LINK_SPEC} is intended to depend upon the
+C library in use.
+
+Do not define this macro if it does not need to do anything.
+@end defmac
+
 @defmac LIB_SPEC
 Another C string constant used much like @code{LINK_SPEC}.  The difference
 between the two is that @code{LIB_SPEC} is used at the end of the
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 6b6ad86c81b6..d63e863d2bef 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -727,6 +727,13 @@ proper position among the other output files.  */
 #define CPP_SPEC ""
 #endif
 
+/* libc can define LIBC_CPP_SPEC to provide extra args to the C preprocessor
+   or extra switch-translations. */
+
+#ifndef LIBC_CPP_SPEC
+#define LIBC_CPP_SPEC ""
+#endif
+
 /* Operating systems can define OS_CC1_SPEC to provide extra args to cc1 and
    cc1plus or extra switch-translations.  The OS_CC1_SPEC is appended
    to CC1_SPEC in the initialization of cc1_spec.  */
@@ -752,6 +759,12 @@ proper position among the other output files.  */
 #define LINK_SPEC ""
 #endif
 
+/* libc can define LIBC_LINK_SPEC to provide extra args to the linker
+   or extra switch-translations.  */
+#ifndef LIBC_LINK_SPEC
+#define LIBC_LINK_SPEC ""
+#endif
+
 /* config.h can define LIB_SPEC to override the default libraries.  */
 #ifndef LIB_SPEC
 #define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
@@ -1212,14 +1225,14 @@ proper position among the other output files.  */
 
 static const char *asm_debug = ASM_DEBUG_SPEC;
 static const char *asm_debug_option = ASM_DEBUG_OPTION_SPEC;
-static const char *cpp_spec = CPP_SPEC;
+static const char *cpp_spec = CPP_SPEC LIBC_CPP_SPEC;
 static const char *cc1_spec = CC1_SPEC OS_CC1_SPEC;
 static const char *cc1plus_spec = CC1PLUS_SPEC;
 static const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
 static const char *link_ssp_spec = LINK_SSP_SPEC;
 static const char *asm_spec = ASM_SPEC;
 static const char *asm_final_spec = ASM_FINAL_SPEC;
-static const char *link_spec = LINK_SPEC;
+static const char *link_spec = LINK_SPEC LIBC_LINK_SPEC;
 static const char *lib_spec = LIB_SPEC;
 static const char *link_gomp_spec = "";
 static const char *libgcc_spec = LIBGCC_SPEC;

Reply via email to