Skip to content
Open
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/DXContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ LLVM_ABI PartType parsePartType(StringRef S);
bool isDebugProgramPart(PartType PT);

const char *getProgramPartName(bool IsDebug);
bool isProgramPart(StringRef PartName);

struct VertexPSVInfo {
uint8_t OutputPositionPresent;
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/BinaryFormat/DXContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ const char *dxbc::getProgramPartName(bool IsDebug) {
return IsDebug ? "ILDB" : "DXIL";
}

bool dxbc::isProgramPart(StringRef PartName) {
return PartName == "DXIL" || PartName == "ILDB";
}

bool ShaderHash::isPopulated() {
static uint8_t Zeros[16] = {0};
return Flags > 0 || 0 != memcmp(&Digest, &Zeros, 16);
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/MC/MCDXContainerWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ uint64_t DXContainerObjectWriter::writeObject() {
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 (Sec.getName() == "DXIL")
if (dxbc::isProgramPart(Sec.getName()))
PartOffset += sizeof(dxbc::ProgramHeader);
}
assert(PartOffset < std::numeric_limits<uint32_t>::max() &&
Expand Down Expand Up @@ -78,12 +78,12 @@ uint64_t DXContainerObjectWriter::writeObject() {

uint64_t PartSize = SectionSize;

if (Sec.getName() == "DXIL")
if (dxbc::isProgramPart(Sec.getName()))
PartSize += sizeof(dxbc::ProgramHeader);
// DXContainer parts should be 4-byte aligned.
PartSize = alignTo(PartSize, Align(4));
W.write<uint32_t>(static_cast<uint32_t>(PartSize));
if (Sec.getName() == "DXIL") {
if (dxbc::isProgramPart(Sec.getName())) {
dxbc::ProgramHeader Header;
memset(reinterpret_cast<void *>(&Header), 0, sizeof(dxbc::ProgramHeader));

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/ObjCopy/DXContainer/DXContainerObjcopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static Error dumpPartToFile(StringRef PartName, StringRef Filename,
// documentation on the DXContainer format can be found at
// https://llvm.org/docs/DirectX/DXContainer.html.

if (PartName == "DXIL" || PartName == "ILDB" || PartName == "STAT")
if (llvm::dxbc::isProgramPart(PartName) || PartName == "STAT")
Contents = Contents.drop_front(sizeof(llvm::dxbc::ProgramHeader));
if (Contents.empty())
return createFileError(Filename, object_error::parse_failed,
Expand Down
6 changes: 1 addition & 5 deletions llvm/lib/Target/DirectX/DXContainerGlobals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,13 @@ void DXContainerGlobals::addSection(Module &M,

void DXContainerGlobals::computeShaderHashAndDebugName(
Module &M, SmallVector<GlobalValue *> &Globals) {
// TODO: Add -Zss flag to enable/disable calculating shader hash from ILDB.
auto *DXILConstant =
cast<ConstantDataArray>(M.getNamedGlobal("dx.dxil")->getInitializer());
MD5 Digest;
Digest.update(DXILConstant->getRawDataValues());
MD5::MD5Result Result = Digest.final();

dxbc::ShaderHash HashData = {0, {0}};
// The Hash's IncludesSource flag gets set whenever the hashed shader includes
// debug information.
if (!M.debug_compile_units().empty())
HashData.Flags = static_cast<uint32_t>(dxbc::HashFlags::IncludesSource);

memcpy(reinterpret_cast<void *>(&HashData.Digest), Result.data(), 16);
if (sys::IsBigEndianHost)
Expand Down
102 changes: 89 additions & 13 deletions llvm/lib/Target/DirectX/DXILWriter/DXILWriterPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/ModuleSummaryAnalysis.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IntrinsicInst.h"
Expand All @@ -28,6 +29,7 @@
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/Alignment.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"

using namespace llvm;
Expand Down Expand Up @@ -138,7 +140,72 @@ static void removeLifetimeIntrinsics(Module &M) {
}
}

static void replaceNamedMetadataArray(Module &M, StringRef Name,
ArrayRef<Metadata *> NewOps) {
NamedMDNode *NMD = M.getNamedMetadata(Name);
if (!NMD)
return;
NMD->eraseFromParent();
M.getOrInsertNamedMetadata(Name)->addOperand(
MDTuple::get(M.getContext(), NewOps));
}

class EmbedDXILPass : public llvm::ModulePass {
std::string writeModule(Module &M, bool HasDebugInfo, bool WriteDebug) {
std::string Data;
llvm::raw_string_ostream OS(Data);

if (HasDebugInfo) {
if (WriteDebug) {
// Replace dx.source metadata nodes with stubs.
// TODO: Add /Qsource_in_debug_module flag to enable/disable this.
LLVMContext &Ctx = M.getContext();
MDString *EmptyString = MDString::get(Ctx, "");
replaceNamedMetadataArray(M, "dx.source.contents",
{EmptyString, EmptyString});
replaceNamedMetadataArray(M, "dx.source.defines", {});
replaceNamedMetadataArray(M, "dx.source.mainFileName", {EmptyString});
replaceNamedMetadataArray(M, "dx.source.args", {});
} else {
// If we have an ILDB part, strip DXIL from all debug info.
StripDebugInfo(M);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function returns a bool indicating whether any debug info was stripped, we can use this to avoid checking through debug_compile_units().empty() and get a more reliable answer.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we specifically need to strip debug info only if we already know if there is debug info. Is there any other way to know this?

Copy link
Copy Markdown
Contributor

@dzhidzhoev dzhidzhoev Jun 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function returns a bool indicating whether any debug info was stripped, we can use this to avoid checking through debug_compile_units().empty() and get a more reliable answer.

AFAIK if !llvm.dbg.cu is empty, LLVM assumes no debug info is present in the file (see #150 (comment)). Are you aware of cases when we have correct and full LLVM IR with debug info but without compile units?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no harm in stripping debug info if there is no debug info, the function will just tell you there was nothing to strip, and it will have done a better search than the current code. So something like std::unique_ptr<Module> Clone = llvm::CloneModule(M); bool HaveDebugInfo = llvm::StripDebugInfo(*Clone);, then write the DXIL section from *Clone (which assuredly has no debug info, regardless of whether there was originally debug info), then if HaveDebugInfo is true, create your second clone and write the ILDB section from that.

Copy link
Copy Markdown
Contributor

@dzhidzhoev dzhidzhoev Jun 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no harm in stripping debug info if there is no debug info

But it performs an extra pass over the whole module which can be avoided when shader is compiled without debug info.

(Anyway, my opinion on that matter should not block this PR.)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is, that if we have no compile units, but still have debug info nodes, it may be an issue somewhere in LLVM IR producers, or in an LLVM IR pass which runs before DXILWriterPass.

It may be, sure, but...

By calling strip on such IRs, DXILWriterPass will just hide such an issue.

...the issue won't be hidden: it will accurately write a DXIL section without debug info, and an ILDB section with the weird debug info.

I'd be fine with turning this into an assert instead somewhere, but silently leaving debug info in the section that specifically is meant to not have debug info seems wrong, especially if we don't know if there may be legitimate reasons for it that we're just not thinking of now.

Definition DISubprograms must have compile unit field, which is enforced by Verifier.

Note that I didn't say no DICompileUnit, just no !llvm.dbg.cu named metadata. There are loads of LLVM tests that have a DICompileUnit that is not linked through named metadata, a random example is llvm/test/Transforms/Coroutines/declare-value.ll.

Copy link
Copy Markdown
Contributor

@dzhidzhoev dzhidzhoev Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definition DISubprograms must have compile unit field, which is enforced by Verifier.

Note that I didn't say no DICompileUnit, just no !llvm.dbg.cu named metadata. There are loads of LLVM tests that have a DICompileUnit that is not linked through named metadata

Such IRs are definitely incorrect from the Verifier's point of view - see Verifier::verifyCompileUnits() - it discards debug info containing compile units that are not listed in !llvm.dbg.cu,
For the test you referenced:

DICompileUnit not listed in llvm.dbg.cu
!4 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !5, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
llvm-dis.exe: warning: ignoring invalid debug info in tmp.bc

Tests from llvm\test\Transforms sometimes do not care about that - they run a single pass, not full llc pipeline (and opt silences invalid debug info warning). So it may have happened that there they've been unverified.

By calling strip on such IRs, DXILWriterPass will just hide such an issue.

...the issue won't be hidden: it will accurately write a DXIL section without debug info, and an ILDB section with the weird debug info.

It may be easier to spot a problem when debug info section requested by the user is not created than when it is created but later debug info is discarded by IR consumers. Usually, IR loader does not raise an error if debug info is incorrect - it silently strips it (or it raises a warning if user explicitly invokes llvm-dis, but not an error).

I'd be fine with turning this into an assert instead somewhere, but silently leaving debug info in the section that specifically is meant to not have debug info seems wrong, especially if we don't know if there may be legitimate reasons for it that we're just not thinking of now.

That's definitely worth doing if we leave unconditional Strip call 👍
We could also do it the other way around: detect debug info presence by checking compile units, and add an assert(StripDebugInfo(M) == HasDebugInfo && "This module must not contain anything to be stripped")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, what's the consensus? Do we change the check !M.debug_compile_units().empty() to a call to StripDebugInfo with an assert?

Copy link
Copy Markdown
Contributor

@dzhidzhoev dzhidzhoev Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I won't be blocking it if we use Strip as the source of truth here, but an extra assert for !M.debug_compile_units().empty() value would be nice :)
Motivation: other passes (either DX-specific or generic IR passes) may check compile units list still, to check if debug info should be processed, and they won't be calling StripDebugInfo wherever they want to check for debug info presence. So we want to be sure that both debug info presence indicators converge.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The details of how you do it are up to you, but what matters to me is that if we have debug info, even weird debug info, we don't enter the "no debug info" case, at least in an assertions-enabled build. Checking the result of StripDebugInfo seemed to me like the simplest way of achieving that, but any other way that also achieves that same goal works for me.


// Also, manually remove debug version flags and dx.source nodes.
if (NamedMDNode *Flags = M.getModuleFlagsMetadata()) {
SmallVector<llvm::Module::ModuleFlagEntry, 4> FlagEntries;
M.getModuleFlagsMetadata(FlagEntries);
Flags->eraseFromParent();
for (llvm::Module::ModuleFlagEntry &Entry : FlagEntries) {
if (Entry.Key->getString() == "Dwarf Version" ||
Entry.Key->getString() == "Debug Info Version") {
continue;
}
M.addModuleFlag(Entry.Behavior, Entry.Key->getString(), Entry.Val);
}
}
for (NamedMDNode &NMD : llvm::make_early_inc_range(M.named_metadata()))
if (NMD.getName().starts_with("dx.source"))
NMD.eraseFromParent();
}
}
const auto DIMap = DXILDebugInfoPass::run(M);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this under under if (IsDebug) above, following the email discussion we had (Andrew's email).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The call to WriteDXILToFile requires a DXILDebugInfoMap argument though, I don't think we can not call it. Doesn't seem to do any harm.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hvdijk mentioned that we can pass an empty map.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like this?

const DXILDebugInfoMap DIMap;
WriteDXILToFile(M, OS, DIMap);

I tried, it crashes everything.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be like

const DXILDebugInfoMap DIMap;
...
if (IsDebug) {
   ...
   DIMap = DebugInfoPass::run(M);
} else {
   ... // No DebugInfoPass::run(M);
}
...
WriteDXILToFile(M, OS, DIMap);
...
}

Does it crash in such case as well?

Copy link
Copy Markdown
Contributor

@dzhidzhoev dzhidzhoev Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would decouple the second change from this PR

That means we would have an intermediate stage where modules are emitted without any debug info, neither in the DXIL section nor in the ILDB section. Wouldn't this break the existing dxil-dis tests?

No, it means we may have an intermediate stage where both parts are emitted with debug info.
One PR should add an extra
CloneModule(), WriteDXILToFile(...) call (codepath) which would write to dx.ildb.
Another PR should change dx.dxil emission codepath into something like

CloneModule(...)
StripDebugInfo(...)
...
WriteDXILToFile(...)

I think it will take longer to get dx.dxil change merged.

Copy link
Copy Markdown
Contributor

@dzhidzhoev dzhidzhoev Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another PR should change dx.dxil emission codepath into something like

CloneModule(...)
StripDebugInfo(...)
...
WriteDXILToFile(...)

We can stack this on top of dx.ildb emission patch as well (it will already depend on some other patches anyway).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it means we may have an intermediate stage where both parts are emitted with debug info.

Ah, I see, that is fine for what gets merged into LLVM main but that means the stacked PR approach won't work for the "strip debug info from DXIL" part of it. I think that means we won't be able to create that PR yet to get that reviewed, because it depends on multiple other PRs that are not otherwise related and GitHub does not support that. If it's fine with you to not have that part reviewed just yet, that's also fine with me.

Copy link
Copy Markdown
Contributor

@dzhidzhoev dzhidzhoev Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it means we may have an intermediate stage where both parts are emitted with debug info.

Ah, I see, that is fine for what gets merged into LLVM main but that means the stacked PR approach won't work for the "strip debug info from DXIL" part of it. I think that means we won't be able to create that PR yet to get that reviewed, because it depends on multiple other PRs that are not otherwise related and GitHub does not support that. If it's fine with you to not have that part reviewed just yet, that's also fine with me.

Well, we could try sending dx.ildb PR with !M.debug_compile_units().empty() check to determine debug info presense (that's what I implied when I told dx.ildb change does not depend on Strip changes, sorry), and the assert for checking that "StripDebugInfo() did not find any debug info when there are no compile units" could be a part of dx.dxil change.

Yes, if we choose the approach to check debug info presence mainly with StripDebugInfo, then changes for both sections depend on StripDebugInfo call correctness.

Copy link
Copy Markdown
Contributor

@dzhidzhoev dzhidzhoev Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it depends on multiple other PRs that are not otherwise related and GitHub does not support that

AFAIK if we choose this option from https://llvm.org/docs/GitHub.html#stacked-pull-requests:

  1. Two PRs with a dependency note

Create PR_1 for feature_1 and PR_2 for feature_2. In PR_2, include a note in the PR summary indicating that it depends on PR_1 (e.g., “Depends on #PR_1”).

To make review easier, make it clear which commits are part of the base PR and which are new, e.g. “The first N commits are from the base PR”. This helps reviewers focus only on the incremental changes.

We can make a PR which depends on two other PRs.

WriteDXILToFile(M, OS, DIMap);
return Data;
}

GlobalVariable *createSectionGlobal(Module &M, StringRef Data,
StringRef GlobalName,
StringRef SectionName) {
Constant *ModuleConstant =
ConstantDataArray::get(M.getContext(), arrayRefFromStringRef(Data));
auto *GV = new llvm::GlobalVariable(M, ModuleConstant->getType(), true,
GlobalValue::PrivateLinkage,
ModuleConstant, GlobalName);
GV->setSection(SectionName);
GV->setAlignment(Align(4));
return GV;
}

public:
static char ID; // Pass identification, replacement for typeid
EmbedDXILPass() : ModulePass(ID) {
Expand All @@ -148,29 +215,38 @@ class EmbedDXILPass : public llvm::ModulePass {
StringRef getPassName() const override { return "DXIL Embedder"; }

bool runOnModule(Module &M) override {
std::string Data;
llvm::raw_string_ostream OS(Data);

// Perform late legalization of lifetime intrinsics that would otherwise
// fail the Module Verifier if performed in an earlier pass
legalizeLifetimeIntrinsics(M);

const auto DIMap = DXILDebugInfoPass::run(M);
WriteDXILToFile(M, OS, DIMap);
bool HasDebugInfo = !M.debug_compile_units().empty();
std::string ILDBData;
if (HasDebugInfo) {
// Write DXIL with debug info to ILDB part.
// Clone the module to avoid alternating it with DebugInfoPass
// before stripping the debug info later.
ILDBData =
writeModule(*llvm::CloneModule(M), HasDebugInfo, /*WriteDebug=*/true);
}

// Clone the module to save dx.source metadata nodes from stripping, as they
// are needed for DXILMetadataAnalysisWrapperPass.
std::string DXILData =
writeModule(*llvm::CloneModule(M), HasDebugInfo, /*WriteDebug=*/false);

// We no longer need lifetime intrinsics after bitcode serialization, so we
// simply remove them to keep the Module Verifier happy after our
// not-so-legal legalizations
removeLifetimeIntrinsics(M);

Constant *ModuleConstant =
ConstantDataArray::get(M.getContext(), arrayRefFromStringRef(Data));
auto *GV = new llvm::GlobalVariable(M, ModuleConstant->getType(), true,
GlobalValue::PrivateLinkage,
ModuleConstant, "dx.dxil");
GV->setSection("DXIL");
GV->setAlignment(Align(4));
appendToCompilerUsed(M, {GV});
SmallVector<GlobalValue *, 2> Globals;
if (HasDebugInfo) {
// Create a GV after both parts are written, otherwise it gets
// added to DXIL when `writeModule` is called the second time.
Globals.emplace_back(createSectionGlobal(M, ILDBData, "dx.ildb", "ILDB"));
}
Globals.emplace_back(createSectionGlobal(M, DXILData, "dx.dxil", "DXIL"));
appendToCompilerUsed(M, Globals);
return true;
}

Expand Down
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/DirectX/ContainerData/DebugShaderHash.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
; RUN: llc %s --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC
target triple = "dxil-unknown-shadermodel6.5-library"

; CHECK: @dx.hash = private constant [20 x i8] c"\01\00\00\00{{.*}}", section "HASH", align 4
; CHECK: @dx.hash = private constant [20 x i8] c"\00\00\00\00{{.*}}", section "HASH", align 4

define i32 @add(i32 %a, i32 %b) {
%sum = add i32 %a, %b
Expand All @@ -21,5 +21,5 @@ define i32 @add(i32 %a, i32 %b) {
; DXC: - Name: HASH
; DXC: Size: 20
; DXC: Hash:
; DXC: IncludesSource: true
; DXC: IncludesSource: false
; DXC: Digest: [
98 changes: 98 additions & 0 deletions llvm/test/CodeGen/DirectX/embed-ildb.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
; RUN: opt %s -dxil-embed -dxil-globals -S -o - | FileCheck %s
; RUN: llc %s --filetype=obj -o %t.bc
; RUN: obj2yaml %t.bc | FileCheck %s --check-prefix=YAML
; RUN: llvm-objcopy --dump-section=ILDB=%t.ildb %t.bc
; RUN: llvm-objcopy --dump-section=DXIL=%t.dxil %t.bc
; RUN: llvm-dis %t.ildb -o - | FileCheck %s --check-prefix=ILDB-DIS
; RUN: llvm-dis %t.dxil -o - | FileCheck %s --check-prefix=DXIL-DIS

target triple = "dxil-unknown-shadermodel6.5-library"
; CHECK: target triple = "dxil-unknown-shadermodel6.5-library"

define i32 @add(i32 %a, i32 %b) {
%sum = add i32 %a, %b
ret i32 %sum
}

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4}
!dx.source.contents = !{!5}
!dx.source.defines = !{!6}
!dx.source.mainFileName = !{!7}
!dx.source.args = !{!8}

!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Some Compiler", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "hlsl.hlsl", directory: "/some-path")
!2 = !{}
!3 = !{i32 7, !"Dwarf Version", i32 2}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{!"hlsl.hlsl", !"int add(int a, int b) { return a + b; }"}
!6 = !{}
!7 = !{!"hlsl.hlsl"}
!8 = !{!"-T", !"lib_6_5", !"-g", !"hlsl.hlsl"}

; Check that both parts are emitted as a GV and used by the compiler.

; CHECK: @dx.ildb = private constant [[BC_TYPE:\[[0-9]+ x i8\]]] c"BC\C0\DE{{[^"]+}}", section "ILDB", align 4
; CHECK: @dx.dxil = private constant [[BC_TYPE:\[[0-9]+ x i8\]]] c"BC\C0\DE{{[^"]+}}", section "DXIL", align 4
; CHECK: @llvm.compiler.used = appending global {{\[[0-9]+ x ptr\]}} [ptr @dx.ildb, ptr @dx.dxil

; This is using regex matches on some sizes, offsets and fields. These are all
; going to change as the DirectX backend continues to evolve and implement more
; features. Rather than extending this test to cover those future features, this
; test's matches are extremely fuzzy so that it won't break.

; YAML: --- !dxcontainer
; YAML-NEXT: Header:
; YAML-NEXT: Hash: [ 0x0, 0x0, 0x0,
; YAML: Version:
; YAML-NEXT: Major: 1
; YAML-NEXT: Minor: 0
; YAML-NEXT: FileSize: [[#]]
; YAML-NEXT: PartCount: [[#]]
; YAML-NEXT: PartOffsets: [ {{[0-9, ]+}}
; YAML: Parts:

; In verifying the DXIL and ILDB parts, this test captures the size of the part,
; and derives the program header and dxil size fields from the part's size.

; YAML: - Name: ILDB
; YAML-NEXT: Size: [[#ILDBSIZE:]]
; YAML-NEXT: Program:
; YAML-NEXT: MajorVersion: 6
; YAML-NEXT: MinorVersion: 5
; YAML-NEXT: ShaderKind: 6
; YAML-NEXT: Size: [[#div(ILDBSIZE,4)]]
; YAML-NEXT: DXILMajorVersion: 1
; YAML-NEXT: DXILMinorVersion: 5
; YAML-NEXT: DXILSize: [[#ILDBSIZE - 24]]
; YAML-NEXT: DXIL: [ 0x42, 0x43, 0xC0, 0xDE,
; YAML: - Name: DXIL
; YAML-NEXT: Size: [[#DXILSIZE:]]
; YAML-NEXT: Program:
; YAML-NEXT: MajorVersion: 6
; YAML-NEXT: MinorVersion: 5
; YAML-NEXT: ShaderKind: 6
; YAML-NEXT: Size: [[#div(DXILSIZE,4)]]
; YAML-NEXT: DXILMajorVersion: 1
; YAML-NEXT: DXILMinorVersion: 5
; YAML-NEXT: DXILSize: [[#DXILSIZE - 24]]
; YAML-NEXT: DXIL: [ 0x42, 0x43, 0xC0, 0xDE,

; Check that ILDB has the debug info, and DXIL does not:

; ILDB-DIS: define i32 @add(i32 %a, i32 %b)
; ILDB-DIS: !llvm.dbg.cu
; ILDB-DIS: !DICompileUnit
; ILDB-DIS: !DIFile
; ILDB-DIS: !"Dwarf Version"
; ILDB-DIS: !"Debug Info Version"

; DXIL-DIS: define i32 @add(i32 %a, i32 %b)
; DXIL-DIS-NOT: !llvm.dbg.cu
; DXIL-DIS-NOT: !dx.source
; DXIL-DIS-NOT: !DICompileUnit
; DXIL-DIS-NOT: !DIFile
; DXIL-DIS-NOT: !"Dwarf Version"
; DXIL-DIS-NOT: !"Debug Info Version"
; DXIL-DIS-NOT: "hlsl.hlsl"
4 changes: 3 additions & 1 deletion llvm/test/tools/dxil-dis/dbg-declare-undef.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s
; RUN: llc --filetype=obj %s -o %t.dxbc
; RUN: llvm-objcopy --dump-section=ILDB=%t.bc %t.dxbc
; RUN: dxil-dis %t.bc -o - | FileCheck %s

target triple = "dxil-pc-shadermodel6.3-library"

Expand Down
4 changes: 3 additions & 1 deletion llvm/test/tools/dxil-dis/dbg-value.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s
; RUN: llc --filetype=obj %s -o %t.dxbc
; RUN: llvm-objcopy --dump-section=ILDB=%t.bc %t.dxbc
; RUN: dxil-dis %t.bc -o - | FileCheck %s

target triple = "dxil-pc-shadermodel6.3-library"

Expand Down
4 changes: 3 additions & 1 deletion llvm/test/tools/dxil-dis/debug-info.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s
; RUN: llc --filetype=obj %s -o %t.dxbc
; RUN: llvm-objcopy --dump-section=ILDB=%t.bc %t.dxbc
; RUN: dxil-dis %t.bc -o - | FileCheck %s

target triple = "dxil-unknown-shadermodel6.7-library"
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s
; RUN: llc --filetype=obj %s -o %t.dxbc
; RUN: llvm-objcopy --dump-section=ILDB=%t.bc %t.dxbc
; RUN: dxil-dis %t.bc -o - | FileCheck %s

target triple = "dxil-unknown-shadermodel6.3-library"

Expand Down
4 changes: 3 additions & 1 deletion llvm/test/tools/dxil-dis/di-compile-unit.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s
; RUN: llc --filetype=obj %s -o %t.dxbc
; RUN: llvm-objcopy --dump-section=ILDB=%t.bc %t.dxbc
; RUN: dxil-dis %t.bc -o - | FileCheck %s
target triple = "dxil-unknown-shadermodel6.7-library"

!llvm.dbg.cu = !{!0}
Expand Down
4 changes: 3 additions & 1 deletion llvm/test/tools/dxil-dis/di-label.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s
; RUN: llc --filetype=obj %s -o %t.dxbc
; RUN: llvm-objcopy --dump-section=ILDB=%t.bc %t.dxbc
; RUN: dxil-dis %t.bc -o - | FileCheck %s

target triple = "dxil-pc-shadermodel6.3-library"

Expand Down
4 changes: 3 additions & 1 deletion llvm/test/tools/dxil-dis/di-subprogram.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s
; RUN: llc --filetype=obj %s -o %t.dxbc
; RUN: llvm-objcopy --dump-section=ILDB=%t.bc %t.dxbc
; RUN: dxil-dis %t.bc -o - | FileCheck %s
target triple = "dxil-unknown-shadermodel6.7-library"

define float @fmaf(float %x, float %y, float %z) !dbg !4 {
Expand Down
4 changes: 3 additions & 1 deletion llvm/test/tools/dxil-dis/di-subrange.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s
; RUN: llc --filetype=obj %s -o %t.dxbc
; RUN: llvm-objcopy --dump-section=ILDB=%t.bc %t.dxbc
; RUN: dxil-dis %t.bc -o - | FileCheck %s
target triple = "dxil-unknown-shadermodel6.7-library"

!llvm.module.flags = !{!0, !1}
Expand Down
4 changes: 3 additions & 1 deletion llvm/test/tools/dxil-dis/di-subrangetype.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s
; RUN: llc --filetype=obj %s -o %t.dxbc
; RUN: llvm-objcopy --dump-section=ILDB=%t.bc %t.dxbc
; RUN: dxil-dis %t.bc -o - | FileCheck %s

target triple = "dxil-pc-shadermodel6.3-library"

Expand Down
Loading