You should have received a copy of the GNU General Public License
along with GCC; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "basic-block.h"
#include "output.h"
#include "errors.h"
-#include "expr.h"
#include "diagnostic.h"
#include "tree.h"
#include "c-common.h"
static unsigned int changed_count;
static sbitmap changed;
-DEF_VEC_I(uint);
-DEF_VEC_ALLOC_I(uint,heap);
+DEF_VEC_I(unsigned);
+DEF_VEC_ALLOC_I(unsigned,heap);
/* Strongly Connected Component visitation info. */
sbitmap in_component;
int current_index;
unsigned int *visited_index;
- VEC(uint,heap) *scc_stack;
- VEC(uint,heap) *unification_queue;
+ VEC(unsigned,heap) *scc_stack;
+ VEC(unsigned,heap) *unification_queue;
};
{
unsigned int t = si->visited_index[n];
SET_BIT (si->in_component, n);
- while (VEC_length (uint, si->scc_stack) != 0
- && t < si->visited_index[VEC_last (uint, si->scc_stack)])
+ while (VEC_length (unsigned, si->scc_stack) != 0
+ && t < si->visited_index[VEC_last (unsigned, si->scc_stack)])
{
- unsigned int w = VEC_pop (uint, si->scc_stack);
+ unsigned int w = VEC_pop (unsigned, si->scc_stack);
get_varinfo (w)->node = n;
SET_BIT (si->in_component, w);
/* Mark this node for collapsing. */
- VEC_safe_push (uint, heap, si->unification_queue, w);
+ VEC_safe_push (unsigned, heap, si->unification_queue, w);
}
}
else
- VEC_safe_push (uint, heap, si->scc_stack, n);
+ VEC_safe_push (unsigned, heap, si->scc_stack, n);
}
changed rep's solution.
Delete any 0 weighted self-edges we now have for rep. */
- while (i != VEC_length (uint, si->unification_queue))
+ while (i != VEC_length (unsigned, si->unification_queue))
{
- unsigned int tounify = VEC_index (uint, si->unification_queue, i);
+ unsigned int tounify = VEC_index (unsigned, si->unification_queue, i);
unsigned int n = get_varinfo (tounify)->node;
if (dump_file && (dump_flags & TDF_DETAILS))
/* If we've either finished processing the entire queue, or
finished processing all nodes for component n, update the solution for
n. */
- if (i == VEC_length (uint, si->unification_queue)
- || get_varinfo (VEC_index (uint, si->unification_queue, i))->node != n)
+ if (i == VEC_length (unsigned, si->unification_queue)
+ || get_varinfo (VEC_index (unsigned, si->unification_queue, i))->node != n)
{
struct constraint_edge edge;
sbitmap visited;
/* Array that stores the topological order of the graph, *in
reverse*. */
- VEC(uint,heap) *topo_order;
+ VEC(unsigned,heap) *topo_order;
};
struct topo_info *ti = xmalloc (sizeof (struct topo_info));
ti->visited = sbitmap_alloc (size);
sbitmap_zero (ti->visited);
- ti->topo_order = VEC_alloc (uint, heap, 1);
+ ti->topo_order = VEC_alloc (unsigned, heap, 1);
return ti;
}
free_topo_info (struct topo_info *ti)
{
sbitmap_free (ti->visited);
- VEC_free (uint, heap, ti->topo_order);
+ VEC_free (unsigned, heap, ti->topo_order);
free (ti);
}
if (!TEST_BIT (ti->visited, c->dest))
topo_visit (graph, ti, c->dest);
}
- VEC_safe_push (uint, heap, ti->topo_order, n);
+ VEC_safe_push (unsigned, heap, ti->topo_order, n);
}
/* Return true if variable N + OFFSET is a legal field of N. */
si->in_component = sbitmap_alloc (size);
sbitmap_ones (si->in_component);
si->visited_index = xcalloc (sizeof (unsigned int), size + 1);
- si->scc_stack = VEC_alloc (uint, heap, 1);
- si->unification_queue = VEC_alloc (uint, heap, 1);
+ si->scc_stack = VEC_alloc (unsigned, heap, 1);
+ si->unification_queue = VEC_alloc (unsigned, heap, 1);
return si;
}
sbitmap_free (si->visited);
sbitmap_free (si->in_component);
free (si->visited_index);
- VEC_free (uint, heap, si->scc_stack);
- VEC_free (uint, heap, si->unification_queue);
+ VEC_free (unsigned, heap, si->scc_stack);
+ VEC_free (unsigned, heap, si->unification_queue);
free(si);
}
node in topological order. */
compute_topo_order (graph, ti);
- while (VEC_length (uint, ti->topo_order) != 0)
+ while (VEC_length (unsigned, ti->topo_order) != 0)
{
- unsigned int i = VEC_pop (uint, ti->topo_order);
+ unsigned int i = VEC_pop (unsigned, ti->topo_order);
unsigned int pred;
varinfo_t vi = get_varinfo (i);
bool okay_to_elim = false;
compute_topo_order (graph, ti);
- while (VEC_length (uint, ti->topo_order) != 0)
+ while (VEC_length (unsigned, ti->topo_order) != 0)
{
- i = VEC_pop (uint, ti->topo_order);
+ i = VEC_pop (unsigned, ti->topo_order);
gcc_assert (get_varinfo (i)->node == i);
/* If the node has changed, we need to process the
}
+/* Return true if an access to [ACCESSPOS, ACCESSSIZE]
+ overlaps with a field at [FIELDPOS, FIELDSIZE] */
+
+static bool
+offset_overlaps_with_access (const unsigned HOST_WIDE_INT fieldpos,
+ const unsigned HOST_WIDE_INT fieldsize,
+ const unsigned HOST_WIDE_INT accesspos,
+ const unsigned HOST_WIDE_INT accesssize)
+{
+ if (fieldpos == accesspos && fieldsize == accesssize)
+ return true;
+ if (accesspos >= fieldpos && accesspos < (fieldpos + fieldsize))
+ return true;
+ if (accesspos < fieldpos && (accesspos + accesssize > fieldpos))
+ return true;
+
+ return false;
+}
+
/* Given a COMPONENT_REF T, return the constraint_expr for it. */
static struct constraint_expr
we may have to do something cute here. */
if (result.offset < get_varinfo (result.var)->fullsize)
- result.var = first_vi_for_offset (get_varinfo (result.var),
- result.offset)->id;
+ {
+ /* It's also not true that the constraint will actually start at the
+ right offset, it may start in some padding. We only care about
+ setting the constraint to the first actual field it touches, so
+ walk to find it. */
+ varinfo_t curr;
+ for (curr = get_varinfo (result.var); curr; curr = curr->next)
+ {
+ if (offset_overlaps_with_access (curr->offset, curr->size,
+ result.offset, bitsize))
+ {
+ result.var = curr->id;
+ break;
+
+ }
+ }
+ /* assert that we found *some* field there. The user couldn't be
+ accessing *only* padding. */
+
+ gcc_assert (curr);
+ }
else
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Access to past the end of variable, ignoring\n");
const unsigned HOST_WIDE_INT size)
{
varinfo_t p = get_varinfo (lhs.var);
- unsigned HOST_WIDE_INT pstart,last;
-
+ unsigned HOST_WIDE_INT pstart, last;
pstart = p->offset;
last = p->offset + size;
for (; p && p->offset < last; p = p->next)
unsigned HOST_WIDE_INT lhssize;
unsigned HOST_WIDE_INT rhssize;
- lhssize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (lhsop)));
- rhssize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (rhsop)));
lhs = get_constraint_for (lhsop);
rhs = get_constraint_for (rhsop);
rhs = tmp;
}
- /* If the RHS is a special var, set all the LHS fields to that
- special var. */
+ /* This is fairly conservative for the RHS == ADDRESSOF case, in that it's
+ possible it's something we could handle. However, most cases falling
+ into this are dealing with transparent unions, which are slightly
+ weird. */
+ if (rhs.type == ADDRESSOF && rhs.var > integer_id)
+ {
+ rhs.type = ADDRESSOF;
+ rhs.var = anything_id;
+ }
+
+ /* If the RHS is a special var, or an addressof, set all the LHS fields to
+ that special var. */
if (rhs.var <= integer_id)
{
for (p = get_varinfo (lhs.var); p; p = p->next)
}
else
{
+ /* The size only really matters insofar as we don't set more or less of
+ the variable. If we hit an unknown size var, the size should be the
+ whole darn thing. */
+ if (get_varinfo (rhs.var)->is_unknown_size_var)
+ rhssize = ~0;
+ else
+ rhssize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (rhsop)));
+
+ if (get_varinfo (lhs.var)->is_unknown_size_var)
+ lhssize = ~0;
+ else
+ lhssize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (lhsop)));
+
+
if (rhs.type == SCALAR && lhs.type == SCALAR)
do_simple_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
else if (lhs.type != DEREF && rhs.type == DEREF)
tree rhsdecl = get_varinfo (rhs.var)->decl;
tree pointertype = TREE_TYPE (rhsdecl);
tree pointedtotype = TREE_TYPE (pointertype);
- tree tmpvar;
+ tree tmpvar;
+
gcc_assert (rhs.type == DEREF && lhs.type == DEREF);
tmpvar = create_tmp_var_raw (pointedtotype, "structcopydereftmp");
- lhs = get_constraint_for (tmpvar);
- do_rhs_deref_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
- rhs = lhs;
- lhs = get_constraint_for (lhsop);
- do_lhs_deref_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
+ do_structure_copy (tmpvar, rhsop);
+ do_structure_copy (lhsop, tmpvar);
}
}
}
vi->offset = 0;
vi->has_union = hasunion;
if (!TYPE_SIZE (decltype)
- || TREE_CODE (TYPE_SIZE (decltype)) != INTEGER_CST
+ || TREE_CODE (TYPE_SIZE (decltype)) != INTEGER_CST
|| TREE_CODE (decltype) == ARRAY_TYPE
|| TREE_CODE (decltype) == UNION_TYPE
|| TREE_CODE (decltype) == QUAL_UNION_TYPE)
}
field = fo->field;
- gcc_assert (bitpos_of_field (field) == 0);
vi->size = TREE_INT_CST_LOW (DECL_SIZE (field));
for (i = 1; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
{
subvar_t svars = get_subvars_for_var (vi->decl);
subvar_t sv;
for (sv = svars; sv; sv = sv->next)
- bitmap_set_bit (into, var_ann (sv->var)->uid);
+ bitmap_set_bit (into, DECL_UID (sv->var));
}
/* We may end up with labels in the points-to set because people
take their address, and they are _DECL's. */
else if (TREE_CODE (vi->decl) == VAR_DECL
|| TREE_CODE (vi->decl) == PARM_DECL)
- bitmap_set_bit (into, var_ann (vi->decl)->uid);
+ bitmap_set_bit (into, DECL_UID (vi->decl));
}
rhs.var = anything_id;
rhs.offset = 0;
var_anything->address_taken = true;
- process_constraint (new_constraint (lhs, rhs));
-
+ /* This specifically does not use process_constraint because
+ process_constraint ignores all anything = anything constraints, since all
+ but this one are redundant. */
+ VEC_safe_push (constraint_t, gc, constraints, new_constraint (lhs, rhs));
/* Create the READONLY variable, used to represent that a variable
points to readonly memory. */
rhs.type = ADDRESSOF;
rhs.var = anything_id;
rhs.offset = 0;
- var_readonly->address_taken = true;
process_constraint (new_constraint (lhs, rhs));
var_integer->next = NULL;
integer_id = 3;
VEC_safe_push (varinfo_t, gc, varmap, var_integer);
+
+ /* *INTEGER = ANYTHING, because we don't know where a dereference of a random
+ integer will point to. */
+ lhs.type = SCALAR;
+ lhs.var = integer_id;
+ lhs.offset = 0;
+ rhs.type = ADDRESSOF;
+ rhs.var = anything_id;
+ rhs.offset = 0;
+ process_constraint (new_constraint (lhs, rhs));
}
create_alias_vars (void)
{
basic_block bb;
-
init_alias_vars ();