diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index e8d03f806715..847d8103e681 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainer.h +++ b/llvm/include/llvm/BinaryFormat/DXContainer.h @@ -119,8 +119,7 @@ struct BitcodeHeader { }; struct ProgramHeader { - uint8_t MinorVersion : 4; - uint8_t MajorVersion : 4; + uint8_t Version; uint8_t Unused; uint16_t ShaderKind; uint32_t Size; // Size in uint32_t words including this header. @@ -131,6 +130,11 @@ struct ProgramHeader { sys::swapByteOrder(Size); Bitcode.swapBytes(); } + uint8_t getMajorVersion() { return Version >> 4; } + uint8_t getMinorVersion() { return Version & 0xF; } + static uint8_t getVersion(uint8_t Major, uint8_t Minor) { + return (Major << 4) | Minor; + } }; static_assert(sizeof(ProgramHeader) == 24, "ProgramHeader Size incorrect!"); diff --git a/llvm/lib/MC/MCDXContainerWriter.cpp b/llvm/lib/MC/MCDXContainerWriter.cpp index 0580dc7e4282..ff64c6e538ac 100644 --- a/llvm/lib/MC/MCDXContainerWriter.cpp +++ b/llvm/lib/MC/MCDXContainerWriter.cpp @@ -117,9 +117,11 @@ uint64_t DXContainerObjectWriter::writeObject(MCAssembler &Asm, const Triple &TT = Asm.getContext().getTargetTriple(); VersionTuple Version = TT.getOSVersion(); - Header.MajorVersion = static_cast(Version.getMajor()); - if (Version.getMinor()) - Header.MinorVersion = static_cast(*Version.getMinor()); + uint8_t MajorVersion = static_cast(Version.getMajor()); + uint8_t MinorVersion = + static_cast(Version.getMinor().value_or(0)); + Header.Version = + dxbc::ProgramHeader::getVersion(MajorVersion, MinorVersion); if (TT.hasEnvironment()) Header.ShaderKind = static_cast(TT.getEnvironment() - Triple::Pixel); diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp index f3a518df3175..175f1a12f931 100644 --- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp +++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp @@ -131,8 +131,8 @@ void DXContainerWriter::writeParts(raw_ostream &OS) { if (!P.Program) continue; dxbc::ProgramHeader Header; - Header.MajorVersion = P.Program->MajorVersion; - Header.MinorVersion = P.Program->MinorVersion; + Header.Version = dxbc::ProgramHeader::getVersion(P.Program->MajorVersion, + P.Program->MinorVersion); Header.Unused = 0; Header.ShaderKind = P.Program->ShaderKind; memcpy(Header.Bitcode.Magic, "DXIL", 4); diff --git a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp index ec4f5c74498f..06966b188358 100644 --- a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp +++ b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp @@ -58,8 +58,8 @@ dumpDXContainer(MemoryBufferRef Source) { assert(DXIL && "Since we are iterating and found a DXIL part, " "this should never not have a value"); NewPart.Program = DXContainerYAML::DXILProgram{ - DXIL->first.MajorVersion, - DXIL->first.MinorVersion, + DXIL->first.getMajorVersion(), + DXIL->first.getMinorVersion(), DXIL->first.ShaderKind, DXIL->first.Size, DXIL->first.Bitcode.MajorVersion, diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp index da640225617d..115de47a3cef 100644 --- a/llvm/unittests/Object/DXContainerTest.cpp +++ b/llvm/unittests/Object/DXContainerTest.cpp @@ -174,6 +174,49 @@ TEST(DXCFile, ParseEmptyParts) { } } +// This test verify DXIL part are correctly parsed. +// This test is based on the binary output constructed from this yaml. +// --- !dxcontainer +// Header: +// Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +// 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] +// Version: +// Major: 1 +// Minor: 0 +// PartCount: 1 +// Parts: +// - Name: DXIL +// Size: 28 +// Program: +// MajorVersion: 6 +// MinorVersion: 5 +// ShaderKind: 5 +// Size: 8 +// DXILMajorVersion: 1 +// DXILMinorVersion: 5 +// DXILSize: 4 +// DXIL: [ 0x42, 0x43, 0xC0, 0xDE, ] +// ... +TEST(DXCFile, ParseDXILPart) { + uint8_t Buffer[] = { + 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x44, 0x58, 0x49, 0x4c, 0x1c, 0x00, 0x00, 0x00, 0x65, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x05, 0x01, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde}; + DXContainer C = + llvm::cantFail(DXContainer::create(getMemoryBuffer<116>(Buffer))); + EXPECT_EQ(C.getHeader().PartCount, 1u); + const std::optional &DXIL = C.getDXIL(); + EXPECT_TRUE(DXIL.has_value()); + dxbc::ProgramHeader Header = DXIL->first; + EXPECT_EQ(Header.getMajorVersion(), 6u); + EXPECT_EQ(Header.getMinorVersion(), 5u); + EXPECT_EQ(Header.ShaderKind, 5u); + EXPECT_EQ(Header.Size, 8u); +} + static Expected generateDXContainer(StringRef Yaml, SmallVectorImpl &BinaryData) { DXContainerYAML::Object Obj;