Patchwork [PUSHED,10/11] gdb/fortran: Add support for the ABS intrinsic function

login
register
mail settings
Submitter Andrew Burgess
Date March 6, 2019, 6:15 p.m.
Message ID <739027546fc7a430867d9d6dd2bf6b8e34e04c94.1551895529.git.andrew.burgess@embecosm.com>
Download mbox | patch
Permalink /patch/31753/
State New
Headers show

Comments

Andrew Burgess - March 6, 2019, 6:15 p.m.
Adds support for the abs intrinsic function, this requires adding a
new pattern to the Fortran parser.  Currently only float and integer
argument types are supported to ABS, complex is still not supported,
this can be added later if needed.

gdb/ChangeLog:

	* f-exp.y: New token, UNOP_INTRINSIC.
	(exp): New pattern using UNOP_INTRINSIC token.
	(f77_keywords): Add 'abs' keyword.
	* f-lang.c: Add 'target-float.h' and 'math.h' includes.
	(value_from_host_double): New function.
	(evaluate_subexp_f): Support UNOP_ABS.

gdb/testsuite/ChangeLog:

	* gdb.fortran/intrinsics.exp: Extend to cover ABS.
---
 gdb/ChangeLog                            | 11 +++++++++
 gdb/f-exp.y                              |  8 ++++++-
 gdb/f-lang.c                             | 39 ++++++++++++++++++++++++++++++++
 gdb/testsuite/ChangeLog                  |  4 ++++
 gdb/testsuite/gdb.fortran/intrinsics.exp |  9 ++++++++
 5 files changed, 70 insertions(+), 1 deletion(-)
Tom Tromey - March 6, 2019, 7:11 p.m.
>>>>> "Andrew" == Andrew Burgess <andrew.burgess@embecosm.com> writes:

Andrew> Adds support for the abs intrinsic function, this requires adding a
Andrew> new pattern to the Fortran parser.  Currently only float and integer
Andrew> argument types are supported to ABS, complex is still not supported,
Andrew> this can be added later if needed.

Sorry for not looking at these earlier...

Andrew> +/* Create and return a value object of TYPE containing the value D.  The
Andrew> +   TYPE must be of TYPE_CODE_FLT, and must be large enough to hold D once
Andrew> +   it is converted to target format.  */
Andrew> +
Andrew> +static struct value *
Andrew> +value_from_host_double (struct type *type, double d)
Andrew> +{
Andrew> +  struct value *value = allocate_value (type);
Andrew> +  gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
Andrew> +  target_float_from_host_double (value_contents_raw (value),
Andrew> +                                 value_type (value), d);
Andrew> +  return value;

This seems reasonable to move to value.c.  At least py-value.c could use it.
I can do that if you also think it's worthwhile.

Tom

Patch

diff --git a/gdb/f-exp.y b/gdb/f-exp.y
index d256ff14c1e..88c685a0af3 100644
--- a/gdb/f-exp.y
+++ b/gdb/f-exp.y
@@ -168,6 +168,7 @@  static int parse_number (struct parser_state *, const char *, int,
 %token <voidval> DOLLAR_VARIABLE
 
 %token <opcode> ASSIGN_MODIFY
+%token <opcode> UNOP_INTRINSIC
 
 %left ','
 %left ABOVE_COMMA
@@ -252,6 +253,10 @@  exp	:	exp '('
 					      OP_F77_UNDETERMINED_ARGLIST); }
 	;
 
+exp	:	UNOP_INTRINSIC '(' exp ')'
+			{ write_exp_elt_opcode (pstate, $1); }
+	;
+
 arglist	:
 	;
 
@@ -945,7 +950,8 @@  static const struct token f77_keywords[] =
   { "real", REAL_KEYWORD, BINOP_END, true },
   /* The following correspond to actual functions in Fortran and are case
      insensitive.  */
-  { "kind", KIND, BINOP_END, false }
+  { "kind", KIND, BINOP_END, false },
+  { "abs", UNOP_INTRINSIC, UNOP_ABS, false }
 };
 
 /* Implementation of a dynamically expandable buffer for processing input
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index c329d602e24..24f0e61a46b 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -34,7 +34,9 @@ 
 #include "cp-support.h"
 #include "charset.h"
 #include "c-lang.h"
+#include "target-float.h"
 
+#include <math.h>
 
 /* Local functions */
 
@@ -239,6 +241,20 @@  f_collect_symbol_completion_matches (completion_tracker &tracker,
 						      text, word, ":", code);
 }
 
+/* Create and return a value object of TYPE containing the value D.  The
+   TYPE must be of TYPE_CODE_FLT, and must be large enough to hold D once
+   it is converted to target format.  */
+
+static struct value *
+value_from_host_double (struct type *type, double d)
+{
+  struct value *value = allocate_value (type);
+  gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
+  target_float_from_host_double (value_contents_raw (value),
+                                 value_type (value), d);
+  return value;
+}
+
 /* Special expression evaluation cases for Fortran.  */
 struct value *
 evaluate_subexp_f (struct type *expect_type, struct expression *exp,
@@ -259,6 +275,29 @@  evaluate_subexp_f (struct type *expect_type, struct expression *exp,
       *pos -= 1;
       return evaluate_subexp_standard (expect_type, exp, pos, noside);
 
+    case UNOP_ABS:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+	return eval_skip_value (exp);
+      type = value_type (arg1);
+      switch (TYPE_CODE (type))
+	{
+	case TYPE_CODE_FLT:
+	  {
+	    double d
+	      = fabs (target_float_to_host_double (value_contents (arg1),
+						   value_type (arg1)));
+	    return value_from_host_double (type, d);
+	  }
+	case TYPE_CODE_INT:
+	  {
+	    LONGEST l = value_as_long (arg1);
+	    l = llabs (l);
+	    return value_from_longest (type, l);
+	  }
+	}
+      error (_("ABS of type %s not supported"), TYPE_SAFE_NAME (type));
+
     case UNOP_KIND:
       arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
       type = value_type (arg1);
diff --git a/gdb/testsuite/gdb.fortran/intrinsics.exp b/gdb/testsuite/gdb.fortran/intrinsics.exp
index 674f299c428..00396c74c2f 100644
--- a/gdb/testsuite/gdb.fortran/intrinsics.exp
+++ b/gdb/testsuite/gdb.fortran/intrinsics.exp
@@ -40,3 +40,12 @@  gdb_test "p kind (l2)" " = 2"
 gdb_test "p kind (l4)" " = 4"
 gdb_test "p kind (l8)" " = 8"
 gdb_test "p kind (s1)" "argument to kind must be an intrinsic type"
+
+# Test ABS
+
+gdb_test "p abs (-11)" " = 11"
+gdb_test "p abs (11)" " = 11"
+# Use `$decimal` to match here as we depend on host floating point
+# rounding, which can vary.
+gdb_test "p abs (-9.1)" " = 9.$decimal"
+gdb_test "p abs (9.1)" " = 9.$decimal"