/* Fortran language support routines for GDB, the GNU debugger.
- Copyright (C) 1993-2019 Free Software Foundation, Inc.
+ Copyright (C) 1993-2020 Free Software Foundation, Inc.
Contributed by Motorola. Adapted from the C parser by Farooq Butt
(fmbutt@engage.sps.mot.com).
#include "charset.h"
#include "c-lang.h"
#include "target-float.h"
+#include "gdbarch.h"
#include <math.h>
encoding = target_charset (get_type_arch (type));
break;
case 4:
- if (gdbarch_byte_order (get_type_arch (type)) == BFD_ENDIAN_BIG)
+ if (type_byte_order (type) == BFD_ENDIAN_BIG)
encoding = "UTF-32BE";
else
encoding = "UTF-32LE";
}
/* Special expression evaluation cases for Fortran. */
-struct value *
+
+static 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;
}
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);
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
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;
}
}
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;
}
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
f_printstr, /* function to print string constant */
f_emit_char, /* Function to print a single character */
f_print_type, /* Print a type using appropriate syntax */
- default_print_typedef, /* Print a typedef using appropriate syntax */
+ f_print_typedef, /* Print a typedef using appropriate syntax */
f_val_print, /* Print a value using appropriate syntax */
c_value_print, /* FIXME */
default_read_var_value, /* la_read_var_value */
f_language_arch_info,
default_print_array_index,
default_pass_by_reference,
- default_get_string,
c_watch_location_expression,
- NULL, /* la_get_symbol_name_matcher */
+ cp_get_symbol_name_matcher, /* la_get_symbol_name_matcher */
iterate_over_symbols,
- default_search_name_hash,
+ cp_search_name_hash,
&default_varobj_ops,
NULL,
NULL,
= GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_f_type);
builtin_f_type->builtin_void
- = arch_type (gdbarch, TYPE_CODE_VOID, TARGET_CHAR_BIT, "VOID");
+ = arch_type (gdbarch, TYPE_CODE_VOID, TARGET_CHAR_BIT, "void");
builtin_f_type->builtin_character
= arch_type (gdbarch, TYPE_CODE_CHAR, TARGET_CHAR_BIT, "character");
builtin_f_type->builtin_real_s8
= arch_float_type (gdbarch, gdbarch_double_bit (gdbarch),
"real*8", gdbarch_double_format (gdbarch));
- builtin_f_type->builtin_real_s16
- = arch_float_type (gdbarch, gdbarch_long_double_bit (gdbarch),
- "real*16", gdbarch_long_double_format (gdbarch));
+ auto fmt = gdbarch_floatformat_for_type (gdbarch, "real(kind=16)", 128);
+ if (fmt != nullptr)
+ builtin_f_type->builtin_real_s16
+ = arch_float_type (gdbarch, 128, "real*16", fmt);
+ else if (gdbarch_long_double_bit (gdbarch) == 128)
+ builtin_f_type->builtin_real_s16
+ = arch_float_type (gdbarch, gdbarch_long_double_bit (gdbarch),
+ "real*16", gdbarch_long_double_format (gdbarch));
+ else
+ builtin_f_type->builtin_real_s16
+ = arch_type (gdbarch, TYPE_CODE_ERROR, 128, "real*16");
builtin_f_type->builtin_complex_s8
= arch_complex_type (gdbarch, "complex*8",