config.gcc (*-*-darwin*): Don't build crt2.o for all Darwin ports.
authorGeoffrey Keating <geoffk@apple.com>
Thu, 16 Mar 2006 02:37:09 +0000 (02:37 +0000)
committerGeoffrey Keating <geoffk@gcc.gnu.org>
Thu, 16 Mar 2006 02:37:09 +0000 (02:37 +0000)
2006-03-15  Geoffrey Keating  <geoffk@apple.com>

* config.gcc (*-*-darwin*): Don't build crt2.o for all Darwin ports.
Do switch on default_use_cxa_atexit.
(powerpc*-*-darwin*): Build crt2.o on powerpc.
* config/darwin-crt3.o: New.
* config/darwin.h (LINK_SPEC): If -shared-libgcc, make linker default
to 10.3.  Pass '-multiply_defined suppress' if crt3.o is in use.
(STARTFILE_SPEC): Add crt3.o when -shared-libgcc and appropriate
OS version.
* config/rs6000/t-darwin: Move crt2.o building to here.
* config/rs6000/darwin.h (C_COMMON_OVERRIDE_OPTIONS): Update
Mac OS version for using __cxa_get_exception_ptr.  Don't test versions
of __cxa_atexit.

2006-03-15  Geoffrey Keating  <geoffk@apple.com>

* g++.old-deja/g++.other/init18.C: New.
* g++.old-deja/g++.other/init5.C: Remove xfail.

From-SVN: r112121

gcc/ChangeLog
gcc/config.gcc
gcc/config/darwin-crt3.c [new file with mode: 0644]
gcc/config/darwin.h
gcc/config/rs6000/darwin.h
gcc/config/rs6000/t-darwin
gcc/config/t-darwin
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.other/init18.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/init5.C

index 568767f12920f2a4c2a1174636f973c18be1c4d6..9908e3a3cddf51038bd23f033d80f48e2c2ba26a 100644 (file)
@@ -1,3 +1,18 @@
+2006-03-15  Geoffrey Keating  <geoffk@apple.com>
+
+       * config.gcc (*-*-darwin*): Don't build crt2.o for all Darwin ports.
+       Do switch on default_use_cxa_atexit.
+       (powerpc*-*-darwin*): Build crt2.o on powerpc.
+       * config/darwin-crt3.o: New.
+       * config/darwin.h (LINK_SPEC): If -shared-libgcc, make linker default
+       to 10.3.  Pass '-multiply_defined suppress' if crt3.o is in use.
+       (STARTFILE_SPEC): Add crt3.o when -shared-libgcc and appropriate
+       OS version.
+       * config/rs6000/t-darwin: Move crt2.o building to here.
+       * config/rs6000/darwin.h (C_COMMON_OVERRIDE_OPTIONS): Update
+       Mac OS version for using __cxa_get_exception_ptr.  Don't test versions
+       of __cxa_atexit.
+
 2006-03-15  Jan-Benedict Glaw  <jbglaw@lug-owl.de>
 
        * config/vax/vax.c (nonindexed_address_p): Change logical negation
index 91a20e2f514640f6d5e4d61c3aa3c54e46df1a2d..78a7cc1803c6e02005c16ae6ab138d3f9aa59f75 100644 (file)
@@ -368,8 +368,8 @@ case ${target} in
   extra_options="${extra_options} darwin.opt"
   c_target_objs="darwin-c.o"
   cxx_target_objs="darwin-c.o"
-  extra_parts="crt2.o"
   extra_objs="darwin.o"
+  default_use_cxa_atexit=yes
   case ${enable_threads} in
     "" | yes | posix) thread_file='posix' ;;
   esac
@@ -1664,6 +1664,7 @@ powerpc-*-beos*)
        ;;
 powerpc-*-darwin*)
        extra_options="${extra_options} rs6000/darwin.opt"
+       extra_parts="crt2.o"
        case ${target} in
          *-darwin1[0-9]* | *-darwin[8-9]*)
            tmake_file="${tmake_file} rs6000/t-darwin8" 
