/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "flow_analysis.h"

#include "dex/bytecode_utils.h"
#include "dex/class_accessor-inl.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/dex_instruction-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_exception_helpers.h"
#include "resolver.h"
#include "veridex.h"

namespace art {

VeriFlowAnalysis::VeriFlowAnalysis(VeridexResolver* resolver,
                                   const ClassAccessor::Method& method)
    : resolver_(resolver),
      method_id_(method.GetIndex()),
      code_item_accessor_(method.GetInstructionsAndData()),
      dex_registers_(code_item_accessor_.InsnsSizeInCodeUnits()),
      instruction_infos_(code_item_accessor_.InsnsSizeInCodeUnits()) {}

void VeriFlowAnalysis::SetAsBranchTarget(uint32_t dex_pc) {
  if (dex_registers_[dex_pc] == nullptr) {
    dex_registers_[dex_pc].reset(
        new std::vector<RegisterValue>(code_item_accessor_.RegistersSize()));
  }
}

bool VeriFlowAnalysis::IsBranchTarget(uint32_t dex_pc) {
  return dex_registers_[dex_pc] != nullptr;
}

bool VeriFlowAnalysis::MergeRegisterValues(uint32_t dex_pc) {
  // TODO: Do the merging. Right now, just return that we should continue
  // the iteration if the instruction has not been visited.
  if (!instruction_infos_[dex_pc].has_been_visited) {
    dex_registers_[dex_pc]->assign(current_registers_.begin(), current_registers_.end());
    return true;
  }
  return false;
}

void VeriFlowAnalysis::SetVisited(uint32_t dex_pc) {
  instruction_infos_[dex_pc].has_been_visited = true;
}

void VeriFlowAnalysis::FindBranches() {
  SetAsBranchTarget(0);

  if (code_item_accessor_.TriesSize() != 0) {
    // TODO: We need to mark the range of dex pcs as flowing in the handlers.
    /*
    for (const DexFile::TryItem& try_item : code_item_accessor_.TryItems()) {
      uint32_t dex_pc_start = try_item.start_addr_;
      uint32_t dex_pc_end = dex_pc_start + try_item.insn_count_;
    }
    */

    // Create branch targets for exception handlers.
    const uint8_t* handlers_ptr = code_item_accessor_.GetCatchHandlerData();
    uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
    for (uint32_t idx = 0; idx < handlers_size; ++idx) {
      CatchHandlerIterator iterator(handlers_ptr);
      for (; iterator.HasNext(); iterator.Next()) {
        SetAsBranchTarget(iterator.GetHandlerAddress());
      }
      handlers_ptr = iterator.EndDataPointer();
    }
  }

  // Iterate over all instructions and find branching instructions.
  for (const DexInstructionPcPair& pair : code_item_accessor_) {
    const uint32_t dex_pc = pair.DexPc();
    const Instruction& instruction = pair.Inst();

    if (instruction.IsBranch()) {
      SetAsBranchTarget(dex_pc + instruction.GetTargetOffset());
    } else if (instruction.IsSwitch()) {
      DexSwitchTable table(instruction, dex_pc);
      for (DexSwitchTableIterator s_it(table); !s_it.Done(); s_it.Advance()) {
        SetAsBranchTarget(dex_pc + s_it.CurrentTargetOffset());
        if (table.ShouldBuildDecisionTree() && !s_it.IsLast()) {
          SetAsBranchTarget(s_it.GetDexPcForCurrentIndex());
        }
      }
    }
  }
}

void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register,
                                      RegisterSource kind,
                                      VeriClass* cls,
                                      uint32_t source_id) {
  current_registers_[dex_register] = RegisterValue(
      kind, DexFileReference(&resolver_->GetDexFile(), source_id), cls);
}

void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, const RegisterValue& value) {
  current_registers_[dex_register] = value;
}

void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, const VeriClass* cls) {
  current_registers_[dex_register] =
      RegisterValue(RegisterSource::kNone, DexFileReference(nullptr, 0), cls);
}

void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, int32_t value, const VeriClass* cls) {
  current_registers_[dex_register] =
      RegisterValue(RegisterSource::kConstant, value, DexFileReference(nullptr, 0), cls);
}

