[llvm] [SPIRV] Emit NonSemantic DebugTypedef (PR #211883)
Diego Novillo via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 29 11:49:45 PDT 2026
https://github.com/dnovillo updated https://github.com/llvm/llvm-project/pull/211883
>From 68ce8d8a80d61fe193cf19c38c70de4adac8f219 Mon Sep 17 00:00:00 2001
From: Diego Novillo <dnovillo at nvidia.com>
Date: Fri, 24 Jul 2026 12:33:23 -0400
Subject: [PATCH 1/4] [SPIRV] Emit NonSemantic DebugTypedef
---
.../SPIRV/SPIRVNonSemanticDebugHandler.cpp | 78 +++++++++++++++++--
.../SPIRV/SPIRVNonSemanticDebugHandler.h | 18 +++++
.../debug-info/debug-typedef-nested-drop.ll | 34 ++++++++
.../debug-typedef-skip-base-not-in-regs.ll | 30 +++++++
.../CodeGen/SPIRV/debug-info/debug-typedef.ll | 36 +++++++++
5 files changed, 189 insertions(+), 7 deletions(-)
create mode 100644 llvm/test/CodeGen/SPIRV/debug-info/debug-typedef-nested-drop.ll
create mode 100644 llvm/test/CodeGen/SPIRV/debug-info/debug-typedef-skip-base-not-in-regs.ll
create mode 100644 llvm/test/CodeGen/SPIRV/debug-info/debug-typedef.ll
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
index 8125b1b7dc7f3..6caf688f16354 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
@@ -42,18 +42,19 @@ static std::optional<MCRegister> lookupOptReg(const MapT &Map,
}
/// Partition \p Ty into \p BasicTypes, \p PointerTypes, \p SubroutineTypes,
-/// \p VectorTypes, \p ArrayTypes, and \p CompositeTypes for NSDI emission. Used
-/// when iterating DebugInfoFinder.types(); each DI node is seen once, so no
-/// recursion into pointer bases. Non-pointer derived kinds are ignored because
-/// they are not yet supported. Only types that are supported (later used) are
-/// partitioned.
+/// \p VectorTypes, \p ArrayTypes, \p CompositeTypes, and \p TypedefTypes for
+/// NSDI emission. Used when iterating DebugInfoFinder.types(); each DI node is
+/// seen once, so no recursion into pointer bases. Other composites and the
+/// remaining derived kinds are ignored because they are not yet supported.
+/// Only types that are supported (later used) are partitioned.
static void
partitionTypes(const DIType *Ty, SmallVector<const DIBasicType *> &BasicTypes,
SmallVector<const DIDerivedType *> &PointerTypes,
SmallVector<const DISubroutineType *> &SubroutineTypes,
SmallVector<const DICompositeType *> &VectorTypes,
SmallVector<const DICompositeType *> &ArrayTypes,
- SmallVector<const DICompositeType *> &CompositeTypes) {
+ SmallVector<const DICompositeType *> &CompositeTypes,
+ SmallVector<const DIDerivedType *> &TypedefTypes) {
if (const auto *BT = dyn_cast<DIBasicType>(Ty)) {
BasicTypes.push_back(BT);
return;
@@ -89,6 +90,8 @@ partitionTypes(const DIType *Ty, SmallVector<const DIBasicType *> &BasicTypes,
const auto *DT = dyn_cast<DIDerivedType>(Ty);
if (DT && DT->getTag() == dwarf::DW_TAG_pointer_type)
PointerTypes.push_back(DT);
+ else if (DT && DT->getTag() == dwarf::DW_TAG_typedef)
+ TypedefTypes.push_back(DT);
}
enum : uint32_t {
@@ -234,6 +237,7 @@ void SPIRVNonSemanticDebugHandler::beginModule(Module *M) {
VectorTypes.clear();
ArrayTypes.clear();
CompositeTypes.clear();
+ TypedefTypes.clear();
SubprogramDeclarations.clear();
GlobalVariableDebugInfoMap.clear();
DebugFunctionDeclarationRegs.clear();
@@ -288,7 +292,7 @@ void SPIRVNonSemanticDebugHandler::beginModule(Module *M) {
Finder.processModule(*M);
llvm::for_each(Finder.types(), [&](DIType *Ty) {
partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes, VectorTypes,
- ArrayTypes, CompositeTypes);
+ ArrayTypes, CompositeTypes, TypedefTypes);
});
for (const DISubprogram *SP : Finder.subprograms()) {
@@ -893,6 +897,47 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeComposite(
ExtInstSetReg, Ops, MAI);
}
+std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypedef(
+ const DIDerivedType *TD, MCRegister VoidTypeReg, MCRegister I32TypeReg,
+ MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
+ // The underlying (base) type must already be in DebugTypeRegs.
+ auto BaseRegOpt = lookupOptReg(DebugTypeRegs, TD->getBaseType());
+ if (!BaseRegOpt)
+ return std::nullopt;
+
+ MCRegister NameReg = getCachedOpStringReg(TD->getName());
+ MCRegister FileStrReg = getCachedScopePathOpStringReg(
+ TD->getFile(), /*UseEmptyPathIfNullScope=*/true);
+ MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
+ ExtInstSetReg, MAI);
+ MCRegister LineReg =
+ emitOpConstantI32(static_cast<uint32_t>(TD->getLine()), I32TypeReg, MAI);
+ // DIDerivedType typedefs carry no column, so emit 0.
+ MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
+
+ // Parent: the enclosing type when the scope is an emitted DIType (a typedef
+ // nested in another type), otherwise the compile unit. Fall back to the
+ // compile unit rather than dropping the typedef when the scope type is not
+ // emitted.
+ MCRegister ParentReg;
+ if (const auto *Ty = dyn_cast_or_null<DIType>(TD->getScope()))
+ if (auto TyRegOpt = lookupOptReg(DebugTypeRegs, Ty))
+ ParentReg = *TyRegOpt;
+ if (!ParentReg.isValid()) {
+ assert(!CompileUnits.empty() &&
+ "emitDebugTypedef requires a compile unit for the Parent operand");
+ auto CURegOpt =
+ lookupOptReg(CUToCompilationUnitDbgReg, CompileUnits[0].TheCU);
+ assert(CURegOpt && "DebugCompilationUnit must be emitted before typedefs");
+ ParentReg = *CURegOpt;
+ }
+
+ return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypedef, VoidTypeReg,
+ ExtInstSetReg,
+ {NameReg, *BaseRegOpt, SrcReg, LineReg, ColReg, ParentReg},
+ MAI);
+}
+
void SPIRVNonSemanticDebugHandler::emitNonSemanticDebugStrings(
SPIRV::ModuleAnalysisInfo &MAI) {
if (CompileUnits.empty())
@@ -939,6 +984,14 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticDebugStrings(
}
}
+ // Cache the name and path OpStrings each DebugTypedef uses.
+ for (const DIDerivedType *TD : TypedefTypes) {
+ emitOpStringIfNew(TD->getName(), MAI);
+ MCRegister PathReg = emitOpStringIfNew(getDebugFullPath(TD->getFile()), MAI);
+ if (const DIFile *F = TD->getFile())
+ ScopeToPathOpStringReg[F] = PathReg;
+ }
+
for (const auto &[GV, _] : GlobalVariableDebugInfoMap) {
emitOpStringIfNew(GV->getName(), MAI);
emitOpStringIfNew(GV->getLinkageName(), MAI);
@@ -1086,6 +1139,17 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticGlobalDebugInfo(
DebugTypeRegs[ST] = *FnTyReg;
}
+ // Emit DebugTypedef for each typedef. Placed after the other type loops so a
+ // typedef can resolve its underlying type. A typedef whose base type is not
+ // emitted is skipped. A typedef whose base is another typedef emitted later
+ // in this same pass is also skipped, the emission-order gap tracked in
+ // https://github.com/llvm/llvm-project/issues/211850.
+ for (const DIDerivedType *TD : TypedefTypes) {
+ if (auto TDReg =
+ emitDebugTypedef(TD, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
+ DebugTypeRegs[TD] = *TDReg;
+ }
+
// Emit DebugFunctionDeclaration for DISubprogram declarations.
for (const DISubprogram *SP : SubprogramDeclarations) {
if (auto DeclReg = emitDebugFunctionDeclaration(SP, VoidTypeReg, I32TypeReg,
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
index 59653c19146fd..eb1469a5baf69 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h
@@ -73,6 +73,9 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
// DICompositeType nodes with DW_TAG_structure_type, DW_TAG_class_type, or
// DW_TAG_union_type, partitioned in beginModule() for DebugTypeComposite.
SmallVector<const DICompositeType *> CompositeTypes;
+ // DIDerivedType nodes with DW_TAG_typedef, partitioned in beginModule() for
+ // DebugTypedef emission.
+ SmallVector<const DIDerivedType *> TypedefTypes;
// Filled in emitNonSemanticGlobalDebugInfo(): DI types to their result
// registers.
@@ -370,6 +373,21 @@ class SPIRVNonSemanticDebugHandler : public DebugHandlerBase {
MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
SPIRV::ModuleAnalysisInfo &MAI);
+ /// Emit \c DebugTypedef for the typedef derived type \p TD (a \c
+ /// DIDerivedType with \c DW_TAG_typedef). Operands: Name, Base Type, Source,
+ /// Line, Column, Parent. Parent is the enclosing type when \c TD->getScope()
+ /// is an emitted \c DIType, otherwise the first module \c
+ /// DebugCompilationUnit.
+ ///
+ /// \returns The result id register on success. Returns \c std::nullopt and
+ /// emits nothing if \p TD's base type has not been emitted into \c
+ /// DebugTypeRegs.
+ std::optional<MCRegister> emitDebugTypedef(const DIDerivedType *TD,
+ MCRegister VoidTypeReg,
+ MCRegister I32TypeReg,
+ MCRegister ExtInstSetReg,
+ SPIRV::ModuleAnalysisInfo &MAI);
+
/// Map a \c DISubroutineType::getTypeArray() element to an operand register
/// for
/// \c DebugTypeFunction. Non-null \p Ty resolves via \c DebugTypeRegs; if the
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-typedef-nested-drop.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-typedef-nested-drop.ll
new file mode 100644
index 0000000000000..df4cf9973d9af
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-typedef-nested-drop.ll
@@ -0,0 +1,34 @@
+; RUN: llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV --implicit-check-not=DebugTypedef
+; 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 %}
+
+; Typedefs are emitted in a single DebugInfoFinder pass. Bar is discovered
+; before Foo, so when Bar is emitted its Foo base has no id yet and Bar is
+; dropped. Foo is emitted next and survives. Only one DebugTypedef is emitted
+; here, for Foo. Emitting typedefs in dependency order, would add a second
+; DebugTypedef for Bar (see https://github.com/llvm/llvm-project/issues/211850).
+
+; CHECK-SPIRV: OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-SPIRV: DebugTypedef
+
+define spir_func void @test() !dbg !6 {
+entry:
+ ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!1, !2}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_HLSL, file: !3, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !4)
+!1 = !{i32 7, !"Dwarf Version", i32 5}
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = !DIFile(filename: "typedef.hlsl", directory: "/src")
+
+; Only Bar is retained. Foo is reached solely through Bar's base type, so the
+; finder visits Bar first and Foo second.
+!4 = !{!5}
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar", file: !3, line: 3, baseType: !7, scope: !3)
+!6 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
+!7 = !DIDerivedType(tag: DW_TAG_typedef, name: "Foo", file: !3, line: 2, baseType: !9, scope: !3)
+!8 = !DISubroutineType(types: !10)
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !{null}
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-typedef-skip-base-not-in-regs.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-typedef-skip-base-not-in-regs.ll
new file mode 100644
index 0000000000000..59aa3d3df9a08
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-typedef-skip-base-not-in-regs.ll
@@ -0,0 +1,30 @@
+; RUN: llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV --implicit-check-not=DebugTypedef
+; 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 %}
+
+; emitDebugTypedef emits nothing when the base type is not in DebugTypeRegs.
+; The base type here is a pointer with no DWARF address space, which
+; emitDebugTypePointer skips for lack of a storage class. The base type stays
+; out of DebugTypeRegs regardless of later type support, so the typedef is
+; skipped.
+
+; CHECK-SPIRV: OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+
+define spir_func void @test() !dbg !6 {
+entry:
+ ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!1, !2}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_HLSL, file: !3, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !4)
+!1 = !{i32 7, !"Dwarf Version", i32 5}
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = !DIFile(filename: "typedef.hlsl", directory: "/src")
+!4 = !{!5}
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "MyPtr", file: !3, line: 2, baseType: !7, scope: !3)
+!6 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
+!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64)
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-typedef.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-typedef.ll
new file mode 100644
index 0000000000000..de3df04366add
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-typedef.ll
@@ -0,0 +1,36 @@
+; RUN: llc --verify-machineinstrs --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; 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 %}
+
+; A DIDerivedType with DW_TAG_typedef lowers to DebugTypedef: Name, Base Type,
+; Source, Line, Column, Parent. A file-scope typedef parents to the compile unit.
+
+; CHECK-SPIRV: [[ext:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-SPIRV-DAG: [[void:%[0-9]+]] = OpTypeVoid
+; CHECK-SPIRV-DAG: [[i32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-SPIRV-DAG: [[str_int:%[0-9]+]] = OpString "int"
+; CHECK-SPIRV-DAG: [[str_myint:%[0-9]+]] = OpString "MyInt"
+; CHECK-SPIRV-DAG: [[c0:%[0-9]+]] = OpConstant [[i32]] 0{{$}}
+; CHECK-SPIRV-DAG: [[c2:%[0-9]+]] = OpConstant [[i32]] 2{{$}}
+; CHECK-SPIRV-DAG: [[ds:%[0-9]+]] = OpExtInst [[void]] [[ext]] DebugSource
+; CHECK-SPIRV-DAG: [[cu:%[0-9]+]] = OpExtInst [[void]] [[ext]] DebugCompilationUnit
+; CHECK-SPIRV-DAG: [[basic_int:%[0-9]+]] = OpExtInst [[void]] [[ext]] DebugTypeBasic [[str_int]]
+; CHECK-SPIRV-DAG: OpExtInst [[void]] [[ext]] DebugTypedef [[str_myint]] [[basic_int]] [[ds]] [[c2]] [[c0]] [[cu]]{{$}}
+
+define spir_func void @test() !dbg !6 {
+entry:
+ ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!1, !2}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_HLSL, file: !3, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !4)
+!1 = !{i32 7, !"Dwarf Version", i32 5}
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = !DIFile(filename: "typedef.hlsl", directory: "/src")
+!4 = !{!5}
+!5 = !DIDerivedType(tag: DW_TAG_typedef, name: "MyInt", file: !3, line: 2, baseType: !7, scope: !3)
+!6 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}
>From 399e9410afd14da9c66fe2b034445736f31ac886 Mon Sep 17 00:00:00 2001
From: Diego Novillo <dnovillo at nvidia.com>
Date: Mon, 27 Jul 2026 11:37:29 -0400
Subject: [PATCH 2/4] fix formatting issues.
---
llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
index 6caf688f16354..9517fdc58e464 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
@@ -932,10 +932,9 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypedef(
ParentReg = *CURegOpt;
}
- return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypedef, VoidTypeReg,
- ExtInstSetReg,
- {NameReg, *BaseRegOpt, SrcReg, LineReg, ColReg, ParentReg},
- MAI);
+ return emitExtInst(
+ SPIRV::NonSemanticExtInst::DebugTypedef, VoidTypeReg, ExtInstSetReg,
+ {NameReg, *BaseRegOpt, SrcReg, LineReg, ColReg, ParentReg}, MAI);
}
void SPIRVNonSemanticDebugHandler::emitNonSemanticDebugStrings(
@@ -987,7 +986,8 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticDebugStrings(
// Cache the name and path OpStrings each DebugTypedef uses.
for (const DIDerivedType *TD : TypedefTypes) {
emitOpStringIfNew(TD->getName(), MAI);
- MCRegister PathReg = emitOpStringIfNew(getDebugFullPath(TD->getFile()), MAI);
+ MCRegister PathReg =
+ emitOpStringIfNew(getDebugFullPath(TD->getFile()), MAI);
if (const DIFile *F = TD->getFile())
ScopeToPathOpStringReg[F] = PathReg;
}
>From f203219b3cfa0efc83b3469f6bd543f39848dc69 Mon Sep 17 00:00:00 2001
From: Diego Novillo <dnovillo at nvidia.com>
Date: Mon, 27 Jul 2026 15:35:30 -0400
Subject: [PATCH 3/4] Address review feedback
---
llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
index 9517fdc58e464..3ae8f2d7d4d1f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
@@ -915,10 +915,12 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypedef(
// DIDerivedType typedefs carry no column, so emit 0.
MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
- // Parent: the enclosing type when the scope is an emitted DIType (a typedef
- // nested in another type), otherwise the compile unit. Fall back to the
- // compile unit rather than dropping the typedef when the scope type is not
- // emitted.
+ // Parent must be a lexical scope. Valid NSDI lexical scopes are
+ // DebugCompilationUnit, DebugFunction, DebugLexicalBlock, or
+ // DebugTypeComposite.
+ //
+ // FIXME: We currently only emit DebugCompilationUnit, so the compile unit is
+ // the only parent available today.
MCRegister ParentReg;
if (const auto *Ty = dyn_cast_or_null<DIType>(TD->getScope()))
if (auto TyRegOpt = lookupOptReg(DebugTypeRegs, Ty))
>From 2ec17825caa492e2069f275c2413a9d17712f474 Mon Sep 17 00:00:00 2001
From: Diego Novillo <dnovillo at nvidia.com>
Date: Wed, 29 Jul 2026 14:47:35 -0400
Subject: [PATCH 4/4] Address review feedback.
---
.../Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp | 5 +----
.../SPIRV/debug-info/debug-typedef-nested-drop.ll | 13 +++++++++++--
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
index 3ae8f2d7d4d1f..f22cc1a38a794 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
@@ -988,10 +988,7 @@ void SPIRVNonSemanticDebugHandler::emitNonSemanticDebugStrings(
// Cache the name and path OpStrings each DebugTypedef uses.
for (const DIDerivedType *TD : TypedefTypes) {
emitOpStringIfNew(TD->getName(), MAI);
- MCRegister PathReg =
- emitOpStringIfNew(getDebugFullPath(TD->getFile()), MAI);
- if (const DIFile *F = TD->getFile())
- ScopeToPathOpStringReg[F] = PathReg;
+ emitAndCacheScopePathOpStringReg(TD->getFile(), MAI);
}
for (const auto &[GV, _] : GlobalVariableDebugInfoMap) {
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-typedef-nested-drop.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-typedef-nested-drop.ll
index df4cf9973d9af..39b9852fc0490 100644
--- a/llvm/test/CodeGen/SPIRV/debug-info/debug-typedef-nested-drop.ll
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-typedef-nested-drop.ll
@@ -7,8 +7,17 @@
; here, for Foo. Emitting typedefs in dependency order, would add a second
; DebugTypedef for Bar (see https://github.com/llvm/llvm-project/issues/211850).
-; CHECK-SPIRV: OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
-; CHECK-SPIRV: DebugTypedef
+; CHECK-SPIRV: [[ext:%[0-9]+]] = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
+; CHECK-SPIRV-DAG: [[void:%[0-9]+]] = OpTypeVoid
+; CHECK-SPIRV-DAG: [[i32:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-SPIRV-DAG: [[str_int:%[0-9]+]] = OpString "int"
+; CHECK-SPIRV-DAG: [[str_foo:%[0-9]+]] = OpString "Foo"
+; CHECK-SPIRV-DAG: [[c0:%[0-9]+]] = OpConstant [[i32]] 0{{$}}
+; CHECK-SPIRV-DAG: [[c2:%[0-9]+]] = OpConstant [[i32]] 2{{$}}
+; CHECK-SPIRV-DAG: [[ds:%[0-9]+]] = OpExtInst [[void]] [[ext]] DebugSource
+; CHECK-SPIRV-DAG: [[cu:%[0-9]+]] = OpExtInst [[void]] [[ext]] DebugCompilationUnit
+; CHECK-SPIRV-DAG: [[basic_int:%[0-9]+]] = OpExtInst [[void]] [[ext]] DebugTypeBasic [[str_int]]
+; CHECK-SPIRV-DAG: OpExtInst [[void]] [[ext]] DebugTypedef [[str_foo]] [[basic_int]] [[ds]] [[c2]] [[c0]] [[cu]]{{$}}
define spir_func void @test() !dbg !6 {
entry:
More information about the llvm-commits
mailing list