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

Danny Smith dannysmith@clear.net.nz
Tue Oct 31 10:07:00 GMT 2006


> From: Mark Mitchell
> Sent: Tuesday, 31 October 2006 1:55 p.m.
> 
> Danny Smith wrote:
> 
> > The only problem with that is that configure will refuse to honour
> > --enable___cxa_atexit=yes if can't find __cxa_atexit in libc
> 
> Ugh.  (I'm not a fan; I'd prefer we either silently accept the option 
> (maybe the user is building what looks like a native 
> compiler, but will 
> actually be used in a cross configuration), or issue an error; just 
> echoing a random message in the midst of configure's giant 
> output seems 
> tricky.)
> 
> However, to avoid stirring up a hornet's nest, I'd suggest you just 
> special case $host matches *-mingw32.
> 
> OK,

Here is revised patch, with TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT hook.
Tested on i686-pc-mingw32.    Also tested to with --disable-__cxa_atexit
to confirm
that old behaviour could still be restored.

Danny

Changelog

2006-10-31  Danny Smith  <dannysmith@users.sourceforge.net>
 
	* target.h (targetm.cxx.use_atexit_for_cxa_atexit): New target
hook.
	* target-def.h: (TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT): Define
default.
	* config/i386/mingw32.h (TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT):
Override
	default.
	* doc/tm.texi (TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT): Document.
	* configure.ac (use_cxa_atexit): As a special case, don't test
for
	libc definition of __cxa_atexit on mingw32
	* configure: Regenerate.
	* config.gcc (i[34567]86-pc-mingw32): Default to
	enable__cxa_atexit=yes.

cp/Changelog

	* decl.c (get_atexit_node): Reference atexit, not __cxa_exit.
	if targetm.cxx.use_atexit_for cxa_atexit.
	(register_dtor_fn): Likewise.

Index: target.h
===================================================================
*** target.h	(revision 118179)
--- 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 may use atexit in the same manner as
+     __cxa_atexit  to register static destructors.  */
+     bool (*use_atexit_for_cxa_atexit) (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 118179)
--- 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_ATEXIT_FOR_CXA_ATEXIT
+ #define TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT 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_ATEXIT_FOR_CXA_ATEXIT,	\
      TARGET_CXX_ADJUST_CLASS_AT_DEFINITION	\
    }
  
Index: config/i386/mingw32.h
===================================================================
*** config/i386/mingw32.h	(revision 118179)
--- config/i386/mingw32.h	(working copy)
*************** do {
\
*** 112,114 ****
--- 112,118 ----
  /* mingw32 uses the  -mthreads option to enable thread support.  */
  #undef GOMP_SELF_SPECS
  #define GOMP_SELF_SPECS "%{fopenmp: -mthreads}"
+ 
+ /* mingw32 atexit function is safe to use in shared libraries.  Use it
+    to register C++ static destructors.  */
+ #define TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT hook_bool_void_true
Index: doc/tm.texi
===================================================================
*** doc/tm.texi	(revision 118179)
--- doc/tm.texi	(working copy)
*************** should be used to register static destru
*** 8971,8976 ****
--- 8971,8984 ----
  is in effect.  The default is to return false to use
@code{__cxa_atexit}.
  @end deftypefn
  
+ @deftypefn {Target Hook} bool TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT
(void)
+ This hook returns true if target @code{atexit} function can be used in
+ the same manner as @code{__cxa_atexit} to register C++ static
+ destructors. This requires that @code{atexit}-registered functions in
+ shared libraries are run in correct order when the libraries unload.
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: configure.ac
===================================================================
*** configure.ac	(revision 118179)
--- configure.ac	(working copy)
*************** use_cxa_atexit=no
*** 1429,1436 ****
  if test x$enable___cxa_atexit = xyes || \
     test x$enable___cxa_atexit = x -a x$default_use_cxa_atexit = xyes;
then
    if test x$host = x$target; then
!     AC_CHECK_FUNC(__cxa_atexit,[use_cxa_atexit=yes],
! 	[echo "__cxa_atexit can't be enabled on this target"])
    else
      # We can't check for __cxa_atexit when building a cross, so assume
      # it is available 
--- 1429,1445 ----
  if test x$enable___cxa_atexit = xyes || \
     test x$enable___cxa_atexit = x -a x$default_use_cxa_atexit = xyes;
then
    if test x$host = x$target; then
!     case $host in
!       # mingw32 doesn't have __cxa_atexit but uses atexit registration
!       # keyed to flag_use_cxa_atexit
!       *-*-mingw32*)
! 	use_cxa_atexit=yes
! 	;;
!       *)
! 	AC_CHECK_FUNC(__cxa_atexit,[use_cxa_atexit=yes],
! 	  [echo "__cxa_atexit can't be enabled on this target"])
! 	::
!     esac
    else
      # We can't check for __cxa_atexit when building a cross, so assume
      # it is available 
