[DirectX][Driver] Add /Qpdb_in_private flag support (#204903)
In DXC, when `/Qpdb_in_private` flag is specified, debug info PDB is emitted into PRIV part of the output DXContainer (as well as into separate PDB file, if its name is specified with `/Fd`). This patch reimplements similar behavior in llc and Clang. MC is modified to be able to emit PRIV part. Depends on https://github.com/llvm/llvm-project/pull/204166.
This commit is contained in:
parent
009e841dbd
commit
db816fe2ed
14 changed files with 267 additions and 23 deletions
|
|
@ -9923,6 +9923,9 @@ def dxc_gis : DXCFlag<"Gis">,
|
|||
def : Option<["/", "-"], "Qembed_debug", KIND_FLAG>, Group<dxc_Group>,
|
||||
Flags<[Ignored]>, Visibility<[DXCOption]>,
|
||||
HelpText<"Embed PDB in shader container (ignored)">;
|
||||
def dxc_Qpdb_in_private : DXCFlag<"Qpdb_in_private">,
|
||||
Flags<[HelpHidden]>,
|
||||
HelpText<"Store PDB in private user data">;
|
||||
def spirv : DXCFlag<"spirv">,
|
||||
HelpText<"Generate SPIR-V code">;
|
||||
def metal : DXCFlag<"metal">, HelpText<"Generate Metal library">;
|
||||
|
|
|
|||
|
|
@ -4003,6 +4003,10 @@ static void RenderHLSLOptions(const Driver &D, const ArgList &Args,
|
|||
CmdArgs.push_back("-mllvm");
|
||||
CmdArgs.push_back("--dx-strip-debug");
|
||||
}
|
||||
if (Args.hasArg(options::OPT_dxc_Qpdb_in_private)) {
|
||||
CmdArgs.push_back("-mllvm");
|
||||
CmdArgs.push_back("--dx-pdb-in-private");
|
||||
}
|
||||
}
|
||||
|
||||
static void RenderOpenACCOptions(const Driver &D, const ArgList &Args,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
// RUN: %clang_dxc -Tlib_6_7 -### /Zi /Qembed_debug %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_dxc -Tlib_6_7 -### -Zi %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_dxc -Tlib_6_7 -### -Zi -Qembed_debug %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_dxc -Tlib_6_7 -### /Zi /Qpdb_in_private %s 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-PRIV
|
||||
// RUN: %clang_dxc -Tlib_6_7 -### -Zi -Zss %s 2>&1 | FileCheck %s --check-prefix=CHECK,CHECK-ZSS
|
||||
// RUN: %clang_dxc -Tlib_6_7 -### /Zi -Qsource_in_debug_module %s 2>&1 | FileCheck %s --check-prefix=CHECK,CHECK-SIDM
|
||||
// RUN: %clang_dxc -Tlib_6_7 -### -Zi -Qstrip_debug %s 2>&1 | FileCheck %s --check-prefix=CHECK,CHECK-STRIP
|
||||
|
|
@ -17,6 +18,7 @@
|
|||
// Make sure dwarf-version is 4.
|
||||
// CHECK-DWARF-SAME: -dwarf-version=4
|
||||
// Check that the flags are converted to their llc equivalents.
|
||||
// CHECK-PRIV-SAME: --dx-pdb-in-private
|
||||
// CHECK-ZSS-SAME: -dx-Zss
|
||||
// CHECK-SIDM-SAME: --dx-source-in-debug-module
|
||||
// CHECK-STRIP-SAME: --dx-strip-debug
|
||||
|
|
|
|||
|
|
@ -22,4 +22,15 @@
|
|||
|
||||
// CHECK: - Name: ILDN
|
||||
|
||||
// Check that /Qpdb_in_private emits a PRIV part in the output container.
|
||||
// RUN: %clang_dxc -Tlib_6_7 /Fo %t-priv.dxbc /Zi /Qpdb_in_private %s 2>&1
|
||||
// RUN: obj2yaml %t-priv.dxbc | FileCheck %s --check-prefix=CHECK-PRIV
|
||||
|
||||
// Without /Qpdb_in_private, PRIV is not emitted.
|
||||
// RUN: %clang_dxc -Tlib_6_7 /Fo %t-no-priv.dxbc /Zi %s 2>&1
|
||||
// RUN: obj2yaml %t-no-priv.dxbc | FileCheck %s --check-prefix=CHECK-NO-PRIV
|
||||
|
||||
// CHECK-PRIV: - Name: PRIV
|
||||
// CHECK-NO-PRIV-NOT: - Name: PRIV
|
||||
|
||||
[numthreads(1, 1, 1)] void main() {}
|
||||
|
|
|
|||
|
|
@ -49,14 +49,22 @@ void MCDXContainerBaseWriter::write(raw_ostream &OS, const Triple &TT) {
|
|||
// 16 part offsets gives us a little room for growth.
|
||||
llvm::SmallVector<uint64_t, 16> PartOffsets;
|
||||
uint64_t PartOffset = 0;
|
||||
bool HasPrivate = false;
|
||||
for (const MCDXContainerPart &Part : Parts) {
|
||||
if (HasPrivate)
|
||||
reportFatalInternalError(
|
||||
"PRIV must be the last section in a DXContainer");
|
||||
if (Part.Name == "PRIV")
|
||||
HasPrivate = true;
|
||||
|
||||
uint64_t SectionSize = Part.Data.size();
|
||||
assert(SectionSize < std::numeric_limits<uint32_t>::max() &&
|
||||
"Section size too large for DXContainer");
|
||||
|
||||
PartOffsets.push_back(PartOffset);
|
||||
PartOffset += sizeof(dxbc::PartHeader) + SectionSize;
|
||||
PartOffset = alignTo(PartOffset, Align(4ul));
|
||||
if (!HasPrivate)
|
||||
PartOffset = alignTo(PartOffset, Align(4ul));
|
||||
// The DXIL part also writes a program header, so we need to include its
|
||||
// size when computing the offset for a part after the DXIL part.
|
||||
if (dxbc::isProgramPart(Part.Name))
|
||||
|
|
@ -96,8 +104,10 @@ void MCDXContainerBaseWriter::write(raw_ostream &OS, const Triple &TT) {
|
|||
|
||||
if (dxbc::isProgramPart(Part.Name))
|
||||
PartSize += sizeof(dxbc::ProgramHeader);
|
||||
// DXContainer parts should be 4-byte aligned.
|
||||
PartSize = alignTo(PartSize, Align(4));
|
||||
// DXContainer part should be 4-byte aligned, unless it is PRIV part.
|
||||
bool IsPrivate = Part.Name == "PRIV";
|
||||
if (!IsPrivate)
|
||||
PartSize = alignTo(PartSize, Align(4));
|
||||
W.write<uint32_t>(static_cast<uint32_t>(PartSize));
|
||||
if (dxbc::isProgramPart(Part.Name)) {
|
||||
dxbc::ProgramHeader Header;
|
||||
|
|
@ -127,8 +137,10 @@ void MCDXContainerBaseWriter::write(raw_ostream &OS, const Triple &TT) {
|
|||
sizeof(dxbc::ProgramHeader)));
|
||||
}
|
||||
W.write<char>(Part.Data);
|
||||
unsigned Size = W.OS.tell() - Start;
|
||||
W.OS.write_zeros(offsetToAlignment(Size, Align(4)));
|
||||
if (!IsPrivate) {
|
||||
unsigned Size = W.OS.tell() - Start;
|
||||
W.OS.write_zeros(offsetToAlignment(Size, Align(4)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ static cl::opt<bool> ShaderHashDependsOnSource(
|
|||
"dx-Zss", cl::desc("Compute Shader Hash considering source information"));
|
||||
extern cl::opt<std::string> PdbDebugPath;
|
||||
extern cl::opt<bool> SourceInDebugModule;
|
||||
cl::opt<bool> PdbInPrivate("dx-pdb-in-private",
|
||||
cl::desc("Store PDB in private user data"));
|
||||
|
||||
namespace {
|
||||
class DXContainerGlobals : public llvm::ModulePass {
|
||||
|
|
@ -159,22 +161,26 @@ void DXContainerGlobals::computeShaderHashAndDebugName(
|
|||
SmallString<40> DebugNameStr;
|
||||
Digest.stringifyResult(MD5, DebugNameStr);
|
||||
DebugNameStr += ".pdb";
|
||||
if (!PdbDebugPath.empty()) {
|
||||
StringRef DebugFile = PdbDebugPath.getValue();
|
||||
SmallString<256> AbsoluteDebugName;
|
||||
if (sys::path::is_separator(DebugFile.back())) {
|
||||
// If /Fd was specified as a directory, put the MD5.pdb file there.
|
||||
AbsoluteDebugName = DebugFile;
|
||||
sys::path::append(AbsoluteDebugName, DebugNameStr);
|
||||
} else {
|
||||
// Otherwise, use /Fd value as a user-provided PDB file name.
|
||||
DebugNameStr = DebugFile;
|
||||
AbsoluteDebugName = DebugNameStr;
|
||||
if (!PdbDebugPath.empty() || PdbInPrivate) {
|
||||
if (!PdbDebugPath.empty()) {
|
||||
StringRef DebugFile = PdbDebugPath.getValue();
|
||||
SmallString<256> AbsoluteDebugName;
|
||||
if (sys::path::is_separator(DebugFile.back())) {
|
||||
// If PDB output path was specified as a directory, put the MD5.pdb file
|
||||
// there.
|
||||
AbsoluteDebugName = DebugFile;
|
||||
sys::path::append(AbsoluteDebugName, DebugNameStr);
|
||||
} else {
|
||||
// Otherwise, use PDB output path as a user-provided PDB file name.
|
||||
DebugNameStr = DebugFile;
|
||||
AbsoluteDebugName = DebugNameStr;
|
||||
}
|
||||
|
||||
// Pass PDB name to DXContainerPDBPass via PDBNAME section.
|
||||
addSection(M, Globals, AbsoluteDebugName, "dx.pdb.name",
|
||||
PdbFileNameSectionName);
|
||||
}
|
||||
|
||||
// Pass PDB name to DXContainerPDBPass via PDBNAME section.
|
||||
addSection(M, Globals, AbsoluteDebugName, "dx.pdb.name",
|
||||
PdbFileNameSectionName);
|
||||
// Pass module hash to DXContainerPDBPass.
|
||||
Globals.emplace_back(buildContainerGlobal(
|
||||
M, ConstantDataArray::get(M.getContext(), ArrayRef(HashData.Digest)),
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DirectX.h"
|
||||
#include "llvm/ADT/ScopeExit.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/BinaryFormat/DXContainer.h"
|
||||
#include "llvm/DebugInfo/CodeView/GUID.h"
|
||||
|
|
@ -17,10 +18,15 @@
|
|||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/MC/MCDXContainerWriter.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/IOSandbox.h"
|
||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
extern cl::opt<bool> PdbInPrivate;
|
||||
|
||||
namespace {
|
||||
|
||||
class DXContainerPDB : public ModulePass, MCDXContainerBaseWriter {
|
||||
|
|
@ -85,10 +91,22 @@ ArrayRef<MCDXContainerPart> DXContainerPDB::collectParts() {
|
|||
return Parts;
|
||||
}
|
||||
|
||||
static GlobalVariable *createPrivateDataGlobal(Module &M, StringRef Data) {
|
||||
Constant *Content =
|
||||
ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);
|
||||
auto *GV =
|
||||
new GlobalVariable(M, Content->getType(), true,
|
||||
GlobalValue::PrivateLinkage, Content, "dx.priv");
|
||||
GV->setSection("PRIV");
|
||||
GV->setAlignment(Align(1));
|
||||
return GV;
|
||||
}
|
||||
|
||||
bool DXContainerPDB::runOnModule(Module &M) {
|
||||
llvm::scope_exit Cleanup([&]() { reset(); });
|
||||
this->M = &M;
|
||||
|
||||
StringRef DebugFileName;
|
||||
SmallString<128> DebugFileName;
|
||||
ArrayRef<char> ModuleHash;
|
||||
for (const GlobalVariable &GV : M.globals()) {
|
||||
if (GV.getSection() == PdbFileNameSectionName) {
|
||||
|
|
@ -102,11 +120,23 @@ bool DXContainerPDB::runOnModule(Module &M) {
|
|||
}
|
||||
|
||||
// PDB emission was not requested.
|
||||
if (DebugFileName.empty())
|
||||
if (DebugFileName.empty() && !PdbInPrivate)
|
||||
return false;
|
||||
if (ModuleHash.empty())
|
||||
report_fatal_error("Module hash for PDB not found");
|
||||
|
||||
bool DeleteAfterRead = false;
|
||||
if (DebugFileName.empty()) {
|
||||
if (std::error_code EC =
|
||||
sys::fs::createTemporaryFile("dxil", "pdb", DebugFileName))
|
||||
reportFatalInternalError("Failed to create temporary PDB file");
|
||||
DeleteAfterRead = true;
|
||||
}
|
||||
llvm::scope_exit FileCleanup([&]() {
|
||||
if (DeleteAfterRead)
|
||||
sys::fs::remove(DebugFileName);
|
||||
});
|
||||
|
||||
BumpPtrAllocator Allocator;
|
||||
pdb::PDBFileBuilder Builder(Allocator);
|
||||
|
||||
|
|
@ -151,9 +181,17 @@ bool DXContainerPDB::runOnModule(Module &M) {
|
|||
reportFatalUsageError("Couldn't write to PDB file: " +
|
||||
Twine(toString(std::move(Err))));
|
||||
|
||||
reset();
|
||||
if (!PdbInPrivate)
|
||||
return false;
|
||||
|
||||
return false;
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(
|
||||
DebugFileName, /*IsText=*/false, /*RequiresNullTerminator=*/false);
|
||||
if (!Buf)
|
||||
reportFatalInternalError("Failed to read PDB for PRIV embedding");
|
||||
|
||||
appendToCompilerUsed(M, createPrivateDataGlobal(M, (*Buf)->getBuffer()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char DXContainerPDB::ID = 0;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
## Check that --dx-pdb-in-private generates a PDB in PRIV without --dx-pdb-path.
|
||||
|
||||
# RUN: llc %S/Inputs/SourceInfo.ll --filetype=obj -o %t.dxbc --dx-pdb-in-private
|
||||
# RUN: obj2yaml %t.dxbc | FileCheck %s
|
||||
# RUN: llvm-objcopy --dump-section=PRIV=%t.priv %t.dxbc
|
||||
# RUN: llvm-pdbutil pdb2yaml --dxcontainer %t.priv | FileCheck %s --check-prefix=PDB
|
||||
|
||||
# CHECK: - Name: PRIV
|
||||
# CHECK-NEXT: Size:
|
||||
|
||||
# PDB: PartCount: 5
|
||||
# PDB: Parts:
|
||||
# PDB-DAG: - Name: ILDB
|
||||
# PDB-DAG: - Name: HASH
|
||||
# PDB-DAG: - Name: ILDN
|
||||
# PDB-DAG: - Name: VERS
|
||||
# PDB-DAG: - Name: SRCI
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
## Check that PRIV is not emitted unless --dx-pdb-in-private is specified.
|
||||
|
||||
# RUN: llc %S/Inputs/SourceInfo.ll --filetype=obj -o - | obj2yaml | FileCheck %s --implicit-check-not='PRIV'
|
||||
|
||||
# CHECK: - Name: DXIL
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
;; Check that dxil-pdb can emit PRIV using a temporary PDB when PDBNAME is absent.
|
||||
; RUN: opt %s -dxil-pdb --dx-pdb-in-private -S -o - | FileCheck %s
|
||||
|
||||
;; CHECK: @dx.priv = private constant {{.*}} section "PRIV"
|
||||
|
||||
target triple = "dxilv1.3-pc-shadermodel6.3-library"
|
||||
|
||||
@dx.ildb = private constant [4 x i8] c"BC\C0\DE", section "ILDB", align 4
|
||||
@dx.pdb.hash = private constant [16 x i8] c"dummymodulehash!", section "PDBHASH", align 4
|
||||
@llvm.compiler.used = appending global [2 x ptr] [ptr @dx.ildb, ptr @dx.pdb.hash], section "llvm.metadata"
|
||||
18
llvm/test/CodeGen/DirectX/ContainerData/PdbInPrivate.ll
Normal file
18
llvm/test/CodeGen/DirectX/ContainerData/PdbInPrivate.ll
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
; RUN: opt %s -dxil-pdb --dx-pdb-in-private -S -o - | FileCheck %s --check-prefix=CHECK-IR
|
||||
; RUN: opt %s -dxil-pdb --dx-pdb-in-private -o /dev/null
|
||||
; RUN: llvm-pdbutil pdb2yaml --dxcontainer PdbInPrivateTest.pdb | FileCheck %s --check-prefix=CHECK-PDB
|
||||
|
||||
;; Check that dxil-pdb pass emits a PRIV global when --dx-pdb-in-private is set.
|
||||
; CHECK-IR: @dx.priv = private constant {{.*}} section "PRIV"
|
||||
|
||||
; Check that the companion PDB file is still written when PDBNAME is present.
|
||||
; CHECK-PDB: PartCount: 1
|
||||
; CHECK-PDB: Parts:
|
||||
; CHECK-PDB: - Name: ILDB
|
||||
|
||||
target triple = "dxilv1.3-pc-shadermodel6.3-library"
|
||||
|
||||
@dx.ildb = private constant [4 x i8] c"BC\C0\DE", section "ILDB", align 4
|
||||
@dx.pdb.name = private constant [20 x i8] c"PdbInPrivateTest.pdb", section "PDBNAME", align 4
|
||||
@dx.pdb.hash = private constant [16 x i8] c"dummymodulehash!", section "PDBHASH", align 4
|
||||
@llvm.compiler.used = appending global [3 x ptr] [ptr @dx.ildb, ptr @dx.pdb.name, ptr @dx.pdb.hash], section "llvm.metadata"
|
||||
33
llvm/test/CodeGen/DirectX/ContainerData/PdbInPrivate.test
Normal file
33
llvm/test/CodeGen/DirectX/ContainerData/PdbInPrivate.test
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
## Check that --dx-pdb-in-private stores the generated PDB in the PRIV part.
|
||||
|
||||
## File: --dx-pdb-path specifies the PDB output path.
|
||||
|
||||
# RUN: llc %S/Inputs/SourceInfo.ll --filetype=obj -o %t.dxbc --dx-pdb-in-private --dx-pdb-path=%t.pdb
|
||||
# RUN: obj2yaml %t.dxbc | FileCheck %s
|
||||
# RUN: llvm-objcopy --dump-section=PRIV=%t.priv %t.dxbc
|
||||
# RUN: diff %t.pdb %t.priv
|
||||
# RUN: llvm-pdbutil pdb2yaml --dxcontainer %t.priv | FileCheck %s --check-prefix=PDB
|
||||
|
||||
## Directory: --dx-pdb-path ending in '/' writes <md5>.pdb under that directory.
|
||||
|
||||
# RUN: rm -rf %t.dir && mkdir %t.dir
|
||||
# RUN: llc %S/Inputs/SourceInfo.ll --filetype=obj -o %t.dir.dxbc --dx-pdb-in-private --dx-pdb-path=%t.dir/
|
||||
# RUN: obj2yaml %t.dir.dxbc | FileCheck %s
|
||||
# RUN: llvm-objcopy --dump-section=PRIV=%t.dir.priv %t.dir.dxbc
|
||||
# RUN: llvm-objcopy --dump-section=DXIL=%t.dir.bc %t.dir.dxbc
|
||||
# RUN: %md5sum %t.dir.bc >%t.dir.bc.md5
|
||||
# RUN: %python %S/Inputs/check_pdb_exists.py %t.dir %t.dir.bc.md5
|
||||
# RUN: cat %t.dir/*.pdb > %t.dir.pdb
|
||||
# RUN: diff %t.dir.pdb %t.dir.priv
|
||||
# RUN: llvm-pdbutil pdb2yaml --dxcontainer %t.dir.priv | FileCheck %s --check-prefix=PDB
|
||||
|
||||
# CHECK: - Name: PRIV
|
||||
# CHECK-NEXT: Size:
|
||||
|
||||
# PDB: PartCount: 5
|
||||
# PDB: Parts:
|
||||
# PDB-DAG: - Name: ILDB
|
||||
# PDB-DAG: - Name: HASH
|
||||
# PDB-DAG: - Name: ILDN
|
||||
# PDB-DAG: - Name: VERS
|
||||
# PDB-DAG: - Name: SRCI
|
||||
|
|
@ -6,6 +6,7 @@ endforeach()
|
|||
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
${LLVM_TARGETS_TO_BUILD}
|
||||
BinaryFormat
|
||||
DebugInfoDWARF
|
||||
MC
|
||||
MCDisassembler
|
||||
|
|
@ -19,6 +20,7 @@ add_llvm_unittest(MCTests
|
|||
DwarfDebugFrameCIE.cpp
|
||||
DwarfLineTables.cpp
|
||||
DwarfLineTableHeaders.cpp
|
||||
DXContainerWriterTest.cpp
|
||||
MCInstPrinter.cpp
|
||||
StringTableBuilderTest.cpp
|
||||
TargetRegistry.cpp
|
||||
|
|
|
|||
83
llvm/unittests/MC/DXContainerWriterTest.cpp
Normal file
83
llvm/unittests/MC/DXContainerWriterTest.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
//===- DXContainerWriterTest.cpp - MCDXContainerWriter tests --------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/MC/MCDXContainerWriter.h"
|
||||
#include "llvm/Object/DXContainer.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/MemoryBufferRef.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
|
||||
namespace {
|
||||
|
||||
class TestDXContainerWriter : public MCDXContainerBaseWriter {
|
||||
SmallVector<SmallString<8>> PartNames;
|
||||
SmallVector<SmallString<32>> PartData;
|
||||
SmallVector<MCDXContainerPart> Parts;
|
||||
|
||||
protected:
|
||||
ArrayRef<MCDXContainerPart> collectParts() override { return Parts; }
|
||||
|
||||
public:
|
||||
void addPart(StringRef Name, ArrayRef<uint8_t> Data) {
|
||||
PartNames.emplace_back(Name);
|
||||
PartData.emplace_back(Data.begin(), Data.end());
|
||||
Parts.push_back({PartNames.back(), PartData.back()});
|
||||
}
|
||||
};
|
||||
|
||||
static Triple getTestTriple() {
|
||||
return Triple("dxilv1.3-pc-shadermodel6.3-library");
|
||||
}
|
||||
|
||||
static std::string writeContainer(TestDXContainerWriter &Writer) {
|
||||
std::string Buffer;
|
||||
raw_string_ostream OS(Buffer);
|
||||
Writer.write(OS, getTestTriple());
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
static DXContainer parseContainer(StringRef Buffer) {
|
||||
return llvm::cantFail(DXContainer::create(MemoryBufferRef(Buffer, "")));
|
||||
}
|
||||
|
||||
TEST(MCDXContainerWriterTest, PrivUnaligned) {
|
||||
TestDXContainerWriter Writer;
|
||||
const uint8_t PrivData[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x42};
|
||||
Writer.addPart("PRIV", PrivData);
|
||||
|
||||
std::string Buffer = writeContainer(Writer);
|
||||
DXContainer C = parseContainer(Buffer);
|
||||
|
||||
EXPECT_EQ(C.getHeader().PartCount, 1u);
|
||||
EXPECT_EQ(C.getHeader().FileSize, 49u);
|
||||
EXPECT_EQ(C.getData().size(), 49u);
|
||||
|
||||
ASSERT_TRUE(C.getPrivateData());
|
||||
EXPECT_EQ(C.getPrivateData()->size(), 5u);
|
||||
EXPECT_EQ(
|
||||
*C.getPrivateData(),
|
||||
StringRef(reinterpret_cast<const char *>(PrivData), sizeof(PrivData)));
|
||||
}
|
||||
|
||||
TEST(MCDXContainerWriterTest, PrivMustBeLast) {
|
||||
TestDXContainerWriter Writer;
|
||||
const uint8_t PrivData[] = {0x42};
|
||||
const uint8_t DxilData[] = {0xBC, 0xC0, 0xDE, 0x00};
|
||||
Writer.addPart("PRIV", PrivData);
|
||||
Writer.addPart("DXIL", DxilData);
|
||||
|
||||
EXPECT_DEATH(writeContainer(Writer),
|
||||
"PRIV must be the last section in a DXContainer");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Loading…
Reference in a new issue