/********************************************************************** * 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; }
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); }