diff options
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 46 |
1 files changed, 46 insertions, 0 deletions
@@ -1092,6 +1092,52 @@ double_int_fits_to_tree_p (const_tree type, double_int cst) return double_int_equal_p (cst, ext); } +/* We force the double_int CST to the range of the type TYPE by sign or + zero extending it. OVERFLOWABLE indicates if we are interested in + overflow of the value, when >0 we are only interested in signed + overflow, for <0 we are interested in any overflow. OVERFLOWED + indicates whether overflow has already occurred. CONST_OVERFLOWED + indicates whether constant overflow has already occurred. We force + T's value to be within range of T's type (by setting to 0 or 1 all + the bits outside the type's range). We set TREE_OVERFLOWED if, + OVERFLOWED is nonzero, + or OVERFLOWABLE is >0 and signed overflow occurs + or OVERFLOWABLE is <0 and any overflow occurs + We return a new tree node for the extended double_int. The node + is shared if no overflow flags are set. */ + + +tree +force_fit_type_double (tree type, double_int cst, int overflowable, + bool overflowed) +{ + bool sign_extended_type; + + /* Size types *are* sign extended. */ + sign_extended_type = (!TYPE_UNSIGNED (type) + || (TREE_CODE (type) == INTEGER_TYPE + && TYPE_IS_SIZETYPE (type))); + + /* If we need to set overflow flags, return a new unshared node. */ + if (overflowed || !double_int_fits_to_tree_p(type, cst)) + { + if (overflowed + || overflowable < 0 + || (overflowable > 0 && sign_extended_type)) + { + tree t = make_node (INTEGER_CST); + TREE_INT_CST (t) = double_int_ext (cst, TYPE_PRECISION (type), + !sign_extended_type); + TREE_TYPE (t) = type; + TREE_OVERFLOW (t) = 1; + return t; + } + } + + /* Else build a shared node. */ + return double_int_to_tree (type, cst); +} + /* These are the hash table functions for the hash table of INTEGER_CST nodes of a sizetype. */ |