aboutsummaryrefslogtreecommitdiff
path: root/gdb/ada-lang.c
diff options
context:
space:
mode:
authorUlrich Weigand <ulrich.weigand@de.ibm.com>2017-11-06 15:59:36 +0100
committerUlrich Weigand <ulrich.weigand@de.ibm.com>2017-11-06 16:00:12 +0100
commit50eff16b85073287b1b184a257a8fd80e960fe02 (patch)
treea25945447d908edd2a5a0c878b311dfacc205147 /gdb/ada-lang.c
parent66c02b9ed1eabf1d7981c0c27ec9fd3c17fc5d35 (diff)
downloadgdb-50eff16b85073287b1b184a257a8fd80e960fe02.zip
gdb-50eff16b85073287b1b184a257a8fd80e960fe02.tar.gz
gdb-50eff16b85073287b1b184a257a8fd80e960fe02.tar.bz2
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.
Diffstat (limited to 'gdb/ada-lang.c')
-rw-r--r--gdb/ada-lang.c109
1 files changed, 47 insertions, 62 deletions
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);
}