[PATCH] libgcc/m68k: Fixes for soft float

2023-08-22 Thread Keith Packard via Gcc-patches
Check for non-zero denorm in __adddf3. Need to check both the upper and
lower 32-bit chunks of a 64-bit float for a non-zero value when
checking to see if the value is -0.

Fix __addsf3 when the sum exponent is exactly 0xff to ensure that
produces infinity and not nan.

Handle converting NaN/inf values between formats.

Handle underflow and overflow when truncating.

Write a replacement for __fixxfsi so that it does not raise extra
exceptions during an extra conversion from long double to double.

Signed-off-by: Keith Packard 
---
 libgcc/config/m68k/fpgnulib.c | 161 +++---
 libgcc/config/m68k/lb1sf68.S  |   7 +-
 2 files changed, 134 insertions(+), 34 deletions(-)

diff --git a/libgcc/config/m68k/fpgnulib.c b/libgcc/config/m68k/fpgnulib.c
index fe41edf26aa..5b53778e986 100644
--- a/libgcc/config/m68k/fpgnulib.c
+++ b/libgcc/config/m68k/fpgnulib.c
@@ -54,6 +54,7 @@
 #define SIGNBIT0x8000L
 #define HIDDEN (1L << 23L)
 #define SIGN(fp)   ((fp) & SIGNBIT)
+#define EXPMASK0xFFL
 #define EXP(fp)(((fp) >> 23L) & 0xFF)
 #define MANT(fp)   (((fp) & 0x7FL) | HIDDEN)
 #define PACK(s,e,m)((s) | ((e) << 23L) | (m))
@@ -262,6 +263,9 @@ __extendsfdf2 (float a1)
   mant &= ~HIDDEN;
 }
   exp = exp - EXCESS + EXCESSD;
+  /* Handle inf and NaN */
+  if (exp == EXPMASK - EXCESS + EXCESSD)
+exp = EXPDMASK;
   dl.l.upper |= exp << 20;
   dl.l.upper |= mant >> 3;
   dl.l.lower = mant << 29;
@@ -295,40 +299,52 @@ __truncdfsf2 (double a1)
   /* shift double mantissa 6 bits so we can round */
   sticky |= mant & ((1 << 6) - 1);
   mant >>= 6;
-
-  /* Check for underflow and denormals.  */
-  if (exp <= 0)
+  if (exp == EXPDMASK - EXCESSD + EXCESS)
+{
+  exp = EXPMASK;
+  mant = mant >> 1 | (mant & 1) | !!sticky;
+}
+  else
 {
-  if (exp < -24)
+  /* Check for underflow and denormals.  */
+  if (exp <= 0)
{
- sticky |= mant;
- mant = 0;
+ if (exp < -24)
+   {
+ sticky |= mant;
+ mant = 0;
+   }
+ else
+   {
+ sticky |= mant & ((1 << (1 - exp)) - 1);
+ mant >>= 1 - exp;
+   }
+ exp = 0;
}
-  else
+
+  /* now round */
+  shift = 1;
+  if ((mant & 1) && (sticky || (mant & 2)))
{
- sticky |= mant & ((1 << (1 - exp)) - 1);
- mant >>= 1 - exp;
-   }
-  exp = 0;
-}
-  
-  /* now round */
-  shift = 1;
-  if ((mant & 1) && (sticky || (mant & 2)))
-{
-  int rounding = exp ? 2 : 1;
+ int rounding = exp ? 2 : 1;
 
-  mant += 1;
+ mant += 1;
 
-  /* did the round overflow? */
-  if (mant >= (HIDDEN << rounding))
+ /* did the round overflow? */
+ if (mant >= (HIDDEN << rounding))
+   {
+ exp++;
+ shift = rounding;
+   }
+   }
+  /* shift down */
+  mant >>= shift;
+  if (exp >= EXPMASK)
{
- exp++;
- shift = rounding;
+ exp = EXPMASK;
+ mant = 0;
}
 }
-  /* shift down */
-  mant >>= shift;
 
   mant &= ~HIDDEN;
 
@@ -432,6 +448,30 @@ __extenddfxf2 (double d)
 }
 
   exp = EXPD (dl) - EXCESSD + EXCESSX;
+  /* Check for underflow and denormals. */
+  if (exp < 0)
+{
+  if (exp < -53)
+{
+ ldl.l.middle = 0;
+ ldl.l.lower = 0;
+   }
+  else if (exp < -30)
+{
+ ldl.l.lower = (ldl.l.middle & MANTXMASK) >> ((1 - exp) - 32);
+ ldl.l.middle &= ~MANTXMASK;
+   }
+  else
+{
+ ldl.l.lower >>= 1 - exp;
+ ldl.l.lower |= (ldl.l.middle & MANTXMASK) << (32 - (1 - exp));
+ ldl.l.middle = (ldl.l.middle & ~MANTXMASK) | (ldl.l.middle & 
MANTXMASK >> (1 - exp));
+   }
+  exp = 0;
+}
+  /* Handle inf and NaN */
+  if (exp == EXPDMASK - EXCESSD + EXCESSX)
+exp = EXPXMASK;
   ldl.l.upper |= exp << 16;
   ldl.l.middle = HIDDENX;
   /* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */
@@ -464,9 +504,38 @@ __truncxfdf2 (long double ld)
 }
 
   exp = EXPX (ldl) - EXCESSX + EXCESSD;
-  /* ??? quick and dirty: keep `exp' sane */
-  if (exp >= EXPDMASK)
-exp = EXPDMASK - 1;
+  /* Check for underflow and denormals. */
+  if (exp <= 0)
+{
+  if (exp < -53)
+{
+ ldl.l.middle = 0;
+ ldl.l.lower = 0;
+   }
+  else if (exp < -30)
+{
+ ldl.l.lower = (ldl.l.middle & MANTXMASK) >> ((1 - exp) - 32);
+ ldl.l.middle &= ~MANTXMASK;
+   }
+  else
+{
+ ldl.l.lower >>= 1 - exp;
+ ldl.l.lower |= (ldl.l.middle & MANTXMASK) << (32 - (1 - exp));
+ ldl.l.middle = (ldl.l.middle & ~MANTXMASK) | (ldl.l.middle & 
MANTXMASK >> (1 - exp));
+   }
+  exp = 0;
+}
+  else if (exp == EXPXMASK - EXCESSX + EXCESSD)
+{
+  exp = EXPDMASK;
+  

[PATCH 1/3] Allow default libc to be specified to configure

2023-02-04 Thread Keith Packard via Gcc-patches
The default C library is normally computed based on the target
triplet. However, for embedded systems, it can be useful to leave the
triplet alone while changing which C library is used by default. Other
C libraries may still be available on the system so the compiler and
can be used by specifying suitable include and library paths at build
time.

If an unknown --with-default-libc= value is provided, emit an error
and stop.

Signed-off-by: Keith Packard 
---
 gcc/config.gcc   | 48 
 gcc/configure.ac |  4 
 2 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index f0958e1c959..0679a76bebb 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -663,6 +663,8 @@ esac
 # Common C libraries.
 tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3 LIBC_MUSL=4"
 
+default_libc=""
+
 # 32-bit x86 processors supported by --with-arch=.  Each processor
 # MUST be separated by exactly one space.
 x86_archs="athlon athlon-4 athlon-fx athlon-mp athlon-tbird \
@@ -869,16 +871,16 @@ case ${target} in
   esac
   case $target in
 *-*-*android*)
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_BIONIC"
+  default_libc=LIBC_BIONIC
   ;;
 *-*-*uclibc* | *-*-uclinuxfdpiceabi)
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC"
+  default_libc=LIBC_UCLIBC
   ;;
 *-*-*musl*)
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_MUSL"
+  default_libc=LIBC_MUSL
   ;;
 *)
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
+  default_libc=LIBC_GLIBC
   ;;
   esac
   # Assume that glibc or uClibc or Bionic are being used and so __cxa_atexit
@@ -987,7 +989,8 @@ case ${target} in
   case ${enable_threads} in
 "" | yes | posix) thread_file='posix' ;;
   esac
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC SINGLE_LIBC"
+  tm_defines="$tm_defines SINGLE_LIBC"
+  default_libc=LIBC_UCLIBC
   ;;
 *-*-rdos*)
   use_gcc_stdint=wrap
@@ -1651,13 +1654,13 @@ csky-*-*)
 
case ${target} in
csky-*-linux-gnu*)
-   tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
+   default_libc=LIBC_GLIBC
# Force .init_array support.  The configure script 
cannot always
# automatically detect that GAS supports it, yet we 
require it.
gcc_cv_initfini_array=yes
;;
csky-*-linux-uclibc*)
-   tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC"
+   default_libc=LIBC_UCLIBC
default_use_cxa_atexit=no
;;
*)
@@ -3037,7 +3040,7 @@ powerpc*-wrs-vxworks7r*)
tmake_file="${tmake_file} t-linux rs6000/t-linux64 rs6000/t-fprules 
rs6000/t-ppccomm"
tmake_file="${tmake_file} rs6000/t-vxworks"
 
-   tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
+   default_libc=LIBC_GLIBC
extra_objs="$extra_objs linux.o rs6000-linux.o"
;;
 powerpc-wrs-vxworks*)
