/**********************************************************************
 * once generated the loop body, verify whether some statement caused
 * the analyzer to fail during the 2nd iteration of the loop body (in
 * most case, a null/dead pointer dereference would do it), if so, delete
 * the statement in which analyzer fails and all subsequent statemets
 *
 * also performs effect analysis
 *********************************************************************/
void
Block::post_creation_analysis(CGContext& cg_context, const Effect& pre_effect)
{
	int index;
	FactMgr* fm = get_fact_mgr(&cg_context);
	fm->map_visited[this] = true;
	// compute accumulated effect
	set_accumulated_effect(cg_context);
	//fm->print_facts(fm->global_facts);
	vector<const Fact*> post_facts = fm->global_facts;
	FactMgr::update_facts_for_oos_vars(local_vars, fm->global_facts);
	fm->remove_rv_facts(fm->global_facts);
	fm->set_fact_out(this, fm->global_facts);

	// find out if fixed-point-searching is required
	bool is_loop_body = !must_break_or_return() && looping;
	bool self_back_edge = false;
	if (is_loop_body || need_revisit || has_edge_in(false, true)) {
		if (is_loop_body && from_tail_to_head()) {
			self_back_edge = true;
			fm->create_cfg_edge(this, this, false, true);
		}
		vector<const Fact*> facts_copy = fm->map_facts_in[this];
		// reset the accumulative effect
		cg_context.reset_effect_accum(pre_effect);
		while (!find_fixed_point(facts_copy, post_facts, cg_context, index, need_revisit)) {
			size_t i, len;
			len = stms.size();
			for (i=index; i<len; i++) {
				remove_stmt(stms[i]);
				i = index-1;
				len = stms.size();
			}
			// if we delete some statements, next visit must go through statements (no shortcut)
			need_revisit = true;
			// clean up in/out map from previous analysis that might include facts caused by deleted statements
			fm->reset_stm_fact_maps(this);
			// sometimes a loop would emerge after we delete the "return" statement in body
			if (!self_back_edge && from_tail_to_head()) {
				self_back_edge = true;
				fm->create_cfg_edge(this, this, false, true);
			}
			// reset incoming effects
			cg_context.reset_effect_accum(pre_effect);
		}
		fm->global_facts = fm->map_facts_out[this];
	}
	// make sure we add back return statement for blocks that require it and had such statement deleted
	// only do this for top-level block of a function which requires a return statement
	if (parent == 0 && func->need_return_stmt() && !must_return()) {
		fm->global_facts = post_facts;
		Statement* sr = append_return_stmt(cg_context);
		fm->set_fact_out(this, fm->map_facts_out[sr]);
	}
}
StatementContinue *
StatementContinue::make_random(CGContext &cg_context)
{
	//static int g =0;
	FactMgr* fm = get_fact_mgr(&cg_context);
	// find the closest looping parent block: the one "continue"
	// would apply to
	//int h = g++;
	const Block* b = cg_context.get_current_block();
	const Statement* prev_stm = b->get_last_stm();
	// don't generate "continue" as the first statement in a block
	if (prev_stm == 0) {
		return 0;
	}
	while (b && !b->looping) {
		b = b->parent;
	}
	assert(b);
	cg_context.get_effect_stm().clear();
	Expression *expr = HYPOTHESIS_DRAW(Expression, cg_context, get_int_type(), 0, true, true, eVariable);
	ERROR_GUARD(NULL);
	StatementContinue* sc = new StatementContinue(cg_context.get_current_block(), *expr, *b);
	fm->create_cfg_edge(sc, b, false, true);
    return sc;
}
Exemple #3
0
void
StatementFor::post_loop_analysis(CGContext& cg_context, vector<const Fact*>& pre_facts, Effect& pre_effect)
{
	FactMgr* fm = get_fact_mgr(&cg_context);
	assert(fm);
	// if the control reached the end of this for-loop with must-return body, it means
	// the loop is never entered. restore facts to pre-loop env
	fm->global_facts = fm->map_facts_in[&body];
	if (body.must_return()) {
		fm->restore_facts(pre_facts);
	}
	// add forward edges introduced by "break"
	for (size_t i=0; i<body.break_stms.size(); i++) {
		const StatementBreak* stm = dynamic_cast<const StatementBreak*>(body.break_stms[i]);
		fm->create_cfg_edge(stm, this, true, false);
		FactMgr::merge_jump_facts(fm->global_facts, fm->map_facts_out[stm]);
	}
	// compute accumulated effect
	set_accumulated_effect_after_block(pre_effect, &body, cg_context);
}