Match *-picolibc-* and select picolibc as the default C library, plus
continuing to use the newlib-based logic for other configuration
items.

Add custom spec file fragments 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.

 * '--printf='. Allows targets to customize the version of printf linked
   from the C library.

Signed-off-by: Keith Packard <kei...@keithp.com>
---
 gcc/config.gcc               |  9 ++++++
 gcc/config/picolibc-spec.h   | 57 ++++++++++++++++++++++++++++++++++++
 gcc/config/picolibc.opt      | 47 +++++++++++++++++++++++++++++
 gcc/config/picolibc.opt.urls |  2 ++
 gcc/gcc.cc                   | 17 +++++++++--
 5 files changed, 130 insertions(+), 2 deletions(-)
 create mode 100644 gcc/config/picolibc-spec.h
 create mode 100644 gcc/config/picolibc.opt
 create mode 100644 gcc/config/picolibc.opt.urls

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 1e386a469e0..b20545da649 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1161,6 +1161,15 @@ case ${target} in
       ;;
   esac
   ;;
+*-picolibc-*)
+  # picolibc provides __cxa_atexit
+  default_use_cxa_atexit=yes
+  # picolibc provides stdint.h
+  use_gcc_stdint=none
+  tm_file="${tm_file} picolibc-spec.h"
+  extra_options="${extra_options} picolibc.opt"
+  ;;
+
 *-*-elf|arc*-*-elf*)
   # Assume that newlib is being used and so __cxa_atexit is provided.
   default_use_cxa_atexit=yes
diff --git a/gcc/config/picolibc-spec.h b/gcc/config/picolibc-spec.h
new file mode 100644
index 00000000000..40a55c056f4
--- /dev/null
+++ b/gcc/config/picolibc-spec.h
@@ -0,0 +1,57 @@
+/* Configuration common to all targets running Picolibc.
+   Copyright (C) 2023 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 00000000000..c5192fd6378
--- /dev/null
+++ b/gcc/config/picolibc.opt
@@ -0,0 +1,47 @@
+; Processor-independent options for picolibc.
+;
+; Copyright (C) 2022 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 00000000000..b3a57d15a39
--- /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/gcc.cc b/gcc/gcc.cc
index 4fd87f2c4a1..ddf5b6e5b5b 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -726,6 +726,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.  */
@@ -751,6 +758,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}}"
@@ -1204,14 +1217,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;
-- 
2.49.0

Reply via email to