@@ -5862,3 +5865,32 @@ i[34567]86-*-* | x86_64-*-*)
fi
;;
 esac
+
+case "${with_default_libc}" in
+glibc)
+default_libc=LIBC_GLIBC
+;;
+uclibc)
+default_libc=LIBC_UCLIBC
+;;
+bionic)
+default_libc=LIBC_BIONIC
+;;
+musl)
+default_libc=LIBC_MUSL
+;;
+"")
+;;
+*)
+echo "Unknown libc in --with-default-libc=$with_default_libc" 1>&2
+exit 1
+;;
+esac
+
+case "$default_libc" in
+"")
+;;
+*)
+   tm_defines="$tm_defines DEFAULT_LIBC=$default_libc"
+   ;;
+esac
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 62bc908b991..c30e3c7ae72 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -2481,6 +2481,10 @@ if { { test x$host != x$target && test "x$with_sysroot" 
= x ; } ||
 fi
 AC_SUBST(inhibit_libc)
 
+AC_ARG_WITH(default-libc,
+   [AS_HELP_STRING([--with-default-libc],
+   [Use specified default C library])])
+
 # When building gcc with a cross-compiler, we need to adjust things so
 # that the generator programs are still built with the native compiler.
 # Also, we cannot run fixincludes.
-- 
2.39.0



[PATCH 3/3] Add '--oslib=' option when default C library is picolibc

2023-02-04 Thread Keith Packard via Gcc-patches
This option 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.

For example, picolibc provides 'libsemihost' on various targets which
maps these APIs to semihosting capabilities. This would be used with
this option by specifying --oslib=semihost

Signed-off-by: Keith Packard 
---
 gcc/config.gcc  |  7 +++
 gcc/config/picolibc.h   | 32 
 gcc/config/picolibc.opt | 26 ++
 3 files changed, 65 insertions(+)
 create mode 100644 gcc/config/picolibc.h
 create mode 100644 gcc/config/picolibc.opt

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 84bca8df615..e2863efd680 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -5903,3 +5903,10 @@ case "$default_libc" in
tm_defines="$tm_defines DEFAULT_LIBC=$default_libc"
;;
 esac
+
+case "$default_libc" in
+LIBC_PICOLIBC)
+   extra_options="${extra_options} picolibc.opt"
+   tm_file="${tm_file} picolibc.h"
+   ;;
+esac
diff --git a/gcc/config/picolibc.h b/gcc/config/picolibc.h
new file mode 100644
index 000..144f11ebcf2
--- /dev/null
+++ b/gcc/config/picolibc.h
@@ -0,0 +1,32 @@
+/* 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
+   .  */
+
+#undef  LIB_SPEC
+#define LIB_SPEC "--start-group -lc %{-oslib=*:-l%*} %(libgcc) --end-group"
+
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC "crt0%O%s"
+
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC ""
diff --git a/gcc/config/picolibc.opt b/gcc/config/picolibc.opt
new file mode 100644
index 000..194b3362b03
--- /dev/null
+++ b/gcc/config/picolibc.opt
@@ -0,0 +1,26 @@
+; 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
+; .
+
+-oslib
+Driver Separate Alias(-oslib=)
+
+-oslib=
+Driver Joined
+Specify an OS support library to load after libc.
-- 
2.39.0



[PATCH 0/3] picolibc: Add picolibc linking help (v3)

2023-02-04 Thread Keith Packard via Gcc-patches
Picolibc is a C library for embedded systems based on code from newlib
and avr libc. To connect some system-dependent picolibc functions
(like stdio) to an underlying platform, the platform may provide an OS
library.

This OS library must follow the C library in the link command line. In
current picolibc, that is done by providing an alternate .specs file
which can rewrite the *lib spec to insert the OS library in the right
spot.

This patch series adds the ability to specify the OS library on the
gcc command line when GCC is configured to us picolibc as the default
C library.

The second version of this series includes the following updates:

 1. Add a check for unrecognized C library passed to the
--with-default-libc to catch errors. Suggested by Richard Sandiford.

The third version of this series includes the following updates:

 1. Replace the various target-specific hacks with a new file,
gcc/config/picolibc.h which adjusts the LIB_SPEC, STARTFILE_SPEC
and ENDFILE_SPEC values. Suggested by Sebastian Huber.

Keith Packard (3):
  Allow default libc to be specified to configure
  Add newlib and picolibc as default C library choices
  Add '--oslib=' option when default C library is picolibc

 gcc/config.gcc  | 66 +++--
 gcc/config/picolibc.h   | 32 
 gcc/config/picolibc.opt | 26 
 gcc/configure.ac|  4 +++
 4 files changed, 119 insertions(+), 9 deletions(-)
 create mode 100644 gcc/config/picolibc.h
 create mode 100644 gcc/config/picolibc.opt

-- 
2.39.0



[PATCH 2/3] Add newlib and picolibc as default C library choices

2023-02-04 Thread Keith Packard via Gcc-patches
Signed-off-by: Keith Packard 
---
 gcc/config.gcc | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 0679a76bebb..84bca8df615 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -661,7 +661,7 @@ case ${target} in
 esac
 
 # Common C libraries.
-tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3 LIBC_MUSL=4"
+tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3 LIBC_MUSL=4 
LIBC_NEWLIB=5 LIBC_PICOLIBC=6"
 
 default_libc=""
 
@@ -5879,6 +5879,15 @@ bionic)
 musl)
 default_libc=LIBC_MUSL
 ;;
+newlib)
+# Newlib configurations don't set the DEFAULT_LIBC variable, so
+# avoid changing those by allowing --with-default-libc=newlib but
+# not actually setting the DEFAULT_LIBC variable.
+default_libc=
+;;
+picolibc)
+default_libc=LIBC_PICOLIBC
+;;
 "")
 ;;
 *)
-- 
2.39.0



Making gcc toolchain installs relocatable

2022-09-23 Thread Keith Packard via Gcc-patches

I submitted the referenced patch to extend the 'getenv' .specs function
back in August and didn't see any response, so I wanted to provide a bit
more context to see if that would help people understand why I wrote
this.

Here's a link to that message:

https://gcc.gnu.org/pipermail/gcc-patches/2022-August/600452.html

I'm working with embedded toolchains where I want to distribute binary
versions of binutils, gcc and a suite of libraries in a tar file which
the user can unpack anywhere on their system. To make this work, I need
to create .spec file fragments that can locate the correct libraries
relative to the location where the toolchain was unpacked.

An easy way to do this, which doesn't depend on a default sysroot value,
is to use the GCC_EXEC_PREFIX environment variable in the .specs
file. Gcc sets that whenever it discovers that it hasn't been run from
the defined installation path. However, if the user does end up
installing gcc in the defined installation path, then that variable
isn't set at all. If a .specs file attempts to reference the variable,
gcc will emit a fatal error and exit.

This patch makes it possible for the .specs file fragment to provide the
default path as a fallback for a missing environment variable so that,
instead of exiting, the correct value will be substituted instead.

By doing this, I can create portable .specs file fragments which work
wherever the toolchain is installed.

This patch seemed like the least invasive approach to solving this
problem, but there are two other approaches that could work, and which
would make the .specs files simpler:

 1. Always set the GCC_EXEC_PREFIX environment variable, even if GCC
is executed from the expected location.

 2. Make %R in .specs files expand to the appropriate value even if
there is no sysroot defined.

I'd be happy to provide an implementation of either of those if that
would be more acceptable.

-- 
-keith


signature.asc
Description: PGP signature


[PATCH 1/3] Allow default libc to be specified to configure

2022-09-03 Thread Keith Packard via Gcc-patches
The default C library is normally computed based on the target
triplet. However, for embedded systems, it can be useful to leave the
triplet alone while changing which C library is used by default. Other
C libraries may still be available on the system so the compiler and
can be used by specifying suitable include and library paths at build
time.

If an unknown --with-default-libc= value is provided, emit an error
and stop.

Signed-off-by: Keith Packard 
---
 gcc/config.gcc   | 46 ++
 gcc/configure.ac |  4 
 2 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index f4e757bd853..bf838b1545d 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -644,6 +644,8 @@ esac
 # Common C libraries.
 tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3 LIBC_MUSL=4"
 
+default_libc=""
+
 # 32-bit x86 processors supported by --with-arch=.  Each processor
 # MUST be separated by exactly one space.
 x86_archs="athlon athlon-4 athlon-fx athlon-mp athlon-tbird \
@@ -849,16 +851,16 @@ case ${target} in
   esac
   case $target in
 *-*-*android*)
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_BIONIC"
+  default_libc=LIBC_BIONIC
   ;;
 *-*-*uclibc* | *-*-uclinuxfdpiceabi)
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC"
+  default_libc=LIBC_UCLIBC
   ;;
 *-*-*musl*)
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_MUSL"
+  default_libc=LIBC_MUSL
   ;;
 *)
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
+  default_libc=LIBC_GLIBC
   ;;
   esac
   # Assume that glibc or uClibc or Bionic are being used and so __cxa_atexit
