From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5430 invoked by alias); 5 Feb 2013 01:03:05 -0000 Received: (qmail 5421 invoked by uid 22791); 5 Feb 2013 01:03:03 -0000 X-SWARE-Spam-Status: No, hits=-3.0 required=5.0 tests=AWL,BAYES_00,KHOP_THREADED,TW_EG X-Spam-Check-By: sourceware.org Received: from shards.monkeyblade.net (HELO shards.monkeyblade.net) (149.20.54.216) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 05 Feb 2013 01:02:59 +0000 Received: from localhost (cpe-66-108-118-205.nyc.res.rr.com [66.108.118.205]) (Authenticated sender: davem-davemloft) by shards.monkeyblade.net (Postfix) with ESMTPSA id EB243585E4A; Mon, 4 Feb 2013 17:03:01 -0800 (PST) Date: Tue, 05 Feb 2013 01:03:00 -0000 Message-Id: <20130204.200254.1810401167797646953.davem@davemloft.net> To: mark.kettenis@xs4all.nl Cc: gdb-patches@sourceware.org Subject: Re: [PATCH] Allow struct 'return' on 32-bit sparc. From: David Miller In-Reply-To: <201302042357.r14NvFNC023715@glazunov.sibelius.xs4all.nl> References: <20130201.161300.1158114789368969492.davem@davemloft.net> <201302042357.r14NvFNC023715@glazunov.sibelius.xs4all.nl> Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-IsSubscribed: yes 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: 2013-02/txt/msg00105.txt.bz2 From: Mark Kettenis Date: Tue, 5 Feb 2013 00:57:15 +0100 (CET) > The sparc-tdep.c bits are correct as far as I can see. > > I think it would be better if your new function would still have > "struct_return" in its name. My suggestion would be > "struct_return_convention". > > Also, ... > Return RETURN_VALUE_REGISTER_CONVENTION if there is nothing to return > seems to be a bit odd. But since convention_for_return() is never > called with code being TYPE_CODE (there is an explicit check for that > in stack.c:return_command()) you could simply leave the check in > using_struct_return(). Agreed on all counts, thanks for the feedback. Here is the updated patch: gdb/ * sparc-tdep.c (sparc32_return_value): Handle writing return value when using RETURN_VALUE_ABI_PRESERVES_ADDRESS. * value.c (struct_return_convention): New function. (using_struct_return): Implement in terms of struct_return_convention. * value.h (struct_return_convention): Declare. * stack.c (return_command): Allow successful overriding of the return value when RETURN_VALUE_ABI_PRESERVES_ADDRESS. diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index 3ae7395..2b38521 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -1370,15 +1370,21 @@ sparc32_return_value (struct gdbarch *gdbarch, struct value *function, if (sparc_structure_or_union_p (type) || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16)) { + ULONGEST sp; + CORE_ADDR addr; + if (readbuf) { - ULONGEST sp; - CORE_ADDR addr; - regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp); addr = read_memory_unsigned_integer (sp + 64, 4, byte_order); read_memory (addr, readbuf, TYPE_LENGTH (type)); } + if (writebuf) + { + regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp); + addr = read_memory_unsigned_integer (sp + 64, 4, byte_order); + write_memory (addr, writebuf, TYPE_LENGTH (type)); + } return RETURN_VALUE_ABI_PRESERVES_ADDRESS; } diff --git a/gdb/stack.c b/gdb/stack.c index c8a6a7e..218fc01 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -2274,6 +2274,7 @@ down_command (char *count_exp, int from_tty) void return_command (char *retval_exp, int from_tty) { + enum return_value_convention rv_conv; struct frame_info *thisframe; struct gdbarch *gdbarch; struct symbol *thisfun; @@ -2327,6 +2328,7 @@ return_command (char *retval_exp, int from_tty) if (thisfun != NULL) function = read_var_value (thisfun, thisframe); + rv_conv = RETURN_VALUE_REGISTER_CONVENTION; if (TYPE_CODE (return_type) == TYPE_CODE_VOID) /* If the return-type is "void", don't try to find the return-value's location. However, do still evaluate the @@ -2334,14 +2336,18 @@ return_command (char *retval_exp, int from_tty) is discarded, side effects such as "return i++" still occur. */ return_value = NULL; - else if (thisfun != NULL - && using_struct_return (gdbarch, function, return_type)) + else if (thisfun != NULL) { - query_prefix = "The location at which to store the " - "function's return value is unknown.\n" - "If you continue, the return value " - "that you specified will be ignored.\n"; - return_value = NULL; + rv_conv = struct_return_convention (gdbarch, function, return_type); + if (rv_conv == RETURN_VALUE_STRUCT_CONVENTION + || rv_conv == RETURN_VALUE_ABI_RETURNS_ADDRESS) + { + query_prefix = "The location at which to store the " + "function's return value is unknown.\n" + "If you continue, the return value " + "that you specified will be ignored.\n"; + return_value = NULL; + } } } @@ -2371,9 +2377,8 @@ return_command (char *retval_exp, int from_tty) struct type *return_type = value_type (return_value); struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ()); - gdb_assert (gdbarch_return_value (gdbarch, function, return_type, NULL, - NULL, NULL) - == RETURN_VALUE_REGISTER_CONVENTION); + gdb_assert (rv_conv != RETURN_VALUE_STRUCT_CONVENTION + && rv_conv != RETURN_VALUE_ABI_RETURNS_ADDRESS); gdbarch_return_value (gdbarch, function, return_type, get_current_regcache (), NULL /*read*/, value_contents (return_value) /*write*/); diff --git a/gdb/value.c b/gdb/value.c index dbf1c37..4b70ece 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -3323,6 +3323,23 @@ coerce_array (struct value *arg) } +/* Return the return value convention that will be used for the + specified type. */ + +enum return_value_convention +struct_return_convention (struct gdbarch *gdbarch, + struct value *function, struct type *value_type) +{ + enum type_code code = TYPE_CODE (value_type); + + if (code == TYPE_CODE_ERROR) + error (_("Function return type unknown.")); + + /* Probe the architecture for the return-value convention. */ + return gdbarch_return_value (gdbarch, function, value_type, + NULL, NULL, NULL); +} + /* Return true if the function returning the specified type is using the convention of returning structures in memory (passing in the address as a hidden first parameter). */ @@ -3331,19 +3348,12 @@ int using_struct_return (struct gdbarch *gdbarch, struct value *function, struct type *value_type) { - enum type_code code = TYPE_CODE (value_type); - - if (code == TYPE_CODE_ERROR) - error (_("Function return type unknown.")); - - if (code == TYPE_CODE_VOID) + if (TYPE_CODE (value_type) == TYPE_CODE_VOID) /* A void return value is never in memory. See also corresponding code in "print_return_value". */ return 0; - /* Probe the architecture for the return-value convention. */ - return (gdbarch_return_value (gdbarch, function, value_type, - NULL, NULL, NULL) + return (struct_return_convention (gdbarch, function, value_type) != RETURN_VALUE_REGISTER_CONVENTION); } diff --git a/gdb/value.h b/gdb/value.h index b9013fd..c10c3ec 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -696,6 +696,10 @@ extern int value_in (struct value *element, struct value *set); extern int value_bit_index (struct type *type, const gdb_byte *addr, int index); +extern enum return_value_convention +struct_return_convention (struct gdbarch *gdbarch, struct value *function, + struct type *value_type); + extern int using_struct_return (struct gdbarch *gdbarch, struct value *function, struct type *value_type);