Skip to content

Commit

Permalink
avoid assignment of a struct/union field to a partially overlapped field
Browse files Browse the repository at this point in the history
  • Loading branch information
jxyang committed Sep 28, 2011
1 parent e65d3c7 commit a5e5fd1
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/CGContext.cpp
Expand Up @@ -68,6 +68,7 @@ CGContext::CGContext(Function *current_func, const Effect &eff_context, Effect *
curr_blk(0),
rw_directive(NULL),
iv_bounds(),
curr_rhs(NULL),
effect_context(eff_context),
effect_accum(eff_accum)
{
Expand All @@ -84,6 +85,7 @@ CGContext::CGContext(const CGContext &cgc, const Effect &eff_context, Effect *ef
curr_blk(cgc.curr_blk),
rw_directive(cgc.rw_directive),
iv_bounds(cgc.iv_bounds),
curr_rhs(NULL),
effect_context(eff_context),
effect_accum(eff_accum),
effect_stm()
Expand All @@ -101,6 +103,7 @@ CGContext::CGContext(const CGContext &cgc, Function* f, const Effect &eff_contex
curr_blk(cgc.curr_blk),
rw_directive(cgc.rw_directive),
iv_bounds(cgc.iv_bounds),
curr_rhs(NULL),
effect_context(eff_context),
effect_accum(eff_accum)
{
Expand All @@ -117,6 +120,7 @@ CGContext::CGContext(const CGContext &cgc, RWDirective* rwd, const Variable* iv,
curr_blk(cgc.curr_blk),
rw_directive(rwd),
iv_bounds(cgc.iv_bounds),
curr_rhs(NULL),
effect_context(cgc.effect_context),
effect_accum(cgc.effect_accum)
{
Expand Down
2 changes: 2 additions & 0 deletions src/CGContext.h
Expand Up @@ -163,6 +163,8 @@ class CGContext
RWDirective* rw_directive;
// induction variables for loops, with each IV controls one nested loop
map<const Variable*, unsigned int> iv_bounds;

const Expression* curr_rhs; // only used in the context of LHS

private:
const Effect &effect_context;
Expand Down
25 changes: 25 additions & 0 deletions src/FactPointTo.cpp
Expand Up @@ -842,6 +842,31 @@ FactPointTo::aggregate_all_pointto_sets(void)
assert(all_ptrs.size() == all_aliases.size());
}

/* find union fields that are referred to by this expression */
int
FactPointTo::find_union_pointees(const vector<const Fact*>& facts, const Expression* e, vector<const Variable*>& unions)
{
unions.clear();
vector<const Variable*> vars;
if (e->term_type == eVariable) {
const ExpressionVariable* ev = dynamic_cast<const ExpressionVariable*>(e);
vars = merge_pointees_of_pointer(ev->get_var()->get_collective(), ev->get_indirect_level(), facts);
}
else if (e->term_type == eLhs) {
const Lhs* lhs = dynamic_cast<const Lhs*>(e);
vars = merge_pointees_of_pointer(lhs->get_var()->get_collective(), lhs->get_indirect_level(), facts);
}

for (size_t i=0; i<vars.size(); i++) {
const Variable* u = vars[i]->get_container_union();
// we only care referenced union fields, not unions
if (u && vars[i] != u) {
add_variable_to_set(unions, u);
}
}
return unions.size();
}

///////////////////////////////////////////////////////////////////////////////

// Local Variables:
Expand Down
1 change: 1 addition & 0 deletions src/FactPointTo.h
Expand Up @@ -102,6 +102,7 @@ class FactPointTo : public Fact
static bool is_dangling_ptr(const Variable* p, const std::vector<const Fact*>& facts);
static bool is_special_ptr(const Variable* p) { return p==null_ptr || p==garbage_ptr || p==tbd_ptr;}
static bool is_pointing_to_locals(const Variable* v, const Block* b, int indirection, const vector<const Fact*>& facts);
static int find_union_pointees(const vector<const Fact*>& facts, const Expression* e, vector<const Variable*>& unions);

static std::string point_to_str(const Variable* v);

Expand Down
23 changes: 23 additions & 0 deletions src/Lhs.cpp
Expand Up @@ -297,6 +297,22 @@ Lhs::visit_indices(vector<const Fact*>& inputs, CGContext& cg_context) const
return true;
}

// conservatively assume two fields overlap if they are both part of the same union variable
bool
have_overlapping_fields(const Expression* e1, const Expression* e2, const vector<const Fact*>& facts)
{
vector<const Variable*> vars1, vars2;
if (FactPointTo::find_union_pointees(facts, e1, vars1)) {
FactPointTo::find_union_pointees(facts, e2, vars2);
for (size_t i=0; i<vars2.size(); i++) {
if (is_variable_in_set(vars1, vars2[i])) {
return true;
}
}
}
return false;
}

bool
Lhs::visit_facts(vector<const Fact*>& inputs, CGContext& cg_context) const
{
Expand All @@ -312,6 +328,13 @@ Lhs::visit_facts(vector<const Fact*>& inputs, CGContext& cg_context) const
if (!visit_indices(inputs, cg_context)) {
return false;
}
// avoid a.x = a.y where x and y are partially overlapping fields
if (cg_context.curr_rhs && cg_context.curr_rhs->term_type == eVariable) {
if (have_overlapping_fields(cg_context.curr_rhs, this, inputs)) {
return false;
}
}

if (get_indirect_level() > 0) {
if (!FactPointTo::is_valid_ptr(v, inputs)) {
return false;
Expand Down
3 changes: 3 additions & 0 deletions src/StatementAssign.cpp
Expand Up @@ -151,6 +151,8 @@ StatementAssign::make_random(CGContext &cg_context, const Type* type, const CVQu

CGContext lhs_cg_context(cg_context, running_eff_context, &lhs_accum);
lhs_cg_context.get_effect_stm() = rhs_cg_context.get_effect_stm();
lhs_cg_context.curr_rhs = e;

bool prev_flag = CGOptions::match_exact_qualifiers(); // keep a copy of previous flag
if (qf) CGOptions::match_exact_qualifiers(true); // force exact qualifier match when selecting vars
lhs = Lhs::make_random(lhs_cg_context, type, &qfer, op != eSimpleAssign, need_no_rhs(op));
Expand Down Expand Up @@ -294,6 +296,7 @@ StatementAssign::visit_facts(vector<const Fact*>& inputs, CGContext& cg_context)

CGContext lhs_cg_context(cg_context, running_eff_context, &lhs_accum);
lhs_cg_context.get_effect_stm() = rhs_cg_context.get_effect_stm();
lhs_cg_context.curr_rhs = &expr;
if (!lhs.visit_facts(inputs, lhs_cg_context)) {
return false;
}
Expand Down

0 comments on commit a5e5fd1

Please sign in to comment.