@@ -951,7 +953,8 @@ case ${target} in
   case ${enable_threads} in
 "" | yes | posix) thread_file='posix' ;;
   esac
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC SINGLE_LIBC"
+  tm_defines="$tm_defines SINGLE_LIBC"
+  default_libc=LIBC_UCLIBC
   ;;
 *-*-rdos*)
   use_gcc_stdint=wrap
@@ -1603,13 +1606,13 @@ csky-*-*)
 
case ${target} in
csky-*-linux-gnu*)
-   tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
+   default_libc=LIBC_GLIBC
# Force .init_array support.  The configure script 
cannot always
# automatically detect that GAS supports it, yet we 
require it.
gcc_cv_initfini_array=yes
;;
csky-*-linux-uclibc*)
-   tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC"
+   default_libc=LIBC_UCLIBC
default_use_cxa_atexit=no
;;
*)
@@ -2982,7 +2985,7 @@ powerpc*-wrs-vxworks7r*)
tmake_file="${tmake_file} t-linux rs6000/t-linux64 rs6000/t-fprules 
rs6000/t-ppccomm"
tmake_file="${tmake_file} rs6000/t-vxworks"
 
-   tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
+   default_libc=LIBC_GLIBC
extra_objs="$extra_objs linux.o rs6000-linux.o"
;;
 powerpc-wrs-vxworks*)
@@ -5772,3 +5775,30 @@ i[34567]86-*-* | x86_64-*-*)
fi
;;
 esac
+
+case "${with_default_libc}" in
+glibc)
+default_libc=LIBC_GLIBC
+;;
+uclibc)
+default_libc=LIBC_UCLIBC
+;;
+bionic)
+default_libc=LIBC_BIONIC
+;;
+musl)
+default_libc=LIBC_MUSL
+;;
+*)
+echo "Unknown libc in --with-default-libc=$with_default_libc" 1>&2
+exit 1
+;;
+esac
+
+case "$default_libc" in
+"")
+;;
+*)
+   tm_defines="$tm_defines DEFAULT_LIBC=$default_libc"
+   ;;
+esac
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 50bb61c1b61..7302c987282 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -2472,6 +2472,10 @@ if { { test x$host != x$target && test "x$with_sysroot" 
= x ; } ||
 fi
 AC_SUBST(inhibit_libc)
 
+AC_ARG_WITH(default-libc,
+   [AS_HELP_STRING([--with-default-libc],
+   [Use specified default C library])])
+
 # When building gcc with a cross-compiler, we need to adjust things so
 # that the generator programs are still built with the native compiler.
 # Also, we cannot run fixincludes.
-- 
2.36.1



[PATCH 3/3] Add '--oslib=' option when default C library is picolibc

2022-09-03 Thread Keith Packard via Gcc-patches
This option 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.

For example, picolibc provides 'libsemihost' on various targets which
maps these APIs to semihosting capabilities. This would be used with
this option by specifying --oslib=semihost

This patch enables --oslib= on arm, nds32, riscv and sh.

Signed-off-by: Keith Packard 
---
 gcc/config.gcc|  6 ++
 gcc/config/arm/elf.h  |  5 +
 gcc/config/nds32/elf.h|  4 
 gcc/config/picolibc.opt   | 26 ++
 gcc/config/riscv/elf.h|  4 
 gcc/config/sh/embed-elf.h |  5 +
 6 files changed, 50 insertions(+)
 create mode 100644 gcc/config/picolibc.opt

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 6f8f13a811a..9bb45ec85ab 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -5813,3 +5813,9 @@ case "$default_libc" in
tm_defines="$tm_defines DEFAULT_LIBC=$default_libc"
;;
 esac
+
+case "$default_libc" in
+LIBC_PICOLIBC)
+   extra_options="${extra_options} picolibc.opt"
+   ;;
+esac
diff --git a/gcc/config/arm/elf.h b/gcc/config/arm/elf.h
index 3d111433ede..dc5b9374814 100644
--- a/gcc/config/arm/elf.h
+++ b/gcc/config/arm/elf.h
@@ -150,3 +150,8 @@
 #undef L_floatundisf
 #endif
 
+#if DEFAULT_LIBC == LIBC_PICOLIBC
+#undef  LIB_SPEC
+#define LIB_SPEC "--start-group %(libgcc)  -lc %{-oslib=*:-l%*} --end-group"
+#endif
+
diff --git a/gcc/config/nds32/elf.h b/gcc/config/nds32/elf.h
index ebdc18cee2a..b9d2f2485e8 100644
--- a/gcc/config/nds32/elf.h
+++ b/gcc/config/nds32/elf.h
@@ -34,8 +34,12 @@
   " %{shared:-shared}" \
   NDS32_RELAX_SPEC
 
+#if DEFAULT_LIBC == LIBC_PICOLIBC
+#define LIB_SPEC "--start-group %(libgcc)  -lc %{-oslib=*:-l%*} --end-group"
+#else
 #define LIB_SPEC \
   " -lc -lgloss"
+#endif
 
 #define LIBGCC_SPEC \
   " -lgcc"
diff --git a/gcc/config/picolibc.opt b/gcc/config/picolibc.opt
new file mode 100644
index 000..194b3362b03
--- /dev/null
+++ b/gcc/config/picolibc.opt
@@ -0,0 +1,26 @@
+; 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
+; .
+
+-oslib
+Driver Separate Alias(-oslib=)
+
+-oslib=
+Driver Joined
+Specify an OS support library to load after libc.
diff --git a/gcc/config/riscv/elf.h b/gcc/config/riscv/elf.h
index f3d767c6d42..57471cee702 100644
--- a/gcc/config/riscv/elf.h
+++ b/gcc/config/riscv/elf.h
@@ -27,9 +27,13 @@ along with GCC; see the file COPYING3.  If not see
 /* Link against Newlib libraries, because the ELF backend assumes Newlib.
Handle the circular dependence between libc and libgloss. */
 #undef  LIB_SPEC
+#if DEFAULT_LIBC == LIBC_PICOLIBC
+#define LIB_SPEC "--start-group %(libgcc)  -lc %{-oslib=*:-l%*} --end-group"
+#else
 #define LIB_SPEC \
   "--start-group -lc %{!specs=nosys.specs:-lgloss} --end-group " \
   
"%{!nostartfiles:%{!nodefaultlibs:%{!nolibc:%{!nostdlib:%:riscv_multi_lib_check()"
+#endif
 
 #undef  STARTFILE_SPEC
 #define STARTFILE_SPEC "crt0%O%s crtbegin%O%s"
diff --git a/gcc/config/sh/embed-elf.h b/gcc/config/sh/embed-elf.h
index 21e51dd0bb9..093bf2800db 100644
--- a/gcc/config/sh/embed-elf.h
+++ b/gcc/config/sh/embed-elf.h
@@ -34,3 +34,8 @@ along with GCC; see the file COPYING3.  If not see
   %{Os: -lgcc-Os-4-200} \
   -lgcc \
   %{!Os: -lgcc-Os-4-200}"
+
+#if DEFAULT_LIBC == LIBC_PICOLIBC
+#undef  LIB_SPEC
+#define LIB_SPEC "--start-group %(libgcc)  -lc %{-oslib=*:-l%*} --end-group"
+#endif
-- 
2.36.1



[PATCH 0/3] picolibc: Add picolibc linking help

2022-09-03 Thread Keith Packard via Gcc-patches
Picolibc is a C library for embedded systems based on code from newlib
and avr libc. To connect some system-dependent picolibc functions
(like stdio) to an underlying platform, the platform may provide an OS
library.

This OS library must follow the C library in the link command line. In
current picolibc, that is done by providing an alternate .specs file
which can rewrite the *lib spec to insert the OS library in the right
spot.

This patch series adds the ability to specify the OS library on the
gcc command line when GCC is configured to us picolibc as the default
C library, and then hooks that up for arm, nds32, riscv and sh targets.

This is the second version of these patches which address several
issues raised in review by Richard Sandiford.

Keith Packard (3):
  Allow default libc to be specified to configure
  Add newlib and picolibc as default C library choices
  Add '--oslib=' option when default C library is picolibc

 gcc/config.gcc| 65 +--
 gcc/config/arm/elf.h  |  5 +++
 gcc/config/nds32/elf.h|  4 +++
 gcc/config/picolibc.opt   | 26 
 gcc/config/riscv/elf.h|  4 +++
 gcc/config/sh/embed-elf.h |  5 +++
 gcc/configure.ac  |  4 +++
 7 files changed, 104 insertions(+), 9 deletions(-)
 create mode 100644 gcc/config/picolibc.opt

-- 
2.36.1



[PATCH 2/3] Add newlib and picolibc as default C library choices

2022-09-03 Thread Keith Packard via Gcc-patches
Don't set the DEFAULT_LIBC variable for newlib configurations as that
is how it currently works for systems using newlib as the default.

Signed-off-by: Keith Packard 
---
 gcc/config.gcc | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index bf838b1545d..6f8f13a811a 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -642,7 +642,7 @@ case ${target} in
 esac
 
 # Common C libraries.
-tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3 LIBC_MUSL=4"
+tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3 LIBC_MUSL=4 
LIBC_NEWLIB=5 LIBC_PICOLIBC=6"
 
 default_libc=""
 
@@ -5789,6 +5789,17 @@ bionic)
 musl)
 default_libc=LIBC_MUSL
 ;;
