//===- DXContainer.h - DXContainer file implementation ----------*- C++ -*-===//
 
//
 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 
// See https://llvm.org/LICENSE.txt for license information.
 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
//
 
//===----------------------------------------------------------------------===//
 
//
 
// This file declares the DXContainerFile class, which implements the ObjectFile
 
// interface for DXContainer files.
 
//
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_OBJECT_DXCONTAINER_H
 
#define LLVM_OBJECT_DXCONTAINER_H
 
 
 
#include "llvm/ADT/SmallVector.h"
 
#include "llvm/ADT/StringRef.h"
 
#include "llvm/BinaryFormat/DXContainer.h"
 
#include "llvm/Support/Error.h"
 
#include "llvm/Support/MemoryBufferRef.h"
 
 
 
namespace llvm {
 
namespace object {
 
class DXContainer {
 
public:
 
  using DXILData = std::pair<dxbc::ProgramHeader, const char *>;
 
 
 
private:
 
  DXContainer(MemoryBufferRef O);
 
 
 
  MemoryBufferRef Data;
 
  dxbc::Header Header;
 
  SmallVector<uint32_t, 4> PartOffsets;
 
  std::optional<DXILData> DXIL;
 
  std::optional<uint64_t> ShaderFlags;
 
  std::optional<dxbc::ShaderHash> Hash;
 
 
 
  Error parseHeader();
 
  Error parsePartOffsets();
 
  Error parseDXILHeader(StringRef Part);
 
  Error parseShaderFlags(StringRef Part);
 
  Error parseHash(StringRef Part);
 
  friend class PartIterator;
 
 
 
public:
 
  // The PartIterator is a wrapper around the iterator for the PartOffsets
 
  // member of the DXContainer. It contains a refernce to the container, and the
 
  // current iterator value, as well as storage for a parsed part header.
 
  class PartIterator {
 
    const DXContainer &Container;
 
    SmallVectorImpl<uint32_t>::const_iterator OffsetIt;
 
    struct PartData {
 
      dxbc::PartHeader Part;
 
      uint32_t Offset;
 
      StringRef Data;
 
    } IteratorState;
 
 
 
    friend class DXContainer;
 
 
 
    PartIterator(const DXContainer &C,
 
                 SmallVectorImpl<uint32_t>::const_iterator It)
 
        : Container(C), OffsetIt(It) {
 
      if (OffsetIt == Container.PartOffsets.end())
 
        updateIteratorImpl(Container.PartOffsets.back());
 
      else
 
        updateIterator();
 
    }
 
 
 
    // Updates the iterator's state data. This results in copying the part
 
    // header into the iterator and handling any required byte swapping. This is
 
    // called when incrementing or decrementing the iterator.
 
    void updateIterator() {
 
      if (OffsetIt != Container.PartOffsets.end())
 
        updateIteratorImpl(*OffsetIt);
 
    }
 
 
 
    // Implementation for updating the iterator state based on a specified
 
    // offest.
 
    void updateIteratorImpl(const uint32_t Offset);
 
 
 
  public:
 
    PartIterator &operator++() {
 
      if (OffsetIt == Container.PartOffsets.end())
 
        return *this;
 
      ++OffsetIt;
 
      updateIterator();
 
      return *this;
 
    }
 
 
 
    PartIterator operator++(int) {
 
      PartIterator Tmp = *this;
 
      ++(*this);
 
      return Tmp;
 
    }
 
 
 
    bool operator==(const PartIterator &RHS) const {
 
      return OffsetIt == RHS.OffsetIt;
 
    }
 
 
 
    bool operator!=(const PartIterator &RHS) const {
 
      return OffsetIt != RHS.OffsetIt;
 
    }
 
 
 
    const PartData &operator*() { return IteratorState; }
 
    const PartData *operator->() { return &IteratorState; }
 
  };
 
 
 
  PartIterator begin() const {
 
    return PartIterator(*this, PartOffsets.begin());
 
  }
 
 
 
  PartIterator end() const { return PartIterator(*this, PartOffsets.end()); }
 
 
 
  StringRef getData() const { return Data.getBuffer(); }
 
  static Expected<DXContainer> create(MemoryBufferRef Object);
 
 
 
  const dxbc::Header &getHeader() const { return Header; }
 
 
 
  std::optional<DXILData> getDXIL() const { return DXIL; }
 
 
 
  std::optional<uint64_t> getShaderFlags() const { return ShaderFlags; }
 
 
 
  std::optional<dxbc::ShaderHash> getShaderHash() const { return Hash; }
 
};
 
 
 
} // namespace object
 
} // namespace llvm
 
 
 
#endif // LLVM_OBJECT_DXCONTAINER_H