From: Stu Grossman Date: Sat, 17 Feb 1996 00:07:35 +0000 (+0000) Subject: * Add native support for long double data type. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=aa220473ba2a00a9392bf5f410bf0e930691d6f1;p=binutils-gdb.git * Add native support for long double data type. * c-exp.y (%union): Change dval to typed_val_float. Use DOUBLEST to store actual data. Change types of INT and FLOAT tokens to typed_val_int and typed_val_float respectively. Create new token DOUBLE_KEYWORD to specify the string `double'. Make production for FLOAT use type determined by parse_number. Add production for "long double" data type. * (parse_number): Use sscanf to parse numbers as float, double or long double depending upon the type of typed_val_float.dval. Also allow user to specify `f' or `l' suffix to explicitly specify float or long double constants. Change typed_val to typed_val_int. * (yylex): Change typed_val to typed_val_int. Also, scan for "double" keyword. * coffread.c (decode_base_type): Add support for T_LNGDBL basic type. * configure, configure.in: Add check for long double support in the host compiler. * defs.h: Define DOUBLEST appropriatly depending on whether HAVE_LONG_DOUBLE (from autoconf) is defined. Also, fix prototypes for functions that handle this type. * expression.h (union exp_element): doubleconst is now type DOUBLEST. * m2-exp.y f-exp.y (%union): dval becomes type DOUBLEST. * findvar.c (extract_floating): Make return value be DOUBLEST. Also, add support for numbers with size of long double. * (store_floating): Arg `val' is now type DOUBLEST. Handle all floating types. * parser-defs.h parse.c (write_exp_elt_dblcst): Arg expelt is now DOUBLEST. * valarith.c (value_binop): Change temp variables v1, v2 and v to type DOUBLEST. Coerce type of result to long double if either op was of that type. * valops.c (value_arg_coerce): If argument type is bigger than double, coerce to long double. * (call_function_by_hand): If REG_STRUCT_HAS_ADDR is defined, and arg type is float and > 8 bytes, then use pointer-to-object calling conventions. * valprint.c (print_floating): Arg doub is now type DOUBLEST. Use appropriate format and precision to print out floating point values. * value.h: Fixup prototypes for value_as_double, value_from_double, and unpack_double to use DOUBLEST. * values.c (record_latest_value): Remove check for invalid floats. Allow history to store them so that people may examine them in hex if they want. * (value_as_double unpack_double): Change return value to DOUBLEST. * (value_from_double): Arg `num' is now DOUBLEST. * (using_struct_return): Use RETURN_VALUE_ON_STACK macro (target specific) to expect certain types to always be returned on the stack. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 13107954699..8114a0a9f3e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,56 @@ +Thu Feb 16 16:02:03 1996 Stu Grossman (grossman@cygnus.com) + + * Add native support for long double data type. + * c-exp.y (%union): Change dval to typed_val_float. Use DOUBLEST + to store actual data. Change types of INT and FLOAT tokens to + typed_val_int and typed_val_float respectively. Create new token + DOUBLE_KEYWORD to specify the string `double'. Make production + for FLOAT use type determined by parse_number. Add production for + "long double" data type. + * (parse_number): Use sscanf to parse numbers as float, double or + long double depending upon the type of typed_val_float.dval. Also + allow user to specify `f' or `l' suffix to explicitly specify + float or long double constants. Change typed_val to + typed_val_int. + * (yylex): Change typed_val to typed_val_int. Also, scan for + "double" keyword. + * coffread.c (decode_base_type): Add support for T_LNGDBL basic + type. + * configure, configure.in: Add check for long double support in + the host compiler. + * defs.h: Define DOUBLEST appropriatly depending on whether + HAVE_LONG_DOUBLE (from autoconf) is defined. Also, fix prototypes + for functions that handle this type. + * expression.h (union exp_element): doubleconst is now type + DOUBLEST. + * m2-exp.y f-exp.y (%union): dval becomes type DOUBLEST. + * findvar.c (extract_floating): Make return value be DOUBLEST. + Also, add support for numbers with size of long double. + * (store_floating): Arg `val' is now type DOUBLEST. Handle all + floating types. + * parser-defs.h parse.c (write_exp_elt_dblcst): Arg expelt is now + DOUBLEST. + * valarith.c (value_binop): Change temp variables v1, v2 and v to + type DOUBLEST. Coerce type of result to long double if either op + was of that type. + * valops.c (value_arg_coerce): If argument type is bigger than + double, coerce to long double. + * (call_function_by_hand): If REG_STRUCT_HAS_ADDR is defined, and + arg type is float and > 8 bytes, then use pointer-to-object + calling conventions. + * valprint.c (print_floating): Arg doub is now type DOUBLEST. + Use appropriate format and precision to print out floating point + values. + * value.h: Fixup prototypes for value_as_double, + value_from_double, and unpack_double to use DOUBLEST. + * values.c (record_latest_value): Remove check for invalid + floats. Allow history to store them so that people may examine + them in hex if they want. + * (value_as_double unpack_double): Change return value to DOUBLEST. + * (value_from_double): Arg `num' is now DOUBLEST. + * (using_struct_return): Use RETURN_VALUE_ON_STACK macro (target + specific) to expect certain types to always be returned on the stack. + Fri Feb 16 14:00:54 1996 Fred Fish * bcache.c, bcache.h: New files to implement a byte cache. diff --git a/gdb/c-exp.y b/gdb/c-exp.y index f6bd88fe530..9070a058168 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -119,8 +119,11 @@ yyerror PARAMS ((char *)); struct { LONGEST val; struct type *type; - } typed_val; - double dval; + } typed_val_int; + struct { + DOUBLEST dval; + struct type *type; + } typed_val_float; struct symbol *sym; struct type *tval; struct stoken sval; @@ -152,8 +155,8 @@ parse_number PARAMS ((char *, int, int, YYSTYPE *)); %type ptype %type array_mod -%token INT -%token FLOAT +%token INT +%token FLOAT /* Both NAME and TYPENAME tokens represent symbols in the input, and both convey their data as strings. @@ -183,7 +186,7 @@ parse_number PARAMS ((char *, int, int, YYSTYPE *)); /* Special type cases, put in to allow the parser to distinguish different legal basetypes. */ -%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD +%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD DOUBLE_KEYWORD %token VARIABLE @@ -473,8 +476,8 @@ exp : NAME_OR_INT { YYSTYPE val; parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val); write_exp_elt_opcode (OP_LONG); - write_exp_elt_type (val.typed_val.type); - write_exp_elt_longcst ((LONGEST)val.typed_val.val); + write_exp_elt_type (val.typed_val_int.type); + write_exp_elt_longcst ((LONGEST)val.typed_val_int.val); write_exp_elt_opcode (OP_LONG); } ; @@ -482,8 +485,8 @@ exp : NAME_OR_INT exp : FLOAT { write_exp_elt_opcode (OP_DOUBLE); - write_exp_elt_type (builtin_type_double); - write_exp_elt_dblcst ($1); + write_exp_elt_type ($1.type); + write_exp_elt_dblcst ($1.dval); write_exp_elt_opcode (OP_DOUBLE); } ; @@ -806,6 +809,10 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */ { $$ = builtin_type_short; } | UNSIGNED SHORT INT_KEYWORD { $$ = builtin_type_unsigned_short; } + | DOUBLE_KEYWORD + { $$ = builtin_type_double; } + | LONG DOUBLE_KEYWORD + { $$ = builtin_type_long_double; } | STRUCT name { $$ = lookup_struct (copy_name ($2), expression_context_block); } @@ -926,8 +933,30 @@ parse_number (p, len, parsed_float, putithere) if (parsed_float) { + char c; + /* It's a float since it contains a point or an exponent. */ - putithere->dval = atof (p); + + if (sizeof (putithere->typed_val_float.dval) <= sizeof (float)) + sscanf (p, "%g", &putithere->typed_val_float.dval); + else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double)) + sscanf (p, "%lg", &putithere->typed_val_float.dval); + else + sscanf (p, "%Lg", &putithere->typed_val_float.dval); + + /* See if it has `f' or `l' suffix (float or long double). */ + + c = tolower (p[len - 1]); + + if (c == 'f') + putithere->typed_val_float.type = builtin_type_float; + else if (c == 'l') + putithere->typed_val_float.type = builtin_type_long_double; + else if (isdigit (c) || c == '.') + putithere->typed_val_float.type = builtin_type_double; + else + return ERROR; + return FLOAT; } @@ -1064,18 +1093,18 @@ parse_number (p, len, parsed_float, putithere) signed_type = builtin_type_long_long; } - putithere->typed_val.val = n; + putithere->typed_val_int.val = n; /* If the high bit of the worked out type is set then this number has to be unsigned. */ if (unsigned_p || (n & high_bit)) { - putithere->typed_val.type = unsigned_type; + putithere->typed_val_int.type = unsigned_type; } else { - putithere->typed_val.type = signed_type; + putithere->typed_val_int.type = signed_type; } return INT; @@ -1175,8 +1204,8 @@ yylex () else if (c == '\'') error ("Empty character constant."); - yylval.typed_val.val = c; - yylval.typed_val.type = builtin_type_char; + yylval.typed_val_int.val = c; + yylval.typed_val_int.type = builtin_type_char; c = *lexptr++; if (c != '\'') @@ -1409,6 +1438,8 @@ yylex () return SIGNED_KEYWORD; if (STREQN (tokstart, "sizeof", 6)) return SIZEOF; + if (STREQN (tokstart, "double", 6)) + return DOUBLE_KEYWORD; break; case 5: if (current_language->la_language == language_cplus diff --git a/gdb/configure b/gdb/configure index 826bea72e7b..7d074cc2bbb 100755 --- a/gdb/configure +++ b/gdb/configure @@ -1295,6 +1295,39 @@ EOF fi + +echo $ac_n "checking for long double""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_c_long_double'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&6 +if test $ac_cv_c_long_double = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_LONG_DOUBLE 1 +EOF + +fi + for ac_func in valloc getpagesize do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 @@ -1302,7 +1335,7 @@ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < EOF @@ -1651,7 +1684,7 @@ rm -f conftest* ac_save_LIBS="$LIBS" LIBS="-l$x_direct_test_library $LIBS" cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <&6 else cat > conftest.$ac_ext < EOF @@ -2090,7 +2123,7 @@ if test "$cross_compiling" = yes; then else cat > conftest.$ac_ext < @@ -2250,7 +2283,7 @@ else ac_cv_c_tclib="-l$installedtcllibroot" else cat > conftest.$ac_ext <&6 else cat > conftest.$ac_ext < EOF @@ -2430,7 +2463,7 @@ if test "$cross_compiling" = yes; then else cat > conftest.$ac_ext < @@ -2611,7 +2644,7 @@ else ac_cv_c_tklib="-l$installedtklibroot" else cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <modifiable) error ("Left operand of assignment is not a modifiable lvalue."); - COERCE_ARRAY (fromval); COERCE_REF (toval); type = VALUE_TYPE (toval); if (VALUE_LVAL (toval) != lval_internalvar) fromval = value_cast (type, fromval); + else + COERCE_ARRAY (fromval); CHECK_TYPEDEF (type); /* If TOVAL is a special machine register requiring conversion @@ -886,10 +887,18 @@ value_arg_coerce (arg, param_type) if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int)) type = builtin_type_int; break; - case TYPE_CODE_FLT: - if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double)) - type = builtin_type_double; - break; + case TYPE_CODE_FLT: + /* coerce float to double, unless the function prototype specifies float */ +#if 0 + if (param_type == 0) +#endif + { + if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double)) + type = builtin_type_double; + else if (TYPE_LENGTH (type) > TYPE_LENGTH (builtin_type_double)) + type = builtin_type_long_double; + } + break; case TYPE_CODE_FUNC: type = lookup_pointer_type (type); break; @@ -1139,7 +1148,10 @@ call_function_by_hand (function, nargs, args) || TYPE_CODE (arg_type) == TYPE_CODE_ARRAY || TYPE_CODE (arg_type) == TYPE_CODE_STRING || TYPE_CODE (arg_type) == TYPE_CODE_BITSTRING - || TYPE_CODE (arg_type) == TYPE_CODE_SET) + || TYPE_CODE (arg_type) == TYPE_CODE_SET + || (TYPE_CODE (arg_type) == TYPE_CODE_FLT + && TYPE_LENGTH (arg_type) > 8) + ) && REG_STRUCT_HAS_ADDR (using_gcc, arg_type)) { CORE_ADDR addr; @@ -1363,6 +1375,23 @@ value_array (lowbound, highbound, elemvec) } } + rangetype = create_range_type ((struct type *) NULL, builtin_type_int, + lowbound, highbound); + arraytype = create_array_type ((struct type *) NULL, + VALUE_TYPE (elemvec[0]), rangetype); + + if (!current_language->c_style_arrays) + { + val = allocate_value (arraytype); + for (idx = 0; idx < nelem; idx++) + { + memcpy (VALUE_CONTENTS_RAW (val) + (idx * typelength), + VALUE_CONTENTS (elemvec[idx]), + typelength); + } + return val; + } + /* Allocate space to store the array in the inferior, and then initialize it by copying in each element. FIXME: Is it worth it to create a local buffer in which to collect each value and then write all the @@ -1377,10 +1406,6 @@ value_array (lowbound, highbound, elemvec) /* Create the array type and set up an array value to be evaluated lazily. */ - rangetype = create_range_type ((struct type *) NULL, builtin_type_int, - lowbound, highbound); - arraytype = create_array_type ((struct type *) NULL, - VALUE_TYPE (elemvec[0]), rangetype); val = value_at_lazy (arraytype, addr); return (val); } diff --git a/gdb/values.c b/gdb/values.c index 991d374a84d..b1776aefb88 100644 --- a/gdb/values.c +++ b/gdb/values.c @@ -239,14 +239,6 @@ record_latest_value (val) { int i; - /* Check error now if about to store an invalid float. We return -1 - to the caller, but allow them to continue, e.g. to print it as "Nan". */ - if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT) - { - unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &i); - if (i) return -1; /* Indicate value not saved in history */ - } - /* We don't want this value to have anything to do with the inferior anymore. In particular, "set $1 = 50" should not affect the variable from which the value was taken, and fast watchpoints should be able to assume that @@ -560,11 +552,11 @@ value_as_long (val) return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val)); } -double +DOUBLEST value_as_double (val) register value_ptr val; { - double foo; + DOUBLEST foo; int inv; foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &inv); @@ -655,7 +647,7 @@ unpack_long (type, valaddr) the returned double is OK to use. Argument is in target format, result is in host format. */ -double +DOUBLEST unpack_double (type, valaddr, invp) struct type *type; char *valaddr; @@ -1268,7 +1260,7 @@ value_from_longest (type, num) value_ptr value_from_double (type, num) struct type *type; - double num; + DOUBLEST num; { register value_ptr val = allocate_value (type); struct type *base_type = check_typedef (type); @@ -1350,6 +1342,14 @@ value_being_returned (valtype, retbuf, struct_return) )) #endif +/* Some fundamental types (such as long double) are returned on the stack for + certain architectures. This macro should return true for any type besides + struct, union or array that gets returned on the stack. */ + +#ifndef RETURN_VALUE_ON_STACK +#define RETURN_VALUE_ON_STACK(TYPE) 0 +#endif + /* Return true if the function specified is using the structure returning convention on this machine to return arguments, or 0 if it is using the value returning convention. FUNCTION is the value representing @@ -1370,9 +1370,10 @@ using_struct_return (function, funcaddr, value_type, gcc_p) if (code == TYPE_CODE_ERROR) error ("Function return type unknown."); - if (code == TYPE_CODE_STRUCT || - code == TYPE_CODE_UNION || - code == TYPE_CODE_ARRAY) + if (code == TYPE_CODE_STRUCT + || code == TYPE_CODE_UNION + || code == TYPE_CODE_ARRAY + || RETURN_VALUE_ON_STACK (value_type)) return USE_STRUCT_CONVENTION (gcc_p, value_type); return 0;