]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
adding libcody to lto-wrapper, with some leftover debugging code
authorJohn Ravi <jjravi@ncsu.edu>
Sun, 28 Jun 2020 00:21:36 +0000 (17:21 -0700)
committerJohn Ravi <jjravi@ncsu.edu>
Sun, 28 Jun 2020 00:21:36 +0000 (17:21 -0700)
14 files changed:
Makefile.in
Makefile.tpl
configure
configure.ac
gcc/Makefile.in
gcc/config.in
gcc/configure
gcc/configure.ac
gcc/cp/Make-lang.in
gcc/lto-wrapper.c
gcc/mapper-client.cc [new file with mode: 0644]
gcc/mapper-resolver.cc [new file with mode: 0644]
gcc/mapper-server.cc [new file with mode: 0644]
gcc/mapper.h [new file with mode: 0644]

index 36e369df6e7e2fb01e3e2adcf863faa08cc15ce4..345ef1b76e2c682f3e47215f65f53346c8844746 100644 (file)
@@ -226,6 +226,8 @@ HOST_EXPORTS = \
        GMPINC="$(HOST_GMPINC)"; export GMPINC; \
        ISLLIBS="$(HOST_ISLLIBS)"; export ISLLIBS; \
        ISLINC="$(HOST_ISLINC)"; export ISLINC; \
+       CODYLIB="$(HOST_CODYLIB)"; export CODYLIB; \
+       CODYLIBINC="$(HOST_CODYLIBINC)"; export CODYLIBINC; \
        LIBELFLIBS="$(HOST_LIBELFLIBS)"; export LIBELFLIBS; \
        LIBELFINC="$(HOST_LIBELFINC)"; export LIBELFINC; \
        XGCC_FLAGS_FOR_TARGET="$(XGCC_FLAGS_FOR_TARGET)"; export XGCC_FLAGS_FOR_TARGET; \
@@ -329,6 +331,10 @@ HOST_GMPINC = @gmpinc@
 HOST_ISLLIBS = @isllibs@
 HOST_ISLINC = @islinc@
 
+# Where to find libcody
+HOST_CODYLIB = @codylib@
+HOST_CODYLIBINC = @codylibinc@
+
 # Where to find libelf
 HOST_LIBELFLIBS = @libelflibs@
 HOST_LIBELFINC = @libelfinc@
index efed1511750412f7dff03a363779b78c6ecccb41..6b1a4d723028cbe0aaed44b38a00dc90541d6fee 100644 (file)
@@ -229,6 +229,8 @@ HOST_EXPORTS = \
        GMPINC="$(HOST_GMPINC)"; export GMPINC; \
        ISLLIBS="$(HOST_ISLLIBS)"; export ISLLIBS; \
        ISLINC="$(HOST_ISLINC)"; export ISLINC; \
+       CODYLIB="$(HOST_CODYLIB)"; export CODYLIB; \
+       CODYLIBINC="$(HOST_CODYLIBINC)"; export CODYLIBINC; \
        LIBELFLIBS="$(HOST_LIBELFLIBS)"; export LIBELFLIBS; \
        LIBELFINC="$(HOST_LIBELFINC)"; export LIBELFINC; \
        XGCC_FLAGS_FOR_TARGET="$(XGCC_FLAGS_FOR_TARGET)"; export XGCC_FLAGS_FOR_TARGET; \
@@ -332,6 +334,10 @@ HOST_GMPINC = @gmpinc@
 HOST_ISLLIBS = @isllibs@
 HOST_ISLINC = @islinc@
 
+# Where to find libcody
+HOST_CODYLIB = @codylib@
+HOST_CODYLIBINC = @codylibinc@
+
 # Where to find libelf
 HOST_LIBELFLIBS = @libelflibs@
 HOST_LIBELFINC = @libelfinc@
index a0c5aca9e8d5cae2782c8fe4625a501853dc226a..fc2666567335f443e6f64a61dde554672cfda50b 100755 (executable)
--- a/configure
+++ b/configure
@@ -688,6 +688,8 @@ poststage1_ldflags
 poststage1_libs
 stage1_ldflags
 stage1_libs
+codylibinc
+codylib
 extra_isl_gmp_configure_flags
 extra_mpc_mpfr_configure_flags
 extra_mpc_gmp_configure_flags
@@ -755,6 +757,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -806,6 +809,9 @@ with_gmp_dir
 with_gmp
 with_gmp_include
 with_gmp_lib
+with_libcody
+with_libcody_include
+with_libcody_lib
 with_stage1_libs
 with_static_standard_libraries
 with_stage1_ldflags
@@ -921,6 +927,7 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE}'
@@ -1173,6 +1180,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1310,7 +1326,7 @@ fi
 for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
                datadir sysconfdir sharedstatedir localstatedir includedir \
                oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-               libdir localedir mandir
+               libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1470,6 +1486,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -1580,6 +1597,14 @@ Optional Packages:
                           --with-gmp-lib=PATH/lib
   --with-gmp-include=PATH specify directory for installed GMP include files
   --with-gmp-lib=PATH     specify directory for the installed GMP library
+  --with-libcody=PATH     specify prefix directory for installed libcody
+                          package. Equivalent to
+                          --with-libcody-include=PATH/include plus
+                          --with-libcody-lib=PATH/lib
+  --with-libcody-include=PATH
+                          specify directory for installed libcody include
+                          files
+  --with-libcody-lib=PATH specify directory for the installed libcody library
   --with-stage1-libs=LIBS libraries for stage1
   --with-static-standard-libraries
                           use -static-libstdc++ and -static-libgcc
@@ -6938,6 +6963,39 @@ fi
 
 
 
+# Specify a location for libcody
+
+# Check whether --with-libcody was given.
+if test "${with_libcody+set}" = set; then :
+  withval=$with_libcody;
+fi
+
+
+# Check whether --with-libcody-include was given.
+if test "${with_libcody_include+set}" = set; then :
+  withval=$with_libcody_include;
+fi
+
+
+# Check whether --with-libcody-lib was given.
+if test "${with_libcody_lib+set}" = set; then :
+  withval=$with_libcody_lib;
+fi
+
+
+if test "x$with_libcody" != x; then
+  codylib="-L$with_libcody/lib"
+  codylibinc="-I$with_libcody/include"
+fi
+if test "x$with_libcody_include" != x; then
+  codylibinc="-I$with_libcody_include"
+fi
+if test "x$with_libcody_lib" != x; then
+  codylib="-L$with_libcody_lib"
+fi
+
+
+
 # Libraries to use for stage1 or when not bootstrapping.
 
 # Check whether --with-stage1-libs was given.
index 1a53ed418e4d97606356b14a17b50186c79adcd3..c1a1f2f9305ea441e3bc3fa9925fd619bd1c54b1 100644 (file)
@@ -1708,6 +1708,32 @@ AC_SUBST(extra_mpc_gmp_configure_flags)
 AC_SUBST(extra_mpc_mpfr_configure_flags)
 AC_SUBST(extra_isl_gmp_configure_flags)
 
+# Specify a location for libcody
+AC_ARG_WITH(libcody,
+[AS_HELP_STRING([--with-libcody=PATH],
+               [specify prefix directory for installed libcody package.
+                Equivalent to --with-libcody-include=PATH/include
+                plus --with-libcody-lib=PATH/lib])])
+AC_ARG_WITH(libcody-include,
+[AS_HELP_STRING([--with-libcody-include=PATH],
+               [specify directory for installed libcody include files])])
+AC_ARG_WITH(libcody-lib,
+[AS_HELP_STRING([--with-libcody-lib=PATH],
+               [specify directory for the installed libcody library])])
+
+if test "x$with_libcody" != x; then
+  codylib="-L$with_libcody/lib"
+  codylibinc="-I$with_libcody/include"
+fi
+if test "x$with_libcody_include" != x; then
+  codylibinc="-I$with_libcody_include"
+fi
+if test "x$with_libcody_lib" != x; then
+  codylib="-L$with_libcody_lib"
+fi
+AC_SUBST(codylib)
+AC_SUBST(codylibinc)
+
 # Libraries to use for stage1 or when not bootstrapping.
 AC_ARG_WITH(stage1-libs,
 [AS_HELP_STRING([--with-stage1-libs=LIBS], [libraries for stage1])],
index d5dcc03d59be696d535d0df21de8f63ab58fb894..678561762e124f91ce9163af7595a6bf5a78f23a 100644 (file)
@@ -388,6 +388,10 @@ GMPINC = @GMPINC@
 ISLLIBS = @ISLLIBS@
 ISLINC = @ISLINC@
 
+# How to find libcody
+CODYLIB = @CODYLIB@ -lcody
+CODYLIBINC = @CODYLIBINC@
+
 # Set to 'yes' if the LTO front end is enabled.
 enable_lto = @enable_lto@
 
@@ -1069,7 +1073,7 @@ BUILD_LIBDEPS= $(BUILD_LIBIBERTY)
 # and the system's installed libraries.
 LIBS = @LIBS@ libcommon.a $(CPPLIB) $(LIBINTL) $(LIBICONV) $(LIBBACKTRACE) \
        $(LIBIBERTY) $(LIBDECNUMBER) $(HOST_LIBS)
-BACKENDLIBS = $(ISLLIBS) $(GMPLIBS) $(PLUGINLIBS) $(HOST_LIBS) \
+BACKENDLIBS = $(ISLLIBS) $(GMPLIBS) $(CODYLIB) $(PLUGINLIBS) $(HOST_LIBS) \
        $(ZLIB) $(ZSTD_LIB)
 # Any system libraries needed just for GNAT.
 SYSLIBS = @GNAT_LIBEXC@
@@ -1103,7 +1107,7 @@ BUILD_ERRORS = build/errors.o
 # libintl.h will be found in ../intl if we are using the included libintl.
 INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
           -I$(srcdir)/../include @INCINTL@ \
-          $(CPPINC) $(GMPINC) $(DECNUMINC) $(BACKTRACEINC) \
+          $(CPPINC) $(GMPINC) $(CODYLIBINC) $(DECNUMINC) $(BACKTRACEINC) \
           $(ISLINC)
 
 COMPILE.base = $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) -o $@
@@ -1688,7 +1692,7 @@ ALL_HOST_BACKEND_OBJS = $(GCC_OBJS) $(OBJS) $(OBJS-libcommon) \
   $(OBJS-libcommon-target) main.o c-family/cppspec.o \
   $(COLLECT2_OBJS) $(EXTRA_GCC_OBJS) $(GCOV_OBJS) $(GCOV_DUMP_OBJS) \
   $(GCOV_TOOL_OBJS) $(GENGTYPE_OBJS) gcc-ar.o gcc-nm.o gcc-ranlib.o \
-  lto-wrapper.o collect-utils.o
+  lto-wrapper.o mapper-client.o mapper-resolver.o mapper-server.o collect-utils.o
 
 # for anything that is shared use the cc1plus profile data, as that
 # is likely the most exercised during the build
@@ -1763,16 +1767,22 @@ SELFTEST_DEPS = $(GCC_PASSES) stmp-int-hdrs $(srcdir)/testsuite/selftests
 gnat_install_lib = @gnat_install_lib@
 
 # per-language makefile fragments
--include $(LANG_MAKEFRAGS)
+ifneq ($(LANG_MAKEFRAGS),)
+include $(LANG_MAKEFRAGS)
+endif
 
 # target and host overrides must follow the per-language makefile fragments
 # so they can override or augment language-specific variables
 
 # target overrides
--include $(tmake_file)
+ifneq ($(tmake_file),)
+include $(tmake_file)
+endif
 
 # host overrides
--include $(xmake_file)
+ifneq ($(xmake_file),)
+include $(xmake_file)
+endif
 
 # all-tree.def includes all the tree.def files.
 all-tree.def: s-alltree; @true
@@ -2187,11 +2197,16 @@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
 CFLAGS-collect2.o += -DTARGET_MACHINE=\"$(target_noncanonical)\" \
        @TARGET_SYSTEM_ROOT_DEFINE@
 
-LTO_WRAPPER_OBJS = lto-wrapper.o collect-utils.o ggc-none.o
+LTO_WRAPPER_OBJS = lto-wrapper.o mapper-client.o mapper-resolver.o collect-utils.o ggc-none.o
 lto-wrapper$(exeext): $(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBDEPS)
        +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o T$@ \
-          $(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBS)
+          $(LTO_WRAPPER_OBJS) libcommon-target.a $(CODYLIB) $(LIBS)
        mv -f T$@ $@
+       
+MAPPER_SERVER_OBJS := mapper-server.o mapper-resolver.o
+mapper-server$(exeext): $(MAPPER_SERVER_OBJS) $(LIBDEPS)
+       +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+       $(MAPPER_SERVER_OBJS) version.o $(CODYLIB) $(LIBIBERTY) $(LIBINTL)
 
 # Files used by all variants of C or by the stand-alone pre-processor.
 
@@ -3683,6 +3698,10 @@ install-common: native lang.install-common installdirs
            gcov-dump$(exeext) $(DESTDIR)$(bindir)/$(GCOV_DUMP_INSTALL_NAME)$(exeext); \
          fi; \
        fi
+       rm -f $(DESTDIR)$(libexecsubdir)/mapper-server$(exeext)
+       $(INSTALL_PROGRAM) mapper-server$(exeext) \
+         $(DESTDIR)$(libexecsubdir)/mapper-server$(exeext)
+
 
 # Install the driver program as $(target_noncanonical)-gcc,
 # $(target_noncanonical)-gcc-$(version), and also as gcc if native.
index 364eba4773744f2a5b415dbccc01242df1fc289f..d297dbc09d46f36e05836803f68195762868c055 100644 (file)
 #endif
 
 
+/* Define if accept4 provided. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_ACCEPT4
+#endif
+
+
+/* Define if AF_INET6 supported. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AF_INET6
+#endif
+
+
+/* Define if AF_UNIX supported. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AF_UNIX
+#endif
+
+
 /* Define if your assembler supports architecture modifiers. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_ARCHITECTURE_MODIFIERS
 #endif
 
 
+/* Define if epoll_create, epoll_ctl, epoll_pwait provided. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_EPOLL
+#endif
+
+
+/* Define to 1 if you have the `execv' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_EXECV
+#endif
+
+
 /* Define to 1 if you have the <ext/hash_map> header file. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_EXT_HASH_MAP
 #endif
 
 
+/* Define if inet_ntop provided. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_INET_NTOP
+#endif
+
+
 /* Define 0/1 if .init_array/.fini_array sections are available and working.
    */
 #ifndef USED_FOR_TARGET
 #endif
 
 
+/* Define to 1 if you have the `memrchr' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MEMRCHR
+#endif
+
+
 /* Define to 1 if you have the `mmap' function. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_MMAP
 #endif
 
 
+/* Define to 1 if you have the `posix_fallocate' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_POSIX_FALLOCATE
+#endif
+
+
+/* Define if pselect provided. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_PSELECT
+#endif
+
+
 /* Define to 1 if you have the `putchar_unlocked' function. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_PUTCHAR_UNLOCKED
 #endif
 
 
+/* Define if select provided. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SELECT
+#endif
+
+
 /* Define to 1 if you have the `setlocale' function. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_SETLOCALE
 #endif
 
 
+/* Define if <sys/signal.h> defines sighandler_t */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SIGHANDLER_T
+#endif
+
+
 /* Define if the system-provided CRTs are present on Solaris. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_SOLARIS_CRTS
index f224679ed3ee5e4bbd80318a3eb2f32561dfd89c..6a69799836d6b186c5a6ebe00071fecdbc32e7af 100755 (executable)
@@ -639,6 +639,8 @@ PICFLAG
 enable_host_shared
 enable_plugin
 pluginlibs
+CODYLIBINC
+CODYLIB
 ISLINC
 ISLLIBS
 GMPINC
@@ -1038,7 +1040,9 @@ CPP
 GMPLIBS
 GMPINC
 ISLLIBS
-ISLINC'
+ISLINC
+CODYLIB
+CODYLIBINC'
 
 
 # Initialize some variables set by options.
@@ -1866,6 +1870,8 @@ Some influential environment variables:
   GMPINC      How to find GMP include files
   ISLLIBS     How to link isl
   ISLINC      How to find isl include files
+  CODYLIB     How to link Cody
+  CODYLIBINC  How to find Cody include files
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -10200,6 +10206,14 @@ _ACEOF
 
 fi
 
+ac_fn_cxx_check_type "$LINENO" "sighander_t" "ac_cv_type_sighander_t" "signal.h
+"
+if test "x$ac_cv_type_sighander_t" = xyes; then :
+
+$as_echo "#define HAVE_SIGHANDLER_T 1" >>confdefs.h
+
+fi
+
 
 
 ac_fn_cxx_check_header_preproc "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h"
@@ -11923,6 +11937,296 @@ $as_echo "#define HOST_HAS_F_SETLKW 1" >>confdefs.h
 
 fi
 
+# C++ Modules would like some networking features to provide the mapping
+# server.  You can still use modules without them though.
+# The following network-related checks could probably do with some
+# Windows and other non-linux defenses and checking.
+
+# Local socket connectivity wants AF_UNIX networking
+# Check for AF_UNIX networking
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for AF_UNIX" >&5
+$as_echo_n "checking for AF_UNIX... " >&6; }
+if ${ac_cv_af_unix+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+int
+main ()
+{
+
+sockaddr_un un;
+un.sun_family = AF_UNSPEC;
+int fd = socket (AF_UNIX, SOCK_STREAM, 0);
+connect (fd, (sockaddr *)&un, sizeof (un));
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_af_unix=yes
+else
+  ac_cv_af_unix=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_af_unix" >&5
+$as_echo "$ac_cv_af_unix" >&6; }
+if test $ac_cv_af_unix = yes; then
+
+$as_echo "#define HAVE_AF_UNIX 1" >>confdefs.h
+
+fi
+
+# Remote socket connectivity wants AF_INET6 networking
+# Check for AF_INET6 networking
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for AF_INET6" >&5
+$as_echo_n "checking for AF_INET6... " >&6; }
+if ${ac_cv_af_inet6+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+int
+main ()
+{
+
+sockaddr_in6 in6;
+in6.sin6_family = AF_UNSPEC;
+struct addrinfo *addrs = 0;
+struct addrinfo hints;
+hints.ai_flags = 0;
+hints.ai_family = AF_INET6;
+hints.ai_socktype = SOCK_STREAM;
+hints.ai_protocol = 0;
+hints.ai_canonname = 0;
+hints.ai_addr = 0;
+hints.ai_next = 0;
+int e = getaddrinfo ("localhost", 0, &hints, &addrs);
+const char *str = gai_strerror (e);
+freeaddrinfo (addrs);
+int fd = socket (AF_INET6, SOCK_STREAM, 0);
+connect (fd, (sockaddr *)&in6, sizeof (in6));
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_af_inet6=yes
+else
+  ac_cv_af_inet6=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_af_inet6" >&5
+$as_echo "$ac_cv_af_inet6" >&6; }
+if test $ac_cv_af_inet6 = yes; then
+
+$as_echo "#define HAVE_AF_INET6 1" >>confdefs.h
+
+fi
+
+# Efficient server response wants epoll
+# Check for epoll_create, epoll_ctl, epoll_pwait
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for epoll" >&5
+$as_echo_n "checking for epoll... " >&6; }
+if ${ac_cv_epoll+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/epoll.h>
+int
+main ()
+{
+
+int fd = epoll_create (1);
+epoll_event ev;
+ev.events = EPOLLIN;
+ev.data.fd = 0;
+epoll_ctl (fd, EPOLL_CTL_ADD, 0, &ev);
+epoll_pwait (fd, 0, 0, -1, 0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_epoll=yes
+else
+  ac_cv_epoll=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_epoll" >&5
+$as_echo "$ac_cv_epoll" >&6; }
+if test $ac_cv_epoll = yes; then
+
+$as_echo "#define HAVE_EPOLL 1" >>confdefs.h
+
+fi
+
+# If we can't use epoll, try pselect.
+# Check for pselect
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pselect" >&5
+$as_echo_n "checking for pselect... " >&6; }
+if ${ac_cv_pselect+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/select.h>
+int
+main ()
+{
+
+pselect (0, 0, 0, 0, 0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_pselect=yes
+else
+  ac_cv_pselect=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_pselect" >&5
+$as_echo "$ac_cv_pselect" >&6; }
+if test $ac_cv_pselect = yes; then
+
+$as_echo "#define HAVE_PSELECT 1" >>confdefs.h
+
+fi
+
+# And failing that, use good old select.
+# If we can't even use this, the server is serialized.
+# Check for select
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for select" >&5
+$as_echo_n "checking for select... " >&6; }
+if ${ac_cv_select+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/select.h>
+int
+main ()
+{
+
+select (0, 0, 0, 0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_select=yes
+else
+  ac_cv_select=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_select" >&5
+$as_echo "$ac_cv_select" >&6; }
+if test $ac_cv_select = yes; then
+
+$as_echo "#define HAVE_SELECT 1" >>confdefs.h
+
+fi
+
+# Avoid some fnctl calls by using accept4, when available.
+# Check for accept4
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for accept4" >&5
+$as_echo_n "checking for accept4... " >&6; }
+if ${ac_cv_accept4+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/socket.h>
+int
+main ()
+{
+
+int err = accept4 (1, 0, 0, SOCK_NONBLOCK);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_accept4=yes
+else
+  ac_cv_accept4=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_accept4" >&5
+$as_echo "$ac_cv_accept4" >&6; }
+if test $ac_cv_accept4 = yes; then
+
+$as_echo "#define HAVE_ACCEPT4 1" >>confdefs.h
+
+fi
+
+# For better server messages, look for a way to stringize network addresses
+# Check for inet_ntop
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntop" >&5
+$as_echo_n "checking for inet_ntop... " >&6; }
+if ${ac_cv_inet_ntop+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+int
+main ()
+{
+
+sockaddr_in6 in6;
+char buf[INET6_ADDRSTRLEN];
+const char *str = inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_inet_ntop=yes
+else
+  ac_cv_inet_ntop=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_inet_ntop" >&5
+$as_echo "$ac_cv_inet_ntop" >&6; }
+if test $ac_cv_inet_ntop = yes; then
+
+$as_echo "#define HAVE_INET_NTOP 1" >>confdefs.h
+
+fi
+
 # Restore CFLAGS, CXXFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
 CFLAGS="$saved_CFLAGS"
 CXXFLAGS="$saved_CXXFLAGS"
index e83f0833ef3fb19d6f2d68cc3c24e039da997a08..81b6cb70d2c06c9191bbbc4a491e78eb592925f4 100644 (file)
@@ -1439,6 +1439,10 @@ fi
 
 AC_CHECK_TYPE(ssize_t, int)
 AC_CHECK_TYPE(caddr_t, char *)
+AC_CHECK_TYPE(sighander_t,
+  AC_DEFINE(HAVE_SIGHANDLER_T, 1,
+    [Define if <sys/signal.h> defines sighandler_t]),
+    ,signal.h)
 
 GCC_AC_FUNC_MMAP_BLACKLIST
 
@@ -1584,6 +1588,136 @@ if test $ac_cv_f_setlkw = yes; then
   [Define if F_SETLKW supported by fcntl.])
 fi
 
+# C++ Modules would like some networking features to provide the mapping
+# server.  You can still use modules without them though.
+# The following network-related checks could probably do with some
+# Windows and other non-linux defenses and checking.
+# C++ LTO will take advantage of these networking features too.
+
+# Local socket connectivity wants AF_UNIX networking
+# Check for AF_UNIX networking
+AC_CACHE_CHECK(for AF_UNIX, ac_cv_af_unix, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>]],[[
+sockaddr_un un;
+un.sun_family = AF_UNSPEC;
+int fd = socket (AF_UNIX, SOCK_STREAM, 0);
+connect (fd, (sockaddr *)&un, sizeof (un));]])],
+[ac_cv_af_unix=yes],
+[ac_cv_af_unix=no])])
+if test $ac_cv_af_unix = yes; then
+  AC_DEFINE(HAVE_AF_UNIX, 1,
+  [Define if AF_UNIX supported.])
+fi
+
+# Remote socket connectivity wants AF_INET6 networking
+# Check for AF_INET6 networking
+AC_CACHE_CHECK(for AF_INET6, ac_cv_af_inet6, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>]],[[
+sockaddr_in6 in6;
+in6.sin6_family = AF_UNSPEC;
+struct addrinfo *addrs = 0;
+struct addrinfo hints;
+hints.ai_flags = 0;
+hints.ai_family = AF_INET6;
+hints.ai_socktype = SOCK_STREAM;
+hints.ai_protocol = 0;
+hints.ai_canonname = 0;
+hints.ai_addr = 0;
+hints.ai_next = 0;
+int e = getaddrinfo ("localhost", 0, &hints, &addrs);
+const char *str = gai_strerror (e);
+freeaddrinfo (addrs);
+int fd = socket (AF_INET6, SOCK_STREAM, 0);
+connect (fd, (sockaddr *)&in6, sizeof (in6));]])],
+[ac_cv_af_inet6=yes],
+[ac_cv_af_inet6=no])])
+if test $ac_cv_af_inet6 = yes; then
+  AC_DEFINE(HAVE_AF_INET6, 1,
+  [Define if AF_INET6 supported.])
+fi
+
+# Efficient server response wants epoll
+# Check for epoll_create, epoll_ctl, epoll_pwait
+AC_CACHE_CHECK(for epoll, ac_cv_epoll, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/epoll.h>]],[[
+int fd = epoll_create (1);
+epoll_event ev;
+ev.events = EPOLLIN;
+ev.data.fd = 0;
+epoll_ctl (fd, EPOLL_CTL_ADD, 0, &ev);
+epoll_pwait (fd, 0, 0, -1, 0);]])],
+[ac_cv_epoll=yes],
+[ac_cv_epoll=no])])
+if test $ac_cv_epoll = yes; then
+  AC_DEFINE(HAVE_EPOLL, 1,
+  [Define if epoll_create, epoll_ctl, epoll_pwait provided.])
+fi
+
+# If we can't use epoll, try pselect.
+# Check for pselect
+AC_CACHE_CHECK(for pselect, ac_cv_pselect, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/select.h>]],[[
+pselect (0, 0, 0, 0, 0, 0);]])],
+[ac_cv_pselect=yes],
+[ac_cv_pselect=no])])
+if test $ac_cv_pselect = yes; then
+  AC_DEFINE(HAVE_PSELECT, 1,
+  [Define if pselect provided.])
+fi
+
+# And failing that, use good old select.
+# If we can't even use this, the server is serialized.
+# Check for select
+AC_CACHE_CHECK(for select, ac_cv_select, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/select.h>]],[[
+select (0, 0, 0, 0, 0);]])],
+[ac_cv_select=yes],
+[ac_cv_select=no])])
+if test $ac_cv_select = yes; then
+  AC_DEFINE(HAVE_SELECT, 1,
+  [Define if select provided.])
+fi
+
+# Avoid some fnctl calls by using accept4, when available.
+# Check for accept4
+AC_CACHE_CHECK(for accept4, ac_cv_accept4, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/socket.h>]],[[
+int err = accept4 (1, 0, 0, SOCK_NONBLOCK);]])],
+[ac_cv_accept4=yes],
+[ac_cv_accept4=no])])
+if test $ac_cv_accept4 = yes; then
+  AC_DEFINE(HAVE_ACCEPT4, 1,
+  [Define if accept4 provided.])
+fi
+
+# For better server messages, look for a way to stringize network addresses
+# Check for inet_ntop
+AC_CACHE_CHECK(for inet_ntop, ac_cv_inet_ntop, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <arpa/inet.h>
+#include <netinet/in.h>]],[[
+sockaddr_in6 in6;
+char buf[INET6_ADDRSTRLEN];
+const char *str = inet_ntop (AF_INET6, &in6, buf, sizeof (buf));]])],
+[ac_cv_inet_ntop=yes],
+[ac_cv_inet_ntop=no])])
+if test $ac_cv_inet_ntop = yes; then
+  AC_DEFINE(HAVE_INET_NTOP, 1,
+  [Define if inet_ntop provided.])
+fi
+
 # Restore CFLAGS, CXXFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
 CFLAGS="$saved_CFLAGS"
 CXXFLAGS="$saved_CXXFLAGS"
@@ -6698,6 +6832,9 @@ if test "x${ISLLIBS}" != "x" ; then
    AC_DEFINE(HAVE_isl, 1, [Define if isl is in use.])
 fi
 
+AC_ARG_VAR(CODYLIB,[How to link Cody])
+AC_ARG_VAR(CODYLIBINC,[How to find Cody include files])
+
 GCC_ENABLE_PLUGINS
 AC_SUBST(pluginlibs)
 AC_SUBST(enable_plugin)
index 7896591dd4b2b995b05bc89e807af57680dc4a24..41de295ef9ccad9847eb8369e5a866d0b39af5e0 100644 (file)
@@ -46,7 +46,7 @@ CP_PLUGIN_HEADERS := cp-tree.h cxx-pretty-print.h name-lookup.h type-utils.h ope
 # Note that it would be nice to move the dependency on g++
 # into the C++ rule, but that needs a little bit of work
 # to do the right thing within all.cross.
-c++: cc1plus$(exeext)
+c++: cc1plus$(exeext) mapper-server$(exeext) 
 
 # Tell GNU make to ignore these if they exist.
 .PHONY: c++
index 939a83ac73a4e8238395b60f0bcdca88c78a8aeb..ac77e537e19bf445067deb5df27cc85518f1cb0b 100644 (file)
@@ -3,21 +3,21 @@
 
    Factored out of collect2 by Rafael Espindola <espindola@google.com>
 
-This file is part of GCC.
+   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 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.
+   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/>.  */
+   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/>.  */
 
 
 /* This program is passed a gcc, a list of gcc arguments and a list of
@@ -25,17 +25,16 @@ along with GCC; see the file COPYING3.  If not see
    we are in whopr mode or not modifies the arguments and needed and
    prints a list of output files on stdout.
 
-   Example:
+Example:
+$ lto-wrapper gcc/xgcc -B gcc a.o b.o -o test -flto
 
-   $ lto-wrapper gcc/xgcc -B gcc a.o b.o -o test -flto
+The above will print something like
+/tmp/ccwbQ8B2.lto.o
 
-   The above will print something like
-   /tmp/ccwbQ8B2.lto.o
-
-   If WHOPR is used instead, more than one file might be produced
-   ./ccXj2DTk.lto.ltrans.o
-   ./ccCJuXGv.lto.ltrans.o
-*/
+If WHOPR is used instead, more than one file might be produced
+./ccXj2DTk.lto.ltrans.o
+./ccCJuXGv.lto.ltrans.o
+ */
 
 #include "config.h"
 #include "system.h"
