#pragma once #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif //===- 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; private: DXContainer(MemoryBufferRef O); MemoryBufferRef Data; dxbc::Header Header; SmallVector PartOffsets; std::optional DXIL; std::optional ShaderFlags; std::optional 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::const_iterator OffsetIt; struct PartData { dxbc::PartHeader Part; uint32_t Offset; StringRef Data; } IteratorState; friend class DXContainer; PartIterator(const DXContainer &C, SmallVectorImpl::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 create(MemoryBufferRef Object); const dxbc::Header &getHeader() const { return Header; } std::optional getDXIL() const { return DXIL; } std::optional getShaderFlags() const { return ShaderFlags; } std::optional getShaderHash() const { return Hash; } }; } // namespace object } // namespace llvm #endif // LLVM_OBJECT_DXCONTAINER_H #ifdef __GNUC__ #pragma GCC diagnostic pop #endif