static void
gen_conditions_for_pow_int_base (tree base, tree expn,
vec<gimple> conds,
unsigned *nconds)
{
gimple base_def;
tree base_val0;
tree int_type;
tree temp, tempn;
tree cst0;
gimple stmt1, stmt2;
int bit_sz, max_exp;
inp_domain exp_domain;
base_def = SSA_NAME_DEF_STMT (base);
base_val0 = gimple_assign_rhs1 (base_def);
int_type = TREE_TYPE (base_val0);
bit_sz = TYPE_PRECISION (int_type);
gcc_assert (bit_sz > 0
&& bit_sz <= MAX_BASE_INT_BIT_SIZE);
/* Determine the max exp argument value according to
the size of the base integer. The max exp value
is conservatively estimated assuming IEEE754 double
precision format. */
if (bit_sz == 8)
max_exp = 128;
else if (bit_sz == 16)
max_exp = 64;
else
{
gcc_assert (bit_sz == MAX_BASE_INT_BIT_SIZE);
max_exp = 32;
}
/* For pow ((double)x, y), generate the following conditions:
cond 1:
temp1 = x;
if (temp1 <= 0)
cond 2:
temp2 = y;
if (temp2 > max_exp_real_cst) */
/* Generate condition in reverse order -- first
the condition for the exp argument. */
exp_domain = get_domain (0, false, false,
max_exp, true, true);
gen_conditions_for_domain (expn, exp_domain,
conds, nconds);
/* Now generate condition for the base argument.
Note it does not use the helper function
gen_conditions_for_domain because the base
type is integer. */
/* Push a separator. */
conds.quick_push (NULL);
temp = create_tmp_var (int_type, "DCE_COND1");
cst0 = build_int_cst (int_type, 0);
stmt1 = gimple_build_assign (temp, base_val0);
tempn = make_ssa_name (temp, stmt1);
gimple_assign_set_lhs (stmt1, tempn);
stmt2 = gimple_build_cond (LE_EXPR, tempn, cst0, NULL_TREE, NULL_TREE);
conds.quick_push (stmt1);
conds.quick_push (stmt2);
(*nconds)++;
}
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,
//.........这里部分代码省略.........
//.........这里部分代码省略.........
case OPCODE_iload_3: type = int_type_node; index = 3; goto load;
case OPCODE_lload_0: type = long_type_node; index = 0; goto load;
case OPCODE_lload_1: type = long_type_node; index = 1; goto load;
case OPCODE_lload_2: type = long_type_node; index = 2; goto load;
case OPCODE_lload_3: type = long_type_node; index = 3; goto load;
case OPCODE_fload_0: type = float_type_node; index = 0; goto load;
case OPCODE_fload_1: type = float_type_node; index = 1; goto load;
case OPCODE_fload_2: type = float_type_node; index = 2; goto load;
case OPCODE_fload_3: type = float_type_node; index = 3; goto load;
case OPCODE_dload_0: type = double_type_node; index = 0; goto load;
case OPCODE_dload_1: type = double_type_node; index = 1; goto load;
case OPCODE_dload_2: type = double_type_node; index = 2; goto load;
case OPCODE_dload_3: type = double_type_node; index = 3; goto load;
case OPCODE_aload_0: type = ptr_type_node; index = 0; goto load;
case OPCODE_aload_1: type = ptr_type_node; index = 1; goto load;
case OPCODE_aload_2: type = ptr_type_node; index = 2; goto load;
case OPCODE_aload_3: type = ptr_type_node; index = 3; goto load;
load:
if (index < 0
|| (index + TYPE_IS_WIDE (type)
>= DECL_MAX_LOCALS (current_function_decl)))
VERIFICATION_ERROR_WITH_INDEX
("invalid local variable index %d in load");
tmp = type_map[index];
if (tmp == TYPE_UNKNOWN)
VERIFICATION_ERROR_WITH_INDEX
("loading local variable %d which has unknown type");
else if (tmp == TYPE_SECOND
|| (TYPE_IS_WIDE (type)
&& type_map[index+1] != void_type_node)
|| (type == ptr_type_node
? TREE_CODE (tmp) != POINTER_TYPE
: type == int_type_node
? (! INTEGRAL_TYPE_P (tmp) || TYPE_PRECISION (tmp) > 32)
: type != tmp))
VERIFICATION_ERROR_WITH_INDEX
("loading local variable %d which has invalid type");
PUSH_TYPE (tmp);
goto note_used;
case OPCODE_istore: type = int_type_node; goto general_store;
case OPCODE_lstore: type = long_type_node; goto general_store;
case OPCODE_fstore: type = float_type_node; goto general_store;
case OPCODE_dstore: type = double_type_node; goto general_store;
case OPCODE_astore: type = object_ptr_type_node; goto general_store;
general_store:
index = wide ? IMMEDIATE_u2 : IMMEDIATE_u1;
wide = 0;
goto store;
case OPCODE_istore_0: type = int_type_node; index = 0; goto store;
case OPCODE_istore_1: type = int_type_node; index = 1; goto store;
case OPCODE_istore_2: type = int_type_node; index = 2; goto store;
case OPCODE_istore_3: type = int_type_node; index = 3; goto store;
case OPCODE_lstore_0: type = long_type_node; index=0; goto store;
case OPCODE_lstore_1: type = long_type_node; index=1; goto store;
case OPCODE_lstore_2: type = long_type_node; index=2; goto store;
case OPCODE_lstore_3: type = long_type_node; index=3; goto store;
case OPCODE_fstore_0: type=float_type_node; index=0; goto store;
case OPCODE_fstore_1: type=float_type_node; index=1; goto store;
case OPCODE_fstore_2: type=float_type_node; index=2; goto store;
case OPCODE_fstore_3: type=float_type_node; index=3; goto store;
case OPCODE_dstore_0: type=double_type_node; index=0; goto store;
case OPCODE_dstore_1: type=double_type_node; index=1; goto store;
case OPCODE_dstore_2: type=double_type_node; index=2; goto store;
case OPCODE_dstore_3: type=double_type_node; index=3; goto store;
case OPCODE_astore_0: type = ptr_type_node; index = 0; goto store;
case OPCODE_astore_1: type = ptr_type_node; index = 1; goto store;
//.........这里部分代码省略.........
TARGET_DEC_EVAL_METHOD);
builtin_define_float_constants ("FLT", "F", "%s", float_type_node);
/* Cast the double precision constants when single precision constants are
specified. The correct result is computed by the compiler when using
macros that include a cast. This has the side-effect of making the value
unusable in const expressions. */
if (flag_single_precision_constant)
builtin_define_float_constants ("DBL", "L", "((double)%s)", double_type_node);
else
builtin_define_float_constants ("DBL", "", "%s", double_type_node);
builtin_define_float_constants ("LDBL", "L", "%s", long_double_type_node);
/* For decfloat.h. */
builtin_define_decimal_float_constants ("DEC32", "DF", dfloat32_type_node);
builtin_define_decimal_float_constants ("DEC64", "DD", dfloat64_type_node);
builtin_define_decimal_float_constants ("DEC128", "DL", dfloat128_type_node);
/* For use in assembly language. */
builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0);
builtin_define_with_value ("__USER_LABEL_PREFIX__", user_label_prefix, 0);
/* Misc. */
builtin_define_with_value ("__VERSION__", version_string, 1);
/* APPLE LOCAL begin mainline */
if (flag_gnu89_inline)
cpp_define (pfile, "__GNUC_GNU_INLINE__");
else
cpp_define (pfile, "__GNUC_STDC_INLINE__");
/* APPLE LOCAL end mainline */
/* Definitions for LP64 model. */
if (TYPE_PRECISION (long_integer_type_node) == 64
&& POINTER_SIZE == 64
&& TYPE_PRECISION (integer_type_node) == 32)
{
cpp_define (pfile, "_LP64");
cpp_define (pfile, "__LP64__");
}
/* Other target-independent built-ins determined by command-line
options. */
/* APPLE LOCAL begin blocks */
/* APPLE LOCAL radar 5868913 */
if (flag_blocks)
cpp_define (pfile, "__BLOCKS__=1");
/* APPLE LOCAL end blocks */
if (optimize_size)
cpp_define (pfile, "__OPTIMIZE_SIZE__");
if (optimize)
cpp_define (pfile, "__OPTIMIZE__");
if (fast_math_flags_set_p ())
cpp_define (pfile, "__FAST_MATH__");
if (flag_really_no_inline)
cpp_define (pfile, "__NO_INLINE__");
if (flag_signaling_nans)
cpp_define (pfile, "__SUPPORT_SNAN__");
if (flag_finite_math_only)
cpp_define (pfile, "__FINITE_MATH_ONLY__=1");
else
cpp_define (pfile, "__FINITE_MATH_ONLY__=0");
if (flag_pic)
{
builtin_define_with_int_value ("__pic__", flag_pic);
/* Define NAME with value TYPE precision. */
static void
builtin_define_type_precision (const char *name, tree type)
{
builtin_define_with_int_value (name, TYPE_PRECISION (type));
}
tree
UI_To_gnu (Uint Input, tree type)
{
tree gnu_ret;
/* We might have a TYPE with biased representation and be passed an
unbiased value that doesn't fit. We always use an unbiased type able
to hold any such possible value for intermediate computations, and
then rely on a conversion back to TYPE to perform the bias adjustment
when need be. */
int biased_type_p
= (TREE_CODE (type) == INTEGER_TYPE
&& TYPE_BIASED_REPRESENTATION_P (type));
tree comp_type = biased_type_p ? get_base_type (type) : type;
if (Input <= Uint_Direct_Last)
gnu_ret = build_cst_from_int (comp_type, Input - Uint_Direct_Bias);
else
{
Int Idx = Uints_Ptr[Input].Loc;
Pos Length = Uints_Ptr[Input].Length;
Int First = Udigits_Ptr[Idx];
tree gnu_base;
gcc_assert (Length > 0);
/* The computations we perform below always require a type at least as
large as an integer not to overflow. REAL types are always fine, but
INTEGER or ENUMERAL types we are handed may be too short. We use a
base integer type node for the computations in this case and will
convert the final result back to the incoming type later on.
The base integer precision must be superior than 16. */
if (TREE_CODE (comp_type) != REAL_TYPE
&& TYPE_PRECISION (comp_type)
< TYPE_PRECISION (long_integer_type_node))
{
comp_type = long_integer_type_node;
gcc_assert (TYPE_PRECISION (comp_type) > 16);
}
gnu_base = build_cst_from_int (comp_type, Base);
gnu_ret = build_cst_from_int (comp_type, First);
if (First < 0)
for (Idx++, Length--; Length; Idx++, Length--)
gnu_ret = fold_build2 (MINUS_EXPR, comp_type,
fold_build2 (MULT_EXPR, comp_type,
gnu_ret, gnu_base),
build_cst_from_int (comp_type,
Udigits_Ptr[Idx]));
else
for (Idx++, Length--; Length; Idx++, Length--)
gnu_ret = fold_build2 (PLUS_EXPR, comp_type,
fold_build2 (MULT_EXPR, comp_type,
gnu_ret, gnu_base),
build_cst_from_int (comp_type,
Udigits_Ptr[Idx]));
}
gnu_ret = convert (type, gnu_ret);
/* We don't need any NOP_EXPR or NON_LVALUE_EXPR on GNU_RET. */
while ((TREE_CODE (gnu_ret) == NOP_EXPR
|| TREE_CODE (gnu_ret) == NON_LVALUE_EXPR)
&& TREE_TYPE (TREE_OPERAND (gnu_ret, 0)) == TREE_TYPE (gnu_ret))
gnu_ret = TREE_OPERAND (gnu_ret, 0);
return gnu_ret;
}
请发表评论