const RegisterValue& VeriFlowAnalysis::GetRegister(uint32_t dex_register) const {
  return current_registers_[dex_register];
}

RegisterValue VeriFlowAnalysis::GetReturnType(uint32_t method_index) {
  const DexFile& dex_file = resolver_->GetDexFile();
  const dex::MethodId& method_id = dex_file.GetMethodId(method_index);
  const dex::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
  VeriClass* cls = resolver_->GetVeriClass(proto_id.return_type_idx_);
  return RegisterValue(RegisterSource::kMethod, DexFileReference(&dex_file, method_index), cls);
}

RegisterValue VeriFlowAnalysis::GetFieldType(uint32_t field_index) {
  const DexFile& dex_file = resolver_->GetDexFile();
  const dex::FieldId& field_id = dex_file.GetFieldId(field_index);
  VeriClass* cls = resolver_->GetVeriClass(field_id.type_idx_);
  return RegisterValue(RegisterSource::kField, DexFileReference(&dex_file, field_index), cls);
}

int VeriFlowAnalysis::GetBranchFlags(const Instruction& instruction) const {
  switch (instruction.Opcode()) {
    #define IF_XX(cond, op) \
    case Instruction::IF_##cond: { \
      RegisterValue lhs = GetRegister(instruction.VRegA()); \
      RegisterValue rhs = GetRegister(instruction.VRegB()); \
      if (lhs.IsConstant() && rhs.IsConstant()) { \
        if (lhs.GetConstant() op rhs.GetConstant()) { \
          return Instruction::kBranch; \
        } else { \
          return Instruction::kContinue; \
        } \
      } \
      break; \
    } \
    case Instruction::IF_##cond##Z: { \
      RegisterValue val = GetRegister(instruction.VRegA()); \
      if (val.IsConstant()) { \
        if (val.GetConstant() op 0) {  /* NOLINT */ \
          return Instruction::kBranch; \
        } else { \
          return Instruction::kContinue; \
        } \
      } \
      break; \
    }

    IF_XX(EQ, ==);
    IF_XX(NE, !=);
    IF_XX(LT, <);
    IF_XX(LE, <=);
    IF_XX(GT, >);
    IF_XX(GE, >=);

    #undef IF_XX

    default:
      break;
  }

  return Instruction::FlagsOf(instruction.Opcode());
}

void VeriFlowAnalysis::AnalyzeCode() {
  std::vector<uint32_t> work_list;
  work_list.push_back(0);
  // Iterate over the code.
  // When visiting unconditional branches (goto), move to that instruction.
  // When visiting conditional branches, move to one destination, and put the other
  // in the worklist.
  while (!work_list.empty()) {
    uint32_t dex_pc = work_list.back();
    work_list.pop_back();
    CHECK(IsBranchTarget(dex_pc));
    current_registers_ = *dex_registers_[dex_pc].get();
    while (true) {
      const uint16_t* insns = code_item_accessor_.Insns() + dex_pc;
      const Instruction& inst = *Instruction::At(insns);
      ProcessDexInstruction(inst);
      SetVisited(dex_pc);

      int branch_flags = GetBranchFlags(inst);

      if ((branch_flags & Instruction::kContinue) != 0) {
        if ((branch_flags & Instruction::kBranch) != 0) {
          uint32_t branch_dex_pc = dex_pc + inst.GetTargetOffset();
          if (MergeRegisterValues(branch_dex_pc)) {
            work_list.push_back(branch_dex_pc);
          }
        }
        dex_pc += inst.SizeInCodeUnits();
      } else if ((branch_flags & Instruction::kBranch) != 0) {
        dex_pc += inst.GetTargetOffset();
        DCHECK(IsBranchTarget(dex_pc));
      } else {
        break;
      }

      if (IsBranchTarget(dex_pc)) {
        if (MergeRegisterValues(dex_pc)) {
          current_registers_ = *dex_registers_[dex_pc].get();
        } else {
          break;
        }
      }
    }
  }
}

