From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 444 invoked by alias); 26 Apr 2011 11:50:47 -0000 Received: (qmail 432 invoked by uid 22791); 26 Apr 2011 11:50:46 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL,BAYES_00,SPF_FAIL,TW_EG X-Spam-Check-By: sourceware.org Received: from gate.lvk.cs.msu.su (HELO mail.lvk.cs.msu.su) (158.250.17.1) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 26 Apr 2011 11:50:32 +0000 Received: from mail.lvk.cs.msu.su (localhost [127.0.0.1]) by mail.lvk.cs.msu.su (Postfix) with ESMTP id 71A0A179A1; Tue, 26 Apr 2011 15:50:28 +0400 (MSD) X-Spam-ASN: Received: from thunder.localnet (gate.lvknet [192.168.128.254]) by mail.lvk.cs.msu.su (Postfix) with ESMTPSA id 62AFD133A5; Tue, 26 Apr 2011 15:50:28 +0400 (MSD) From: Vladimir Prus To: Mark Kettenis Subject: Re: m68k-elf return value registers Date: Tue, 26 Apr 2011 11:50:00 -0000 User-Agent: KMail/1.13.5 (Linux/2.6.35-28-generic-pae; KDE/4.6.2; i686; ; ) Cc: gdb-patches@sources.redhat.com References: <201101140157.38487.vladimir@codesourcery.com> <201101141037.p0EAbFFA023135@glazunov.sibelius.xs4all.nl> <201101251949.15840.vladimir@codesourcery.com> In-Reply-To: <201101251949.15840.vladimir@codesourcery.com> MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_DGrtNaG9fgEYxin" Message-Id: <201104261550.27639.vladimir@codesourcery.com> X-AV-Checked: ClamAV using ClamSMTP Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-04/txt/msg00473.txt.bz2 --Boundary-00=_DGrtNaG9fgEYxin Content-Type: Text/Plain; charset="iso-8859-6" Content-Transfer-Encoding: 7bit Content-length: 293 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 --Boundary-00=_DGrtNaG9fgEYxin Content-Type: text/x-patch; charset="UTF-8"; name="is_using_register_for_struct_return.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="is_using_register_for_struct_return.diff" Content-length: 4279 commit 46907f38a4f2d3fadf755aad647fb089d32ad6cb Author: Vladimir Prus 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 --Boundary-00=_DGrtNaG9fgEYxin--