Skip to content

Commit

Permalink
fix a bug in analyzing effect conflicts of union fields
Browse files Browse the repository at this point in the history
* avoid writing to a field of a struct which is inside an union when loop iv is another field of the union
* manually sort the vector retrieved from hash table iv_bounds so that random output is the same regardless the implementation of std::map
* clean up a little
  • Loading branch information
Xuejun Yang committed Jun 22, 2011
1 parent 94e6f00 commit c3fe5ff
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 63 deletions.
2 changes: 1 addition & 1 deletion src/ArrayVariable.cpp
Expand Up @@ -186,7 +186,7 @@ ArrayVariable::ArrayVariable(Block* blk, const std::string &name, const Type *ty
}

ArrayVariable::ArrayVariable(const ArrayVariable& av)
: Variable(av.name, av.type, av.init, &(av.qfer), av.isFieldVarOf_, true),
: Variable(av.name, av.type, av.init, &(av.qfer), av.field_var_of, true),
collective(av.collective),
parent(av.parent),
sizes(av.sizes),
Expand Down
6 changes: 3 additions & 3 deletions src/CGContext.cpp
Expand Up @@ -376,14 +376,14 @@ CGContext::read_indices(const Variable* v, const vector<const Fact*>& facts)
return false;
}
}
if (av->isFieldVarOf_) {
return read_indices(av->isFieldVarOf_, facts);
if (av->field_var_of) {
return read_indices(av->field_var_of, facts);
}
return true;
}
else if (v->is_array_field()) {
// find the parent that is an array
for (; v && !v->isArray; v = v->isFieldVarOf_) {
for (; v && !v->isArray; v = v->field_var_of) {
/* Empty. */
}
assert(v);
Expand Down
32 changes: 16 additions & 16 deletions src/Effect.cpp
Expand Up @@ -292,8 +292,8 @@ Effect::is_read(const Variable *v) const
// however we can not say the same thing for unions: reading a particular
// unions field can cause unspecified behaviors, while reading the whole
// union won't
if (v->isFieldVarOf_ && v->isFieldVarOf_->type->eType == eStruct) {
return is_read(v->isFieldVarOf_);
if (v->field_var_of && v->field_var_of->type->eType == eStruct) {
return is_read(v->field_var_of);
}
return false;
}
Expand Down Expand Up @@ -354,8 +354,8 @@ Effect::is_written(const Variable *v) const
}
}
// if we write a struct/union, presumingly all the fields are written too
if (v->isFieldVarOf_) {
return is_written(v->isFieldVarOf_);
if (v->field_var_of) {
return is_written(v->field_var_of);
}
return false;
}
Expand Down Expand Up @@ -440,37 +440,37 @@ Effect::field_is_written(const Variable *v) const
bool
Effect::sibling_union_field_is_read(const Variable *v) const
{
while (v->isFieldVarOf_) {
while (v->field_var_of) {
// check other fields of the union
if (v->isFieldVarOf_->type->eType == eUnion) {
for (size_t j=0; j<v->isFieldVarOf_->field_vars.size(); j++) {
Variable* field_var = v->isFieldVarOf_->field_vars[j];
if (v->field_var_of->type->eType == eUnion) {
for (size_t j=0; j<v->field_var_of->field_vars.size(); j++) {
Variable* field_var = v->field_var_of->field_vars[j];
if (field_var == v) continue;
if (is_read(field_var) || field_is_read(field_var)) {
return true;
}
}
}
v = v->isFieldVarOf_;
v = v->field_var_of;
}
return false;
}

bool
Effect::sibling_union_field_is_written(const Variable *v) const
{
while (v->isFieldVarOf_) {
while (v->field_var_of) {
// check other fields of the union
if (v->isFieldVarOf_->type->eType == eUnion) {
for (size_t j=0; j<v->isFieldVarOf_->field_vars.size(); j++) {
Variable* field_var = v->isFieldVarOf_->field_vars[j];
if (v->field_var_of->type->eType == eUnion) {
for (size_t j=0; j<v->field_var_of->field_vars.size(); j++) {
Variable* field_var = v->field_var_of->field_vars[j];
if (field_var == v) continue;
if (is_written(field_var) || field_is_written(field_var)) {
return true;
}
}
}
v = v->isFieldVarOf_;
v = v->field_var_of;
}
return false;
}
Expand All @@ -497,7 +497,7 @@ Effect::consolidate(void)
size_t len = read_vars.size();
for (i=0; i<len; i++) {
const Variable* tmp = read_vars[i];
if (tmp->is_field_var() && is_read(tmp->isFieldVarOf_)) {
if (tmp->is_field_var() && is_read(tmp->field_var_of)) {
read_vars.erase(read_vars.begin() + i);
i--;
len--;
Expand All @@ -506,7 +506,7 @@ Effect::consolidate(void)
len = write_vars.size();
for (i=0; i<len; i++) {
const Variable* tmp = write_vars[i];
if (tmp->is_field_var() && is_written(tmp->isFieldVarOf_)) {
if (tmp->is_field_var() && is_written(tmp->field_var_of)) {
write_vars.erase(write_vars.begin() + i);
i--;
len--;
Expand Down
6 changes: 2 additions & 4 deletions src/FactPointTo.cpp
Expand Up @@ -719,12 +719,10 @@ FactPointTo::update_with_modified_index(const Variable* index_var) const
size_t j, k;
vector<const Variable*> pointees = point_to_vars;
bool changed = false;
if (index_var->name == "p_4")
j = 0;
for (j=0; j<point_to_vars.size(); j++) {
const Variable* v = point_to_vars[j];
while (v->isFieldVarOf_) {
v = v->isFieldVarOf_;
while (v->field_var_of) {
v = v->field_var_of;
}
// if v is an itemized array variable, check it's indices
if (v->isArray && v->get_collective() != v) {
Expand Down
4 changes: 2 additions & 2 deletions src/FactUnion.cpp
Expand Up @@ -122,7 +122,7 @@ FactUnion::abstract_fact_for_assign(const std::vector<const Fact*>& facts, const
const Variable* v = lvars[i];
const FactUnion* fu = 0;
if (v->is_union_field()) {
fu = make_fact(v->isFieldVarOf_, v->get_field_id());
fu = make_fact(v->field_var_of, v->get_field_id());
}
if (fu) {
ret_facts.push_back(fu);
Expand Down Expand Up @@ -179,7 +179,7 @@ bool
FactUnion::is_nonreadable_field(const Variable *v, const std::vector<const Fact*>& facts)
{
if (v->is_union_field()) {
FactUnion tmp(v->isFieldVarOf_, v->get_field_id());
FactUnion tmp(v->field_var_of, v->get_field_id());
const FactUnion* fu = dynamic_cast<const FactUnion*>(find_related_fact(facts, &tmp));
if (fu && !tmp.imply(*fu)) {
return true;
Expand Down
84 changes: 52 additions & 32 deletions src/Variable.cpp
Expand Up @@ -191,8 +191,8 @@ void remove_field_vars(vector<const Variable*>& set)
for (i=0; i<len; i++) {
const Variable* v = set[i];
if (v->is_field_var()) {
while (v->isFieldVarOf_) {
v = v->isFieldVarOf_;
while (v->field_var_of) {
v = v->field_var_of;
}
set.erase(set.begin() + i);
add_variable_to_set(set, v);
Expand All @@ -204,7 +204,7 @@ void remove_field_vars(vector<const Variable*>& set)

/*
* examples: array[0] "loose matches" array[1]; array[3] "loose matches" array[x].f1...
* union.f1 "loose matches" union.f2
* union.f1 "loose matches" union.f2.f3
*/
bool
Variable::loose_match(const Variable* v) const
Expand All @@ -214,10 +214,12 @@ Variable::loose_match(const Variable* v) const
if (me->match(you)) {
return true;
}
if (me->isFieldVarOf_== you->isFieldVarOf_ && me->is_union_field()) {
return true;
}
return false;
// find the union variable(s) that contain me and you
for (me = me->field_var_of; me && me->type->eType != eUnion; me = me->field_var_of)
;
for (you = you->field_var_of; you && you->type->eType != eUnion; you = you->field_var_of)
;
return you && me && (you == me);
}

/*
Expand Down Expand Up @@ -246,8 +248,8 @@ Variable::get_seq_num(void) const
bool
Variable::is_array_field(void) const
{
if (isFieldVarOf_) {
return isFieldVarOf_->is_array_field();
if (field_var_of) {
return field_var_of->is_array_field();
}
return isArray;
}
Expand All @@ -258,8 +260,8 @@ Variable::is_array_field(void) const
bool
Variable::is_virtual(void) const
{
if (isFieldVarOf_) {
return isFieldVarOf_->is_virtual();
if (field_var_of) {
return field_var_of->is_virtual();
}
if (isArray) {
return ((const ArrayVariable*)this)->collective==0;
Expand All @@ -278,7 +280,7 @@ bool Variable::has_field_var(const Variable* v) const
if (tmp == this) {
return true;
}
tmp = tmp->isFieldVarOf_;
tmp = tmp->field_var_of;
}
}
return false;
Expand All @@ -287,9 +289,9 @@ bool Variable::has_field_var(const Variable* v) const
int
Variable::get_field_id(void) const
{
if (isFieldVarOf_) {
for (size_t i=0; i<isFieldVarOf_->field_vars.size(); i++) {
if (isFieldVarOf_->field_vars[i] == this) {
if (field_var_of) {
for (size_t i=0; i<field_var_of->field_vars.size(); i++) {
if (field_var_of->field_vars[i] == this) {
return i;
}
}
Expand Down Expand Up @@ -389,7 +391,7 @@ Variable::Variable(const std::string &name, const Type *type,
: name(name), type(type),
init(0),
isAuto(isAuto), isStatic(isStatic), isRegister(isRegister),
isBitfield_(isBitfield), isFieldVarOf_(isFieldVarOf), isArray(false),
isBitfield_(isBitfield), field_var_of(isFieldVarOf), isArray(false),
qfer(isConsts, isVolatiles)
{
// nothing else to do
Expand All @@ -401,7 +403,7 @@ Variable::Variable(const std::string &name, const Type *type,
Variable::Variable(const std::string &name, const Type *type, const Expression* init, const CVQualifiers* qfer)
: name(name), type(type),
init(init),
isAuto(false), isStatic(false), isRegister(false), isBitfield_(false), isFieldVarOf_(0), isArray(false),
isAuto(false), isStatic(false), isRegister(false), isBitfield_(false), field_var_of(0), isArray(false),
qfer(*qfer)
{
// nothing else to do
Expand All @@ -411,7 +413,7 @@ Variable::Variable(const std::string &name, const Type *type, const Expression*
: name(name), type(type),
init(init),
isAuto(false), isStatic(false), isRegister(false), isBitfield_(false),
isFieldVarOf_(isFieldVarOf),
field_var_of(isFieldVarOf),
isArray(isArray),
qfer(*qfer)
{
Expand Down Expand Up @@ -439,7 +441,7 @@ bool
Variable::is_global(void) const
{
if (is_field_var()) {
return isFieldVarOf_->is_global();
return field_var_of->is_global();
}
return (name.find("g_") == 0);
}
Expand All @@ -452,7 +454,7 @@ Variable::is_visible_local(const Block* blk) const
return is_global();
}
if (is_field_var()) {
return isFieldVarOf_->is_visible_local(blk);
return field_var_of->is_visible_local(blk);
}
size_t i;
const Function* func = blk->func;
Expand Down Expand Up @@ -615,8 +617,8 @@ Variable::deputy_annotation(void) const
anno = oss.str();
}
//if (pointee->is_array_field()) {
// while (pointee->isFieldVarOf_) {
// pointee = pointee->isFieldVarOf_;
// while (pointee->field_var_of) {
// pointee = pointee->field_var_of;
// }
// assert(pointee->isArray);
//}
Expand Down Expand Up @@ -658,8 +660,8 @@ Variable::get_collective(void) const
// special handling for array fields
if (is_array_field()) {
// find top-level parent, which should be an array
const Variable* parent = isFieldVarOf_;
for (; parent && !parent->isArray; parent = parent->isFieldVarOf_) {
const Variable* parent = field_var_of;
for (; parent && !parent->isArray; parent = parent->field_var_of) {
/* Empty. */
}
assert(parent);
Expand Down Expand Up @@ -691,8 +693,8 @@ const Variable*
Variable::get_named_var(void) const
{
const Variable* v = this;
while (v->isFieldVarOf_) {
v = v->isFieldVarOf_;
while (v->field_var_of) {
v = v->field_var_of;
}
return v->get_collective();
}
Expand All @@ -703,8 +705,8 @@ Variable::get_array(string& field) const
// special handling for array fields
if (is_array_field()) {
// find top-level parent, which should be an array
const Variable* parent = isFieldVarOf_;
for (; parent && !parent->isArray; parent = parent->isFieldVarOf_) {
const Variable* parent = field_var_of;
for (; parent && !parent->isArray; parent = parent->field_var_of) {
/* Empty. */
}
assert(parent);
Expand Down Expand Up @@ -811,8 +813,8 @@ Variable::output_qualified_type(std::ostream &out) const
void
Variable::OutputUpperBound(std::ostream &out) const
{
if (isFieldVarOf_) {
isFieldVarOf_->OutputUpperBound(out);
if (field_var_of) {
field_var_of->OutputUpperBound(out);
size_t dot = name.find_last_of(".");
assert(dot != string::npos);
string postfix = name.substr(dot, string::npos);
Expand All @@ -827,8 +829,8 @@ Variable::OutputUpperBound(std::ostream &out) const
void
Variable::OutputLowerBound(std::ostream &out) const
{
if (isFieldVarOf_) {
isFieldVarOf_->OutputLowerBound(out);
if (field_var_of) {
field_var_of->OutputLowerBound(out);
size_t dot = name.find_last_of(".");
assert(dot != string::npos);
string postfix = name.substr(dot, string::npos);
Expand Down Expand Up @@ -1305,6 +1307,24 @@ Variable::match_var_name(const string& vname) const
return NULL;
}

/* order fields inside a struct/union variable */
int
Variable::compare_field(const Variable* v) const
{
if (is_field_var() && v->is_field_var()) {
const Variable* my_base = NULL;
const Variable* your_base = NULL;
for (my_base = this->field_var_of; my_base->field_var_of; my_base = my_base->field_var_of)
;
for (your_base = v->field_var_of; your_base->field_var_of; your_base = your_base->field_var_of)
;
if (my_base == your_base) {
return name.compare(v->name);
}
}
return 0;
}

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

// Local Variables:
Expand Down
7 changes: 4 additions & 3 deletions src/Variable.h
Expand Up @@ -87,16 +87,17 @@ class Variable
bool is_const_after_deref(int deref_level) const;
bool is_volatile_after_deref(int deref_level) const;
bool has_field_var(const Variable* v) const;
bool is_field_var(void) const { return isFieldVarOf_ != 0; };
bool is_field_var(void) const { return field_var_of != 0; };
int get_field_id(void) const;
bool is_union_field(void) const { return isFieldVarOf_ != 0 && isFieldVarOf_->type->eType == eUnion; };
bool is_union_field(void) const { return field_var_of != 0 && field_var_of->type->eType == eUnion; };
bool is_array_field(void) const;
bool is_virtual(void) const;
bool is_aggregate(void) const { return type && type->is_aggregate(); }
bool match(const Variable* v) const;
bool loose_match(const Variable* v) const;
bool is_pointer(void) const { return type && type->eType == ePointer;}
bool is_rv(void) const { return StringUtils::end_with(name, "_rv"); }
int compare_field(const Variable* v) const;
int get_seq_num(void) const;

virtual std::string get_actual_name() const;
Expand Down Expand Up @@ -144,7 +145,7 @@ class Variable
const bool isStatic;
const bool isRegister;
const bool isBitfield_; // expanded from a full-bitfield struct var
const Variable* isFieldVarOf_; //expanded from a struct/union
const Variable* field_var_of; //expanded from a struct/union
const bool isArray;
const CVQualifiers qfer;
static std::vector<const Variable*> ctrl_vars;
Expand Down

0 comments on commit c3fe5ff

Please sign in to comment.