/*
 * Copyright (C) 2016 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.
 *
 * Header file of an in-memory representation of DEX files.
 */

#ifndef ART_DEXLAYOUT_DEX_IR_H_
#define ART_DEXLAYOUT_DEX_IR_H_

#include <stdint.h>
#include <unordered_map>
#include <vector>

#include "base/iteration_range.h"
#include "base/leb128.h"
#include "base/safe_map.h"
#include "base/stl_util.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_types.h"
#include "dex/utf.h"

namespace art {
namespace dex_ir {

// Forward declarations for classes used in containers or pointed to.
class AnnotationItem;
class AnnotationsDirectoryItem;
class AnnotationSetItem;
class AnnotationSetRefList;
class CallSiteId;
class ClassData;
class ClassDef;
class CodeItem;
class DebugInfoItem;
class EncodedAnnotation;
class EncodedArrayItem;
class EncodedValue;
class FieldId;
class FieldItem;
class Header;
class HiddenapiClassData;
class MapList;
class MapItem;
class MethodHandleItem;
class MethodId;
class MethodItem;
class ParameterAnnotation;
class ProtoId;
class StringData;
class StringId;
class TryItem;
class TypeId;
class TypeList;

// Item size constants.
static constexpr size_t kHeaderItemSize = 112;
static constexpr size_t kStringIdItemSize = 4;
static constexpr size_t kTypeIdItemSize = 4;
static constexpr size_t kProtoIdItemSize = 12;
static constexpr size_t kFieldIdItemSize = 8;
static constexpr size_t kMethodIdItemSize = 8;
static constexpr size_t kClassDefItemSize = 32;
static constexpr size_t kCallSiteIdItemSize = 4;
static constexpr size_t kMethodHandleItemSize = 8;

// Visitor support
class AbstractDispatcher {
 public:
  AbstractDispatcher() = default;
  virtual ~AbstractDispatcher() { }

  virtual void Dispatch(Header* header) = 0;
  virtual void Dispatch(const StringData* string_data) = 0;
  virtual void Dispatch(const StringId* string_id) = 0;
  virtual void Dispatch(const TypeId* type_id) = 0;
  virtual void Dispatch(const ProtoId* proto_id) = 0;
  virtual void Dispatch(const FieldId* field_id) = 0;
  virtual void Dispatch(const MethodId* method_id) = 0;
  virtual void Dispatch(const CallSiteId* call_site_id) = 0;
  virtual void Dispatch(const MethodHandleItem* method_handle_item) = 0;
  virtual void Dispatch(ClassData* class_data) = 0;
  virtual void Dispatch(ClassDef* class_def) = 0;
  virtual void Dispatch(FieldItem* field_item) = 0;
  virtual void Dispatch(MethodItem* method_item) = 0;
  virtual void Dispatch(EncodedArrayItem* array_item) = 0;
  virtual void Dispatch(CodeItem* code_item) = 0;
  virtual void Dispatch(TryItem* try_item) = 0;
  virtual void Dispatch(DebugInfoItem* debug_info_item) = 0;
  virtual void Dispatch(AnnotationItem* annotation_item) = 0;
  virtual void Dispatch(AnnotationSetItem* annotation_set_item) = 0;
  virtual void Dispatch(AnnotationSetRefList* annotation_set_ref_list) = 0;
  virtual void Dispatch(AnnotationsDirectoryItem* annotations_directory_item) = 0;
  virtual void Dispatch(HiddenapiClassData* hiddenapi_class_data) = 0;
  virtual void Dispatch(MapList* map_list) = 0;
  virtual void Dispatch(MapItem* map_item) = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(AbstractDispatcher);
};

template <class T>
class Iterator {
 public:
  using iterator_category = std::random_access_iterator_tag;
  using value_type = T;
  using difference_type = ptrdiff_t;
  using pointer = value_type*;
  using reference = value_type&;

  Iterator(const Iterator&) = default;
  Iterator(Iterator&&) noexcept = default;
  Iterator& operator=(const Iterator&) = default;
  Iterator& operator=(Iterator&&) noexcept = default;

  Iterator(const std::vector<T>& vector,
           uint32_t position,
           uint32_t iterator_end)
      : vector_(&vector),
        position_(position),
        iterator_end_(iterator_end) { }
  Iterator() : vector_(nullptr), position_(0U), iterator_end_(0U) { }

  bool IsValid() const { return position_ < iterator_end_; }

  bool operator==(const Iterator& rhs) const { return position_ == rhs.position_; }
  bool operator!=(const Iterator& rhs) const { return !(*this == rhs); }
  bool operator<(const Iterator& rhs) const { return position_ < rhs.position_; }
  bool operator>(const Iterator& rhs) const { return rhs < *this; }
  bool operator<=(const Iterator& rhs) const { return !(rhs < *this); }
  bool operator>=(const Iterator& rhs) const { return !(*this < rhs); }

  Iterator& operator++() {  // Value after modification.
    ++position_;
    return *this;
  }

  Iterator operator++(int) {
    Iterator temp = *this;
    ++position_;
    return temp;
  }

  Iterator& operator+=(difference_type delta) {
    position_ += delta;
    return *this;
  }

  Iterator operator+(difference_type delta) const {
    Iterator temp = *this;
    temp += delta;
    return temp;
  }

  Iterator& operator--() {  // Value after modification.
    --position_;
    return *this;
  }

  Iterator operator--(int) {
    Iterator temp = *this;
    --position_;
    return temp;
  }

  Iterator& operator-=(difference_type delta) {
    position_ -= delta;
    return *this;
  }

  Iterator operator-(difference_type delta) const {
    Iterator temp = *this;
    temp -= delta;
    return temp;
  }

  difference_type operator-(const Iterator& rhs) {
    return position_ - rhs.position_;
  }

  reference operator*() const {
    return const_cast<reference>((*vector_)[position_]);
  }

  pointer operator->() const {
    return const_cast<pointer>(&((*vector_)[position_]));
  }

  reference operator[](difference_type n) const {
    return (*vector_)[position_ + n];
  }

