This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] RISC-V: Fix unnamed arg alignment in registers.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8b2d40cbba8fbf98d6e031c7d8c7e2ac1baae2d9

commit 8b2d40cbba8fbf98d6e031c7d8c7e2ac1baae2d9
Author: Jim Wilson <jimw@sifive.com>
Date:   Wed Nov 14 14:54:10 2018 -0800

    RISC-V: Fix unnamed arg alignment in registers.
    
    For riscv64-linux target, second half of fix for
    FAIL: gdb.base/gnu_vector.exp: call add_various_floatvecs
    
    Unnamed arguments with 2*XLEN alignment are passed in aligned register pairs.
    
    	gdb/
    	* 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.

Diff:
---
 gdb/ChangeLog    |  9 +++++++++
 gdb/riscv-tdep.c | 26 ++++++++++++++++++++++----
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a918439..6ce18fe 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
 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.
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 92f8c6e..943af95 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -1739,6 +1739,9 @@ struct riscv_arg_info
        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
@@ -1935,6 +1938,12 @@ riscv_call_arg_scalar_int (struct riscv_arg_info *ainfo,
       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],
@@ -2215,7 +2224,9 @@ riscv_call_arg_struct (struct riscv_arg_info *ainfo,
    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.  */
 
@@ -2223,11 +2234,12 @@ static void
 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))
@@ -2376,6 +2388,11 @@ riscv_push_dummy_call (struct gdbarch *gdbarch,
 
   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;
@@ -2389,7 +2406,8 @@ riscv_push_dummy_call (struct gdbarch *gdbarch,
       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);
@@ -2566,7 +2584,7 @@ riscv_return_value (struct gdbarch  *gdbarch,
   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)
     {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]