From 9a8ce21f3b47a109b9ac35239e21198bb36e1146 Mon Sep 17 00:00:00 2001 From: Jon Grimm Date: Fri, 16 Dec 2005 06:38:26 +0000 Subject: target-def.h (TARGET_DECIMAL_FLOAT_SUPPORTED_P): New. 2005-12-16 Jon Grimm Janis Johnson Ben Elliston * target-def.h (TARGET_DECIMAL_FLOAT_SUPPORTED_P): New. (TARGET_INITIALIZER): Add TARGET_DECIMAL_FLOAT_P. * target.h (struct gcc_target): Add decimal_float_supported_p. * targhooks.c (default_scalar_mode_supported_p): Handle MODE_DECIMAL_FLOAT. * builtins.def: Add new builtins for 32, 64 and 128 bit variants of inf, nan, finite, isinf and isnan. * builtin-types.def (BT_DFLOAT32, BT_DFLOAT64, BT_DFLOAT128, BT_DFLOAT32_PTR, BT_DFLOAT64_PTR, BT_DFLOAT128_PTR, BT_FN_DFLOAT32, BT_FN_DFLOAT64, BT_FN_DFLOAT128, BT_FN_INT_DFLOAT32, BT_FN_INT_DFLOAT64, BT_FN_INT_DFLOAT128, BT_FN_DFLOAT32_CONST_STRING, BT_FN_DFLOAT64_CONST_STRING, BT_FN_DFLOAT32_CONST_STRING, BT_FN_DFLOAT32_DFLOAT32, BT_FN_DFLOAT64_DFLOAT64, BT_FN_DFLOAT128_DFLOAT128): New. * c-decl.c (declspecs_add_type): Verify combos on type qualifiers. Pedwarn if decimal floating point types are used. Error if decimal floating point is not supported by the target. (finish_declspecs): Return type from DFP typespec_word. * c-typeck.c (c_common_type): Choose the decimal floating point type with the greater precision when determining a common type. (convert_arguments): Warn if there is a mismatch between argument and prototype for decimal float types. Warn of conversions with binary float types and of precision narrowing due to prototype. * c-parser.c (reswords): Add _Decimal32, _Decimal64, _Decimal128. (c_token_starts_typename): Handle RID_DFLOAT32/64/128. (c_token_starts_declspecs): Likewise. (c_parser_attributes): Likewise. * c-common.h (enum rid): Add new enumeration values RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128. (T_D32, TEX_D32, T_D64, TEX_D64, T_D128, TEX_D128): New macros. * c-common.c (c_common_type_for_mode): Handle decimal float modes. (shorten_compare): Convert DFP/BFP operands to a common type. (c_common_modes_and_builtins): Register built-in decimal float types if the target supports them. (handle_mode_addtribute): Handle MODE_DECIMAL_FLOAT. * builtins.c (fold_builtin_1): Handle 32, 64 and 128 bit cases of inf, nan, finite, isinf and isnan builtins. * c-cppbuiltin.c (builtin_define_decimal_float_constants): New. (builtin_define_float_constants): Assert non-decimal radix. (c_cpp_builtins): Register built-in __DEC_EVAL_METHOD__ define. Call builtin_define_decimal_float_constants for each type. * c-lex.c (interpret_float): Decode decimal float types from CPP_N flags. Use real_from_string3, which can handle binary or decimal floats. * c-tree.h (enum c_typespec_keyword): Add cts_dfloat32, cts_dfloat64, cts_dfloat128. * tree.c (build_common_tree_nodes_2): Add decimal float types. * tree.h (enum tree_index): Add new enumeration values TI_DFLOAT32_TYPE, TI_DFLOAT64_TYPE, TI_DFLOAT128_TYPE, TI_DFLOAT32_PTR_TYPE, TI_DFLOAT64_PTR_TYPE, TI_DFLOAT128_PTR_TYPE. (dfloat32_type_node): New macro. (dfloat64_type_node, dfloat128_type_node): Likewise. (dfloat32_ptr_type_node, dfloat64_ptr_type_node): Likewise. (dfloat128_ptr_type_node): Likewise. * c-pretty-print.c (pp_c_floating_constant): Append 32, 64 and 128 bit decimal floating point types with "df", "dd" and "dl". * c-format.h (enum format_lengths): Add new enumeration values FMT_LEN_H, FMT_LEN_D and FMT_LEN_DD. * c-format.c (printf_length_specs, scanf_length_specs): Add entries for H, D, DD. (print_char_table, scan_char_table): Use new entries. (asm_fprintf_char_table, gcc_diag_char_table, gcc_cdiag_char_table, gcc_cxxdiag_char_table): Adjust for longer length arrays. * defaults.h (DECIMAL32_TYPE_SIZE): Define. (DECIMAL64_TYPE_SIZE): Likewise. (DECIMAL128_TYPE_SIZE): Likewise. (TARGET_DEC_EVAL_METHOD): Likewise. * doc/extend.texi (Decimal Float): New node. (Constructing Calls): Document decimal float built-ins. * doc/tm.texi: Document TARGET_DECIMAL_FLOAT_SUPPORTED_P hook. * Makefile.in (USER_H): Add $(srcdir)/ginclude/decfloat.h. * ginclude/decfloat.h: New file. Co-Authored-By: Ben Elliston Co-Authored-By: Janis Johnson From-SVN: r108629 --- gcc/ChangeLog | 78 +++++++++++++++++++++++++++++++ gcc/Makefile.in | 3 +- gcc/builtin-types.def | 20 ++++++++ gcc/builtins.c | 15 ++++++ gcc/builtins.def | 15 ++++++ gcc/c-common.c | 31 +++++++++++++ gcc/c-common.h | 1 + gcc/c-cppbuiltin.c | 74 +++++++++++++++++++++++++++++ gcc/c-decl.c | 98 +++++++++++++++++++++++++++++++++++++++ gcc/c-format.c | 121 +++++++++++++++++++++++++----------------------- gcc/c-format.h | 9 ++++ gcc/c-lex.c | 50 ++++++++++---------- gcc/c-parser.c | 18 +++++++ gcc/c-pretty-print.c | 6 +++ gcc/c-tree.h | 5 +- gcc/c-typeck.c | 48 ++++++++++++++++++- gcc/defaults.h | 16 +++++++ gcc/doc/extend.texi | 66 +++++++++++++++++++++++++- gcc/doc/tm.texi | 5 ++ gcc/ginclude/decfloat.h | 108 ++++++++++++++++++++++++++++++++++++++++++ gcc/target-def.h | 5 ++ gcc/target.h | 3 ++ gcc/targhooks.c | 3 ++ gcc/tree.c | 19 ++++++++ gcc/tree.h | 15 ++++++ 25 files changed, 744 insertions(+), 88 deletions(-) create mode 100644 gcc/ginclude/decfloat.h diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f2481a5..661e533 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,81 @@ +2005-12-16 Jon Grimm + Janis Johnson + Ben Elliston + + * target-def.h (TARGET_DECIMAL_FLOAT_SUPPORTED_P): New. + (TARGET_INITIALIZER): Add TARGET_DECIMAL_FLOAT_P. + * target.h (struct gcc_target): Add decimal_float_supported_p. + * targhooks.c (default_scalar_mode_supported_p): Handle + MODE_DECIMAL_FLOAT. + * builtins.def: Add new builtins for 32, 64 and 128 bit variants + of inf, nan, finite, isinf and isnan. + * builtin-types.def (BT_DFLOAT32, BT_DFLOAT64, BT_DFLOAT128, + BT_DFLOAT32_PTR, BT_DFLOAT64_PTR, BT_DFLOAT128_PTR, + BT_FN_DFLOAT32, BT_FN_DFLOAT64, BT_FN_DFLOAT128, + BT_FN_INT_DFLOAT32, BT_FN_INT_DFLOAT64, BT_FN_INT_DFLOAT128, + BT_FN_DFLOAT32_CONST_STRING, BT_FN_DFLOAT64_CONST_STRING, + BT_FN_DFLOAT32_CONST_STRING, BT_FN_DFLOAT32_DFLOAT32, + BT_FN_DFLOAT64_DFLOAT64, BT_FN_DFLOAT128_DFLOAT128): New. + * c-decl.c (declspecs_add_type): Verify combos on type qualifiers. + Pedwarn if decimal floating point types are used. Error if + decimal floating point is not supported by the target. + (finish_declspecs): Return type from DFP typespec_word. + * c-typeck.c (c_common_type): Choose the decimal floating point + type with the greater precision when determining a common type. + (convert_arguments): Warn if there is a mismatch between argument + and prototype for decimal float types. Warn of conversions with + binary float types and of precision narrowing due to prototype. + * c-parser.c (reswords): Add _Decimal32, _Decimal64, _Decimal128. + (c_token_starts_typename): Handle RID_DFLOAT32/64/128. + (c_token_starts_declspecs): Likewise. + (c_parser_attributes): Likewise. + * c-common.h (enum rid): Add new enumeration values RID_DFLOAT32, + RID_DFLOAT64, RID_DFLOAT128. + (T_D32, TEX_D32, T_D64, TEX_D64, T_D128, TEX_D128): New macros. + * c-common.c (c_common_type_for_mode): Handle decimal float modes. + (shorten_compare): Convert DFP/BFP operands to a common type. + (c_common_modes_and_builtins): Register built-in decimal float + types if the target supports them. + (handle_mode_addtribute): Handle MODE_DECIMAL_FLOAT. + * builtins.c (fold_builtin_1): Handle 32, 64 and 128 bit cases of + inf, nan, finite, isinf and isnan builtins. + * c-cppbuiltin.c (builtin_define_decimal_float_constants): New. + (builtin_define_float_constants): Assert non-decimal radix. + (c_cpp_builtins): Register built-in __DEC_EVAL_METHOD__ define. + Call builtin_define_decimal_float_constants for each type. + * c-lex.c (interpret_float): Decode decimal float types from CPP_N + flags. Use real_from_string3, which can handle binary or decimal + floats. + * c-tree.h (enum c_typespec_keyword): Add cts_dfloat32, + cts_dfloat64, cts_dfloat128. + * tree.c (build_common_tree_nodes_2): Add decimal float types. + * tree.h (enum tree_index): Add new enumeration values + TI_DFLOAT32_TYPE, TI_DFLOAT64_TYPE, TI_DFLOAT128_TYPE, + TI_DFLOAT32_PTR_TYPE, TI_DFLOAT64_PTR_TYPE, TI_DFLOAT128_PTR_TYPE. + (dfloat32_type_node): New macro. + (dfloat64_type_node, dfloat128_type_node): Likewise. + (dfloat32_ptr_type_node, dfloat64_ptr_type_node): Likewise. + (dfloat128_ptr_type_node): Likewise. + * c-pretty-print.c (pp_c_floating_constant): Append 32, 64 and 128 + bit decimal floating point types with "df", "dd" and "dl". + * c-format.h (enum format_lengths): Add new enumeration values + FMT_LEN_H, FMT_LEN_D and FMT_LEN_DD. + * c-format.c (printf_length_specs, scanf_length_specs): Add + entries for H, D, DD. + (print_char_table, scan_char_table): Use new entries. + (asm_fprintf_char_table, gcc_diag_char_table, + gcc_cdiag_char_table, gcc_cxxdiag_char_table): Adjust for longer + length arrays. + * defaults.h (DECIMAL32_TYPE_SIZE): Define. + (DECIMAL64_TYPE_SIZE): Likewise. + (DECIMAL128_TYPE_SIZE): Likewise. + (TARGET_DEC_EVAL_METHOD): Likewise. + * doc/extend.texi (Decimal Float): New node. + (Constructing Calls): Document decimal float built-ins. + * doc/tm.texi: Document TARGET_DECIMAL_FLOAT_SUPPORTED_P hook. + * Makefile.in (USER_H): Add $(srcdir)/ginclude/decfloat.h. + * ginclude/decfloat.h: New file. + 2005-12-16 Alan Modra * reload.c (find_reloads): Fix comment typo. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 3afa7b2..2808035 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -312,7 +312,8 @@ INSTALL_HEADERS_DIR = @build_install_headers_dir@ # Header files that are made available under the same name # to programs compiled with GCC. -USER_H = $(srcdir)/ginclude/float.h \ +USER_H = $(srcdir)/ginclude/decfloat.h \ + $(srcdir)/ginclude/float.h \ $(srcdir)/ginclude/iso646.h \ $(srcdir)/ginclude/stdarg.h \ $(srcdir)/ginclude/stdbool.h \ diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def index 3f25cdd..2e3851a 100644 --- a/gcc/builtin-types.def +++ b/gcc/builtin-types.def @@ -98,6 +98,13 @@ DEF_PRIMITIVE_TYPE (BT_WINT, wint_type_node) DEF_PRIMITIVE_TYPE (BT_STRING, string_type_node) DEF_PRIMITIVE_TYPE (BT_CONST_STRING, const_string_type_node) +DEF_PRIMITIVE_TYPE (BT_DFLOAT32, dfloat32_type_node) +DEF_PRIMITIVE_TYPE (BT_DFLOAT64, dfloat64_type_node) +DEF_PRIMITIVE_TYPE (BT_DFLOAT128, dfloat128_type_node) +DEF_PRIMITIVE_TYPE (BT_DFLOAT32_PTR, dfloat32_ptr_type_node) +DEF_PRIMITIVE_TYPE (BT_DFLOAT64_PTR, dfloat64_ptr_type_node) +DEF_PRIMITIVE_TYPE (BT_DFLOAT128_PTR, dfloat128_ptr_type_node) + DEF_PRIMITIVE_TYPE (BT_VALIST_REF, va_list_ref_type_node) DEF_PRIMITIVE_TYPE (BT_VALIST_ARG, va_list_arg_type_node) @@ -118,6 +125,9 @@ DEF_FUNCTION_TYPE_0 (BT_FN_DOUBLE, BT_DOUBLE) distinguish it from two types in sequence, "long" followed by "double". */ DEF_FUNCTION_TYPE_0 (BT_FN_LONGDOUBLE, BT_LONGDOUBLE) +DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT32, BT_DFLOAT32) +DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT64, BT_DFLOAT64) +DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT128, BT_DFLOAT128) DEF_FUNCTION_TYPE_1 (BT_FN_LONG_LONG, BT_LONG, BT_LONG) DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_LONGLONG, BT_LONGLONG, BT_LONGLONG) @@ -152,6 +162,9 @@ DEF_FUNCTION_TYPE_1 (BT_FN_INT_PTR, BT_INT, BT_PTR) DEF_FUNCTION_TYPE_1 (BT_FN_INT_FLOAT, BT_INT, BT_FLOAT) DEF_FUNCTION_TYPE_1 (BT_FN_INT_DOUBLE, BT_INT, BT_DOUBLE) DEF_FUNCTION_TYPE_1 (BT_FN_INT_LONGDOUBLE, BT_INT, BT_LONGDOUBLE) +DEF_FUNCTION_TYPE_1 (BT_FN_INT_DFLOAT32, BT_INT, BT_DFLOAT32) +DEF_FUNCTION_TYPE_1 (BT_FN_INT_DFLOAT64, BT_INT, BT_DFLOAT64) +DEF_FUNCTION_TYPE_1 (BT_FN_INT_DFLOAT128, BT_INT, BT_DFLOAT128) DEF_FUNCTION_TYPE_1 (BT_FN_LONG_FLOAT, BT_LONG, BT_FLOAT) DEF_FUNCTION_TYPE_1 (BT_FN_LONG_DOUBLE, BT_LONG, BT_DOUBLE) DEF_FUNCTION_TYPE_1 (BT_FN_LONG_LONGDOUBLE, BT_LONG, BT_LONGDOUBLE) @@ -168,10 +181,17 @@ DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_CONST_STRING, BT_FLOAT, BT_CONST_STRING) DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_CONST_STRING, BT_DOUBLE, BT_CONST_STRING) DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_CONST_STRING, BT_LONGDOUBLE, BT_CONST_STRING) +DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT32_CONST_STRING, BT_DFLOAT32, BT_CONST_STRING) +DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_CONST_STRING, BT_DFLOAT64, BT_CONST_STRING) +DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_CONST_STRING, + BT_DFLOAT128, BT_CONST_STRING) DEF_FUNCTION_TYPE_1 (BT_FN_STRING_CONST_STRING, BT_STRING, BT_CONST_STRING) DEF_FUNCTION_TYPE_1 (BT_FN_WORD_PTR, BT_WORD, BT_PTR) DEF_FUNCTION_TYPE_1 (BT_FN_INT_WINT, BT_INT, BT_WINT) DEF_FUNCTION_TYPE_1 (BT_FN_WINT_WINT, BT_WINT, BT_WINT) +DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT32_DFLOAT32, BT_DFLOAT32, BT_DFLOAT32) +DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_DFLOAT64, BT_DFLOAT64, BT_DFLOAT64) +DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_DFLOAT128, BT_DFLOAT128, BT_DFLOAT128) DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_INT, BT_VOID, BT_PTR, BT_INT) diff --git a/gcc/builtins.c b/gcc/builtins.c index 2e42f46..29ec05c 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -8593,12 +8593,18 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore) return fold_builtin_powi (fndecl, arglist, type); CASE_FLT_FN (BUILT_IN_INF): + case BUILT_IN_INFD32: + case BUILT_IN_INFD64: + case BUILT_IN_INFD128: return fold_builtin_inf (type, true); CASE_FLT_FN (BUILT_IN_HUGE_VAL): return fold_builtin_inf (type, false); CASE_FLT_FN (BUILT_IN_NAN): + case BUILT_IN_NAND32: + case BUILT_IN_NAND64: + case BUILT_IN_NAND128: return fold_builtin_nan (arglist, type, true); CASE_FLT_FN (BUILT_IN_NANS): @@ -8664,12 +8670,21 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore) return fold_builtin_copysign (fndecl, arglist, type); CASE_FLT_FN (BUILT_IN_FINITE): + case BUILT_IN_FINITED32: + case BUILT_IN_FINITED64: + case BUILT_IN_FINITED128: return fold_builtin_classify (fndecl, arglist, BUILT_IN_FINITE); CASE_FLT_FN (BUILT_IN_ISINF): + case BUILT_IN_ISINFD32: + case BUILT_IN_ISINFD64: + case BUILT_IN_ISINFD128: return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISINF); CASE_FLT_FN (BUILT_IN_ISNAN): + case BUILT_IN_ISNAND32: + case BUILT_IN_ISNAND64: + case BUILT_IN_ISNAND128: return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISNAN); case BUILT_IN_ISGREATER: diff --git a/gcc/builtins.def b/gcc/builtins.def index 063ca1c..7788719 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -261,6 +261,9 @@ DEF_C99_BUILTIN (BUILT_IN_ILOGBL, "ilogbl", BT_FN_INT_LONGDOUBLE, ATTR_MA DEF_GCC_BUILTIN (BUILT_IN_INF, "inf", BT_FN_DOUBLE, ATTR_CONST_NOTHROW_LIST) DEF_GCC_BUILTIN (BUILT_IN_INFF, "inff", BT_FN_FLOAT, ATTR_CONST_NOTHROW_LIST) DEF_GCC_BUILTIN (BUILT_IN_INFL, "infl", BT_FN_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST) +DEF_GCC_BUILTIN (BUILT_IN_INFD32, "infd32", BT_FN_DFLOAT32, ATTR_CONST_NOTHROW_LIST) +DEF_GCC_BUILTIN (BUILT_IN_INFD64, "infd64", BT_FN_DFLOAT64, ATTR_CONST_NOTHROW_LIST) +DEF_GCC_BUILTIN (BUILT_IN_INFD128, "infd128", BT_FN_DFLOAT128, ATTR_CONST_NOTHROW_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_J0, "j0", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_EXT_LIB_BUILTIN (BUILT_IN_J0F, "j0f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_EXT_LIB_BUILTIN (BUILT_IN_J0L, "j0l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) @@ -321,6 +324,9 @@ DEF_C99_C90RES_BUILTIN (BUILT_IN_MODFL, "modfl", BT_FN_LONGDOUBLE_LONGDOUBLE_LON DEF_GCC_BUILTIN (BUILT_IN_NAN, "nan", BT_FN_DOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_GCC_BUILTIN (BUILT_IN_NANF, "nanf", BT_FN_FLOAT_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_GCC_BUILTIN (BUILT_IN_NANL, "nanl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) +DEF_GCC_BUILTIN (BUILT_IN_NAND32, "nand32", BT_FN_DFLOAT32_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) +DEF_GCC_BUILTIN (BUILT_IN_NAND64, "nand64", BT_FN_DFLOAT64_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) +DEF_GCC_BUILTIN (BUILT_IN_NAND128, "nand128", BT_FN_DFLOAT128_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_GCC_BUILTIN (BUILT_IN_NANS, "nans", BT_FN_DOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_GCC_BUILTIN (BUILT_IN_NANSF, "nansf", BT_FN_FLOAT_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_GCC_BUILTIN (BUILT_IN_NANSL, "nansl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) @@ -619,12 +625,21 @@ DEF_GCC_BUILTIN (BUILT_IN_INIT_DWARF_REG_SIZES, "init_dwarf_reg_size_tabl DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITE, "finite", BT_FN_INT_DOUBLE, ATTR_CONST_NOTHROW_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITEF, "finitef", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITEL, "finitel", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITED32, "finited32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITED64, "finited64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITED128, "finited128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LIST) DEF_C99_C90RES_BUILTIN (BUILT_IN_ISINF, "isinf", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFF, "isinff", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFL, "isinfl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFD32, "isinfd32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFD64, "isinfd64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFD128, "isinfd128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LIST) DEF_C99_C90RES_BUILTIN (BUILT_IN_ISNAN, "isnan", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNANF, "isnanf", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNANL, "isnanl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNAND32, "isnand32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNAND64, "isnand64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNAND128, "isnand128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LIST) DEF_GCC_BUILTIN (BUILT_IN_ISGREATER, "isgreater", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST) DEF_GCC_BUILTIN (BUILT_IN_ISGREATEREQUAL, "isgreaterequal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST) DEF_GCC_BUILTIN (BUILT_IN_ISLESS, "isless", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST) diff --git a/gcc/c-common.c b/gcc/c-common.c index 5f97a97..30a61c2 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -131,6 +131,10 @@ cpp_reader *parse_in; /* Declared in c-pragma.h. */ tree complex_double_type_node; tree complex_long_double_type_node; + tree dfloat32_type_node; + tree dfloat64_type_node; + tree_dfloat128_type_node; + tree intQI_type_node; tree intHI_type_node; tree intSI_type_node; @@ -1686,6 +1690,13 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp) return build_vector_type_for_mode (inner_type, mode); } + if (mode == TYPE_MODE (dfloat32_type_node)) + return dfloat32_type_node; + if (mode == TYPE_MODE (dfloat64_type_node)) + return dfloat64_type_node; + if (mode == TYPE_MODE (dfloat128_type_node)) + return dfloat128_type_node; + for (t = registered_builtin_types; t; t = TREE_CHAIN (t)) if (TYPE_MODE (TREE_VALUE (t)) == mode) return TREE_VALUE (t); @@ -2168,6 +2179,14 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, in the type of the operand that is not constant. TYPE is already properly set. */ } + + /* If either arg is decimal float and the other is float, find the + proper common type to use for comparison. */ + else if (real1 && real2 + && (DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop0))) + || DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop1))))) + type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1)); + else if (real1 && real2 && (TYPE_PRECISION (TREE_TYPE (primop0)) == TYPE_PRECISION (TREE_TYPE (primop1)))) @@ -3084,6 +3103,17 @@ c_common_nodes_and_builtins (void) record_builtin_type (RID_DOUBLE, NULL, double_type_node); record_builtin_type (RID_MAX, "long double", long_double_type_node); + /* Only supported decimal floating point extension if the target + actually supports underlying modes. */ + if (targetm.scalar_mode_supported_p (SDmode) + && targetm.scalar_mode_supported_p (DDmode) + && targetm.scalar_mode_supported_p (TDmode)) + { + record_builtin_type (RID_DFLOAT32, NULL, dfloat32_type_node); + record_builtin_type (RID_DFLOAT64, NULL, dfloat64_type_node); + record_builtin_type (RID_DFLOAT128, NULL, dfloat128_type_node); + } + lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"), complex_integer_type_node)); @@ -4506,6 +4536,7 @@ handle_mode_attribute (tree *node, tree name, tree args, case MODE_INT: case MODE_PARTIAL_INT: case MODE_FLOAT: + case MODE_DECIMAL_FLOAT: valid_mode = targetm.scalar_mode_supported_p (mode); break; diff --git a/gcc/c-common.h b/gcc/c-common.h index c78f462..bcc4caa 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -72,6 +72,7 @@ enum rid RID_ASM, RID_TYPEOF, RID_ALIGNOF, RID_ATTRIBUTE, RID_VA_ARG, RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR, RID_TYPES_COMPATIBLE_P, + RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, /* Too many ways of getting the name of a function as a string */ RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME, RID_C99_FUNCTION_NAME, diff --git a/gcc/c-cppbuiltin.c b/gcc/c-cppbuiltin.c index dc87980..12e0879 100644 --- a/gcc/c-cppbuiltin.c +++ b/gcc/c-cppbuiltin.c @@ -96,6 +96,7 @@ builtin_define_float_constants (const char *name_prefix, int decimal_dig; fmt = REAL_MODE_FORMAT (TYPE_MODE (type)); + gcc_assert (fmt->b != 10); /* The radix of the exponent representation. */ if (type == float_type_node) @@ -266,6 +267,70 @@ builtin_define_float_constants (const char *name_prefix, builtin_define_with_int_value (name, MODE_HAS_NANS (TYPE_MODE (type))); } +/* Define __DECx__ constants for TYPE using NAME_PREFIX and SUFFIX. */ +static void +builtin_define_decimal_float_constants (const char *name_prefix, + const char *suffix, + tree type) +{ + const struct real_format *fmt; + char name[64], buf[128], *p; + int digits; + + fmt = REAL_MODE_FORMAT (TYPE_MODE (type)); + + /* The number of radix digits, p, in the significand. */ + sprintf (name, "__%s_MANT_DIG__", name_prefix); + builtin_define_with_int_value (name, fmt->p); + + /* The minimum negative int x such that b**(x-1) is a normalized float. */ + sprintf (name, "__%s_MIN_EXP__", name_prefix); + sprintf (buf, "(%d)", fmt->emin); + builtin_define_with_value (name, buf, 0); + + /* The maximum int x such that b**(x-1) is a representable float. */ + sprintf (name, "__%s_MAX_EXP__", name_prefix); + builtin_define_with_int_value (name, fmt->emax); + + /* Compute the minimum representable value. */ + sprintf (name, "__%s_MIN__", name_prefix); + sprintf (buf, "1E%d%s", fmt->emin, suffix); + builtin_define_with_value (name, buf, 0); + + /* Compute the maximum representable value. */ + sprintf (name, "__%s_MAX__", name_prefix); + p = buf; + for (digits = fmt->p; digits; digits--) + { + *p++ = '9'; + if (digits == fmt->p) + *p++ = '.'; + } + *p = 0; + /* fmt->p plus 1, to account for the decimal point. */ + sprintf (&buf[fmt->p + 1], "E%d%s", fmt->emax, suffix); + builtin_define_with_value (name, buf, 0); + + /* Compute epsilon (the difference between 1 and least value greater + than 1 representable). */ + sprintf (name, "__%s_EPSILON__", name_prefix); + sprintf (buf, "1E-%d%s", fmt->p - 1, suffix); + builtin_define_with_value (name, buf, 0); + + /* Minimum denormalized postive decimal value. */ + sprintf (name, "__%s_DEN__", name_prefix); + p = buf; + for (digits = fmt->p; digits > 1; digits--) + { + *p++ = '0'; + if (digits == fmt->p) + *p++ = '.'; + } + *p = 0; + sprintf (&buf[fmt->p], "1E%d%s", fmt->emin, suffix); + builtin_define_with_value (name, buf, 0); +} + /* Define __GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__. */ static void define__GNUC__ (void) @@ -392,6 +457,10 @@ c_cpp_builtins (cpp_reader *pfile) builtin_define_with_int_value ("__FLT_EVAL_METHOD__", TARGET_FLT_EVAL_METHOD); + /* And decfloat.h needs this. */ + builtin_define_with_int_value ("__DEC_EVAL_METHOD__", + TARGET_DEC_EVAL_METHOD); + builtin_define_float_constants ("FLT", "F", "%s", float_type_node); /* Cast the double precision constants when single precision constants are specified. The correct result is computed by the compiler when using @@ -403,6 +472,11 @@ c_cpp_builtins (cpp_reader *pfile) builtin_define_float_constants ("DBL", "", "%s", double_type_node); builtin_define_float_constants ("LDBL", "L", "%s", long_double_type_node); + /* For decfloat.h. */ + builtin_define_decimal_float_constants ("DEC32", "DF", dfloat32_type_node); + builtin_define_decimal_float_constants ("DEC64", "DD", dfloat64_type_node); + builtin_define_decimal_float_constants ("DEC128", "DL", dfloat128_type_node); + /* For use in assembly language. */ builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0); builtin_define_with_value ("__USER_LABEL_PREFIX__", user_label_prefix, 0); diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 44e03ab..8a27e97 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -7069,6 +7069,15 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) else if (specs->typespec_word == cts_float) error ("both % and % in " "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat32) + error ("both % and %<_Decimal32%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat64) + error ("both % and %<_Decimal64%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat128) + error ("both % and %<_Decimal128%> in " + "declaration specifiers"); else specs->long_p = true; break; @@ -7092,6 +7101,15 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) else if (specs->typespec_word == cts_double) error ("both % and % in " "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat32) + error ("both % and %<_Decimal32%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat64) + error ("both % and %<_Decimal64%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat128) + error ("both % and %<_Decimal128%> in " + "declaration specifiers"); else specs->short_p = true; break; @@ -7112,6 +7130,15 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) else if (specs->typespec_word == cts_double) error ("both % and % in " "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat32) + error ("both % and %<_Decimal32%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat64) + error ("both % and %<_Decimal64%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat128) + error ("both % and %<_Decimal128%> in " + "declaration specifiers"); else specs->signed_p = true; break; @@ -7132,6 +7159,15 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) else if (specs->typespec_word == cts_double) error ("both % and % in " "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat32) + error ("both % and %<_Decimal32%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat64) + error ("both % and %<_Decimal64%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat128) + error ("both % and %<_Decimal128%> in " + "declaration specifiers"); else specs->unsigned_p = true; break; @@ -7145,6 +7181,15 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) else if (specs->typespec_word == cts_bool) error ("both % and %<_Bool%> in " "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat32) + error ("both % and %<_Decimal32%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat64) + error ("both % and %<_Decimal64%> in " + "declaration specifiers"); + else if (specs->typespec_word == cts_dfloat128) + error ("both % and %<_Decimal128%> in " + "declaration specifiers"); else specs->complex_p = true; break; @@ -7250,6 +7295,47 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec) else specs->typespec_word = cts_double; return specs; + case RID_DFLOAT32: + case RID_DFLOAT64: + case RID_DFLOAT128: + { + const char *str; + if (i == RID_DFLOAT32) + str = "_Decimal32"; + else if (i == RID_DFLOAT64) + str = "_Decimal64"; + else + str = "_Decimal128"; + if (specs->long_long_p) + error ("both % and %<%s%> in " + "declaration specifiers", str); + if (specs->long_p) + error ("both % and %<%s%> in " + "declaration specifiers", str); + else if (specs->short_p) + error ("both % and %<%s%> in " + "declaration specifiers", str); + else if (specs->signed_p) + error ("both % and %<%s%> in " + "declaration specifiers", str); + else if (specs->unsigned_p) + error ("both % and %<%s%> in " + "declaration specifiers", str); + else if (specs->complex_p) + error ("both % and %<%s%> in " + "declaration specifiers", str); + else if (i == RID_DFLOAT32) + specs->typespec_word = cts_dfloat32; + else if (i == RID_DFLOAT64) + specs->typespec_word = cts_dfloat64; + else + specs->typespec_word = cts_dfloat128; + } + if (!targetm.decimal_float_supported_p ()) + error ("decimal floating point not supported for this target"); + if (pedantic) + pedwarn ("ISO C does not support decimal floating point"); + return specs; default: /* ObjC reserved word "id", handled below. */ break; @@ -7527,6 +7613,18 @@ finish_declspecs (struct c_declspecs *specs) : double_type_node); } break; + case cts_dfloat32: + case cts_dfloat64: + case cts_dfloat128: + gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p + && !specs->signed_p && !specs->unsigned_p && !specs->complex_p); + if (specs->typespec_word == cts_dfloat32) + specs->type = dfloat32_type_node; + else if (specs->typespec_word == cts_dfloat64) + specs->type = dfloat64_type_node; + else + specs->type = dfloat128_type_node; + break; default: gcc_unreachable (); } diff --git a/gcc/c-format.c b/gcc/c-format.c index 82f2bc7..8a8fa2f 100644 --- a/gcc/c-format.c +++ b/gcc/c-format.c @@ -291,6 +291,8 @@ static const format_length_info printf_length_specs[] = { "Z", FMT_LEN_z, STD_EXT, NULL, 0, 0 }, { "t", FMT_LEN_t, STD_C99, NULL, 0, 0 }, { "j", FMT_LEN_j, STD_C99, NULL, 0, 0 }, + { "H", FMT_LEN_H, STD_EXT, NULL, 0, 0 }, + { "D", FMT_LEN_D, STD_EXT, "DD", FMT_LEN_DD, STD_EXT }, { NULL, 0, 0, NULL, 0, 0 } }; @@ -325,6 +327,8 @@ static const format_length_info scanf_length_specs[] = { "z", FMT_LEN_z, STD_C99, NULL, 0, 0 }, { "t", FMT_LEN_t, STD_C99, NULL, 0, 0 }, { "j", FMT_LEN_j, STD_C99, NULL, 0, 0 }, + { "H", FMT_LEN_H, STD_EXT, NULL, 0, 0 }, + { "D", FMT_LEN_D, STD_EXT, "DD", FMT_LEN_DD, STD_EXT }, { NULL, 0, 0, NULL, 0, 0 } }; @@ -489,34 +493,34 @@ static const format_flag_pair strfmon_flag_pairs[] = static const format_char_info print_char_table[] = { /* C89 conversion specifiers. */ - { "di", 0, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, TEX_LL, T99_SST, T99_PD, T99_IM }, "-wp0 +'I", "i", NULL }, - { "oxX", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "-wp0#", "i", NULL }, - { "u", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "-wp0'I", "i", NULL }, - { "fgG", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#'I", "", NULL }, - { "eE", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#I", "", NULL }, - { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, T94_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL }, - { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR", NULL }, - { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "c", NULL }, - { "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM }, "", "W", NULL }, + { "di", 0, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, TEX_LL, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "-wp0 +'I", "i", NULL }, + { "oxX", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL }, + { "u", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "-wp0'I", "i", NULL }, + { "fgG", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#'I", "", NULL }, + { "eE", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#I", "", NULL }, + { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, T94_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL }, + { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR", NULL }, + { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "c", NULL }, + { "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "", "W", NULL }, /* C99 conversion specifiers. */ - { "F", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#'I", "", NULL }, - { "aA", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "", NULL }, + { "F", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#'I", "", NULL }, + { "aA", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "", NULL }, /* X/Open conversion specifiers. */ - { "C", 0, STD_EXT, { TEX_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL }, - { "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "R", NULL }, + { "C", 0, STD_EXT, { TEX_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL }, + { "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "R", NULL }, /* GNU conversion specifiers. */ - { "m", 0, STD_EXT, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "", NULL }, + { "m", 0, STD_EXT, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "", NULL }, { NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL } }; static const format_char_info asm_fprintf_char_table[] = { /* C89 conversion specifiers. */ - { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +", "i", NULL }, - { "oxX", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL }, - { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0", "i", NULL }, - { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL }, - { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR", NULL }, + { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +", "i", NULL }, + { "oxX", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL }, + { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0", "i", NULL }, + { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL }, + { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR", NULL }, /* asm_fprintf conversion specifiers. */ { "O", 0, STD_C89, NOARGUMENTS, "", "", NULL }, @@ -524,7 +528,7 @@ static const format_char_info asm_fprintf_char_table[] = { "I", 0, STD_C89, NOARGUMENTS, "", "", NULL }, { "L", 0, STD_C89, NOARGUMENTS, "", "", NULL }, { "U", 0, STD_C89, NOARGUMENTS, "", "", NULL }, - { "r", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL }, + { "r", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL }, { "@", 0, STD_C89, NOARGUMENTS, "", "", NULL }, { NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL } }; @@ -532,20 +536,20 @@ static const format_char_info asm_fprintf_char_table[] = static const format_char_info gcc_diag_char_table[] = { /* C89 conversion specifiers. */ - { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, - { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, + { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, + { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, /* Custom conversion specifiers. */ /* %H will require "location_t" at runtime. */ - { "H", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "H", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, /* These will require a "tree" at runtime. */ - { "J", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "J", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, { "<>'", 0, STD_C89, NOARGUMENTS, "", "", NULL }, { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, @@ -578,20 +582,20 @@ static const format_char_info gcc_tdiag_char_table[] = static const format_char_info gcc_cdiag_char_table[] = { /* C89 conversion specifiers. */ - { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, - { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, + { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, + { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, /* Custom conversion specifiers. */ /* %H will require "location_t" at runtime. */ - { "H", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "H", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, /* These will require a "tree" at runtime. */ - { "DEFJT", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, + { "DEFJT", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, { "<>'", 0, STD_C89, NOARGUMENTS, "", "", NULL }, { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, @@ -601,23 +605,23 @@ static const format_char_info gcc_cdiag_char_table[] = static const format_char_info gcc_cxxdiag_char_table[] = { /* C89 conversion specifiers. */ - { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, - { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, + { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, + { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, /* Custom conversion specifiers. */ /* %H will require "location_t" at runtime. */ - { "H", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "H", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, /* These will require a "tree" at runtime. */ - { "ADEFJTV",0,STD_C89,{ T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL }, + { "ADEFJTV",0,STD_C89,{ T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL }, /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */ - { "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, { "<>'", 0, STD_C89, NOARGUMENTS, "", "", NULL }, { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, @@ -644,20 +648,21 @@ static const format_char_info gcc_gfc_char_table[] = static const format_char_info scan_char_table[] = { /* C89 conversion specifiers. */ - { "di", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, TEX_LL, T99_SST, T99_PD, T99_IM }, "*w'I", "W", NULL }, - { "u", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "*w'I", "W", NULL }, - { "oxX", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "*w", "W", NULL }, - { "efgEG", 1, STD_C89, { T89_F, BADLEN, BADLEN, T89_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL }, - { "c", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "cW", NULL }, - { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW", NULL }, - { "[", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW[", NULL }, - { "p", 2, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL }, - { "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM }, "", "W", NULL }, + { "di", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, TEX_LL, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "*w'I", "W", NULL }, + { "u", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "*w'I", "W", NULL }, + { "oxX", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL }, + { "efgEG", 1, STD_C89, { T89_F, BADLEN, BADLEN, T89_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "*w'", "W", NULL }, + { "c", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "cW", NULL }, + { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW", NULL }, + { "[", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW[", NULL }, + { "p", 2, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL }, + { "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "", "W", NULL }, /* C99 conversion specifiers. */ - { "FaA", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL }, + { "F", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "*w'", "W", NULL }, + { "aA", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL }, /* X/Open conversion specifiers. */ - { "C", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL }, - { "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "W", NULL }, + { "C", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL }, + { "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "W", NULL }, { NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL } }; @@ -690,7 +695,7 @@ static const format_char_info time_char_table[] = static const format_char_info monetary_char_table[] = { - { "in", 0, STD_C89, { T89_D, BADLEN, BADLEN, BADLEN, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "=^+(!-w#p", "", NULL }, + { "in", 0, STD_C89, { T89_D, BADLEN, BADLEN, BADLEN, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "=^+(!-w#p", "", NULL }, { NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL } }; diff --git a/gcc/c-format.h b/gcc/c-format.h index 0cb1573..5fa544d 100644 --- a/gcc/c-format.h +++ b/gcc/c-format.h @@ -35,6 +35,9 @@ enum format_lengths FMT_LEN_z, FMT_LEN_t, FMT_LEN_j, + FMT_LEN_H, + FMT_LEN_D, + FMT_LEN_DD, FMT_LEN_MAX }; @@ -295,5 +298,11 @@ typedef struct #define T99_IM { STD_C99, "intmax_t", T_IM } #define T_UIM &uintmax_type_node #define T99_UIM { STD_C99, "uintmax_t", T_UIM } +#define T_D32 &dfloat32_type_node +#define TEX_D32 { STD_EXT, "_Decimal32", T_D32 } +#define T_D64 &dfloat64_type_node +#define TEX_D64 { STD_EXT, "_Decimal64", T_D64 } +#define T_D128 &dfloat128_type_node +#define TEX_D128 { STD_EXT, "_Decimal128", T_D128 } #endif /* GCC_C_FORMAT_H */ diff --git a/gcc/c-lex.c b/gcc/c-lex.c index 4ceb6e4..e745388 100644 --- a/gcc/c-lex.c +++ b/gcc/c-lex.c @@ -640,43 +640,45 @@ interpret_float (const cpp_token *token, unsigned int flags) REAL_VALUE_TYPE real; char *copy; size_t copylen; - const char *type_name; - /* FIXME: make %T work in error/warning, then we don't need type_name. */ - if ((flags & CPP_N_WIDTH) == CPP_N_LARGE) - { + /* Decode type based on width and properties. */ + if (flags & CPP_N_DFLOAT) + if ((flags & CPP_N_WIDTH) == CPP_N_LARGE) + type = dfloat128_type_node; + else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL) + type = dfloat32_type_node; + else + type = dfloat64_type_node; + else + if ((flags & CPP_N_WIDTH) == CPP_N_LARGE) type = long_double_type_node; - type_name = "long double"; - } - else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL - || flag_single_precision_constant) - { + else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL + || flag_single_precision_constant) type = float_type_node; - type_name = "float"; - } - else - { + else type = double_type_node; - type_name = "double"; - } /* Copy the constant to a nul-terminated buffer. If the constant has any suffixes, cut them off; REAL_VALUE_ATOF/ REAL_VALUE_HTOF can't handle them. */ copylen = token->val.str.len; - if ((flags & CPP_N_WIDTH) != CPP_N_MEDIUM) - /* Must be an F or L suffix. */ - copylen--; - if (flags & CPP_N_IMAGINARY) - /* I or J suffix. */ - copylen--; + if (flags & CPP_N_DFLOAT) + copylen -= 2; + else + { + if ((flags & CPP_N_WIDTH) != CPP_N_MEDIUM) + /* Must be an F or L suffix. */ + copylen--; + if (flags & CPP_N_IMAGINARY) + /* I or J suffix. */ + copylen--; + } copy = (char *) alloca (copylen + 1); memcpy (copy, token->val.str.text, copylen); copy[copylen] = '\0'; - real_from_string (&real, copy); - real_convert (&real, TYPE_MODE (type), &real); + real_from_string3 (&real, copy, TYPE_MODE (type)); /* Both C and C++ require a diagnostic for a floating constant outside the range of representable values of its type. Since we @@ -684,7 +686,7 @@ interpret_float (const cpp_token *token, unsigned int flags) appropriate for this to be a mandatory pedwarn rather than conditioned on -pedantic. */ if (REAL_VALUE_ISINF (real) && pedantic) - pedwarn ("floating constant exceeds range of %<%s%>", type_name); + pedwarn ("floating constant exceeds range of %qT", type); /* Create a node with determined type and value. */ value = build_real (type, real); diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 6ddbe51..8469eca 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -93,6 +93,9 @@ static const struct resword reswords[] = { { "_Bool", RID_BOOL, 0 }, { "_Complex", RID_COMPLEX, 0 }, + { "_Decimal32", RID_DFLOAT32, D_EXT }, + { "_Decimal64", RID_DFLOAT64, D_EXT }, + { "_Decimal128", RID_DFLOAT128, D_EXT }, { "__FUNCTION__", RID_FUNCTION_NAME, 0 }, { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 }, { "__alignof", RID_ALIGNOF, 0 }, @@ -461,6 +464,9 @@ c_token_starts_typename (c_token *token) case RID_FLOAT: case RID_DOUBLE: case RID_VOID: + case RID_DFLOAT32: + case RID_DFLOAT64: + case RID_DFLOAT128: case RID_BOOL: case RID_ENUM: case RID_STRUCT: @@ -532,6 +538,9 @@ c_token_starts_declspecs (c_token *token) case RID_FLOAT: case RID_DOUBLE: case RID_VOID: + case RID_DFLOAT32: + case RID_DFLOAT64: + case RID_DFLOAT128: case RID_BOOL: case RID_ENUM: case RID_STRUCT: @@ -1396,6 +1405,9 @@ c_parser_asm_definition (c_parser *parser) type-specifier: typeof-specifier + _Decimal32 + _Decimal64 + _Decimal128 Objective-C: @@ -1494,6 +1506,9 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, case RID_FLOAT: case RID_DOUBLE: case RID_VOID: + case RID_DFLOAT32: + case RID_DFLOAT64: + case RID_DFLOAT128: case RID_BOOL: if (!typespec_ok) goto out; @@ -2714,6 +2729,9 @@ c_parser_attributes (c_parser *parser) case RID_FLOAT: case RID_DOUBLE: case RID_VOID: + case RID_DFLOAT32: + case RID_DFLOAT64: + case RID_DFLOAT128: case RID_BOOL: ok = true; break; diff --git a/gcc/c-pretty-print.c b/gcc/c-pretty-print.c index 6618a70..058d3b9 100644 --- a/gcc/c-pretty-print.c +++ b/gcc/c-pretty-print.c @@ -911,6 +911,12 @@ pp_c_floating_constant (c_pretty_printer *pp, tree r) pp_character (pp, 'f'); else if (TREE_TYPE (r) == long_double_type_node) pp_character (pp, 'l'); + else if (TREE_TYPE (r) == dfloat128_type_node) + pp_string (pp, "dl"); + else if (TREE_TYPE (r) == dfloat64_type_node) + pp_string (pp, "dd"); + else if (TREE_TYPE (r) == dfloat32_type_node) + pp_string (pp, "df"); } /* Pretty-print a compound literal expression. GNU extensions include diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 6468ef2..db6c382 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -207,7 +207,10 @@ enum c_typespec_keyword { cts_char, cts_int, cts_float, - cts_double + cts_double, + cts_dfloat32, + cts_dfloat64, + cts_dfloat128 }; /* A sequence of declaration specifiers in C. */ diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index a38ce6c..53e20d7 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -617,6 +617,22 @@ c_common_type (tree t1, tree t2) if (code2 == REAL_TYPE && code1 != REAL_TYPE) return t2; + /* If both are real and either are decimal floating point types, use + the decimal floating point type with the greater precision. */ + + if (code1 == REAL_TYPE && code2 == REAL_TYPE) + { + if (TYPE_MAIN_VARIANT (t1) == dfloat128_type_node + || TYPE_MAIN_VARIANT (t2) == dfloat128_type_node) + return dfloat128_type_node; + else if (TYPE_MAIN_VARIANT (t1) == dfloat64_type_node + || TYPE_MAIN_VARIANT (t2) == dfloat64_type_node) + return dfloat64_type_node; + else if (TYPE_MAIN_VARIANT (t1) == dfloat32_type_node + || TYPE_MAIN_VARIANT (t2) == dfloat32_type_node) + return dfloat32_type_node; + } + /* Both real or both integers; use the one with greater precision. */ if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2)) @@ -2370,10 +2386,37 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) { /* Warn if any argument is passed as `float', since without a prototype it would be `double'. */ - if (formal_prec == TYPE_PRECISION (float_type_node)) + if (formal_prec == TYPE_PRECISION (float_type_node) + && type != dfloat32_type_node) warning (0, "passing argument %d of %qE as % " "rather than % due to prototype", argnum, rname); + + /* Warn if mismatch between argument and prototype + for decimal float types. Warn of conversions with + binary float types and of precision narrowing due to + prototype. */ + else if (type != TREE_TYPE (val) + && (type == dfloat32_type_node + || type == dfloat64_type_node + || type == dfloat128_type_node + || TREE_TYPE (val) == dfloat32_type_node + || TREE_TYPE (val) == dfloat64_type_node + || TREE_TYPE (val) == dfloat128_type_node) + && (formal_prec + <= TYPE_PRECISION (TREE_TYPE (val)) + || (type == dfloat128_type_node + && (TREE_TYPE (val) + != dfloat64_type_node + && (TREE_TYPE (val) + != dfloat32_type_node))) + || (type == dfloat64_type_node + && (TREE_TYPE (val) + != dfloat32_type_node)))) + warning (0, "passing argument %d of %qE as %qT " + "rather than %qT due to prototype", + argnum, rname, type, TREE_TYPE (val)); + } /* Detect integer changing in width or signedness. These warnings are only activated with @@ -2436,7 +2479,8 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) } else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE && (TYPE_PRECISION (TREE_TYPE (val)) - < TYPE_PRECISION (double_type_node))) + < TYPE_PRECISION (double_type_node)) + && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val)))) /* Convert `float' to `double'. */ result = tree_cons (NULL_TREE, convert (double_type_node, val), result); else if ((invalid_func_diag = diff --git a/gcc/defaults.h b/gcc/defaults.h index 38dab33..eb7733d 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -431,6 +431,18 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2) #endif +#ifndef DECIMAL32_TYPE_SIZE +#define DECIMAL32_TYPE_SIZE 32 +#endif + +#ifndef DECIMAL64_TYPE_SIZE +#define DECIMAL64_TYPE_SIZE 64 +#endif + +#ifndef DECIMAL128_TYPE_SIZE +#define DECIMAL128_TYPE_SIZE 128 +#endif + /* Width in bits of a pointer. Mind the value of the macro `Pmode'. */ #ifndef POINTER_SIZE #define POINTER_SIZE BITS_PER_WORD @@ -696,6 +708,10 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #define TARGET_FLT_EVAL_METHOD 0 #endif +#ifndef TARGET_DEC_EVAL_METHOD +#define TARGET_DEC_EVAL_METHOD 2 +#endif + #ifndef HOT_TEXT_SECTION_NAME #define HOT_TEXT_SECTION_NAME ".text.hot" #endif diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 341d624..0d54654 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1,5 +1,6 @@ -@c Copyright (C) 1988,1989,1992,1993,1994,1996,1998,1999,2000,2001,2002,2003,2004,2005 -@c Free Software Foundation, Inc. +@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 1999, 2000, +@c 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + @c This is part of the GCC manual. @c For copying conditions, see the file gcc.texi. @@ -32,6 +33,7 @@ extensions, accepted by GCC in C89 mode and in C++. * Conditionals:: Omitting the middle operand of a @samp{?:} expression. * Long Long:: Double-word integers---@code{long long int}. * Complex:: Data types for complex numbers. +* Decimal Float:: Decimal Floating Point. * Hex Floats:: Hexadecimal floating-point constants. * Zero Length:: Zero-length arrays. * Variable Length:: Arrays whose length is computed at run time. @@ -813,6 +815,42 @@ If the variable's actual name is @code{foo}, the two fictitious variables are named @code{foo$real} and @code{foo$imag}. You can examine and set these two fictitious variables with your debugger. +@node Decimal Float +@section Decimal Floating Point +@cindex decimal floating point +@cindex @code{_Decimal32} data type +@cindex @code{_Decimal64} data type +@cindex @code{_Decimal128} data type +@cindex @code{df} integer suffix +@cindex @code{dd} integer suffix +@cindex @code{dl} integer suffix +@cindex @code{DF} integer suffix +@cindex @code{DD} integer suffix +@cindex @code{DL} integer suffix + +GNU C supports decimal floating point types in addition to the +standard floating-point types. This extension supports decimal +floating-point arithmetic as defined in IEEE-754R, the proposed +revision of IEEE-754. The C language extension is defined in ISO/IEC +DTR 24732, Draft 5. Support for this functionality will change when +it is accepted into the C standard and might change for new drafts +of the proposal. Calling conventions for any target might also change. +Not all targets support decimal floating point. + +Support for decimal floating point includes the arithmetic operators +add, subtract, multiply, divide; unary arithmetic operators; +relational operators; equality operators; and conversions to and from +integer and other floating-point types. Use a suffix @samp{df} or +@samp{DF} in a literal constant of type @code{_Decimal32}, @samp{dd} +or @samp{DD} for @code{_Decimal64}, and @samp{dl} or @samp{DL} for +@code{_Decimal128}. + +Passing a decimal floating-point value as an argument to a function +without a prototype is undefined. + +Types @code{_Decimal32}, @code{_Decimal64}, and @code{_Decimal128} +are supported by the DWARF2 debug information format. + @node Hex Floats @section Hex Floats @cindex hex floats @@ -5661,6 +5699,18 @@ Similar to @code{__builtin_huge_val}, except a warning is generated if the target floating-point format does not support infinities. @end deftypefn +@deftypefn {Built-in Function} _Decimal32 __builtin_infd32 (void) +Similar to @code{__builtin_inf}, except the return type is @code{_Decimal32}. +@end deftypefn + +@deftypefn {Built-in Function} _Decimal64 __builtin_infd64 (void) +Similar to @code{__builtin_inf}, except the return type is @code{_Decimal64}. +@end deftypefn + +@deftypefn {Built-in Function} _Decimal128 __builtin_infd128 (void) +Similar to @code{__builtin_inf}, except the return type is @code{_Decimal128}. +@end deftypefn + @deftypefn {Built-in Function} float __builtin_inff (void) Similar to @code{__builtin_inf}, except the return type is @code{float}. This function is suitable for implementing the ISO C99 macro @code{INFINITY}. @@ -5687,6 +5737,18 @@ This function, if given a string literal, is evaluated early enough that it is considered a compile-time constant. @end deftypefn +@deftypefn {Built-in Function} _Decimal32 __builtin_nand32 (const char *str) +Similar to @code{__builtin_nan}, except the return type is @code{_Decimal32}. +@end deftypefn + +@deftypefn {Built-in Function} _Decimal64 __builtin_nand64 (const char *str) +Similar to @code{__builtin_nan}, except the return type is @code{_Decimal64}. +@end deftypefn + +@deftypefn {Built-in Function} _Decimal128 __builtin_nand128 (const char *str) +Similar to @code{__builtin_nan}, except the return type is @code{_Decimal128}. +@end deftypefn + @deftypefn {Built-in Function} float __builtin_nanf (const char *str) Similar to @code{__builtin_nan}, except the return type is @code{float}. @end deftypefn diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index ea57dbe..4960599 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1421,6 +1421,11 @@ precedence for that field, but the alignment of the rest of the structure may affect its placement. @end deftypefn +@deftypefn {Target Hook} {bool} TARGET_DECIMAL_FLOAT_SUPPORTED_P (void) +Returns true if the target supports decimal floating point. +The default version of this hook always returns false. +@end deftypefn + @deftypefn {Target Hook} {const char *} TARGET_MANGLE_FUNDAMENTAL_TYPE (tree @var{type}) If your target defines any fundamental types, define this hook to return the appropriate encoding for these types as part of a C++ diff --git a/gcc/ginclude/decfloat.h b/gcc/ginclude/decfloat.h new file mode 100644 index 0000000..fbf1346 --- /dev/null +++ b/gcc/ginclude/decfloat.h @@ -0,0 +1,108 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + +/* As a special exception, if you include this header file into source + files compiled by GCC, this header file does not by itself cause + the resulting executable to be covered by the GNU General Public + License. This exception does not however invalidate any other + reasons why the executable file might be covered by the GNU General + Public License. */ + +/* + * Draft C Extension to support decimal floating-pointing arithmetic: + * Characteristics of decimal floating types + */ + +#ifndef _DECFLOAT_H___ +#define _DECFLOAT_H___ + +/* Number of base-FLT_RADIX digits in the significand, p. */ +#undef DEC32_MANT_DIG +#undef DEC64_MANT_DIG +#undef DEC128_MANT_DIG +#define DEC32_MANT_DIG __DEC32_MANT_DIG__ +#define DEC64_MANT_DIG __DEC64_MANT_DIG__ +#define DEC128_MANT_DIG __DEC128_MANT_DIG__ + +/* Minimum exponent. */ +#undef DEC32_MIN_EXP +#undef DEC64_MIN_EXP +#undef DEC128_MIN_EXP +#define DEC32_MIN_EXP __DEC32_MIN_EXP__ +#define DEC64_MIN_EXP __DEC64_MIN_EXP__ +#define DEC128_MIN_EXP __DEC128_MIN_EXP__ + +/* Maximum exponent. */ +#undef DEC32_MAX_EXP +#undef DEC64_MAX_EXP +#undef DEC128_MAX_EXP +#define DEC32_MAX_EXP __DEC32_MAX_EXP__ +#define DEC64_MAX_EXP __DEC64_MAX_EXP__ +#define DEC128_MAX_EXP __DEC128_MAX_EXP__ + +/* Maximum representable finite decimal floating-point number + (there are 6, 15, and 33 9s after the decimal points respectively). */ +#undef DEC32_MAX +#undef DEC64_MAX +#undef DEC128_MAX +#define DEC32_MAX __DEC32_MAX__ +#define DEC64_MAX __DEC64_MAX__ +#define DEC128_MAX __DEC128_MAX__ + +/* The difference between 1 and the least value greater than 1 that is + representable in the given floating point type. */ +#undef DEC32_EPSILON +#undef DEC64_EPSILON +#undef DEC128_EPSILON +#define DEC32_EPSILON __DEC32_EPSILON__ +#define DEC64_EPSILON __DEC64_EPSILON__ +#define DEC128_EPSILON __DEC128_EPSILON__ + +/* Minimum normalized positive floating-point number. */ +#undef DEC32_MIN +#undef DEC64_MIN +#undef DEC128_MIN +#define DEC32_MIN __DEC32_MIN__ +#define DEC64_MIN __DEC64_MIN__ +#define DEC128_MIN __DEC128_MIN__ + +/* Minimum denormalized positive floating-point number. */ +#undef DEC32_DEN +#undef DEC64_DEN +#undef DEC128_DEN +#define DEC32_DEN __DEC32_MIN__ +#define DEC64_DEN __DEC64_MIN__ +#define DEC128_DEN __DEC128_MIN__ + +/* The floating-point expression evaluation method. + -1 indeterminate + 0 evaluate all operations and constants just to the range and + precision of the type + 1 evaluate operations and constants of type _Decimal32 + and _Decimal64 to the range and precision of the _Decimal64 + type, evaluate _Decimal128 operations and constants to the + range and precision of the _Decimal128 type; + 2 evaluate all operations and constants to the range and + precision of the _Decimal128 type. +*/ + +#undef DECFLT_EVAL_METHOD +#define DECFLT_EVAL_METHOD __DECFLT_EVAL_METHOD__ + +#endif /* _DECFLOAT_H___ */ diff --git a/gcc/target-def.h b/gcc/target-def.h index c15c798..de0f19b 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -366,6 +366,10 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define TARGET_MANGLE_FUNDAMENTAL_TYPE hook_constcharptr_tree_null #define TARGET_ALLOCATE_INITIAL_VALUE NULL +#ifndef TARGET_DECIMAL_FLOAT_SUPPORTED_P +#define TARGET_DECIMAL_FLOAT_SUPPORTED_P hook_bool_void_false +#endif + #ifndef TARGET_INIT_LIBFUNCS #define TARGET_INIT_LIBFUNCS hook_void_void #endif @@ -557,6 +561,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. TARGET_INSERT_ATTRIBUTES, \ TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P, \ TARGET_MS_BITFIELD_LAYOUT_P, \ + TARGET_DECIMAL_FLOAT_SUPPORTED_P, \ TARGET_ALIGN_ANON_BITFIELD, \ TARGET_INIT_BUILTINS, \ TARGET_EXPAND_BUILTIN, \ diff --git a/gcc/target.h b/gcc/target.h index 96dc425..6a49463 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -352,6 +352,9 @@ struct gcc_target Microsoft Visual C++ bitfield layout rules. */ bool (* ms_bitfield_layout_p) (tree record_type); + /* True if the target supports decimal floating point. */ + bool (* decimal_float_supported_p) (void); + /* Return true if anonymous bitfields affect structure alignment. */ bool (* align_anon_bitfield) (void); diff --git a/gcc/targhooks.c b/gcc/targhooks.c index afeba1f..5ef2369 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -262,6 +262,9 @@ default_scalar_mode_supported_p (enum machine_mode mode) return true; return false; + case MODE_DECIMAL_FLOAT: + return false; + default: gcc_unreachable (); } diff --git a/gcc/tree.c b/gcc/tree.c index 5e99305..7d2a292 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -6259,6 +6259,25 @@ build_common_tree_nodes_2 (int short_double) long_double_ptr_type_node = build_pointer_type (long_double_type_node); integer_ptr_type_node = build_pointer_type (integer_type_node); + /* Decimal float types. */ + dfloat32_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE; + layout_type (dfloat32_type_node); + TYPE_MODE (dfloat32_type_node) = SDmode; + dfloat32_ptr_type_node = build_pointer_type (dfloat32_type_node); + + dfloat64_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (dfloat64_type_node) = DECIMAL64_TYPE_SIZE; + layout_type (dfloat64_type_node); + TYPE_MODE (dfloat64_type_node) = DDmode; + dfloat64_ptr_type_node = build_pointer_type (dfloat64_type_node); + + dfloat128_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE; + layout_type (dfloat128_type_node); + TYPE_MODE (dfloat128_type_node) = TDmode; + dfloat128_ptr_type_node = build_pointer_type (dfloat128_type_node); + complex_integer_type_node = make_node (COMPLEX_TYPE); TREE_TYPE (complex_integer_type_node) = integer_type_node; layout_type (complex_integer_type_node); diff --git a/gcc/tree.h b/gcc/tree.h index 6c20db8..0efe683 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2933,6 +2933,13 @@ enum tree_index TI_BOOLEAN_TYPE, TI_FILEPTR_TYPE, + TI_DFLOAT32_TYPE, + TI_DFLOAT64_TYPE, + TI_DFLOAT128_TYPE, + TI_DFLOAT32_PTR_TYPE, + TI_DFLOAT64_PTR_TYPE, + TI_DFLOAT128_PTR_TYPE, + TI_VOID_LIST_NODE, TI_MAIN_IDENTIFIER, @@ -3005,6 +3012,14 @@ extern GTY(()) tree global_trees[TI_MAX]; #define boolean_false_node global_trees[TI_BOOLEAN_FALSE] #define boolean_true_node global_trees[TI_BOOLEAN_TRUE] +/* The decimal floating point types. */ +#define dfloat32_type_node global_trees[TI_DFLOAT32_TYPE] +#define dfloat64_type_node global_trees[TI_DFLOAT64_TYPE] +#define dfloat128_type_node global_trees[TI_DFLOAT128_TYPE] +#define dfloat32_ptr_type_node global_trees[TI_DFLOAT32_PTR_TYPE] +#define dfloat64_ptr_type_node global_trees[TI_DFLOAT64_PTR_TYPE] +#define dfloat128_ptr_type_node global_trees[TI_DFLOAT128_PTR_TYPE] + /* The node that should be placed at the end of a parameter list to indicate that the function does not take a variable number of arguments. The TREE_VALUE will be void_type_node and there will be -- cgit v1.1