19 return make_error<GenericBinaryError>(Msg.
str(), object_error::parse_failed);
25 if (Src < Buffer.
begin() || Src +
sizeof(
T) > Buffer.
end())
26 return parseFailed(
"Reading structure out of file bounds");
28 memcpy(&
Struct, Src,
sizeof(
T));
37 Twine Str =
"structure") {
38 static_assert(std::is_integral_v<T>,
39 "Cannot call readInteger on non-integral type.");
41 if (Src < Buffer.
begin() || Src +
sizeof(
T) > Buffer.
end())
47 if (
reinterpret_cast<uintptr_t
>(Src) %
alignof(
T) != 0)
48 memcpy(
reinterpret_cast<char *
>(&Val), Src,
sizeof(
T));
50 Val = *
reinterpret_cast<const T *
>(Src);
59Error DXContainer::parseHeader() {
65 return parseFailed(
"More than one DXIL part is present in the file");
66 const char *Current = Part.
begin();
71 DXIL.emplace(std::make_pair(Header, Current));
76 if (ShaderFeatureFlags)
77 return parseFailed(
"More than one SFI0 part is present in the file");
81 ShaderFeatureFlags = FlagValue;
87 return parseFailed(
"More than one HASH part is present in the file");
97 return parseFailed(
"More than one PSV0 part is present in the file");
111 return parseFailed(
"Signature parameters extend beyond the part boundary");
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");
129Error DXContainer::parsePartOffsets() {
133 for (
uint32_t Part = 0; Part < Header.PartCount; ++Part) {
137 if (PartOffset < LastOffset)
140 "Part offset for part {0} begins before the previous part ends",
144 if (PartOffset >=
Data.getBufferSize())
145 return parseFailed(
"Part offset points beyond boundary of the file");
152 return parseFailed(
"File not large enough to read part name");
153 PartOffsets.push_back(PartOffset);
160 Data.getBufferStart() + PartOffset + 4,
161 PartSize,
"part size"))
163 StringRef PartData =
Data.getBuffer().substr(PartDataStart, PartSize);
164 LastOffset = PartOffset + PartSize;
166 case dxbc::PartType::DXIL:
167 if (
Error Err = parseDXILHeader(PartData))
170 case dxbc::PartType::SFI0:
171 if (
Error Err = parseShaderFeatureFlags(PartData))
174 case dxbc::PartType::HASH:
175 if (
Error Err = parseHash(PartData))
178 case dxbc::PartType::PSV0:
179 if (
Error Err = parsePSVInfo(PartData))
182 case dxbc::PartType::ISG1:
183 if (
Error Err = InputSignature.initialize(PartData))
186 case dxbc::PartType::OSG1:
187 if (
Error Err = OutputSignature.initialize(PartData))
190 case dxbc::PartType::PSG1:
191 if (
Error Err = PatchConstantSignature.initialize(PartData))
203 return parseFailed(
"Cannot fully parse pipeline state validation "
204 "information without DXIL part.");
205 if (
Error Err = PSVInfo->parse(DXIL->first.ShaderKind))
213 if (
Error Err = Container.parseHeader())
214 return std::move(Err);
215 if (
Error Err = Container.parsePartOffsets())
216 return std::move(Err);
220void DXContainer::PartIterator::updateIteratorImpl(
const uint32_t Offset) {
221 StringRef Buffer = Container.Data.getBuffer();
228 IteratorState.Offset =
Offset;
234 const char *Current =
Data.begin();
243 "Pipeline state data extends beyond the bounds of the part");
245 using namespace dxbc::PSV;
247 const uint32_t PSVVersion = getVersion();
250 if (PSVVersion == 3) {
251 v3::RuntimeInfo
Info;
255 Info.swapBytes(ShaderStage);
257 }
else if (PSVVersion == 2) {
258 v2::RuntimeInfo
Info;
262 Info.swapBytes(ShaderStage);
264 }
else if (PSVVersion == 1) {
265 v1::RuntimeInfo
Info;
269 Info.swapBytes(ShaderStage);
271 }
else if (PSVVersion == 0) {
272 v0::RuntimeInfo
Info;
276 Info.swapBytes(ShaderStage);
280 "Cannot read PSV Runtime Info, unsupported PSV version.");
289 if (ResourceCount > 0) {
294 size_t BindingDataSize = Resources.Stride * ResourceCount;
295 Resources.Data =
Data.substr(Current -
Data.begin(), BindingDataSize);
297 if (Resources.Data.size() < BindingDataSize)
299 "Resource binding data extends beyond the bounds of the part");
301 Current += BindingDataSize;
303 Resources.Stride =
sizeof(v2::ResourceBindInfo);
310 Current =
reinterpret_cast<const char *
>(
311 alignTo<4>(
reinterpret_cast<uintptr_t
>(Current)));
316 if (StringTableSize % 4 != 0)
321 Current += StringTableSize;
323 uint32_t SemanticIndexTableSize = 0;
328 SemanticIndexTable.reserve(SemanticIndexTableSize);
329 for (
uint32_t I = 0;
I < SemanticIndexTableSize; ++
I) {
334 SemanticIndexTable.push_back(Index);
337 uint8_t InputCount = getSigInputCount();
338 uint8_t OutputCount = getSigOutputCount();
339 uint8_t PatchOrPrimCount = getSigPatchOrPrimCount();
348 SigOutputElements.Stride = SigPatchOrPrimElements.Stride =
349 SigInputElements.Stride;
351 if (
Data.end() - Current <
354 "Signature elements extend beyond the size of the part");
356 size_t InputSize = SigInputElements.Stride * InputCount;
357 SigInputElements.Data =
Data.substr(Current -
Data.begin(), InputSize);
358 Current += InputSize;
360 size_t OutputSize = SigOutputElements.Stride * OutputCount;
361 SigOutputElements.Data =
Data.substr(Current -
Data.begin(), OutputSize);
362 Current += OutputSize;
364 size_t PSize = SigPatchOrPrimElements.Stride * PatchOrPrimCount;
365 SigPatchOrPrimElements.Data =
Data.substr(Current -
Data.begin(), PSize);
370 uint8_t PatchConstOrPrimVectorCount = getPatchConstOrPrimVectorCount();
371 uint8_t InputVectorCount = getInputVectorCount();
378 return maskDwordSize(
Y) *
X * 4;
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);
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);
403 if (InputVectorCount == 0 || OutputVectorCounts[
I] == 0)
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);
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);
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);
435 if (
const auto *
P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo))
436 return P->SigInputElements;
437 if (
const auto *
P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))
438 return P->SigInputElements;
439 if (
const auto *
P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))
440 return P->SigInputElements;
445 if (
const auto *
P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo))
446 return P->SigOutputElements;
447 if (
const auto *
P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))
448 return P->SigOutputElements;
449 if (
const auto *
P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))
450 return P->SigOutputElements;
455 if (
const auto *
P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo))
456 return P->SigPatchOrPrimElements;
457 if (
const auto *
P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))
458 return P->SigPatchOrPrimElements;
459 if (
const auto *
P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))
460 return P->SigPatchOrPrimElements;
#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.