c++, mingw, v2: Fix up types of dtor hooks to __cxa_{,thread_}atexit/__cxa_throw on mingw ia32 [PR114968]

Message ID Zj0aBHDYche0TYIB@tucnak
State New
Headers
Series c++, mingw, v2: Fix up types of dtor hooks to __cxa_{,thread_}atexit/__cxa_throw on mingw ia32 [PR114968] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Testing passed

Commit Message

Jakub Jelinek May 9, 2024, 6:46 p.m. UTC
  On Thu, May 09, 2024 at 01:05:59PM -0400, Jason Merrill wrote:
> I think I'd rather pass ob_parm to start_cleanup_fn, where it can also
> replace the flag_use_cxa_atexit check in that function.

Good idea, changed in the following patch.

> > @@ -9998,7 +10004,8 @@ register_dtor_fn (tree decl)
> >       {
> >         /* We must convert CLEANUP to the type that "__cxa_atexit"
> >   	 expects.  */
> > -      cleanup = build_nop (get_atexit_fn_ptr_type (), cleanup);
> > +      cleanup = build_nop (ob_parm ? get_cxa_atexit_fn_ptr_type ()
> > +				   : get_atexit_fn_ptr_type (), cleanup);
> 
> If we're (now) using the correct type to build the cleanup fn, this
> conversion should be unnecessary.

This is the use_dtor case, where cleanup will have METHOD_TYPE, so
I think we need to cast.  But, we can cast always to
get_cxa_atexit_fn_ptr_type () type, because this is in use_dtor guarded code
and use_dtor is ob_parm && CLASS_TYPE_P (type), so when use_dtor is true,
ob_parm is also true.

Ok for trunk if it passes another bootstrap/regtest?

2024-05-09  Jakub Jelinek  <jakub@redhat.com>

	PR target/114968
gcc/
	* target.def (use_atexit_for_cxa_atexit): Remove spurious space
	from comment.
	(adjust_cdtor_callabi_fntype): New cxx target hook.
	* targhooks.h (default_cxx_adjust_cdtor_callabi_fntype): Declare.
	* targhooks.cc (default_cxx_adjust_cdtor_callabi_fntype): New
	function.
	* doc/tm.texi.in (TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Add.
	* doc/tm.texi: Regenerate.
	* config/i386/i386.cc (ix86_cxx_adjust_cdtor_callabi_fntype): New
	function.
	(TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Redefine.
gcc/cp/
	* cp-tree.h (atexit_fn_ptr_type_node, cleanup_type): Adjust macro
	comments.
	(get_cxa_atexit_fn_ptr_type): Declare.
	* decl.cc (get_atexit_fn_ptr_type): Adjust function comment, only
	build type for atexit argument.
	(get_cxa_atexit_fn_ptr_type): New function.
	(get_atexit_node): Call get_cxa_atexit_fn_ptr_type rather than
	get_atexit_fn_ptr_type when using __cxa_atexit.
	(get_thread_atexit_node): Call get_cxa_atexit_fn_ptr_type
	rather than get_atexit_fn_ptr_type.
	(start_cleanup_fn): Add ob_parm argument, call
	get_cxa_atexit_fn_ptr_type or get_atexit_fn_ptr_type depending
	on it and create PARM_DECL also based on that argument.
	(register_dtor_fn): Adjust start_cleanup_fn caller, use
	get_cxa_atexit_fn_ptr_type rather than get_atexit_fn_ptr_type
	for use_dtor casts.
	* except.cc (build_throw): Use get_cxa_atexit_fn_ptr_type ().



	Jakub
  

Comments

Jason Merrill May 9, 2024, 7:52 p.m. UTC | #1
On 5/9/24 14:46, Jakub Jelinek wrote:
> On Thu, May 09, 2024 at 01:05:59PM -0400, Jason Merrill wrote:
>> I think I'd rather pass ob_parm to start_cleanup_fn, where it can also
>> replace the flag_use_cxa_atexit check in that function.
> 
> Good idea, changed in the following patch.
> 
>>> @@ -9998,7 +10004,8 @@ register_dtor_fn (tree decl)
>>>        {
>>>          /* We must convert CLEANUP to the type that "__cxa_atexit"
>>>    	 expects.  */
>>> -      cleanup = build_nop (get_atexit_fn_ptr_type (), cleanup);
>>> +      cleanup = build_nop (ob_parm ? get_cxa_atexit_fn_ptr_type ()
>>> +				   : get_atexit_fn_ptr_type (), cleanup);
>>
>> If we're (now) using the correct type to build the cleanup fn, this
>> conversion should be unnecessary.
> 
> This is the use_dtor case, where cleanup will have METHOD_TYPE, so
> I think we need to cast.  But, we can cast always to
> get_cxa_atexit_fn_ptr_type () type, because this is in use_dtor guarded code
> and use_dtor is ob_parm && CLASS_TYPE_P (type), so when use_dtor is true,
> ob_parm is also true.
> 
> Ok for trunk if it passes another bootstrap/regtest?

OK.

> 2024-05-09  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR target/114968
> gcc/
> 	* target.def (use_atexit_for_cxa_atexit): Remove spurious space
> 	from comment.
> 	(adjust_cdtor_callabi_fntype): New cxx target hook.
> 	* targhooks.h (default_cxx_adjust_cdtor_callabi_fntype): Declare.
> 	* targhooks.cc (default_cxx_adjust_cdtor_callabi_fntype): New
> 	function.
> 	* doc/tm.texi.in (TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Add.
> 	* doc/tm.texi: Regenerate.
> 	* config/i386/i386.cc (ix86_cxx_adjust_cdtor_callabi_fntype): New
> 	function.
> 	(TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Redefine.
> gcc/cp/
> 	* cp-tree.h (atexit_fn_ptr_type_node, cleanup_type): Adjust macro
> 	comments.
> 	(get_cxa_atexit_fn_ptr_type): Declare.
> 	* decl.cc (get_atexit_fn_ptr_type): Adjust function comment, only
> 	build type for atexit argument.
> 	(get_cxa_atexit_fn_ptr_type): New function.
> 	(get_atexit_node): Call get_cxa_atexit_fn_ptr_type rather than
> 	get_atexit_fn_ptr_type when using __cxa_atexit.
> 	(get_thread_atexit_node): Call get_cxa_atexit_fn_ptr_type
> 	rather than get_atexit_fn_ptr_type.
> 	(start_cleanup_fn): Add ob_parm argument, call
> 	get_cxa_atexit_fn_ptr_type or get_atexit_fn_ptr_type depending
> 	on it and create PARM_DECL also based on that argument.
> 	(register_dtor_fn): Adjust start_cleanup_fn caller, use
> 	get_cxa_atexit_fn_ptr_type rather than get_atexit_fn_ptr_type
> 	for use_dtor casts.
> 	* except.cc (build_throw): Use get_cxa_atexit_fn_ptr_type ().
> 
> --- gcc/target.def.jj	2024-05-09 10:30:54.926503473 +0200
> +++ gcc/target.def	2024-05-09 20:27:16.294780780 +0200
> @@ -6498,7 +6498,7 @@ is in effect.  The default is to return
>    hook_bool_void_false)
>   
>   /* Returns true if target may use atexit in the same manner as
> -   __cxa_atexit  to register static destructors.  */
> +   __cxa_atexit to register static destructors.  */
>   DEFHOOK
>   (use_atexit_for_cxa_atexit,
>    "This hook returns true if the target @code{atexit} function can be used\n\
> @@ -6509,6 +6509,17 @@ unloaded. The default is to return false
>    bool, (void),
>    hook_bool_void_false)
>   
> +/* Returns modified FUNCTION_TYPE for cdtor callabi.  */
> +DEFHOOK
> +(adjust_cdtor_callabi_fntype,
> + "This hook returns a possibly modified @code{FUNCTION_TYPE} for arguments\n\
> +to @code{__cxa_atexit}, @code{__cxa_thread_atexit} or @code{__cxa_throw}\n\
> +function pointers.  ABIs like mingw32 require special attributes to be added\n\
> +to function types pointed to by arguments of these functions.\n\
> +The default is to return the passed argument unmodified.",
> + tree, (tree fntype),
> + default_cxx_adjust_cdtor_callabi_fntype)
> +
>   DEFHOOK
>   (adjust_class_at_definition,
>   "@var{type} is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that has just\n\
> --- gcc/targhooks.h.jj	2024-05-09 10:30:54.941503269 +0200
> +++ gcc/targhooks.h	2024-05-09 20:27:16.315780505 +0200
> @@ -65,6 +65,7 @@ extern machine_mode default_mode_for_suf
>   
>   extern tree default_cxx_guard_type (void);
>   extern tree default_cxx_get_cookie_size (tree);
> +extern tree default_cxx_adjust_cdtor_callabi_fntype (tree);
>   
>   extern bool hook_pass_by_reference_must_pass_in_stack
>     (cumulative_args_t, const function_arg_info &);
> --- gcc/targhooks.cc.jj	2024-05-09 10:30:54.927503459 +0200
> +++ gcc/targhooks.cc	2024-05-09 20:27:16.338780204 +0200
> @@ -329,6 +329,14 @@ default_cxx_get_cookie_size (tree type)
>     return cookie_size;
>   }
>   
> +/* Returns modified FUNCTION_TYPE for cdtor callabi.  */
> +
> +tree
> +default_cxx_adjust_cdtor_callabi_fntype (tree fntype)
> +{
> +  return fntype;
> +}
> +
>   /* Return true if a parameter must be passed by reference.  This version
>      of the TARGET_PASS_BY_REFERENCE hook uses just MUST_PASS_IN_STACK.  */
>   
> --- gcc/doc/tm.texi.in.jj	2024-05-09 10:30:54.897503866 +0200
> +++ gcc/doc/tm.texi.in	2024-05-09 20:27:16.355779981 +0200
> @@ -7223,6 +7223,8 @@ floating-point support; they are not inc
>   
>   @hook TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT
>   
> +@hook TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE
> +
>   @hook TARGET_CXX_ADJUST_CLASS_AT_DEFINITION
>   
>   @hook TARGET_CXX_DECL_MANGLING_CONTEXT
> --- gcc/doc/tm.texi.jj	2024-05-09 10:30:54.862504342 +0200
> +++ gcc/doc/tm.texi	2024-05-09 20:27:16.368779810 +0200
> @@ -11117,6 +11117,14 @@ shared libraries are run in the correct
>   unloaded. The default is to return false.
>   @end deftypefn
>   
> +@deftypefn {Target Hook} tree TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE (tree @var{fntype})
> +This hook returns a possibly modified @code{FUNCTION_TYPE} for arguments
> +to @code{__cxa_atexit}, @code{__cxa_thread_atexit} or @code{__cxa_throw}
> +function pointers.  ABIs like mingw32 require special attributes to be added
> +to function types pointed to by arguments of these functions.
> +The default is to return the passed argument unmodified.
> +@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
> --- gcc/config/i386/i386.cc.jj	2024-05-09 10:30:58.508454809 +0200
> +++ gcc/config/i386/i386.cc	2024-05-09 20:27:16.392779496 +0200
> @@ -25800,6 +25800,20 @@ ix86_bitint_type_info (int n, struct bit
>     return true;
>   }
>   
> +/* Returns modified FUNCTION_TYPE for cdtor callabi.  */
> +tree
> +ix86_cxx_adjust_cdtor_callabi_fntype (tree fntype)
> +{
> +  if (TARGET_64BIT
> +      || TARGET_RTD
> +      || ix86_function_type_abi (fntype) != MS_ABI)
> +    return fntype;
> +  /* For 32-bit MS ABI add thiscall attribute.  */
> +  tree attribs = tree_cons (get_identifier ("thiscall"), NULL_TREE,
> +			    TYPE_ATTRIBUTES (fntype));
> +  return build_type_attribute_variant (fntype, attribs);
> +}
> +
>   /* Implement PUSH_ROUNDING.  On 386, we have pushw instruction that
>      decrements by exactly 2 no matter what the position was, there is no pushb.
>   
> @@ -26411,6 +26425,8 @@ static const scoped_attribute_specs *con
>   #define TARGET_C_EXCESS_PRECISION ix86_get_excess_precision
>   #undef TARGET_C_BITINT_TYPE_INFO
>   #define TARGET_C_BITINT_TYPE_INFO ix86_bitint_type_info
> +#undef TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE
> +#define TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE ix86_cxx_adjust_cdtor_callabi_fntype
>   #undef TARGET_PROMOTE_PROTOTYPES
>   #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
>   #undef TARGET_PUSH_ARGUMENT
> --- gcc/cp/cp-tree.h.jj	2024-05-09 20:26:12.619615230 +0200
> +++ gcc/cp/cp-tree.h	2024-05-09 20:27:16.395779457 +0200
> @@ -368,8 +368,7 @@ extern GTY(()) tree cp_global_trees[CPTI
>   #define throw_fn			cp_global_trees[CPTI_THROW_FN]
>   #define rethrow_fn			cp_global_trees[CPTI_RETHROW_FN]
>   
> -/* The type of the function-pointer argument to "__cxa_atexit" (or
> -   "std::atexit", if "__cxa_atexit" is not being used).  */
> +/* The type of the function-pointer argument to "std::atexit".  */
>   #define atexit_fn_ptr_type_node         cp_global_trees[CPTI_ATEXIT_FN_PTR_TYPE]
>   
>   /* A pointer to `std::atexit'.  */
> @@ -384,7 +383,8 @@ extern GTY(()) tree cp_global_trees[CPTI
>   /* The declaration of the dynamic_cast runtime.  */
>   #define dynamic_cast_node		cp_global_trees[CPTI_DCAST]
>   
> -/* The type of a destructor.  */
> +/* The type of a destructor, passed to __cxa_atexit, __cxa_thread_atexit
> +   or __cxa_throw.  */
>   #define cleanup_type			cp_global_trees[CPTI_CLEANUP_TYPE]
>   
>   /* The type of the vtt parameter passed to subobject constructors and
> @@ -7067,6 +7067,7 @@ extern tree check_default_argument		(tre
>   extern int wrapup_namespace_globals		();
>   extern tree create_implicit_typedef		(tree, tree);
>   extern int local_variable_p			(const_tree);
> +extern tree get_cxa_atexit_fn_ptr_type		();
>   extern tree register_dtor_fn			(tree);
>   extern tmpl_spec_kind current_tmpl_spec_kind	(int);
>   extern tree cxx_builtin_function		(tree decl);
> --- gcc/cp/decl.cc.jj	2024-05-09 20:26:12.670614561 +0200
> +++ gcc/cp/decl.cc	2024-05-09 20:34:08.556378168 +0200
> @@ -93,7 +93,7 @@ static void record_key_method_defined (t
>   static tree create_array_type_for_decl (tree, tree, tree, location_t);
>   static tree get_atexit_node (void);
>   static tree get_dso_handle_node (void);
> -static tree start_cleanup_fn (void);
> +static tree start_cleanup_fn (bool);
>   static void end_cleanup_fn (void);
>   static tree cp_make_fname_decl (location_t, tree, int);
>   static void initialize_predefined_identifiers (void);
> @@ -9678,34 +9678,39 @@ declare_global_var (tree name, tree type
>     return decl;
>   }
>   
> -/* Returns the type for the argument to "__cxa_atexit" (or "atexit",
> -   if "__cxa_atexit" is not being used) corresponding to the function
> +/* Returns the type for the argument to "atexit" corresponding to the function
>      to be called when the program exits.  */
>   
>   static tree
> -get_atexit_fn_ptr_type (void)
> +get_atexit_fn_ptr_type ()
>   {
> -  tree fn_type;
> -
>     if (!atexit_fn_ptr_type_node)
>       {
> -      tree arg_type;
> -      if (flag_use_cxa_atexit
> -	  && !targetm.cxx.use_atexit_for_cxa_atexit ())
> -	/* The parameter to "__cxa_atexit" is "void (*)(void *)".  */
> -	arg_type = ptr_type_node;
> -      else
> -	/* The parameter to "atexit" is "void (*)(void)".  */
> -	arg_type = NULL_TREE;
> -
> -      fn_type = build_function_type_list (void_type_node,
> -					  arg_type, NULL_TREE);
> +      tree fn_type = build_function_type_list (void_type_node, NULL_TREE);
>         atexit_fn_ptr_type_node = build_pointer_type (fn_type);
>       }
>   
>     return atexit_fn_ptr_type_node;
>   }
>   
> +/* Returns the type for the argument to "__cxa_atexit", "__cxa_thread_atexit"
> +   or "__cxa_throw" corresponding to the destructor to be called when the
> +   program exits.  */
> +
> +tree
> +get_cxa_atexit_fn_ptr_type ()
> +{
> +  if (!cleanup_type)
> +    {
> +      tree fntype = build_function_type_list (void_type_node,
> +					      ptr_type_node, NULL_TREE);
> +      fntype = targetm.cxx.adjust_cdtor_callabi_fntype (fntype);
> +      cleanup_type = build_pointer_type (fntype);
> +    }
> +
> +  return cleanup_type;
> +}
> +
>   /* Returns a pointer to the `atexit' function.  Note that if
>      FLAG_USE_CXA_ATEXIT is nonzero, then this will actually be the new
>      `__cxa_atexit' function specified in the IA64 C++ ABI.  */
> @@ -9736,7 +9741,7 @@ get_atexit_node (void)
>         use_aeabi_atexit = targetm.cxx.use_aeabi_atexit ();
>         /* First, build the pointer-to-function type for the first
>   	 argument.  */
> -      fn_ptr_type = get_atexit_fn_ptr_type ();
> +      fn_ptr_type = get_cxa_atexit_fn_ptr_type ();
>         /* Then, build the rest of the argument types.  */
>         argtype2 = ptr_type_node;
>         if (use_aeabi_atexit)
> @@ -9819,7 +9824,7 @@ get_thread_atexit_node (void)
>   
>        int __cxa_thread_atexit (void (*)(void *), void *, void *) */
>     tree fn_type = build_function_type_list (integer_type_node,
> -					   get_atexit_fn_ptr_type (),
> +					   get_cxa_atexit_fn_ptr_type (),
>   					   ptr_type_node, ptr_type_node,
>   					   NULL_TREE);
>   
> @@ -9861,12 +9866,13 @@ get_dso_handle_node (void)
>   }
>   
>   /* Begin a new function with internal linkage whose job will be simply
> -   to destroy some particular variable.  */
> +   to destroy some particular variable.  OB_PARM is true if object pointer
> +   is passed to the cleanup function, otherwise no argument is passed.  */
>   
>   static GTY(()) int start_cleanup_cnt;
>   
>   static tree
> -start_cleanup_fn (void)
> +start_cleanup_fn (bool ob_parm)
>   {
>     char name[32];
>   
> @@ -9877,8 +9883,9 @@ start_cleanup_fn (void)
>   
>     /* Build the name of the function.  */
>     sprintf (name, "__tcf_%d", start_cleanup_cnt++);
> +  tree fntype = TREE_TYPE (ob_parm ? get_cxa_atexit_fn_ptr_type ()
> +				   : get_atexit_fn_ptr_type ());
>     /* Build the function declaration.  */
> -  tree fntype = TREE_TYPE (get_atexit_fn_ptr_type ());
>     tree fndecl = build_lang_decl (FUNCTION_DECL, get_identifier (name), fntype);
>     DECL_CONTEXT (fndecl) = FROB_CONTEXT (current_namespace);
>     /* It's a function with internal linkage, generated by the
> @@ -9891,7 +9898,7 @@ start_cleanup_fn (void)
>        emissions this way.  */
>     DECL_DECLARED_INLINE_P (fndecl) = 1;
>     DECL_INTERFACE_KNOWN (fndecl) = 1;
> -  if (flag_use_cxa_atexit && !targetm.cxx.use_atexit_for_cxa_atexit ())
> +  if (ob_parm)
>       {
>         /* Build the parameter.  */
>         tree parmdecl = cp_build_parm_decl (fndecl, NULL_TREE, ptr_type_node);
> @@ -9968,8 +9975,8 @@ register_dtor_fn (tree decl)
>         build_cleanup (decl);
>     
>         /* Now start the function.  */
> -      cleanup = start_cleanup_fn ();
> -
> +      cleanup = start_cleanup_fn (ob_parm);
> +
>         /* Now, recompute the cleanup.  It may contain SAVE_EXPRs that refer
>   	 to the original function, rather than the anonymous one.  That
>   	 will make the back end think that nested functions are in use,
> @@ -9998,7 +10005,7 @@ register_dtor_fn (tree decl)
>       {
>         /* We must convert CLEANUP to the type that "__cxa_atexit"
>   	 expects.  */
> -      cleanup = build_nop (get_atexit_fn_ptr_type (), cleanup);
> +      cleanup = build_nop (get_cxa_atexit_fn_ptr_type (), cleanup);
>         /* "__cxa_atexit" will pass the address of DECL to the
>   	 cleanup function.  */
>         mark_used (decl);
> --- gcc/cp/except.cc.jj	2024-05-09 10:30:54.821504899 +0200
> +++ gcc/cp/except.cc	2024-05-09 20:27:16.412779234 +0200
> @@ -645,11 +645,7 @@ build_throw (location_t loc, tree exp, t
>   
>         /* The CLEANUP_TYPE is the internal type of a destructor.  */
>         if (!cleanup_type)
> -	{
> -	  tree tmp = build_function_type_list (void_type_node,
> -					       ptr_type_node, NULL_TREE);
> -	  cleanup_type = build_pointer_type (tmp);
> -	}
> +	cleanup_type = get_cxa_atexit_fn_ptr_type ();
>   
>         if (!throw_fn)
>   	{
> 
> 
> 	Jakub
>
  

Patch

--- gcc/target.def.jj	2024-05-09 10:30:54.926503473 +0200
+++ gcc/target.def	2024-05-09 20:27:16.294780780 +0200
@@ -6498,7 +6498,7 @@  is in effect.  The default is to return
  hook_bool_void_false)
 
 /* Returns true if target may use atexit in the same manner as
-   __cxa_atexit  to register static destructors.  */
+   __cxa_atexit to register static destructors.  */
 DEFHOOK
 (use_atexit_for_cxa_atexit,
  "This hook returns true if the target @code{atexit} function can be used\n\
@@ -6509,6 +6509,17 @@  unloaded. The default is to return false
  bool, (void),
  hook_bool_void_false)
 
+/* Returns modified FUNCTION_TYPE for cdtor callabi.  */
+DEFHOOK
+(adjust_cdtor_callabi_fntype,
+ "This hook returns a possibly modified @code{FUNCTION_TYPE} for arguments\n\
+to @code{__cxa_atexit}, @code{__cxa_thread_atexit} or @code{__cxa_throw}\n\
+function pointers.  ABIs like mingw32 require special attributes to be added\n\
+to function types pointed to by arguments of these functions.\n\
+The default is to return the passed argument unmodified.",
+ tree, (tree fntype),
+ default_cxx_adjust_cdtor_callabi_fntype)
+
 DEFHOOK
 (adjust_class_at_definition,
 "@var{type} is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that has just\n\
--- gcc/targhooks.h.jj	2024-05-09 10:30:54.941503269 +0200
+++ gcc/targhooks.h	2024-05-09 20:27:16.315780505 +0200
@@ -65,6 +65,7 @@  extern machine_mode default_mode_for_suf
 
 extern tree default_cxx_guard_type (void);
 extern tree default_cxx_get_cookie_size (tree);
+extern tree default_cxx_adjust_cdtor_callabi_fntype (tree);
 
 extern bool hook_pass_by_reference_must_pass_in_stack
   (cumulative_args_t, const function_arg_info &);
--- gcc/targhooks.cc.jj	2024-05-09 10:30:54.927503459 +0200
+++ gcc/targhooks.cc	2024-05-09 20:27:16.338780204 +0200
@@ -329,6 +329,14 @@  default_cxx_get_cookie_size (tree type)
   return cookie_size;
 }
 
+/* Returns modified FUNCTION_TYPE for cdtor callabi.  */
+
+tree
+default_cxx_adjust_cdtor_callabi_fntype (tree fntype)
+{
+  return fntype;
+}
+
 /* Return true if a parameter must be passed by reference.  This version
    of the TARGET_PASS_BY_REFERENCE hook uses just MUST_PASS_IN_STACK.  */
 
--- gcc/doc/tm.texi.in.jj	2024-05-09 10:30:54.897503866 +0200
+++ gcc/doc/tm.texi.in	2024-05-09 20:27:16.355779981 +0200
@@ -7223,6 +7223,8 @@  floating-point support; they are not inc
 
 @hook TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT
 
+@hook TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE
+
 @hook TARGET_CXX_ADJUST_CLASS_AT_DEFINITION
 
 @hook TARGET_CXX_DECL_MANGLING_CONTEXT
--- gcc/doc/tm.texi.jj	2024-05-09 10:30:54.862504342 +0200
+++ gcc/doc/tm.texi	2024-05-09 20:27:16.368779810 +0200
@@ -11117,6 +11117,14 @@  shared libraries are run in the correct
 unloaded. The default is to return false.
 @end deftypefn
 
+@deftypefn {Target Hook} tree TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE (tree @var{fntype})
+This hook returns a possibly modified @code{FUNCTION_TYPE} for arguments
+to @code{__cxa_atexit}, @code{__cxa_thread_atexit} or @code{__cxa_throw}
+function pointers.  ABIs like mingw32 require special attributes to be added
+to function types pointed to by arguments of these functions.
+The default is to return the passed argument unmodified.
+@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
--- gcc/config/i386/i386.cc.jj	2024-05-09 10:30:58.508454809 +0200
+++ gcc/config/i386/i386.cc	2024-05-09 20:27:16.392779496 +0200
@@ -25800,6 +25800,20 @@  ix86_bitint_type_info (int n, struct bit
   return true;
 }
 
+/* Returns modified FUNCTION_TYPE for cdtor callabi.  */
+tree
+ix86_cxx_adjust_cdtor_callabi_fntype (tree fntype)
+{
+  if (TARGET_64BIT
+      || TARGET_RTD
+      || ix86_function_type_abi (fntype) != MS_ABI)
+    return fntype;
+  /* For 32-bit MS ABI add thiscall attribute.  */
+  tree attribs = tree_cons (get_identifier ("thiscall"), NULL_TREE,
+			    TYPE_ATTRIBUTES (fntype));
+  return build_type_attribute_variant (fntype, attribs);
+}
+
 /* Implement PUSH_ROUNDING.  On 386, we have pushw instruction that
    decrements by exactly 2 no matter what the position was, there is no pushb.
 
@@ -26411,6 +26425,8 @@  static const scoped_attribute_specs *con
 #define TARGET_C_EXCESS_PRECISION ix86_get_excess_precision
 #undef TARGET_C_BITINT_TYPE_INFO
 #define TARGET_C_BITINT_TYPE_INFO ix86_bitint_type_info
+#undef TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE
+#define TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE ix86_cxx_adjust_cdtor_callabi_fntype
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
 #undef TARGET_PUSH_ARGUMENT
--- gcc/cp/cp-tree.h.jj	2024-05-09 20:26:12.619615230 +0200
+++ gcc/cp/cp-tree.h	2024-05-09 20:27:16.395779457 +0200
@@ -368,8 +368,7 @@  extern GTY(()) tree cp_global_trees[CPTI
 #define throw_fn			cp_global_trees[CPTI_THROW_FN]
 #define rethrow_fn			cp_global_trees[CPTI_RETHROW_FN]
 
-/* The type of the function-pointer argument to "__cxa_atexit" (or
-   "std::atexit", if "__cxa_atexit" is not being used).  */
+/* The type of the function-pointer argument to "std::atexit".  */
 #define atexit_fn_ptr_type_node         cp_global_trees[CPTI_ATEXIT_FN_PTR_TYPE]
 
 /* A pointer to `std::atexit'.  */
@@ -384,7 +383,8 @@  extern GTY(()) tree cp_global_trees[CPTI
 /* The declaration of the dynamic_cast runtime.  */
 #define dynamic_cast_node		cp_global_trees[CPTI_DCAST]
 
-/* The type of a destructor.  */
+/* The type of a destructor, passed to __cxa_atexit, __cxa_thread_atexit
+   or __cxa_throw.  */
 #define cleanup_type			cp_global_trees[CPTI_CLEANUP_TYPE]
 
 /* The type of the vtt parameter passed to subobject constructors and
@@ -7067,6 +7067,7 @@  extern tree check_default_argument		(tre
 extern int wrapup_namespace_globals		();
 extern tree create_implicit_typedef		(tree, tree);
 extern int local_variable_p			(const_tree);
+extern tree get_cxa_atexit_fn_ptr_type		();
 extern tree register_dtor_fn			(tree);
 extern tmpl_spec_kind current_tmpl_spec_kind	(int);
 extern tree cxx_builtin_function		(tree decl);
--- gcc/cp/decl.cc.jj	2024-05-09 20:26:12.670614561 +0200
+++ gcc/cp/decl.cc	2024-05-09 20:34:08.556378168 +0200
@@ -93,7 +93,7 @@  static void record_key_method_defined (t
 static tree create_array_type_for_decl (tree, tree, tree, location_t);
 static tree get_atexit_node (void);
 static tree get_dso_handle_node (void);
-static tree start_cleanup_fn (void);
+static tree start_cleanup_fn (bool);
 static void end_cleanup_fn (void);
 static tree cp_make_fname_decl (location_t, tree, int);
 static void initialize_predefined_identifiers (void);
@@ -9678,34 +9678,39 @@  declare_global_var (tree name, tree type
   return decl;
 }
 
-/* Returns the type for the argument to "__cxa_atexit" (or "atexit",
-   if "__cxa_atexit" is not being used) corresponding to the function
+/* Returns the type for the argument to "atexit" corresponding to the function
    to be called when the program exits.  */
 
 static tree
-get_atexit_fn_ptr_type (void)
+get_atexit_fn_ptr_type ()
 {
-  tree fn_type;
-
   if (!atexit_fn_ptr_type_node)
     {
-      tree arg_type;
-      if (flag_use_cxa_atexit 
-	  && !targetm.cxx.use_atexit_for_cxa_atexit ())
-	/* The parameter to "__cxa_atexit" is "void (*)(void *)".  */
-	arg_type = ptr_type_node;
-      else
-	/* The parameter to "atexit" is "void (*)(void)".  */
-	arg_type = NULL_TREE;
-      
-      fn_type = build_function_type_list (void_type_node,
-					  arg_type, NULL_TREE);
+      tree fn_type = build_function_type_list (void_type_node, NULL_TREE);
       atexit_fn_ptr_type_node = build_pointer_type (fn_type);
     }
 
   return atexit_fn_ptr_type_node;
 }
 
+/* Returns the type for the argument to "__cxa_atexit", "__cxa_thread_atexit"
+   or "__cxa_throw" corresponding to the destructor to be called when the
+   program exits.  */
+
+tree
+get_cxa_atexit_fn_ptr_type ()
+{
+  if (!cleanup_type)
+    {
+      tree fntype = build_function_type_list (void_type_node,
+					      ptr_type_node, NULL_TREE);
+      fntype = targetm.cxx.adjust_cdtor_callabi_fntype (fntype);
+      cleanup_type = build_pointer_type (fntype);
+    }
+
+  return cleanup_type;
+}
+
 /* Returns a pointer to the `atexit' function.  Note that if
    FLAG_USE_CXA_ATEXIT is nonzero, then this will actually be the new
    `__cxa_atexit' function specified in the IA64 C++ ABI.  */
@@ -9736,7 +9741,7 @@  get_atexit_node (void)
       use_aeabi_atexit = targetm.cxx.use_aeabi_atexit ();
       /* First, build the pointer-to-function type for the first
 	 argument.  */
-      fn_ptr_type = get_atexit_fn_ptr_type ();
+      fn_ptr_type = get_cxa_atexit_fn_ptr_type ();
       /* Then, build the rest of the argument types.  */
       argtype2 = ptr_type_node;
       if (use_aeabi_atexit)
@@ -9819,7 +9824,7 @@  get_thread_atexit_node (void)
 
      int __cxa_thread_atexit (void (*)(void *), void *, void *) */
   tree fn_type = build_function_type_list (integer_type_node,
-					   get_atexit_fn_ptr_type (),
+					   get_cxa_atexit_fn_ptr_type (),
 					   ptr_type_node, ptr_type_node,
 					   NULL_TREE);
 
@@ -9861,12 +9866,13 @@  get_dso_handle_node (void)
 }
 
 /* Begin a new function with internal linkage whose job will be simply
-   to destroy some particular variable.  */
+   to destroy some particular variable.  OB_PARM is true if object pointer
+   is passed to the cleanup function, otherwise no argument is passed.  */
 
 static GTY(()) int start_cleanup_cnt;
 
 static tree
-start_cleanup_fn (void)
+start_cleanup_fn (bool ob_parm)
 {
   char name[32];
 
@@ -9877,8 +9883,9 @@  start_cleanup_fn (void)
 
   /* Build the name of the function.  */
   sprintf (name, "__tcf_%d", start_cleanup_cnt++);
+  tree fntype = TREE_TYPE (ob_parm ? get_cxa_atexit_fn_ptr_type ()
+				   : get_atexit_fn_ptr_type ());
   /* Build the function declaration.  */
-  tree fntype = TREE_TYPE (get_atexit_fn_ptr_type ());
   tree fndecl = build_lang_decl (FUNCTION_DECL, get_identifier (name), fntype);
   DECL_CONTEXT (fndecl) = FROB_CONTEXT (current_namespace);
   /* It's a function with internal linkage, generated by the
@@ -9891,7 +9898,7 @@  start_cleanup_fn (void)
      emissions this way.  */
   DECL_DECLARED_INLINE_P (fndecl) = 1;
   DECL_INTERFACE_KNOWN (fndecl) = 1;
-  if (flag_use_cxa_atexit && !targetm.cxx.use_atexit_for_cxa_atexit ())
+  if (ob_parm)
     {
       /* Build the parameter.  */
       tree parmdecl = cp_build_parm_decl (fndecl, NULL_TREE, ptr_type_node);
@@ -9968,8 +9975,8 @@  register_dtor_fn (tree decl)
       build_cleanup (decl);
   
       /* Now start the function.  */
-      cleanup = start_cleanup_fn ();
-      
+      cleanup = start_cleanup_fn (ob_parm);
+
       /* Now, recompute the cleanup.  It may contain SAVE_EXPRs that refer
 	 to the original function, rather than the anonymous one.  That
 	 will make the back end think that nested functions are in use,
@@ -9998,7 +10005,7 @@  register_dtor_fn (tree decl)
     {
       /* We must convert CLEANUP to the type that "__cxa_atexit"
 	 expects.  */
-      cleanup = build_nop (get_atexit_fn_ptr_type (), cleanup);
+      cleanup = build_nop (get_cxa_atexit_fn_ptr_type (), cleanup);
       /* "__cxa_atexit" will pass the address of DECL to the
 	 cleanup function.  */
       mark_used (decl);
--- gcc/cp/except.cc.jj	2024-05-09 10:30:54.821504899 +0200
+++ gcc/cp/except.cc	2024-05-09 20:27:16.412779234 +0200
@@ -645,11 +645,7 @@  build_throw (location_t loc, tree exp, t
 
       /* The CLEANUP_TYPE is the internal type of a destructor.  */
       if (!cleanup_type)
-	{
-	  tree tmp = build_function_type_list (void_type_node,
-					       ptr_type_node, NULL_TREE);
-	  cleanup_type = build_pointer_type (tmp);
-	}
+	cleanup_type = get_cxa_atexit_fn_ptr_type ();
 
       if (!throw_fn)
 	{