* arch-utils.c (default_return_in_first_hidden_param_p): New.
	* arch-utils.h: Declare.
	* gdbarch.sh: Add return_in_first_hidden_param_p.
	* gdbarch.c, gdbarch.h: Regenerated.
	* infcall.c (call_function_by_hand): Call
	gdbarch_return_in_first_hidden_param_p instead of
	language_pass_by_reference.

	* m68k-tdep.c (m68k_return_in_first_hidden_param_p): New.
	(m68k_gdbarch_init): Install m68k_return_in_first_hidden_param_p.
	* sh-tdep.c (sh_return_in_first_hidden_param_p): New.
	(sh_gdbarch_init): Install sh_return_in_first_hidden_param_p.
	* tic6x-tdep.c (tic6x_push_dummy_call): Remove local variable
	`cplus_return_struct_by_reference'.
	(tic6x_return_value): Handle language cplusplus.
	(tic6x_return_in_first_hidden_param_p): New.
	(tic6x_gdbarch_init): Install tic6x_return_in_first_hidden_param_p.
This commit is contained in:
Yao Qi 2012-06-08 14:24:57 +00:00
parent 16bdd41fc6
commit 18648a3749
10 changed files with 135 additions and 42 deletions

View file

@ -1,3 +1,24 @@
2012-06-08 Yao Qi <yao@codesourcery.com>
Chung-Lin Tang <cltang@codesourcery.com>
* arch-utils.c (default_return_in_first_hidden_param_p): New.
* arch-utils.h: Declare.
* gdbarch.sh: Add return_in_first_hidden_param_p.
* gdbarch.c, gdbarch.h: Regenerated.
* infcall.c (call_function_by_hand): Call
gdbarch_return_in_first_hidden_param_p instead of
language_pass_by_reference.
* m68k-tdep.c (m68k_return_in_first_hidden_param_p): New.
(m68k_gdbarch_init): Install m68k_return_in_first_hidden_param_p.
* sh-tdep.c (sh_return_in_first_hidden_param_p): New.
(sh_gdbarch_init): Install sh_return_in_first_hidden_param_p.
* tic6x-tdep.c (tic6x_push_dummy_call): Remove local variable
`cplus_return_struct_by_reference'.
(tic6x_return_value): Handle language cplusplus.
(tic6x_return_in_first_hidden_param_p): New.
(tic6x_gdbarch_init): Install tic6x_return_in_first_hidden_param_p.
2012-06-07 Doug Evans <dje@google.com> 2012-06-07 Doug Evans <dje@google.com>
* dwarf2read.c (dwarf2_cu): Add comment. * dwarf2read.c (dwarf2_cu): Add comment.

View file

@ -31,6 +31,7 @@
#include "osabi.h" #include "osabi.h"
#include "target-descriptions.h" #include "target-descriptions.h"
#include "objfiles.h" #include "objfiles.h"
#include "language.h"
#include "version.h" #include "version.h"
@ -793,6 +794,16 @@ default_gen_return_address (struct gdbarch *gdbarch,
error (_("This architecture has no method to collect a return address.")); error (_("This architecture has no method to collect a return address."));
} }
int
default_return_in_first_hidden_param_p (struct gdbarch *gdbarch,
struct type *type)
{
/* Usually, the return value's address is stored the in the "first hidden"
parameter if the return value should be passed by reference, as
specified in ABI. */
return language_pass_by_reference (type);
}
/* */ /* */
/* -Wmissing-prototypes */ /* -Wmissing-prototypes */

View file

