[PATCH 2/4] tic6x: Install return_with_first_hidden_param_p

Yao Qi
2012-04-18T13:18:16Z

This patch can be logically separated to two parts,
- 1) Remove local variable `cplus_return_struct_by_reference' in
tic6x_push_dummy_call
- 2) Implement hook return_with_first_hidden_param_p.

As we can see in the comment to `cplus_return_struct_by_reference',
it is used to address the same problem as what gdbarch hook
`return_with_first_hidden_param_p' tries to address. Originally,
I used a tic6x-specific approach (`cplus_return_struct_by_reference')
to address this issue, because at that moment, I thought that
problem is tic6x specific. Today, we realize that this kind
of problem exists on targets more than tic6x, such as SH, m68k, etc.

This patch is to remove code of using `cplus_return_struct_by_reference',
and switch to use this new gdbarch hook.

Regression tested for tic6x-uclinux.

gdb:

2012-04-16 Yao Qi <yao@codesourcery.com>

* tic6x-tdep.c (tic6x_push_dummy_call): Remove local variable
`cplus_return_struct_by_reference'.
(tic6x_return_value): Handle language cplusplus.
(tic6x_return_with_first_hidden_param_p): New.
(tic6x_gdbarch_init): Install tic6x_return_with_first_hidden_param_p.
---
gdb/tic6x-tdep.c | 65 ++++++++++++++++++++++++-----------------------------
1 files changed, 29 insertions(+), 36 deletions(-)

diff --git a/gdb/tic6x-tdep.c b/gdb/tic6x-tdep.c
index 2dce8da..815522f 100644
--- a/gdb/tic6x-tdep.c
+++ b/gdb/tic6x-tdep.c
@@ -825,6 +825,19 @@ tic6x_return_value (struct gdbarch *gdbarch, struct type *func_type,
struct type *type, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
+ /* In C++, when function returns an object, even its size is small
+ enough, it stii has to be passed via reference, pointed by register
+ A3. */
+ if (current_language->la_language == language_cplus)
+ {
+ if (type != NULL)
+ {
+ CHECK_TYPEDEF (type);
+ if (language_pass_by_reference (type))
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ }
+ }
+
if (TYPE_LENGTH (type) > 8)
return RETURN_VALUE_STRUCT_CONVENTION;

@@ -915,32 +928,7 @@ tic6x_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
/* The first arg passed on stack. Mostly the first 10 args are passed by
registers. */
int first_arg_on_stack = 10;
- /* If this inf-call is a cpp method call, and return value is passed by
- reference, this flag is set to 1, otherwise set to 0. We need this flag
- because computation of the return location in
- infcall.c:call_function_by_hand is wrong for C6000 ELF ABI. In
- call_function_by_hand, the language is considered first, and then
- target ABI is considered. If language_pass_by_reference returns true,
- the return location is passed as the first parameter to the function,
- which is conflict with C6000 ELF ABI. If this flag is true, we should
- adjust args and return locations accordingly to comply with C6000 ELF
- ABI. */
- int cplus_return_struct_by_reference = 0;
-
- if (current_language->la_language == language_cplus)
- {
- struct type *values_type;
-
- find_function_addr (function, &values_type);
-
- if (values_type)
- {
- CHECK_TYPEDEF (values_type);
- if (language_pass_by_reference (values_type))
- cplus_return_struct_by_reference = 1;
- }

- }
/* Set the return address register to point to the entry point of
the program, where a breakpoint lies in wait. */
regcache_cooked_write_unsigned (regcache, TIC6X_RA_REGNUM, bp_addr);
@@ -950,12 +938,6 @@ tic6x_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
the address in A3. */
if (struct_return)
regcache_cooked_write_unsigned (regcache, 3, struct_addr);
- else if (cplus_return_struct_by_reference)
- /* When cplus_return_struct_by_reference is 1, means local variable
- lang_struct_return in call_function_by_hand is 1, so struct is
- returned by reference, even STRUCT_RETURN is 0. Note that STRUCT_ADDR
- is still valid in this case. */
- regcache_cooked_write_unsigned (regcache, 3, struct_addr);

/* Determine the type of this function. */
func_type = check_typedef (func_type);
@@ -970,10 +952,8 @@ tic6x_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
if (TYPE_VARARGS (func_type))
first_arg_on_stack = TYPE_NFIELDS (func_type) - 1;

- /* Now make space on the stack for the args. If
- cplus_return_struct_by_reference is 1, means GDB pass an extra parameter
- in ARGS, which is useless here, skip it. */
- for (argnum = cplus_return_struct_by_reference; argnum < nargs; argnum++)
+ /* Now make space on the stack for the args. */
+ for (argnum = 0; argnum < nargs; argnum++)
{
int len = align_up (TYPE_LENGTH (value_type (args[argnum])), 4);
if (argnum >= 10 - argreg)
@@ -989,7 +969,7 @@ tic6x_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
/* Now load as many as possible of the first arguments into
registers, and push the rest onto the stack. Loop through args
from first to last. */
- for (argnum = cplus_return_struct_by_reference; argnum < nargs; argnum++)
+ for (argnum = 0; argnum < nargs; argnum++)
{
const gdb_byte *val;
struct value *arg = args[argnum];
@@ -1210,6 +1190,16 @@ tic6x_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
return 1;
}

+/* This is the implementation of gdbarch method
+ return_with_first_hidden_param_p. */
+
+static int
+tic6x_return_with_first_hidden_param_p (struct gdbarch *gdbarch,
+ struct type *type)
+{
+ return 0;
+}
+
static struct gdbarch *
tic6x_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
@@ -1368,6 +1358,9 @@ tic6x_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)

set_gdbarch_in_function_epilogue_p (gdbarch, tic6x_in_function_epilogue_p);

+ set_gdbarch_return_with_first_hidden_param_p (gdbarch,
+ tic6x_return_with_first_hidden_param_p);
+
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);

--
1.7.0.4