2003-10-20 Andrew Cagney <cagney@redhat.com>
authorAndrew Cagney <cagney@redhat.com>
Mon, 20 Oct 2003 15:38:02 +0000 (15:38 +0000)
committerAndrew Cagney <cagney@redhat.com>
Mon, 20 Oct 2003 15:38:02 +0000 (15:38 +0000)
* values.c (register_value_being_returned): Update comments.  Use
"gdbarch_return_value" when available.
(using_struct_return): Ditto.
(set_return_value): Ditto.  Use "gdbarch_return_value" when
available..  Print a warning, and not an error, when an unhandled
return type is encountered.
* infcmd.c: Include "gdb_assert.h".
(print_return_value): When gdbarch_return_value_p, and using
struct return, assume that the value is not available.
* defs.h (return_value_convention): Define.
* gdbarch.sh (gdbarch_return_value): New predicate method.
* gdbarch.h, gdbarch.c: Re-generate
* ppc-sysv-tdep.c (return_value_convention): Delete definition.

Index: doc/ChangeLog
2003-10-20  Andrew Cagney  <cagney@redhat.com>

* gdbint.texinfo (Target Architecture Definition): Document
gdbarch_return_value.  Add cross references from
USE_STRUCT_CONVENTION, EXTRACT_RETURN_VALUE, and
STORE_RETURN_VALUE, and from/to EXTRACT_STRUCT_VALUE_ADDRESS.

gdb/ChangeLog
gdb/defs.h
gdb/doc/ChangeLog
gdb/doc/gdbint.texinfo
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/infcmd.c
gdb/ppc-sysv-tdep.c
gdb/values.c

index 28fa74569dc58d99971c06ce29336d78cc7a957c..bed0fbf1664f0967e1d500e467a4be329e62c5d2 100644 (file)
@@ -1,3 +1,19 @@
+2003-10-20  Andrew Cagney  <cagney@redhat.com>
+
+       * values.c (register_value_being_returned): Update comments.  Use
+       "gdbarch_return_value" when available.
+       (using_struct_return): Ditto.
+       (set_return_value): Ditto.  Use "gdbarch_return_value" when
+       available..  Print a warning, and not an error, when an unhandled
+       return type is encountered.
+       * infcmd.c: Include "gdb_assert.h".
+       (print_return_value): When gdbarch_return_value_p, and using
+       struct return, assume that the value is not available.
+       * defs.h (return_value_convention): Define.
+       * gdbarch.sh (gdbarch_return_value): New predicate method.
+       * gdbarch.h, gdbarch.c: Re-generate
+       * ppc-sysv-tdep.c (return_value_convention): Delete definition.
+
 2003-10-20  Andrew Cagney  <cagney@redhat.com>
 
        * symtab.c: Replace "struct sec" with "struct bfd_section".
index 696ee5b4452bc4e3fcc0a3ab623d0ba791d6a0d4..c7713b90c3491eff0f19ca8dd08e4380bb237965 100644 (file)
@@ -230,6 +230,21 @@ enum auto_boolean
   AUTO_BOOLEAN_AUTO
 };
 