void VeriFlowAnalysis::ProcessDexInstruction(const Instruction& instruction) {
  switch (instruction.Opcode()) {
    case Instruction::CONST_4: {
      int32_t register_index = instruction.VRegA();
      int32_t value = instruction.VRegB_11n();
      UpdateRegister(register_index, value, VeriClass::integer_);
      break;
    }
    case Instruction::CONST_16: {
      int32_t register_index = instruction.VRegA();
      int32_t value = instruction.VRegB_21s();
      UpdateRegister(register_index, value, VeriClass::integer_);
      break;
    }

    case Instruction::CONST: {
      int32_t register_index = instruction.VRegA();
      int32_t value = instruction.VRegB_31i();
      UpdateRegister(register_index, value, VeriClass::integer_);
      break;
    }

    case Instruction::CONST_HIGH16: {
      int32_t register_index = instruction.VRegA();
      int32_t value = instruction.VRegB_21h();
      UpdateRegister(register_index, value, VeriClass::integer_);
      break;
    }

    case Instruction::CONST_WIDE_16:
    case Instruction::CONST_WIDE_32:
    case Instruction::CONST_WIDE:
    case Instruction::CONST_WIDE_HIGH16: {
      int32_t register_index = instruction.VRegA();
      UpdateRegister(register_index, VeriClass::long_);
      break;
    }

    case Instruction::MOVE:
    case Instruction::MOVE_FROM16:
    case Instruction::MOVE_16: {
      UpdateRegister(instruction.VRegA(), GetRegister(instruction.VRegB()));
      break;
    }

    case Instruction::MOVE_WIDE:
    case Instruction::MOVE_WIDE_FROM16:
    case Instruction::MOVE_WIDE_16: {
      UpdateRegister(instruction.VRegA(), GetRegister(instruction.VRegB()));
      break;
    }

    case Instruction::MOVE_OBJECT:
    case Instruction::MOVE_OBJECT_16:
    case Instruction::MOVE_OBJECT_FROM16: {
      UpdateRegister(instruction.VRegA(), GetRegister(instruction.VRegB()));
      break;
    }
    case Instruction::CONST_CLASS: {
      UpdateRegister(instruction.VRegA_21c(),
                     RegisterSource::kClass,
                     VeriClass::class_,
                     instruction.VRegB_21c());
      break;
    }
    case Instruction::CONST_STRING: {
      UpdateRegister(instruction.VRegA_21c(),
                     RegisterSource::kString,
                     VeriClass::string_,
                     instruction.VRegB_21c());
      break;
    }

    case Instruction::CONST_STRING_JUMBO: {
      UpdateRegister(instruction.VRegA_31c(),
                     RegisterSource::kString,
                     VeriClass::string_,
                     instruction.VRegB_31c());
      break;
    }
    case Instruction::INVOKE_DIRECT:
    case Instruction::INVOKE_INTERFACE:
    case Instruction::INVOKE_STATIC:
    case Instruction::INVOKE_SUPER:
    case Instruction::INVOKE_VIRTUAL: {
      last_result_ = AnalyzeInvoke(instruction, /* is_range= */ false);
      break;
    }

    case Instruction::INVOKE_DIRECT_RANGE:
    case Instruction::INVOKE_INTERFACE_RANGE:
    case Instruction::INVOKE_STATIC_RANGE:
    case Instruction::INVOKE_SUPER_RANGE:
    case Instruction::INVOKE_VIRTUAL_RANGE: {
      last_result_ = AnalyzeInvoke(instruction, /* is_range= */ true);
      break;
    }

    case Instruction::MOVE_RESULT:
    case Instruction::MOVE_RESULT_WIDE:
    case Instruction::MOVE_RESULT_OBJECT: {
      UpdateRegister(instruction.VRegA(), last_result_);
      break;
    }
    case Instruction::RETURN_VOID:
    case Instruction::RETURN_OBJECT:
    case Instruction::RETURN_WIDE:
    case Instruction::RETURN: {
      break;
    }

    // If operations will be handled when looking at the control flow.
    #define IF_XX(cond) \
    case Instruction::IF_##cond: break; \
    case Instruction::IF_##cond##Z: break

    IF_XX(EQ);
    IF_XX(NE);
    IF_XX(LT);
    IF_XX(LE);
    IF_XX(GT);
    IF_XX(GE);

    #undef IF_XX

    case Instruction::GOTO:
    case Instruction::GOTO_16:
    case Instruction::GOTO_32: {
      break;
    }
    case Instruction::INVOKE_POLYMORPHIC: {
      // TODO
      break;
    }

    case Instruction::INVOKE_POLYMORPHIC_RANGE: {
      // TODO
      break;
    }

    case Instruction::NEG_INT:
    case Instruction::NEG_LONG:
    case Instruction::NEG_FLOAT:
    case Instruction::NEG_DOUBLE:
    case Instruction::NOT_INT:
    case Instruction::NOT_LONG: {
      UpdateRegister(instruction.VRegA(), VeriClass::integer_);
      break;
    }

    case Instruction::INT_TO_LONG:
    case Instruction::INT_TO_FLOAT:
    case Instruction::INT_TO_DOUBLE:
    case Instruction::LONG_TO_INT:
    case Instruction::LONG_TO_FLOAT:
    case Instruction::LONG_TO_DOUBLE:
    case Instruction::FLOAT_TO_INT:
    case Instruction::FLOAT_TO_LONG:
    case Instruction::FLOAT_TO_DOUBLE:
    case Instruction::DOUBLE_TO_INT:
    case Instruction::DOUBLE_TO_LONG:
    case Instruction::DOUBLE_TO_FLOAT:
    case Instruction::INT_TO_BYTE:
    case Instruction::INT_TO_SHORT:
    case Instruction::INT_TO_CHAR: {
      UpdateRegister(instruction.VRegA(), VeriClass::integer_);
      break;
    }

    case Instruction::ADD_INT:
    case Instruction::ADD_LONG:
    case Instruction::ADD_DOUBLE:
    case Instruction::ADD_FLOAT:
    case Instruction::SUB_INT:
    case Instruction::SUB_LONG:
    case Instruction::SUB_FLOAT:
    case Instruction::SUB_DOUBLE:
    case Instruction::MUL_INT:
    case Instruction::MUL_LONG:
    case Instruction::MUL_FLOAT:
    case Instruction::MUL_DOUBLE:
    case Instruction::DIV_INT:
    case Instruction::DIV_LONG:
    case Instruction::DIV_FLOAT:
    case Instruction::DIV_DOUBLE:
    case Instruction::REM_INT:
    case Instruction::REM_LONG:
    case Instruction::REM_FLOAT:
    case Instruction::REM_DOUBLE:
    case Instruction::AND_INT:
    case Instruction::AND_LONG:
    case Instruction::SHL_INT:
    case Instruction::SHL_LONG:
    case Instruction::SHR_INT:
    case Instruction::SHR_LONG:
    case Instruction::USHR_INT:
    case Instruction::USHR_LONG:
    case Instruction::OR_INT:
    case Instruction::OR_LONG:
    case Instruction::XOR_INT:
    case Instruction::XOR_LONG: {
      UpdateRegister(instruction.VRegA(), VeriClass::integer_);
      break;
    }

    case Instruction::ADD_INT_2ADDR:
    case Instruction::ADD_LONG_2ADDR:
    case Instruction::ADD_DOUBLE_2ADDR:
    case Instruction::ADD_FLOAT_2ADDR:
    case Instruction::SUB_INT_2ADDR:
    case Instruction::SUB_LONG_2ADDR:
    case Instruction::SUB_FLOAT_2ADDR:
    case Instruction::SUB_DOUBLE_2ADDR:
    case Instruction::MUL_INT_2ADDR:
    case Instruction::MUL_LONG_2ADDR:
    case Instruction::MUL_FLOAT_2ADDR:
    case Instruction::MUL_DOUBLE_2ADDR:
    case Instruction::DIV_INT_2ADDR:
    case Instruction::DIV_LONG_2ADDR:
    case Instruction::REM_INT_2ADDR:
    case Instruction::REM_LONG_2ADDR:
    case Instruction::REM_FLOAT_2ADDR:
    case Instruction::REM_DOUBLE_2ADDR:
    case Instruction::SHL_INT_2ADDR:
    case Instruction::SHL_LONG_2ADDR:
    case Instruction::SHR_INT_2ADDR:
    case Instruction::SHR_LONG_2ADDR:
    case Instruction::USHR_INT_2ADDR:
    case Instruction::USHR_LONG_2ADDR:
    case Instruction::DIV_FLOAT_2ADDR:
    case Instruction::DIV_DOUBLE_2ADDR:
    case Instruction::AND_INT_2ADDR:
    case Instruction::AND_LONG_2ADDR:
    case Instruction::OR_INT_2ADDR:
    case Instruction::OR_LONG_2ADDR:
    case Instruction::XOR_INT_2ADDR:
    case Instruction::XOR_LONG_2ADDR: {
      UpdateRegister(instruction.VRegA(), VeriClass::integer_);
      break;
    }

    case Instruction::ADD_INT_LIT16:
    case Instruction::AND_INT_LIT16:
    case Instruction::OR_INT_LIT16:
    case Instruction::XOR_INT_LIT16:
    case Instruction::RSUB_INT:
    case Instruction::MUL_INT_LIT16:
    case Instruction::DIV_INT_LIT16:
    case Instruction::REM_INT_LIT16: {
      UpdateRegister(instruction.VRegA(), VeriClass::integer_);
      break;
    }

    case Instruction::ADD_INT_LIT8:
    case Instruction::AND_INT_LIT8:
    case Instruction::OR_INT_LIT8:
    case Instruction::XOR_INT_LIT8:
    case Instruction::RSUB_INT_LIT8:
    case Instruction::MUL_INT_LIT8:
    case Instruction::DIV_INT_LIT8:
    case Instruction::REM_INT_LIT8:
    case Instruction::SHL_INT_LIT8:
    case Instruction::SHR_INT_LIT8:
    case Instruction::USHR_INT_LIT8: {
      UpdateRegister(instruction.VRegA(), VeriClass::integer_);
      break;
    }

    case Instruction::NEW_INSTANCE: {
      VeriClass* cls = resolver_->GetVeriClass(dex::TypeIndex(instruction.VRegB_21c()));
      UpdateRegister(instruction.VRegA(), cls);
      break;
    }

    case Instruction::NEW_ARRAY: {
      dex::TypeIndex type_index(instruction.VRegC_22c());
      VeriClass* cls = resolver_->GetVeriClass(type_index);
      UpdateRegister(instruction.VRegA_22c(), cls);
      break;
    }

    case Instruction::FILLED_NEW_ARRAY: {
      dex::TypeIndex type_index(instruction.VRegB_35c());
      VeriClass* cls = resolver_->GetVeriClass(type_index);
      UpdateRegister(instruction.VRegA_22c(), cls);
      break;
    }

    case Instruction::FILLED_NEW_ARRAY_RANGE: {
      dex::TypeIndex type_index(instruction.VRegB_3rc());
      uint32_t register_index = instruction.VRegC_3rc();
      VeriClass* cls = resolver_->GetVeriClass(type_index);
      UpdateRegister(register_index, cls);
      break;
    }

    case Instruction::FILL_ARRAY_DATA: {
      break;
    }

    case Instruction::CMP_LONG:
    case Instruction::CMPG_FLOAT:
    case Instruction::CMPG_DOUBLE:
    case Instruction::CMPL_FLOAT:
    case Instruction::CMPL_DOUBLE: {
      UpdateRegister(instruction.VRegA(), VeriClass::integer_);
      break;
    }

    case Instruction::NOP:
      break;

    case Instruction::IGET:
    case Instruction::IGET_WIDE:
    case Instruction::IGET_OBJECT:
    case Instruction::IGET_BOOLEAN:
    case Instruction::IGET_BYTE:
    case Instruction::IGET_CHAR:
    case Instruction::IGET_SHORT: {
      UpdateRegister(instruction.VRegA_22c(), GetFieldType(instruction.VRegC_22c()));
      break;
    }

    case Instruction::IPUT:
    case Instruction::IPUT_WIDE:
    case Instruction::IPUT_OBJECT:
    case Instruction::IPUT_BOOLEAN:
    case Instruction::IPUT_BYTE:
    case Instruction::IPUT_CHAR:
    case Instruction::IPUT_SHORT: {
      AnalyzeFieldSet(instruction);
      break;
    }

    case Instruction::SGET:
    case Instruction::SGET_WIDE:
    case Instruction::SGET_OBJECT:
    case Instruction::SGET_BOOLEAN:
    case Instruction::SGET_BYTE:
    case Instruction::SGET_CHAR:
    case Instruction::SGET_SHORT: {
      uint32_t dest_reg = instruction.VRegA_21c();
      uint16_t field_index = instruction.VRegB_21c();
      if (VeriClass::sdkInt_ != nullptr && resolver_->GetField(field_index) == VeriClass::sdkInt_) {
        UpdateRegister(dest_reg, gTargetSdkVersion, VeriClass::integer_);
      } else {
        UpdateRegister(dest_reg, GetFieldType(instruction.VRegC_22c()));
      }
      break;
    }

    case Instruction::SPUT:
    case Instruction::SPUT_WIDE:
    case Instruction::SPUT_OBJECT:
    case Instruction::SPUT_BOOLEAN:
    case Instruction::SPUT_BYTE:
    case Instruction::SPUT_CHAR:
    case Instruction::SPUT_SHORT: {
      AnalyzeFieldSet(instruction);
      break;
    }

#define ARRAY_XX(kind, anticipated_type)                                          \
    case Instruction::AGET##kind: {                                               \
      UpdateRegister(instruction.VRegA_23x(), anticipated_type);                  \
      break;                                                                      \
    }                                                                             \
    case Instruction::APUT##kind: {                                               \
      break;                                                                      \
    }

    ARRAY_XX(, VeriClass::integer_);
    ARRAY_XX(_WIDE, VeriClass::long_);
    ARRAY_XX(_BOOLEAN, VeriClass::boolean_);
    ARRAY_XX(_BYTE, VeriClass::byte_);
    ARRAY_XX(_CHAR, VeriClass::char_);
    ARRAY_XX(_SHORT, VeriClass::short_);

    case Instruction::AGET_OBJECT: {
      // TODO: take the component type.
      UpdateRegister(instruction.VRegA_23x(), VeriClass::object_);
      break;
    }

    case Instruction::APUT_OBJECT: {
      break;
    }

    case Instruction::ARRAY_LENGTH: {
      UpdateRegister(instruction.VRegA_12x(), VeriClass::integer_);
      break;
    }

    case Instruction::MOVE_EXCEPTION: {
      UpdateRegister(instruction.VRegA_11x(), VeriClass::throwable_);
      break;
    }

    case Instruction::THROW: {
      break;
    }

    case Instruction::INSTANCE_OF: {
      uint8_t destination = instruction.VRegA_22c();
      UpdateRegister(destination, VeriClass::boolean_);
      break;
    }

    case Instruction::CHECK_CAST: {
      uint8_t reference = instruction.VRegA_21c();
      dex::TypeIndex type_index(instruction.VRegB_21c());
      UpdateRegister(reference, resolver_->GetVeriClass(type_index));
      break;
    }

    case Instruction::MONITOR_ENTER:
    case Instruction::MONITOR_EXIT: {
      break;
    }

    case Instruction::SPARSE_SWITCH:
    case Instruction::PACKED_SWITCH:
      break;

    default:
      break;
  }
}