@@ -48,6 +47,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "simple-object.h"
 #include "lto-section-names.h"
 #include "collect-utils.h"
+#include <stdio.h>
+#include <unistd.h>
+
+#define MAPPER_FOR_GCC 1
+#include "mapper.h"
 
 /* Environment variable, used for passing the names of offload targets from GCC
    driver to lto-wrapper.  */
@@ -84,11 +88,48 @@ static bool xassembler_options_error = false;
 
 const char tool_name[] = "lto-wrapper";
 
-/* Delete tempfiles.  Called from utils_cleanup.  */
+/********************************************************************/
+
+// FIXME: Put in header somewhere, and maybe verify value
+static const location_t main_source_loc = 32;
+
+/* Our module mapper (created lazily).  */
+module_client *mapper;
+
+static module_client *make_mapper (location_t loc);
+inline module_client *get_mapper (location_t loc) {
+  auto *res = mapper;
+  if (!res)
+    res = make_mapper (loc);
+  return res;
+}
+
+/********************************************************************/
+
+/* Create a new mapper connecting to OPTION.  */
 
-void
-tool_cleanup (bool)
+module_client *
+make_mapper (location_t loc)
 {
+  //const char *option = module_mapper_name;
+  //if (!option)
+  //  option = getenv ("CXX_MODULE_MAPPER");
+
+  const char *option = getenv ("CXX_MODULE_MAPPER");
+  fprintf(stderr, "\tCXX_MODULE_MAPPER option: %s\n", option);
+
+  //mapper = module_client::open_module_client(loc, option, &set_cmi_repo, (save_decoded_options[0].opt_index == OPT_SPECIAL_program_name) && save_decoded_options[0].arg != progname ? save_decoded_options[0].arg : nullptr);
+  
+  fprintf(stderr, "\tcalling module_client constructor\n");
+  mapper = module_client::open_module_client(loc, option, nullptr, nullptr);
+
+  return mapper;
+}
+
+
+/* Delete tempfiles.  Called from utils_cleanup.  */
+
+void tool_cleanup (bool) {
   unsigned int i;
 
   if (ltrans_output_file)
@@ -102,32 +143,25 @@ tool_cleanup (bool)
   if (early_debug_object_names)
     for (i = 0; i < num_deb_objs; ++i)
       if (early_debug_object_names[i])
-       maybe_unlink (early_debug_object_names[i]);
-  for (i = 0; i < nr; ++i)
-    {
-      maybe_unlink (input_names[i]);
-      if (output_names[i])
-       maybe_unlink (output_names[i]);
-    }
+        maybe_unlink (early_debug_object_names[i]);
+  for (i = 0; i < nr; ++i) {
+    maybe_unlink (input_names[i]);
+    if (output_names[i])
+      maybe_unlink (output_names[i]);
+  }
 }
 
