@@ -118,6 +118,8 @@ vrange_allocator::clone_varying (tree type)
{
if (irange::supports_p (type))
return irange_storage::alloc (*m_alloc, int_range <1> (type));
+ if (prange::supports_p (type))
+ return prange_storage::alloc (*m_alloc, prange (type));
if (frange::supports_p (type))
return frange_storage::alloc (*m_alloc, frange (type));
return NULL;
@@ -128,6 +130,8 @@ vrange_allocator::clone_undefined (tree type)
{
if (irange::supports_p (type))
return irange_storage::alloc (*m_alloc, int_range<1> ());
+ if (prange::supports_p (type))
+ return prange_storage::alloc (*m_alloc, prange ());
if (frange::supports_p (type))
return frange_storage::alloc (*m_alloc, frange ());
return NULL;
@@ -141,6 +145,8 @@ vrange_storage::alloc (vrange_internal_alloc &allocator, const vrange &r)
{
if (is_a <irange> (r))
return irange_storage::alloc (allocator, as_a <irange> (r));
+ if (is_a <prange> (r))
+ return prange_storage::alloc (allocator, as_a <prange> (r));
if (is_a <frange> (r))
return frange_storage::alloc (allocator, as_a <frange> (r));
return NULL;
@@ -157,6 +163,12 @@ vrange_storage::set_vrange (const vrange &r)
gcc_checking_assert (s->fits_p (as_a <irange> (r)));
s->set_irange (as_a <irange> (r));
}
+ else if (is_a <prange> (r))
+ {
+ prange_storage *s = static_cast <prange_storage *> (this);
+ gcc_checking_assert (s->fits_p (as_a <prange> (r)));
+ s->set_prange (as_a <prange> (r));
+ }
else if (is_a <frange> (r))
{
frange_storage *s = static_cast <frange_storage *> (this);
@@ -190,6 +202,11 @@ vrange_storage::get_vrange (vrange &r, tree type) const
const irange_storage *s = static_cast <const irange_storage *> (this);
s->get_irange (as_a <irange> (r), type);
}
+ else if (is_a <prange> (r))
+ {
+ const prange_storage *s = static_cast <const prange_storage *> (this);
+ s->get_prange (as_a <prange> (r), type);
+ }
else if (is_a <frange> (r))
{
const frange_storage *s = static_cast <const frange_storage *> (this);
@@ -209,6 +226,11 @@ vrange_storage::fits_p (const vrange &r) const
const irange_storage *s = static_cast <const irange_storage *> (this);
return s->fits_p (as_a <irange> (r));
}
+ if (is_a <prange> (r))
+ {
+ const prange_storage *s = static_cast <const prange_storage *> (this);
+ return s->fits_p (as_a <prange> (r));
+ }
if (is_a <frange> (r))
{
const frange_storage *s = static_cast <const frange_storage *> (this);
@@ -230,6 +252,11 @@ vrange_storage::equal_p (const vrange &r) const
const irange_storage *s = static_cast <const irange_storage *> (this);
return s->equal_p (as_a <irange> (r));
}
+ if (is_a <prange> (r))
+ {
+ const prange_storage *s = static_cast <const prange_storage *> (this);
+ return s->equal_p (as_a <prange> (r));
+ }
if (is_a <frange> (r))
{
const frange_storage *s = static_cast <const frange_storage *> (this);
@@ -559,6 +586,96 @@ frange_storage::fits_p (const frange &) const
return true;
}
+//============================================================================
+// prange_storage implementation
+//============================================================================
+
+prange_storage *
+prange_storage::alloc (vrange_internal_alloc &allocator, const prange &r)
+{
+ // Assume all pointers are the same size.
+ unsigned prec = TYPE_PRECISION (TREE_TYPE (null_pointer_node));
+ gcc_checking_assert (r.undefined_p () || TYPE_PRECISION (r.type ()) == prec);
+
+ typedef trailing_wide_ints<NINTS> twi;
+ size_t size = sizeof (prange_storage) + twi::extra_size (prec);
+ prange_storage *p = static_cast <prange_storage *> (allocator.alloc (size));
+ new (p) prange_storage (r);
+ return p;
+}
+
+// Initialize the storage with R.
+
+prange_storage::prange_storage (const prange &r)
+{
+ // It is the caller's responsibility to allocate enough space such
+ // that the precision fits.
+ unsigned prec = TYPE_PRECISION (TREE_TYPE (null_pointer_node));
+ m_trailing_ints.set_precision (prec);
+
+ set_prange (r);
+}
+
+void
+prange_storage::set_prange (const prange &r)
+{
+ if (r.undefined_p ())
+ m_kind = VR_UNDEFINED;
+ else if (r.varying_p ())
+ m_kind = VR_VARYING;
+ else
+ {
+ m_kind = VR_RANGE;
+ set_low (r.lower_bound ());
+ set_high (r.upper_bound ());
+ irange_bitmask bm = r.m_bitmask;
+ set_value (bm.value ());
+ set_mask (bm.mask ());
+ }
+}
+
+void
+prange_storage::get_prange (prange &r, tree type) const
+{
+ gcc_checking_assert (r.supports_type_p (type));
+
+ if (m_kind == VR_UNDEFINED)
+ r.set_undefined ();
+ else if (m_kind == VR_VARYING)
+ r.set_varying (type);
+ else
+ {
+ gcc_checking_assert (m_kind == VR_RANGE);
+ gcc_checking_assert (TYPE_PRECISION (type) == m_trailing_ints.get_precision ());
+ r.m_kind = VR_RANGE;
+ r.m_type = type;
+ r.m_min = get_low ();
+ r.m_max = get_high ();
+ r.m_bitmask = irange_bitmask (get_value (), get_mask ());
+ if (flag_checking)
+ r.verify_range ();
+ }
+}
+
+bool
+prange_storage::equal_p (const prange &r) const
+{
+ if (r.undefined_p ())
+ return m_kind == VR_UNDEFINED;
+
+ prange tmp;
+ get_prange (tmp, r.type ());
+ return tmp == r;
+}
+
+bool
+prange_storage::fits_p (const prange &) const
+{
+ // All pointers are the same size.
+ return true;
+}
+
+
static vrange_allocator ggc_vrange_allocator (true);
vrange_storage *ggc_alloc_vrange_storage (tree type)
@@ -98,6 +98,39 @@ private:
irange_storage (const irange &r);
};
+// Efficient memory storage for a prange.
+
+class prange_storage : public vrange_storage
+{
+public:
+ static prange_storage *alloc (vrange_internal_alloc &, const prange &);
+ void set_prange (const prange &r);
+ void get_prange (prange &r, tree type) const;
+ bool equal_p (const prange &r) const;
+ bool fits_p (const prange &r) const;
+ void dump () const;
+private:
+ DISABLE_COPY_AND_ASSIGN (prange_storage);
+ prange_storage (const prange &r);
+
+ enum value_range_kind m_kind : 3;
+
+ // We don't use TRAILING_WIDE_INT_ACCESSOR because the getters here
+ // must be const. Perhaps TRAILING_WIDE_INT_ACCESSOR could be made
+ // const and return wide_int instead of trailing_wide_int.
+ wide_int get_low () const { return m_trailing_ints[0]; }
+ wide_int get_high () const { return m_trailing_ints[1]; }
+ wide_int get_value () const { return m_trailing_ints[2]; }
+ wide_int get_mask () const { return m_trailing_ints[3]; }
+ template <typename T> void set_low (const T &x) { m_trailing_ints[0] = x; }
+ template <typename T> void set_high (const T &x) { m_trailing_ints[1] = x; }
+ template <typename T> void set_value (const T &x) { m_trailing_ints[2] = x; }
+ template <typename T> void set_mask (const T &x) { m_trailing_ints[3] = x; }
+
+ static const unsigned int NINTS = 4;
+ trailing_wide_ints<NINTS> m_trailing_ints;
+};
+
// Efficient memory storage for an frange.
class frange_storage : public vrange_storage