X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ff-lang.c;h=022918efa2d928fdfbf87a354d596adad3f671bc;hb=401e101e0274d401e90e50cd8280a9ff36006477;hp=5beb46c5f3174b2737bbf920a51fd6fe0804e143;hpb=9dad4a58a1bddeb1cc2ec8b3782d7463b03b7b4b;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/f-lang.c b/gdb/f-lang.c index 5beb46c5f3..022918efa2 100644 --- a/gdb/f-lang.c +++ b/gdb/f-lang.c @@ -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,12 +243,371 @@ 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) { - /* Currently no special handling is required. */ - return evaluate_subexp_standard (expect_type, exp, pos, noside); + struct value *arg1 = NULL, *arg2 = NULL; + enum exp_opcode op; + int pc; + struct type *type; + + pc = *pos; + *pos += 1; + op = exp->elts[pc].opcode; + + switch (op) + { + default: + *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 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); + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + case TYPE_CODE_MODULE: + case TYPE_CODE_FUNC: + error (_("argument to kind must be an intrinsic type")); + } + + if (!TYPE_TARGET_TYPE (type)) + return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, + TYPE_LENGTH (type)); + return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, + TYPE_LENGTH (TYPE_TARGET_TYPE(type))); + } + + /* Should be unreachable. */ + 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[] = @@ -258,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 }; @@ -283,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 */ @@ -310,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 * @@ -328,10 +690,10 @@ 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_integer_type (gdbarch, TARGET_CHAR_BIT, 0, "character"); + = arch_type (gdbarch, TYPE_CODE_CHAR, TARGET_CHAR_BIT, "character"); builtin_f_type->builtin_logical_s1 = arch_boolean_type (gdbarch, TARGET_CHAR_BIT, 1, "logical*1"); @@ -340,6 +702,10 @@ build_fortran_types (struct gdbarch *gdbarch) = arch_integer_type (gdbarch, gdbarch_short_bit (gdbarch), 0, "integer*2"); + builtin_f_type->builtin_integer_s8 + = arch_integer_type (gdbarch, gdbarch_long_long_bit (gdbarch), 0, + "integer*8"); + builtin_f_type->builtin_logical_s2 = arch_boolean_type (gdbarch, gdbarch_short_bit (gdbarch), 1, "logical*2"); @@ -362,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",