-static void
-lto_wrapper_cleanup (void)
-{
+static void lto_wrapper_cleanup (void) {
   utils_cleanup (false);
 }
 
 /* Unlink a temporary LTRANS file unless requested otherwise.  */
-
-void
-maybe_unlink (const char *file)
-{
-  if (!save_temps)
-    {
-      if (unlink_if_ordinary (file)
-         && errno != ENOENT)
-       fatal_error (input_location, "deleting LTRANS file %s: %m", file);
-    }
+void maybe_unlink (const char *file) {
+  if (!save_temps) {
+    if (unlink_if_ordinary (file)
+      && errno != ENOENT)
+      fatal_error (input_location, "deleting LTRANS file %s: %m", file);
+  }
   else if (verbose)
     fprintf (stderr, "[Leaving LTRANS %s]\n", file);
 }
@@ -138,12 +172,10 @@ maybe_unlink (const char *file)
 /* Create decoded options from the COLLECT_GCC and COLLECT_GCC_OPTIONS
    environment.  */
 
-static void
-get_options_from_collect_gcc_options (const char *collect_gcc,
-                                     const char *collect_gcc_options,
-                                     struct cl_decoded_option **decoded_options,
-                                     unsigned int *decoded_options_count)
-{
+static void get_options_from_collect_gcc_options (const char *collect_gcc,
+  const char *collect_gcc_options, struct cl_decoded_option **decoded_options,
+  unsigned int *decoded_options_count) {
+
   struct obstack argv_obstack;
   const char **argv;
   int argc;
@@ -152,55 +184,50 @@ get_options_from_collect_gcc_options (const char *collect_gcc,
   obstack_ptr_grow (&argv_obstack, collect_gcc);
 
   parse_options_from_collect_gcc_options (collect_gcc_options,
-                                         &argv_obstack, &argc);
+    &argv_obstack, &argc);
   argv = XOBFINISH (&argv_obstack, const char **);
 
   decode_cmdline_options_to_array (argc, (const char **)argv, CL_DRIVER,
-                                  decoded_options, decoded_options_count);
+    decoded_options, decoded_options_count);
   obstack_free (&argv_obstack, NULL);
 }
 
 /* Append OPTION to the options array DECODED_OPTIONS with size
    DECODED_OPTIONS_COUNT.  */
 
-static void
-append_option (struct cl_decoded_option **decoded_options,
-              unsigned int *decoded_options_count,
-              struct cl_decoded_option *option)
-{
+static void append_option (struct cl_decoded_option **decoded_options,
+  unsigned int *decoded_options_count, struct cl_decoded_option *option) {
+
   ++*decoded_options_count;
   *decoded_options
     = (struct cl_decoded_option *)
-       xrealloc (*decoded_options,
-                 (*decoded_options_count
-                  * sizeof (struct cl_decoded_option)));
+    xrealloc (*decoded_options,
+      (*decoded_options_count
+       * sizeof (struct cl_decoded_option)));
   memcpy (&(*decoded_options)[*decoded_options_count - 1], option,
-         sizeof (struct cl_decoded_option));
+    sizeof (struct cl_decoded_option));
 }
 
 /* Remove option number INDEX from DECODED_OPTIONS, update
    DECODED_OPTIONS_COUNT.  */
 
-static void
-remove_option (struct cl_decoded_option **decoded_options,
-              int index, unsigned int *decoded_options_count)
-{
+static void remove_option (struct cl_decoded_option **decoded_options,
+  int index, unsigned int *decoded_options_count) {
+
   --*decoded_options_count;
   memmove (&(*decoded_options)[index + 1],
-          &(*decoded_options)[index],
-          sizeof (struct cl_decoded_option)
-          * (*decoded_options_count - index));
+    &(*decoded_options)[index],
+    sizeof (struct cl_decoded_option)
+    * (*decoded_options_count - index));
 }
 
 /* Try to merge and complain about options FDECODED_OPTIONS when applied
    ontop of DECODED_OPTIONS.  */
 
-static void
-merge_and_complain (struct cl_decoded_option **decoded_options,
-                   unsigned int *decoded_options_count,
-                   struct cl_decoded_option *fdecoded_options,
-                   unsigned int fdecoded_options_count)
-{
+static void merge_and_complain (struct cl_decoded_option **decoded_options,
+  unsigned int *decoded_options_count, struct cl_decoded_option *fdecoded_options,
+  unsigned int fdecoded_options_count) {
+
   unsigned int i, j;
   struct cl_decoded_option *pic_option = NULL;
   struct cl_decoded_option *pie_option = NULL;
@@ -220,334 +247,313 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
 
   /* The following does what the old LTO option code did,
      union all target and a selected set of common options.  */
-  for (i = 0; i < fdecoded_options_count; ++i)
-    {
-      struct cl_decoded_option *foption = &fdecoded_options[i];
-      switch (foption->opt_index)
-       {
-       case OPT_SPECIAL_unknown:
-       case OPT_SPECIAL_ignore:
-       case OPT_SPECIAL_warn_removed:
-       case OPT_SPECIAL_program_name:
-       case OPT_SPECIAL_input_file:
-         break;
-
-       default:
-         if (!(cl_options[foption->opt_index].flags & CL_TARGET))
-           break;
-
-         /* Fallthru.  */
-       case OPT_fdiagnostics_show_caret:
-       case OPT_fdiagnostics_show_labels:
-       case OPT_fdiagnostics_show_line_numbers:
-       case OPT_fdiagnostics_show_option:
-       case OPT_fdiagnostics_show_location_:
-       case OPT_fshow_column:
-       case OPT_fcommon:
-       case OPT_fgnu_tm:
-       case OPT_g:
-         /* Do what the old LTO code did - collect exactly one option
-            setting per OPT code, we pick the first we encounter.
-            ???  This doesn't make too much sense, but when it doesn't
-            then we should complain.  */
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == foption->opt_index)
-             break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
-         break;
-
-       /* Figure out what PIC/PIE level wins and merge the results.  */
-       case OPT_fPIC:
-       case OPT_fpic:
-         pic_option = foption;
-         break;
-       case OPT_fPIE:
-       case OPT_fpie:
-         pie_option = foption;
-         break;
-
-       case OPT_fopenmp:
-       case OPT_fopenacc:
-         /* For selected options we can merge conservatively.  */
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == foption->opt_index)
-             break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
-         /* -fopenmp > -fno-openmp,
-            -fopenacc > -fno-openacc  */
-         else if (foption->value > (*decoded_options)[j].value)
-           (*decoded_options)[j] = *foption;
-         break;
-
-       case OPT_fopenacc_dim_:
-         /* Append or check identical.  */
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == foption->opt_index)
-             break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
-         else if (strcmp ((*decoded_options)[j].arg, foption->arg))
-           fatal_error (input_location,
-                        "option %s with different values",
-                        foption->orig_option_with_args_text);
-         break;
-
-       case OPT_O:
-       case OPT_Ofast:
-       case OPT_Og:
-       case OPT_Os:
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == OPT_O
-               || (*decoded_options)[j].opt_index == OPT_Ofast
-               || (*decoded_options)[j].opt_index == OPT_Og
-               || (*decoded_options)[j].opt_index == OPT_Os)
-             break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
-         else if ((*decoded_options)[j].opt_index == foption->opt_index
-                  && foption->opt_index != OPT_O)
-           /* Exact same options get merged.  */
-           ;
-         else
-           {
-             /* For mismatched option kinds preserve the optimization
-                level only, thus merge it as -On.  This also handles
-                merging of same optimization level -On.  */
-             int level = 0;
-             switch (foption->opt_index)
-               {
-               case OPT_O:
-                 if (foption->arg[0] == '\0')
-                   level = MAX (level, 1);
-                 else
-                   level = MAX (level, atoi (foption->arg));
-                 break;
-               case OPT_Ofast:
-                 level = MAX (level, 3);
-                 break;
-               case OPT_Og:
-                 level = MAX (level, 1);
-                 break;
-               case OPT_Os:
-                 level = MAX (level, 2);
-                 break;
-               default:
-                 gcc_unreachable ();
-               }
-             switch ((*decoded_options)[j].opt_index)
-               {
-               case OPT_O:
-                 if ((*decoded_options)[j].arg[0] == '\0')
-                   level = MAX (level, 1);
-                 else
-                   level = MAX (level, atoi ((*decoded_options)[j].arg));
-                 break;
-               case OPT_Ofast:
-                 level = MAX (level, 3);
-                 break;
-               case OPT_Og:
-                 level = MAX (level, 1);
-                 break;
-               case OPT_Os:
-                 level = MAX (level, 2);
-                 break;
-               default:
-                 gcc_unreachable ();
-               }
-             (*decoded_options)[j].opt_index = OPT_O;
-             char *tem;
-             tem = xasprintf ("-O%d", level);
-             (*decoded_options)[j].arg = &tem[2];
-             (*decoded_options)[j].canonical_option[0] = tem;
-             (*decoded_options)[j].value = 1;
-           }
-         break;
-
-       case OPT_foffload_abi_:
-         for (j = 0; j < *decoded_options_count; ++j)
-           if ((*decoded_options)[j].opt_index == foption->opt_index)
-             break;
-         if (j == *decoded_options_count)
-           append_option (decoded_options, decoded_options_count, foption);
-         else if (foption->value != (*decoded_options)[j].value)
-           fatal_error (input_location,
-                        "option %s not used consistently in all LTO input"
-                        " files", foption->orig_option_with_args_text);
-         break;
-
-
-       case OPT_foffload_:
-         append_option (decoded_options, decoded_options_count, foption);
-         break;
-       }
+  for (i = 0; i < fdecoded_options_count; ++i) {
+    struct cl_decoded_option *foption = &fdecoded_options[i];
+    switch (foption->opt_index) {
+    case OPT_SPECIAL_unknown:
+    case OPT_SPECIAL_ignore:
+    case OPT_SPECIAL_warn_removed:
+    case OPT_SPECIAL_program_name:
+    case OPT_SPECIAL_input_file:
+      break;
+
+    default:
+      if (!(cl_options[foption->opt_index].flags & CL_TARGET))
+        break;
+
+      /* Fallthru.  */
+    case OPT_fdiagnostics_show_caret:
+    case OPT_fdiagnostics_show_labels:
+    case OPT_fdiagnostics_show_line_numbers:
+    case OPT_fdiagnostics_show_option:
+    case OPT_fdiagnostics_show_location_:
+    case OPT_fshow_column:
+    case OPT_fcommon:
+    case OPT_fgnu_tm:
+    case OPT_g:
+      /* Do what the old LTO code did - collect exactly one option
+         setting per OPT code, we pick the first we encounter.
+         ???  This doesn't make too much sense, but when it doesn't
+         then we should complain.  */
+      for (j = 0; j < *decoded_options_count; ++j)
+        if ((*decoded_options)[j].opt_index == foption->opt_index)
+          break;
+      if (j == *decoded_options_count)
+        append_option (decoded_options, decoded_options_count, foption);
+      break;
+
+      /* Figure out what PIC/PIE level wins and merge the results.  */
+    case OPT_fPIC:
+    case OPT_fpic:
+      pic_option = foption;
+      break;
+    case OPT_fPIE:
+    case OPT_fpie:
+      pie_option = foption;
+      break;
+
+    case OPT_fopenmp:
+    case OPT_fopenacc:
+      /* For selected options we can merge conservatively.  */
+      for (j = 0; j < *decoded_options_count; ++j)
+        if ((*decoded_options)[j].opt_index == foption->opt_index)
+          break;
+      if (j == *decoded_options_count)
+        append_option (decoded_options, decoded_options_count, foption);
+      /* -fopenmp > -fno-openmp,
+         -fopenacc > -fno-openacc  */
+      else if (foption->value > (*decoded_options)[j].value)
+        (*decoded_options)[j] = *foption;
+      break;
+
+    case OPT_fopenacc_dim_:
+      /* Append or check identical.  */
+      for (j = 0; j < *decoded_options_count; ++j)
+        if ((*decoded_options)[j].opt_index == foption->opt_index)
+          break;
+      if (j == *decoded_options_count)
+        append_option (decoded_options, decoded_options_count, foption);
+      else if (strcmp ((*decoded_options)[j].arg, foption->arg))
+        fatal_error (input_location,
+          "option %s with different values",
+          foption->orig_option_with_args_text);
+      break;
+
+    case OPT_O:
+    case OPT_Ofast:
+    case OPT_Og:
+    case OPT_Os:
+      for (j = 0; j < *decoded_options_count; ++j)
+        if ((*decoded_options)[j].opt_index == OPT_O
+          || (*decoded_options)[j].opt_index == OPT_Ofast
+          || (*decoded_options)[j].opt_index == OPT_Og
+          || (*decoded_options)[j].opt_index == OPT_Os)
+          break;
+      if (j == *decoded_options_count)
+        append_option (decoded_options, decoded_options_count, foption);
+      else if ((*decoded_options)[j].opt_index == foption->opt_index
+        && foption->opt_index != OPT_O)
+        /* Exact same options get merged.  */
+        ;
+      else {
+        /* For mismatched option kinds preserve the optimization
+           level only, thus merge it as -On.  This also handles
+           merging of same optimization level -On.  */
+        int level = 0;
+        switch (foption->opt_index) {
+        case OPT_O:
+          if (foption->arg[0] == '\0')
+            level = MAX (level, 1);
+          else
+            level = MAX (level, atoi (foption->arg));
+          break;
+        case OPT_Ofast:
+          level = MAX (level, 3);
+          break;
+        case OPT_Og:
+          level = MAX (level, 1);
+          break;
+        case OPT_Os:
+          level = MAX (level, 2);
+          break;
+        default:
+          gcc_unreachable ();
+        }
+        switch ((*decoded_options)[j].opt_index) {
+        case OPT_O:
+          if ((*decoded_options)[j].arg[0] == '\0')
+            level = MAX (level, 1);
+          else
+            level = MAX (level, atoi ((*decoded_options)[j].arg));
+          break;
+        case OPT_Ofast:
+          level = MAX (level, 3);
+          break;
+        case OPT_Og:
+          level = MAX (level, 1);
+          break;
+        case OPT_Os:
+          level = MAX (level, 2);
+          break;
+        default:
+          gcc_unreachable ();
+        }
+        (*decoded_options)[j].opt_index = OPT_O;
+        char *tem;
+        tem = xasprintf ("-O%d", level);
+        (*decoded_options)[j].arg = &tem[2];
+        (*decoded_options)[j].canonical_option[0] = tem;
+        (*decoded_options)[j].value = 1;
+      }
+      break;
+
+
+    case OPT_foffload_abi_:
+      for (j = 0; j < *decoded_options_count; ++j)
+        if ((*decoded_options)[j].opt_index == foption->opt_index)
+          break;
+      if (j == *decoded_options_count)
+        append_option (decoded_options, decoded_options_count, foption);
+      else if (foption->value != (*decoded_options)[j].value)
+        fatal_error (input_location,
+          "option %s not used consistently in all LTO input"
+          " files", foption->orig_option_with_args_text);
+      break;
+
+
+    case OPT_foffload_:
+      append_option (decoded_options, decoded_options_count, foption);
+      break;
     }
+  }
 
   /* Merge PIC options:
-      -fPIC + -fpic = -fpic
-      -fPIC + -fno-pic = -fno-pic
-      -fpic/-fPIC + nothing = nothing.
+     -fPIC + -fpic = -fpic
+     -fPIC + -fno-pic = -fno-pic
+     -fpic/-fPIC + nothing = nothing.
      It is a common mistake to mix few -fPIC compiled objects into otherwise
      non-PIC code.  We do not want to build everything with PIC then.
 
      Similarly we merge PIE options, however in addition we keep
-      -fPIC + -fPIE = -fPIE
-      -fpic + -fPIE = -fpie
-      -fPIC/-fpic + -fpie = -fpie
+     -fPIC + -fPIE = -fPIE
+     -fpic + -fPIE = -fpie
+     -fPIC/-fpic + -fpie = -fpie
 
      It would be good to warn on mismatches, but it is bit hard to do as
      we do not know what nothing translates to.  */
-    
+
   for (unsigned int j = 0; j < *decoded_options_count;)
     if ((*decoded_options)[j].opt_index == OPT_fPIC
-        || (*decoded_options)[j].opt_index == OPT_fpic)
-      {
-       /* -fno-pic in one unit implies -fno-pic everywhere.  */
-       if ((*decoded_options)[j].value == 0)
-         j++;
-       /* If we have no pic option or merge in -fno-pic, we still may turn
-          existing pic/PIC mode into pie/PIE if -fpie/-fPIE is present.  */
-       else if ((pic_option && pic_option->value == 0)
-                || !pic_option)
-         {
-           if (pie_option)
-             {
-               bool big = (*decoded_options)[j].opt_index == OPT_fPIC
-                          && pie_option->opt_index == OPT_fPIE;
-               (*decoded_options)[j].opt_index = big ? OPT_fPIE : OPT_fpie;
-               if (pie_option->value)
-                 (*decoded_options)[j].canonical_option[0]
-                   = big ? "-fPIE" : "-fpie";
-               else
-                 (*decoded_options)[j].canonical_option[0] = "-fno-pie";
-               (*decoded_options)[j].value = pie_option->value;
-               j++;
-             }
-           else if (pic_option)
-             {
-               (*decoded_options)[j] = *pic_option;
-               j++;
-             }
-           /* We do not know if target defaults to pic or not, so just remove
-              option if it is missing in one unit but enabled in other.  */
-           else
-             remove_option (decoded_options, j, decoded_options_count);
-         }
-       else if (pic_option->opt_index == OPT_fpic
-                && (*decoded_options)[j].opt_index == OPT_fPIC)
-         {
-           (*decoded_options)[j] = *pic_option;
-           j++;
-         }
-       else
-         j++;
+      || (*decoded_options)[j].opt_index == OPT_fpic) {
+
+      /* -fno-pic in one unit implies -fno-pic everywhere.  */
+      if ((*decoded_options)[j].value == 0)
+        j++;
+      /* If we have no pic option or merge in -fno-pic, we still may turn
+         existing pic/PIC mode into pie/PIE if -fpie/-fPIE is present.  */
+      else if ((pic_option && pic_option->value == 0) || !pic_option) {
+        if (pie_option) {
+          bool big = (*decoded_options)[j].opt_index == OPT_fPIC
+            && pie_option->opt_index == OPT_fPIE;
+          (*decoded_options)[j].opt_index = big ? OPT_fPIE : OPT_fpie;
+          if (pie_option->value)
+            (*decoded_options)[j].canonical_option[0] = big ? "-fPIE" : "-fpie";
+          else
+            (*decoded_options)[j].canonical_option[0] = "-fno-pie";
+          (*decoded_options)[j].value = pie_option->value;
+          j++;
+        }
+        else if (pic_option) {
+          (*decoded_options)[j] = *pic_option;
+          j++;
+        }
+        /* We do not know if target defaults to pic or not, so just remove
+           option if it is missing in one unit but enabled in other.  */
+        else
+          remove_option (decoded_options, j, decoded_options_count);
+      }
+      else if (pic_option->opt_index == OPT_fpic &&
+        (*decoded_options)[j].opt_index == OPT_fPIC) {
+
+        (*decoded_options)[j] = *pic_option;
+        j++;
       }
-   else if ((*decoded_options)[j].opt_index == OPT_fPIE
-            || (*decoded_options)[j].opt_index == OPT_fpie)
+      else
+        j++;
+    }
+    else if ((*decoded_options)[j].opt_index == OPT_fPIE
+      || (*decoded_options)[j].opt_index == OPT_fpie) {
+      /* -fno-pie in one unit implies -fno-pie everywhere.  */
+      if ((*decoded_options)[j].value == 0)
+        j++;
+      /* If we have no pie option or merge in -fno-pie, we still preserve
+         PIE/pie if pic/PIC is present.  */
+      else if ((pie_option && pie_option->value == 0) || !pie_option) {
+        /* If -fPIC/-fpic is given, merge it with -fPIE/-fpie.  */
+        if (pic_option) {
+          if (pic_option->opt_index == OPT_fpic &&
+            (*decoded_options)[j].opt_index == OPT_fPIE) {
+
+            (*decoded_options)[j].opt_index = OPT_fpie;
+            (*decoded_options)[j].canonical_option[0] = pic_option->value ? "-fpie" : "-fno-pie";
+          }
+          else if (!pic_option->value)
+            (*decoded_options)[j].canonical_option[0] = "-fno-pie";
+          (*decoded_options)[j].value = pic_option->value;
+          j++;
+        }
+        else if (pie_option)
+        {
+          (*decoded_options)[j] = *pie_option;
+          j++;
+        }
+        /* Because we always append pic/PIE options this code path should
+           not happen unless the LTO object was built by old lto1 which
+           did not contain that logic yet.  */
+        else
+          remove_option (decoded_options, j, decoded_options_count);
+      }
+      else if (pie_option->opt_index == OPT_fpie
+        && (*decoded_options)[j].opt_index == OPT_fPIE)
       {
-       /* -fno-pie in one unit implies -fno-pie everywhere.  */
-       if ((*decoded_options)[j].value == 0)
-         j++;
-       /* If we have no pie option or merge in -fno-pie, we still preserve
-          PIE/pie if pic/PIC is present.  */
-       else if ((pie_option && pie_option->value == 0)
-                || !pie_option)
-         {
-           /* If -fPIC/-fpic is given, merge it with -fPIE/-fpie.  */
-           if (pic_option)
-             {
-               if (pic_option->opt_index == OPT_fpic
-                   && (*decoded_options)[j].opt_index == OPT_fPIE)
-                 {
-                   (*decoded_options)[j].opt_index = OPT_fpie;
-                   (*decoded_options)[j].canonical_option[0]
-                     = pic_option->value ? "-fpie" : "-fno-pie";
-                 }
-               else if (!pic_option->value)
-                 (*decoded_options)[j].canonical_option[0] = "-fno-pie";
-               (*decoded_options)[j].value = pic_option->value;
-               j++;
-             }
-           else if (pie_option)
-             {
-               (*decoded_options)[j] = *pie_option;
-               j++;
-             }
-           /* Because we always append pic/PIE options this code path should
-              not happen unless the LTO object was built by old lto1 which
-              did not contain that logic yet.  */
-           else
-             remove_option (decoded_options, j, decoded_options_count);
-         }
-       else if (pie_option->opt_index == OPT_fpie
-                && (*decoded_options)[j].opt_index == OPT_fPIE)
-         {
-           (*decoded_options)[j] = *pie_option;
-           j++;
-         }
-       else
-         j++;
+        (*decoded_options)[j] = *pie_option;
+        j++;
       }
-   else
-     j++;
+      else
+        j++;
+    }
+    else
+      j++;
 
   if (!xassembler_options_error)
     for (i = j = 0; ; i++, j++)
-      {
-       for (; i < *decoded_options_count; i++)
-         if ((*decoded_options)[i].opt_index == OPT_Xassembler)
-           break;
-
-       for (; j < fdecoded_options_count; j++)
-         if (fdecoded_options[j].opt_index == OPT_Xassembler)
-           break;
-
-       if (i == *decoded_options_count && j == fdecoded_options_count)
-         break;
-       else if (i < *decoded_options_count && j == fdecoded_options_count)
-         {
-           warning (0, "Extra option to %<-Xassembler%>: %s,"
-                    " dropping all %<-Xassembler%> and %<-Wa%> options.",
-                    (*decoded_options)[i].arg);
-           xassembler_options_error = true;
-           break;
-         }
-       else if (i == *decoded_options_count && j < fdecoded_options_count)
-         {
-           warning (0, "Extra option to %<-Xassembler%>: %s,"
-                    " dropping all %<-Xassembler%> and %<-Wa%> options.",
-                    fdecoded_options[j].arg);
-           xassembler_options_error = true;
-           break;
-         }
-       else if (strcmp ((*decoded_options)[i].arg, fdecoded_options[j].arg))
-         {
-           warning (0, "Options to %<-Xassembler%> do not match: %s, %s,"
-                    " dropping all %<-Xassembler%> and %<-Wa%> options.",
-                    (*decoded_options)[i].arg, fdecoded_options[j].arg);
-           xassembler_options_error = true;
-           break;
-         }
+    {
+      for (; i < *decoded_options_count; i++)
+        if ((*decoded_options)[i].opt_index == OPT_Xassembler)
+          break;
+
+      for (; j < fdecoded_options_count; j++)
+        if (fdecoded_options[j].opt_index == OPT_Xassembler)
+          break;
+
+      if (i == *decoded_options_count && j == fdecoded_options_count)
+        break;
+      else if (i < *decoded_options_count && j == fdecoded_options_count) {
+        warning (0, "Extra option to %<-Xassembler%>: %s,"
+          " dropping all %<-Xassembler%> and %<-Wa%> options.",
+          (*decoded_options)[i].arg);
+        xassembler_options_error = true;
+        break;
+      }
+      else if (i == *decoded_options_count && j < fdecoded_options_count) {
+        warning (0, "Extra option to %<-Xassembler%>: %s,"
+          " dropping all %<-Xassembler%> and %<-Wa%> options.",
+          fdecoded_options[j].arg);
+        xassembler_options_error = true;
+        break;
+      }
+      else if (strcmp ((*decoded_options)[i].arg, fdecoded_options[j].arg)) {
+        warning (0, "Options to %<-Xassembler%> do not match: %s, %s,"
+          " dropping all %<-Xassembler%> and %<-Wa%> options.",
+          (*decoded_options)[i].arg, fdecoded_options[j].arg);
+        xassembler_options_error = true;
+        break;
       }
+    }
 }
 
 /* Auxiliary function that frees elements of PTR and PTR itself.
    N is number of elements to be freed.  If PTR is NULL, nothing is freed.
    If an element is NULL, subsequent elements are not freed.  */
 
-static void **
-free_array_of_ptrs (void **ptr, unsigned n)
-{
+static void ** free_array_of_ptrs (void **ptr, unsigned n) {
   if (!ptr)
     return NULL;
-  for (unsigned i = 0; i < n; i++)
-    {
-      if (!ptr[i])
-       break;
-      free (ptr[i]);
-    }
+  for (unsigned i = 0; i < n; i++) {
+    if (!ptr[i])
+      break;
+    free (ptr[i]);
+  }
   free (ptr);
   return NULL;
 }
@@ -556,19 +562,17 @@ free_array_of_ptrs (void **ptr, unsigned n)
    Tokens are assumed to be delimited by ':'.  If APPEND is non-null,
    append it to every token we find.  */
 
-static unsigned
-parse_env_var (const char *str, char ***pvalues, const char *append)
-{
+static unsigned parse_env_var (const char *str, char ***pvalues, const char *append) {
+
   const char *curval, *nextval;
   char **values;
   unsigned num = 1, i;
 
   curval = strchr (str, ':');
-  while (curval)
-    {
-      num++;
-      curval = strchr (curval + 1, ':');
-    }
+  while (curval) {
+    num++;
+    curval = strchr (curval + 1, ':');
+  }
 
   values = (char**) xmalloc (num * sizeof (char*));
   curval = str;
@@ -577,243 +581,220 @@ parse_env_var (const char *str, char ***pvalues, const char *append)
     nextval = strchr (curval, '\0');
 
   int append_len = append ? strlen (append) : 0;
-  for (i = 0; i < num; i++)
-    {
-      int l = nextval - curval;
-      values[i] = (char*) xmalloc (l + 1 + append_len);
-      memcpy (values[i], curval, l);
-      values[i][l] = 0;
-      if (append)
-       strcat (values[i], append);
-      curval = nextval + 1;
-      nextval = strchr (curval, ':');
-      if (nextval == NULL)
-       nextval = strchr (curval, '\0');
-    }
+  for (i = 0; i < num; i++) {
+    int l = nextval - curval;
+    values[i] = (char*) xmalloc (l + 1 + append_len);
+    memcpy (values[i], curval, l);
+    values[i][l] = 0;
+    if (append)
+      strcat (values[i], append);
+    curval = nextval + 1;
+    nextval = strchr (curval, ':');
+    if (nextval == NULL)
+      nextval = strchr (curval, '\0');
+  }
   *pvalues = values;
   return num;
 }
 
 /* Append options OPTS from lto or offload_lto sections to ARGV_OBSTACK.  */
 
-static void
-append_compiler_options (obstack *argv_obstack, struct cl_decoded_option *opts,
-                        unsigned int count)
-{
+static void append_compiler_options (obstack *argv_obstack, 
+  struct cl_decoded_option *opts, unsigned int count) {
+
   /* Append compiler driver arguments as far as they were merged.  */
-  for (unsigned int j = 1; j < count; ++j)
-    {
-      struct cl_decoded_option *option = &opts[j];
-
-      /* File options have been properly filtered by lto-opts.c.  */
-      switch (option->opt_index)
-       {
-       /* Drop arguments that we want to take from the link line.  */
-       case OPT_flto_:
-       case OPT_flto:
-       case OPT_flto_partition_:
-         continue;
-
-       default:
-         break;
-       }
-
-      /* For now do what the original LTO option code was doing - pass
-        on any CL_TARGET flag and a few selected others.  */
-      switch (option->opt_index)
-       {
-       case OPT_fdiagnostics_show_caret:
-       case OPT_fdiagnostics_show_labels:
-       case OPT_fdiagnostics_show_line_numbers:
-       case OPT_fdiagnostics_show_option:
-       case OPT_fdiagnostics_show_location_:
-       case OPT_fshow_column:
-       case OPT_fPIC:
-       case OPT_fpic:
-       case OPT_fPIE:
-       case OPT_fpie:
-       case OPT_fcommon:
-       case OPT_fgnu_tm:
-       case OPT_fopenmp:
-       case OPT_fopenacc:
-       case OPT_fopenacc_dim_:
-       case OPT_foffload_abi_:
-       case OPT_g:
-       case OPT_O:
-       case OPT_Ofast:
-       case OPT_Og:
-       case OPT_Os:
-         break;
-
-       case OPT_Xassembler:
-         /* When we detected a mismatch in assembler options between
-            the input TU's fall back to previous behavior of ignoring them.  */
-         if (xassembler_options_error)
-           continue;
-         break;
-
-       default:
-         if (!(cl_options[option->opt_index].flags & CL_TARGET))
-           continue;
-       }
-
-      /* Pass the option on.  */
-      for (unsigned int i = 0; i < option->canonical_option_num_elements; ++i)
-       obstack_ptr_grow (argv_obstack, option->canonical_option[i]);
+  for (unsigned int j = 1; j < count; ++j) {
+    struct cl_decoded_option *option = &opts[j];
+
+    /* File options have been properly filtered by lto-opts.c.  */
+    switch (option->opt_index) {
+      /* Drop arguments that we want to take from the link line.  */
+    case OPT_flto_:
+    case OPT_flto:
+    case OPT_flto_partition_:
+      continue;
+
+    default:
+      break;
     }
+
+    /* For now do what the original LTO option code was doing - pass
+       on any CL_TARGET flag and a few selected others.  */
+    switch (option->opt_index) {
+    case OPT_fdiagnostics_show_caret:
+    case OPT_fdiagnostics_show_labels:
+    case OPT_fdiagnostics_show_line_numbers:
+    case OPT_fdiagnostics_show_option:
+    case OPT_fdiagnostics_show_location_:
+    case OPT_fshow_column:
+    case OPT_fPIC:
+    case OPT_fpic:
+    case OPT_fPIE:
+    case OPT_fpie:
+    case OPT_fcommon:
+    case OPT_fgnu_tm:
+    case OPT_fopenmp:
+    case OPT_fopenacc:
+    case OPT_fopenacc_dim_:
+    case OPT_foffload_abi_:
+    case OPT_g:
+    case OPT_O:
+    case OPT_Ofast:
+    case OPT_Og:
+    case OPT_Os:
+      break;
+
+    case OPT_Xassembler:
+      /* When we detected a mismatch in assembler options between
+         the input TU's fall back to previous behavior of ignoring them.  */
+      if (xassembler_options_error)
+        continue;
+      break;
+
+    default:
+      if (!(cl_options[option->opt_index].flags & CL_TARGET))
+        continue;
+    }
+
+    /* Pass the option on.  */
+    for (unsigned int i = 0; i < option->canonical_option_num_elements; ++i)
+      obstack_ptr_grow (argv_obstack, option->canonical_option[i]);
+  }
 }
 
 /* Append diag options in OPTS with length COUNT to ARGV_OBSTACK.  */
 
-static void
-append_diag_options (obstack *argv_obstack, struct cl_decoded_option *opts,
-                    unsigned int count)
-{
+static void append_diag_options (obstack *argv_obstack, 
+  struct cl_decoded_option *opts, unsigned int count) {
   /* Append compiler driver arguments as far as they were merged.  */
-  for (unsigned int j = 1; j < count; ++j)
-    {
-      struct cl_decoded_option *option = &opts[j];
-
-      switch (option->opt_index)
-       {
-       case OPT_fdiagnostics_color_:
-       case OPT_fdiagnostics_format_:
-       case OPT_fdiagnostics_show_caret:
-       case OPT_fdiagnostics_show_labels:
-       case OPT_fdiagnostics_show_line_numbers:
-       case OPT_fdiagnostics_show_option:
-       case OPT_fdiagnostics_show_location_:
-       case OPT_fshow_column:
-         break;
-       default:
-         continue;
-       }
-
-      /* Pass the option on.  */
-      for (unsigned int i = 0; i < option->canonical_option_num_elements; ++i)
-       obstack_ptr_grow (argv_obstack, option->canonical_option[i]);
+  for (unsigned int j = 1; j < count; ++j) {
+    struct cl_decoded_option *option = &opts[j];
+
+    switch (option->opt_index) {
+    case OPT_fdiagnostics_color_:
+    case OPT_fdiagnostics_format_:
+    case OPT_fdiagnostics_show_caret:
+    case OPT_fdiagnostics_show_labels:
+    case OPT_fdiagnostics_show_line_numbers:
+    case OPT_fdiagnostics_show_option:
+    case OPT_fdiagnostics_show_location_:
+    case OPT_fshow_column:
+      break;
+    default:
+      continue;
     }
+
+    /* Pass the option on.  */
+    for (unsigned int i = 0; i < option->canonical_option_num_elements; ++i)
+      obstack_ptr_grow (argv_obstack, option->canonical_option[i]);
+  }
 }
 
 
 /* Append linker options OPTS to ARGV_OBSTACK.  */
 
-static void
-append_linker_options (obstack *argv_obstack, struct cl_decoded_option *opts,
-                      unsigned int count)
-{
+static void append_linker_options (obstack *argv_obstack, 
+  struct cl_decoded_option *opts, unsigned int count) {
   /* Append linker driver arguments.  Compiler options from the linker
      driver arguments will override / merge with those from the compiler.  */
-  for (unsigned int j = 1; j < count; ++j)
-    {
-      struct cl_decoded_option *option = &opts[j];
-
-      /* Do not pass on frontend specific flags not suitable for lto.  */
-      if (!(cl_options[option->opt_index].flags
-           & (CL_COMMON|CL_TARGET|CL_DRIVER|CL_LTO)))
-       continue;
-
-      switch (option->opt_index)
-       {
-       case OPT_o:
-       case OPT_flto_:
-       case OPT_flto:
-         /* We've handled these LTO options, do not pass them on.  */
-         continue;
-
-       case OPT_fopenmp:
-       case OPT_fopenacc:
-         /* Ignore -fno-XXX form of these options, as otherwise
-            corresponding builtins will not be enabled.  */
-         if (option->value == 0)
-           continue;
-         break;
-
-       default:
-         break;
-       }
-
-      /* Pass the option on.  */
-      for (unsigned int i = 0; i < option->canonical_option_num_elements; ++i)
-       obstack_ptr_grow (argv_obstack, option->canonical_option[i]);
+  for (unsigned int j = 1; j < count; ++j) {
+    struct cl_decoded_option *option = &opts[j];
+
+    /* Do not pass on frontend specific flags not suitable for lto.  */
+    if (!(cl_options[option->opt_index].flags
+        & (CL_COMMON|CL_TARGET|CL_DRIVER|CL_LTO)))
+      continue;
+
+    switch (option->opt_index) {
+    case OPT_o:
+    case OPT_flto_:
+    case OPT_flto:
+      /* We've handled these LTO options, do not pass them on.  */
+      continue;
+
+    case OPT_fopenmp:
+    case OPT_fopenacc:
+      /* Ignore -fno-XXX form of these options, as otherwise
+         corresponding builtins will not be enabled.  */
+      if (option->value == 0)
+        continue;
+      break;
+
+    default:
+      break;
     }
+
+    /* Pass the option on.  */
+    for (unsigned int i = 0; i < option->canonical_option_num_elements; ++i)
+      obstack_ptr_grow (argv_obstack, option->canonical_option[i]);
+  }
 }
 
 /* Extract options for TARGET offload compiler from OPTIONS and append
    them to ARGV_OBSTACK.  */
 
-static void
-append_offload_options (obstack *argv_obstack, const char *target,
-                       struct cl_decoded_option *options,
-                       unsigned int options_count)
-{
-  for (unsigned i = 0; i < options_count; i++)
-    {
-      const char *cur, *next, *opts;
-      char **argv;
-      unsigned argc;
-      struct cl_decoded_option *option = &options[i];
-
-      if (option->opt_index != OPT_foffload_)
-       continue;
-
-      /* If option argument starts with '-' then no target is specified.  That
-        means offload options are specified for all targets, so we need to
-        append them.  */
-      if (option->arg[0] == '-')
-       opts = option->arg;
-      else
-       {
-         opts = strchr (option->arg, '=');
-         /* If there are offload targets specified, but no actual options,
-            there is nothing to do here.  */
-         if (!opts)
-           continue;
-
-         cur = option->arg;
-
-         while (cur < opts)
-           {
-             next = strchr (cur, ',');
-             if (next == NULL)
-               next = opts;
-             next = (next > opts) ? opts : next;
-
-             /* Are we looking for this offload target?  */
-             if (strlen (target) == (size_t) (next - cur)
-                 && strncmp (target, cur, next - cur) == 0)
-               break;
-
-             /* Skip the comma or equal sign.  */
-             cur = next + 1;
-           }
-
-         if (cur >= opts)
-           continue;
-
-         opts++;
-       }
-
-      argv = buildargv (opts);
-      for (argc = 0; argv[argc]; argc++)
-       obstack_ptr_grow (argv_obstack, argv[argc]);
+static void append_offload_options (obstack *argv_obstack, const char *target,
+  struct cl_decoded_option *options, unsigned int options_count) {
+
+  for (unsigned i = 0; i < options_count; i++) {
+    const char *cur, *next, *opts;
+    char **argv;
+    unsigned argc;
+    struct cl_decoded_option *option = &options[i];
+
+    if (option->opt_index != OPT_foffload_)
+      continue;
+
+    /* If option argument starts with '-' then no target is specified.  That
+       means offload options are specified for all targets, so we need to
+       append them.  */
+    if (option->arg[0] == '-')
+      opts = option->arg;
+    else {
+      opts = strchr (option->arg, '=');
+      /* If there are offload targets specified, but no actual options,
+         there is nothing to do here.  */
+      if (!opts)
+        continue;
+
+      cur = option->arg;
+
+      while (cur < opts) {
+        next = strchr (cur, ',');
+        if (next == NULL)
+          next = opts;
+        next = (next > opts) ? opts : next;
+
+        /* Are we looking for this offload target?  */
+        if (strlen (target) == (size_t) (next - cur) && strncmp (target, cur, next - cur) == 0)
+          break;
+
+        /* Skip the comma or equal sign.  */
+        cur = next + 1;
+      }
+
+      if (cur >= opts)
+        continue;
+
+      opts++;
     }
+
+    argv = buildargv (opts);
+    for (argc = 0; argv[argc]; argc++)
+      obstack_ptr_grow (argv_obstack, argv[argc]);
+  }
 }
 
 /* Check whether NAME can be accessed in MODE.  This is like access,
    except that it never considers directories to be executable.  */
 
-static int
-access_check (const char *name, int mode)
-{
-  if (mode == X_OK)
-    {
-      struct stat st;
+static int access_check (const char *name, int mode) {
+  if (mode == X_OK) {
+    struct stat st;
 
-      if (stat (name, &st) < 0
-         || S_ISDIR (st.st_mode))
-       return -1;
-    }
+    if (stat (name, &st) < 0 || S_ISDIR (st.st_mode))
+      return -1;
+  }
 
   return access (name, mode);
 }
@@ -821,19 +802,16 @@ access_check (const char *name, int mode)
 /* Prepare a target image for offload TARGET, using mkoffload tool from
    COMPILER_PATH.  Return the name of the resultant object file.  */
 
-static char *
-compile_offload_image (const char *target, const char *compiler_path,
-                      unsigned in_argc, char *in_argv[],
-                      struct cl_decoded_option *compiler_opts,
-                      unsigned int compiler_opt_count,
-                      struct cl_decoded_option *linker_opts,
-                      unsigned int linker_opt_count)
-{
+static char * compile_offload_image (const char *target, const char *compiler_path,
+  unsigned in_argc, char *in_argv[],
+  struct cl_decoded_option *compiler_opts,
+  unsigned int compiler_opt_count,
+  struct cl_decoded_option *linker_opts,
+  unsigned int linker_opt_count) {
+
   char *filename = NULL;
-  char *dumpbase;
   char **argv;
-  char *suffix
-    = XALLOCAVEC (char, sizeof ("/accel//mkoffload") + strlen (target));
+  char *suffix = XALLOCAVEC (char, sizeof ("/accel//mkoffload") + strlen (target));
   strcpy (suffix, "/accel/");
   strcat (suffix, target);
   strcat (suffix, "/mkoffload");
@@ -843,24 +821,18 @@ compile_offload_image (const char *target, const char *compiler_path,
 
   const char *compiler = NULL;
   for (unsigned i = 0; i < n_paths; i++)
-    if (access_check (paths[i], X_OK) == 0)
-      {
-       compiler = paths[i];
-       break;
-      }
+    if (access_check (paths[i], X_OK) == 0) {
+      compiler = paths[i];
+      break;
+    }
 
   if (!compiler)
     fatal_error (input_location,
-                "could not find %s in %s (consider using %<-B%>)",
-                suffix + 1, compiler_path);
-
-  dumpbase = concat (dumppfx, "x", target, NULL);
+      "could not find %s in %s (consider using %<-B%>)",
+      suffix + 1, compiler_path);
 
   /* Generate temporary output file name.  */
-  if (save_temps)
-    filename = concat (dumpbase, ".o", NULL);
-  else
-    filename = make_temp_file (".target.o");
+  filename = make_temp_file (".target.o");
 
   struct obstack argv_obstack;
   obstack_init (&argv_obstack);
@@ -878,18 +850,15 @@ compile_offload_image (const char *target, const char *compiler_path,
 
   /* Append options from offload_lto sections.  */
   append_compiler_options (&argv_obstack, compiler_opts,
-                          compiler_opt_count);
+    compiler_opt_count);
   append_diag_options (&argv_obstack, linker_opts, linker_opt_count);
 
-  obstack_ptr_grow (&argv_obstack, "-dumpbase");
-  obstack_ptr_grow (&argv_obstack, dumpbase);
-
   /* Append options specified by -foffload last.  In case of conflicting
      options we expect offload compiler to choose the latest.  */
   append_offload_options (&argv_obstack, target, compiler_opts,
-                         compiler_opt_count);
+    compiler_opt_count);
   append_offload_options (&argv_obstack, target, linker_opts,
-                         linker_opt_count);
+    linker_opt_count);
 
   obstack_ptr_grow (&argv_obstack, NULL);
   argv = XOBFINISH (&argv_obstack, char **);
@@ -906,13 +875,11 @@ compile_offload_image (const char *target, const char *compiler_path,
    IN_ARGV specify options and input object files.  As all of them could contain
    target sections, we pass them all to target compilers.  */
 
-static void
-compile_images_for_offload_targets (unsigned in_argc, char *in_argv[],
-                                   struct cl_decoded_option *compiler_opts,
-                                   unsigned int compiler_opt_count,
-                                   struct cl_decoded_option *linker_opts,
-                                   unsigned int linker_opt_count)
-{
+static void compile_images_for_offload_targets (unsigned in_argc,
+  char *in_argv[], struct cl_decoded_option *compiler_opts,
+  unsigned int compiler_opt_count, struct cl_decoded_option *linker_opts,
+  unsigned int linker_opt_count) {
+
   char **names = NULL;
   const char *target_names = getenv (OFFLOAD_TARGET_NAMES_ENV);
   if (!target_names)
@@ -927,57 +894,52 @@ compile_images_for_offload_targets (unsigned in_argc, char *in_argv[],
   /* Prepare an image for each target and save the name of the resultant object
      file to the OFFLOAD_NAMES array.  It is terminated by a NULL entry.  */
   offload_names = XCNEWVEC (char *, num_targets + 1);
-  for (unsigned i = 0; i < num_targets; i++)
-    {
-      /* HSA does not use LTO-like streaming and a different compiler, skip
-        it. */
-      if (strcmp (names[i], "hsa") == 0)
-       continue;
-
-      offload_names[next_name_entry]
-       = compile_offload_image (names[i], compiler_path, in_argc, in_argv,
-                                compiler_opts, compiler_opt_count,
-                                linker_opts, linker_opt_count);
-      if (!offload_names[next_name_entry])
-       fatal_error (input_location,
-                    "problem with building target image for %s", names[i]);
-      next_name_entry++;
-    }
-
- out:
+  for (unsigned i = 0; i < num_targets; i++) {
+    /* HSA does not use LTO-like streaming and a different compiler, skip
+       it. */
+    if (strcmp (names[i], "hsa") == 0)
+      continue;
+
+    offload_names[next_name_entry]
+      = compile_offload_image (names[i], compiler_path, in_argc, in_argv,
+        compiler_opts, compiler_opt_count,
+        linker_opts, linker_opt_count);
+    if (!offload_names[next_name_entry])
+      fatal_error (input_location,
+        "problem with building target image for %s", names[i]);
+    next_name_entry++;
+  }
+
+out:
   free_array_of_ptrs ((void **) names, num_targets);
 }
 
 /* Copy a file from SRC to DEST.  */
-
-static void
-copy_file (const char *dest, const char *src)
+static void copy_file (const char *dest, const char *src)
 {
-  FILE *d = fopen (dest, "wb");
-  FILE *s = fopen (src, "rb");
-  char buffer[512];
-  while (!feof (s))
-    {
-      size_t len = fread (buffer, 1, 512, s);
-      if (ferror (s) != 0)
-       fatal_error (input_location, "reading input file");
-      if (len > 0)
-       {
-         fwrite (buffer, 1, len, d);
-         if (ferror (d) != 0)
-           fatal_error (input_location, "writing output file");
-       }
-    }
-  fclose (d);
-  fclose (s);
+FILE *d = fopen (dest, "wb");
+FILE *s = fopen (src, "rb");
+char buffer[512];
+while (!feof (s))
+{
+size_t len = fread (buffer, 1, 512, s);
+if (ferror (s) != 0)
+  fatal_error (input_location, "reading input file");
+if (len > 0)
+{
+fwrite (buffer, 1, len, d);
+if (ferror (d) != 0)
+  fatal_error (input_location, "writing output file");
+}
+}
+fclose (d);
+fclose (s);
 }
 
 /* Find the crtoffloadtable.o file in LIBRARY_PATH, make copy and pass name of
    the copy to the linker.  */
 
-static void
-find_crtoffloadtable (void)
-{
+static void find_crtoffloadtable (void) {
   char **paths = NULL;
   const char *library_path = getenv ("LIBRARY_PATH");
   if (!library_path)
@@ -986,18 +948,17 @@ find_crtoffloadtable (void)
 
   unsigned i;
   for (i = 0; i < n_paths; i++)
-    if (access_check (paths[i], R_OK) == 0)
-      {
-       /* The linker will delete the filename we give it, so make a copy.  */
-       char *crtoffloadtable = make_temp_file (".crtoffloadtable.o");
-       copy_file (crtoffloadtable, paths[i]);
-       printf ("%s\n", crtoffloadtable);
-       XDELETEVEC (crtoffloadtable);
-       break;
-      }
+    if (access_check (paths[i], R_OK) == 0) {
+      /* The linker will delete the filename we give it, so make a copy.  */
+      char *crtoffloadtable = make_temp_file (".crtoffloadtable.o");
+      copy_file (crtoffloadtable, paths[i]);
+      printf ("%s\n", crtoffloadtable);
+      XDELETEVEC (crtoffloadtable);
+      break;
+    }
   if (i == n_paths)
     fatal_error (input_location,
-                "installation error, cannot find %<crtoffloadtable.o%>");
+      "installation error, cannot find %<crtoffloadtable.o%>");
 
   free_array_of_ptrs ((void **) paths, n_paths);
 }
@@ -1008,11 +969,10 @@ find_crtoffloadtable (void)
    otherwise.  COLLECT_GCC holds the value of the environment variable with
    the same name.  */
 
-static bool
-find_and_merge_options (int fd, off_t file_offset, const char *prefix,
-                       struct cl_decoded_option **opts,
-                       unsigned int *opt_count, const char *collect_gcc)
-{
+static bool find_and_merge_options (int fd, off_t file_offset,
+  const char *prefix, struct cl_decoded_option **opts, unsigned int *opt_count,
+  const char *collect_gcc) {
+
   off_t offset, length;
   char *data;
   char *fopts;
@@ -1023,7 +983,7 @@ find_and_merge_options (int fd, off_t file_offset, const char *prefix,
 
   simple_object_read *sobj;
   sobj = simple_object_start_read (fd, file_offset, "__GNU_LTO",
-                                  &errmsg, &err);
+    &errmsg, &err);
   if (!sobj)
     return false;
 
@@ -1031,35 +991,32 @@ find_and_merge_options (int fd, off_t file_offset, const char *prefix,
   strcpy (secname, prefix);
   strcat (secname, ".opts");
   if (!simple_object_find_section (sobj, secname, &offset, &length,
-                                  &errmsg, &err))
-    {
-      simple_object_release_read (sobj);
-      return false;
-    }
+      &errmsg, &err)) {
+    simple_object_release_read (sobj);
+    return false;
+  }
 
   lseek (fd, file_offset + offset, SEEK_SET);
   data = (char *)xmalloc (length);
   read (fd, data, length);
   fopts = data;
-  do
-    {
-      struct cl_decoded_option *f2decoded_options;
-      unsigned int f2decoded_options_count;
-      get_options_from_collect_gcc_options (collect_gcc, fopts,
-                                           &f2decoded_options,
-                                           &f2decoded_options_count);
-      if (!fdecoded_options)
-       {
-        fdecoded_options = f2decoded_options;
-        fdecoded_options_count = f2decoded_options_count;
-       }
-      else
-       merge_and_complain (&fdecoded_options,
-                           &fdecoded_options_count,
-                           f2decoded_options, f2decoded_options_count);
-
-      fopts += strlen (fopts) + 1;
+  do {
+    struct cl_decoded_option *f2decoded_options;
+    unsigned int f2decoded_options_count;
+    get_options_from_collect_gcc_options (collect_gcc, fopts,
+      &f2decoded_options,
+      &f2decoded_options_count);
+    if (!fdecoded_options) {
+      fdecoded_options = f2decoded_options;
+      fdecoded_options_count = f2decoded_options_count;
     }
+    else
+      merge_and_complain (&fdecoded_options,
+        &fdecoded_options_count,
+        f2decoded_options, f2decoded_options_count);
+
+    fopts += strlen (fopts) + 1;
+  }
   while (fopts - data < length);
 
   free (data);
@@ -1072,9 +1029,7 @@ find_and_merge_options (int fd, off_t file_offset, const char *prefix,
 /* Copy early debug info sections from INFILE to a new file whose name
    is returned.  Return NULL on error.  */
 
-const char *
-debug_objcopy (const char *infile, bool rename)
-{
+const char * debug_objcopy (const char *infile, bool rename) {
   char *outfile;
   const char *errmsg;
   int err;
@@ -1085,46 +1040,43 @@ debug_objcopy (const char *infile, bool rename)
   long loffset;
   int consumed;
   if ((p = strrchr (infile, '@'))
-      && p != infile
-      && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
-      && strlen (p) == (unsigned int) consumed)
-    {
-      char *fname = xstrdup (infile);
-      fname[p - infile] = '\0';
-      infile = fname;
-      inoff = (off_t) loffset;
-    }
+    && p != infile
+    && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
+    && strlen (p) == (unsigned int) consumed) {
+    char *fname = xstrdup (infile);
+    fname[p - infile] = '\0';
+    infile = fname;
+    inoff = (off_t) loffset;
+  }
   int infd = open (infile, O_RDONLY | O_BINARY);
   if (infd == -1)
     return NULL;
   simple_object_read *inobj = simple_object_start_read (infd, inoff,
-                                                       "__GNU_LTO",
-                                                       &errmsg, &err);
+    "__GNU_LTO",
+    &errmsg, &err);
   if (!inobj)
     return NULL;
 
   off_t off, len;
   if (simple_object_find_section (inobj, ".gnu.debuglto_.debug_info",
-                                 &off, &len, &errmsg, &err) != 1)
-    {
-      if (errmsg)
-       fatal_error (0, "%s: %s", errmsg, xstrerror (err));
+      &off, &len, &errmsg, &err) != 1) {
+    if (errmsg)
+      fatal_error (0, "%s: %s", errmsg, xstrerror (err));
 
-      simple_object_release_read (inobj);
-      close (infd);
-      return NULL;
-    }
+    simple_object_release_read (inobj);
+    close (infd);
+    return NULL;
+  }
 
   if (save_temps)
     outfile = concat (orig_infile, ".debug.temp.o", NULL);
   else
     outfile = make_temp_file (".debug.temp.o");
   errmsg = simple_object_copy_lto_debug_sections (inobj, outfile, &err, rename);
-  if (errmsg)
-    {
-      unlink_if_ordinary (outfile);
-      fatal_error (0, "%s: %s", errmsg, xstrerror (err));
-    }
+  if (errmsg) {
+    unlink_if_ordinary (outfile);
+    fatal_error (0, "%s: %s", errmsg, xstrerror (err));
+  }
 
   simple_object_release_read (inobj);
   close (infd);
@@ -1134,9 +1086,7 @@ debug_objcopy (const char *infile, bool rename)
 
 /* Helper for qsort: compare priorities for parallel compilation.  */
 
-int
-cmp_priority (const void *a, const void *b)
-{
+int cmp_priority (const void *a, const void *b) {
   return *((const int *)b)-*((const int *)a);
 }
 
@@ -1150,8 +1100,7 @@ static unsigned long get_cpuset_size;
 cpu_set_t *cpusetp;
 
 unsigned long
-static cpuset_popcount (unsigned long cpusetsize, cpu_set_t *cpusetp)
-{
+static cpuset_popcount (unsigned long cpusetsize, cpu_set_t *cpusetp) {
 #ifdef CPU_COUNT_S
   /* glibc 2.7 and above provide a macro for this.  */
   return CPU_COUNT_S (cpusetsize, cpusetp);
@@ -1164,13 +1113,12 @@ static cpuset_popcount (unsigned long cpusetsize, cpu_set_t *cpusetp)
   size_t i;
   unsigned long ret = 0;
   STATIC_ASSERT (sizeof (cpusetp->__bits[0]) == sizeof (unsigned long int));
-  for (i = 0; i < cpusetsize / sizeof (cpusetp->__bits[0]); i++)
-    {
-      unsigned long int mask = cpusetp->__bits[i];
-      if (mask == 0)
-       continue;
-      ret += __builtin_popcountl (mask);
-    }
+  for (i = 0; i < cpusetsize / sizeof (cpusetp->__bits[0]); i++) {
+    unsigned long int mask = cpusetp->__bits[i];
+    if (mask == 0)
+      continue;
+    ret += __builtin_popcountl (mask);
+  }
   return ret;
 #endif
 }
@@ -1179,9 +1127,7 @@ static cpuset_popcount (unsigned long cpusetsize, cpu_set_t *cpusetp)
 /* At startup, determine the default number of threads.  It would seem
    this should be related to the number of cpus online.  */
 
-static void
-init_num_threads (void)
-{
+static void init_num_threads (void) {
 #ifdef HAVE_PTHREAD_AFFINITY_NP
 #if defined (_SC_NPROCESSORS_CONF) && defined (CPU_ALLOC_SIZE)
   cpuset_size = sysconf (_SC_NPROCESSORS_CONF);
@@ -1191,49 +1137,47 @@ init_num_threads (void)
 #endif
 
   cpusetp = (cpu_set_t *) xmalloc (gomp_cpuset_size);
-  do
-    {
-      int ret = pthread_getaffinity_np (pthread_self (), gomp_cpuset_size,
-                                       cpusetp);
-      if (ret == 0)
-       {
-         /* Count only the CPUs this process can use.  */
-         nthreads_var = cpuset_popcount (cpuset_size, cpusetp);
-         if (nthreads_var == 0)
-           break;
-         get_cpuset_size = cpuset_size;
+  do {
+    int ret = pthread_getaffinity_np (pthread_self (), gomp_cpuset_size,
+      cpusetp);
+    if (ret == 0) {
+      /* Count only the CPUs this process can use.  */
+      nthreads_var = cpuset_popcount (cpuset_size, cpusetp);
+      if (nthreads_var == 0)
+        break;
+      get_cpuset_size = cpuset_size;
 #ifdef CPU_ALLOC_SIZE
-         unsigned long i;
-         for (i = cpuset_size * 8; i; i--)
-           if (CPU_ISSET_S (i - 1, cpuset_size, cpusetp))
-             break;
-         cpuset_size = CPU_ALLOC_SIZE (i);
+      unsigned long i;
+      for (i = cpuset_size * 8; i; i--)
+        if (CPU_ISSET_S (i - 1, cpuset_size, cpusetp))
+          break;
+      cpuset_size = CPU_ALLOC_SIZE (i);
 #endif
-         return;
-       }
-      if (ret != EINVAL)
-       break;
+      return;
+    }
+    if (ret != EINVAL)
+      break;
 #ifdef CPU_ALLOC_SIZE
-      if (cpuset_size < sizeof (cpu_set_t))
-       cpuset_size = sizeof (cpu_set_t);
-      else
-       cpuset_size = cpuset_size * 2;
-      if (cpuset_size < 8 * sizeof (cpu_set_t))
-       cpusetp
-         = (cpu_set_t *) realloc (cpusetp, cpuset_size);
-      else
-       {
-         /* Avoid fatal if too large memory allocation would be
-            requested, e.g. kernel returning EINVAL all the time.  */
-         void *p = realloc (cpusetp, cpuset_size);
-         if (p == NULL)
-           break;
-         cpusetp = (cpu_set_t *) p;
-       }
+    if (cpuset_size < sizeof (cpu_set_t))
+      cpuset_size = sizeof (cpu_set_t);
+    else
+      cpuset_size = cpuset_size * 2;
+    if (cpuset_size < 8 * sizeof (cpu_set_t))
+      cpusetp
+        = (cpu_set_t *) realloc (cpusetp, cpuset_size);
+    else
+    {
+      /* Avoid fatal if too large memory allocation would be
+         requested, e.g. kernel returning EINVAL all the time.  */
+      void *p = realloc (cpusetp, cpuset_size);
+      if (p == NULL)
+        break;
+      cpusetp = (cpu_set_t *) p;
+    }
 #else
-      break;
+    break;
 #endif
-    }
+  }
   while (1);
   cpuset_size = 0;
   nthreads_var = 1;
@@ -1249,11 +1193,9 @@ init_num_threads (void)
 
 /* Test and return reason why a jobserver cannot be detected.  */
 
-static const char *
-jobserver_active_p (void)
-{
-  #define JS_PREFIX "jobserver is not available: "
-  #define JS_NEEDLE "--jobserver-auth="
+static const char * jobserver_active_p (void) {
+#define JS_PREFIX "jobserver is not available: "
+#define JS_NEEDLE "--jobserver-auth="
 
   const char *makeflags = getenv ("MAKEFLAGS");
   if (makeflags == NULL)
@@ -1267,10 +1209,10 @@ jobserver_active_p (void)
   int wfd = -1;
 
   if (sscanf (n + strlen (JS_NEEDLE), "%d,%d", &rfd, &wfd) == 2
-      && rfd > 0
-      && wfd > 0
-      && is_valid_fd (rfd)
-      && is_valid_fd (wfd))
+    && rfd > 0
+    && wfd > 0
+    && is_valid_fd (rfd)
+    && is_valid_fd (wfd))
     return NULL;
   else
     return JS_PREFIX "cannot access %<" JS_NEEDLE "%> file descriptors";
@@ -1278,9 +1220,9 @@ jobserver_active_p (void)
 
 /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
 
-static void
-run_gcc (unsigned argc, char *argv[])
-{
+static void run_gcc (unsigned argc, char *argv[]) {
+  fprintf(stderr, "JOHN PRINT: run_gcc\n");
+
   unsigned i, j;
   const char **new_argv;
   const char **argv_ptr;
@@ -1307,41 +1249,40 @@ run_gcc (unsigned argc, char *argv[])
   bool linker_output_rel = false;
   bool skip_debug = false;
   unsigned n_debugobj;
-  const char *incoming_dumppfx = dumppfx = NULL;
+  const char *dumppfx = NULL, *incoming_dumppfx = NULL;
   static char current_dir[] = { '.', DIR_SEPARATOR, '\0' };
 
   /* Get the driver and options.  */
   collect_gcc = getenv ("COLLECT_GCC");
   if (!collect_gcc)
     fatal_error (input_location,
-                "environment variable %<COLLECT_GCC%> must be set");
+      "environment variable %<COLLECT_GCC%> must be set");
   collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
   if (!collect_gcc_options)
     fatal_error (input_location,
-                "environment variable %<COLLECT_GCC_OPTIONS%> must be set");
+      "environment variable %<COLLECT_GCC_OPTIONS%> must be set");
 
   char *collect_as_options = getenv ("COLLECT_AS_OPTIONS");
 
   /* Prepend -Xassembler to each option, and append the string
      to collect_gcc_options.  */
-  if (collect_as_options)
-    {
-      obstack temporary_obstack;
-      obstack_init (&temporary_obstack);
+  if (collect_as_options) {
+    obstack temporary_obstack;
+    obstack_init (&temporary_obstack);
 
-      prepend_xassembler_to_collect_as_options (collect_as_options,
-                                               &temporary_obstack);
-      obstack_1grow (&temporary_obstack, '\0');
+    prepend_xassembler_to_collect_as_options (collect_as_options,
+      &temporary_obstack);
+    obstack_1grow (&temporary_obstack, '\0');
 
-      char *xassembler_opts_string
-       = XOBFINISH (&temporary_obstack, char *);
-      collect_gcc_options = concat (collect_gcc_options, xassembler_opts_string,
-                                   NULL);
-    }
+    char *xassembler_opts_string
+      = XOBFINISH (&temporary_obstack, char *);
+    collect_gcc_options = concat (collect_gcc_options, xassembler_opts_string,
+      NULL);
+  }
 
   get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options,
-                                       &decoded_options,
-                                       &decoded_options_count);
+    &decoded_options,
+    &decoded_options_count);
 
   /* Allocate array for input object files with LTO IL,
      and for possible preceding arguments.  */
@@ -1349,56 +1290,53 @@ run_gcc (unsigned argc, char *argv[])
   ltoobj_argv = XNEWVEC (char *, argc);
 
   /* Look at saved options in the IL files.  */
-  for (i = 1; i < argc; ++i)
-    {
-      char *p;
-      int fd;
-      off_t file_offset = 0;
-      long loffset;
-      int consumed;
-      char *filename = argv[i];
-
-      if (strncmp (argv[i], "-foffload-objects=",
-                  sizeof ("-foffload-objects=") - 1) == 0)
-       {
-         have_offload = true;
-         offload_objects_file_name
-           = argv[i] + sizeof ("-foffload-objects=") - 1;
-         continue;
-       }
-
-      if ((p = strrchr (argv[i], '@'))
-         && p != argv[i] 
-         && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
-         && strlen (p) == (unsigned int) consumed)
-       {
-         filename = XNEWVEC (char, p - argv[i] + 1);
-         memcpy (filename, argv[i], p - argv[i]);
-         filename[p - argv[i]] = '\0';
-         file_offset = (off_t) loffset;
-       }
-      fd = open (filename, O_RDONLY | O_BINARY);
-      /* Linker plugin passes -fresolution and -flinker-output options.
-        -flinker-output is passed only when user did not specify one and thus
-        we do not need to worry about duplicities with the option handling
-        below. */
-      if (fd == -1)
-       {
-         lto_argv[lto_argc++] = argv[i];
-         if (strcmp (argv[i], "-flinker-output=rel") == 0)
-           linker_output_rel = true;
-         continue;
-       }
-
-      if (find_and_merge_options (fd, file_offset, LTO_SECTION_NAME_PREFIX,
-                                 &fdecoded_options, &fdecoded_options_count,
-                                 collect_gcc))
-       {
-         have_lto = true;
-         ltoobj_argv[ltoobj_argc++] = argv[i];
-       }
-      close (fd);
+  for (i = 1; i < argc; ++i) {
+    char *p;
+    int fd;
+    off_t file_offset = 0;
+    long loffset;
+    int consumed;
+    char *filename = argv[i];
+
+    if (strncmp (argv[i], "-foffload-objects=",
+        sizeof ("-foffload-objects=") - 1) == 0) {
+
+      have_offload = true;
+      offload_objects_file_name
+        = argv[i] + sizeof ("-foffload-objects=") - 1;
+      continue;
+    }
+
+    if ((p = strrchr (argv[i], '@'))
+      && p != argv[i]
+      && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
+      && strlen (p) == (unsigned int) consumed) {
+
+      filename = XNEWVEC (char, p - argv[i] + 1);
+      memcpy (filename, argv[i], p - argv[i]);
+      filename[p - argv[i]] = '\0';
+      file_offset = (off_t) loffset;
+    }
+    fd = open (filename, O_RDONLY | O_BINARY);
+    /* Linker plugin passes -fresolution and -flinker-output options.
+       -flinker-output is passed only when user did not specify one and thus
+       we do not need to worry about duplicities with the option handling
+       below. */
+    if (fd == -1) {
+      lto_argv[lto_argc++] = argv[i];
+      if (strcmp (argv[i], "-flinker-output=rel") == 0)
+        linker_output_rel = true;
+      continue;
+    }
+
+    if (find_and_merge_options (fd, file_offset, LTO_SECTION_NAME_PREFIX,
+        &fdecoded_options, &fdecoded_options_count,
+        collect_gcc)) {
+      have_lto = true;
+      ltoobj_argv[ltoobj_argc++] = argv[i];
     }
+    close (fd);
+  }
 
   /* Initalize the common arguments for the driver.  */
   obstack_init (&argv_obstack);
@@ -1407,134 +1345,122 @@ run_gcc (unsigned argc, char *argv[])
   obstack_ptr_grow (&argv_obstack, "-c");
 
   append_compiler_options (&argv_obstack, fdecoded_options,
-                          fdecoded_options_count);
+    fdecoded_options_count);
   append_linker_options (&argv_obstack, decoded_options, decoded_options_count);
 
   /* Scan linker driver arguments for things that are of relevance to us.  */
-  for (j = 1; j < decoded_options_count; ++j)
-    {
-      struct cl_decoded_option *option = &decoded_options[j];
-      switch (option->opt_index)
-       {
-       case OPT_o:
-         linker_output = option->arg;
-         break;
-
-         /* We don't have to distinguish between -save-temps=* and
-            -save-temps, -dumpdir already carries that
-            information.  */
-       case OPT_save_temps_:
-       case OPT_save_temps:
-         save_temps = 1;
-         break;
-
-       case OPT_v:
-         verbose = 1;
-         break;
-
-       case OPT_flto_partition_:
-         if (strcmp (option->arg, "none") == 0)
-           no_partition = true;
-         break;
-
-       case OPT_flto_:
-         if (strcmp (option->arg, "jobserver") == 0)
-           {
-             parallel = 1;
-             jobserver = 1;
-           }
-         else if (strcmp (option->arg, "auto") == 0)
-           {
-             parallel = 1;
-             auto_parallel = 1;
-           }
-         else
-           {
-             parallel = atoi (option->arg);
-             if (parallel <= 1)
-               parallel = 0;
-           }
-         /* Fallthru.  */
-
-       case OPT_flto:
-         lto_mode = LTO_MODE_WHOPR;
-         break;
-
-       case OPT_flinker_output_:
-         linker_output_rel = !strcmp (option->arg, "rel");
-         break;
-
-       case OPT_g:
-         /* Recognize -g0.  */
-         skip_debug = option->arg && !strcmp (option->arg, "0");
-         break;
-
-       case OPT_dumpdir:
-         incoming_dumppfx = dumppfx = option->arg;
-         break;
-
-       default:
-         break;
-       }
+  for (j = 1; j < decoded_options_count; ++j) {
+    struct cl_decoded_option *option = &decoded_options[j];
+    switch (option->opt_index) {
+    case OPT_o:
+      linker_output = option->arg;
+      break;
+
+      /* We don't have to distinguish between -save-temps=* and
+         -save-temps, -dumpdir already carries that
+         information.  */
+    case OPT_save_temps_:
+    case OPT_save_temps:
+      save_temps = 1;
+      break;
+
+    case OPT_v:
+      verbose = 1;
+      break;
+
+    case OPT_flto_partition_:
+      if (strcmp (option->arg, "none") == 0)
+        no_partition = true;
+      break;
+
+    case OPT_flto_:
+      if (strcmp (option->arg, "jobserver") == 0) {
+        parallel = 1;
+        jobserver = 1;
+      }
+      else if (strcmp (option->arg, "auto") == 0) {
+        parallel = 1;
+        auto_parallel = 1;
+      }
+      else {
+        parallel = atoi (option->arg);
+        if (parallel <= 1)
+          parallel = 0;
+      }
+      /* Fallthru.  */
+
+    case OPT_flto:
+      lto_mode = LTO_MODE_WHOPR;
+      break;
+
+    case OPT_flinker_output_:
+      linker_output_rel = !strcmp (option->arg, "rel");
+      break;
+
+    case OPT_g:
+      /* Recognize -g0.  */
+      skip_debug = option->arg && !strcmp (option->arg, "0");
+      break;
+
+    case OPT_dumpdir:
+      incoming_dumppfx = dumppfx = option->arg;
+      break;
+
+    default:
+      break;
     }
+  }
 
   /* Output lto-wrapper invocation command.  */
-  if (verbose)
-    {
-      for (i = 0; i < argc; ++i)
-       {
-         fputs (argv[i], stderr);
-         fputc (' ', stderr);
-       }
-      fputc ('\n', stderr);
+  if (verbose) {
+    for (i = 0; i < argc; ++i) {
+      fputs (argv[i], stderr);
+      fputc (' ', stderr);
     }
+    fputc ('\n', stderr);
+  }
 
   if (linker_output_rel)
     no_partition = true;
 
-  if (no_partition)
-    {
-      lto_mode = LTO_MODE_LTO;
-      jobserver = 0;
-      auto_parallel = 0;
-      parallel = 0;
+  if (no_partition) {
+    lto_mode = LTO_MODE_LTO;
+    jobserver = 0;
+    auto_parallel = 0;
+    parallel = 0;
+  }
+  else {
+    const char *jobserver_error = jobserver_active_p ();
+    if (jobserver && jobserver_error != NULL)
+      warning (0, jobserver_error);
+    else if (!jobserver && jobserver_error == NULL) {
+      parallel = 1;
+      jobserver = 1;
     }
-  else
-    {
-      const char *jobserver_error = jobserver_active_p ();
-      if (jobserver && jobserver_error != NULL)
-       warning (0, jobserver_error);
-      else if (!jobserver && jobserver_error == NULL)
-       {
-         parallel = 1;
-         jobserver = 1;
-       }
-    }
-
-  if (!dumppfx)
-    {
-      if (!linker_output
-         || strcmp (linker_output, HOST_BIT_BUCKET) == 0)
-       dumppfx = "a.";
-      else
-       {
-         const char *obase = lbasename (linker_output), *temp;
-
-         /* Strip the executable extension.  */
-         size_t blen = strlen (obase), xlen;
-         if ((temp = strrchr (obase + 1, '.'))
-             && (xlen = strlen (temp))
-             && (strcmp (temp, ".exe") == 0
+  }
+
+  if (!dumppfx) {
+    if (!linker_output
+      || strcmp (linker_output, HOST_BIT_BUCKET) == 0)
+      dumppfx = "a.";
+    else {
+      const char *obase = lbasename (linker_output), *temp;
+
+      /* Strip the executable extension.  */
+      size_t blen = strlen (obase), xlen;
+      if ((temp = strrchr (obase + 1, '.'))
+        && (xlen = strlen (temp))
+        && (strcmp (temp, ".exe") == 0
 #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
-                 || strcmp (temp, TARGET_EXECUTABLE_SUFFIX) == 0
+          || strcmp (temp, TARGET_EXECUTABLE_SUFFIX) == 0
 #endif
-                 || strcmp (obase, "a.out") == 0))
-           dumppfx = xstrndup (linker_output,
-                               obase - linker_output + blen - xlen + 1);
-         else
-           dumppfx = concat (linker_output, ".", NULL);
-       }
+          || strcmp (obase, "a.out") == 0))
+        dumppfx = xstrndup (linker_output,
+          obase - linker_output + blen - xlen + 1);
+      else
+        dumppfx = concat (linker_output, ".", NULL);
     }
+  }
 
   /* If there's no directory component in the dumppfx, add one, so
      that, when it is used as -dumpbase, it overrides any occurrence
@@ -1546,166 +1472,155 @@ run_gcc (unsigned argc, char *argv[])
      -dumpbase overriding semantics.  If we got an incoming -dumpdir
      argument, we'll pass it on, so don't bother with another one
      then.  */
-  if (!incoming_dumppfx)
-    {
-      obstack_ptr_grow (&argv_obstack, "-dumpdir");
-      obstack_ptr_grow (&argv_obstack, "");
-    }
+  if (!incoming_dumppfx) {
+    obstack_ptr_grow (&argv_obstack, "-dumpdir");
+    obstack_ptr_grow (&argv_obstack, "");
+  }
   obstack_ptr_grow (&argv_obstack, "-dumpbase");
 
   /* Remember at which point we can scrub args to re-use the commons.  */
   new_head_argc = obstack_object_size (&argv_obstack) / sizeof (void *);
 
-  if (have_offload)
-    {
-      unsigned i, num_offload_files;
-      char **offload_argv;
-      FILE *f;
-
-      f = fopen (offload_objects_file_name, "r");
-      if (f == NULL)
-       fatal_error (input_location, "cannot open %s: %m",
-                    offload_objects_file_name);
-      if (fscanf (f, "%u ", &num_offload_files) != 1)
-       fatal_error (input_location, "cannot read %s: %m",
-                    offload_objects_file_name);
-      offload_argv = XCNEWVEC (char *, num_offload_files);
-
-      /* Read names of object files with offload.  */
-      for (i = 0; i < num_offload_files; i++)
-       {
-         const unsigned piece = 32;
-         char *buf, *filename = XNEWVEC (char, piece);
-         size_t len;
-
-         buf = filename;
+  if (have_offload) {
+    unsigned i, num_offload_files;
+    char **offload_argv;
+    FILE *f;
+
+    f = fopen (offload_objects_file_name, "r");
+    if (f == NULL)
+      fatal_error (input_location, "cannot open %s: %m",
+        offload_objects_file_name);
+    if (fscanf (f, "%u ", &num_offload_files) != 1)
+      fatal_error (input_location, "cannot read %s: %m",
+        offload_objects_file_name);
+    offload_argv = XCNEWVEC (char *, num_offload_files);
+
+    /* Read names of object files with offload.  */
+    for (i = 0; i < num_offload_files; i++) {
+      const unsigned piece = 32;
+      char *buf, *filename = XNEWVEC (char, piece);
+      size_t len;
+
+      buf = filename;
 cont1:
-         if (!fgets (buf, piece, f))
-           break;
-         len = strlen (filename);
-         if (filename[len - 1] != '\n')
-           {
-             filename = XRESIZEVEC (char, filename, len + piece);
-             buf = filename + len;
-             goto cont1;
-           }
-         filename[len - 1] = '\0';
-         offload_argv[i] = filename;
-       }
-      fclose (f);
-      if (offload_argv[num_offload_files - 1] == NULL)
-       fatal_error (input_location, "invalid format of %s",
-                    offload_objects_file_name);
-      maybe_unlink (offload_objects_file_name);
-      offload_objects_file_name = NULL;
-
-      /* Look at saved offload options in files.  */
-      for (i = 0; i < num_offload_files; i++)
-       {
-         char *p;
-         long loffset;
-         int fd, consumed;
-         off_t file_offset = 0;
-         char *filename = offload_argv[i];
-
-         if ((p = strrchr (offload_argv[i], '@'))
-             && p != offload_argv[i]
-             && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
-             && strlen (p) == (unsigned int) consumed)
-           {
-             filename = XNEWVEC (char, p - offload_argv[i] + 1);
-             memcpy (filename, offload_argv[i], p - offload_argv[i]);
-             filename[p - offload_argv[i]] = '\0';
-             file_offset = (off_t) loffset;
-           }
-         fd = open (filename, O_RDONLY | O_BINARY);
-         if (fd == -1)
-           fatal_error (input_location, "cannot open %s: %m", filename);
-         if (!find_and_merge_options (fd, file_offset,
-                                      OFFLOAD_SECTION_NAME_PREFIX,
-                                      &offload_fdecoded_options,
-                                      &offload_fdecoded_options_count,
-                                      collect_gcc))
-           fatal_error (input_location, "cannot read %s: %m", filename);
-         close (fd);
-         if (filename != offload_argv[i])
-           XDELETEVEC (filename);
-       }
-
-      compile_images_for_offload_targets (num_offload_files, offload_argv,
-                                         offload_fdecoded_options,
-                                         offload_fdecoded_options_count,
-                                         decoded_options,
-                                         decoded_options_count);
-
-      free_array_of_ptrs ((void **) offload_argv, num_offload_files);
-
-      if (offload_names)
-       {
-         find_crtoffloadtable ();
-         for (i = 0; offload_names[i]; i++)
-           printf ("%s\n", offload_names[i]);
-         free_array_of_ptrs ((void **) offload_names, i);
-       }
+      if (!fgets (buf, piece, f))
+        break;
+      len = strlen (filename);
+      if (filename[len - 1] != '\n') {
+        filename = XRESIZEVEC (char, filename, len + piece);
+        buf = filename + len;
+        goto cont1;
+      }
+      filename[len - 1] = '\0';
+      offload_argv[i] = filename;
+    }
+    fclose (f);
+    if (offload_argv[num_offload_files - 1] == NULL)
+      fatal_error (input_location, "invalid format of %s",
+        offload_objects_file_name);
+    maybe_unlink (offload_objects_file_name);
+    offload_objects_file_name = NULL;
+
+    /* Look at saved offload options in files.  */
+    for (i = 0; i < num_offload_files; i++) {
+      char *p;
+      long loffset;
+      int fd, consumed;
+      off_t file_offset = 0;
+      char *filename = offload_argv[i];
+
+      if ((p = strrchr (offload_argv[i], '@'))
+        && p != offload_argv[i]
+        && sscanf (p, "@%li%n", &loffset, &consumed) >= 1
+        && strlen (p) == (unsigned int) consumed) {
+
+        filename = XNEWVEC (char, p - offload_argv[i] + 1);
+        memcpy (filename, offload_argv[i], p - offload_argv[i]);
+        filename[p - offload_argv[i]] = '\0';
+        file_offset = (off_t) loffset;
+      }
+      fd = open (filename, O_RDONLY | O_BINARY);
+      if (fd == -1)
+        fatal_error (input_location, "cannot open %s: %m", filename);
+      if (!find_and_merge_options (fd, file_offset,
+          OFFLOAD_SECTION_NAME_PREFIX,
+          &offload_fdecoded_options,
+          &offload_fdecoded_options_count,
+          collect_gcc))
+        fatal_error (input_location, "cannot read %s: %m", filename);
+      close (fd);
+      if (filename != offload_argv[i])
+        XDELETEVEC (filename);
     }
 
+    compile_images_for_offload_targets (num_offload_files, offload_argv,
+      offload_fdecoded_options,
+      offload_fdecoded_options_count,
+      decoded_options,
+      decoded_options_count);
+
+    free_array_of_ptrs ((void **) offload_argv, num_offload_files);
+
+    if (offload_names) {
+      find_crtoffloadtable ();
+      for (i = 0; offload_names[i]; i++)
+        printf ("%s\n", offload_names[i]);
+      free_array_of_ptrs ((void **) offload_names, i);
+    }
+  }
+
   /* If object files contain offload sections, but do not contain LTO sections,
      then there is no need to perform a link-time recompilation, i.e.
      lto-wrapper is used only for a compilation of offload images.  */
   if (have_offload && !have_lto)
     goto finish;
 
-  if (lto_mode == LTO_MODE_LTO)
-    {
-      /* -dumpbase argument for LTO.  */
-      flto_out = concat (dumppfx, "lto.o", NULL);
-      obstack_ptr_grow (&argv_obstack, flto_out);
-
-      if (!save_temps)
-       flto_out = make_temp_file (".lto.o");
-      obstack_ptr_grow (&argv_obstack, "-o");
-      obstack_ptr_grow (&argv_obstack, flto_out);
+  if (lto_mode == LTO_MODE_LTO) {
+    /* -dumpbase argument for LTO.  */
+    flto_out = concat (dumppfx, "lto.o", NULL);
+    obstack_ptr_grow (&argv_obstack, flto_out);
+
+    if (!save_temps)
+      flto_out = make_temp_file (".lto.o");
+    obstack_ptr_grow (&argv_obstack, "-o");
+    obstack_ptr_grow (&argv_obstack, flto_out);
+  }
+  else {
+    const char *list_option = "-fltrans-output-list=";
+
+    /* -dumpbase argument for WPA.  */
+    char *dumpbase = concat (dumppfx, "wpa", NULL);
+    obstack_ptr_grow (&argv_obstack, dumpbase);
+
+    if (save_temps)
+      ltrans_output_file = concat (dumppfx, "ltrans.out", NULL);
+    else
+      ltrans_output_file = make_temp_file (".ltrans.out");
+    list_option_full = concat (list_option, ltrans_output_file, NULL);
+    obstack_ptr_grow (&argv_obstack, list_option_full);
+
+    if (jobserver) {
+      if (verbose)
+        fprintf (stderr, "Using make jobserver\n");
+      obstack_ptr_grow (&argv_obstack, xstrdup ("-fwpa=jobserver"));
     }
-  else 
-    {
-      const char *list_option = "-fltrans-output-list=";
-
-      /* -dumpbase argument for WPA.  */
-      char *dumpbase = concat (dumppfx, "wpa", NULL);
-      obstack_ptr_grow (&argv_obstack, dumpbase);
-
-      if (save_temps)
-       ltrans_output_file = concat (dumppfx, "ltrans.out", NULL);
-      else
-       ltrans_output_file = make_temp_file (".ltrans.out");
-      list_option_full = concat (list_option, ltrans_output_file, NULL);
-      obstack_ptr_grow (&argv_obstack, list_option_full);
-
-      if (jobserver)
-       {
-         if (verbose)
-           fprintf (stderr, "Using make jobserver\n");
-         obstack_ptr_grow (&argv_obstack, xstrdup ("-fwpa=jobserver"));
-       }
-      else if (auto_parallel)
-       {
-         char buf[256];
-         init_num_threads ();
-         if (verbose)
-           fprintf (stderr, "LTO parallelism level set to %ld\n",
-                    nthreads_var);
-         sprintf (buf, "-fwpa=%ld", nthreads_var);
-         obstack_ptr_grow (&argv_obstack, xstrdup (buf));
-       }
-      else if (parallel > 1)
-       {
-         char buf[256];
-         sprintf (buf, "-fwpa=%i", parallel);
-         obstack_ptr_grow (&argv_obstack, xstrdup (buf));
-       }
-      else
-        obstack_ptr_grow (&argv_obstack, "-fwpa");
+    else if (auto_parallel) {
+      char buf[256];
+      init_num_threads ();
+      if (verbose)
+        fprintf (stderr, "LTO parallelism level set to %ld\n",
+          nthreads_var);
+      sprintf (buf, "-fwpa=%ld", nthreads_var);
+      obstack_ptr_grow (&argv_obstack, xstrdup (buf));
+    }
+    else if (parallel > 1) {
+      char buf[256];
+      sprintf (buf, "-fwpa=%i", parallel);
+      obstack_ptr_grow (&argv_obstack, xstrdup (buf));
     }
+    else
+      obstack_ptr_grow (&argv_obstack, "-fwpa");
+  }
 
   /* Append input arguments.  */
   for (i = 0; i < lto_argc; ++i)
@@ -1723,238 +1638,263 @@ cont1:
      files and append those to the partial link commandline.  */
   n_debugobj = 0;
   early_debug_object_names = NULL;
-  if (! skip_debug)
-    {
-      early_debug_object_names = XCNEWVEC (const char *, ltoobj_argc+ 1);
-      num_deb_objs = ltoobj_argc;
-      for (i = 0; i < ltoobj_argc; ++i)
-       {
-         const char *tem;
-         if ((tem = debug_objcopy (ltoobj_argv[i], !linker_output_rel)))
-           {
-             early_debug_object_names[i] = tem;
-             n_debugobj++;
-           }
-       }
+  if (!skip_debug) {
+    early_debug_object_names = XCNEWVEC (const char *, ltoobj_argc+ 1);
+    num_deb_objs = ltoobj_argc;
+    for (i = 0; i < ltoobj_argc; ++i) {
+      const char *tem;
+      if ((tem = debug_objcopy (ltoobj_argv[i], !linker_output_rel))) {
+        early_debug_object_names[i] = tem;
+        n_debugobj++;
+      }
     }
+  }
 
-  if (lto_mode == LTO_MODE_LTO)
-    {
-      printf ("%s\n", flto_out);
-      if (!skip_debug)
-       {
-         for (i = 0; i < ltoobj_argc; ++i)
-           if (early_debug_object_names[i] != NULL)
-             printf ("%s\n", early_debug_object_names[i]);           
-       }
-      /* These now belong to collect2.  */
-      free (flto_out);
-      flto_out = NULL;
-      free (early_debug_object_names);
-      early_debug_object_names = NULL;
+  if (lto_mode == LTO_MODE_LTO) {
+    printf ("%s\n", flto_out);
+    if (!skip_debug) {
+      for (i = 0; i < ltoobj_argc; ++i)
+        if (early_debug_object_names[i] != NULL)
+          printf ("%s\n", early_debug_object_names[i]);
     }
-  else
-    {
-      FILE *stream = fopen (ltrans_output_file, "r");
-      FILE *mstream = NULL;
-      struct obstack env_obstack;
-      int priority;
-
-      if (!stream)
-       fatal_error (input_location, "%<fopen%>: %s: %m", ltrans_output_file);
-
-      /* Parse the list of LTRANS inputs from the WPA stage.  */
-      obstack_init (&env_obstack);
-      nr = 0;
-      for (;;)
-       {
-         const unsigned piece = 32;
-         char *output_name = NULL;
-         char *buf, *input_name = (char *)xmalloc (piece);
-         size_t len;
-
-         buf = input_name;
-          if (fscanf (stream, "%i\n", &priority) != 1)
-           {
-             if (!feof (stream))
-               fatal_error (input_location,
-                            "corrupted ltrans output file %s",
-                            ltrans_output_file);
-             break;
-           }
+    /* These now belong to collect2.  */
+    free (flto_out);
+    flto_out = NULL;
+    free (early_debug_object_names);
+    early_debug_object_names = NULL;
+  }
+  else {
+    FILE *stream = fopen (ltrans_output_file, "r");
+    FILE *mstream = NULL;
+    struct obstack env_obstack;
+    int priority;
+
+    if (!stream)
+      fatal_error (input_location, "%<fopen%>: %s: %m", ltrans_output_file);
+
+    /* Parse the list of LTRANS inputs from the WPA stage.  */
+    obstack_init (&env_obstack);
+    nr = 0;
+    for (;;) {
+      const unsigned piece = 32;
+      char *output_name = NULL;
+      char *buf, *input_name = (char *)xmalloc (piece);
+      size_t len;
+
+      buf = input_name;
+      if (fscanf (stream, "%i\n", &priority) != 1) {
+        if (!feof (stream))
+          fatal_error (input_location,
+            "corrupted ltrans output file %s",
+            ltrans_output_file);
+        break;
+      }
 cont:
-         if (!fgets (buf, piece, stream))
-           break;
-         len = strlen (input_name);
-         if (input_name[len - 1] != '\n')
-           {
-             input_name = (char *)xrealloc (input_name, len + piece);
-             buf = input_name + len;
-             goto cont;
-           }
-         input_name[len - 1] = '\0';
-
-         if (input_name[0] == '*')
-           output_name = &input_name[1];
-
-         nr++;
-         ltrans_priorities
-            = (int *)xrealloc (ltrans_priorities, nr * sizeof (int) * 2);
-         input_names = (char **)xrealloc (input_names, nr * sizeof (char *));
-         output_names = (char **)xrealloc (output_names, nr * sizeof (char *));
-         ltrans_priorities[(nr-1)*2] = priority;
-         ltrans_priorities[(nr-1)*2+1] = nr-1;
-         input_names[nr-1] = input_name;
-         output_names[nr-1] = output_name;
-       }
-      fclose (stream);
-      maybe_unlink (ltrans_output_file);
-      ltrans_output_file = NULL;
-
-      if (parallel)
-       {
-         makefile = make_temp_file (".mk");
-         mstream = fopen (makefile, "w");
-         qsort (ltrans_priorities, nr, sizeof (int) * 2, cmp_priority);
-       }
-
-      /* Execute the LTRANS stage for each input file (or prepare a
-        makefile to invoke this in parallel).  */
-      for (i = 0; i < nr; ++i)
-       {
-         char *output_name;
-         char *input_name = input_names[i];
-         /* If it's a pass-through file do nothing.  */
-         if (output_names[i])
-           continue;
-
-         /* Replace the .o suffix with a .ltrans.o suffix and write
-            the resulting name to the LTRANS output list.  */
-         obstack_grow (&env_obstack, input_name, strlen (input_name) - 2);
-         obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
-         output_name = XOBFINISH (&env_obstack, char *);
-
-         /* Adjust the dumpbase if the linker output file was seen.  */
-         int dumpbase_len = (strlen (dumppfx) + sizeof (DUMPBASE_SUFFIX));
-         char *dumpbase = (char *) xmalloc (dumpbase_len + 1);
-         snprintf (dumpbase, dumpbase_len, "%sltrans%u.ltrans", dumppfx, i);
-         argv_ptr[0] = dumpbase;
-
-         argv_ptr[1] = "-fltrans";
-         argv_ptr[2] = "-o";
-         argv_ptr[3] = output_name;
-         argv_ptr[4] = input_name;
-         argv_ptr[5] = NULL;
-         if (parallel)
-           {
-             fprintf (mstream, "%s:\n\t@%s ", output_name, new_argv[0]);
-             for (j = 1; new_argv[j] != NULL; ++j)
-               fprintf (mstream, " '%s'", new_argv[j]);
-             fprintf (mstream, "\n");
-             /* If we are not preserving the ltrans input files then
-                truncate them as soon as we have processed it.  This
-                reduces temporary disk-space usage.  */
-             if (! save_temps)
-               fprintf (mstream, "\t@-touch -r %s %s.tem > /dev/null 2>&1 "
-                        "&& mv %s.tem %s\n",
-                        input_name, input_name, input_name, input_name); 
-           }
-         else
-           {
-             fork_execute (new_argv[0], CONST_CAST (char **, new_argv),
-                           true);
-             maybe_unlink (input_name);
-           }
-
-         output_names[i] = output_name;
-       }
-      if (parallel)
-       {
-         struct pex_obj *pex;
-         char jobs[32];
-
-         fprintf (mstream,
-                  ".PHONY: all\n"
-                  "all:");
-         for (i = 0; i < nr; ++i)
-           {
-             int j = ltrans_priorities[i*2 + 1];
-             fprintf (mstream, " \\\n\t%s", output_names[j]);
-           }
-         fprintf (mstream, "\n");
-         fclose (mstream);
-         if (!jobserver)
-           {
-             /* Avoid passing --jobserver-fd= and similar flags 
-                unless jobserver mode is explicitly enabled.  */
-             putenv (xstrdup ("MAKEFLAGS="));
-             putenv (xstrdup ("MFLAGS="));
-           }
-
-         char **make_argv = buildargv (getenv ("MAKE"));
-         if (make_argv)
-           {
-             for (unsigned argc = 0; make_argv[argc]; argc++)
-               obstack_ptr_grow (&argv_obstack, make_argv[argc]);
-           }
-         else
-           obstack_ptr_grow (&argv_obstack, "make");
-
-         obstack_ptr_grow (&argv_obstack, "-f");
-         obstack_ptr_grow (&argv_obstack, makefile);
-         if (!jobserver)
-           {
-             snprintf (jobs, 31, "-j%ld",
-                       auto_parallel ? nthreads_var : parallel);
-             obstack_ptr_grow (&argv_obstack, jobs);
-           }
-         obstack_ptr_grow (&argv_obstack, "all");
-         obstack_ptr_grow (&argv_obstack, NULL);
-         new_argv = XOBFINISH (&argv_obstack, const char **);
-
-         pex = collect_execute (new_argv[0], CONST_CAST (char **, new_argv),
-                                NULL, NULL, PEX_SEARCH, false);
-         do_wait (new_argv[0], pex);
-         freeargv (make_argv);
-         maybe_unlink (makefile);
-         makefile = NULL;
-         for (i = 0; i < nr; ++i)
-           maybe_unlink (input_names[i]);
-       }
+      if (!fgets (buf, piece, stream))
+        break;
+      len = strlen (input_name);
+      if (input_name[len - 1] != '\n') {
+        input_name = (char *)xrealloc (input_name, len + piece);
+        buf = input_name + len;
+        goto cont;
+      }
+      input_name[len - 1] = '\0';
+
+      if (input_name[0] == '*')
+        output_name = &input_name[1];
+
+      nr++;
+      ltrans_priorities
+        = (int *)xrealloc (ltrans_priorities, nr * sizeof (int) * 2);
+      input_names = (char **)xrealloc (input_names, nr * sizeof (char *));
+      output_names = (char **)xrealloc (output_names, nr * sizeof (char *));
+      ltrans_priorities[(nr-1)*2] = priority;
+      ltrans_priorities[(nr-1)*2+1] = nr-1;
+      input_names[nr-1] = input_name;
+      output_names[nr-1] = output_name;
+    }
+    fclose (stream);
+    maybe_unlink (ltrans_output_file);
+    ltrans_output_file = NULL;
+
+    fprintf(stderr, "JOHN PRINT: parallel=%d\n", parallel);
+
+    if (parallel) {
+      makefile = make_temp_file (".mk");
+      fprintf(stderr, "JOHN PRINT: created mk\n");
+      mstream = fopen (makefile, "w");
+      qsort (ltrans_priorities, nr, sizeof (int) * 2, cmp_priority);
+      sleep(5);
+    }
+
+    fprintf(stderr, "\tcreating mapper\n");
+    auto *mapper = get_mapper (main_source_loc);
+    fprintf(stderr, "\tgot mapper\n");
+    //char test[]="gcc test.c -o test";
+    //mapper->Cork();
+    //mapper->LTOCompile(test);
+    //mapper->Uncork();
+
+
+    /* Execute the LTRANS stage for each input file (or prepare a
+       makefile to invoke this in parallel).  */
+    for (i = 0; i < nr; ++i) {
+      char *output_name;
+      char *input_name = input_names[i];
+      /* If it's a pass-through file do nothing.  */
+      if (output_names[i])
+        continue;
+
+      /* Replace the .o suffix with a .ltrans.o suffix and write
+         the resulting name to the LTRANS output list.  */
+      obstack_grow (&env_obstack, input_name, strlen (input_name) - 2);
+      obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
+      output_name = XOBFINISH (&env_obstack, char *);
+
+      /* Adjust the dumpbase if the linker output file was seen.  */
+      int dumpbase_len = (strlen (dumppfx) + sizeof (DUMPBASE_SUFFIX));
+      char *dumpbase = (char *) xmalloc (dumpbase_len + 1);
+      snprintf (dumpbase, dumpbase_len, "%sltrans%u.ltrans", dumppfx, i);
+      argv_ptr[0] = dumpbase;
+
+      argv_ptr[1] = "-fltrans";
+      argv_ptr[2] = "-o";
+      argv_ptr[3] = output_name;
+      argv_ptr[4] = input_name;
+      argv_ptr[5] = NULL;
+      if (parallel) {
+        fprintf (mstream, "%s:\n\t@%s ", output_name, new_argv[0]);
+        for (j = 1; new_argv[j] != NULL; ++j)
+          fprintf (mstream, " '%s'", new_argv[j]);
+        fprintf (mstream, "\n");
+        /* If we are not preserving the ltrans input files then
+           truncate them as soon as we have processed it.  This
+           reduces temporary disk-space usage.  */
+        if (! save_temps)
+          fprintf (mstream, "\t@-touch -r %s %s.tem > /dev/null 2>&1 "
+            "&& mv %s.tem %s\n",
+            input_name, input_name, input_name, input_name);
+      }
+      else {
+
+        fprintf(stderr, "\tRAVI PRINT: %s ", new_argv[0]);
+
+        mapper->Cork();
+        mapper->LTOCompile(new_argv[0]);
+
+        const char **arg_it = new_argv + 1;
+
+        while(*arg_it != NULL) {
+          //fprintf(stderr, "\tRAVI PRINT: %s\n", *arg_it);
+          fprintf(stderr, " \'%s\' ", *arg_it);
+          mapper->LTOCompile(*arg_it);
+          arg_it++;
+        }
+        fprintf(stderr, "\n");
+
+        mapper->Uncork();
+
+        //fprintf(stderr, "\tRAVI PRINT: %s\n", new_argv[0]);
+        fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
+        maybe_unlink (input_name);
+      }
+
+      output_names[i] = output_name;
+    }
+    if (parallel) {
+      struct pex_obj *pex;
+      char jobs[32];
+
+      fprintf (mstream,
+        ".PHONY: all\n"
+        "all:");
+      for (i = 0; i < nr; ++i) {
+        int j = ltrans_priorities[i*2 + 1];
+        fprintf (mstream, " \\\n\t%s", output_names[j]);
+      }
+      fprintf (mstream, "\n");
+      fclose (mstream);
+      fprintf(stderr, "JOHN PRINT: go check mstream!\n");
+
+      sleep(60);
+      if (!jobserver) {
+        /* Avoid passing --jobserver-fd= and similar flags
+           unless jobserver mode is explicitly enabled.  */
+        putenv (xstrdup ("MAKEFLAGS="));
+        putenv (xstrdup ("MFLAGS="));
+      }
+
+      char **make_argv = buildargv (getenv ("MAKE"));
+      if (make_argv) {
+        for (unsigned argc = 0; make_argv[argc]; argc++)
+          obstack_ptr_grow (&argv_obstack, make_argv[argc]);
+      }
+      else
+        obstack_ptr_grow (&argv_obstack, "make");
+
+      obstack_ptr_grow (&argv_obstack, "-f");
+      obstack_ptr_grow (&argv_obstack, makefile);
+      if (!jobserver) {
+        snprintf (jobs, 31, "-j%ld",
+          auto_parallel ? nthreads_var : parallel);
+        obstack_ptr_grow (&argv_obstack, jobs);
+      }
+      obstack_ptr_grow (&argv_obstack, "all");
+      obstack_ptr_grow (&argv_obstack, NULL);
+      new_argv = XOBFINISH (&argv_obstack, const char **);
+
+      pex = collect_execute (new_argv[0], CONST_CAST (char **, new_argv),
+        NULL, NULL, PEX_SEARCH, false);
+      do_wait (new_argv[0], pex);
+      freeargv (make_argv);
+      maybe_unlink (makefile);
+      makefile = NULL;
       for (i = 0; i < nr; ++i)
-       {
-         fputs (output_names[i], stdout);
-         putc ('\n', stdout);
-         free (input_names[i]);
-       }
-      if (!skip_debug)
-       {
-         for (i = 0; i < ltoobj_argc; ++i)
-           if (early_debug_object_names[i] != NULL)
-             printf ("%s\n", early_debug_object_names[i]);           
-       }
-      nr = 0;
-      free (ltrans_priorities);
-      free (output_names);
-      output_names = NULL;
-      free (early_debug_object_names);
-      early_debug_object_names = NULL;
-      free (input_names);
-      free (list_option_full);
-      obstack_free (&env_obstack, NULL);
+        maybe_unlink (input_names[i]);
     }
 
- finish:
+    for (i = 0; i < nr; ++i) {
+      fputs (output_names[i], stdout);
+      putc ('\n', stdout);
+      free (input_names[i]);
+    }
+    if (!skip_debug) {
+      for (i = 0; i < ltoobj_argc; ++i)
+        if (early_debug_object_names[i] != NULL)
+          printf ("%s\n", early_debug_object_names[i]);
+    }
+    nr = 0;
+    free (ltrans_priorities);
+    free (output_names);
+    output_names = NULL;
+    free (early_debug_object_names);
+    early_debug_object_names = NULL;
+    free (input_names);
+    free (list_option_full);
+    obstack_free (&env_obstack, NULL);
+  }
+
+finish:
   XDELETE (lto_argv);
   obstack_free (&argv_obstack, NULL);
 }
 
 
 /* Entry point.  */
+int main (int argc, char *argv[]) {
+  fprintf(stderr, "JOHN PRINT: lto-wrapper\n");
+
+  char cwd[PATH_MAX];
+  if (getcwd(cwd, sizeof(cwd)) != NULL) {
+    fprintf(stderr, "Current working dir: %s\n", cwd);
+  } else {
+    perror("getcwd() error");
+    return 1;
+  }
+  fflush(stderr);
+
+  sleep(5);
 
-int
-main (int argc, char *argv[])
-{
   const char *p;
 
   init_opts_obstack ();
diff --git a/gcc/mapper-client.cc b/gcc/mapper-client.cc
new file mode 100644 (file)
index 0000000..5b36bc5
--- /dev/null
@@ -0,0 +1,331 @@
+/* C++ modules.  Experimental!
+   Copyright (C) 2017-2020 Free Software Foundation, Inc.
+   Written by Nathan Sidwell <nathan@acm.org> while at FaceBook
+
+   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/>.  */
+
+#include "config.h"
+#include "system.h"
+
+#include "line-map.h"
+#include "diagnostic-core.h"
+#define MAPPER_FOR_GCC 1
+#include "mapper.h"
+
+module_client::module_client (pex_obj *p, int fd_from, int fd_to)
+  : Client (fd_from, fd_to), pex (p)
+{
+}
+
+static module_client *
+spawn_mapper_program (char const **errmsg, std::string &name,
+                     char const *full_program_name)
+{
+  /* Split writable at white-space.  No space-containing args for
+     you!  */
+  // At most every other char could be an argument
+  char **argv = new char *[name.size () / 2 + 2];
+  unsigned arg_no = 0;
+  char *str = new char[name.size ()];
+  memcpy (str, name.c_str () + 1, name.size ());
+
+  for (auto ptr = str; ; ++ptr)
+    {
+      while (*ptr == ' ')
+       ptr++;
+      if (!*ptr)
+       break;
+      argv[arg_no++] = ptr;
+      while (*ptr && *ptr != ' ')
+       ptr++;
+      if (!*ptr)
+       break;
+      *ptr = 0;
+    }
+  argv[arg_no] = nullptr;
+
+  auto *pex = pex_init (PEX_USE_PIPES, progname, NULL);
+  FILE *to = pex_input_pipe (pex, false);
+  name = argv[0];
+  if (!to)
+    *errmsg = "connecting input";
+  else
+    {
+      int flags = PEX_SEARCH;
+         
+      if (full_program_name)
+       {
+         /* Prepend the invoking path.  */
+         size_t dir_len = progname - full_program_name;
+         std::string argv0;
+         argv0.reserve (dir_len + name.size ());
+         argv0.append (full_program_name, dir_len).append (name);
+         name = std::move (argv0);
+         argv[0] = const_cast <char *> (name.c_str ());
+         flags = 0;
+       }
+      int err;
+      *errmsg = pex_run (pex, flags, argv[0], argv, NULL, NULL, &err);
+    }
+  delete[] str;
+  delete[] argv;
+
+  int fd_from = -1, fd_to = -1;
+  if (!*errmsg)
+    {
+      FILE *from = pex_read_output (pex, false);
+      if (from && (fd_to = dup (fileno (to))) >= 0)
+       fd_from = fileno (from);
+      else
+       *errmsg = "connecting output";
+      fclose (to);
+    }
+
+  if (*errmsg)
+    {
+      pex_free (pex);
+      return nullptr;
+    }
+
+  return new module_client (pex, fd_from, fd_to);
+}
+
+module_client *
+module_client::open_module_client (location_t loc, const char *o,
+                                  void (*set_repo) (const char *),
+                                  char const *full_program_name)
+{
+  fprintf(stderr, "\tinside open_module_client\n");
+
+  module_client *c = nullptr;
+  std::string ident;
+  std::string name;
+  char const *errmsg = nullptr;
+
+  if (o && o[0])
+    {
+      fprintf(stderr, "\tmaybe a local or ipv6 address\n");
+      /* Maybe a local or ipv6 address.  */
+      name = o;
+      auto last = name.find_last_of ('?');
+      if (last != name.npos)
+       {
+         ident = name.substr (last + 1);
+         name.erase (last);
+       }
+
+      if (name.size ())
+       {
+         switch (name[0])
+           {
+           case '<':
+             // <from>to or <>fromto, or <>
+             {
+               int fd_from = -1, fd_to = -1;
+               char const *ptr = name.c_str ();
+               char *eptr;
+
+               fd_from = strtoul (++ptr, &eptr, 0);
+               if (*eptr == '>')
+                 {
+                   ptr = eptr;
+                   fd_to = strtoul (++ptr, &eptr, 0);
+                   if (eptr != ptr && ptr == name.c_str () + 1)
+                     fd_from = fd_to;
+                 }
+
+               if (*eptr)
+                 errmsg = "parsing";
+               else
+                 {
+                   if (name.size () == 2)
+                     {
+                       fd_from = fileno (stdin);
+                       fd_to = fileno (stdout);
+                     }
+                   c = new module_client (fd_from, fd_to);
+                 }
+             }
+             break;
+
+           case '=':
+             // =localsocket
+             {
+               int fd = Cody::OpenLocal (&errmsg, name.c_str () + 1);
+               if (fd >= 0)
+                 c = new module_client (fd, fd);
+             }
+             break;
+
+           case '|':
+             // |program and args
+             c = spawn_mapper_program (&errmsg, name, full_program_name);
+             break;
+
+           default:
+             // file or hostname:port
+             {
+               auto colon = name.find_last_of (':');
+               if (colon != name.npos)
+                 {
+                   char const *cptr = name.c_str () + colon;
+                   char *endp;
+                   unsigned port = strtoul (cptr + 1, &endp, 10);
+
+                   if (port && endp != cptr + 1 && !*endp)
+                     {
+                       name[colon] = 0;
+                       int fd = Cody::OpenInet6 (&errmsg, name.c_str (), port);
+                       name[colon] = ':';
+
+                       if (fd >= 0)
+                         c = new module_client (fd, fd);
+                     }
+                 }
+               
+             }
+             break;
+           }
+       }
+    }
+
+  if (!c)
+    {
+    fprintf(stderr, "\tmake a default in-process client\n");
+
+      // Make a default in-process client
+      auto r = new module_resolver ();
+    fprintf(stderr, "\tcreated module_resolver\n");
+      auto *s = new Cody::Server (r);
+    fprintf(stderr, "\tcreated Cody::Server\n");
+      c = new module_client (s);
+    fprintf(stderr, "\tcreated module_client\n");
+      if (!errmsg && !name.empty ())
+       {
+       int fd = open (name.c_str (), O_RDONLY | O_CLOEXEC);
+       if (fd < 0)
+         errmsg = "opening";
+       else
+         {
+           if (r->read_tuple_file (fd, ident, false))
+             errmsg = "reading";
+             
+           close (fd);
+         }
+       }
+      else
+       {
+         r->set_repo ("gcm.cache");
+         r->set_default (true);
+       }
+    }
+
+#ifdef SIGPIPE
+  fprintf(stderr, "\tSIGPIPE\n");
+  if (!c->IsDirect ()) {
+    /* We need to ignore sig pipe for a while.  */
+    c->sigpipe = signal (SIGPIPE, SIG_IGN);
+  }
+#endif
+
+  fprintf(stderr, "\tcheck for errmsg\n");
+  if (errmsg) {
+    fprintf(stderr, "\terror! %s mapper %s\n", errmsg, name.c_str());
+    error_at (loc, "failed %s mapper %qs", errmsg, name.c_str ());
+  }
+  fprintf(stderr, "\tc->Cork\n");
+
+  // now wave hello!
+  c->Cork ();
+  fprintf(stderr, "\tc->Connect\n");
+
+  c->Connect (std::string ("GCC"), ident);
+  //if( c->Connect("TEST" , "IDENT").GetCode() != Client::PC_CORKED ) {
+  //  fprintf(stderr, "\tclient is not corked!!\n");
+  //}
+
+  //fprintf(stderr, "\tc->ModuleRepo\n");
+
+  //c->ModuleRepo ();
+  fprintf(stderr, "\tc->Uncork\n");
+
+  auto packets = c->Uncork ();
+
+  fprintf(stderr, "\ttime to look at the packets..\n");
+
+  auto &connect = packets[0];
+  if (connect.GetCode () == Cody::Client::PC_CONNECT) {
+    fprintf(stderr, "\tgood PC_CONNECT\n");
+  }
+  else if (connect.GetCode () == Cody::Client::PC_ERROR) {
+    fprintf(stderr, "\tfailed PC_ERROR\n");
+    error_at (loc, "failed mapper handshake %s", connect.GetString ().c_str ());
+  }
+
+  //auto &repo = packets[1];
+  //if (repo.GetCode () == Cody::Client::PC_MODULE_REPO)
+  //  set_repo (repo.GetString ().c_str ());
+
+  return c;
+}
+
+void
+module_client::close_module_client (location_t loc, module_client *mapper)
+{
+  if (mapper->IsDirect ())
+    {
+      auto *s = mapper->GetServer ();
+      auto *r = s->GetResolver ();
+      delete s;
+      delete r;
+    }
+  else
+    {
+      if (mapper->pex)
+       {
+         int fd_write = mapper->GetFDWrite ();
+         if (fd_write >= 0)
+           close (fd_write);
+
+         int status;
+         pex_get_status (mapper->pex, 1, &status);
+
+         pex_free (mapper->pex);
+         mapper->pex = NULL;
+
+         if (WIFSIGNALED (status))
+           error_at (loc, "mapper died by signal %s",
+                     strsignal (WTERMSIG (status)));
+         else if (WIFEXITED (status) && WEXITSTATUS (status) != 0)
+           error_at (loc, "mapper exit status %d",
+                     WEXITSTATUS (status));
+       }
+      else
+       {
+         int fd_read = mapper->GetFDRead ();
+         close (fd_read);
+       }
+
+#ifdef SIGPIPE
+      // Restore sigpipe
+      if (mapper->sigpipe != SIG_IGN)
+       signal (SIGPIPE, mapper->sigpipe);
+#endif
+    }
+
+  delete mapper;
+}
diff --git a/gcc/mapper-resolver.cc b/gcc/mapper-resolver.cc
new file mode 100644 (file)
index 0000000..be4849d
--- /dev/null
@@ -0,0 +1,246 @@
+/* C++ modules.  Experimental! -*- c++-mode -*-
+   Copyright (C) 2017-2020 Free Software Foundation, Inc.
+   Written by Nathan Sidwell <nathan@acm.org> while at FaceBook
+
+   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/>.  */
+
+#include "mapper.h"
+// C++
+#include <algorithm>
+// C
+#include <cstring>
+// OS
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+module_resolver::module_resolver (bool def)
+  : provide_default (def)
+{
+  fprintf(stderr, "\t module_resolver constructor \n");
+
+}
+
+module_resolver::~module_resolver ()
+{
+  if (fd_repo >= 0)
+    close (fd_repo);
+}
+
+bool
+module_resolver::set_repo (std::string &&r, bool force)
+{
+  if (force || repo.empty ())
+    {
+      repo = std::move (r);
+      force = true;
+    }
+  return force;
+}
+
+bool
+module_resolver::add_mapping (std::string &&module, std::string &&file,
+                             bool force)
+{
+  auto res = map.emplace (std::move (module), std::move (file));
+  if (res.second)
+    force = true;
+  else if (force)
+    res.first->second = std::move (file);
+
+  return force;
+}
+
+int
+module_resolver::read_tuple_file (int fd, char const *prefix, bool force)
+{
+  struct stat stat;
+  if (fstat (fd, &stat) < 0)
+    return -errno;
+
+  // Just Map the file, we're gonna read all of it, so no need for
+  // line buffering
+  void *buffer = mmap (nullptr, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+  if (buffer == MAP_FAILED)
+    return -errno;
+
+  size_t prefix_len = prefix ? strlen (prefix) : 0;
+  unsigned lineno = 0;
+
+  for (char const *begin = reinterpret_cast <char const *> (buffer),
+        *end = begin + stat.st_size, *eol;
+       begin != end; begin = eol + 1)
+    {
+      lineno++;
+      eol = std::find (begin, end, '\n');
+      if (eol == end)
+       // last line has no \n, ignore the line, you lose
+       break;
+
+      auto *pos = begin;
+      bool pfx_search = prefix_len != 0;
+
+    pfx_search:
+      while (*pos == ' ' || *pos == '\t')
+       pos++;
+
+      auto *space = pos;
+      while (*space != '\n' && *space != ' ' && *space != '\t')
+       space++;
+
+      if (pos == space)
+       // at end of line, nothing here 
+       continue;
+
+      if (pfx_search)
+       {
+         if (size_t (space - pos) == prefix_len
+             && std::equal (pos, space, prefix))
+           pfx_search = false;
+         pos = space;
+         goto pfx_search;
+       }
+
+      std::string module (pos, space);
+      while (*space == ' ' || *space == '\t')
+       space++;
+      std::string file (space, eol);
+
+      if (module[0] == '$')
+       {
+         if (module == "$root")
+           set_repo (std::move (file));
+         else
+           return lineno;
+       }
+      else
+       {
+         if (file.empty ())
+           file = GetCMIName (module);
+         add_mapping (std::move (module), std::move (file), force);
+       }
+    }
+
+  munmap (buffer, stat.st_size);
+
+  return 0;
+}
+
+char const *
+module_resolver::GetCMISuffix ()
+{
+  return "gcm";
+}
+
+module_resolver *
+module_resolver::ConnectRequest (Cody::Server *s, unsigned version,
+                                std::string &a, std::string &i)
+{
+  if (!version || version > Cody::Version)
+    s->ErrorResponse ("version mismatch");
+  else if (a != "GCC")
+    // Refuse anything but GCC
+    ErrorResponse (s, std::string ("only GCC supported"));
+  else if (!ident.empty () && ident != i)
+    // Failed ident check
+    ErrorResponse (s, std::string ("bad ident"));
+  else
+    // Success!
+    s->ConnectResponse ("gcc");
+
+  return this;
+}
+
+int
+module_resolver::ModuleRepoRequest (Cody::Server *s)
+{
+  s->ModuleRepoResponse (repo);
+  return 0;
+}
+
+int
+module_resolver::cmi_response (Cody::Server *s, std::string &module)
+{
+  auto iter = map.find (module);
+  if (iter == map.end ())
+    {
+      std::string file;
+      if (provide_default)
+       file = std::move (GetCMIName (module));
+      auto res = map.emplace (module, file);
+      iter = res.first;
+    }
+
+  if (iter->second.empty ())
+    s->ErrorResponse ("no such module");
+  else
+    s->ModuleCMIResponse (iter->second);
+
+  return 0;
+}
+
+int
+module_resolver::ModuleExportRequest (Cody::Server *s, std::string &module)
+{
+  return cmi_response (s, module);
+}
+
+int
+module_resolver::ModuleImportRequest (Cody::Server *s, std::string &module)
+{
+  return cmi_response (s, module);
+}
+
+int
+module_resolver::IncludeTranslateRequest (Cody::Server *s,
+                                             std::string &include)
+{
+  auto iter = map.find (include);
+  if (iter == map.end ())
+    {
+      // Not found, look for it
+      if (fd_repo == -1 && !repo.empty ())
+       {
+         fd_repo = open (repo.c_str (), O_RDONLY | O_CLOEXEC | O_DIRECTORY);
+         if (fd_repo < 0)
+           fd_repo = -2;
+       }
+
+      if (fd_repo >= 0 || repo.empty ())
+       {
+         auto file = GetCMIName (include);
+         struct stat statbuf;
+         if (fstatat (repo.empty () ? AT_FDCWD : fd_repo,
+                      file.c_str (), &statbuf, 0) < 0
+             || !S_ISREG (statbuf.st_mode))
+           // Mark as not present
+           file.clear ();
+         auto res = map.emplace (include, file);
+         iter = res.first;
+       }
+    }
+
+  if (iter == map.end () || iter->second.empty ())
+    s->IncludeTranslateResponse (false);
+  else
+    s->ModuleCMIResponse (iter->second);
+
+  return 0;
+}
+
diff --git a/gcc/mapper-server.cc b/gcc/mapper-server.cc
new file mode 100644 (file)
index 0000000..23b847f
--- /dev/null
@@ -0,0 +1,994 @@
+/* C++ modules.  Experimental!
+   Copyright (C) 2018-2020 Free Software Foundation, Inc.
+   Written by Nathan Sidwell <nathan@acm.org> while at FaceBook
+
+   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/>.  */
+
+#include "config.h"
+#include "mapper.h"
+
+// C++
+#include <set>
+#include <vector>
+// GCC
+#define INCLUDE_VECTOR
+#define INCLUDE_MAP
+#define INCLUDE_SET
+
+// Network
+/* Include network stuff first.  Excitingly OSX10.14 uses bcmp here, which
+   we poison later!  */
+#if defined (HAVE_AF_UNIX) || defined (HAVE_AF_INET6)
+/* socket, bind, listen, accept{4}  */
+# define NETWORKING 1
+# include <sys/socket.h>
+# ifdef HAVE_AF_UNIX
+/* sockaddr_un  */
+#  include <sys/un.h>
+# endif
+# include <netinet/in.h>
+# ifdef HAVE_AF_INET6
+/* sockaddr_in6, getaddrinfo, freeaddrinfo, gai_sterror, ntohs, htons.  */
+#  include <netdb.h>
+# endif
+#ifdef HAVE_INET_NTOP
+/* inet_ntop.  */
+#include <arpa/inet.h>
+#endif
+#endif
+#ifndef HAVE_AF_INET6
+# define gai_strerror(X) ""
+#endif
+
+// Excitingly Darwin uses bcmp in its network headers, and we poison
+// that in our setup.
+#include "system.h"
+#include "version.h"
+#include "intl.h"
+#include <getopt.h>
+
+// Select or epoll
+#ifdef NETWORKING
+#ifdef HAVE_EPOLL
+/* epoll_create, epoll_ctl, epoll_pwait  */
+#include <sys/epoll.h>
+#endif
+#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
+/* pselect or select  */
+#include <sys/select.h>
+#endif
+#endif
+
+#ifndef HAVE_SIGHANDLER_T
+typedef void (*sighandler_t) (int);
+#endif
+
+struct netmask {
+  in6_addr addr;
+  unsigned bits;
+
+  netmask (const in6_addr &a, unsigned b)
+  {
+    if (b > sizeof (in6_addr) * 8)
+      b = sizeof (in6_addr) * 8;
+    bits = b;
+    unsigned byte = (b + 7) / 8;
+    unsigned ix = 0;
+    for (ix = 0; ix < byte; ix++)
+      addr.s6_addr[ix] = a.s6_addr[ix];
+    for (; ix != sizeof (in6_addr); ix++)
+      addr.s6_addr[ix] = 0;
+    if (b & 3)
+      addr.s6_addr[b/7] &= (255 << 8) >> (b & 3);
+  }
+
+  bool includes (const in6_addr &a) const
+  {
+    unsigned byte = bits / 8;
+    for (unsigned ix = 0; ix != byte; ix++)
+      if (addr.s6_addr[ix] != a.s6_addr[ix])
+       return false;
+    if (bits & 3)
+      if ((addr.s6_addr[byte] ^ a.s6_addr[byte]) >> (8 - (bits & 3)))
+       return false;
+    return true;
+  }
+};
+
+/* Netmask comparison.  */
+struct netmask_cmp {
+  bool operator() (const netmask &a, const netmask &b) const
+  {
+    if (a.bits != b.bits)
+      return a.bits < b.bits;
+    for (unsigned ix = 0; ix != sizeof (in6_addr); ix++)
+      if (a.addr.s6_addr[ix] != b.addr.s6_addr[ix])
+       return a.addr.s6_addr[ix] < b.addr.s6_addr[ix];
+    return false;
+  }
+};
+
+typedef std::set<netmask, netmask_cmp> netmask_set_t;
+typedef std::vector<netmask> netmask_vec_t;
+
+const char *progname;
+
+/* Speak thoughts out loud.  */
+static bool flag_noisy = false;
+
+/* One and done.  */
+static bool flag_one = false;
+
+/* Serialize connections.  */
+static bool flag_sequential = false;
+
+/* Fallback to default if map file is unrewarding.  */
+static bool flag_fallback = false;
+
+/* Root binary directory.  */
+static const char *flag_root = "gcm.cache";
+
+static netmask_set_t netmask_set;
+
+static netmask_vec_t accept_addrs;
+
+/* Strip out the source directory from FILE.  */
+
+static const char *
+trim_src_file (const char *file)
+{
+  static const char me[] = __FILE__;
+  unsigned pos = 0;
+
+  while (file[pos] == me[pos] && me[pos])
+    pos++;
+  while (pos && !IS_DIR_SEPARATOR (me[pos-1]))
+    pos--;
+
+  return file + pos;
+}
+
+/* Die screaming.  */
+
+void ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD
+internal_error (const char *fmt, ...)
+{
+  fprintf (stderr, "%s:Internal error ", progname);
+  va_list args;
+
+  va_start (args, fmt);
+  vfprintf (stderr, fmt, args);
+  va_end (args);
+  fprintf (stderr, "\n");
+
+  exit (FATAL_EXIT_CODE);
+}
+
+/* Hooked to from gcc_assert & gcc_unreachable.  */
+
+void ATTRIBUTE_NORETURN ATTRIBUTE_COLD
+fancy_abort (const char *file, int line, const char *func)
+{
+  internal_error ("in %s, at %s:%d", func, trim_src_file (file), line);
+}
+
+/* Exploded on a signal.  */
+
+static void ATTRIBUTE_NORETURN ATTRIBUTE_COLD
+crash_signal (int sig)
+{
+  signal (sig, SIG_DFL);
+  internal_error ("signal %s", strsignal (sig));
+}
+
+/* A fatal error of some kind.  */
+
+static void ATTRIBUTE_NORETURN ATTRIBUTE_COLD ATTRIBUTE_PRINTF_1
+error (const char *msg, ...)
+{
+  fprintf (stderr, "%s:error: ", progname);
+  va_list args;
+
+  va_start (args, msg);
+  vfprintf (stderr, msg, args);
+  va_end (args);
+  fprintf (stderr, "\n");
+
+  exit (1);
+}
+
+/* Progress messages to the user.  */
+static bool ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD
+noisy (const char *fmt, ...)
+{
+  fprintf (stderr, "%s:", progname);
+  va_list args;
+  va_start (args, fmt);
+  vfprintf (stderr, fmt, args);
+  va_end (args);
+  fprintf (stderr, "\n");
+
+  return false;
+}
+
+/* More messages to the user.  */
+
+static void ATTRIBUTE_PRINTF_2
+fnotice (FILE *file, const char *fmt, ...)
+{
+  va_list args;
+
+  va_start (args, fmt);
+  vfprintf (file, _(fmt), args);
+  va_end (args);
+}
+
+static void ATTRIBUTE_NORETURN
+print_usage (int error_p)
+{
+  FILE *file = error_p ? stderr : stdout;
+  int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
+
+  fnotice (file, "Usage: cxx-mapper [OPTION...] [CONNECTION] [MAPPINGS...] \n\n");
+  fnotice (file, "C++ Module Mapper.\n\n");
+  fnotice (file, "  -a, --accept     Netmask to accept from\n");
+  fnotice (file, "  -f, --fallback   Use fallback for missing mappings\n");
+  fnotice (file, "  -h, --help       Print this help, then exit\n");
+  fnotice (file, "  -n, --noisy      Print progress messages\n");
+  fnotice (file, "  -1, --one        One connection and then exit\n");
+  fnotice (file, "  -r, --root DIR   Root compiled module directory\n");
+  fnotice (file, "  -s, --sequential Process connections sequentially\n");
+  fnotice (file, "  -v, --version    Print version number, then exit\n");
+  fnotice (file, "Send SIGTERM(%d) to terminate\n", SIGTERM);
+  fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
+          bug_report_url);
+  exit (status);
+}
+
+/* Print version information and exit.  */
+
+static void ATTRIBUTE_NORETURN
+print_version (void)
+{
+  fnotice (stdout, "cxx-mapper %s%s\n", pkgversion_string, version_string);
+  fprintf (stdout, "Copyright %s 2018-2020 Free Software Foundation, Inc.\n",
+          _("(C)"));
+  fnotice (stdout,
+          _("This is free software; see the source for copying conditions.\n"
+            "There is NO warranty; not even for MERCHANTABILITY or \n"
+            "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
+  exit (SUCCESS_EXIT_CODE);
+}
+
+/* ARG is a netmask to accept from.  Add it to the table.  Return
+   false if we fail to resolve it.  */
+
+static bool
+accept_from (char *arg)
+{
+  bool ok = true;
+#if HAVE_AF_INET6
+  unsigned bits = sizeof (in6_addr) * 8;
+  char *slash = strrchr (arg, '/');
+  if (slash)
+    {
+      *slash = 0;
+      if (slash[1])
+       {
+         char *endp;
+         bits = strtoul (slash + 1, &endp, 0);
+       }
+    }
+
+  addrinfo hints;
+
+  hints.ai_flags = AI_NUMERICSERV;
+  hints.ai_family = AF_INET6;
+  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_protocol = 0;
+  hints.ai_addrlen = 0;
+  hints.ai_addr = NULL;
+  hints.ai_canonname = NULL;
+  hints.ai_next = NULL;
+
+  struct addrinfo *addrs = NULL;
+  if (int e = getaddrinfo (slash == arg ? NULL : arg, "0", &hints, &addrs))
+    {
+      noisy ("cannot resolve '%s': %s", arg, gai_strerror (e));
+      ok = false;
+    }
+  else
+    for (addrinfo *next = addrs; next; next = next->ai_next)
+      if (next->ai_family == AF_INET6)
+       {
+         netmask mask (((const sockaddr_in6 *)next->ai_addr)->sin6_addr, bits);
+         netmask_set.insert (mask);
+       }
+  freeaddrinfo (addrs);
+#endif
+  return ok;
+}
+
+/* Process args, return index to first non-arg.  */
+
+static int
+process_args (int argc, char **argv)
+{
+  static const struct option options[] =
+    {
+     { "accept", required_argument, NULL, 'a' },
+     { "fallback",no_argument, NULL, 'f' },
+     { "help", no_argument,    NULL, 'h' },
+     { "noisy",        no_argument,    NULL, 'n' },
+     { "one",  no_argument,    NULL, '1' },
+     { "root", required_argument, NULL, 'r' },
+     { "sequential", no_argument, NULL, 's' },
+     { "version", no_argument, NULL, 'v' },
+     { 0, 0, 0, 0 }
+    };
+  int opt;
+  bool bad_accept = false;
+  const char *opts = "a:fhn1r:sv";
+  while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1)
+    {
+      switch (opt)
+       {
+       case 'a':
+         if (!accept_from (optarg))
+           bad_accept = true;
+         break;
+       case 'f':
+         flag_fallback = true;
+         break;
+       case 'h':
+         print_usage (false);
+         /* print_usage will exit.  */
+       case 'n':
+         flag_noisy = true;
+         break;
+       case '1':
+         flag_one = true;
+         break;
+       case 'r':
+         flag_root = optarg;
+         break;
+       case 's':
+         flag_sequential = true;
+         break;
+       case 'v':
+         print_version ();
+         /* print_version will exit.  */
+       default:
+         print_usage (true);
+         /* print_usage will exit.  */
+       }
+    }
+
+  if (bad_accept)
+    error ("failed to resolve all accept addresses");
+
+  return optind;
+}
+
+/* Manipulate the EPOLL state, or do nothing, if there is epoll.  */
+
+#ifdef HAVE_EPOLL
+static inline void
+do_epoll_ctl (int epoll_fd, int code, int event, int fd, unsigned data)
+{
+  epoll_event ev;
+  ev.events = event;
+  ev.data.u32 = data;
+  if (epoll_ctl (epoll_fd, code, fd, &ev))
+    {
+      noisy ("epoll_ctl error:%s", xstrerror (errno));
+      gcc_unreachable ();
+    }
+}
+#define my_epoll_ctl(EFD,C,EV,FD,CL) \
+  ((EFD) >= 0 ? do_epoll_ctl (EFD,C,EV,FD,CL) : (void)0)
+#else
+#define my_epoll_ctl(EFD,C,EV,FD,CL) ((void)(EFD), (void)(FD), (void)(CL))
+#endif
+
+#ifdef NETWORKING
+/* We increment this to tell the server to shut down.  */
+static volatile int term = false;
+static volatile int kill_sock_fd = -1;
+#if !defined (HAVE_PSELECT) && defined (HAVE_SELECT)
+static int term_pipe[2] = {-1, -1};
+#else
+#define term_pipe ((int *)NULL)
+#endif
+
+/* A terminate signal.  Shutdown gracefully.  */
+
+static void
+term_signal (int sig)
+{
+  signal (sig, term_signal);
+  term = term + 1;
+  if (term_pipe && term_pipe[1] >= 0)
+    write (term_pipe[1], &term_pipe[1], 1);
+}
+
+/* A kill signal.  Shutdown immediately.  */
+
+static void
+kill_signal (int sig)
+{
+  signal (sig, SIG_DFL);
+  int sock_fd = kill_sock_fd;
+  if (sock_fd >= 0)
+    close (sock_fd);
+  exit (2);
+}
+
+bool process_server (Cody::Server *server, unsigned slot, int epoll_fd)
+{
+  switch (server->GetDirection ())
+    {
+    case Cody::Server::READING:
+      if (int err = server->Read ())
+       return !(err == EINTR || err == EAGAIN);
+      server->ProcessRequests ();
+      server->PrepareToWrite ();
+      break;
+
+    case Cody::Server::WRITING:
+      if (int err = server->Write ())
+       return !(err == EINTR || err == EAGAIN);
+      server->PrepareToRead ();
+      break;
+
+    default:
+      // We should never get here
+      return true;
+    }
+
+  // We've changed direction, so update epoll
+  gcc_assert (server->GetFDRead () == server->GetFDWrite ());
+  my_epoll_ctl (epoll_fd, EPOLL_CTL_MOD,
+               server->GetDirection () == Cody::Server::READING
+               ? EPOLLIN : EPOLLOUT, server->GetFDRead (), slot + 1);
+
+  return false;
+}
+
+void close_server (Cody::Server *server, int epoll_fd)
+{
+  my_epoll_ctl (epoll_fd, EPOLL_CTL_DEL, EPOLLIN, server->GetFDRead (), 0);
+
+  close (server->GetFDRead ());
+  
+  delete server;
+}
+
+int open_server (bool ip6, int sock_fd)
+{
+  sockaddr_in6 addr;
+  socklen_t addr_len = sizeof (addr);
+
+#ifdef HAVE_ACCEPT4
+  int client_fd = accept4 (sock_fd, ip6 ? (sockaddr *)&addr : nullptr,
+                          &addr_len, SOCK_NONBLOCK);
+#else
+  int client_fd = accept (sock_fd, ip6 ? (sockaddr *)&addr : nullptr, &addr_len);
+#endif
+  if (client_fd < 0)
+    {
+      error ("cannot accept: %s", xstrerror (errno));
+      flag_one = true;
+    }
+  else if (ip6)
+    {
+      const char *str = NULL;
+#if HAVE_INET_NTOP
+      char name[INET6_ADDRSTRLEN];
+      str = inet_ntop (addr.sin6_family, &addr.sin6_addr, name, sizeof (name));
+#endif
+      if (!accept_addrs.empty ())
+       {
+         netmask_vec_t::iterator e = accept_addrs.end ();
+         for (netmask_vec_t::iterator i = accept_addrs.begin ();
+              i != e; ++i)
+           if (i->includes (addr.sin6_addr))
+             goto present;
+         close (client_fd);
+         client_fd = -1;
+         noisy ("Rejecting connection from disallowed source '%s'",
+                str ? str : "");
+       present:;
+       }
+      if (client_fd >= 0)
+       flag_noisy && noisy ("Accepting connection from '%s'", str ? str : "");
+    }
+
+  return client_fd;
+}
+
+/* A server listening on bound socket SOCK_FD.  */
+
+static void
+server (bool ipv6, int sock_fd, module_resolver *resolver)
+{
+  int epoll_fd = -1;
+
+  signal (SIGTERM, term_signal);
+#ifdef HAVE_EPOLL
+  epoll_fd = epoll_create (1);
+#endif
+  if (epoll_fd >= 0)
+    my_epoll_ctl (epoll_fd, EPOLL_CTL_ADD, EPOLLIN, sock_fd, 0);
+
+#if defined (HAVE_EPOLL) || defined (HAVE_PSELECT) || defined (HAVE_SELECT)
+  sigset_t mask;
+  {
+    sigset_t block;
+    sigemptyset (&block);
+    sigaddset (&block, SIGTERM);
+    sigprocmask (SIG_BLOCK, &block, &mask);
+  }
+#endif
+
+#ifdef HAVE_EPOLL
+  const unsigned max_events = 20;
+  epoll_event events[max_events];
+#endif
+#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
+  fd_set readers, writers;
+#endif
+  if (term_pipe)
+    pipe (term_pipe);
+
+  // We need stable references to servers, so this array can contain nulls
+  std::vector<Cody::Server *> connections;
+  unsigned live = 0;
+  fprintf(stderr, "\tabout to go into a wait loop\n");
+  while (sock_fd >= 0 || live)
+    {
+      /* Wait for one or more events.  */
+      bool eintr = false;
+      int event_count;
+
+      if (epoll_fd >= 0)
+       {
+#ifdef HAVE_EPOLL
+         event_count = epoll_pwait (epoll_fd, events, max_events, -1, &mask);
+#endif
+       }
+      else
+       {
+#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
+         FD_ZERO (&readers);
+         FD_ZERO (&writers);
+
+         unsigned limit = 0;
+         if (sock_fd >= 0
+             && !(term || (live && (flag_one || flag_sequential))))
+           {
+             FD_SET (sock_fd, &readers);
+             limit = sock_fd + 1;
+           }
+
+         if (term_pipe && term_pipe[0] >= 0)
+           {
+             FD_SET (term_pipe[0], &readers);
+             if (unsigned (term_pipe[0]) >= limit)
+               limit = term_pipe[0] + 1;
+           }
+
+         for (auto iter = connections.begin ();
+              iter != connections.end (); ++iter)
+           if (auto *server = *iter)
+             {
+               int fd = -1;
+               switch (server->GetDirection ())
+                 {
+                 case Cody::Server::READING:
+                   fd = server->GetFDRead ();
+                   FD_SET (fd, &readers);
+                   break;
+                 case Cody::Server::WRITING:
+                   fd = server->GetFDWrite ();
+                   FD_SET (fd, &writers);
+                   break;
+                 default:
+                   break;
+                 }
+
+               if (fd >= 0 && limit <= unsigned (fd))
+                 limit = fd + 1;
+             }
+
+#ifdef HAVE_PSELECT
+         event_count = pselect (limit, &readers, &writers, NULL, NULL, &mask);
+#else
+         event_count = select (limit, &readers, &writers, NULL, NULL);
+#endif
+         if (term_pipe && FD_ISSET (term_pipe[0], &readers))
+           {
+             /* Fake up an interrupted system call.  */
+             event_count = -1;
+             errno = EINTR;
+           }
+#endif
+       }
+
+      if (event_count < 0)
+       {
+         // Error in waiting
+         if (errno == EINTR)
+           {
+             flag_noisy && noisy ("Interrupted wait");
+             eintr = true;
+           }
+         else
+           error ("cannot %s: %s", epoll_fd >= 0 ? "epoll_wait"
+#ifdef HAVE_PSELECT
+                  : "pselect",
+#else
+                  : "select",
+#endif
+                  xstrerror (errno));
+         event_count = 0;
+       }
+
+      auto iter = connections.begin ();
+      while (event_count--)
+       {
+         // Process an event
+         int active = -2;
+
+         if (epoll_fd >= 0)
+           {
+#ifdef HAVE_EPOLL
+             /* See PR c++/88664 for why a temporary is used.  */
+             unsigned data = events[event_count].data.u32;
+             active = int (data) - 1;
+#endif
+           }
+         else
+           {
+             for (; iter != connections.end (); ++iter)
+               if (auto *server = *iter)
+                 {
+                   bool found = false;
+                   switch (server->GetDirection ())
+                     {
+#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
+                     case Cody::Server::READING:
+                       found = FD_ISSET (server->GetFDRead (), &readers);
+                       break;
+                     case Cody::Server::WRITING:
+                       found = FD_ISSET (server->GetFDWrite (), &writers);
+                       break;
+#endif
+                     default:
+                       break;
+                     }
+
+                   if (found)
+                     {
+                       active = iter - connections.begin ();
+                       ++iter;
+                       break;
+                     }
+                 }
+
+             if (active < 0 && sock_fd >= 0 && FD_ISSET (sock_fd, &readers))
+               active = -1;
+           }
+
+         if (active >= 0)
+           {
+             // Do the action
+             auto *server = connections[active];
+             if (process_server (server, active, epoll_fd))
+               {
+                 connections[active] = nullptr;
+                 close_server (server, epoll_fd);
+                 live--;
+                 if (flag_sequential)
+                   my_epoll_ctl (epoll_fd, EPOLL_CTL_ADD, EPOLLIN, sock_fd, 0);
+               }
+           }
+         else if (active == -1 && !eintr)
+           {
+             // New connection
+             int fd = open_server (ipv6, sock_fd);
+             if (fd >= 0)
+               {
+#if !defined (HAVE_ACCEPT4) \
+  && (defined (HAVE_EPOLL) || defined (HAVE_PSELECT) || defined (HAVE_SELECT))
+                 int flags = fcntl (fd, F_GETFL, 0);
+                 fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+#endif
+                 auto *server = new Cody::Server (resolver, fd);
+
+                 unsigned slot = connections.size ();
+                 if (live == slot)
+                   connections.push_back (server);
+                 else
+                   for (auto iter = connections.begin (); ; ++iter)
+                     if (!*iter)
+                       {
+                         *iter = server;
+                         slot = iter - connections.begin ();
+                         break;
+                       }
+                 live++;
+                 my_epoll_ctl (epoll_fd, EPOLL_CTL_ADD, EPOLLIN, fd, slot + 1);
+               }
+           }
+
+         if (sock_fd >= 0
+             && (term || (live && (flag_one || flag_sequential))))
+           {
+             /* Stop paying attention to sock_fd.  */
+             my_epoll_ctl (epoll_fd, EPOLL_CTL_DEL, EPOLLIN, sock_fd, 0);
+             if (flag_one || term)
+               {
+                 close (sock_fd);
+                 sock_fd = -1;
+               }
+           }
+       }
+    }
+#if defined (HAVE_EPOLL) || defined (HAVE_PSELECT) || defined (HAVE_SELECT)
+  /* Restore the signal mask.  */
+  sigprocmask (SIG_SETMASK, &mask, NULL);
+#endif
+
+  gcc_assert (sock_fd < 0);
+  if (epoll_fd >= 0)
+    close (epoll_fd);
+
+  if (term_pipe && term_pipe[0] >= 0)
+    {
+      close (term_pipe[0]);
+      close (term_pipe[1]);
+    }
+}
+
+#if 0
+      
+
+      if (eintr)
+       flag_noisy && noisy ("Interrupted wait");
+
+      if (sock_fd >= 0 && (term || flag_one || flag_sequential))
+       {
+         /* Stop paying attention to sock_fd.  */
+         my_epoll_ctl (epoll_fd, EPOLL_CTL_DEL, EPOLLIN, sock_fd, NULL);
+         if (flag_one || term)
+           {
+             close (sock_fd);
+             sock_fd = -1;
+           }
+       }
+    }
+
+#if defined (HAVE_EPOLL) || defined (HAVE_PSELECT) || defined (HAVE_SELECT)
+  /* Restore the signal mask.  */
+  sigprocmask (SIG_SETMASK, &mask, NULL);
+#endif
+
+  gcc_assert (sock_fd < 0);
+  if (epoll_fd >= 0)
+    close (epoll_fd);
+
+  if (term_pipe && term_pipe[0] >= 0)
+    {
+      close (term_pipe[0]);
+      close (term_pipe[1]);
+    }
+}
+#endif
+
+#endif
+
+static int maybe_parse_socket (std::string &option, module_resolver *r)
+{
+  /* Local or ipv6 address.  */
+  auto last = option.find_last_of ('?');
+  if (last != option.npos)
+    {
+      r->set_ident (option.c_str () + last + 1);
+      option.erase (last);
+    }
+  int fd = -2;
+  char const *errmsg = nullptr;
+
+  /* Does it look like a socket?  */
+  if (option[0] == '=')
+    /* A local socket.  */
+    fd = Cody::ListenLocal (&errmsg, option.c_str () + 1);
+  else
+    {
+      auto colon = option.find_last_of (':');
+      if (colon != option.npos)
+       {
+         /* Try a hostname:port address.  */
+         char const *cptr = option.c_str () + colon;
+         char *endp;
+         unsigned port = strtoul (cptr + 1, &endp, 10);
+
+         if (port && endp != cptr + 1 && !*endp)
+           {
+             /* Ends in ':number', treat as ipv6 domain socket.  */
+             option.erase (colon);
+             fd = Cody::ListenInet6 (&errmsg, option.c_str (), port);
+           }
+       }
+    }
+
+  if (errmsg)
+    error ("failed to open socket: %s", errmsg);
+
+  return fd;
+}
+
+int
+main (int argc, char *argv[])
+{
+  fprintf(stderr, "\tmapper-server main\n");
+
+  const char *p = argv[0] + strlen (argv[0]);
+  while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
+    --p;
+  progname = p;
+
+  xmalloc_set_program_name (progname);
+  fprintf(stderr, "\tsignals\n");
+
+#ifdef SIGSEGV
+  signal (SIGSEGV, crash_signal);
+#endif
+#ifdef SIGILL
+  signal (SIGILL, crash_signal);
+#endif
+#ifdef SIGBUS
+  signal (SIGBUS, crash_signal);
+#endif
+#ifdef SIGABRT
+  signal (SIGABRT, crash_signal);
+#endif
+#ifdef SIGFPE
+  signal (SIGFPE, crash_signal);
+#endif
+#ifdef SIGPIPE
+  /* Ignore sigpipe, so read/write get an error.  */
+  signal (SIGPIPE, SIG_IGN);
+#endif
+#ifdef SIGINT
+  signal (SIGINT, kill_signal);
+#endif
+
+  int argno = process_args (argc, argv);
+
+  module_resolver r;
+  fprintf(stderr, "\tgot a module_resolver\n");
+  if (flag_root)
+    r.set_repo (flag_root);
+
+  std::string name;
+  int sock_fd = -1; /* Socket fd, otherwise stdin/stdout.  */
+
+  fprintf(stderr, "\tneed a sock_fd\n");
+  if (argno != argc)
+    {
+      name = argv[argno];
+      sock_fd = maybe_parse_socket (name, &r);
+      if (!name.empty ())
+       argno++;
+    }
+  fprintf(stderr, "\tsock_fd?  = %d\n", sock_fd);
+
+  if (argno != argc)
+    for (; argno != argc; argno++)
+      {
+       std::string option = argv[argno];
+       char const *prefix = nullptr;
+       auto ident = option.find_last_of ('?');
+       if (ident != option.npos)
+         {
+           prefix = option.c_str () + ident + 1;
+           option[ident] = 0;
+         }
+       int fd = open (option.c_str (), O_RDONLY | O_CLOEXEC);
+       int err = 0;
+       if (fd < 0)
+         err = errno;
+       else
+         {
+           err = r.read_tuple_file (fd, prefix, false);
+           close (fd);
+         }
+
+       if (err)
+         error ("failed reading '%s': %s", option.c_str (), xstrerror (err));
+      }
+  else
+    flag_fallback = true;
+  r.set_default (flag_fallback);
+
+  fprintf(stderr, "\tnetmask stuff\n");
+#ifdef HAVE_AF_INET6
+  netmask_set_t::iterator end = netmask_set.end ();
+  for (netmask_set_t::iterator iter = netmask_set.begin ();
+       iter != end; ++iter)
+    {
+      netmask_vec_t::iterator e = accept_addrs.end ();
+      for (netmask_vec_t::iterator i = accept_addrs.begin (); i != e; ++i)
+       if (i->includes (iter->addr))
+         goto present;
+      accept_addrs.push_back (*iter);
+    present:;
+    }
+#endif
+
+#ifdef NETWORKING
+  if (sock_fd >= 0)
+    {
+    fprintf(stderr, "\tstarting a server\n");
+      server (name[0] != '=', sock_fd, &r);
+    fprintf(stderr, "\tgot a server\n");
+      if (name[0] == '=')
+       unlink (name.c_str () + 1);
+    fprintf(stderr, "\t name: %s \n", name.c_str());
+    }
+  else
+#endif
+    {
+    fprintf(stderr, "\tabout to loop infinitely\n");
+
+
+      gcc_assert (sock_fd < 0);
+      auto server = Cody::Server (&r, 0, 1);
+
+    fprintf(stderr, "\tmade a cody server\n");
+
+      int err = 0;
+      for (;;)
+       {
+         server.PrepareToRead ();
+         while ((err = server.Read ()))
+           {
+             if (err == EINTR || err == EAGAIN)
+               continue;
+             goto done;
+           }
+
+         server.ProcessRequests ();
+
+         server.PrepareToWrite ();
+         while ((err = server.Write ()))
+           {
+             if (err == EINTR || err == EAGAIN)
+               continue;
+             goto done;
+           }
+       }
+    done:;
+      if (err > 0)
+       error ("communication error:%s", xstrerror (err));
+    }
+
+  return 0;
+}
diff --git a/gcc/mapper.h b/gcc/mapper.h
new file mode 100644 (file)
index 0000000..f794012
--- /dev/null
@@ -0,0 +1,117 @@
+/* C++ modules.  Experimental! -*- c++ -*-
+   Copyright (C) 2017-2020 Free Software Foundation, Inc.
+   Written by Nathan Sidwell <nathan@acm.org> while at FaceBook
+
+   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/>.  */
+
+// Mapper interface for client and server bits
+#include "cody.hh"
+// C++
+#include <string>
+#include <map>
+
+// This is a GCC class, so GCC coding conventions on new bits.  
+class module_resolver : public Cody::Resolver
+{
+public:
+  using parent = Cody::Resolver;
+  using module_map = std::map<std::string, std::string>;
+
+private:
+  std::string repo;
+  std::string ident;
+  module_map map;
+  int fd_repo = -1;
+  bool provide_default = true;
+
+public:
+  module_resolver (bool def = true);
+  virtual ~module_resolver () override;
+
+public:
+  void set_default (bool d)
+  {
+    provide_default = d;
+  }
+  void set_ident (char const *i)
+  {
+    ident = i;
+  }
+  bool set_repo (std::string &&repo, bool force = false);
+  bool add_mapping (std::string &&module, std::string &&file,
+                   bool force = false);
+
+  // Return +ve line number of error, or -ve errno
+  int read_tuple_file (int fd, char const *prefix, bool force = false);
+  int read_tuple_file (int fd, std::string const &prefix,
+                           bool force = false)
+  {
+    return read_tuple_file (fd, prefix.empty () ? nullptr : prefix.c_str (),
+                           force);
+  }
+
+public:
+  // Virtual overriders, names are controlle by Cody::Resolver
+  virtual module_resolver *ConnectRequest (Cody::Server *, unsigned version,
+                                          std::string &agent,
+                                          std::string &ident)
+    override;
+  virtual int ModuleRepoRequest (Cody::Server *) override;
+  virtual int ModuleExportRequest (Cody::Server *s, std::string &module)
+    override;
+  virtual int ModuleImportRequest (Cody::Server *s, std::string &module)
+    override;
+  virtual int IncludeTranslateRequest (Cody::Server *s, std::string &include)
+    override;
+
+private:
+  virtual char const *GetCMISuffix () override;
+
+private:
+  int cmi_response (Cody::Server *s, std::string &module);
+};
+
+#ifdef MAPPER_FOR_GCC
+#ifndef HAVE_SIGHANDLER_T
+typedef void (*sighandler_t) (int);
+#endif
+
+class module_client : public Cody::Client
+{
+  pex_obj *pex = nullptr;
+  sighandler_t sigpipe = SIG_IGN;
+
+public:
+  module_client (Cody::Server *s)
+    : Client (s)
+  {
+  }
+  module_client (pex_obj *pex, int fd_from, int fd_to);
+
+  module_client (int fd_from, int fd_to)
+    : Client (fd_from, fd_to)
+  {
+  }
+
+public:
+  static module_client *open_module_client (location_t loc, const char *option,
+                                           void (*set_repo) (const char *),
+                                           char const *);
+  static void close_module_client (location_t loc, module_client *);
+};
+
+#endif