@ -172,4 +172,6 @@ extern void default_gen_return_address (struct gdbarch *gdbarch,
extern const char *default_auto_charset (void); extern const char *default_auto_charset (void);
extern const char *default_auto_wide_charset (void); extern const char *default_auto_wide_charset (void);
extern int default_return_in_first_hidden_param_p (struct gdbarch *,
struct type *);
#endif #endif

View file

@ -200,6 +200,7 @@ struct gdbarch
gdbarch_address_to_pointer_ftype *address_to_pointer; gdbarch_address_to_pointer_ftype *address_to_pointer;
gdbarch_integer_to_address_ftype *integer_to_address; gdbarch_integer_to_address_ftype *integer_to_address;
gdbarch_return_value_ftype *return_value; gdbarch_return_value_ftype *return_value;
gdbarch_return_in_first_hidden_param_p_ftype *return_in_first_hidden_param_p;
gdbarch_skip_prologue_ftype *skip_prologue; gdbarch_skip_prologue_ftype *skip_prologue;
gdbarch_skip_main_prologue_ftype *skip_main_prologue; gdbarch_skip_main_prologue_ftype *skip_main_prologue;
gdbarch_inner_than_ftype *inner_than; gdbarch_inner_than_ftype *inner_than;
@ -368,6 +369,7 @@ struct gdbarch startup_gdbarch =
unsigned_address_to_pointer, /* address_to_pointer */ unsigned_address_to_pointer, /* address_to_pointer */
0, /* integer_to_address */ 0, /* integer_to_address */
0, /* return_value */ 0, /* return_value */
default_return_in_first_hidden_param_p, /* return_in_first_hidden_param_p */
0, /* skip_prologue */ 0, /* skip_prologue */
0, /* skip_main_prologue */ 0, /* skip_main_prologue */
0, /* inner_than */ 0, /* inner_than */
@ -519,6 +521,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
gdbarch->value_from_register = default_value_from_register; gdbarch->value_from_register = default_value_from_register;
gdbarch->pointer_to_address = unsigned_pointer_to_address; gdbarch->pointer_to_address = unsigned_pointer_to_address;
gdbarch->address_to_pointer = unsigned_address_to_pointer; gdbarch->address_to_pointer = unsigned_address_to_pointer;
gdbarch->return_in_first_hidden_param_p = default_return_in_first_hidden_param_p;
gdbarch->remote_breakpoint_from_pc = default_remote_breakpoint_from_pc; gdbarch->remote_breakpoint_from_pc = default_remote_breakpoint_from_pc;
gdbarch->memory_insert_breakpoint = default_memory_insert_breakpoint; gdbarch->memory_insert_breakpoint = default_memory_insert_breakpoint;
gdbarch->memory_remove_breakpoint = default_memory_remove_breakpoint; gdbarch->memory_remove_breakpoint = default_memory_remove_breakpoint;
@ -665,6 +668,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of address_to_pointer, invalid_p == 0 */ /* Skip verify of address_to_pointer, invalid_p == 0 */
/* Skip verify of integer_to_address, has predicate. */ /* Skip verify of integer_to_address, has predicate. */
/* Skip verify of return_value, has predicate. */ /* Skip verify of return_value, has predicate. */
/* Skip verify of return_in_first_hidden_param_p, invalid_p == 0 */
if (gdbarch->skip_prologue == 0) if (gdbarch->skip_prologue == 0)
fprintf_unfiltered (log, "\n\tskip_prologue"); fprintf_unfiltered (log, "\n\tskip_prologue");
/* Skip verify of skip_main_prologue, has predicate. */ /* Skip verify of skip_main_prologue, has predicate. */
@ -1242,6 +1246,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
fprintf_unfiltered (file, fprintf_unfiltered (file,
"gdbarch_dump: remote_register_number = <%s>\n", "gdbarch_dump: remote_register_number = <%s>\n",
host_address_to_string (gdbarch->remote_register_number)); host_address_to_string (gdbarch->remote_register_number));
fprintf_unfiltered (file,
"gdbarch_dump: return_in_first_hidden_param_p = <%s>\n",
host_address_to_string (gdbarch->return_in_first_hidden_param_p));
fprintf_unfiltered (file, fprintf_unfiltered (file,
"gdbarch_dump: gdbarch_return_value_p() = %d\n", "gdbarch_dump: gdbarch_return_value_p() = %d\n",
gdbarch_return_value_p (gdbarch)); gdbarch_return_value_p (gdbarch));
@ -2555,6 +2562,23 @@ set_gdbarch_return_value (struct gdbarch *gdbarch,
gdbarch->return_value = return_value; gdbarch->return_value = return_value;
} }
int
gdbarch_return_in_first_hidden_param_p (struct gdbarch *gdbarch, struct type *type)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->return_in_first_hidden_param_p != NULL);
if (gdbarch_debug >= 2)
fprintf_unfiltered (gdb_stdlog, "gdbarch_return_in_first_hidden_param_p called\n");
return gdbarch->return_in_first_hidden_param_p (gdbarch, type);
}
void
set_gdbarch_return_in_first_hidden_param_p (struct gdbarch *gdbarch,
gdbarch_return_in_first_hidden_param_p_ftype return_in_first_hidden_param_p)
{
gdbarch->return_in_first_hidden_param_p = return_in_first_hidden_param_p;
}
CORE_ADDR CORE_ADDR
gdbarch_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR ip) gdbarch_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR ip)
{ {

View file

@ -457,6 +457,16 @@ typedef enum return_value_convention (gdbarch_return_value_ftype) (struct gdbarc
extern enum return_value_convention gdbarch_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf); extern enum return_value_convention gdbarch_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf);
extern void set_gdbarch_return_value (struct gdbarch *gdbarch, gdbarch_return_value_ftype *return_value); extern void set_gdbarch_return_value (struct gdbarch *gdbarch, gdbarch_return_value_ftype *return_value);
/* Return true if the return value of function is stored in the first hidden
parameter. In theory, this feature should be language-dependent, specified
by language and its ABI, such as C++. Unfortunately, compiler may
implement it to a target-dependent feature. So that we need such hook here
to be aware of this in GDB. */
typedef int (gdbarch_return_in_first_hidden_param_p_ftype) (struct gdbarch *gdbarch, struct type *type);
extern int gdbarch_return_in_first_hidden_param_p (struct gdbarch *gdbarch, struct type *type);
extern void set_gdbarch_return_in_first_hidden_param_p (struct gdbarch *gdbarch, gdbarch_return_in_first_hidden_param_p_ftype *return_in_first_hidden_param_p);
typedef CORE_ADDR (gdbarch_skip_prologue_ftype) (struct gdbarch *gdbarch, CORE_ADDR ip); typedef CORE_ADDR (gdbarch_skip_prologue_ftype) (struct gdbarch *gdbarch, CORE_ADDR ip);
extern CORE_ADDR gdbarch_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR ip); extern CORE_ADDR gdbarch_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR ip);
extern void set_gdbarch_skip_prologue (struct gdbarch *gdbarch, gdbarch_skip_prologue_ftype *skip_prologue); extern void set_gdbarch_skip_prologue (struct gdbarch *gdbarch, gdbarch_skip_prologue_ftype *skip_prologue);

