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] Target FP: Perform Ada fixed-point scaling in target format


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

commit 50eff16b85073287b1b184a257a8fd80e960fe02
Author: Ulrich Weigand <ulrich.weigand@de.ibm.com>
Date:   Mon Nov 6 15:59:36 2017 +0100

    Target FP: Perform Ada fixed-point scaling in target format
    
    One of the few still remaining uses of DOUBLEST in GDB is the Ada front-end
    code that handles scaling of Ada fixed-point types.  The target format for
    those types is some integer format; to convert those values to standard
    floating-point representation, that integer needs to be multiplied by a
    rational scale factor, given as a pair of numerator and denominator.
    
    To avoid having to deal with long integer arithmetic, the current Ada
    front-end code currently performs those scaling operations in host
    DOUBLEST arithmetic.  To eliminate this use of DOUBLEST, this patch
    changes the front-end to instead perform those operations in the
    *target* floating-point format (chosing to use the target "long double").
    
    The implementation is mostly straight-forward, using value_cast and
    value_binop to perform the target operations.
    
    Scanning in the scale numerator and denominator is now done into
    a host "long long" instead of a DOUBLEST, which should be large
    enough to hold all possible values.  (Otherwise, this can be replaced
    by target-format target_float_from_string operations as well.)
    
    Printing fixed-point types and values should be completely unchanges,
    using target_float_to_string with the same format strings as current code.
    
    gdb/ChangeLog:
    2017-11-06  Ulrich Weigand  <uweigand@de.ibm.com>
    
    	* ada-lang.c (cast_to_fixed): Reimplement in target arithmetic.
    	(cast_from_fixed): Likewise.
    	(ada_scaling_type): New function.
    	(ada_delta): Return value instead of DOUBLEST.  Perform target
    	arithmetic instead of host arithmetic.
    	(scaling_factor): Rename to ...
    	(ada_scaling_factor) ... this.  Make non-static.  Return value instead
    	of DOUBLEST.  Perform target arithmetic instead of host arithmetic.
    	(ada_fixed_to_float): Remove.
    	(ada_float_to_fixed): Remove.
    	* ada-lang.h (ada_fixed_to_float): Remove.
    	(ada_float_to_fixed): Remove.
    	(ada_delta): Return value instead of DOUBLEST.
    	(ada_scaling_factor): Add prototype.
    
    	* ada-typeprint.c: Include "target-float.h".
    	(print_fixed_point_type): Perform target arithmetic instead of
    	host arithmetic.
    	* ada-valprint.c: Include "target-float.h".
    	(ada_val_print_num): Perform target arithmetic instead of
    	host arithmetic for fixed-point types.

Diff:
---
 gdb/ChangeLog       |  24 ++++++++++++
 gdb/ada-lang.c      | 109 ++++++++++++++++++++++------------------------------
 gdb/ada-lang.h      |   6 +--
 gdb/ada-typeprint.c |  20 +++++++---
 gdb/ada-valprint.c  |  14 +++++--
 5 files changed, 97 insertions(+), 76 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6d3c6a1..ad8e029 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,29 @@
 2017-11-06  Ulrich Weigand  <uweigand@de.ibm.com>
 
+	* ada-lang.c (cast_to_fixed): Reimplement in target arithmetic.
+	(cast_from_fixed): Likewise.
+	(ada_scaling_type): New function.
+	(ada_delta): Return value instead of DOUBLEST.  Perform target
+	arithmetic instead of host arithmetic.
+	(scaling_factor): Rename to ...
+	(ada_scaling_factor) ... this.  Make non-static.  Return value instead
+	of DOUBLEST.  Perform target arithmetic instead of host arithmetic.
+	(ada_fixed_to_float): Remove.
+	(ada_float_to_fixed): Remove.
+	* ada-lang.h (ada_fixed_to_float): Remove.
+	(ada_float_to_fixed): Remove.
+	(ada_delta): Return value instead of DOUBLEST.
+	(ada_scaling_factor): Add prototype.
+
+	* ada-typeprint.c: Include "target-float.h".
+	(print_fixed_point_type): Perform target arithmetic instead of
+	host arithmetic.
+	* ada-valprint.c: Include "target-float.h".
+	(ada_val_print_num): Perform target arithmetic instead of
+	host arithmetic for fixed-point types.
+
+2017-11-06  Ulrich Weigand  <uweigand@de.ibm.com>
+
 	* target-float.c: Include <math.h>.
 	(floatformat_binop): New function.
 	(floatformat_compare): Likewise.
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index b8636e6..32b978c 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -9567,33 +9567,29 @@ unwrap_value (struct value *val)
 }
 
 static struct value *
