undefined, so it doesn't matter what we return, and some callers
expect to be able to use this routine for both signed and
unsigned conversions. */
- if (exp > HOST_BITS_PER_DOUBLE_INT)
+ if (exp > precision)
goto overflow;
- rshift_significand (&t, r, HOST_BITS_PER_DOUBLE_INT - exp);
- if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
+ words = (precision + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT;
+
+ for (unsigned int i = 0; i < ARRAY_SIZE (val); i++)
+ val[i] = 0;
+
+#if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
+ for (int i = 0; i < words; i++)
{
- high = t.sig[SIGSZ-1];
- low = t.sig[SIGSZ-2];
+ int j = SIGSZ - words + i;
+ val[i] = (j < 0) ? 0 : r->sig[j];
}
- else
+#else
+ gcc_assert (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG);
+ for (int i = 0; i < words; i++)
{
- gcc_assert (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG);
- high = t.sig[SIGSZ-1];
- high = high << (HOST_BITS_PER_LONG - 1) << 1;
- high |= t.sig[SIGSZ-2];
-
- low = t.sig[SIGSZ-3];
- low = low << (HOST_BITS_PER_LONG - 1) << 1;
- low |= t.sig[SIGSZ-4];
+ int j = SIGSZ - (words * 2) + (i + 2) + 1;
+ if (j < 0)
+ val[i] = 0;
+ else
+ {
+ val[i] = r->sig[j];
- val[i] <<= HOST_BITS_PER_LONG;
++ unsigned HOST_WIDE_INT v = val[i];
++ v <<= HOST_BITS_PER_LONG;
++ val[i] = v;
+ val[i] |= r->sig[j - 1];
+ }
}
+#endif
+ w = SIGSZ * HOST_BITS_PER_LONG + words * HOST_BITS_PER_WIDE_INT;
+ tmp = real_int::from_array
+ (val, (w + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT, w);
+ tmp = wi::lrshift (tmp, (words * HOST_BITS_PER_WIDE_INT) - exp);
+ result = wide_int::from (tmp, precision, UNSIGNED);
if (r->sign)
- {
- if (low == 0)
- high = -high;
- else
- low = -low, high = ~high;
- }
- break;
+ return -result;
+ else
+ return result;
default:
gcc_unreachable ();
HOST_WIDE_INT *psize,
HOST_WIDE_INT *pmax_size)
{
- HOST_WIDE_INT bitsize = -1;
- HOST_WIDE_INT maxsize = -1;
- double_int bitsize = double_int_minus_one;
- double_int maxsize;
++ offset_int bitsize = -1;
++ offset_int maxsize;
tree size_tree = NULL_TREE;
- double_int bit_offset = double_int_zero;
+ offset_int bit_offset = 0;
- HOST_WIDE_INT hbit_offset;
bool seen_variable_array_ref = false;
/* First get the final access size from just the outermost expression. */
if (mode == BLKmode)
size_tree = TYPE_SIZE (TREE_TYPE (exp));
else
- bitsize = GET_MODE_BITSIZE (mode);
- }
- if (size_tree != NULL_TREE)
- {
- if (! tree_fits_uhwi_p (size_tree))
- bitsize = -1;
- else
- bitsize = tree_to_uhwi (size_tree);
- bitsize = double_int::from_uhwi (GET_MODE_BITSIZE (mode));
++ bitsize = wi::to_offset (GET_MODE_BITSIZE (mode));
}
- bitsize = tree_to_double_int (size_tree);
+ if (size_tree != NULL_TREE
+ && TREE_CODE (size_tree) == INTEGER_CST)
++ bitsize = wi::to_offset (size_tree);
/* Initially, maxsize is the same as the accessed element size.
In the following it will only grow (or become -1). */
{
tree fsize = DECL_SIZE_UNIT (field);
tree ssize = TYPE_SIZE_UNIT (stype);
- if (tree_fits_shwi_p (fsize)
- && tree_fits_shwi_p (ssize)
- && wi::fits_shwi_p (woffset))
- maxsize += ((tree_to_shwi (ssize)
- - tree_to_shwi (fsize))
- * BITS_PER_UNIT
- - woffset.to_shwi ());
- else
+ if (fsize == NULL
+ || TREE_CODE (fsize) != INTEGER_CST
+ || ssize == NULL
+ || TREE_CODE (ssize) != INTEGER_CST)
- maxsize = double_int_minus_one;
+ maxsize = -1;
+ else
+ {
- double_int tem = tree_to_double_int (ssize)
- - tree_to_double_int (fsize);
++ offset_int tem = (wi::to_offset (ssize)
++ - wi::to_offset (fsize);
+ if (BITS_PER_UNIT == 8)
- tem = tem.lshift (3);
++ tem = wi::lshift (tem, 3);
+ else
- tem *= double_int::from_uhwi (BITS_PER_UNIT);
- tem -= doffset;
++ tem *= wi::to_offset (BITS_PER_UNIT);
++ tem -= woffset;
+ maxsize += tem;
+ }
}
}
}
/* We need to adjust maxsize to the whole structure bitsize.
But we can subtract any constant offset seen so far,
because that would get us out of the structure otherwise. */
- if (!maxsize.is_minus_one ()
+ if (maxsize != -1
&& csize
- && tree_fits_uhwi_p (csize)
- && wi::fits_shwi_p (bit_offset))
- maxsize = tree_to_uhwi (csize) - bit_offset.to_shwi ();
+ && TREE_CODE (csize) == INTEGER_CST)
- maxsize = tree_to_double_int (csize) - bit_offset;
++ maxsize = wi::to_offset (csize) - bit_offset;
else
- maxsize = double_int_minus_one;
+ maxsize = -1;
}
}
break;
/* We need to adjust maxsize to the whole array bitsize.
But we can subtract any constant offset seen so far,
because that would get us outside of the array otherwise. */
- if (!maxsize.is_minus_one ()
+ if (maxsize != -1
&& asize
- && tree_fits_uhwi_p (asize)
- && wi::fits_shwi_p (bit_offset))
- maxsize = tree_to_uhwi (asize) - bit_offset.to_shwi ();
+ && TREE_CODE (asize) == INTEGER_CST)
- maxsize = tree_to_double_int (asize) - bit_offset;
++ maxsize = wi::to_offset (asize) - bit_offset;
else
- maxsize = double_int_minus_one;
+ maxsize = -1;
/* Remember that we have seen an array ref with a variable
index. */
base type boundary. This needs to include possible trailing
padding that is there for alignment purposes. */
if (seen_variable_array_ref
- && !maxsize.is_minus_one ()
+ && maxsize != -1
- && (!wi::fits_shwi_p (bit_offset)
- || !tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp)))
- || (bit_offset.to_shwi () + maxsize
- == (HOST_WIDE_INT) tree_to_uhwi
- (TYPE_SIZE (TREE_TYPE (exp))))))
+ && (TYPE_SIZE (TREE_TYPE (exp)) == NULL_TREE
+ || TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
+ || (bit_offset + maxsize
- == tree_to_double_int (TYPE_SIZE (TREE_TYPE (exp))))))
- maxsize = double_int_minus_one;
++ == wi::to_offset (TYPE_SIZE (TREE_TYPE (exp))))))
+ maxsize = -1;
/* Hand back the decl for MEM[&decl, off]. */
if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
/* We need to deal with variable arrays ending structures. */
if (seen_variable_array_ref
- && !maxsize.is_minus_one ()
+ && maxsize != -1
- && (!wi::fits_shwi_p (bit_offset)
- || !tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp)))
- || (bit_offset.to_shwi () + maxsize
- == (HOST_WIDE_INT) tree_to_uhwi
- (TYPE_SIZE (TREE_TYPE (exp))))))
+ && (TYPE_SIZE (TREE_TYPE (exp)) == NULL_TREE
+ || TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
+ || (bit_offset + maxsize
- == tree_to_double_int (TYPE_SIZE (TREE_TYPE (exp))))))
- maxsize = double_int_minus_one;
++ == wi::to_offset (TYPE_SIZE (TREE_TYPE (exp))))))
+ maxsize = -1;
done:
- if (!wi::fits_shwi_p (bit_offset))
- if (!bitsize.fits_shwi () || bitsize.is_negative ())
++ if (!wi::fits_shwi_p (bitsize) || wi::neg_p (bitsize))
{
*poffset = 0;
- *psize = bitsize;
+ *psize = -1;
*pmax_size = -1;
return exp;
}
- hbit_offset = bit_offset.to_shwi ();
+ *psize = bitsize.to_shwi ();
+
- if (!bit_offset.fits_shwi ())
++ if (!wi::fits_shwi_p (bit_offset))
+ {
+ *poffset = 0;
+ *pmax_size = -1;
+
+ return exp;
+ }
/* In case of a decl or constant base object we can do better. */
{
/* If maxsize is unknown adjust it according to the size of the
base decl. */
- if (maxsize.is_minus_one ()
+ if (maxsize == -1
- && tree_fits_uhwi_p (DECL_SIZE (exp)))
- maxsize = tree_to_uhwi (DECL_SIZE (exp)) - hbit_offset;
+ && DECL_SIZE (exp)
+ && TREE_CODE (DECL_SIZE (exp)) == INTEGER_CST)
- maxsize = tree_to_double_int (DECL_SIZE (exp)) - bit_offset;
++ maxsize = wi::to_offset (DECL_SIZE (exp)) - bit_offset;
}
else if (CONSTANT_CLASS_P (exp))
{
/* If maxsize is unknown adjust it according to the size of the
base type constant. */
- if (maxsize.is_minus_one ()
+ if (maxsize == -1
- && tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp))))
- maxsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (exp))) - hbit_offset;
+ && TYPE_SIZE (TREE_TYPE (exp))
+ && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST)
- maxsize = tree_to_double_int (TYPE_SIZE (TREE_TYPE (exp)))
- - bit_offset;
++ maxsize = (wi::to_offset (TYPE_SIZE (TREE_TYPE (exp)))
++ - bit_offset);
}
/* ??? Due to negative offsets in ARRAY_REF we can end up with
negative bit_offset here. We might want to store a zero offset
in this case. */
- *poffset = hbit_offset;
- *psize = bitsize;
- *pmax_size = maxsize;
+ *poffset = bit_offset.to_shwi ();
- if (!maxsize.fits_shwi () || maxsize.is_negative ())
++ if (!wi::fits_shwi (maxsize) || wi::neg_p (maxsize))
+ *pmax_size = -1;
+ else
+ *pmax_size = maxsize.to_shwi ();
return exp;
}