/**************************************************************************** * 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; }
/********************************************************************** * 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]); } }
bool Statement::stm_visit_facts(vector<const Fact*>& inputs, CGContext& cg_context) const { cg_context.get_effect_stm().clear(); cg_context.curr_blk = parent; FactMgr* fm = get_fact_mgr(&cg_context); //static int g = 0; //int h = g++; bool ok = visit_facts(inputs, cg_context); if (!ok && !is_compound(eType)) { failed_stm = this; } //if (!FactPointTo::is_valid_ptr("g_75", inputs)) // Output(cout, fm); fm->remove_rv_facts(inputs); fm->map_accum_effect[this] = *(cg_context.get_effect_accum()); fm->map_visited[this] = true; return ok; }