From 50eff16b85073287b1b184a257a8fd80e960fe02 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Mon, 6 Nov 2017 15:59:36 +0100 Subject: [PATCH] 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 * 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. --- 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 6d3c6a1aca6..ad8e0297610 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,27 @@ +2017-11-06 Ulrich Weigand + + * 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 * target-float.c: Include . diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index b8636e6347f..32b978c33cf 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 a47fe828f4f..d15fbbdd421 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 0d1f9dc117c..9d233028650 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 @@ -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 8095eede721..91dc301af5f 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) -- 2.30.2