+/* Potential ways that a function can return a value of a given type.  */
+enum return_value_convention
+{
+  /* Where the return value has been squeezed into one or more
+     registers.  */
+  RETURN_VALUE_REGISTER_CONVENTION,
+  /* Commonly known as the "struct return convention".  The caller
+     passes an additional hidden first parameter to the caller.  That
+     parameter contains the address at which the value being returned
+     should be stored.  While typically, and historically, used for
+     large structs, this is convention is applied to values of many
+     different types.  */
+  RETURN_VALUE_STRUCT_CONVENTION
+};
+
 /* the cleanup list records things that have to be undone
    if an error happens (descriptors to be closed, memory to be freed, etc.)
    Each link in the chain records a function to call and an
index d81239f862c311ed04ccf8c0ff004c550f949fff..115921d38afacd6dd6eebd0727e6a9ba4d224c31 100644 (file)
@@ -1,3 +1,10 @@
+2003-10-20  Andrew Cagney  <cagney@redhat.com>
+
+       * gdbint.texinfo (Target Architecture Definition): Document
+       gdbarch_return_value.  Add cross references from
+       USE_STRUCT_CONVENTION, EXTRACT_RETURN_VALUE, and
+       STORE_RETURN_VALUE, and from/to EXTRACT_STRUCT_VALUE_ADDRESS.
+
 2003-10-18  Mark Kettenis  <kettenis@gnu.org>
 
        * gdbint.texinfo (Target Architecture Definition): Document
index e0dcf3541ef0e9deee0bdd527a40512aa239f7e8..77e2b7eb690f07cd36834f2002443d7bf94a2254 100644 (file)
@@ -3219,13 +3219,17 @@ Define this to extract a function's return value of type @var{type} from
 the raw register state @var{regbuf} and copy that, in virtual format,
 into @var{valbuf}.
  
+This method has been deprecated in favour of @code{gdbarch_return_value}
+(@pxref{gdbarch_return_value}).
+
 @item EXTRACT_STRUCT_VALUE_ADDRESS(@var{regbuf})
 @findex EXTRACT_STRUCT_VALUE_ADDRESS
+@anchor{EXTRACT_STRUCT_VALUE_ADDRESS}
 When defined, extract from the array @var{regbuf} (containing the raw
 register state) the @code{CORE_ADDR} at which a function should return
 its structure value.
 
-If not defined, @code{EXTRACT_RETURN_VALUE} is used.
+@xref{gdbarch_return_value}.
 
 @item EXTRACT_STRUCT_VALUE_ADDRESS_P()
 @findex EXTRACT_STRUCT_VALUE_ADDRESS_P
@@ -3824,6 +3828,48 @@ allocated on the stack.  @xref{unwind_dummy_id}.
 Define this to convert sdb register numbers into @value{GDBN} regnums.  If not
 defined, no conversion will be done.
 
+@item enum return_value_convention gdbarch_return_value (struct gdbarch *@var{gdbarch}, struct type *@var{valtype}, struct regcache *@var{regcache}, const void *@var{inval}, void *@var{outval})
+@findex gdbarch_return_value
+@anchor{gdbarch_return_value} Given a function with a return-value of
+type @var{rettype}, return which return-value convention that function
+would use.
+
+@value{GDBN} currently recognizes two function return-value conventions:
+@code{RETURN_VALUE_REGISTER_CONVENTION} where the return value is found
+in registers; and @code{RETURN_VALUE_STRUCT_CONVENTION} where the return
+value is found in memory and the address of that memory location is
+passed in as the function's first parameter.
+
+If the register convention is being used, and @var{inval} is
+non-@code{NULL}, also copy the return-value in @var{inval} into
+@var{regcache}.
+
+If the register convention is being used, and @var{outval} is
+non-@code{NULL}, also copy the return value from @var{regcache} into
+@var{outval} (@var{regcache} contains a copy of the registers from the
+just returned function).
+
+@xref{EXTRACT_STRUCT_VALUE_ADDRESS}, for a description of how
+return-values that use the struct convention are handled.
+
+@emph{Maintainer note: This method replaces separate predicate, extract,
+store methods.  By having only one method, the logic needed to determine
+the return-value convention need only be implemented in one place.  If
+@value{GDBN} were written in an @sc{oo} language, this method would
+instead return an object that knew how to perform the register
+return-value extract and store.}
+
+@emph{Maintainer note: This method does not take a @var{gcc_p}
+parameter, and such a parameter should not be added.  If an architecture
+that requires per-compiler or per-function information be identified,
+then the replacement of @var{rettype} with @code{struct value}
+@var{function} should be persued.}
+
+@emph{Maintainer note: The @var{regcache} parameter limits this methods
+to the inner most frame.  While replacing @var{regcache} with a
+@code{struct frame_info} @var{frame} parameter would remove that
+limitation there has yet to be a demonstrated need for such a change.}
+
 @item SKIP_PERMANENT_BREAKPOINT
 @findex SKIP_PERMANENT_BREAKPOINT
 Advance the inferior's PC past a permanent breakpoint.  @value{GDBN} normally
@@ -3882,6 +3928,9 @@ A C expression that writes the function return value, found in
 @var{valbuf}, into the @var{regcache}.  @var{type} is the type of the
 value that is to be returned.
 
+This method has been deprecated in favour of @code{gdbarch_return_value}
+(@pxref{gdbarch_return_value}).
+
 @item SUN_FIXED_LBRAC_BUG
 @findex SUN_FIXED_LBRAC_BUG
 (Used only for Sun-3 and Sun-4 targets.)
@@ -4017,6 +4066,9 @@ being considered is known to have been compiled by GCC; this is helpful
 for systems where GCC is known to use different calling convention than
 other compilers.
 
+This method has been deprecated in favour of @code{gdbarch_return_value}
+(@pxref{gdbarch_return_value}).
+
 @item VALUE_TO_REGISTER(@var{type}, @var{regnum}, @var{from}, @var{to})
 @findex VALUE_TO_REGISTER
 Convert a value of type @var{type} into the raw contents of register
index feb6725606947a98e48ecef6ae8e21361eec9463..1983421d0f39420430b8345c73a49b9dca6b3e58 100644 (file)
@@ -203,16 +203,17 @@ struct gdbarch
   gdbarch_pointer_to_address_ftype *pointer_to_address;
   gdbarch_address_to_pointer_ftype *address_to_pointer;
   gdbarch_integer_to_address_ftype *integer_to_address;
-  gdbarch_return_value_on_stack_ftype *return_value_on_stack;
   gdbarch_deprecated_pop_frame_ftype *deprecated_pop_frame;
   gdbarch_deprecated_store_struct_return_ftype *deprecated_store_struct_return;
+  gdbarch_return_value_ftype *return_value;
+  gdbarch_return_value_on_stack_ftype *return_value_on_stack;
   gdbarch_extract_return_value_ftype *extract_return_value;
   gdbarch_store_return_value_ftype *store_return_value;
   gdbarch_deprecated_extract_return_value_ftype *deprecated_extract_return_value;
   gdbarch_deprecated_store_return_value_ftype *deprecated_store_return_value;
+  gdbarch_use_struct_convention_ftype *use_struct_convention;
   gdbarch_extract_struct_value_address_ftype *extract_struct_value_address;
   gdbarch_deprecated_extract_struct_value_address_ftype *deprecated_extract_struct_value_address;
-  gdbarch_use_struct_convention_ftype *use_struct_convention;
   gdbarch_deprecated_frame_init_saved_regs_ftype *deprecated_frame_init_saved_regs;
   gdbarch_deprecated_init_extra_frame_info_ftype *deprecated_init_extra_frame_info;
   gdbarch_skip_prologue_ftype *skip_prologue;
@@ -374,16 +375,17 @@ struct gdbarch startup_gdbarch =
   0,  /* pointer_to_address */
   0,  /* address_to_pointer */
   0,  /* integer_to_address */