+newlib)
+
+# Newlib configurations don't set the DEFAULT_LIBC variable, so
+# avoid changing those allowing --with-default-libc=newlib but
+# don't actually set the DEFAULT_LIBC variable.
+
+default_libc=
+;;
+picolibc)
+default_libc=LIBC_PICOLIBC
+;;
 *)
 echo "Unknown libc in --with-default-libc=$with_default_libc" 1>&2
 exit 1
-- 
2.36.1



Re: [PATCH 0/3] picolibc: Add picolibc linking help

2022-09-03 Thread Keith Packard via Gcc-patches
Richard Sandiford  writes:

Thanks much for reviewing this series. I really appreciate it.

>   should there be a default case that raises an error for unrecognised
>   libcs?  Command-line checking for configure isn't very tight, but we
>   do raise similar errors for things like invalid --enable-threads
>   values.

Good thinking. It's way to easy to introduce a typo somewhere and have
it get missed.

>   On balance I think it would be better to accept
>   --with-default-libc=newlib but set default_libc to the empty string.

That also makes good sense -- leave existing configurations unchanged.

> - Should we raise an error for toolchains that don't support the given
>   C library?  It feels like we should, but I realise that could be
>   difficult to do.

That would be nice, but it also feels like making it reliable enough to
be useful would be difficult to maintain in the future, even if we did
manage to make it mostly work today.

> - Very minor, but in lines like:
>
>   +#if defined(DEFAULT_LIBC) && defined(LIBC_PICOLIBC) && DEFAULT_LIBC == 
> LIBC_PICOLIBC
>
>   is LIBC_PICOLIB ever undefined?  It looks like config.gcc provides
>   an unconditional definition.  If it is always defined then:
>
>   #if DEFAULT_LIBC == LIBC_PICOLIB
>
>   would be clearer.

Agreed. Thanks again for taking a look; I'll send a new series with
these issues fixed shortly.

-- 
-keith


signature.asc
Description: PGP signature


[PATCH] driver: Extend 'getenv' function to allow default value

2022-08-26 Thread Keith Packard via Gcc-patches
Right now, a missing environment variable provided to the 'getenv'
function in a .specs file causes a fatal error. That makes writing a
spec file that uses the GCC_EXEC_PREFIX value difficult as that
variable is only set when the driver has been relocated, but not when
run from the defined location. This makes building a relocatable
toolchain difficult to extend to other ancilary pieces which use specs
files to locate header and library files adjacent to the toolchain.

This patch adds an optional third argument to the getenv function that
can be used to fall back to the standard installation path when the
driver hasn't set GCC_EXEC_PREFIX in the environment.

For example, if an alternate C library is installed in
${prefix}/extra, then this change allows the specs file to locate that
relative to the gcc directory, if gcc is located in the original
installation directory (which would leave GCC_EXEC_PREFIX unset), or
if the gcc tree has been moved to a different location (where gcc
would set GCC_EXEC_PREFIX itself):

*cpp:
-isystem %:getenv(GCC_EXEC_PREFIX ../../extra/include ${prefix}/extra/include)

I considered changing the behavior of either the %R sequence so that
it had a defined behavior when there was no sysroot defined, or making
the driver always set the GCC_EXEC_PREFIX environment variable and
decided that the approach of adding functionality to getenv where it
was previously invalid would cause the least potential for affecting
existing usage.

Signed-off-by: Keith Packard 
---
 gcc/doc/invoke.texi | 18 +++---
 gcc/gcc.cc  | 10 +-
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 6131bfa7acf..669c28a609a 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -34223,17 +34223,21 @@ The following built-in spec functions are provided:
 
 @table @code
 @item @code{getenv}
-The @code{getenv} spec function takes two arguments: an environment
-variable name and a string.  If the environment variable is not
-defined, a fatal error is issued.  Otherwise, the return value is the
-value of the environment variable concatenated with the string.  For
-example, if @env{TOPDIR} is defined as @file{/path/to/top}, then:
+
+The @code{getenv} spec function takes two or three arguments: an
+environment variable name, a string and an optional default value.  If
+the environment variable is not defined and a default value is
+provided, that is used as the return value; otherwise a fatal error is
+issued.  Otherwise, the return value is the value of the environment
+variable concatenated with the string.  For example, if @env{TOPDIR}
+is defined as @file{/path/to/top}, then:
 
 @smallexample
-%:getenv(TOPDIR /include)
+%:getenv(TOPDIR /include /path/to/default/include)
 @end smallexample
 
-expands to @file{/path/to/top/include}.
+expands to @file{/path/to/top/include}. If @env{TOPDIR} is not
+defined, then this expands to @file{/path/to/default/include}.
 
 @item @code{if-exists}
 The @code{if-exists} spec function takes one argument, an absolute
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index b6d562a92f0..16295702db7 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -10169,12 +10169,20 @@ getenv_spec_function (int argc, const char **argv)
   char *ptr;
   size_t len;
 
-  if (argc != 2)
+  if (argc != 2 && argc != 3)
 return NULL;
 
   varname = argv[0];
   value = env.get (varname);
 
+  if (!value && argc == 3)
+{
+  value = argv[2];
+  result = XNEWVAR(char, strlen(value) + 1);
+  strcpy(result, value);
+  return result;
+}
+
   /* If the variable isn't defined and this is allowed, craft our expected
  return value.  Assume variable names used in specs strings don't contain
  any active spec character so don't need escaping.  */
-- 
2.36.1



Re: [PATCH 0/3] picolibc: Add picolibc linking help

2022-08-25 Thread Keith Packard via Gcc-patches
Kito Cheng  writes:

> I am thinking that maybe we should add
> -mlibc=[newlib|newlib-nano|picolibc|unknown] option to bare-matel
> toolchain, one reason is having an unify interface to select libc
> implementation between clang/LLVM, spec file is a GCC specific stuff,
> that cause very bad compatibility between GCC and clang/LLVM, and
> having option to control that would be better since clang/LLVM don't
> have those configure time option.

You can create specs file for each library so that you select the
library with --specs=picolibc.specs or --specs=newlib-nano.specs. That
seems sufficient as you can mess with various compiler options and set
the header paths. Crosstool-ng does this and it enables delivering
newlib, newlib-nano and picolibc in the same toolchain.

-- 
-keith


signature.asc
Description: PGP signature


Re: [PATCH 0/3] picolibc: Add picolibc linking help

2022-08-24 Thread Keith Packard via Gcc-patches
Andrew Pinski  writes:

(removing gcc@ as not appropriate for patch discussions)

Thanks for reviewing my patches; I appreciate the time you have taken to
think about this.

> Why do you need to change the specs to support picolibc? Why not have
> the library supply the specs file instead, like what is done for
> newlib and libgloss?

Several architectures do include support for newlib's libgloss in their
gcc configuration today (i386, m32r, microblaze, nds32, pru, riscv and
sh), so I wondered if it made sense to add support for picolibc's
target-specific libraries as well.

Picolibc does deliver a spec file fragment which implements this
functionality, but that requires the addition of --specs=picolibc.specs
to the gcc command line instead of being built-in to gcc itself. When
creating an integrated toolchain using picolibc, it seems a bit odd to
require an option for the toolchain to work.

> What OS libraries are not included in libc? I trying to figure out why
> this needs to be special cased here.

As a general-purpose embedded C library, picolibc doesn't include any
OS-specific code. Instead, it defines a limited subset of POSIX
interfaces which are to be supplied by the target platform.

Picolibc itself supplies sample implementations of these ABIs that can
run on top of bare metal systems with semihosting support which are used
while testing picolibc itself.

This is similar to newlib's libgloss: the C library is built atop
another library which needs to follow it in the linker command line for
symbol resolution to work correctly. Making this work requires a change
in the *lib spec file fragment.

Adjusting the *lib fragment can either be done in an externally provided
specs file, or built-in to gcc. Both of these mechanisms are present in
the gcc ecosystem today, leading me to wonder whether the gcc community
would be interested in having an integrated option available.

-- 
-keith


signature.asc
Description: PGP signature


[PATCH 0/3] picolibc: Add picolibc linking help

2022-08-24 Thread Keith Packard via Gcc-patches
Picolibc is a C library for embedded systems based on code from newlib
and avr libc. To connect some system-dependent picolibc functions
(like stdio) to an underlying platform, the platform may provide an OS
library.

This OS library must follow the C library in the link command line. In
current picolibc, that is done by providing an alternate .specs file
which can rewrite the *lib spec to insert the OS library in the right
spot.

This patch series adds the ability to specify the OS library on the
gcc command line when GCC is configured to us picolibc as the default
C library, and then hooks that up for arm, nds32, riscv and sh targets.

Keith Packard (3):
  Allow default libc to be specified to configure
  Add newlib and picolibc as default C library choices
  Add '--oslib=' option when default C library is picolibc

 gcc/config.gcc| 56 ---
 gcc/config/arm/elf.h  |  5 
 gcc/config/nds32/elf.h|  4 +++
 gcc/config/picolibc.opt   | 26 ++
 gcc/config/riscv/elf.h|  4 +++
 gcc/config/sh/embed-elf.h |  5 
 gcc/configure.ac  |  4 +++
 7 files changed, 95 insertions(+), 9 deletions(-)
 create mode 100644 gcc/config/picolibc.opt

