LLVM 18.0.0git
DXContainer.h
Go to the documentation of this file.
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
19#include "llvm/ADT/StringRef.h"
21#include "llvm/Support/Error.h"
24#include <array>
25#include <variant>
26
27namespace llvm {
28namespace object {
29
30namespace DirectX {
31
32namespace detail {
33template <typename T>
34std::enable_if_t<std::is_arithmetic<T>::value, void> swapBytes(T &value) {
36}
37
38template <typename T>
39std::enable_if_t<std::is_class<T>::value, void> swapBytes(T &value) {
40 value.swapBytes();
41}
42} // namespace detail
44
45 // This class provides a view into the underlying resource array. The Resource
46 // data is little-endian encoded and may not be properly aligned to read
47 // directly from. The dereference operator creates a copy of the data and byte
48 // swaps it as appropriate.
49 template <typename T> struct ViewArray {
51 uint32_t Stride = sizeof(T); // size of each element in the list.
52
53 ViewArray() = default;
54 ViewArray(StringRef D, size_t S) : Data(D), Stride(S) {}
55
56 using value_type = T;
57 static constexpr uint32_t MaxStride() {
58 return static_cast<uint32_t>(sizeof(value_type));
59 }
60
61 struct iterator {
63 uint32_t Stride; // size of each element in the list.
64 const char *Current;
65
66 iterator(const ViewArray &A, const char *C)
67 : Data(A.Data), Stride(A.Stride), Current(C) {}
68 iterator(const iterator &) = default;
69
71 // Explicitly zero the structure so that unused fields are zeroed. It is
72 // up to the user to know if the fields are used by verifying the PSV
73 // version.
74 value_type Val;
75 std::memset(&Val, 0, sizeof(value_type));
76 if (Current >= Data.end())
77 return Val;
78 memcpy(static_cast<void *>(&Val), Current,
79 std::min(Stride, MaxStride()));
82 return Val;
83 }
84
86 if (Current < Data.end())
87 Current += Stride;
88 return *this;
89 }
90
92 iterator Tmp = *this;
93 ++*this;
94 return Tmp;
95 }
96
98 if (Current > Data.begin())
99 Current -= Stride;
100 return *this;
101 }
102
104 iterator Tmp = *this;
105 --*this;
106 return Tmp;
107 }
108
109 bool operator==(const iterator I) { return I.Current == Current; }
110 bool operator!=(const iterator I) { return !(*this == I); }
111 };
112
113 iterator begin() const { return iterator(*this, Data.begin()); }
114
115 iterator end() const { return iterator(*this, Data.end()); }
116
117 size_t size() const { return Data.size() / Stride; }
118 };
119
120 using ResourceArray = ViewArray<dxbc::PSV::v2::ResourceBindInfo>;
121 using SigElementArray = ViewArray<dxbc::PSV::v0::SignatureElement>;
122
123 StringRef Data;
124 uint32_t Size;
125 using InfoStruct =
126 std::variant<std::monostate, dxbc::PSV::v0::RuntimeInfo,
127 dxbc::PSV::v1::RuntimeInfo, dxbc::PSV::v2::RuntimeInfo>;
128 InfoStruct BasicInfo;
129 ResourceArray Resources;
130 StringRef StringTable;
131 SmallVector<uint32_t> SemanticIndexTable;
132 SigElementArray SigInputElements;
133 SigElementArray SigOutputElements;
134 SigElementArray SigPatchOrPrimElements;
135
136 std::array<ViewArray<uint32_t>, 4> OutputVectorMasks;
137 ViewArray<uint32_t> PatchOrPrimMasks;
138 std::array<ViewArray<uint32_t>, 4> InputOutputMap;
139 ViewArray<uint32_t> InputPatchMap;
140 ViewArray<uint32_t> PatchOutputMap;
141
142public:
144
145 // Parsing depends on the shader kind
146 Error parse(uint16_t ShaderKind);
147
148 uint32_t getSize() const { return Size; }
149 uint32_t getResourceCount() const { return Resources.size(); }
150 ResourceArray getResources() const { return Resources; }
151
153 return Size >= sizeof(dxbc::PSV::v2::RuntimeInfo)
154 ? 2
155 : (Size >= sizeof(dxbc::PSV::v1::RuntimeInfo) ? 1 : 0);
156 }
157
158 uint32_t getResourceStride() const { return Resources.Stride; }
159
160 const InfoStruct &getInfo() const { return BasicInfo; }
161
162 template <typename T> const T *getInfoAs() const {
163 if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))
164 return static_cast<const T *>(P);
165 if (std::is_same<T, dxbc::PSV::v2::RuntimeInfo>::value)
166 return nullptr;
167
168 if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))
169 return static_cast<const T *>(P);
170 if (std::is_same<T, dxbc::PSV::v1::RuntimeInfo>::value)
171 return nullptr;
172
173 if (const auto *P = std::get_if<dxbc::PSV::v0::RuntimeInfo>(&BasicInfo))
174 return static_cast<const T *>(P);
175 return nullptr;
176 }
177
178 StringRef getStringTable() const { return StringTable; }
180 return SemanticIndexTable;
181 }
182
183 uint8_t getSigInputCount() const;
184 uint8_t getSigOutputCount() const;
185 uint8_t getSigPatchOrPrimCount() const;
186
187 SigElementArray getSigInputElements() const { return SigInputElements; }
188 SigElementArray getSigOutputElements() const { return SigOutputElements; }
189 SigElementArray getSigPatchOrPrimElements() const {
190 return SigPatchOrPrimElements;
191 }
192
193 ViewArray<uint32_t> getOutputVectorMasks(size_t Idx) const {
194 assert(Idx < 4);
195 return OutputVectorMasks[Idx];
196 }
197
198 ViewArray<uint32_t> getPatchOrPrimMasks() const { return PatchOrPrimMasks; }
199
200 ViewArray<uint32_t> getInputOutputMap(size_t Idx) const {
201 assert(Idx < 4);
202 return InputOutputMap[Idx];
203 }
204
205 ViewArray<uint32_t> getInputPatchMap() const { return InputPatchMap; }
206 ViewArray<uint32_t> getPatchOutputMap() const { return PatchOutputMap; }
207
208 uint32_t getSigElementStride() const { return SigInputElements.Stride; }
209
210 bool usesViewID() const {
211 if (const auto *P = getInfoAs<dxbc::PSV::v1::RuntimeInfo>())
212 return P->UsesViewID != 0;
213 return false;
214 }
215
216 uint8_t getInputVectorCount() const {
217 if (const auto *P = getInfoAs<dxbc::PSV::v1::RuntimeInfo>())
218 return P->SigInputVectors;
219 return 0;
220 }
221
223 if (const auto *P = getInfoAs<dxbc::PSV::v1::RuntimeInfo>())
224 return ArrayRef<uint8_t>(P->SigOutputVectors);
225 return ArrayRef<uint8_t>();
226 }
227
229 if (const auto *P = getInfoAs<dxbc::PSV::v1::RuntimeInfo>())
230 return P->GeomData.SigPatchConstOrPrimVectors;
231 return 0;
232 }
233};
234
235} // namespace DirectX
236
238public:
239 using DXILData = std::pair<dxbc::ProgramHeader, const char *>;
240
241private:
243
244 MemoryBufferRef Data;
245 dxbc::Header Header;
246 SmallVector<uint32_t, 4> PartOffsets;
247 std::optional<DXILData> DXIL;
248 std::optional<uint64_t> ShaderFlags;
249 std::optional<dxbc::ShaderHash> Hash;
250 std::optional<DirectX::PSVRuntimeInfo> PSVInfo;
251
252 Error parseHeader();
253 Error parsePartOffsets();
254 Error parseDXILHeader(StringRef Part);
255 Error parseShaderFlags(StringRef Part);
256 Error parseHash(StringRef Part);
257 Error parsePSVInfo(StringRef Part);
258 friend class PartIterator;
259
260public:
261 // The PartIterator is a wrapper around the iterator for the PartOffsets
262 // member of the DXContainer. It contains a refernce to the container, and the
263 // current iterator value, as well as storage for a parsed part header.
265 const DXContainer &Container;
267 struct PartData {
268 dxbc::PartHeader Part;
269 uint32_t Offset;
271 } IteratorState;
272
273 friend class DXContainer;
274
277 : Container(C), OffsetIt(It) {
278 if (OffsetIt == Container.PartOffsets.end())
279 updateIteratorImpl(Container.PartOffsets.back());
280 else
281 updateIterator();
282 }
283
284 // Updates the iterator's state data. This results in copying the part
285 // header into the iterator and handling any required byte swapping. This is
286 // called when incrementing or decrementing the iterator.
287 void updateIterator() {
288 if (OffsetIt != Container.PartOffsets.end())
289 updateIteratorImpl(*OffsetIt);
290 }
291
292 // Implementation for updating the iterator state based on a specified
293 // offest.
294 void updateIteratorImpl(const uint32_t Offset);
295
296 public:
298 if (OffsetIt == Container.PartOffsets.end())
299 return *this;
300 ++OffsetIt;
301 updateIterator();
302 return *this;
303 }
304
306 PartIterator Tmp = *this;
307 ++(*this);
308 return Tmp;
309 }
310
311 bool operator==(const PartIterator &RHS) const {
312 return OffsetIt == RHS.OffsetIt;
313 }
314
315 bool operator!=(const PartIterator &RHS) const {
316 return OffsetIt != RHS.OffsetIt;
317 }
318
319 const PartData &operator*() { return IteratorState; }
320 const PartData *operator->() { return &IteratorState; }
321 };
322
324 return PartIterator(*this, PartOffsets.begin());
325 }
326
327 PartIterator end() const { return PartIterator(*this, PartOffsets.end()); }
328
329 StringRef getData() const { return Data.getBuffer(); }
331
332 const dxbc::Header &getHeader() const { return Header; }
333
334 const std::optional<DXILData> &getDXIL() const { return DXIL; }
335
336 std::optional<uint64_t> getShaderFlags() const { return ShaderFlags; }
337
338 std::optional<dxbc::ShaderHash> getShaderHash() const { return Hash; }
339
340 const std::optional<DirectX::PSVRuntimeInfo> &getPSVInfo() const {
341 return PSVInfo;
342 };
343};
344
345} // namespace object
346} // namespace llvm
347
348#endif // LLVM_OBJECT_DXCONTAINER_H
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
Given that RA is a live value
#define I(x, y, z)
Definition: MD5.cpp:58
#define T
#define P(N)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
Value * RHS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
Tagged union holding either a T or a Error.
Definition: Error.h:474
typename SuperClass::const_iterator const_iterator
Definition: SmallVector.h:582
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
iterator begin() const
Definition: StringRef.h:111
iterator end() const
Definition: StringRef.h:113
bool operator!=(const PartIterator &RHS) const
Definition: DXContainer.h:315
bool operator==(const PartIterator &RHS) const
Definition: DXContainer.h:311
std::optional< uint64_t > getShaderFlags() const
Definition: DXContainer.h:336
PartIterator end() const
Definition: DXContainer.h:327
const std::optional< DXILData > & getDXIL() const
Definition: DXContainer.h:334
const std::optional< DirectX::PSVRuntimeInfo > & getPSVInfo() const
Definition: DXContainer.h:340
const dxbc::Header & getHeader() const
Definition: DXContainer.h:332
std::pair< dxbc::ProgramHeader, const char * > DXILData
Definition: DXContainer.h:239
StringRef getData() const
Definition: DXContainer.h:329
PartIterator begin() const
Definition: DXContainer.h:323
static Expected< DXContainer > create(MemoryBufferRef Object)
std::optional< dxbc::ShaderHash > getShaderHash() const
Definition: DXContainer.h:338
ArrayRef< uint8_t > getOutputVectorCounts() const
Definition: DXContainer.h:222
ArrayRef< uint32_t > getSemanticIndexTable() const
Definition: DXContainer.h:179
ResourceArray getResources() const
Definition: DXContainer.h:150
ViewArray< uint32_t > getInputOutputMap(size_t Idx) const
Definition: DXContainer.h:200
uint8_t getPatchConstOrPrimVectorCount() const
Definition: DXContainer.h:228
ViewArray< uint32_t > getPatchOrPrimMasks() const
Definition: DXContainer.h:198
ViewArray< uint32_t > getInputPatchMap() const
Definition: DXContainer.h:205
ViewArray< uint32_t > getOutputVectorMasks(size_t Idx) const
Definition: DXContainer.h:193
SigElementArray getSigPatchOrPrimElements() const
Definition: DXContainer.h:189
SigElementArray getSigInputElements() const
Definition: DXContainer.h:187
SigElementArray getSigOutputElements() const
Definition: DXContainer.h:188
const InfoStruct & getInfo() const
Definition: DXContainer.h:160
ViewArray< uint32_t > getPatchOutputMap() const
Definition: DXContainer.h:206
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
std::enable_if_t< std::is_arithmetic< T >::value, void > swapBytes(T &value)
Definition: DXContainer.h:34
constexpr bool IsBigEndianHost
Definition: SwapByteOrder.h:54
void swapByteOrder(T &Value)
Definition: SwapByteOrder.h:90
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:440
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1685
Use this type to describe the size and type of a DXIL container part.
Definition: DXContainer.h:93
Definition: regcomp.c:192