 private:
  const std::vector<T>* vector_;
  uint32_t position_;
  uint32_t iterator_end_;

  template <typename U>
  friend bool operator<(const Iterator<U>& lhs, const Iterator<U>& rhs);
};

// Collections become owners of the objects added by moving them into unique pointers.
class CollectionBase {
 public:
  CollectionBase() = default;
  virtual ~CollectionBase() { }

  uint32_t GetOffset() const { return offset_; }
  void SetOffset(uint32_t new_offset) { offset_ = new_offset; }
  virtual uint32_t Size() const = 0;
  bool Empty() const { return Size() == 0u; }

 private:
  // Start out unassigned.
  uint32_t offset_ = 0u;

  DISALLOW_COPY_AND_ASSIGN(CollectionBase);
};

template<class T> class CollectionVector : public CollectionBase {
 public:
  using ElementType = std::unique_ptr<T>;

  CollectionVector() { }
  explicit CollectionVector(size_t size) {
    // Preallocate so that assignment does not invalidate pointers into the vector.
    collection_.reserve(size);
  }
  ~CollectionVector() override { }

  template<class... Args>
  T* CreateAndAddItem(Args&&... args) {
    T* object = new T(std::forward<Args>(args)...);
    collection_.push_back(std::unique_ptr<T>(object));
    return object;
  }

  uint32_t Size() const override { return collection_.size(); }

  Iterator<ElementType> begin() const { return Iterator<ElementType>(collection_, 0U, Size()); }
  Iterator<ElementType> end() const { return Iterator<ElementType>(collection_, Size(), Size()); }

  const ElementType& operator[](size_t index) const {
    DCHECK_LT(index, Size());
    return collection_[index];
  }
  ElementType& operator[](size_t index) {
    DCHECK_LT(index, Size());
    return collection_[index];
  }

  // Sort the vector by copying pointers over.
  template <typename MapType>
  void SortByMapOrder(const MapType& map) {
    CHECK_EQ(map.size(), Size());

    // Move all pointers to a temporary map owning the pointers.
    std::unordered_map<T*, ElementType> pointers_map;
    pointers_map.reserve(Size());
    for (std::unique_ptr<T>& element : collection_) {
      pointers_map[element.get()] = std::move(element);
    }

    // Move back the pointers to the original vector according to the map order.
    auto it = map.begin();
    for (size_t i = 0; i < Size(); ++i) {
      auto element_it = pointers_map.find(it->second);
      DCHECK(element_it != pointers_map.end());
      collection_[i] = std::move(element_it->second);
      ++it;
    }
  }

 protected:
  std::vector<ElementType> collection_;

 private:
  DISALLOW_COPY_AND_ASSIGN(CollectionVector);
};

template<class T> class IndexedCollectionVector : public CollectionVector<T> {
 public:
  using Vector = std::vector<std::unique_ptr<T>>;
  IndexedCollectionVector() = default;
  explicit IndexedCollectionVector(size_t size) : CollectionVector<T>(size) { }

  template <class... Args>
  T* CreateAndAddIndexedItem(uint32_t index, Args&&... args) {
    T* object = CollectionVector<T>::CreateAndAddItem(std::forward<Args>(args)...);
    object->SetIndex(index);
    return object;
  }

  T* operator[](size_t index) const {
    DCHECK_NE(CollectionVector<T>::collection_[index].get(), static_cast<T*>(nullptr));
    return CollectionVector<T>::collection_[index].get();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(IndexedCollectionVector);
};

class Item {
 public:
  Item() { }
  virtual ~Item() { }

  Item(Item&&) = default;

  // Return the assigned offset.
  uint32_t GetOffset() const WARN_UNUSED {
    CHECK(OffsetAssigned());
    return offset_;
  }
  uint32_t GetSize() const WARN_UNUSED { return size_; }
  void SetOffset(uint32_t offset) { offset_ = offset; }
  void SetSize(uint32_t size) { size_ = size; }
  bool OffsetAssigned() const {
    return offset_ != kOffsetUnassigned;
  }

 protected:
  Item(uint32_t offset, uint32_t size) : offset_(offset), size_(size) { }

  // 0 is the dex file header and shouldn't be a valid offset for any part of the dex file.
  static constexpr uint32_t kOffsetUnassigned = 0u;

  // Start out unassigned.
  uint32_t offset_ = kOffsetUnassigned;
  uint32_t size_ = 0;
};

class IndexedItem : public Item {
 public:
  IndexedItem() { }
  virtual ~IndexedItem() { }

  uint32_t GetIndex() const { return index_; }
  void SetIndex(uint32_t index) { index_ = index; }

 protected:
  IndexedItem(uint32_t offset, uint32_t size, uint32_t index)
      : Item(offset, size), index_(index) { }

  uint32_t index_ = 0;
};

class Header : public Item {
 public:
  Header(DexFile::Magic magic,
         uint32_t checksum,
         DexFile::Sha1 signature,
         uint32_t endian_tag,
         uint32_t file_size,
         uint32_t header_size,
         uint32_t link_size,
         uint32_t link_offset,
         uint32_t data_size,
         uint32_t data_offset,
         bool support_default_methods)
      : Item(0, kHeaderItemSize), support_default_methods_(support_default_methods) {
    ConstructorHelper(magic,
                      checksum,
                      signature,
                      endian_tag,
                      file_size,
                      header_size,
                      link_size,
                      link_offset,
                      data_size,
                      data_offset);
  }

  Header(DexFile::Magic magic,
         uint32_t checksum,
         DexFile::Sha1 signature,
         uint32_t endian_tag,
         uint32_t file_size,
         uint32_t header_size,
         uint32_t link_size,
         uint32_t link_offset,
         uint32_t data_size,
         uint32_t data_offset,
         bool support_default_methods,
         uint32_t num_string_ids,
         uint32_t num_type_ids,
         uint32_t num_proto_ids,
         uint32_t num_field_ids,
         uint32_t num_method_ids,
         uint32_t num_class_defs)
      : Item(0, kHeaderItemSize),
        support_default_methods_(support_default_methods),
        string_ids_(num_string_ids),
        type_ids_(num_type_ids),
        proto_ids_(num_proto_ids),
        field_ids_(num_field_ids),
        method_ids_(num_method_ids),
        class_defs_(num_class_defs) {
    ConstructorHelper(magic,
                      checksum,
                      signature,
                      endian_tag,
                      file_size,
                      header_size,
                      link_size,
                      link_offset,
                      data_size,
                      data_offset);
  }
  ~Header() override { }

  static size_t ItemSize() { return kHeaderItemSize; }

  DexFile::Magic Magic() const { return magic_; }
  uint32_t Checksum() const { return checksum_; }
  DexFile::Sha1 Signature() const { return signature_; }
  uint32_t EndianTag() const { return endian_tag_; }
  uint32_t FileSize() const { return file_size_; }
  uint32_t HeaderSize() const { return header_size_; }
  uint32_t LinkSize() const { return link_size_; }
  uint32_t LinkOffset() const { return link_offset_; }
  uint32_t DataSize() const { return data_size_; }
  uint32_t DataOffset() const { return data_offset_; }

  void SetChecksum(uint32_t new_checksum) { checksum_ = new_checksum; }
  void SetSignature(DexFile::Sha1 new_signature) { signature_ = new_signature; }
  void SetFileSize(uint32_t new_file_size) { file_size_ = new_file_size; }
  void SetHeaderSize(uint32_t new_header_size) { header_size_ = new_header_size; }
  void SetLinkSize(uint32_t new_link_size) { link_size_ = new_link_size; }
  void SetLinkOffset(uint32_t new_link_offset) { link_offset_ = new_link_offset; }
  void SetDataSize(uint32_t new_data_size) { data_size_ = new_data_size; }
  void SetDataOffset(uint32_t new_data_offset) { data_offset_ = new_data_offset; }

  IndexedCollectionVector<StringId>& StringIds() { return string_ids_; }
  const IndexedCollectionVector<StringId>& StringIds() const { return string_ids_; }
  IndexedCollectionVector<TypeId>& TypeIds() { return type_ids_; }
  const IndexedCollectionVector<TypeId>& TypeIds() const { return type_ids_; }
  IndexedCollectionVector<ProtoId>& ProtoIds() { return proto_ids_; }
  const IndexedCollectionVector<ProtoId>& ProtoIds() const { return proto_ids_; }
  IndexedCollectionVector<FieldId>& FieldIds() { return field_ids_; }
  const IndexedCollectionVector<FieldId>& FieldIds() const { return field_ids_; }
  IndexedCollectionVector<MethodId>& MethodIds() { return method_ids_; }
  const IndexedCollectionVector<MethodId>& MethodIds() const { return method_ids_; }
  IndexedCollectionVector<ClassDef>& ClassDefs() { return class_defs_; }
  const IndexedCollectionVector<ClassDef>& ClassDefs() const { return class_defs_; }
  IndexedCollectionVector<CallSiteId>& CallSiteIds() { return call_site_ids_; }
  const IndexedCollectionVector<CallSiteId>& CallSiteIds() const { return call_site_ids_; }
  IndexedCollectionVector<MethodHandleItem>& MethodHandleItems() { return method_handle_items_; }
  const IndexedCollectionVector<MethodHandleItem>& MethodHandleItems() const {
    return method_handle_items_;
  }
  CollectionVector<StringData>& StringDatas() { return string_datas_; }
  const CollectionVector<StringData>& StringDatas() const { return string_datas_; }
  CollectionVector<TypeList>& TypeLists() { return type_lists_; }
  const CollectionVector<TypeList>& TypeLists() const { return type_lists_; }
  CollectionVector<EncodedArrayItem>& EncodedArrayItems() { return encoded_array_items_; }
  const CollectionVector<EncodedArrayItem>& EncodedArrayItems() const {
    return encoded_array_items_;
  }
  CollectionVector<AnnotationItem>& AnnotationItems() { return annotation_items_; }
  const CollectionVector<AnnotationItem>& AnnotationItems() const { return annotation_items_; }
  CollectionVector<AnnotationSetItem>& AnnotationSetItems() { return annotation_set_items_; }
  const CollectionVector<AnnotationSetItem>& AnnotationSetItems() const {
    return annotation_set_items_;
  }
  CollectionVector<AnnotationSetRefList>& AnnotationSetRefLists() {
    return annotation_set_ref_lists_;
  }
  const CollectionVector<AnnotationSetRefList>& AnnotationSetRefLists() const {
    return annotation_set_ref_lists_;
  }
  CollectionVector<AnnotationsDirectoryItem>& AnnotationsDirectoryItems() {
    return annotations_directory_items_;
  }
  const CollectionVector<AnnotationsDirectoryItem>& AnnotationsDirectoryItems() const {
    return annotations_directory_items_;
  }
  IndexedCollectionVector<HiddenapiClassData>& HiddenapiClassDatas() {
    return hiddenapi_class_datas_;
  }
  const IndexedCollectionVector<HiddenapiClassData>& HiddenapiClassDatas() const {
    return hiddenapi_class_datas_;
  }
  CollectionVector<DebugInfoItem>& DebugInfoItems() { return debug_info_items_; }
  const CollectionVector<DebugInfoItem>& DebugInfoItems() const { return debug_info_items_; }
  CollectionVector<CodeItem>& CodeItems() { return code_items_; }
  const CollectionVector<CodeItem>& CodeItems() const { return code_items_; }
  CollectionVector<ClassData>& ClassDatas() { return class_datas_; }
  const CollectionVector<ClassData>& ClassDatas() const { return class_datas_; }

  StringId* GetStringIdOrNullPtr(uint32_t index) {
    return index == dex::kDexNoIndex ? nullptr : StringIds()[index];
  }
  TypeId* GetTypeIdOrNullPtr(uint16_t index) {
    return index == DexFile::kDexNoIndex16 ? nullptr : TypeIds()[index];
  }

  uint32_t MapListOffset() const { return map_list_offset_; }
  void SetMapListOffset(uint32_t new_offset) { map_list_offset_ = new_offset; }

  const std::vector<uint8_t>& LinkData() const { return link_data_; }
  void SetLinkData(std::vector<uint8_t>&& link_data) { link_data_ = std::move(link_data); }

  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

  bool SupportDefaultMethods() const {
    return support_default_methods_;
  }

 private:
  DexFile::Magic magic_;
  uint32_t checksum_;
  DexFile::Sha1 signature_;
  uint32_t endian_tag_;
  uint32_t file_size_;
  uint32_t header_size_;
  uint32_t link_size_;
  uint32_t link_offset_;
  uint32_t data_size_;
  uint32_t data_offset_;
  const bool support_default_methods_;

  void ConstructorHelper(DexFile::Magic magic,
                         uint32_t checksum,
                         DexFile::Sha1 signature,
                         uint32_t endian_tag,
                         uint32_t file_size,
                         uint32_t header_size,
                         uint32_t link_size,
                         uint32_t link_offset,
                         uint32_t data_size,
                         uint32_t data_offset) {
    checksum_ = checksum;
    endian_tag_ = endian_tag;
    file_size_ = file_size;
    header_size_ = header_size;
    link_size_ = link_size;
    link_offset_ = link_offset;
    data_size_ = data_size;
    data_offset_ = data_offset;
    magic_ = magic;
    signature_ = signature;
  }

  // Collection vectors own the IR data.
  IndexedCollectionVector<StringId> string_ids_;
  IndexedCollectionVector<TypeId> type_ids_;
  IndexedCollectionVector<ProtoId> proto_ids_;
  IndexedCollectionVector<FieldId> field_ids_;
  IndexedCollectionVector<MethodId> method_ids_;
  IndexedCollectionVector<ClassDef> class_defs_;
  IndexedCollectionVector<CallSiteId> call_site_ids_;
  IndexedCollectionVector<MethodHandleItem> method_handle_items_;
  IndexedCollectionVector<StringData> string_datas_;
  IndexedCollectionVector<TypeList> type_lists_;
  IndexedCollectionVector<EncodedArrayItem> encoded_array_items_;
  IndexedCollectionVector<AnnotationItem> annotation_items_;
  IndexedCollectionVector<AnnotationSetItem> annotation_set_items_;
  IndexedCollectionVector<AnnotationSetRefList> annotation_set_ref_lists_;
  IndexedCollectionVector<AnnotationsDirectoryItem> annotations_directory_items_;
  IndexedCollectionVector<HiddenapiClassData> hiddenapi_class_datas_;
  // The order of the vectors controls the layout of the output file by index order, to change the
  // layout just sort the vector. Note that you may only change the order of the non indexed vectors
  // below. Indexed vectors are accessed by indices in other places, changing the sorting order will
  // invalidate the existing indices and is not currently supported.
  CollectionVector<DebugInfoItem> debug_info_items_;
  CollectionVector<CodeItem> code_items_;
  CollectionVector<ClassData> class_datas_;

  uint32_t map_list_offset_ = 0;

  // Link data.
  std::vector<uint8_t> link_data_;

  DISALLOW_COPY_AND_ASSIGN(Header);
};

class StringData : public Item {
 public:
  explicit StringData(const char* data) : data_(strdup(data)) {
    size_ = UnsignedLeb128Size(CountModifiedUtf8Chars(data)) + strlen(data);
  }

  const char* Data() const { return data_.get(); }

  void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }

 private:
  UniqueCPtr<const char> data_;

  DISALLOW_COPY_AND_ASSIGN(StringData);
};

class StringId : public IndexedItem {
 public:
  explicit StringId(StringData* string_data) : string_data_(string_data) {
    size_ = kStringIdItemSize;
  }
  ~StringId() override { }

