LLVM: lib/Object/DXContainer.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
14
15using namespace llvm;
17
19 return make_error(Msg.str(), object_error::parse_failed);
20}
21
22template
24
25 if (Src < Buffer.begin() || Src + sizeof(T) > Buffer.end())
26 return parseFailed("Reading structure out of file bounds");
27
28 memcpy(&Struct, Src, sizeof(T));
29
33}
34
35template
37 Twine Str = "structure") {
38 static_assert(std::is_integral_v,
39 "Cannot call readInteger on non-integral type.");
40
41 if (Src < Buffer.begin() || Src + sizeof(T) > Buffer.end())
42 return parseFailed(Twine("Reading ") + Str + " out of file bounds");
43
44
45
46
47 if (reinterpret_cast<uintptr_t>(Src) % alignof(T) != 0)
48 memcpy(reinterpret_cast<char *>(&Val), Src, sizeof(T));
49 else
50 Val = *reinterpret_cast<const T *>(Src);
51
55}
56
58
59Error DXContainer::parseHeader() {
61}
62
64 if (DXIL)
65 return parseFailed("More than one DXIL part is present in the file");
66 const char *Current = Part.begin();
69 return Err;
71 DXIL.emplace(std::make_pair(Header, Current));
73}
74
75Error DXContainer::parseShaderFeatureFlags(StringRef Part) {
76 if (ShaderFeatureFlags)
77 return parseFailed("More than one SFI0 part is present in the file");
80 return Err;
81 ShaderFeatureFlags = FlagValue;
83}
84
86 if (Hash)
87 return parseFailed("More than one HASH part is present in the file");
90 return Err;
91 Hash = ReadHash;
93}
94
96 if (PSVInfo)
97 return parseFailed("More than one PSV0 part is present in the file");
99
100
102}
103
107 return Err;
109
111 return parseFailed("Signature parameters extend beyond the part boundary");
112
114
117
118 for (const auto &Param : Parameters) {
120 return parseFailed("Invalid parameter name offset: name starts before "
121 "the first name offset");
123 return parseFailed("Invalid parameter name offset: name starts after the "
124 "end of the part data");
125 }
127}
128
129Error DXContainer::parsePartOffsets() {
132 const char *Current = Data.getBuffer().data() + sizeof(dxbc::Header);
133 for (uint32_t Part = 0; Part < Header.PartCount; ++Part) {
136 return Err;
137 if (PartOffset < LastOffset)
140 "Part offset for part {0} begins before the previous part ends",
141 Part)
142 .str());
144 if (PartOffset >= Data.getBufferSize())
145 return parseFailed("Part offset points beyond boundary of the file");
146
147
148
149
150
152 return parseFailed("File not large enough to read part name");
153 PartOffsets.push_back(PartOffset);
154
160 Data.getBufferStart() + PartOffset + 4,
161 PartSize, "part size"))
162 return Err;
163 StringRef PartData = Data.getBuffer().substr(PartDataStart, PartSize);
164 LastOffset = PartOffset + PartSize;
165 switch (PT) {
166 case dxbc::PartType::DXIL:
167 if (Error Err = parseDXILHeader(PartData))
168 return Err;
169 break;
170 case dxbc::PartType::SFI0:
171 if (Error Err = parseShaderFeatureFlags(PartData))
172 return Err;
173 break;
174 case dxbc::PartType::HASH:
175 if (Error Err = parseHash(PartData))
176 return Err;
177 break;
178 case dxbc::PartType::PSV0:
179 if (Error Err = parsePSVInfo(PartData))
180 return Err;
181 break;
182 case dxbc::PartType::ISG1:
183 if (Error Err = InputSignature.initialize(PartData))
184 return Err;
185 break;
186 case dxbc::PartType::OSG1:
187 if (Error Err = OutputSignature.initialize(PartData))
188 return Err;
189 break;
190 case dxbc::PartType::PSG1:
191 if (Error Err = PatchConstantSignature.initialize(PartData))
192 return Err;
193 break;
195 break;
196 }
197 }
198
199
200
201 if (PSVInfo) {
202 if (!DXIL)
203 return parseFailed("Cannot fully parse pipeline state validation "
204 "information without DXIL part.");
205 if (Error Err = PSVInfo->parse(DXIL->first.ShaderKind))
206 return Err;
207 }
209}
210
213 if (Error Err = Container.parseHeader())
214 return std::move(Err);
215 if (Error Err = Container.parsePartOffsets())
216 return std::move(Err);
217 return Container;
218}
219
220void DXContainer::PartIterator::updateIteratorImpl(const uint32_t Offset) {
221 StringRef Buffer = Container.Data.getBuffer();
222 const char *Current = Buffer.data() + Offset;
223
224
226 IteratorState.Data =
228 IteratorState.Offset = Offset;
229}
230
233
234 const char *Current = Data.begin();
236 return Err;
238
240
241 if (PSVInfoData.size() < Size)
243 "Pipeline state data extends beyond the bounds of the part");
244
245 using namespace dxbc::PSV;
246
247 const uint32_t PSVVersion = getVersion();
248
249
250 if (PSVVersion == 3) {
251 v3::RuntimeInfo Info;
253 return Err;
255 Info.swapBytes(ShaderStage);
256 BasicInfo = Info;
257 } else if (PSVVersion == 2) {
258 v2::RuntimeInfo Info;
260 return Err;
262 Info.swapBytes(ShaderStage);
263 BasicInfo = Info;
264 } else if (PSVVersion == 1) {
265 v1::RuntimeInfo Info;
267 return Err;
269 Info.swapBytes(ShaderStage);
270 BasicInfo = Info;
271 } else if (PSVVersion == 0) {
272 v0::RuntimeInfo Info;
274 return Err;
276 Info.swapBytes(ShaderStage);
277 BasicInfo = Info;
278 } else
280 "Cannot read PSV Runtime Info, unsupported PSV version.");
281
282 Current += Size;
283
286 return Err;
288
289 if (ResourceCount > 0) {
291 return Err;
293
294 size_t BindingDataSize = Resources.Stride * ResourceCount;
295 Resources.Data = Data.substr(Current - Data.begin(), BindingDataSize);
296
297 if (Resources.Data.size() < BindingDataSize)
299 "Resource binding data extends beyond the bounds of the part");
300
301 Current += BindingDataSize;
302 } else
303 Resources.Stride = sizeof(v2::ResourceBindInfo);
304
305
306 if (PSVVersion == 0)
308
309
310 Current = reinterpret_cast<const char *>(
311 alignTo<4>(reinterpret_cast<uintptr_t>(Current)));
312
313 uint32_t StringTableSize = 0;
315 return Err;
316 if (StringTableSize % 4 != 0)
317 return parseFailed("String table misaligned");
320
321 Current += StringTableSize;
322
323 uint32_t SemanticIndexTableSize = 0;
325 return Err;
327
328 SemanticIndexTable.reserve(SemanticIndexTableSize);
329 for (uint32_t I = 0; I < SemanticIndexTableSize; ++I) {
332 return Err;
334 SemanticIndexTable.push_back(Index);
335 }
336
337 uint8_t InputCount = getSigInputCount();
338 uint8_t OutputCount = getSigOutputCount();
339 uint8_t PatchOrPrimCount = getSigPatchOrPrimCount();
340
342
345 return Err;
347
348 SigOutputElements.Stride = SigPatchOrPrimElements.Stride =
349 SigInputElements.Stride;
350
351 if (Data.end() - Current <
354 "Signature elements extend beyond the size of the part");
355
356 size_t InputSize = SigInputElements.Stride * InputCount;
357 SigInputElements.Data = Data.substr(Current - Data.begin(), InputSize);
358 Current += InputSize;
359
360 size_t OutputSize = SigOutputElements.Stride * OutputCount;
361 SigOutputElements.Data = Data.substr(Current - Data.begin(), OutputSize);
362 Current += OutputSize;
363
364 size_t PSize = SigPatchOrPrimElements.Stride * PatchOrPrimCount;
365 SigPatchOrPrimElements.Data = Data.substr(Current - Data.begin(), PSize);
366 Current += PSize;
367 }
368
370 uint8_t PatchConstOrPrimVectorCount = getPatchConstOrPrimVectorCount();
371 uint8_t InputVectorCount = getInputVectorCount();
372
375 };
376
378 return maskDwordSize(Y) * X * 4;
379 };
380
381 if (usesViewID()) {
382 for (uint32_t I = 0; I < OutputVectorCounts.size(); ++I) {
383
384
385
387 maskDwordSize(static_cast<uint32_t>(OutputVectorCounts[I]));
388 size_t NumBytes = NumDwords * sizeof(uint32_t);
389 OutputVectorMasks[I].Data = Data.substr(Current - Data.begin(), NumBytes);
390 Current += NumBytes;
391 }
392
393 if (ShaderStage == Triple::Hull && PatchConstOrPrimVectorCount > 0) {
394 uint32_t NumDwords = maskDwordSize(PatchConstOrPrimVectorCount);
395 size_t NumBytes = NumDwords * sizeof(uint32_t);
396 PatchOrPrimMasks.Data = Data.substr(Current - Data.begin(), NumBytes);
397 Current += NumBytes;
398 }
399 }
400
401
402 for (uint32_t I = 0; I < OutputVectorCounts.size(); ++I) {
403 if (InputVectorCount == 0 || OutputVectorCounts[I] == 0)
404 continue;
405 uint32_t NumDwords = mapTableSize(InputVectorCount, OutputVectorCounts[I]);
406 size_t NumBytes = NumDwords * sizeof(uint32_t);
407 InputOutputMap[I].Data = Data.substr(Current - Data.begin(), NumBytes);
408 Current += NumBytes;
409 }
410
411
412 if (ShaderStage == Triple::Hull && PatchConstOrPrimVectorCount > 0 &&
413 InputVectorCount > 0) {
415 mapTableSize(InputVectorCount, PatchConstOrPrimVectorCount);
416 size_t NumBytes = NumDwords * sizeof(uint32_t);
417 InputPatchMap.Data = Data.substr(Current - Data.begin(), NumBytes);
418 Current += NumBytes;
419 }
420
421
422 if (ShaderStage == Triple::Domain && PatchConstOrPrimVectorCount > 0 &&
423 OutputVectorCounts[0] > 0) {
425 mapTableSize(PatchConstOrPrimVectorCount, OutputVectorCounts[0]);
426 size_t NumBytes = NumDwords * sizeof(uint32_t);
427 PatchOutputMap.Data = Data.substr(Current - Data.begin(), NumBytes);
428 Current += NumBytes;
429 }
430
432}
433
435 if (const auto *P = std::get_ifdxbc::PSV::v3::RuntimeInfo(&BasicInfo))
436 return P->SigInputElements;
437 if (const auto *P = std::get_ifdxbc::PSV::v2::RuntimeInfo(&BasicInfo))
438 return P->SigInputElements;
439 if (const auto *P = std::get_ifdxbc::PSV::v1::RuntimeInfo(&BasicInfo))
440 return P->SigInputElements;
441 return 0;
442}
443
445 if (const auto *P = std::get_ifdxbc::PSV::v3::RuntimeInfo(&BasicInfo))
446 return P->SigOutputElements;
447 if (const auto *P = std::get_ifdxbc::PSV::v2::RuntimeInfo(&BasicInfo))
448 return P->SigOutputElements;
449 if (const auto *P = std::get_ifdxbc::PSV::v1::RuntimeInfo(&BasicInfo))
450 return P->SigOutputElements;
451 return 0;
452}
453
455 if (const auto *P = std::get_ifdxbc::PSV::v3::RuntimeInfo(&BasicInfo))
456 return P->SigPatchOrPrimElements;
457 if (const auto *P = std::get_ifdxbc::PSV::v2::RuntimeInfo(&BasicInfo))
458 return P->SigPatchOrPrimElements;
459 if (const auto *P = std::get_ifdxbc::PSV::v1::RuntimeInfo(&BasicInfo))
460 return P->SigPatchOrPrimElements;
461 return 0;
462}
#define offsetof(TYPE, MEMBER)
Analysis containing CSE Info
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static Error parseFailed(const Twine &Msg)
static Error readStruct(StringRef Buffer, const char *Src, T &Struct)
static Error readInteger(StringRef Buffer, const char *Src, T &Val, Twine Str="structure")
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
StringRef getBuffer() const
StringRef - Represent a constant reference to a string, i.e.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
A table of densely packed, null-terminated strings indexed by offset.
constexpr size_t size() const
Returns the byte size of the table.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::string str() const
Return the twine contents as a std::string.
static Expected< DXContainer > create(MemoryBufferRef Object)
uint8_t getSigInputCount() const
uint8_t getSigPatchOrPrimCount() const
Error parse(uint16_t ShaderKind)
uint8_t getSigOutputCount() const
Error initialize(StringRef Part)
PartType parsePartType(StringRef S)
Triple::EnvironmentType getShaderStage(uint32_t Kind)
constexpr bool IsBigEndianHost
void swapByteOrder(T &Value)
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.