typedef struct constraint_expr ce_s;
DEF_VEC_O(ce_s);
DEF_VEC_ALLOC_O(ce_s, heap);
-static void get_constraint_for_1 (tree, VEC(ce_s, heap) **, bool);
+static void get_constraint_for_1 (tree, VEC(ce_s, heap) **, bool, bool);
static void get_constraint_for (tree, VEC(ce_s, heap) **);
+static void get_constraint_for_rhs (tree, VEC(ce_s, heap) **);
static void do_deref (VEC (ce_s, heap) **);
/* Our set constraints are made up of two constraint expressions, one
does not change the points-to solution. */
if (!use_field_sensitive)
{
- get_constraint_for (ptr, results);
+ get_constraint_for_rhs (ptr, results);
return;
}
rhsoffset = UNKNOWN_OFFSET;
}
- get_constraint_for (ptr, results);
+ get_constraint_for_rhs (ptr, results);
if (rhsoffset == 0)
return;
/* Given a COMPONENT_REF T, return the constraint_expr vector for it.
- If address_p is true the result will be taken its address of. */
+ If address_p is true the result will be taken its address of.
+ If lhs_p is true then the constraint expression is assumed to be used
+ as the lhs. */
static void
get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results,
- bool address_p)
+ bool address_p, bool lhs_p)
{
tree orig_t = t;
HOST_WIDE_INT bitsize = -1;
return;
}
+ /* Handle type-punning through unions. If we are extracting a pointer
+ from a union via a possibly type-punning access that pointer
+ points to anything, similar to a conversion of an integer to
+ a pointer. */
+ if (!lhs_p)
+ {
+ tree u;
+ for (u = t;
+ TREE_CODE (u) == COMPONENT_REF || TREE_CODE (u) == ARRAY_REF;
+ u = TREE_OPERAND (u, 0))
+ if (TREE_CODE (u) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE)
+ {
+ struct constraint_expr temp;
+
+ temp.offset = 0;
+ temp.var = anything_id;
+ temp.type = ADDRESSOF;
+ VEC_safe_push (ce_s, heap, *results, &temp);
+ return;
+ }
+ }
+
t = get_ref_base_and_extent (t, &bitpos, &bitsize, &bitmaxsize);
/* Pretend to take the address of the base, we'll take care of
adding the required subset of sub-fields below. */
- get_constraint_for_1 (t, results, true);
+ get_constraint_for_1 (t, results, true, lhs_p);
gcc_assert (VEC_length (ce_s, *results) == 1);
result = VEC_last (ce_s, *results);
}
}
-static void get_constraint_for_1 (tree, VEC (ce_s, heap) **, bool);
-
/* Given a tree T, return the constraint expression for taking the
address of it. */
struct constraint_expr *c;
unsigned int i;
- get_constraint_for_1 (t, results, true);
+ get_constraint_for_1 (t, results, true, true);
FOR_EACH_VEC_ELT (ce_s, *results, i, c)
{
/* Given a tree T, return the constraint expression for it. */
static void
-get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p)
+get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p,
+ bool lhs_p)
{
struct constraint_expr temp;
case ARRAY_REF:
case ARRAY_RANGE_REF:
case COMPONENT_REF:
- get_constraint_for_component_ref (t, results, address_p);
+ get_constraint_for_component_ref (t, results, address_p, lhs_p);
return;
case VIEW_CONVERT_EXPR:
- get_constraint_for_1 (TREE_OPERAND (t, 0), results, address_p);
+ get_constraint_for_1 (TREE_OPERAND (t, 0), results, address_p,
+ lhs_p);
return;
/* We are missing handling for TARGET_MEM_REF here. */
default:;
{
struct constraint_expr *rhsp;
unsigned j;
- get_constraint_for_1 (val, &tmp, address_p);
+ get_constraint_for_1 (val, &tmp, address_p, lhs_p);
FOR_EACH_VEC_ELT (ce_s, tmp, j, rhsp)
VEC_safe_push (ce_s, heap, *results, rhsp);
VEC_truncate (ce_s, tmp, 0);
{
gcc_assert (VEC_length (ce_s, *results) == 0);
- get_constraint_for_1 (t, results, false);
+ get_constraint_for_1 (t, results, false, true);
+}
+
+/* Given a gimple tree T, return the constraint expression vector for it
+ to be used as the rhs of a constraint. */
+
+static void
+get_constraint_for_rhs (tree t, VEC (ce_s, heap) **results)
+{
+ gcc_assert (VEC_length (ce_s, *results) == 0);
+
+ get_constraint_for_1 (t, results, false, false);
}
unsigned j;
get_constraint_for (lhsop, &lhsc);
- get_constraint_for (rhsop, &rhsc);
+ get_constraint_for_rhs (rhsop, &rhsc);
lhsp = VEC_index (ce_s, lhsc, 0);
rhsp = VEC_index (ce_s, rhsc, 0);
if (lhsp->type == DEREF
includes.offset = 0;
includes.type = SCALAR;
- get_constraint_for (op, &rhsc);
+ get_constraint_for_rhs (op, &rhsc);
FOR_EACH_VEC_ELT (ce_s, rhsc, j, c)
process_constraint (new_constraint (includes, *c));
VEC_free (ce_s, heap, rhsc);
VEC(ce_s, heap) *argc = NULL;
unsigned i;
struct constraint_expr *argp;
- get_constraint_for (arg, &argc);
+ get_constraint_for_rhs (arg, &argc);
FOR_EACH_VEC_ELT (ce_s, argc, i, argp)
VEC_safe_push (ce_s, heap, *results, argp);
VEC_free(ce_s, heap, argc);
tree strippedrhs = PHI_ARG_DEF (t, i);
STRIP_NOPS (strippedrhs);
- get_constraint_for (gimple_phi_arg_def (t, i), &rhsc);
+ get_constraint_for_rhs (gimple_phi_arg_def (t, i), &rhsc);
FOR_EACH_VEC_ELT (ce_s, lhsc, j, c)
{
if (!could_have_pointers (arg))
continue;
- get_constraint_for (arg, &rhsc);
+ get_constraint_for_rhs (arg, &rhsc);
lhs = get_function_part_constraint (fi, fi_parm_base + j);
while (VEC_length (ce_s, rhsc) != 0)
{
&& !(POINTER_TYPE_P (gimple_expr_type (t))
&& !POINTER_TYPE_P (TREE_TYPE (rhsop))))
|| gimple_assign_single_p (t))
- get_constraint_for (rhsop, &rhsc);
+ get_constraint_for_rhs (rhsop, &rhsc);
else
{
temp.type = ADDRESSOF;
unsigned i;
lhs = get_function_part_constraint (fi, fi_result);
- get_constraint_for (gimple_return_retval (t), &rhsc);
+ get_constraint_for_rhs (gimple_return_retval (t), &rhsc);
FOR_EACH_VEC_ELT (ce_s, rhsc, i, rhsp)
process_constraint (new_constraint (lhs, *rhsp));
}
VEC(ce_s, heap) *ptrc = NULL;
struct constraint_expr *c, lhs;
unsigned i;
- get_constraint_for (ptr, &ptrc);
+ get_constraint_for_rhs (ptr, &ptrc);
lhs = get_function_part_constraint (fi, fi_clobbers);
FOR_EACH_VEC_ELT (ce_s, ptrc, i, c)
process_constraint (new_constraint (lhs, *c));
VEC (ce_s, heap) *rhsc = NULL;
struct constraint_expr lhs, *rhsp;
unsigned i;
- get_constraint_for (DECL_INITIAL (decl), &rhsc);
+ get_constraint_for_rhs (DECL_INITIAL (decl), &rhsc);
lhs.var = vi->id;
lhs.offset = 0;
lhs.type = SCALAR;