/* Pass an object-like macro a hexadecimal floating-point value. */ static void builtin_define_with_hex_fp_value (const char *macro, tree type ATTRIBUTE_UNUSED, int digits, const char *hex_str, const char *fp_suffix, const char *fp_cast) { REAL_VALUE_TYPE real; char dec_str[64], buf1[256], buf2[256]; /* Hex values are really cool and convenient, except that they're not supported in strict ISO C90 mode. First, the "p-" sequence is not valid as part of a preprocessor number. Second, we get a pedwarn from the preprocessor, which has no context, so we can't suppress the warning with __extension__. So instead what we do is construct the number in hex (because it's easy to get the exact correct value), parse it as a real, then print it back out as decimal. */ real_from_string (&real, hex_str); real_to_decimal (dec_str, &real, sizeof (dec_str), digits, 0); /* Assemble the macro in the following fashion macro = fp_cast [dec_str fp_suffix] */ sprintf (buf1, "%s%s", dec_str, fp_suffix); sprintf (buf2, fp_cast, buf1); sprintf (buf1, "%s=%s", macro, buf2); cpp_define (parse_in, buf1); }
tree gfc_conv_mpfr_to_tree (mpfr_t f, int kind, int is_snan) { tree type; int n; REAL_VALUE_TYPE real; n = gfc_validate_kind (BT_REAL, kind, false); gcc_assert (gfc_real_kinds[n].radix == 2); type = gfc_get_real_type (kind); if (mpfr_nan_p (f) && is_snan) real_from_string (&real, "SNaN"); else real_from_mpfr (&real, f, type, GFC_RND_MODE); return build_real (type, real); }
void real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, tree type, mp_rnd_t rndmode) { /* We use a string as an intermediate type. */ char buf[128], *rstr; mp_exp_t exp; /* Take care of Infinity and NaN. */ if (mpfr_inf_p (m)) { real_inf (r); if (mpfr_sgn (m) < 0) *r = real_value_negate (r); return; } if (mpfr_nan_p (m)) { real_nan (r, "", 1, TYPE_MODE (type)); return; } rstr = mpfr_get_str (NULL, &exp, 16, 0, m, rndmode); /* The additional 12 chars add space for the sprintf below. This leaves 6 digits for the exponent which is supposedly enough. */ gcc_assert (rstr != NULL && strlen (rstr) < sizeof (buf) - 12); /* REAL_VALUE_ATOF expects the exponent for mantissa * 2**exp, mpfr_get_str returns the exponent for mantissa * 16**exp, adjust for that. */ exp *= 4; if (rstr[0] == '-') sprintf (buf, "-0x.%sp%d", &rstr[1], (int) exp); else sprintf (buf, "0x.%sp%d", rstr, (int) exp); mpfr_free_str (rstr); real_from_string (r, buf); }
void fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, machine_mode mode) { REAL_VALUE_TYPE real_value, fixed_value, base_value; unsigned int fbit; enum fixed_value_range_code temp; bool fail; f->mode = mode; fbit = GET_MODE_FBIT (mode); real_from_string (&real_value, str); temp = check_real_for_fixed_mode (&real_value, f->mode); /* We don't want to warn the case when the _Fract value is 1.0. */ if (temp == FIXED_UNDERFLOW || temp == FIXED_GT_MAX_EPS || (temp == FIXED_MAX_EPS && ALL_ACCUM_MODE_P (f->mode))) warning (OPT_Woverflow, "large fixed-point constant implicitly truncated to fixed-point type"); real_2expN (&base_value, fbit, VOIDmode); real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value); wide_int w = real_to_integer (&fixed_value, &fail, GET_MODE_PRECISION (mode)); f->data.low = w.ulow (); f->data.high = w.elt (1); if (temp == FIXED_MAX_EPS && ALL_FRACT_MODE_P (f->mode)) { /* From the spec, we need to evaluate 1 to the maximal value. */ f->data.low = -1; f->data.high = -1; f->data = f->data.zext (GET_MODE_FBIT (f->mode) + GET_MODE_IBIT (f->mode)); } else f->data = f->data.ext (SIGNED_FIXED_POINT_MODE_P (f->mode) + GET_MODE_FBIT (f->mode) + GET_MODE_IBIT (f->mode), UNSIGNED_FIXED_POINT_MODE_P (f->mode)); }
static enum fixed_value_range_code check_real_for_fixed_mode (REAL_VALUE_TYPE *real_value, machine_mode mode) { REAL_VALUE_TYPE max_value, min_value, epsilon_value; real_2expN (&max_value, GET_MODE_IBIT (mode), VOIDmode); real_2expN (&epsilon_value, -GET_MODE_FBIT (mode), VOIDmode); if (SIGNED_FIXED_POINT_MODE_P (mode)) min_value = real_value_negate (&max_value); else real_from_string (&min_value, "0.0"); if (real_compare (LT_EXPR, real_value, &min_value)) return FIXED_UNDERFLOW; if (real_compare (EQ_EXPR, real_value, &max_value)) return FIXED_MAX_EPS; real_arithmetic (&max_value, MINUS_EXPR, &max_value, &epsilon_value); if (real_compare (GT_EXPR, real_value, &max_value)) return FIXED_GT_MAX_EPS; return FIXED_OK; }
/* Interpret TOKEN, a floating point number with FLAGS as classified by cpplib. */ static tree interpret_float (const cpp_token *token, unsigned int flags) { tree type; tree value; REAL_VALUE_TYPE real; char *copy; size_t copylen; const char *type_name; /* FIXME: make %T work in error/warning, then we don't need type_name. */ if ((flags & CPP_N_WIDTH) == CPP_N_LARGE) { type = long_double_type_node; type_name = "long double"; } else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL || flag_single_precision_constant) { type = float_type_node; type_name = "float"; } else { type = double_type_node; type_name = "double"; } /* Copy the constant to a nul-terminated buffer. If the constant has any suffixes, cut them off; REAL_VALUE_ATOF/ REAL_VALUE_HTOF can't handle them. */ copylen = token->val.str.len; if ((flags & CPP_N_WIDTH) != CPP_N_MEDIUM) /* Must be an F or L suffix. */ copylen--; if (flags & CPP_N_IMAGINARY) /* I or J suffix. */ copylen--; copy = (char *) alloca (copylen + 1); memcpy (copy, token->val.str.text, copylen); copy[copylen] = '\0'; real_from_string (&real, copy); real_convert (&real, TYPE_MODE (type), &real); /* Both C and C++ require a diagnostic for a floating constant outside the range of representable values of its type. Since we have __builtin_inf* to produce an infinity, it might now be appropriate for this to be a mandatory pedwarn rather than conditioned on -pedantic. */ if (REAL_VALUE_ISINF (real) && pedantic) pedwarn ("floating constant exceeds range of %<%s%>", type_name); /* Create a node with determined type and value. */ value = build_real (type, real); if (flags & CPP_N_IMAGINARY) value = build_complex (NULL_TREE, convert (type, integer_zero_node), value); return value; }