예제 #1
0
Expression *
ExpressionFuncall::make_random(CGContext &cg_context, const Type* type, const CVQualifiers* qfer)
{
    Expression *e = 0;
    bool std_func = ExpressionFunctionProbability(cg_context);
    ERROR_GUARD(NULL);
    // unary/binary "functions" produce scalar types only
    if (type && (type->eType != eSimple || type->simple_type == eVoid))
        std_func = false;

    Effect effect_accum = cg_context.get_accum_effect();
    Effect effect_stm = cg_context.get_effect_stm();
    FactMgr* fm = get_fact_mgr(&cg_context);
    vector<const Fact*> facts_copy = fm->global_facts;
    FunctionInvocation *fi = FunctionInvocation::make_random(std_func, cg_context, type, qfer);
    ERROR_GUARD(NULL);

    if (fi->failed) {
        // if it's a invalid invocation, (see FunctionInvocationUser::revisit)
        // restore the env, and replace invocation with a simple var
        cg_context.reset_effect_accum(effect_accum);
        cg_context.reset_effect_stm(effect_stm);
        fm->restore_facts(facts_copy);
        e = ExpressionVariable::make_random(cg_context, type, qfer);
        delete fi;
    }
    else {
        e = new ExpressionFuncall(*fi);
    }
    return e;
}
예제 #2
0
Expression *
Expression::make_random_param(CGContext &cg_context, const Type* type, const CVQualifiers* qfer, enum eTermType tt)
{
	DEPTH_GUARD_BY_TYPE_RETURN_WITH_FLAG(dtExpressionRandomParam, tt, NULL);
	Expression *e = 0;
	assert(type);
	// 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);   // 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);
		}
		if (type->is_const_struct_union()) {
			filter.add(eAssignment);
		}
		if (cg_context.expr_depth + 2 > CGOptions::max_expr_depth()) {
			filter.add(eFunction).add(eAssignment).add(eCommaExpr);
		}
		tt = ExpressionTypeProbability(&filter);
	}

	ERROR_GUARD(NULL);

	switch (tt) {
	case eConstant:
		if (type->eType == eSimple)
			assert(type->simple_type != eVoid);
		e = HYPOTHESIS_DRAW(Constant, type);
		break;
	case eVariable:
		e = HYPOTHESIS_DRAW(ExpressionVariable, cg_context, type, qfer, true);
		break;
	case eFunction:
		e = HYPOTHESIS_DRAW(ExpressionFuncall, cg_context, type, qfer);
		break;
	case eAssignment:
		e = HYPOTHESIS_DRAW(ExpressionAssign, cg_context, type, qfer);
		break;
	case eCommaExpr:
		e = HYPOTHESIS_DRAW(ExpressionComma, cg_context, type, qfer);
		break;
	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;
}
예제 #3
0
static eTermType
ExpressionTypeProbability(const VectorFilter *filter)
{
	if (PartialExpander::direct_expand_check(eInvoke))
		return eFunction;

	assert(filter);

	int i = rnd_upto(filter->get_max_prob(), filter);
	ERROR_GUARD(MAX_TERM_TYPES);
	return (eTermType)(filter->lookup(i));
}
예제 #4
0
int
DFSRndNumGenerator::revisit_node(DFSRndNumGenerator::SearchState *state, int local_current_pos,
					int bound, const Filter *filter, const string *)
{
	int rv = state->value();
	if (filter) {
		if (rv >= bound) {
			state->dump("");
			dumpCurrentState(bound, "");
			cout << "rv = " << rv << ", bound = " << bound << std::endl;
			assert(0);
		}

		filter->filter(rv);

		ERROR_GUARD(-1);

		assert(current_pos_ < CGOptions::max_exhaustive_depth());

	}
	seq_->add_number(rv, bound, local_current_pos);
	return rv;
}
ExpressionVariable *
ExpressionVariable::make_random(CGContext &cg_context, const Type* type, const CVQualifiers* qfer, bool as_param, bool as_return)
{
	DEPTH_GUARD_BY_TYPE_RETURN(dtExpressionVariable, NULL);
	Function *curr_func = cg_context.get_current_func(); 
	FactMgr* fm = get_fact_mgr_for_func(curr_func);
	vector<const Variable*> dummy; 

	// 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();
  
	ExpressionVariable *ev = 0;
	do {
		const Variable* var = 0; 
		// try to use one of must_read_vars in CGContext 
		var = VariableSelector::select_must_use_var(Effect::READ, cg_context, type, qfer);  
		if (var == NULL) {
			var = VariableSelector::select(Effect::READ, cg_context, type, qfer, dummy, eFlexible);
		}
		ERROR_GUARD(NULL);
		if (!var) 
			continue;
		if (!type->is_float() && var->type->is_float())
			continue;
		// forbid a parameter to take the address of an argument
		// this is to simplify the path shortcutting delta
		if (as_param && var->is_argument() && var->type->is_dereferenced_from(type)) {
			continue;
		}
		if (!CGOptions::addr_taken_of_locals()
			&& var->type->is_dereferenced_from(type)
			&& (var->is_argument() || var->is_local())) {
			continue;
		}

		// forbid a escaping pointer to take the address of an argument or a local variable
		int indirection = var->type->get_indirect_level() - type->get_indirect_level();
		if (as_return && CGOptions::no_return_dead_ptr() &&
			FactPointTo::is_pointing_to_locals(var, cg_context.get_current_block(), indirection, fm->global_facts)) {
			continue;
		}
		int valid = FactPointTo::opportunistic_validate(var, type, fm->global_facts);
		if (valid) {
			ExpressionVariable tmp(*var, type);
			if (tmp.visit_facts(fm->global_facts, cg_context)) { 
				ev = tmp.get_indirect_level() == 0 ? new ExpressionVariable(*var) : new ExpressionVariable(*var, type); 
				cg_context.curr_blk = cg_context.get_current_block();
				break;
			}  
			else {
				cg_context.reset_effect_accum(eff_accum);
				cg_context.reset_effect_stm(eff_stmt);
			}
		}
		dummy.push_back(var);
	} while (true);

	// statistics
	int deref_level = ev->get_indirect_level();
	if (deref_level > 0) {
		incr_counter(Bookkeeper::read_dereference_cnts, deref_level); 
	}
	if (deref_level < 0) {
		Bookkeeper::record_address_taken(ev->get_var());
	}   
	Bookkeeper::record_volatile_access(ev->get_var(), deref_level, false);
	return ev;
}
예제 #6
0
int
DFSRndNumGenerator::random_choice (int bound, const Filter *filter, const string *where, vector<int> *invalid_nums)
{
	int err = Error::get_error();

	if (err == BACKTRACKING_ERROR) {
		return -1;
	}
	else if (err != SUCCESS) {
		assert("request random number in an error state. " && 0);
	}

	++current_pos_;
	if (use_debug_sequence_) {
		int rv = seq_->get_number_by_pos(current_pos_);
		if (filter)
			filter->filter(rv);
		//cout << "current_pos _ = " << current_pos_ << ", length = " << seq_->sequence_length() << std::endl;
		if (static_cast<unsigned int>(current_pos_) >= seq_->sequence_length() - 1) {
			all_done_ = true;
		}
		return rv;
	}

	int local_current_pos = current_pos_;

	if (current_pos_ >= CGOptions::max_exhaustive_depth() ||
		decision_depth_ >= CGOptions::max_exhaustive_depth()) {
		Error::set_error(EXCEED_MAX_DEPTH_ERROR);
		return -1;
	}

	DFSRndNumGenerator::SearchState *state = states_[current_pos_];

	state->set_bound(bound);
	//dumpCurrentState(bound, "");
	//state->dump("");

	// Revisit a node
	if (current_pos_ < decision_depth_ && state->init()) {
		return revisit_node(state, local_current_pos, bound, filter, where);
	}

	if (state->init()) {
		int v = state->value();
		int local_decision_depth = decision_depth_;
		do { // Filter out invalid value
			++v;
			state->set_value(v);
			current_pos_ = local_current_pos;
			decision_depth_ = local_decision_depth;
			ERROR_GUARD(-1);
		} while (v < bound && ((filter && filter->filter(v)) || filter_invalid_nums(invalid_nums, v)));

		state->set_value(v);

		if (state->value() >= bound) { // backtracking
			current_pos_ = local_current_pos;
			for (int i = current_pos_; i < CGOptions::max_exhaustive_depth(); ++i) {
				states_[i]->set_init(false);
			}
			--decision_depth_;
			if (decision_depth_ < 0)
				all_done_ = true;
			Error::set_error(BACKTRACKING_ERROR);
			return -1;
		}
		else { // switch branch
			ERROR_GUARD(-1);

			int rv = state->value();
			seq_->add_number(rv, bound, local_current_pos);
			return rv;
		}
	}
	else { // First time to visit this node
		int v = 0;

		++decision_depth_;
		state->initSearchState(true, v, bound);

		while (v < bound && ((filter && (filter->filter(v))) || filter_invalid_nums(invalid_nums, v))) { // Filter out invalid value
			for (int i = decision_depth_; i < CGOptions::max_exhaustive_depth(); ++i) {
				states_[i]->set_value(0);
			}
			ERROR_GUARD(-1);
			decision_depth_ = current_pos_;
			current_pos_ = local_current_pos;
			++v;
		}
		decision_depth_ = current_pos_;

		if (v >= bound) {
			current_pos_ = local_current_pos;
			for (int i = current_pos_; i < CGOptions::max_exhaustive_depth(); ++i) {
				states_[i]->set_init(false);
			}
			--decision_depth_;
			if (decision_depth_ < 0)
				all_done_ = true;
			Error::set_error(BACKTRACKING_ERROR);
			return -1;
		}

		state->set_value(v);

		ERROR_GUARD(-1);

		seq_->add_number(v, bound, local_current_pos);
		return v;
	}
}
예제 #7
0
Expression *
Expression::make_random(CGContext &cg_context, const Type* type, const CVQualifiers* qfer, bool no_func, bool no_const, enum eTermType tt)
{
	DEPTH_GUARD_BY_TYPE_RETURN_WITH_FLAG(dtExpression, tt, NULL);
	Expression *e = 0;
	if (type == NULL) {
		do {
			type = cg_context.get_effect_context().is_side_effect_free() ? Type::choose_random_nonvoid() : Type::choose_random_nonvoid_nonvolatile();
		} while (type->eType == eStruct && tt == eConstant);
	}
	assert(!(no_func && tt == eFunction));
	assert(!(no_const && tt == eConstant));
	// constant struct variables can not be a subexpression?
	assert(!(type->eType == eStruct && tt == eConstant));

	// if no term type is provided, choose a random term type with restrictions
	if (tt == MAX_TERM_TYPES) {
		VectorFilter filter(&Expression::exprTable_);
		if (no_func ||
			(!CGOptions::return_structs() && type->eType == eStruct) ||
			(!CGOptions::return_unions() && type->eType == eUnion)) {
			filter.add(eFunction);
		}
		// struct constants can't be subexpressions (union constant can't either?)
		if (no_const || type->eType == eStruct || type->eType == eUnion) {
			filter.add(eConstant);
		}
		// can't assign to constant struct/unions. on the other hand, assign to a volatile
		// struct/union cause too much trouble for effect analysis, disable it for now
		if (type->is_const_struct_union() || type->is_volatile_struct_union()) {
			filter.add(eAssignment);
		}
		if (cg_context.expr_depth + 2 > CGOptions::max_expr_depth()) {
			filter.add(eFunction).add(eAssignment).add(eCommaExpr);
		}
		tt = ExpressionTypeProbability(&filter);
	}

	ERROR_GUARD(NULL);

	switch (tt) {
	case eConstant:
		if (type->eType == eSimple)
			assert(type->simple_type != eVoid);
		e = HYPOTHESIS_DRAW(Constant, type);
		break;
	case eVariable:
		e = HYPOTHESIS_DRAW(ExpressionVariable, cg_context, type, qfer);
		break;
	case eFunction:
		e = HYPOTHESIS_DRAW(ExpressionFuncall, cg_context, type, qfer);
		break;
	case eAssignment:
		e = HYPOTHESIS_DRAW(ExpressionAssign, cg_context, type, qfer);
		break;
	case eCommaExpr:
		e = HYPOTHESIS_DRAW(ExpressionComma, cg_context, type, qfer);
		break;
	default: break;
	}
#if 0
	if (!cg_context.get_effect_context().is_side_effect_free()) {
		assert(e->effect.is_side_effect_free());
	}
#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;
}