-cast_to_fixed (struct type *type, struct value *arg)
+cast_from_fixed (struct type *type, struct value *arg)
 {
-  LONGEST val;
-
-  if (type == value_type (arg))
-    return arg;
-  else if (ada_is_fixed_point_type (value_type (arg)))
-    val = ada_float_to_fixed (type,
-                              ada_fixed_to_float (value_type (arg),
-                                                  value_as_long (arg)));
-  else
-    {
-      DOUBLEST argd = value_as_double (arg);
-
-      val = ada_float_to_fixed (type, argd);
-    }
+  struct value *scale = ada_scaling_factor (value_type (arg));
+  arg = value_cast (value_type (scale), arg);
 
-  return value_from_longest (type, val);
+  arg = value_binop (arg, scale, BINOP_MUL);
+  return value_cast (type, arg);
 }
 
 static struct value *
-cast_from_fixed (struct type *type, struct value *arg)
+cast_to_fixed (struct type *type, struct value *arg)
 {
-  DOUBLEST val = ada_fixed_to_float (value_type (arg),
-                                     value_as_long (arg));
+  if (type == value_type (arg))
+    return arg;
 
-  return value_from_double (type, val);
+  struct value *scale = ada_scaling_factor (type);
+  if (ada_is_fixed_point_type (value_type (arg)))
+    arg = cast_from_fixed (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
@@ -11475,68 +11471,57 @@ ada_is_system_address_type (struct type *type)
 }
 
 /* Assuming that TYPE is the representation of an Ada fixed-point
-   type, return its delta, or -1 if the type is malformed and the
+   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 (get_type_arch (type))->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.  */
 
-DOUBLEST
+struct value *
 ada_delta (struct type *type)
 {
   const char *encoding = fixed_type_info (type);
-  DOUBLEST num, den;
-
-  /* Strictly speaking, num and den are encoded as integer.  However,
-     they may not fit into a long, and they will have to be converted
-     to DOUBLEST anyway.  So scan them as DOUBLEST.  */
-  if (sscanf (encoding, "_%" DOUBLEST_SCAN_FORMAT "_%" DOUBLEST_SCAN_FORMAT,
-	      &num, &den) < 2)
-    return -1.0;
+  struct type *scale_type = ada_scaling_type (type);
+
+  long long num, den;
+
+  if (sscanf (encoding, "_%lld_%lld", &num, &den) < 2)
+    return nullptr;
   else
-    return num / den;
+    return value_binop (value_from_longest (scale_type, num),
+			value_from_longest (scale_type, den), BINOP_DIV);
 }
 
 /* Assuming that ada_is_fixed_point_type (TYPE), return the scaling
    factor ('SMALL value) associated with the type.  */
 
-static DOUBLEST
-scaling_factor (struct type *type)
+struct value *
+ada_scaling_factor (struct type *type)
 {
   const char *encoding = fixed_type_info (type);
-  DOUBLEST num0, den0, num1, den1;
+  struct type *scale_type = ada_scaling_type (type);
+
+  long long num0, den0, num1, den1;
   int n;
 
-  /* Strictly speaking, num's and den's are encoded as integer.  However,
-     they may not fit into a long, and they will have to be converted
-     to DOUBLEST anyway.  So scan them as DOUBLEST.  */
-  n = sscanf (encoding,
-	      "_%" DOUBLEST_SCAN_FORMAT "_%" DOUBLEST_SCAN_FORMAT
-	      "_%" DOUBLEST_SCAN_FORMAT "_%" DOUBLEST_SCAN_FORMAT,
+  n = sscanf (encoding, "_%lld_%lld_%lld_%lld",
 	      &num0, &den0, &num1, &den1);
 
   if (n < 2)
-    return 1.0;
+    return value_from_longest (scale_type, 1);
   else if (n == 4)
-    return num1 / den1;
+    return value_binop (value_from_longest (scale_type, num1),
+			value_from_longest (scale_type, den1), BINOP_DIV);
   else
-    return num0 / den0;
-}
-
-
-/* Assuming that X is the representation of a value of fixed-point
-   type TYPE, return its floating-point equivalent.  */
-
-DOUBLEST
-ada_fixed_to_float (struct type *type, LONGEST x)
-{
-  return (DOUBLEST) x *scaling_factor (type);
-}
-
-/* The representation of a fixed-point value of type TYPE
-   corresponding to the value X.  */
-
-LONGEST
-ada_float_to_fixed (struct type *type, DOUBLEST x)
-{
-  return (LONGEST) (x / scaling_factor (type) + 0.5);
+    return value_binop (value_from_longest (scale_type, num0),
+			value_from_longest (scale_type, den0), BINOP_DIV);
 }
 
 
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index a47fe82..d15fbbd 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -305,11 +305,9 @@ extern int ada_is_fixed_point_type (struct type *);
 
 extern int ada_is_system_address_type (struct type *);
 
-extern DOUBLEST ada_delta (struct type *);
+extern struct value *ada_delta (struct type *);
 
-extern DOUBLEST ada_fixed_to_float (struct type *, LONGEST);
-
-extern LONGEST ada_float_to_fixed (struct type *, DOUBLEST);
+extern struct value *ada_scaling_factor (struct type *);
 
 extern struct type *ada_system_address_type (void);
 
diff --git a/gdb/ada-typeprint.c b/gdb/ada-typeprint.c
index 0d1f9dc..9d23302 100644
--- a/gdb/ada-typeprint.c
+++ b/gdb/ada-typeprint.c
@@ -31,6 +31,7 @@
 #include "demangle.h"
 #include "c-lang.h"
 #include "typeprint.h"
+#include "target-float.h"
 #include "ada-lang.h"
 #include <ctype.h>
 
@@ -356,16 +357,23 @@ print_enum_type (struct type *type, struct ui_file *stream)
 static void
 print_fixed_point_type (struct type *type, struct ui_file *stream)
 {
-  DOUBLEST delta = ada_delta (type);
-  DOUBLEST small = ada_fixed_to_float (type, 1);
+  struct value *delta = ada_delta (type);
+  struct value *small = ada_scaling_factor (type);
 
-  if (delta < 0.0)
+  if (delta == nullptr)
     fprintf_filtered (stream, "delta ??");
   else
     {
-      fprintf_filtered (stream, "delta %g", (double) delta);
-      if (delta != small)
-	fprintf_filtered (stream, " <'small = %g>", (double) small);
+      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());
+	}
     }
 }
 
diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
index 8095eed..91dc301 100644
--- a/gdb/ada-valprint.c
+++ b/gdb/ada-valprint.c
@@ -31,6 +31,7 @@
 #include "c-lang.h"
 #include "infcall.h"
 #include "objfiles.h"
+#include "target-float.h"
 
 static int print_field_values (struct type *, const gdb_byte *,
 			       int,
@@ -796,10 +797,15 @@ ada_val_print_num (struct type *type, const gdb_byte *valaddr,
 {
   if (ada_is_fixed_point_type (type))
     {
-      LONGEST v = unpack_long (type, valaddr + offset_aligned);
-
-      fprintf_filtered (stream, TYPE_LENGTH (type) < 4 ? "%.11g" : "%.17g",
-			(double) ada_fixed_to_float (type, v));
+      struct value *scale = ada_scaling_factor (type);
+      struct value *v = value_from_contents (type, valaddr + offset_aligned);
+      v = value_cast (value_type (scale), v);
+      v = value_binop (v, scale, BINOP_MUL);
+
+      const char *fmt = TYPE_LENGTH (type) < 4 ? "%.11g" : "%.17g";
+      std::string str
+	= target_float_to_string (value_contents (v), value_type (v), fmt);
+      fputs_filtered (str.c_str (), stream);
       return;
     }
   else if (TYPE_CODE (type) == TYPE_CODE_RANGE)


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