  static size_t ItemSize() { return kStringIdItemSize; }

  const char* Data() const { return string_data_->Data(); }
  StringData* DataItem() const { return string_data_; }

  void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }

 private:
  StringData* string_data_;

  DISALLOW_COPY_AND_ASSIGN(StringId);
};

class TypeId : public IndexedItem {
 public:
  explicit TypeId(StringId* string_id) : string_id_(string_id) { size_ = kTypeIdItemSize; }
  ~TypeId() override { }

  static size_t ItemSize() { return kTypeIdItemSize; }

  StringId* GetStringId() const { return string_id_; }

  void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }

 private:
  StringId* string_id_;

  DISALLOW_COPY_AND_ASSIGN(TypeId);
};

using TypeIdVector = std::vector<const TypeId*>;

class TypeList : public Item {
 public:
  explicit TypeList(TypeIdVector* type_list) : type_list_(type_list) {
    size_ = sizeof(uint32_t) + (type_list->size() * sizeof(uint16_t));
  }
  ~TypeList() override { }

  const TypeIdVector* GetTypeList() const { return type_list_.get(); }

 private:
  std::unique_ptr<TypeIdVector> type_list_;

  DISALLOW_COPY_AND_ASSIGN(TypeList);
};

class ProtoId : public IndexedItem {
 public:
  ProtoId(const StringId* shorty, const TypeId* return_type, TypeList* parameters)
      : shorty_(shorty), return_type_(return_type), parameters_(parameters)
      { size_ = kProtoIdItemSize; }
  ~ProtoId() override { }

