X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Ff-lang.c;h=c7c47cf8dcfeebadb91f76b4a68a1331f531d093;hb=452f10a186cdb18091f590315c55488b871812e3;hp=c329d602e24348189f0737373222fbf626ffe778;hpb=4a270568d93263e4970099456b4efb58466134a6;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/f-lang.c b/gdb/f-lang.c index c329d602e2..c7c47cf8dc 100644 --- a/gdb/f-lang.c +++ b/gdb/f-lang.c @@ -1,6 +1,6 @@ /* 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). @@ -34,7 +34,10 @@ #include "cp-support.h" #include "charset.h" #include "c-lang.h" +#include "target-float.h" +#include "gdbarch.h" +#include /* Local functions */ @@ -56,7 +59,7 @@ f_get_encoding (struct type *type) 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"; @@ -240,11 +243,12 @@ f_collect_symbol_completion_matches (completion_tracker &tracker, } /* 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; @@ -259,7 +263,139 @@ evaluate_subexp_f (struct type *expect_type, struct expression *exp, *pos -= 1; return evaluate_subexp_standard (expect_type, exp, pos, noside); - case UNOP_KIND: + 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 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); @@ -283,6 +419,197 @@ evaluate_subexp_f (struct type *expect_type, struct expression *exp, return nullptr; } +/* Return true if TYPE is a string. */ + +static bool +f_is_string_type_p (struct type *type) +{ + type = check_typedef (type); + return (TYPE_CODE (type) == TYPE_CODE_STRING + || (TYPE_CODE (type) == TYPE_CODE_ARRAY + && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CHAR)); +} + +/* Special expression lengths for Fortran. */ + +static void +operator_length_f (const struct expression *exp, int pc, int *oplenp, + int *argsp) +{ + int oplen = 1; + int args = 0; + + switch (exp->elts[pc - 1].opcode) + { + default: + operator_length_standard (exp, pc, oplenp, argsp); + 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 +print_subexp_f (struct expression *exp, int *pos, + struct ui_file *stream, enum precedence prec) +{ + int pc = *pos; + enum exp_opcode op = exp->elts[pc].opcode; + + switch (op) + { + default: + print_subexp_standard (exp, pos, stream, prec); + return; + + case UNOP_FORTRAN_KIND: + 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; + } +} + +/* Special expression names for Fortran. */ + +static const char * +op_name_f (enum exp_opcode opcode) +{ + switch (opcode) + { + default: + return op_name_standard (opcode); + +#define OP(name) \ + case name: \ + return #name ; +#include "fortran-operator.def" +#undef OP + } +} + +/* Special expression dumping for Fortran. */ + +static int +dump_subexp_body_f (struct expression *exp, + struct ui_file *stream, int elt) +{ + int opcode = exp->elts[elt].opcode; + int oplen, nargs, i; + + switch (opcode) + { + default: + 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; + } + + elt += oplen; + for (i = 0; i < nargs; i += 1) + elt = dump_subexp (exp, stream, elt); + + return elt; +} + +/* Special expression checking for Fortran. */ + +static int +operator_check_f (struct expression *exp, int pos, + int (*objfile_func) (struct objfile *objfile, + void *data), + void *data) +{ + const union exp_element *const elts = exp->elts; + + 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 + will take care of checking each argument. */ + break; + + default: + return operator_check_standard (exp, pos, objfile_func, data); + } + + return 0; +} + static const char *f_extensions[] = { ".f", ".F", ".for", ".FOR", ".ftn", ".FTN", ".fpp", ".FPP", @@ -293,11 +620,11 @@ static const char *f_extensions[] = /* Expression processing for Fortran. */ static const struct exp_descriptor exp_descriptor_f = { - print_subexp_standard, - operator_length_standard, - operator_check_standard, - op_name_standard, - dump_subexp_body_standard, + print_subexp_f, + operator_length_f, + operator_check_f, + op_name_f, + dump_subexp_body_f, evaluate_subexp_f }; @@ -318,7 +645,7 @@ extern const struct language_defn f_language_defn = 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 */ @@ -345,15 +672,15 @@ extern const struct language_defn f_language_defn = 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, - LANG_MAGIC + f_is_string_type_p, + "(...)" /* la_struct_too_deep_ellipsis */ }; static void * @@ -363,7 +690,7 @@ build_fortran_types (struct gdbarch *gdbarch) = 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"); @@ -401,9 +728,17 @@ build_fortran_types (struct gdbarch *gdbarch) 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",