void VeriFlowAnalysis::Run() {
  FindBranches();
  uint32_t number_of_registers = code_item_accessor_.RegistersSize();
  uint32_t number_of_parameters = code_item_accessor_.InsSize();
  std::vector<RegisterValue>& initial_values = *dex_registers_[0].get();
  for (uint32_t i = 0; i < number_of_parameters; ++i) {
    initial_values[number_of_registers - number_of_parameters + i] = RegisterValue(
      RegisterSource::kParameter,
      i,
      DexFileReference(&resolver_->GetDexFile(), method_id_),
      nullptr);
  }
  AnalyzeCode();
}

static uint32_t GetParameterAt(const Instruction& instruction,
                               bool is_range,
                               uint32_t* args,
                               uint32_t index) {
  return is_range ? instruction.VRegC() + index : args[index];
}

RegisterValue FlowAnalysisCollector::AnalyzeInvoke(const Instruction& instruction, bool is_range) {
  uint32_t id = is_range ? instruction.VRegB_3rc() : instruction.VRegB_35c();
  VeriMethod method = resolver_->GetMethod(id);
  uint32_t args[5];
  if (!is_range) {
    instruction.GetVarArgs(args);
  }

  if (method == VeriClass::forName_) {
    // Class.forName. Fetch the first parameter.
    RegisterValue value = GetRegister(GetParameterAt(instruction, is_range, args, 0));
    return RegisterValue(
        value.GetSource(), value.GetDexFileReference(), VeriClass::class_);
  } else if (IsGetField(method)) {
    // Class.getField or Class.getDeclaredField. Fetch the first parameter for the class, and the
    // second parameter for the field name.
    RegisterValue cls = GetRegister(GetParameterAt(instruction, is_range, args, 0));
    RegisterValue name = GetRegister(GetParameterAt(instruction, is_range, args, 1));
    uses_.push_back(ReflectAccessInfo(cls, name, /* is_method= */ false));
    return GetReturnType(id);
  } else if (IsGetMethod(method)) {
    // Class.getMethod or Class.getDeclaredMethod. Fetch the first parameter for the class, and the
    // second parameter for the field name.
    RegisterValue cls = GetRegister(GetParameterAt(instruction, is_range, args, 0));
    RegisterValue name = GetRegister(GetParameterAt(instruction, is_range, args, 1));
    uses_.push_back(ReflectAccessInfo(cls, name, /* is_method= */ true));
    return GetReturnType(id);
  } else if (method == VeriClass::getClass_) {
    // Get the type of the first parameter.
    RegisterValue obj = GetRegister(GetParameterAt(instruction, is_range, args, 0));
    const VeriClass* cls = obj.GetType();
    if (cls != nullptr && cls->GetClassDef() != nullptr) {
      const dex::ClassDef* def = cls->GetClassDef();
      return RegisterValue(
          RegisterSource::kClass,
          DexFileReference(&resolver_->GetDexFileOf(*cls), def->class_idx_.index_),
          VeriClass::class_);
    } else {
      return RegisterValue(
          obj.GetSource(), obj.GetDexFileReference(), VeriClass::class_);
    }
  } else if (method == VeriClass::loadClass_) {
    // ClassLoader.loadClass. Fetch the first parameter.
    RegisterValue value = GetRegister(GetParameterAt(instruction, is_range, args, 1));
    return RegisterValue(
        value.GetSource(), value.GetDexFileReference(), VeriClass::class_);
  } else {
    // Return a RegisterValue referencing the method whose type is the return type
    // of the method.
    return GetReturnType(id);
  }
}

