2018-11-14 Jim Wilson <jimw@sifive.com>
+ * riscv-tdep.c (struct riscv_arg_info): New field is_unnamed.
+ (riscv_call_arg_scalar_int): If unnamed arg with twice xlen alignment,
+ then increment next_regnum if odd.
+ (riscv_arg_location): New arg is_unnamed. Set ainfo->is_unnamed.
+ (riscv_push_dummy_call): New local ftype. Call check_typedef to set
+ function type. Pass new arg to riscv_arg_location based on function
+ type.
+ (riscv_return_value): Pass new arg to riscv_arg_location.
+
* riscv-tdep.c (BIGGEST_ALIGNMENT): New.
(riscv_type_alignment) <TYPE_CODE_ARRAY>: If TYPE_VECTOR, return min
of TYPE_LENGTH and BIGGEST_ALIGNMENT.
then this offset will be set to 0. */
int c_offset;
} argloc[2];
+
+ /* TRUE if this is an unnamed argument. */
+ bool is_unnamed;
};
/* Information about a set of registers being used for passing arguments as
int len = std::min (ainfo->length, cinfo->xlen);
int align = std::max (ainfo->align, cinfo->xlen);
+ /* Unnamed arguments in registers that require 2*XLEN alignment are
+ passed in an aligned register pair. */
+ if (ainfo->is_unnamed && (align == cinfo->xlen * 2)
+ && cinfo->int_regs.next_regnum & 1)
+ cinfo->int_regs.next_regnum++;
+
if (!riscv_assign_reg_location (&ainfo->argloc[0],
&cinfo->int_regs, len, 0))
riscv_assign_stack_location (&ainfo->argloc[0],
selected from CINFO which holds information about what call argument
locations are available for use next. The TYPE is the type of the
argument being passed, this information is recorded into AINFO (along
- with some additional information derived from the type).
+ with some additional information derived from the type). IS_UNNAMED
+ is true if this is an unnamed (stdarg) argument, this info is also
+ recorded into AINFO.
After assigning a location to AINFO, CINFO will have been updated. */
riscv_arg_location (struct gdbarch *gdbarch,
struct riscv_arg_info *ainfo,
struct riscv_call_info *cinfo,
- struct type *type)
+ struct type *type, bool is_unnamed)
{
ainfo->type = type;
ainfo->length = TYPE_LENGTH (ainfo->type);
ainfo->align = riscv_type_alignment (ainfo->type);
+ ainfo->is_unnamed = is_unnamed;
ainfo->contents = nullptr;
switch (TYPE_CODE (ainfo->type))
CORE_ADDR osp = sp;
+ struct type *ftype = check_typedef (value_type (function));
+
+ if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
+ ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
+
/* We'll use register $a0 if we're returning a struct. */
if (struct_return)
++call_info.int_regs.next_regnum;
arg_value = args[i];
arg_type = check_typedef (value_type (arg_value));
- riscv_arg_location (gdbarch, info, &call_info, arg_type);
+ riscv_arg_location (gdbarch, info, &call_info, arg_type,
+ TYPE_VARARGS (ftype) && i >= TYPE_NFIELDS (ftype));
if (info->type != arg_type)
arg_value = value_cast (info->type, arg_value);
struct type *arg_type;
arg_type = check_typedef (type);
- riscv_arg_location (gdbarch, &info, &call_info, arg_type);
+ riscv_arg_location (gdbarch, &info, &call_info, arg_type, false);
if (riscv_debug_infcall > 0)
{