Example #1
0
/***************************************************************************************
 * for a given input env, abstract a given statement, generate an output env, and
 * update both input/output env for this statement
 *
 * shortcut: if this input env matches previous input env, use previous output env directly
 ***************************************************************************************/
bool
Statement::validate_and_update_facts(vector<const Fact*>& inputs, CGContext& cg_context) const
{
	FactMgr* fm = get_fact_mgr_for_func(func);
	int shortcut = shortcut_analysis(inputs, cg_context);
	if (shortcut==0) {
		/* mark the goto statements inside this statement as visited
		   this is to fix scenario like the following:

		   lbl:  s1
		   for (...) {
		      goto lbl;
		   }

		   where the "for" statement is bypassed, but the output from "goto lbl"
		   must be feed into s1 in order to achieve a fixed point */
		for (size_t i=0; i<fm->cfg_edges.size(); i++) {
			const Statement* s = fm->cfg_edges[i]->src;
			if (s->eType == eGoto && contains_stmt(s)) {
				fm->map_visited[s] = true;
			}
		}
		return true;
	}
	if (shortcut==1) return false;

	vector<const Fact*> inputs_copy = inputs;
	if (!stm_visit_facts(inputs, cg_context)) {
		return false;
	}
	fm->set_fact_in(this, inputs_copy);
	fm->set_fact_out(this, inputs);
	return true;
}
Example #2
0
/****************************************************************************
 * Entry point to pointer analysis and other DFA analysis for newly
 * created statement. remember some analysis has already been done during the
 * statement generation, some analysis work is only possible with a complete
 * statement, we do it here
 ****************************************************************************/
void
Statement::post_creation_analysis(vector<const Fact*>& pre_facts, const Effect& pre_effect, CGContext& cg_context) const
{
	FactMgr* fm = get_fact_mgr_for_func(func);
	if (eType == eIfElse) {
		((const StatementIf*)this)->combine_branch_facts(pre_facts);
	} else {
		fm->makeup_new_var_facts(pre_facts, fm->global_facts);
	}

	// save the effect for this statement if this is a simple statement
	// for compound statements, it's effect is saved in make_random
	if (!is_compound(eType)) {
		fm->map_stm_effect[this] = cg_context.get_effect_stm();
	}

	bool special_handled = false;
	// special handling for non-looping statements in func_1, which we never re-visit to
	// save run-time
	if (cg_context.get_current_func()->name == "func_1" && !(cg_context.flags & IN_LOOP) ) {
		if (has_uncertain_call_recursive()) {
			FactVec outputs = pre_facts;
			cg_context.reset_effect_accum(pre_effect);
			//if (stm_id == 573)
				/*if (this->eType == eAssign) {
					((const StatementAssign*)this)->get_rhs()->indented_output(cout, 0);
				}
				cout << endl;
				Output(cout, fm);*/
			//}
			if (!validate_and_update_facts(outputs, cg_context)) {
				assert(0);
			}
			fm->global_facts = outputs;
			special_handled = true;
		}
	}

	if (!special_handled) {
		// for if...else..., we don't want to walk through the true branch and false branch again
		// compute the output with consideration of return statement(s) in both branches
		if (eType == eAssign) {
			const StatementAssign* sa = (const StatementAssign*)this;
			// abstract fact for assignment itself. No analysis on function calls
			// on RHS since they are already handled during statement generation
			FactMgr::update_fact_for_assign(sa, fm->global_facts);
		}
		else if (eType == eReturn) {
			const StatementReturn* sr = (const StatementReturn*)this;
			FactMgr::update_fact_for_return(sr, fm->global_facts);
		}
	}
	fm->remove_rv_facts(fm->global_facts);
	fm->set_fact_in(this, pre_facts);
	fm->set_fact_out(this, fm->global_facts);
	fm->map_accum_effect[this] = *(cg_context.get_effect_accum());
	fm->map_visited[this] = true;
}
Example #3
0
/**************************************************************************************************
 * DFA analysis for a block:
 *
 * we must considers all kinds of blocks: block for for-loops; block for if-true and if-false; block for
 * function body; block that loops; block has jump destination insdie; block being a jump destination itself
 * (in the case of "continue" in for-loops). All of them must be taken care in this function.
 *
 * params:
 *    inputs: the inputs env before entering block
 *    cg_context: code generation context
 *    fail_index: records which statement in this block caused analyzer to fail
 *    visit_one: when is true, the statements in this block must be visited at least once
 ****************************************************************************************************/
