This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Make i386 target use return_value


This makes the results from Andrew's new structs.exp a bit more
reasonable on the i386 target.  I'll look into AMD64 if I can't find
the time, but it needs some real work, and I don't know if I can find
the time in the coming week.

Committed,

Mark

Index: ChangeLog
from  Mark Kettenis  <kettenis@gnu.org>

	* i386-tdep.c (i386_extract_return_value,
	i386_store_return_value): Add gdbarch argument.  Use it instead of
	determining it from REGCACHE.  Remove recursive call for
	structures with a single member.
	(i386_use_struct_convention): Remove.
	(i386_reg_struct_return_p): New function.
	(i386_return_value): New function.
	(i386_gdbarch_init): Set return_value, don't set
	extract_return_value, store_return_value and
	use_struct_convention.
	* x86-64-tdep.c (x86_64_init_abi): Set return_value to NULL.

Index: i386-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.c,v
retrieving revision 1.176
diff -u -p -r1.176 i386-tdep.c
--- i386-tdep.c 16 Nov 2003 15:07:00 -0000 1.176
+++ i386-tdep.c 20 Nov 2003 22:33:02 -0000
@@ -1151,25 +1151,17 @@ i386_push_dummy_call (struct gdbarch *gd
 #define LOW_RETURN_REGNUM	I386_EAX_REGNUM /* %eax */
 #define HIGH_RETURN_REGNUM	I386_EDX_REGNUM /* %edx */
 
-/* Extract from an array REGBUF containing the (raw) register state, a
-   function return value of TYPE, and copy that, in virtual format,
-   into VALBUF.  */
+/* Read, for architecture GDBARCH, a function return value of TYPE
+   from REGCACHE, and copy that into VALBUF.  */
 
 static void
-i386_extract_return_value (struct type *type, struct regcache *regcache,
-			   void *valbuf)
+i386_extract_return_value (struct gdbarch *gdbarch, struct type *type,
+			   struct regcache *regcache, void *valbuf)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int len = TYPE_LENGTH (type);
   char buf[I386_MAX_REGISTER_SIZE];
 
-  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
-      && TYPE_NFIELDS (type) == 1)
-    {
-      i386_extract_return_value (TYPE_FIELD_TYPE (type, 0), regcache, valbuf);
-      return;
-    }
-
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
     {
       if (tdep->st0_regnum < 0)
@@ -1209,27 +1201,20 @@ i386_extract_return_value (struct type *
     }
 }
 
-/* Write into the appropriate registers a function return value stored
-   in VALBUF of type TYPE, given in virtual format.  */
+/* Write, for architecture GDBARCH, a function return value of TYPE
+   from VALBUF into REGCACHE.  */
 
 static void
-i386_store_return_value (struct type *type, struct regcache *regcache,
-			 const void *valbuf)
+i386_store_return_value (struct gdbarch *gdbarch, struct type *type,
+			 struct regcache *regcache, const void *valbuf)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int len = TYPE_LENGTH (type);
 
   /* Define I387_ST0_REGNUM such that we use the proper definitions
      for the architecture.  */
 #define I387_ST0_REGNUM I386_ST0_REGNUM
 
-  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
-      && TYPE_NFIELDS (type) == 1)
-    {
-      i386_store_return_value (TYPE_FIELD_TYPE (type, 0), regcache, valbuf);
-      return;
-    }
-
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
     {
       ULONGEST fstat;
@@ -1314,20 +1299,62 @@ static const char *valid_conventions[] =
 };
 static const char *struct_convention = default_struct_convention;
 
+/* Return non-zero if TYPE, which is assumed to be a structure or
+   union type, should be returned in registers for architecture
+   GDBARCH.  */
+
 static int
