[v3,amd64] Fix AMD64 return value ABI in expression evaluation

Message ID 87o955u7nl.fsf@tromey.com
State New, archived
Headers

Commit Message

Tom Tromey April 16, 2019, 6:28 p.m. UTC
  >>> This ABI mismatch resulted in issues when calling a function that returns
>>> a class of size <16 bytes which has a base class, including issues such
>>> as the "this" pointer being incorrect (as it was passed as the second
>>> argument rather than the first).

Tom> I'm still looking into the problem, but this regressed an internal test
Tom> case here at AdaCore.  In particular, this patch doesn't seem to treat
Tom> bitfields the same way that gcc does.

The appended fixes the test case that's included, but I'm not really
sure it's correct, since I am not sure that the test for
"bit-field-ness" is correct here.

Let me know what you think.

Tom

commit 93fb3e610bcd0ff5763334588bd84e41a4f73ef9
Author: Tom Tromey <tromey@adacore.com>
Date:   Tue Apr 16 11:11:10 2019 -0600

    Fix passing of struct with bitfields on x86-64
    
    Commit 4aa866af ("Fix AMD64 return value ABI in expression
    evaluation") introduced a regression when calling a function with a
    structure that contains bitfields.
    
    Because the caller of amd64_has_unaligned_fields handles bitfields
    already, it seemed to me that the simplest fix was to ignore bitfields
    here.
    
    gdb/ChangeLog
    2019-04-16  Tom Tromey  <tromey@adacore.com>
    
            * amd64-tdep.c (amd64_has_unaligned_fields): Ignore bitfields.
    
    gdb/testsuite/ChangeLog
    2019-04-16  Tom Tromey  <tromey@adacore.com>
    
            * gdb.arch/amd64-eval.exp: Test bitfield return.
            * gdb.arch/amd64-eval.cc (struct Bitfields): New.
            (class Foo) <return_bitfields>: New method.
            (main): Call it.
  

Comments

Tom Tromey April 24, 2019, 6:03 p.m. UTC | #1
>>>>> "Tom" == Tom Tromey <tromey@adacore.com> writes:

Tom> The appended fixes the test case that's included, but I'm not really
Tom> sure it's correct, since I am not sure that the test for
Tom> "bit-field-ness" is correct here.

Tom> Let me know what you think.

I'm checking this in now.
It seems to me that since this fixes the regression and also does not
regress the other new tests that it must be at least an improvement.

Tom
  

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ba1300d57ef..bc4a4b50ff5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,7 @@ 
+2019-04-16  Tom Tromey  <tromey@adacore.com>
+
+	* amd64-tdep.c (amd64_has_unaligned_fields): Ignore bitfields.
+
 2019-04-15  Leszek Swirski  <leszeks@google.com>
 
 	* amd64-tdep.c (amd64_classify_aggregate): Use cp_pass_by_reference
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index d4c96de5716..31791f9a9f1 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -555,11 +555,13 @@  amd64_has_unaligned_fields (struct type *type)
 	  int bitpos = TYPE_FIELD_BITPOS (type, i);
 	  int align = type_align(subtype);
 
-	  /* Ignore static fields, or empty fields, for example nested
-	     empty structures.  */
+	  /* Ignore static fields, empty fields (for example nested
+	     empty structures), and bitfields (these are handled by
+	     the caller).  */
 	  if (field_is_static (&TYPE_FIELD (type, i))
 	      || (TYPE_FIELD_BITSIZE (type, i) == 0
-		  && TYPE_LENGTH (subtype) == 0))
+		  && TYPE_LENGTH (subtype) == 0)
+	      || TYPE_FIELD_PACKED (type, i))
 	    continue;
 
 	  if (bitpos % 8 != 0)
@@ -569,7 +571,7 @@  amd64_has_unaligned_fields (struct type *type)
 	  if (bytepos % align != 0)
 	    return true;
 
-	  if (amd64_has_unaligned_fields(subtype))
+	  if (amd64_has_unaligned_fields (subtype))
 	    return true;
 	}
     }
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index d46422635be..f9cc0259c56 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,10 @@ 
+2019-04-16  Tom Tromey  <tromey@adacore.com>
+
+	* gdb.arch/amd64-eval.exp: Test bitfield return.
+	* gdb.arch/amd64-eval.cc (struct Bitfields): New.
+	(class Foo) <return_bitfields>: New method.
+	(main): Call it.
+
 2019-04-15  Leszek Swirski  <leszeks@google.com>
 
 	* gdb.arch/amd64-eval.cc: New file.
diff --git a/gdb/testsuite/gdb.arch/amd64-eval.cc b/gdb/testsuite/gdb.arch/amd64-eval.cc
index a986a49db34..907233ff04a 100644
--- a/gdb/testsuite/gdb.arch/amd64-eval.cc
+++ b/gdb/testsuite/gdb.arch/amd64-eval.cc
@@ -63,6 +63,16 @@  struct UnalignedFieldsInBase : public UnalignedFields
   int32_t x2;
 };
 
+struct Bitfields
+{
+  Bitfields(unsigned int x, unsigned int y)
+    : fld(x), fld2(y)
+  {}
+
+  unsigned fld : 7;
+  unsigned fld2 : 7;
+};
+
 class Foo
 {
 public:
@@ -101,6 +111,13 @@  public:
     return UnalignedFieldsInBase (x, y, x2);
   }
 
+  Bitfields
+  return_bitfields (unsigned int x, unsigned int y)
+  {
+    assert (this->tag == EXPECTED_TAG);
+    return Bitfields(x, y);
+  }
+
 private:
   /* Use a tag to detect if the "this" value is correct.  */
   static const int EXPECTED_TAG = 0xF00F00F0;
@@ -116,5 +133,6 @@  main (int argc, char *argv[])
   foo.return_non_trivial_destructor(3);
   foo.return_unaligned(4, 5);
   foo.return_unaligned_in_base(6, 7, 8);
+  foo.return_bitfields(23, 74);
   return 0;  // break-here
 }
diff --git a/gdb/testsuite/gdb.arch/amd64-eval.exp b/gdb/testsuite/gdb.arch/amd64-eval.exp
index c33777d2b41..beef46ad133 100644
--- a/gdb/testsuite/gdb.arch/amd64-eval.exp
+++ b/gdb/testsuite/gdb.arch/amd64-eval.exp
@@ -41,3 +41,5 @@  gdb_test "call foo.return_unaligned(78, 9.25)" \
     " = {x = 78, y = 9.25}"
 gdb_test "call foo.return_unaligned_in_base(23, 4.5, 67)" \
     " = {<UnalignedFields> = {x = 23, y = 4.5}, x2 = 67}"
+gdb_test "call foo.return_bitfields(23, 74)" \
+    " = {fld = 23, fld2 = 74}"