[llvm] [SPIRV] LLVM IR DIScope nodes are now emitted after their dependencies. (PR #227361)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 30 01:48:40 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-spir-v
Author: Manuel Carrasco (mgcarrasco)
<details>
<summary>Changes</summary>
LLVM IR `DIScope` nodes are now emitted after their dependencies.
This allows supporting more legal cases:
- A pointer, array, typedef, or function type whose operand is a composite.
- A nested composite member, and a typedef whose base is another typedef.
- A type scoped in a function, lexical block, or namespace, and a function declaration whose parent is a composite.
Cycles are not fully supported so back edges are not allowed. No emission happen for those cases, which may lead to partial emission of composite types.
Emission functions now return an `EmitResult`, which indicates the status of the emission. `Emitted` and `Unsupported` results are cached. `InProgress` is not.
For `struct S { S *p; }`, the edge from `p` back to `S` returns `InProgress`, so member `p` is dropped and `S` is still emitted. `S*` is left uncached, so a later call emits it once `S` exists. Caching that `InProgress` result would completely drop `S*`.
The new core logic to review is in `getOrCreateDebugScope`, `resolveScope`, and the member loop in `emitDebugTypeComposite`. The first emits dependencies before the node and returns `InProgress` on a back edge. The second creates a function, lexical block, or namespace parent on demand. The loop drops a member whose type failed and still emits the composite. The remaining changes only propagate `EmitResult` through the existing emitters.
As future work, for cycles support the most principled solution would be support `SPV_KHR_relaxed_extended_instruction` but that may also require changes in the SPIRV-LLVM Translator. The translator at the moment supports cycles without the extension but emits invalid SPV.
We could also get rid of some of the partitioning logic when the debug info finder is called, but kept that out of scope to avoid introducing too many changes at once.
---
Patch is 70.89 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/227361.diff
12 Files Affected:
- (modified) llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp (+308-276)
- (modified) llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.h (+128-85)
- (modified) llvm/test/CodeGen/SPIRV/debug-info/debug-function-declaration-composite-scope.ll (+9-5)
- (modified) llvm/test/CodeGen/SPIRV/debug-info/debug-function-declaration-skip-type-not-in-debug-type-regs.ll (+10-4)
- (modified) llvm/test/CodeGen/SPIRV/debug-info/debug-lexical-block-namespace-in-block.ll (+8-15)
- (modified) llvm/test/CodeGen/SPIRV/debug-info/debug-type-array-of-composite-drop.ll (+7-9)
- (modified) llvm/test/CodeGen/SPIRV/debug-info/debug-type-composite-nested-drop.ll (+11-13)
- (modified) llvm/test/CodeGen/SPIRV/debug-info/debug-type-function-omit.ll (+4-2)
- (modified) llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer-composite-pointee.ll (+3-2)
- (modified) llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer-to-composite-drop.ll (+6-10)
- (modified) llvm/test/CodeGen/SPIRV/debug-info/debug-typedef-nested-drop.ll (+11-8)
- (modified) llvm/test/CodeGen/SPIRV/debug-info/debug-value-typedef-cycle.ll (+3-3)
``````````diff
diff --git a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
index 05e79d8f8fb98..a01e861f1aa49 100644
--- a/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVNonSemanticDebugHandler.cpp
@@ -398,6 +398,8 @@ void SPIRVNonSemanticDebugHandler::beginModule(Module *M) {
DebugExpressionRegs.clear();
LexicalBlocks.clear();
DebugScopeRegs.clear();
+ ScopesInProgress.clear();
+ FailedScopes.clear();
DebugInlinedAtRegs.clear();
ScopeToPathOpStringReg.clear();
DebugSourceRegByFileStr.clear();
@@ -833,13 +835,160 @@ MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
return Reg;
}
-std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
+// Each node emits its dependencies first. E.g. for `void f() { struct L; }`,
+// node L emits f, then L. For `struct S { S *p; }`, S* is a back edge, so S
+// is emitted without member p.
+SPIRVNonSemanticDebugHandler::EmitResult
+SPIRVNonSemanticDebugHandler::getOrCreateDebugScope(const DIScope *S) {
+ if (!S || FailedScopes.contains(S))
+ return EmitResult::unsupported();
+ if (auto Reg = lookupOptReg(DebugScopeRegs, S))
+ return EmitResult::emitted(*Reg);
+
+ // Mark the node as in progress while its dependencies are resolved/emitted.
+ // This also prevents cycles from happening.
+ if (!ScopesInProgress.insert(S).second)
+ return EmitResult::inProgress();
+ EmitResult R = emitDebugScope(S);
+ ScopesInProgress.erase(S);
+ assert((!R || !GlobalNSDIEnabled) &&
+ "debug type or scope created after module-scope NSDI emission");
+ if (R)
+ DebugScopeRegs[S] = R.Reg;
+ else if (R.Status == EmitStatus::Unsupported)
+ FailedScopes.insert(S);
+ return R;
+}
+
+SPIRVNonSemanticDebugHandler::EmitResult
+SPIRVNonSemanticDebugHandler::emitDebugTypeBasic(
+ const DIBasicType *BT, MCRegister VoidTypeReg, MCRegister I32TypeReg,
+ MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
+ if (!isUInt<32>(BT->getSizeInBits()))
+ return EmitResult::unsupported();
+
+ MCRegister NameReg = getCachedOpStringReg(BT->getName());
+ MCRegister SizeReg = emitOpConstantI32(
+ static_cast<uint32_t>(BT->getSizeInBits()), I32TypeReg, MAI);
+
+ // Map DWARF base type encodings to NSDI encoding codes per
+ // NonSemantic.Shader.DebugInfo.100 specification, section 4.5.
+ unsigned Encoding = 0; // Unspecified
+ switch (BT->getEncoding()) {
+ case dwarf::DW_ATE_address:
+ Encoding = 1;
+ break;
+ case dwarf::DW_ATE_boolean:
+ Encoding = 2;
+ break;
+ case dwarf::DW_ATE_float:
+ Encoding = 3;
+ break;
+ case dwarf::DW_ATE_signed:
+ Encoding = 4;
+ break;
+ case dwarf::DW_ATE_signed_char:
+ Encoding = 5;
+ break;
+ case dwarf::DW_ATE_unsigned:
+ Encoding = 6;
+ break;
+ case dwarf::DW_ATE_unsigned_char:
+ Encoding = 7;
+ break;
+ }
+ MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
+ MCRegister FlagsReg = emitOpConstantI32(0, I32TypeReg, MAI);
+ return EmitResult::emitted(emitExtInst(
+ SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
+ {NameReg, SizeReg, EncodingReg, FlagsReg}, MAI));
+}
+
+SPIRVNonSemanticDebugHandler::EmitResult
+SPIRVNonSemanticDebugHandler::emitDebugScope(const DIScope *S) {
+ assert(CurrentMAI && "emitDebugScope requires CurrentMAI");
+ SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
+ MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
+ MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
+ MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
+
+ if (const auto *BT = dyn_cast<DIBasicType>(S))
+ return emitDebugTypeBasic(BT, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
+ if (const auto *ST = dyn_cast<DISubroutineType>(S))
+ return emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI);
+ if (const auto *CT = dyn_cast<DICompositeType>(S))
+ return emitDebugTypeForCompositeType(CT, VoidTypeReg, I32TypeReg,
+ ExtInstSetReg, MAI);
+ if (const auto *DT = dyn_cast<DIDerivedType>(S))
+ return emitDebugTypeForDerivedType(DT, VoidTypeReg, I32TypeReg,
+ ExtInstSetReg, MAI);
+ if (isa<DILexicalBlock, DINamespace>(S))
+ return emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg, ExtInstSetReg,
+ MAI);
+ if (const auto *SP = dyn_cast<DISubprogram>(S)) {
+ if (SP->isDefinition())
+ return emitDebugFunction(SP, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
+ return emitDebugFunctionDeclaration(SP, VoidTypeReg, I32TypeReg,
+ ExtInstSetReg, MAI);
+ }
+ return EmitResult::unsupported();
+}
+
+SPIRVNonSemanticDebugHandler::EmitResult
+SPIRVNonSemanticDebugHandler::emitDebugTypeForCompositeType(
+ const DICompositeType *CT, MCRegister VoidTypeReg, MCRegister I32TypeReg,
+ MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
+ switch (CT->getTag()) {
+ case dwarf::DW_TAG_array_type:
+ if (CT->isVector())
+ return emitDebugTypeVector(CT, ExtInstSetReg, MAI);
+ return emitDebugTypeArray(CT, ExtInstSetReg, MAI);
+ case dwarf::DW_TAG_structure_type:
+ case dwarf::DW_TAG_class_type:
+ case dwarf::DW_TAG_union_type:
+ return emitDebugTypeComposite(CT, VoidTypeReg, I32TypeReg, ExtInstSetReg,
+ MAI);
+ default:
+ return EmitResult::unsupported();
+ }
+}
+
+SPIRVNonSemanticDebugHandler::EmitResult
+SPIRVNonSemanticDebugHandler::emitDebugTypeForDerivedType(
+ const DIDerivedType *DT, MCRegister VoidTypeReg, MCRegister I32TypeReg,
+ MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
+ switch (DT->getTag()) {
+ case dwarf::DW_TAG_pointer_type:
+ return emitDebugTypePointer(DT, ExtInstSetReg, MAI);
+ case dwarf::DW_TAG_typedef:
+ return emitDebugTypedef(DT, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
+ default:
+ return EmitResult::unsupported();
+ }
+}
+
+SPIRVNonSemanticDebugHandler::EmitResult
+SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
const DIDerivedType *PT, MCRegister ExtInstSetReg,
SPIRV::ModuleAnalysisInfo &MAI) {
// A DWARF address space is required to determine the SPIR-V storage class.
// Skip pointer types that do not carry one.
if (!PT->getDWARFAddressSpace().has_value())
- return std::nullopt;
+ return EmitResult::unsupported();
+
+ MCRegister BaseReg;
+ if (const DIType *BaseTy = PT->getBaseType()) {
+ EmitResult Base = getOrCreateDebugScope(BaseTy);
+ if (!Base)
+ return Base;
+ BaseReg = Base.Reg;
+ } else {
+ // No getBaseType() (typical for void*): use DebugInfoNone as Base Type,
+ // same as SPIRV-LLVM-Translator (see issue #109287 and the DISABLED
+ // spirv-val run in debug-type-pointer.ll). spirv-val may still reject this
+ // encoding; see https://github.com/KhronosGroup/SPIRV-Registry/pull/287.
+ BaseReg = CachedDebugInfoNoneReg;
+ }
MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
@@ -853,26 +1002,12 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
addressSpaceToStorageClass(PT->getDWARFAddressSpace().value(), ST),
I32TypeReg, MAI);
- if (const DIType *BaseTy = PT->getBaseType()) {
- auto BaseIt = DebugScopeRegs.find(BaseTy);
- if (BaseIt != DebugScopeRegs.end())
- return emitExtInst(
- SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
- ExtInstSetReg,
- {BaseIt->second, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
- // Unsupported type, no DebugType* id available.
- return std::nullopt;
- }
- // No getBaseType() (typical for void*): use DebugInfoNone as Base Type,
- // same as SPIRV-LLVM-Translator (see issue #109287 and the DISABLED
- // spirv-val run in debug-type-pointer.ll). spirv-val may still reject this
- // encoding; see https://github.com/KhronosGroup/SPIRV-Registry/pull/287.
- return emitExtInst(
+ return EmitResult::emitted(emitExtInst(
SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg, ExtInstSetReg,
- {CachedDebugInfoNoneReg, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
+ {BaseReg, StorageClassReg, DebugTypePointerFlagsReg}, MAI));
}
-std::optional<MCRegister>
+SPIRVNonSemanticDebugHandler::EmitResult
SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
const DISubroutineType *ST, MCRegister ExtInstSetReg,
SPIRV::ModuleAnalysisInfo &MAI) {
@@ -891,42 +1026,48 @@ SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
} else {
for (unsigned I = 0, E = TA.size(); I != E; ++I) {
bool IsReturnType = (I == 0);
- auto OptReg = mapDISignatureTypeToReg(TA[I], VoidTypeReg, IsReturnType);
+ EmitResult Slot =
+ mapDISignatureTypeToReg(TA[I], VoidTypeReg, IsReturnType);
// No emitted DebugType* id for this slot (e.g., pointer that
// was skipped due missing address space, etc.).
- if (!OptReg)
- return std::nullopt;
- Ops.push_back(*OptReg);
+ if (!Slot)
+ return Slot;
+ Ops.push_back(Slot.Reg);
}
}
- return getOrEmitDebugTypeFunction(Ops, VoidTypeReg, ExtInstSetReg, MAI);
+ return EmitResult::emitted(
+ getOrEmitDebugTypeFunction(Ops, VoidTypeReg, ExtInstSetReg, MAI));
}
// Match SPIRV-LLVM-Translator's selection logic for the Parent operand.
-std::optional<MCRegister> SPIRVNonSemanticDebugHandler::resolveScope(
- const DIScope *Scope, const DICompileUnit *FallbackCU) const {
-
+SPIRVNonSemanticDebugHandler::EmitResult
+SPIRVNonSemanticDebugHandler::resolveScope(const DIScope *Scope,
+ const DICompileUnit *FallbackCU) {
if (isa_and_nonnull<DIType, DILexicalBlock, DINamespace, DISubprogram>(Scope))
- return lookupOptReg(DebugScopeRegs, Scope);
+ return getOrCreateDebugScope(Scope);
// For a file, compile-unit, or absent scope, fall back to a compile unit.
+ auto CUResult = [](std::optional<MCRegister> Reg) {
+ return Reg ? EmitResult::emitted(*Reg) : EmitResult::unsupported();
+ };
if (FallbackCU)
- return lookupOptReg(DebugScopeRegs, FallbackCU);
+ return CUResult(lookupOptReg(DebugScopeRegs, FallbackCU));
if (CompileUnits.empty())
- return std::nullopt;
+ return EmitResult::unsupported();
- return lookupOptReg(DebugScopeRegs, CompileUnits[0].TheCU);
+ return CUResult(lookupOptReg(DebugScopeRegs, CompileUnits[0].TheCU));
}
-std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLexicalBlock(
+SPIRVNonSemanticDebugHandler::EmitResult
+SPIRVNonSemanticDebugHandler::emitDebugLexicalBlock(
const DIScope *S, MCRegister VoidTypeReg, MCRegister I32TypeReg,
MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
assert((isa<DILexicalBlock, DINamespace>(S)) &&
"S must be a DILexicalBlock or DINamespace in emitDebugLexicalBlock");
- auto ParentRegOpt = resolveScope(S->getScope());
- if (!ParentRegOpt)
- return std::nullopt;
+ EmitResult Parent = resolveScope(S->getScope());
+ if (!Parent)
+ return Parent;
MCRegister FileStrReg = getCachedScopePathOpStringReg(
S->getFile(), /*UseEmptyPathIfNullScope=*/true);
@@ -939,18 +1080,19 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLexicalBlock(
I32TypeReg, MAI);
MCRegister ColReg = emitOpConstantI32(
static_cast<uint32_t>(LB->getColumn()), I32TypeReg, MAI);
- Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt};
+ Ops = {SrcReg, LineReg, ColReg, Parent.Reg};
} else {
const auto *NS = cast<DINamespace>(S);
// DINamespace carries no line/column info.
MCRegister LineReg = emitOpConstantI32(0, I32TypeReg, MAI);
MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
MCRegister NameReg = getCachedOpStringReg(NS->getName());
- Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt, NameReg};
+ Ops = {SrcReg, LineReg, ColReg, Parent.Reg, NameReg};
}
- return emitExtInst(SPIRV::NonSemanticExtInst::DebugLexicalBlock, VoidTypeReg,
- ExtInstSetReg, Ops, MAI);
+ return EmitResult::emitted(
+ emitExtInst(SPIRV::NonSemanticExtInst::DebugLexicalBlock, VoidTypeReg,
+ ExtInstSetReg, Ops, MAI));
}
MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugInlinedAt(
@@ -961,14 +1103,14 @@ MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugInlinedAt(
if (MCRegister Cached = DebugInlinedAtRegs.lookup(IA))
return Cached;
- auto ScopeRegOpt = resolveScope(IA->getScope());
- if (!ScopeRegOpt)
+ EmitResult Scope = resolveScope(IA->getScope());
+ if (!Scope)
return MCRegister();
MCRegister LineReg =
emitOpConstantI32(static_cast<uint32_t>(IA->getLine()), I32TypeReg, MAI);
- SmallVector<MCRegister, 3> Ops{LineReg, *ScopeRegOpt};
+ SmallVector<MCRegister, 3> Ops{LineReg, Scope.Reg};
// Recurse before building this instruction's operands so an outer
// inlined-at link is always available.
if (const DILocation *Outer = IA->getInlinedAt()) {
@@ -985,7 +1127,7 @@ MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugInlinedAt(
return Reg;
}
-std::optional<MCRegister>
+SPIRVNonSemanticDebugHandler::EmitResult
SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
@@ -994,18 +1136,13 @@ SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
"SP must not be a definition in emitDebugFunctionDeclaration");
// The IR verifier already enforces that this cannot be null.
- const DISubroutineType *ST = SP->getType();
-
- auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
- if (!FnTyRegOpt)
- return std::nullopt;
- MCRegister FnTyReg = *FnTyRegOpt;
-
- auto ParentRegOpt = resolveScope(SP->getScope(), SP->getUnit());
- if (!ParentRegOpt)
- return std::nullopt;
+ EmitResult FnTy = getOrCreateDebugScope(SP->getType());
+ if (!FnTy)
+ return FnTy;
- MCRegister ParentReg = *ParentRegOpt;
+ EmitResult Parent = resolveScope(SP->getScope(), SP->getUnit());
+ if (!Parent)
+ return Parent;
MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
@@ -1024,27 +1161,28 @@ SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
FlagsVal &= ~NSDIFlagIsDefinition;
MCRegister FlagsReg = emitOpConstantI32(FlagsVal, I32TypeReg, MAI);
- return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
- VoidTypeReg, ExtInstSetReg,
- {NameReg, FnTyReg, SrcReg, LineReg, ColReg, ParentReg,
- LinkageReg, FlagsReg},
- MAI);
+ return EmitResult::emitted(
+ emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
+ VoidTypeReg, ExtInstSetReg,
+ {NameReg, FnTy.Reg, SrcReg, LineReg, ColReg, Parent.Reg,
+ LinkageReg, FlagsReg},
+ MAI));
}
-std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugFunction(
+SPIRVNonSemanticDebugHandler::EmitResult
+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(DebugScopeRegs, ST);
- if (!FnTyRegOpt)
- return std::nullopt;
+ EmitResult FnTy = getOrCreateDebugScope(SP->getType());
+ if (!FnTy)
+ return FnTy;
- auto ParentRegOpt = resolveScope(SP->getScope(), SP->getUnit());
- if (!ParentRegOpt)
- return std::nullopt;
+ EmitResult Parent = resolveScope(SP->getScope(), SP->getUnit());
+ if (!Parent)
+ return Parent;
MCRegister NameReg = getCachedOpStringReg(SP->getName());
MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
@@ -1061,29 +1199,34 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugFunction(
MCRegister ScopeLineReg = emitOpConstantI32(
static_cast<uint32_t>(SP->getScopeLine()), I32TypeReg, MAI);
- SmallVector<MCRegister, 10> Ops = {NameReg, *FnTyRegOpt, SrcReg,
- LineReg, ColReg, *ParentRegOpt,
- LinkageReg, FlagsReg, ScopeLineReg};
+ SmallVector<MCRegister, 10> Ops = {NameReg, FnTy.Reg, SrcReg,
+ LineReg, ColReg, Parent.Reg,
+ LinkageReg, FlagsReg, ScopeLineReg};
+ // TODO: Create on demand once beginModule collects missing getDeclaration()
+ // cases.
if (const DISubprogram *Decl = SP->getDeclaration()) {
if (auto DeclRegOpt = lookupOptReg(DebugScopeRegs, Decl))
Ops.push_back(*DeclRegOpt);
}
- return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunction, VoidTypeReg,
- ExtInstSetReg, Ops, MAI);
+ return EmitResult::emitted(
+ emitExtInst(SPIRV::NonSemanticExtInst::DebugFunction, VoidTypeReg,
+ ExtInstSetReg, Ops, MAI));
}
-std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
- const DIType *Ty, MCRegister VoidTypeReg, bool ReturnType) {
+SPIRVNonSemanticDebugHandler::EmitResult
+SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(const DIType *Ty,
+ MCRegister VoidTypeReg,
+ bool ReturnType) {
if (!Ty) {
if (ReturnType)
- return VoidTypeReg;
+ return EmitResult::emitted(VoidTypeReg);
assert(CachedDebugInfoNoneReg.isValid() &&
"DebugInfoNone must be emitted before DISubroutineType operands");
- return CachedDebugInfoNoneReg;
+ return EmitResult::emitted(CachedDebugInfoNoneReg);
}
- return lookupOptReg(DebugScopeRegs, Ty);
+ return getOrCreateDebugScope(Ty);
}
// NonSemantic.Shader.DebugInfo.100 debug operation encodings
@@ -1200,11 +1343,11 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugGlobalVariable(
SPIRV::ModuleAnalysisInfo &MAI) {
assert(GV && "GV must not be null in emitDebugGlobalVariable");
- auto ParentRegOpt = resolveScope(GV->getScope());
- if (!ParentRegOpt)
+ EmitResult Parent = resolveScope(GV->getScope());
+ if (!Parent)
return std::nullopt;
- MCRegister ParentReg = *ParentRegOpt;
+ MCRegister ParentReg = Parent.Reg;
// TyReg: DebugInfoNone when GV has no DI type (as done in
// SPIRV-LLVM-Translator). Declarations (isDefinition: false) can have null
@@ -1273,8 +1416,8 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLocalVariable(
MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
assert(LV && "LV must not be null in emitDebugLocalVariable");
- auto ParentRegOpt = resolveScope(LV->getScope());
- if (!ParentRegOpt)
+ EmitResult Parent = resolveScope(LV->getScope());
+ if (!Parent)
return std::nullopt;
MCRegister TyReg = CachedDebugInfoNoneReg;
@@ -1296,8 +1439,8 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLocalVariable(
MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(LV), I32TypeReg, MAI);
- SmallVector<MCRegister, 8> Ops = {NameReg, TyReg, SrcReg, LineReg,
- ColReg, *ParentRegOpt, FlagsReg};
+ SmallVector<MCRegister, 8> Ops = {NameReg, TyReg, SrcReg, LineReg,
+ ColReg, Parent.Reg, FlagsReg};
if (unsigned Arg = LV->getArg())
Ops.push_back(emitOpConstantI32(Arg, I32TypeReg, MAI));
@@ -1305,48 +1448,52 @@ std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLocalVariable(
ExtInstSetReg, Ops, MAI);
}
-std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
+SPIRVNonSemanticDebugHandler::EmitResult
+SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
const DICompositeType *VT, MCR...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/227361
More information about the llvm-commits
mailing list