1 //===------ dxcontainer2yaml.cpp - obj2yaml conversion tool -----*- 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 #include "obj2yaml.h"
10 #include "llvm/Object/DXContainer.h"
11 #include "llvm/ObjectYAML/DXContainerYAML.h"
12 #include "llvm/Support/Error.h"
13
14 #include <algorithm>
15
16 using namespace llvm;
17 using namespace llvm::object;
18
19 static Expected<DXContainerYAML::Object *>
dumpDXContainer(MemoryBufferRef Source)20 dumpDXContainer(MemoryBufferRef Source) {
21 assert(file_magic::dxcontainer_object == identify_magic(Source.getBuffer()));
22
23 Expected<DXContainer> ExDXC = DXContainer::create(Source);
24 if (!ExDXC)
25 return ExDXC.takeError();
26 DXContainer Container = *ExDXC;
27
28 std::unique_ptr<DXContainerYAML::Object> Obj =
29 std::make_unique<DXContainerYAML::Object>();
30
31 for (uint8_t Byte : Container.getHeader().FileHash.Digest)
32 Obj->Header.Hash.push_back(Byte);
33 Obj->Header.Version.Major = Container.getHeader().Version.Major;
34 Obj->Header.Version.Minor = Container.getHeader().Version.Minor;
35 Obj->Header.FileSize = Container.getHeader().FileSize;
36 Obj->Header.PartCount = Container.getHeader().PartCount;
37
38 Obj->Header.PartOffsets = std::vector<uint32_t>();
39 for (const auto P : Container) {
40 Obj->Header.PartOffsets->push_back(P.Offset);
41 Obj->Parts.push_back(
42 DXContainerYAML::Part(P.Part.getName().str(), P.Part.Size));
43 DXContainerYAML::Part &NewPart = Obj->Parts.back();
44 dxbc::PartType PT = dxbc::parsePartType(P.Part.getName());
45 switch (PT) {
46 case dxbc::PartType::DXIL: {
47 std::optional<DXContainer::DXILData> DXIL = Container.getDXIL();
48 assert(DXIL && "Since we are iterating and found a DXIL part, "
49 "this should never not have a value");
50 NewPart.Program = DXContainerYAML::DXILProgram{
51 DXIL->first.MajorVersion,
52 DXIL->first.MinorVersion,
53 DXIL->first.ShaderKind,
54 DXIL->first.Size,
55 DXIL->first.Bitcode.MajorVersion,
56 DXIL->first.Bitcode.MinorVersion,
57 DXIL->first.Bitcode.Offset,
58 DXIL->first.Bitcode.Size,
59 std::vector<llvm::yaml::Hex8>(
60 DXIL->second, DXIL->second + DXIL->first.Bitcode.Size)};
61 break;
62 }
63 case dxbc::PartType::SFI0: {
64 std::optional<uint64_t> Flags = Container.getShaderFlags();
65 // Omit the flags in the YAML if they are missing or zero.
66 if (Flags && *Flags > 0)
67 NewPart.Flags = DXContainerYAML::ShaderFlags(*Flags);
68 break;
69 }
70 case dxbc::PartType::HASH: {
71 std::optional<dxbc::ShaderHash> Hash = Container.getShaderHash();
72 if (Hash && Hash->isPopulated())
73 NewPart.Hash = DXContainerYAML::ShaderHash(*Hash);
74 break;
75 }
76 case dxbc::PartType::Unknown:
77 break;
78 }
79 }
80
81 return Obj.release();
82 }
83
dxcontainer2yaml(llvm::raw_ostream & Out,llvm::MemoryBufferRef Source)84 llvm::Error dxcontainer2yaml(llvm::raw_ostream &Out,
85 llvm::MemoryBufferRef Source) {
86 Expected<DXContainerYAML::Object *> YAMLOrErr = dumpDXContainer(Source);
87 if (!YAMLOrErr)
88 return YAMLOrErr.takeError();
89
90 std::unique_ptr<DXContainerYAML::Object> YAML(YAMLOrErr.get());
91 yaml::Output Yout(Out);
92 Yout << *YAML;
93
94 return Error::success();
95 }
96