File indexing completed on 2026-05-10 08:44:17
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_OBJECT_DXCONTAINER_H
0016 #define LLVM_OBJECT_DXCONTAINER_H
0017
0018 #include "llvm/ADT/SmallVector.h"
0019 #include "llvm/ADT/StringRef.h"
0020 #include "llvm/BinaryFormat/DXContainer.h"
0021 #include "llvm/Support/Error.h"
0022 #include "llvm/Support/MemoryBufferRef.h"
0023 #include "llvm/TargetParser/Triple.h"
0024 #include <array>
0025 #include <variant>
0026
0027 namespace llvm {
0028 namespace object {
0029
0030 namespace detail {
0031 template <typename T>
0032 std::enable_if_t<std::is_arithmetic<T>::value, void> swapBytes(T &value) {
0033 sys::swapByteOrder(value);
0034 }
0035
0036 template <typename T>
0037 std::enable_if_t<std::is_class<T>::value, void> swapBytes(T &value) {
0038 value.swapBytes();
0039 }
0040 }
0041
0042
0043
0044
0045
0046 template <typename T> struct ViewArray {
0047 StringRef Data;
0048 uint32_t Stride = sizeof(T);
0049
0050 ViewArray() = default;
0051 ViewArray(StringRef D, size_t S) : Data(D), Stride(S) {}
0052
0053 using value_type = T;
0054 static constexpr uint32_t MaxStride() {
0055 return static_cast<uint32_t>(sizeof(value_type));
0056 }
0057
0058 struct iterator {
0059 StringRef Data;
0060 uint32_t Stride;
0061 const char *Current;
0062
0063 iterator(const ViewArray &A, const char *C)
0064 : Data(A.Data), Stride(A.Stride), Current(C) {}
0065 iterator(const iterator &) = default;
0066
0067 value_type operator*() {
0068
0069
0070
0071 value_type Val;
0072 std::memset(&Val, 0, sizeof(value_type));
0073 if (Current >= Data.end())
0074 return Val;
0075 memcpy(static_cast<void *>(&Val), Current, std::min(Stride, MaxStride()));
0076 if (sys::IsBigEndianHost)
0077 detail::swapBytes(Val);
0078 return Val;
0079 }
0080
0081 iterator operator++() {
0082 if (Current < Data.end())
0083 Current += Stride;
0084 return *this;
0085 }
0086
0087 iterator operator++(int) {
0088 iterator Tmp = *this;
0089 ++*this;
0090 return Tmp;
0091 }
0092
0093 iterator operator--() {
0094 if (Current > Data.begin())
0095 Current -= Stride;
0096 return *this;
0097 }
0098
0099 iterator operator--(int) {
0100 iterator Tmp = *this;
0101 --*this;
0102 return Tmp;
0103 }
0104
0105 bool operator==(const iterator I) { return I.Current == Current; }
0106 bool operator!=(const iterator I) { return !(*this == I); }
0107 };
0108
0109 iterator begin() const { return iterator(*this, Data.begin()); }
0110
0111 iterator end() const { return iterator(*this, Data.end()); }
0112
0113 size_t size() const { return Data.size() / Stride; }
0114
0115 bool isEmpty() const { return Data.empty(); }
0116 };
0117
0118 namespace DirectX {
0119 class PSVRuntimeInfo {
0120
0121 using ResourceArray = ViewArray<dxbc::PSV::v2::ResourceBindInfo>;
0122 using SigElementArray = ViewArray<dxbc::PSV::v0::SignatureElement>;
0123
0124 StringRef Data;
0125 uint32_t Size;
0126 using InfoStruct =
0127 std::variant<std::monostate, dxbc::PSV::v0::RuntimeInfo,
0128 dxbc::PSV::v1::RuntimeInfo, dxbc::PSV::v2::RuntimeInfo,
0129 dxbc::PSV::v3::RuntimeInfo>;
0130 InfoStruct BasicInfo;
0131 ResourceArray Resources;
0132 StringRef StringTable;
0133 SmallVector<uint32_t> SemanticIndexTable;
0134 SigElementArray SigInputElements;
0135 SigElementArray SigOutputElements;
0136 SigElementArray SigPatchOrPrimElements;
0137
0138 std::array<ViewArray<uint32_t>, 4> OutputVectorMasks;
0139 ViewArray<uint32_t> PatchOrPrimMasks;
0140 std::array<ViewArray<uint32_t>, 4> InputOutputMap;
0141 ViewArray<uint32_t> InputPatchMap;
0142 ViewArray<uint32_t> PatchOutputMap;
0143
0144 public:
0145 PSVRuntimeInfo(StringRef D) : Data(D), Size(0) {}
0146
0147
0148 Error parse(uint16_t ShaderKind);
0149
0150 uint32_t getSize() const { return Size; }
0151 uint32_t getResourceCount() const { return Resources.size(); }
0152 ResourceArray getResources() const { return Resources; }
0153
0154 uint32_t getVersion() const {
0155 return Size >= sizeof(dxbc::PSV::v3::RuntimeInfo)
0156 ? 3
0157 : (Size >= sizeof(dxbc::PSV::v2::RuntimeInfo) ? 2
0158 : (Size >= sizeof(dxbc::PSV::v1::RuntimeInfo)) ? 1
0159 : 0);
0160 }
0161
0162 uint32_t getResourceStride() const { return Resources.Stride; }
0163
0164 const InfoStruct &getInfo() const { return BasicInfo; }
0165
0166 template <typename T> const T *getInfoAs() const {
0167 if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo))
0168 return static_cast<const T *>(P);
0169 if (std::is_same<T, dxbc::PSV::v3::RuntimeInfo>::value)
0170 return nullptr;
0171
0172 if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))
0173 return static_cast<const T *>(P);
0174 if (std::is_same<T, dxbc::PSV::v2::RuntimeInfo>::value)
0175 return nullptr;
0176
0177 if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))
0178 return static_cast<const T *>(P);
0179 if (std::is_same<T, dxbc::PSV::v1::RuntimeInfo>::value)
0180 return nullptr;
0181
0182 if (const auto *P = std::get_if<dxbc::PSV::v0::RuntimeInfo>(&BasicInfo))
0183 return static_cast<const T *>(P);
0184 return nullptr;
0185 }
0186
0187 StringRef getStringTable() const { return StringTable; }
0188 ArrayRef<uint32_t> getSemanticIndexTable() const {
0189 return SemanticIndexTable;
0190 }
0191
0192 uint8_t getSigInputCount() const;
0193 uint8_t getSigOutputCount() const;
0194 uint8_t getSigPatchOrPrimCount() const;
0195
0196 SigElementArray getSigInputElements() const { return SigInputElements; }
0197 SigElementArray getSigOutputElements() const { return SigOutputElements; }
0198 SigElementArray getSigPatchOrPrimElements() const {
0199 return SigPatchOrPrimElements;
0200 }
0201
0202 ViewArray<uint32_t> getOutputVectorMasks(size_t Idx) const {
0203 assert(Idx < 4);
0204 return OutputVectorMasks[Idx];
0205 }
0206
0207 ViewArray<uint32_t> getPatchOrPrimMasks() const { return PatchOrPrimMasks; }
0208
0209 ViewArray<uint32_t> getInputOutputMap(size_t Idx) const {
0210 assert(Idx < 4);
0211 return InputOutputMap[Idx];
0212 }
0213
0214 ViewArray<uint32_t> getInputPatchMap() const { return InputPatchMap; }
0215 ViewArray<uint32_t> getPatchOutputMap() const { return PatchOutputMap; }
0216
0217 uint32_t getSigElementStride() const { return SigInputElements.Stride; }
0218
0219 bool usesViewID() const {
0220 if (const auto *P = getInfoAs<dxbc::PSV::v1::RuntimeInfo>())
0221 return P->UsesViewID != 0;
0222 return false;
0223 }
0224
0225 uint8_t getInputVectorCount() const {
0226 if (const auto *P = getInfoAs<dxbc::PSV::v1::RuntimeInfo>())
0227 return P->SigInputVectors;
0228 return 0;
0229 }
0230
0231 ArrayRef<uint8_t> getOutputVectorCounts() const {
0232 if (const auto *P = getInfoAs<dxbc::PSV::v1::RuntimeInfo>())
0233 return ArrayRef<uint8_t>(P->SigOutputVectors);
0234 return ArrayRef<uint8_t>();
0235 }
0236
0237 uint8_t getPatchConstOrPrimVectorCount() const {
0238 if (const auto *P = getInfoAs<dxbc::PSV::v1::RuntimeInfo>())
0239 return P->GeomData.SigPatchConstOrPrimVectors;
0240 return 0;
0241 }
0242 };
0243
0244 class Signature {
0245 ViewArray<dxbc::ProgramSignatureElement> Parameters;
0246 uint32_t StringTableOffset;
0247 StringRef StringTable;
0248
0249 public:
0250 ViewArray<dxbc::ProgramSignatureElement>::iterator begin() const {
0251 return Parameters.begin();
0252 }
0253
0254 ViewArray<dxbc::ProgramSignatureElement>::iterator end() const {
0255 return Parameters.end();
0256 }
0257
0258 StringRef getName(uint32_t Offset) const {
0259 assert(Offset >= StringTableOffset &&
0260 Offset < StringTableOffset + StringTable.size() &&
0261 "Offset out of range.");
0262
0263
0264
0265 uint32_t TableOffset = Offset - StringTableOffset;
0266 return StringTable.slice(TableOffset, StringTable.find('\0', TableOffset));
0267 }
0268
0269 bool isEmpty() const { return Parameters.isEmpty(); }
0270
0271 Error initialize(StringRef Part);
0272 };
0273
0274 }
0275
0276 class DXContainer {
0277 public:
0278 using DXILData = std::pair<dxbc::ProgramHeader, const char *>;
0279
0280 private:
0281 DXContainer(MemoryBufferRef O);
0282
0283 MemoryBufferRef Data;
0284 dxbc::Header Header;
0285 SmallVector<uint32_t, 4> PartOffsets;
0286 std::optional<DXILData> DXIL;
0287 std::optional<uint64_t> ShaderFeatureFlags;
0288 std::optional<dxbc::ShaderHash> Hash;
0289 std::optional<DirectX::PSVRuntimeInfo> PSVInfo;
0290 DirectX::Signature InputSignature;
0291 DirectX::Signature OutputSignature;
0292 DirectX::Signature PatchConstantSignature;
0293
0294 Error parseHeader();
0295 Error parsePartOffsets();
0296 Error parseDXILHeader(StringRef Part);
0297 Error parseShaderFeatureFlags(StringRef Part);
0298 Error parseHash(StringRef Part);
0299 Error parsePSVInfo(StringRef Part);
0300 Error parseSignature(StringRef Part, DirectX::Signature &Array);
0301 friend class PartIterator;
0302
0303 public:
0304
0305
0306
0307 class PartIterator {
0308 const DXContainer &Container;
0309 SmallVectorImpl<uint32_t>::const_iterator OffsetIt;
0310 struct PartData {
0311 dxbc::PartHeader Part;
0312 uint32_t Offset;
0313 StringRef Data;
0314 } IteratorState;
0315
0316 friend class DXContainer;
0317
0318 PartIterator(const DXContainer &C,
0319 SmallVectorImpl<uint32_t>::const_iterator It)
0320 : Container(C), OffsetIt(It) {
0321 if (OffsetIt == Container.PartOffsets.end())
0322 updateIteratorImpl(Container.PartOffsets.back());
0323 else
0324 updateIterator();
0325 }
0326
0327
0328
0329
0330 void updateIterator() {
0331 if (OffsetIt != Container.PartOffsets.end())
0332 updateIteratorImpl(*OffsetIt);
0333 }
0334
0335
0336
0337 void updateIteratorImpl(const uint32_t Offset);
0338
0339 public:
0340 PartIterator &operator++() {
0341 if (OffsetIt == Container.PartOffsets.end())
0342 return *this;
0343 ++OffsetIt;
0344 updateIterator();
0345 return *this;
0346 }
0347
0348 PartIterator operator++(int) {
0349 PartIterator Tmp = *this;
0350 ++(*this);
0351 return Tmp;
0352 }
0353
0354 bool operator==(const PartIterator &RHS) const {
0355 return OffsetIt == RHS.OffsetIt;
0356 }
0357
0358 bool operator!=(const PartIterator &RHS) const {
0359 return OffsetIt != RHS.OffsetIt;
0360 }
0361
0362 const PartData &operator*() { return IteratorState; }
0363 const PartData *operator->() { return &IteratorState; }
0364 };
0365
0366 PartIterator begin() const {
0367 return PartIterator(*this, PartOffsets.begin());
0368 }
0369
0370 PartIterator end() const { return PartIterator(*this, PartOffsets.end()); }
0371
0372 StringRef getData() const { return Data.getBuffer(); }
0373 static Expected<DXContainer> create(MemoryBufferRef Object);
0374
0375 const dxbc::Header &getHeader() const { return Header; }
0376
0377 const std::optional<DXILData> &getDXIL() const { return DXIL; }
0378
0379 std::optional<uint64_t> getShaderFeatureFlags() const {
0380 return ShaderFeatureFlags;
0381 }
0382
0383 std::optional<dxbc::ShaderHash> getShaderHash() const { return Hash; }
0384
0385 const std::optional<DirectX::PSVRuntimeInfo> &getPSVInfo() const {
0386 return PSVInfo;
0387 };
0388
0389 const DirectX::Signature &getInputSignature() const { return InputSignature; }
0390 const DirectX::Signature &getOutputSignature() const {
0391 return OutputSignature;
0392 }
0393 const DirectX::Signature &getPatchConstantSignature() const {
0394 return PatchConstantSignature;
0395 }
0396 };
0397
0398 }
0399 }
0400
0401 #endif