  static size_t ItemSize() { return kProtoIdItemSize; }

  const StringId* Shorty() const { return shorty_; }
  const TypeId* ReturnType() const { return return_type_; }
  const TypeList* Parameters() const { return parameters_; }

  void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }

 private:
  const StringId* shorty_;
  const TypeId* return_type_;
  TypeList* parameters_;  // This can be nullptr.

  DISALLOW_COPY_AND_ASSIGN(ProtoId);
};

class FieldId : public IndexedItem {
 public:
  FieldId(const TypeId* klass, const TypeId* type, const StringId* name)
      : class_(klass), type_(type), name_(name) { size_ = kFieldIdItemSize; }
  ~FieldId() override { }

  static size_t ItemSize() { return kFieldIdItemSize; }

  const TypeId* Class() const { return class_; }
  const TypeId* Type() const { return type_; }
  const StringId* Name() const { return name_; }

  void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }

 private:
  const TypeId* class_;
  const TypeId* type_;
  const StringId* name_;

  DISALLOW_COPY_AND_ASSIGN(FieldId);
};

class MethodId : public IndexedItem {
 public:
  MethodId(const TypeId* klass, const ProtoId* proto, const StringId* name)
      : class_(klass), proto_(proto), name_(name) { size_ = kMethodIdItemSize; }
  ~MethodId() override { }

