* 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-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>
* dwarf2read.c (dwarf2_cu): Add comment.
#include "osabi.h"
#include "target-descriptions.h"
#include "objfiles.h"
+#include "language.h"
#include "version.h"
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 */
extern const char *default_auto_charset (void);
extern const char *default_auto_wide_charset (void);
+extern int default_return_in_first_hidden_param_p (struct gdbarch *,
+ struct type *);
#endif
gdbarch_address_to_pointer_ftype *address_to_pointer;
gdbarch_integer_to_address_ftype *integer_to_address;
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_main_prologue_ftype *skip_main_prologue;
gdbarch_inner_than_ftype *inner_than;
unsigned_address_to_pointer, /* address_to_pointer */
0, /* integer_to_address */
0, /* return_value */
+ default_return_in_first_hidden_param_p, /* return_in_first_hidden_param_p */
0, /* skip_prologue */
0, /* skip_main_prologue */
0, /* inner_than */
gdbarch->value_from_register = default_value_from_register;
gdbarch->pointer_to_address = unsigned_pointer_to_address;
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->memory_insert_breakpoint = default_memory_insert_breakpoint;
gdbarch->memory_remove_breakpoint = default_memory_remove_breakpoint;
/* Skip verify of address_to_pointer, invalid_p == 0 */
/* Skip verify of integer_to_address, 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)
fprintf_unfiltered (log, "\n\tskip_prologue");
/* Skip verify of skip_main_prologue, has predicate. */
"gdbarch_dump: remote_register_number = <%s>\n",
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,
"gdbarch_dump: gdbarch_return_value_p() = %d\n",
gdbarch_return_value_p (gdbarch));
fprintf_unfiltered (file,
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
gdbarch_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR ip)
{
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);
+/* 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);
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);
# 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
+# 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_main_prologue:CORE_ADDR ip:ip
f:int:inner_than:CORE_ADDR lhs, CORE_ADDR rhs:lhs, rhs:0:0
{
CORE_ADDR sp;
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;
struct infcall_control_state *inf_status;
struct cleanup *inf_status_cleanup;
the first argument is passed in out0 but the hidden structure
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
expect a value. */
stack, if necessary. Make certain that the value is correctly
aligned. */
- if (struct_return || lang_struct_return)
+ if (struct_return || hidden_first_param_p)
{
int len = TYPE_LENGTH (values_type);
}
}
- if (lang_struct_return)
+ if (hidden_first_param_p)
{
struct value **new_args;
/* Figure out the value returned by the function. */
retval = allocate_value (values_type);
- if (lang_struct_return)
+ if (hidden_first_param_p)
read_value_memory (retval, 0, 1, struct_addr,
value_contents_raw (retval),
TYPE_LENGTH (values_type));
}
\f
+/* 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). */
void
/* Function call & return. */
set_gdbarch_push_dummy_call (gdbarch, m68k_push_dummy_call);
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. */
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;
+}
+
\f
static struct gdbarch *
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
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);
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;
/* 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);
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);
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)
/* 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];
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 *
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_in_first_hidden_param_p (gdbarch,
+ tic6x_return_in_first_hidden_param_p);
+
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);