-  0,  /* return_value_on_stack */
   0,  /* deprecated_pop_frame */
   0,  /* deprecated_store_struct_return */
+  0,  /* return_value */
+  0,  /* return_value_on_stack */
   0,  /* extract_return_value */
   0,  /* store_return_value */
   0,  /* deprecated_extract_return_value */
   0,  /* deprecated_store_return_value */
+  0,  /* use_struct_convention */
   0,  /* extract_struct_value_address */
   0,  /* deprecated_extract_struct_value_address */
-  0,  /* use_struct_convention */
   0,  /* deprecated_frame_init_saved_regs */
   0,  /* deprecated_init_extra_frame_info */
   0,  /* skip_prologue */
@@ -692,14 +694,15 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of pointer_to_address, invalid_p == 0 */
   /* Skip verify of address_to_pointer, invalid_p == 0 */
   /* Skip verify of integer_to_address, has predicate */
-  /* Skip verify of return_value_on_stack, invalid_p == 0 */
   /* Skip verify of deprecated_pop_frame, has predicate */
   /* Skip verify of deprecated_store_struct_return, has predicate */
+  /* Skip verify of return_value, has predicate */
+  /* Skip verify of return_value_on_stack, invalid_p == 0 */
   /* Skip verify of extract_return_value, invalid_p == 0 */
   /* Skip verify of store_return_value, invalid_p == 0 */
+  /* Skip verify of use_struct_convention, invalid_p == 0 */
   /* Skip verify of extract_struct_value_address, has predicate */
   /* Skip verify of deprecated_extract_struct_value_address, has predicate */
-  /* Skip verify of use_struct_convention, invalid_p == 0 */
   /* Skip verify of deprecated_frame_init_saved_regs, has predicate */
   /* Skip verify of deprecated_init_extra_frame_info, has predicate */
   if ((GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL)
@@ -807,6 +810,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: regset_from_core_section = 0x%08lx\n",
                       (long) current_gdbarch->regset_from_core_section);
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_return_value_p() = %d\n",
+                      gdbarch_return_value_p (current_gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: return_value = 0x%08lx\n",
+                      (long) current_gdbarch->return_value);
   fprintf_unfiltered (file,
                       "gdbarch_dump: in_function_epilogue_p = 0x%08lx\n",
                       (long) current_gdbarch->in_function_epilogue_p);
@@ -4229,23 +4238,6 @@ set_gdbarch_integer_to_address (struct gdbarch *gdbarch,
   gdbarch->integer_to_address = integer_to_address;
 }
 
