* 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 *********************************************************************/
| 750 | * also performs effect analysis |
| 751 | *********************************************************************/ |
| 752 | void |
| 753 | Block::post_creation_analysis(CGContext& cg_context, const Effect& pre_effect) |
| 754 | { |
| 755 | int index; |
| 756 | FactMgr* fm = get_fact_mgr(&cg_context); |
| 757 | fm->map_visited[this] = true; |
| 758 | // compute accumulated effect |
| 759 | set_accumulated_effect(cg_context); |
| 760 | //fm->print_facts(fm->global_facts); |
| 761 | vector<const Fact*> post_facts = fm->global_facts; |
| 762 | FactMgr::update_facts_for_oos_vars(local_vars, fm->global_facts); |
| 763 | fm->remove_rv_facts(fm->global_facts); |
| 764 | fm->set_fact_out(this, fm->global_facts); |
| 765 | |
| 766 | // find out if fixed-point-searching is required |
| 767 | bool is_loop_body = !must_break_or_return() && looping; |
| 768 | bool self_back_edge = false; |
| 769 | if (is_loop_body || need_revisit || has_edge_in(false, true)) { |
| 770 | if (is_loop_body && from_tail_to_head()) { |
| 771 | self_back_edge = true; |
| 772 | fm->create_cfg_edge(this, this, false, true); |
| 773 | } |
| 774 | vector<const Fact*> facts_copy = fm->map_facts_in[this]; |
| 775 | // reset the accumulative effect |
| 776 | cg_context.reset_effect_accum(pre_effect); |
| 777 | while (!find_fixed_point(facts_copy, post_facts, cg_context, index, need_revisit)) { |
| 778 | size_t i, len; |
| 779 | len = stms.size(); |
| 780 | for (i=index; i<len; i++) { |
| 781 | remove_stmt(stms[i]); |
| 782 | i = index-1; |
| 783 | len = stms.size(); |
| 784 | } |
| 785 | // if we delete some statements, next visit must go through statements (no shortcut) |
| 786 | need_revisit = true; |
| 787 | // clean up in/out map from previous analysis that might include facts caused by deleted statements |
| 788 | fm->reset_stm_fact_maps(this); |
| 789 | // sometimes a loop would emerge after we delete the "return" statement in body |
| 790 | if (!self_back_edge && from_tail_to_head()) { |
| 791 | self_back_edge = true; |
| 792 | fm->create_cfg_edge(this, this, false, true); |
| 793 | } |
| 794 | // reset incoming effects |
| 795 | cg_context.reset_effect_accum(pre_effect); |
| 796 | } |
| 797 | fm->global_facts = fm->map_facts_out[this]; |
| 798 | } |
| 799 | // make sure we add back return statement for blocks that require it and had such statement deleted |
| 800 | // only do this for top-level block of a function which requires a return statement |
| 801 | if (parent == 0 && func->need_return_stmt() && !must_return()) { |
| 802 | fm->global_facts = post_facts; |
| 803 | Statement* sr = append_return_stmt(cg_context); |
| 804 | fm->set_fact_out(this, fm->map_facts_out[sr]); |
| 805 | } |
| 806 | } |
| 807 | |
| 808 | /////////////////////////////////////////////////////////////////////////////// |
| 809 |
no test coverage detected