-- 
2.36.1



[PATCH 3/3] picolibc: Add '--oslib=' option when default C library is picolibc

2022-08-24 Thread Keith Packard via Gcc-patches
This option 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.

For example, picolibc provides 'libsemihost' on various targets which
maps these APIs to semihosting capabilities. This would be used with
this option by specifying --oslib=semihost

This patch enables --oslib= on arm, nds32, riscv and sh.

Signed-off-by: Keith Packard 
---
 gcc/config.gcc|  6 ++
 gcc/config/arm/elf.h  |  5 +
 gcc/config/nds32/elf.h|  4 
 gcc/config/picolibc.opt   | 26 ++
 gcc/config/riscv/elf.h|  4 
 gcc/config/sh/embed-elf.h |  5 +
 6 files changed, 50 insertions(+)
 create mode 100644 gcc/config/picolibc.opt

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 0aa4bd6c3dd..80740d8f04e 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -5893,3 +5893,9 @@ case "$default_libc" in
tm_defines="$tm_defines DEFAULT_LIBC=$default_libc"
;;
 esac
+
+case "$default_libc" in
+LIBC_PICOLIBC)
+   extra_options="${extra_options} picolibc.opt"
+   ;;
+esac
diff --git a/gcc/config/arm/elf.h b/gcc/config/arm/elf.h
index 3d111433ede..d83ee4a1a8c 100644
--- a/gcc/config/arm/elf.h
+++ b/gcc/config/arm/elf.h
@@ -150,3 +150,8 @@
 #undef L_floatundisf
 #endif
 
+#if defined(DEFAULT_LIBC) && defined(LIBC_PICOLIBC) && DEFAULT_LIBC == 
LIBC_PICOLIBC
+#undef  LIB_SPEC
+#define LIB_SPEC "--start-group %(libgcc)  -lc %{-oslib=*:-l%*} --end-group"
+#endif
+
diff --git a/gcc/config/nds32/elf.h b/gcc/config/nds32/elf.h
index ebdc18cee2a..a956d531ef4 100644
--- a/gcc/config/nds32/elf.h
+++ b/gcc/config/nds32/elf.h
@@ -34,8 +34,12 @@
   " %{shared:-shared}" \
   NDS32_RELAX_SPEC
 
+#if defined(DEFAULT_LIBC) && defined(LIBC_PICOLIBC) && DEFAULT_LIBC == 
LIBC_PICOLIBC
+#define LIB_SPEC "--start-group %(libgcc)  -lc %{-oslib=*:-l%*} --end-group"
+#else
 #define LIB_SPEC \
   " -lc -lgloss"
+#endif
 
 #define LIBGCC_SPEC \
   " -lgcc"
diff --git a/gcc/config/picolibc.opt b/gcc/config/picolibc.opt
new file mode 100644
index 000..194b3362b03
--- /dev/null
+++ b/gcc/config/picolibc.opt
@@ -0,0 +1,26 @@
+; 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
+; .
+
+-oslib
+Driver Separate Alias(-oslib=)
+
+-oslib=
+Driver Joined
+Specify an OS support library to load after libc.
diff --git a/gcc/config/riscv/elf.h b/gcc/config/riscv/elf.h
index f0e865d6ef4..ca906afcd52 100644
--- a/gcc/config/riscv/elf.h
+++ b/gcc/config/riscv/elf.h
@@ -27,7 +27,11 @@ along with GCC; see the file COPYING3.  If not see
 /* Link against Newlib libraries, because the ELF backend assumes Newlib.
Handle the circular dependence between libc and libgloss. */
 #undef  LIB_SPEC
+#if defined(DEFAULT_LIBC) && defined(LIBC_PICOLIBC) && DEFAULT_LIBC == 
LIBC_PICOLIBC
+#define LIB_SPEC "--start-group %(libgcc)  -lc %{-oslib=*:-l%*} --end-group"
+#else
 #define LIB_SPEC "--start-group -lc %{!specs=nosys.specs:-lgloss} --end-group"
+#endif
 
 #undef  STARTFILE_SPEC
 #define STARTFILE_SPEC "crt0%O%s crtbegin%O%s"
diff --git a/gcc/config/sh/embed-elf.h b/gcc/config/sh/embed-elf.h
index 21e51dd0bb9..e8605849e07 100644
--- a/gcc/config/sh/embed-elf.h
+++ b/gcc/config/sh/embed-elf.h
@@ -34,3 +34,8 @@ along with GCC; see the file COPYING3.  If not see
   %{Os: -lgcc-Os-4-200} \
   -lgcc \
   %{!Os: -lgcc-Os-4-200}"
+
+#if defined(DEFAULT_LIBC) && defined(LIBC_PICOLIBC) && DEFAULT_LIBC == 
LIBC_PICOLIBC
+#undef  LIB_SPEC
+#define LIB_SPEC "--start-group %(libgcc)  -lc %{-oslib=*:-l%*} --end-group"
+#endif
-- 
2.36.1



[PATCH 1/3] picolibc: Allow default libc to be specified to configure

2022-08-24 Thread Keith Packard via Gcc-patches
The default C library is normally computed based on the target
triplet. However, for embedded systems, it can be useful to leave the
triplet alone while changing which C library is used by default. Other
C libraries may still be available on the system so the compiler and
can be used by specifying suitable include and library paths at build
time.

Signed-off-by: Keith Packard 
---
 gcc/config.gcc   | 42 ++
 gcc/configure.ac |  4 
 2 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 02f58970db0..f8b6da4f4e7 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -641,6 +641,8 @@ esac
 # Common C libraries.
 tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3 LIBC_MUSL=4"
 
+default_libc=""
+
 # 32-bit x86 processors supported by --with-arch=.  Each processor
 # MUST be separated by exactly one space.
 x86_archs="athlon athlon-4 athlon-fx athlon-mp athlon-tbird \
@@ -847,16 +849,16 @@ case ${target} in
   esac
   case $target in
 *-*-*android*)
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_BIONIC"
+  default_libc=LIBC_BIONIC
   ;;
 *-*-*uclibc* | *-*-uclinuxfdpiceabi)
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC"
+  default_libc=LIBC_UCLIBC
   ;;
 *-*-*musl*)
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_MUSL"
+  default_libc=LIBC_MUSL
   ;;
 *)
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
+  default_libc=LIBC_GLIBC
   ;;
   esac
   # Assume that glibc or uClibc or Bionic are being used and so __cxa_atexit
@@ -949,7 +951,8 @@ case ${target} in
   case ${enable_threads} in
 "" | yes | posix) thread_file='posix' ;;
   esac
-  tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC SINGLE_LIBC"
+  tm_defines="$tm_defines SINGLE_LIBC"
+  default_libc=LIBC_UCLIBC
   ;;
 *-*-rdos*)
   use_gcc_stdint=wrap
@@ -1606,13 +1609,13 @@ csky-*-*)
 
case ${target} in
csky-*-linux-gnu*)
-   tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
+   default_libc=LIBC_GLIBC
# Force .init_array support.  The configure script 
cannot always
# automatically detect that GAS supports it, yet we 
require it.
gcc_cv_initfini_array=yes
;;
csky-*-linux-uclibc*)
-   tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC"
+   default_libc=LIBC_UCLIBC
default_use_cxa_atexit=no
;;
*)
@@ -3065,7 +3068,7 @@ powerpc*-wrs-vxworks7r*)
tmake_file="${tmake_file} t-linux rs6000/t-linux64 rs6000/t-fprules 
rs6000/t-ppccomm"
tmake_file="${tmake_file} rs6000/t-vxworks"
 
-   tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
+   default_libc=LIBC_GLIBC
extra_objs="$extra_objs linux.o rs6000-linux.o"
;;
 powerpc-wrs-vxworks*)
@@ -5861,3 +5864,26 @@ i[34567]86-*-* | x86_64-*-*)
fi
;;
 esac
+
+case "${with_default_libc}" in
+glibc)
+default_libc=LIBC_GLIBC
+;;
+uclibc)
+default_libc=LIBC_UCLIBC
+;;
+bionic)
+default_libc=LIBC_BIONIC
+;;
+musl)
+default_libc=LIBC_MUSL
+;;
+esac
+
+case "$default_libc" in
+"")
+;;
+*)
+   tm_defines="$tm_defines DEFAULT_LIBC=$default_libc"
+   ;;
+esac
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 819b490d1b6..0b76613b635 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -2490,6 +2490,10 @@ if { { test x$host != x$target && test "x$with_sysroot" 
= x ; } ||
 fi
 AC_SUBST(inhibit_libc)
 
+AC_ARG_WITH(default-libc,
+   [AS_HELP_STRING([--with-default-libc],
+   [Use specified default C library])])
+
 # When building gcc with a cross-compiler, we need to adjust things so
 # that the generator programs are still built with the native compiler.
 # Also, we cannot run fixincludes.
-- 
2.36.1



[PATCH 2/3] picolibc: Add newlib and picolibc as default C library choices

2022-08-24 Thread Keith Packard via Gcc-patches
Signed-off-by: Keith Packard 
---
 gcc/config.gcc | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index f8b6da4f4e7..0aa4bd6c3dd 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -639,7 +639,7 @@ case ${target} in
 esac
 
 # Common C libraries.
-tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3 LIBC_MUSL=4"
+tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3 LIBC_MUSL=4 
LIBC_NEWLIB=5 LIBC_PICOLIBC=6"
 
 default_libc=""
 
@@ -5878,6 +5878,12 @@ bionic)
 musl)
 default_libc=LIBC_MUSL
 ;;
