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, ¤t_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, ¤t_state);
}
}
return environments;
}