Allow struct 'return' on 32-bit sparc.
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.
This commit is contained in:
parent
bc9abe4a91
commit
bbfdfe1c57
5 changed files with 57 additions and 22 deletions
|
@ -1,3 +1,13 @@
|
||||||
|
2013-02-06 David S. Miller <davem@davemloft.net>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
2013-02-06 Tom Tromey <tromey@redhat.com>
|
2013-02-06 Tom Tromey <tromey@redhat.com>
|
||||||
|
|
||||||
* python/py-type.c (typy_strip_typedefs): Don't call check_typedef
|
* python/py-type.c (typy_strip_typedefs): Don't call check_typedef
|
||||||
|
|
|
@ -1369,16 +1369,22 @@ sparc32_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||||
|
|
||||||
if (sparc_structure_or_union_p (type)
|
if (sparc_structure_or_union_p (type)
|
||||||
|| (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
|
|| (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
|
||||||
{
|
|
||||||
if (readbuf)
|
|
||||||
{
|
{
|
||||||
ULONGEST sp;
|
ULONGEST sp;
|
||||||
CORE_ADDR addr;
|
CORE_ADDR addr;
|
||||||
|
|
||||||
|
if (readbuf)
|
||||||
|
{
|
||||||
regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
|
regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
|
||||||
addr = read_memory_unsigned_integer (sp + 64, 4, byte_order);
|
addr = read_memory_unsigned_integer (sp + 64, 4, byte_order);
|
||||||
read_memory (addr, readbuf, TYPE_LENGTH (type));
|
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;
|
return RETURN_VALUE_ABI_PRESERVES_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
15
gdb/stack.c
15
gdb/stack.c
|
@ -2278,6 +2278,7 @@ down_command (char *count_exp, int from_tty)
|
||||||
void
|
void
|
||||||
return_command (char *retval_exp, int from_tty)
|
return_command (char *retval_exp, int from_tty)
|
||||||
{
|
{
|
||||||
|
enum return_value_convention rv_conv;
|
||||||
struct frame_info *thisframe;
|
struct frame_info *thisframe;
|
||||||
struct gdbarch *gdbarch;
|
struct gdbarch *gdbarch;
|
||||||
struct symbol *thisfun;
|
struct symbol *thisfun;
|
||||||
|
@ -2331,6 +2332,7 @@ return_command (char *retval_exp, int from_tty)
|
||||||
if (thisfun != NULL)
|
if (thisfun != NULL)
|
||||||
function = read_var_value (thisfun, thisframe);
|
function = read_var_value (thisfun, thisframe);
|
||||||
|
|
||||||
|
rv_conv = RETURN_VALUE_REGISTER_CONVENTION;
|
||||||
if (TYPE_CODE (return_type) == TYPE_CODE_VOID)
|
if (TYPE_CODE (return_type) == TYPE_CODE_VOID)
|
||||||
/* If the return-type is "void", don't try to find the
|
/* If the return-type is "void", don't try to find the
|
||||||
return-value's location. However, do still evaluate the
|
return-value's location. However, do still evaluate the
|
||||||
|
@ -2338,8 +2340,11 @@ return_command (char *retval_exp, int from_tty)
|
||||||
is discarded, side effects such as "return i++" still
|
is discarded, side effects such as "return i++" still
|
||||||
occur. */
|
occur. */
|
||||||
return_value = NULL;
|
return_value = NULL;
|
||||||
else if (thisfun != NULL
|
else if (thisfun != NULL)
|
||||||
&& using_struct_return (gdbarch, function, return_type))
|
{
|
||||||
|
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 "
|
query_prefix = "The location at which to store the "
|
||||||
"function's return value is unknown.\n"
|
"function's return value is unknown.\n"
|
||||||
|
@ -2348,6 +2353,7 @@ return_command (char *retval_exp, int from_tty)
|
||||||
return_value = NULL;
|
return_value = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Does an interactive user really want to do this? Include
|
/* Does an interactive user really want to do this? Include
|
||||||
information, such as how well GDB can handle the return value, in
|
information, such as how well GDB can handle the return value, in
|
||||||
|
@ -2375,9 +2381,8 @@ return_command (char *retval_exp, int from_tty)
|
||||||
struct type *return_type = value_type (return_value);
|
struct type *return_type = value_type (return_value);
|
||||||
struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
|
struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
|
||||||
|
|
||||||
gdb_assert (gdbarch_return_value (gdbarch, function, return_type, NULL,
|
gdb_assert (rv_conv != RETURN_VALUE_STRUCT_CONVENTION
|
||||||
NULL, NULL)
|
&& rv_conv != RETURN_VALUE_ABI_RETURNS_ADDRESS);
|
||||||
== RETURN_VALUE_REGISTER_CONVENTION);
|
|
||||||
gdbarch_return_value (gdbarch, function, return_type,
|
gdbarch_return_value (gdbarch, function, return_type,
|
||||||
get_current_regcache (), NULL /*read*/,
|
get_current_regcache (), NULL /*read*/,
|
||||||
value_contents (return_value) /*write*/);
|
value_contents (return_value) /*write*/);
|
||||||
|
|
28
gdb/value.c
28
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
|
/* Return true if the function returning the specified type is using
|
||||||
the convention of returning structures in memory (passing in the
|
the convention of returning structures in memory (passing in the
|
||||||
address as a hidden first parameter). */
|
address as a hidden first parameter). */
|
||||||
|
@ -3331,19 +3348,12 @@ int
|
||||||
using_struct_return (struct gdbarch *gdbarch,
|
using_struct_return (struct gdbarch *gdbarch,
|
||||||
struct value *function, struct type *value_type)
|
struct value *function, struct type *value_type)
|
||||||
{
|
{
|
||||||
enum type_code code = TYPE_CODE (value_type);
|
if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
|
||||||
|
|
||||||
if (code == TYPE_CODE_ERROR)
|
|
||||||
error (_("Function return type unknown."));
|
|
||||||
|
|
||||||
if (code == TYPE_CODE_VOID)
|
|
||||||
/* A void return value is never in memory. See also corresponding
|
/* A void return value is never in memory. See also corresponding
|
||||||
code in "print_return_value". */
|
code in "print_return_value". */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Probe the architecture for the return-value convention. */
|
return (struct_return_convention (gdbarch, function, value_type)
|
||||||
return (gdbarch_return_value (gdbarch, function, value_type,
|
|
||||||
NULL, NULL, NULL)
|
|
||||||
!= RETURN_VALUE_REGISTER_CONVENTION);
|
!= RETURN_VALUE_REGISTER_CONVENTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
extern int value_bit_index (struct type *type, const gdb_byte *addr,
|
||||||
int index);
|
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,
|
extern int using_struct_return (struct gdbarch *gdbarch,
|
||||||
struct value *function,
|
struct value *function,
|
||||||
struct type *value_type);
|
struct type *value_type);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue