/*
 * Copyright (C) 2017 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.
 */

// TODO: Dex helpers have ART specific APIs, we may want to refactor these for use in dexdump.

#ifndef ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_
#define ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_

#include "compact_dex_file.h"
#include "dex_file.h"
#include "dex_instruction_iterator.h"
#include "standard_dex_file.h"

namespace art {

class ArtMethod;

// Abstracts accesses to the instruction fields of code items for CompactDexFile and
// StandardDexFile.
class CodeItemInstructionAccessor {
 public:
  ALWAYS_INLINE CodeItemInstructionAccessor(const DexFile& dex_file,
                                            const DexFile::CodeItem* code_item);

  ALWAYS_INLINE explicit CodeItemInstructionAccessor(ArtMethod* method);

  ALWAYS_INLINE DexInstructionIterator begin() const;

  ALWAYS_INLINE DexInstructionIterator end() const;

  IterationRange<DexInstructionIterator> InstructionsFrom(uint32_t start_dex_pc) const;

  uint32_t InsnsSizeInCodeUnits() const {
    return insns_size_in_code_units_;
  }

  uint32_t InsnsSizeInBytes() const {
    static constexpr uint32_t kCodeUnitSizeInBytes = 2u;
    return insns_size_in_code_units_ * kCodeUnitSizeInBytes;
  }

  const uint16_t* Insns() const {
    return insns_;
  }

  // Return the instruction for a dex pc.
  const Instruction& InstructionAt(uint32_t dex_pc) const {
    DCHECK_LT(dex_pc, InsnsSizeInCodeUnits());
    return *Instruction::At(insns_ + dex_pc);
  }

  // Return true if the accessor has a code item.
  bool HasCodeItem() const {
    return Insns() != nullptr;
  }

 protected:
  CodeItemInstructionAccessor() = default;

  ALWAYS_INLINE void Init(uint32_t insns_size_in_code_units, const uint16_t* insns);
  ALWAYS_INLINE void Init(const CompactDexFile::CodeItem& code_item);
  ALWAYS_INLINE void Init(const StandardDexFile::CodeItem& code_item);
  ALWAYS_INLINE void Init(const DexFile& dex_file, const DexFile::CodeItem* code_item);

 private:
  // size of the insns array, in 2 byte code units. 0 if there is no code item.
  uint32_t insns_size_in_code_units_ = 0;

  // Pointer to the instructions, null if there is no code item.
  const uint16_t* insns_ = 0;
};

// Abstracts accesses to code item fields other than debug info for CompactDexFile and
// StandardDexFile.
class CodeItemDataAccessor : public CodeItemInstructionAccessor {
 public:
  ALWAYS_INLINE CodeItemDataAccessor(const DexFile& dex_file, const DexFile::CodeItem* code_item);

  uint16_t RegistersSize() const {
    return registers_size_;
  }

  uint16_t InsSize() const {
    return ins_size_;
  }

  uint16_t OutsSize() const {
    return outs_size_;
  }

  uint16_t TriesSize() const {
    return tries_size_;
  }

  IterationRange<const DexFile::TryItem*> TryItems() const;

  const uint8_t* GetCatchHandlerData(size_t offset = 0) const;

  const DexFile::TryItem* FindTryItem(uint32_t try_dex_pc) const;

  inline const void* CodeItemDataEnd() const;

 protected:
  CodeItemDataAccessor() = default;

  ALWAYS_INLINE void Init(const CompactDexFile::CodeItem& code_item);
  ALWAYS_INLINE void Init(const StandardDexFile::CodeItem& code_item);
  ALWAYS_INLINE void Init(const DexFile& dex_file, const DexFile::CodeItem* code_item);

 private:
  // Fields mirrored from the dex/cdex code item.
  uint16_t registers_size_;
  uint16_t ins_size_;
  uint16_t outs_size_;
  uint16_t tries_size_;
};

// Abstract accesses to code item data including debug info offset. More heavy weight than the other
// helpers.
class CodeItemDebugInfoAccessor : public CodeItemDataAccessor {
 public:
  CodeItemDebugInfoAccessor() = default;

  // Initialize with an existing offset.
  ALWAYS_INLINE CodeItemDebugInfoAccessor(const DexFile& dex_file,
                                          const DexFile::CodeItem* code_item,
                                          uint32_t dex_method_index) {
    Init(dex_file, code_item, dex_method_index);
  }

  ALWAYS_INLINE void Init(const DexFile& dex_file,
                          const DexFile::CodeItem* code_item,
                          uint32_t dex_method_index);

  ALWAYS_INLINE explicit CodeItemDebugInfoAccessor(ArtMethod* method);

  uint32_t DebugInfoOffset() const {
    return debug_info_offset_;
  }

  template<typename NewLocalCallback>
  bool DecodeDebugLocalInfo(bool is_static,
                            uint32_t method_idx,
                            NewLocalCallback new_local,
                            void* context) const;

 protected:
  ALWAYS_INLINE void Init(const CompactDexFile::CodeItem& code_item, uint32_t dex_method_index);
  ALWAYS_INLINE void Init(const StandardDexFile::CodeItem& code_item);

 private:
  const DexFile* dex_file_ = nullptr;
  uint32_t debug_info_offset_ = 0u;
};

}  // namespace art

#endif  // ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_