-i386_use_struct_convention (int gcc_p, struct type *type)
+i386_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type)
 {
-  enum struct_return struct_return;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum type_code code = TYPE_CODE (type);
+  int len = TYPE_LENGTH (type);
 
-  if (struct_convention == default_struct_convention)
-    struct_return = gdbarch_tdep (current_gdbarch)->struct_return;
-  else if (struct_convention == pcc_struct_convention)
-    struct_return = pcc_struct_return;
-  else
-    struct_return = reg_struct_return;
+  gdb_assert (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION);
+
+  if (struct_convention == pcc_struct_convention
+      || (struct_convention == default_struct_convention
+	  && tdep->struct_return == pcc_struct_return))
+    return 0;
+
+  return (len == 1 || len == 2 || len == 4 || len == 8);
+}
+
+/* Determine, for architecture GDBARCH, how a return value of TYPE
+   should be returned.  If it is supposed to be returned in registers,
+   and READBUF is non-zero, read the appropriate value from REGCACHE,
+   and copy it into READBUF.  If WRITEBUF is non-zero, write the value
+   from WRITEBUF into REGCACHE.  */
+
+static enum return_value_convention
+i386_return_value (struct gdbarch *gdbarch, struct type *type,
+		   struct regcache *regcache, void *readbuf,
+		   const void *writebuf)
+{
+  enum type_code code = TYPE_CODE (type);
+
+  if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
+      && !i386_reg_struct_return_p (gdbarch, type))
+    return RETURN_VALUE_STRUCT_CONVENTION;
+
+  /* This special case is for structures consisting of a single
+     `float' or `double' member.  These structures are returned in
+     %st(0).  For these structures, we call ourselves recursively,
+     changing TYPE into the type of the first member of the structure.
+     Since that should work for all structures that have only one
+     member, we don't bother to check the member's type here.  */
+  if (code == TYPE_CODE_STRUCT && TYPE_NFIELDS (type) == 1)
+    {
+      type = check_typedef (TYPE_FIELD_TYPE (type, 0));
+      return i386_return_value (gdbarch, type, regcache, readbuf, writebuf);
+    }
+
+  if (readbuf)
+    i386_extract_return_value (gdbarch, type, regcache, readbuf);
+  if (writebuf)
+    i386_store_return_value (gdbarch, type, regcache, writebuf);
 
-  return generic_use_struct_convention (struct_return == reg_struct_return,
-					type);
+  return RETURN_VALUE_REGISTER_CONVENTION;
 }
 
 
@@ -1963,11 +1990,9 @@ i386_gdbarch_init (struct gdbarch_info i
   set_gdbarch_register_to_value (gdbarch,  i386_register_to_value);
   set_gdbarch_value_to_register (gdbarch, i386_value_to_register);
 
-  set_gdbarch_extract_return_value (gdbarch, i386_extract_return_value);
-  set_gdbarch_store_return_value (gdbarch, i386_store_return_value);
+  set_gdbarch_return_value (gdbarch, i386_return_value);
   set_gdbarch_extract_struct_value_address (gdbarch,
 					    i386_extract_struct_value_address);
-  set_gdbarch_use_struct_convention (gdbarch, i386_use_struct_convention);
 
   set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue);
 
Index: x86-64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-tdep.c,v
retrieving revision 1.101
diff -u -p -r1.101 x86-64-tdep.c
--- x86-64-tdep.c 26 Oct 2003 14:47:26 -0000 1.101
+++ x86-64-tdep.c 20 Nov 2003 22:33:02 -0000
@@ -1300,6 +1300,7 @@ x86_64_init_abi (struct gdbarch_info inf
   set_gdbarch_register_to_value (gdbarch, i387_register_to_value);
   set_gdbarch_value_to_register (gdbarch, i387_value_to_register);
 
+  set_gdbarch_return_value (gdbarch, NULL);
   set_gdbarch_extract_return_value (gdbarch, x86_64_extract_return_value);
   set_gdbarch_store_return_value (gdbarch, x86_64_store_return_value);
   /* Override, since this is handled by x86_64_extract_return_value.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]