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 *> 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 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