This is the mail archive of the gdb-patches@sourceware.org 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]

Re: m68k-elf return value registers


On Tuesday, January 25, 2011 19:49:15 Vladimir Prus wrote:

> How about this split:
> 
> - Register used to return structures
> - Logic used to decide whether a structure is returned in register

Here's a patch for this aspect.

- Volodya

-- 
Vladimir Prus
Mentor Graphics
+7 (812) 677-68-40
commit 46907f38a4f2d3fadf755aad647fb089d32ad6cb
Author: Vladimir Prus <vladimir@codesourcery.com>
Date:   Tue Apr 26 15:47:50 2011 +0400

    Adjust "is register used for struct returns" logic to what GCC does.
    
        	* m68k-tdep.c (m68k_reg_struct_return_r): New, broken out of ...
        	(m68k_reg_struct_return_p): ... here.  Implement gcc's structure
        	mode algorithm.
    	(m68k_svr4_return_value): Adjust to gcc behaviour.

diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c
index c6ae36d..736bf5b 100644
--- a/gdb/m68k-tdep.c
+++ b/gdb/m68k-tdep.c
@@ -378,6 +378,70 @@ m68k_svr4_store_return_value (struct type *type, struct regcache *regcache,
 
 /* Return non-zero if TYPE, which is assumed to be a structure or
    union type, should be returned in registers for architecture
+   GDBARCH.
+
+   Unfortunately GCC incorrectly implements this optimization.  Rather
+   than simply return all small structs, or even just those of size
+   2^N, it uses the mode of the structure to determine this.  BLKmode
+   structs will be returned by memory and QI,HI,SI,DI,SF&DF mode
+   structs will be returned by register.  For m68k a struct is BLKmode
+   unless it's size is 2^N and the mode for that size does not need a
+   greater alignment than the structure itself.  This is horrible.  */
+
+
+static int
+m68k_reg_struct_return_r (struct type *type, int *align_p)
+{
+  enum type_code code = TYPE_CODE (type);
+  int len = TYPE_LENGTH (type);
+  int field_align = 1;
+  int my_align = len > 2 ? 2 : len;
+  int ix;
+
+  if (code != TYPE_CODE_STRUCT && code != TYPE_CODE_UNION)
+    {
+      if (align_p && my_align > *align_p)
+	*align_p = my_align;
+      return 1;
+    }
+
+  if ((len & -len) != len)
+    /* Length is not 2^n. */
+    return 0;
+
+  for (ix = 0; ix != TYPE_NFIELDS (type); ix++)
+    {
+      struct type *field_type;
+      int field_len;
+
+      if (field_is_static (&TYPE_FIELD (type, ix)))
+	/* Skip static fields.  */
+	continue;
+
+      field_type = TYPE_FIELD_TYPE (type, ix);
+      field_type = check_typedef (field_type);
+      field_len = TYPE_LENGTH (field_type);
+
+      /* Look through arrays.  */
+      while (TYPE_CODE (field_type) == TYPE_CODE_ARRAY)
+	{
+	  field_type = TYPE_TARGET_TYPE (field_type);
+	  field_type = check_typedef (field_type);
+	  field_len = TYPE_LENGTH (field_type);
+	}
+
+      if (!m68k_reg_struct_return_r (field_type, &field_align))
+	return 0;
+    }
+
+  if (align_p && field_align > *align_p)
+    *align_p = field_align;
+
+  return align_p || my_align <= field_align;
+}
+
+/* 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
@@ -392,7 +456,11 @@ m68k_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type)
   if (tdep->struct_return == pcc_struct_return)
     return 0;
 
-  return (len == 1 || len == 2 || len == 4 || len == 8);
+  if (len > 8)
+    /* Length is too big. */
+    return 0;
+
+  return m68k_reg_struct_return_r (type, NULL);
 }
 
 /* Determine, for architecture GDBARCH, how a return value of TYPE
@@ -446,25 +514,11 @@ m68k_svr4_return_value (struct gdbarch *gdbarch, struct type *func_type,
   if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
       && !m68k_reg_struct_return_p (gdbarch, type))
     {
-      /* The System V ABI says that:
-
-	 "A function returning a structure or union also sets %a0 to
-	 the value it finds in %a0.  Thus when the caller receives
-	 control again, the address of the returned object resides in
-	 register %a0."
-
-	 So the ABI guarantees that we can always find the return
-	 value just after the function has returned.  */
-
-      if (readbuf)
-	{
-	  ULONGEST addr;
-
-	  regcache_raw_read_unsigned (regcache, M68K_A0_REGNUM, &addr);
-	  read_memory (addr, readbuf, TYPE_LENGTH (type));
-	}
-
-      return RETURN_VALUE_ABI_RETURNS_ADDRESS;
+      /* Although they SYSV ABI specifies that a function returning a
+	 structure this way should preserve %a0, GCC doesn't do that.
+	 Furthermore there's no point changeing GCC to make it do it,
+	 as that would just be bloat. */
+      return RETURN_VALUE_STRUCT_CONVENTION;
     }
 
   /* This special case is for structures consisting of a single

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