diff --git a/gcc/config/darwin-crt3.c b/gcc/config/darwin-crt3.c
new file mode 100644 (file)
index 0000000..698b375
--- /dev/null
@@ -0,0 +1,208 @@
+/* __cxa_atexit backwards-compatibility support for Darwin.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+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 COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+/* It is incorrect to include config.h here, because this file is being
+   compiled for the target, and hence definitions concerning only the host
+   do not apply.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+
+#include <dlfcn.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+/* This file works around two different problems.
+
+   The first problem is that there is no __cxa_atexit on Mac OS versions
+   before 10.4.  It fixes this by providing one, and having it called from
+   a destructor.  This is not quite as good as having a real __cxa_atexit,
+   but it's good enough to imitate the behaviour that you'd get if
+   you didn't have one.
+
+   The second problem is that on 10.4 Mac OS versions, __cxa_finalize
+   doesn't work right: it doesn't run routines that were registered
+   while other atexit routines are running.  This is worked around by
+   installing our own handler so that it runs last, and repeatedly
+   running __cxa_finalize until no new calls to __cxa_atexit are made.  */
+
+typedef int (*cxa_atexit_p)(void (*func) (void*), void* arg, void* dso);
+
+#ifdef __ppc__
+void __cxa_finalize (void* dso) __attribute__((weak));
+#else
+void __cxa_finalize (void* dso);
+#endif
+
+/* new_atexit_routines is set if __cxa_finalize exists in the system C
+   library and our copy of __cxa_atexit has been called.  */
+
+static bool new_atexit_routines;
+
+/* first_atexit_handler is called after all other atexit routines
+   that were registered before __cxa_finalize is called.
+   It may be called more than once, but is not re-entered.  */
+
+static void
+first_atexit_handler(void* dso)
+{
+  /* Keep running __cxa_finalize until no new atexit routines are
+     registered.  
+     Note that this means __cxa_finalize will be called at least twice,
+     even if the first call didn't register any new routines.  */
+  while (new_atexit_routines) {
+    new_atexit_routines = false;
+    __cxa_finalize (dso);
+  };
+}
+
+/* This is our wrapper around __cxa_atexit that's called if __cxa_finalize
+   exists in the system library.  All it does is, on its first call,
+   install first_atexit_handler; and on every call, set new_atexit_routines
+   and pass control to the system __cxa_atexit.
+   This proves to be somewhat more complicated than you might expect,
+   because it may be called in a multithreaded environment.  Fortunately
+   it turns out to be possible to do what's needed without resorting
+   to locking.  */
+
+static int
+cxa_atexit_wrapper (void (*func) (void*), void* arg, void* dso)
+{
+  static volatile cxa_atexit_p real_cxa_atexit;
+  cxa_atexit_p auto_cxa_atexit = real_cxa_atexit;
+  if (! auto_cxa_atexit)
+    {
+      void* handle = dlopen ("/usr/lib/libSystem.B.dylib", RTLD_NOLOAD);
+      if (! handle)
+       return -1;
+      
+      auto_cxa_atexit = (cxa_atexit_p)dlsym (handle, "__cxa_atexit");
+      if (! auto_cxa_atexit)
+       return -1;
+    }
+  /* At this point, auto_cxa_atexit contains the address of
+     the system __cxa_atexit.  */
+  if (! real_cxa_atexit)
+    {
+      /* Install our handler above before any other handlers
+        for this image, so it will be called last.  */
+      int result = (*auto_cxa_atexit)(first_atexit_handler, dso, dso);
+      if (result != 0)
+       return result;
+      /* Now set the global real_cxa_atexit to prevent further
+        installations of first_atexit_handler.  Do this after
+        the installation so that if another thread sees it is set,
+        it can be sure that first_atexit_handler really has been
+        installed.  */
+      real_cxa_atexit = auto_cxa_atexit;
+    }
+  /* At this point, we know that first_atexit_handler has been
+     installed at least once, and real_cxa_atexit is not NULL.  */
+  /* It's not necessary to mark new_atexit_routines as volatile, so long
+     as this write eventually happens before this shared object is
+     unloaded.  */
+  new_atexit_routines = true;
+  /* Call the original __cxa_atexit for this function.  */
+  return (*auto_cxa_atexit)(func, arg, dso);
+}
+\f
+#ifdef __ppc__
+/* This code is used while running on 10.3.9, when __cxa_atexit doesn't
+   exist in the system library.  10.3.9 only supported regular PowerPC,
+   so this code isn't necessary on x86 or ppc64.  */
+
+/* This structure holds a routine to call.  */
+struct atexit_routine
+{
+  struct atexit_routine * next;
+  void (*func)(void *);
+  void * arg;
+};
+
+static struct atexit_routine * volatile atexit_routines_list;
+
+/* If __cxa_atexit doesn't exist at all in the system library, this
+   routine is used; it completely emulates __cxa_atexit.  
+
+   This routine has to be thread-safe, but fortunately this just means
+   that it has to do atomic list insertion.  */
+
+static int
+cxa_atexit_substitute (void (*func) (void*), void* arg,
+                      /* The 'dso' value will always be equal to this
+                         object's __dso_handle.  */
+                      void* dso __attribute__((unused)))
+{
+  struct atexit_routine * s = malloc (sizeof (struct atexit_routine));
+  struct atexit_routine * next, * old_next;
+  if (!s)
+    return -1;
+  s->func = func;
+  s->arg = arg;
+  next = atexit_routines_list;
+  do {
+    s->next = old_next = next;
+    next = __sync_val_compare_and_swap (&atexit_routines_list, old_next, s);
+  } while (next != old_next);
+  return 0;
+}
+
+/* The routines added in cxa_atexit_substitute get run here, in a destructor.
+   This routine doesn't have to be thread-safe.  */
+
+static void cxa_dtor (void) __attribute__((destructor));
+static void
+cxa_dtor (void)
+{
+  while (atexit_routines_list)
+    {
+      struct atexit_routine * working_list = atexit_routines_list;
+      atexit_routines_list = NULL;
+      while (working_list)
+       {
+         struct atexit_routine * called_routine = working_list;
+         working_list->func (working_list->arg);
+         working_list = working_list->next;
+         free (called_routine);
+       }
+    }
+}
+#endif
+
+int __cxa_atexit (void (*func) (void*), void* arg, 
+                 void* dso) __attribute__((visibility("hidden")));
+int
+__cxa_atexit (void (*func) (void*), void* arg, void* dso)
+{
+#ifdef __ppc__
+  if (! __cxa_finalize)
+    return cxa_atexit_substitute (func, arg, dso);
+#endif
+  return cxa_atexit_wrapper (func, arg, dso);
+}
index a2c276dd4da8ec9f812d44655d60f6a74a58df22..edced4d80cf4b92b4a40bc1ea67327091ed77fc5 100644 (file)
@@ -262,9 +262,13 @@ Boston, MA 02110-1301, USA.  */
    %{Zimage_base*:-image_base %*} \
    %{Zinit*:-init %*} \
    %{mmacosx-version-min=*:-macosx_version_min %*} \