+newlib)
+default_libc=LIBC_NEWLIB
+;;
+picolibc)
+default_libc=LIBC_PICOLIBC
+;;
 esac
 
 case "$default_libc" in
-- 
2.36.1



Re: [PATCH] Add 'no_builtin' function attribute

2021-11-03 Thread Keith Packard via Gcc-patches
Martin Sebor  writes:

> Can this option be used in attribute optimize?  If yes, what's
> the advantage of also providing an atttribute?

Compatibility with the clang attribute.

> It seems to me that as a matter of QOI, GCC should be able to
> disable the expansion of built-ins to calls to themselves in
> their bodies (I would view it as a bug if GCC expanded a byte
> copying loop into a call to __builtin_memcpy in the body of
> a function named memcpy, without issuing a warnings; but even
> with a warning I'd hope it to do the sensible thing and avoid
> introducing infinite recursion).

That's a pretty sensible plan and would resolve many of the issues
caused by these optimizations while implementing libc itself. Of course,
that wouldn't fix other places where the compiler is using knowledge of
builtin semantics to drive optimization (like the memset call before
free).

> A compiler may not be able
> to do that in calls made from those functions, and for that
> the built-in expansion needs to be disabled explicitly.
> -fno-builtin isn't good enough because it doesn't prevent GCC
> from introiducing calls to __builtin_ functions, and that's
> what this feature is for.  Do I understand correctly?

-fno-builtin has two problems:

 1. Cannot be used in source code, only on the command line.

 2. Also disables explicit use of builtin functions.

> If we end up adding a new attribute (as opposed to relying
> on attribute optimize) and the attribute is expected to have
> an effect only on the definitions of functions and not also
> on their callers, I would suggest to consider having
> the handler check that it is, in fact, on a definiton and
> not a declaration and issuing a warning that it has no effect
> on a declaration, to avoid misunderstandings.

Hrm. I copied the code from the 'optimize' attribute to make this have
the same effect; as above, this new attribute offers clang compatibility
for something that can also be done with the existing optimize
attribute.

> If either a new attribute or a new option is introduced they
> need to be documented in the manual.  From your description
> it's not clear to me if it's just about disabling the expansion
> of the built-ins or if it's meant to prevent GCC from making
> any assumptions about their semantics in calls to the annotated
> functions.  That will likely be of interest to users and it
> matters for diagnostics.

Yes, I definitely need to add documentation. I'm actually using this
thread to help clarify precisely what those semantics should be; it's a
pretty subtle operation when compared with -fno-builtin.

> We will also need to add tests for the feature.  There are many
> built-ins in GCC but the patch only affects a small subset of
> them (e.g., I see it affects a few stdio and string functions
> but I'm not sure the printf family are among them -- all those
> handled in gimple-ssa-sprintf.c).

Yeah, I can get started on tests.

Keeping this operation from affecting things that it shouldn't while
hitting everything it should is a bit more difficult than I had hoped; I
suspect we'll be finding cases for some time unless I can discover an
easier place to hook this into.

> Besides its effect on codegen, I would also hope for a few test
> cases for warnings, those issued by the strlen pass in particular,
> to make sure their effects either are preserved or are disabled
> (whichever is appropriate).

Because the goal is to have the optimizer "forget" about the semantics of
builtins, but let them still be used when explicitly named in the code,
these warnings would still need to be enabled, so I left them in.

I think we need to get a clear description of what this attribute should
do before making many more changes in the code. Here's a first stab:

 no_builtin

This attribute directs GCC to not use knowledge of the semantics
of built-in functions to direct code optimization.  GCC will not
add or remove usage of builtin functions, or restructure code in
ways that depend on built-in knowledge of their
operation. Explicit use of builtin functions will still use any
internal implementations.

In contrast to -fno-builtin, the no_builtin attribute does not
disable declaration of the built-in functions, so messages
related to use and definition will still be enabled, and they
can still be used when named explicitly. In addition, the
no_builtin attribute can be applied on a function-at-a-time
level, while -fno-builtin must be specified on the command line.

-- 
-keith


signature.asc
Description: PGP signature


[PATCH] Add 'no_builtin' function attribute

2021-11-02 Thread Keith Packard via Gcc-patches
This attribute controls optimizations which make assumptions about the
semantics of builtin functions. Typical cases here are code which
match memcpy, calloc, sincos, or which call builtins like free.

This extends on things like the -ftree-loop-distribute-patterns
flag. That flag only covers converting loops into builtin calls, not
numerous other places where knowledge of builtin function semantics
changes the generated code.

The goal is to allow built-in functions to be declared by the compiler
and used directly by the application, but to disable optimizations
which take advantage of compiler knowledge about their semantics, and
to allow this optimization behavior to be changed for individual
functions.

One place where this behavior is especially useful is when compiling
the builtin functions that gcc knows about, as in the C
library. Currently, C library source code and build systems have
various kludges to work around the compilers operations in these
areas, using a combination of -fno-tree-loop-distribute-patterns,
-fno-builtins and even symbol aliases to keep GCC from generating
infinite recursions.

This can be applied globally to a file using the -fno-optimize-builtin
flag.

This disables optimizations which translate a sequence of builtin calls
into an equivalent sequence:

void
attribute((no_builtin))
sincos(double x, double *s, double *c)
{
*s = sin(x);
*c = cos(x);
}

This also avoids converting loops into builtin calls like this:

void *
attribute((no_builtin))
memcpy(void *__restrict__ dst, const void *__restrict__ src, size_t n)
{
char *d = dst;
const char *s = src;

while (n--)
*d++ = *s++;
return dst;
}

As well as disabling analysis of memory lifetimes around free as in
this example:

void *
attribute((no_builtin))
erase_and_free(void *ptr)
{
memset(ptr, '\0', malloc_usable_size(ptr));
free(ptr);
}

It also prevents converting builtin calls into inline code:

void
attribute((no_builtin))
copy_fixed(char *dest)
{
strcpy(dest, "hello world");
}

Clang has a more sophisticated version of this mechanism which
can disable specific builtins:

double
attribute((no_builtin("exp2")))
exp2(double x)
{
return pow (2.0, x);
}

The general approach in this change is to introduce checks in some
places where builtin functions are used to see if the specific
function is 'allowed' to be used for optimization, skipping the
optimization when the desired function has been disabled.

Three new functions, builtin_decl_implicit_opt_p,
builtin_decl_explicit_opt and builtin_decl_implicit_opt are introduced
which add checks for whether the compiler can assume standard
semantics for the specified function for purposes of
optimization. These are used throughout the compiler wherever
appropriate. Code which must use builtins for correct operation
(e.g. struct assignment) are not affected.

The machinery proposed here could be extended to support the
additional clang feature by extending the attribute parsing function
and creating a list of disabled builtins checked by the builtin_decl
functions described above.

Signed-off-by: Keith Packard 
---
 gcc/builtins.c   | 12 +++---
 gcc/c-family/c-attribs.c | 68 ++
 gcc/common.opt   |  4 ++
 gcc/gimple-fold.c| 72 ++--
 gcc/gimple-match-head.c  |  2 +-
 gcc/tree-loop-distribution.c |  7 
 gcc/tree-ssa-alias.c |  3 +-
 gcc/tree-ssa-strlen.c| 48 ++--
 gcc/tree-ssa-structalias.c   |  3 +-
 gcc/tree.h   | 39 +++
 10 files changed, 194 insertions(+), 64 deletions(-)

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 7d0f61fc98b..d665ee716e8 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -2061,7 +2061,7 @@ mathfn_built_in_1 (tree type, combined_fn fn, bool 
implicit_p)
   if (fcode2 == END_BUILTINS)
 return NULL_TREE;
 
-  if (implicit_p && !builtin_decl_implicit_p (fcode2))
+  if (implicit_p && !builtin_decl_implicit_opt_p (fcode2))
 return NULL_TREE;
 
   return builtin_decl_explicit (fcode2);
@@ -3481,9 +3481,9 @@ expand_builtin_stpcpy_1 (tree exp, rtx target, 
machine_mode mode)
   src = CALL_EXPR_ARG (exp, 1);
 
   /* If return value is ignored, transform stpcpy into strcpy.  */
