aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoffrey Keating <geoffk@apple.com>2006-03-16 02:37:09 +0000
committerGeoffrey Keating <geoffk@apple.com>2006-03-16 02:37:09 +0000
commit34df2308eeb8717d1c7c79719bc5f1bb6adbcc45 (patch)
treeb6ff2fd69076032fa47ae9dc5b1da921c649b574
parent97191b5d7f2372f71255f12ae2b28889985716ad (diff)
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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@112121 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/config.gcc3
-rw-r--r--gcc/config/darwin-crt3.c208
-rw-r--r--gcc/config/darwin.h32
-rw-r--r--gcc/config/rs6000/darwin.h10
-rw-r--r--gcc/config/rs6000/t-darwin6
-rw-r--r--gcc/config/t-darwin7
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/init18.C32
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/init5.C2
10 files changed, 296 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 568767f1292..9908e3a3cdd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 91a20e2f514..78a7cc1803c 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -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
index 00000000000..698b375c69c
--- /dev/null
+++ b/gcc/config/darwin-crt3.c
@@ -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);
+}
+
+#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);
+}
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index a2c276dd4da..edced4d80cf 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -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
diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h
index c116fa4e852..adefe2fdf13 100644
--- a/gcc/config/rs6000/darwin.h
+++ b/gcc/config/rs6000/darwin.h
@@ -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.
diff --git a/gcc/config/rs6000/t-darwin b/gcc/config/rs6000/t-darwin
index 264cb63c87d..8dd9832b9a2 100644
--- a/gcc/config/rs6000/t-darwin
+++ b/gcc/config/rs6000/t-darwin
@@ -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)
diff --git a/gcc/config/t-darwin b/gcc/config/t-darwin
index 3e524f36901..5995f30131f 100644
--- a/gcc/config/t-darwin
+++ b/gcc/config/t-darwin
@@ -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 \
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c32cef64aca..6b093acf92e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..64d9f3d24c4
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/init18.C
@@ -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);
+}
+
diff --git a/gcc/testsuite/g++.old-deja/g++.other/init5.C b/gcc/testsuite/g++.old-deja/g++.other/init5.C
index 89b8cd3fc0e..27765dc11c7 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/init5.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/init5.C
@@ -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>