bool
Block::find_fixed_point(vector<const Fact*> inputs, vector<const Fact*>& post_facts, CGContext& cg_context, int& fail_index, bool visit_once) const
{
	FactMgr* fm = get_fact_mgr(&cg_context);
	// include outputs from all back edges leading to this block
	size_t i;
	static int g = 0;
	vector<const CFGEdge*> edges;
	int cnt = 0;
	do {
		// if we have never visited the block, force the visitor to go through all statements at least once
		if (fm->map_visited[this]) {
			if (cnt++ > 7) {
				// takes too many iterations to reach a fixed point, must be something wrong
				assert(0);
			}
			find_edges_in(edges, false, true);
			for (i=0; i<edges.size(); i++) {
				const Statement* src = edges[i]->src;
				//assert(fm->map_visited[src]);
				merge_facts(inputs, fm->map_facts_out[src]);
			}
		}
		if (!visit_once) {
			int shortcut = shortcut_analysis(inputs, cg_context);
			if (shortcut == 0) return true;
		}
		//if (shortcut == 1) return false;

		FactVec outputs = inputs;
		// add facts for locals
		for (i=0; i<local_vars.size(); i++) {
			const Variable* v = local_vars[i];
			FactMgr::add_new_var_fact(v, outputs);
		}

		// revisit statements with new inputs
		for (i=0; i<stms.size(); i++) {
			int h = g++;
			if (h == 2585)
				BREAK_NOP;		// for debugging
			if (!stms[i]->analyze_with_edges_in(outputs, cg_context)) {
				fail_index = i;
				return false;
			}
		}
		fm->set_fact_in(this, inputs);
		post_facts = outputs;
		FactMgr::update_facts_for_oos_vars(local_vars, outputs);
		fm->set_fact_out(this, outputs);
		fm->map_visited[this] = true;
		// compute accumulated effect
		set_accumulated_effect(cg_context);
		visit_once = false;
	} while (true);
	return true;
}
Example #4
0
Block *
Block::make_dummy_block(CGContext &cg_context)
{
	Function *curr_func = cg_context.get_current_func();
	assert(curr_func);

	Block *b = new Block(cg_context.get_current_block(), 0);
	b->func = curr_func;
	b->in_array_loop = !(cg_context.iv_bounds.empty());
	curr_func->blocks.push_back(b);
	curr_func->stack.push_back(b);
	FactMgr* fm = get_fact_mgr_for_func(curr_func);
	fm->set_fact_in(b, fm->global_facts);
	Effect pre_effect = cg_context.get_accum_effect();
	b->post_creation_analysis(cg_context, pre_effect);
	curr_func->stack.pop_back();
	return b;
}
Example #5
0
Statement* 
Block::append_return_stmt(CGContext& cg_context)
{
	FactMgr* fm = get_fact_mgr_for_func(func);
	FactVec pre_facts = fm->global_facts; 
	cg_context.get_effect_stm().clear();
	Statement* sr = Statement::make_random(cg_context, eReturn);
	ERROR_GUARD(NULL);
	stms.push_back(sr);
	fm->makeup_new_var_facts(pre_facts, fm->global_facts);
	assert(sr->visit_facts(fm->global_facts, cg_context));

	fm->set_fact_in(sr, pre_facts);
	fm->set_fact_out(sr, fm->global_facts); 
	fm->map_accum_effect[sr] = *(cg_context.get_effect_accum());
	fm->map_visited[sr] = true;
	//sr->post_creation_analysis(pre_facts, cg_context);
	fm->map_accum_effect[this] = *(cg_context.get_effect_accum());
	fm->map_stm_effect[this].add_effect(fm->map_stm_effect[sr]);
	return sr;
}
Example #6
0
Statement*
Block::append_nested_loop(CGContext& cg_context)
{
	FactMgr* fm = get_fact_mgr_for_func(func);
	FactVec pre_facts = fm->global_facts;
	cg_context.get_effect_stm().clear();

	Statement* sf = HYPOTHESIS_DRAW(Statement, cg_context, eFor);
	ERROR_GUARD(NULL);
	stms.push_back(sf);
	fm->makeup_new_var_facts(pre_facts, fm->global_facts);
	//assert(sf->visit_facts(fm->global_facts, cg_context));

	fm->set_fact_in(sf, pre_facts);
	fm->set_fact_out(sf, fm->global_facts);
	fm->map_accum_effect[sf] = *(cg_context.get_effect_accum());
	fm->map_visited[sf] = true;
	//sf->post_creation_analysis(pre_facts, cg_context);
	fm->map_accum_effect[this] = *(cg_context.get_effect_accum());
	fm->map_stm_effect[this].add_effect(fm->map_stm_effect[sf]);
	return sf;
}
Example #7
0
Block *
Block::make_random(CGContext &cg_context, bool looping)
{
	//static int bid = 0;
	DEPTH_GUARD_BY_TYPE_RETURN(dtBlock, NULL);

	Function *curr_func = cg_context.get_current_func();
	assert(curr_func);

	Block *b = new Block(cg_context.get_current_block(), CGOptions::max_block_size());
	b->func = curr_func;
	b->looping = looping;
	// if there are induction variables, we are in a loop that traverses array(s)
	b->in_array_loop = !(cg_context.iv_bounds.empty());
	//b->stm_id = bid++;

	// Push this block onto the variable scope stack.
	curr_func->stack.push_back(b);
	curr_func->blocks.push_back(b);

	// record global facts at this moment so that subsequent statement
	// inside the block doesn't ruin it
	FactMgr* fm = get_fact_mgr_for_func(curr_func);
	fm->set_fact_in(b, fm->global_facts);
	Effect pre_effect = cg_context.get_accum_effect();

	unsigned int max = BlockProbability(*b);
	if (Error::get_error() != SUCCESS) {
		curr_func->stack.pop_back();
		delete b;
		return NULL;
	}
	unsigned int i;
	if (b->stm_id == 1)
		BREAK_NOP;			// for debugging
	for (i = 0; i <= max; ++i) {
		Statement *s = HYPOTHESIS_DRAW(Statement, cg_context);
		// In the exhaustive mode, Statement::make_random could return NULL;
		if (!s)
			break;
		b->stms.push_back(s);
		if (s->must_return()) {
			break;
		}
	}

	if (Error::get_error() != SUCCESS) {
		curr_func->stack.pop_back();
		delete b;
		return NULL;
	}

	// append nested loop if some must-read/write variables hasn't been accessed
	if (b->need_nested_loop(cg_context) && cg_context.blk_depth < CGOptions::max_blk_depth()) {
		b->append_nested_loop(cg_context);
	}

	// perform DFA analysis after creation
	b->post_creation_analysis(cg_context, pre_effect);

	if (Error::get_error() != SUCCESS) {
		curr_func->stack.pop_back();
		delete b;
		return NULL;
	}

	curr_func->stack.pop_back();
	if (Error::get_error() != SUCCESS) {
		//curr_func->stack.pop_back();
		delete b;
		return NULL;
	}

	// ISSUE: in the exhaustive mode, do we need a return statement here
	// if the last statement is not?
	Error::set_error(SUCCESS);
	return b;
}