gdb/fortran: Additional builtin procedures
Add some additional builtin procedures for Fortran, these are MOD, CEILING, FLOOR, MODULO, and CMPLX. gdb/ChangeLog: * f-exp.y (BINOP_INTRINSIC): New token. (exp): New parser rule handling BINOP_INTRINSIC. (f77_keywords): Add new builtin procedures. * f-lang.c (evaluate_subexp_f): Handle BINOP_MOD, UNOP_FORTRAN_CEILING, UNOP_FORTRAN_FLOOR, BINOP_FORTRAN_MODULO, BINOP_FORTRAN_CMPLX. (operator_length_f): Handle UNOP_FORTRAN_CEILING, UNOP_FORTRAN_FLOOR, BINOP_FORTRAN_MODULO, BINOP_FORTRAN_CMPLX. (print_unop_subexp_f): New function. (print_binop_subexp_f): New function. (print_subexp_f): Handle UNOP_FORTRAN_CEILING, UNOP_FORTRAN_FLOOR, BINOP_FORTRAN_MODULO, BINOP_FORTRAN_CMPLX. (dump_subexp_body_f): Likewise. (operator_check_f): Likewise. * fortran-operator.def: Add UNOP_FORTRAN_CEILING, UNOP_FORTRAN_FLOOR, BINOP_FORTRAN_MODULO, BINOP_FORTRAN_CMPLX gdb/testsuite/ChangeLog: * gdb.fortran/intrinsics.exp: Extend to cover MOD, CEILING, FLOOR, MODULO, CMPLX.
This commit is contained in:
parent
83228e93ef
commit
b6d03bb2b6
@ -1,3 +1,23 @@
|
||||
2019-04-30 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
Chris January <chris.january@arm.com>
|
||||
David Lecomber <david.lecomber@arm.com>
|
||||
|
||||
* f-exp.y (BINOP_INTRINSIC): New token.
|
||||
(exp): New parser rule handling BINOP_INTRINSIC.
|
||||
(f77_keywords): Add new builtin procedures.
|
||||
* f-lang.c (evaluate_subexp_f): Handle BINOP_MOD, UNOP_FORTRAN_CEILING,
|
||||
UNOP_FORTRAN_FLOOR, BINOP_FORTRAN_MODULO, BINOP_FORTRAN_CMPLX.
|
||||
(operator_length_f): Handle UNOP_FORTRAN_CEILING,
|
||||
UNOP_FORTRAN_FLOOR, BINOP_FORTRAN_MODULO, BINOP_FORTRAN_CMPLX.
|
||||
(print_unop_subexp_f): New function.
|
||||
(print_binop_subexp_f): New function.
|
||||
(print_subexp_f): Handle UNOP_FORTRAN_CEILING, UNOP_FORTRAN_FLOOR,
|
||||
BINOP_FORTRAN_MODULO, BINOP_FORTRAN_CMPLX.
|
||||
(dump_subexp_body_f): Likewise.
|
||||
(operator_check_f): Likewise.
|
||||
* fortran-operator.def: Add UNOP_FORTRAN_CEILING, UNOP_FORTRAN_FLOOR,
|
||||
BINOP_FORTRAN_MODULO, BINOP_FORTRAN_CMPLX
|
||||
|
||||
2019-04-30 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
|
||||
* gdb/expprint.c (dump_subexp_body_standard): Remove use of
|
||||
|
13
gdb/f-exp.y
13
gdb/f-exp.y
@ -174,7 +174,7 @@ static int parse_number (struct parser_state *, const char *, int,
|
||||
%token <voidval> DOLLAR_VARIABLE
|
||||
|
||||
%token <opcode> ASSIGN_MODIFY
|
||||
%token <opcode> UNOP_INTRINSIC
|
||||
%token <opcode> UNOP_INTRINSIC BINOP_INTRINSIC
|
||||
|
||||
%left ','
|
||||
%left ABOVE_COMMA
|
||||
@ -263,6 +263,10 @@ exp : UNOP_INTRINSIC '(' exp ')'
|
||||
{ write_exp_elt_opcode (pstate, $1); }
|
||||
;
|
||||
|
||||
exp : BINOP_INTRINSIC '(' exp ',' exp ')'
|
||||
{ write_exp_elt_opcode (pstate, $1); }
|
||||
;
|
||||
|
||||
arglist :
|
||||
;
|
||||
|
||||
@ -959,7 +963,12 @@ static const struct token f77_keywords[] =
|
||||
/* The following correspond to actual functions in Fortran and are case
|
||||
insensitive. */
|
||||
{ "kind", KIND, BINOP_END, false },
|
||||
{ "abs", UNOP_INTRINSIC, UNOP_ABS, false }
|
||||
{ "abs", UNOP_INTRINSIC, UNOP_ABS, false },
|
||||
{ "mod", BINOP_INTRINSIC, BINOP_MOD, false },
|
||||
{ "floor", UNOP_INTRINSIC, UNOP_FORTRAN_FLOOR, false },
|
||||
{ "ceiling", UNOP_INTRINSIC, UNOP_FORTRAN_CEILING, false },
|
||||
{ "modulo", BINOP_INTRINSIC, BINOP_FORTRAN_MODULO, false },
|
||||
{ "cmplx", BINOP_INTRINSIC, BINOP_FORTRAN_CMPLX, false },
|
||||
};
|
||||
|
||||
/* Implementation of a dynamically expandable buffer for processing input
|
||||
|
180
gdb/f-lang.c
180
gdb/f-lang.c
@ -246,7 +246,7 @@ struct value *
|
||||
evaluate_subexp_f (struct type *expect_type, struct expression *exp,
|
||||
int *pos, enum noside noside)
|
||||
{
|
||||
struct value *arg1 = NULL;
|
||||
struct value *arg1 = NULL, *arg2 = NULL;
|
||||
enum exp_opcode op;
|
||||
int pc;
|
||||
struct type *type;
|
||||
@ -284,6 +284,115 @@ evaluate_subexp_f (struct type *expect_type, struct expression *exp,
|
||||
}
|
||||
error (_("ABS of type %s not supported"), TYPE_SAFE_NAME (type));
|
||||
|
||||
case BINOP_MOD:
|
||||
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
return eval_skip_value (exp);
|
||||
type = value_type (arg1);
|
||||
if (TYPE_CODE (type) != TYPE_CODE (value_type (arg2)))
|
||||
error (_("non-matching types for parameters to MOD ()"));
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_FLT:
|
||||
{
|
||||
double d1
|
||||
= target_float_to_host_double (value_contents (arg1),
|
||||
value_type (arg1));
|
||||
double d2
|
||||
= target_float_to_host_double (value_contents (arg2),
|
||||
value_type (arg2));
|
||||
double d3 = fmod (d1, d2);
|
||||
return value_from_host_double (type, d3);
|
||||
}
|
||||
case TYPE_CODE_INT:
|
||||
{
|
||||
LONGEST v1 = value_as_long (arg1);
|
||||
LONGEST v2 = value_as_long (arg2);
|
||||
if (v2 == 0)
|
||||
error (_("calling MOD (N, 0) is undefined"));
|
||||
LONGEST v3 = v1 - (v1 / v2) * v2;
|
||||
return value_from_longest (value_type (arg1), v3);
|
||||
}
|
||||
}
|
||||
error (_("MOD of type %s not supported"), TYPE_SAFE_NAME (type));
|
||||
|
||||
case UNOP_FORTRAN_CEILING:
|
||||
{
|
||||
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
return eval_skip_value (exp);
|
||||
type = value_type (arg1);
|
||||
if (TYPE_CODE (type) != TYPE_CODE_FLT)
|
||||
error (_("argument to CEILING must be of type float"));
|
||||
double val
|
||||
= target_float_to_host_double (value_contents (arg1),
|
||||
value_type (arg1));
|
||||
val = ceil (val);
|
||||
return value_from_host_double (type, val);
|
||||
}
|
||||
|
||||
case UNOP_FORTRAN_FLOOR:
|
||||
{
|
||||
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
return eval_skip_value (exp);
|
||||
type = value_type (arg1);
|
||||
if (TYPE_CODE (type) != TYPE_CODE_FLT)
|
||||
error (_("argument to FLOOR must be of type float"));
|
||||
double val
|
||||
= target_float_to_host_double (value_contents (arg1),
|
||||
value_type (arg1));
|
||||
val = floor (val);
|
||||
return value_from_host_double (type, val);
|
||||
}
|
||||
|
||||
case BINOP_FORTRAN_MODULO:
|
||||
{
|
||||
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
return eval_skip_value (exp);
|
||||
type = value_type (arg1);
|
||||
if (TYPE_CODE (type) != TYPE_CODE (value_type (arg2)))
|
||||
error (_("non-matching types for parameters to MODULO ()"));
|
||||
/* MODULO(A, P) = A - FLOOR (A / P) * P */
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_INT:
|
||||
{
|
||||
LONGEST a = value_as_long (arg1);
|
||||
LONGEST p = value_as_long (arg2);
|
||||
LONGEST result = a - (a / p) * p;
|
||||
if (result != 0 && (a < 0) != (p < 0))
|
||||
result += p;
|
||||
return value_from_longest (value_type (arg1), result);
|
||||
}
|
||||
case TYPE_CODE_FLT:
|
||||
{
|
||||
double a
|
||||
= target_float_to_host_double (value_contents (arg1),
|
||||
value_type (arg1));
|
||||
double p
|
||||
= target_float_to_host_double (value_contents (arg2),
|
||||
value_type (arg2));
|
||||
double result = fmod (a, p);
|
||||
if (result != 0 && (a < 0.0) != (p < 0.0))
|
||||
result += p;
|
||||
return value_from_host_double (type, result);
|
||||
}
|
||||
}
|
||||
error (_("MODULO of type %s not supported"), TYPE_SAFE_NAME (type));
|
||||
}
|
||||
|
||||
case BINOP_FORTRAN_CMPLX:
|
||||
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
return eval_skip_value (exp);
|
||||
type = builtin_f_type(exp->gdbarch)->builtin_complex_s16;
|
||||
return value_literal_complex (arg1, arg2, type);
|
||||
|
||||
case UNOP_FORTRAN_KIND:
|
||||
arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
|
||||
type = value_type (arg1);
|
||||
@ -335,15 +444,55 @@ operator_length_f (const struct expression *exp, int pc, int *oplenp,
|
||||
return;
|
||||
|
||||
case UNOP_FORTRAN_KIND:
|
||||
case UNOP_FORTRAN_FLOOR:
|
||||
case UNOP_FORTRAN_CEILING:
|
||||
oplen = 1;
|
||||
args = 1;
|
||||
break;
|
||||
|
||||
case BINOP_FORTRAN_CMPLX:
|
||||
case BINOP_FORTRAN_MODULO:
|
||||
oplen = 1;
|
||||
args = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
*oplenp = oplen;
|
||||
*argsp = args;
|
||||
}
|
||||
|
||||
/* Helper for PRINT_SUBEXP_F. Arguments are as for PRINT_SUBEXP_F, except
|
||||
the extra argument NAME which is the text that should be printed as the
|
||||
name of this operation. */
|
||||
|
||||
static void
|
||||
print_unop_subexp_f (struct expression *exp, int *pos,
|
||||
struct ui_file *stream, enum precedence prec,
|
||||
const char *name)
|
||||
{
|
||||
(*pos)++;
|
||||
fprintf_filtered (stream, "%s(", name);
|
||||
print_subexp (exp, pos, stream, PREC_SUFFIX);
|
||||
fputs_filtered (")", stream);
|
||||
}
|
||||
|
||||
/* Helper for PRINT_SUBEXP_F. Arguments are as for PRINT_SUBEXP_F, except
|
||||
the extra argument NAME which is the text that should be printed as the
|
||||
name of this operation. */
|
||||
|
||||
static void
|
||||
print_binop_subexp_f (struct expression *exp, int *pos,
|
||||
struct ui_file *stream, enum precedence prec,
|
||||
const char *name)
|
||||
{
|
||||
(*pos)++;
|
||||
fprintf_filtered (stream, "%s(", name);
|
||||
print_subexp (exp, pos, stream, PREC_SUFFIX);
|
||||
fputs_filtered (",", stream);
|
||||
print_subexp (exp, pos, stream, PREC_SUFFIX);
|
||||
fputs_filtered (")", stream);
|
||||
}
|
||||
|
||||
/* Special expression printing for Fortran. */
|
||||
|
||||
static void
|
||||
@ -360,10 +509,23 @@ print_subexp_f (struct expression *exp, int *pos,
|
||||
return;
|
||||
|
||||
case UNOP_FORTRAN_KIND:
|
||||
(*pos)++;
|
||||
fputs_filtered ("KIND(", stream);
|
||||
print_subexp (exp, pos, stream, PREC_SUFFIX);
|
||||
fputs_filtered (")", stream);
|
||||
print_unop_subexp_f (exp, pos, stream, prec, "KIND");
|
||||
return;
|
||||
|
||||
case UNOP_FORTRAN_FLOOR:
|
||||
print_unop_subexp_f (exp, pos, stream, prec, "FLOOR");
|
||||
return;
|
||||
|
||||
case UNOP_FORTRAN_CEILING:
|
||||
print_unop_subexp_f (exp, pos, stream, prec, "CEILING");
|
||||
return;
|
||||
|
||||
case BINOP_FORTRAN_CMPLX:
|
||||
print_binop_subexp_f (exp, pos, stream, prec, "CMPLX");
|
||||
return;
|
||||
|
||||
case BINOP_FORTRAN_MODULO:
|
||||
print_binop_subexp_f (exp, pos, stream, prec, "MODULO");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -401,6 +563,10 @@ dump_subexp_body_f (struct expression *exp,
|
||||
return dump_subexp_body_standard (exp, stream, elt);
|
||||
|
||||
case UNOP_FORTRAN_KIND:
|
||||
case UNOP_FORTRAN_FLOOR:
|
||||
case UNOP_FORTRAN_CEILING:
|
||||
case BINOP_FORTRAN_CMPLX:
|
||||
case BINOP_FORTRAN_MODULO:
|
||||
operator_length_f (exp, (elt + 1), &oplen, &nargs);
|
||||
break;
|
||||
}
|
||||
@ -425,6 +591,10 @@ operator_check_f (struct expression *exp, int pos,
|
||||
switch (elts[pos].opcode)
|
||||
{
|
||||
case UNOP_FORTRAN_KIND:
|
||||
case UNOP_FORTRAN_FLOOR:
|
||||
case UNOP_FORTRAN_CEILING:
|
||||
case BINOP_FORTRAN_CMPLX:
|
||||
case BINOP_FORTRAN_MODULO:
|
||||
/* Any references to objfiles are held in the arguments to this
|
||||
expression, not within the expression itself, so no additional
|
||||
checking is required here, the outer expression iteration code
|
||||
|
@ -19,4 +19,9 @@
|
||||
|
||||
/* Single operand builtins. */
|
||||
OP (UNOP_FORTRAN_KIND)
|
||||
OP (UNOP_FORTRAN_FLOOR)
|
||||
OP (UNOP_FORTRAN_CEILING)
|
||||
|
||||
/* Two operand builtins. */
|
||||
OP (BINOP_FORTRAN_CMPLX)
|
||||
OP (BINOP_FORTRAN_MODULO)
|
||||
|
@ -1,3 +1,8 @@
|
||||
2019-04-30 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
|
||||
* gdb.fortran/intrinsics.exp: Extend to cover MOD, CEILING, FLOOR,
|
||||
MODULO, CMPLX.
|
||||
|
||||
2019-04-29 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
Richard Bunt <richard.bunt@arm.com>
|
||||
|
||||
|
@ -49,3 +49,38 @@ gdb_test "p abs (11)" " = 11"
|
||||
# rounding, which can vary.
|
||||
gdb_test "p abs (-9.1)" " = 9.$decimal"
|
||||
gdb_test "p abs (9.1)" " = 9.$decimal"
|
||||
|
||||
# Test MOD
|
||||
|
||||
gdb_test "p mod (3.0, 2.0)" " = 1"
|
||||
gdb_test "ptype mod (3.0, 2.0)" "type = real\\*8"
|
||||
gdb_test "p mod (2.0, 3.0)" " = 2"
|
||||
gdb_test "p mod (8, 5)" " = 3"
|
||||
gdb_test "ptype mod (8, 5)" "type = int"
|
||||
gdb_test "p mod (-8, 5)" " = -3"
|
||||
gdb_test "p mod (8, -5)" " = 3"
|
||||
gdb_test "p mod (-8, -5)" " = -3"
|
||||
|
||||
# Test CEILING
|
||||
|
||||
gdb_test "p ceiling (3.7)" " = 4"
|
||||
gdb_test "p ceiling (-3.7)" " = -3"
|
||||
|
||||
# Test FLOOR
|
||||
|
||||
gdb_test "p floor (3.7)" " = 3"
|
||||
gdb_test "p floor (-3.7)" " = -4"
|
||||
|
||||
# Test MODULO
|
||||
|
||||
gdb_test "p MODULO (8,5)" " = 3"
|
||||
gdb_test "ptype MODULO (8,5)" "type = int"
|
||||
gdb_test "p MODULO (-8,5)" " = 2"
|
||||
gdb_test "p MODULO (8,-5)" " = -2"
|
||||
gdb_test "p MODULO (-8,-5)" " = -3"
|
||||
gdb_test "p MODULO (3.0,2.0)" " = 1"
|
||||
gdb_test "ptype MODULO (3.0,2.0)" "type = real\\*8"
|
||||
|
||||
# Test CMPLX
|
||||
|
||||
gdb_test "p CMPLX (4.1, 2.0)" " = \\(4.$decimal,2\\)"
|
||||
|
Loading…
Reference in New Issue
Block a user