re PR c++/11326 (C++ IA64 ABI: 3.1.4: sometimes pointer to temporary return value...
authorMark Mitchell <mark@codesourcery.com>
Tue, 17 Feb 2004 18:32:45 +0000 (18:32 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 17 Feb 2004 18:32:45 +0000 (18:32 +0000)
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

16 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/c-opts.c
gcc/c.opt
gcc/calls.c
gcc/common.opt
gcc/config/ia64/ia64.c
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/mangle.c
gcc/flags.h
gcc/opts.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/structret1.C [new file with mode: 0644]
gcc/toplev.c

index 04f0f75..c099df6 100644 (file)
@@ -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):
index 184f26e..63ce3c7 100644 (file)
@@ -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.  */
 
index f409e7a..00d5d5c 100644 (file)
@@ -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.  */
 
index 37d2ac4..a0d7382 100644 (file)
@@ -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;
index 4856fc5..2a2ff85 100644 (file)
--- a/gcc/c.opt
+++ b/gcc/c.opt
@@ -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
index d702ed0..c667575 100644 (file)
@@ -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
index 4c08b97..8598d8c 100644 (file)
@@ -179,6 +179,9 @@ Common
 fPIE
 Common
 
+fabi-version=
+Common Joined UInteger
+
 falign-functions
 Common
 Align the start of functions
index 8dcee21..ffbb349 100644 (file)
@@ -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));
 }
 
index 6c5e957..48edcfd 100644 (file)
@@ -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
index 0097c42..36acc5a 100644 (file)
@@ -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))
-
 \f
 /* Language-dependent contents of an identifier.  */
 
index 70b022b..a41c141 100644 (file)
@@ -58,6 +58,7 @@
 #include "obstack.h"
 #include "toplev.h"
 #include "varray.h"
+#include "flags.h"
 
 /* Debugging support.  */
 
index 1ca9d98..626993f 100644 (file)
@@ -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
index d54d1b4..45acba3 100644 (file)
@@ -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;
index 7529302..a49e599 100644 (file)
@@ -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.
diff --git a/gcc/testsuite/g++.dg/abi/structret1.C b/gcc/testsuite/g++.dg/abi/structret1.C
new file mode 100644 (file)
index 0000000..e9d4fd0
--- /dev/null
@@ -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;
+}
+
index c470cf0..7473ead 100644 (file)
@@ -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;