[pushed/v2 9/9] Add support for fixed-point type comparison operators

Joel Brobecker
2020-11-15T08:36:25Z

This patch adds support for binary comparison operators with
fixed-point type values.

gdb/ChangeLog:

* valarith.c (fixed_point_binop): Add BINOP_EQUAL and BINOP_LESS
handling.
(value_less): Add fixed-point handling.

gdb/testsuite/ChangeLog:

* gdb.ada/fixed_cmp.exp: Add -fgnat-encodings=minimal testing.
* gdb.dwarf2/dw2-fixed-point.c (pck__fp1_var2): New global.
(main): Add reference to pck__fp1_var2.
* gdb.dwarf2/dw2-fixed-point.exp: Add comparison operator testing.
---
gdb/ChangeLog | 6 ++
gdb/testsuite/ChangeLog | 7 ++
gdb/testsuite/gdb.ada/fixed_cmp.exp | 2 +-
gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c | 7 ++
gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp | 102 +++++++++++++++++++++++++++
gdb/valarith.c | 15 +++-
6 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e9f0afd..6d0a0c6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>

+ * valarith.c (fixed_point_binop): Add BINOP_EQUAL and BINOP_LESS
+ handling.
+ (value_less): Add fixed-point handling.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* eval.c (binop_promote): Add fixed-point type handling.
* valarith.c (fixed_point_binop): New function.
(scalar_binop): Add fixed-point type handling.
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 3c53f6c..6ecb04c 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,12 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>

+ * gdb.ada/fixed_cmp.exp: Add -fgnat-encodings=minimal testing.
+ * gdb.dwarf2/dw2-fixed-point.c (pck__fp1_var2): New global.
+ (main): Add reference to pck__fp1_var2.
+ * gdb.dwarf2/dw2-fixed-point.exp: Add comparison operator testing.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* gdb.dwarf2/dw2-fixed-point.exp: Add arithmetic tests.

2020-11-15 Joel Brobecker <brobecker@adacore.com>
diff --git a/gdb/testsuite/gdb.ada/fixed_cmp.exp b/gdb/testsuite/gdb.ada/fixed_cmp.exp
index cfdbb1c..e2c88b8 100644
--- a/gdb/testsuite/gdb.ada/fixed_cmp.exp
+++ b/gdb/testsuite/gdb.ada/fixed_cmp.exp
@@ -19,7 +19,7 @@ if { [skip_ada_tests] } { return -1 }

standard_ada_testfile fixed

