Skip to content

Commit

Permalink
Support Unions in random programs to the extend Structs were supported
Browse files Browse the repository at this point in the history
Note the unspecified behavior: writing to one field of an union, then reading the value of another field, is not avoided currently. They are supposed to be handled by an updated generation time analyzer that I will check in soon.
  • Loading branch information
Xuejun Yang committed Jun 10, 2011
1 parent a776365 commit e7e4945
Show file tree
Hide file tree
Showing 30 changed files with 384 additions and 358 deletions.
18 changes: 9 additions & 9 deletions src/ArrayVariable.cpp
Expand Up @@ -157,7 +157,7 @@ ArrayVariable::CreateArrayVariable(Block* blk, const std::string &name, const Ty
}
ArrayVariable *var = new ArrayVariable(blk, name, type, init, qfer, sizes, isFieldVarOf);
ERROR_GUARD_AND_DEL1(NULL, var);
if (type->eType == eStruct) {
if (type->is_aggregate()) {
var->create_field_vars(type);
}
// create a list of alternative initial values. now only support integer arrays
Expand Down Expand Up @@ -257,8 +257,8 @@ ArrayVariable::itemize(void) const
av->add_index(new Constant(get_int_type(), StringUtils::int2str(index)));
}
av->collective = this;
// only expand struct for itemized array variable
if (type->eType == eStruct) {
// only expand struct/union for itemized array variable
if (type->is_aggregate()) {
av->create_field_vars(type);
}
return av;
Expand All @@ -277,8 +277,8 @@ ArrayVariable::itemize(const vector<int>& const_indices) const
av->add_index(new Constant(get_int_type(), StringUtils::int2str(index)));
}
av->collective = this;
// only expand struct for itemized array variable
if (type->eType == eStruct) {
// only expand struct/union for itemized array variable
if (type->is_aggregate()) {
av->create_field_vars(type);
}
return av;
Expand All @@ -296,8 +296,8 @@ ArrayVariable::itemize(const std::vector<const Variable*>& indices, Block* blk)
}
av->collective = this;
av->parent = blk;
// only expand struct for itemized array variable
if (type->eType == eStruct) {
// only expand struct/union for itemized array variable
if (type->is_aggregate()) {
av->create_field_vars(type);
}
blk->local_vars.push_back(av);
Expand All @@ -316,8 +316,8 @@ ArrayVariable::itemize(const std::vector<const Expression*>& indices, Block* blk
}
av->collective = this;
av->parent = blk;
// only expand struct for itemized array variable
if (type->eType == eStruct) {
// only expand struct/union for itemized array variable
if (type->is_aggregate()) {
av->create_field_vars(type);
}
blk->local_vars.push_back(av);
Expand Down
7 changes: 3 additions & 4 deletions src/Bookkeeper.cpp
Expand Up @@ -382,7 +382,7 @@ Bookkeeper::record_vars_with_bitfields(const Type *type)
{
assert(type);
const Type *base_type = type->get_base_type();
if ((base_type->eType != eStruct) ||
if (!base_type->is_aggregate() ||
(!base_type->has_bitfields()))
return;

Expand All @@ -393,10 +393,9 @@ Bookkeeper::record_vars_with_bitfields(const Type *type)
}

void
Bookkeeper::record_bitfields_structs(const Type *typ)
Bookkeeper::record_type_with_bitfields(const Type *typ)
{
if (typ->eType != eStruct)
return;
if (!typ->is_aggregate()) return;

if (typ->has_bitfields()) {
Bookkeeper::structs_with_bitfields++;
Expand Down
2 changes: 1 addition & 1 deletion src/Bookkeeper.h
Expand Up @@ -73,7 +73,7 @@ class Bookkeeper

static void record_volatile_access(const Variable* var, int deref_level, bool write);

static void record_bitfields_structs(const Type* typ);
static void record_type_with_bitfields(const Type* typ);

static void record_vars_with_bitfields(const Type *type);

Expand Down
2 changes: 1 addition & 1 deletion src/CGContext.cpp
Expand Up @@ -541,7 +541,7 @@ CGContext::allow_const(Effect::Access access) const
bool
CGContext::accept_type(const Type* t) const
{
return get_effect_context().is_side_effect_free() || !t->is_volatile_struct();
return get_effect_context().is_side_effect_free() || !t->is_volatile_struct_union();
}

/* return true if an incoming effect is in conflict with current context */
Expand Down
8 changes: 8 additions & 0 deletions src/CGOptions.cpp
Expand Up @@ -83,11 +83,13 @@ DEFINE_GETTER_SETTER_BOOL(wrap_volatiles)
DEFINE_GETTER_SETTER_BOOL(allow_const_volatile)
DEFINE_GETTER_SETTER_BOOL(avoid_signed_overflow)
DEFINE_GETTER_SETTER_INT (max_struct_fields)
DEFINE_GETTER_SETTER_INT (max_union_fields)
DEFINE_GETTER_SETTER_INT (max_nested_struct_level)
DEFINE_GETTER_SETTER_STRING_REF(struct_output)
DEFINE_GETTER_SETTER_BOOL (fixed_struct_fields)
DEFINE_GETTER_SETTER_BOOL (expand_struct)
DEFINE_GETTER_SETTER_BOOL (use_struct)
DEFINE_GETTER_SETTER_BOOL (use_union)
DEFINE_GETTER_SETTER_INT (max_indirect_level)
DEFINE_GETTER_SETTER_INT (max_array_dimensions)
DEFINE_GETTER_SETTER_INT (max_array_length_per_dimension)
Expand Down Expand Up @@ -131,6 +133,8 @@ DEFINE_GETTER_SETTER_BOOL(strict_const_arrays)
DEFINE_GETTER_SETTER_BOOL(jumps)
DEFINE_GETTER_SETTER_BOOL(return_structs)
DEFINE_GETTER_SETTER_BOOL(arg_structs)
DEFINE_GETTER_SETTER_BOOL(return_unions)
DEFINE_GETTER_SETTER_BOOL(arg_unions)
DEFINE_GETTER_SETTER_BOOL(volatiles)
DEFINE_GETTER_SETTER_BOOL(volatile_pointers)
DEFINE_GETTER_SETTER_BOOL(enable_vol_tests)
Expand Down Expand Up @@ -168,6 +172,7 @@ CGOptions::set_default_settings(void)
max_stmt_depth(CGOPTIONS_DEFAULT_MAX_STMT_DEPTH);
max_expr_depth(CGOPTIONS_DEFAULT_MAX_EXPR_DEPTH);
max_struct_fields(CGOPTIONS_DEFAULT_MAX_STRUCT_FIELDS);
max_union_fields(CGOPTIONS_DEFAULT_MAX_UNION_FIELDS);
max_nested_struct_level(CGOPTIONS_DEFAULT_MAX_NESTED_STRUCT_LEVEL);
fixed_struct_fields(false);
expand_struct(false);
Expand All @@ -186,6 +191,7 @@ CGOptions::set_default_settings(void)
CGOptions::nomain(false);
random_based(true);
use_struct(true);
use_union(true);
compact_output(false);
msp(false);
func1_max_params(CGOPTIONS_DEFAULT_FUNC1_MAX_PARAMS);
Expand All @@ -210,6 +216,8 @@ CGOptions::set_default_settings(void)
jumps(true);
return_structs(true);
arg_structs(true);
return_unions(true);
arg_unions(true);
volatiles(true);
volatile_pointers(true);
vol_addr_file(CGOPTIONS_DEFAULT_VOL_ADDR_FILE);
Expand Down
17 changes: 17 additions & 0 deletions src/CGOptions.h
Expand Up @@ -50,6 +50,7 @@ using namespace std;
#define CGOPTIONS_DEFAULT_MAX_STMT_DEPTH (5)
#define CGOPTIONS_DEFAULT_MAX_EXPR_DEPTH (5)
#define CGOPTIONS_DEFAULT_MAX_STRUCT_FIELDS (10)
#define CGOPTIONS_DEFAULT_MAX_UNION_FIELDS (5)
#define CGOPTIONS_DEFAULT_MAX_NESTED_STRUCT_LEVEL (0)
#define CGOPTIONS_DEFAULT_MAX_INDIRECT_LEVEL (2)
#define CGOPTIONS_DEFAULT_MAX_ARRAY_DIMENSIONS (3)
Expand Down Expand Up @@ -110,6 +111,9 @@ class CGOptions {
static int max_struct_fields();
static int max_struct_fields(int p);

static int max_union_fields();
static int max_union_fields(int p);

static int max_nested_struct_level();
static int max_nested_struct_level(int p);

Expand All @@ -125,6 +129,9 @@ class CGOptions {
static bool use_struct();
static bool use_struct(bool p);

static bool use_union();
static bool use_union(bool p);

static int max_indirect_level();
static int max_indirect_level(int p);

Expand Down Expand Up @@ -254,9 +261,15 @@ class CGOptions {
static bool return_structs(void);
static bool return_structs(bool p);

static bool return_unions(void);
static bool return_unions(bool p);

static bool arg_structs(void);
static bool arg_structs(bool p);

static bool arg_unions(void);
static bool arg_unions(bool p);

static bool volatiles(void);
static bool volatiles(bool p);

Expand Down Expand Up @@ -380,11 +393,13 @@ class CGOptions {
static bool allow_const_volatile_;
static bool avoid_signed_overflow_;
static int max_struct_fields_;
static int max_union_fields_;
static int max_nested_struct_level_;
static std::string struct_output_;
static bool fixed_struct_fields_;
static bool expand_struct_;
static bool use_struct_;
static bool use_union_;
static int max_indirect_level_;
static int max_array_dimensions_;
static int max_array_length_per_dimension_;
Expand Down Expand Up @@ -433,6 +448,8 @@ class CGOptions {
static bool jumps_;
static bool return_structs_;
static bool arg_structs_;
static bool return_unions_;
static bool arg_unions_;
static bool volatiles_;
static bool volatile_pointers_;
static bool enable_vol_tests_;
Expand Down
2 changes: 1 addition & 1 deletion src/CVQualifiers.cpp
Expand Up @@ -347,7 +347,7 @@ CVQualifiers::random_qualifiers(const Type* t)

/*
* be careful to use it because it will generate volatile without knowing the context.
* Only used to generate qulifiers for structs
* Only used to generate qulifiers for struct/unions
*/
CVQualifiers
CVQualifiers::random_qualifiers(const Type* t, unsigned int const_prob, unsigned int volatile_prob)
Expand Down
20 changes: 19 additions & 1 deletion src/Constant.cpp
Expand Up @@ -230,6 +230,20 @@ GenerateRandomStructConstant(const Type* type)
return value;
}

// --------------------------------------------------------------
/* generate an union initializer: unlike struct, initializing
the first field is enough
*************************************************************/
static string
GenerateRandomUnionConstant(const Type* type)
{
string value = "{";
assert(type->eType == eUnion && type->fields.size() == type->bitfields_length_.size());
value += GenerateRandomConstant(type->fields[0]);
value += "}";
return value;
}

static string
GenerateRandomConstant(const Type* type)
{
Expand All @@ -239,7 +253,11 @@ GenerateRandomConstant(const Type* type)
}
else if (type->eType == eStruct) {
v = GenerateRandomStructConstant(type);
ERROR_GUARD("");
ERROR_GUARD("");
}
else if (type->eType == eUnion) {
v = GenerateRandomUnionConstant(type);
ERROR_GUARD("");
}
// the only possible constant for a pointer is "0"
else if (type->eType == ePointer) {
Expand Down
4 changes: 2 additions & 2 deletions src/DFSOutputMgr.cpp
Expand Up @@ -75,10 +75,10 @@ DFSOutputMgr::OutputHeader(int argc, char *argv[], unsigned long seed)
}

void
DFSOutputMgr::OutputStructs(ostream& /*out*/)
DFSOutputMgr::OutputStructUnions(ostream& /*out*/)
{
ofstream o_struct(struct_output_.c_str());
OutputStructDeclarations(o_struct);
OutputStructUnionDeclarations(o_struct);
o_struct.close();
}

Expand Down
2 changes: 1 addition & 1 deletion src/DFSOutputMgr.h
Expand Up @@ -42,7 +42,7 @@ class DFSOutputMgr : public OutputMgr {

virtual void OutputHeader(int argc, char *argv[], unsigned long seed);

virtual void OutputStructs(ostream& /*out*/);
virtual void OutputStructUnions(ostream& /*out*/);

virtual void Output();

Expand Down
2 changes: 1 addition & 1 deletion src/DFSProgramGenerator.cpp
Expand Up @@ -83,7 +83,7 @@ DFSProgramGenerator::goGenerator()
dynamic_cast<DFSRndNumGenerator*>(RandomNumber::GetRndNumGenerator());
//unsigned long long count = 0;
GenerateAllTypes();
output_mgr_->OutputStructs(cout);
output_mgr_->OutputStructUnions(cout);
while(!impl->get_all_done()) {
Error::set_error(SUCCESS);
GenerateFunctions();
Expand Down
4 changes: 2 additions & 2 deletions src/DefaultOutputMgr.cpp
Expand Up @@ -121,7 +121,7 @@ DefaultOutputMgr::OutputGlobals()
string prefix = "extern ";
OutputGlobalVariablesDecls(ofile, prefix);

OutputStructDeclarations(ofile);
OutputStructUnionDeclarations(ofile);
ofile << "#endif" << std::endl;
ofile.close();
}
Expand Down Expand Up @@ -204,7 +204,7 @@ DefaultOutputMgr::Output()
RandomOutputDefs();
}
else {
OutputStructDeclarations(out);
OutputStructUnionDeclarations(out);
OutputGlobalVariables(out);
OutputForwardDeclarations(out);
OutputFunctions(out);
Expand Down
24 changes: 6 additions & 18 deletions src/Effect.cpp
Expand Up @@ -129,12 +129,6 @@ Effect::read_var(const Variable *v)
{
if (!is_read(v)) {
read_vars.push_back(v);
//if (v->type->eType == eStruct) {
// for (size_t i=0; i<v->field_vars.size(); i++) {
// read_var(v->field_vars[i]);
// }
// //read_vars.insert(read_vars.end(), v->field_vars.begin(), v->field_vars.end());
//}
}
pure &= (v->is_const() && !v->is_volatile());
side_effect_free &= !v->is_volatile();
Expand All @@ -148,12 +142,6 @@ Effect::write_var(const Variable *v)
{
if (!is_written(v)) {
write_vars.push_back(v);
//if (v->type->eType == eStruct) {
// for (size_t i=0; i<v->field_vars.size(); i++) {
// write_var(v->field_vars[i]);
// }
// //write_vars.insert(write_vars.end(), v->field_vars.begin(), v->field_vars.end());
//}
}
// pure = pure;
// TODO: not quite correct below ---
Expand Down Expand Up @@ -300,7 +288,7 @@ Effect::is_read(const Variable *v) const
return true;
}
}
// if we read a struct, presumingly all the fields are read too
// if we read a struct/union, presumingly all the fields are read too
if (v->isFieldVarOf_) {
return is_read(v->isFieldVarOf_);
}
Expand Down Expand Up @@ -362,7 +350,7 @@ Effect::is_written(const Variable *v) const
return true;
}
}
// if we write a struct, presumingly all the fields are written too
// if we write a struct/union, presumingly all the fields are written too
if (v->isFieldVarOf_) {
return is_written(v->isFieldVarOf_);
}
Expand Down Expand Up @@ -411,13 +399,13 @@ Effect::is_written(string vname) const
}

/*
* whether any field of a struct is been read
* whether any field of a struct/union is been read
*/
bool
Effect::field_is_read(const Variable *v) const
{
size_t j;
if (v->type->eType == eStruct) {
if (v->is_aggregate()) {
for (j=0; j<v->field_vars.size(); j++) {
Variable* field_var = v->field_vars[j];
if (is_read(field_var) || field_is_read(field_var)) {
Expand All @@ -429,13 +417,13 @@ Effect::field_is_read(const Variable *v) const
}

/*
* whether any field of a struct is been written
* whether any field of a struct/union is been written
*/
bool
Effect::field_is_written(const Variable *v) const
{
size_t j;
if (v->type->eType == eStruct) {
if (v->is_aggregate()) {
for (j=0; j<v->field_vars.size(); j++) {
Variable* field_var = v->field_vars[j];
if (is_written(field_var) || field_is_written(field_var)) {
Expand Down

0 comments on commit e7e4945

Please sign in to comment.