1 //===- DXContainer.h - DXContainer file implementation ----------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file declares the DXContainerFile class, which implements the ObjectFile 10 // interface for DXContainer files. 11 // 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_OBJECT_DXCONTAINER_H 16 #define LLVM_OBJECT_DXCONTAINER_H 17 18 #include "llvm/ADT/Optional.h" 19 #include "llvm/ADT/SmallVector.h" 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/BinaryFormat/DXContainer.h" 22 #include "llvm/Support/Error.h" 23 #include "llvm/Support/MemoryBufferRef.h" 24 25 namespace llvm { 26 namespace object { 27 class DXContainer { 28 public: 29 using DXILData = std::pair<dxbc::ProgramHeader, const char *>; 30 31 private: 32 DXContainer(MemoryBufferRef O); 33 34 MemoryBufferRef Data; 35 dxbc::Header Header; 36 SmallVector<uint32_t, 4> PartOffsets; 37 Optional<DXILData> DXIL; 38 39 Error parseHeader(); 40 Error parsePartOffsets(); 41 Error parseDXILHeader(uint32_t Offset); 42 friend class PartIterator; 43 44 public: 45 // The PartIterator is a wrapper around the iterator for the PartOffsets 46 // member of the DXContainer. It contains a refernce to the container, and the 47 // current iterator value, as well as storage for a parsed part header. 48 class PartIterator { 49 const DXContainer &Container; 50 SmallVectorImpl<uint32_t>::const_iterator OffsetIt; 51 struct PartData { 52 dxbc::PartHeader Part; 53 uint32_t Offset; 54 StringRef Data; 55 } IteratorState; 56 57 friend class DXContainer; 58 59 PartIterator(const DXContainer &C, 60 SmallVectorImpl<uint32_t>::const_iterator It) 61 : Container(C), OffsetIt(It) { 62 if (OffsetIt == Container.PartOffsets.end()) 63 updateIteratorImpl(Container.PartOffsets.back()); 64 else 65 updateIterator(); 66 } 67 68 // Updates the iterator's state data. This results in copying the part 69 // header into the iterator and handling any required byte swapping. This is 70 // called when incrementing or decrementing the iterator. 71 void updateIterator() { 72 if (OffsetIt != Container.PartOffsets.end()) 73 updateIteratorImpl(*OffsetIt); 74 } 75 76 // Implementation for updating the iterator state based on a specified 77 // offest. 78 void updateIteratorImpl(const uint32_t Offset); 79 80 public: 81 PartIterator &operator++() { 82 if (OffsetIt == Container.PartOffsets.end()) 83 return *this; 84 ++OffsetIt; 85 updateIterator(); 86 return *this; 87 } 88 89 PartIterator operator++(int) { 90 PartIterator Tmp = *this; 91 ++(*this); 92 return Tmp; 93 } 94 95 bool operator==(const PartIterator &RHS) const { 96 return OffsetIt == RHS.OffsetIt; 97 } 98 99 bool operator!=(const PartIterator &RHS) const { 100 return OffsetIt != RHS.OffsetIt; 101 } 102 103 const PartData &operator*() { return IteratorState; } 104 const PartData *operator->() { return &IteratorState; } 105 }; 106 107 PartIterator begin() const { 108 return PartIterator(*this, PartOffsets.begin()); 109 } 110 111 PartIterator end() const { return PartIterator(*this, PartOffsets.end()); } 112 113 StringRef getData() const { return Data.getBuffer(); } 114 static Expected<DXContainer> create(MemoryBufferRef Object); 115 116 const dxbc::Header &getHeader() const { return Header; } 117 118 Optional<DXILData> getDXIL() const { return DXIL; } 119 }; 120 121 } // namespace object 122 } // namespace llvm 123 124 #endif // LLVM_OBJECT_DXCONTAINER_H 125