View file

@ -515,6 +515,13 @@ M:CORE_ADDR:integer_to_address:struct type *type, const gdb_byte *buf:type, buf
# for instance). # for instance).
M:enum return_value_convention:return_value:struct value *function, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf:function, valtype, regcache, readbuf, writebuf M:enum return_value_convention:return_value:struct value *function, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf:function, valtype, regcache, readbuf, writebuf
# Return true if the return value of function is stored in the first hidden
# parameter. In theory, this feature should be language-dependent, specified
# by language and its ABI, such as C++. Unfortunately, compiler may
# implement it to a target-dependent feature. So that we need such hook here
# to be aware of this in GDB.
m:int:return_in_first_hidden_param_p:struct type *type:type::default_return_in_first_hidden_param_p::0
m:CORE_ADDR:skip_prologue:CORE_ADDR ip:ip:0:0 m:CORE_ADDR:skip_prologue:CORE_ADDR ip:ip:0:0
M:CORE_ADDR:skip_main_prologue:CORE_ADDR ip:ip M:CORE_ADDR:skip_main_prologue:CORE_ADDR ip:ip
f:int:inner_than:CORE_ADDR lhs, CORE_ADDR rhs:lhs, rhs:0:0 f:int:inner_than:CORE_ADDR lhs, CORE_ADDR rhs:lhs, rhs:0:0

