Beispiel #1
0
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;
  }
}
Beispiel #3
0
/*
 * 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;
}
Beispiel #4
0
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();
}