-int
-gdbarch_return_value_on_stack (struct gdbarch *gdbarch, struct type *type)
-{
-  gdb_assert (gdbarch != NULL);
-  gdb_assert (gdbarch->return_value_on_stack != NULL);
-  if (gdbarch_debug >= 2)
-    fprintf_unfiltered (gdb_stdlog, "gdbarch_return_value_on_stack called\n");
-  return gdbarch->return_value_on_stack (type);
-}
-
-void
-set_gdbarch_return_value_on_stack (struct gdbarch *gdbarch,
-                                   gdbarch_return_value_on_stack_ftype return_value_on_stack)
-{
-  gdbarch->return_value_on_stack = return_value_on_stack;
-}
-
 int
 gdbarch_deprecated_pop_frame_p (struct gdbarch *gdbarch)
 {
@@ -4294,6 +4286,47 @@ set_gdbarch_deprecated_store_struct_return (struct gdbarch *gdbarch,
   gdbarch->deprecated_store_struct_return = deprecated_store_struct_return;
 }
 
+int
+gdbarch_return_value_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->return_value != NULL;
+}
+
+enum return_value_convention
+gdbarch_return_value (struct gdbarch *gdbarch, struct type *valtype, struct regcache *regcache, const void *inval, void *outval)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->return_value != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_return_value called\n");
+  return gdbarch->return_value (gdbarch, valtype, regcache, inval, outval);
+}
+
+void
+set_gdbarch_return_value (struct gdbarch *gdbarch,
+                          gdbarch_return_value_ftype return_value)
+{
+  gdbarch->return_value = return_value;
+}
+
+int
+gdbarch_return_value_on_stack (struct gdbarch *gdbarch, struct type *type)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->return_value_on_stack != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_return_value_on_stack called\n");
+  return gdbarch->return_value_on_stack (type);
+}
+
+void
+set_gdbarch_return_value_on_stack (struct gdbarch *gdbarch,
+                                   gdbarch_return_value_on_stack_ftype return_value_on_stack)
+{
+  gdbarch->return_value_on_stack = return_value_on_stack;
+}
+
 void
 gdbarch_extract_return_value (struct gdbarch *gdbarch, struct type *type, struct regcache *regcache, void *valbuf)
 {
@@ -4362,6 +4395,23 @@ set_gdbarch_deprecated_store_return_value (struct gdbarch *gdbarch,
   gdbarch->deprecated_store_return_value = deprecated_store_return_value;
 }
 
+int
+gdbarch_use_struct_convention (struct gdbarch *gdbarch, int gcc_p, struct type *value_type)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->use_struct_convention != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_use_struct_convention called\n");
+  return gdbarch->use_struct_convention (gcc_p, value_type);
+}
+
+void
+set_gdbarch_use_struct_convention (struct gdbarch *gdbarch,
+                                   gdbarch_use_struct_convention_ftype use_struct_convention)
+{
+  gdbarch->use_struct_convention = use_struct_convention;
+}
+
 int
 gdbarch_extract_struct_value_address_p (struct gdbarch *gdbarch)
 {
@@ -4410,23 +4460,6 @@ set_gdbarch_deprecated_extract_struct_value_address (struct gdbarch *gdbarch,
   gdbarch->deprecated_extract_struct_value_address = deprecated_extract_struct_value_address;
 }
 
-int
-gdbarch_use_struct_convention (struct gdbarch *gdbarch, int gcc_p, struct type *value_type)
-{
-  gdb_assert (gdbarch != NULL);
-  gdb_assert (gdbarch->use_struct_convention != NULL);
-  if (gdbarch_debug >= 2)
-    fprintf_unfiltered (gdb_stdlog, "gdbarch_use_struct_convention called\n");
-  return gdbarch->use_struct_convention (gcc_p, value_type);
-}
-
-void
-set_gdbarch_use_struct_convention (struct gdbarch *gdbarch,
-                                   gdbarch_use_struct_convention_ftype use_struct_convention)
-{
-  gdbarch->use_struct_convention = use_struct_convention;
-}
-
 int
 gdbarch_deprecated_frame_init_saved_regs_p (struct gdbarch *gdbarch)
 {
index a82a12faac499015dc5d822bed8e60672186042a..03dcc37272b1ff850436d019530b96bfd2f527e6 100644 (file)
@@ -1392,16 +1392,6 @@ extern void set_gdbarch_integer_to_address (struct gdbarch *gdbarch, gdbarch_int
 #define INTEGER_TO_ADDRESS(type, buf) (gdbarch_integer_to_address (current_gdbarch, type, buf))
 #endif
 
-typedef int (gdbarch_return_value_on_stack_ftype) (struct type *type);
-extern int gdbarch_return_value_on_stack (struct gdbarch *gdbarch, struct type *type);
-extern void set_gdbarch_return_value_on_stack (struct gdbarch *gdbarch, gdbarch_return_value_on_stack_ftype *return_value_on_stack);
-#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (RETURN_VALUE_ON_STACK)
-#error "Non multi-arch definition of RETURN_VALUE_ON_STACK"
-#endif
-#if !defined (RETURN_VALUE_ON_STACK)
-#define RETURN_VALUE_ON_STACK(type) (gdbarch_return_value_on_stack (current_gdbarch, type))
-#endif
-
 #if defined (DEPRECATED_POP_FRAME)
 /* Legacy for systems yet to multi-arch DEPRECATED_POP_FRAME */
 #if !defined (DEPRECATED_POP_FRAME_P)
@@ -1454,6 +1444,34 @@ extern void set_gdbarch_deprecated_store_struct_return (struct gdbarch *gdbarch,
 #define DEPRECATED_STORE_STRUCT_RETURN(addr, sp) (gdbarch_deprecated_store_struct_return (current_gdbarch, addr, sp))
 #endif
 
+/* It has been suggested that this, well actually its predecessor,
+   should take the type/value of the function to be called and not the
+   return type.  This is left as an exercise for the reader. */
+
+extern int gdbarch_return_value_p (struct gdbarch *gdbarch);
+
+typedef enum return_value_convention (gdbarch_return_value_ftype) (struct gdbarch *gdbarch, struct type *valtype, struct regcache *regcache, const void *inval, void *outval);
+extern enum return_value_convention gdbarch_return_value (struct gdbarch *gdbarch, struct type *valtype, struct regcache *regcache, const void *inval, void *outval);
+extern void set_gdbarch_return_value (struct gdbarch *gdbarch, gdbarch_return_value_ftype *return_value);
+
+/* The deprecated methods RETURN_VALUE_ON_STACK, EXTRACT_RETURN_VALUE,
+   STORE_RETURN_VALUE and USE_STRUCT_CONVENTION have all been folded
+   into RETURN_VALUE.  For the moment do not try to fold in
+   EXTRACT_STRUCT_VALUE_ADDRESS as, dependant on the ABI, the debug
+   info, and the level of effort, it may well be possible to find the
+   address of a structure being return on the stack.  Someone else can
+   make that change. */
+
+typedef int (gdbarch_return_value_on_stack_ftype) (struct type *type);
+extern int gdbarch_return_value_on_stack (struct gdbarch *gdbarch, struct type *type);
+extern void set_gdbarch_return_value_on_stack (struct gdbarch *gdbarch, gdbarch_return_value_on_stack_ftype *return_value_on_stack);
+#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (RETURN_VALUE_ON_STACK)
+#error "Non multi-arch definition of RETURN_VALUE_ON_STACK"
+#endif
+#if !defined (RETURN_VALUE_ON_STACK)
+#define RETURN_VALUE_ON_STACK(type) (gdbarch_return_value_on_stack (current_gdbarch, type))
+#endif
+
 typedef void (gdbarch_extract_return_value_ftype) (struct type *type, struct regcache *regcache, void *valbuf);
 extern void gdbarch_extract_return_value (struct gdbarch *gdbarch, struct type *type, struct regcache *regcache, void *valbuf);
 extern void set_gdbarch_extract_return_value (struct gdbarch *gdbarch, gdbarch_extract_return_value_ftype *extract_return_value);
@@ -1494,6 +1512,16 @@ extern void set_gdbarch_deprecated_store_return_value (struct gdbarch *gdbarch,
 #define DEPRECATED_STORE_RETURN_VALUE(type, valbuf) (gdbarch_deprecated_store_return_value (current_gdbarch, type, valbuf))
 #endif
 
+typedef int (gdbarch_use_struct_convention_ftype) (int gcc_p, struct type *value_type);
+extern int gdbarch_use_struct_convention (struct gdbarch *gdbarch, int gcc_p, struct type *value_type);
+extern void set_gdbarch_use_struct_convention (struct gdbarch *gdbarch, gdbarch_use_struct_convention_ftype *use_struct_convention);
+#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (USE_STRUCT_CONVENTION)
+#error "Non multi-arch definition of USE_STRUCT_CONVENTION"
+#endif
+#if !defined (USE_STRUCT_CONVENTION)
+#define USE_STRUCT_CONVENTION(gcc_p, value_type) (gdbarch_use_struct_convention (current_gdbarch, gcc_p, value_type))
+#endif
+
 #if defined (EXTRACT_STRUCT_VALUE_ADDRESS)
 /* Legacy for systems yet to multi-arch EXTRACT_STRUCT_VALUE_ADDRESS */
 #if !defined (EXTRACT_STRUCT_VALUE_ADDRESS_P)
@@ -1544,16 +1572,6 @@ extern void set_gdbarch_deprecated_extract_struct_value_address (struct gdbarch
 #define DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS(regbuf) (gdbarch_deprecated_extract_struct_value_address (current_gdbarch, regbuf))
 #endif
 
-typedef int (gdbarch_use_struct_convention_ftype) (int gcc_p, struct type *value_type);
-extern int gdbarch_use_struct_convention (struct gdbarch *gdbarch, int gcc_p, struct type *value_type);
-extern void set_gdbarch_use_struct_convention (struct gdbarch *gdbarch, gdbarch_use_struct_convention_ftype *use_struct_convention);
-#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (USE_STRUCT_CONVENTION)
-#error "Non multi-arch definition of USE_STRUCT_CONVENTION"
-#endif
-#if !defined (USE_STRUCT_CONVENTION)
-#define USE_STRUCT_CONVENTION(gcc_p, value_type) (gdbarch_use_struct_convention (current_gdbarch, gcc_p, value_type))
-#endif
-
 #if defined (DEPRECATED_FRAME_INIT_SAVED_REGS)
 /* Legacy for systems yet to multi-arch DEPRECATED_FRAME_INIT_SAVED_REGS */
 #if !defined (DEPRECATED_FRAME_INIT_SAVED_REGS_P)
index 3835ac0b940b78bed4509cba86910f5248993f91..8e1c0a44482a9d867e248cae48262825b87db714 100755 (executable)
@@ -593,19 +593,33 @@ f:2:POINTER_TO_ADDRESS:CORE_ADDR:pointer_to_address:struct type *type, const voi
 f:2:ADDRESS_TO_POINTER:void:address_to_pointer:struct type *type, void *buf, CORE_ADDR addr:type, buf, addr:::unsigned_address_to_pointer::0
 F:2:INTEGER_TO_ADDRESS:CORE_ADDR:integer_to_address:struct type *type, void *buf:type, buf
 #
-f:2:RETURN_VALUE_ON_STACK:int:return_value_on_stack:struct type *type:type:::generic_return_value_on_stack_not::0
 F:2:DEPRECATED_POP_FRAME:void:deprecated_pop_frame:void:-
 # NOTE: cagney/2003-03-24: Replaced by PUSH_ARGUMENTS.
 F:2:DEPRECATED_STORE_STRUCT_RETURN:void:deprecated_store_struct_return:CORE_ADDR addr, CORE_ADDR sp:addr, sp
-#
+
+# It has been suggested that this, well actually its predecessor,
+# should take the type/value of the function to be called and not the
+# return type.  This is left as an exercise for the reader.
+
+M:::enum return_value_convention:return_value:struct type *valtype, struct regcache *regcache, const void *inval, void *outval:valtype, regcache, inval, outval
+
+# The deprecated methods RETURN_VALUE_ON_STACK, EXTRACT_RETURN_VALUE,
+# STORE_RETURN_VALUE and USE_STRUCT_CONVENTION have all been folded
+# into RETURN_VALUE.  For the moment do not try to fold in
+# EXTRACT_STRUCT_VALUE_ADDRESS as, dependant on the ABI, the debug
+# info, and the level of effort, it may well be possible to find the
+# address of a structure being return on the stack.  Someone else can
+# make that change.
+
+f:2:RETURN_VALUE_ON_STACK:int:return_value_on_stack:struct type *type:type:::generic_return_value_on_stack_not::0
 f:2:EXTRACT_RETURN_VALUE:void:extract_return_value:struct type *type, struct regcache *regcache, void *valbuf:type, regcache, valbuf:::legacy_extract_return_value::0
 f:2:STORE_RETURN_VALUE:void:store_return_value:struct type *type, struct regcache *regcache, const void *valbuf:type, regcache, valbuf:::legacy_store_return_value::0
 f:2:DEPRECATED_EXTRACT_RETURN_VALUE:void:deprecated_extract_return_value:struct type *type, char *regbuf, char *valbuf:type, regbuf, valbuf
 f:2:DEPRECATED_STORE_RETURN_VALUE:void:deprecated_store_return_value:struct type *type, char *valbuf:type, valbuf
-#
+f:2:USE_STRUCT_CONVENTION:int:use_struct_convention:int gcc_p, struct type *value_type:gcc_p, value_type:::generic_use_struct_convention::0
+
 F:2:EXTRACT_STRUCT_VALUE_ADDRESS:CORE_ADDR:extract_struct_value_address:struct regcache *regcache:regcache
 F:2:DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS:CORE_ADDR:deprecated_extract_struct_value_address:char *regbuf:regbuf
-f:2:USE_STRUCT_CONVENTION:int:use_struct_convention:int gcc_p, struct type *value_type:gcc_p, value_type:::generic_use_struct_convention::0
 #
 F:2:DEPRECATED_FRAME_INIT_SAVED_REGS:void:deprecated_frame_init_saved_regs:struct frame_info *frame:frame
 F:2:DEPRECATED_INIT_EXTRA_FRAME_INFO:void:deprecated_init_extra_frame_info:int fromleaf, struct frame_info *frame:fromleaf, frame
index 60ebbea9ee2de91f43e26fca997e55094546a3d3..9287f031e98469924594df32410f3352ff3b3f33 100644 (file)
@@ -44,6 +44,7 @@
 #include "reggroups.h"
 #include "block.h"
 #include <ctype.h>
+#include "gdb_assert.h"
 
 /* Functions exported for general use, in inferior.h: */
 
@@ -1079,25 +1080,34 @@ print_return_value (int structure_return, struct type *value_type)
       ui_out_field_stream (uiout, "return-value", stb);
       ui_out_text (uiout, "\n");
     }
-  else
-    {
-      /* FIXME: 2003-09-27: When returning from a nested inferior
-         function call, it's possible (with no help from the
-         architecture vector) to locate and return/print a "struct
-         return" value.  This is just a more complicated case of what
-         is already being done in in the inferior function call code.
-         In fact, when inferior function calls are made async, this
-         will likely be made the norm.  */
-      /* We cannot determine the contents of the structure because
-        it is on the stack, and we don't know where, since we did not
-        initiate the call, as opposed to the call_function_by_hand case */
+  /* FIXME: 2003-09-27: When returning from a nested inferior function
+     call, it's possible (with no help from the architecture vector)
+     to locate and return/print a "struct return" value.  This is just
+     a more complicated case of what is already being done in in the
+     inferior function call code.  In fact, when inferior function
+     calls are made async, this will likely be made the norm.  */
 #ifdef DEPRECATED_VALUE_RETURNED_FROM_STACK
-      value = 0;
+#define DEPRECATED_VALUE_RETURNED_FROM_STACK_P 1
+#else
+#define DEPRECATED_VALUE_RETURNED_FROM_STACK_P 0
+#endif
+  else if (gdbarch_return_value_p (current_gdbarch)
+          || DEPRECATED_VALUE_RETURNED_FROM_STACK_P)
+    /* We cannot determine the contents of the structure because it is
+       on the stack, and we don't know where, since we did not
+       initiate the call, as opposed to the call_function_by_hand
+       case.  */
+    {
+      gdb_assert (gdbarch_return_value (current_gdbarch, value_type, NULL, NULL, NULL)
+                 == RETURN_VALUE_STRUCT_CONVENTION);
       ui_out_text (uiout, "Value returned has type: ");
       ui_out_field_string (uiout, "return-type", TYPE_NAME (value_type));
       ui_out_text (uiout, ".");
       ui_out_text (uiout, " Cannot determine contents\n");
-#else
+      return;
+    }
+  else
+    {
       if (EXTRACT_STRUCT_VALUE_ADDRESS_P ())
        {
          CORE_ADDR addr = EXTRACT_STRUCT_VALUE_ADDRESS (stop_registers);
@@ -1133,7 +1143,6 @@ print_return_value (int structure_return, struct type *value_type)
       value_print (value, stb->stream, 0, Val_no_prettyprint);
       ui_out_field_stream (uiout, "return-value", stb);
       ui_out_text (uiout, "\n");
-#endif
     }
 }
 
index 8091c2f56c2907ad2a6b9454585093bbe85c0dd0..0fb0d6a6c9593e31741a4db7b2558e4d611e31fd 100644 (file)
@@ -305,21 +305,6 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   return sp;
 }
 
-/* Potential ways that a function can return a value of a given type.  */
-enum return_value_convention
-{
-  /* Where the return value has been squeezed into one or more
-     registers.  */
-  RETURN_VALUE_REGISTER_CONVENTION,
-  /* Commonly known as the "struct return convention".  The caller
-     passes an additional hidden first parameter to the caller.  That
-     parameter contains the address at which the value being returned
-     should be stored.  While typically, and historically, used for
-     large structs, this is convention is applied to values of many
-     different types.  */
-  RETURN_VALUE_STRUCT_CONVENTION
-};
-
 /* Handle the return-value conventions specified by the SysV 32-bit
    PowerPC ABI (including all the supplements):
 
index 3b1bca8a7860c72bd5a681a1dd6a60200862eebb..da5c18022d6a5bdd3acee6d6851c08ba9f45ff46 100644 (file)
@@ -1202,25 +1202,48 @@ value_from_double (struct type *type, DOUBLEST num)
   return val;
 }
 \f
-/* Deal with the value that is "about to be returned".
+/* Deal with the return-value of a function that has "just returned".
 
-   Return the value that a function, using the register convention,
-   returning now would be returning to its caller, assuming its type
-   is VALTYPE.  RETBUF is where we look for what ought to be the
-   contents of the registers (in raw form).  This is because it is
-   often desirable to restore old values to those registers after
-   saving the contents of interest, and then call this function using
-   the saved values.  */
+   Extract the return-value (as a "struct value") that a function,
+   using register convention, has just returned to its caller.  Assume
+   that the type of the function is VALTYPE, and that the "just
+   returned" register state is found in RETBUF.
+
+   The function has "just returned" because GDB halts a returning
+   function by setting a breakpoint at the return address (in the
+   caller), and not the return instruction (in the callee).
+
+   Because, in the case of a return from an inferior function call,
+   GDB needs to restore the inferiors registers, RETBUF is normally a
+   copy of the inferior's registers.  */
 
 struct value *
 register_value_being_returned (struct type *valtype, struct regcache *retbuf)
 {
   struct value *val = allocate_value (valtype);
-  CHECK_TYPEDEF (valtype);
+
   /* If the function returns void, don't bother fetching the return
      value.  */
-  if (TYPE_CODE (valtype) != TYPE_CODE_VOID)
-    EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS_RAW (val));
+  if (TYPE_CODE (valtype) == TYPE_CODE_VOID)
+    return val;
+
+  if (!gdbarch_return_value_p (current_gdbarch))
+    {
+      /* NOTE: cagney/2003-10-20: Unlike "gdbarch_return_value", the
+         EXTRACT_RETURN_VALUE and USE_STRUCT_CONVENTION methods do not
+         handle the edge case of a function returning a small
+         structure / union in registers.  */
+      CHECK_TYPEDEF (valtype);
+      EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS_RAW (val));
+      return val;
+    }
+
+  /* This function only handles "register convention".  */
+  gdb_assert (gdbarch_return_value (current_gdbarch, valtype,
+                                   NULL, NULL, NULL)
+             == RETURN_VALUE_REGISTER_CONVENTION);
+  gdbarch_return_value (current_gdbarch, valtype, retbuf,
+                       NULL, VALUE_CONTENTS_RAW (val));
   return val;
 }
 
@@ -1262,13 +1285,25 @@ using_struct_return (struct type *value_type, int gcc_p)
   if (code == TYPE_CODE_ERROR)
     error ("Function return type unknown.");
 
-  if (code == TYPE_CODE_STRUCT
-      || code == TYPE_CODE_UNION
-      || code == TYPE_CODE_ARRAY
-      || RETURN_VALUE_ON_STACK (value_type))
-    return USE_STRUCT_CONVENTION (gcc_p, value_type);
+  if (!gdbarch_return_value_p (current_gdbarch))
+    {
+      /* FIXME: cagney/2003-10-01: The below is dead.  Instead an
+        architecture should implement "gdbarch_return_value".  Using
+        that new function it is possible to exactly specify the ABIs
+        "struct return" vs "register return" conventions.  */
+      if (code == TYPE_CODE_STRUCT
+         || code == TYPE_CODE_UNION
+         || code == TYPE_CODE_ARRAY
+         || RETURN_VALUE_ON_STACK (value_type))
+       return USE_STRUCT_CONVENTION (gcc_p, value_type);
+      else
+       return 0;
+    }
 
-  return 0;
+  /* Probe the architecture for the return-value convention.  */
+  return (gdbarch_return_value (current_gdbarch, value_type,
+                               NULL, NULL, NULL)
+         == RETURN_VALUE_STRUCT_CONVENTION);
 }
 
 /* Store VAL so it will be returned if a function returns now.
@@ -1284,9 +1319,41 @@ set_return_value (struct value *val)
   if (code == TYPE_CODE_ERROR)
     error ("Function return type unknown.");
 
+  if (gdbarch_return_value_p (current_gdbarch))
+    {
+      switch (gdbarch_return_value (current_gdbarch, type, NULL, NULL, NULL))
+       {
+       case RETURN_VALUE_REGISTER_CONVENTION:
+         /* Success.  The architecture can deal with it, write it to
+             the regcache.  */
+         gdbarch_return_value (current_gdbarch, type, current_regcache,
+                               VALUE_CONTENTS (val), NULL);
+         return;
+       case RETURN_VALUE_STRUCT_CONVENTION:
+         /* Failure.  For the moment, assume that it is not possible
+             to find the location, on the stack, at which the "struct
+             return" value should be stored.  Only a warning because
+             an error aborts the "return" command leaving GDB in a
+             weird state.  */
+         warning ("Location of return value unknown");
+         return;
+       }
+    }
+
+
   if (code == TYPE_CODE_STRUCT
       || code == TYPE_CODE_UNION)      /* FIXME, implement struct return.  */
-    error ("GDB does not support specifying a struct or union return value.");
+    /* FIXME: cagney/2003-10-20: This should be an internal-warning.
+       The problem is that while GDB's core supports "struct return"
+       using "register convention", many architectures haven't been
+       updated to implement the mechanisms needed to make it work.
+       It's a warning, and not an error, as otherwize it will jump out
+       of the "return" command leaving both GDB and the user in a very
+       confused state.  */
+    {
+      warning ("This architecture does not support specifying a struct or union return-value.");
+      return;
+    }
 
   STORE_RETURN_VALUE (type, current_regcache, VALUE_CONTENTS (val));
 }