View file

@ -464,7 +464,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
{ {
CORE_ADDR sp; CORE_ADDR sp;
struct type *values_type, *target_values_type; struct type *values_type, *target_values_type;
unsigned char struct_return = 0, lang_struct_return = 0; unsigned char struct_return = 0, hidden_first_param_p = 0;
CORE_ADDR struct_addr = 0; CORE_ADDR struct_addr = 0;
struct infcall_control_state *inf_status; struct infcall_control_state *inf_status;
struct cleanup *inf_status_cleanup; struct cleanup *inf_status_cleanup;
@ -598,9 +598,9 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
the first argument is passed in out0 but the hidden structure the first argument is passed in out0 but the hidden structure
return pointer would normally be passed in r8. */ return pointer would normally be passed in r8. */
if (language_pass_by_reference (values_type)) if (gdbarch_return_in_first_hidden_param_p (gdbarch, values_type))
{ {
lang_struct_return = 1; hidden_first_param_p = 1;
/* Tell the target specific argument pushing routine not to /* Tell the target specific argument pushing routine not to
expect a value. */ expect a value. */
@ -680,7 +680,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
stack, if necessary. Make certain that the value is correctly stack, if necessary. Make certain that the value is correctly
aligned. */ aligned. */
if (struct_return || lang_struct_return) if (struct_return || hidden_first_param_p)
{ {
int len = TYPE_LENGTH (values_type); int len = TYPE_LENGTH (values_type);
@ -706,7 +706,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
} }
} }
if (lang_struct_return) if (hidden_first_param_p)
{ {
struct value **new_args; struct value **new_args;
@ -1012,7 +1012,7 @@ When the function is done executing, GDB will silently stop."),
/* Figure out the value returned by the function. */ /* Figure out the value returned by the function. */
retval = allocate_value (values_type); retval = allocate_value (values_type);
if (lang_struct_return) if (hidden_first_param_p)
read_value_memory (retval, 0, 1, struct_addr, read_value_memory (retval, 0, 1, struct_addr,
value_contents_raw (retval), value_contents_raw (retval),
TYPE_LENGTH (values_type)); TYPE_LENGTH (values_type));

View file

@ -1050,6 +1050,16 @@ m68k_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
} }
/* This is the implementation of gdbarch method
return_in_first_hidden_param_p. */
static int
m68k_return_in_first_hidden_param_p (struct gdbarch *gdbarch,
struct type *type)
{
return 0;
}
/* System V Release 4 (SVR4). */ /* System V Release 4 (SVR4). */
void void
@ -1235,6 +1245,8 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Function call & return. */ /* Function call & return. */
set_gdbarch_push_dummy_call (gdbarch, m68k_push_dummy_call); set_gdbarch_push_dummy_call (gdbarch, m68k_push_dummy_call);
set_gdbarch_return_value (gdbarch, m68k_return_value); set_gdbarch_return_value (gdbarch, m68k_return_value);
set_gdbarch_return_in_first_hidden_param_p (gdbarch,
m68k_return_in_first_hidden_param_p);
/* Disassembler. */ /* Disassembler. */

View file

@ -2209,6 +2209,17 @@ sh_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name,
return NULL; return NULL;
} }
/* This is the implementation of gdbarch method
return_in_first_hidden_param_p. */
static int
sh_return_in_first_hidden_param_p (struct gdbarch *gdbarch,
struct type *type)
{
return 0;
}
static struct gdbarch * static struct gdbarch *
@ -2260,6 +2271,8 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_inner_than (gdbarch, core_addr_lessthan); set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_nofpu); set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_nofpu);
set_gdbarch_return_in_first_hidden_param_p (gdbarch,
sh_return_in_first_hidden_param_p);
set_gdbarch_believe_pcc_promotion (gdbarch, 1); set_gdbarch_believe_pcc_promotion (gdbarch, 1);