+   %{!mmacosx-version-min=*:%{shared-libgcc:-macosx_version_min 10.3}} \
    %{nomultidefs} \
    %{Zmulti_module:-multi_module} %{Zsingle_module:-single_module} \
    %{Zmultiply_defined*:-multiply_defined %*} \
+   %{!Zmultiply_defined*:%{shared-libgcc: \
+     %:version-compare(< 10.5 mmacosx-version-min= -multiply_defined) \
+     %:version-compare(< 10.5 mmacosx-version-min= suppress)}} \
    %{Zmultiplydefinedunused*:-multiply_defined_unused %*} \
    %{prebind} %{noprebind} %{nofixprebinding} %{prebind_all_twolevel_modules} \
    %{read_only_relocs} \
@@ -319,19 +323,25 @@ Boston, MA 02110-1301, USA.  */
        %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_s.10.5)       \
        -lgcc}"
 
-/* We specify crt0.o as -lcrt0.o so that ld will search the library path.  */
+/* We specify crt0.o as -lcrt0.o so that ld will search the library path.
+
+   crt3.o provides __cxa_atexit on systems that don't have it.  Since
+   it's only used with C++, which requires passing -shared-libgcc, key
+   off that to avoid unnecessarily adding a destructor to every
+   powerpc program built.  */
 
 #undef  STARTFILE_SPEC
-#define STARTFILE_SPEC  \
-  "%{!Zdynamiclib:%{Zbundle:%{!static:-lbundle1.o}} \
-     %{!Zbundle:%{pg:%{static:-lgcrt0.o} \
-                     %{!static:%{object:-lgcrt0.o} \
-                               %{!object:%{preload:-lgcrt0.o} \
-                                 %{!preload:-lgcrt1.o %(darwin_crt2)}}}} \
-                %{!pg:%{static:-lcrt0.o} \
-                      %{!static:%{object:-lcrt0.o} \
-                                %{!object:%{preload:-lcrt0.o} \
-                                  %{!preload:-lcrt1.o %(darwin_crt2)}}}}}}"
+#define STARTFILE_SPEC                                                     \
+  "%{!Zdynamiclib:%{Zbundle:%{!static:-lbundle1.o}}                        \
+     %{!Zbundle:%{pg:%{static:-lgcrt0.o}                                   \
+                     %{!static:%{object:-lgcrt0.o}                         \
+                               %{!object:%{preload:-lgcrt0.o}              \
+                                 %{!preload:-lgcrt1.o %(darwin_crt2)}}}}    \
+                %{!pg:%{static:-lcrt0.o}                                   \
+                      %{!static:%{object:-lcrt0.o}                         \
+                                %{!object:%{preload:-lcrt0.o}              \
+                                  %{!preload:-lcrt1.o %(darwin_crt2)}}}}}}  \
+  %{shared-libgcc:%:version-compare(< 10.5 mmacosx-version-min= -lcrt3.o)}"
 
 /* The native Darwin linker doesn't necessarily place files in the order
    that they're specified on the link line.  Thus, it is pointless
index c116fa4e852a01c882969195b8d4431abe5cfaeb..adefe2fdf13745ff5bdd34ab18567e13171135df 100644 (file)
@@ -97,17 +97,11 @@ do {                                                                        \
 
 #define C_COMMON_OVERRIDE_OPTIONS do {                                 \
   /* On powerpc, __cxa_get_exception_ptr is available starting in the  \
-     10.5 libstdc++.dylib.  */                                         \
+     10.4.6 libstdc++.dylib.  */                                       \
   if ((! darwin_macosx_version_min                                     \
-       || strverscmp (darwin_macosx_version_min, "10.5") < 0)          \
+       || strverscmp (darwin_macosx_version_min, "10.4.6") < 0)                \
       && flag_use_cxa_get_exception_ptr == 2)                          \
     flag_use_cxa_get_exception_ptr = 0;                                        \