Index: config.gcc
===================================================================
*** config.gcc	(revision 118179)
--- config.gcc	(working copy)
*************** i[34567]86-*-mingw32*)
*** 1310,1315 ****
--- 1310,1316 ----
  	extra_options="${extra_options} i386/cygming.opt"
  	extra_objs="winnt.o winnt-stubs.o"
  	cxx_target_objs=winnt-cxx.o
+ 	default_use_cxa_atexit=yes
  	case ${enable_threads} in
  	  "" | yes | win32)
  	  thread_file='win32'
Index: cp/decl.c
===================================================================
*** cp/decl.c	(revision 118179)
--- cp/decl.c	(working copy)
*************** get_atexit_node (void)
*** 5347,5353 ****
    if (atexit_node)
      return atexit_node;
  
!   if (flag_use_cxa_atexit)
      {
        /* The declaration for `__cxa_atexit' is:
  
--- 5347,5353 ----
    if (atexit_node)
      return atexit_node;
  
!   if (flag_use_cxa_atexit && !targetm.cxx.use_atexit_for_cxa_atexit
())
      {
        /* The declaration for `__cxa_atexit' is:
  
*************** start_cleanup_fn (void)
*** 5435,5440 ****
--- 5435,5442 ----
    tree parmtypes;
    tree fntype;
    tree fndecl;
+   bool use_cxa_atexit = flag_use_cxa_atexit
+ 			&& !targetm.cxx.use_atexit_for_cxa_atexit ();
  
    push_to_top_level ();
  
*************** start_cleanup_fn (void)
*** 5447,5453 ****
       We'll just ignore it.  After we implement the new calling
       convention for destructors, we can eliminate the use of
       additional cleanup functions entirely in the -fnew-abi case.  */
!   if (flag_use_cxa_atexit)
      parmtypes = tree_cons (NULL_TREE, ptr_type_node, parmtypes);
    /* Build the function type itself.  */
    fntype = build_function_type (void_type_node, parmtypes);
--- 5449,5455 ----
       We'll just ignore it.  After we implement the new calling
       convention for destructors, we can eliminate the use of
       additional cleanup functions entirely in the -fnew-abi case.  */
!   if (use_cxa_atexit)
      parmtypes = tree_cons (NULL_TREE, ptr_type_node, parmtypes);
    /* Build the function type itself.  */
    fntype = build_function_type (void_type_node, parmtypes);
*************** start_cleanup_fn (void)
*** 5467,5473 ****
    DECL_DECLARED_INLINE_P (fndecl) = 1;
    DECL_INTERFACE_KNOWN (fndecl) = 1;
    /* Build the parameter.  */
!   if (flag_use_cxa_atexit)
      {
        tree parmdecl;
  
--- 5469,5475 ----
    DECL_DECLARED_INLINE_P (fndecl) = 1;
    DECL_INTERFACE_KNOWN (fndecl) = 1;
    /* Build the parameter.  */
!   if (use_cxa_atexit)
      {
        tree parmdecl;
  
*************** register_dtor_fn (tree decl)
*** 5536,5542 ****
    cxx_mark_addressable (cleanup);
    mark_used (cleanup);
    cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
!   if (flag_use_cxa_atexit)
      {
        args = tree_cons (NULL_TREE,
  			build_unary_op (ADDR_EXPR, get_dso_handle_node
(), 0),
--- 5538,5544 ----
    cxx_mark_addressable (cleanup);
    mark_used (cleanup);
    cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
!   if (flag_use_cxa_atexit && !targetm.cxx.use_atexit_for_cxa_atexit
())
      {
        args = tree_cons (NULL_TREE,
  			build_unary_op (ADDR_EXPR, get_dso_handle_node
(), 0),



More information about the Gcc-patches mailing list