re PR c++/11326 (C++ IA64 ABI: 3.1.4: sometimes pointer to temporary return value is implicit first parameter preceding "this")
PR c++/11326 * c-common.c (flag_abi_version): Remove. * c-common.h (flag_abi_version): Likewise. * c-opts.c (c_common_handle_option): Remove OPT_fabi_version case. * c.opt (fabi-version): Remove. * calls.c (expand_call): Always pass a function type to struct_value_rtx. Use convert_memory_address. * common.opt (fabi-version): Add it. * flags.h (flag_abi_version): Likewise. (abi_version_at_least): New macro. * opts.c (common_handle_option): Add OPT_fabi_version. * toplev.c (flag_abi_version): Define it. * config/ia64/ia64.c (ia64_struct_retval_addr_is_first_parm_p): New function. (ia64_output_mi_thunk): Use it. (ia64_struct_value_rtx): Likewise. PR c++/11326 * cp-tree.h (abi_version_at_least): Remove. * mangle.c: Include flags.h. PR c++/11326 * g++.dg/abi/structret1.C: New test. From-SVN: r77968
This commit is contained in:
parent
3977a4a1ee
commit
57782ad852
|
@ -1,3 +1,22 @@
|
|||
2004-02-17 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/11326
|
||||
* c-common.c (flag_abi_version): Remove.
|
||||
* c-common.h (flag_abi_version): Likewise.
|
||||
* c-opts.c (c_common_handle_option): Remove OPT_fabi_version case.
|
||||
* c.opt (fabi-version): Remove.
|
||||
* calls.c (expand_call): Always pass a function type to
|
||||
struct_value_rtx. Use convert_memory_address.
|
||||
* common.opt (fabi-version): Add it.
|
||||
* flags.h (flag_abi_version): Likewise.
|
||||
(abi_version_at_least): New macro.
|
||||
* opts.c (common_handle_option): Add OPT_fabi_version.
|
||||
* toplev.c (flag_abi_version): Define it.
|
||||
* config/ia64/ia64.c (ia64_struct_retval_addr_is_first_parm_p):
|
||||
New function.
|
||||
(ia64_output_mi_thunk): Use it.
|
||||
(ia64_struct_value_rtx): Likewise.
|
||||
|
||||
2004-02-17 Kazu Hirata <kazu@cs.umass.edu>
|
||||
|
||||
* config/h8300/h8300.c (h8300_emit_stack_adjustment):
|
||||
|
|
|
@ -599,23 +599,6 @@ int flag_permissive;
|
|||
|
||||
int flag_enforce_eh_specs = 1;
|
||||
|
||||
/* The version of the C++ ABI in use. The following values are
|
||||
allowed:
|
||||
|
||||
0: The version of the ABI believed most conformant with the
|
||||
C++ ABI specification. This ABI may change as bugs are
|
||||
discovered and fixed. Therefore, 0 will not necessarily
|
||||
indicate the same ABI in different versions of G++.
|
||||
|
||||
1: The version of the ABI first used in G++ 3.2.
|
||||
|
||||
2: The version of the ABI first used in G++ 3.4.
|
||||
|
||||
Additional positive integers will be assigned as new versions of
|
||||
the ABI become the default version of the ABI. */
|
||||
|
||||
int flag_abi_version = 2;
|
||||
|
||||
/* Nonzero means warn about things that will change when compiling
|
||||
with an ABI-compliant compiler. */
|
||||
|
||||
|
|
|
@ -760,21 +760,6 @@ extern int flag_permissive;
|
|||
|
||||
extern int flag_enforce_eh_specs;
|
||||
|
||||
/* The version of the C++ ABI in use. The following values are
|
||||
allowed:
|
||||
|
||||
0: The version of the ABI believed most conformant with the
|
||||
C++ ABI specification. This ABI may change as bugs are
|
||||
discovered and fixed. Therefore, 0 will not necessarily
|
||||
indicate the same ABI in different versions of G++.
|
||||
|
||||
1: The version of the ABI first used in G++ 3.2.
|
||||
|
||||
Additional positive integers will be assigned as new versions of
|
||||
the ABI become the default version of the ABI. */
|
||||
|
||||
extern int flag_abi_version;
|
||||
|
||||
/* Nonzero means warn about things that will change when compiling
|
||||
with an ABI-compliant compiler. */
|
||||
|
||||
|
|
|
@ -692,10 +692,6 @@ c_common_handle_option (size_t scode, const char *arg, int value)
|
|||
warning ("switch \"%s\" is no longer supported", option->opt_text);
|
||||
break;
|
||||
|
||||
case OPT_fabi_version_:
|
||||
flag_abi_version = value;
|
||||
break;
|
||||
|
||||
case OPT_faccess_control:
|
||||
flag_access_control = value;
|
||||
break;
|
||||
|
|
|
@ -411,9 +411,6 @@ d
|
|||
C ObjC C++ ObjC++ Joined
|
||||
; Documented in common.opt. FIXME - what about -dI, -dD, -dN and -dD?
|
||||
|
||||
fabi-version=
|
||||
C++ ObjC++ Joined UInteger
|
||||
|
||||
faccess-control
|
||||
C++ ObjC++
|
||||
Enforce class member access control semantics
|
||||
|
|
14
gcc/calls.c
14
gcc/calls.c
|
@ -2080,6 +2080,8 @@ expand_call (tree exp, rtx target, int ignore)
|
|||
/* Declaration of the function being called,
|
||||
or 0 if the function is computed (not known by name). */
|
||||
tree fndecl = 0;
|
||||
/* The type of the function being called. */
|
||||
tree fntype;
|
||||
rtx insn;
|
||||
int try_tail_call = 1;
|
||||
int try_tail_recursion = 1;
|
||||
|
@ -2188,6 +2190,7 @@ expand_call (tree exp, rtx target, int ignore)
|
|||
fndecl = get_callee_fndecl (exp);
|
||||
if (fndecl)
|
||||
{
|
||||
fntype = TREE_TYPE (fndecl);
|
||||
if (!flag_no_inline
|
||||
&& fndecl != current_function_decl
|
||||
&& DECL_INLINE (fndecl)
|
||||
|
@ -2223,15 +2226,15 @@ expand_call (tree exp, rtx target, int ignore)
|
|||
attributes set in the type. */
|
||||
else
|
||||
{
|
||||
fntype = TREE_TYPE (TREE_TYPE (p));
|
||||
if (ignore
|
||||
&& lookup_attribute ("warn_unused_result",
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (TREE_TYPE (p)))))
|
||||
&& lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (fntype)))
|
||||
warning ("ignoring return value of function "
|
||||
"declared with attribute warn_unused_result");
|
||||
flags |= flags_from_decl_or_type (TREE_TYPE (TREE_TYPE (p)));
|
||||
flags |= flags_from_decl_or_type (fntype);
|
||||
}
|
||||
|
||||
struct_value = targetm.calls.struct_value_rtx (fndecl ? TREE_TYPE (fndecl) : 0, 0);
|
||||
struct_value = targetm.calls.struct_value_rtx (fntype, 0);
|
||||
|
||||
/* Warn if this value is an aggregate type,
|
||||
regardless of which calling convention we are using for it. */
|
||||
|
@ -2385,7 +2388,8 @@ expand_call (tree exp, rtx target, int ignore)
|
|||
|| (ACCUMULATE_OUTGOING_ARGS
|
||||
&& stack_arg_under_construction
|
||||
&& structure_value_addr == virtual_outgoing_args_rtx)
|
||||
? copy_addr_to_reg (structure_value_addr)
|
||||
? copy_addr_to_reg (convert_memory_address
|
||||
(Pmode, structure_value_addr))
|
||||
: structure_value_addr);
|
||||
|
||||
actparms
|
||||
|
|
|
@ -179,6 +179,9 @@ Common
|
|||
fPIE
|
||||
Common
|
||||
|
||||
fabi-version=
|
||||
Common Joined UInteger
|
||||
|
||||
falign-functions
|
||||
Common
|
||||
Align the start of functions
|
||||
|
|
|
@ -8802,6 +8802,27 @@ ia64_rwreloc_section_type_flags (tree decl, const char *name, int reloc)
|
|||
return default_section_type_flags_1 (decl, name, reloc, true);
|
||||
}
|
||||
|
||||
/* Returns true if FNTYPE (a FUNCTION_TYPE or a METHOD_TYPE) returns a
|
||||
structure type and that the address of that type should be passed
|
||||
in out0, rather than in r8. */
|
||||
|
||||
static bool
|
||||
ia64_struct_retval_addr_is_first_parm_p (tree fntype)
|
||||
{
|
||||
tree ret_type = TREE_TYPE (fntype);
|
||||
|
||||
/* The Itanium C++ ABI requires that out0, rather than r8, be used
|
||||
as the structure return address parameter, if the return value
|
||||
type has a non-trivial copy constructor or destructor. It is not
|
||||
clear if this same convention should be used for other
|
||||
programming languages. Until G++ 3.4, we incorrectly used r8 for
|
||||
these return values. */
|
||||
return (abi_version_at_least (2)
|
||||
&& ret_type
|
||||
&& TYPE_MODE (ret_type) == BLKmode
|
||||
&& TREE_ADDRESSABLE (ret_type)
|
||||
&& strcmp (lang_hooks.name, "GNU C++") == 0);
|
||||
}
|
||||
|
||||
/* Output the assembler code for a thunk function. THUNK_DECL is the
|
||||
declaration for the thunk function itself, FUNCTION is the decl for
|
||||
|
@ -8815,6 +8836,8 @@ ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
|
|||
tree function)
|
||||
{
|
||||
rtx this, insn, funexp;
|
||||
unsigned int this_parmno;
|
||||
unsigned int this_regno;
|
||||
|
||||
reload_completed = 1;
|
||||
epilogue_completed = 1;
|
||||
|
@ -8828,16 +8851,23 @@ ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
|
|||
current_frame_info.n_input_regs = 1;
|
||||
current_frame_info.need_regstk = (TARGET_REG_NAMES != 0);
|
||||
|
||||
if (!TARGET_REG_NAMES)
|
||||
reg_names[IN_REG (0)] = ia64_reg_numbers[0];
|
||||
|
||||
/* Mark the end of the (empty) prologue. */
|
||||
emit_note (NOTE_INSN_PROLOGUE_END);
|
||||
|
||||
this = gen_rtx_REG (Pmode, IN_REG (0));
|
||||
/* Figure out whether "this" will be the first parameter (the
|
||||
typical case) or the second parameter (as happens when the
|
||||
virtual function returns certain class objects). */
|
||||
this_parmno
|
||||
= (ia64_struct_retval_addr_is_first_parm_p (TREE_TYPE (thunk))
|
||||
? 1 : 0);
|
||||
this_regno = IN_REG (this_parmno);
|
||||
if (!TARGET_REG_NAMES)
|
||||
reg_names[this_regno] = ia64_reg_numbers[this_parmno];
|
||||
|
||||
this = gen_rtx_REG (Pmode, this_regno);
|
||||
if (TARGET_ILP32)
|
||||
{
|
||||
rtx tmp = gen_rtx_REG (ptr_mode, IN_REG (0));
|
||||
rtx tmp = gen_rtx_REG (ptr_mode, this_regno);
|
||||
REG_POINTER (tmp) = 1;
|
||||
if (delta && CONST_OK_FOR_I (delta))
|
||||
{
|
||||
|
@ -8945,9 +8975,11 @@ ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
|
|||
/* Worker function for TARGET_STRUCT_VALUE_RTX. */
|
||||
|
||||
static rtx
|
||||
ia64_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
|
||||
ia64_struct_value_rtx (tree fntype,
|
||||
int incoming ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (ia64_struct_retval_addr_is_first_parm_p (fntype))
|
||||
return NULL_RTX;
|
||||
return gen_rtx_REG (Pmode, GR_REG (8));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2004-02-17 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/11326
|
||||
* cp-tree.h (abi_version_at_least): Remove.
|
||||
* mangle.c: Include flags.h.
|
||||
|
||||
2004-02-15 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/13971
|
||||
|
|
|
@ -213,12 +213,6 @@ struct diagnostic_context;
|
|||
|
||||
#endif
|
||||
|
||||
/* Returns TRUE if generated code should match ABI version N or
|
||||
greater is in use. */
|
||||
|
||||
#define abi_version_at_least(N) \
|
||||
(flag_abi_version == 0 || flag_abi_version >= (N))
|
||||
|
||||
|
||||
/* Language-dependent contents of an identifier. */
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "obstack.h"
|
||||
#include "toplev.h"
|
||||
#include "varray.h"
|
||||
#include "flags.h"
|
||||
|
||||
/* Debugging support. */
|
||||
|
||||
|
|
21
gcc/flags.h
21
gcc/flags.h
|
@ -731,6 +731,27 @@ extern int flag_var_tracking;
|
|||
|
||||
extern const char *flag_random_seed;
|
||||
|
||||
/* The version of the C++ ABI in use. The following values are
|
||||
allowed:
|
||||
|
||||
0: The version of the ABI believed most conformant with the
|
||||
C++ ABI specification. This ABI may change as bugs are
|
||||
discovered and fixed. Therefore, 0 will not necessarily
|
||||
indicate the same ABI in different versions of G++.
|
||||
|
||||
1: The version of the ABI first used in G++ 3.2.
|
||||
|
||||
Additional positive integers will be assigned as new versions of
|
||||
the ABI become the default version of the ABI. */
|
||||
|
||||
extern int flag_abi_version;
|
||||
|
||||
/* Returns TRUE if generated code should match ABI version N or
|
||||
greater is in use. */
|
||||
|
||||
#define abi_version_at_least(N) \
|
||||
(flag_abi_version == 0 || flag_abi_version >= (N))
|
||||
|
||||
/* True if the given mode has a NaN representation and the treatment of
|
||||
NaN operands is important. Certain optimizations, such as folding
|
||||
x * 0 into x, are not correct for NaN operands, and are normally
|
||||
|
|
|
@ -833,6 +833,10 @@ common_handle_option (size_t scode, const char *arg,
|
|||
flag_pie = value + value;
|
||||
break;
|
||||
|
||||
case OPT_fabi_version_:
|
||||
flag_abi_version = value;
|
||||
break;
|
||||
|
||||
case OPT_falign_functions:
|
||||
align_functions = !value;
|
||||
break;
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2004-02-17 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/11326
|
||||
* g++.dg/abi/structret1.C: New test.
|
||||
|
||||
2004-02-17 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc.dg/i386-cpuid.h (bit_CMOV): Define.
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// { dg-do run { target ia64-*-* } }
|
||||
// { dg-options "-fabi-version=0" }
|
||||
|
||||
extern "C" void abort ();
|
||||
|
||||
struct ConstructedObject {
|
||||
ConstructedObject() {};
|
||||
~ConstructedObject() {};
|
||||
ConstructedObject(const ConstructedObject &from) {};
|
||||
};
|
||||
|
||||
struct FrameworkObject {
|
||||
ConstructedObject action();
|
||||
};
|
||||
|
||||
ConstructedObject FrameworkObject::action() {
|
||||
void *r32, *r33;
|
||||
|
||||
asm("mov %0 = r32\nmov %1 = r33" : "=r"(r32), "=r"(r33) : );
|
||||
if (this != r33) {
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FrameworkObject slawa;
|
||||
slawa.action();
|
||||
return 0;
|
||||
}
|
||||
|
17
gcc/toplev.c
17
gcc/toplev.c
|
@ -1016,6 +1016,23 @@ int flag_evaluation_order = 0;
|
|||
/* Add or remove a leading underscore from user symbols. */
|
||||
int flag_leading_underscore = -1;
|
||||
|
||||
/* The version of the C++ ABI in use. The following values are
|
||||
allowed:
|
||||
|
||||
0: The version of the ABI believed most conformant with the
|
||||
C++ ABI specification. This ABI may change as bugs are
|
||||
discovered and fixed. Therefore, 0 will not necessarily
|
||||
indicate the same ABI in different versions of G++.
|
||||
|
||||
1: The version of the ABI first used in G++ 3.2.
|
||||
|
||||
2: The version of the ABI first used in G++ 3.4.
|
||||
|
||||
Additional positive integers will be assigned as new versions of
|
||||
the ABI become the default version of the ABI. */
|
||||
|
||||
int flag_abi_version = 2;
|
||||
|
||||
/* The user symbol prefix after having resolved same. */
|
||||
const char *user_label_prefix;
|
||||
|
||||
|
|
Loading…
Reference in New Issue