-  /* On powerpc, __cxa_atexit is available starting in the 10.4                \
-     libSystem.dylib.  */                                              \
-  if ((! darwin_macosx_version_min                                     \
-       || strverscmp (darwin_macosx_version_min, "10.4") < 0)          \
-      && flag_use_cxa_atexit == 2)                                     \
-    flag_use_cxa_atexit = 0;                                           \
 } while (0)
 
 /* Darwin has 128-bit long double support in libc in 10.4 and later.
index 264cb63c87d830d42330c4186e65d302bf23deac..8dd9832b9a267b5fa9f538d36cc4a0e8620d1e94 100644 (file)
@@ -25,3 +25,9 @@ LIB2ADDEH += $(srcdir)/config/rs6000/darwin-fallback.c
 
 darwin-fpsave.o:       $(srcdir)/config/rs6000/darwin-asm.h
 darwin-tramp.o:                $(srcdir)/config/rs6000/darwin-asm.h
+
+# Explain how to build crt2.o
+$(T)crt2$(objext): $(srcdir)/config/darwin-crt2.c $(GCC_PASSES) \
+       $(TCONFIG_H) stmp-int-hdrs tsystem.h
+       $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) \
+         -c $(srcdir)/config/darwin-crt2.c -o $(T)crt2$(objext)
index 3e524f36901d7abee56b20c41b3c2a23c754bb3f..5995f30131f56a0d0785c1f9543df3f6223c4dbe 100644 (file)
@@ -12,11 +12,12 @@ darwin-c.o: $(srcdir)/config/darwin-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
 
 gt-darwin.h : s-gtype ; @true
 
-# Explain how to build crt2.o
-$(T)crt2$(objext): $(srcdir)/config/darwin-crt2.c $(GCC_PASSES) \
+# How to build crt3.o
+EXTRA_MULTILIB_PARTS=crt3.o
+$(T)crt3$(objext): $(srcdir)/config/darwin-crt3.c $(GCC_PASSES) \
        $(TCONFIG_H) stmp-int-hdrs tsystem.h
        $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) \
-         -c $(srcdir)/config/darwin-crt2.c -o $(T)crt2$(objext)
+         -c $(srcdir)/config/darwin-crt3.c -o $(T)crt3$(objext)
 
 # Use unwind-dw2-fde-darwin
 LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-darwin.c \
index c32cef64aca4268ca0823d1aa9a8d0fba8d3a07c..6b093acf92edbdf450c469436c9dfa57a9ee80ee 100644 (file)
@@ -1,3 +1,8 @@
+2006-03-15  Geoffrey Keating  <geoffk@apple.com>
+
+       * g++.old-deja/g++.other/init18.C: New.
+       * g++.old-deja/g++.other/init5.C: Remove xfail.
+
 2006-03-15  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * g++.dg/opt/pr15551.C: Cleanup temp file.
diff --git a/gcc/testsuite/g++.old-deja/g++.other/init18.C b/gcc/testsuite/g++.old-deja/g++.other/init18.C
new file mode 100644 (file)
index 0000000..64d9f3d
--- /dev/null
@@ -0,0 +1,32 @@
+// { dg-do run }
+
+#include <stdlib.h>
+
+static int cnt = 0;
+
+class Foo2
+{
+       public:
+               Foo2() {};
+               ~Foo2() { if (++cnt == 2) _Exit (0); };
+};
+
+static Foo2& GetFoo2()
+{
+       static Foo2 foo2;
+       return foo2;
+}
+
+class Foo1
+{
+       public:
+               Foo1() {}
+               ~Foo1() { if (++cnt != 1) abort(); GetFoo2(); };
+};
+
+int main( int argc, const char* argv[] )
+{
+       static Foo1 anotherFoo;
+       exit (1);
+}
+
index 89b8cd3fc0ebafe919a45b537f47758497a7ab57..27765dc11c717c8acfcf704a2f97aabcd622d724 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-do run { xfail { ! "powerpc*-*-linux*" } } }
+// { dg-do run }
 // Objects must be destructed in decreasing cnt order
 // Original test attributed to James Kanze <jkanze@otelo.ibmmail.com>