Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions llvm/include/llvm/BinaryFormat/DXContainerConstants.def
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
CONTAINER_PART(DXIL)
CONTAINER_PART(ILDB)
CONTAINER_PART(ILDN)
CONTAINER_PART(PRIV)
CONTAINER_PART(SFI0)
CONTAINER_PART(SRCI)
CONTAINER_PART(HASH)
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/Object/DXContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ class DXContainer {
std::optional<mcdxbc::DebugName> DebugName;
std::optional<mcdxbc::CompilerVersion> VersionInfo;
std::optional<mcdxbc::SourceInfo> SourceInfo;
std::optional<StringRef> PrivateData;

Error parseHeader();
Error parsePartOffsets();
Expand All @@ -492,6 +493,7 @@ class DXContainer {
Error parseSignature(StringRef Part, DirectX::Signature &Array);
Error parseCompilerVersionInfo(StringRef Part);
Error parseSourceInfo(StringRef Part);
Error parsePrivateData(StringRef Part);
friend class PartIterator;

public:
Expand Down Expand Up @@ -613,6 +615,8 @@ class DXContainer {
const std::optional<mcdxbc::SourceInfo> &getSourceInfo() const {
return SourceInfo;
}

const std::optional<StringRef> &getPrivateData() const { return PrivateData; }
};

class LLVM_ABI DXContainerObjectFile : public ObjectFile {
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/ObjectYAML/DXContainerYAML.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ struct Part {
std::optional<DXContainerYAML::DebugName> DebugName;
std::optional<DXContainerYAML::CompilerVersion> CompilerVersion;
std::optional<DXContainerYAML::SourceInfo> SourceInfo;
std::optional<std::vector<llvm::yaml::Hex8>> PrivateData;
};

struct Object {
Expand Down
14 changes: 14 additions & 0 deletions llvm/lib/Object/DXContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ Error DXContainer::parseDebugName(StringRef Part) {
return Error::success();
}

Error DXContainer::parsePrivateData(StringRef Part) {
if (PrivateData)
return parseFailed("more than one PRIV part is present in the file");
PrivateData.emplace(Part);
return Error::success();
}

Error DXContainer::parseShaderFeatureFlags(StringRef Part) {
if (ShaderFeatureFlags)
return parseFailed("More than one SFI0 part is present in the file");
Expand Down Expand Up @@ -536,6 +543,9 @@ Error DXContainer::parsePartOffsets() {
sizeof(dxbc::Header) + (Header.PartCount * sizeof(uint32_t));
const char *Current = Data.getBuffer().data() + sizeof(dxbc::Header);
for (uint32_t Part = 0; Part < Header.PartCount; ++Part) {
if (PrivateData)
return parseFailed("PRIV must be the last section in a DXContainer");

uint32_t PartOffset;
if (Error Err = readInteger(Data.getBuffer(), Current, PartOffset))
return Err;
Expand Down Expand Up @@ -577,6 +587,10 @@ Error DXContainer::parsePartOffsets() {
if (Error Err = parseDebugName(PartData))
return Err;
break;
case dxbc::PartType::PRIV:
if (Error Err = parsePrivateData(PartData))
return Err;
break;
case dxbc::PartType::SFI0:
if (Error Err = parseShaderFeatureFlags(PartData))
return Err;
Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/ObjectYAML/DXContainerEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,15 @@ assignSectionHeader(dxbc::SourceInfo::SectionHeader &Dst,
}

Error DXContainerWriter::writeParts(raw_ostream &OS) {
bool HasPrivate = false;
uint32_t RollingOffset =
sizeof(dxbc::Header) + (ObjectFile.Header.PartCount * sizeof(uint32_t));
for (auto I : llvm::zip(ObjectFile.Parts, *ObjectFile.Header.PartOffsets)) {
if (HasPrivate)
return createStringError(
errc::invalid_argument,
"PRIV must be the last section in a DXContainer");

if (RollingOffset < std::get<1>(I)) {
uint32_t PadBytes = std::get<1>(I) - RollingOffset;
OS.write_zeros(PadBytes);
Expand Down Expand Up @@ -205,6 +211,15 @@ Error DXContainerWriter::writeParts(raw_ostream &OS) {
DebugName.write(OS);
break;
}
case dxbc::PartType::PRIV: {
if (!P.PrivateData)
continue;

HasPrivate = true;
OS.write(reinterpret_cast<char *>(P.PrivateData->data()),
P.PrivateData->size());
break;
}
case dxbc::PartType::SFI0: {
// If we don't have any flags we can continue here and the data will be
// zeroed out.
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/ObjectYAML/DXContainerYAML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ void MappingTraits<DXContainerYAML::Part>::mapping(IO &IO,
IO.mapOptional("DebugName", P.DebugName);
IO.mapOptional("CompilerVersion", P.CompilerVersion);
IO.mapOptional("SourceInfo", P.SourceInfo);
IO.mapOptional("PrivateData", P.PrivateData);
}

void MappingTraits<DXContainerYAML::Object>::mapping(
Expand Down Expand Up @@ -981,6 +982,14 @@ DXContainerYAML::fromDXContainer(object::DXContainer &Container) {
DebugName->Filename.str()};
break;
}
case dxbc::PartType::PRIV: {
std::optional<StringRef> PrivateData = Container.getPrivateData();
assert(PrivateData && "Since we are iterating and found a PRIV part, "
"this should never not have a value");
NewPart.PrivateData.emplace(PrivateData->data(),
PrivateData->data() + PrivateData->size());
break;
}
case dxbc::PartType::SFI0: {
std::optional<uint64_t> Flags = Container.getShaderFeatureFlags();
// Omit the flags in the YAML if they are missing or zero.
Expand Down
29 changes: 29 additions & 0 deletions llvm/test/ObjectYAML/DXContainer/PRIV-not-last.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## Check that ObjectYAML rejects PRIV parts that are not the last section.

# RUN: not yaml2obj %s 2>&1 | FileCheck %s

# CHECK: PRIV must be the last section in a DXContainer

--- !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: 2
Parts:
- Name: PRIV
Size: 5
PrivateData: [ 0xDE, 0xAD, 0xBE, 0xEF, 0x42 ]
- Name: DXIL
Size: 24
Program:
MajorVersion: 6
MinorVersion: 0
ShaderKind: 5
Size: 6
DXILMajorVersion: 0
DXILMinorVersion: 1
DXILSize: 0
...
35 changes: 35 additions & 0 deletions llvm/test/tools/llvm-objcopy/DXContainer/dump-section-priv.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## Check that --dump-section exports the raw PRIV part data, including when the
## part size is not a multiple of 4.

# RUN: yaml2obj %s -o %t.dxbc
# RUN: llvm-objcopy --dump-section=PRIV=%t.priv %t.dxbc

# RUN: wc -c %t.priv | FileCheck %s --check-prefix=PRIV-SIZE
# PRIV-SIZE: 5

# RUN: od -t x1 %t.priv | FileCheck %s --ignore-case
# CHECK: de ad be ef 42

--- !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: 2
Parts:
- Name: DXIL
Size: 24
Program:
MajorVersion: 6
MinorVersion: 0
ShaderKind: 5
Size: 6
DXILMajorVersion: 0
DXILMinorVersion: 1
DXILSize: 0
- Name: PRIV
Size: 5
PrivateData: [ 0xDE, 0xAD, 0xBE, 0xEF, 0x42 ]
...
42 changes: 42 additions & 0 deletions llvm/test/tools/obj2yaml/DXContainer/PRIVPart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
## Check that the PRIV part round-trips through yaml2obj and obj2yaml when the
## part size is not a multiple of 4. The pipeline is run twice to ensure obj2yaml
## output with a non-multiple-of-4 FileSize can be fed back through yaml2obj.

# RUN: yaml2obj %s 2>&1 | obj2yaml 2>&1 | yaml2obj %s 2>&1 | obj2yaml 2>&1 | FileCheck %s

--- !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: 2
Parts:
- Name: DXIL
Size: 24
Program:
MajorVersion: 6
MinorVersion: 0
ShaderKind: 5
Size: 6
DXILMajorVersion: 0
DXILMinorVersion: 1
DXILSize: 0
- Name: PRIV
Size: 5
PrivateData: [ 0xDE, 0xAD, 0xBE, 0xEF, 0x42 ]
...

# CHECK: FileSize: 85
# CHECK: PartCount: 2
# CHECK: PartOffsets: [ 40, 72 ]
# CHECK: Parts:
# CHECK: - Name: DXIL
# CHECK: Program:
# CHECK: MajorVersion: 6
# CHECK: MinorVersion: 0
# CHECK: ShaderKind: 5
# CHECK: - Name: PRIV
# CHECK: Size: 5
# CHECK: PrivateData: [ 0xDE, 0xAD, 0xBE, 0xEF, 0x42 ]
30 changes: 30 additions & 0 deletions llvm/unittests/Object/DXContainerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,36 @@ TEST(DXCFile, ParseILDNPart) {
EXPECT_EQ(ILDN->Filename, "abc.pdb");
}

// This test verifies that PRIV part is 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: PRIV
// Size: 5
// PrivateData: [ 0xDE, 0xAD, 0xBE, 0xEF, 0x42 ]
// ...
TEST(DXCFile, ParsePRIVPart) {
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, 0x31, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
0x50, 0x52, 0x49, 0x56, 0x05, 0x00, 0x00, 0x00, 0xDE,
0xAD, 0xBE, 0xEF, 0x42};
DXContainer C =
llvm::cantFail(DXContainer::create(getMemoryBuffer<49>(Buffer)));
EXPECT_EQ(C.getHeader().PartCount, 1u);
const std::optional<StringRef> &PrivateData = C.getPrivateData();
EXPECT_TRUE(PrivateData.has_value());
EXPECT_EQ(*PrivateData, "\xDE\xAD\xBE\xEF\x42");
}

// This test verifies that VERS part is correctly parsed.
// This test is based on the binary output constructed from this yaml.
// --- !dxcontainer
Expand Down
29 changes: 29 additions & 0 deletions llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,35 @@ TEST(DXCFile, ParseILDNPart) {
EXPECT_TRUE(memcmp(Buffer, Storage.data(), 56u) == 0);
}

TEST(DXCFile, ParsePRIVPart) {
SmallString<128> Storage;

ASSERT_TRUE(convert(Storage, R"(--- !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
PartOffsets: [ 36 ]
Parts:
- Name: PRIV
Size: 5
PrivateData: [ 0xDE, 0xAD, 0xBE, 0xEF, 0x42 ]
)"));

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, 0x31, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
0x50, 0x52, 0x49, 0x56, 0x05, 0x00, 0x00, 0x00, 0xDE,
0xAD, 0xBE, 0xEF, 0x42};

EXPECT_EQ(Storage.size(), 49u);
EXPECT_TRUE(memcmp(Buffer, Storage.data(), 49u) == 0);
}

TEST(DXCFile, ParseVERSPart) {
SmallString<128> Storage;

Expand Down