diff options
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/config.gcc | 3 | ||||
-rw-r--r-- | gcc/config/darwin-crt3.c | 208 | ||||
-rw-r--r-- | gcc/config/darwin.h | 32 | ||||
-rw-r--r-- | gcc/config/rs6000/darwin.h | 10 | ||||
-rw-r--r-- | gcc/config/rs6000/t-darwin | 6 | ||||
-rw-r--r-- | gcc/config/t-darwin | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/init18.C | 32 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/init5.C | 2 |
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> |