Skip to content

Commit

Permalink
expose more generation controls to command lines
Browse files Browse the repository at this point in the history
1) add the following command line options to disable/enable side effecting expressions:

  --incr-decr-operators
  --no-incr-decr-operators
  --embedded-assigns
  --no-embedded-assigns
  --comma-operators
  --no-comma-operators

2) add "--max-struct-nested-level" to command line options. And enforce the default limit at 3, i.e. struct in struct in struct.

3) add "more_struct_union_type_prob" to Probabilities. (a finer way to config Csmith through --probability-configuration <file>). Also slightly decrease the chance of having struct/union types in random programs.

4) Add a class DistributionTable to represent more flexible distribution of probabilities than ProbabilityTable in that the sum of individual distributions doesn't have to be 100. With this class we disable/enable entries in the table without painful re-calibration of numbers.
  • Loading branch information
Xuejun Yang committed Aug 8, 2011
1 parent bc564f0 commit a139329
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 63 deletions.
6 changes: 5 additions & 1 deletion src/CGOptions.cpp
Expand Up @@ -165,6 +165,8 @@ DEFINE_GETTER_SETTER_INT(null_pointer_dereference_prob)
DEFINE_GETTER_SETTER_INT(dead_pointer_dereference_prob)
DEFINE_GETTER_SETTER_BOOL(union_read_type_sensitive);
DEFINE_GETTER_SETTER_BOOL(use_incr_decr_opers);
DEFINE_GETTER_SETTER_BOOL(use_embedded_assigns);
DEFINE_GETTER_SETTER_BOOL(use_comma_exprs);
DEFINE_GETTER_SETTER_INT(int_bytes);
DEFINE_GETTER_SETTER_INT(pointer_bytes);

