/*
 * 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.
 */

#ifndef ART_TOOLS_VERIDEX_FLOW_ANALYSIS_H_
#define ART_TOOLS_VERIDEX_FLOW_ANALYSIS_H_

#include "dex/class_accessor.h"
#include "dex/code_item_accessors.h"
#include "dex/dex_file_reference.h"
#include "dex/method_reference.h"
#include "hidden_api.h"
#include "resolver.h"
#include "veridex.h"

namespace art {

/**
 * The source where a dex register comes from.
 */
enum class RegisterSource {
  kParameter,
  kField,
  kMethod,
  kClass,
  kString,
  kConstant,
  kNone
};

/**
 * Abstract representation of a dex register value.
 */
class RegisterValue {
 public:
  RegisterValue() : source_(RegisterSource::kNone),
                    value_(0),
                    reference_(nullptr, 0),
                    type_(nullptr) {}
  RegisterValue(RegisterSource source, DexFileReference reference, const VeriClass* type)
      : source_(source), value_(0), reference_(reference), type_(type) {}

  RegisterValue(RegisterSource source,
                uint32_t value,
                DexFileReference reference,
                const VeriClass* type)
      : source_(source), value_(value), reference_(reference), type_(type) {}

  RegisterSource GetSource() const { return source_; }
  DexFileReference GetDexFileReference() const { return reference_; }
  const VeriClass* GetType() const { return type_; }
  uint32_t GetParameterIndex() const {
    CHECK(IsParameter());
    return value_;
  }
  uint32_t GetConstant() const {
    CHECK(IsConstant());
    return value_;
  }
  bool IsParameter() const { return source_ == RegisterSource::kParameter; }
  bool IsClass() const { return source_ == RegisterSource::kClass; }
  bool IsString() const { return source_ == RegisterSource::kString; }
  bool IsConstant() const { return source_ == RegisterSource::kConstant; }

  std::string ToString() const {
    switch (source_) {
      case RegisterSource::kString: {
        const char* str = reference_.dex_file->StringDataByIdx(dex::StringIndex(reference_.index));
        if (type_ == VeriClass::class_) {
          // Class names at the Java level are of the form x.y.z, but the list encodes
          // them of the form Lx/y/z;. Inner classes have '$' for both Java level class
          // names in strings, and hidden API lists.
          return HiddenApi::ToInternalName(str);
        } else {
          return str;
        }
      }
      case RegisterSource::kClass:
        return reference_.dex_file->StringByTypeIdx(dex::TypeIndex(reference_.index));
      case RegisterSource::kParameter:
        return std::string("Parameter of ") + reference_.dex_file->PrettyMethod(reference_.index);
      default:
        return "<unknown>";
    }
  }

 private:
  RegisterSource source_;
  uint32_t value_;
  DexFileReference reference_;
  const VeriClass* type_;
};

struct InstructionInfo {
  bool has_been_visited;
};

class VeriFlowAnalysis {
 public:
  VeriFlowAnalysis(VeridexResolver* resolver, const ClassAccessor::Method& method);

  void Run();

  virtual RegisterValue AnalyzeInvoke(const Instruction& instruction, bool is_range) = 0;
  virtual void AnalyzeFieldSet(const Instruction& instruction) = 0;
  virtual ~VeriFlowAnalysis() {}

 private:
  // Find all branches in the code.
  void FindBranches();

  // Analyze all non-deead instructions in the code.
  void AnalyzeCode();

  // Set the instruction at the given pc as a branch target.
  void SetAsBranchTarget(uint32_t dex_pc);

  // Whether the instruction at the given pc is a branch target.
  bool IsBranchTarget(uint32_t dex_pc);

  // Merge the register values at the given pc with `current_registers`.
  // Return whether the register values have changed, and the instruction needs
  // to be visited again.
  bool MergeRegisterValues(uint32_t dex_pc);

  void UpdateRegister(
      uint32_t dex_register, RegisterSource kind, VeriClass* cls, uint32_t source_id);
  void UpdateRegister(uint32_t dex_register, const RegisterValue& value);
  void UpdateRegister(uint32_t dex_register, const VeriClass* cls);
  void UpdateRegister(uint32_t dex_register, int32_t value, const VeriClass* cls);
  void ProcessDexInstruction(const Instruction& inst);
  void SetVisited(uint32_t dex_pc);
  RegisterValue GetFieldType(uint32_t field_index);

  int GetBranchFlags(const Instruction& instruction) const;

 protected:
  const RegisterValue& GetRegister(uint32_t dex_register) const;
  RegisterValue GetReturnType(uint32_t method_index);

  VeridexResolver* resolver_;

 private:
  const uint32_t method_id_;
  CodeItemDataAccessor code_item_accessor_;

  // Vector of register values for all branch targets.
  std::vector<std::unique_ptr<std::vector<RegisterValue>>> dex_registers_;

  // The current values of dex registers.
  std::vector<RegisterValue> current_registers_;

  // Information on each instruction useful for the analysis.
  std::vector<InstructionInfo> instruction_infos_;

  // The value of invoke instructions, to be fetched when visiting move-result.
  RegisterValue last_result_;
};

struct ReflectAccessInfo {
  RegisterValue cls;
  RegisterValue name;
  bool is_method;

  ReflectAccessInfo(RegisterValue c, RegisterValue n, bool is_method)
      : cls(c), name(n), is_method(is_method) {}

  bool IsConcrete() const {
    // We capture RegisterSource::kString for the class, for example in Class.forName.
    return (cls.IsClass() || cls.IsString()) && name.IsString();
  }
};

// Collects all reflection uses.
class FlowAnalysisCollector : public VeriFlowAnalysis {
 public:
  FlowAnalysisCollector(VeridexResolver* resolver, const ClassAccessor::Method& method)
      : VeriFlowAnalysis(resolver, method) {}

  const std::vector<ReflectAccessInfo>& GetUses() const {
    return uses_;
  }

  RegisterValue AnalyzeInvoke(const Instruction& instruction, bool is_range) override;
  void AnalyzeFieldSet(const Instruction& instruction) override;

 private:
  // List of reflection uses found, concrete and abstract.
  std::vector<ReflectAccessInfo> uses_;
};

// Substitutes reflection uses by new ones.
class FlowAnalysisSubstitutor : public VeriFlowAnalysis {
 public:
  FlowAnalysisSubstitutor(VeridexResolver* resolver,
                          const ClassAccessor::Method& method,
                          const std::map<MethodReference, std::vector<ReflectAccessInfo>>& accesses)
      : VeriFlowAnalysis(resolver, method), accesses_(accesses) {}

  const std::vector<ReflectAccessInfo>& GetUses() const {
    return uses_;
  }

  RegisterValue AnalyzeInvoke(const Instruction& instruction, bool is_range) override;
  void AnalyzeFieldSet(const Instruction& instruction) override;

 private:
  // List of reflection uses found, concrete and abstract.
  std::vector<ReflectAccessInfo> uses_;
  // The abstract uses we are trying to subsititute.
  const std::map<MethodReference, std::vector<ReflectAccessInfo>>& accesses_;
};

}  // namespace art

#endif  // ART_TOOLS_VERIDEX_FLOW_ANALYSIS_H_