  static size_t ItemSize() { return kMethodIdItemSize; }

  const TypeId* Class() const { return class_; }
  const ProtoId* Proto() const { return proto_; }
  const StringId* Name() const { return name_; }

  void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }

 private:
  const TypeId* class_;
  const ProtoId* proto_;
  const StringId* name_;

  DISALLOW_COPY_AND_ASSIGN(MethodId);
};

class FieldItem : public Item {
 public:
  FieldItem(uint32_t access_flags, const FieldId* field_id)
      : access_flags_(access_flags), field_id_(field_id) { }
  ~FieldItem() override { }

  FieldItem(FieldItem&&) = default;

  uint32_t GetAccessFlags() const { return access_flags_; }
  const FieldId* GetFieldId() const { return field_id_; }

  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

 private:
  uint32_t access_flags_;
  const FieldId* field_id_;

  DISALLOW_COPY_AND_ASSIGN(FieldItem);
};

using FieldItemVector = std::vector<FieldItem>;

class MethodItem : public Item {
 public:
  MethodItem(uint32_t access_flags, const MethodId* method_id, CodeItem* code)
      : access_flags_(access_flags), method_id_(method_id), code_(code) { }
  ~MethodItem() override { }

  MethodItem(MethodItem&&) = default;

  uint32_t GetAccessFlags() const { return access_flags_; }
  const MethodId* GetMethodId() const { return method_id_; }
  CodeItem* GetCodeItem() { return code_; }

  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

 private:
  uint32_t access_flags_;
  const MethodId* method_id_;
  CodeItem* code_;  // This can be nullptr.

  DISALLOW_COPY_AND_ASSIGN(MethodItem);
};

using MethodItemVector = std::vector<MethodItem>;

class EncodedValue {
 public:
  explicit EncodedValue(uint8_t type) : type_(type) { }

  int8_t Type() const { return type_; }

  void SetBoolean(bool z) { u_.bool_val_ = z; }
  void SetByte(int8_t b) { u_.byte_val_ = b; }
  void SetShort(int16_t s) { u_.short_val_ = s; }
  void SetChar(uint16_t c) { u_.char_val_ = c; }
  void SetInt(int32_t i) { u_.int_val_ = i; }
  void SetLong(int64_t l) { u_.long_val_ = l; }
  void SetFloat(float f) { u_.float_val_ = f; }
  void SetDouble(double d) { u_.double_val_ = d; }
  void SetStringId(StringId* string_id) { u_.string_val_ = string_id; }
  void SetTypeId(TypeId* type_id) { u_.type_val_ = type_id; }
  void SetProtoId(ProtoId* proto_id) { u_.proto_val_ = proto_id; }
  void SetFieldId(FieldId* field_id) { u_.field_val_ = field_id; }
  void SetMethodId(MethodId* method_id) { u_.method_val_ = method_id; }
  void SetMethodHandle(MethodHandleItem* method_handle) { u_.method_handle_val_ = method_handle; }
  void SetEncodedArray(EncodedArrayItem* encoded_array) { encoded_array_.reset(encoded_array); }
  void SetEncodedAnnotation(EncodedAnnotation* encoded_annotation)
      { encoded_annotation_.reset(encoded_annotation); }

  bool GetBoolean() const { return u_.bool_val_; }
  int8_t GetByte() const { return u_.byte_val_; }
  int16_t GetShort() const { return u_.short_val_; }
  uint16_t GetChar() const { return u_.char_val_; }
  int32_t GetInt() const { return u_.int_val_; }
  int64_t GetLong() const { return u_.long_val_; }
  float GetFloat() const { return u_.float_val_; }
  double GetDouble() const { return u_.double_val_; }
  StringId* GetStringId() const { return u_.string_val_; }
  TypeId* GetTypeId() const { return u_.type_val_; }
  ProtoId* GetProtoId() const { return u_.proto_val_; }
  FieldId* GetFieldId() const { return u_.field_val_; }
  MethodId* GetMethodId() const { return u_.method_val_; }
  MethodHandleItem* GetMethodHandle() const { return u_.method_handle_val_; }
  EncodedArrayItem* GetEncodedArray() const { return encoded_array_.get(); }
  EncodedAnnotation* GetEncodedAnnotation() const { return encoded_annotation_.get(); }

  EncodedAnnotation* ReleaseEncodedAnnotation() { return encoded_annotation_.release(); }

 private:
  uint8_t type_;
  union {
    bool bool_val_;
    int8_t byte_val_;
    int16_t short_val_;
    uint16_t char_val_;
    int32_t int_val_;
    int64_t long_val_;
    float float_val_;
    double double_val_;
    StringId* string_val_;
    TypeId* type_val_;
    ProtoId* proto_val_;
    FieldId* field_val_;
    MethodId* method_val_;
    MethodHandleItem* method_handle_val_;
  } u_;
  std::unique_ptr<EncodedArrayItem> encoded_array_;
  std::unique_ptr<EncodedAnnotation> encoded_annotation_;

  DISALLOW_COPY_AND_ASSIGN(EncodedValue);
};

using EncodedValueVector = std::vector<std::unique_ptr<EncodedValue>>;

class AnnotationElement {
 public:
  AnnotationElement(StringId* name, EncodedValue* value) : name_(name), value_(value) { }

  StringId* GetName() const { return name_; }
  EncodedValue* GetValue() const { return value_.get(); }

 private:
  StringId* name_;
  std::unique_ptr<EncodedValue> value_;