-foreach_with_prefix gnat_encodings {all} {
+foreach_with_prefix gnat_encodings {all minimal} {
set flags [list debug additional_flags=-fgnat-encodings=$gnat_encodings]

if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $flags] != "" } {
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c
index d9c811c..971a7a8 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c
+++ b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c
@@ -23,6 +23,12 @@
int8_t pck__fp1_var = 4;

/* Simulate an Ada variable declared inside package Pck as follow:
+ type FP1_Type is delta 0.1 range -1.0 .. +1.0;
+ FP1_Var2 : FP1_Type := 0.50;
+ Basically, the same as FP1_Var, but with a different value. */
+int8_t pck__fp1_var2 = 8;
+
+/* Simulate an Ada variable declared inside package Pck as follow:
type FP2_Type is delta 0.01 digits 14;
FP2_Var : FP2_Type := -0.01; */
int32_t pck__fp2_var = -1;
@@ -41,6 +47,7 @@ int
main (void)
{
pck__fp1_var++;
+ pck__fp1_var2++;
pck__fp2_var++;
pck__fp3_var++;
pck__fp1_range_var++;
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
index 0252195..a82a9af 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
@@ -49,6 +49,15 @@ Dwarf::assemble $asm_file {
{external 1 flag}
}

+ DW_TAG_variable {
+ {DW_AT_name pck__fp1_var2}
+ {DW_AT_type :$fp1_base_type}
+ {DW_AT_location {
+ DW_OP_addr [gdb_target_symbol pck__fp1_var2]
+ } SPECIAL_expr}
+ {external 1 flag}
+ }
+
fp2_base_type: DW_TAG_base_type {
{DW_AT_byte_size 1 DW_FORM_sdata}
{DW_AT_encoding @DW_ATE_signed_fixed}
@@ -161,6 +170,99 @@ gdb_test "print pck.fp1_range_var - 0.5" \
gdb_test "print -pck.fp1_var" \
" = -0.25"

+gdb_test "print pck.fp1_var = pck.fp1_var" \
+ " = true"
+
+gdb_test "print pck.fp1_var = pck.fp1_var2" \
+ " = false"
+
+gdb_test "print pck.fp1_var /= pck.fp1_var" \
+ " = false"
+
+gdb_test "print pck.fp1_var /= pck.fp1_var2" \
+ " = true"
+
+gdb_test "print pck.fp1_var < pck.fp1_var" \
+ " = false"
+
+gdb_test "print pck.fp1_var < pck.fp1_var2" \
+ " = true"
+
+gdb_test "print pck.fp1_var <= pck.fp1_var2" \
+ " = true"
+
+gdb_test "print pck.fp1_var <= pck.fp1_var" \
+ " = true"
+
+gdb_test "print pck.fp1_var > pck.fp1_var2" \
+ " = false"
+
+gdb_test "print pck.fp1_var2 > pck.fp1_var" \
+ " = true"
+
+gdb_test "print pck.fp1_var >= pck.fp1_var" \
+ " = true"
+
+gdb_test "print pck.fp1_var >= pck.fp1_var2" \
+ " = false"
+
+# Same as above, but with litterals...
+
+gdb_test "print pck.fp1_var = 0.25" \
+ " = true"
+
+gdb_test "print pck.fp1_var = 0.5" \
+ " = false"
+
+gdb_test "print pck.fp1_var = 1" \
+ " = false"
+
+gdb_test "print pck.fp1_var /= 0.25" \
+ " = false"
+
+gdb_test "print pck.fp1_var /= 0.5" \
+ " = true"
+
+gdb_test "print pck.fp1_var /= 1" \
+ " = true"
+
+gdb_test "print pck.fp1_var < 0.25" \
+ " = false"
+
+gdb_test "print pck.fp1_var < 0.5" \
+ " = true"
+
+gdb_test "print pck.fp1_var < 1" \
+ " = true"
+
+gdb_test "print pck.fp1_var <= 0.25" \
+ " = true"
+
+gdb_test "print pck.fp1_var <= 0.5" \
+ " = true"
+
+gdb_test "print pck.fp1_var <= 1" \
+ " = true"
+
+gdb_test "print pck.fp1_var > 0.25" \
+ " = false"
+
+gdb_test "print pck.fp1_var > 0.5" \
+ " = false"
+
+gdb_test "print pck.fp1_var > 1" \
+ " = false"
+
+gdb_test "print pck.fp1_var >= 0.25" \
+ " = true"
+
+gdb_test "print pck.fp1_var >= 0.5" \
+ " = false"
+
+gdb_test "print pck.fp1_var >= 1" \
+ " = false"
+
+
# Set the language to LANG and do a ptype test on pck__fp1_var,
# pck__fp2_var and pck__fp3_var, verifying that the output matches
# FP1_RE, FP2_RE, FP2_RE (resp.).
diff --git a/gdb/valarith.c b/gdb/valarith.c
index 65a6f13..f4497cd 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -890,7 +890,9 @@ fixed_point_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
{
struct type *type1 = check_typedef (value_type (arg1));
struct type *type2 = check_typedef (value_type (arg2));
+ const struct language_defn *language = current_language;

+ struct gdbarch *gdbarch = get_type_arch (type1);
struct value *val;

gdb_assert (is_fixed_point_type (type1) || is_fixed_point_type (type2));
@@ -952,6 +954,16 @@ fixed_point_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
INIT_VAL_WITH_FIXED_POINT_VAL (res);
break;

+ case BINOP_EQUAL:
+ val = value_from_ulongest (language_bool_type (language, gdbarch),
+ mpq_cmp (v1.val, v2.val) == 0 ? 1 : 0);
+ break;
+
+ case BINOP_LESS:
+ val = value_from_ulongest (language_bool_type (language, gdbarch),
+ mpq_cmp (v1.val, v2.val) < 0 ? 1 : 0);
+ break;
+
default:
error (_("Integer-only operation on fixed point number."));
}
@@ -1774,7 +1786,8 @@ value_less (struct value *arg1, struct value *arg2)
is_int1 = is_integral_type (type1);
is_int2 = is_integral_type (type2);

- if (is_int1 && is_int2)
+ if ((is_int1 && is_int2)
+ || (is_fixed_point_type (type1) && is_fixed_point_type (type2)))
return longest_to_int (value_as_long (value_binop (arg1, arg2,
BINOP_LESS)));
else if ((is_floating_value (arg1) || is_int1)
--
2.1.4