[llvm] Implement support for NSDI DebugFunction opcode. (PR #211760)
Manuel Carrasco via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 30 07:01:54 PDT 2026
https://github.com/mgcarrasco updated https://github.com/llvm/llvm-project/pull/211760
>From 112360ef251d24ced1d64ea30a6d324b43a8f6b1 Mon Sep 17 00:00:00 2001
From: Manuel Carrasco <Manuel.Carrasco at amd.com>
Date: Fri, 24 Jul 2026 04:42:51 -0500
Subject: [PATCH 1/5] Implement support for NSDI DebugFunction opcode.
---
.../SPIRV/SPIRVNonSemanticDebugHandler.cpp | 58 ++++++++++++++++++-
.../SPIRV/SPIRVNonSemanticDebugHandler.h | 28 ++++++---
.../debug-function-namespace-scope.ll | 41 +++++++++++++
.../debug-function-with-declaration.ll | 37 ++++++++++++
.../SPIRV/debug-info/debug-function.ll | 43 ++++++++++++++
5 files changed, 199 insertions(+), 8 deletions(-)
create mode 100644 llvm/test/CodeGen/SPIRV/debug-info/debug-function-namespace-scope.ll
create mode 100644 llvm/test/CodeGen/SPIRV/debug-info/debug-function-with-declaration.ll
create mode 100644 llvm/test/CodeGen/SPIRV/debug-info/debug-function.ll
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
index f22cc1a38a794..12783da9a34f3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
@@ -239,6 +239,7 @@ void SPIRVNonSemanticDebugHandler::beginModule(Module *M) {
CompositeTypes.clear();
TypedefTypes.clear();
SubprogramDeclarations.clear();
+ SubprogramDefinitions.clear();
GlobalVariableDebugInfoMap.clear();
DebugFunctionDeclarationRegs.clear();
ScopeToPathOpStringReg.clear();
@@ -296,7 +297,9 @@ void SPIRVNonSemanticDebugHandler::beginModule(Module *M) {
});
for (const DISubprogram *SP : Finder.subprograms()) {
- if (!SP->isDefinition())
+ if (SP->isDefinition())
+ SubprogramDefinitions.push_back(SP);
+ else
SubprogramDeclarations.push_back(SP);
}
@@ -650,6 +653,49 @@ SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
MAI);
}
+std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugFunction(
+ const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
+ MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
+ assert(SP && "SP must not be null in emitDebugFunction");
+ assert(SP->isDefinition() && "SP must be a definition in emitDebugFunction");
+
+ const DISubroutineType *ST = SP->getType();
+ auto FnTyRegOpt = lookupOptReg(DebugTypeRegs, ST);
+ if (!FnTyRegOpt)
+ return std::nullopt;
+
+ auto ParentRegOpt = resolveDebugFunctionDeclarationParent(SP);
+ if (!ParentRegOpt)
+ return std::nullopt;
+
+ MCRegister NameReg = getCachedOpStringReg(SP->getName());
+ MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
+ MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
+ MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
+ ExtInstSetReg, MAI);
+
+ MCRegister LineReg =
+ emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
+ // LLVM's DISubprogram has no column field but SPIR-V expects one in
+ // DebugFunction.
+ MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
+ MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(SP), I32TypeReg, MAI);
+ MCRegister ScopeLineReg = emitOpConstantI32(
+ static_cast<uint32_t>(SP->getScopeLine()), I32TypeReg, MAI);
+
+ SmallVector<MCRegister, 10> Ops = {NameReg, *FnTyRegOpt, SrcReg,
+ LineReg, ColReg, *ParentRegOpt,
+ LinkageReg, FlagsReg, ScopeLineReg};
+
+ if (const DISubprogram *Decl = SP->getDeclaration()) {
+ if (auto DeclRegOpt = lookupOptReg(DebugFunctionDeclarationRegs, Decl))
+ Ops.push_back(*DeclRegOpt);
+ }
+
+ return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunction, VoidTypeReg,
+ ExtInstSetReg, Ops, MAI);
+}
+
std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
const DIType *Ty, MCRegister VoidTypeReg, bool ReturnType) {
if (!Ty) {
@@ -991,6 +1037,12 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticDebugStrings(
emitAndCacheScopePathOpStringReg(TD->getFile(), MAI);
}
+ for (const DISubprogram *SP : SubprogramDefinitions) {
+ emitOpStringIfNew(SP->getName(), MAI);
+ emitOpStringIfNew(SP->getLinkageName(), MAI);
+ emitAndCacheScopePathOpStringReg(SP, MAI);
+ }
+
for (const auto &[GV, _] : GlobalVariableDebugInfoMap) {
emitOpStringIfNew(GV->getName(), MAI);
emitOpStringIfNew(GV->getLinkageName(), MAI);
@@ -1175,6 +1227,10 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticGlobalDebugInfo(
DebugTypeRegs[CT] = *CompReg;
}
+ // Emit DebugFunction for DISubprogram definitions.
+ for (const DISubprogram *SP : SubprogramDefinitions)
+ emitDebugFunction(SP, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
+
// Emit DebugGlobalVariable for each collected DIGlobalVariable.
for (const auto &[GV, Info] : GlobalVariableDebugInfoMap)
emitDebugGlobalVariable(GV, Info, VoidTypeReg, I32TypeReg, ExtInstSetReg,
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
index eb1469a5baf69..0dbfe945bb587 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
@@ -46,7 +46,8 @@ class SPIRVSubtarget;
/// emitNonSemanticGlobalDebugInfo() -- emit DebugSource,
/// DebugCompilationUnit, DebugTypeBasic,
/// DebugTypePointer, DebugTypeFunction,
-/// DebugFunctionDeclaration.
+/// DebugFunctionDeclaration,
+/// DebugFunction.
/// beginFunctionImpl() -- no-op (no per-function DI yet).
/// endFunctionImpl() -- no-op.
class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
@@ -85,6 +86,10 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
// in beginModule() for DebugFunctionDeclaration emission.
SmallVector<const DISubprogram *> SubprogramDeclarations;
+ // DISubprogram nodes that are definitions, collected in beginModule() for
+ // DebugFunction emission.
+ SmallVector<const DISubprogram *> SubprogramDefinitions;
+
struct GlobalVariableDebugInfo {
const DIExpression *Expr = nullptr;
const GlobalVariable *LLVMGV = nullptr;
@@ -168,7 +173,7 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
/// Emit module-scope NSDI instructions (DebugSource, DebugCompilationUnit,
/// DebugTypeBasic, DebugTypePointer, DebugTypeFunction,
- /// DebugFunctionDeclaration). Called by
+ /// DebugFunctionDeclaration, DebugFunction). Called by
/// SPIRVAsmPrinter::outputModuleSections() at section 10 in place of
/// outputModuleSection(MB_NonSemanticGlobalDI). Requires
/// emitNonSemanticDebugStrings() to have run first when NSDI strings apply.
@@ -191,12 +196,13 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
void beginInstruction(const MachineInstr *MI) override {}
void endInstruction() override {}
- // TODO: Emit DebugFunction and DebugFunctionDefinition here once per-function
- // NSDI emission is implemented. DebugHandlerBase::beginFunction() populates
- // LScopes and DbgValues, which are needed for DebugLine emission. Do not
- // override beginFunction() until that work is in place.
+ // TODO: Emit DebugFunctionDefinition here once per-function NSDI emission is
+ // implemented. DebugHandlerBase::beginFunction() populates LScopes and
+ // DbgValues, which are needed for DebugLine emission. Do not override
+ // beginFunction() until that work is in place.
void beginFunctionImpl(const MachineFunction *MF) override {}
- // TODO: Add per-function cleanup when DebugFunction emission is in place.
+ // TODO: Add per-function cleanup when DebugFunctionDefinition emission is in
+ // place.
void endFunctionImpl(const MachineFunction *MF) override {}
private:
@@ -291,6 +297,14 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
MCRegister I32TypeReg, MCRegister ExtInstSetReg,
SPIRV::ModuleAnalysisInfo &MAI);
+ /// Emit \c DebugFunction for a defining \c DISubprogram (\p SP must satisfy
+ /// \c isDefinition()).
+ std::optional<MCRegister> emitDebugFunction(const DISubprogram *SP,
+ MCRegister VoidTypeReg,
+ MCRegister I32TypeReg,
+ MCRegister ExtInstSetReg,
+ SPIRV::ModuleAnalysisInfo &MAI);
+
/// Emit \c DebugGlobalVariable for the source global variable \p GV.
///
/// (\c SPIRVDebug::Operand::GlobalVariable): Name, Type, Source, Line,
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-function-namespace-scope.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-function-namespace-scope.ll
new file mode 100644
index 0000000000000..a9e9160435b37
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-function-namespace-scope.ll
@@ -0,0 +1,41 @@
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; DISubprogram definition scoped in a DINamespace. Namespace scopes are not yet
+; supported as DebugFunction Parent, so no DebugFunction is emitted.
+
+; CHECK: [[EXT:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-DAG: [[VOID:%[0-9]+]] = OpTypeVoid
+; CHECK-DAG: [[I32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: OpString "ns_fn"
+; CHECK-DAG: [[PATH:%[0-9]+]] = OpString "{{[/\\]}}tmp{{[/\\]}}namespace-scope-fn.c"
+; CHECK-DAG: [[C100:%[0-9]+]] = OpConstant [[I32]] 100
+; CHECK-DAG: [[C5:%[0-9]+]] = OpConstant [[I32]] 5
+; CHECK-DAG: [[C0:%[0-9]+]] = OpConstant [[I32]] 0
+; CHECK-DAG: [[DS:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugSource [[PATH]]
+; CHECK-DAG: OpExtInst [[VOID]] [[EXT]] DebugCompilationUnit [[C100]] [[C5]] [[DS]] [[C0]]
+; CHECK-DAG: OpExtInst [[VOID]] [[EXT]] DebugTypeFunction [[C0]] [[VOID]]
+; CHECK-NOT: DebugFunction
+
+target triple = "spirv64-unknown-unknown"
+
+define spir_func void @ns_fn() !dbg !9 {
+entry:
+ ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "namespace-scope-fn.c", directory: "/tmp", checksumkind: CSK_MD5, checksum: "00000000000000000000000000000000")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"frame-pointer", i32 2}
+
+!6 = !DISubroutineType(cc: DW_CC_LLVM_SpirFunction, types: !7)
+!7 = !{}
+!8 = !DINamespace(name: "ns", scope: !1)
+
+!9 = distinct !DISubprogram(name: "ns_fn", linkageName: "ns_fn", scope: !8, file: !1, line: 2, type: !6, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-function-with-declaration.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-function-with-declaration.ll
new file mode 100644
index 0000000000000..7a9523010d6f9
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-function-with-declaration.ll
@@ -0,0 +1,37 @@
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; DebugFunction should reference the emitted DebugFunctionDeclaration when the
+; defining DISubprogram carries a declaration operand.
+
+; CHECK-DAG: [[EXT:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-DAG: [[VOID:%[0-9]+]] = OpTypeVoid
+; CHECK-DAG: [[NAME:%[0-9]+]] = OpString "add_one"
+; CHECK-DAG: [[DECL:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugFunctionDeclaration [[NAME]] {{.*}} [[NAME]] {{.*}}
+; CHECK-DAG: [[DF:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugFunction [[NAME]] {{.*}} [[DECL]]
+
+target triple = "spirv64-unknown-unknown"
+
+define spir_func i32 @add_one(i32 %value) !dbg !5 {
+entry:
+ %result = add i32 %value, 1
+ ret i32 %result, !dbg !8
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None, retainedTypes: !9)
+!1 = !DIFile(filename: "debug-function-with-declaration.c", directory: "/src")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+
+!4 = !DISubroutineType(types: !6)
+!6 = !{!7, !7}
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+
+!9 = !{!10}
+!10 = !DISubprogram(name: "add_one", linkageName: "add_one", scope: !1, file: !1, line: 1, type: !4, scopeLine: 1, flags: DIFlagPrototyped, spFlags: 0)
+
+!5 = distinct !DISubprogram(name: "add_one", linkageName: "add_one", scope: !1, file: !1, line: 1, type: !4, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, declaration: !10)
+!8 = !DILocation(line: 3, column: 3, scope: !5)
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-function.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-function.ll
new file mode 100644
index 0000000000000..e71dc38829e94
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-function.ll
@@ -0,0 +1,43 @@
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; Exercise NonSemantic DebugFunction for a defined function (module scope).
+
+; CHECK-DAG: [[EXT:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-DAG: [[VOID:%[0-9]+]] = OpTypeVoid
+; CHECK-DAG: [[I32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[PATH:%[0-9]+]] = OpString "/src/debug-function.c"
+; CHECK-DAG: [[NAME:%[0-9]+]] = OpString "add_one"
+; CHECK-DAG: [[C100:%[0-9]+]] = OpConstant [[I32]] 100
+; CHECK-DAG: [[C5:%[0-9]+]] = OpConstant [[I32]] 5
+; CHECK-DAG: [[C0:%[0-9]+]] = OpConstant [[I32]] 0
+; CHECK-DAG: [[C136:%[0-9]+]] = OpConstant [[I32]] 136
+; CHECK-DAG: [[DS:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugSource [[PATH]]
+; CHECK-DAG: [[CU:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugCompilationUnit [[C100]] [[C5]] [[DS]] [[C0]]
+; CHECK-DAG: [[INTNAME:%[0-9]+]] = OpString "int"
+; CHECK-DAG: [[INT:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugTypeBasic [[INTNAME]] {{.*}} [[C0]]
+; CHECK-DAG: [[TF:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugTypeFunction [[C0]] [[INT]] [[INT]]
+; CHECK-DAG: [[DF:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugFunction [[NAME]] [[TF]] [[DS]] {{.*}} [[C0]] [[CU]] [[NAME]] [[C136]] {{.*}}
+
+target triple = "spirv64-unknown-unknown"
+
+define spir_func i32 @add_one(i32 %value) !dbg !5 {
+entry:
+ %result = add i32 %value, 1
+ ret i32 %result, !dbg !8
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "debug-function.c", directory: "/src")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+
+!4 = !DISubroutineType(types: !6)
+!6 = !{!7, !7}
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+
+!5 = distinct !DISubprogram(name: "add_one", linkageName: "add_one", scope: !1, file: !1, line: 1, type: !4, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
+!8 = !DILocation(line: 3, column: 3, scope: !5)
>From a6717b4a8d7ea0592420c3f5010970f52a494fc0 Mon Sep 17 00:00:00 2001
From: Manuel Carrasco <Manuel.Carrasco at amd.com>
Date: Tue, 28 Jul 2026 07:15:41 -0500
Subject: [PATCH 2/5] Fix path separators.
---
llvm/test/CodeGen/SPIRV/debug-info/debug-function.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-function.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-function.ll
index e71dc38829e94..67ea1d4ffdeb1 100644
--- a/llvm/test/CodeGen/SPIRV/debug-info/debug-function.ll
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-function.ll
@@ -6,7 +6,7 @@
; CHECK-DAG: [[EXT:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
; CHECK-DAG: [[VOID:%[0-9]+]] = OpTypeVoid
; CHECK-DAG: [[I32:%[0-9]+]] = OpTypeInt 32 0
-; CHECK-DAG: [[PATH:%[0-9]+]] = OpString "/src/debug-function.c"
+; CHECK-DAG: [[PATH:%[0-9]+]] = OpString "{{[/\\]}}src{{[/\\]}}debug-function.c"
; CHECK-DAG: [[NAME:%[0-9]+]] = OpString "add_one"
; CHECK-DAG: [[C100:%[0-9]+]] = OpConstant [[I32]] 100
; CHECK-DAG: [[C5:%[0-9]+]] = OpConstant [[I32]] 5
>From 3a3fee2ee715ed46d4bbf541d403287fc9ec8b70 Mon Sep 17 00:00:00 2001
From: Manuel Carrasco <Manuel.Carrasco at amd.com>
Date: Tue, 28 Jul 2026 08:14:48 -0500
Subject: [PATCH 3/5] Fix negative checks.
---
.../SPIRV/debug-info/debug-function-namespace-scope.ll | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-function-namespace-scope.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-function-namespace-scope.ll
index a9e9160435b37..e97c705abeb33 100644
--- a/llvm/test/CodeGen/SPIRV/debug-info/debug-function-namespace-scope.ll
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-function-namespace-scope.ll
@@ -1,4 +1,6 @@
-; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s
+; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o %t.spt
+; RUN: FileCheck %s --check-prefix=CHECK --input-file %t.spt
+; RUN: FileCheck %s --check-prefix=NO-DBG-FUNC --input-file %t.spt
; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
; DISubprogram definition scoped in a DINamespace. Namespace scopes are not yet
@@ -15,7 +17,8 @@
; CHECK-DAG: [[DS:%[0-9]+]] = OpExtInst [[VOID]] [[EXT]] DebugSource [[PATH]]
; CHECK-DAG: OpExtInst [[VOID]] [[EXT]] DebugCompilationUnit [[C100]] [[C5]] [[DS]] [[C0]]
; CHECK-DAG: OpExtInst [[VOID]] [[EXT]] DebugTypeFunction [[C0]] [[VOID]]
-; CHECK-NOT: DebugFunction
+
+; NO-DBG-FUNC-NOT: DebugFunction
target triple = "spirv64-unknown-unknown"
>From 15c7658165573ad6071f445cf7cd4a7b2de366a8 Mon Sep 17 00:00:00 2001
From: Manuel Carrasco <Manuel.Carrasco at amd.com>
Date: Tue, 28 Jul 2026 08:19:05 -0500
Subject: [PATCH 4/5] Rename function.
---
.../Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp | 6 +++---
llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h | 12 ++++++------
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
index 12783da9a34f3..9c071120a27b7 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
@@ -572,7 +572,7 @@ SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
// Match SPIRV-LLVM-Translator's selection logic for the Parent operand.
std::optional<MCRegister>
-SPIRVNonSemanticDebugHandler::resolveDebugFunctionDeclarationParent(
+SPIRVNonSemanticDebugHandler::resolveDebugFunctionParent(
const DISubprogram *SP) const {
const DIScope *Scope = SP->getScope();
if (Scope && !isa<DIFile>(Scope)) {
@@ -623,7 +623,7 @@ SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
return std::nullopt;
MCRegister FnTyReg = *FnTyRegOpt;
- auto ParentRegOpt = resolveDebugFunctionDeclarationParent(SP);
+ auto ParentRegOpt = resolveDebugFunctionParent(SP);
if (!ParentRegOpt)
return std::nullopt;
@@ -664,7 +664,7 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugFunction(
if (!FnTyRegOpt)
return std::nullopt;
- auto ParentRegOpt = resolveDebugFunctionDeclarationParent(SP);
+ auto ParentRegOpt = resolveDebugFunctionParent(SP);
if (!ParentRegOpt)
return std::nullopt;
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
index 0dbfe945bb587..5da526587df91 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
@@ -290,7 +290,7 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
/// DISubroutineType type, the signature type was not emitted in \c
/// DebugTypeRegs, no path
/// \c OpString was recorded for \p SP in section 7, or
- /// \c resolveDebugFunctionDeclarationParent returns no id for the \c Parent
+ /// \c resolveDebugFunctionParent returns no id for the \c Parent
/// operand.
std::optional<MCRegister>
emitDebugFunctionDeclaration(const DISubprogram *SP, MCRegister VoidTypeReg,
@@ -436,15 +436,15 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
MCRegister ExtInstSetReg,
SPIRV::ModuleAnalysisInfo &MAI);
- /// Resolve the \c Parent operand for \c DebugFunctionDeclaration: an emitted
- /// debug type id when \c SP->getScope() is a \c DIType in \c DebugTypeRegs,
- /// otherwise \c DebugCompilationUnit for \c SP->getUnit() (or the first
- /// module CU when \c unit: is absent).
+ /// Resolve the \c Parent operand for \c DebugFunctionDeclaration and
+ /// \c DebugFunction: an emitted debug type id when \c SP->getScope() is a
+ /// \c DIType in \c DebugTypeRegs, otherwise \c DebugCompilationUnit for
+ /// \c SP->getUnit() (or the first module CU when \c unit: is absent).
/// \returns \c std::nullopt when the scope requires a parent we cannot supply
/// (non-file scope that is not a mapped \c DIType) or the CU has no emitted
/// id.
std::optional<MCRegister>
- resolveDebugFunctionDeclarationParent(const DISubprogram *SP) const;
+ resolveDebugFunctionParent(const DISubprogram *SP) const;
/// Resolve the \c Parent operand for a type instruction (\c
/// DebugTypeComposite) from its \p Scope: an emitted debug type id when \p
>From 99315866c22316da15d1a5d9884fb4c2e33c3336 Mon Sep 17 00:00:00 2001
From: Manuel Carrasco <Manuel.Carrasco at amd.com>
Date: Tue, 28 Jul 2026 08:23:12 -0500
Subject: [PATCH 5/5] Simplify loops.
---
llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
index 9c071120a27b7..d0b7f67866acb 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
@@ -1009,7 +1009,8 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticDebugStrings(
for (const DIBasicType *BT : BasicTypes)
emitOpStringIfNew(BT->getName(), MAI);
- for (const DISubprogram *SP : SubprogramDeclarations) {
+ for (const DISubprogram *SP : concat<const DISubprogram *>(
+ SubprogramDeclarations, SubprogramDefinitions)) {
emitOpStringIfNew(SP->getName(), MAI);
emitOpStringIfNew(SP->getLinkageName(), MAI);
emitAndCacheScopePathOpStringReg(SP, MAI);
@@ -1037,12 +1038,6 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticDebugStrings(
emitAndCacheScopePathOpStringReg(TD->getFile(), MAI);
}
- for (const DISubprogram *SP : SubprogramDefinitions) {
- emitOpStringIfNew(SP->getName(), MAI);
- emitOpStringIfNew(SP->getLinkageName(), MAI);
- emitAndCacheScopePathOpStringReg(SP, MAI);
- }
-
for (const auto &[GV, _] : GlobalVariableDebugInfoMap) {
emitOpStringIfNew(GV->getName(), MAI);
emitOpStringIfNew(GV->getLinkageName(), MAI);
More information about the llvm-commits
mailing list