diff options
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 29 |
1 files changed, 29 insertions, 0 deletions
@@ -8489,6 +8489,35 @@ int_cst_value (const_tree x) return val; } +/* Return value of a constant X and sign-extend it. */ + +HOST_WIDEST_INT +widest_int_cst_value (const_tree x) +{ + unsigned bits = TYPE_PRECISION (TREE_TYPE (x)); + unsigned HOST_WIDEST_INT val = TREE_INT_CST_LOW (x); + +#if HOST_BITS_PER_WIDEST_INT > HOST_BITS_PER_WIDE_INT + gcc_assert (HOST_BITS_PER_WIDEST_INT >= 2 * HOST_BITS_PER_WIDE_INT); + val |= TREE_INT_CST_HIGH (x) << HOST_BITS_PER_WIDE_INT; +#else + /* Make sure the sign-extended value will fit in a HOST_WIDE_INT. */ + gcc_assert (TREE_INT_CST_HIGH (x) == 0 + || TREE_INT_CST_HIGH (x) == -1); +#endif + + if (bits < HOST_BITS_PER_WIDEST_INT) + { + bool negative = ((val >> (bits - 1)) & 1) != 0; + if (negative) + val |= (~(unsigned HOST_WIDEST_INT) 0) << (bits - 1) << 1; + else + val &= ~((~(unsigned HOST_WIDEST_INT) 0) << (bits - 1) << 1); + } + + return val; +} + /* If TYPE is an integral type, return an equivalent type which is unsigned iff UNSIGNEDP is true. If TYPE is not an integral type, return TYPE itself. */ |