diff options
106 files changed, 2932 insertions, 126 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 04ad7c1c316..3e03050ede4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,65 @@ +2016-08-19 Joseph Myers <joseph@codesourcery.com> + + PR c/32187 + * tree-core.h (TI_COMPLEX_FLOAT16_TYPE) + (TI_COMPLEX_FLOATN_NX_TYPE_FIRST, TI_COMPLEX_FLOAT32_TYPE) + (TI_COMPLEX_FLOAT64_TYPE, TI_COMPLEX_FLOAT128_TYPE) + (TI_COMPLEX_FLOAT32X_TYPE, TI_COMPLEX_FLOAT64X_TYPE) + (TI_COMPLEX_FLOAT128X_TYPE, TI_FLOAT16_TYPE, TI_FLOATN_TYPE_FIRST) + (TI_FLOATN_NX_TYPE_FIRST, TI_FLOAT32_TYPE, TI_FLOAT64_TYPE) + (TI_FLOAT128_TYPE, TI_FLOATN_TYPE_LAST, TI_FLOAT32X_TYPE) + (TI_FLOATNX_TYPE_FIRST, TI_FLOAT64X_TYPE, TI_FLOAT128X_TYPE) + (TI_FLOATNX_TYPE_LAST, TI_FLOATN_NX_TYPE_LAST): New enum + tree_index values. + (NUM_FLOATN_TYPES, NUM_FLOATNX_TYPES, NUM_FLOATN_NX_TYPES): New + macros. + (struct floatn_type_info): New structure type. + (floatn_nx_types): New variable declaration. + * tree.h (FLOATN_TYPE_NODE, FLOATN_NX_TYPE_NODE) + (FLOATNX_TYPE_NODE, float128_type_node, float64x_type_node) + (COMPLEX_FLOATN_NX_TYPE_NODE): New macros. + * tree.c (floatn_nx_types): New variable. + (build_common_tree_nodes): Initialize _FloatN, _FloatNx and + corresponding complex types. + * target.def (floatn_mode): New hook. + * targhooks.c: Include "real.h". + (default_floatn_mode): New function. + * targhooks.h (default_floatn_mode): New prototype. + * doc/extend.texi (Floating Types): Document _FloatN and _FloatNx + types. + * doc/sourcebuild.texi (float@var{n}, float@var{n}x): Document new + effective-target and dg-add-options keywords. + (float@var{n}_runtime, float@var{n}x_runtime, floatn_nx_runtime): + Document new effective-target keywords. + * doc/tm.texi.in (TARGET_FLOATN_MODE): New @hook. + * doc/tm.texi: Regenerate. + * ginclude/float.h (LDBL_DECIMAL_DIG): Define to + __LDBL_DECIMAL_DIG__, not __DECIMAL_DIG__. + [__STDC_WANT_IEC_60559_TYPES_EXT__]: Define macros from TS + 18661-3. + * real.h (struct real_format): Add field ieee_bits. + * real.c (ieee_single_format, mips_single_format) + (motorola_single_format, spu_single_format, ieee_double_format) + (mips_double_format, motorola_double_format) + (ieee_extended_motorola_format, ieee_extended_intel_96_format) + (ieee_extended_intel_128_format) + (ieee_extended_intel_96_round_53_format, ibm_extended_format) + (mips_extended_format, ieee_quad_format, mips_quad_format) + (vax_f_format, vax_d_format, vax_g_format, decimal_single_format) + (decimal_double_format, decimal_quad_format, ieee_half_format) + (arm_half_format, real_internal_format: Initialize ieee_bits + field. + * config/i386/i386.c (ix86_init_builtin_types): Do not initialize + float128_type_node. Set float80_type_node to float64x_type_node + if appropriate and long_double_type_node not appropriate. + * config/ia64/ia64.c (ia64_init_builtins): Likewise. + * config/pdp11/pdp11.c (pdp11_f_format, pdp11_d_format): + Initialize ieee_bits field. + * config/rs6000/rs6000.c (TARGET_FLOATN_MODE): New macro. + (rs6000_init_builtins): Set ieee128_float_type_node to + float128_type_node. + (rs6000_floatn_mode): New function. + 2016-08-19 Jakub Jelinek <jakub@redhat.com> * config/i386/rdseedintrin.h (_rdseed16_step, _rdseed32_step, diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 616ca132de3..bec37cffd75 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,28 @@ +2016-08-19 Joseph Myers <joseph@codesourcery.com> + + PR c/32187 + * c-common.h (RID_FLOAT16, RID_FLOATN_NX_FIRST, RID_FLOAT32) + (RID_FLOAT64, RID_FLOAT128, RID_FLOAT32X, RID_FLOAT64X) + (RID_FLOAT128X): New enum rid values. + (CASE_RID_FLOATN_NX): New macro. + * c-common.c (c_common_reswords): Add _FloatN and _FloatNx + keywords. + (c_common_type_for_mode): Check for _FloatN and _FloatNx and + corresponding complex types. + (c_common_nodes_and_builtins): For non-C++, register _FloatN and + _FloatNx and corresponding complex types. + (keyword_begins_type_specifier): Use CASE_RID_FLOATN_NX. + * c-cppbuiltin.c (builtin_define_float_constants): Check _FloatN + and _FloatNx types for the widest type for determining + DECIMAL_DIG. Define __LDBL_DECIMAL_DIG__ as well as + __DECIMAL_DIG__ for long double. Handle FMA_SUFFIX being NULL. + (c_cpp_builtins): Call builtin_define_float_constants for _FloatN + and _FloatNx types. + * c-lex.c (interpret_float): Handle _FloatN and _FloatNx + constants. + * c-pretty-print.c (pp_c_floating_constant): Handle _FloatN and + _FloatNx types. + 2016-08-18 David Malcolm <dmalcolm@redhat.com> * c-opts.c (c_diagnostic_finalizer): Update for change to diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 9082883cb68..32468ca1351 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -434,6 +434,13 @@ const struct c_common_resword c_common_reswords[] = { "_Cilk_sync", RID_CILK_SYNC, 0 }, { "_Cilk_for", RID_CILK_FOR, 0 }, { "_Imaginary", RID_IMAGINARY, D_CONLY }, + { "_Float16", RID_FLOAT16, D_CONLY }, + { "_Float32", RID_FLOAT32, D_CONLY }, + { "_Float64", RID_FLOAT64, D_CONLY }, + { "_Float128", RID_FLOAT128, D_CONLY }, + { "_Float32x", RID_FLOAT32X, D_CONLY }, + { "_Float64x", RID_FLOAT64X, D_CONLY }, + { "_Float128x", RID_FLOAT128X, D_CONLY }, { "_Decimal32", RID_DFLOAT32, D_CONLY | D_EXT }, { "_Decimal64", RID_DFLOAT64, D_CONLY | D_EXT }, { "_Decimal128", RID_DFLOAT128, D_CONLY | D_EXT }, @@ -3478,6 +3485,11 @@ c_common_type_for_mode (machine_mode mode, int unsignedp) if (mode == TYPE_MODE (long_double_type_node)) return long_double_type_node; + for (i = 0; i < NUM_FLOATN_NX_TYPES; i++) + if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE + && mode == TYPE_MODE (FLOATN_NX_TYPE_NODE (i))) + return FLOATN_NX_TYPE_NODE (i); + if (mode == TYPE_MODE (void_type_node)) return void_type_node; @@ -3503,6 +3515,11 @@ c_common_type_for_mode (machine_mode mode, int unsignedp) if (mode == TYPE_MODE (complex_long_double_type_node)) return complex_long_double_type_node; + for (i = 0; i < NUM_FLOATN_NX_TYPES; i++) + if (COMPLEX_FLOATN_NX_TYPE_NODE (i) != NULL_TREE + && mode == TYPE_MODE (COMPLEX_FLOATN_NX_TYPE_NODE (i))) + return COMPLEX_FLOATN_NX_TYPE_NODE (i); + if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp) return complex_integer_type_node; @@ -5406,6 +5423,12 @@ 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); + if (!c_dialect_cxx ()) + for (i = 0; i < NUM_FLOATN_NX_TYPES; i++) + if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE) + record_builtin_type ((enum rid) (RID_FLOATN_NX_FIRST + i), NULL, + FLOATN_NX_TYPE_NODE (i)); + /* Only supported decimal floating point extension if the target actually supports underlying modes. */ if (targetm.scalar_mode_supported_p (SDmode) @@ -5495,6 +5518,20 @@ c_common_nodes_and_builtins (void) TYPE_DECL, get_identifier ("complex long double"), complex_long_double_type_node)); + if (!c_dialect_cxx ()) + for (i = 0; i < NUM_FLOATN_NX_TYPES; i++) + if (COMPLEX_FLOATN_NX_TYPE_NODE (i) != NULL_TREE) + { + char buf[30]; + sprintf (buf, "complex _Float%d%s", floatn_nx_types[i].n, + floatn_nx_types[i].extended ? "x" : ""); + lang_hooks.decls.pushdecl + (build_decl (UNKNOWN_LOCATION, + TYPE_DECL, + get_identifier (buf), + COMPLEX_FLOATN_NX_TYPE_NODE (i))); + } + if (c_dialect_cxx ()) /* For C++, make fileptr_type_node a distinct void * type until FILE type is defined. */ @@ -12523,6 +12560,7 @@ keyword_begins_type_specifier (enum rid keyword) case RID_LONG: case RID_SHORT: case RID_SIGNED: + CASE_RID_FLOATN_NX: case RID_DFLOAT32: case RID_DFLOAT64: case RID_DFLOAT128: diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 31320bf7c87..bc22baa26b8 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -102,6 +102,20 @@ enum rid RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR, RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE, RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, + + /* TS 18661-3 keywords, in the same sequence as the TI_* values. */ + RID_FLOAT16, + RID_FLOATN_NX_FIRST = RID_FLOAT16, + RID_FLOAT32, + RID_FLOAT64, + RID_FLOAT128, + RID_FLOAT32X, + RID_FLOAT64X, + RID_FLOAT128X, +#define CASE_RID_FLOATN_NX \ + case RID_FLOAT16: case RID_FLOAT32: case RID_FLOAT64: case RID_FLOAT128: \ + case RID_FLOAT32X: case RID_FLOAT64X: case RID_FLOAT128X + RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN, /* C11 */ diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c index 82ed19d1f8d..1f7d013239f 100644 --- a/gcc/c-family/c-cppbuiltin.c +++ b/gcc/c-family/c-cppbuiltin.c @@ -125,7 +125,7 @@ builtin_define_float_constants (const char *name_prefix, const double log10_2 = .30102999566398119521; double log10_b; const struct real_format *fmt; - const struct real_format *ldfmt; + const struct real_format *widefmt; char name[64], buf[128]; int dig, min_10_exp, max_10_exp; @@ -134,8 +134,20 @@ builtin_define_float_constants (const char *name_prefix, fmt = REAL_MODE_FORMAT (TYPE_MODE (type)); gcc_assert (fmt->b != 10); - ldfmt = REAL_MODE_FORMAT (TYPE_MODE (long_double_type_node)); - gcc_assert (ldfmt->b != 10); + widefmt = REAL_MODE_FORMAT (TYPE_MODE (long_double_type_node)); + gcc_assert (widefmt->b != 10); + for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) + { + tree wtype = FLOATN_NX_TYPE_NODE (i); + if (wtype != NULL_TREE) + { + const struct real_format *wfmt + = REAL_MODE_FORMAT (TYPE_MODE (wtype)); + gcc_assert (wfmt->b != 10); + if (wfmt->p > widefmt->p) + widefmt = wfmt; + } + } /* The radix of the exponent representation. */ if (type == float_type_node) @@ -219,7 +231,7 @@ builtin_define_float_constants (const char *name_prefix, floating type, but we want this value for rendering constants below. */ { double d_decimal_dig - = 1 + (fmt->p < ldfmt->p ? ldfmt->p : fmt->p) * log10_b; + = 1 + (fmt->p < widefmt->p ? widefmt->p : fmt->p) * log10_b; decimal_dig = d_decimal_dig; if (decimal_dig < d_decimal_dig) decimal_dig++; @@ -231,13 +243,13 @@ builtin_define_float_constants (const char *name_prefix, if (type_decimal_dig < type_d_decimal_dig) type_decimal_dig++; } + /* Arbitrarily, define __DECIMAL_DIG__ when defining macros for long + double, although it may be greater than the value for long + double. */ if (type == long_double_type_node) builtin_define_with_int_value ("__DECIMAL_DIG__", decimal_dig); - else - { - sprintf (name, "__%s_DECIMAL_DIG__", name_prefix); - builtin_define_with_int_value (name, type_decimal_dig); - } + sprintf (name, "__%s_DECIMAL_DIG__", name_prefix); + builtin_define_with_int_value (name, type_decimal_dig); /* Since, for the supported formats, B is always a power of 2, we construct the following numbers directly as a hexadecimal @@ -289,7 +301,7 @@ builtin_define_float_constants (const char *name_prefix, builtin_define_with_int_value (name, MODE_HAS_NANS (TYPE_MODE (type))); /* Note whether we have fast FMA. */ - if (mode_has_fma (TYPE_MODE (type))) + if (mode_has_fma (TYPE_MODE (type)) && fma_suffix != NULL) { sprintf (name, "__FP_FAST_FMA%s", fma_suffix); builtin_define_with_int_value (name, 1); @@ -984,6 +996,19 @@ c_cpp_builtins (cpp_reader *pfile) builtin_define_float_constants ("LDBL", "L", "%s", "L", long_double_type_node); + for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) + { + if (FLOATN_NX_TYPE_NODE (i) == NULL_TREE) + continue; + char prefix[20], csuffix[20]; + sprintf (prefix, "FLT%d%s", floatn_nx_types[i].n, + floatn_nx_types[i].extended ? "X" : ""); + sprintf (csuffix, "F%d%s", floatn_nx_types[i].n, + floatn_nx_types[i].extended ? "x" : ""); + builtin_define_float_constants (prefix, csuffix, "%s", NULL, + FLOATN_NX_TYPE_NODE (i)); + } + /* For decfloat.h. */ builtin_define_decimal_float_constants ("DEC32", "DF", dfloat32_type_node); builtin_define_decimal_float_constants ("DEC64", "DD", dfloat64_type_node); diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c index c904ee67fc0..829c18b26a4 100644 --- a/gcc/c-family/c-lex.c +++ b/gcc/c-family/c-lex.c @@ -840,6 +840,26 @@ interpret_float (const cpp_token *token, unsigned int flags, type = c_common_type_for_mode (mode, 0); gcc_assert (type); } + else if ((flags & (CPP_N_FLOATN | CPP_N_FLOATNX)) != 0) + { + unsigned int n = (flags & CPP_N_WIDTH_FLOATN_NX) >> CPP_FLOATN_SHIFT; + bool extended = (flags & CPP_N_FLOATNX) != 0; + type = NULL_TREE; + for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) + if (floatn_nx_types[i].n == (int) n + && floatn_nx_types[i].extended == extended) + { + type = FLOATN_NX_TYPE_NODE (i); + break; + } + if (type == NULL_TREE) + { + error ("unsupported non-standard suffix on floating constant"); + return error_mark_node; + } + else + pedwarn (input_location, OPT_Wpedantic, "non-standard suffix on floating constant"); + } else if ((flags & CPP_N_WIDTH) == CPP_N_LARGE) type = long_double_type_node; else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL @@ -868,6 +888,17 @@ interpret_float (const cpp_token *token, unsigned int flags, if (flags & CPP_N_IMAGINARY) /* I or J suffix. */ copylen--; + if (flags & CPP_N_FLOATNX) + copylen--; + if (flags & (CPP_N_FLOATN | CPP_N_FLOATNX)) + { + unsigned int n = (flags & CPP_N_WIDTH_FLOATN_NX) >> CPP_FLOATN_SHIFT; + while (n > 0) + { + copylen--; + n /= 10; + } + } } copy = (char *) alloca (copylen + 1); diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c index 374bd1a3484..90428cac183 100644 --- a/gcc/c-family/c-pretty-print.c +++ b/gcc/c-family/c-pretty-print.c @@ -1045,6 +1045,16 @@ pp_c_floating_constant (c_pretty_printer *pp, tree r) pp_string (pp, "dd"); else if (TREE_TYPE (r) == dfloat32_type_node) pp_string (pp, "df"); + else if (TREE_TYPE (r) != double_type_node) + for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) + if (TREE_TYPE (r) == FLOATN_NX_TYPE_NODE (i)) + { + pp_character (pp, 'f'); + pp_decimal_int (pp, floatn_nx_types[i].n); + if (floatn_nx_types[i].extended) + pp_character (pp, 'x'); + break; + } } /* Print out a FIXED value as a decimal-floating-constant. */ diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 522da71ff64..8d9d4aabb0a 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,17 @@ +2016-08-19 Joseph Myers <joseph@codesourcery.com> + + PR c/32187 + * c-tree.h (cts_floatn_nx): New enum c_typespec_keyword value. + (struct c_declspecs): Add field floatn_nx_idx. + * c-decl.c (declspecs_add_type, finish_declspecs): Handle _FloatN + and _FloatNx type specifiers. + * c-parser.c (c_keyword_starts_typename, c_token_starts_declspecs) + (c_parser_declspecs, c_parser_attribute_any_word) + (c_parser_objc_selector): Use CASE_RID_FLOATN_NX. + * c-typeck.c (c_common_type): Handle _FloatN and _FloatNx types. + (convert_arguments): Avoid promoting _FloatN and _FloatNx types + narrower than double. + 2016-08-12 Jakub Jelinek <jakub@redhat.com> Martin Liska <mliska@suse.cz> diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 9ad473cdbcb..0fb2d206458 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -9804,6 +9804,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, error_at (loc, ("both %<long%> and %<float%> in " "declaration specifiers")); + else if (specs->typespec_word == cts_floatn_nx) + error_at (loc, + ("both %<long%> and %<_Float%d%s%> in " + "declaration specifiers"), + floatn_nx_types[specs->floatn_nx_idx].n, + (floatn_nx_types[specs->floatn_nx_idx].extended + ? "x" + : "")); else if (specs->typespec_word == cts_dfloat32) error_at (loc, ("both %<long%> and %<_Decimal32%> in " @@ -9857,6 +9865,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, error_at (loc, ("both %<short%> and %<double%> in " "declaration specifiers")); + else if (specs->typespec_word == cts_floatn_nx) + error_at (loc, + ("both %<short%> and %<_Float%d%s%> in " + "declaration specifiers"), + floatn_nx_types[specs->floatn_nx_idx].n, + (floatn_nx_types[specs->floatn_nx_idx].extended + ? "x" + : "")); else if (specs->typespec_word == cts_dfloat32) error_at (loc, ("both %<short%> and %<_Decimal32%> in " @@ -9901,6 +9917,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, error_at (loc, ("both %<signed%> and %<double%> in " "declaration specifiers")); + else if (specs->typespec_word == cts_floatn_nx) + error_at (loc, + ("both %<signed%> and %<_Float%d%s%> in " + "declaration specifiers"), + floatn_nx_types[specs->floatn_nx_idx].n, + (floatn_nx_types[specs->floatn_nx_idx].extended + ? "x" + : "")); else if (specs->typespec_word == cts_dfloat32) error_at (loc, ("both %<signed%> and %<_Decimal32%> in " @@ -9945,6 +9969,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, error_at (loc, ("both %<unsigned%> and %<double%> in " "declaration specifiers")); + else if (specs->typespec_word == cts_floatn_nx) + error_at (loc, + ("both %<unsigned%> and %<_Float%d%s%> in " + "declaration specifiers"), + floatn_nx_types[specs->floatn_nx_idx].n, + (floatn_nx_types[specs->floatn_nx_idx].extended + ? "x" + : "")); else if (specs->typespec_word == cts_dfloat32) error_at (loc, ("both %<unsigned%> and %<_Decimal32%> in " @@ -10049,6 +10081,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, error_at (loc, ("both %<_Sat%> and %<double%> in " "declaration specifiers")); + else if (specs->typespec_word == cts_floatn_nx) + error_at (loc, + ("both %<_Sat%> and %<_Float%d%s%> in " + "declaration specifiers"), + floatn_nx_types[specs->floatn_nx_idx].n, + (floatn_nx_types[specs->floatn_nx_idx].extended + ? "x" + : "")); else if (specs->typespec_word == cts_dfloat32) error_at (loc, ("both %<_Sat%> and %<_Decimal32%> in " @@ -10082,8 +10122,9 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, } else { - /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32", - "__intN", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or + /* "void", "_Bool", "char", "int", "float", "double", + "_FloatN", "_FloatNx", "_Decimal32", "__intN", + "_Decimal64", "_Decimal128", "_Fract", "_Accum" or "__auto_type". */ if (specs->typespec_word != cts_none) { @@ -10308,6 +10349,69 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, specs->locations[cdw_typespec] = loc; } return specs; + CASE_RID_FLOATN_NX: + specs->floatn_nx_idx = i - RID_FLOATN_NX_FIRST; + if (!in_system_header_at (input_location)) + pedwarn (loc, OPT_Wpedantic, + "ISO C does not support the %<_Float%d%s%> type", + floatn_nx_types[specs->floatn_nx_idx].n, + (floatn_nx_types[specs->floatn_nx_idx].extended + ? "x" + : "")); + + if (specs->long_p) + error_at (loc, + ("both %<long%> and %<_Float%d%s%> in " + "declaration specifiers"), + floatn_nx_types[specs->floatn_nx_idx].n, + (floatn_nx_types[specs->floatn_nx_idx].extended + ? "x" + : "")); + else if (specs->short_p) + error_at (loc, + ("both %<short%> and %<_Float%d%s%> in " + "declaration specifiers"), + floatn_nx_types[specs->floatn_nx_idx].n, + (floatn_nx_types[specs->floatn_nx_idx].extended + ? "x" + : "")); + else if (specs->signed_p) + error_at (loc, + ("both %<signed%> and %<_Float%d%s%> in " + "declaration specifiers"), + floatn_nx_types[specs->floatn_nx_idx].n, + (floatn_nx_types[specs->floatn_nx_idx].extended + ? "x" + : "")); + else if (specs->unsigned_p) + error_at (loc, + ("both %<unsigned%> and %<_Float%d%s%> in " + "declaration specifiers"), + floatn_nx_types[specs->floatn_nx_idx].n, + (floatn_nx_types[specs->floatn_nx_idx].extended + ? "x" + : "")); + else if (specs->saturating_p) + error_at (loc, + ("both %<_Sat%> and %<_Float%d%s%> in " + "declaration specifiers"), + floatn_nx_types[specs->floatn_nx_idx].n, + (floatn_nx_types[specs->floatn_nx_idx].extended + ? "x" + : "")); + else if (FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx) == NULL_TREE) + error_at (loc, + "%<_Float%d%s%> is not supported on this target", + floatn_nx_types[specs->floatn_nx_idx].n, + (floatn_nx_types[specs->floatn_nx_idx].extended + ? "x" + : "")); + else + { + specs->typespec_word = cts_floatn_nx; + specs->locations[cdw_typespec] = loc; + } + return specs; case RID_DFLOAT32: case RID_DFLOAT64: case RID_DFLOAT128: @@ -10785,6 +10889,13 @@ finish_declspecs (struct c_declspecs *specs) : double_type_node); } break; + case cts_floatn_nx: + gcc_assert (!specs->long_p && !specs->short_p + && !specs->signed_p && !specs->unsigned_p); + specs->type = (specs->complex_p + ? COMPLEX_FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx) + : FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx)); + break; case cts_dfloat32: case cts_dfloat64: case cts_dfloat128: diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index c050f644566..fe0c95f3b1b 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -540,6 +540,7 @@ c_keyword_starts_typename (enum rid keyword) case RID_DFLOAT32: case RID_DFLOAT64: case RID_DFLOAT128: + CASE_RID_FLOATN_NX: case RID_BOOL: case RID_ENUM: case RID_STRUCT: @@ -727,6 +728,7 @@ c_token_starts_declspecs (c_token *token) case RID_DFLOAT32: case RID_DFLOAT64: case RID_DFLOAT128: + CASE_RID_FLOATN_NX: case RID_BOOL: case RID_ENUM: case RID_STRUCT: @@ -2536,6 +2538,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, case RID_DFLOAT32: case RID_DFLOAT64: case RID_DFLOAT128: + CASE_RID_FLOATN_NX: case RID_BOOL: case RID_FRACT: case RID_ACCUM: @@ -4009,6 +4012,7 @@ c_parser_attribute_any_word (c_parser *parser) case RID_DFLOAT32: case RID_DFLOAT64: case RID_DFLOAT128: + CASE_RID_FLOATN_NX: case RID_BOOL: case RID_FRACT: case RID_ACCUM: @@ -9638,6 +9642,7 @@ c_parser_objc_selector (c_parser *parser) case RID_CHAR: case RID_FLOAT: case RID_DOUBLE: + CASE_RID_FLOATN_NX: case RID_VOID: case RID_BOOL: case RID_ATOMIC: diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index 46be53ece21..5a8ab6df483 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -230,6 +230,7 @@ enum c_typespec_keyword { cts_dfloat32, cts_dfloat64, cts_dfloat128, + cts_floatn_nx, cts_fract, cts_accum, cts_auto_type @@ -295,6 +296,9 @@ struct c_declspecs { int align_log; /* For the __intN declspec, this stores the index into the int_n_* arrays. */ int int_n_idx; + /* For the _FloatN and _FloatNx declspec, this stores the index into + the floatn_nx_types array. */ + int floatn_nx_idx; /* The storage class specifier, or csc_none if none. */ enum c_storage_class storage_class; /* Any type specifier keyword used such as "int", not reflecting diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 2e1e09dab00..bc8728a49b6 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -927,18 +927,41 @@ c_common_type (tree t1, tree t2) return long_integer_type_node; } + /* For floating types of the same TYPE_PRECISION (which we here + assume means either the same set of values, or sets of values + neither a subset of the other, with behavior being undefined in + the latter case), follow the rules from TS 18661-3: prefer + interchange types _FloatN, then standard types long double, + double, float, then extended types _FloatNx. For extended types, + check them starting with _Float128x as that seems most consistent + in spirit with preferring long double to double; for interchange + types, also check in that order for consistency although it's not + possible for more than one of them to have the same + precision. */ + tree mv1 = TYPE_MAIN_VARIANT (t1); + tree mv2 = TYPE_MAIN_VARIANT (t2); + + for (int i = NUM_FLOATN_TYPES - 1; i >= 0; i--) + if (mv1 == FLOATN_TYPE_NODE (i) || mv2 == FLOATN_TYPE_NODE (i)) + return FLOATN_TYPE_NODE (i); + /* Likewise, prefer long double to double even if same size. */ - if (TYPE_MAIN_VARIANT (t1) == long_double_type_node - || TYPE_MAIN_VARIANT (t2) == long_double_type_node) + if (mv1 == long_double_type_node || mv2 == long_double_type_node) return long_double_type_node; /* Likewise, prefer double to float even if same size. We got a couple of embedded targets with 32 bit doubles, and the pdp11 might have 64 bit floats. */ - if (TYPE_MAIN_VARIANT (t1) == double_type_node - || TYPE_MAIN_VARIANT (t2) == double_type_node) + if (mv1 == double_type_node || mv2 == double_type_node) return double_type_node; + if (mv1 == float_type_node || mv2 == float_type_node) + return float_type_node; + + for (int i = NUM_FLOATNX_TYPES - 1; i >= 0; i--) + if (mv1 == FLOATNX_TYPE_NODE (i) || mv2 == FLOATNX_TYPE_NODE (i)) + return FLOATNX_TYPE_NODE (i); + /* Otherwise prefer the unsigned one. */ if (TYPE_UNSIGNED (t1)) @@ -3284,6 +3307,30 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist, val = require_complete_type (ploc, val); + /* Some floating-point arguments must be promoted to double when + no type is specified by a prototype. This applies to + arguments of type float, and to architecture-specific types + (ARM __fp16), but not to _FloatN or _FloatNx types. */ + bool promote_float_arg = false; + if (type == NULL_TREE + && TREE_CODE (valtype) == REAL_TYPE + && (TYPE_PRECISION (valtype) + <= TYPE_PRECISION (double_type_node)) + && TYPE_MAIN_VARIANT (valtype) != double_type_node + && TYPE_MAIN_VARIANT (valtype) != long_double_type_node + && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (valtype))) + { + /* Promote this argument, unless it has a _FloatN or + _FloatNx type. */ + promote_float_arg = true; + for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) + if (TYPE_MAIN_VARIANT (valtype) == FLOATN_NX_TYPE_NODE (i)) + { + promote_float_arg = false; + break; + } + } + if (type != 0) { /* Formal parm type is specified by a function prototype. */ @@ -3450,12 +3497,7 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist, parmval = default_conversion (parmval); } } - else if (TREE_CODE (valtype) == REAL_TYPE - && (TYPE_PRECISION (valtype) - <= TYPE_PRECISION (double_type_node)) - && TYPE_MAIN_VARIANT (valtype) != double_type_node - && TYPE_MAIN_VARIANT (valtype) != long_double_type_node - && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (valtype))) + else if (promote_float_arg) { if (type_generic) parmval = val; diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index be027f5e2dd..39794230c10 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -33325,24 +33325,29 @@ ix86_init_builtins_va_builtins_abi (void) static void ix86_init_builtin_types (void) { - tree float128_type_node, float80_type_node, const_string_type_node; + tree float80_type_node, const_string_type_node; /* The __float80 type. */ float80_type_node = long_double_type_node; if (TYPE_MODE (float80_type_node) != XFmode) { - /* The __float80 type. */ - float80_type_node = make_node (REAL_TYPE); + if (float64x_type_node != NULL_TREE + && TYPE_MODE (float64x_type_node) == XFmode) + float80_type_node = float64x_type_node; + else + { + /* The __float80 type. */ + float80_type_node = make_node (REAL_TYPE); - TYPE_PRECISION (float80_type_node) = 80; - layout_type (float80_type_node); + TYPE_PRECISION (float80_type_node) = 80; + layout_type (float80_type_node); + } } lang_hooks.types.register_builtin_type (float80_type_node, "__float80"); - /* The __float128 type. */ - float128_type_node = make_node (REAL_TYPE); - TYPE_PRECISION (float128_type_node) = 128; - layout_type (float128_type_node); + /* The __float128 type. The node has already been created as + _Float128, so we only need to register the __float128 name for + it. */ lang_hooks.types.register_builtin_type (float128_type_node, "__float128"); const_string_type_node diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 4fd7c84a18d..ebd2c86b8d8 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -10350,9 +10350,15 @@ ia64_init_builtins (void) (*lang_hooks.types.register_builtin_type) (fpreg_type, "__fpreg"); /* The __float80 type. */ - float80_type = make_node (REAL_TYPE); - TYPE_PRECISION (float80_type) = 80; - layout_type (float80_type); + if (float64x_type_node != NULL_TREE + && TYPE_MODE (float64x_type_node) == XFmode) + float80_type = float64x_type_node; + else + { + float80_type = make_node (REAL_TYPE); + TYPE_PRECISION (float80_type) = 80; + layout_type (float80_type); + } (*lang_hooks.types.register_builtin_type) (float80_type, "__float80"); /* The __float128 type. */ @@ -10362,14 +10368,12 @@ ia64_init_builtins (void) tree const_string_type = build_pointer_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST)); - tree float128_type = make_node (REAL_TYPE); - TYPE_PRECISION (float128_type) = 128; - layout_type (float128_type); - (*lang_hooks.types.register_builtin_type) (float128_type, "__float128"); + (*lang_hooks.types.register_builtin_type) (float128_type_node, + "__float128"); /* TFmode support builtins. */ - ftype = build_function_type_list (float128_type, NULL_TREE); + ftype = build_function_type_list (float128_type_node, NULL_TREE); decl = add_builtin_function ("__builtin_infq", ftype, IA64_BUILTIN_INFQ, BUILT_IN_MD, NULL, NULL_TREE); @@ -10380,7 +10384,7 @@ ia64_init_builtins (void) NULL, NULL_TREE); ia64_builtins[IA64_BUILTIN_HUGE_VALQ] = decl; - ftype = build_function_type_list (float128_type, + ftype = build_function_type_list (float128_type_node, const_string_type, NULL_TREE); decl = add_builtin_function ("__builtin_nanq", ftype, @@ -10395,8 +10399,8 @@ ia64_init_builtins (void) TREE_READONLY (decl) = 1; ia64_builtins[IA64_BUILTIN_NANSQ] = decl; - ftype = build_function_type_list (float128_type, - float128_type, + ftype = build_function_type_list (float128_type_node, + float128_type_node, NULL_TREE); decl = add_builtin_function ("__builtin_fabsq", ftype, IA64_BUILTIN_FABSQ, BUILT_IN_MD, @@ -10404,9 +10408,9 @@ ia64_init_builtins (void) TREE_READONLY (decl) = 1; ia64_builtins[IA64_BUILTIN_FABSQ] = decl; - ftype = build_function_type_list (float128_type, - float128_type, - float128_type, + ftype = build_function_type_list (float128_type_node, + float128_type_node, + float128_type_node, NULL_TREE); decl = add_builtin_function ("__builtin_copysignq", ftype, IA64_BUILTIN_COPYSIGNQ, BUILT_IN_MD, diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c index ec3d61a03ed..35d57c72488 100644 --- a/gcc/config/pdp11/pdp11.c +++ b/gcc/config/pdp11/pdp11.c @@ -69,6 +69,7 @@ const struct real_format pdp11_f_format = 127, 15, 15, + 0, false, false, false, @@ -91,6 +92,7 @@ const struct real_format pdp11_d_format = 127, 15, 15, + 0, false, false, false, diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index e58ede1e9f2..b232099b9e7 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1703,6 +1703,9 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_VECTOR_MODE_SUPPORTED_P #define TARGET_VECTOR_MODE_SUPPORTED_P rs6000_vector_mode_supported_p +#undef TARGET_FLOATN_MODE +#define TARGET_FLOATN_MODE rs6000_floatn_mode + #undef TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN #define TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN invalid_arg_for_unprototyped_fn @@ -16303,10 +16306,7 @@ rs6000_init_builtins (void) layout_type (ibm128_float_type_node); SET_TYPE_MODE (ibm128_float_type_node, IFmode); - ieee128_float_type_node = make_node (REAL_TYPE); - TYPE_PRECISION (ieee128_float_type_node) = 128; - layout_type (ieee128_float_type_node); - SET_TYPE_MODE (ieee128_float_type_node, KFmode); + ieee128_float_type_node = float128_type_node; lang_hooks.types.register_builtin_type (ieee128_float_type_node, "__float128"); @@ -36199,6 +36199,54 @@ rs6000_vector_mode_supported_p (machine_mode mode) return false; } +/* Target hook for floatn_mode. */ +static machine_mode +rs6000_floatn_mode (int n, bool extended) +{ + if (extended) + { + switch (n) + { + case 32: + return DFmode; + + case 64: + if (TARGET_FLOAT128) + return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode; + else + return VOIDmode; + + case 128: + return VOIDmode; + + default: + /* Those are the only valid _FloatNx types. */ + gcc_unreachable (); + } + } + else + { + switch (n) + { + case 32: + return SFmode; + + case 64: + return DFmode; + + case 128: + if (TARGET_FLOAT128) + return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode; + else + return VOIDmode; + + default: + return VOIDmode; + } + } + +} + /* Target hook for c_mode_for_suffix. */ static machine_mode rs6000_c_mode_for_suffix (char suffix) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 5285e002d7e..5124883ae5c 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -927,6 +927,8 @@ examine and set these two fictitious variables with your debugger. @node Floating Types @section Additional Floating Types @cindex additional floating types +@cindex @code{_Float@var{n}} data types +@cindex @code{_Float@var{n}x} data types @cindex @code{__float80} data type @cindex @code{__float128} data type @cindex @code{__ibm128} data type @@ -935,9 +937,19 @@ examine and set these two fictitious variables with your debugger. @cindex @code{W} floating point suffix @cindex @code{Q} floating point suffix -As an extension, GNU C supports additional floating +ISO/IEC TS 18661-3:2015 defines C support for additional floating +types @code{_Float@var{n}} and @code{_Float@var{n}x}, and GCC supports +these type names; the set of types supported depends on the target +architecture. These types are not supported when compiling C++. +Constants with these types use suffixes @code{f@var{n}} or +@code{F@var{n}} and @code{f@var{n}x} or @code{F@var{n}x}. These type +names can be used together with @code{_Complex} to declare complex +types. + +As an extension, GNU C and GNU C++ support additional floating types, @code{__float80} and @code{__float128} to support 80-bit -(@code{XFmode}) and 128-bit (@code{TFmode}) floating types. +(@code{XFmode}) and 128-bit (@code{TFmode}) floating types; these are +aliases for the type names @code{_Float64x} and @code{_Float128}. Support for additional types includes the arithmetic operators: add, subtract, multiply, divide; unary arithmetic operators; relational operators; equality operators; and conversions to and from @@ -954,9 +966,11 @@ typedef _Complex float __attribute__((mode(TC))) _Complex128; typedef _Complex float __attribute__((mode(XC))) _Complex80; @end smallexample -In order to use @code{__float128} and @code{__ibm128} on PowerPC Linux +In order to use @code{_Float128}, @code{__float128} and +@code{__ibm128} on PowerPC Linux systems, you must use the @option{-mfloat128}. It is expected in -future versions of GCC that @code{__float128} will be enabled +future versions of GCC that @code{_Float128} and @code{__float128} +will be enabled automatically. In addition, there are currently problems in using the complex @code{__float128} type. When these problems are fixed, you would use the following syntax to declare @code{_Complex128} to be a @@ -976,7 +990,14 @@ Not all targets support additional floating-point types. IA-64 targets. The @code{__float128} type is supported on hppa HP-UX. The @code{__float128} type is supported on PowerPC 64-bit Linux systems by default if the vector scalar instruction set (VSX) is -enabled. +enabled. The @code{_Float128} type is supported on all systems where +@code{__float128} is supported or where @code{long double} has the +IEEE binary128 format. The @code{_Float64x} type is supported on all +systems where @code{__float128} is supported. The @code{_Float32} +type is supported on all systems supporting IEEE binary32; the +@code{_Float64} and @code{Float32x} types are supported on all systems +supporting IEEE binary64. GCC does not currently support +@code{_Float16} or @code{_Float128x} on any systems. On the PowerPC, @code{__ibm128} provides access to the IBM extended double format, and it is intended to be used by the library functions diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index fa41fc04f95..d18c3b4c27b 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -1321,6 +1321,25 @@ Target supports array and structure sizes that are 32 bits or longer. @item 4byte_wchar_t Target has @code{wchar_t} that is at least 4 bytes. + +@item float@var{n} +Target has the @code{_Float@var{n}} type. + +@item float@var{n}x +Target has the @code{_Float@var{n}x} type. + +@item float@var{n}_runtime +Target has the @code{_Float@var{n}} type, including runtime support +for any options added with @code{dg-add-options}. + +@item float@var{n}x_runtime +Target has the @code{_Float@var{n}x} type, including runtime support +for any options added with @code{dg-add-options}. + +@item floatn_nx_runtime +Target has runtime support for any options added with +@code{dg-add-options} for any @code{_Float@var{n}} or +@code{_Float@var{n}x} type. @end table @subsubsection Fortran-specific attributes @@ -2135,6 +2154,12 @@ locally when using pic/PIC passes in the testsuite. @item c99_runtime Add the target-specific flags needed to access the C99 runtime. +@item float@var{n} +Add the target-specific flags needed to use the @code{_Float@var{n}} type. + +@item float@var{n}x +Add the target-specific flags needed to use the @code{_Float@var{n}x} type. + @item ieee Add the target-specific flags needed to enable full IEEE compliance mode. diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 9edb006cb06..58662606243 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -4269,6 +4269,24 @@ hook returns true for all of @code{SFmode}, @code{DFmode}, @code{XFmode} and @code{TFmode}, if such modes exist. @end deftypefn +@deftypefn {Target Hook} machine_mode TARGET_FLOATN_MODE (int @var{n}, bool @var{extended}) +Define this to return the machine mode to use for the type +@code{_Float@var{n}}, if @var{extended} is false, or the type +@code{_Float@var{n}x}, if @var{extended} is true. If such a type +is not supported, return @code{VOIDmode}. The default version of this +hook returns @code{SFmode} for @code{_Float32}, @code{DFmode} for +@code{_Float64} and @code{_Float32x} and @code{TFmode} for +@code{_Float128}, if those modes exist and satisfy the requirements for +those types and pass @code{TARGET_SCALAR_MODE_SUPPORTED_P} and +@code{TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P}; for @code{_Float64x}, it +returns the first of @code{XFmode} and @code{TFmode} that exists and +satisfies the same requirements; for other types, it returns +@code{VOIDmode}. The hook is only called for values of @var{n} and +@var{extended} that are valid according to ISO/IEC TS 18661-3:2015; that +is, @var{n} is one of 32, 64, 128, or, if @var{extended} is false, 16 or +greater than 128 and a multiple of 32. +@end deftypefn + @deftypefn {Target Hook} bool TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P (machine_mode @var{mode}) Define this to return nonzero for machine modes for which the port has small register classes. If this target hook returns nonzero for a given diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index a72c3d8ab10..da133a4b701 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -3527,6 +3527,8 @@ stack. @hook TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P +@hook TARGET_FLOATN_MODE + @hook TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P @node Scalar Return diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 23386cce487..a404c432d64 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,13 @@ +2016-08-19 Joseph Myers <joseph@codesourcery.com> + + PR c/32187 + * trans-types.h (float128_type_node): Rename to + gfc_float128_type_node. + (complex_float128_type_node): Rename to + gfc_complex_float128_type_node. + * iso-c-binding.def, trans-intrinsic.c, trans-types.c: All users + changed. + 2016-08-19 Jakub Jelinek <jakub@redhat.com> PR fortran/71014 diff --git a/gcc/fortran/iso-c-binding.def b/gcc/fortran/iso-c-binding.def index c3f87e9da83..472e7ae4faf 100644 --- a/gcc/fortran/iso-c-binding.def +++ b/gcc/fortran/iso-c-binding.def @@ -115,8 +115,8 @@ NAMED_REALCST (ISOCBINDING_DOUBLE, "c_double", \ NAMED_REALCST (ISOCBINDING_LONG_DOUBLE, "c_long_double", \ get_real_kind_from_node (long_double_type_node), GFC_STD_F2003) NAMED_REALCST (ISOCBINDING_FLOAT128, "c_float128", \ - float128_type_node == NULL_TREE \ - ? -4 : get_real_kind_from_node (float128_type_node), \ + gfc_float128_type_node == NULL_TREE \ + ? -4 : get_real_kind_from_node (gfc_float128_type_node), \ GFC_STD_GNU) NAMED_CMPXCST (ISOCBINDING_FLOAT_COMPLEX, "c_float_complex", \ get_real_kind_from_node (float_type_node), GFC_STD_F2003) @@ -125,8 +125,8 @@ NAMED_CMPXCST (ISOCBINDING_DOUBLE_COMPLEX, "c_double_complex", \ NAMED_CMPXCST (ISOCBINDING_LONG_DOUBLE_COMPLEX, "c_long_double_complex", \ get_real_kind_from_node (long_double_type_node), GFC_STD_F2003) NAMED_CMPXCST (ISOCBINDING_FLOAT128_COMPLEX, "c_float128_complex", \ - float128_type_node == NULL_TREE \ - ? -4 : get_real_kind_from_node (float128_type_node), \ + gfc_float128_type_node == NULL_TREE \ + ? -4 : get_real_kind_from_node (gfc_float128_type_node), \ GFC_STD_GNU) NAMED_LOGCST (ISOCBINDING_BOOL, "c_bool", \ diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 17dd8c266a2..81678428f18 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -149,7 +149,7 @@ builtin_decl_for_precision (enum built_in_function base_built_in, i = m->double_built_in; else if (precision == TYPE_PRECISION (long_double_type_node)) i = m->long_double_built_in; - else if (precision == TYPE_PRECISION (float128_type_node)) + else if (precision == TYPE_PRECISION (gfc_float128_type_node)) { /* Special treatment, because it is not exactly a built-in, but a library function. */ @@ -621,8 +621,8 @@ gfc_build_intrinsic_lib_fndecls (void) memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1)); - type = float128_type_node; - complex_type = complex_float128_type_node; + type = gfc_float128_type_node; + complex_type = gfc_complex_float128_type_node; /* type (*) (type) */ func_1 = build_function_type_list (type, type, NULL_TREE); /* int (*) (type) */ diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c index bde64f499c7..6a89b30e3bf 100644 --- a/gcc/fortran/trans-types.c +++ b/gcc/fortran/trans-types.c @@ -62,8 +62,8 @@ tree pfunc_type_node; tree gfc_charlen_type_node; -tree float128_type_node = NULL_TREE; -tree complex_float128_type_node = NULL_TREE; +tree gfc_float128_type_node = NULL_TREE; +tree gfc_complex_float128_type_node = NULL_TREE; bool gfc_real16_is_float128 = false; @@ -901,7 +901,7 @@ gfc_init_types (void) PUSH_TYPE (name_buf, type); if (gfc_real_kinds[index].c_float128) - float128_type_node = type; + gfc_float128_type_node = type; type = gfc_build_complex_type (type); gfc_complex_types[index] = type; @@ -910,7 +910,7 @@ gfc_init_types (void) PUSH_TYPE (name_buf, type); if (gfc_real_kinds[index].c_float128) - complex_float128_type_node = type; + gfc_complex_float128_type_node = type; } for (index = 0; gfc_character_kinds[index].kind != 0; ++index) diff --git a/gcc/fortran/trans-types.h b/gcc/fortran/trans-types.h index 95d98e9359c..c518cc18926 100644 --- a/gcc/fortran/trans-types.h +++ b/gcc/fortran/trans-types.h @@ -30,8 +30,8 @@ extern GTY(()) tree ppvoid_type_node; extern GTY(()) tree pvoid_type_node; extern GTY(()) tree prvoid_type_node; extern GTY(()) tree pchar_type_node; -extern GTY(()) tree float128_type_node; -extern GTY(()) tree complex_float128_type_node; +extern GTY(()) tree gfc_float128_type_node; +extern GTY(()) tree gfc_complex_float128_type_node; /* This is the type used to hold the lengths of character variables. It must be the same as the corresponding definition in gfortran.h. */ diff --git a/gcc/ginclude/float.h b/gcc/ginclude/float.h index 862f7cc40b4..de46a2711a9 100644 --- a/gcc/ginclude/float.h +++ b/gcc/ginclude/float.h @@ -165,7 +165,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #undef LDBL_DECIMAL_DIG #define FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__ #define DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__ -#define LDBL_DECIMAL_DIG __DECIMAL_DIG__ +#define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__ /* Whether types support subnormal numbers. */ #undef FLT_HAS_SUBNORM @@ -185,6 +185,187 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #endif /* C11 */ +#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__ +/* Constants for _FloatN and _FloatNx types from TS 18661-3. See + comments above for their semantics. */ + +#ifdef __FLT16_MANT_DIG__ +#undef FLT16_MANT_DIG +#define FLT16_MANT_DIG __FLT16_MANT_DIG__ +#undef FLT16_DIG +#define FLT16_DIG __FLT16_DIG__ +#undef FLT16_MIN_EXP +#define FLT16_MIN_EXP __FLT16_MIN_EXP__ +#undef FLT16_MIN_10_EXP +#define FLT16_MIN_10_EXP __FLT16_MIN_10_EXP__ +#undef FLT16_MAX_EXP +#define FLT16_MAX_EXP __FLT16_MAX_EXP__ +#undef FLT16_MAX_10_EXP +#define FLT16_MAX_10_EXP __FLT16_MAX_10_EXP__ +#undef FLT16_MAX +#define FLT16_MAX __FLT16_MAX__ +#undef FLT16_EPSILON +#define FLT16_EPSILON __FLT16_EPSILON__ +#undef FLT16_MIN +#define FLT16_MIN __FLT16_MIN__ +#undef FLT16_DECIMAL_DIG +#define FLT16_DECIMAL_DIG __FLT16_DECIMAL_DIG__ +#undef FLT16_TRUE_MIN +#define FLT16_TRUE_MIN __FLT16_DENORM_MIN__ +#endif /* __FLT16_MANT_DIG__. */ + +#ifdef __FLT32_MANT_DIG__ +#undef FLT32_MANT_DIG +#define FLT32_MANT_DIG __FLT32_MANT_DIG__ +#undef FLT32_DIG +#define FLT32_DIG __FLT32_DIG__ +#undef FLT32_MIN_EXP +#define FLT32_MIN_EXP __FLT32_MIN_EXP__ +#undef FLT32_MIN_10_EXP +#define FLT32_MIN_10_EXP __FLT32_MIN_10_EXP__ +#undef FLT32_MAX_EXP +#define FLT32_MAX_EXP __FLT32_MAX_EXP__ +#undef FLT32_MAX_10_EXP +#define FLT32_MAX_10_EXP __FLT32_MAX_10_EXP__ +#undef FLT32_MAX +#define FLT32_MAX __FLT32_MAX__ +#undef FLT32_EPSILON +#define FLT32_EPSILON __FLT32_EPSILON__ +#undef FLT32_MIN +#define FLT32_MIN __FLT32_MIN__ +#undef FLT32_DECIMAL_DIG +#define FLT32_DECIMAL_DIG __FLT32_DECIMAL_DIG__ +#undef FLT32_TRUE_MIN +#define FLT32_TRUE_MIN __FLT32_DENORM_MIN__ +#endif /* __FLT32_MANT_DIG__. */ + +#ifdef __FLT64_MANT_DIG__ +#undef FLT64_MANT_DIG +#define FLT64_MANT_DIG __FLT64_MANT_DIG__ +#undef FLT64_DIG +#define FLT64_DIG __FLT64_DIG__ +#undef FLT64_MIN_EXP +#define FLT64_MIN_EXP __FLT64_MIN_EXP__ +#undef FLT64_MIN_10_EXP +#define FLT64_MIN_10_EXP __FLT64_MIN_10_EXP__ +#undef FLT64_MAX_EXP +#define FLT64_MAX_EXP __FLT64_MAX_EXP__ +#undef FLT64_MAX_10_EXP +#define FLT64_MAX_10_EXP __FLT64_MAX_10_EXP__ +#undef FLT64_MAX +#define FLT64_MAX __FLT64_MAX__ +#undef FLT64_EPSILON +#define FLT64_EPSILON __FLT64_EPSILON__ +#undef FLT64_MIN +#define FLT64_MIN __FLT64_MIN__ +#undef FLT64_DECIMAL_DIG +#define FLT64_DECIMAL_DIG __FLT64_DECIMAL_DIG__ +#undef FLT64_TRUE_MIN +#define FLT64_TRUE_MIN __FLT64_DENORM_MIN__ +#endif /* __FLT64_MANT_DIG__. */ + +#ifdef __FLT128_MANT_DIG__ +#undef FLT128_MANT_DIG +#define FLT128_MANT_DIG __FLT128_MANT_DIG__ +#undef FLT128_DIG +#define FLT128_DIG __FLT128_DIG__ +#undef FLT128_MIN_EXP +#define FLT128_MIN_EXP __FLT128_MIN_EXP__ +#undef FLT128_MIN_10_EXP +#define FLT128_MIN_10_EXP __FLT128_MIN_10_EXP__ +#undef FLT128_MAX_EXP +#define FLT128_MAX_EXP __FLT128_MAX_EXP__ +#undef FLT128_MAX_10_EXP +#define FLT128_MAX_10_EXP __FLT128_MAX_10_EXP__ +#undef FLT128_MAX +#define FLT128_MAX __FLT128_MAX__ +#undef FLT128_EPSILON +#define FLT128_EPSILON __FLT128_EPSILON__ +#undef FLT128_MIN +#define FLT128_MIN __FLT128_MIN__ +#undef FLT128_DECIMAL_DIG +#define FLT128_DECIMAL_DIG __FLT128_DECIMAL_DIG__ +#undef FLT128_TRUE_MIN +#define FLT128_TRUE_MIN __FLT128_DENORM_MIN__ +#endif /* __FLT128_MANT_DIG__. */ + +#ifdef __FLT32X_MANT_DIG__ +#undef FLT32X_MANT_DIG +#define FLT32X_MANT_DIG __FLT32X_MANT_DIG__ +#undef FLT32X_DIG +#define FLT32X_DIG __FLT32X_DIG__ +#undef FLT32X_MIN_EXP +#define FLT32X_MIN_EXP __FLT32X_MIN_EXP__ +#undef FLT32X_MIN_10_EXP +#define FLT32X_MIN_10_EXP __FLT32X_MIN_10_EXP__ +#undef FLT32X_MAX_EXP +#define FLT32X_MAX_EXP __FLT32X_MAX_EXP__ +#undef FLT32X_MAX_10_EXP +#define FLT32X_MAX_10_EXP __FLT32X_MAX_10_EXP__ +#undef FLT32X_MAX +#define FLT32X_MAX __FLT32X_MAX__ +#undef FLT32X_EPSILON +#define FLT32X_EPSILON __FLT32X_EPSILON__ +#undef FLT32X_MIN +#define FLT32X_MIN __FLT32X_MIN__ +#undef FLT32X_DECIMAL_DIG +#define FLT32X_DECIMAL_DIG __FLT32X_DECIMAL_DIG__ +#undef FLT32X_TRUE_MIN +#define FLT32X_TRUE_MIN __FLT32X_DENORM_MIN__ +#endif /* __FLT32X_MANT_DIG__. */ + +#ifdef __FLT64X_MANT_DIG__ +#undef FLT64X_MANT_DIG +#define FLT64X_MANT_DIG __FLT64X_MANT_DIG__ +#undef FLT64X_DIG +#define FLT64X_DIG __FLT64X_DIG__ +#undef FLT64X_MIN_EXP +#define FLT64X_MIN_EXP __FLT64X_MIN_EXP__ +#undef FLT64X_MIN_10_EXP +#define FLT64X_MIN_10_EXP __FLT64X_MIN_10_EXP__ +#undef FLT64X_MAX_EXP +#define FLT64X_MAX_EXP __FLT64X_MAX_EXP__ +#undef FLT64X_MAX_10_EXP +#define FLT64X_MAX_10_EXP __FLT64X_MAX_10_EXP__ +#undef FLT64X_MAX +#define FLT64X_MAX __FLT64X_MAX__ +#undef FLT64X_EPSILON +#define FLT64X_EPSILON __FLT64X_EPSILON__ +#undef FLT64X_MIN +#define FLT64X_MIN __FLT64X_MIN__ +#undef FLT64X_DECIMAL_DIG +#define FLT64X_DECIMAL_DIG __FLT64X_DECIMAL_DIG__ +#undef FLT64X_TRUE_MIN +#define FLT64X_TRUE_MIN __FLT64X_DENORM_MIN__ +#endif /* __FLT64X_MANT_DIG__. */ + +#ifdef __FLT128X_MANT_DIG__ +#undef FLT128X_MANT_DIG +#define FLT128X_MANT_DIG __FLT128X_MANT_DIG__ +#undef FLT128X_DIG +#define FLT128X_DIG __FLT128X_DIG__ +#undef FLT128X_MIN_EXP +#define FLT128X_MIN_EXP __FLT128X_MIN_EXP__ +#undef FLT128X_MIN_10_EXP +#define FLT128X_MIN_10_EXP __FLT128X_MIN_10_EXP__ +#undef FLT128X_MAX_EXP +#define FLT128X_MAX_EXP __FLT128X_MAX_EXP__ +#undef FLT128X_MAX_10_EXP +#define FLT128X_MAX_10_EXP __FLT128X_MAX_10_EXP__ +#undef FLT128X_MAX +#define FLT128X_MAX __FLT128X_MAX__ +#undef FLT128X_EPSILON +#define FLT128X_EPSILON __FLT128X_EPSILON__ +#undef FLT128X_MIN +#define FLT128X_MIN __FLT128X_MIN__ +#undef FLT128X_DECIMAL_DIG +#define FLT128X_DECIMAL_DIG __FLT128X_DECIMAL_DIG__ +#undef FLT128X_TRUE_MIN +#define FLT128X_TRUE_MIN __FLT128X_DENORM_MIN__ +#endif /* __FLT128X_MANT_DIG__. */ + +#endif /* __STDC_WANT_IEC_60559_TYPES_EXT__. */ + #ifdef __STDC_WANT_DEC_FP__ /* Draft Technical Report 24732, extension for decimal floating-point arithmetic: Characteristic of decimal floating types <float.h>. */ diff --git a/gcc/real.c b/gcc/real.c index 25f0a5b1466..66e88e2ad36 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -3043,6 +3043,7 @@ const struct real_format ieee_single_format = 128, 31, 31, + 32, false, true, true, @@ -3065,6 +3066,7 @@ const struct real_format mips_single_format = 128, 31, 31, + 32, false, true, true, @@ -3087,6 +3089,7 @@ const struct real_format motorola_single_format = 128, 31, 31, + 32, false, true, true, @@ -3120,6 +3123,7 @@ const struct real_format spu_single_format = 129, 31, 31, + 0, true, false, false, @@ -3330,6 +3334,7 @@ const struct real_format ieee_double_format = 1024, 63, 63, + 64, false, true, true, @@ -3352,6 +3357,7 @@ const struct real_format mips_double_format = 1024, 63, 63, + 64, false, true, true, @@ -3374,6 +3380,7 @@ const struct real_format motorola_double_format = 1024, 63, 63, + 64, false, true, true, @@ -3719,6 +3726,7 @@ const struct real_format ieee_extended_motorola_format = 16384, 95, 95, + 0, false, true, true, @@ -3741,6 +3749,7 @@ const struct real_format ieee_extended_intel_96_format = 16384, 79, 79, + 65, false, true, true, @@ -3763,6 +3772,7 @@ const struct real_format ieee_extended_intel_128_format = 16384, 79, 79, + 65, false, true, true, @@ -3787,6 +3797,7 @@ const struct real_format ieee_extended_intel_96_round_53_format = 16384, 79, 79, + 33, false, true, true, @@ -3876,6 +3887,7 @@ const struct real_format ibm_extended_format = 1024, 127, -1, + 0, false, true, true, @@ -3898,6 +3910,7 @@ const struct real_format mips_extended_format = 1024, 127, -1, + 0, false, true, true, @@ -4162,6 +4175,7 @@ const struct real_format ieee_quad_format = 16384, 127, 127, + 128, false, true, true, @@ -4184,6 +4198,7 @@ const struct real_format mips_quad_format = 16384, 127, 127, + 128, false, true, true, @@ -4485,6 +4500,7 @@ const struct real_format vax_f_format = 127, 15, 15, + 0, false, false, false, @@ -4507,6 +4523,7 @@ const struct real_format vax_d_format = 127, 15, 15, + 0, false, false, false, @@ -4529,6 +4546,7 @@ const struct real_format vax_g_format = 1023, 15, 15, + 0, false, false, false, @@ -4606,6 +4624,7 @@ const struct real_format decimal_single_format = 97, 31, 31, + 32, false, true, true, @@ -4629,6 +4648,7 @@ const struct real_format decimal_double_format = 385, 63, 63, + 64, false, true, true, @@ -4652,6 +4672,7 @@ const struct real_format decimal_quad_format = 6145, 127, 127, + 128, false, true, true, @@ -4790,6 +4811,7 @@ const struct real_format ieee_half_format = 16, 15, 15, + 16, false, true, true, @@ -4815,6 +4837,7 @@ const struct real_format arm_half_format = 17, 15, 15, + 0, false, true, false, @@ -4861,6 +4884,7 @@ const struct real_format real_internal_format = MAX_EXP, -1, -1, + 0, false, false, true, diff --git a/gcc/real.h b/gcc/real.h index be95161cf0a..59af580e78f 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -139,6 +139,17 @@ struct real_format or -1 for a complex encoding. */ int signbit_rw; + /* If this is an IEEE interchange format, the number of bits in the + format; otherwise, if it is an IEEE extended format, one more + than the greatest number of bits in an interchange format it + extends; otherwise 0. Formats need not follow the IEEE 754-2008 + recommended practice regarding how signaling NaNs are identified, + and may vary in the choice of default NaN, but must follow other + IEEE practice regarding having NaNs, infinities and subnormal + values, and the relation of minimum and maximum exponents, and, + for interchange formats, the details of the encoding. */ + int ieee_bits; + /* Default rounding mode for operations on this format. */ bool round_towards_zero; bool has_sign_dependent_rounding; diff --git a/gcc/target.def b/gcc/target.def index 929d9ea05a8..8d506912063 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -3333,6 +3333,26 @@ hook returns true for all of @code{SFmode}, @code{DFmode}, \n\ bool, (machine_mode mode), default_libgcc_floating_mode_supported_p) +DEFHOOK +(floatn_mode, + "Define this to return the machine mode to use for the type \n\ +@code{_Float@var{n}}, if @var{extended} is false, or the type \n\ +@code{_Float@var{n}x}, if @var{extended} is true. If such a type \n\ +is not supported, return @code{VOIDmode}. The default version of this \n\ +hook returns @code{SFmode} for @code{_Float32}, @code{DFmode} for \n\ +@code{_Float64} and @code{_Float32x} and @code{TFmode} for \n\ +@code{_Float128}, if those modes exist and satisfy the requirements for \n\ +those types and pass @code{TARGET_SCALAR_MODE_SUPPORTED_P} and \n\ +@code{TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P}; for @code{_Float64x}, it \n\ +returns the first of @code{XFmode} and @code{TFmode} that exists and \n\ +satisfies the same requirements; for other types, it returns \n\ +@code{VOIDmode}. The hook is only called for values of @var{n} and \n\ +@var{extended} that are valid according to ISO/IEC TS 18661-3:2015; that \n\ +is, @var{n} is one of 32, 64, 128, or, if @var{extended} is false, 16 or \n\ +greater than 128 and a multiple of 32.", + machine_mode, (int n, bool extended), + default_floatn_mode) + /* Compute cost of moving data from a register of class FROM to one of TO, using MODE. */ DEFHOOK diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 69037c1ca0f..9d5be1706dd 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -76,6 +76,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "predict.h" #include "params.h" +#include "real.h" bool @@ -461,6 +462,92 @@ default_libgcc_floating_mode_supported_p (machine_mode mode) } } +/* Return the machine mode to use for the type _FloatN, if EXTENDED is + false, or _FloatNx, if EXTENDED is true, or VOIDmode if not + supported. */ +machine_mode +default_floatn_mode (int n, bool extended) +{ + if (extended) + { + machine_mode cand1 = VOIDmode, cand2 = VOIDmode; + switch (n) + { + case 32: +#ifdef HAVE_DFmode + cand1 = DFmode; +#endif + break; + + case 64: +#ifdef HAVE_XFmode + cand1 = XFmode; +#endif +#ifdef HAVE_TFmode + cand2 = TFmode; +#endif + break; + + case 128: + break; + + default: + /* Those are the only valid _FloatNx types. */ + gcc_unreachable (); + } + if (cand1 != VOIDmode + && REAL_MODE_FORMAT (cand1)->ieee_bits > n + && targetm.scalar_mode_supported_p (cand1) + && targetm.libgcc_floating_mode_supported_p (cand1)) + return cand1; + if (cand2 != VOIDmode + && REAL_MODE_FORMAT (cand2)->ieee_bits > n + && targetm.scalar_mode_supported_p (cand2) + && targetm.libgcc_floating_mode_supported_p (cand2)) + return cand2; + } + else + { + machine_mode cand = VOIDmode; + switch (n) + { + case 16: + /* We do not use HFmode for _Float16 by default because the + required excess precision support is not present and the + interactions with promotion of the older __fp16 need to + be worked out. */ + break; + + case 32: +#ifdef HAVE_SFmode + cand = SFmode; +#endif + break; + + case 64: +#ifdef HAVE_DFmode + cand = DFmode; +#endif + break; + + case 128: +#ifdef HAVE_TFmode + cand = TFmode; +#endif + break; + + default: + break; + } + if (cand != VOIDmode + && REAL_MODE_FORMAT (cand)->ieee_bits == n + && targetm.scalar_mode_supported_p (cand) + && targetm.libgcc_floating_mode_supported_p (cand)) + return cand; + } + return VOIDmode; +} + /* Make some target macros useable by target-independent code. */ bool targhook_words_big_endian (void) diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 2e7ca72a871..a2fa49f89b3 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -73,6 +73,7 @@ extern tree default_mangle_assembler_name (const char *); extern bool default_scalar_mode_supported_p (machine_mode); extern bool default_libgcc_floating_mode_supported_p (machine_mode); +extern machine_mode default_floatn_mode (int, bool); extern bool targhook_words_big_endian (void); extern bool targhook_float_words_big_endian (void); extern bool default_float_exceptions_rounding_supported_p (void); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fa0c6985b9e..91ea2788d4c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,77 @@ +2016-08-19 Joseph Myers <joseph@codesourcery.com> + + PR c/32187 + * lib/target-supports.exp (check_effective_target_float16) + (check_effective_target_float32, check_effective_target_float64) + (check_effective_target_float128, check_effective_target_float32x) + (check_effective_target_float64x) + (check_effective_target_float128x) + (check_effective_target_float16_runtime) + (check_effective_target_float32_runtime) + (check_effective_target_float64_runtime) + (check_effective_target_float128_runtime) + (check_effective_target_float32x_runtime) + (check_effective_target_float64x_runtime) + (check_effective_target_float128x_runtime) + (check_effective_target_floatn_nx_runtime) + (add_options_for_float16, add_options_for_float32) + (add_options_for_float64, add_options_for_float128) + (add_options_for_float32x, add_options_for_float64x) + (add_options_for_float128x): New procedures. + * gcc.dg/dfp/floatn.c, gcc.dg/float128-typeof.c, + gcc.dg/float128x-typeof.c, gcc.dg/float16-typeof.c, + gcc.dg/float32-typeof.c, gcc.dg/float32x-typeof.c, + gcc.dg/float64-typeof.c, gcc.dg/float64x-typeof.c, + gcc.dg/floatn-arithconv.c, gcc.dg/floatn-errs.c, + gcc.dg/floatn-typeof.h, gcc.dg/torture/float128-basic.c, + gcc.dg/torture/float128-complex.c, + gcc.dg/torture/float128-floath.c, gcc.dg/torture/float128-tg.c, + gcc.dg/torture/float128x-basic.c, + gcc.dg/torture/float128x-complex.c, + gcc.dg/torture/float128x-floath.c, gcc.dg/torture/float128x-tg.c, + gcc.dg/torture/float16-basic.c, gcc.dg/torture/float16-complex.c, + gcc.dg/torture/float16-floath.c, gcc.dg/torture/float16-tg.c, + gcc.dg/torture/float32-basic.c, gcc.dg/torture/float32-complex.c, + gcc.dg/torture/float32-floath.c, gcc.dg/torture/float32-tg.c, + gcc.dg/torture/float32x-basic.c, + gcc.dg/torture/float32x-complex.c, + gcc.dg/torture/float32x-floath.c, gcc.dg/torture/float32x-tg.c, + gcc.dg/torture/float64-basic.c, gcc.dg/torture/float64-complex.c, + gcc.dg/torture/float64-floath.c, gcc.dg/torture/float64-tg.c, + gcc.dg/torture/float64x-basic.c, + gcc.dg/torture/float64x-complex.c, + gcc.dg/torture/float64x-floath.c, gcc.dg/torture/float64x-tg.c, + gcc.dg/torture/floatn-basic.h, gcc.dg/torture/floatn-complex.h, + gcc.dg/torture/floatn-convert.c, gcc.dg/torture/floatn-floath.h, + gcc.dg/torture/floatn-tg.h, + gcc.dg/torture/fp-int-convert-float128-ieee-timode.c, + gcc.dg/torture/fp-int-convert-float128-ieee.c, + gcc.dg/torture/fp-int-convert-float128x-timode.c, + gcc.dg/torture/fp-int-convert-float128x.c, + gcc.dg/torture/fp-int-convert-float16-timode.c, + gcc.dg/torture/fp-int-convert-float16.c, + gcc.dg/torture/fp-int-convert-float32-timode.c, + gcc.dg/torture/fp-int-convert-float32.c, + gcc.dg/torture/fp-int-convert-float32x-timode.c, + gcc.dg/torture/fp-int-convert-float32x.c, + gcc.dg/torture/fp-int-convert-float64-timode.c, + gcc.dg/torture/fp-int-convert-float64.c, + gcc.dg/torture/fp-int-convert-float64x-timode.c, + gcc.dg/torture/fp-int-convert-float64x.c: New tests. + * gcc.dg/torture/fp-int-convert.h (TEST_I_F): Add argument for + maximum exponent of floating-point type. Use it in testing + whether 0x8...0 fits in the floating-point type. Always treat -1 + (signed 0xf...f) as fitting in the floating-point type. + (M_OK1): New macro. + * gcc.dg/torture/fp-int-convert-double.c, + gcc.dg/torture/fp-int-convert-float.c, + gcc.dg/torture/fp-int-convert-float128-timode.c, + gcc.dg/torture/fp-int-convert-float128.c, + gcc.dg/torture/fp-int-convert-float80-timode.c, + gcc.dg/torture/fp-int-convert-float80.c, + gcc.dg/torture/fp-int-convert-long-double.c, + gcc.dg/torture/fp-int-convert-timode.c: Update calls to TEST_I_F. + 2016-08-19 Jakub Jelinek <jakub@redhat.com> PR fortran/72744 diff --git a/gcc/testsuite/gcc.dg/dfp/floatn.c b/gcc/testsuite/gcc.dg/dfp/floatn.c new file mode 100644 index 00000000000..4fa7a091ab9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/dfp/floatn.c @@ -0,0 +1,20 @@ +/* Tests for _FloatN / _FloatNx types: test erroneous mixing with DFP. */ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-add-options float32 } */ +/* { dg-add-options float32x } */ +/* { dg-require-effective-target float32 } */ +/* { dg-require-effective-target float32x } */ + +_Decimal32 d32; +_Float32 f32; +_Float32x f32x; +int i; + +void +f (void) +{ + (void) (d32 + f32); /* { dg-error "mix operands" } */ + (void) (f32x * d32); /* { dg-error "mix operands" } */ + (void) (i ? d32 : f32); /* { dg-error "mix operands" } */ +} diff --git a/gcc/testsuite/gcc.dg/float128-typeof.c b/gcc/testsuite/gcc.dg/float128-typeof.c new file mode 100644 index 00000000000..b6f95b770aa --- /dev/null +++ b/gcc/testsuite/gcc.dg/float128-typeof.c @@ -0,0 +1,9 @@ +/* Test _Float128 constant types. */ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-add-options float128 } */ +/* { dg-require-effective-target float128 } */ + +#define WIDTH 128 +#define EXT 0 +#include "floatn-typeof.h" diff --git a/gcc/testsuite/gcc.dg/float128x-typeof.c b/gcc/testsuite/gcc.dg/float128x-typeof.c new file mode 100644 index 00000000000..3ab2ce2debb --- /dev/null +++ b/gcc/testsuite/gcc.dg/float128x-typeof.c @@ -0,0 +1,9 @@ +/* Test _Float128x constant types. */ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-add-options float128x } */ +/* { dg-require-effective-target float128x } */ + +#define WIDTH 128 +#define EXT 1 +#include "floatn-typeof.h" diff --git a/gcc/testsuite/gcc.dg/float16-typeof.c b/gcc/testsuite/gcc.dg/float16-typeof.c new file mode 100644 index 00000000000..a781239efa2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/float16-typeof.c @@ -0,0 +1,9 @@ +/* Test _Float16 constant types. */ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-add-options float16 } */ +/* { dg-require-effective-target float16 } */ + +#define WIDTH 16 +#define EXT 0 +#include "floatn-typeof.h" diff --git a/gcc/testsuite/gcc.dg/float32-typeof.c b/gcc/testsuite/gcc.dg/float32-typeof.c new file mode 100644 index 00000000000..4b9ccf82cc3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/float32-typeof.c @@ -0,0 +1,9 @@ +/* Test _Float32 constant types. */ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-add-options float32 } */ +/* { dg-require-effective-target float32 } */ + +#define WIDTH 32 +#define EXT 0 +#include "floatn-typeof.h" diff --git a/gcc/testsuite/gcc.dg/float32x-typeof.c b/gcc/testsuite/gcc.dg/float32x-typeof.c new file mode 100644 index 00000000000..9af60778d44 --- /dev/null +++ b/gcc/testsuite/gcc.dg/float32x-typeof.c @@ -0,0 +1,9 @@ +/* Test _Float32x constant types. */ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-add-options float32x } */ +/* { dg-require-effective-target float32x } */ + +#define WIDTH 32 +#define EXT 1 +#include "floatn-typeof.h" diff --git a/gcc/testsuite/gcc.dg/float64-typeof.c b/gcc/testsuite/gcc.dg/float64-typeof.c new file mode 100644 index 00000000000..aa7d504efda --- /dev/null +++ b/gcc/testsuite/gcc.dg/float64-typeof.c @@ -0,0 +1,9 @@ +/* Test _Float64 constant types. */ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-add-options float64 } */ +/* { dg-require-effective-target float64 } */ + +#define WIDTH 64 +#define EXT 0 +#include "floatn-typeof.h" diff --git a/gcc/testsuite/gcc.dg/float64x-typeof.c b/gcc/testsuite/gcc.dg/float64x-typeof.c new file mode 100644 index 00000000000..934d6cf5f4e --- /dev/null +++ b/gcc/testsuite/gcc.dg/float64x-typeof.c @@ -0,0 +1,9 @@ +/* Test _Float64x constant types. */ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-add-options float64x } */ +/* { dg-require-effective-target float64x } */ + +#define WIDTH 64 +#define EXT 1 +#include "floatn-typeof.h" diff --git a/gcc/testsuite/gcc.dg/floatn-arithconv.c b/gcc/testsuite/gcc.dg/floatn-arithconv.c new file mode 100644 index 00000000000..c3eb24e1fcd --- /dev/null +++ b/gcc/testsuite/gcc.dg/floatn-arithconv.c @@ -0,0 +1,50 @@ +/* Tests for _FloatN / _FloatNx types: test usual arithmetic + conversions. */ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-add-options float32 } */ +/* { dg-add-options float64 } */ +/* { dg-add-options float32x } */ +/* { dg-require-effective-target float32 } */ +/* { dg-require-effective-target float64 } */ +/* { dg-require-effective-target float32x } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> + +int i; + +#define TEST(VAR, TYPE1, TYPE2, RESTYPE) \ + do \ + { \ + typedef __typeof__ ((TYPE1) 0 + (TYPE2) 1) restype; \ + typedef __typeof__ (i ? (TYPE1) 0 : (TYPE2) 1) restype2; \ + typedef RESTYPE exptype; \ + extern restype VAR; \ + extern restype2 VAR; \ + extern exptype VAR; \ + } \ + while (0) + +void +f (void) +{ + TEST (v1, float, double, double); +#if DBL_MANT_DIG > FLT32_MANT_DIG + TEST (v2, double, _Float32, double); +#endif +#if DBL_MANT_DIG <= FLT64_MANT_DIG + TEST (v3, double, _Float64, _Float64); +#endif +#if DBL_MANT_DIG >= FLT32X_MANT_DIG + TEST (v4, double, _Float32x, double); +#endif +#if FLT_MANT_DIG <= FLT32_MANT_DIG + TEST (v5, float, _Float32, _Float32); +#endif +#if FLT32X_MANT_DIG <= FLT64_MANT_DIG + TEST (v6, _Float32x, _Float64, _Float64); +#endif + TEST (v7, _Float32, _Float64, _Float64); + TEST (v8, _Float32, _Float32x, _Float32x); +} diff --git a/gcc/testsuite/gcc.dg/floatn-errs.c b/gcc/testsuite/gcc.dg/floatn-errs.c new file mode 100644 index 00000000000..0dcc2f1bb97 --- /dev/null +++ b/gcc/testsuite/gcc.dg/floatn-errs.c @@ -0,0 +1,44 @@ +/* Tests for _FloatN / _FloatNx types: test erroneous code. */ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-add-options float32 } */ +/* { dg-add-options float64 } */ +/* { dg-add-options float32x } */ +/* { dg-require-effective-target float32 } */ +/* { dg-require-effective-target float32x } */ +/* { dg-require-effective-target float64 } */ + +/* _FloatN, _FloatNx and standard types are incompatible even if they + have the same ABI. */ + +extern float a; /* { dg-message "previous declaration" } */ +extern _Float32 a; /* { dg-error "conflicting" } */ + +extern double b; /* { dg-message "previous declaration" } */ +extern _Float32x b; /* { dg-error "conflicting" } */ + +extern _Float64 c; /* { dg-message "previous declaration" } */ +extern _Float32x c; /* { dg-error "conflicting" } */ + +/* These types are not promoted in old-style function definitions. */ + +void f (_Float32); +void +f (x) + _Float32 x; +{ +} + +void g (double); /* { dg-error "prototype declaration" } */ +void +g (x) + _Float32 x; /* { dg-error "match prototype" } */ +{ +} + +void h (_Float64); /* { dg-error "prototype declaration" } */ +void +h (x) + _Float32 x; /* { dg-error "match prototype" } */ +{ +} diff --git a/gcc/testsuite/gcc.dg/floatn-typeof.h b/gcc/testsuite/gcc.dg/floatn-typeof.h new file mode 100644 index 00000000000..4a3e5865a4b --- /dev/null +++ b/gcc/testsuite/gcc.dg/floatn-typeof.h @@ -0,0 +1,22 @@ +/* Tests for _FloatN / _FloatNx types: test types of constants. + Before including this file, define WIDTH as the value N; define EXT + to 1 for _FloatNx and 0 for _FloatN. */ + +#define CONCATX(X, Y) X ## Y +#define CONCAT(X, Y) CONCATX (X, Y) +#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z) +#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z) + +#if EXT +# define TYPE CONCAT3 (_Float, WIDTH, x) +# define CST(C) CONCAT4 (C, f, WIDTH, x) +# define CSTU(C) CONCAT4 (C, F, WIDTH, x) +#else +# define TYPE CONCAT (_Float, WIDTH) +# define CST(C) CONCAT3 (C, f, WIDTH) +# define CSTU(C) CONCAT3 (C, F, WIDTH) +#endif + +extern TYPE test_type; +extern __typeof (CST (1.0)) test_type; +extern __typeof (CSTU (1.0)) test_type; diff --git a/gcc/testsuite/gcc.dg/torture/float128-basic.c b/gcc/testsuite/gcc.dg/torture/float128-basic.c new file mode 100644 index 00000000000..b23d45bf72b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float128-basic.c @@ -0,0 +1,9 @@ +/* Test _Float128. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128 } */ +/* { dg-require-effective-target float128_runtime } */ + +#define WIDTH 128 +#define EXT 0 +#include "floatn-basic.h" diff --git a/gcc/testsuite/gcc.dg/torture/float128-complex.c b/gcc/testsuite/gcc.dg/torture/float128-complex.c new file mode 100644 index 00000000000..fe93fe69a57 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float128-complex.c @@ -0,0 +1,9 @@ +/* Test _Float128 complex arithmetic. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128 } */ +/* { dg-require-effective-target float128_runtime } */ + +#define WIDTH 128 +#define EXT 0 +#include "floatn-complex.h" diff --git a/gcc/testsuite/gcc.dg/torture/float128-floath.c b/gcc/testsuite/gcc.dg/torture/float128-floath.c new file mode 100644 index 00000000000..68147c35fb6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float128-floath.c @@ -0,0 +1,61 @@ +/* Test _Float128 <float.h> macros. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128 } */ +/* { dg-require-effective-target float128_runtime } */ + +#define WIDTH 128 +#define EXT 0 +#include "floatn-floath.h" + +#ifndef FLT128_MANT_DIG +# error "FLT128_MANT_DIG undefined" +#endif + +#ifndef FLT128_DECIMAL_DIG +# error "FLT128_DECIMAL_DIG undefined" +#endif + +#ifndef FLT128_DIG +# error "FLT128_DIG undefined" +#endif + +#ifndef FLT128_MIN_EXP +# error "FLT128_MIN_EXP undefined" +#endif + +#ifndef FLT128_MIN_10_EXP +# error "FLT128_MIN_10_EXP undefined" +#endif + +#ifndef FLT128_MAX_EXP +# error "FLT128_MAX_EXP undefined" +#endif + +#ifndef FLT128_MAX_10_EXP +# error "FLT128_MAX_10_EXP undefined" +#endif + +#ifndef FLT128_MAX +# error "FLT128_MAX undefined" +#endif + +#ifndef FLT128_EPSILON +# error "FLT128_EPSILON undefined" +#endif + +#ifndef FLT128_MIN +# error "FLT128_MIN undefined" +#endif + +#ifndef FLT128_TRUE_MIN +# error "FLT128_TRUE_MIN undefined" +#endif + +#if FLT128_DECIMAL_DIG > DECIMAL_DIG +# error "FLT128_DECIMAL_DIG > DECIMAL_DIG" +#endif + +#if FLT128_MANT_DIG != 113 || FLT128_MAX_EXP != 16384 || FLT128_MIN_EXP != -16381 +# error "_Float128 bad format" +#endif diff --git a/gcc/testsuite/gcc.dg/torture/float128-tg.c b/gcc/testsuite/gcc.dg/torture/float128-tg.c new file mode 100644 index 00000000000..c1b6398d92b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float128-tg.c @@ -0,0 +1,9 @@ +/* Test _Float128 type-generic built-in functions. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128 } */ +/* { dg-require-effective-target float128_runtime } */ + +#define WIDTH 128 +#define EXT 0 +#include "floatn-tg.h" diff --git a/gcc/testsuite/gcc.dg/torture/float128x-basic.c b/gcc/testsuite/gcc.dg/torture/float128x-basic.c new file mode 100644 index 00000000000..75c5a28bb9d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float128x-basic.c @@ -0,0 +1,9 @@ +/* Test _Float128x. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128x } */ +/* { dg-require-effective-target float128x_runtime } */ + +#define WIDTH 128 +#define EXT 1 +#include "floatn-basic.h" diff --git a/gcc/testsuite/gcc.dg/torture/float128x-complex.c b/gcc/testsuite/gcc.dg/torture/float128x-complex.c new file mode 100644 index 00000000000..185b501840c --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float128x-complex.c @@ -0,0 +1,9 @@ +/* Test _Float128x complex arithmetic. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128x } */ +/* { dg-require-effective-target float128x_runtime } */ + +#define WIDTH 128 +#define EXT 1 +#include "floatn-complex.h" diff --git a/gcc/testsuite/gcc.dg/torture/float128x-floath.c b/gcc/testsuite/gcc.dg/torture/float128x-floath.c new file mode 100644 index 00000000000..0fc3db2744f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float128x-floath.c @@ -0,0 +1,61 @@ +/* Test _Float128x <float.h> macros. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128x } */ +/* { dg-require-effective-target float128x_runtime } */ + +#define WIDTH 128 +#define EXT 1 +#include "floatn-floath.h" + +#ifndef FLT128X_MANT_DIG +# error "FLT128X_MANT_DIG undefined" +#endif + +#ifndef FLT128X_DECIMAL_DIG +# error "FLT128X_DECIMAL_DIG undefined" +#endif + +#ifndef FLT128X_DIG +# error "FLT128X_DIG undefined" +#endif + +#ifndef FLT128X_MIN_EXP +# error "FLT128X_MIN_EXP undefined" +#endif + +#ifndef FLT128X_MIN_10_EXP +# error "FLT128X_MIN_10_EXP undefined" +#endif + +#ifndef FLT128X_MAX_EXP +# error "FLT128X_MAX_EXP undefined" +#endif + +#ifndef FLT128X_MAX_10_EXP +# error "FLT128X_MAX_10_EXP undefined" +#endif + +#ifndef FLT128X_MAX +# error "FLT128X_MAX undefined" +#endif + +#ifndef FLT128X_EPSILON +# error "FLT128X_EPSILON undefined" +#endif + +#ifndef FLT128X_MIN +# error "FLT128X_MIN undefined" +#endif + +#ifndef FLT128X_TRUE_MIN +# error "FLT128X_TRUE_MIN undefined" +#endif + +#if FLT128X_DECIMAL_DIG > DECIMAL_DIG +# error "FLT128X_DECIMAL_DIG > DECIMAL_DIG" +#endif + +#if FLT128X_MANT_DIG < 128 || FLT128X_MAX_EXP < 65536 || FLT128X_MIN_EXP + FLT128X_MAX_EXP != 3 +# error "_Float128x bad format" +#endif diff --git a/gcc/testsuite/gcc.dg/torture/float128x-tg.c b/gcc/testsuite/gcc.dg/torture/float128x-tg.c new file mode 100644 index 00000000000..0dc1e0f6823 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float128x-tg.c @@ -0,0 +1,9 @@ +/* Test _Float128x type-generic built-in functions. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128x } */ +/* { dg-require-effective-target float128x_runtime } */ + +#define WIDTH 128 +#define EXT 1 +#include "floatn-tg.h" diff --git a/gcc/testsuite/gcc.dg/torture/float16-basic.c b/gcc/testsuite/gcc.dg/torture/float16-basic.c new file mode 100644 index 00000000000..e94aa203d40 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float16-basic.c @@ -0,0 +1,9 @@ +/* Test _Float16. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float16 } */ +/* { dg-require-effective-target float16_runtime } */ + +#define WIDTH 16 +#define EXT 0 +#include "floatn-basic.h" diff --git a/gcc/testsuite/gcc.dg/torture/float16-complex.c b/gcc/testsuite/gcc.dg/torture/float16-complex.c new file mode 100644 index 00000000000..463e703d6c8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float16-complex.c @@ -0,0 +1,9 @@ +/* Test _Float16 complex arithmetic. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float16 } */ +/* { dg-require-effective-target float16_runtime } */ + +#define WIDTH 16 +#define EXT 0 +#include "floatn-complex.h" diff --git a/gcc/testsuite/gcc.dg/torture/float16-floath.c b/gcc/testsuite/gcc.dg/torture/float16-floath.c new file mode 100644 index 00000000000..6857c2e9aa8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float16-floath.c @@ -0,0 +1,61 @@ +/* Test _Float16 <float.h> macros. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float16 } */ +/* { dg-require-effective-target float16_runtime } */ + +#define WIDTH 16 +#define EXT 0 +#include "floatn-floath.h" + +#ifndef FLT16_MANT_DIG +# error "FLT16_MANT_DIG undefined" +#endif + +#ifndef FLT16_DECIMAL_DIG +# error "FLT16_DECIMAL_DIG undefined" +#endif + +#ifndef FLT16_DIG +# error "FLT16_DIG undefined" +#endif + +#ifndef FLT16_MIN_EXP +# error "FLT16_MIN_EXP undefined" +#endif + +#ifndef FLT16_MIN_10_EXP +# error "FLT16_MIN_10_EXP undefined" +#endif + +#ifndef FLT16_MAX_EXP +# error "FLT16_MAX_EXP undefined" +#endif + +#ifndef FLT16_MAX_10_EXP +# error "FLT16_MAX_10_EXP undefined" +#endif + +#ifndef FLT16_MAX +# error "FLT16_MAX undefined" +#endif + +#ifndef FLT16_EPSILON +# error "FLT16_EPSILON undefined" +#endif + +#ifndef FLT16_MIN +# error "FLT16_MIN undefined" +#endif + +#ifndef FLT16_TRUE_MIN +# error "FLT16_TRUE_MIN undefined" +#endif + +#if FLT16_DECIMAL_DIG > DECIMAL_DIG +# error "FLT16_DECIMAL_DIG > DECIMAL_DIG" +#endif + +#if FLT16_MANT_DIG != 11 || FLT16_MAX_EXP != 16 || FLT16_MIN_EXP != -13 +# error "_Float16 bad format" +#endif diff --git a/gcc/testsuite/gcc.dg/torture/float16-tg.c b/gcc/testsuite/gcc.dg/torture/float16-tg.c new file mode 100644 index 00000000000..39e8285b6e8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float16-tg.c @@ -0,0 +1,9 @@ +/* Test _Float16 type-generic built-in functions. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float16 } */ +/* { dg-require-effective-target float16_runtime } */ + +#define WIDTH 16 +#define EXT 0 +#include "floatn-tg.h" diff --git a/gcc/testsuite/gcc.dg/torture/float32-basic.c b/gcc/testsuite/gcc.dg/torture/float32-basic.c new file mode 100644 index 00000000000..2d3e7a96175 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float32-basic.c @@ -0,0 +1,9 @@ +/* Test _Float32. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32 } */ +/* { dg-require-effective-target float32_runtime } */ + +#define WIDTH 32 +#define EXT 0 +#include "floatn-basic.h" diff --git a/gcc/testsuite/gcc.dg/torture/float32-complex.c b/gcc/testsuite/gcc.dg/torture/float32-complex.c new file mode 100644 index 00000000000..8717a3f4571 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float32-complex.c @@ -0,0 +1,9 @@ +/* Test _Float32 complex arithmetic. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32 } */ +/* { dg-require-effective-target float32_runtime } */ + +#define WIDTH 32 +#define EXT 0 +#include "floatn-complex.h" diff --git a/gcc/testsuite/gcc.dg/torture/float32-floath.c b/gcc/testsuite/gcc.dg/torture/float32-floath.c new file mode 100644 index 00000000000..795cb21082f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float32-floath.c @@ -0,0 +1,61 @@ +/* Test _Float32 <float.h> macros. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32 } */ +/* { dg-require-effective-target float32_runtime } */ + +#define WIDTH 32 +#define EXT 0 +#include "floatn-floath.h" + +#ifndef FLT32_MANT_DIG +# error "FLT32_MANT_DIG undefined" +#endif + +#ifndef FLT32_DECIMAL_DIG +# error "FLT32_DECIMAL_DIG undefined" +#endif + +#ifndef FLT32_DIG +# error "FLT32_DIG undefined" +#endif + +#ifndef FLT32_MIN_EXP +# error "FLT32_MIN_EXP undefined" +#endif + +#ifndef FLT32_MIN_10_EXP +# error "FLT32_MIN_10_EXP undefined" +#endif + +#ifndef FLT32_MAX_EXP +# error "FLT32_MAX_EXP undefined" +#endif + +#ifndef FLT32_MAX_10_EXP +# error "FLT32_MAX_10_EXP undefined" +#endif + +#ifndef FLT32_MAX +# error "FLT32_MAX undefined" +#endif + +#ifndef FLT32_EPSILON +# error "FLT32_EPSILON undefined" +#endif + +#ifndef FLT32_MIN +# error "FLT32_MIN undefined" +#endif + +#ifndef FLT32_TRUE_MIN +# error "FLT32_TRUE_MIN undefined" +#endif + +#if FLT32_DECIMAL_DIG > DECIMAL_DIG +# error "FLT32_DECIMAL_DIG > DECIMAL_DIG" +#endif + +#if FLT32_MANT_DIG != 24 || FLT32_MAX_EXP != 128 || FLT32_MIN_EXP != -125 +# error "_Float32 bad format" +#endif diff --git a/gcc/testsuite/gcc.dg/torture/float32-tg.c b/gcc/testsuite/gcc.dg/torture/float32-tg.c new file mode 100644 index 00000000000..da480ca87c5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float32-tg.c @@ -0,0 +1,9 @@ +/* Test _Float32 type-generic built-in functions. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32 } */ +/* { dg-require-effective-target float32_runtime } */ + +#define WIDTH 32 +#define EXT 0 +#include "floatn-tg.h" diff --git a/gcc/testsuite/gcc.dg/torture/float32x-basic.c b/gcc/testsuite/gcc.dg/torture/float32x-basic.c new file mode 100644 index 00000000000..f2abc332488 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float32x-basic.c @@ -0,0 +1,9 @@ +/* Test _Float32x. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32x } */ +/* { dg-require-effective-target float32x_runtime } */ + +#define WIDTH 32 +#define EXT 1 +#include "floatn-basic.h" diff --git a/gcc/testsuite/gcc.dg/torture/float32x-complex.c b/gcc/testsuite/gcc.dg/torture/float32x-complex.c new file mode 100644 index 00000000000..4a63a50b5c9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float32x-complex.c @@ -0,0 +1,9 @@ +/* Test _Float32x complex arithmetic. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32x } */ +/* { dg-require-effective-target float32x_runtime } */ + +#define WIDTH 32 +#define EXT 1 +#include "floatn-complex.h" diff --git a/gcc/testsuite/gcc.dg/torture/float32x-floath.c b/gcc/testsuite/gcc.dg/torture/float32x-floath.c new file mode 100644 index 00000000000..49e7ba4ed3a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float32x-floath.c @@ -0,0 +1,61 @@ +/* Test _Float32x <float.h> macros. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32x } */ +/* { dg-require-effective-target float32x_runtime } */ + +#define WIDTH 32 +#define EXT 1 +#include "floatn-floath.h" + +#ifndef FLT32X_MANT_DIG +# error "FLT32X_MANT_DIG undefined" +#endif + +#ifndef FLT32X_DECIMAL_DIG +# error "FLT32X_DECIMAL_DIG undefined" +#endif + +#ifndef FLT32X_DIG +# error "FLT32X_DIG undefined" +#endif + +#ifndef FLT32X_MIN_EXP +# error "FLT32X_MIN_EXP undefined" +#endif + +#ifndef FLT32X_MIN_10_EXP +# error "FLT32X_MIN_10_EXP undefined" +#endif + +#ifndef FLT32X_MAX_EXP +# error "FLT32X_MAX_EXP undefined" +#endif + +#ifndef FLT32X_MAX_10_EXP +# error "FLT32X_MAX_10_EXP undefined" +#endif + +#ifndef FLT32X_MAX +# error "FLT32X_MAX undefined" +#endif + +#ifndef FLT32X_EPSILON +# error "FLT32X_EPSILON undefined" +#endif + +#ifndef FLT32X_MIN +# error "FLT32X_MIN undefined" +#endif + +#ifndef FLT32X_TRUE_MIN +# error "FLT32X_TRUE_MIN undefined" +#endif + +#if FLT32X_DECIMAL_DIG > DECIMAL_DIG +# error "FLT32X_DECIMAL_DIG > DECIMAL_DIG" +#endif + +#if FLT32X_MANT_DIG < 32 || FLT32X_MAX_EXP < 1024 || FLT32X_MIN_EXP + FLT32X_MAX_EXP != 3 +# error "_Float32x bad format" +#endif diff --git a/gcc/testsuite/gcc.dg/torture/float32x-tg.c b/gcc/testsuite/gcc.dg/torture/float32x-tg.c new file mode 100644 index 00000000000..9f9a3bf8682 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float32x-tg.c @@ -0,0 +1,9 @@ +/* Test _Float32x type-generic built-in functions. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32x } */ +/* { dg-require-effective-target float32x_runtime } */ + +#define WIDTH 32 +#define EXT 1 +#include "floatn-tg.h" diff --git a/gcc/testsuite/gcc.dg/torture/float64-basic.c b/gcc/testsuite/gcc.dg/torture/float64-basic.c new file mode 100644 index 00000000000..decb05f34b2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float64-basic.c @@ -0,0 +1,9 @@ +/* Test _Float64. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64 } */ +/* { dg-require-effective-target float64_runtime } */ + +#define WIDTH 64 +#define EXT 0 +#include "floatn-basic.h" diff --git a/gcc/testsuite/gcc.dg/torture/float64-complex.c b/gcc/testsuite/gcc.dg/torture/float64-complex.c new file mode 100644 index 00000000000..6a832c2a057 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float64-complex.c @@ -0,0 +1,9 @@ +/* Test _Float64 complex arithmetic. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64 } */ +/* { dg-require-effective-target float64_runtime } */ + +#define WIDTH 64 +#define EXT 0 +#include "floatn-complex.h" diff --git a/gcc/testsuite/gcc.dg/torture/float64-floath.c b/gcc/testsuite/gcc.dg/torture/float64-floath.c new file mode 100644 index 00000000000..a03d2e7dab7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float64-floath.c @@ -0,0 +1,61 @@ +/* Test _Float64 <float.h> macros. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64 } */ +/* { dg-require-effective-target float64_runtime } */ + +#define WIDTH 64 +#define EXT 0 +#include "floatn-floath.h" + +#ifndef FLT64_MANT_DIG +# error "FLT64_MANT_DIG undefined" +#endif + +#ifndef FLT64_DECIMAL_DIG +# error "FLT64_DECIMAL_DIG undefined" +#endif + +#ifndef FLT64_DIG +# error "FLT64_DIG undefined" +#endif + +#ifndef FLT64_MIN_EXP +# error "FLT64_MIN_EXP undefined" +#endif + +#ifndef FLT64_MIN_10_EXP +# error "FLT64_MIN_10_EXP undefined" +#endif + +#ifndef FLT64_MAX_EXP +# error "FLT64_MAX_EXP undefined" +#endif + +#ifndef FLT64_MAX_10_EXP +# error "FLT64_MAX_10_EXP undefined" +#endif + +#ifndef FLT64_MAX +# error "FLT64_MAX undefined" +#endif + +#ifndef FLT64_EPSILON +# error "FLT64_EPSILON undefined" +#endif + +#ifndef FLT64_MIN +# error "FLT64_MIN undefined" +#endif + +#ifndef FLT64_TRUE_MIN +# error "FLT64_TRUE_MIN undefined" +#endif + +#if FLT64_DECIMAL_DIG > DECIMAL_DIG +# error "FLT64_DECIMAL_DIG > DECIMAL_DIG" +#endif + +#if FLT64_MANT_DIG != 53 || FLT64_MAX_EXP != 1024 || FLT64_MIN_EXP != -1021 +# error "_Float64 bad format" +#endif diff --git a/gcc/testsuite/gcc.dg/torture/float64-tg.c b/gcc/testsuite/gcc.dg/torture/float64-tg.c new file mode 100644 index 00000000000..c970d53b5ec --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float64-tg.c @@ -0,0 +1,9 @@ +/* Test _Float64 type-generic built-in functions. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64 } */ +/* { dg-require-effective-target float64_runtime } */ + +#define WIDTH 64 +#define EXT 0 +#include "floatn-tg.h" diff --git a/gcc/testsuite/gcc.dg/torture/float64x-basic.c b/gcc/testsuite/gcc.dg/torture/float64x-basic.c new file mode 100644 index 00000000000..7a140af0bd7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float64x-basic.c @@ -0,0 +1,9 @@ +/* Test _Float64x. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64x } */ +/* { dg-require-effective-target float64x_runtime } */ + +#define WIDTH 64 +#define EXT 1 +#include "floatn-basic.h" diff --git a/gcc/testsuite/gcc.dg/torture/float64x-complex.c b/gcc/testsuite/gcc.dg/torture/float64x-complex.c new file mode 100644 index 00000000000..cb573befebb --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float64x-complex.c @@ -0,0 +1,9 @@ +/* Test _Float64x complex arithmetic. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64x } */ +/* { dg-require-effective-target float64x_runtime } */ + +#define WIDTH 64 +#define EXT 1 +#include "floatn-complex.h" diff --git a/gcc/testsuite/gcc.dg/torture/float64x-floath.c b/gcc/testsuite/gcc.dg/torture/float64x-floath.c new file mode 100644 index 00000000000..11eddc7036b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float64x-floath.c @@ -0,0 +1,61 @@ +/* Test _Float64x <float.h> macros. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64x } */ +/* { dg-require-effective-target float64x_runtime } */ + +#define WIDTH 64 +#define EXT 1 +#include "floatn-floath.h" + +#ifndef FLT64X_MANT_DIG +# error "FLT64X_MANT_DIG undefined" +#endif + +#ifndef FLT64X_DECIMAL_DIG +# error "FLT64X_DECIMAL_DIG undefined" +#endif + +#ifndef FLT64X_DIG +# error "FLT64X_DIG undefined" +#endif + +#ifndef FLT64X_MIN_EXP +# error "FLT64X_MIN_EXP undefined" +#endif + +#ifndef FLT64X_MIN_10_EXP +# error "FLT64X_MIN_10_EXP undefined" +#endif + +#ifndef FLT64X_MAX_EXP +# error "FLT64X_MAX_EXP undefined" +#endif + +#ifndef FLT64X_MAX_10_EXP +# error "FLT64X_MAX_10_EXP undefined" +#endif + +#ifndef FLT64X_MAX +# error "FLT64X_MAX undefined" +#endif + +#ifndef FLT64X_EPSILON +# error "FLT64X_EPSILON undefined" +#endif + +#ifndef FLT64X_MIN +# error "FLT64X_MIN undefined" +#endif + +#ifndef FLT64X_TRUE_MIN +# error "FLT64X_TRUE_MIN undefined" +#endif + +#if FLT64X_DECIMAL_DIG > DECIMAL_DIG +# error "FLT64X_DECIMAL_DIG > DECIMAL_DIG" +#endif + +#if FLT64X_MANT_DIG < 64 || FLT64X_MAX_EXP < 16384 || FLT64X_MIN_EXP + FLT64X_MAX_EXP != 3 +# error "_Float64x bad format" +#endif diff --git a/gcc/testsuite/gcc.dg/torture/float64x-tg.c b/gcc/testsuite/gcc.dg/torture/float64x-tg.c new file mode 100644 index 00000000000..ac14675a669 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float64x-tg.c @@ -0,0 +1,9 @@ +/* Test _Float64x type-generic built-in functions. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64x } */ +/* { dg-require-effective-target float64x_runtime } */ + +#define WIDTH 64 +#define EXT 1 +#include "floatn-tg.h" diff --git a/gcc/testsuite/gcc.dg/torture/floatn-basic.h b/gcc/testsuite/gcc.dg/torture/floatn-basic.h new file mode 100644 index 00000000000..9131f46752c --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/floatn-basic.h @@ -0,0 +1,141 @@ +/* Basic tests for _FloatN / _FloatNx types: compile and execution + tests for valid code. Before including this file, define WIDTH as + the value N; define EXT to 1 for _FloatNx and 0 for _FloatN. */ + +#include <stdarg.h> + +#define CONCATX(X, Y) X ## Y +#define CONCAT(X, Y) CONCATX (X, Y) +#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z) +#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z) + +#if EXT +# define TYPE CONCAT3 (_Float, WIDTH, x) +# define CST(C) CONCAT4 (C, f, WIDTH, x) +# define CSTU(C) CONCAT4 (C, F, WIDTH, x) +#else +# define TYPE CONCAT (_Float, WIDTH) +# define CST(C) CONCAT3 (C, f, WIDTH) +# define CSTU(C) CONCAT3 (C, F, WIDTH) +#endif + +extern void exit (int); +extern void abort (void); + +volatile TYPE a = CST (1.0), b = CSTU (2.5), c = -CST (2.5); +volatile TYPE a2 = CST (1.0), z = CST (0.0), nz = -CST (0.0); + +/* These types are not subject to default argument promotions. */ + +TYPE +vafn (TYPE arg1, ...) +{ + va_list ap; + TYPE ret; + va_start (ap, arg1); + ret = arg1 + va_arg (ap, TYPE); + va_end (ap); + return ret; +} + +TYPE +krfn (arg) + TYPE arg; +{ + return arg + 1; +} + +TYPE krprofn (TYPE); +TYPE +krprofn (arg) + TYPE arg; +{ + return arg * 3; +} + +TYPE +profn (TYPE arg) +{ + return arg / 4; +} + +int +main (void) +{ + volatile TYPE r; + r = -b; + if (r != c) + abort (); + r = a + b; + if (r != CST (3.5)) + abort (); + r = a - b; + if (r != -CST (1.5)) + abort (); + r = 2 * c; + if (r != -5) + abort (); + r = b * c; + if (r != -CST (6.25)) + abort (); + r = b / (a + a); + if (r != CST (1.25)) + abort (); + r = c * 3; + if (r != -CST (7.5)) + abort (); + volatile int i = r; + if (i != -7) + abort (); + r = vafn (a, c); + if (r != -CST (1.5)) + abort (); + r = krfn (b); + if (r != CST (3.5)) + abort (); + r = krprofn (a); + if (r != CST (3.0)) + abort (); + r = profn (a); + if (r != CST (0.25)) + abort (); + if ((a < b) != 1) + abort (); + if ((b < a) != 0) + abort (); + if ((a < a2) != 0) + abort (); + if ((nz < z) != 0) + abort (); + if ((a <= b) != 1) + abort (); + if ((b <= a) != 0) + abort (); + if ((a <= a2) != 1) + abort (); + if ((nz <= z) != 1) + abort (); + if ((a > b) != 0) + abort (); + if ((b > a) != 1) + abort (); + if ((a > a2) != 0) + abort (); + if ((nz > z) != 0) + abort (); + if ((a >= b) != 0) + abort (); + if ((b >= a) != 1) + abort (); + if ((a >= a2) != 1) + abort (); + if ((nz >= z) != 1) + abort (); + i = (nz == z); + if (i != 1) + abort (); + i = (a == b); + if (i != 0) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/floatn-complex.h b/gcc/testsuite/gcc.dg/torture/floatn-complex.h new file mode 100644 index 00000000000..7e32fafdbcf --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/floatn-complex.h @@ -0,0 +1,76 @@ +/* Tests for _FloatN / _FloatNx types: compile and execution tests for + valid code with complex arithmetic. Before including this file, + define WIDTH as the value N; define EXT to 1 for _FloatNx and 0 for + _FloatN. */ + +#define CONCATX(X, Y) X ## Y +#define CONCAT(X, Y) CONCATX (X, Y) +#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z) +#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z) + +#if EXT +# define TYPE CONCAT3 (_Float, WIDTH, x) +# define CST(C) CONCAT4 (C, f, WIDTH, x) +# define CSTI(C) CONCAT4 (C, if, WIDTH, x) +# define CSTI2(C) CONCAT4 (C, F, WIDTH, xi) +#else +# define TYPE CONCAT (_Float, WIDTH) +# define CST(C) CONCAT3 (C, f, WIDTH) +# define CSTI(C) CONCAT3 (C, if, WIDTH) +# define CSTI2(C) CONCAT4 (C, F, WIDTH, i) +#endif + +extern void exit (int); +extern void abort (void); + +volatile TYPE a = CST (1.0); +volatile _Complex TYPE b = CST (2.0) + CSTI (3.0); +volatile _Complex TYPE c = CST (2.0) + CSTI2 (3.0); +volatile _Complex TYPE d = __builtin_complex (CST (2.0), CST (3.0)); + +_Complex TYPE +fn (_Complex TYPE arg) +{ + return arg / 4; +} + +int +main (void) +{ + volatile _Complex TYPE r; + if (b != c) + abort (); + if (b != d) + abort (); + r = a + b; + if (__real__ r != CST (3.0) || __imag__ r != CST (3.0)) + abort (); + r += d; + if (__real__ r != CST (5.0) || __imag__ r != CST (6.0)) + abort (); + r -= a; + if (__real__ r != CST (4.0) || __imag__ r != CST (6.0)) + abort (); + r /= (a + a); + if (__real__ r != CST (2.0) || __imag__ r != CST (3.0)) + abort (); + r *= (a + a); + if (__real__ r != CST (4.0) || __imag__ r != CST (6.0)) + abort (); + r -= b; + if (__real__ r != CST (2.0) || __imag__ r != CST (3.0)) + abort (); + r *= r; + if (__real__ r != -CST (5.0) || __imag__ r != CST (12.0)) + abort (); + /* Division may not be exact, so round result before comparing. */ + r /= b; + r += __builtin_complex (CST (100.0), CST (100.0)); + r -= __builtin_complex (CST (100.0), CST (100.0)); + if (r != b) + abort (); + r = fn (r); + if (__real__ r != CST (0.5) || __imag__ r != CST (0.75)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/floatn-convert.c b/gcc/testsuite/gcc.dg/torture/floatn-convert.c new file mode 100644 index 00000000000..741ffc8800f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/floatn-convert.c @@ -0,0 +1,104 @@ +/* Tests for _FloatN / _FloatNx types: test conversions. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float16 } */ +/* { dg-add-options float32 } */ +/* { dg-add-options float64 } */ +/* { dg-add-options float128 } */ +/* { dg-add-options float32x } */ +/* { dg-add-options float64x } */ +/* { dg-add-options float128x } */ +/* { dg-require-effective-target float32 } */ +/* { dg-require-effective-target floatn_nx_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> + +#ifndef FLT16_MAX +# define _Float16 _Float32 +# define FLT16_MAX FLT32_MAX +# define FLT16_MANT_DIG FLT32_MANT_DIG +# define FLT16_EPSILON FLT32_EPSILON +#endif + +#ifndef FLT64_MAX +# define _Float64 _Float32 +# define FLT64_MAX FLT32_MAX +# define FLT64_MANT_DIG FLT32_MANT_DIG +# define FLT64_EPSILON FLT32_EPSILON +#endif + +#ifndef FLT128_MAX +# define _Float128 _Float32 +# define FLT128_MAX FLT32_MAX +# define FLT128_MANT_DIG FLT32_MANT_DIG +# define FLT128_EPSILON FLT32_EPSILON +#endif + +#ifndef FLT32X_MAX +# define _Float32x _Float32 +# define FLT32X_MAX FLT32_MAX +# define FLT32X_MANT_DIG FLT32_MANT_DIG +# define FLT32X_EPSILON FLT32_EPSILON +#endif + +#ifndef FLT64X_MAX +# define _Float64x _Float32 +# define FLT64X_MAX FLT32_MAX +# define FLT64X_MANT_DIG FLT32_MANT_DIG +# define FLT64X_EPSILON FLT32_EPSILON +#endif + +#ifndef FLT128X_MAX +# define _Float128x _Float32 +# define FLT128X_MAX FLT32_MAX +# define FLT128X_MANT_DIG FLT32_MANT_DIG +# define FLT128X_EPSILON FLT32_EPSILON +#endif + +#define CONCATX(X, Y) X ## Y +#define CONCAT(X, Y) CONCATX (X, Y) + +extern void exit (int); +extern void abort (void); + +#define DO_TEST(TYPE1, PFX1, TYPE2, PFX2) \ + do \ + { \ + volatile TYPE1 a = (TYPE1) 1 + CONCAT (PFX1, _EPSILON); \ + volatile TYPE2 b = (TYPE2) a; \ + volatile TYPE2 expected; \ + if (CONCAT (PFX2, _MANT_DIG) < CONCAT (PFX1, _MANT_DIG)) \ + expected = (TYPE2) 1; \ + else \ + expected = (TYPE2) 1 + (TYPE2) CONCAT (PFX1, _EPSILON); \ + if (b != expected) \ + abort (); \ + } \ + while (0) + +#define DO_TEST1(TYPE1, PFX1) \ + do \ + { \ + DO_TEST (TYPE1, PFX1, _Float16, FLT16); \ + DO_TEST (TYPE1, PFX1, _Float32, FLT32); \ + DO_TEST (TYPE1, PFX1, _Float64, FLT64); \ + DO_TEST (TYPE1, PFX1, _Float128, FLT128); \ + DO_TEST (TYPE1, PFX1, _Float32x, FLT32X); \ + DO_TEST (TYPE1, PFX1, _Float64x, FLT64X); \ + DO_TEST (TYPE1, PFX1, _Float128x, FLT128X); \ + } \ + while (0) + +int +main (void) +{ + DO_TEST1 (_Float16, FLT16); + DO_TEST1 (_Float32, FLT32); + DO_TEST1 (_Float64, FLT64); + DO_TEST1 (_Float128, FLT128); + DO_TEST1 (_Float32x, FLT32X); + DO_TEST1 (_Float64x, FLT64X); + DO_TEST1 (_Float128x, FLT128X); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/floatn-floath.h b/gcc/testsuite/gcc.dg/torture/floatn-floath.h new file mode 100644 index 00000000000..a09b59e7551 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/floatn-floath.h @@ -0,0 +1,52 @@ +/* Tests for _FloatN / _FloatNx types: compile and execution tests for + <float.h>. Before including this file, define WIDTH as the value + N; define EXT to 1 for _FloatNx and 0 for _FloatN. */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> + +#define CONCATX(X, Y) X ## Y +#define CONCAT(X, Y) CONCATX (X, Y) +#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z) +#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z) + +#if EXT +# define TYPE CONCAT3 (_Float, WIDTH, x) +# define CST(C) CONCAT4 (C, f, WIDTH, x) +# define FMAC(M) CONCAT4 (FLT, WIDTH, X_, M) +#else +# define TYPE CONCAT (_Float, WIDTH) +# define CST(C) CONCAT3 (C, f, WIDTH) +# define FMAC(M) CONCAT4 (FLT, WIDTH, _, M) +#endif + +extern void exit (int); +extern void abort (void); + +int +main (void) +{ + volatile TYPE a = CST (1.0); + for (int i = 0; i >= FMAC (MIN_EXP); i--) + a *= CST (0.5); + if (a != FMAC (MIN)) + abort (); + for (int i = 0; i < FMAC (MANT_DIG) - 1; i++) + a *= CST (0.5); + if (a != FMAC (TRUE_MIN)) + abort (); + a *= CST (0.5); + if (a != CST (0.0)) + abort (); + a = FMAC (EPSILON); + for (int i = 0; i < FMAC (MANT_DIG) - 1; i++) + a *= CST (2.0); + if (a != CST (1.0)) + abort (); + a = FMAC (MAX); + for (int i = 0; i < FMAC (MAX_EXP); i++) + a *= CST (0.5); + if (a != CST (1.0) - FMAC (EPSILON) * CST (0.5)) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/floatn-tg.h b/gcc/testsuite/gcc.dg/torture/floatn-tg.h new file mode 100644 index 00000000000..822229764ae --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/floatn-tg.h @@ -0,0 +1,113 @@ +/* Tests for _FloatN / _FloatNx types: compile and execution tests for + type-generic built-in functions. Before including this file, + define WIDTH as the value N; define EXT to 1 for _FloatNx and 0 for + _FloatN. */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> + +#define CONCATX(X, Y) X ## Y +#define CONCAT(X, Y) CONCATX (X, Y) +#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z) +#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z) + +#if EXT +# define TYPE CONCAT3 (_Float, WIDTH, x) +# define CST(C) CONCAT4 (C, f, WIDTH, x) +# define TRUE_MIN CONCAT3 (FLT, WIDTH, X_TRUE_MIN) +#else +# define TYPE CONCAT (_Float, WIDTH) +# define CST(C) CONCAT3 (C, f, WIDTH) +# define TRUE_MIN CONCAT3 (FLT, WIDTH, _TRUE_MIN) +#endif + +extern void exit (int); +extern void abort (void); + +volatile TYPE inf = __builtin_inf (), nanval = __builtin_nan (""); +volatile TYPE zero = CST (0.0), negzero = -CST (0.0), one = CST (1.0); +volatile TYPE true_min = TRUE_MIN; + +int +main (void) +{ + if (__builtin_signbit (inf) != 0) + abort (); + if (__builtin_signbit (zero) != 0) + abort (); + if (__builtin_signbit (negzero) == 0) + abort (); + if (__builtin_isfinite (nanval) != 0) + abort (); + if (__builtin_isfinite (inf) != 0) + abort (); + if (__builtin_isfinite (one) == 0) + abort (); + if (__builtin_isinf (nanval) != 0) + abort (); + if (__builtin_isinf (inf) == 0) + abort (); + if (__builtin_isnan (nanval) == 0) + abort (); + if (__builtin_isnan (inf) != 0) + abort (); + if (__builtin_isnormal (inf) != 0) + abort (); + if (__builtin_isnormal (one) == 0) + abort (); + if (__builtin_isnormal (nanval) != 0) + abort (); + if (__builtin_isnormal (zero) != 0) + abort (); + if (__builtin_isnormal (true_min) != 0) + abort (); + if (__builtin_islessequal (zero, one) != 1) + abort (); + if (__builtin_islessequal (one, zero) != 0) + abort (); + if (__builtin_islessequal (zero, negzero) != 1) + abort (); + if (__builtin_islessequal (zero, nanval) != 0) + abort (); + if (__builtin_isless (zero, one) != 1) + abort (); + if (__builtin_isless (one, zero) != 0) + abort (); + if (__builtin_isless (zero, negzero) != 0) + abort (); + if (__builtin_isless (zero, nanval) != 0) + abort (); + if (__builtin_isgreaterequal (zero, one) != 0) + abort (); + if (__builtin_isgreaterequal (one, zero) != 1) + abort (); + if (__builtin_isgreaterequal (zero, negzero) != 1) + abort (); + if (__builtin_isgreaterequal (zero, nanval) != 0) + abort (); + if (__builtin_isgreater (zero, one) != 0) + abort (); + if (__builtin_isgreater (one, zero) != 1) + abort (); + if (__builtin_isgreater (zero, negzero) != 0) + abort (); + if (__builtin_isgreater (zero, nanval) != 0) + abort (); + if (__builtin_islessgreater (zero, one) != 1) + abort (); + if (__builtin_islessgreater (one, zero) != 1) + abort (); + if (__builtin_islessgreater (zero, negzero) != 0) + abort (); + if (__builtin_islessgreater (zero, nanval) != 0) + abort (); + if (__builtin_isunordered (zero, one) != 0) + abort (); + if (__builtin_isunordered (one, zero) != 0) + abort (); + if (__builtin_isunordered (zero, negzero) != 0) + abort (); + if (__builtin_isunordered (zero, nanval) != 1) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-double.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-double.c index 39ec3cde110..f2446d7fd5a 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-double.c +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-double.c @@ -9,10 +9,10 @@ int main (void) { - TEST_I_F(signed char, unsigned char, double, DBL_MANT_DIG); - TEST_I_F(signed short, unsigned short, double, DBL_MANT_DIG); - TEST_I_F(signed int, unsigned int, double, DBL_MANT_DIG); - TEST_I_F(signed long, unsigned long, double, DBL_MANT_DIG); - TEST_I_F(signed long long, unsigned long long, double, DBL_MANT_DIG); + TEST_I_F(signed char, unsigned char, double, DBL_MANT_DIG, DBL_MAX_EXP); + TEST_I_F(signed short, unsigned short, double, DBL_MANT_DIG, DBL_MAX_EXP); + TEST_I_F(signed int, unsigned int, double, DBL_MANT_DIG, DBL_MAX_EXP); + TEST_I_F(signed long, unsigned long, double, DBL_MANT_DIG, DBL_MAX_EXP); + TEST_I_F(signed long long, unsigned long long, double, DBL_MANT_DIG, DBL_MAX_EXP); exit (0); } diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float.c index 7fca1df7adf..f0f371bcbc1 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float.c +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float.c @@ -9,10 +9,10 @@ int main (void) { - TEST_I_F(signed char, unsigned char, float, FLT_MANT_DIG); - TEST_I_F(signed short, unsigned short, float, FLT_MANT_DIG); - TEST_I_F(signed int, unsigned int, float, FLT_MANT_DIG); - TEST_I_F(signed long, unsigned long, float, FLT_MANT_DIG); - TEST_I_F(signed long long, unsigned long long, float, FLT_MANT_DIG); + TEST_I_F(signed char, unsigned char, float, FLT_MANT_DIG, FLT_MAX_EXP); + TEST_I_F(signed short, unsigned short, float, FLT_MANT_DIG, FLT_MAX_EXP); + TEST_I_F(signed int, unsigned int, float, FLT_MANT_DIG, FLT_MAX_EXP); + TEST_I_F(signed long, unsigned long, float, FLT_MANT_DIG, FLT_MAX_EXP); + TEST_I_F(signed long long, unsigned long long, float, FLT_MANT_DIG, FLT_MAX_EXP); exit (0); } diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee-timode.c new file mode 100644 index 00000000000..59a7a8c07ca --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee-timode.c @@ -0,0 +1,16 @@ +/* Test floating-point conversions. _Float128 type with TImode. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128 } */ +/* { dg-require-effective-target float128_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(TItype, UTItype, _Float128, FLT128_MANT_DIG, FLT128_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee.c new file mode 100644 index 00000000000..e1aeab0581a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee.c @@ -0,0 +1,20 @@ +/* Test floating-point conversions. Standard types and _Float128. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128 } */ +/* { dg-require-effective-target float128_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(signed char, unsigned char, _Float128, FLT128_MANT_DIG, FLT128_MAX_EXP); + TEST_I_F(signed short, unsigned short, _Float128, FLT128_MANT_DIG, FLT128_MAX_EXP); + TEST_I_F(signed int, unsigned int, _Float128, FLT128_MANT_DIG, FLT128_MAX_EXP); + TEST_I_F(signed long, unsigned long, _Float128, FLT128_MANT_DIG, FLT128_MAX_EXP); + TEST_I_F(signed long long, unsigned long long, _Float128, FLT128_MANT_DIG, FLT128_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-timode.c index 493dee892b0..ddeef869581 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-timode.c +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-timode.c @@ -9,10 +9,11 @@ #include "fp-int-convert.h" #define FLOAT128_MANT_DIG 113 +#define FLOAT128_MAX_EXP 16384 int main (void) { - TEST_I_F(TItype, UTItype, __float128, FLOAT128_MANT_DIG); + TEST_I_F(TItype, UTItype, __float128, FLOAT128_MANT_DIG, FLOAT128_MAX_EXP); exit (0); } diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128.c index bc5e5adebc1..4adff79078d 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128.c +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128.c @@ -6,14 +6,15 @@ #include "fp-int-convert.h" #define FLOAT128_MANT_DIG 113 +#define FLOAT128_MAX_EXP 16384 int main (void) { - TEST_I_F(signed char, unsigned char, __float128, FLOAT128_MANT_DIG); - TEST_I_F(signed short, unsigned short, __float128, FLOAT128_MANT_DIG); - TEST_I_F(signed int, unsigned int, __float128, FLOAT128_MANT_DIG); - TEST_I_F(signed long, unsigned long, __float128, FLOAT128_MANT_DIG); - TEST_I_F(signed long long, unsigned long long, __float128, FLOAT128_MANT_DIG); + TEST_I_F(signed char, unsigned char, __float128, FLOAT128_MANT_DIG, FLOAT128_MAX_EXP); + TEST_I_F(signed short, unsigned short, __float128, FLOAT128_MANT_DIG, FLOAT128_MAX_EXP); + TEST_I_F(signed int, unsigned int, __float128, FLOAT128_MANT_DIG, FLOAT128_MAX_EXP); + TEST_I_F(signed long, unsigned long, __float128, FLOAT128_MANT_DIG, FLOAT128_MAX_EXP); + TEST_I_F(signed long long, unsigned long long, __float128, FLOAT128_MANT_DIG, FLOAT128_MAX_EXP); exit (0); } diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x-timode.c new file mode 100644 index 00000000000..682dcdc82f2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x-timode.c @@ -0,0 +1,16 @@ +/* Test floating-point conversions. _Float128x type with TImode. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128x } */ +/* { dg-require-effective-target float128x_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(TItype, UTItype, _Float128, FLT128X_MANT_DIG, FLT128X_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x.c new file mode 100644 index 00000000000..a09ed5d545e --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x.c @@ -0,0 +1,20 @@ +/* Test floating-point conversions. Standard types and _Float128x. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128x } */ +/* { dg-require-effective-target float128x_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(signed char, unsigned char, _Float128x, FLT128X_MANT_DIG, FLT128X_MAX_EXP); + TEST_I_F(signed short, unsigned short, _Float128x, FLT128X_MANT_DIG, FLT128X_MAX_EXP); + TEST_I_F(signed int, unsigned int, _Float128x, FLT128X_MANT_DIG, FLT128X_MAX_EXP); + TEST_I_F(signed long, unsigned long, _Float128x, FLT128X_MANT_DIG, FLT128X_MAX_EXP); + TEST_I_F(signed long long, unsigned long long, _Float128x, FLT128X_MANT_DIG, FLT128X_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float16-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float16-timode.c new file mode 100644 index 00000000000..f64f1d2ed6b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float16-timode.c @@ -0,0 +1,16 @@ +/* Test floating-point conversions. _Float16 type with TImode. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float16 } */ +/* { dg-require-effective-target float16_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(TItype, UTItype, _Float16, FLT16_MANT_DIG, FLT16_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float16.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float16.c new file mode 100644 index 00000000000..92e976f6ac1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float16.c @@ -0,0 +1,20 @@ +/* Test floating-point conversions. Standard types and _Float16. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float16 } */ +/* { dg-require-effective-target float16_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(signed char, unsigned char, _Float16, FLT16_MANT_DIG, FLT16_MAX_EXP); + TEST_I_F(signed short, unsigned short, _Float16, FLT16_MANT_DIG, FLT16_MAX_EXP); + TEST_I_F(signed int, unsigned int, _Float16, FLT16_MANT_DIG, FLT16_MAX_EXP); + TEST_I_F(signed long, unsigned long, _Float16, FLT16_MANT_DIG, FLT16_MAX_EXP); + TEST_I_F(signed long long, unsigned long long, _Float16, FLT16_MANT_DIG, FLT16_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32-timode.c new file mode 100644 index 00000000000..c248497d7dc --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32-timode.c @@ -0,0 +1,16 @@ +/* Test floating-point conversions. _Float32 type with TImode. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32 } */ +/* { dg-require-effective-target float32_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(TItype, UTItype, _Float32, FLT32_MANT_DIG, FLT32_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32.c new file mode 100644 index 00000000000..09847d82a3a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32.c @@ -0,0 +1,20 @@ +/* Test floating-point conversions. Standard types and _Float32. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32 } */ +/* { dg-require-effective-target float32_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(signed char, unsigned char, _Float32, FLT32_MANT_DIG, FLT32_MAX_EXP); + TEST_I_F(signed short, unsigned short, _Float32, FLT32_MANT_DIG, FLT32_MAX_EXP); + TEST_I_F(signed int, unsigned int, _Float32, FLT32_MANT_DIG, FLT32_MAX_EXP); + TEST_I_F(signed long, unsigned long, _Float32, FLT32_MANT_DIG, FLT32_MAX_EXP); + TEST_I_F(signed long long, unsigned long long, _Float32, FLT32_MANT_DIG, FLT32_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x-timode.c new file mode 100644 index 00000000000..f08bd0073b0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x-timode.c @@ -0,0 +1,16 @@ +/* Test floating-point conversions. _Float32x type with TImode. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32x } */ +/* { dg-require-effective-target float32x_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(TItype, UTItype, _Float32, FLT32X_MANT_DIG, FLT32X_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x.c new file mode 100644 index 00000000000..8ea2eafe2f3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x.c @@ -0,0 +1,20 @@ +/* Test floating-point conversions. Standard types and _Float32x. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32x } */ +/* { dg-require-effective-target float32x_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(signed char, unsigned char, _Float32x, FLT32X_MANT_DIG, FLT32X_MAX_EXP); + TEST_I_F(signed short, unsigned short, _Float32x, FLT32X_MANT_DIG, FLT32X_MAX_EXP); + TEST_I_F(signed int, unsigned int, _Float32x, FLT32X_MANT_DIG, FLT32X_MAX_EXP); + TEST_I_F(signed long, unsigned long, _Float32x, FLT32X_MANT_DIG, FLT32X_MAX_EXP); + TEST_I_F(signed long long, unsigned long long, _Float32x, FLT32X_MANT_DIG, FLT32X_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64-timode.c new file mode 100644 index 00000000000..ecefa8120b8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64-timode.c @@ -0,0 +1,16 @@ +/* Test floating-point conversions. _Float64 type with TImode. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64 } */ +/* { dg-require-effective-target float64_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(TItype, UTItype, _Float64, FLT64_MANT_DIG, FLT64_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64.c new file mode 100644 index 00000000000..196d611493f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64.c @@ -0,0 +1,20 @@ +/* Test floating-point conversions. Standard types and _Float64. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64 } */ +/* { dg-require-effective-target float64_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(signed char, unsigned char, _Float64, FLT64_MANT_DIG, FLT64_MAX_EXP); + TEST_I_F(signed short, unsigned short, _Float64, FLT64_MANT_DIG, FLT64_MAX_EXP); + TEST_I_F(signed int, unsigned int, _Float64, FLT64_MANT_DIG, FLT64_MAX_EXP); + TEST_I_F(signed long, unsigned long, _Float64, FLT64_MANT_DIG, FLT64_MAX_EXP); + TEST_I_F(signed long long, unsigned long long, _Float64, FLT64_MANT_DIG, FLT64_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x-timode.c new file mode 100644 index 00000000000..7b06a804226 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x-timode.c @@ -0,0 +1,16 @@ +/* Test floating-point conversions. _Float64x type with TImode. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64x } */ +/* { dg-require-effective-target float64x_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(TItype, UTItype, _Float64, FLT64X_MANT_DIG, FLT64X_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x.c new file mode 100644 index 00000000000..e103a5e6d0d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x.c @@ -0,0 +1,20 @@ +/* Test floating-point conversions. Standard types and _Float64x. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64x } */ +/* { dg-require-effective-target float64x_runtime } */ + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include <float.h> +#include "fp-int-convert.h" + +int +main (void) +{ + TEST_I_F(signed char, unsigned char, _Float64x, FLT64X_MANT_DIG, FLT64X_MAX_EXP); + TEST_I_F(signed short, unsigned short, _Float64x, FLT64X_MANT_DIG, FLT64X_MAX_EXP); + TEST_I_F(signed int, unsigned int, _Float64x, FLT64X_MANT_DIG, FLT64X_MAX_EXP); + TEST_I_F(signed long, unsigned long, _Float64x, FLT64X_MANT_DIG, FLT64X_MAX_EXP); + TEST_I_F(signed long long, unsigned long long, _Float64x, FLT64X_MANT_DIG, FLT64X_MAX_EXP); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80-timode.c index 7600994b4bd..9c94438b56e 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80-timode.c +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80-timode.c @@ -7,10 +7,11 @@ #include "fp-int-convert.h" #define FLOAT80_MANT_DIG 64 +#define FLOAT80_MAX_EXP 16384 int main (void) { - TEST_I_F(TItype, UTItype, __float80, FLOAT80_MANT_DIG); + TEST_I_F(TItype, UTItype, __float80, FLOAT80_MANT_DIG, FLOAT80_MAX_EXP); exit (0); } diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80.c index 3e25f904dbe..e545613beed 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80.c +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80.c @@ -6,14 +6,15 @@ #include "fp-int-convert.h" #define FLOAT80_MANT_DIG 64 +#define FLOAT80_MAX_EXP 16384 int main (void) { - TEST_I_F(signed char, unsigned char, __float80, FLOAT80_MANT_DIG); - TEST_I_F(signed short, unsigned short, __float80, FLOAT80_MANT_DIG); - TEST_I_F(signed int, unsigned int, __float80, FLOAT80_MANT_DIG); - TEST_I_F(signed long, unsigned long, __float80, FLOAT80_MANT_DIG); - TEST_I_F(signed long long, unsigned long long, __float80, FLOAT80_MANT_DIG); + TEST_I_F(signed char, unsigned char, __float80, FLOAT80_MANT_DIG, FLOAT80_MAX_EXP); + TEST_I_F(signed short, unsigned short, __float80, FLOAT80_MANT_DIG, FLOAT80_MAX_EXP); + TEST_I_F(signed int, unsigned int, __float80, FLOAT80_MANT_DIG, FLOAT80_MAX_EXP); + TEST_I_F(signed long, unsigned long, __float80, FLOAT80_MANT_DIG, FLOAT80_MAX_EXP); + TEST_I_F(signed long long, unsigned long long, __float80, FLOAT80_MANT_DIG, FLOAT80_MAX_EXP); exit (0); } diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-long-double.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-long-double.c index bb189a34c32..d8e5197f1d3 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-long-double.c +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-long-double.c @@ -9,10 +9,10 @@ int main (void) { - TEST_I_F(signed char, unsigned char, long double, LDBL_MANT_DIG); - TEST_I_F(signed short, unsigned short, long double, LDBL_MANT_DIG); - TEST_I_F(signed int, unsigned int, long double, LDBL_MANT_DIG); - TEST_I_F(signed long, unsigned long, long double, LDBL_MANT_DIG); - TEST_I_F(signed long long, unsigned long long, long double, LDBL_MANT_DIG); + TEST_I_F(signed char, unsigned char, long double, LDBL_MANT_DIG, LDBL_MAX_EXP); + TEST_I_F(signed short, unsigned short, long double, LDBL_MANT_DIG, LDBL_MAX_EXP); + TEST_I_F(signed int, unsigned int, long double, LDBL_MANT_DIG, LDBL_MAX_EXP); + TEST_I_F(signed long, unsigned long, long double, LDBL_MANT_DIG, LDBL_MAX_EXP); + TEST_I_F(signed long long, unsigned long long, long double, LDBL_MANT_DIG, LDBL_MAX_EXP); exit (0); } diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c index 3a60d01ffa5..0ef3e545465 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c @@ -9,13 +9,13 @@ int main (void) { - TEST_I_F(TItype, UTItype, float, FLT_MANT_DIG); - TEST_I_F(TItype, UTItype, double, DBL_MANT_DIG); + TEST_I_F(TItype, UTItype, float, FLT_MANT_DIG, FLT_MAX_EXP); + TEST_I_F(TItype, UTItype, double, DBL_MANT_DIG, DBL_MAX_EXP); /* Disable the long double tests when using IBM Extended Doubles. They have variable precision, but constants calculated by gcc's real.c assume fixed precision. */ #if DBL_MANT_DIG != LDBL_MANT_DIG && LDBL_MANT_DIG != 106 - TEST_I_F(TItype, UTItype, long double, LDBL_MANT_DIG); + TEST_I_F(TItype, UTItype, long double, LDBL_MANT_DIG, LDBL_MAX_EXP); #endif exit (0); } diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert.h b/gcc/testsuite/gcc.dg/torture/fp-int-convert.h index 8ac9c3de1ac..59773e34fa8 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert.h +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert.h @@ -15,20 +15,21 @@ typedef long TItype; typedef unsigned long UTItype; #endif -/* TEST_I_F(I, U, F, P) tests conversions between the pair of signed - and unsigned integer types I and U and the floating-point type F, - where P is the binary precision of the floating point type. We - test conversions of the values 0, 1, 0x7...f, 0x8...0, 0xf...f. We - also test conversions of values half way between two - representable values (rounding both ways), just above half way, and - just below half way. */ -#define TEST_I_F(I, U, F, P) \ +/* TEST_I_F(I, U, F, P, M) tests conversions between the pair of + signed and unsigned integer types I and U and the floating-point + type F, where P is the binary precision of the floating point type + and M is the MAX_EXP value for that type (so 2^M overflows, 2^(M-1) + does not). We test conversions of the values 0, 1, 0x7...f, + 0x8...0, 0xf...f. We also test conversions of values half way + between two representable values (rounding both ways), just above + half way, and just below half way. */ +#define TEST_I_F(I, U, F, P, M) \ do { \ TEST_I_F_VAL (I, F, (I)0, 1); \ TEST_I_F_VAL (I, F, (I)1, 1); \ TEST_I_F_VAL (I, F, (I)(((U)~(U)0) >> 1), P_OK1 (P, I)); \ - TEST_I_F_VAL (I, F, (I)(U)~(((U)~(U)0) >> 1), 1); \ - TEST_I_F_VAL (I, F, (I)(U)~(U)0, P_OK (P, I)); \ + TEST_I_F_VAL (I, F, (I)(U)~(((U)~(U)0) >> 1), M_OK1 (M, I)); \ + TEST_I_F_VAL (I, F, (I)(U)~(U)0, 1); \ TEST_I_F_VAL (I, F, HVAL0S (P, I), P_OK (P, I)); \ TEST_I_F_VAL (I, F, HVAL0S (P, I) + 1, P_OK (P, I)); \ TEST_I_F_VAL (I, F, HVAL0S (P, I) - 1, P_OK (P, I)); \ @@ -44,7 +45,7 @@ do { \ TEST_I_F_VAL (U, F, (U)0, 1); \ TEST_I_F_VAL (U, F, (U)1, 1); \ TEST_I_F_VAL (U, F, (U)(((U)~(U)0) >> 1), P_OK1 (P, U)); \ - TEST_I_F_VAL (U, F, (U)~(((U)~(U)0) >> 1), 1); \ + TEST_I_F_VAL (U, F, (U)~(((U)~(U)0) >> 1), M_OK1 (M, U)); \ TEST_I_F_VAL (U, F, (U)~(U)0, P_OK (P, U)); \ TEST_I_F_VAL (U, F, HVAL0U (P, U), P_OK (P, U)); \ TEST_I_F_VAL (U, F, HVAL0U (P, U) + 1, P_OK (P, U)); \ @@ -56,6 +57,7 @@ do { \ #define P_OK(P, T) ((P) >= sizeof(T) * CHAR_BIT) #define P_OK1(P, T) ((P) >= sizeof(T) * CHAR_BIT - 1) +#define M_OK1(M, T) ((M) > sizeof(T) * CHAR_BIT - 1) #define HVAL0U(P, U) (U)(P_OK (P, U) \ ? (U)1 \ : (((U)1 << (sizeof(U) * CHAR_BIT - 1)) \ diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index fc386b62f2a..b264686324a 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -2433,6 +2433,135 @@ proc check_effective_target_has_q_floating_suffix { } { } "$opts"] } +# Return 1 if the target supports the _FloatN / _FloatNx type +# indicated in the function name, 0 otherwise. + +proc check_effective_target_float16 {} { + return [check_no_compiler_messages_nocache float16 object { + _Float16 x; + }] +} + +proc check_effective_target_float32 {} { + return [check_no_compiler_messages_nocache float32 object { + _Float32 x; + }] +} + +proc check_effective_target_float64 {} { + return [check_no_compiler_messages_nocache float64 object { + _Float64 x; + }] +} + +proc check_effective_target_float128 {} { + return [check_no_compiler_messages_nocache float128 object { + _Float128 x; + }] +} + +proc check_effective_target_float32x {} { + return [check_no_compiler_messages_nocache float32x object { + _Float32x x; + }] +} + +proc check_effective_target_float64x {} { + return [check_no_compiler_messages_nocache float64x object { + _Float64x x; + }] +} + +proc check_effective_target_float128x {} { + return [check_no_compiler_messages_nocache float128x object { + _Float128x x; + }] +} + +# Likewise, but runtime support for any special options used as well +# as compile-time support is required. + +proc check_effective_target_float16_runtime {} { + return [check_effective_target_float16] +} + +proc check_effective_target_float32_runtime {} { + return [check_effective_target_float32] +} + +proc check_effective_target_float64_runtime {} { + return [check_effective_target_float64] +} + +proc check_effective_target_float128_runtime {} { + if { ![check_effective_target_float128] } { + return 0 + } + if { [istarget powerpc*-*-*] } { + return [check_effective_target_base_quadfloat_support] + } + return 1 +} + +proc check_effective_target_float32x_runtime {} { + return [check_effective_target_float32x] +} + +proc check_effective_target_float64x_runtime {} { + if { ![check_effective_target_float64x] } { + return 0 + } + if { [istarget powerpc*-*-*] } { + return [check_effective_target_base_quadfloat_support] + } + return 1 +} + +proc check_effective_target_float128x_runtime {} { + return [check_effective_target_float128x] +} + +# Return 1 if the target hardware supports any options added for +# _FloatN and _FloatNx types, 0 otherwise. + +proc check_effective_target_floatn_nx_runtime {} { + if { [istarget powerpc*-*-*] } { + return [check_effective_target_base_quadfloat_support] + } + return 1 +} + +# Add options needed to use the _FloatN / _FloatNx type indicated in +# the function name. + +proc add_options_for_float16 { flags } { + return "$flags" +} + +proc add_options_for_float32 { flags } { + return "$flags" +} + +proc add_options_for_float64 { flags } { + return "$flags" +} + +proc add_options_for_float128 { flags } { + return [add_options_for___float128 "$flags"] +} + +proc add_options_for_float32x { flags } { + return "$flags" +} + +proc add_options_for_float64x { flags } { + return [add_options_for___float128 "$flags"] +} + +proc add_options_for_float128x { flags } { + return "$flags" +} + # Return 1 if the target supports __float128, # 0 otherwise. diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 6e8595c3855..8b3e5cc75a4 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -558,10 +558,44 @@ enum tree_index { TI_COMPLEX_DOUBLE_TYPE, TI_COMPLEX_LONG_DOUBLE_TYPE, + TI_COMPLEX_FLOAT16_TYPE, + TI_COMPLEX_FLOATN_NX_TYPE_FIRST = TI_COMPLEX_FLOAT16_TYPE, + TI_COMPLEX_FLOAT32_TYPE, + TI_COMPLEX_FLOAT64_TYPE, + TI_COMPLEX_FLOAT128_TYPE, + TI_COMPLEX_FLOAT32X_TYPE, + TI_COMPLEX_FLOAT64X_TYPE, + TI_COMPLEX_FLOAT128X_TYPE, + TI_FLOAT_TYPE, TI_DOUBLE_TYPE, TI_LONG_DOUBLE_TYPE, + /* The _FloatN and _FloatNx types must be consecutive, and in the + same sequence as the corresponding complex types, which must also + be consecutive; _FloatN must come before _FloatNx; the order must + also be the same as in the floatn_nx_types array and the RID_* + values in c-common.h. This is so that iterations over these + types work as intended. */ + TI_FLOAT16_TYPE, + TI_FLOATN_TYPE_FIRST = TI_FLOAT16_TYPE, + TI_FLOATN_NX_TYPE_FIRST = TI_FLOAT16_TYPE, + TI_FLOAT32_TYPE, + TI_FLOAT64_TYPE, + TI_FLOAT128_TYPE, + TI_FLOATN_TYPE_LAST = TI_FLOAT128_TYPE, +#define NUM_FLOATN_TYPES (TI_FLOATN_TYPE_LAST - TI_FLOATN_TYPE_FIRST + 1) + TI_FLOAT32X_TYPE, + TI_FLOATNX_TYPE_FIRST = TI_FLOAT32X_TYPE, + TI_FLOAT64X_TYPE, + TI_FLOAT128X_TYPE, + TI_FLOATNX_TYPE_LAST = TI_FLOAT128X_TYPE, + TI_FLOATN_NX_TYPE_LAST = TI_FLOAT128X_TYPE, +#define NUM_FLOATNX_TYPES (TI_FLOATNX_TYPE_LAST - TI_FLOATNX_TYPE_FIRST + 1) +#define NUM_FLOATN_NX_TYPES (TI_FLOATN_NX_TYPE_LAST \ + - TI_FLOATN_NX_TYPE_FIRST \ + + 1) + TI_FLOAT_PTR_TYPE, TI_DOUBLE_PTR_TYPE, TI_LONG_DOUBLE_PTR_TYPE, @@ -1959,6 +1993,16 @@ struct GTY(()) builtin_info_type { unsigned declared_p : 1; }; +/* Information about a _FloatN or _FloatNx type that may be + supported. */ +struct floatn_type_info { + /* The number N in the type name. */ + int n; + /* Whether it is an extended type _FloatNx (true) or an interchange + type (false). */ + bool extended; +}; + /*--------------------------------------------------------------------------- Global variables @@ -2023,4 +2067,7 @@ extern GTY(()) tree current_function_decl; /* Nonzero means a FUNC_BEGIN label was emitted. */ extern GTY(()) const char * current_function_func_begin_label; +/* Information about the _FloatN and _FloatNx types. */ +extern const floatn_type_info floatn_nx_types[NUM_FLOATN_NX_TYPES]; + #endif // GCC_TREE_CORE_H diff --git a/gcc/tree.c b/gcc/tree.c index 6efc30ce5c8..33e6f979b55 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -10140,6 +10140,20 @@ build_atomic_base (tree type, unsigned int align) return t; } +/* Information about the _FloatN and _FloatNx types. This must be in + the same order as the corresponding TI_* enum values. */ +const floatn_type_info floatn_nx_types[NUM_FLOATN_NX_TYPES] = + { + { 16, false }, + { 32, false }, + { 64, false }, + { 128, false }, + { 32, true }, + { 64, true }, + { 128, true }, + }; + + /* Create nodes for all integer types (and error_mark_node) using the sizes of C datatypes. SIGNED_CHAR specifies whether char is signed. */ @@ -10312,6 +10326,29 @@ build_common_tree_nodes (bool signed_char) TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE; layout_type (long_double_type_node); + for (i = 0; i < NUM_FLOATN_NX_TYPES; i++) + { + int n = floatn_nx_types[i].n; + bool extended = floatn_nx_types[i].extended; + machine_mode mode = targetm.floatn_mode (n, extended); + if (mode == VOIDmode) + continue; + int precision = GET_MODE_PRECISION (mode); + /* Work around the rs6000 KFmode having precision 113 not + 128. */ + const struct real_format *fmt = REAL_MODE_FORMAT (mode); + gcc_assert (fmt->b == 2 && fmt->emin + fmt->emax == 3); + int min_precision = fmt->p + ceil_log2 (fmt->emax - fmt->emin); + if (!extended) + gcc_assert (min_precision == n); + if (precision < min_precision) + precision = min_precision; + FLOATN_NX_TYPE_NODE (i) = make_node (REAL_TYPE); + TYPE_PRECISION (FLOATN_NX_TYPE_NODE (i)) = precision; + layout_type (FLOATN_NX_TYPE_NODE (i)); + SET_TYPE_MODE (FLOATN_NX_TYPE_NODE (i), mode); + } + float_ptr_type_node = build_pointer_type (float_type_node); double_ptr_type_node = build_pointer_type (double_type_node); long_double_ptr_type_node = build_pointer_type (long_double_type_node); @@ -10346,6 +10383,13 @@ build_common_tree_nodes (bool signed_char) complex_double_type_node = build_complex_type (double_type_node); complex_long_double_type_node = build_complex_type (long_double_type_node); + for (i = 0; i < NUM_FLOATN_NX_TYPES; i++) + { + if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE) + COMPLEX_FLOATN_NX_TYPE_NODE (i) + = build_complex_type (FLOATN_NX_TYPE_NODE (i)); + } + /* Make fixed-point nodes based on sat/non-sat and signed/unsigned. */ #define MAKE_FIXED_TYPE_NODE(KIND,SIZE) \ sat_ ## KIND ## _type_node = \ diff --git a/gcc/tree.h b/gcc/tree.h index fff65d6c809..16d13f3266b 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3605,6 +3605,17 @@ tree_operand_check_code (const_tree __t, enum tree_code __code, int __i, #define double_type_node global_trees[TI_DOUBLE_TYPE] #define long_double_type_node global_trees[TI_LONG_DOUBLE_TYPE] +/* Nodes for particular _FloatN and _FloatNx types in sequence. */ +#define FLOATN_TYPE_NODE(IDX) global_trees[TI_FLOATN_TYPE_FIRST + (IDX)] +#define FLOATN_NX_TYPE_NODE(IDX) global_trees[TI_FLOATN_NX_TYPE_FIRST + (IDX)] +#define FLOATNX_TYPE_NODE(IDX) global_trees[TI_FLOATNX_TYPE_FIRST + (IDX)] + +/* Names for individual types, where required by back ends + (architecture-independent code should always iterate over all such + types). */ +#define float128_type_node global_trees[TI_FLOAT128_TYPE] +#define float64x_type_node global_trees[TI_FLOAT64X_TYPE] + #define float_ptr_type_node global_trees[TI_FLOAT_PTR_TYPE] #define double_ptr_type_node global_trees[TI_DOUBLE_PTR_TYPE] #define long_double_ptr_type_node global_trees[TI_LONG_DOUBLE_PTR_TYPE] @@ -3615,6 +3626,8 @@ tree_operand_check_code (const_tree __t, enum tree_code __code, int __i, #define complex_double_type_node global_trees[TI_COMPLEX_DOUBLE_TYPE] #define complex_long_double_type_node global_trees[TI_COMPLEX_LONG_DOUBLE_TYPE] +#define COMPLEX_FLOATN_NX_TYPE_NODE(IDX) global_trees[TI_COMPLEX_FLOATN_NX_TYPE_FIRST + (IDX)] + #define pointer_bounds_type_node global_trees[TI_POINTER_BOUNDS_TYPE] #define void_type_node global_trees[TI_VOID_TYPE] diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index e8e43f7285b..f680f8bc899 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,12 @@ +2016-08-19 Joseph Myers <joseph@codesourcery.com> + + PR c/32187 + * include/cpplib.h (CPP_N_FLOATN, CPP_N_FLOATNX) + (CPP_N_WIDTH_FLOATN_NX, CPP_FLOATN_SHIFT, CPP_FLOATN_MAX): New + macros. + * expr.c (interpret_float_suffix): Handle fN, fNx, FN and FNx + suffixes. + 2016-08-19 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org> * expr.c (eval_token): Append "evaluates to 0" to Wundef diagnostic. diff --git a/libcpp/expr.c b/libcpp/expr.c index d32f5a97189..61bc1b21af1 100644 --- a/libcpp/expr.c +++ b/libcpp/expr.c @@ -86,15 +86,52 @@ static cpp_num parse_has_include (cpp_reader *, enum include_type); /* Subroutine of cpp_classify_number. S points to a float suffix of length LEN, possibly zero. Returns 0 for an invalid suffix, or a - flag vector describing the suffix. */ + flag vector (of CPP_N_* bits) describing the suffix. */ static unsigned int interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len) { size_t flags; - size_t f, d, l, w, q, i; + size_t f, d, l, w, q, i, fn, fnx, fn_bits; flags = 0; - f = d = l = w = q = i = 0; + f = d = l = w = q = i = fn = fnx = fn_bits = 0; + + /* The following decimal float suffixes, from TR 24732:2009 and TS + 18661-2:2015, are supported: + + df, DF - _Decimal32. + dd, DD - _Decimal64. + dl, DL - _Decimal128. + + The dN and DN suffixes for _DecimalN, and dNx and DNx for + _DecimalNx, defined in TS 18661-3:2015, are not supported. + + Fixed-point suffixes, from TR 18037:2008, are supported. They + consist of three parts, in order: + + (i) An optional u or U, for unsigned types. + + (ii) An optional h or H, for short types, or l or L, for long + types, or ll or LL, for long long types. Use of ll or LL is a + GNU extension. + + (iii) r or R, for _Fract types, or k or K, for _Accum types. + + Otherwise the suffix is for a binary or standard floating-point + type. Such a suffix, or the absence of a suffix, may be preceded + or followed by i, I, j or J, to indicate an imaginary number with + the corresponding complex type. The following suffixes for + binary or standard floating-point types are supported: + + f, F - float (ISO C and C++). + l, L - long double (ISO C and C++). + d, D - double, even with the FLOAT_CONST_DECIMAL64 pragma in + operation (from TR 24732:2009; the pragma and the suffix + are not included in TS 18661-2:2015). + w, W - machine-specific type such as __float80 (GNU extension). + q, Q - machine-specific type such as __float128 (GNU extension). + fN, FN - _FloatN (TS 18661-3:2015). + fNx, FNx - _FloatNx (TS 18661-3:2015). */ /* Process decimal float suffixes, which are two letters starting with d or D. Order and case are significant. */ @@ -172,20 +209,64 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len) /* In any remaining valid suffix, the case and order don't matter. */ while (len--) - switch (s[len]) - { - case 'f': case 'F': f++; break; - case 'd': case 'D': d++; break; - case 'l': case 'L': l++; break; - case 'w': case 'W': w++; break; - case 'q': case 'Q': q++; break; - case 'i': case 'I': - case 'j': case 'J': i++; break; - default: - return 0; - } + { + switch (s[0]) + { + case 'f': case 'F': + f++; + if (len > 0 + && !CPP_OPTION (pfile, cplusplus) + && s[1] >= '1' + && s[1] <= '9' + && fn_bits == 0) + { + f--; + while (len > 0 + && s[1] >= '0' + && s[1] <= '9' + && fn_bits < CPP_FLOATN_MAX) + { + fn_bits = fn_bits * 10 + (s[1] - '0'); + len--; + s++; + } + if (len > 0 && s[1] == 'x') + { + fnx++; + len--; + s++; + } + else + fn++; + } + break; + case 'd': case 'D': d++; break; + case 'l': case 'L': l++; break; + case 'w': case 'W': w++; break; + case 'q': case 'Q': q++; break; + case 'i': case 'I': + case 'j': case 'J': i++; break; + default: + return 0; + } + s++; + } - if (f + d + l + w + q > 1 || i > 1) + /* Reject any case of multiple suffixes specifying types, multiple + suffixes specifying an imaginary constant, _FloatN or _FloatNx + suffixes for invalid values of N, and _FloatN suffixes for values + of N larger than can be represented in the return value. The + caller is responsible for rejecting _FloatN suffixes where + _FloatN is not supported on the chosen target. */ + if (f + d + l + w + q + fn + fnx > 1 || i > 1) + return 0; + if (fn_bits > CPP_FLOATN_MAX) + return 0; + if (fnx && fn_bits != 32 && fn_bits != 64 && fn_bits != 128) + return 0; + if (fn && fn_bits != 16 && fn_bits % 32 != 0) + return 0; + if (fn && fn_bits == 96) return 0; if (i && !CPP_OPTION (pfile, ext_numeric_literals)) @@ -199,7 +280,10 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len) d ? CPP_N_MEDIUM : l ? CPP_N_LARGE : w ? CPP_N_MD_W : - q ? CPP_N_MD_Q : CPP_N_DEFAULT)); + q ? CPP_N_MD_Q : + fn ? CPP_N_FLOATN | (fn_bits << CPP_FLOATN_SHIFT) : + fnx ? CPP_N_FLOATNX | (fn_bits << CPP_FLOATN_SHIFT) : + CPP_N_DEFAULT)); } /* Return the classification flags for a float suffix. */ diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index a497811eec0..cfc6ccd1a90 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -956,9 +956,16 @@ struct cpp_num #define CPP_N_FRACT 0x100000 /* Fract types. */ #define CPP_N_ACCUM 0x200000 /* Accum types. */ +#define CPP_N_FLOATN 0x400000 /* _FloatN types. */ +#define CPP_N_FLOATNX 0x800000 /* _FloatNx types. */ #define CPP_N_USERDEF 0x1000000 /* C++0x user-defined literal. */ +#define CPP_N_WIDTH_FLOATN_NX 0xF0000000 /* _FloatN / _FloatNx value + of N, divided by 16. */ +#define CPP_FLOATN_SHIFT 24 +#define CPP_FLOATN_MAX 0xF0 + /* Classify a CPP_NUMBER token. The return value is a combination of the flags from the above sets. */ extern unsigned cpp_classify_number (cpp_reader *, const cpp_token *, |