This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RE: [Patch/C++]: Use dllonexit for static destructors on mingw32
- From: Danny Smith <dannysmith at clear dot net dot nz>
- To: 'Mark Mitchell' <mark at codesourcery dot com>
- Cc: 'GCC-patches' <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 31 Oct 2006 22:29:06 +1300
- Subject: RE: [Patch/C++]: Use dllonexit for static destructors on mingw32
> 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),