if (!dstsize)
dstsize = maxobjsize;
- /* Set RANGE to that of DSTWRITE if non-null, bounded by PAD->DST.BNDRNG
+ /* Set RANGE to that of DSTWRITE if non-null, bounded by PAD->DST_BNDRNG
if valid. */
gimple *stmt = pad ? pad->stmt : nullptr;
- get_size_range (rvals, dstwrite, stmt, range, pad ? pad->dst.bndrng : NULL);
+ get_size_range (rvals, dstwrite, stmt, range, pad ? pad->dst_bndrng : NULL);
tree func = get_callee_fndecl (exp);
/* Read vs write access by built-ins can be determined from the const
of an object. */
if (maxread)
{
- /* Set RANGE to that of MAXREAD, bounded by PAD->SRC.BNDRNG if
+ /* Set RANGE to that of MAXREAD, bounded by PAD->SRC_BNDRNG if
PAD is nonnull and BNDRNG is valid. */
- get_size_range (rvals, maxread, stmt, range, pad ? pad->src.bndrng : NULL);
+ get_size_range (rvals, maxread, stmt, range, pad ? pad->src_bndrng : NULL);
location_t loc = get_location (exp);
tree size = dstsize;
&& (pad->src.offrng[1] < 0
|| pad->src.offrng[0] <= pad->src.offrng[1]))
{
- /* Set RANGE to that of MAXREAD, bounded by PAD->SRC.BNDRNG if
+ /* Set RANGE to that of MAXREAD, bounded by PAD->SRC_BNDRNG if
PAD is nonnull and BNDRNG is valid. */
- get_size_range (rvals, maxread, stmt, range, pad ? pad->src.bndrng : NULL);
+ get_size_range (rvals, maxread, stmt, range, pad ? pad->src_bndrng : NULL);
/* Set OVERREAD for reads starting just past the end of an object. */
- overread = pad->src.sizrng[1] - pad->src.offrng[0] < pad->src.bndrng[0];
- range[0] = wide_int_to_tree (sizetype, pad->src.bndrng[0]);
+ overread = pad->src.sizrng[1] - pad->src.offrng[0] < pad->src_bndrng[0];
+ range[0] = wide_int_to_tree (sizetype, pad->src_bndrng[0]);
slen = size_zero_node;
}
/* Determine the range of the bound first and bail if it fails; it's
cheaper than computing the size of the objects. */
tree bndrng[2] = { NULL_TREE, NULL_TREE };
- get_size_range (m_ptr_qry.rvals, bound, stmt, bndrng, adata1.src.bndrng);
+ get_size_range (m_ptr_qry.rvals, bound, stmt, bndrng, adata1.src_bndrng);
if (!bndrng[0] || integer_zerop (bndrng[0]))
return;
return var;
}
-/* Given a statement STMT, set the bounds of the reference to at most
- as many bytes as BOUND or unknown when null, and at least one when
- the MINACCESS is true unless BOUND is a constant zero. STMT is
- used for context to get accurate range info. */
-
-access_ref::access_ref (range_query *qry /* = nullptr */,
- tree bound /* = NULL_TREE */,
- gimple *stmt /* = nullptr */,
- bool minaccess /* = false */)
+/* Initialize the object. */
+
+access_ref::access_ref ()
: ref (), eval ([](tree x){ return x; }), deref (), trail1special (true),
base0 (true), parmarray ()
{
offmax[0] = offmax[1] = 0;
/* Invalidate. */
sizrng[0] = sizrng[1] = -1;
-
- /* Set the default bounds of the access and adjust below. */
- bndrng[0] = minaccess ? 1 : 0;
- bndrng[1] = HOST_WIDE_INT_M1U;
-
- /* When BOUND is nonnull and a range can be extracted from it,
- set the bounds of the access to reflect both it and MINACCESS.
- BNDRNG[0] is the size of the minimum access. */
- tree rng[2];
- if (bound && get_size_range (qry, bound, stmt, rng, SR_ALLOW_ZERO))
- {
- bndrng[0] = wi::to_offset (rng[0]);
- bndrng[1] = wi::to_offset (rng[1]);
- bndrng[0] = bndrng[0] > 0 && minaccess ? 1 : 0;
- }
}
/* Return the PHI node REF refers to or null if it doesn't. */
sizestr, allocfn);
}
+/* Set the access to at most MAXWRITE and MAXREAD bytes, and at least 1
+ when MINWRITE or MINREAD, respectively, is set. */
+access_data::access_data (range_query *query, gimple *stmt, access_mode mode,
+ tree maxwrite /* = NULL_TREE */,
+ bool minwrite /* = false */,
+ tree maxread /* = NULL_TREE */,
+ bool minread /* = false */)
+ : stmt (stmt), call (), dst (), src (), mode (mode)
+{
+ set_bound (dst_bndrng, maxwrite, minwrite, query, stmt);
+ set_bound (src_bndrng, maxread, minread, query, stmt);
+}
+
+/* Set the access to at most MAXWRITE and MAXREAD bytes, and at least 1
+ when MINWRITE or MINREAD, respectively, is set. */
+access_data::access_data (range_query *query, tree expr, access_mode mode,
+ tree maxwrite /* = NULL_TREE */,
+ bool minwrite /* = false */,
+ tree maxread /* = NULL_TREE */,
+ bool minread /* = false */)
+ : stmt (), call (expr), dst (), src (), mode (mode)
+{
+ set_bound (dst_bndrng, maxwrite, minwrite, query, stmt);
+ set_bound (src_bndrng, maxread, minread, query, stmt);
+}
+
+/* Set BNDRNG to the range of BOUND for the statement STMT. */
+
+void
+access_data::set_bound (offset_int bndrng[2], tree bound, bool minaccess,
+ range_query *query, gimple *stmt)
+{
+ /* Set the default bounds of the access and adjust below. */
+ bndrng[0] = minaccess ? 1 : 0;
+ bndrng[1] = HOST_WIDE_INT_M1U;
+
+ /* When BOUND is nonnull and a range can be extracted from it,
+ set the bounds of the access to reflect both it and MINACCESS.
+ BNDRNG[0] is the size of the minimum access. */
+ tree rng[2];
+ if (bound && get_size_range (query, bound, stmt, rng, SR_ALLOW_ZERO))
+ {
+ bndrng[0] = wi::to_offset (rng[0]);
+ bndrng[1] = wi::to_offset (rng[1]);
+ bndrng[0] = bndrng[0] > 0 && minaccess ? 1 : 0;
+ }
+}
+
/* Set a bit for the PHI in VISITED and return true if it wasn't
already set. */
if (const access_ref *cache_ref = qry->get_ref (ptr))
{
/* If the pointer is in the cache set *PREF to what it refers
- to and return success.
- FIXME: BNDRNG is determined by each access and so it doesn't
- belong in access_ref. Until the design is changed, keep it
- unchanged here. */
- const offset_int bndrng[2] = { pref->bndrng[0], pref->bndrng[1] };
+ to and return success. */
*pref = *cache_ref;
- pref->bndrng[0] = bndrng[0];
- pref->bndrng[1] = bndrng[1];
return true;
}
}
struct access_ref
{
/* Set the bounds of the reference. */
- access_ref (range_query *query = nullptr, tree = NULL_TREE,
- gimple * = nullptr, bool = false);
+ access_ref ();
/* Return the PHI node REF refers to or null if it doesn't. */
gphi *phi () const;
offset_int sizrng[2];
/* The minimum and maximum offset computed. */
offset_int offmax[2];
- /* Range of the bound of the access: denotes that the access
- is at least BNDRNG[0] bytes but no more than BNDRNG[1].
- For string functions the size of the actual access is
- further constrained by the length of the string. */
- offset_int bndrng[2];
/* Used to fold integer expressions when called from front ends. */
tree (*eval)(tree);
{
/* Set the access to at most MAXWRITE and MAXREAD bytes, and
at least 1 when MINWRITE or MINREAD, respectively, is set. */
- access_data (range_query *query, gimple *stmt, access_mode mode,
- tree maxwrite = NULL_TREE, bool minwrite = false,
- tree maxread = NULL_TREE, bool minread = false)
- : stmt (stmt), call (),
- dst (query, maxwrite, stmt, minwrite),
- src (query, maxread, stmt, minread),
- mode (mode) { }
+ access_data (range_query *, gimple *, access_mode,
+ tree = NULL_TREE, bool = false,
+ tree = NULL_TREE, bool = false);
/* Set the access to at most MAXWRITE and MAXREAD bytes, and
at least 1 when MINWRITE or MINREAD, respectively, is set. */
- access_data (range_query *query, tree expr, access_mode mode,
- tree maxwrite = NULL_TREE, bool minwrite = false,
- tree maxread = NULL_TREE, bool minread = false)
- : stmt (), call (expr),
- dst (query, maxwrite, nullptr, minwrite),
- src (query, maxread, nullptr, minread),
- mode (mode) { }
+ access_data (range_query *, tree, access_mode,
+ tree = NULL_TREE, bool = false,
+ tree = NULL_TREE, bool = false);
+
+ /* Constructor helper. */
+ static void set_bound (offset_int[2], tree, bool, range_query *, gimple *);
/* Access statement. */
gimple *stmt;
tree call;
/* Destination and source of the access. */
access_ref dst, src;
+
+ /* Range of the bound of the access: denotes that the access is at
+ least XXX_BNDRNG[0] bytes but no more than XXX_BNDRNG[1]. For
+ string functions the size of the actual access is further
+ constrained by the length of the string. */
+ offset_int dst_bndrng[2];
+ offset_int src_bndrng[2];
+
/* Read-only for functions like memcmp or strlen, write-only
for memset, read-write for memcpy or strcat. */
access_mode mode;