-  if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
+  if (target == const0_rtx && builtin_decl_implicit_opt (BUILT_IN_STRCPY))
 {
-  tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
+  tree fn = builtin_decl_implicit_opt (BUILT_IN_STRCPY);
   tree result = build_call_nofold_loc (loc, fn, 2, 

Re: [PATCH] Add -fopt-builtin optimization option

2021-11-02 Thread Keith Packard via Gcc-patches
Richard Biener  writes:

> I don't think it reliably works the way you implement it.  It's also having
> more side-effects than what you document, in particular

Yeah, I made a 'minimal' patch that had the effect I needed, but it's
clearly in the wrong place as it disables the matching of builtins
against the incoming source code instead of the generation of new
builtin references from the tree.

> I think you may want to instead change builtin_decl_implicit
> to avoid code-generating a specific builtin.

Yup, I looked at that and there are numerous places which assume that
will work, so it will be a more complicated patch.

> Generally we'd also want sth like the clang attribute and _not_
> use optimize("") for this or a global flag_*, so the behavior can
> be more readily encoded in the IL.  In fact a flag on the call
> statement could be added to denote the desired effect on it.

Agreed, using the existing optimize attribute was a short-cut to
leverage the existing code handling that case. If we think providing
something that matches the clang attribute would be useful, it makes
sense to provide it using the same syntax.

> I also don't see the advantage compared to -fno-builtin[-foo].
> Declaring the function should be something that's already done.

The semantic of the clang option is not to completely disable access
to the given builtin function, but rather to stop the optimizer from
creating new builtin function references (either to a specific builtin,
or to all builtins).

If I could use "no-builtin" in a function attribute, I probably wouldn't
have bothered looking to implement the clang semantics, but -fno-builtin
isn't supported in this way. But, now that I think I understand the
behavior of attribute((no_builtin)) in clang, I think it has value
beyond what -fno-builtin performs as you can still gain access to
builtin functions when they are directly named.

I'll go implement changes in builtin_decl_implicit and all of the
affected call sites and see what that looks like.

Thanks much for your review!

-- 
-keith


signature.asc
Description: PGP signature


[PATCH] Add -fopt-builtin optimization option

2021-10-31 Thread Keith Packard via Gcc-patches
This option (enabled by default) controls optimizations which convert
a sequence of operations into an equivalent sequence that includes
calls to builtin functions. Typical cases here are code which matches
memcpy, calloc, sincos.

The -ftree-loop-distribute-patterns flag only covers converting loops
into builtin calls, not numerous other places where knowledge of
builtin function semantics changes the generated code.

The goal is to allow built-in functions to be declared by the compiler
and used directly by the application, but to disable optimizations
which create new calls to them, and to allow this optimization
behavior to be changed for individual functions by decorating the
function definition like this:

void
attribute((optimize("no-opt-builtin")))
sincos(double x, double *s, double *c)
{
*s = sin(x);
*c = cos(x);
}

This also avoids converting loops into library calls like this:

void *
attribute((optimize("no-opt-builtin")))
memcpy(void *__restrict__ dst, const void *__restrict__ src, size_t n)
{
char *d = dst;
const char *s = src;

while (n--)
*d++ = *s++;
return dst;
}

As well as disabling analysis of memory lifetimes around free as in
this example:

void *
attribute((optimize("no-opt-builtin")))
erase_and_free(void *ptr)
{
memset(ptr, '\0', malloc_usable_size(ptr));
free(ptr);
}

Clang has a more sophisticated version of this mechanism which
can disable all builtins, or disable a specific builtin:

double
attribute((no_builtin("exp2")))
exp2(double x)
{
return pow (2.0, x);
}

Signed-off-by: Keith Packard 
---
 gcc/builtins.c   | 6 ++
 gcc/common.opt   | 4 
 gcc/gimple.c | 3 +++
 gcc/tree-loop-distribution.c | 2 ++
 4 files changed, 15 insertions(+)

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 7d0f61fc98b..7aae57deab5 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1922,6 +1922,9 @@ mathfn_built_in_2 (tree type, combined_fn fn)
   built_in_function fcodef64x = END_BUILTINS;
   built_in_function fcodef128x = END_BUILTINS;
 
+  if (flag_no_opt_builtin)
+return END_BUILTINS;
+
   switch (fn)
 {
 #define SEQ_OF_CASE_MATHFN \
@@ -2125,6 +2128,9 @@ mathfn_built_in_type (combined_fn fn)
   case CFN_BUILT_IN_##MATHFN##L_R: \
 return long_double_type_node;
 
+  if (flag_no_opt_builtin)
+return NULL_TREE;
+
   switch (fn)
 {
 SEQ_OF_CASE_MATHFN
diff --git a/gcc/common.opt b/gcc/common.opt
index eeba1a727f2..d6111cc776a 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -2142,6 +2142,10 @@ fomit-frame-pointer
 Common Var(flag_omit_frame_pointer) Optimization
 When possible do not generate stack frames.
 
+fopt-builtin
+Common Var(flag_no_opt_builtin, 0) Optimization
+Match code sequences equivalent to builtin functions
+
 fopt-info
 Common Var(flag_opt_info) Optimization
 Enable all optimization info dumps on stderr.
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 22dd6417d19..5b82b9409c0 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -2790,6 +2790,9 @@ gimple_builtin_call_types_compatible_p (const gimple 
*stmt, tree fndecl)
 {
   gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN);
 
+  if (flag_no_opt_builtin)
+return false;
+
   tree ret = gimple_call_lhs (stmt);
   if (ret
   && !useless_type_conversion_p (TREE_TYPE (ret),
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 583c01a42d8..43f22a3c7ce 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -1859,6 +1859,7 @@ loop_distribution::classify_partition (loop_p loop,
 
   /* Perform general partition disqualification for builtins.  */
   if (volatiles_p
+  || flag_no_opt_builtin
   || !flag_tree_loop_distribute_patterns)
 return has_reduction;
 
@@ -3764,6 +3765,7 @@ loop_distribution::execute (function *fun)
   /* Don't distribute multiple exit edges loop, or cold loop when
  not doing pattern detection.  */
   if (!single_exit (loop)
+ || flag_no_opt_builtin
  || (!flag_tree_loop_distribute_patterns
  && !optimize_loop_for_speed_p (loop)))
continue;
-- 
2.33.0



Re: [PATCH 1/2] libstdc++: Add --enable-stdio=stdio_pure option [v2]

2020-12-10 Thread Keith Packard via Gcc-patches
Jonathan Wakely  writes:

> I'll do a bit more testing and push it next week.

That's awesome news. Thanks so much for you help; I'm looking forward to
having real C++ support for my embedded customers!

-- 
-keith


signature.asc
Description: PGP signature


[PATCH 1/2] libstdc++: Add --enable-stdio=stdio_pure option [v2]

2020-12-09 Thread Keith Packard via Gcc-patches
This option directs the library to only use simple stdio APIs instead
of using fileno to get the file descriptor for use with POSIX APIs.

Aided-by: Jonathan Wakely 
Signed-off-by: Keith Packard 

-

v2:
Switch from --enable-libstdcxx-pure-stdio to
--enable-stdio=stdio_pure based on a patch from Jonathan
Wakely .
---
 libstdc++-v3/acinclude.m4  | 20 ++
 libstdc++-v3/config/io/basic_file_stdio.cc | 46 +++---
 2 files changed, 54 insertions(+), 12 deletions(-)

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index fcd9ea3d23a..703962ce2d7 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -2862,24 +2862,30 @@ AC_DEFUN([GLIBCXX_ENABLE_PARALLEL], [
 
 
 dnl
-dnl Check for which I/O library to use:  stdio, or something specific.
+dnl Check for which I/O library to use:  stdio and POSIX, or pure stdio.
 dnl
-dnl Default is stdio.
+dnl Default is stdio_posix.
 dnl
 AC_DEFUN([GLIBCXX_ENABLE_CSTDIO], [
   AC_MSG_CHECKING([for underlying I/O to use])
   GLIBCXX_ENABLE(cstdio,stdio,[[[=PACKAGE]]],
-[use target-specific I/O package], [permit stdio])
+[use target-specific I/O package], [permit stdio|stdio_posix|stdio_pure])
 
-  # Now that libio has been removed, you can have any color you want as long
-  # as it's black.  This is one big no-op until other packages are added, but
-  # showing the framework never hurts.
+  # The only available I/O model is based on stdio, via basic_file_stdio.
+  # The default "stdio" is actually "stdio + POSIX" because it uses fdopen(3)
+  # to get a file descriptor and then uses read(3) and write(3) with it.
+  # The "stdio_pure" model doesn't use fdopen and only uses FILE* for I/O.
   case ${enable_cstdio} in
-stdio)
+stdio*)
   CSTDIO_H=config/io/c_io_stdio.h
   BASIC_FILE_H=config/io/basic_file_stdio.h
   BASIC_FILE_CC=config/io/basic_file_stdio.cc
   AC_MSG_RESULT(stdio)
+
+  if test "x$enable_cstdio" = "xstdio_pure" ; then
+   AC_DEFINE(_GLIBCXX_USE_STDIO_PURE, 1,
+ [Define to restrict std::__basic_file<> to stdio APIs.])
+  fi
   ;;
   esac
 
diff --git a/libstdc++-v3/config/io/basic_file_stdio.cc 
b/libstdc++-v3/config/io/basic_file_stdio.cc
index ba830fb9e97..eedffb017b6 100644
--- a/libstdc++-v3/config/io/basic_file_stdio.cc
+++ b/libstdc++-v3/config/io/basic_file_stdio.cc
@@ -111,13 +111,21 @@ namespace
 
   // Wrapper handling partial write.
   static std::streamsize
+#ifdef _GLIBCXX_USE_STDIO_PURE
+  xwrite(FILE *__file, const char* __s, std::streamsize __n)
+#else
   xwrite(int __fd, const char* __s, std::streamsize __n)
+#endif
   {
 std::streamsize __nleft = __n;
 
 for (;;)
   {
+#ifdef _GLIBCXX_USE_STDIO_PURE
+   const std::streamsize __ret = fwrite(__file, 1, __nleft, __file);
+#else
const std::streamsize __ret = write(__fd, __s, __nleft);
+#endif
if (__ret == -1L && errno == EINTR)
  continue;
if (__ret == -1L)
@@ -133,7 +141,7 @@ namespace
 return __n - __nleft;
   }
 
-#ifdef _GLIBCXX_HAVE_WRITEV
+#if defined(_GLIBCXX_HAVE_WRITEV) && !defined(_GLIBCXX_USE_STDIO_PURE)
   // Wrapper handling partial writev.
   static std::streamsize
   xwritev(int __fd, const char* __s1, std::streamsize __n1,
@@ -286,9 +294,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __basic_file::is_open() const throw ()
   { return _M_cfile != 0; }
 
+#ifndef _GLIBCCXX_USE_STDIO_PURE
   int
   __basic_file::fd() throw ()
   { return fileno(_M_cfile); }
+#endif
 
   __c_file*
   __basic_file::file() throw ()
@@ -315,28 +325,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
 streamsize __ret;
 do
+#ifdef _GLIBCXX_USE_STDIO_PURE
+  __ret = fread(__s, 1, __n, this->file());
+#else
   __ret = read(this->fd(), __s, __n);
+#endif
 while (__ret == -1L && errno == EINTR);
 return __ret;
   }
 
   streamsize
   __basic_file::xsputn(const char* __s, streamsize __n)
-  { return xwrite(this->fd(), __s, __n); }
+  {
+#ifdef _GLIBCXX_USE_STDIO_PURE
+return xwrite(this->file(), __s, __n);
+#else
+return xwrite(this->fd(), __s, __n);
+#endif
+  }
 
   streamsize
   __basic_file::xsputn_2(const char* __s1, streamsize __n1,
   const char* __s2, streamsize __n2)
   {
 streamsize __ret = 0;
-#ifdef _GLIBCXX_HAVE_WRITEV
+#if defined(_GLIBCXX_HAVE_WRITEV) && !defined(_GLIBCXX_USE_STDIO_PURE)
 __ret = xwritev(this->fd(), __s1, __n1, __s2, __n2);
 #else
 if (__n1)
+#ifdef _GLIBCXX_USE_STDIO_PURE
+  __ret = xwrite(this->file(), __s1, __n1);
+#else
   __ret = xwrite(this->fd(), __s1, __n1);
+#endif
 
 if (__ret == __n1)
+#ifdef _GLIBCXX_USE_STDIO_PURE
+  __ret += xwrite(this->file(), __s2, __n2);
+#else
   __ret += xwrite(this->fd(), __s2, __n2);
+#endif
 #endif
 return __ret;
   }
@@ -350,7 +378,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 if (__off > numeric_limits::max()
|| __off < numeric_limits::min())
 

[PATCH 2/2] Regenerate libstdc++-v3 autoconf files

2020-12-09 Thread Keith Packard via Gcc-patches
These are the changes to autoconf files for the stdio_pure patch

Signed-off-by: Keith Packard 
---
 libstdc++-v3/config.h.in |  3 +++
 libstdc++-v3/configure   | 17 -
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index 72faabfb2c1..c0c166715cb 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -1022,6 +1022,9 @@
 /* Define if POSIX read/write locks are available in . */
 #undef _GLIBCXX_USE_PTHREAD_RWLOCK_T
 
+/* Define to restrict std::__basic_file<> to stdio APIs. */
+#undef _GLIBCXX_USE_STDIO_PURE
+
 /* Define if /dev/random and /dev/urandom are available for the random_device
of TR1 (Chapter 5.1). */
 #undef _GLIBCXX_USE_RANDOM_TR1
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index d128de2f186..36c61a77d07 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -16376,7 +16376,7 @@ $as_echo_n "checking for underlying I/O to use... " 
>&6; }
 if test "${enable_cstdio+set}" = set; then :
   enableval=$enable_cstdio;
   case "$enableval" in
-   stdio) ;;
+   stdio|stdio_posix|stdio_pure) ;;
*) as_fn_error $? "Unknown argument to enable/disable cstdio" "$LINENO" 
5 ;;
esac
 
@@ -16386,16 +16386,23 @@ fi
 
 
 
-  # Now that libio has been removed, you can have any color you want as long
-  # as it's black.  This is one big no-op until other packages are added, but
-  # showing the framework never hurts.
+  # The only available I/O model is based on stdio, via basic_file_stdio.
+  # The default "stdio" is actually "stdio + POSIX" because it uses fdopen(3)
+  # to get a file descriptor and then uses read(3) and write(3) with it.
+  # The "stdio_pure" model doesn't use fdopen and only uses FILE* for I/O.
   case ${enable_cstdio} in
-stdio)
+stdio*)
   CSTDIO_H=config/io/c_io_stdio.h
   BASIC_FILE_H=config/io/basic_file_stdio.h
   BASIC_FILE_CC=config/io/basic_file_stdio.cc
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: stdio" >&5
 $as_echo "stdio" >&6; }
+
+  if test "x$enable_cstdio" = "xstdio_pure" ; then
+
+$as_echo "#define _GLIBCXX_USE_STDIO_PURE 1" >>confdefs.h
+
+  fi
   ;;
   esac
 
-- 
2.29.2



[PATCH 0/2] Support libc with stdio-only I/O in libstdc++

2020-12-09 Thread Keith Packard via Gcc-patches
The current libstdc++ basic_file_stdio.cc code assumes a POSIX API
underneath the stdio implementation provided by the host libc. This
means that the host must provide a fairly broad POSIX file API,
including read, write, open, close, lseek and ioctl.

This patch changes basic_file_stdio.cc to only use basic ANSI-C stdio
functions, allowing it to be used with libc implementations like
picolibc which may not have a POSIX operating system underneath.

This is version 2 of the patch. This version uses the existing
--enable-stdio option, extending that to add 'stdio_pure' for this
mode using a patch created by Jonathan Wakely 




Re: [PATCH 1/2] libstdc++: Add --enable-pure-stdio-libstdcxx option

2020-12-09 Thread Keith Packard via Gcc-patches
Jonathan Wakely  writes:

> OK. In principle, changes to avoid using the POSIX APIs are definitely
> fine. I would like to combine your new configure switch with the
> existing --enable-cstdio one though.
>
> How about the attached change for acinclude.m4 which would allow you
> to do --enable-cstdio=stdio_pure? (It also adds "stdio_posix" as a
> more accurate alternative spelling of the current "stdio" option.)

Oh, that's very nice. I'll integrate that into my patch and send it
along.

-- 
-keith


signature.asc
Description: PGP signature


Re: [PATCH 1/2] libstdc++: Add --enable-pure-stdio-libstdcxx option

2020-12-07 Thread Keith Packard via Gcc-patches
Jonathan Wakely  writes:

> GCC changelog files are autogenerated now, so patches should not touch
> them. Just include the ChangeLog entry in the Git commit log (which
> will usually end up being quoted in the patch and/or the email body of
> the mail to gcc-patches).

Awesome.

> I think the right way to do this (or at least, the way that was
> intended when basic_file_stdio.cc was added) is to provide a new file
> and change GLIBCXX_ENABLE_CSTDIO in acinclude.m4 to use that new file.
>
> The two biggest downsides of that are that it duplicates a lot of the
> file (because the diffs for your changes are small) and that the
> correct name for your new file is already taken!

I can definitely see a reason to use a separate file when implementing
the basic_file interface on top of something other than stdio, but
this patch doesn't do that -- it only changes the interaction between
basic_file and stdio in a few places.

I think it makes the best long-term sense to leave everything in
basic_file_stdio.cc and avoid having the two implementations diverge in
the future.

> However, it's rather late in the GCC 11 process to make a change like
> that (even though it's really just renaming some files). Would you be
> OK waiting until after GCC 11 is released (in 4-5 months) to do it
> "properly"? Is this blocking something that would require doing it
> sooner?

This patch enables the use of C++ with picolibc, a libc designed for 32-
and 64- bit embedded systems.

Right now, I'm working on getting picolibc support integrated into
Zephyr, which uses toolchains build by crosstool-ng. I've gotten
picolibc support merged to crosstool-ng, but the Zephyr developers are
interested in having a single toolchain support three different libc
implementations (newlib, newlib-nano and picolibc), but that's blocked
on having C++ support available in all three libraries.

So, you're at the bottom of my current dependency graph :-)

I don't particularly need this released in gcc, but I would like to
get patches reviewed and the general approach agreed on so that I can
feel more confident in preparing patches to be applied to gcc in
crosstool-ng itself.

Once that's done, I'll also be able to release new Debian packages of
GCC for embedded ARM and RISC-V and have those include suitable patches
so that we can support embedded C++ development there too. 

-- 
-keith


signature.asc
Description: PGP signature