This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch/C++]: Use dllonexit for static destructors on mingw32


One of things mingw32 C runtime lacks is an implementation of
__cxa_atexit. However, some of the behaviour of __cxa_atexit is already
in the C runtime atexit implementation. On mingw32, each dll has its own
onexit table, which is initialized on dll load,  Calls to atexit or
onexit will register functions in the onexit table of the containing
module. Each dll-specific onexit table is finalized when that dll
unloads.
The calls to atexit from the main app, (ie, including all static libs)
are
finalized at process exit.

The addition of a target hook to take advantage of this allows PASSES
for
the three __cxa_atexit dependent testcases.in g++.old-deja/other.

OK for mainline?

Changelog

2006-10-27  Danny Smith  <dannysmith@users.sourceforge.net>
 
	* target.h (targetm.cxx.use_dllonexit): New target hook.
	* target-def.h: (TARGET_CXX_USE_DLLONEXIT): Define default.
	* config/i386/mingw32.h (TARGET_CXX_USE_DLLONEXIT): Override
	default.
	* doc/tm.texi (TARGET_CXX_USE_DLLONEXIT): Document.

cp/Changelog

	*decl2.c (one_static_initialization_or_destruction): Check,
	set guard variable and register static destructor here if
	targetm.cxx.use_dllonexit.
	(cp_finish_file): Don't generate destructor if
	targetm.cxx.use_dllonexit.
		


Index: target.h
===================================================================
*** target.h	(revision 117970)
--- target.h	(working copy)
*************** struct gcc_target
*** 776,781 ****
--- 776,784 ----
      /* Returns true if __aeabi_atexit should be used to register
static
         destructors.  */
      bool (*use_aeabi_atexit) (void);
+     /* Returns true if target uses dll-private onexit tables to
register
+        static destructors.  */
+     bool (*use_dllonexit) (void);
      /* TYPE is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that
         has just been defined.  Use this hook to make adjustments to
the
         class  (eg, tweak visibility or perform any other required
Index: target-def.h
===================================================================
*** target-def.h	(revision 117970)
--- target-def.h	(working copy)
*************** Foundation, 51 Franklin Street, Fifth Fl
*** 583,588 ****
--- 583,592 ----
  #define TARGET_CXX_USE_AEABI_ATEXIT hook_bool_void_false
  #endif
  
+ #ifndef TARGET_CXX_USE_DLLONEXIT
+ #define TARGET_CXX_USE_DLLONEXIT hook_bool_void_false
+ #endif
+ 
  #ifndef TARGET_CXX_ADJUST_CLASS_AT_DEFINITION
  #define TARGET_CXX_ADJUST_CLASS_AT_DEFINITION hook_void_tree
  #endif
*************** Foundation, 51 Franklin Street, Fifth Fl
*** 599,604 ****
--- 603,609 ----
      TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY,	\
      TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT,        \
      TARGET_CXX_USE_AEABI_ATEXIT,		\
+     TARGET_CXX_USE_DLLONEXIT,			\
      TARGET_CXX_ADJUST_CLASS_AT_DEFINITION	\
    }
  
  #include "gt-winnt.h"
Index: doc/tm.texi
===================================================================
*** doc/tm.texi	(revision 117970)
--- doc/tm.texi	(working copy)
*************** should be used to register static destru
*** 8971,8976 ****
--- 8971,8985 ----
  is in effect.  The default is to return false to use
@code{__cxa_atexit}.
  @end deftypefn
  
+ @deftypefn {Target Hook} bool TARGET_CXX_USE_DLLONEXIT (void)
+ This hook returns true if target has its own mechanism to ensure that
+ functions registered with @code{atexit} are run in correct order
+ when a shared library unloads and so can be used register C++ static
+ destructors, This is the case for MS Windows32 targets that initialize
+ and use a private onexit table in each dll that is loaded.
+ The default is to return false.
+ @end deftypefn
+ 
  @deftypefn {Target Hook} void TARGET_CXX_ADJUST_CLASS_AT_DEFINITION
(tree @var{type})
  @var{type} is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that has
just been
  defined.  Use this hook to make adjustments to the class (eg, tweak
Index: config/i386/mingw32.h
===================================================================
*** config/i386/mingw32.h	(revision 117970)
--- config/i386/mingw32.h	(working copy)
*************** do {
\
*** 112,114 ****
--- 112,119 ----
  /* mingw32 uses the  -mthreads option to enable thread support.  */
  #undef GOMP_SELF_SPECS
  #define GOMP_SELF_SPECS "%{fopenmp: -mthreads}"
