UsedVarsFixpointIterator::UsedVarsFixpointIterator( const local_pointers::FixpointIterator& pointers_fp_iter, const EffectSummaryMap& effect_summaries, const std::unordered_set<const DexMethod*>& non_overridden_virtuals, const cfg::ControlFlowGraph& cfg) : MonotonicFixpointIterator(cfg, cfg.blocks().size()), m_insn_env_map(gen_instruction_environment_map(cfg, pointers_fp_iter)), m_effect_summaries(effect_summaries), m_non_overridden_virtuals(non_overridden_virtuals) {}
boost::optional<ParamIndex> find_return_param_index( cfg::ControlFlowGraph& cfg) { for (auto& mie : InstructionIterable(cfg)) { TRACE(RP, 2, " %s\n", SHOW(mie.insn)); } // find register that is being returned (if any) cfg.calculate_exit_block(); auto exit_block = cfg.exit_block(); auto it = exit_block->rbegin(); if (it == exit_block->rend() || !is_return_value(it->insn->opcode())) return boost::none; auto return_reg = it->insn->src(0); TRACE(RP, 2, " returns v%d\n", return_reg); ++it; if (it == exit_block->rend() || !is_move(it->insn->opcode())) return boost::none; auto src_reg = it->insn->src(0); TRACE(RP, 2, " move v%d, v%d\n", it->insn->dest(), src_reg); if (it->insn->dest() != return_reg) return boost::none; // let's see if it came from a unique load-param IRInstruction* load_param = nullptr; for (auto& mie : InstructionIterable(cfg)) { if (mie.insn->dests_size()) { if (mie.insn->dest() == src_reg) { if (opcode::is_load_param(mie.insn->opcode())) { load_param = mie.insn; } else { TRACE(RP, 2, " move_reg clobbered\n"); return boost::none; } } } } if (load_param != nullptr) { ParamIndex param_index = get_load_param_map(cfg).at(load_param); TRACE(RP, 2, " found matching load-param %d\n", param_index); return param_index; } else { TRACE(RP, 2, " did not find matching load-param\n"); return boost::none; } }
/* * Record the environment before the execution of every instruction. We need * this data during the backwards used vars analysis. */ static std::unordered_map<const IRInstruction*, ptrs::Environment> gen_instruction_environment_map(const cfg::ControlFlowGraph& cfg, const ptrs::FixpointIterator& fp_iter) { std::unordered_map<const IRInstruction*, ptrs::Environment> result; for (auto* block : cfg.blocks()) { auto env = fp_iter.get_entry_state_at(block); for (auto& mie : InstructionIterable(block)) { auto* insn = mie.insn; result.emplace(insn, env); fp_iter.analyze_instruction(insn, &env); } } return result; }
std::string show(const cfg::ControlFlowGraph& cfg) { const auto& blocks = cfg.blocks(); std::ostringstream ss; ss << "CFG:\n"; for (const auto& b : blocks) { ss << " Block B" << b->id() << ":\n"; ss << " preds:"; for (const auto& p : b->preds()) { ss << " (" << *p << " B" << p->src()->id() << ")"; } ss << "\n"; ss << show(b); ss << " succs:"; for (auto& s : b->succs()) { ss << " (" << *s << " B" << s->target()->id() << ")"; } ss << "\n"; } return ss.str(); }