std::unique_ptr Types::infer_types_for_method()

in source/Types.cpp [133:191]


std::unique_ptr<TypeEnvironments> Types::infer_types_for_method(
    const Method* method) const {
  auto* code = method->get_code();
  if (!code) {
    WARNING(
        4,
        "Trying to get types for `{}` which does not have code.",
        method->show());
    return std::make_unique<TypeEnvironments>();
  }

  // Call TypeInference first, then use GlobalTypeAnalyzer to refine results.
  auto environments = infer_local_types_for_method(method);
  if (global_type_analyzer_ == nullptr) {
    return environments;
  }
  auto local_type_analyzer =
      global_type_analyzer_->get_local_analysis(method->dex_method());

  for (cfg::Block* block : code->cfg().blocks()) {
    auto current_state = local_type_analyzer->get_entry_state_at(block);
    for (auto& entry : InstructionIterable(block)) {
      auto* instruction = entry.insn;
      local_type_analyzer->analyze_instruction(instruction, &current_state);

      if (!is_interesting_opcode(instruction->opcode())) {
        continue;
      }
      auto found = environments->find(instruction);
      auto& environment_at_instruction = found->second;

      auto register_type_environment = current_state.get_reg_environment();
      if (!register_type_environment.is_value()) {
        continue;
      }
      for (auto& ir_register : instruction->srcs()) {
        DexTypeDomain domain = register_type_environment.get(ir_register);
        auto found = environment_at_instruction.find(ir_register);
        if (found != environment_at_instruction.end()) {
          auto dex_type = found->second;
          auto new_dex_type_domain =
              domain.is_top() ? DexTypeDomain(dex_type) : domain;
          auto new_dex_type = new_dex_type_domain.get_dex_type();
          environment_at_instruction[ir_register] =
              new_dex_type ? *new_dex_type : dex_type;
        } else {
          auto new_dex_type = domain.get_dex_type();
          if (new_dex_type) {
            environment_at_instruction[ir_register] = *new_dex_type;
          }
        }
      }

      local_type_analyzer->analyze_instruction(entry.insn, &current_state);
    }
  }

  return environments;
}