LLVM 24.0.0git
SPIRVNonSemanticDebugHandler.cpp
Go to the documentation of this file.
1//===-- SPIRVNonSemanticDebugHandler.cpp - NSDI AsmPrinter handler -*- C++
2//-*-===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
12#include "SPIRVSubtarget.h"
13#include "SPIRVUtils.h"
14#include "llvm/ADT/SetVector.h"
16#include "llvm/ADT/Twine.h"
21#include "llvm/IR/DebugInfo.h"
27#include "llvm/IR/Module.h"
28#include "llvm/MC/MCInst.h"
29#include "llvm/MC/MCStreamer.h"
31#include "llvm/Support/Path.h"
32#include <cassert>
33
34using namespace llvm;
35
36namespace {
37
38/// Look up \p Key in a register map and return its value, or std::nullopt when
39/// the key is absent.
40template <typename MapT>
41static std::optional<MCRegister> lookupOptReg(const MapT &Map,
42 typename MapT::key_type Key) {
43 auto It = Map.find(Key);
44 if (It == Map.end())
45 return std::nullopt;
46 assert(It->second.isValid() && "invalid register stored in map");
47 return It->second;
48}
49
50/// Partition \p Ty into \p BasicTypes, \p PointerTypes, \p SubroutineTypes,
51/// \p VectorTypes, \p ArrayTypes, \p CompositeTypes, and \p TypedefTypes for
52/// NSDI emission. Used when iterating DebugInfoFinder.types(); each DI node is
53/// seen once, so no recursion into pointer bases. Other composites and the
54/// remaining derived kinds are ignored because they are not yet supported.
55/// Only types that are supported (later used) are partitioned.
56static void
57partitionTypes(const DIType *Ty, SmallVector<const DIBasicType *> &BasicTypes,
64 if (const auto *BT = dyn_cast<DIBasicType>(Ty)) {
65 BasicTypes.push_back(BT);
66 return;
67 }
68 if (const auto *ST = dyn_cast<DISubroutineType>(Ty)) {
69 SubroutineTypes.push_back(ST);
70 return;
71 }
72 if (const auto *CT = dyn_cast<DICompositeType>(Ty)) {
73 if (CT->getTag() == dwarf::DW_TAG_array_type) {
74 // A vector is an array with DINode::FlagVector. A plain array is the
75 // same tag without it. A matrix is also lowered to a DW_TAG_array_type
76 // (two subranges), so it is indistinguishable from a 2D array here and
77 // is emitted as a DebugTypeArray.
78 //
79 // FIXME: Emitting a matrix as a DebugTypeArray is valid but loses the
80 // matrix shape. DWARF has no matrix tag, so distinguishing a matrix needs
81 // a new DINode flag analogous to FlagVector, set on the array, plus a way
82 // to carry column-major vs row-major traits. Array-of-vectors alone would
83 // not disambiguate a matrix from a genuine array of vectors. Once the
84 // frontend marks matrices, route them to a DebugTypeMatrix path here.
85 if (CT->isVector())
86 VectorTypes.push_back(CT);
87 else
88 ArrayTypes.push_back(CT);
89 } else if (CT->getTag() == dwarf::DW_TAG_structure_type ||
90 CT->getTag() == dwarf::DW_TAG_class_type ||
91 CT->getTag() == dwarf::DW_TAG_union_type) {
92 CompositeTypes.push_back(CT);
93 }
94 return;
95 }
96 const auto *DT = dyn_cast<DIDerivedType>(Ty);
97 if (DT && DT->getTag() == dwarf::DW_TAG_pointer_type)
98 PointerTypes.push_back(DT);
99 else if (DT && DT->getTag() == dwarf::DW_TAG_typedef)
100 TypedefTypes.push_back(DT);
101}
102
103enum : uint32_t {
104 NSDIFlagIsProtected = 1u << 0,
105 NSDIFlagIsPrivate = 1u << 1,
106 NSDIFlagIsPublic = NSDIFlagIsPrivate | NSDIFlagIsProtected,
107 NSDIFlagIsLocal = 1u << 2,
108 NSDIFlagIsDefinition = 1u << 3,
109 NSDIFlagFwdDecl = 1u << 4,
110 NSDIFlagArtificial = 1u << 5,
111 NSDIFlagExplicit = 1u << 6,
112 NSDIFlagPrototyped = 1u << 7,
113 NSDIFlagObjectPointer = 1u << 8,
114 NSDIFlagStaticMember = 1u << 9,
115 NSDIFlagIndirectVariable = 1u << 10,
116 NSDIFlagLValueReference = 1u << 11,
117 NSDIFlagRValueReference = 1u << 12,
118 NSDIFlagIsOptimized = 1u << 13,
119 NSDIFlagIsEnumClass = 1u << 14,
120 NSDIFlagTypePassByValue = 1u << 15,
121 NSDIFlagTypePassByReference = 1u << 16,
122 NSDIFlagUnknownPhysicalLayout = 1u << 17,
123};
124
125static uint32_t mapDIFlagsToNonSemantic(DINode::DIFlags DFlags) {
126 uint32_t Flags = 0;
127 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPublic)
128 Flags |= NSDIFlagIsPublic;
129 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagProtected)
130 Flags |= NSDIFlagIsProtected;
131 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPrivate)
132 Flags |= NSDIFlagIsPrivate;
133 if (DFlags & DINode::FlagFwdDecl)
134 Flags |= NSDIFlagFwdDecl;
135 if (DFlags & DINode::FlagArtificial)
136 Flags |= NSDIFlagArtificial;
137 if (DFlags & DINode::FlagExplicit)
138 Flags |= NSDIFlagExplicit;
139 if (DFlags & DINode::FlagPrototyped)
140 Flags |= NSDIFlagPrototyped;
141 if (DFlags & DINode::FlagObjectPointer)
142 Flags |= NSDIFlagObjectPointer;
143 if (DFlags & DINode::FlagStaticMember)
144 Flags |= NSDIFlagStaticMember;
145 if (DFlags & DINode::FlagLValueReference)
146 Flags |= NSDIFlagLValueReference;
147 if (DFlags & DINode::FlagRValueReference)
148 Flags |= NSDIFlagRValueReference;
149 if (DFlags & DINode::FlagTypePassByValue)
150 Flags |= NSDIFlagTypePassByValue;
151 if (DFlags & DINode::FlagTypePassByReference)
152 Flags |= NSDIFlagTypePassByReference;
153 if (DFlags & DINode::FlagEnumClass)
154 Flags |= NSDIFlagIsEnumClass;
155 return Flags;
156}
157
158static uint32_t transDebugFlags(const DINode *DN) {
159 uint32_t Flags = 0;
160 if (const auto *GV = dyn_cast<DIGlobalVariable>(DN)) {
161 if (GV->isLocalToUnit())
162 Flags |= NSDIFlagIsLocal;
163 if (GV->isDefinition())
164 Flags |= NSDIFlagIsDefinition;
165 }
166 if (const auto *SP = dyn_cast<DISubprogram>(DN)) {
167 if (SP->isLocalToUnit())
168 Flags |= NSDIFlagIsLocal;
169 if (SP->isOptimized())
170 Flags |= NSDIFlagIsOptimized;
171 if (SP->isDefinition())
172 Flags |= NSDIFlagIsDefinition;
173 Flags |= mapDIFlagsToNonSemantic(SP->getFlags());
174 }
175 if (DN->getTag() == dwarf::DW_TAG_reference_type)
176 Flags |= NSDIFlagLValueReference;
177 if (DN->getTag() == dwarf::DW_TAG_rvalue_reference_type)
178 Flags |= NSDIFlagRValueReference;
179 if (const auto *Ty = dyn_cast<DIType>(DN))
180 Flags |= mapDIFlagsToNonSemantic(Ty->getFlags());
181 if (const auto *LV = dyn_cast<DILocalVariable>(DN))
182 Flags |= mapDIFlagsToNonSemantic(LV->getFlags());
183 return Flags;
184}
185
186// Map a DWARF composite tag to a NonSemantic.Shader.DebugInfo Composite Type
187// value: Class 0, Structure 1, Union 2.
188static uint32_t mapCompositeTypeTag(unsigned Tag) {
189 switch (Tag) {
190 case dwarf::DW_TAG_class_type:
191 return 0;
192 case dwarf::DW_TAG_structure_type:
193 return 1;
194 case dwarf::DW_TAG_union_type:
195 return 2;
196 default:
197 reportFatalInternalError("unexpected DWARF composite tag " + Twine(Tag) +
198 ". Expecting 0, 1 or 2");
199 }
200}
201
202static const MachineInstr *
203findLastFunctionOpVariableDeclaration(const MachineFunction &MF,
205
206 // We iterate over the instructions to find the last OpVariable instruction if
207 // any. The following SPIRV rule is used to terminate the traversal earlier:
208 // SPIR-V 2.16.1, Function Structure: "All OpVariable instructions in a
209 // function must be in the first block in the function. These instructions,
210 // together with any intermixed OpLine and OpNoLine instructions, must be the
211 // first instructions in that block."
212 const MachineInstr *LastOpVariable = nullptr;
213 bool SeenOpVariable = false;
214 for (const MachineInstr &MI : MF.front()) {
215 if (MI.getOpcode() == SPIRV::OpVariable) {
216 SeenOpVariable = true;
217 if (!MAI.getSkipEmission(&MI))
218 LastOpVariable = &MI;
219 continue;
220 }
221
222 bool CanInterleaveWithOpVariable =
223 MI.getOpcode() == SPIRV::OpLine || MI.getOpcode() == SPIRV::OpNoLine;
224 if (SeenOpVariable && !CanInterleaveWithOpVariable &&
225 !MAI.getSkipEmission(&MI))
226 break;
227 }
228 return LastOpVariable;
229}
230
231} // namespace
232
235
236// Map DWARF source language codes to NonSemantic.Shader.DebugInfo.100 source
237// language codes. Values are from the SourceLanguage enum in the
238// NonSemantic.Shader.DebugInfo.100 specification, section 4.3.
239unsigned SPIRVNonSemanticDebugHandler::toNSDISrcLang(unsigned DwarfSrcLang) {
240 switch (DwarfSrcLang) {
241 case dwarf::DW_LANG_OpenCL:
242 return 3; // OpenCL_C
243 case dwarf::DW_LANG_OpenCL_CPP:
244 return 4; // OpenCL_CPP
245 case dwarf::DW_LANG_CPP_for_OpenCL:
246 return 6; // CPP_for_OpenCL
247 case dwarf::DW_LANG_GLSL:
248 return 2; // GLSL
249 case dwarf::DW_LANG_HLSL:
250 return 5; // HLSL
251 case dwarf::DW_LANG_SYCL:
252 return 7; // SYCL
253 case dwarf::DW_LANG_Zig:
254 return 12; // Zig
255 default:
256 return 0; // Unknown
257 }
258}
259
260// Collect distinct DILocations from LLVM IR. DebugLine pre-emission and MIR
261// lookups assume every machine-instruction debug location already appeared
262// here; a codegen-only location would not be collected and emission will be
263// skipped.
266 for (const Function &F : M) {
267 if (!F.getSubprogram())
268 continue;
269 for (const Instruction &I : instructions(F)) {
270 if (const DILocation *DL = I.getDebugLoc().get())
271 Out.insert(DL);
272 for (DbgRecord &DR : I.getDbgRecordRange())
273 if (const DILocation *DL = DR.getDebugLoc().get())
274 Out.insert(DL);
275 }
276 }
277}
278
279// Insert \p S and its enclosing DILexicalBlock/DINamespace chain into \p Out,
280// parent before child, so single-pass emission never needs a forward
281// reference for the Parent operand.
284 // Walk up child-first, then insert in reverse to get parents in first.
286 while (S && !Out.contains(S) && isa<DILexicalBlock, DINamespace>(S)) {
287 Chain.push_back(S);
288 S = S->getScope();
289 }
290 Out.insert(Chain.rbegin(), Chain.rend());
291}
292
294 // The base class sets Asm = nullptr when the module has no compile units,
295 // and initializes lexical scope tracking otherwise.
297
298 if (!Asm)
299 return;
300
301 CompileUnits.clear();
302 BasicTypes.clear();
303 PointerTypes.clear();
304 SubroutineTypes.clear();
305 VectorTypes.clear();
306 ArrayTypes.clear();
307 CompositeTypes.clear();
308 TypedefTypes.clear();
309 SubprogramDeclarations.clear();
310 SubprogramDefinitions.clear();
311 UniqueDebugLocations.clear();
312 GlobalVariableDebugInfoMap.clear();
313 LexicalBlocks.clear();
314 DebugScopeRegs.clear();
315 ScopeToPathOpStringReg.clear();
316 DebugSourceRegByFileStr.clear();
317 OpStringContentCache.clear();
318 I32ConstantCache.clear();
319 DebugTypeFunctionCache.clear();
320 GlobalDIEmitted = false;
321 GlobalNSDIEnabled = false;
322 CurrentMAI = nullptr;
323#ifndef NDEBUG
324 NonSemanticOpStringsSectionEmitted = false;
325#endif
326 CachedDebugInfoNoneReg = MCRegister();
327 CachedEmptyStringReg = MCRegister();
328 CachedOpTypeVoidReg = MCRegister();
329 CachedOpTypeInt32Reg = MCRegister();
330
331 // Collect compile-unit info: file paths and source languages.
332 for (const DICompileUnit *CU : M->debug_compile_units()) {
333 const DIFile *File = CU->getFile();
334 CompileUnitInfo Info;
335 Info.TheCU = CU;
336 if (sys::path::is_absolute(File->getFilename()))
337 Info.FilePath = File->getFilename();
338 else
339 sys::path::append(Info.FilePath, File->getDirectory(),
340 File->getFilename());
341 // getName() returns the language code regardless of whether the name is
342 // versioned. getUnversionedName() would assert on versioned names.
343 Info.SpirvSourceLanguage = toNSDISrcLang(CU->getSourceLanguage().getName());
344 CompileUnits.push_back(std::move(Info));
345 }
346
347 // Collect DWARF version from module flags. For CodeView modules there is no
348 // "Dwarf Version" flag; DwarfVersion remains 0, which is the correct value
349 // for the DebugCompilationUnit DWARF Version operand in that case.
350 if (const NamedMDNode *Flags = M->getNamedMetadata("llvm.module.flags")) {
351 for (const auto *Op : Flags->operands()) {
352 const MDOperand &NameOp = Op->getOperand(1);
353 if (NameOp.equalsStr("Dwarf Version"))
354 DwarfVersion =
356 cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
357 ->getSExtValue();
358 }
359 }
360
361 // Find all debug info types that may be referenced by NSDI instructions.
362 DebugInfoFinder Finder;
363 Finder.processModule(*M);
364 llvm::for_each(Finder.types(), [&](DIType *Ty) {
365 partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes, VectorTypes,
366 ArrayTypes, CompositeTypes, TypedefTypes);
367 });
368
369 for (const DISubprogram *SP : Finder.subprograms()) {
370 if (SP->isDefinition())
371 SubprogramDefinitions.push_back(SP);
372 else
373 SubprogramDeclarations.push_back(SP);
374 }
375
376 // Walk LLVM globals to map each DIGlobalVariable to its llvm::GlobalVariable.
378 for (const GlobalVariable &G : M->globals()) {
380 G.getDebugInfo(GVEs);
381 for (DIGlobalVariableExpression *GVE : GVEs) {
382 if (const DIGlobalVariable *GV = GVE->getVariable()) {
383 DIGVToLLVMGV.try_emplace(GV, &G);
384 }
385 }
386 }
387
388 for (const DIGlobalVariableExpression *GVE : Finder.global_variables()) {
389 const DIGlobalVariable *GV = GVE->getVariable();
390 const DIExpression *Expr = GVE->getExpression();
391 GlobalVariableDebugInfoMap.try_emplace(
392 GV, GlobalVariableDebugInfo{Expr, DIGVToLLVMGV.lookup(GV)});
393 }
394
395 collectUniqueDebugLocations(*M, UniqueDebugLocations);
396
397 // DILexicalBlock and DINamespace scopes are lowered to DebugLexicalBlock.
398 // Collect them in parent-before-child order so they can be later emitted in a
399 // single pass.
400 for (const DIScope *S : Finder.scopes())
401 collectLexicalBlockChain(S, LexicalBlocks);
402}
403
406 if (CompileUnits.empty())
407 return;
408 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_non_semantic_info))
409 return;
410
411 // Add the extension to requirements so OpExtension is output.
412 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
413
414 // Add the NonSemantic.Shader.DebugInfo.100 entry to ExtInstSetMap so that
415 // outputOpExtInstImports() emits the OpExtInstImport instruction. Allocate a
416 // fresh result ID for it now; the same ID is used in emitExtInst() operands.
417 if (!MAI.ExtInstSetMap.count(NSSet))
418 MAI.ExtInstSetMap[NSSet] = MAI.getNextIDRegister();
419}
420
421void SPIRVNonSemanticDebugHandler::emitMCInst(MCInst &Inst) {
422 Asm->OutStreamer->emitInstruction(Inst, Asm->getSubtargetInfo());
423}
424
426SPIRVNonSemanticDebugHandler::emitOpString(StringRef S,
429 MCInst Inst;
430 Inst.setOpcode(SPIRV::OpString);
432 addStringImm(S, Inst);
433 emitMCInst(Inst);
434 return Reg;
435}
436
437MCRegister SPIRVNonSemanticDebugHandler::emitOpStringIfNew(
439#ifndef NDEBUG
440 assert(!NonSemanticOpStringsSectionEmitted &&
441 "emitOpStringIfNew is only valid while emitting SPIR-V section 7");
442#endif
443 auto [It, Inserted] = OpStringContentCache.try_emplace(S, MCRegister());
444 if (Inserted)
445 It->second = emitOpString(S, MAI);
446
447 return It->second;
448}
449
450MCRegister SPIRVNonSemanticDebugHandler::getCachedOpStringReg(StringRef S) {
451#ifndef NDEBUG
452 assert(NonSemanticOpStringsSectionEmitted &&
453 "getCachedOpStringReg requires emitNonSemanticDebugStrings() first");
454#endif
455 auto It = OpStringContentCache.find(S);
456 assert(It != OpStringContentCache.end() &&
457 "NSDI OpString missing from cache; emitNonSemanticDebugStrings must "
458 "cache every string used in section 10");
459 return It->second;
460}
461
462MCRegister SPIRVNonSemanticDebugHandler::emitAndCacheScopePathOpStringReg(
463 const DIScope *Scope, SPIRV::ModuleAnalysisInfo &MAI) {
464 auto [It, Inserted] = ScopeToPathOpStringReg.try_emplace(Scope, MCRegister());
465 if (Inserted)
466 It->second = emitOpStringIfNew(getDebugFullPath(Scope), MAI);
467 return It->second;
468}
469
470MCRegister SPIRVNonSemanticDebugHandler::getCachedScopePathOpStringReg(
471 const DIScope *Scope, bool UseEmptyPathIfNullScope) {
472 if (!Scope) {
473 assert(UseEmptyPathIfNullScope &&
474 "null scope path lookup requires UseEmptyPathIfNullScope");
475 assert(CachedEmptyStringReg.isValid() &&
476 "empty path OpString must be cached in emitNonSemanticDebugStrings");
477 return CachedEmptyStringReg;
478 }
479 auto It = ScopeToPathOpStringReg.find(Scope);
480 assert(It != ScopeToPathOpStringReg.end() &&
481 "path OpString must be cached in emitNonSemanticDebugStrings");
482 MCRegister FileStrReg = It->second;
483 assert(FileStrReg.isValid() && "path OpString id must be valid once cached");
484 return FileStrReg;
485}
486
487MCRegister SPIRVNonSemanticDebugHandler::emitOpConstantI32(
488 uint32_t Value, MCRegister I32TypeReg, SPIRV::ModuleAnalysisInfo &MAI) {
489 auto [It, Inserted] = I32ConstantCache.try_emplace(Value);
490 if (!Inserted)
491 return It->second;
492
493 MCRegister Reg = MAI.getNextIDRegister();
494 It->second = Reg;
495 MCInst Inst;
496 Inst.setOpcode(SPIRV::OpConstantI);
498 Inst.addOperand(MCOperand::createReg(I32TypeReg));
499 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Value)));
500 emitMCInst(Inst);
501 return Reg;
502}
503
504MCRegister SPIRVNonSemanticDebugHandler::emitExtInst(
505 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
506 MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
508 MCRegister Reg = MAI.getNextIDRegister();
509 MCInst Inst;
510 Inst.setOpcode(SPIRV::OpExtInst);
512 Inst.addOperand(MCOperand::createReg(VoidTypeReg));
513 Inst.addOperand(MCOperand::createReg(ExtInstSetReg));
514 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Opcode)));
515 for (MCRegister R : Operands)
517 emitMCInst(Inst);
518 return Reg;
519}
520
521MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugTypeFunction(
522 ArrayRef<MCRegister> Ops, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
524 auto [It, Inserted] =
525 DebugTypeFunctionCache.try_emplace(SmallVector<MCRegister, 8>(Ops));
526 if (!Inserted)
527 return It->second;
528
529 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeFunction,
530 VoidTypeReg, ExtInstSetReg, Ops, MAI);
531 It->second = Reg;
532 return Reg;
533}
534
535MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeVoidReg(
537 if (!CachedOpTypeVoidReg.isValid())
538 CachedOpTypeVoidReg = findOrEmitOpTypeVoid(MAI);
539 return CachedOpTypeVoidReg;
540}
541
542MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeInt32Reg(
544 if (!CachedOpTypeInt32Reg.isValid())
545 CachedOpTypeInt32Reg = findOrEmitOpTypeInt32(MAI);
546 return CachedOpTypeInt32Reg;
547}
548
549MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
551 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
552 if (MI->getOpcode() == SPIRV::OpTypeVoid)
553 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
554 }
555 MCRegister Reg = MAI.getNextIDRegister();
556 MCInst Inst;
557 Inst.setOpcode(SPIRV::OpTypeVoid);
559 emitMCInst(Inst);
560 return Reg;
561}
562
563MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
565 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
566 if (MI->getOpcode() == SPIRV::OpTypeInt &&
567 MI->getOperand(1).getImm() == 32 && MI->getOperand(2).getImm() == 0)
568 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
569 }
570 MCRegister Reg = MAI.getNextIDRegister();
571 MCInst Inst;
572 Inst.setOpcode(SPIRV::OpTypeInt);
574 Inst.addOperand(MCOperand::createImm(32)); // width
575 Inst.addOperand(MCOperand::createImm(0)); // signedness (unsigned)
576 emitMCInst(Inst);
577 return Reg;
578}
579
580std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
581 const DIDerivedType *PT, MCRegister ExtInstSetReg,
583 // A DWARF address space is required to determine the SPIR-V storage class.
584 // Skip pointer types that do not carry one.
585 if (!PT->getDWARFAddressSpace().has_value())
586 return std::nullopt;
587
588 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
589 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
590 MCRegister DebugTypePointerFlagsReg =
591 emitOpConstantI32(transDebugFlags(PT), I32TypeReg, MAI);
592
593 // For SPIR-V targets, Clang sets DwarfAddressSpace to the LLVM IR address
594 // space, which addressSpaceToStorageClass expects.
595 const auto &ST = static_cast<const SPIRVSubtarget &>(Asm->getSubtargetInfo());
596 MCRegister StorageClassReg = emitOpConstantI32(
597 addressSpaceToStorageClass(PT->getDWARFAddressSpace().value(), ST),
598 I32TypeReg, MAI);
599
600 if (const DIType *BaseTy = PT->getBaseType()) {
601 auto BaseIt = DebugScopeRegs.find(BaseTy);
602 if (BaseIt != DebugScopeRegs.end())
603 return emitExtInst(
604 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
605 ExtInstSetReg,
606 {BaseIt->second, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
607 // Unsupported type, no DebugType* id available.
608 return std::nullopt;
609 }
610 // No getBaseType() (typical for void*): use DebugInfoNone as Base Type,
611 // same as SPIRV-LLVM-Translator (see issue #109287 and the DISABLED
612 // spirv-val run in debug-type-pointer.ll). spirv-val may still reject this
613 // encoding; see https://github.com/KhronosGroup/SPIRV-Registry/pull/287.
614 return emitExtInst(
615 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg, ExtInstSetReg,
616 {CachedDebugInfoNoneReg, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
617}
618
619std::optional<MCRegister>
620SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
621 const DISubroutineType *ST, MCRegister ExtInstSetReg,
623 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
624 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
625 MCRegister DebugTypeFunctionFlagsReg =
626 emitOpConstantI32(transDebugFlags(ST), I32TypeReg, MAI);
627 DITypeArray TA = ST->getTypeArray();
629 Ops.push_back(DebugTypeFunctionFlagsReg);
630 // Empty DI type tuple: no explicit return or parameter slots (hand-written IR
631 // may use !{}). Emit void-only prototype. Same as SPIRV-LLVM-Translator when
632 // DISubroutineType::getTypeArray() has zero elements.
633 if (TA.empty()) {
634 Ops.push_back(VoidTypeReg);
635 } else {
636 for (unsigned I = 0, E = TA.size(); I != E; ++I) {
637 bool IsReturnType = (I == 0);
638 auto OptReg = mapDISignatureTypeToReg(TA[I], VoidTypeReg, IsReturnType);
639 // No emitted DebugType* id for this slot (e.g., pointer that
640 // was skipped due missing address space, etc.).
641 if (!OptReg)
642 return std::nullopt;
643 Ops.push_back(*OptReg);
644 }
645 }
646 return getOrEmitDebugTypeFunction(Ops, VoidTypeReg, ExtInstSetReg, MAI);
647}
648
649// Match SPIRV-LLVM-Translator's selection logic for the Parent operand.
650std::optional<MCRegister> SPIRVNonSemanticDebugHandler::resolveScope(
651 const DIScope *Scope, const DICompileUnit *FallbackCU) const {
652
654 return lookupOptReg(DebugScopeRegs, Scope);
655
656 // For a file, compile-unit, or absent scope, fall back to a compile unit.
657 if (FallbackCU)
658 return lookupOptReg(DebugScopeRegs, FallbackCU);
659
660 if (CompileUnits.empty())
661 return std::nullopt;
662
663 return lookupOptReg(DebugScopeRegs, CompileUnits[0].TheCU);
664}
665
666std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLexicalBlock(
667 const DIScope *S, MCRegister VoidTypeReg, MCRegister I32TypeReg,
668 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
670 "S must be a DILexicalBlock or DINamespace in emitDebugLexicalBlock");
671 auto ParentRegOpt = resolveScope(S->getScope());
672 if (!ParentRegOpt)
673 return std::nullopt;
674
675 MCRegister FileStrReg = getCachedScopePathOpStringReg(
676 S->getFile(), /*UseEmptyPathIfNullScope=*/true);
677 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
678 ExtInstSetReg, MAI);
679
681 if (const auto *LB = dyn_cast<DILexicalBlock>(S)) {
682 MCRegister LineReg = emitOpConstantI32(static_cast<uint32_t>(LB->getLine()),
683 I32TypeReg, MAI);
684 MCRegister ColReg = emitOpConstantI32(
685 static_cast<uint32_t>(LB->getColumn()), I32TypeReg, MAI);
686 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt};
687 } else {
688 const auto *NS = cast<DINamespace>(S);
689 // DINamespace carries no line/column info.
690 MCRegister LineReg = emitOpConstantI32(0, I32TypeReg, MAI);
691 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
692 MCRegister NameReg = getCachedOpStringReg(NS->getName());
693 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt, NameReg};
694 }
695
696 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLexicalBlock, VoidTypeReg,
697 ExtInstSetReg, Ops, MAI);
698}
699
700std::optional<MCRegister>
701SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
702 const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
703 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
704 assert(SP && "SP must not be null in emitDebugFunctionDeclaration");
705 assert(!SP->isDefinition() &&
706 "SP must not be a definition in emitDebugFunctionDeclaration");
707
708 // The IR verifier already enforces that this cannot be null.
709 const DISubroutineType *ST = SP->getType();
710
711 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
712 if (!FnTyRegOpt)
713 return std::nullopt;
714 MCRegister FnTyReg = *FnTyRegOpt;
715
716 auto ParentRegOpt = resolveScope(SP->getScope(), SP->getUnit());
717 if (!ParentRegOpt)
718 return std::nullopt;
719
720 MCRegister ParentReg = *ParentRegOpt;
721
722 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
723
724 MCRegister NameReg = getCachedOpStringReg(SP->getName());
725 MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
726 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
727 ExtInstSetReg, MAI);
728
729 MCRegister LineReg =
730 emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
731 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
732
733 uint32_t FlagsVal = transDebugFlags(SP);
734 // TODO: When composite scopes are DebugFunctionDeclaration parents (available
735 // in DebugScopeRegs), sync declaration Flags with SPIRV-LLVM-Translator.
736 FlagsVal &= ~NSDIFlagIsDefinition;
737 MCRegister FlagsReg = emitOpConstantI32(FlagsVal, I32TypeReg, MAI);
738
739 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
740 VoidTypeReg, ExtInstSetReg,
741 {NameReg, FnTyReg, SrcReg, LineReg, ColReg, ParentReg,
742 LinkageReg, FlagsReg},
743 MAI);
744}
745
746std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugFunction(
747 const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
748 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
749 assert(SP && "SP must not be null in emitDebugFunction");
750 assert(SP->isDefinition() && "SP must be a definition in emitDebugFunction");
751
752 const DISubroutineType *ST = SP->getType();
753 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
754 if (!FnTyRegOpt)
755 return std::nullopt;
756
757 auto ParentRegOpt = resolveScope(SP->getScope(), SP->getUnit());
758 if (!ParentRegOpt)
759 return std::nullopt;
760
761 MCRegister NameReg = getCachedOpStringReg(SP->getName());
762 MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
763 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
764 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
765 ExtInstSetReg, MAI);
766
767 MCRegister LineReg =
768 emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
769 // LLVM's DISubprogram has no column field but SPIR-V expects one in
770 // DebugFunction.
771 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
772 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(SP), I32TypeReg, MAI);
773 MCRegister ScopeLineReg = emitOpConstantI32(
774 static_cast<uint32_t>(SP->getScopeLine()), I32TypeReg, MAI);
775
776 SmallVector<MCRegister, 10> Ops = {NameReg, *FnTyRegOpt, SrcReg,
777 LineReg, ColReg, *ParentRegOpt,
778 LinkageReg, FlagsReg, ScopeLineReg};
779
780 if (const DISubprogram *Decl = SP->getDeclaration()) {
781 if (auto DeclRegOpt = lookupOptReg(DebugScopeRegs, Decl))
782 Ops.push_back(*DeclRegOpt);
783 }
784
785 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunction, VoidTypeReg,
786 ExtInstSetReg, Ops, MAI);
787}
788
789std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
790 const DIType *Ty, MCRegister VoidTypeReg, bool ReturnType) {
791 if (!Ty) {
792 if (ReturnType)
793 return VoidTypeReg;
794 assert(CachedDebugInfoNoneReg.isValid() &&
795 "DebugInfoNone must be emitted before DISubroutineType operands");
796 return CachedDebugInfoNoneReg;
797 }
798 return lookupOptReg(DebugScopeRegs, Ty);
799}
800
801// Unimplemented no-op; see emitDebugExpression declaration.
802std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugExpression(
804 return std::nullopt;
805}
806
807std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugGlobalVariable(
808 const DIGlobalVariable *GV, const GlobalVariableDebugInfo &Info,
809 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
811 assert(GV && "GV must not be null in emitDebugGlobalVariable");
812
813 auto ParentRegOpt = resolveScope(GV->getScope());
814 if (!ParentRegOpt)
815 return std::nullopt;
816
817 MCRegister ParentReg = *ParentRegOpt;
818
819 // TyReg: DebugInfoNone when GV has no DI type (as done in
820 // SPIRV-LLVM-Translator). Declarations (isDefinition: false) can have null
821 // getType() while definitions must have a non-null one (enforced by the IR
822 // verifier).
823 MCRegister TyReg = CachedDebugInfoNoneReg;
824 if (const DIType *Ty = GV->getType()) {
825 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
826 if (!TyRegOpt)
827 return std::nullopt;
828 TyReg = *TyRegOpt;
829 }
830
831 std::optional<MCRegister> StaticMemberRegOpt;
832 if (const DIDerivedType *SM = GV->getStaticDataMemberDeclaration()) {
833 StaticMemberRegOpt = lookupOptReg(DebugScopeRegs, SM);
834 if (!StaticMemberRegOpt)
835 return std::nullopt;
836 }
837
838 MCRegister NameReg = getCachedOpStringReg(GV->getName());
839 MCRegister LinkageReg = getCachedOpStringReg(GV->getLinkageName());
840 MCRegister FileStrReg = getCachedScopePathOpStringReg(
841 GV->getFile(), /*UseEmptyPathIfNullScope=*/true);
842 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
843 ExtInstSetReg, MAI);
844
845 MCRegister LineReg =
846 emitOpConstantI32(static_cast<uint32_t>(GV->getLine()), I32TypeReg, MAI);
847 // DIGlobalVariable or DIGlobalVariableExpression metadata carry no column
848 // field. Column is hardcoded to 0 (because it can't be determined), matching
849 // SPIRV-LLVM-Translator.
850 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
851
852 // Variable: @g OpVariable id when !dbg matches; else a DebugExpression for
853 // the GVE init value when no @g exists; else DebugInfoNone.
854 MCRegister VariableReg = CachedDebugInfoNoneReg;
855 if (const GlobalVariable *LLVMGV = Info.LLVMGV) {
856 MCRegister GVReg = MAI.getGlobalObjReg(LLVMGV);
857 if (GVReg.isValid())
858 VariableReg = GVReg;
859 } else if (Info.Expr) {
860 if (auto ExprReg =
861 emitDebugExpression(Info.Expr, VoidTypeReg, ExtInstSetReg, MAI))
862 VariableReg = *ExprReg;
863 }
864
865 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(GV), I32TypeReg, MAI);
866
867 SmallVector<MCRegister, 10> Ops = {NameReg, TyReg, SrcReg,
868 LineReg, ColReg, ParentReg,
869 LinkageReg, VariableReg, FlagsReg};
870
871 if (StaticMemberRegOpt)
872 Ops.push_back(*StaticMemberRegOpt);
873
874 return emitExtInst(SPIRV::NonSemanticExtInst::DebugGlobalVariable,
875 VoidTypeReg, ExtInstSetReg, Ops, MAI);
876}
877
878std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
879 const DICompositeType *VT, MCRegister ExtInstSetReg,
881 const auto *BaseTy = dyn_cast_or_null<DIBasicType>(VT->getBaseType());
882 if (!BaseTy)
883 return std::nullopt;
884 auto BTIt = DebugScopeRegs.find(BaseTy);
885 if (BTIt == DebugScopeRegs.end())
886 return std::nullopt;
887
888 // DebugTypeVector models only 1D vectors (multi-subrange types cannot be
889 // encoded).
890 DINodeArray Elements = VT->getElements();
891 if (Elements.size() != 1)
892 return std::nullopt;
893 const auto *SR = cast<DISubrange>(Elements[0]);
894 const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount());
895 if (!CI)
896 return std::nullopt;
897
898 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
899 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
900 MCRegister CountReg = emitOpConstantI32(
901 static_cast<uint32_t>(CI->getZExtValue()), I32TypeReg, MAI);
902 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeVector, VoidTypeReg,
903 ExtInstSetReg, {BTIt->second, CountReg}, MAI);
904}
905
906std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeArray(
907 const DICompositeType *AT, MCRegister ExtInstSetReg,
909 // The element (base) type must already be in DebugScopeRegs. Unlike
910 // DebugTypeVector, the element may be any debug type, not only a basic type.
911 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, AT->getBaseType());
912 if (!BaseRegOpt)
913 return std::nullopt;
914
915 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
916 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
917
919 Ops.push_back(*BaseRegOpt);
920
921 // One component count per DISubrange, in DWARF subrange order. Emit 0 for
922 // counts that are not a compile-time constant (dynamic arrays). This matches
923 // OpTypeRuntimeArray.
924 for (const DINode *Element : AT->getElements()) {
925 const auto *SR = dyn_cast<DISubrange>(Element);
926 if (!SR)
927 continue;
928 // A DIVariable count (a variable-length array) is not a ConstantInt, so it
929 // maps to 0 here. DebugTypeArray also allows a DebugLocalVariable or
930 // DebugGlobalVariable id for it, but no frontend we target emits one. A
931 // constant wider than 32 bits maps to 0 too, since the count operand is a
932 // 32-bit OpConstant and such an array cannot occur in a shader.
933 uint32_t Count = 0;
934 if (const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount())) {
935 const APInt &Value = CI->getValue();
936 if (Value.getActiveBits() <= 32)
937 Count = static_cast<uint32_t>(Value.getZExtValue());
938 }
939 Ops.push_back(emitOpConstantI32(Count, I32TypeReg, MAI));
940 }
941
942 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeArray, VoidTypeReg,
943 ExtInstSetReg, Ops, MAI);
944}
945
946std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeMember(
947 const DIDerivedType *M, MCRegister VoidTypeReg, MCRegister I32TypeReg,
948 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
949 // The member type must already be in DebugScopeRegs.
950 auto TyRegOpt = lookupOptReg(DebugScopeRegs, M->getBaseType());
951 if (!TyRegOpt)
952 return std::nullopt;
953
954 MCRegister NameReg = getCachedOpStringReg(M->getName());
955 MCRegister FileStrReg = getCachedScopePathOpStringReg(
956 M->getFile(), /*UseEmptyPathIfNullScope=*/true);
957 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
958 ExtInstSetReg, MAI);
959 MCRegister LineReg =
960 emitOpConstantI32(static_cast<uint32_t>(M->getLine()), I32TypeReg, MAI);
961
962 // DIDerivedType members carry no column, so emit 0.
963 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
964 MCRegister OffsetReg = emitOpConstantI32(
965 static_cast<uint32_t>(M->getOffsetInBits()), I32TypeReg, MAI);
966 MCRegister SizeReg = emitOpConstantI32(
967 static_cast<uint32_t>(M->getSizeInBits()), I32TypeReg, MAI);
968 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(M), I32TypeReg, MAI);
969
970 // In NonSemantic.Shader.DebugInfo a DebugTypeMember has no Parent operand:
971 // only the composite references its members. This is by design, it drops the
972 // Parent that OpenCL.DebugInfo.100 had, and it avoids a composite/member
973 // reference cycle.
974 //
975 // FIXME: Static members are not handled yet: their constant initializer is
976 // available but is not emitted as the optional Value operand, and under DWARF
977 // 5 a static member is tagged DW_TAG_variable, which the caller's member loop
978 // skips.
979 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeMember, VoidTypeReg,
980 ExtInstSetReg,
981 {NameReg, *TyRegOpt, SrcReg, LineReg, ColReg, OffsetReg,
982 SizeReg, FlagsReg},
983 MAI);
984}
985
986std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeComposite(
987 const DICompositeType *CT, ArrayRef<MCRegister> MemberRegs,
988 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
990 auto ParentRegOpt = resolveScope(CT->getScope());
991 if (!ParentRegOpt)
992 return std::nullopt;
993
994 MCRegister NameReg = getCachedOpStringReg(CT->getName());
995 MCRegister LinkageReg = getCachedOpStringReg(CT->getIdentifier());
996 MCRegister FileStrReg = getCachedScopePathOpStringReg(
997 CT->getFile(), /*UseEmptyPathIfNullScope=*/true);
998 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
999 ExtInstSetReg, MAI);
1000
1001 MCRegister TagReg =
1002 emitOpConstantI32(mapCompositeTypeTag(CT->getTag()), I32TypeReg, MAI);
1003 MCRegister LineReg =
1004 emitOpConstantI32(static_cast<uint32_t>(CT->getLine()), I32TypeReg, MAI);
1005 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1006
1007 // A forward declaration has no known size or members: Size is DebugInfoNone.
1008 MCRegister SizeReg = CachedDebugInfoNoneReg;
1009 if (!CT->isForwardDecl())
1010 SizeReg = emitOpConstantI32(static_cast<uint32_t>(CT->getSizeInBits()),
1011 I32TypeReg, MAI);
1012
1013 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(CT), I32TypeReg, MAI);
1014
1015 SmallVector<MCRegister> Ops = {NameReg, TagReg, SrcReg,
1016 LineReg, ColReg, *ParentRegOpt,
1017 LinkageReg, SizeReg, FlagsReg};
1018 Ops.append(MemberRegs.begin(), MemberRegs.end());
1019 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeComposite, VoidTypeReg,
1020 ExtInstSetReg, Ops, MAI);
1021}
1022
1023std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypedef(
1024 const DIDerivedType *TD, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1025 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1026 // The underlying (base) type must already be in DebugScopeRegs.
1027 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, TD->getBaseType());
1028 if (!BaseRegOpt)
1029 return std::nullopt;
1030
1031 MCRegister NameReg = getCachedOpStringReg(TD->getName());
1032 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1033 TD->getFile(), /*UseEmptyPathIfNullScope=*/true);
1034 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1035 ExtInstSetReg, MAI);
1036 MCRegister LineReg =
1037 emitOpConstantI32(static_cast<uint32_t>(TD->getLine()), I32TypeReg, MAI);
1038 // DIDerivedType typedefs carry no column, so emit 0.
1039 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1040
1041 // Parent must be a lexical scope. Valid NSDI lexical scopes are
1042 // DebugCompilationUnit, DebugFunction, DebugLexicalBlock, or
1043 // DebugTypeComposite.
1044 auto ParentRegOpt = resolveScope(TD->getScope());
1045 if (!ParentRegOpt)
1046 return std::nullopt;
1047 MCRegister ParentReg = *ParentRegOpt;
1048
1049 return emitExtInst(
1050 SPIRV::NonSemanticExtInst::DebugTypedef, VoidTypeReg, ExtInstSetReg,
1051 {NameReg, *BaseRegOpt, SrcReg, LineReg, ColReg, ParentReg}, MAI);
1052}
1053
1056 if (CompileUnits.empty())
1057 return;
1058 // Check that prepareModuleOutput() registered the extended instruction set.
1059 // If the subtarget does not support the extension, neither strings nor ext
1060 // insts are emitted.
1061 if (!MAI.getExtInstSetReg(NSSet).isValid())
1062 return;
1063
1064 for (const CompileUnitInfo &Info : CompileUnits) {
1065 if (Info.TheCU) {
1066 MCRegister PathReg = emitOpStringIfNew(Info.FilePath, MAI);
1067 ScopeToPathOpStringReg[Info.TheCU] = PathReg;
1068 if (const DIFile *F = Info.TheCU->getFile())
1069 ScopeToPathOpStringReg[F] = PathReg;
1070 }
1071 }
1072
1073 for (const DIBasicType *BT : BasicTypes)
1074 emitOpStringIfNew(BT->getName(), MAI);
1075
1077 SubprogramDeclarations, SubprogramDefinitions)) {
1078 emitOpStringIfNew(SP->getName(), MAI);
1079 emitOpStringIfNew(SP->getLinkageName(), MAI);
1080 emitAndCacheScopePathOpStringReg(SP, MAI);
1081 }
1082
1083 // Cache the OpStrings each DebugTypeComposite and its DebugTypeMembers use:
1084 // the composite name, identifier (linkage name), and path, plus each member
1085 // name and path.
1086 for (const DICompositeType *CT : CompositeTypes) {
1087 emitOpStringIfNew(CT->getName(), MAI);
1088 emitOpStringIfNew(CT->getIdentifier(), MAI);
1089 emitAndCacheScopePathOpStringReg(CT->getFile(), MAI);
1090 for (const DINode *Element : CT->getElements()) {
1091 const auto *M = dyn_cast<DIDerivedType>(Element);
1092 if (!M || M->getTag() != dwarf::DW_TAG_member)
1093 continue;
1094 emitOpStringIfNew(M->getName(), MAI);
1095 emitAndCacheScopePathOpStringReg(M->getFile(), MAI);
1096 }
1097 }
1098
1099 // Cache the name and path OpStrings each DebugTypedef uses.
1100 for (const DIDerivedType *TD : TypedefTypes) {
1101 emitOpStringIfNew(TD->getName(), MAI);
1102 emitAndCacheScopePathOpStringReg(TD->getFile(), MAI);
1103 }
1104
1105 for (const auto &[GV, _] : GlobalVariableDebugInfoMap) {
1106 emitOpStringIfNew(GV->getName(), MAI);
1107 emitOpStringIfNew(GV->getLinkageName(), MAI);
1108 emitAndCacheScopePathOpStringReg(GV->getFile(), MAI);
1109 }
1110
1111 // Cache the path OpString each DebugLexicalBlock uses (source file), plus
1112 // the Name OpString for the DINamespace case.
1113 for (const DIScope *S : LexicalBlocks) {
1114 emitAndCacheScopePathOpStringReg(S->getFile(), MAI);
1115 if (const auto *NS = dyn_cast<DINamespace>(S))
1116 emitOpStringIfNew(NS->getName(), MAI);
1117 }
1118
1119 for (const DILocation *DL : UniqueDebugLocations)
1120 emitAndCacheScopePathOpStringReg(DL->getScope(), MAI);
1121
1122 CachedEmptyStringReg = emitOpStringIfNew("", MAI);
1123
1124#ifndef NDEBUG
1125 NonSemanticOpStringsSectionEmitted = true;
1126#endif
1127}
1128
1129void SPIRVNonSemanticDebugHandler::emitDebugFunctionDefinition(
1130 MCRegister DebugFunctionReg, MCRegister OpFunctionReg,
1132 assert(DebugFunctionReg.isValid() && OpFunctionReg.isValid() &&
1133 "DebugFunctionDefinition operands must be valid");
1134 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1135 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1136 emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDefinition, VoidTypeReg,
1137 ExtInstSetReg, {DebugFunctionReg, OpFunctionReg}, MAI);
1138}
1139
1140void SPIRVNonSemanticDebugHandler::resetPerFunctionDebugState() {
1141 CurrentMF = nullptr;
1142 LastFunctionOpVariable = nullptr;
1143 DebugFunctionDefinitionEmitted = false;
1144 LastLineMI = nullptr;
1145}
1146
1147void SPIRVNonSemanticDebugHandler::preparePerFunctionDebug(
1148 const MachineFunction *MF) {
1149 resetPerFunctionDebugState();
1150 if (!GlobalNSDIEnabled || !CurrentMAI)
1151 return;
1152
1153 CurrentMF = MF;
1154
1155 if (MF->getFunction()
1157 .isValid())
1158 return;
1159
1160 const DISubprogram *SP = MF->getFunction().getSubprogram();
1161 if (!SP || !SP->isDefinition())
1162 return;
1163
1164 // DebugFunctionDefinition is emitted after the last function-level
1165 // OpVariable. If there are none, it is emitted after the entry OpLabel.
1166 LastFunctionOpVariable =
1167 findLastFunctionOpVariableDeclaration(*MF, *CurrentMAI);
1168}
1169
1170void SPIRVNonSemanticDebugHandler::tryEmitDebugFunctionDefinition(
1172 if (DebugFunctionDefinitionEmitted || !GlobalNSDIEnabled)
1173 return;
1174
1175 assert(CurrentMF && "no current MachineFunction");
1176 const Function &F = CurrentMF->getFunction();
1177 const DISubprogram *SP = F.getSubprogram();
1178 if (!SP || !SP->isDefinition())
1179 return;
1180
1181 auto DFIt = DebugScopeRegs.find(SP);
1182 if (DFIt == DebugScopeRegs.end())
1183 return;
1184
1185 MCRegister OpFunctionReg = MAI.getGlobalObjReg(&F);
1186 if (!OpFunctionReg.isValid())
1187 return;
1188
1189 emitDebugFunctionDefinition(DFIt->second, OpFunctionReg, MAI);
1190 DebugFunctionDefinitionEmitted = true;
1191}
1192
1194 const MachineFunction *MF) {
1195 preparePerFunctionDebug(MF);
1196}
1197
1199 (void)MF;
1200 resetPerFunctionDebugState();
1201}
1202
1204 assert(CurMI == nullptr && "CurMI must be null");
1205 CurMI = MI;
1206
1207 if (!DebugFunctionDefinitionEmitted)
1208 return;
1209 emitDebugLineForInstruction(MI);
1210}
1211
1212static bool isMergeInstruction(unsigned Opcode) {
1213 return Opcode == SPIRV::OpSelectionMerge || Opcode == SPIRV::OpLoopMerge ||
1214 Opcode == SPIRV::OpLoopControlINTEL;
1215}
1216
1219 if (MAI.getSkipEmission(MI))
1220 return false;
1221 switch (MI->getOpcode()) {
1222 case SPIRV::OpFunction:
1223 case SPIRV::OpFunctionParameter:
1224 case SPIRV::OpFunctionEnd:
1225 case SPIRV::OpLabel:
1226 case SPIRV::OpPhi:
1227 return false;
1228 default:
1229 return true;
1230 }
1231}
1232
1233static const MachineInstr *
1235 SPIRV::ModuleAnalysisInfo &MAI, bool Forward) {
1236 for (const MachineInstr *Adj = Forward ? MI->getNextNode()
1237 : MI->getPrevNode();
1238 Adj; Adj = Forward ? Adj->getNextNode() : Adj->getPrevNode()) {
1239 if (MAI.getSkipEmission(Adj))
1240 continue;
1241 return Adj;
1242 }
1243 return nullptr;
1244}
1245
1246void SPIRVNonSemanticDebugHandler::emitDebugLineForInstruction(
1247 const MachineInstr *MI) {
1248 assert(DebugFunctionDefinitionEmitted &&
1249 "DebugFunctionDefinition must be emitted");
1250 assert(CurrentMAI && "CurrentMAI must be set");
1251
1252 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1253
1254 // Structural opcodes don't require a DebugLine, other opcodes might have
1255 // already been emitted in the module scope.
1256 if (!isDebugLineTarget(MI, MAI))
1257 return;
1258
1259 // DebugLine can be emitted before a merge instruction, but not after it
1260 // (nothing may sit between the merge and its terminator). We can use either
1261 // the merge's or the terminator's debug info; we emit the terminator's one.
1262 const MachineInstr *Prev = findAdjacentEmittedInstruction(MI, MAI, false);
1263 if (Prev && isMergeInstruction(Prev->getOpcode()))
1264 return;
1265
1266 if (isMergeInstruction(MI->getOpcode())) {
1267 // Use the terminator's debug info; when we reach it later, the check
1268 // above skips it.
1269 MI = findAdjacentEmittedInstruction(MI, MAI, true);
1270 assert(MI && "Merge instruction must be followed by a terminator");
1271 }
1272
1273 // The range of DebugLine must be reset at each basic block boundary.
1274 if (LastLineMI && MI->getParent() != LastLineMI->getParent())
1275 LastLineMI = nullptr;
1276
1277 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1278 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1279
1280 const DILocation *DL = MI->getDebugLoc().get();
1281 if (!DL) {
1282 // No location for the current instruction
1283 if (LastLineMI) {
1284 // Close the current DebugLine region.
1285 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoLine, VoidTypeReg,
1286 ExtInstSetReg, {}, MAI);
1287 LastLineMI = nullptr;
1288 }
1289 // No DebugLine region to close.
1290 return;
1291 }
1292
1293 // At this point, there is a location for the current instruction.
1294 // If it matches the last emitted DebugLine, no new DebugLine region is
1295 // needed. Otherwise, emit a new DebugLine region and update LastLineMI.
1296
1297 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1298 DL->getScope(), /*UseEmptyPathIfNullScope=*/true);
1299 unsigned Line = DL->getLine();
1300 unsigned Col = DL->getColumn();
1301
1302 MCRegister SrcReg = DebugSourceRegByFileStr.lookup(FileStrReg.id());
1303 MCRegister LineReg = I32ConstantCache.lookup(Line);
1304 MCRegister ColStartReg = I32ConstantCache.lookup(Col);
1305 MCRegister ColEndReg = I32ConstantCache.lookup(Col + 1);
1306
1307 // The elements of each collected DILocation (DebugSource, line/column
1308 // constants) are pre-emitted from LLVM-IR instruction !dbg attachments and
1309 // debug-program records; MIR is expected to reuse those same locations (or
1310 // carry none). A lookup miss means codegen attached a source position whose
1311 // elements were never pre-emitted, and debug-line emission is skipped.
1312 if (!SrcReg.isValid() || !LineReg.isValid() || !ColStartReg.isValid() ||
1313 !ColEndReg.isValid())
1314 return;
1315
1316 // Current location matches the last emitted DebugLine region.
1317 if (LastLineMI && MI->getDebugLoc() == LastLineMI->getDebugLoc())
1318 return;
1319
1320 // A new DebugLine region is needed. Emit it and update LastLineMI.
1321 emitExtInst(SPIRV::NonSemanticExtInst::DebugLine, VoidTypeReg, ExtInstSetReg,
1322 {SrcReg, LineReg, LineReg, ColStartReg, ColEndReg}, MAI);
1323
1324 LastLineMI = MI;
1325}
1326
1328 const MachineInstr *MI = CurMI;
1329 CurMI = nullptr;
1330
1331 if (!MI || !GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
1332 return;
1333
1334 if (MI != LastFunctionOpVariable)
1335 return;
1336
1337 // If this is the last function-level OpVariable, emit the
1338 // DebugFunctionDefinition. Otherwise, we had already done it before right
1339 // after the OpLabel (see notifyEntryLabelEmitted).
1340 assert(CurrentMAI && "CurrentMAI must be set");
1341 tryEmitDebugFunctionDefinition(*CurrentMAI);
1342}
1343
1345 const MachineFunction &MF) {
1346 if (!GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
1347 return;
1348
1349 assert(CurrentMF == &MF &&
1350 "notification does not match the current MachineFunction");
1351
1352 if (LastFunctionOpVariable)
1353 return;
1354
1355 // If there are no function-level OpVariables, emit the
1356 // DebugFunctionDefinition. Otherwise, DebugFunctionDefinition is emitted
1357 // after the last OpVariable (see endInstruction).
1358 tryEmitDebugFunctionDefinition(*CurrentMAI);
1359}
1360
1363 if (GlobalDIEmitted)
1364 return;
1365
1366 GlobalDIEmitted = true;
1367
1368 if (CompileUnits.empty()) {
1369 GlobalNSDIEnabled = false;
1370 return;
1371 }
1372
1373 // Retrieve the ext inst set register allocated by prepareModuleOutput().
1374 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1375 if (!ExtInstSetReg.isValid()) {
1376 GlobalNSDIEnabled = false;
1377 return;
1378 }
1379
1380#ifndef NDEBUG
1381 assert(NonSemanticOpStringsSectionEmitted &&
1382 "emitNonSemanticDebugStrings() must run before "
1383 "emitNonSemanticGlobalDebugInfo()");
1384#endif
1385
1386 CurrentMAI = &MAI;
1387
1388 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1389 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1390
1391 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
1392 VoidTypeReg, ExtInstSetReg, {}, MAI);
1393
1394 // Emit integer constants shared across all NSDI instructions. The constant
1395 // cache ensures each value is emitted at most once even when referenced from
1396 // multiple instructions. All constants are pre-emitted before any DebugSource
1397 // so that the output order is: constants, then
1398 // DebugSource+DebugCompilationUnit pairs. This keeps OpConstant instructions
1399 // grouped before the OpExtInst instructions.
1400
1401 // The Version operand of DebugCompilationUnit is the version of the
1402 // NonSemantic.Shader.DebugInfo instruction set, which is 100 for
1403 // "NonSemantic.Shader.DebugInfo.100" (NonSemanticShaderDebugInfo100Version).
1404 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
1405 MCRegister DwarfVersionReg =
1406 emitOpConstantI32(static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
1407
1408 // Pre-emit source language constants for all compile units before entering
1409 // the DebugSource loop.
1410 SmallVector<MCRegister> SrcLangRegs =
1411 map_to_vector(CompileUnits, [&](const CompileUnitInfo &Info) {
1412 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
1413 });
1414
1415 // Emit DebugSource and DebugCompilationUnit for each compile unit.
1416 for (auto [Info, SrcLangReg] : llvm::zip(CompileUnits, SrcLangRegs)) {
1417 MCRegister FileStrReg = ScopeToPathOpStringReg.lookup(Info.TheCU);
1418 assert(FileStrReg.isValid() &&
1419 "CU path OpString must be emitted in emitNonSemanticDebugStrings");
1420 MCRegister DebugSourceReg = getOrEmitDebugSourceForFileStrReg(
1421 FileStrReg, VoidTypeReg, ExtInstSetReg, MAI);
1422 MCRegister CUDbgReg = emitExtInst(
1423 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
1424 ExtInstSetReg,
1425 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
1426 MAI);
1427 if (Info.TheCU)
1428 DebugScopeRegs[Info.TheCU] = CUDbgReg;
1429 }
1430
1431 // Zero constant used as the Flags operand in DebugTypeBasic and
1432 // DebugTypePointer. Cached with other i32 constants.
1433 MCRegister I32ZeroReg = emitOpConstantI32(0, I32TypeReg, MAI);
1434
1435 for (const DIBasicType *BT : BasicTypes) {
1436 MCRegister NameReg = getCachedOpStringReg(BT->getName());
1437 MCRegister SizeReg = emitOpConstantI32(
1438 static_cast<uint32_t>(BT->getSizeInBits()), I32TypeReg, MAI);
1439
1440 // Map DWARF base type encodings to NSDI encoding codes per
1441 // NonSemantic.Shader.DebugInfo.100 specification, section 4.5.
1442 unsigned Encoding = 0; // Unspecified
1443 switch (BT->getEncoding()) {
1444 case dwarf::DW_ATE_address:
1445 Encoding = 1;
1446 break;
1447 case dwarf::DW_ATE_boolean:
1448 Encoding = 2;
1449 break;
1450 case dwarf::DW_ATE_float:
1451 Encoding = 3;
1452 break;
1453 case dwarf::DW_ATE_signed:
1454 Encoding = 4;
1455 break;
1456 case dwarf::DW_ATE_signed_char:
1457 Encoding = 5;
1458 break;
1459 case dwarf::DW_ATE_unsigned:
1460 Encoding = 6;
1461 break;
1462 case dwarf::DW_ATE_unsigned_char:
1463 Encoding = 7;
1464 break;
1465 }
1466 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
1467
1468 MCRegister BTReg = emitExtInst(
1469 SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
1470 {NameReg, SizeReg, EncodingReg, I32ZeroReg}, MAI);
1471 DebugScopeRegs[BT] = BTReg;
1472 }
1473
1474 // Emit DebugTypeVector for each collected vector type.
1475 for (const DICompositeType *VT : VectorTypes) {
1476 if (auto VecReg = emitDebugTypeVector(VT, ExtInstSetReg, MAI))
1477 DebugScopeRegs[VT] = *VecReg;
1478 }
1479
1480 // Emit DebugTypePointer for each referenced pointer type.
1481 for (const DIDerivedType *PT : PointerTypes) {
1482 if (auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
1483 DebugScopeRegs[PT] = *PtrReg;
1484 }
1485
1486 // Emit DebugTypeArray for each collected array type. Placed after the basic,
1487 // vector, and pointer types so an array over any of them can resolve its
1488 // element id. An array whose element type was not emitted is skipped.
1489 for (const DICompositeType *AT : ArrayTypes) {
1490 if (auto ArrReg = emitDebugTypeArray(AT, ExtInstSetReg, MAI))
1491 DebugScopeRegs[AT] = *ArrReg;
1492 }
1493
1494 // Emit DebugTypeFunction for each distinct DISubroutineType.
1495 for (const DISubroutineType *ST : SubroutineTypes) {
1496 if (auto FnTyReg =
1497 emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI))
1498 DebugScopeRegs[ST] = *FnTyReg;
1499 }
1500
1501 // Emit DebugLexicalBlock for each collected DINamespace, in parent-before-
1502 // child order. Placed before any DINamespace-scoped entity (typedefs,
1503 // function declarations, composite types, functions, global variables) so
1504 // their Parent operand can reference an already-emitted DebugLexicalBlock.
1505 // DINamespace never chains through a DISubprogram (DINamespace::getScope()
1506 // returns DIScope, not DILocalScope), so this never depends on
1507 // DebugScopeRegs.
1508 for (const DIScope *S :
1509 make_filter_range(LexicalBlocks, IsaPred<DINamespace>)) {
1510 if (auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
1511 ExtInstSetReg, MAI))
1512 DebugScopeRegs[S] = *LBReg;
1513 }
1514
1515 // Emit DebugTypedef for each typedef. Placed after the other type loops so a
1516 // typedef can resolve its underlying type. A typedef whose base type is not
1517 // emitted is skipped. A typedef whose base is another typedef emitted later
1518 // in this same pass is also skipped, the emission-order gap tracked in
1519 // https://github.com/llvm/llvm-project/issues/211850.
1520 for (const DIDerivedType *TD : TypedefTypes) {
1521 if (auto TDReg =
1522 emitDebugTypedef(TD, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
1523 DebugScopeRegs[TD] = *TDReg;
1524 }
1525
1526 // Emit DebugFunctionDeclaration for DISubprogram declarations.
1527 for (const DISubprogram *SP : SubprogramDeclarations) {
1528 if (auto DeclReg = emitDebugFunctionDeclaration(SP, VoidTypeReg, I32TypeReg,
1529 ExtInstSetReg, MAI))
1530 DebugScopeRegs[SP] = *DeclReg;
1531 }
1532
1533 // Emit DebugTypeMember and DebugTypeComposite for each struct, class, or
1534 // union. Each member is emitted before the composite that lists it, so the
1535 // Members operand references already-defined ids. A member whose type is not
1536 // in DebugScopeRegs is skipped.
1537 for (const DICompositeType *CT : CompositeTypes) {
1538 SmallVector<MCRegister> MemberRegs;
1539 for (const DINode *Element : CT->getElements()) {
1540 const auto *M = dyn_cast<DIDerivedType>(Element);
1541 if (!M || M->getTag() != dwarf::DW_TAG_member)
1542 continue;
1543 if (auto MemberReg = emitDebugTypeMember(M, VoidTypeReg, I32TypeReg,
1544 ExtInstSetReg, MAI))
1545 MemberRegs.push_back(*MemberReg);
1546 }
1547 if (auto CompReg = emitDebugTypeComposite(CT, MemberRegs, VoidTypeReg,
1548 I32TypeReg, ExtInstSetReg, MAI))
1549 DebugScopeRegs[CT] = *CompReg;
1550 }
1551
1552 // Emit DebugFunction for DISubprogram definitions.
1553 for (const DISubprogram *SP : SubprogramDefinitions) {
1554 if (auto FnReg =
1555 emitDebugFunction(SP, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
1556 DebugScopeRegs[SP] = *FnReg;
1557 }
1558
1559 // Emit DebugLexicalBlock for each collected DILexicalBlock, in parent-
1560 // before-child order. Placed after DebugFunction so a block directly
1561 // enclosed by a function (the common case) can resolve its Parent operand;
1562 // DINamespace entries were already emitted above.
1563 for (const DIScope *S :
1565 if (auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
1566 ExtInstSetReg, MAI))
1567 DebugScopeRegs[S] = *LBReg;
1568 }
1569
1570 // Emit DebugGlobalVariable for each collected DIGlobalVariable.
1571 for (const auto &[GV, Info] : GlobalVariableDebugInfoMap)
1572 emitDebugGlobalVariable(GV, Info, VoidTypeReg, I32TypeReg, ExtInstSetReg,
1573 MAI);
1574
1575 for (const DILocation *DL : UniqueDebugLocations) {
1576 emitOpConstantI32(DL->getLine(), I32TypeReg, MAI);
1577 emitOpConstantI32(DL->getColumn(), I32TypeReg, MAI);
1578 emitOpConstantI32(DL->getColumn() + 1, I32TypeReg, MAI);
1579 MCRegister FileStrReg =
1580 getCachedScopePathOpStringReg(DL->getScope(),
1581 /*UseEmptyPathIfNullScope=*/true);
1582 getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg, ExtInstSetReg,
1583 MAI);
1584 }
1585
1586 GlobalNSDIEnabled = true;
1587}
1588
1590SPIRVNonSemanticDebugHandler::getDebugFullPath(const DIScope *Scope) const {
1591 SmallString<128> Out;
1592 if (!Scope)
1593 return Out;
1594 StringRef Filename = Scope->getFilename();
1595 const auto Style = sys::path::Style::native;
1596 if (sys::path::is_absolute(Filename, Style))
1597 Out.assign(Filename.begin(), Filename.end());
1598 else {
1599 StringRef Dir = Scope->getDirectory();
1600 Out.assign(Dir.begin(), Dir.end());
1601 sys::path::append(Out, Style, Filename);
1602 }
1603 return Out;
1604}
1605
1606MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugSourceForFileStrReg(
1607 MCRegister FileStrReg, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
1609 const unsigned Key = FileStrReg.id();
1610 auto It = DebugSourceRegByFileStr.find(Key);
1611 if (It != DebugSourceRegByFileStr.end())
1612 return It->second;
1613
1614 MCRegister DS = emitExtInst(SPIRV::NonSemanticExtInst::DebugSource,
1615 VoidTypeReg, ExtInstSetReg, {FileStrReg}, MAI);
1616 DebugSourceRegByFileStr[Key] = DS;
1617 return DS;
1618}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
BitTracker BT
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains constants used for implementing Dwarf debug support.
#define _
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
Register Reg
static constexpr StringLiteral Filename
SI Fold Operands
static const MachineInstr * findAdjacentEmittedInstruction(const MachineInstr *MI, SPIRV::ModuleAnalysisInfo &MAI, bool Forward)
static void collectLexicalBlockChain(const DIScope *S, SetVector< const DIScope * > &Out)
static bool isMergeInstruction(unsigned Opcode)
static bool isDebugLineTarget(const MachineInstr *MI, SPIRV::ModuleAnalysisInfo &MAI)
static void collectUniqueDebugLocations(const Module &M, SetVector< const DILocation * > &Out)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
Definition SPIRVUtils.h:567
This file implements a set that has insertion order iteration characteristics.
This file defines less commonly used SmallVector utilities.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
iterator end() const
Definition ArrayRef.h:130
iterator begin() const
Definition ArrayRef.h:129
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:91
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:106
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:263
Basic type, like 'int' or 'float'.
StringRef getIdentifier() const
DINodeArray getElements() const
DIType * getBaseType() const
DWARF expression.
A pair of DIGlobalVariable and DIExpression.
DIDerivedType * getStaticDataMemberDeclaration() const
StringRef getLinkageName() const
Tagged DWARF-like metadata node.
LLVM_ABI dwarf::Tag getTag() const
DIFlags
Debug info flags.
Base class for scope-like contexts.
DIFile * getFile() const
LLVM_ABI DIScope * getScope() const
Subprogram description. Uses SubclassData1.
Type array for a subprogram.
Base class for types.
StringRef getName() const
bool isForwardDecl() const
uint64_t getSizeInBits() const
unsigned getLine() const
DIScope * getScope() const
DIFile * getFile() const
DIScope * getScope() const
DIType * getType() const
unsigned getLine() const
StringRef getName() const
Base class for non-instruction debug metadata records that have positions within IR.
const MachineInstr * CurMI
If nonnull, stores the current machine instruction we're processing.
AsmPrinter * Asm
Target of debug info emission.
void beginModule(Module *M) override
Utility to find all debug info in a module.
Definition DebugInfo.h:105
LLVM_ABI void processModule(const Module &M)
Process entire module and collect debug info anchors.
iterator_range< global_variable_expression_iterator > global_variables() const
Definition DebugInfo.h:155
iterator_range< subprogram_iterator > subprograms() const
Definition DebugInfo.h:153
iterator_range< type_iterator > types() const
Definition DebugInfo.h:159
iterator_range< scope_iterator > scopes() const
Definition DebugInfo.h:161
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:250
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:299
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:765
DISubprogram * getSubprogram() const
Get the attached subprogram.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
constexpr bool isValid() const
Definition MCRegister.h:84
constexpr unsigned id() const
Definition MCRegister.h:82
Tracking metadata reference owned by Metadata.
Definition Metadata.h:891
bool equalsStr(StringRef Str) const
Definition Metadata.h:913
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock & front() const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A tuple of MDNodes.
Definition Metadata.h:1755
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
void emitNonSemanticDebugStrings(SPIRV::ModuleAnalysisInfo &MAI)
Emit OpString instructions for all NSDI file paths and basic type names into the debug section (secti...
void beginModule(Module *M) override
Collect compile-unit metadata from the module.
void endFunctionImpl(const MachineFunction *MF) override
void beginFunctionImpl(const MachineFunction *MF) override
void emitNonSemanticGlobalDebugInfo(SPIRV::ModuleAnalysisInfo &MAI)
Emit module-scope NSDI instructions (DebugSource, DebugCompilationUnit, DebugTypeBasic,...
void prepareModuleOutput(const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI)
Add SPV_KHR_non_semantic_info extension and NonSemantic.Shader.DebugInfo.100 ext inst set entry to MA...
void endInstruction() override
Process end of an instruction.
void notifyEntryLabelEmitted(const MachineFunction &MF)
Called after the synthesized entry OpLabel has been emitted.
A vector that has set insertion semantics.
Definition SetVector.h:57
bool contains(const_arg_type key) const
Check if the SetVector contains the given key.
Definition SetVector.h:258
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
void assign(StringRef RHS)
Assign from a StringRef.
Definition SmallString.h:51
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
iterator begin() const
Definition StringRef.h:114
iterator end() const
Definition StringRef.h:116
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition Path.cpp:688
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition Path.cpp:467
This is an optimization pass for GlobalISel generic memory operations.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
Definition STLExtras.h:830
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1732
void addStringImm(StringRef Str, MCInst &Inst)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto map_to_vector(ContainerTy &&C, FuncTy &&F)
Map a range to a SmallVector with element types deduced from the mapping.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
bool isa_and_nonnull(const Y &Val)
Definition Casting.h:676
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
Definition Error.cpp:173
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
Definition STLExtras.h:1151
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
Definition STLExtras.h:551
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
Definition Casting.h:866
MCRegister getExtInstSetReg(unsigned SetNum)
DenseMap< unsigned, MCRegister > ExtInstSetMap
InstrList & getMSInstrs(unsigned MSType)
MCRegister getRegisterAlias(const MachineFunction *MF, Register Reg)
bool getSkipEmission(const MachineInstr *MI)
MCRegister getGlobalObjReg(const GlobalObject *GO)
void addExtension(Extension::Extension ToAdd)