  DISALLOW_COPY_AND_ASSIGN(AnnotationElement);
};

using AnnotationElementVector = std::vector<std::unique_ptr<AnnotationElement>>;

class EncodedAnnotation {
 public:
  EncodedAnnotation(TypeId* type, AnnotationElementVector* elements)
      : type_(type), elements_(elements) { }

  TypeId* GetType() const { return type_; }
  AnnotationElementVector* GetAnnotationElements() const { return elements_.get(); }

 private:
  TypeId* type_;
  std::unique_ptr<AnnotationElementVector> elements_;

  DISALLOW_COPY_AND_ASSIGN(EncodedAnnotation);
};

class EncodedArrayItem : public Item {
 public:
  explicit EncodedArrayItem(EncodedValueVector* encoded_values)
      : encoded_values_(encoded_values) { }

  EncodedValueVector* GetEncodedValues() const { return encoded_values_.get(); }

 private:
  std::unique_ptr<EncodedValueVector> encoded_values_;

  DISALLOW_COPY_AND_ASSIGN(EncodedArrayItem);
};

class ClassData : public Item {
 public:
  ClassData(FieldItemVector* static_fields,
            FieldItemVector* instance_fields,
            MethodItemVector* direct_methods,
            MethodItemVector* virtual_methods)
      : static_fields_(static_fields),
        instance_fields_(instance_fields),
        direct_methods_(direct_methods),
        virtual_methods_(virtual_methods) { }

  ~ClassData() override = default;
  FieldItemVector* StaticFields() { return static_fields_.get(); }
  FieldItemVector* InstanceFields() { return instance_fields_.get(); }
  MethodItemVector* DirectMethods() { return direct_methods_.get(); }
  MethodItemVector* VirtualMethods() { return virtual_methods_.get(); }

  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

 private:
  std::unique_ptr<FieldItemVector> static_fields_;
  std::unique_ptr<FieldItemVector> instance_fields_;
  std::unique_ptr<MethodItemVector> direct_methods_;
  std::unique_ptr<MethodItemVector> virtual_methods_;

  DISALLOW_COPY_AND_ASSIGN(ClassData);
};

class ClassDef : public IndexedItem {
 public:
  ClassDef(const TypeId* class_type,
           uint32_t access_flags,
           const TypeId* superclass,
           TypeList* interfaces,
           const StringId* source_file,
           AnnotationsDirectoryItem* annotations,
           EncodedArrayItem* static_values,
           ClassData* class_data)
      : class_type_(class_type),
        access_flags_(access_flags),
        superclass_(superclass),
        interfaces_(interfaces),
        source_file_(source_file),
        annotations_(annotations),
        class_data_(class_data),
        static_values_(static_values) { size_ = kClassDefItemSize; }

  ~ClassDef() override { }

  static size_t ItemSize() { return kClassDefItemSize; }

  const TypeId* ClassType() const { return class_type_; }
  uint32_t GetAccessFlags() const { return access_flags_; }
  const TypeId* Superclass() const { return superclass_; }
  const TypeList* Interfaces() { return interfaces_; }
  uint32_t InterfacesOffset() { return interfaces_ == nullptr ? 0 : interfaces_->GetOffset(); }
  const StringId* SourceFile() const { return source_file_; }
  AnnotationsDirectoryItem* Annotations() const { return annotations_; }
  ClassData* GetClassData() { return class_data_; }
  EncodedArrayItem* StaticValues() { return static_values_; }

  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

 private:
  const TypeId* class_type_;
  uint32_t access_flags_;
  const TypeId* superclass_;  // This can be nullptr.
  TypeList* interfaces_;  // This can be nullptr.
  const StringId* source_file_;  // This can be nullptr.
  AnnotationsDirectoryItem* annotations_;  // This can be nullptr.
  ClassData* class_data_;  // This can be nullptr.
  EncodedArrayItem* static_values_;  // This can be nullptr.

  DISALLOW_COPY_AND_ASSIGN(ClassDef);
};

class TypeAddrPair {
 public:
  TypeAddrPair(const TypeId* type_id, uint32_t address) : type_id_(type_id), address_(address) { }

  const TypeId* GetTypeId() const { return type_id_; }
  uint32_t GetAddress() const { return address_; }

 private:
  const TypeId* type_id_;  // This can be nullptr.
  uint32_t address_;

  DISALLOW_COPY_AND_ASSIGN(TypeAddrPair);
};

using TypeAddrPairVector = std::vector<std::unique_ptr<const TypeAddrPair>>;

class CatchHandler {
 public:
  explicit CatchHandler(bool catch_all, uint16_t list_offset, TypeAddrPairVector* handlers)
      : catch_all_(catch_all), list_offset_(list_offset), handlers_(handlers) { }

  bool HasCatchAll() const { return catch_all_; }
  uint16_t GetListOffset() const { return list_offset_; }
  TypeAddrPairVector* GetHandlers() const { return handlers_.get(); }

 private:
  bool catch_all_;
  uint16_t list_offset_;
  std::unique_ptr<TypeAddrPairVector> handlers_;

  DISALLOW_COPY_AND_ASSIGN(CatchHandler);
};

using CatchHandlerVector = std::vector<std::unique_ptr<const CatchHandler>>;

class TryItem : public Item {
 public:
  TryItem(uint32_t start_addr, uint16_t insn_count, const CatchHandler* handlers)
      : start_addr_(start_addr), insn_count_(insn_count), handlers_(handlers) { }
  ~TryItem() override { }

  uint32_t StartAddr() const { return start_addr_; }
  uint16_t InsnCount() const { return insn_count_; }
  const CatchHandler* GetHandlers() const { return handlers_; }

  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

 private:
  uint32_t start_addr_;
  uint16_t insn_count_;
  const CatchHandler* handlers_;

  DISALLOW_COPY_AND_ASSIGN(TryItem);
};

using TryItemVector = std::vector<std::unique_ptr<const TryItem>>;

