Speaking in terms of a patch:
Index: tree.h
===================================================================
--- tree.h (revision 203690)
+++ tree.h (working copy)
@@ -5184,14 +5184,11 @@ wi::int_traits <const_tree>::decompose (
/ HOST_BITS_PER_WIDE_INT);
unsigned int xprecision = get_precision (x);
- gcc_assert (precision >= xprecision);
+ gcc_checking_assert (precision >= xprecision && precision != 0);
- /* Got to be careful of precision 0 values. */
- if (precision)
- len = MIN (len, max_len);
if (TYPE_SIGN (TREE_TYPE (x)) == UNSIGNED)
{
- unsigned int small_prec = precision & (HOST_BITS_PER_WIDE_INT - 1);
+ unsigned int small_prec = xprecision & (HOST_BITS_PER_WIDE_INT -
1);
if (small_prec)
{
/* We have to futz with this because the canonization for
@@ -5201,7 +5198,7 @@ wi::int_traits <const_tree>::decompose (
{
for (unsigned int i = 0; i < len - 1; i++)
scratch[i] = val[i];
- scratch[len - 1] = sext_hwi (val[len - 1], precision);
+ scratch[len - 1] = sext_hwi (val[len - 1], small_prec);
return wi::storage_ref (scratch, len, precision);
}
}
the precision 0 thing is gone as far as I understand?
Also sign-extending the upper hwi must be done with precision %
HOST_BITS_PER_WIDE_INT, no? And it assumes that we only ever
have to extend the upper most HWI, thus 'len' is never too big.
I note that we immediately return in the above case, so
if (precision < xprecision + HOST_BITS_PER_WIDE_INT)
{
len = wi::force_to_size (scratch, val, len, xprecision,
precision, UNSIGNED);
return wi::storage_ref (scratch, len, precision);
}
applies only when the desired precision is a multiple of a HWI.
I assume it adds that extra zero word in case the MSB is set,
right? I am confused about the condition written here and
how we look at precision and not xprecision when deciding how
to extend - given a 8-bit precision unsigned 0xff and precision == 64
we do not even consider sign-extending the value because we look
at precision and not xprecision. Don't we need to look at
xprecision here? After all an assert precision == xprecision
does not work in this routine.
Quickly execute.exp tested only.
To avoid code quality wreckage we have to implement a different way
of allocating the 'scratch' storage of wide_int_ref_storage
(well, ideally we wouldn't need it ...). I thought of simply
allocating it via alloca (), but we need to do that in all
callers that build a wide_int_ref (eventually via a hidden
default arg). But as that's a template specialization of
generic_wide_int ... so the option is to provide a function
wrapper inside wi:: for this, like
template <typename T>
wide_int_ref
wi::ref (const T &t, HOST_WIDE_INT *scratch = XALLOCAVEC (HOST_WIDE_INT,
WIDE_INT_MAX_ELTS))
{
return wide_int_ref (t, scratch);
}
and amend the storage constructors to get a scratch argument.
The reason for all this is that otherwise the wide_int_ref object
escapes when we pass the scratch storage to the workers in
int_traits <const_tree>.
Thanks,
Richard.