void FlowAnalysisCollector::AnalyzeFieldSet(const Instruction& instruction ATTRIBUTE_UNUSED) {
  // There are no fields that escape reflection uses.
}

RegisterValue FlowAnalysisSubstitutor::AnalyzeInvoke(const Instruction& instruction,
                                                     bool is_range) {
  uint32_t id = is_range ? instruction.VRegB_3rc() : instruction.VRegB_35c();
  MethodReference method(&resolver_->GetDexFile(), id);
  // TODO: doesn't work for multidex
  // TODO: doesn't work for overriding (but maybe should be done at a higher level);
  auto method_accesses_it = accesses_.find(method);
  if (method_accesses_it == accesses_.end()) {
    return GetReturnType(id);
  }
  uint32_t args[5];
  if (!is_range) {
    instruction.GetVarArgs(args);
  }
  for (const ReflectAccessInfo& info : method_accesses_it->second) {
    if (info.cls.IsParameter() || info.name.IsParameter()) {
      RegisterValue cls = info.cls.IsParameter()
          ? GetRegister(GetParameterAt(instruction, is_range, args, info.cls.GetParameterIndex()))
          : info.cls;
      RegisterValue name = info.name.IsParameter()
          ? GetRegister(GetParameterAt(instruction, is_range, args, info.name.GetParameterIndex()))
          : info.name;
      uses_.push_back(ReflectAccessInfo(cls, name, info.is_method));
    }
  }
  return GetReturnType(id);
}

void FlowAnalysisSubstitutor::AnalyzeFieldSet(const Instruction& instruction ATTRIBUTE_UNUSED) {
  // TODO: analyze field sets.
}

}  // namespace art