class CodeFixups {
 public:
  CodeFixups(std::vector<TypeId*> type_ids,
             std::vector<StringId*> string_ids,
             std::vector<MethodId*> method_ids,
             std::vector<FieldId*> field_ids)
      : type_ids_(std::move(type_ids)),
        string_ids_(std::move(string_ids)),
        method_ids_(std::move(method_ids)),
        field_ids_(std::move(field_ids)) { }

  const std::vector<TypeId*>& TypeIds() const { return type_ids_; }
  const std::vector<StringId*>& StringIds() const { return string_ids_; }
  const std::vector<MethodId*>& MethodIds() const { return method_ids_; }
  const std::vector<FieldId*>& FieldIds() const { return field_ids_; }

 private:
  std::vector<TypeId*> type_ids_;
  std::vector<StringId*> string_ids_;
  std::vector<MethodId*> method_ids_;
  std::vector<FieldId*> field_ids_;

  DISALLOW_COPY_AND_ASSIGN(CodeFixups);
};

class CodeItem : public Item {
 public:
  CodeItem(uint16_t registers_size,
           uint16_t ins_size,
           uint16_t outs_size,
           DebugInfoItem* debug_info,
           uint32_t insns_size,
           uint16_t* insns,
           TryItemVector* tries,
           CatchHandlerVector* handlers)
      : registers_size_(registers_size),
        ins_size_(ins_size),
        outs_size_(outs_size),
        debug_info_(debug_info),
        insns_size_(insns_size),
        insns_(insns),
        tries_(tries),
        handlers_(handlers) { }

  ~CodeItem() override { }

  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_ == nullptr ? 0 : tries_->size(); }
  DebugInfoItem* DebugInfo() const { return debug_info_; }
  uint32_t InsnsSize() const { return insns_size_; }
  uint16_t* Insns() const { return insns_.get(); }
  TryItemVector* Tries() const { return tries_.get(); }
  CatchHandlerVector* Handlers() const { return handlers_.get(); }

  void SetCodeFixups(CodeFixups* fixups) { fixups_.reset(fixups); }
  CodeFixups* GetCodeFixups() const { return fixups_.get(); }

  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

  IterationRange<DexInstructionIterator> Instructions() const {
    return MakeIterationRange(DexInstructionIterator(Insns(), 0u),
                              DexInstructionIterator(Insns(), InsnsSize()));
  }

 private:
  uint16_t registers_size_;
  uint16_t ins_size_;
  uint16_t outs_size_;
  DebugInfoItem* debug_info_;  // This can be nullptr.
  uint32_t insns_size_;
  std::unique_ptr<uint16_t[]> insns_;
  std::unique_ptr<TryItemVector> tries_;  // This can be nullptr.
  std::unique_ptr<CatchHandlerVector> handlers_;  // This can be nullptr.
  std::unique_ptr<CodeFixups> fixups_;  // This can be nullptr.

  DISALLOW_COPY_AND_ASSIGN(CodeItem);
};

class DebugInfoItem : public Item {
 public:
  DebugInfoItem(uint32_t debug_info_size, uint8_t* debug_info)
     : debug_info_size_(debug_info_size), debug_info_(debug_info) { }

  uint32_t GetDebugInfoSize() const { return debug_info_size_; }
  uint8_t* GetDebugInfo() const { return debug_info_.get(); }

 private:
  uint32_t debug_info_size_;
  std::unique_ptr<uint8_t[]> debug_info_;

  DISALLOW_COPY_AND_ASSIGN(DebugInfoItem);
};

class AnnotationItem : public Item {
 public:
  AnnotationItem(uint8_t visibility, EncodedAnnotation* annotation)
      : visibility_(visibility), annotation_(annotation) { }

  uint8_t GetVisibility() const { return visibility_; }
  EncodedAnnotation* GetAnnotation() const { return annotation_.get(); }

  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

 private:
  uint8_t visibility_;
  std::unique_ptr<EncodedAnnotation> annotation_;

  DISALLOW_COPY_AND_ASSIGN(AnnotationItem);
};

class AnnotationSetItem : public Item {
 public:
  explicit AnnotationSetItem(std::vector<AnnotationItem*>* items) : items_(items) {
    size_ = sizeof(uint32_t) + items->size() * sizeof(uint32_t);
  }
  ~AnnotationSetItem() override { }

  std::vector<AnnotationItem*>* GetItems() { return items_.get(); }

  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

 private:
  std::unique_ptr<std::vector<AnnotationItem*>> items_;

  DISALLOW_COPY_AND_ASSIGN(AnnotationSetItem);
};

class AnnotationSetRefList : public Item {
 public:
  explicit AnnotationSetRefList(std::vector<AnnotationSetItem*>* items) : items_(items) {
    size_ = sizeof(uint32_t) + items->size() * sizeof(uint32_t);
  }
  ~AnnotationSetRefList() override { }

  std::vector<AnnotationSetItem*>* GetItems() { return items_.get(); }

  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

 private:
  std::unique_ptr<std::vector<AnnotationSetItem*>> items_;  // Elements of vector can be nullptr.

  DISALLOW_COPY_AND_ASSIGN(AnnotationSetRefList);
};

class FieldAnnotation {
 public:
  FieldAnnotation(FieldId* field_id, AnnotationSetItem* annotation_set_item)
      : field_id_(field_id), annotation_set_item_(annotation_set_item) { }

  FieldId* GetFieldId() const { return field_id_; }
  AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_; }

 private:
  FieldId* field_id_;
  AnnotationSetItem* annotation_set_item_;

  DISALLOW_COPY_AND_ASSIGN(FieldAnnotation);
};

using FieldAnnotationVector = std::vector<std::unique_ptr<FieldAnnotation>>;

class MethodAnnotation {
 public:
  MethodAnnotation(MethodId* method_id, AnnotationSetItem* annotation_set_item)
      : method_id_(method_id), annotation_set_item_(annotation_set_item) { }

  MethodId* GetMethodId() const { return method_id_; }
  AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_; }

 private:
  MethodId* method_id_;
  AnnotationSetItem* annotation_set_item_;

  DISALLOW_COPY_AND_ASSIGN(MethodAnnotation);
};

