xref: /openbsd-src/gnu/llvm/llvm/tools/obj2yaml/dxcontainer2yaml.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
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