View file

@ -822,6 +822,19 @@ tic6x_return_value (struct gdbarch *gdbarch, struct value *function,
struct type *type, struct regcache *regcache, struct type *type, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf) 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) if (TYPE_LENGTH (type) > 8)
return RETURN_VALUE_STRUCT_CONVENTION; return RETURN_VALUE_STRUCT_CONVENTION;
@ -912,32 +925,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 /* The first arg passed on stack. Mostly the first 10 args are passed by
registers. */ registers. */
int first_arg_on_stack = 10; 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 /* Set the return address register to point to the entry point of
the program, where a breakpoint lies in wait. */ the program, where a breakpoint lies in wait. */
regcache_cooked_write_unsigned (regcache, TIC6X_RA_REGNUM, bp_addr); regcache_cooked_write_unsigned (regcache, TIC6X_RA_REGNUM, bp_addr);
@ -947,12 +935,6 @@ tic6x_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
the address in A3. */ the address in A3. */
if (struct_return) if (struct_return)
regcache_cooked_write_unsigned (regcache, 3, struct_addr); 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. */ /* Determine the type of this function. */
func_type = check_typedef (func_type); func_type = check_typedef (func_type);
@ -967,10 +949,8 @@ tic6x_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
if (TYPE_VARARGS (func_type)) if (TYPE_VARARGS (func_type))
first_arg_on_stack = TYPE_NFIELDS (func_type) - 1; first_arg_on_stack = TYPE_NFIELDS (func_type) - 1;
/* Now make space on the stack for the args. If /* Now make space on the stack for the args. */
cplus_return_struct_by_reference is 1, means GDB pass an extra parameter for (argnum = 0; argnum < nargs; argnum++)
in ARGS, which is useless here, skip it. */
for (argnum = cplus_return_struct_by_reference; argnum < nargs; argnum++)
{ {
int len = align_up (TYPE_LENGTH (value_type (args[argnum])), 4); int len = align_up (TYPE_LENGTH (value_type (args[argnum])), 4);
if (argnum >= 10 - argreg) if (argnum >= 10 - argreg)
@ -986,7 +966,7 @@ tic6x_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
/* Now load as many as possible of the first arguments into /* Now load as many as possible of the first arguments into
registers, and push the rest onto the stack. Loop through args registers, and push the rest onto the stack. Loop through args
from first to last. */ from first to last. */
for (argnum = cplus_return_struct_by_reference; argnum < nargs; argnum++) for (argnum = 0; argnum < nargs; argnum++)
{ {
const gdb_byte *val; const gdb_byte *val;
struct value *arg = args[argnum]; struct value *arg = args[argnum];
@ -1207,6 +1187,16 @@ tic6x_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
return 1; return 1;
} }
/* This is the implementation of gdbarch method
return_in_first_hidden_param_p. */
static int
tic6x_return_in_first_hidden_param_p (struct gdbarch *gdbarch,
struct type *type)
{
return 0;
}
static struct gdbarch * static struct gdbarch *
tic6x_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tic6x_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{ {
@ -1365,6 +1355,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_in_function_epilogue_p (gdbarch, tic6x_in_function_epilogue_p);
set_gdbarch_return_in_first_hidden_param_p (gdbarch,
tic6x_return_in_first_hidden_param_p);
/* Hook in ABI-specific overrides, if they have been registered. */ /* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch); gdbarch_init_osabi (info, gdbarch);