using MethodAnnotationVector = std::vector<std::unique_ptr<MethodAnnotation>>;

class ParameterAnnotation {
 public:
  ParameterAnnotation(MethodId* method_id, AnnotationSetRefList* annotations)
      : method_id_(method_id), annotations_(annotations) { }

  MethodId* GetMethodId() const { return method_id_; }
  AnnotationSetRefList* GetAnnotations() { return annotations_; }

 private:
  MethodId* method_id_;
  AnnotationSetRefList* annotations_;

  DISALLOW_COPY_AND_ASSIGN(ParameterAnnotation);
};

using ParameterAnnotationVector = std::vector<std::unique_ptr<ParameterAnnotation>>;

class AnnotationsDirectoryItem : public Item {
 public:
  AnnotationsDirectoryItem(AnnotationSetItem* class_annotation,
                           FieldAnnotationVector* field_annotations,
                           MethodAnnotationVector* method_annotations,
                           ParameterAnnotationVector* parameter_annotations)
      : class_annotation_(class_annotation),
        field_annotations_(field_annotations),
        method_annotations_(method_annotations),
        parameter_annotations_(parameter_annotations) { }

  AnnotationSetItem* GetClassAnnotation() const { return class_annotation_; }
  FieldAnnotationVector* GetFieldAnnotations() { return field_annotations_.get(); }
  MethodAnnotationVector* GetMethodAnnotations() { return method_annotations_.get(); }
  ParameterAnnotationVector* GetParameterAnnotations() { return parameter_annotations_.get(); }

  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

 private:
  AnnotationSetItem* class_annotation_;  // This can be nullptr.
  std::unique_ptr<FieldAnnotationVector> field_annotations_;  // This can be nullptr.
  std::unique_ptr<MethodAnnotationVector> method_annotations_;  // This can be nullptr.
  std::unique_ptr<ParameterAnnotationVector> parameter_annotations_;  // This can be nullptr.

  DISALLOW_COPY_AND_ASSIGN(AnnotationsDirectoryItem);
};

class CallSiteId : public IndexedItem {
 public:
  explicit CallSiteId(EncodedArrayItem* call_site_item) : call_site_item_(call_site_item) {
    size_ = kCallSiteIdItemSize;
  }
  ~CallSiteId() override { }

  static size_t ItemSize() { return kCallSiteIdItemSize; }

  EncodedArrayItem* CallSiteItem() const { return call_site_item_; }

  void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }

 private:
  EncodedArrayItem* call_site_item_;

  DISALLOW_COPY_AND_ASSIGN(CallSiteId);
};

class MethodHandleItem : public IndexedItem {
 public:
  MethodHandleItem(DexFile::MethodHandleType method_handle_type, IndexedItem* field_or_method_id)
      : method_handle_type_(method_handle_type),
        field_or_method_id_(field_or_method_id) {
    size_ = kMethodHandleItemSize;
  }
  ~MethodHandleItem() override { }

  static size_t ItemSize() { return kMethodHandleItemSize; }

  DexFile::MethodHandleType GetMethodHandleType() const { return method_handle_type_; }
  IndexedItem* GetFieldOrMethodId() const { return field_or_method_id_; }

  void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }

 private:
  DexFile::MethodHandleType method_handle_type_;
  IndexedItem* field_or_method_id_;

  DISALLOW_COPY_AND_ASSIGN(MethodHandleItem);
};

using HiddenapiFlagsMap = SafeMap<const Item*, uint32_t>;

class HiddenapiClassData : public IndexedItem {
 public:
  HiddenapiClassData(const ClassDef* class_def, std::unique_ptr<HiddenapiFlagsMap> flags)
      : class_def_(class_def), flags_(std::move(flags)) { }
  ~HiddenapiClassData() override { }

  const ClassDef* GetClassDef() const { return class_def_; }

  uint32_t GetFlags(const Item* field_or_method_item) const {
    return (flags_ == nullptr) ? 0u : flags_->Get(field_or_method_item);
  }

  static uint32_t GetFlags(Header* header, ClassDef* class_def, const Item* field_or_method_item) {
    DCHECK(header != nullptr);
    DCHECK(class_def != nullptr);
    return (header->HiddenapiClassDatas().Empty())
        ? 0u
        : header->HiddenapiClassDatas()[class_def->GetIndex()]->GetFlags(field_or_method_item);
  }

  uint32_t ItemSize() const {
    uint32_t size = 0u;
    bool has_non_zero_entries = false;
    if (flags_ != nullptr) {
      for (const auto& entry : *flags_) {
        size += UnsignedLeb128Size(entry.second);
        has_non_zero_entries |= (entry.second != 0u);
      }
    }
    return has_non_zero_entries ? size : 0u;
  }

  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

 private:
  const ClassDef* class_def_;
  std::unique_ptr<HiddenapiFlagsMap> flags_;

  DISALLOW_COPY_AND_ASSIGN(HiddenapiClassData);
};

// TODO(sehr): implement MapList.
class MapList : public Item {
 public:
  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

 private:
  DISALLOW_COPY_AND_ASSIGN(MapList);
};

class MapItem : public Item {
 public:
  void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }

 private:
  DISALLOW_COPY_AND_ASSIGN(MapItem);
};

// Interface for building a vector of file sections for use by other clients.
struct DexFileSection {
 public:
  DexFileSection(const std::string& name, uint16_t type, uint32_t size, uint32_t offset)
      : name(name), type(type), size(size), offset(offset) { }
  std::string name;
  // The type (DexFile::MapItemType).
  uint16_t type;
  // The size (in elements, not bytes).
  uint32_t size;
  // The byte offset from the start of the file.
  uint32_t offset;
};

enum class SortDirection {
  kSortAscending,
  kSortDescending
};

std::vector<DexFileSection> GetSortedDexFileSections(dex_ir::Header* header,
                                                     SortDirection direction);

}  // namespace dex_ir
}  // namespace art

#endif  // ART_DEXLAYOUT_DEX_IR_H_
