void fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig, size_t buf_size) { REAL_VALUE_TYPE real_value, base_value, fixed_value; real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), f_orig->mode); real_from_integer (&real_value, VOIDmode, f_orig->data.low, f_orig->data.high, UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode)); real_arithmetic (&fixed_value, RDIV_EXPR, &real_value, &base_value); real_to_decimal (str, &fixed_value, buf_size, 0, 1); }
void fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig, size_t buf_size) { REAL_VALUE_TYPE real_value, base_value, fixed_value; signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode) ? UNSIGNED : SIGNED; real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), VOIDmode); real_from_integer (&real_value, VOIDmode, wide_int::from (f_orig->data, GET_MODE_PRECISION (f_orig->mode), sgn), sgn); real_arithmetic (&fixed_value, RDIV_EXPR, &real_value, &base_value); real_to_decimal (str, &fixed_value, buf_size, 0, 1); }
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; }
tree ubsan_instrument_float_cast (location_t loc, tree type, tree expr) { tree expr_type = TREE_TYPE (expr); tree t, tt, fn, min, max; enum machine_mode mode = TYPE_MODE (expr_type); int prec = TYPE_PRECISION (type); bool uns_p = TYPE_UNSIGNED (type); /* Float to integer conversion first truncates toward zero, so even signed char c = 127.875f; is not problematic. Therefore, we should complain only if EXPR is unordered or smaller or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than TYPE_MAX_VALUE + 1.0. */ if (REAL_MODE_FORMAT (mode)->b == 2) { /* For maximum, TYPE_MAX_VALUE might not be representable in EXPR_TYPE, e.g. if TYPE is 64-bit long long and EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is either representable or infinity. */ REAL_VALUE_TYPE maxval = dconst1; SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p); real_convert (&maxval, mode, &maxval); max = build_real (expr_type, maxval); /* For unsigned, assume -1.0 is always representable. */ if (uns_p) min = build_minus_one_cst (expr_type); else { /* TYPE_MIN_VALUE is generally representable (or -inf), but TYPE_MIN_VALUE - 1.0 might not be. */ REAL_VALUE_TYPE minval = dconstm1, minval2; SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1); real_convert (&minval, mode, &minval); real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1); real_convert (&minval2, mode, &minval2); if (real_compare (EQ_EXPR, &minval, &minval2) && !real_isinf (&minval)) { /* If TYPE_MIN_VALUE - 1.0 is not representable and rounds to TYPE_MIN_VALUE, we need to subtract more. As REAL_MODE_FORMAT (mode)->p is the number of base digits, we want to subtract a number that will be 1 << (REAL_MODE_FORMAT (mode)->p - 1) times smaller than minval. */ minval2 = dconst1; gcc_assert (prec > REAL_MODE_FORMAT (mode)->p); SET_REAL_EXP (&minval2, REAL_EXP (&minval2) + prec - 1 - REAL_MODE_FORMAT (mode)->p + 1); real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2); real_convert (&minval2, mode, &minval2); } min = build_real (expr_type, minval2); } } else if (REAL_MODE_FORMAT (mode)->b == 10) { /* For _Decimal128 up to 34 decimal digits, - sign, dot, e, exponent. */ char buf[64]; mpfr_t m; int p = REAL_MODE_FORMAT (mode)->p; REAL_VALUE_TYPE maxval, minval; /* Use mpfr_snprintf rounding to compute the smallest representable decimal number greater or equal than 1 << (prec - !uns_p). */ mpfr_init2 (m, prec + 2); mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN); mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m); decimal_real_from_string (&maxval, buf); max = build_real (expr_type, maxval); /* For unsigned, assume -1.0 is always representable. */ if (uns_p) min = build_minus_one_cst (expr_type); else { /* Use mpfr_snprintf rounding to compute the largest representable decimal number less or equal than (-1 << (prec - 1)) - 1. */ mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN); mpfr_sub_ui (m, m, 1, GMP_RNDN); mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m); decimal_real_from_string (&minval, buf); min = build_real (expr_type, minval); } mpfr_clear (m); } else return NULL_TREE; if (flag_sanitize_undefined_trap_on_error) fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0); else { /* Create the __ubsan_handle_float_cast_overflow fn call. */ tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", NULL, NULL, ubsan_type_descriptor (expr_type), ubsan_type_descriptor (type), NULL_TREE); enum built_in_function bcode = flag_sanitize_recover ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT; fn = builtin_decl_explicit (bcode); fn = build_call_expr_loc (loc, fn, 2, build_fold_addr_expr_loc (loc, data), ubsan_encode_value (expr, false)); } t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min); tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max); return fold_build3 (COND_EXPR, void_type_node, fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt), fn, integer_zero_node); }