1//===- DXContainerEmitter.cpp - Convert YAML to a DXContainer -------------===//
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/// \file
10/// Binary emitter for yaml to DXContainer binary
11///
12//===----------------------------------------------------------------------===//
13
14#include "llvm/ADT/Sequence.h"
15#include "llvm/BinaryFormat/DXContainer.h"
16#include "llvm/MC/DXContainerInfo.h"
17#include "llvm/MC/DXContainerPSVInfo.h"
18#include "llvm/MC/DXContainerRootSignature.h"
19#include "llvm/ObjectYAML/DXContainerYAML.h"
20#include "llvm/ObjectYAML/yaml2obj.h"
21#include "llvm/Support/Errc.h"
22#include "llvm/Support/Error.h"
23#include "llvm/Support/raw_ostream.h"
24
25using namespace llvm;
26
27namespace {
28class DXContainerWriter {
29public:
30 DXContainerWriter(DXContainerYAML::Object &ObjectFile)
31 : ObjectFile(ObjectFile) {}
32
33 Error write(raw_ostream &OS);
34
35private:
36 DXContainerYAML::Object &ObjectFile;
37
38 Error computePartOffsets();
39 Error validatePartOffsets();
40 Error validateSize(uint32_t Computed);
41
42 void writeHeader(raw_ostream &OS);
43 Error writeParts(raw_ostream &OS);
44};
45} // namespace
46
47Error DXContainerWriter::validateSize(uint32_t Computed) {
48 if (!ObjectFile.Header.FileSize)
49 ObjectFile.Header.FileSize = Computed;
50 else if (*ObjectFile.Header.FileSize < Computed)
51 return createStringError(EC: errc::result_out_of_range,
52 S: "File size specified is too small.");
53 return Error::success();
54}
55
56Error DXContainerWriter::validatePartOffsets() {
57 if (ObjectFile.Parts.size() != ObjectFile.Header.PartOffsets->size())
58 return createStringError(
59 EC: errc::invalid_argument,
60 S: "Mismatch between number of parts and part offsets.");
61 uint32_t RollingOffset =
62 sizeof(dxbc::Header) + (ObjectFile.Header.PartCount * sizeof(uint32_t));
63 for (auto I : llvm::zip(t&: ObjectFile.Parts, u&: *ObjectFile.Header.PartOffsets)) {
64 if (RollingOffset > std::get<1>(t&: I))
65 return createStringError(EC: errc::invalid_argument,
66 S: "Offset mismatch, not enough space for data.");
67 RollingOffset =
68 std::get<1>(t&: I) + sizeof(dxbc::PartHeader) + std::get<0>(t&: I).Size;
69 }
70 if (Error Err = validateSize(Computed: RollingOffset))
71 return Err;
72
73 return Error::success();
74}
75
76Error DXContainerWriter::computePartOffsets() {
77 if (ObjectFile.Header.PartOffsets)
78 return validatePartOffsets();
79 uint32_t RollingOffset =
80 sizeof(dxbc::Header) + (ObjectFile.Header.PartCount * sizeof(uint32_t));
81 ObjectFile.Header.PartOffsets = std::vector<uint32_t>();
82 for (const auto &Part : ObjectFile.Parts) {
83 ObjectFile.Header.PartOffsets->push_back(x: RollingOffset);
84 RollingOffset += sizeof(dxbc::PartHeader) + Part.Size;
85 }
86 if (Error Err = validateSize(Computed: RollingOffset))
87 return Err;
88
89 return Error::success();
90}
91
92void DXContainerWriter::writeHeader(raw_ostream &OS) {
93 dxbc::Header Header;
94 memcpy(dest: Header.Magic, src: "DXBC", n: 4);
95 memcpy(dest: Header.FileHash.Digest, src: ObjectFile.Header.Hash.data(), n: 16);
96 Header.Version.Major = ObjectFile.Header.Version.Major;
97 Header.Version.Minor = ObjectFile.Header.Version.Minor;
98 Header.FileSize = *ObjectFile.Header.FileSize;
99 Header.PartCount = ObjectFile.Parts.size();
100 if (sys::IsBigEndianHost)
101 Header.swapBytes();
102 OS.write(Ptr: reinterpret_cast<char *>(&Header), Size: sizeof(Header));
103 SmallVector<uint32_t> Offsets(ObjectFile.Header.PartOffsets->begin(),
104 ObjectFile.Header.PartOffsets->end());
105 if (sys::IsBigEndianHost)
106 for (auto &O : Offsets)
107 sys::swapByteOrder(Value&: O);
108 OS.write(Ptr: reinterpret_cast<char *>(Offsets.data()),
109 Size: Offsets.size() * sizeof(uint32_t));
110}
111
112// TODO use it for VERS too
113template <typename T>
114static void assign_if(T &Dst, const std::optional<T> &Src) {
115 if (Src)
116 Dst = *Src;
117}
118
119static void
120assignSectionHeader(dxbc::SourceInfo::SectionHeader &Dst,
121 const DXContainerYAML::SourceInfo::Section &Src) {
122 assign_if(Dst&: Dst.AlignedSizeInBytes, Src: Src.GenericHeader.AlignedSizeInBytes);
123 assign_if(Dst&: Dst.Flags, Src: Src.GenericHeader.Flags);
124 assign_if(Dst&: Dst.Type, Src: Src.GenericHeader.Type);
125}
126
127Error DXContainerWriter::writeParts(raw_ostream &OS) {
128 uint32_t RollingOffset =
129 sizeof(dxbc::Header) + (ObjectFile.Header.PartCount * sizeof(uint32_t));
130 for (auto I : llvm::zip(t&: ObjectFile.Parts, u&: *ObjectFile.Header.PartOffsets)) {
131 if (RollingOffset < std::get<1>(t&: I)) {
132 uint32_t PadBytes = std::get<1>(t&: I) - RollingOffset;
133 OS.write_zeros(NumZeros: PadBytes);
134 }
135 DXContainerYAML::Part P = std::get<0>(t&: I);
136 RollingOffset = std::get<1>(t&: I) + sizeof(dxbc::PartHeader);
137 uint32_t PartSize = P.Size;
138
139 OS.write(Ptr: P.Name.c_str(), Size: 4);
140 if (sys::IsBigEndianHost)
141 sys::swapByteOrder(Value&: P.Size);
142 OS.write(Ptr: reinterpret_cast<const char *>(&P.Size), Size: sizeof(uint32_t));
143
144 dxbc::PartType PT = dxbc::parsePartType(S: P.Name);
145
146 uint64_t DataStart = OS.tell();
147 switch (PT) {
148 case dxbc::PartType::DXIL:
149 case dxbc::PartType::ILDB: {
150 if (!P.Program)
151 continue;
152 dxbc::ProgramHeader Header;
153 Header.Version = dxbc::ProgramHeader::getVersion(Major: P.Program->MajorVersion,
154 Minor: P.Program->MinorVersion);
155 Header.Unused = 0;
156 Header.ShaderKind = P.Program->ShaderKind;
157 memcpy(dest: Header.Bitcode.Magic, src: "DXIL", n: 4);
158 Header.Bitcode.MajorVersion = P.Program->DXILMajorVersion;
159 Header.Bitcode.MinorVersion = P.Program->DXILMinorVersion;
160 Header.Bitcode.Unused = 0;
161
162 // Compute the optional fields if needed...
163 if (P.Program->DXILOffset)
164 Header.Bitcode.Offset = *P.Program->DXILOffset;
165 else
166 Header.Bitcode.Offset = sizeof(dxbc::BitcodeHeader);
167
168 if (P.Program->DXILSize)
169 Header.Bitcode.Size = *P.Program->DXILSize;
170 else
171 Header.Bitcode.Size = P.Program->DXIL ? P.Program->DXIL->size() : 0;
172
173 if (P.Program->Size)
174 Header.Size = *P.Program->Size;
175 else
176 Header.Size = sizeof(dxbc::ProgramHeader) + Header.Bitcode.Size;
177
178 uint32_t BitcodeOffset = Header.Bitcode.Offset;
179 if (sys::IsBigEndianHost)
180 Header.swapBytes();
181 OS.write(Ptr: reinterpret_cast<const char *>(&Header),
182 Size: sizeof(dxbc::ProgramHeader));
183 if (P.Program->DXIL) {
184 if (BitcodeOffset > sizeof(dxbc::BitcodeHeader)) {
185 uint32_t PadBytes = BitcodeOffset - sizeof(dxbc::BitcodeHeader);
186 OS.write_zeros(NumZeros: PadBytes);
187 }
188 OS.write(Ptr: reinterpret_cast<char *>(P.Program->DXIL->data()),
189 Size: P.Program->DXIL->size());
190 }
191 break;
192 }
193 case dxbc::PartType::ILDN: {
194 if (!P.DebugName)
195 continue;
196
197 mcdxbc::DebugName DebugName;
198 DebugName.setFilename(P.DebugName->Filename);
199 // Override default flags with value from YAML.
200 if (P.DebugName->Flags)
201 DebugName.Parameters.Flags = *P.DebugName->Flags;
202 // Override computed filename length with value from YAML.
203 if (P.DebugName->NameLength)
204 DebugName.Parameters.NameLength = *P.DebugName->NameLength;
205 DebugName.write(OS);
206 break;
207 }
208 case dxbc::PartType::PRIV: {
209 if (!P.PrivateData)
210 continue;
211 OS.write(Ptr: reinterpret_cast<char *>(P.PrivateData->data()),
212 Size: P.PrivateData->size());
213 break;
214 }
215 case dxbc::PartType::SFI0: {
216 // If we don't have any flags we can continue here and the data will be
217 // zeroed out.
218 if (!P.Flags.has_value())
219 continue;
220 uint64_t Flags = P.Flags->getEncodedFlags();
221 if (sys::IsBigEndianHost)
222 sys::swapByteOrder(Value&: Flags);
223 OS.write(Ptr: reinterpret_cast<char *>(&Flags), Size: sizeof(uint64_t));
224 break;
225 }
226 case dxbc::PartType::HASH: {
227 if (!P.Hash.has_value())
228 continue;
229 dxbc::ShaderHash Hash = {.Flags: 0, .Digest: {0}};
230 if (P.Hash->IncludesSource)
231 Hash.Flags |= static_cast<uint32_t>(dxbc::HashFlags::IncludesSource);
232 memcpy(dest: &Hash.Digest[0], src: &P.Hash->Digest[0], n: 16);
233 if (sys::IsBigEndianHost)
234 Hash.swapBytes();
235 OS.write(Ptr: reinterpret_cast<char *>(&Hash), Size: sizeof(dxbc::ShaderHash));
236 break;
237 }
238 case dxbc::PartType::PSV0: {
239 if (!P.Info.has_value())
240 continue;
241 mcdxbc::PSVRuntimeInfo PSV;
242 memcpy(dest: &PSV.BaseData, src: &P.Info->Info, n: sizeof(dxbc::PSV::v3::RuntimeInfo));
243 PSV.Resources = P.Info->Resources;
244 PSV.EntryName = P.Info->EntryName;
245
246 for (auto El : P.Info->SigInputElements)
247 PSV.InputElements.push_back(Elt: mcdxbc::PSVSignatureElement{
248 .Name: El.Name, .Indices: El.Indices, .StartRow: El.StartRow, .Cols: El.Cols, .StartCol: El.StartCol,
249 .Allocated: El.Allocated, .Kind: El.Kind, .Type: El.Type, .Mode: El.Mode, .DynamicMask: El.DynamicMask,
250 .Stream: El.Stream});
251
252 for (auto El : P.Info->SigOutputElements)
253 PSV.OutputElements.push_back(Elt: mcdxbc::PSVSignatureElement{
254 .Name: El.Name, .Indices: El.Indices, .StartRow: El.StartRow, .Cols: El.Cols, .StartCol: El.StartCol,
255 .Allocated: El.Allocated, .Kind: El.Kind, .Type: El.Type, .Mode: El.Mode, .DynamicMask: El.DynamicMask,
256 .Stream: El.Stream});
257
258 for (auto El : P.Info->SigPatchOrPrimElements)
259 PSV.PatchOrPrimElements.push_back(Elt: mcdxbc::PSVSignatureElement{
260 .Name: El.Name, .Indices: El.Indices, .StartRow: El.StartRow, .Cols: El.Cols, .StartCol: El.StartCol,
261 .Allocated: El.Allocated, .Kind: El.Kind, .Type: El.Type, .Mode: El.Mode, .DynamicMask: El.DynamicMask,
262 .Stream: El.Stream});
263
264 static_assert(PSV.OutputVectorMasks.size() == PSV.InputOutputMap.size());
265 for (unsigned I = 0; I < PSV.OutputVectorMasks.size(); ++I) {
266 PSV.OutputVectorMasks[I].insert(I: PSV.OutputVectorMasks[I].begin(),
267 From: P.Info->OutputVectorMasks[I].begin(),
268 To: P.Info->OutputVectorMasks[I].end());
269 PSV.InputOutputMap[I].insert(I: PSV.InputOutputMap[I].begin(),
270 From: P.Info->InputOutputMap[I].begin(),
271 To: P.Info->InputOutputMap[I].end());
272 }
273
274 PSV.PatchOrPrimMasks.insert(I: PSV.PatchOrPrimMasks.begin(),
275 From: P.Info->PatchOrPrimMasks.begin(),
276 To: P.Info->PatchOrPrimMasks.end());
277 PSV.InputPatchMap.insert(I: PSV.InputPatchMap.begin(),
278 From: P.Info->InputPatchMap.begin(),
279 To: P.Info->InputPatchMap.end());
280 PSV.PatchOutputMap.insert(I: PSV.PatchOutputMap.begin(),
281 From: P.Info->PatchOutputMap.begin(),
282 To: P.Info->PatchOutputMap.end());
283
284 PSV.finalize(Stage: static_cast<Triple::EnvironmentType>(
285 Triple::Pixel + P.Info->Info.ShaderStage),
286 Version: P.Info->Version);
287 PSV.write(OS, Version: P.Info->Version);
288 break;
289 }
290 case dxbc::PartType::ISG1:
291 case dxbc::PartType::OSG1:
292 case dxbc::PartType::PSG1: {
293 mcdxbc::Signature Sig;
294 if (P.Signature.has_value()) {
295 for (const auto &Param : P.Signature->Parameters) {
296 Sig.addParam(Stream: Param.Stream, Name: Param.Name, Index: Param.Index, SystemValue: Param.SystemValue,
297 CompType: Param.CompType, Register: Param.Register, Mask: Param.Mask,
298 ExclusiveMask: Param.ExclusiveMask, MinPrecision: Param.MinPrecision);
299 }
300 }
301 Sig.write(OS);
302 break;
303 }
304 case dxbc::PartType::Unknown:
305 break; // Skip any handling for unrecognized parts.
306 case dxbc::PartType::RTS0: {
307 if (!P.RootSignature.has_value())
308 continue;
309
310 mcdxbc::RootSignatureDesc RS;
311 RS.Flags = P.RootSignature->getEncodedFlags();
312 RS.Version = P.RootSignature->Version;
313 RS.NumStaticSamplers = P.RootSignature->NumStaticSamplers;
314
315 for (DXContainerYAML::RootParameterLocationYaml &L :
316 P.RootSignature->Parameters.Locations) {
317
318 const dxbc::RootParameterType Type = L.Header.Type;
319 const dxbc::ShaderVisibility Visibility = L.Header.Visibility;
320
321 switch (Type) {
322 case dxbc::RootParameterType::Constants32Bit: {
323 const DXContainerYAML::RootConstantsYaml &ConstantYaml =
324 P.RootSignature->Parameters.getOrInsertConstants(ParamDesc&: L);
325 mcdxbc::RootConstants Constants;
326
327 Constants.Num32BitValues = ConstantYaml.Num32BitValues;
328 Constants.RegisterSpace = ConstantYaml.RegisterSpace;
329 Constants.ShaderRegister = ConstantYaml.ShaderRegister;
330 RS.ParametersContainer.addParameter(Type, Visibility, Constant: Constants);
331 break;
332 }
333 case dxbc::RootParameterType::CBV:
334 case dxbc::RootParameterType::SRV:
335 case dxbc::RootParameterType::UAV: {
336 const DXContainerYAML::RootDescriptorYaml &DescriptorYaml =
337 P.RootSignature->Parameters.getOrInsertDescriptor(ParamDesc&: L);
338
339 mcdxbc::RootDescriptor Descriptor;
340 Descriptor.RegisterSpace = DescriptorYaml.RegisterSpace;
341 Descriptor.ShaderRegister = DescriptorYaml.ShaderRegister;
342 if (RS.Version > 1)
343 Descriptor.Flags = DescriptorYaml.getEncodedFlags();
344 RS.ParametersContainer.addParameter(Type, Visibility, Descriptor);
345 break;
346 }
347 case dxbc::RootParameterType::DescriptorTable: {
348 const DXContainerYAML::DescriptorTableYaml &TableYaml =
349 P.RootSignature->Parameters.getOrInsertTable(ParamDesc&: L);
350 mcdxbc::DescriptorTable Table;
351 for (const auto &R : TableYaml.Ranges) {
352 mcdxbc::DescriptorRange Range;
353 Range.RangeType = R.RangeType;
354 Range.NumDescriptors = R.NumDescriptors;
355 Range.BaseShaderRegister = R.BaseShaderRegister;
356 Range.RegisterSpace = R.RegisterSpace;
357 Range.OffsetInDescriptorsFromTableStart =
358 R.OffsetInDescriptorsFromTableStart;
359
360 if (RS.Version > 1)
361 Range.Flags = R.getEncodedFlags();
362
363 Table.Ranges.push_back(Elt: Range);
364 }
365 RS.ParametersContainer.addParameter(Type, Visibility, Table);
366 break;
367 }
368 }
369 }
370
371 for (const auto &Param : P.RootSignature->samplers()) {
372 mcdxbc::StaticSampler NewSampler;
373 NewSampler.Filter = Param.Filter;
374 NewSampler.AddressU = Param.AddressU;
375 NewSampler.AddressV = Param.AddressV;
376 NewSampler.AddressW = Param.AddressW;
377 NewSampler.MipLODBias = Param.MipLODBias;
378 NewSampler.MaxAnisotropy = Param.MaxAnisotropy;
379 NewSampler.ComparisonFunc = Param.ComparisonFunc;
380 NewSampler.BorderColor = Param.BorderColor;
381 NewSampler.MinLOD = Param.MinLOD;
382 NewSampler.MaxLOD = Param.MaxLOD;
383 NewSampler.ShaderRegister = Param.ShaderRegister;
384 NewSampler.RegisterSpace = Param.RegisterSpace;
385 NewSampler.ShaderVisibility = Param.ShaderVisibility;
386
387 if (RS.Version > 2)
388 NewSampler.Flags = Param.getEncodedFlags();
389
390 RS.StaticSamplers.push_back(Elt: NewSampler);
391 }
392
393 // Handling of offsets
394 RS.RootParameterOffset = RS.computeRootParametersOffset();
395 if (P.RootSignature->RootParametersOffset &&
396 P.RootSignature->RootParametersOffset.value() !=
397 RS.RootParameterOffset) {
398 return createStringError(
399 EC: errc::invalid_argument,
400 Fmt: "Specified RootParametersOffset does not match required value: %d.",
401 Vals: RS.RootParameterOffset);
402 }
403
404 RS.StaticSamplersOffset = RS.computeStaticSamplersOffset();
405 if (P.RootSignature->StaticSamplersOffset &&
406 P.RootSignature->StaticSamplersOffset.value() !=
407 RS.StaticSamplersOffset) {
408 return createStringError(
409 EC: errc::invalid_argument,
410 Fmt: "Specified StaticSamplersOffset does not match computed value: %d.",
411 Vals: RS.StaticSamplersOffset);
412 }
413
414 RS.write(OS);
415 break;
416 }
417 case dxbc::PartType::SRCI: {
418 if (!P.SourceInfo.has_value())
419 continue;
420 mcdxbc::SourceInfoBuilder SourceInfo;
421 auto &ContentsYAML = P.SourceInfo->Contents;
422 SourceInfo.setCompressionType(ContentsYAML.Parameters.Type);
423
424 if (ContentsYAML.Entries.size() != P.SourceInfo->Names.Entries.size())
425 return createStringError(
426 EC: errc::invalid_argument,
427 S: "number of entries in Names section must match number of entries "
428 "in Contents section in SRCI part");
429
430 for (size_t I : llvm::seq(Size: ContentsYAML.Entries.size()))
431 SourceInfo.addFile(Name: P.SourceInfo->Names.Entries[I].FileName,
432 Content: ContentsYAML.Entries[I].FileContent);
433 for (auto &ArgEntry : P.SourceInfo->Args.Args)
434 SourceInfo.addArg(Name: ArgEntry.first, Value: ArgEntry.second);
435
436 SourceInfo.computeEntries();
437
438 // If entries field values are provided in YAML, override them in
439 // SourceInfo.
440 for (size_t I : llvm::seq(Size: ContentsYAML.Entries.size())) {
441 auto &ContentEntryYAML = ContentsYAML.Entries[I];
442 auto &ContentEntry = SourceInfo.BaseData.Contents.Entries[I];
443 assign_if(Dst&: ContentEntry.Parameters.AlignedSizeInBytes,
444 Src: ContentEntryYAML.AlignedSizeInBytes);
445 assign_if(Dst&: ContentEntry.Parameters.Flags, Src: ContentEntryYAML.Flags);
446 assign_if(Dst&: ContentEntry.Parameters.ContentSizeInBytes,
447 Src: ContentEntryYAML.ContentSizeInBytes);
448
449 auto &NameEntryYAML = P.SourceInfo->Names.Entries[I];
450 auto &NameEntry = SourceInfo.BaseData.Names.Entries[I];
451 assign_if(Dst&: NameEntry.Parameters.AlignedSizeInBytes,
452 Src: NameEntryYAML.AlignedSizeInBytes);
453 assign_if(Dst&: NameEntry.Parameters.Flags, Src: NameEntryYAML.Flags);
454 assign_if(Dst&: NameEntry.Parameters.NameSizeInBytes,
455 Src: NameEntryYAML.NameSizeInBytes);
456 assign_if(Dst&: NameEntry.Parameters.ContentSizeInBytes,
457 Src: NameEntryYAML.ContentSizeInBytes);
458 }
459
460 SourceInfo.finalize();
461
462 // If section header field values are provided in YAML, override them in
463 // SourceInfo.
464 auto &Contents = SourceInfo.BaseData.Contents;
465 assignSectionHeader(Dst&: Contents.GenericHeader, Src: ContentsYAML);
466 assign_if(Dst&: Contents.Parameters.AlignedSizeInBytes,
467 Src: ContentsYAML.Parameters.AlignedSizeInBytes);
468 assign_if(Dst&: Contents.Parameters.Flags, Src: ContentsYAML.Parameters.Flags);
469 assign_if(Dst&: Contents.Parameters.EntriesSizeInBytes,
470 Src: ContentsYAML.Parameters.EntriesSizeInBytes);
471 assign_if(Dst&: Contents.Parameters.UncompressedEntriesSizeInBytes,
472 Src: ContentsYAML.Parameters.UncompressedEntriesSizeInBytes);
473 if (ContentsYAML.Parameters.Count &&
474 ContentsYAML.Parameters.Count != Contents.Parameters.Count)
475 return createStringError(
476 EC: errc::invalid_argument,
477 S: "the value of Count field in Contents header must match the number "
478 "of entries in Contents section");
479
480 auto &NamesYAML = P.SourceInfo->Names;
481 auto &Names = SourceInfo.BaseData.Names;
482 assignSectionHeader(Dst&: Names.GenericHeader, Src: NamesYAML);
483 assign_if(Dst&: Names.Parameters.Flags, Src: NamesYAML.Parameters.Flags);
484 assign_if(Dst&: Names.Parameters.EntriesSizeInBytes,
485 Src: NamesYAML.Parameters.EntriesSizeInBytes);
486 if (NamesYAML.Parameters.Count &&
487 NamesYAML.Parameters.Count != Names.Parameters.Count)
488 return createStringError(
489 EC: errc::invalid_argument,
490 S: "the value of Count field in Names header must match the number of "
491 "entries in Names section");
492
493 auto &ArgsYAML = P.SourceInfo->Args;
494 auto &Args = SourceInfo.BaseData.Args;
495 assignSectionHeader(Dst&: Args.GenericHeader, Src: ArgsYAML);
496 assign_if(Dst&: Args.Parameters.Flags, Src: ArgsYAML.Parameters.Flags);
497 assign_if(Dst&: Args.Parameters.SizeInBytes, Src: ArgsYAML.Parameters.SizeInBytes);
498 if (ArgsYAML.Parameters.Count &&
499 ArgsYAML.Parameters.Count != Args.Parameters.Count)
500 return createStringError(EC: errc::invalid_argument,
501 S: "the value of Count field in Args header must "
502 "match the number of entries in Args section");
503
504 assign_if(Dst&: SourceInfo.BaseData.Parameters.AlignedSizeInBytes,
505 Src: P.SourceInfo->Parameters.AlignedSizeInBytes);
506 assign_if(Dst&: SourceInfo.BaseData.Parameters.Flags,
507 Src: P.SourceInfo->Parameters.Flags);
508 assign_if(Dst&: SourceInfo.BaseData.Parameters.SectionCount,
509 Src: P.SourceInfo->Parameters.SectionCount);
510
511 SourceInfo.write(OS);
512 break;
513 }
514 case dxbc::PartType::VERS: {
515 if (!P.CompilerVersion)
516 continue;
517
518 mcdxbc::CompilerVersion CompilerVersion;
519 CompilerVersion.Parameters.Major =
520 P.CompilerVersion->Major.value_or(u&: CompilerVersion.Parameters.Major);
521 CompilerVersion.Parameters.Minor =
522 P.CompilerVersion->Minor.value_or(u&: CompilerVersion.Parameters.Minor);
523
524 if (P.CompilerVersion->IsDebugBuild || P.CompilerVersion->IsValidated)
525 CompilerVersion.Parameters.Flags = dxbc::CompilerVersionFlags::Default;
526 if (P.CompilerVersion->IsDebugBuild.value_or(u: false))
527 CompilerVersion.Parameters.Flags |= dxbc::CompilerVersionFlags::Debug;
528 if (P.CompilerVersion->IsValidated.value_or(u: false))
529 CompilerVersion.Parameters.Flags |=
530 dxbc::CompilerVersionFlags::Internal;
531
532 CompilerVersion.Parameters.CommitCount =
533 P.CompilerVersion->CommitCount.value_or(
534 u&: CompilerVersion.Parameters.CommitCount);
535
536 if (P.CompilerVersion->CommitSha)
537 CompilerVersion.setCommitSha(*P.CompilerVersion->CommitSha);
538 if (P.CompilerVersion->CustomVersionString)
539 CompilerVersion.setVersionString(
540 *P.CompilerVersion->CustomVersionString);
541
542 CompilerVersion.Parameters.ContentSizeInBytes =
543 P.CompilerVersion->ContentSizeInBytes.value_or(
544 u&: CompilerVersion.Parameters.ContentSizeInBytes);
545
546 CompilerVersion.write(OS);
547 break;
548 }
549 }
550 uint64_t BytesWritten = OS.tell() - DataStart;
551 RollingOffset += BytesWritten;
552 if (BytesWritten < PartSize)
553 OS.write_zeros(NumZeros: PartSize - BytesWritten);
554 RollingOffset += PartSize;
555 }
556
557 return Error::success();
558}
559
560Error DXContainerWriter::write(raw_ostream &OS) {
561 if (Error Err = computePartOffsets())
562 return Err;
563 writeHeader(OS);
564 return writeParts(OS);
565}
566
567namespace llvm {
568namespace yaml {
569
570bool yaml2dxcontainer(DXContainerYAML::Object &Doc, raw_ostream &Out,
571 ErrorHandler EH) {
572 DXContainerWriter Writer(Doc);
573 if (Error Err = Writer.write(OS&: Out)) {
574 handleAllErrors(E: std::move(Err),
575 Handlers: [&](const ErrorInfoBase &Err) { EH(Err.message()); });
576 return false;
577 }
578 return true;
579}
580
581} // namespace yaml
582} // namespace llvm
583