This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: m68k-elf return value registers
- From: Vladimir Prus <vladimir at codesourcery dot com>
- To: Mark Kettenis <mark dot kettenis at xs4all dot nl>
- Cc: gdb-patches at sources dot redhat dot com
- Date: Tue, 26 Apr 2011 15:50:27 +0400
- Subject: Re: m68k-elf return value registers
- References: <201101140157.38487.vladimir@codesourcery.com> <201101141037.p0EAbFFA023135@glazunov.sibelius.xs4all.nl> <201101251949.15840.vladimir@codesourcery.com>
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