Fix fixed-point regression with recent GCC
authorTom Tromey <tromey@adacore.com>
Mon, 25 Jan 2021 15:13:51 +0000 (08:13 -0700)
committerTom Tromey <tromey@adacore.com>
Mon, 25 Jan 2021 15:13:51 +0000 (08:13 -0700)
A recent version of GCC changed how fixed-point types are described.
For example, a denominator in one test case now looks like:

    GNU_denominator      (exprloc)
     [ 0] implicit_value: 16 byte block: 00 00 b8 9d 0d 69 55 a0 01 00 00 00 00 00 00 00

... the difference being that this now uses exprloc and emits a
DW_OP_implicit_value for the 16-byte block.  (DWARF 5 still uses
DW_FORM_data16.)

This change was made here:

    https://gcc.gnu.org/pipermail/gcc-patches/2020-December/560897.html

This patch updates gdb to handle this situation.

Note that, before GCC 11, this test would not give the same answer.
Earlier versions of GCC fell back to GNAT encodings for this case.

gdb/ChangeLog
2021-01-25  Tom Tromey  <tromey@adacore.com>

* dwarf2/read.c (get_mpz): New function.
(get_dwarf2_rational_constant): Use it.

gdb/testsuite/ChangeLog
2021-01-25  Tom Tromey  <tromey@adacore.com>

* gdb.ada/fixed_points.exp: Add regression test.
* gdb.ada/fixed_points/fixed_points.adb (FP5_Var): New variable.
* gdb.ada/fixed_points/pck.adb (Delta5, FP5_Type): New.

gdb/ChangeLog
gdb/dwarf2/read.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.ada/fixed_points.exp
gdb/testsuite/gdb.ada/fixed_points/fixed_points.adb
gdb/testsuite/gdb.ada/fixed_points/pck.ads

index 3a4844fc70c78f24ad1cb6e1e64e45837b8eb4ee..0c30d7550bd49814b9b069c7b0e9ddec62df25bb 100644 (file)
@@ -1,3 +1,8 @@
+2021-01-25  Tom Tromey  <tromey@adacore.com>
+
+       * dwarf2/read.c (get_mpz): New function.
+       (get_dwarf2_rational_constant): Use it.
+
 2021-01-25  Tom Tromey  <tromey@adacore.com>
 
        * ada-lang.c (resolve_subexp): Handle array context.
index 309ff8331e720b1796a51f558ea0ccb0d16b89d6..ae95c650f1ea9c8e1335cda2a7bf71311ea4ed45 100644 (file)
@@ -18228,6 +18228,46 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
   return this_type;
 }
 
