diff options
author | John Ravi <jjravi@ncsu.edu> | 2020-06-30 17:31:20 -0400 |
---|---|---|
committer | John Ravi <jjravi@ncsu.edu> | 2020-06-30 17:31:20 -0400 |
commit | 5946cce94dd0d7e92703b5bd319ba17266cb9c6e (patch) | |
tree | 71173edd7df0127465dcec352cf76c90cbf1e446 /gcc | |
parent | 0a1ce58cbde6ce7ca7cc65d0554c218a85236bfe (diff) | |
download | gcc-5946cce94dd0d7e92703b5bd319ba17266cb9c6e.zip gcc-5946cce94dd0d7e92703b5bd319ba17266cb9c6e.tar.gz gcc-5946cce94dd0d7e92703b5bd319ba17266cb9c6e.tar.bz2 |
Revert "adding libcody to lto-wrapper, with some leftover debugging code"
This reverts commit 0a1ce58cbde6ce7ca7cc65d0554c218a85236bfe.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/Makefile.in | 35 | ||||
-rw-r--r-- | gcc/config.in | 66 | ||||
-rwxr-xr-x | gcc/configure | 306 | ||||
-rw-r--r-- | gcc/configure.ac | 137 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 2 | ||||
-rw-r--r-- | gcc/lto-wrapper.c | 2612 | ||||
-rw-r--r-- | gcc/mapper-client.cc | 331 | ||||
-rw-r--r-- | gcc/mapper-resolver.cc | 246 | ||||
-rw-r--r-- | gcc/mapper-server.cc | 994 | ||||
-rw-r--r-- | gcc/mapper.h | 117 |
10 files changed, 1346 insertions, 3500 deletions
diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 6785617..d5dcc03 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -388,10 +388,6 @@ 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@ @@ -1073,7 +1069,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) $(CODYLIB) $(PLUGINLIBS) $(HOST_LIBS) \ +BACKENDLIBS = $(ISLLIBS) $(GMPLIBS) $(PLUGINLIBS) $(HOST_LIBS) \ $(ZLIB) $(ZSTD_LIB) # Any system libraries needed just for GNAT. SYSLIBS = @GNAT_LIBEXC@ @@ -1107,7 +1103,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) $(CODYLIBINC) $(DECNUMINC) $(BACKTRACEINC) \ + $(CPPINC) $(GMPINC) $(DECNUMINC) $(BACKTRACEINC) \ $(ISLINC) COMPILE.base = $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) -o $@ @@ -1692,7 +1688,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 mapper-client.o mapper-resolver.o mapper-server.o collect-utils.o + lto-wrapper.o collect-utils.o # for anything that is shared use the cc1plus profile data, as that # is likely the most exercised during the build @@ -1767,22 +1763,16 @@ SELFTEST_DEPS = $(GCC_PASSES) stmp-int-hdrs $(srcdir)/testsuite/selftests gnat_install_lib = @gnat_install_lib@ # per-language makefile fragments -ifneq ($(LANG_MAKEFRAGS),) -include $(LANG_MAKEFRAGS) -endif +-include $(LANG_MAKEFRAGS) # target and host overrides must follow the per-language makefile fragments # so they can override or augment language-specific variables # target overrides -ifneq ($(tmake_file),) -include $(tmake_file) -endif +-include $(tmake_file) # host overrides -ifneq ($(xmake_file),) -include $(xmake_file) -endif +-include $(xmake_file) # all-tree.def includes all the tree.def files. all-tree.def: s-alltree; @true @@ -2197,16 +2187,11 @@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS) CFLAGS-collect2.o += -DTARGET_MACHINE=\"$(target_noncanonical)\" \ @TARGET_SYSTEM_ROOT_DEFINE@ -LTO_WRAPPER_OBJS = lto-wrapper.o mapper-client.o mapper-resolver.o collect-utils.o ggc-none.o +LTO_WRAPPER_OBJS = lto-wrapper.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 $(CODYLIB) $(LIBS) + $(LTO_WRAPPER_OBJS) libcommon-target.a $(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. @@ -3698,10 +3683,6 @@ 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. diff --git a/gcc/config.in b/gcc/config.in index d297dbc..364eba4 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -308,24 +308,6 @@ #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 @@ -1179,18 +1161,6 @@ #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 @@ -1461,12 +1431,6 @@ #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 @@ -1731,12 +1695,6 @@ #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 @@ -1780,18 +1738,6 @@ #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 @@ -1804,12 +1750,6 @@ #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 @@ -1822,12 +1762,6 @@ #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 diff --git a/gcc/configure b/gcc/configure index 6a69799..f224679 100755 --- a/gcc/configure +++ b/gcc/configure @@ -639,8 +639,6 @@ PICFLAG enable_host_shared enable_plugin pluginlibs -CODYLIBINC -CODYLIB ISLINC ISLLIBS GMPINC @@ -1040,9 +1038,7 @@ CPP GMPLIBS GMPINC ISLLIBS -ISLINC -CODYLIB -CODYLIBINC' +ISLINC' # Initialize some variables set by options. @@ -1870,8 +1866,6 @@ 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. @@ -10206,14 +10200,6 @@ _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" @@ -11937,296 +11923,6 @@ $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" diff --git a/gcc/configure.ac b/gcc/configure.ac index 81b6cb7..e83f083 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -1439,10 +1439,6 @@ 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 @@ -1588,136 +1584,6 @@ 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" @@ -6832,9 +6698,6 @@ 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) diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 41de295..7896591 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -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) mapper-server$(exeext) +c++: cc1plus$(exeext) # Tell GNU make to ignore these if they exist. .PHONY: c++ diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index ac77e53..939a83a 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -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,16 +25,17 @@ we are in whopr mode or not modifies the arguments and needed and prints a list of output files on stdout. -Example: -$ lto-wrapper gcc/xgcc -B gcc a.o b.o -o test -flto + Example: -The above will print something like -/tmp/ccwbQ8B2.lto.o + $ lto-wrapper gcc/xgcc -B gcc a.o b.o -o test -flto -If WHOPR is used instead, more than one file might be produced -./ccXj2DTk.lto.ltrans.o -./ccCJuXGv.lto.ltrans.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 +*/ #include "config.h" #include "system.h" @@ -47,11 +48,6 @@ If WHOPR is used instead, more than one file might be produced #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. */ @@ -88,48 +84,11 @@ static bool xassembler_options_error = false; const char tool_name[] = "lto-wrapper"; -/********************************************************************/ - -// 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. */ - -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) { +void +tool_cleanup (bool) +{ unsigned int i; if (ltrans_output_file) @@ -143,25 +102,32 @@ void 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); } @@ -172,10 +138,12 @@ void 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; @@ -184,50 +152,55 @@ static void 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; @@ -247,313 +220,334 @@ static void 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++; - } - 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); + || (*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++; } - else if (pie_option->opt_index == OPT_fpie - && (*decoded_options)[j].opt_index == OPT_fPIE) + else if ((*decoded_options)[j].opt_index == OPT_fPIE + || (*decoded_options)[j].opt_index == OPT_fpie) { - (*decoded_options)[j] = *pie_option; - j++; + /* -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++; } - 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; } @@ -562,17 +556,19 @@ static void ** 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; @@ -581,220 +577,243 @@ static unsigned parse_env_var (const char *str, char ***pvalues, const char *app 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; + 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]); } - - /* 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; + 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]); } - - /* 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; + 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]); } - - /* 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++; +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]); } - - 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); } @@ -802,16 +821,19 @@ static int 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"); @@ -821,18 +843,24 @@ static char * compile_offload_image (const char *target, const char *compiler_pa 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); + "could not find %s in %s (consider using %<-B%>)", + suffix + 1, compiler_path); + + dumpbase = concat (dumppfx, "x", target, NULL); /* Generate temporary output file name. */ - filename = make_temp_file (".target.o"); + if (save_temps) + filename = concat (dumpbase, ".o", NULL); + else + filename = make_temp_file (".target.o"); struct obstack argv_obstack; obstack_init (&argv_obstack); @@ -850,15 +878,18 @@ static char * compile_offload_image (const char *target, const char *compiler_pa /* 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 **); @@ -875,11 +906,13 @@ static char * compile_offload_image (const char *target, const char *compiler_pa 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) @@ -894,52 +927,57 @@ static void compile_images_for_offload_targets (unsigned in_argc, /* 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) -{ -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) + +static void +copy_file (const char *dest, const char *src) { -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) @@ -948,17 +986,18 @@ static void 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); } @@ -969,10 +1008,11 @@ static void 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; @@ -983,7 +1023,7 @@ static bool find_and_merge_options (int fd, off_t file_offset, simple_object_read *sobj; sobj = simple_object_start_read (fd, file_offset, "__GNU_LTO", - &errmsg, &err); + &errmsg, &err); if (!sobj) return false; @@ -991,32 +1031,35 @@ static bool find_and_merge_options (int fd, off_t file_offset, 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); + 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; - } + fopts += strlen (fopts) + 1; + } while (fopts - data < length); free (data); @@ -1029,7 +1072,9 @@ static bool find_and_merge_options (int fd, off_t file_offset, /* 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; @@ -1040,43 +1085,46 @@ const char * 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); @@ -1086,7 +1134,9 @@ const char * 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); } @@ -1100,7 +1150,8 @@ 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); @@ -1113,12 +1164,13 @@ 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 } @@ -1127,7 +1179,9 @@ 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); @@ -1137,47 +1191,49 @@ static void 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; @@ -1193,9 +1249,11 @@ static void 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) @@ -1209,10 +1267,10 @@ static const char * 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"; @@ -1220,9 +1278,9 @@ static const char * jobserver_active_p (void) { /* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */ -static void run_gcc (unsigned argc, char *argv[]) { - fprintf(stderr, "JOHN PRINT: run_gcc\n"); - +static void +run_gcc (unsigned argc, char *argv[]) +{ unsigned i, j; const char **new_argv; const char **argv_ptr; @@ -1249,40 +1307,41 @@ static void run_gcc (unsigned argc, char *argv[]) { bool linker_output_rel = false; bool skip_debug = false; unsigned n_debugobj; - const char *dumppfx = NULL, *incoming_dumppfx = NULL; + const char *incoming_dumppfx = 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. */ @@ -1290,53 +1349,56 @@ static void 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]; + 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); } - close (fd); - } /* Initalize the common arguments for the driver. */ obstack_init (&argv_obstack); @@ -1345,122 +1407,134 @@ static void 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); + if (verbose) + { + for (i = 0; i < argc; ++i) + { + fputs (argv[i], stderr); + fputc (' ', stderr); + } + fputc ('\n', 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; - } - 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 (no_partition) + { + lto_mode = LTO_MODE_LTO; + jobserver = 0; + auto_parallel = 0; + parallel = 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 + 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 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 @@ -1472,155 +1546,166 @@ static void 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); + 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); + } } - 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); - } - 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)); + 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 if (parallel > 1) { - char buf[256]; - sprintf (buf, "-fwpa=%i", parallel); - obstack_ptr_grow (&argv_obstack, xstrdup (buf)); + 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 - obstack_ptr_grow (&argv_obstack, "-fwpa"); - } /* Append input arguments. */ for (i = 0; i < lto_argc; ++i) @@ -1638,263 +1723,238 @@ 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 (lto_mode == LTO_MODE_LTO) { - printf ("%s\n", flto_out); - if (!skip_debug) { + 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) - if (early_debug_object_names[i] != NULL) - printf ("%s\n", early_debug_object_names[i]); + { + const char *tem; + if ((tem = debug_objcopy (ltoobj_argv[i], !linker_output_rel))) + { + early_debug_object_names[i] = tem; + n_debugobj++; + } + } } - /* 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; - - 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 (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 (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; + 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]); + } for (i = 0; i < nr; ++i) - maybe_unlink (input_names[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); } - 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: + 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 deleted file mode 100644 index 5b36bc5..0000000 --- a/gcc/mapper-client.cc +++ /dev/null @@ -1,331 +0,0 @@ -/* 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 deleted file mode 100644 index be4849d..0000000 --- a/gcc/mapper-resolver.cc +++ /dev/null @@ -1,246 +0,0 @@ -/* 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 deleted file mode 100644 index 23b847f..0000000 --- a/gcc/mapper-server.cc +++ /dev/null @@ -1,994 +0,0 @@ -/* 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 deleted file mode 100644 index f794012..0000000 --- a/gcc/mapper.h +++ /dev/null @@ -1,117 +0,0 @@ -/* 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 |