Expand Down Expand Up @@ -250,8 +252,10 @@ CGOptions::set_default_settings(void)
dead_pointer_dereference_prob(0);
union_read_type_sensitive(true);
use_incr_decr_opers(true);
use_embedded_assigns(true);
use_comma_exprs(true);
// these are defaults for x86-64 machine, our most used platform.
// configure them to generate random programs for other platforms.
// configure them to generate *correct* random programs for other platforms.
int_bytes(4);
pointer_bytes(8);
}
Expand Down
10 changes: 9 additions & 1 deletion src/CGOptions.h
Expand Up @@ -51,7 +51,7 @@ using namespace std;
#define CGOPTIONS_DEFAULT_MAX_EXPR_DEPTH (10)
#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_NESTED_STRUCT_LEVEL (3)
#define CGOPTIONS_DEFAULT_MAX_INDIRECT_LEVEL (2)
#define CGOPTIONS_DEFAULT_MAX_ARRAY_DIMENSIONS (3)
#define CGOPTIONS_DEFAULT_MAX_ARRAY_LENGTH_PER_DIMENSION (10)
Expand Down Expand Up @@ -384,6 +384,12 @@ class CGOptions {
static bool use_incr_decr_opers(void);
static bool use_incr_decr_opers(bool p);

static bool use_embedded_assigns(void);
static bool use_embedded_assigns(bool p);

static bool use_comma_exprs(void);
static bool use_comma_exprs(bool p);

static int int_bytes(void);
static int int_bytes(int p);

Expand Down Expand Up @@ -502,6 +508,8 @@ class CGOptions {
// flag that indicate the comformance level to C99. true means relaxed
static bool union_read_type_sensitive_;
static bool use_incr_decr_opers_;
static bool use_embedded_assigns_;
static bool use_comma_exprs_;
static int int_bytes_;
static int pointer_bytes_;
static Reducer* reducer_;
Expand Down
43 changes: 25 additions & 18 deletions src/Expression.cpp
Expand Up @@ -60,29 +60,36 @@

int eid = 0;

ProbabilityTable<unsigned int, int> *Expression::exprTable_ = NULL;
DistributionTable Expression::exprTable_;
DistributionTable Expression::paramTable_;

void
Expression::InitExprProbabilityTable()
{
Expression::exprTable_ = new ProbabilityTable<unsigned int, int>();
Expression::exprTable_->add_elem(40, (int)eFunction);
Expression::exprTable_->add_elem(50, (int)eAssignment);
Expression::exprTable_->add_elem(60, (int)eCommaExpr);
Expression::exprTable_->add_elem(70, (int)eConstant);
Expression::exprTable_->add_elem(100, (int)eVariable);
{
exprTable_.add_entry((int)eFunction, 70);
exprTable_.add_entry((int)eVariable, 20);
exprTable_.add_entry((int)eConstant, 10);
if (CGOptions::use_embedded_assigns()) {
exprTable_.add_entry((int)eAssignment, 10);
}
if (CGOptions::use_comma_exprs()) {
exprTable_.add_entry((int)eCommaExpr, 10);
}
}

ProbabilityTable<unsigned int, int> *Expression::paramTable_ = NULL;
void
Expression::InitParamProbabilityTable()
{
Expression::paramTable_ = new ProbabilityTable<unsigned int, int>();
Expression::paramTable_->add_elem(30, (int)eFunction);
Expression::paramTable_->add_elem(40, (int)eConstant);
Expression::paramTable_->add_elem(50, (int)eAssignment);
Expression::paramTable_->add_elem(60, (int)eCommaExpr);
Expression::paramTable_->add_elem(100, (int)eVariable);
paramTable_.add_entry((int)eFunction, 40);
paramTable_.add_entry((int)eVariable, 40);
// constant parameters lead to non-interesting code
paramTable_.add_entry((int)eConstant, 0);
if (CGOptions::use_embedded_assigns()) {
paramTable_.add_entry((int)eAssignment, 10);
}
if (CGOptions::use_comma_exprs()) {
paramTable_.add_entry((int)eCommaExpr, 10);
}
}

void
Expand All @@ -105,7 +112,7 @@ ExpressionTypeProbability(const VectorFilter *filter)

assert(filter);

int i = rnd_upto(100, filter);
int i = rnd_upto(filter->get_max_prob(), filter);
ERROR_GUARD(MAX_TERM_TYPES);
return (eTermType)(filter->lookup(i));
}
Expand Down Expand Up @@ -161,7 +168,7 @@ Expression::make_random(CGContext &cg_context, const Type* type, const CVQualifi

// if no term type is provided, choose a random term type with restrictions
if (tt == MAX_TERM_TYPES) {
VectorFilter filter(Expression::exprTable_);
VectorFilter filter(&Expression::exprTable_);
if (no_func ||
(!CGOptions::return_structs() && type->eType == eStruct) ||
(!CGOptions::return_unions() && type->eType == eUnion)) {
Expand Down Expand Up @@ -230,7 +237,7 @@ Expression::make_random_param(CGContext &cg_context, const Type* type, const CVQ
assert(type);
// if a term type is provided, no need to choose random term type
if (tt == MAX_TERM_TYPES) {
VectorFilter filter(Expression::paramTable_);
VectorFilter filter(&Expression::paramTable_);
filter.add(eConstant); // don't call functions with constant parameters because it is not interesting
if ((!CGOptions::return_structs() && type->eType == eStruct) ||
(!CGOptions::return_unions() && type->eType == eUnion)) {
Expand Down
5 changes: 3 additions & 2 deletions src/Expression.h
Expand Up @@ -44,6 +44,7 @@
#include <ostream>
#include "CGContext.h"
#include "CVQualifiers.h"
#include "ProbabilityTable.h"
#include <vector>
#include <string>
using namespace std;
Expand Down Expand Up @@ -154,8 +155,8 @@ class Expression
static void InitExprProbabilityTable();
static void InitParamProbabilityTable();

static ProbabilityTable<unsigned int, int> *exprTable_;
static ProbabilityTable<unsigned int, int> *paramTable_;
static DistributionTable exprTable_;
static DistributionTable paramTable_;
};

///////////////////////////////////////////////////////////////////////////////
Expand Down
36 changes: 36 additions & 0 deletions src/Probabilities.cpp
Expand Up @@ -409,6 +409,9 @@ void
Probabilities::set_single_name_maps()
{
// for single probs
// for generating more struct or union types
set_single_name("more_struct_union_type_prob", pMoreStructUnionProb);

set_single_name("bitfields_creation_prob", pBitFieldsCreationProb);

// for single bitfield in a normal struct
Expand Down Expand Up @@ -512,6 +515,7 @@ void
Probabilities::initialize_single_probs()
{
std::map<ProbName, int> m;
m[pMoreStructUnionProb] = 50;
m[pBitFieldsCreationProb] = 50;
m[pBitFieldInNormalStructProb] = 10;
m[pScalarFieldInFullBitFieldsProb] = 10;
Expand Down Expand Up @@ -1033,3 +1037,35 @@ Probabilities::~Probabilities()
clear_filter(extra_filters_);
}

void DistributionTable::add_entry(int key, int prob)
{
keys_.push_back(key);
probs_.push_back(prob);
max_prob_ += prob;
}

int DistributionTable::key_to_prob(int key) const
{
for (size_t i=0; i<keys_.size(); i++) {
if (keys_[i] == key) {
return probs_[i];
}
}
// 0 probablility for keys not found
return 0;
}

int DistributionTable::rnd_num_to_key(int rnd) const
{
assert(rnd < max_prob_ && rnd >= 0);
assert(keys_.size() == probs_.size());
for (size_t i=0; i<probs_.size(); i++) {
if (rnd < probs_[i]) {
return keys_[i];
}
rnd -= probs_[i];
}
assert(0);
return -1;
}

6 changes: 5 additions & 1 deletion src/Probabilities.h
Expand Up @@ -41,7 +41,8 @@ class ProbabilityTable;

using namespace std;
enum ProbName {
pBitFieldsCreationProb = 0,
pMoreStructUnionProb,
pBitFieldsCreationProb,
pBitFieldsSignedProb,
pBitFieldInNormalStructProb,
pScalarFieldInFullBitFieldsProb,
Expand Down Expand Up @@ -138,6 +139,9 @@ enum ProbName {

#define MAX_PROB_NAME ((ProbName)(pStatementProb+1))

#define MoreStructUnionTypeProb \
Probabilities::get_prob(pMoreStructUnionProb)

#define BitFieldsCreationProb \
Probabilities::get_prob(pBitFieldsCreationProb)

Expand Down
15 changes: 15 additions & 0 deletions src/ProbabilityTable.h
Expand Up @@ -173,4 +173,19 @@ ProbabilityTable<Key, Value>::get_value(Key k)
return (*i)->get_value();
}

class DistributionTable {
public:
DistributionTable() { max_prob_ = 0;}
~DistributionTable() {};

void add_entry(int key, int prob);
int get_max(void) const { return max_prob_;}
int key_to_prob(int key) const;
int rnd_num_to_key(int rnd) const;
private:
int max_prob_;
vector<int> keys_;
vector<int> probs_;
};

#endif
47 changes: 46 additions & 1 deletion src/RandomProgramGenerator.cpp
Expand Up @@ -168,7 +168,10 @@ static void print_help()
cout << " --packed-struct | --no-packed-struct: enable | disable packed structs by adding #pragma pack(1) before struct definition (disabled by default)." << endl << endl;
cout << " --bitfields | --no-bitfields: enable | disable full-bitfields structs (disabled by default)." << endl << endl;
cout << " --argc | --no-argc: genereate main function with/without argv and argc being passed (enabled by default)." << endl << endl;

cout << " --incr-decr-operators | --no-incr-decr-operators: enable | disable ++/-- operators (enabled by default)." << endl << endl;
cout << " --embedded-assigns | --no-embedded-assigns: enable | disable embedded assignments as sub-expressions (enabled by default)." << endl << endl;
cout << " --comma-operators | --no-comma-operators: enable | disable comma operators (enabled by default)." << endl << endl;

// numbered controls
cout << " --max-block-size <size>: limit the number of non-return statements in a block to <size> (default 4)." << endl << endl;
cout << " --max-funcs <num>: limit the number of functions (besides main) to <num> (default 10)." << endl << endl;
Expand Down Expand Up @@ -295,6 +298,8 @@ static void print_advanced_help()

cout << " --union-read-type-sensitive | --no-union-read-type-sensitive: allow | disallow reading an union field when there is no risk of "
<< "reading padding bits (enabled by default)." << endl << endl;

cout << " --max-struct-nested-level: controls the max depth of nested structs (default is 3)." << endl << endl;
}

void arg_check(int argc, int i)
Expand Down Expand Up @@ -1094,6 +1099,16 @@ main(int argc, char **argv)
continue;
}

if (strcmp (argv[i], "--max-struct-nested-level") ==0 ) {
unsigned long depth;
i++;
arg_check(argc, i);
if (!parse_int_arg(argv[i], &depth))
exit(-1);
CGOptions::max_nested_struct_level(depth);
continue;
}

if (strcmp (argv[i], "--union-read-type-sensitive") == 0) {
CGOptions::union_read_type_sensitive(true);
continue;
Expand All @@ -1104,6 +1119,36 @@ main(int argc, char **argv)
continue;
}

if (strcmp (argv[i], "--incr-decr-operators") == 0) {
CGOptions::use_incr_decr_opers(true);
continue;
}

if (strcmp (argv[i], "--no-incr-decr-operators") == 0) {
CGOptions::use_incr_decr_opers(false);
continue;
}

if (strcmp (argv[i], "--embedded-assigns") == 0) {
CGOptions::use_embedded_assigns(true);
continue;
}

if (strcmp (argv[i], "--no-embedded-assigns") == 0) {
CGOptions::use_embedded_assigns(false);
continue;
}

if (strcmp (argv[i], "--comma-operators") == 0) {
CGOptions::use_comma_exprs(true);
continue;
}

if (strcmp (argv[i], "--no-comma-operators") == 0) {
CGOptions::use_comma_exprs(false);
continue;
}

if (strcmp (argv[i], "--reduce") == 0) {
string filename;
i++;
Expand Down
33 changes: 13 additions & 20 deletions src/StatementAssign.cpp
Expand Up @@ -61,28 +61,21 @@ using namespace std;
//
// use a table to define probabilities of different kinds of statements
// Must initialize it before use
ProbabilityTable<unsigned int, int> *StatementAssign::assignOpsTable_ = NULL;
DistributionTable StatementAssign::assignOpsTable_;

void
StatementAssign::InitProbabilityTable()
{
assignOpsTable_ = new ProbabilityTable<unsigned int, int>();
if (CGOptions::use_incr_decr_opers()) {
assignOpsTable_->add_elem(60, (int)eSimpleAssign);
assignOpsTable_->add_elem(70, (int)eBitAndAssign);
assignOpsTable_->add_elem(79, (int)eBitXorAssign);
assignOpsTable_->add_elem(88, (int)eBitOrAssign);
assignOpsTable_->add_elem(91, (int)ePreIncr);
assignOpsTable_->add_elem(94, (int)ePreDecr);
assignOpsTable_->add_elem(97, (int)ePostIncr);
assignOpsTable_->add_elem(100, (int)ePostDecr);
{
assignOpsTable_.add_entry((int)eSimpleAssign, 70);
assignOpsTable_.add_entry((int)eBitAndAssign, 10);
assignOpsTable_.add_entry((int)eBitXorAssign, 10);
assignOpsTable_.add_entry((int)eBitOrAssign, 10);
if (CGOptions::use_incr_decr_opers()) {
assignOpsTable_.add_entry((int)ePreIncr, 5);
assignOpsTable_.add_entry((int)ePreDecr, 5);
assignOpsTable_.add_entry((int)ePostIncr, 5);
assignOpsTable_.add_entry((int)ePostDecr, 5);
}
else {
assignOpsTable_->add_elem(70, (int)eSimpleAssign);
assignOpsTable_->add_elem(80, (int)eBitAndAssign);
assignOpsTable_->add_elem(90, (int)eBitXorAssign);
assignOpsTable_->add_elem(100, (int)eBitOrAssign);
}
}

eAssignOps
Expand All @@ -95,12 +88,12 @@ StatementAssign::AssignOpsProbability(const Type* type)
return eSimpleAssign;
}

VectorFilter filter(assignOpsTable_);
VectorFilter filter(&assignOpsTable_);
if (type && type->is_signed()) {
filter.add(ePreIncr).add(ePreDecr).add(ePostIncr).add(ePostDecr);
}

int value = rnd_upto(100, &filter);
int value = rnd_upto(filter.get_max_prob(), &filter);
return (eAssignOps)(filter.lookup(value));
}

Expand Down
2 changes: 1 addition & 1 deletion src/StatementAssign.h
Expand Up @@ -138,7 +138,7 @@ class StatementAssign : public Statement
std::string tmp_var1;
std::string tmp_var2;

static ProbabilityTable<unsigned int, int> *assignOpsTable_;
static DistributionTable assignOpsTable_;

StatementAssign(const StatementAssign &sa); // unimplemented

Expand Down

0 comments on commit a139329

Please sign in to comment.