public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Rewrite GNAT-encoded fixed point types in DWARF reader
@ 2021-02-10 19:19 Tom Tromey
  2021-03-02 20:08 ` Tom Tromey
  0 siblings, 1 reply; 2+ messages in thread
From: Tom Tromey @ 2021-02-10 19:19 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

gdb currently supports two different styles of fixed-point.  The
original style, where fixed point types are "GNAT encoded", is handled
primarily in the Ada code.  The newer style, encoded using DWARF, is
handled by the core of gdb.

This patch changes gdb to read the GNAT encodings in the DWARF reader
as well.  This removes some code and unifies the two paths.  As a
result, GNAT-encoded fixed-point now works a bit better.

One possible drawback of this change is that, if someone uses stabs,
then fixed-point might now stop working.  I consider stabs to be fully
obsolete, though, so I don't intend to address this.

gdb/ChangeLog
2021-02-10  Tom Tromey  <tromey@adacore.com>

	* ada-lang.c (cast_from_gnat_encoded_fixed_point_type)
	(cast_to_gnat_encoded_fixed_point_type): Remove.
	(ada_value_cast, ada_evaluate_subexp): Update.
	(gnat_encoded_fixed_point_type_info)
	(ada_is_gnat_encoded_fixed_point_type)
	(gnat_encoded_fixed_point_delta)
	(gnat_encoded_fixed_point_scaling_factor): Remove.
	* ada-lang.h (ada_is_gnat_encoded_fixed_point_type)
	(gnat_encoded_fixed_point_delta)
	(gnat_encoded_fixed_point_scaling_factor): Don't declare.
	* ada-typeprint.c (print_gnat_encoded_fixed_point_type): Remove.
	(ada_print_type): Update.
	* ada-valprint.c (ada_value_print_num): Update.
	* dwarf2/read.c (ada_get_gnat_encoded_number)
	(ada_get_gnat_encoded_ratio): New functions.
	(finish_fixed_point_type): Use them.  Add parameters.
	(GNAT_FIXED_POINT_SUFFIX): New define.
	(gnat_encoded_fixed_point_type_info): New function.
	(read_base_type): Handle gnat encodings.

gdb/testsuite/ChangeLog
2021-02-10  Tom Tromey  <tromey@adacore.com>

	* gdb.ada/fixed_points.exp: Remove most special cases for minimal
	encodings.
---
 gdb/ChangeLog                          |  22 ++++
 gdb/ada-lang.c                         | 152 +-----------------------
 gdb/ada-lang.h                         |   6 -
 gdb/ada-typeprint.c                    |  58 +++------
 gdb/ada-valprint.c                     |  20 +---
 gdb/dwarf2/read.c                      | 157 ++++++++++++++++++++-----
 gdb/testsuite/ChangeLog                |   5 +
 gdb/testsuite/gdb.ada/fixed_points.exp |  85 ++++---------
 8 files changed, 198 insertions(+), 307 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 416a45be58e..74a969606ec 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -9263,33 +9263,6 @@ unwrap_value (struct value *val)
     }
 }
 
-static struct value *
-cast_from_gnat_encoded_fixed_point_type (struct type *type, struct value *arg)
-{
-  struct value *scale
-    = gnat_encoded_fixed_point_scaling_factor (value_type (arg));
-  arg = value_cast (value_type (scale), arg);
-
-  arg = value_binop (arg, scale, BINOP_MUL);
-  return value_cast (type, arg);
-}
-
-static struct value *
-cast_to_gnat_encoded_fixed_point_type (struct type *type, struct value *arg)
-{
-  if (type == value_type (arg))
-    return arg;
-
-  struct value *scale = gnat_encoded_fixed_point_scaling_factor (type);
-  if (ada_is_gnat_encoded_fixed_point_type (value_type (arg)))
-    arg = cast_from_gnat_encoded_fixed_point_type (value_type (scale), arg);
-  else
-    arg = value_cast (value_type (scale), arg);
-
-  arg = value_binop (arg, scale, BINOP_DIV);
-  return value_cast (type, arg);
-}
-
 /* Given two array types T1 and T2, return nonzero iff both arrays
    contain the same number of elements.  */
 
@@ -9789,12 +9762,6 @@ ada_value_cast (struct type *type, struct value *arg2)
   if (type == ada_check_typedef (value_type (arg2)))
     return arg2;
 
-  if (ada_is_gnat_encoded_fixed_point_type (type))
-    return cast_to_gnat_encoded_fixed_point_type (type, arg2);
-
-  if (ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-    return cast_from_gnat_encoded_fixed_point_type (type, arg2);
-
   return value_cast (type, arg2);
 }
 
@@ -10192,11 +10159,6 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
 	{
 	  /* Nothing.  */
 	}
-      else if (ada_is_gnat_encoded_fixed_point_type (value_type (arg1)))
-	arg2 = cast_to_gnat_encoded_fixed_point_type (value_type (arg1), arg2);
-      else if (ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-	error
-	  (_("Fixed-point values must be assigned to fixed-point variables"));
       else
 	arg2 = coerce_for_assign (value_type (arg1), arg2);
       return ada_value_assign (arg1, arg2);
@@ -10220,14 +10182,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       type = value_type (arg1);
       while (type->code () == TYPE_CODE_REF)
 	type = TYPE_TARGET_TYPE (type);
-      if (ada_is_gnat_encoded_fixed_point_type (value_type (arg1))
-	  || ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-	{
-	  if (value_type (arg1) != value_type (arg2))
-	    error (_("Operands of fixed-point addition must have the same type"));
-	}
-      else
-	binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
       arg1 = value_binop (arg1, arg2, BINOP_ADD);
       /* We need to special-case the result of adding to a range.
 	 This is done for the benefit of "ptype".  gdb's Ada support
@@ -10256,15 +10211,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       type = value_type (arg1);
       while (type->code () == TYPE_CODE_REF)
 	type = TYPE_TARGET_TYPE (type);
-      if (ada_is_gnat_encoded_fixed_point_type (value_type (arg1))
-	  || ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-	{
-	  if (value_type (arg1) != value_type (arg2))
-	    error (_("Operands of fixed-point subtraction "
-		     "must have the same type"));
-	}
-      else
-	binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
       arg1 = value_binop (arg1, arg2, BINOP_SUB);
       /* We need to special-case the result of adding to a range.
 	 This is done for the benefit of "ptype".  gdb's Ada support
@@ -10290,10 +10237,6 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       else
 	{
 	  type = builtin_type (exp->gdbarch)->builtin_double;
-	  if (ada_is_gnat_encoded_fixed_point_type (value_type (arg1)))
-	    arg1 = cast_from_gnat_encoded_fixed_point_type (type, arg1);
-	  if (ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-	    arg2 = cast_from_gnat_encoded_fixed_point_type (type, arg2);
 	  binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
 	  return ada_value_binop (arg1, arg2, op);
 	}
@@ -10320,8 +10263,6 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
       if (noside == EVAL_SKIP)
 	goto nosideret;
-      else if (ada_is_gnat_encoded_fixed_point_type (value_type (arg1)))
-	return value_cast (value_type (arg1), value_neg (arg1));
       else
 	{
 	  unop_promote (exp->language_defn, exp->gdbarch, &arg1);
@@ -11187,41 +11128,6 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
 }
 \f
 
-				/* Fixed point */
-
-/* If TYPE encodes an Ada fixed-point type, return the suffix of the
-   type name that encodes the 'small and 'delta information.
-   Otherwise, return NULL.  */
-
-static const char *
-gnat_encoded_fixed_point_type_info (struct type *type)
-{
-  const char *name = ada_type_name (type);
-  enum type_code code = (type == NULL) ? TYPE_CODE_UNDEF : type->code ();
-
-  if ((code == TYPE_CODE_INT || code == TYPE_CODE_RANGE) && name != NULL)
-    {
-      const char *tail = strstr (name, "___XF_");
-
-      if (tail == NULL)
-	return NULL;
-      else
-	return tail + 5;
-    }
-  else if (code == TYPE_CODE_RANGE && TYPE_TARGET_TYPE (type) != type)
-    return gnat_encoded_fixed_point_type_info (TYPE_TARGET_TYPE (type));
-  else
-    return NULL;
-}
-
-/* Returns non-zero iff TYPE represents an Ada fixed-point type.  */
-
-int
-ada_is_gnat_encoded_fixed_point_type (struct type *type)
-{
-  return gnat_encoded_fixed_point_type_info (type) != NULL;
-}
-
 /* Return non-zero iff TYPE represents a System.Address type.  */
 
 int
@@ -11230,60 +11136,6 @@ ada_is_system_address_type (struct type *type)
   return (type->name () && strcmp (type->name (), "system__address") == 0);
 }
 
-/* Assuming that TYPE is the representation of an Ada fixed-point
-   type, return the target floating-point type to be used to represent
-   of this type during internal computation.  */
-
-static struct type *
-ada_scaling_type (struct type *type)
-{
-  return builtin_type (type->arch ())->builtin_long_double;
-}
-
-/* Assuming that TYPE is the representation of an Ada fixed-point
-   type, return its delta, or NULL if the type is malformed and the
-   delta cannot be determined.  */
-
-struct value *
-gnat_encoded_fixed_point_delta (struct type *type)
-{
-  const char *encoding = gnat_encoded_fixed_point_type_info (type);
-  struct type *scale_type = ada_scaling_type (type);
-
-  long long num, den;
-
-  if (sscanf (encoding, "_%lld_%lld", &num, &den) < 2)
-    return nullptr;
-  else
-    return value_binop (value_from_longest (scale_type, num),
-			value_from_longest (scale_type, den), BINOP_DIV);
-}
-
-/* Assuming that ada_is_gnat_encoded_fixed_point_type (TYPE), return
-   the scaling factor ('SMALL value) associated with the type.  */
-
-struct value *
-gnat_encoded_fixed_point_scaling_factor (struct type *type)
-{
-  const char *encoding = gnat_encoded_fixed_point_type_info (type);
-  struct type *scale_type = ada_scaling_type (type);
-
-  long long num0, den0, num1, den1;
-  int n;
-
-  n = sscanf (encoding, "_%lld_%lld_%lld_%lld",
-	      &num0, &den0, &num1, &den1);
-
-  if (n < 2)
-    return value_from_longest (scale_type, 1);
-  else if (n == 4)
-    return value_binop (value_from_longest (scale_type, num1),
-			value_from_longest (scale_type, den1), BINOP_DIV);
-  else
-    return value_binop (value_from_longest (scale_type, num0),
-			value_from_longest (scale_type, den0), BINOP_DIV);
-}
-
 \f
 
 				/* Range types */
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index dbf45a84928..0d774ff4a86 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -281,14 +281,8 @@ extern struct type *ada_aligned_type (struct type *);
 extern const gdb_byte *ada_aligned_value_addr (struct type *,
 					       const gdb_byte *);
 
-extern int ada_is_gnat_encoded_fixed_point_type (struct type *);
-
 extern int ada_is_system_address_type (struct type *);
 
-extern struct value *gnat_encoded_fixed_point_delta (struct type *);
-
-extern struct value *gnat_encoded_fixed_point_scaling_factor (struct type *);
-
 extern int ada_which_variant_applies (struct type *, struct value *);
 
 extern struct type *ada_to_fixed_type (struct type *, const gdb_byte *,
diff --git a/gdb/ada-typeprint.c b/gdb/ada-typeprint.c
index 2b4af67fc93..54bbe0f1a01 100644
--- a/gdb/ada-typeprint.c
+++ b/gdb/ada-typeprint.c
@@ -339,31 +339,6 @@ print_enum_type (struct type *type, struct ui_file *stream)
   fprintf_filtered (stream, ")");
 }
 
-/* Print representation of Ada fixed-point type TYPE on STREAM.  */
-
-static void
-print_gnat_encoded_fixed_point_type (struct type *type, struct ui_file *stream)
-{
-  struct value *delta = gnat_encoded_fixed_point_delta (type);
-  struct value *small = gnat_encoded_fixed_point_scaling_factor (type);
-
-  if (delta == nullptr)
-    fprintf_filtered (stream, "delta ??");
-  else
-    {
-      std::string str;
-      str = target_float_to_string (value_contents (delta),
-				    value_type (delta), "%g");
-      fprintf_filtered (stream, "delta %s", str.c_str());
-      if (!value_equal (delta, small))
-	{
-	  str = target_float_to_string (value_contents (small),
-					value_type (small), "%g");
-	  fprintf_filtered (stream, " <'small = %s>", str.c_str());
-	}
-    }
-}
-
 /* Print simple (constrained) array type TYPE on STREAM.  LEVEL is the
    recursion (indentation) level, in case the element type itself has
    nested structure, and SHOW is the number of levels of internal
@@ -1026,27 +1001,22 @@ ada_print_type (struct type *type0, const char *varstring,
 	fprintf_filtered (stream, "(false, true)");
 	break;
       case TYPE_CODE_INT:
-	if (ada_is_gnat_encoded_fixed_point_type (type))
-	  print_gnat_encoded_fixed_point_type (type, stream);
-	else
-	  {
-	    const char *name = ada_type_name (type);
-
-	    if (!ada_is_range_type_name (name))
-	      fprintf_styled (stream, metadata_style.style (),
-			      _("<%s-byte integer>"),
-			      pulongest (TYPE_LENGTH (type)));
-	    else
-	      {
-		fprintf_filtered (stream, "range ");
-		print_range_type (type, stream, 1 /* bounds_prefered_p */);
-	      }
-	  }
+	{
+	  const char *name = ada_type_name (type);
+
+	  if (!ada_is_range_type_name (name))
+	    fprintf_styled (stream, metadata_style.style (),
+			    _("<%s-byte integer>"),
+			    pulongest (TYPE_LENGTH (type)));
+	  else
+	    {
+	      fprintf_filtered (stream, "range ");
+	      print_range_type (type, stream, 1 /* bounds_prefered_p */);
+	    }
+	}
 	break;
       case TYPE_CODE_RANGE:
-	if (ada_is_gnat_encoded_fixed_point_type (type))
-	  print_gnat_encoded_fixed_point_type (type, stream);
-	else if (is_fixed_point_type (type))
+	if (is_fixed_point_type (type))
 	  {
 	    fprintf_filtered (stream, "<");
 	    print_type_fixed_point (type, stream);
diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
index 8af9ef0012f..0d5b6d73076 100644
--- a/gdb/ada-valprint.c
+++ b/gdb/ada-valprint.c
@@ -741,22 +741,10 @@ ada_value_print_num (struct value *val, struct ui_file *stream, int recurse,
   struct type *type = ada_check_typedef (value_type (val));
   const gdb_byte *valaddr = value_contents_for_printing (val);
 
-  if (ada_is_gnat_encoded_fixed_point_type (type))
-    {
-      struct value *scale = gnat_encoded_fixed_point_scaling_factor (type);
-      val = value_cast (value_type (scale), val);
-      val = value_binop (val, scale, BINOP_MUL);
-
-      const char *fmt = TYPE_LENGTH (type) < 4 ? "%.11g" : "%.17g";
-      std::string str
-	= target_float_to_string (value_contents (val), value_type (val), fmt);
-      fputs_filtered (str.c_str (), stream);
-      return;
-    }
-  else if (type->code () == TYPE_CODE_RANGE
-	   && (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_ENUM
-	       || TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_BOOL
-	       || TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_CHAR))
+  if (type->code () == TYPE_CODE_RANGE
+      && (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_ENUM
+	  || TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_BOOL
+	  || TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_CHAR))
     {
       /* For enum-valued ranges, we want to recurse, because we'll end
 	 up printing the constant's name rather than its numeric
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 51bf0fbeea5..0a9cbf8277d 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -18373,24 +18373,77 @@ get_dwarf2_unsigned_rational_constant (struct die_info *die,
   *denominator = std::move (denom);
 }
 
+/* Assuming that ENCODING is a string whose contents starting at the
+   K'th character is "_nn" where "nn" is a decimal number, scan that
+   number and set RESULT to the value. K is updated to point to the
+   character immediately following the number.
+
+   If the string does not conform to the format described above, false
+   is returned, and K may or may not be changed.  */
+
+static bool
+ada_get_gnat_encoded_number (const char *encoding, int &k, gdb_mpz *result)
+{
+  /* The next character should be an underscore ('_') followed
+     by a digit.  */
+  if (encoding[k] != '_' || !isdigit (encoding[k + 1]))
+    return false;
+
+  /* Skip the underscore.  */
+  k++;
+  int start = k;
+
+  /* Determine the number of digits for our number.  */
+  while (isdigit (encoding[k]))
+    k++;
+  if (k == start)
+    return false;
+
+  std::string copy (&encoding[start], k - start);
+  if (mpz_set_str (result->val, copy.c_str (), 10) == -1)
+    return false;
+
+  return true;
+}
+
+/* Scan two numbers from ENCODING at OFFSET, assuming the string is of
+   the form _NN_DD, where NN and DD are decimal numbers.  Set NUM and
+   DENOM, update OFFSET, and return true on success.  Return false on
+   failure.  */
+
+static bool
+ada_get_gnat_encoded_ratio (const char *encoding, int &offset,
+			    gdb_mpz *num, gdb_mpz *denom)
+{
+  if (!ada_get_gnat_encoded_number (encoding, offset, num))
+    return false;
+  return ada_get_gnat_encoded_number (encoding, offset, denom);
+}
+
 /* Assuming DIE corresponds to a fixed point type, finish the creation
-   of the corresponding TYPE by setting its type-specific data.
-   CU is the DIE's CU.  */
+   of the corresponding TYPE by setting its type-specific data.  CU is
+   the DIE's CU.  SUFFIX is the "XF" type name suffix coming from GNAT
+   encodings.  It is nullptr if the GNAT encoding should be
+   ignored.  */
 
 static void
-finish_fixed_point_type (struct type *type, struct die_info *die,
-			 struct dwarf2_cu *cu)
+finish_fixed_point_type (struct type *type, const char *suffix,
+			 struct die_info *die, struct dwarf2_cu *cu)
 {
-  struct attribute *attr;
-
   gdb_assert (type->code () == TYPE_CODE_FIXED_POINT
 	      && TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_FIXED_POINT);
 
-  attr = dwarf2_attr (die, DW_AT_binary_scale, cu);
-  if (!attr)
-    attr = dwarf2_attr (die, DW_AT_decimal_scale, cu);
-  if (!attr)
-    attr = dwarf2_attr (die, DW_AT_small, cu);
+  /* If GNAT encodings are preferred, don't examine the
+     attributes.  */
+  struct attribute *attr = nullptr;
+  if (suffix == nullptr)
+    {
+      attr = dwarf2_attr (die, DW_AT_binary_scale, cu);
+      if (attr == nullptr)
+	attr = dwarf2_attr (die, DW_AT_decimal_scale, cu);
+      if (attr == nullptr)
+	attr = dwarf2_attr (die, DW_AT_small, cu);
+    }
 
   /* Numerator and denominator of our fixed-point type's scaling factor.
      The default is a scaling factor of 1, which we use as a fallback
@@ -18403,11 +18456,29 @@ finish_fixed_point_type (struct type *type, struct die_info *die,
 
   if (attr == nullptr)
     {
-      /* Scaling factor not found.  Assume a scaling factor of 1,
-	 and hope for the best.  At least the user will be able to see
-	 the encoded value.  */
-      complaint (_("no scale found for fixed-point type (DIE at %s)"),
-		 sect_offset_str (die->sect_off));
+      int offset = 0;
+      if (suffix != nullptr
+	  && ada_get_gnat_encoded_ratio (suffix, offset, &scale_num,
+					 &scale_denom)
+	  /* The number might be encoded as _nn_dd_nn_dd, where the
+	     second ratio is the 'small value.  In this situation, we
+	     want the second value.  */
+	  && (suffix[offset] != '_'
+	      || ada_get_gnat_encoded_ratio (suffix, offset, &scale_num,
+					     &scale_denom)))
+	{
+	  /* Found it.  */
+	}
+      else
+	{
+	  /* Scaling factor not found.  Assume a scaling factor of 1,
+	     and hope for the best.  At least the user will be able to
+	     see the encoded value.  */
+	  scale_num = 1;
+	  scale_denom = 1;
+	  complaint (_("no scale found for fixed-point type (DIE at %s)"),
+		     sect_offset_str (die->sect_off));
+	}
     }
   else if (attr->name == DW_AT_binary_scale)
     {
@@ -18451,6 +18522,20 @@ finish_fixed_point_type (struct type *type, struct die_info *die,
   mpq_canonicalize (scaling_factor.val);
 }
 
+/* The gnat-encoding suffix for fixed point.  */
+
+#define GNAT_FIXED_POINT_SUFFIX "___XF_"
+
+/* If NAME encodes an Ada fixed-point type, return a pointer to the
+   "XF" suffix of the name.  The text after this is what encodes the
+   'small and 'delta information.  Otherwise, return nullptr.  */
+
+static const char *
+gnat_encoded_fixed_point_type_info (const char *name)
+{
+  return strstr (name, GNAT_FIXED_POINT_SUFFIX);
+}
+
 /* Allocate a floating-point type of size BITS and name NAME.  Pass NAME_HINT
    (which may be different from NAME) to the architecture back-end to allow
    it to guess the correct format if necessary.  */
@@ -18639,20 +18724,38 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
 	 of fixed point types for which GNAT is unable to provide
 	 the scaling factor via the standard DWARF mechanisms, and
 	 for which the info is provided via the GNAT encodings instead.
-	 This is likely what this DIE is about.
-
-	 Ideally, GNAT should be declaring this type the same way
-	 it declares other fixed point types when using the legacy
-	 GNAT encoding, which is to use a simple signed or unsigned
-	 base type.  A report to the GNAT team has been created to
-	 look into it.  In the meantime, pretend this type is a simple
-	 signed or unsigned integral, rather than a fixed point type,
-	 to avoid any confusion later on as to how to process this type.  */
+	 This is likely what this DIE is about.  */
       encoding = (encoding == DW_ATE_signed_fixed
 		  ? DW_ATE_signed
 		  : DW_ATE_unsigned);
     }
 
+  /* With GNAT encodings, fixed-point information will be encoded in
+     the type name.  Note that this can also occur with the above
+     zero-over-zero case, which is why this is a separate "if" rather
+     than an "else if".  */
+  const char *gnat_encoding_suffix = nullptr;
+  if ((encoding == DW_ATE_signed || encoding == DW_ATE_unsigned)
+      && cu->language == language_ada
+      && name != nullptr)
+    {
+      gnat_encoding_suffix = gnat_encoded_fixed_point_type_info (name);
+      if (gnat_encoding_suffix != nullptr)
+	{
+	  gdb_assert (startswith (gnat_encoding_suffix,
+				  GNAT_FIXED_POINT_SUFFIX));
+	  name = obstack_strndup (&cu->per_objfile->objfile->objfile_obstack,
+				  name, gnat_encoding_suffix - name);
+	  /* Use -1 here so that SUFFIX points at the "_" after the
+	     "XF".  */
+	  gnat_encoding_suffix += strlen (GNAT_FIXED_POINT_SUFFIX) - 1;
+
+	  encoding = (encoding == DW_ATE_signed
+		      ? DW_ATE_signed_fixed
+		      : DW_ATE_unsigned_fixed);
+	}
+    }
+
   switch (encoding)
     {
       case DW_ATE_address:
@@ -18731,11 +18834,11 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
 	break;
       case DW_ATE_signed_fixed:
 	type = init_fixed_point_type (objfile, bits, 0, name);
-	finish_fixed_point_type (type, die, cu);
+	finish_fixed_point_type (type, gnat_encoding_suffix, die, cu);
 	break;
       case DW_ATE_unsigned_fixed:
 	type = init_fixed_point_type (objfile, bits, 1, name);
-	finish_fixed_point_type (type, die, cu);
+	finish_fixed_point_type (type, gnat_encoding_suffix, die, cu);
 	break;
 
       default:
diff --git a/gdb/testsuite/gdb.ada/fixed_points.exp b/gdb/testsuite/gdb.ada/fixed_points.exp
index ac45ef92ce9..7267c3181ed 100644
--- a/gdb/testsuite/gdb.ada/fixed_points.exp
+++ b/gdb/testsuite/gdb.ada/fixed_points.exp
@@ -49,84 +49,41 @@ foreach_with_prefix scenario {all minimal} {
     gdb_test "print Overprecise_Object" \
 	"= 0.13579135791"
 
-    gdb_test_multiple "ptype Overprecise_Object" "" {
-	-re "type = <2-byte fixed point \\(small = 135791357913579/1000000000000000\\)>\r\n$gdb_prompt $" {
-	    pass $gdb_test_name
-	}
-	-re "type = delta 0.135791\r\n$gdb_prompt $" {
-	    # The (legacy) output we obtain when the compiler described
-	    # our fixed point types using the GNAT encodings rather than
-	    # standard DWARF.  OK as well.
-	    pass $gdb_test_name
-	}
-    }
+    gdb_test "ptype Overprecise_Object" \
+	"type = <2-byte fixed point \\(small = 135791357913579/1000000000000000\\)>"
 
     # FP*_Var...
 
     gdb_test "print fp1_var" \
 	" = 0.25"
 
-    gdb_test_multiple "ptype fp1_var" "" {
-	-re "type = <1-byte fixed point \\(small = 1/16\\)>\r\n$gdb_prompt $" {
-	    pass $gdb_test_name
-	}
-	-re "type = delta 0\\.1 <'small = 0\\.0625>\r\n$gdb_prompt $" {
-	    # The (legacy) output we obtain when the compiler described
-	    # our fixed point types using the GNAT encodings rather than
-	    # standard DWARF.  OK as well.
-	    pass $gdb_test_name
-	}
-    }
+    gdb_test "ptype fp1_var" "type = <1-byte fixed point \\(small = 1/16\\)>"
 
     gdb_test "print fp2_var" \
 	" = -0.01"
 
-    gdb_test_multiple "ptype fp2_var" "" {
-	-re "type = <8-byte fixed point \\(small = 1/100\\)>\r\n$gdb_prompt $" {
-	    pass $gdb_test_name
-	}
-	-re "type = delta 0\\.01\r\n$gdb_prompt $" {
-	    # The (legacy) output we obtain when the compiler described
-	    # our fixed point types using the GNAT encodings rather than
-	    # standard DWARF.  OK as well.
-	    pass $gdb_test_name
-	}
-    }
+    gdb_test "ptype fp2_var" "type = <8-byte fixed point \\(small = 1/100\\)>"
 
     gdb_test "print fp3_var" \
 	" = 0.1"
 
-    gdb_test_multiple "ptype fp3_var" "" {
-	-re "type = <1-byte fixed point \\(small = 1/30\\)>\r\n$gdb_prompt $" {
-	    pass $gdb_test_name
-	}
-	-re "type = delta 0\\.1 <'small = 0\\.0333333>\r\n$gdb_prompt $" {
-	    # The (legacy) output we obtain when the compiler described
-	    # our fixed point types using the GNAT encodings rather than
-	    # standard DWARF.  OK as well.
-	    pass $gdb_test_name
-	}
-    }
+    gdb_test "ptype fp3_var" "type = <1-byte fixed point \\(small = 1/30\\)>"
+
+    gdb_test "print fp2_var + 0" \
+	" = -0.01"
+    gdb_test "print 0 + fp2_var" \
+	" = -0.01"
+    gdb_test "print fp2_var - 0" \
+	" = -0.01"
+
+    set fp4 "= 2e-07"
+    gdb_test "print fp4_var" $fp4
+    gdb_test "print fp4_var * 1" $fp4
+    gdb_test "print 1 * fp4_var" $fp4
+    gdb_test "print fp4_var / 1" $fp4
 
-    # One of the benefits of minimal encoding is that operations work
-    # a bit better.
-    if {$scenario == "minimal"} {
-	gdb_test "print fp2_var + 0" \
-	    " = -0.01"
-	gdb_test "print 0 + fp2_var" \
-	    " = -0.01"
-	gdb_test "print fp2_var - 0" \
-	    " = -0.01"
-
-	set fp4 "= 2e-07"
-	gdb_test "print fp4_var" $fp4
-	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"
-	}
+    # This only started working in GCC 11.
+    if {$scenario == "minimal" && [test_compiler_info {gcc-11-*}]} {
+	gdb_test "print fp5_var" " = 3e-19"
     }
 }
-- 
2.26.2


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] Rewrite GNAT-encoded fixed point types in DWARF reader
  2021-02-10 19:19 [PATCH] Rewrite GNAT-encoded fixed point types in DWARF reader Tom Tromey
@ 2021-03-02 20:08 ` Tom Tromey
  0 siblings, 0 replies; 2+ messages in thread
From: Tom Tromey @ 2021-03-02 20:08 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

>>>>> "Tom" == Tom Tromey <tromey@adacore.com> writes:

Tom> gdb currently supports two different styles of fixed-point.  The
Tom> original style, where fixed point types are "GNAT encoded", is handled
Tom> primarily in the Ada code.  The newer style, encoded using DWARF, is
Tom> handled by the core of gdb.

Tom> This patch changes gdb to read the GNAT encodings in the DWARF reader
Tom> as well.  This removes some code and unifies the two paths.  As a
Tom> result, GNAT-encoded fixed-point now works a bit better.

Tom> One possible drawback of this change is that, if someone uses stabs,
Tom> then fixed-point might now stop working.  I consider stabs to be fully
Tom> obsolete, though, so I don't intend to address this.

I'm checking this in now.

Tom

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-03-02 20:08 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-10 19:19 [PATCH] Rewrite GNAT-encoded fixed point types in DWARF reader Tom Tromey
2021-03-02 20:08 ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).