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.
This commit is contained in:
parent
66c02b9ed1
commit
50eff16b85
5 changed files with 95 additions and 74 deletions
|
@ -1,3 +1,27 @@
|
|||
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>.
|
||||
|
|
107
gdb/ada-lang.c
107
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;
|
||||
struct value *scale = ada_scaling_factor (value_type (arg));
|
||||
arg = value_cast (value_type (scale), arg);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
struct type *scale_type = ada_scaling_type (type);
|
||||
|
||||
/* 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;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
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);
|
||||
|
||||
fprintf_filtered (stream, TYPE_LENGTH (type) < 4 ? "%.11g" : "%.17g",
|
||||
(double) ada_fixed_to_float (type, v));
|
||||
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)
|
||||
|
|
Loading…
Add table
Reference in a new issue