+ 
+ /* mingw32 uses dll-private onexit tables to register static
+    destructors.  */
+ #define TARGET_CXX_USE_DLLONEXIT hook_bool_void_true
+
Index: cp/decl2.c
===================================================================
*** cp/decl2.c	(revision 117970)
--- cp/decl2.c	(working copy)
*************** one_static_initialization_or_destruction
*** 2618,2624 ****
  
        /* When using __cxa_atexit, we just check the GUARD as we would
  	 for a local static.  */
!       if (flag_use_cxa_atexit)
  	{
  	  /* When using __cxa_atexit, we never try to destroy
  	     anything from a static destructor.  */
--- 2618,2624 ----
  
        /* When using __cxa_atexit, we just check the GUARD as we would
  	 for a local static.  */
!       if (flag_use_cxa_atexit  || targetm.cxx.use_dllonexit())
  	{
  	  /* When using __cxa_atexit, we never try to destroy
  	     anything from a static destructor.  */
*************** one_static_initialization_or_destruction
*** 2654,2660 ****
  
    /* If we're using __cxa_atexit, we have not already set the GUARD,
       so we must do so now.  */
!   if (guard && initp && flag_use_cxa_atexit)
      finish_expr_stmt (set_guard (guard));
  
    /* Perform the initialization or destruction.  */
--- 2654,2660 ----
  
    /* If we're using __cxa_atexit, we have not already set the GUARD,
       so we must do so now.  */
!   if (guard && initp && (flag_use_cxa_atexit ||
targetm.cxx.use_dllonexit()))
      finish_expr_stmt (set_guard (guard));
  
    /* Perform the initialization or destruction.  */
*************** one_static_initialization_or_destruction
*** 2665,2671 ****
  
        /* If we're using __cxa_atexit, register a function that calls
the
  	 destructor for the object.  */
!       if (flag_use_cxa_atexit)
  	finish_expr_stmt (register_dtor_fn (decl));
      }
    else
--- 2665,2671 ----
  
        /* If we're using __cxa_atexit, register a function that calls
the
  	 destructor for the object.  */
!       if (flag_use_cxa_atexit  || targetm.cxx.use_dllonexit())
  	finish_expr_stmt (register_dtor_fn (decl));
      }
    else
*************** cp_finish_file (void)
*** 3171,3180 ****
  	  /* Then, generate code to do all the destructions.  Do these
  	     in reverse order so that the most recently constructed
  	     variable is the first destroyed.  If we're using
! 	     __cxa_atexit, then we don't need to do this; functions
! 	     were registered at initialization time to destroy the
! 	     local statics.  */
! 	  if (!flag_use_cxa_atexit && vars)
  	    {
  	      vars = nreverse (vars);
  	      do_static_initialization_or_destruction (vars,
/*initp=*/false);
--- 3171,3180 ----
  	  /* Then, generate code to do all the destructions.  Do these
  	     in reverse order so that the most recently constructed
  	     variable is the first destroyed.  If we're using
! 	     __cxa_atexit or dllonexit, then we don't need to do this;
! 	     functions were registered at initialization time to destroy
! 	      the local statics.  */
! 	  if (!(flag_use_cxa_atexit || targetm.cxx.use_dllonexit()) &&
vars)
  	    {
  	      vars = nreverse (vars);
  	      do_static_initialization_or_destruction (vars,
/*initp=*/false); 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]