diff --git a/src/Block.cpp b/src/Block.cpp index cbbe98e5f..31d784995 100644 --- a/src/Block.cpp +++ b/src/Block.cpp @@ -110,7 +110,6 @@ Block::make_random(CGContext &cg_context, bool looping) b->in_array_loop = !(cg_context.iv_bounds.empty()); //b->stm_id = bid++; - ++cg_context.stmt_depth; // Push this block onto the variable scope stack. curr_func->stack.push_back(b); curr_func->blocks.push_back(b); @@ -148,7 +147,7 @@ Block::make_random(CGContext &cg_context, bool looping) } // append nested loop if some must-read/write variables hasn't been accessed - if (b->need_nested_loop(cg_context)) { + if (b->need_nested_loop(cg_context) && cg_context.blk_depth < CGOptions::max_blk_depth()) { b->append_nested_loop(cg_context); } @@ -162,8 +161,6 @@ Block::make_random(CGContext &cg_context, bool looping) } curr_func->stack.pop_back(); - --cg_context.stmt_depth; - if (Error::get_error() != SUCCESS) { //curr_func->stack.pop_back(); delete b; diff --git a/src/Bookkeeper.cpp b/src/Bookkeeper.cpp index b1d8e8dcb..f79722588 100644 --- a/src/Bookkeeper.cpp +++ b/src/Bookkeeper.cpp @@ -43,6 +43,7 @@ #include "FactMgr.h" #include "CVQualifiers.h" #include "Statement.h" +#include "Block.h" #include "CGOptions.h" using namespace std; @@ -53,6 +54,7 @@ using namespace std; std::vector Bookkeeper::struct_depth_cnts; int Bookkeeper::union_var_cnt = 0; std::vector Bookkeeper::expr_depth_cnts; +std::vector Bookkeeper::blk_depth_cnts; std::vector Bookkeeper::dereference_level_cnts; int Bookkeeper::address_taken_cnt = 0; std::vector Bookkeeper::read_dereference_cnts; @@ -127,10 +129,49 @@ Bookkeeper::doFinalization() } +int +Bookkeeper::stat_blk_depths_for_stmt(const Statement* s) +{ + size_t i, j; + int cnt = 0; + if (s->eType != eBlock) { + incr_counter(blk_depth_cnts, s->get_blk_depth() -1); + cnt++; + } + vector blks; + s->get_blocks(blks); + for (i=0; istms.size(); j++) { + cnt += stat_blk_depths_for_stmt(blks[i]->stms[j]); + } + } + return cnt; +} + +int +Bookkeeper::stat_blk_depths(void) +{ + const vector& funcs = get_all_functions(); + int cnt = 0; + for (size_t i=0; ibody); + } + return cnt; +} + void Bookkeeper::output_stmts_statistics(std::ostream &out) { - formated_output(out, "stmts: ", Statement::get_current_sid()); + size_t i; + int stmt_cnt = stat_blk_depths(); + formated_output(out, "stmts: ", stmt_cnt); + formated_output(out, "max block depth: ", (blk_depth_cnts.size() - 1)); + out << "breakdown:" << endl; + for (i=0; i exprs; + vector blks; + s->get_exprs(exprs); + for (i=0; iget_complexity()); + } + s->get_blocks(blks); + for (i=0; istms.size(); j++) { + stat_expr_depths_for_stmt(blks[i]->stms[j]); + } + } +} + +void +Bookkeeper::stat_expr_depths(void) +{ + const vector& funcs = get_all_functions(); + for (size_t i=0; ibody); + } +} + void Bookkeeper::output_expr_statistics(std::ostream &out) { size_t i; + stat_expr_depths(); formated_output(out, "max expression depth: ", (expr_depth_cnts.size() - 1)); out << "breakdown:" << endl; for (i=0; i struct_depth_cnts; static int union_var_cnt; static std::vector expr_depth_cnts; + static std::vector blk_depth_cnts; + static std::vector dereference_level_cnts; static int address_taken_cnt; diff --git a/src/CGContext.cpp b/src/CGContext.cpp index 4b99c5c7e..0cb5719e1 100644 --- a/src/CGContext.cpp +++ b/src/CGContext.cpp @@ -58,12 +58,11 @@ const CGContext CGContext::empty_context(0, Effect::get_empty_effect(), 0); /////////////////////////////////////////////////////////////////////////////// /* - * A convenience constructor. Set `stmt_depth' and `flags' to zero, and set - * `no_read_vars' and `no_write_vars' each to be an empty set. + * A convenience constructor. Context is created when entering functions */ CGContext::CGContext(Function *current_func, const Effect &eff_context, Effect *eff_accum) : current_func(current_func), - stmt_depth(0), + blk_depth(0), expr_depth(0), flags(0), curr_blk(0), @@ -78,7 +77,7 @@ CGContext::CGContext(Function *current_func, const Effect &eff_context, Effect * // adapt current context to create context of parameters CGContext::CGContext(const CGContext &cgc, const Effect &eff_context, Effect *eff_accum) : current_func(cgc.current_func), - stmt_depth(cgc.stmt_depth), + blk_depth(cgc.blk_depth), expr_depth(cgc.expr_depth), flags(cgc.flags), call_chain(cgc.call_chain), @@ -95,8 +94,8 @@ CGContext::CGContext(const CGContext &cgc, const Effect &eff_context, Effect *ef // adapt current context to create context of callee CGContext::CGContext(const CGContext &cgc, Function* f, const Effect &eff_context, Effect *eff_accum) : current_func(f), - stmt_depth(cgc.stmt_depth), - expr_depth(cgc.expr_depth), + blk_depth(0), + expr_depth(0), flags(cgc.flags), call_chain(cgc.call_chain), curr_blk(cgc.curr_blk), @@ -111,8 +110,8 @@ CGContext::CGContext(const CGContext &cgc, Function* f, const Effect &eff_contex // adapt current context to create context of loop body CGContext::CGContext(const CGContext &cgc, RWDirective* rwd, const Variable* iv, unsigned int bound) : current_func(cgc.current_func), - stmt_depth(cgc.stmt_depth), - expr_depth(cgc.expr_depth), + blk_depth(cgc.blk_depth), + expr_depth(0), flags(cgc.flags | IN_LOOP), call_chain(cgc.call_chain), curr_blk(cgc.curr_blk), @@ -405,6 +404,13 @@ CGContext::add_effect(const Effect &e, bool include_lhs_effects) sanity_check(); } +void +CGContext::merge_param_context(const CGContext& param_cg_context, bool include_lhs_effects) +{ + add_effect(*param_cg_context.get_effect_accum(), include_lhs_effects); + expr_depth = param_cg_context.expr_depth; +} + /* * */ diff --git a/src/CGContext.h b/src/CGContext.h index 3b7bbf860..e60f48b65 100644 --- a/src/CGContext.h +++ b/src/CGContext.h @@ -138,6 +138,7 @@ class CGContext void add_effect(const Effect &e, bool include_lhs_effects=false); void add_external_effect(const Effect &e); void add_visible_effect(const Effect &e, const Block* b); + void merge_param_context(const CGContext& param_cg_context, bool include_lhs_effects=false); int find_variable_scope(const Variable* var) const; @@ -154,7 +155,7 @@ class CGContext public: // XXX - int stmt_depth; + int blk_depth; int expr_depth; unsigned int flags; std::vector call_chain; diff --git a/src/CGOptions.cpp b/src/CGOptions.cpp index 6dc592013..8a6a40b52 100644 --- a/src/CGOptions.cpp +++ b/src/CGOptions.cpp @@ -77,7 +77,7 @@ DEFINE_GETTER_SETTER_STRING_REF(output_file) DEFINE_GETTER_SETTER_INT (max_funcs) DEFINE_GETTER_SETTER_INT (max_params) DEFINE_GETTER_SETTER_INT (max_block_size) -DEFINE_GETTER_SETTER_INT (max_stmt_depth) +DEFINE_GETTER_SETTER_INT (max_blk_depth) DEFINE_GETTER_SETTER_INT (max_expr_depth) DEFINE_GETTER_SETTER_BOOL(wrap_volatiles) DEFINE_GETTER_SETTER_BOOL(allow_const_volatile) @@ -176,7 +176,7 @@ CGOptions::set_default_settings(void) max_funcs(CGOPTIONS_DEFAULT_MAX_FUNCS); max_params(CGOPTIONS_DEFAULT_MAX_PARAMS); max_block_size(CGOPTIONS_DEFAULT_MAX_BLOCK_SIZE); - max_stmt_depth(CGOPTIONS_DEFAULT_MAX_STMT_DEPTH); + max_blk_depth(CGOPTIONS_DEFAULT_MAX_BLOCK_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); @@ -409,7 +409,7 @@ CGOptions::has_conflict(void) conflict_msg_ = "max-funcs must be at least 1"; return true; } - if (CGOptions::max_stmt_depth() < 1) { + if (CGOptions::max_blk_depth() < 1) { conflict_msg_ = "max-stmt-depth must be at least 1"; return true; } diff --git a/src/CGOptions.h b/src/CGOptions.h index 2c2b0ff87..b36992d15 100644 --- a/src/CGOptions.h +++ b/src/CGOptions.h @@ -47,13 +47,13 @@ using namespace std; #define CGOPTIONS_DEFAULT_FUNC1_MAX_PARAMS (3) #define CGOPTIONS_DEFAULT_COVERAGE_TEST_SIZE (500) #define CGOPTIONS_DEFAULT_MAX_BLOCK_SIZE (4) -#define CGOPTIONS_DEFAULT_MAX_STMT_DEPTH (5) -#define CGOPTIONS_DEFAULT_MAX_EXPR_DEPTH (5) +#define CGOPTIONS_DEFAULT_MAX_BLOCK_DEPTH (5) +#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_INDIRECT_LEVEL (2) -#define CGOPTIONS_DEFAULT_MAX_ARRAY_DIMENSIONS (3) +#define CGOPTIONS_DEFAULT_MAX_ARRAY_DIMENSIONS (3) #define CGOPTIONS_DEFAULT_MAX_ARRAY_LENGTH_PER_DIMENSION (10) #define CGOPTIONS_DEFAULT_MAX_ARRAY_LENGTH (256) #define CGOPTIONS_DEFAULT_MAX_ARRAY_NUM_IN_LOOP (4) @@ -93,8 +93,8 @@ class CGOptions { static int max_block_size(void); static int max_block_size(int p); - static int max_stmt_depth(void); - static int max_stmt_depth(int p); + static int max_blk_depth(void); + static int max_blk_depth(int p); static int max_expr_depth(void); static int max_expr_depth(int p); @@ -408,7 +408,7 @@ class CGOptions { static std::string output_file_; static int max_params_; static int max_block_size_; - static int max_stmt_depth_; + static int max_blk_depth_; static int max_expr_depth_; static bool wrap_volatiles_; static bool allow_const_volatile_; diff --git a/src/Constant.h b/src/Constant.h index c59c15c4c..5bea57e28 100644 --- a/src/Constant.h +++ b/src/Constant.h @@ -80,6 +80,7 @@ class Constant : public Expression virtual bool equals(int num) const; virtual void get_referenced_ptrs(std::vector& /*ptrs*/) const {}; + virtual unsigned int get_complexity(void) const { return 1;} // unsigned long SizeInBytes(void) const; virtual void Output(std::ostream &) const; diff --git a/src/Expression.cpp b/src/Expression.cpp index 2424363d7..c782a4987 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -98,11 +98,8 @@ Expression::InitProbabilityTables() * */ static eTermType -ExpressionTypeProbability(const CGContext &cg_context, const VectorFilter *filter) +ExpressionTypeProbability(const VectorFilter *filter) { - if (cg_context.expr_depth > CGOptions::max_expr_depth()) - return eVariable; - if (PartialExpander::direct_expand_check(eInvoke)) return eFunction; @@ -179,7 +176,10 @@ Expression::make_random(CGContext &cg_context, const Type* type, const CVQualifi if (type->is_const_struct_union() || type->is_volatile_struct_union()) { filter.add(eAssignment); } - tt = ExpressionTypeProbability(cg_context, &filter); + if (cg_context.expr_depth + 2 > CGOptions::max_expr_depth()) { + filter.add(eFunction).add(eAssignment).add(eCommaExpr); + } + tt = ExpressionTypeProbability(&filter); } ERROR_GUARD(NULL); @@ -193,8 +193,7 @@ Expression::make_random(CGContext &cg_context, const Type* type, const CVQualifi case eVariable: e = ExpressionVariable::make_random(cg_context, type, qfer); break; - case eFunction: - cg_context.expr_depth++; + case eFunction: e = ExpressionFuncall::make_random(cg_context, type, qfer); break; case eAssignment: @@ -209,8 +208,13 @@ Expression::make_random(CGContext &cg_context, const Type* type, const CVQualifi if (!cg_context.get_effect_context().is_side_effect_free()) { assert(e->effect.is_side_effect_free()); } -#endif +#endif + // increment expression depth. A function call increase the depth by 1 + if (e->term_type == eConstant || e->term_type == eVariable || + (e->get_invoke() && e->get_invoke()->invoke_type == eFuncCall)) { + cg_context.expr_depth++; + } ERROR_GUARD(NULL); return e; } @@ -227,7 +231,7 @@ Expression::make_random_param(CGContext &cg_context, const Type* type, const CVQ // if a term type is provided, no need to choose random term type if (tt == MAX_TERM_TYPES) { VectorFilter filter(Expression::paramTable_); - filter.add(eConstant); // no constants as function call parameters + 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)) { filter.add(eFunction); @@ -235,7 +239,10 @@ Expression::make_random_param(CGContext &cg_context, const Type* type, const CVQ if (type->is_const_struct_union()) { filter.add(eAssignment); } - tt = ExpressionTypeProbability(cg_context, &filter); + if (cg_context.expr_depth + 2 > CGOptions::max_expr_depth()) { + filter.add(eFunction).add(eAssignment).add(eCommaExpr); + } + tt = ExpressionTypeProbability(&filter); } ERROR_GUARD(NULL); @@ -250,7 +257,6 @@ Expression::make_random_param(CGContext &cg_context, const Type* type, const CVQ e = ExpressionVariable::make_random(cg_context, type, qfer, true); break; case eFunction: - cg_context.expr_depth++; e = ExpressionFuncall::make_random(cg_context, type, qfer); break; case eAssignment: @@ -262,6 +268,10 @@ Expression::make_random_param(CGContext &cg_context, const Type* type, const CVQ default: break; } + if (e->term_type == eConstant || e->term_type == eVariable || + (e->get_invoke() && e->get_invoke()->invoke_type == eFuncCall)) { + cg_context.expr_depth++; + } ERROR_GUARD(NULL); return e; } diff --git a/src/Expression.h b/src/Expression.h index 90f4fb345..4ec1d78f3 100644 --- a/src/Expression.h +++ b/src/Expression.h @@ -122,6 +122,7 @@ class Expression virtual bool has_uncertain_call_recursive(void) const {return false;} + virtual unsigned int get_complexity(void) const = 0; virtual bool less_than(int /*num*/) const { return false;} virtual bool not_equals(int /*num*/) const { return false;} virtual bool equals(int /*num*/) const { return false;} diff --git a/src/ExpressionAssign.h b/src/ExpressionAssign.h index 2ad3bb501..1c2779872 100644 --- a/src/ExpressionAssign.h +++ b/src/ExpressionAssign.h @@ -70,7 +70,8 @@ class ExpressionAssign : public Expression virtual std::vector get_dereferenced_ptrs(void) const { return assign->get_dereferenced_ptrs();} virtual void get_referenced_ptrs(std::vector& ptrs) const { assign->get_referenced_ptrs(ptrs);} - + virtual unsigned int get_complexity(void) const { return get_lhs()->get_complexity() + get_rhs()->get_complexity();} + const Expression* get_rhs(void) const { return assign->get_expr();} const Lhs* get_lhs(void) const { return assign->get_lhs();} const StatementAssign* get_stm_assign(void) const { return assign;} diff --git a/src/ExpressionComma.h b/src/ExpressionComma.h index 47dfdb812..efa21fbc0 100644 --- a/src/ExpressionComma.h +++ b/src/ExpressionComma.h @@ -64,7 +64,8 @@ class ExpressionComma : public Expression virtual std::vector get_dereferenced_ptrs(void) const; virtual void get_referenced_ptrs(std::vector& ptrs) const { lhs.get_referenced_ptrs(ptrs); rhs.get_referenced_ptrs(ptrs);} - + virtual unsigned int get_complexity(void) const { return get_lhs()->get_complexity() + get_rhs()->get_complexity();} + const Expression* get_lhs(void) const { return &lhs;} const Expression* get_rhs(void) const { return &rhs;} void Output(std::ostream &) const; diff --git a/src/ExpressionFuncall.cpp b/src/ExpressionFuncall.cpp index 83968c576..53ad3ffbd 100644 --- a/src/ExpressionFuncall.cpp +++ b/src/ExpressionFuncall.cpp @@ -67,8 +67,7 @@ ExpressionFunctionProbability(const CGContext &/*cg_context*/) Expression * ExpressionFuncall::make_random(CGContext &cg_context, const Type* type, const CVQualifiers* qfer) { - Expression *e = 0; - ++cg_context.stmt_depth; + Expression *e = 0; bool std_func = ExpressionFunctionProbability(cg_context); ERROR_GUARD(NULL); // unary/binary "functions" produce scalar types only @@ -94,7 +93,6 @@ ExpressionFuncall::make_random(CGContext &cg_context, const Type* type, const CV else { e = new ExpressionFuncall(*fi); } - --cg_context.stmt_depth; return e; } @@ -142,6 +140,20 @@ ExpressionFuncall::get_called_funcs(std::vector& invoke.get_called_funcs(funcs); } +unsigned int +ExpressionFuncall::get_complexity(void) const +{ + unsigned int comp = 0; + const FunctionInvocation* invoke = get_invoke(); + if (invoke->invoke_type == eFuncCall) { + comp++; // function call itself counts as 1 complexity + } + for (size_t i=0; iparam_value.size(); i++) { + comp += invoke->param_value[i]->get_complexity(); + } + return comp; +} + bool ExpressionFuncall::visit_facts(vector& inputs, CGContext& cg_context) const { diff --git a/src/ExpressionFuncall.h b/src/ExpressionFuncall.h index 3b4d00782..229e688be 100644 --- a/src/ExpressionFuncall.h +++ b/src/ExpressionFuncall.h @@ -64,6 +64,8 @@ class ExpressionFuncall : public Expression virtual void get_called_funcs(std::vector& funcs ) const; + virtual unsigned int get_complexity(void) const; + virtual bool visit_facts(vector& inputs, CGContext& cg_context) const; virtual bool has_uncertain_call_recursive(void) const; diff --git a/src/ExpressionVariable.cpp b/src/ExpressionVariable.cpp index 2aa3a2de9..33c681f4e 100644 --- a/src/ExpressionVariable.cpp +++ b/src/ExpressionVariable.cpp @@ -61,10 +61,8 @@ ExpressionVariable::make_random(CGContext &cg_context, const Type* type, const C // save current effects, in case we need to reset Effect eff_accum = cg_context.get_accum_effect(); Effect eff_stmt = cg_context.get_effect_stm(); - - ++cg_context.stmt_depth; + ExpressionVariable *ev = 0; - do { const Variable* var = 0; // try to use one of must_read_vars in CGContext @@ -111,8 +109,6 @@ ExpressionVariable::make_random(CGContext &cg_context, const Type* type, const C Bookkeeper::record_address_taken(ev->get_var()); } Bookkeeper::record_volatile_access(ev->get_var(), deref_level, false); - - --cg_context.stmt_depth; return ev; } diff --git a/src/ExpressionVariable.h b/src/ExpressionVariable.h index b84348ae2..0dc82e91d 100644 --- a/src/ExpressionVariable.h +++ b/src/ExpressionVariable.h @@ -66,6 +66,8 @@ class ExpressionVariable : public Expression virtual std::vector get_dereferenced_ptrs(void) const; virtual void get_referenced_ptrs(std::vector& ptrs) const; + virtual unsigned int get_complexity(void) const { return 1;} + virtual bool visit_facts(vector& inputs, CGContext& cg_context) const; virtual const Type &get_type(void) const; diff --git a/src/FunctionInvocation.cpp b/src/FunctionInvocation.cpp index 53e693180..68da6ab25 100644 --- a/src/FunctionInvocation.cpp +++ b/src/FunctionInvocation.cpp @@ -189,7 +189,7 @@ FunctionInvocation::make_random_binary(CGContext &cg_context, const Type* type) ERROR_GUARD_AND_DEL1(NULL, fi); Expression *rhs = 0; - cg_context.add_effect(lhs_eff_accum, true); + cg_context.merge_param_context(lhs_cg_context, true); FactMgr* fm = get_fact_mgr(&cg_context); vector facts_copy = fm->global_facts; @@ -227,7 +227,7 @@ FunctionInvocation::make_random_binary(CGContext &cg_context, const Type* type) fi->set_operation(op); } } - cg_context.add_effect(rhs_eff_accum, true); + cg_context.merge_param_context(rhs_cg_context, true); } ERROR_GUARD_AND_DEL2(NULL, fi, lhs); @@ -272,7 +272,7 @@ FunctionInvocation::make_random_binary_ptr_comparison(CGContext &cg_context) lhs_cg_context.flags |= NO_DANGLING_PTR; Expression *lhs = Expression::make_random(lhs_cg_context, type, 0, true); ERROR_GUARD_AND_DEL1(NULL, fi); - cg_context.add_effect(lhs_eff_accum, true); + cg_context.merge_param_context(lhs_cg_context, true); // now focus on RHS ... enum eTermType tt = MAX_TERM_TYPES; @@ -302,7 +302,7 @@ FunctionInvocation::make_random_binary_ptr_comparison(CGContext &cg_context) CGContext rhs_cg_context(cg_context, rhs_eff_context, &rhs_eff_accum); rhs_cg_context.flags |= NO_DANGLING_PTR; rhs = Expression::make_random(rhs_cg_context, type, 0, true, false, tt); - cg_context.add_effect(rhs_eff_accum, true); + cg_context.merge_param_context(rhs_cg_context, true); } ERROR_GUARD_AND_DEL2(NULL, fi, lhs); @@ -499,7 +499,7 @@ FunctionInvocation::visit_facts(vector& inputs, CGContext& cg_conte // when we generate subsequent parameters within this invocation. running_eff_context.add_effect(param_eff_accum); // Update the total effect of this invocation, too. - cg_context.add_effect(param_eff_accum, !is_func_call); + cg_context.merge_param_context(param_cg_context, !is_func_call); } ok = true; } diff --git a/src/FunctionInvocationUser.cpp b/src/FunctionInvocationUser.cpp index 2ac477ee4..9ecb560be 100644 --- a/src/FunctionInvocationUser.cpp +++ b/src/FunctionInvocationUser.cpp @@ -200,7 +200,7 @@ FunctionInvocationUser::build_invocation_and_function(CGContext &cg_context, con // when we generate subsequent parameters within this invocation. running_eff_context.add_effect(param_eff_accum); // Update the total effect of this invocation, too. - cg_context.add_effect(param_eff_accum); + cg_context.merge_param_context(param_cg_context); } FunctionInvocationUser* fiu = new FunctionInvocationUser(func, false, NULL); @@ -255,7 +255,7 @@ FunctionInvocationUser::build_invocation(Function *target, CGContext &cg_context Effect running_eff_context(cg_context.get_effect_context()); FactMgr* fm = get_fact_mgr(&cg_context); // XXX DEBUGGING - if (func->name == "func_10" && cg_context.get_current_func()->name=="func_1") { + if (func->name == "func_36" && cg_context.get_current_func()->name=="func_22") { i = 0; // Set breakpoint here. } @@ -271,7 +271,7 @@ FunctionInvocationUser::build_invocation(Function *target, CGContext &cg_context // when we generate subsequent parameters within this invocation. running_eff_context.add_effect(param_eff_accum); // Update the total effect of this invocation, too. - cg_context.add_effect(param_eff_accum); + cg_context.merge_param_context(param_cg_context); } // no need to validate func_1 as it has no parameters and it's called only once diff --git a/src/Lhs.h b/src/Lhs.h index cee5d3174..6e6563ccc 100644 --- a/src/Lhs.h +++ b/src/Lhs.h @@ -75,6 +75,7 @@ class Lhs : public Expression // virtual std::vector get_dereferenced_ptrs(void) const; virtual void get_referenced_ptrs(std::vector& ptrs) const; + virtual unsigned int get_complexity(void) const { return 1;} virtual bool visit_facts(vector& inputs, CGContext& cg_context) const; diff --git a/src/RandomProgramGenerator.cpp b/src/RandomProgramGenerator.cpp index 77d288efa..baeeab2e9 100644 --- a/src/RandomProgramGenerator.cpp +++ b/src/RandomProgramGenerator.cpp @@ -177,6 +177,8 @@ static void print_help() cout << " --max-pointer-depth : limit the indirect depth of pointers to (default 2)." << endl << endl; cout << " --max-array-dim : limit array dimensions to . (default 3)" << endl << endl; cout << " --max-array-len-per-dim : limit array length per dimension to (default 10)." << endl << endl; + cout << " --upper-expr-complexity : limit expression complexities to (default 10)." << endl << endl; + cout << " --max-block-depth : limit depth of nested blocks to (default 5)." << endl << endl; } static void print_advanced_help() @@ -1072,6 +1074,26 @@ main(int argc, char **argv) continue; } + if (strcmp (argv[i], "--upper-expr-complexity") ==0 ) { + unsigned long comp; + i++; + arg_check(argc, i); + if (!parse_int_arg(argv[i], &comp)) + exit(-1); + CGOptions::max_expr_depth(comp); + continue; + } + + if (strcmp (argv[i], "--max-block-depth") ==0 ) { + unsigned long depth; + i++; + arg_check(argc, i); + if (!parse_int_arg(argv[i], &depth)) + exit(-1); + CGOptions::max_blk_depth(depth); + continue; + } + if (strcmp (argv[i], "--union-read-type-sensitive") == 0) { CGOptions::union_read_type_sensitive(true); continue; diff --git a/src/Statement.cpp b/src/Statement.cpp index 3bc559f10..305f1decb 100644 --- a/src/Statement.cpp +++ b/src/Statement.cpp @@ -158,14 +158,9 @@ bool StatementFilter::filter(int value) const return true; } - // Limit Function complexity (depth of nested control structures and - // expressions) - if (cg_context_.stmt_depth > CGOptions::max_stmt_depth()) { - if (type == eAssign || type == eReturn) - return false; - else - return true; - + // Limit Function complexity (depth of nested control structures) + if (cg_context_.blk_depth >= CGOptions::max_blk_depth()) { + return Statement::is_compound(type); } else if (FuncListSize() > CGOptions::max_funcs()) { // Limit # of functions.. if (type != eInvoke) return false; @@ -257,8 +252,13 @@ Statement::make_random(CGContext &cg_context, FactVec pre_facts = fm->global_facts; Effect pre_effect = cg_context.get_accum_effect(); cg_context.get_effect_stm().clear(); + cg_context.expr_depth = 0; + if (is_compound(t)) { + cg_context.blk_depth++; + } // XXX: interim ickiness Statement *s = 0; + switch (t) { default: assert(!"unknown Statement type"); @@ -296,7 +296,9 @@ Statement::make_random(CGContext &cg_context, } ERROR_GUARD(NULL); - + if (is_compound(t)) { + cg_context.blk_depth--; + } // sometimes make_random may return 0 for various reasons. keep generating if (s == 0) { return make_random(cg_context); @@ -334,6 +336,16 @@ Statement::get_referenced_ptrs(std::vector& ptrs) const } } +int +Statement::get_blk_depth(void) const +{ + int depth = 0; + for (const Block* b = parent; b != NULL; b = b->parent) { + depth++; + } + return depth; +} + bool Statement::is_ptr_used(void) const { diff --git a/src/Statement.h b/src/Statement.h index 99507d931..8a5aee7e4 100644 --- a/src/Statement.h +++ b/src/Statement.h @@ -176,6 +176,8 @@ class Statement static int get_current_sid(void) { return sid; } + int get_blk_depth(void) const; + // unique id for each statement int stm_id; Function* func; diff --git a/src/StatementAssign.cpp b/src/StatementAssign.cpp index 443590632..f5370e336 100644 --- a/src/StatementAssign.cpp +++ b/src/StatementAssign.cpp @@ -112,9 +112,11 @@ StatementAssign::make_random(CGContext &cg_context, const Type* type, const CVQu { // decide assignment operator eAssignOps op = AssignOpsProbability(type); + bool stand_alone_assign = false; // decide type if (type == NULL) { + stand_alone_assign = true; type = Type::SelectLType(!cg_context.get_effect_context().is_side_effect_free(), op); } assert(!type->is_const_struct_union()); @@ -126,7 +128,6 @@ StatementAssign::make_random(CGContext &cg_context, const Type* type, const CVQu // pre-generation initializations Lhs *lhs = NULL; Expression *e = NULL; - cg_context.expr_depth = 0; Effect running_eff_context(cg_context.get_effect_context()); Effect rhs_accum, lhs_accum; CGContext rhs_cg_context(cg_context, running_eff_context, &rhs_accum); @@ -154,7 +155,7 @@ StatementAssign::make_random(CGContext &cg_context, const Type* type, const CVQu qfer.set_volatile(false); } } - cg_context.add_effect(rhs_accum, true); + cg_context.merge_param_context(rhs_cg_context, true); running_eff_context.write_var_set(rhs_accum.get_lhs_write_vars()); CGContext lhs_cg_context(cg_context, running_eff_context, &lhs_accum); @@ -172,10 +173,7 @@ StatementAssign::make_random(CGContext &cg_context, const Type* type, const CVQu return NULL; } - cg_context.add_effect(lhs_accum, true); - - // book keeping - incr_counter(Bookkeeper::expr_depth_cnts, cg_context.expr_depth); + cg_context.merge_param_context(lhs_cg_context, true); ERROR_GUARD_AND_DEL2(NULL, e, lhs); StatementAssign *stmt_assign = make_possible_compound_assign(cg_context, *lhs, op, *e); ERROR_GUARD_AND_DEL2(NULL, e, lhs); @@ -300,7 +298,7 @@ StatementAssign::visit_facts(vector& inputs, CGContext& cg_context) if (op != eSimpleAssign) { running_eff_context.add_effect(rhs_accum); } - cg_context.add_effect(rhs_accum, true); + cg_context.merge_param_context(rhs_cg_context, true); running_eff_context.write_var_set(rhs_accum.get_lhs_write_vars()); CGContext lhs_cg_context(cg_context, running_eff_context, &lhs_accum); @@ -308,7 +306,7 @@ StatementAssign::visit_facts(vector& inputs, CGContext& cg_context) if (!lhs.visit_facts(inputs, lhs_cg_context)) { return false; } - cg_context.add_effect(lhs_accum, true); + cg_context.merge_param_context(lhs_cg_context, true); //cg_context.get_effect_stm() = lhs_cg_context.get_effect_stm(); update_fact_for_assign(this, inputs); // save effect diff --git a/src/StatementIf.cpp b/src/StatementIf.cpp index 6b17427ad..629985d6c 100644 --- a/src/StatementIf.cpp +++ b/src/StatementIf.cpp @@ -57,7 +57,6 @@ StatementIf::make_random(CGContext &cg_context) { DEPTH_GUARD_BY_TYPE_RETURN(dtStatementIf, NULL); FactMgr* fm = get_fact_mgr(&cg_context); - cg_context.expr_depth = 0; FactVec pre_facts; Effect pre_effect; // func_1 hacking, save the env in case we need to re-analyze @@ -85,8 +84,6 @@ StatementIf::make_random(CGContext &cg_context) } Effect eff = cg_context.get_effect_stm(); - incr_counter(Bookkeeper::expr_depth_cnts, cg_context.expr_depth); - // this will save global_facts to map_facts_in[if_true], and update // facts for new variables created while generating if_true Block *if_true = Block::make_random(cg_context); diff --git a/src/StatementReturn.cpp b/src/StatementReturn.cpp index e49320fc5..59fa647f8 100644 --- a/src/StatementReturn.cpp +++ b/src/StatementReturn.cpp @@ -58,11 +58,9 @@ StatementReturn::make_random(CGContext &cg_context) FactMgr* fm = get_fact_mgr(&cg_context); assert(fm); - cg_context.expr_depth = 0; ExpressionVariable* ev = ExpressionVariable::make_random(cg_context, curr_func->return_type, &curr_func->rv->qfer, false, true); // XXX ERROR_GUARD(NULL); - incr_counter(Bookkeeper::expr_depth_cnts, cg_context.expr_depth); StatementReturn* sr = new StatementReturn(cg_context.get_current_block(), *ev); return sr; diff --git a/src/VectorFilter.cpp b/src/VectorFilter.cpp index f92c0fcaf..5e99d8ff3 100644 --- a/src/VectorFilter.cpp +++ b/src/VectorFilter.cpp @@ -74,6 +74,15 @@ VectorFilter::filter(int v) const return (flag_ == FILTER_OUT) ? re : !re; } +VectorFilter& +VectorFilter::add(unsigned int item) +{ + if (std::find(vs_.begin(), vs_.end(), item) == vs_.end()) { + vs_.push_back(item); + } + return *this; +} + int VectorFilter::lookup(int v) const { diff --git a/src/VectorFilter.h b/src/VectorFilter.h index 2a056353e..886d824a7 100644 --- a/src/VectorFilter.h +++ b/src/VectorFilter.h @@ -47,7 +47,7 @@ class VectorFilter : public Filter VectorFilter(ProbabilityTable *table); explicit VectorFilter(std::vector &vs, int flag = FILTER_OUT); - VectorFilter& add(unsigned int item) { vs_.push_back(item); return *this;} + VectorFilter& add(unsigned int item); int lookup(int v) const;