+/* Helper for get_dwarf2_rational_constant that computes the value of
+   a given gmp_mpz given an attribute.  */
+
+static void
+get_mpz (struct dwarf2_cu *cu, gdb_mpz *value, struct attribute *attr)
+{
+  /* GCC will sometimes emit a 16-byte constant value as a DWARF
+     location expression that pushes an implicit value.  */
+  if (attr->form == DW_FORM_exprloc)
+    {
+      dwarf_block *blk = attr->as_block ();
+      if (blk->size > 0 && blk->data[0] == DW_OP_implicit_value)
+       {
+         uint64_t len;
+         const gdb_byte *ptr = safe_read_uleb128 (blk->data + 1,
+                                                  blk->data + blk->size,
+                                                  &len);
+         if (ptr - blk->data + len <= blk->size)
+           {
+             mpz_import (value->val, len,
+                         bfd_big_endian (cu->per_objfile->objfile->obfd) ? 1 : -1,
+                         1, 0, 0, ptr);
+             return;
+           }
+       }
+
+      /* On failure set it to 1.  */
+      *value = gdb_mpz (1);
+    }
+  else if (attr->form_is_block ())
+    {
+      dwarf_block *blk = attr->as_block ();
+      mpz_import (value->val, blk->size,
+                 bfd_big_endian (cu->per_objfile->objfile->obfd) ? 1 : -1,
+                 1, 0, 0, blk->data);
+    }
+  else
+    *value = gdb_mpz (attr->constant_value (1));
+}
+
 /* Assuming DIE is a rational DW_TAG_constant, read the DIE's
    numerator and denominator into NUMERATOR and DENOMINATOR (resp).
 
@@ -18254,25 +18294,8 @@ get_dwarf2_rational_constant (struct die_info *die, struct dwarf2_cu *cu,
   if (num_attr == nullptr || denom_attr == nullptr)
     return;
 
-  if (num_attr->form_is_block ())
-    {
-      dwarf_block *blk = num_attr->as_block ();
-      mpz_import (numerator->val, blk->size,
-                 bfd_big_endian (cu->per_objfile->objfile->obfd) ? 1 : -1,
-                 1, 0, 0, blk->data);
-    }
-  else
-    *numerator = gdb_mpz (num_attr->constant_value (1));
-
-  if (denom_attr->form_is_block ())
-    {
-      dwarf_block *blk = denom_attr->as_block ();
-      mpz_import (denominator->val, blk->size,
-                 bfd_big_endian (cu->per_objfile->objfile->obfd) ? 1 : -1,
-                 1, 0, 0, blk->data);
-    }
-  else
-    *denominator = gdb_mpz (denom_attr->constant_value (1));
+  get_mpz (cu, numerator, num_attr);
+  get_mpz (cu, denominator, denom_attr);
 }
 
 /* Same as get_dwarf2_rational_constant, but extracting an unsigned
index 7fa1074598e37a1c7a7fdc2b95e584056beabe02..dad00fe5d5278d25cb337e4976e9121a65364df2 100644 (file)
@@ -1,3 +1,9 @@
+2021-01-25  Tom Tromey  <tromey@adacore.com>
+
+       * gdb.ada/fixed_points.exp: Add regression test.
+       * gdb.ada/fixed_points/fixed_points.adb (FP5_Var): New variable.
+       * gdb.ada/fixed_points/pck.adb (Delta5, FP5_Type): New.
+
 2021-01-25  Tom Tromey  <tromey@adacore.com>
 
        * gdb.ada/local-enum.exp: Add enumerator resolution test.
index 0d24453497542d49fcaddba85f1ad724ecf41401..ac45ef92ce948fd9c8f38914fb7a93526c49a95c 100644 (file)
@@ -123,5 +123,10 @@ foreach_with_prefix scenario {all minimal} {
        gdb_test "print fp4_var * 1" $fp4
        gdb_test "print 1 * fp4_var" $fp4
        gdb_test "print fp4_var / 1" $fp4
+
+       # This only started working in GCC 11.
+       if {[test_compiler_info {gcc-11-*}]} {
+           gdb_test "print fp5_var" " = 3e-19"
+       }
     }
 }
index cc2c637776133dd6d91cb7210172cee92d483f56..4298cdf899e835d8f46916603ede58be43e9dceb 100644 (file)
@@ -55,6 +55,8 @@ procedure Fixed_Points is
    Overprecise_Object : Overprecise_Fixed_Point :=
      Overprecise_Fixed_Point'Small;
 
+   FP5_Var : FP5_Type := 3 * Delta5;
+
 begin
    Base_Object := 1.0/16.0;   -- Set breakpoint here
    Subtype_Object := 1.0/16.0;
@@ -64,4 +66,5 @@ begin
    Do_Nothing (FP2_Var'Address);
    Do_Nothing (FP3_Var'Address);
    Do_Nothing (FP4_Var'Address);
+   Do_Nothing (FP5_Var'Address);
 end Fixed_Points;
index b5c1bc01c4484e1d956c0935bcdc1c025e213715..3bdf0595076b5ace2163bb6f5555caba65ff1de8 100644 (file)
@@ -30,6 +30,10 @@ package Pck is
       with Small => Delta4 / 3.0;
    FP4_Var : FP4_Type := 2 * Delta4;
 
+   Delta5 : constant := 0.000_000_000_000_000_000_1;
+   type FP5_Type is delta Delta5 range 0.0 .. Delta5 * 10
+      with Small => Delta5 / 3.0;
+
    procedure Do_Nothing (A : System.Address);
 end pck;