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"
22#include "llvm/IR/DebugInfo.h"
28#include "llvm/IR/Module.h"
29#include "llvm/MC/MCInst.h"
30#include "llvm/MC/MCStreamer.h"
33#include "llvm/Support/Path.h"
34#include <cassert>
35
36using namespace llvm;
37
38namespace {
39
40/// Look up \p Key in a register map and return its value, or std::nullopt when
41/// the key is absent.
42template <typename MapT>
43static std::optional<MCRegister> lookupOptReg(const MapT &Map,
44 typename MapT::key_type Key) {
45 auto It = Map.find(Key);
46 if (It == Map.end())
47 return std::nullopt;
48 assert(It->second.isValid() && "invalid register stored in map");
49 return It->second;
50}
51
52/// Partition \p Ty into \p BasicTypes, \p PointerTypes, \p SubroutineTypes,
53/// \p VectorTypes, \p ArrayTypes, \p CompositeTypes, and \p TypedefTypes for
54/// NSDI emission. Used when iterating DebugInfoFinder.types(); each DI node is
55/// seen once, so no recursion into pointer bases. Other composites and the
56/// remaining derived kinds are ignored because they are not yet supported.
57/// Only types that are supported (later used) are partitioned.
58static void
59partitionTypes(const DIType *Ty, SmallVector<const DIBasicType *> &BasicTypes,
66 if (const auto *BT = dyn_cast<DIBasicType>(Ty)) {
67 BasicTypes.push_back(BT);
68 return;
69 }
70 if (const auto *ST = dyn_cast<DISubroutineType>(Ty)) {
71 SubroutineTypes.push_back(ST);
72 return;
73 }
74 if (const auto *CT = dyn_cast<DICompositeType>(Ty)) {
75 if (CT->getTag() == dwarf::DW_TAG_array_type) {
76 // A vector is an array with DINode::FlagVector. A plain array is the
77 // same tag without it. A matrix is also lowered to a DW_TAG_array_type
78 // (two subranges), so it is indistinguishable from a 2D array here and
79 // is emitted as a DebugTypeArray.
80 //
81 // FIXME: Emitting a matrix as a DebugTypeArray is valid but loses the
82 // matrix shape. DWARF has no matrix tag, so distinguishing a matrix needs
83 // a new DINode flag analogous to FlagVector, set on the array, plus a way
84 // to carry column-major vs row-major traits. Array-of-vectors alone would
85 // not disambiguate a matrix from a genuine array of vectors. Once the
86 // frontend marks matrices, route them to a DebugTypeMatrix path here.
87 if (CT->isVector())
88 VectorTypes.push_back(CT);
89 else
90 ArrayTypes.push_back(CT);
91 } else if (CT->getTag() == dwarf::DW_TAG_structure_type ||
92 CT->getTag() == dwarf::DW_TAG_class_type ||
93 CT->getTag() == dwarf::DW_TAG_union_type) {
94 CompositeTypes.push_back(CT);
95 }
96 return;
97 }
98 const auto *DT = dyn_cast<DIDerivedType>(Ty);
99 if (DT && DT->getTag() == dwarf::DW_TAG_pointer_type)
100 PointerTypes.push_back(DT);
101 else if (DT && DT->getTag() == dwarf::DW_TAG_typedef)
102 TypedefTypes.push_back(DT);
103}
104
105enum : uint32_t {
106 NSDIFlagIsProtected = 1u << 0,
107 NSDIFlagIsPrivate = 1u << 1,
108 NSDIFlagIsPublic = NSDIFlagIsPrivate | NSDIFlagIsProtected,
109 NSDIFlagIsLocal = 1u << 2,
110 NSDIFlagIsDefinition = 1u << 3,
111 NSDIFlagFwdDecl = 1u << 4,
112 NSDIFlagArtificial = 1u << 5,
113 NSDIFlagExplicit = 1u << 6,
114 NSDIFlagPrototyped = 1u << 7,
115 NSDIFlagObjectPointer = 1u << 8,
116 NSDIFlagStaticMember = 1u << 9,
117 NSDIFlagIndirectVariable = 1u << 10,
118 NSDIFlagLValueReference = 1u << 11,
119 NSDIFlagRValueReference = 1u << 12,
120 NSDIFlagIsOptimized = 1u << 13,
121 NSDIFlagIsEnumClass = 1u << 14,
122 NSDIFlagTypePassByValue = 1u << 15,
123 NSDIFlagTypePassByReference = 1u << 16,
124 NSDIFlagUnknownPhysicalLayout = 1u << 17,
125};
126
127static uint32_t mapDIFlagsToNonSemantic(DINode::DIFlags DFlags) {
128 uint32_t Flags = 0;
129 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPublic)
130 Flags |= NSDIFlagIsPublic;
131 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagProtected)
132 Flags |= NSDIFlagIsProtected;
133 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPrivate)
134 Flags |= NSDIFlagIsPrivate;
135 if (DFlags & DINode::FlagFwdDecl)
136 Flags |= NSDIFlagFwdDecl;
137 if (DFlags & DINode::FlagArtificial)
138 Flags |= NSDIFlagArtificial;
139 if (DFlags & DINode::FlagExplicit)
140 Flags |= NSDIFlagExplicit;
141 if (DFlags & DINode::FlagPrototyped)
142 Flags |= NSDIFlagPrototyped;
143 if (DFlags & DINode::FlagObjectPointer)
144 Flags |= NSDIFlagObjectPointer;
145 if (DFlags & DINode::FlagStaticMember)
146 Flags |= NSDIFlagStaticMember;
147 if (DFlags & DINode::FlagLValueReference)
148 Flags |= NSDIFlagLValueReference;
149 if (DFlags & DINode::FlagRValueReference)
150 Flags |= NSDIFlagRValueReference;
151 if (DFlags & DINode::FlagTypePassByValue)
152 Flags |= NSDIFlagTypePassByValue;
153 if (DFlags & DINode::FlagTypePassByReference)
154 Flags |= NSDIFlagTypePassByReference;
155 if (DFlags & DINode::FlagEnumClass)
156 Flags |= NSDIFlagIsEnumClass;
157 return Flags;
158}
159
160static uint32_t transDebugFlags(const DINode *DN) {
161 uint32_t Flags = 0;
162 if (const auto *GV = dyn_cast<DIGlobalVariable>(DN)) {
163 if (GV->isLocalToUnit())
164 Flags |= NSDIFlagIsLocal;
165 if (GV->isDefinition())
166 Flags |= NSDIFlagIsDefinition;
167 }
168 if (const auto *SP = dyn_cast<DISubprogram>(DN)) {
169 if (SP->isLocalToUnit())
170 Flags |= NSDIFlagIsLocal;
171 if (SP->isOptimized())
172 Flags |= NSDIFlagIsOptimized;
173 if (SP->isDefinition())
174 Flags |= NSDIFlagIsDefinition;
175 Flags |= mapDIFlagsToNonSemantic(SP->getFlags());
176 }
177 if (DN->getTag() == dwarf::DW_TAG_reference_type)
178 Flags |= NSDIFlagLValueReference;
179 if (DN->getTag() == dwarf::DW_TAG_rvalue_reference_type)
180 Flags |= NSDIFlagRValueReference;
181 if (const auto *Ty = dyn_cast<DIType>(DN))
182 Flags |= mapDIFlagsToNonSemantic(Ty->getFlags());
183 if (const auto *LV = dyn_cast<DILocalVariable>(DN))
184 Flags |= mapDIFlagsToNonSemantic(LV->getFlags());
185 return Flags;
186}
187
188// Map a DWARF composite tag to a NonSemantic.Shader.DebugInfo Composite Type
189// value: Class 0, Structure 1, Union 2.
190static uint32_t mapCompositeTypeTag(unsigned Tag) {
191 switch (Tag) {
192 case dwarf::DW_TAG_class_type:
193 return 0;
194 case dwarf::DW_TAG_structure_type:
195 return 1;
196 case dwarf::DW_TAG_union_type:
197 return 2;
198 default:
199 reportFatalInternalError("unexpected DWARF composite tag " + Twine(Tag) +
200 ". Expecting 0, 1 or 2");
201 }
202}
203
204static const MachineInstr *
205findLastFunctionOpVariableDeclaration(const MachineFunction &MF,
207
208 // We iterate over the instructions to find the last OpVariable instruction if
209 // any. The following SPIRV rule is used to terminate the traversal earlier:
210 // SPIR-V 2.16.1, Function Structure: "All OpVariable instructions in a
211 // function must be in the first block in the function. These instructions,
212 // together with any intermixed OpLine and OpNoLine instructions, must be the
213 // first instructions in that block."
214 const MachineInstr *LastOpVariable = nullptr;
215 bool SeenOpVariable = false;
216 for (const MachineInstr &MI : MF.front()) {
217 if (MI.getOpcode() == SPIRV::OpVariable) {
218 SeenOpVariable = true;
219 if (!MAI.getSkipEmission(&MI))
220 LastOpVariable = &MI;
221 continue;
222 }
223
224 bool CanInterleaveWithOpVariable =
225 MI.getOpcode() == SPIRV::OpLine || MI.getOpcode() == SPIRV::OpNoLine;
226 if (SeenOpVariable && !CanInterleaveWithOpVariable &&
227 !MAI.getSkipEmission(&MI))
228 break;
229 }
230 return LastOpVariable;
231}
232
233} // namespace
234
237
238// Map DWARF source language codes to NonSemantic.Shader.DebugInfo.100 source
239// language codes. Values are from the SourceLanguage enum in the
240// NonSemantic.Shader.DebugInfo.100 specification, section 4.3.
241unsigned SPIRVNonSemanticDebugHandler::toNSDISrcLang(unsigned DwarfSrcLang) {
242 switch (DwarfSrcLang) {
243 case dwarf::DW_LANG_OpenCL:
244 return 3; // OpenCL_C
245 case dwarf::DW_LANG_OpenCL_CPP:
246 return 4; // OpenCL_CPP
247 case dwarf::DW_LANG_CPP_for_OpenCL:
248 return 6; // CPP_for_OpenCL
249 case dwarf::DW_LANG_GLSL:
250 return 2; // GLSL
251 case dwarf::DW_LANG_HLSL:
252 return 5; // HLSL
253 case dwarf::DW_LANG_SYCL:
254 return 7; // SYCL
255 case dwarf::DW_LANG_Zig:
256 return 12; // Zig
257 default:
258 return 0; // Unknown
259 }
260}
261
262// Collect distinct DILocations and DILocalVariables from LLVM IR.
263//
264// DILocations come from instruction debug locations and from the debug records
265// attached to them. DebugLine pre-emission and MIR lookups assume every
266// machine-instruction debug location already appeared here; a codegen-only
267// location would not be collected and emission will be skipped.
268//
269// DILocalVariables come from the DbgVariableRecords attached to instructions
270// and from the retained nodes of each DISubprogram. Retained nodes are needed
271// because a variable with no remaining debug record (e.g. optimized away) must
272// still get a DebugLocalVariable.
274 const Module &M, SetVector<const DILocation *> &Locations,
276 for (const Function &F : M) {
277 const DISubprogram *SP = F.getSubprogram();
278 if (!SP)
279 continue;
280 for (const MDNode *N : SP->getRetainedNodes())
281 if (const auto *LV = dyn_cast_or_null<DILocalVariable>(N))
282 LVs.insert(LV);
283 for (const Instruction &I : instructions(F)) {
284 if (const DILocation *DL = I.getDebugLoc().get())
285 Locations.insert(DL);
286 for (DbgRecord &DR : I.getDbgRecordRange()) {
287 if (const DILocation *DL = DR.getDebugLoc().get())
288 Locations.insert(DL);
289 if (const auto *DVR = dyn_cast<DbgVariableRecord>(&DR))
290 if (const DILocalVariable *LV = DVR->getVariable())
291 LVs.insert(LV);
292 }
293 }
294 }
295}
296
297// Insert \p S and its enclosing DILexicalBlock/DINamespace chain into \p Out,
298// parent before child, so single-pass emission never needs a forward
299// reference for the Parent operand.
302 // Walk up child-first, then insert in reverse to get parents in first.
304 while (S && !Out.contains(S) && isa<DILexicalBlock, DINamespace>(S)) {
305 Chain.push_back(S);
306 S = S->getScope();
307 }
308 Out.insert(Chain.rbegin(), Chain.rend());
309}
310
312 // The base class sets Asm = nullptr when the module has no compile units,
313 // and initializes lexical scope tracking otherwise.
315
316 if (!Asm)
317 return;
318
319 CompileUnits.clear();
320 BasicTypes.clear();
321 PointerTypes.clear();
322 SubroutineTypes.clear();
323 VectorTypes.clear();
324 ArrayTypes.clear();
325 CompositeTypes.clear();
326 TypedefTypes.clear();
327 SubprogramDeclarations.clear();
328 SubprogramDefinitions.clear();
329 UniqueDebugLocations.clear();
330 GlobalVariableDebugInfoMap.clear();
331 LocalVariables.clear();
332 DebugLocalVariableRegs.clear();
333 DebugExpressionRegs.clear();
334 LexicalBlocks.clear();
335 DebugScopeRegs.clear();
336 DebugInlinedAtRegs.clear();
337 ScopeToPathOpStringReg.clear();
338 DebugSourceRegByFileStr.clear();
339 OpStringContentCache.clear();
340 I32ConstantCache.clear();
341 DebugTypeFunctionCache.clear();
342 DebugOperationCache.clear();
343 DebugExpressionCache.clear();
344 GlobalDIEmitted = false;
345 GlobalNSDIEnabled = false;
346 CurrentMAI = nullptr;
347#ifndef NDEBUG
348 NonSemanticOpStringsSectionEmitted = false;
349#endif
350 CachedDebugInfoNoneReg = MCRegister();
351 CachedEmptyStringReg = MCRegister();
352 CachedOpTypeVoidReg = MCRegister();
353 CachedOpTypeInt32Reg = MCRegister();
354
355 // Collect compile-unit info: file paths and source languages.
356 for (const DICompileUnit *CU : M->debug_compile_units()) {
357 const DIFile *File = CU->getFile();
358 CompileUnitInfo Info;
359 Info.TheCU = CU;
360 if (sys::path::is_absolute(File->getFilename()))
361 Info.FilePath = File->getFilename();
362 else
363 sys::path::append(Info.FilePath, File->getDirectory(),
364 File->getFilename());
365 // getName() returns the language code regardless of whether the name is
366 // versioned. getUnversionedName() would assert on versioned names.
367 Info.SpirvSourceLanguage = toNSDISrcLang(CU->getSourceLanguage().getName());
368 CompileUnits.push_back(std::move(Info));
369 }
370
371 // Collect DWARF version from module flags. For CodeView modules there is no
372 // "Dwarf Version" flag; DwarfVersion remains 0, which is the correct value
373 // for the DebugCompilationUnit DWARF Version operand in that case.
374 if (const NamedMDNode *Flags = M->getNamedMetadata("llvm.module.flags")) {
375 for (const auto *Op : Flags->operands()) {
376 const MDOperand &NameOp = Op->getOperand(1);
377 if (NameOp.equalsStr("Dwarf Version"))
378 DwarfVersion =
380 cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
381 ->getSExtValue();
382 }
383 }
384
385 // Find all debug info types that may be referenced by NSDI instructions.
386 DebugInfoFinder Finder;
387 Finder.processModule(*M);
388 llvm::for_each(Finder.types(), [&](DIType *Ty) {
389 partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes, VectorTypes,
390 ArrayTypes, CompositeTypes, TypedefTypes);
391 });
392
393 for (const DISubprogram *SP : Finder.subprograms()) {
394 if (SP->isDefinition())
395 SubprogramDefinitions.push_back(SP);
396 else
397 SubprogramDeclarations.push_back(SP);
398 }
399
400 // Walk LLVM globals to map each DIGlobalVariable to its llvm::GlobalVariable.
402 for (const GlobalVariable &G : M->globals()) {
404 G.getDebugInfo(GVEs);
405 for (DIGlobalVariableExpression *GVE : GVEs) {
406 if (const DIGlobalVariable *GV = GVE->getVariable()) {
407 DIGVToLLVMGV.try_emplace(GV, &G);
408 }
409 }
410 }
411
412 for (const DIGlobalVariableExpression *GVE : Finder.global_variables()) {
413 const DIGlobalVariable *GV = GVE->getVariable();
414 const DIExpression *Expr = GVE->getExpression();
415 GlobalVariableDebugInfoMap.try_emplace(
416 GV, GlobalVariableDebugInfo{Expr, DIGVToLLVMGV.lookup(GV)});
417 }
418
419 collectDebugLocationsAndLocalVariables(*M, UniqueDebugLocations,
420 LocalVariables);
421
422 // DILexicalBlock and DINamespace scopes are lowered to DebugLexicalBlock.
423 // Collect them in parent-before-child order so they can be later emitted in a
424 // single pass.
425 for (const DIScope *S : Finder.scopes())
426 collectLexicalBlockChain(S, LexicalBlocks);
427}
428
431 if (CompileUnits.empty())
432 return;
433 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_non_semantic_info))
434 return;
435
436 // Add the extension to requirements so OpExtension is output.
437 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
438
439 // Add the NonSemantic.Shader.DebugInfo.100 entry to ExtInstSetMap so that
440 // outputOpExtInstImports() emits the OpExtInstImport instruction. Allocate a
441 // fresh result ID for it now; the same ID is used in emitExtInst() operands.
442 if (!MAI.ExtInstSetMap.count(NSSet))
443 MAI.ExtInstSetMap[NSSet] = MAI.getNextIDRegister();
444}
445
446void SPIRVNonSemanticDebugHandler::emitMCInst(MCInst &Inst) {
447 Asm->OutStreamer->emitInstruction(Inst, Asm->getSubtargetInfo());
448}
449
451SPIRVNonSemanticDebugHandler::emitOpString(StringRef S,
454 MCInst Inst;
455 Inst.setOpcode(SPIRV::OpString);
457 addStringImm(S, Inst);
458 emitMCInst(Inst);
459 return Reg;
460}
461
462MCRegister SPIRVNonSemanticDebugHandler::emitOpStringIfNew(
464#ifndef NDEBUG
465 assert(!NonSemanticOpStringsSectionEmitted &&
466 "emitOpStringIfNew is only valid while emitting SPIR-V section 7");
467#endif
468 auto [It, Inserted] = OpStringContentCache.try_emplace(S, MCRegister());
469 if (Inserted)
470 It->second = emitOpString(S, MAI);
471
472 return It->second;
473}
474
475MCRegister SPIRVNonSemanticDebugHandler::getCachedOpStringReg(StringRef S) {
476#ifndef NDEBUG
477 assert(NonSemanticOpStringsSectionEmitted &&
478 "getCachedOpStringReg requires emitNonSemanticDebugStrings() first");
479#endif
480 auto It = OpStringContentCache.find(S);
481 assert(It != OpStringContentCache.end() &&
482 "NSDI OpString missing from cache; emitNonSemanticDebugStrings must "
483 "cache every string used in section 10");
484 return It->second;
485}
486
487MCRegister SPIRVNonSemanticDebugHandler::emitAndCacheScopePathOpStringReg(
488 const DIScope *Scope, SPIRV::ModuleAnalysisInfo &MAI) {
489 auto [It, Inserted] = ScopeToPathOpStringReg.try_emplace(Scope, MCRegister());
490 if (Inserted)
491 It->second = emitOpStringIfNew(getDebugFullPath(Scope), MAI);
492 return It->second;
493}
494
495MCRegister SPIRVNonSemanticDebugHandler::getCachedScopePathOpStringReg(
496 const DIScope *Scope, bool UseEmptyPathIfNullScope) {
497 if (!Scope) {
498 assert(UseEmptyPathIfNullScope &&
499 "null scope path lookup requires UseEmptyPathIfNullScope");
500 assert(CachedEmptyStringReg.isValid() &&
501 "empty path OpString must be cached in emitNonSemanticDebugStrings");
502 return CachedEmptyStringReg;
503 }
504 auto It = ScopeToPathOpStringReg.find(Scope);
505 assert(It != ScopeToPathOpStringReg.end() &&
506 "path OpString must be cached in emitNonSemanticDebugStrings");
507 MCRegister FileStrReg = It->second;
508 assert(FileStrReg.isValid() && "path OpString id must be valid once cached");
509 return FileStrReg;
510}
511
512MCRegister SPIRVNonSemanticDebugHandler::emitOpConstantI32(
513 uint32_t Value, MCRegister I32TypeReg, SPIRV::ModuleAnalysisInfo &MAI) {
514 auto [It, Inserted] = I32ConstantCache.try_emplace(Value);
515 if (!Inserted)
516 return It->second;
517
518 MCRegister Reg = MAI.getNextIDRegister();
519 It->second = Reg;
520 MCInst Inst;
521 Inst.setOpcode(SPIRV::OpConstantI);
523 Inst.addOperand(MCOperand::createReg(I32TypeReg));
524 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Value)));
525 emitMCInst(Inst);
526 return Reg;
527}
528
529MCRegister SPIRVNonSemanticDebugHandler::emitExtInst(
530 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
531 MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
533 MCRegister Reg = MAI.getNextIDRegister();
534 MCInst Inst;
535 Inst.setOpcode(SPIRV::OpExtInst);
537 Inst.addOperand(MCOperand::createReg(VoidTypeReg));
538 Inst.addOperand(MCOperand::createReg(ExtInstSetReg));
539 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Opcode)));
540 for (MCRegister R : Operands)
542 emitMCInst(Inst);
543 return Reg;
544}
545
546MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugTypeFunction(
547 ArrayRef<MCRegister> Ops, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
549 auto [It, Inserted] =
550 DebugTypeFunctionCache.try_emplace(SmallVector<MCRegister, 8>(Ops));
551 if (!Inserted)
552 return It->second;
553
554 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeFunction,
555 VoidTypeReg, ExtInstSetReg, Ops, MAI);
556 It->second = Reg;
557 return Reg;
558}
559
560MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeVoidReg(
562 if (!CachedOpTypeVoidReg.isValid())
563 CachedOpTypeVoidReg = findOrEmitOpTypeVoid(MAI);
564 return CachedOpTypeVoidReg;
565}
566
567MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeInt32Reg(
569 if (!CachedOpTypeInt32Reg.isValid())
570 CachedOpTypeInt32Reg = findOrEmitOpTypeInt32(MAI);
571 return CachedOpTypeInt32Reg;
572}
573
574MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
576 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
577 if (MI->getOpcode() == SPIRV::OpTypeVoid)
578 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
579 }
580 MCRegister Reg = MAI.getNextIDRegister();
581 MCInst Inst;
582 Inst.setOpcode(SPIRV::OpTypeVoid);
584 emitMCInst(Inst);
585 return Reg;
586}
587
588MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
590 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
591 if (MI->getOpcode() == SPIRV::OpTypeInt &&
592 MI->getOperand(1).getImm() == 32 && MI->getOperand(2).getImm() == 0)
593 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
594 }
595 MCRegister Reg = MAI.getNextIDRegister();
596 MCInst Inst;
597 Inst.setOpcode(SPIRV::OpTypeInt);
599 Inst.addOperand(MCOperand::createImm(32)); // width
600 Inst.addOperand(MCOperand::createImm(0)); // signedness (unsigned)
601 emitMCInst(Inst);
602 return Reg;
603}
604
605std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
606 const DIDerivedType *PT, MCRegister ExtInstSetReg,
608 // A DWARF address space is required to determine the SPIR-V storage class.
609 // Skip pointer types that do not carry one.
610 if (!PT->getDWARFAddressSpace().has_value())
611 return std::nullopt;
612
613 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
614 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
615 MCRegister DebugTypePointerFlagsReg =
616 emitOpConstantI32(transDebugFlags(PT), I32TypeReg, MAI);
617
618 // For SPIR-V targets, Clang sets DwarfAddressSpace to the LLVM IR address
619 // space, which addressSpaceToStorageClass expects.
620 const auto &ST = static_cast<const SPIRVSubtarget &>(Asm->getSubtargetInfo());
621 MCRegister StorageClassReg = emitOpConstantI32(
622 addressSpaceToStorageClass(PT->getDWARFAddressSpace().value(), ST),
623 I32TypeReg, MAI);
624
625 if (const DIType *BaseTy = PT->getBaseType()) {
626 auto BaseIt = DebugScopeRegs.find(BaseTy);
627 if (BaseIt != DebugScopeRegs.end())
628 return emitExtInst(
629 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
630 ExtInstSetReg,
631 {BaseIt->second, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
632 // Unsupported type, no DebugType* id available.
633 return std::nullopt;
634 }
635 // No getBaseType() (typical for void*): use DebugInfoNone as Base Type,
636 // same as SPIRV-LLVM-Translator (see issue #109287 and the DISABLED
637 // spirv-val run in debug-type-pointer.ll). spirv-val may still reject this
638 // encoding; see https://github.com/KhronosGroup/SPIRV-Registry/pull/287.
639 return emitExtInst(
640 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg, ExtInstSetReg,
641 {CachedDebugInfoNoneReg, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
642}
643
644std::optional<MCRegister>
645SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
646 const DISubroutineType *ST, MCRegister ExtInstSetReg,
648 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
649 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
650 MCRegister DebugTypeFunctionFlagsReg =
651 emitOpConstantI32(transDebugFlags(ST), I32TypeReg, MAI);
652 DITypeArray TA = ST->getTypeArray();
654 Ops.push_back(DebugTypeFunctionFlagsReg);
655 // Empty DI type tuple: no explicit return or parameter slots (hand-written IR
656 // may use !{}). Emit void-only prototype. Same as SPIRV-LLVM-Translator when
657 // DISubroutineType::getTypeArray() has zero elements.
658 if (TA.empty()) {
659 Ops.push_back(VoidTypeReg);
660 } else {
661 for (unsigned I = 0, E = TA.size(); I != E; ++I) {
662 bool IsReturnType = (I == 0);
663 auto OptReg = mapDISignatureTypeToReg(TA[I], VoidTypeReg, IsReturnType);
664 // No emitted DebugType* id for this slot (e.g., pointer that
665 // was skipped due missing address space, etc.).
666 if (!OptReg)
667 return std::nullopt;
668 Ops.push_back(*OptReg);
669 }
670 }
671 return getOrEmitDebugTypeFunction(Ops, VoidTypeReg, ExtInstSetReg, MAI);
672}
673
674// Match SPIRV-LLVM-Translator's selection logic for the Parent operand.
675std::optional<MCRegister> SPIRVNonSemanticDebugHandler::resolveScope(
676 const DIScope *Scope, const DICompileUnit *FallbackCU) const {
677
679 return lookupOptReg(DebugScopeRegs, Scope);
680
681 // For a file, compile-unit, or absent scope, fall back to a compile unit.
682 if (FallbackCU)
683 return lookupOptReg(DebugScopeRegs, FallbackCU);
684
685 if (CompileUnits.empty())
686 return std::nullopt;
687
688 return lookupOptReg(DebugScopeRegs, CompileUnits[0].TheCU);
689}
690
691std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLexicalBlock(
692 const DIScope *S, MCRegister VoidTypeReg, MCRegister I32TypeReg,
693 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
695 "S must be a DILexicalBlock or DINamespace in emitDebugLexicalBlock");
696 auto ParentRegOpt = resolveScope(S->getScope());
697 if (!ParentRegOpt)
698 return std::nullopt;
699
700 MCRegister FileStrReg = getCachedScopePathOpStringReg(
701 S->getFile(), /*UseEmptyPathIfNullScope=*/true);
702 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
703 ExtInstSetReg, MAI);
704
706 if (const auto *LB = dyn_cast<DILexicalBlock>(S)) {
707 MCRegister LineReg = emitOpConstantI32(static_cast<uint32_t>(LB->getLine()),
708 I32TypeReg, MAI);
709 MCRegister ColReg = emitOpConstantI32(
710 static_cast<uint32_t>(LB->getColumn()), I32TypeReg, MAI);
711 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt};
712 } else {
713 const auto *NS = cast<DINamespace>(S);
714 // DINamespace carries no line/column info.
715 MCRegister LineReg = emitOpConstantI32(0, I32TypeReg, MAI);
716 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
717 MCRegister NameReg = getCachedOpStringReg(NS->getName());
718 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt, NameReg};
719 }
720
721 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLexicalBlock, VoidTypeReg,
722 ExtInstSetReg, Ops, MAI);
723}
724
725MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugInlinedAt(
726 const DILocation *IA, MCRegister VoidTypeReg, MCRegister I32TypeReg,
727 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
728 assert(IA && "IA must not be null in getOrEmitDebugInlinedAt");
729
730 if (MCRegister Cached = DebugInlinedAtRegs.lookup(IA))
731 return Cached;
732
733 auto ScopeRegOpt = resolveScope(IA->getScope());
734 if (!ScopeRegOpt)
735 return MCRegister();
736
737 MCRegister LineReg =
738 emitOpConstantI32(static_cast<uint32_t>(IA->getLine()), I32TypeReg, MAI);
739
740 SmallVector<MCRegister, 3> Ops{LineReg, *ScopeRegOpt};
741 // Recurse before building this instruction's operands so an outer
742 // inlined-at link is always available.
743 if (const DILocation *Outer = IA->getInlinedAt()) {
744 MCRegister OuterReg = getOrEmitDebugInlinedAt(
745 Outer, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
746 if (!OuterReg.isValid())
747 return MCRegister();
748 Ops.push_back(OuterReg);
749 }
750
751 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInlinedAt,
752 VoidTypeReg, ExtInstSetReg, Ops, MAI);
753 DebugInlinedAtRegs[IA] = Reg;
754 return Reg;
755}
756
757std::optional<MCRegister>
758SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
759 const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
760 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
761 assert(SP && "SP must not be null in emitDebugFunctionDeclaration");
762 assert(!SP->isDefinition() &&
763 "SP must not be a definition in emitDebugFunctionDeclaration");
764
765 // The IR verifier already enforces that this cannot be null.
766 const DISubroutineType *ST = SP->getType();
767
768 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
769 if (!FnTyRegOpt)
770 return std::nullopt;
771 MCRegister FnTyReg = *FnTyRegOpt;
772
773 auto ParentRegOpt = resolveScope(SP->getScope(), SP->getUnit());
774 if (!ParentRegOpt)
775 return std::nullopt;
776
777 MCRegister ParentReg = *ParentRegOpt;
778
779 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
780
781 MCRegister NameReg = getCachedOpStringReg(SP->getName());
782 MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
783 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
784 ExtInstSetReg, MAI);
785
786 MCRegister LineReg =
787 emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
788 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
789
790 uint32_t FlagsVal = transDebugFlags(SP);
791 // TODO: When composite scopes are DebugFunctionDeclaration parents (available
792 // in DebugScopeRegs), sync declaration Flags with SPIRV-LLVM-Translator.
793 FlagsVal &= ~NSDIFlagIsDefinition;
794 MCRegister FlagsReg = emitOpConstantI32(FlagsVal, I32TypeReg, MAI);
795
796 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
797 VoidTypeReg, ExtInstSetReg,
798 {NameReg, FnTyReg, SrcReg, LineReg, ColReg, ParentReg,
799 LinkageReg, FlagsReg},
800 MAI);
801}
802
803std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugFunction(
804 const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
805 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
806 assert(SP && "SP must not be null in emitDebugFunction");
807 assert(SP->isDefinition() && "SP must be a definition in emitDebugFunction");
808
809 const DISubroutineType *ST = SP->getType();
810 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
811 if (!FnTyRegOpt)
812 return std::nullopt;
813
814 auto ParentRegOpt = resolveScope(SP->getScope(), SP->getUnit());
815 if (!ParentRegOpt)
816 return std::nullopt;
817
818 MCRegister NameReg = getCachedOpStringReg(SP->getName());
819 MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
820 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
821 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
822 ExtInstSetReg, MAI);
823
824 MCRegister LineReg =
825 emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
826 // LLVM's DISubprogram has no column field but SPIR-V expects one in
827 // DebugFunction.
828 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
829 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(SP), I32TypeReg, MAI);
830 MCRegister ScopeLineReg = emitOpConstantI32(
831 static_cast<uint32_t>(SP->getScopeLine()), I32TypeReg, MAI);
832
833 SmallVector<MCRegister, 10> Ops = {NameReg, *FnTyRegOpt, SrcReg,
834 LineReg, ColReg, *ParentRegOpt,
835 LinkageReg, FlagsReg, ScopeLineReg};
836
837 if (const DISubprogram *Decl = SP->getDeclaration()) {
838 if (auto DeclRegOpt = lookupOptReg(DebugScopeRegs, Decl))
839 Ops.push_back(*DeclRegOpt);
840 }
841
842 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunction, VoidTypeReg,
843 ExtInstSetReg, Ops, MAI);
844}
845
846std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
847 const DIType *Ty, MCRegister VoidTypeReg, bool ReturnType) {
848 if (!Ty) {
849 if (ReturnType)
850 return VoidTypeReg;
851 assert(CachedDebugInfoNoneReg.isValid() &&
852 "DebugInfoNone must be emitted before DISubroutineType operands");
853 return CachedDebugInfoNoneReg;
854 }
855 return lookupOptReg(DebugScopeRegs, Ty);
856}
857
858// NonSemantic.Shader.DebugInfo.100 debug operation encodings
859// (section 4.5, "Debug Operations").
872
873static std::optional<NonSemanticDebugOp>
875 switch (DwarfOp) {
876 case dwarf::DW_OP_deref:
878 case dwarf::DW_OP_plus:
880 case dwarf::DW_OP_minus:
882 case dwarf::DW_OP_plus_uconst:
884 case dwarf::DW_OP_bit_piece:
886 case dwarf::DW_OP_swap:
888 case dwarf::DW_OP_xderef:
890 case dwarf::DW_OP_stack_value:
892 case dwarf::DW_OP_constu:
896 default:
897 return std::nullopt;
898 }
899}
900
901std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugOperation(
902 const DIExpression::ExprOperand &Op, MCRegister VoidTypeReg,
903 MCRegister I32TypeReg, MCRegister ExtInstSetReg,
905 std::optional<NonSemanticDebugOp> NSOp =
907 if (!NSOp)
908 return std::nullopt;
909
910 SmallVector<uint32_t, 3> Key{static_cast<uint32_t>(*NSOp)};
911 for (unsigned I = 0, E = Op.getNumArgs(); I != E; ++I) {
912 uint64_t Arg = Op.getArg(I);
913 if (!isUInt<32>(Arg))
914 return std::nullopt;
915 Key.push_back(static_cast<uint32_t>(Arg));
916 }
917
918 auto [It, Inserted] = DebugOperationCache.try_emplace(std::move(Key));
919 if (!Inserted)
920 return It->second;
921
923 for (uint32_t V : It->first)
924 Operands.push_back(emitOpConstantI32(V, I32TypeReg, MAI));
925 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugOperation,
926 VoidTypeReg, ExtInstSetReg, Operands, MAI);
927 It->second = Reg;
928 return Reg;
929}
930
931std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugExpression(
932 const DIExpression *Expr, MCRegister VoidTypeReg, MCRegister I32TypeReg,
933 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
934 assert(Expr && "Expr must not be null in emitDebugExpression");
935
936 SmallVector<MCRegister> OperationRegs;
937 for (const DIExpression::ExprOperand &Op : Expr->expr_ops()) {
938 std::optional<MCRegister> OpReg =
939 emitDebugOperation(Op, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
940 if (!OpReg)
941 return std::nullopt;
942 OperationRegs.push_back(*OpReg);
943 }
944
945 auto [It, Inserted] =
946 DebugExpressionCache.try_emplace(std::move(OperationRegs));
947 if (!Inserted)
948 return It->second;
949
950 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugExpression,
951 VoidTypeReg, ExtInstSetReg, It->first, MAI);
952 It->second = Reg;
953 return Reg;
954}
955
956std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugGlobalVariable(
957 const DIGlobalVariable *GV, const GlobalVariableDebugInfo &Info,
958 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
960 assert(GV && "GV must not be null in emitDebugGlobalVariable");
961
962 auto ParentRegOpt = resolveScope(GV->getScope());
963 if (!ParentRegOpt)
964 return std::nullopt;
965
966 MCRegister ParentReg = *ParentRegOpt;
967
968 // TyReg: DebugInfoNone when GV has no DI type (as done in
969 // SPIRV-LLVM-Translator). Declarations (isDefinition: false) can have null
970 // getType() while definitions must have a non-null one (enforced by the IR
971 // verifier).
972 MCRegister TyReg = CachedDebugInfoNoneReg;
973 if (const DIType *Ty = GV->getType()) {
974 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
975 if (!TyRegOpt)
976 return std::nullopt;
977 TyReg = *TyRegOpt;
978 }
979
980 std::optional<MCRegister> StaticMemberRegOpt;
981 if (const DIDerivedType *SM = GV->getStaticDataMemberDeclaration()) {
982 StaticMemberRegOpt = lookupOptReg(DebugScopeRegs, SM);
983 if (!StaticMemberRegOpt)
984 return std::nullopt;
985 }
986
987 MCRegister NameReg = getCachedOpStringReg(GV->getName());
988 MCRegister LinkageReg = getCachedOpStringReg(GV->getLinkageName());
989 MCRegister FileStrReg = getCachedScopePathOpStringReg(
990 GV->getFile(), /*UseEmptyPathIfNullScope=*/true);
991 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
992 ExtInstSetReg, MAI);
993
994 MCRegister LineReg =
995 emitOpConstantI32(static_cast<uint32_t>(GV->getLine()), I32TypeReg, MAI);
996 // DIGlobalVariable or DIGlobalVariableExpression metadata carry no column
997 // field. Column is hardcoded to 0 (because it can't be determined), matching
998 // SPIRV-LLVM-Translator.
999 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1000
1001 // Variable: @g OpVariable id when !dbg matches; else a DebugExpression for
1002 // the GVE init value when no @g exists and the expression is non-empty; else
1003 // DebugInfoNone. As per spec, the DebugExpression must contain the constant
1004 // value of the variable that was optimized out. An empty expression contains
1005 // no value, so we emit DebugInfoNone instead.
1006 MCRegister VariableReg = CachedDebugInfoNoneReg;
1007 if (const GlobalVariable *LLVMGV = Info.LLVMGV) {
1008 MCRegister GVReg = MAI.getGlobalObjReg(LLVMGV);
1009 if (GVReg.isValid())
1010 VariableReg = GVReg;
1011 } else if (Info.Expr && Info.Expr->getNumElements() != 0) {
1012 if (auto ExprReg = emitDebugExpression(Info.Expr, VoidTypeReg, I32TypeReg,
1013 ExtInstSetReg, MAI))
1014 VariableReg = *ExprReg;
1015 }
1016
1017 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(GV), I32TypeReg, MAI);
1018
1019 SmallVector<MCRegister, 10> Ops = {NameReg, TyReg, SrcReg,
1020 LineReg, ColReg, ParentReg,
1021 LinkageReg, VariableReg, FlagsReg};
1022
1023 if (StaticMemberRegOpt)
1024 Ops.push_back(*StaticMemberRegOpt);
1025
1026 return emitExtInst(SPIRV::NonSemanticExtInst::DebugGlobalVariable,
1027 VoidTypeReg, ExtInstSetReg, Ops, MAI);
1028}
1029
1030std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLocalVariable(
1031 const DILocalVariable *LV, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1032 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1033 assert(LV && "LV must not be null in emitDebugLocalVariable");
1034
1035 auto ParentRegOpt = resolveScope(LV->getScope());
1036 if (!ParentRegOpt)
1037 return std::nullopt;
1038
1039 MCRegister TyReg = CachedDebugInfoNoneReg;
1040 if (const DIType *Ty = LV->getType()) {
1041 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1042 if (!TyRegOpt)
1043 return std::nullopt;
1044 TyReg = *TyRegOpt;
1045 }
1046
1047 MCRegister NameReg = getCachedOpStringReg(LV->getName());
1048 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1049 LV->getFile(), /*UseEmptyPathIfNullScope=*/true);
1050 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1051 ExtInstSetReg, MAI);
1052 MCRegister LineReg =
1053 emitOpConstantI32(static_cast<uint32_t>(LV->getLine()), I32TypeReg, MAI);
1054 // DILocalVariable has no column field. Column is hardcoded to 0.
1055 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1056 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(LV), I32TypeReg, MAI);
1057
1058 SmallVector<MCRegister, 8> Ops = {NameReg, TyReg, SrcReg, LineReg,
1059 ColReg, *ParentRegOpt, FlagsReg};
1060 if (unsigned Arg = LV->getArg())
1061 Ops.push_back(emitOpConstantI32(Arg, I32TypeReg, MAI));
1062
1063 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLocalVariable, VoidTypeReg,
1064 ExtInstSetReg, Ops, MAI);
1065}
1066
1067std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
1068 const DICompositeType *VT, MCRegister ExtInstSetReg,
1070 const auto *BaseTy = dyn_cast_or_null<DIBasicType>(VT->getBaseType());
1071 if (!BaseTy)
1072 return std::nullopt;
1073 auto BTIt = DebugScopeRegs.find(BaseTy);
1074 if (BTIt == DebugScopeRegs.end())
1075 return std::nullopt;
1076
1077 // DebugTypeVector models only 1D vectors (multi-subrange types cannot be
1078 // encoded).
1079 DINodeArray Elements = VT->getElements();
1080 if (Elements.size() != 1)
1081 return std::nullopt;
1082 const auto *SR = cast<DISubrange>(Elements[0]);
1083 const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount());
1084 if (!CI)
1085 return std::nullopt;
1086
1087 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1088 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1089 MCRegister CountReg = emitOpConstantI32(
1090 static_cast<uint32_t>(CI->getZExtValue()), I32TypeReg, MAI);
1091 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeVector, VoidTypeReg,
1092 ExtInstSetReg, {BTIt->second, CountReg}, MAI);
1093}
1094
1095std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeArray(
1096 const DICompositeType *AT, MCRegister ExtInstSetReg,
1098 // The element (base) type must already be in DebugScopeRegs. Unlike
1099 // DebugTypeVector, the element may be any debug type, not only a basic type.
1100 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, AT->getBaseType());
1101 if (!BaseRegOpt)
1102 return std::nullopt;
1103
1104 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1105 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1106
1108 Ops.push_back(*BaseRegOpt);
1109
1110 // One component count per DISubrange, in DWARF subrange order. Emit 0 for
1111 // counts that are not a compile-time constant (dynamic arrays). This matches
1112 // OpTypeRuntimeArray.
1113 for (const DINode *Element : AT->getElements()) {
1114 const auto *SR = dyn_cast<DISubrange>(Element);
1115 if (!SR)
1116 continue;
1117 // A DIVariable count (a variable-length array) is not a ConstantInt, so it
1118 // maps to 0 here. DebugTypeArray also allows a DebugLocalVariable or
1119 // DebugGlobalVariable id for it, but no frontend we target emits one. A
1120 // constant wider than 32 bits maps to 0 too, since the count operand is a
1121 // 32-bit OpConstant and such an array cannot occur in a shader.
1122 uint32_t Count = 0;
1123 if (const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount())) {
1124 const APInt &Value = CI->getValue();
1125 if (Value.getActiveBits() <= 32)
1126 Count = static_cast<uint32_t>(Value.getZExtValue());
1127 }
1128 Ops.push_back(emitOpConstantI32(Count, I32TypeReg, MAI));
1129 }
1130
1131 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeArray, VoidTypeReg,
1132 ExtInstSetReg, Ops, MAI);
1133}
1134
1135std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeMember(
1136 const DIDerivedType *M, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1137 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1138 // The member type must already be in DebugScopeRegs.
1139 auto TyRegOpt = lookupOptReg(DebugScopeRegs, M->getBaseType());
1140 if (!TyRegOpt)
1141 return std::nullopt;
1142
1143 MCRegister NameReg = getCachedOpStringReg(M->getName());
1144 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1145 M->getFile(), /*UseEmptyPathIfNullScope=*/true);
1146 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1147 ExtInstSetReg, MAI);
1148 MCRegister LineReg =
1149 emitOpConstantI32(static_cast<uint32_t>(M->getLine()), I32TypeReg, MAI);
1150
1151 // DIDerivedType members carry no column, so emit 0.
1152 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1153 MCRegister OffsetReg = emitOpConstantI32(
1154 static_cast<uint32_t>(M->getOffsetInBits()), I32TypeReg, MAI);
1155 MCRegister SizeReg = emitOpConstantI32(
1156 static_cast<uint32_t>(M->getSizeInBits()), I32TypeReg, MAI);
1157 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(M), I32TypeReg, MAI);
1158
1159 // In NonSemantic.Shader.DebugInfo a DebugTypeMember has no Parent operand:
1160 // only the composite references its members. This is by design, it drops the
1161 // Parent that OpenCL.DebugInfo.100 had, and it avoids a composite/member
1162 // reference cycle.
1163 //
1164 // FIXME: Static members are not handled yet: their constant initializer is
1165 // available but is not emitted as the optional Value operand, and under DWARF
1166 // 5 a static member is tagged DW_TAG_variable, which the caller's member loop
1167 // skips.
1168 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeMember, VoidTypeReg,
1169 ExtInstSetReg,
1170 {NameReg, *TyRegOpt, SrcReg, LineReg, ColReg, OffsetReg,
1171 SizeReg, FlagsReg},
1172 MAI);
1173}
1174
1175std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeComposite(
1176 const DICompositeType *CT, ArrayRef<MCRegister> MemberRegs,
1177 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
1179 auto ParentRegOpt = resolveScope(CT->getScope());
1180 if (!ParentRegOpt)
1181 return std::nullopt;
1182
1183 MCRegister NameReg = getCachedOpStringReg(CT->getName());
1184 MCRegister LinkageReg = getCachedOpStringReg(CT->getIdentifier());
1185 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1186 CT->getFile(), /*UseEmptyPathIfNullScope=*/true);
1187 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1188 ExtInstSetReg, MAI);
1189
1190 MCRegister TagReg =
1191 emitOpConstantI32(mapCompositeTypeTag(CT->getTag()), I32TypeReg, MAI);
1192 MCRegister LineReg =
1193 emitOpConstantI32(static_cast<uint32_t>(CT->getLine()), I32TypeReg, MAI);
1194 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1195
1196 // A forward declaration has no known size or members: Size is DebugInfoNone.
1197 MCRegister SizeReg = CachedDebugInfoNoneReg;
1198 if (!CT->isForwardDecl())
1199 SizeReg = emitOpConstantI32(static_cast<uint32_t>(CT->getSizeInBits()),
1200 I32TypeReg, MAI);
1201
1202 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(CT), I32TypeReg, MAI);
1203
1204 SmallVector<MCRegister> Ops = {NameReg, TagReg, SrcReg,
1205 LineReg, ColReg, *ParentRegOpt,
1206 LinkageReg, SizeReg, FlagsReg};
1207 Ops.append(MemberRegs.begin(), MemberRegs.end());
1208 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeComposite, VoidTypeReg,
1209 ExtInstSetReg, Ops, MAI);
1210}
1211
1212std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypedef(
1213 const DIDerivedType *TD, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1214 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1215 // The underlying (base) type must already be in DebugScopeRegs.
1216 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, TD->getBaseType());
1217 if (!BaseRegOpt)
1218 return std::nullopt;
1219
1220 MCRegister NameReg = getCachedOpStringReg(TD->getName());
1221 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1222 TD->getFile(), /*UseEmptyPathIfNullScope=*/true);
1223 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1224 ExtInstSetReg, MAI);
1225 MCRegister LineReg =
1226 emitOpConstantI32(static_cast<uint32_t>(TD->getLine()), I32TypeReg, MAI);
1227 // DIDerivedType typedefs carry no column, so emit 0.
1228 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1229
1230 // Parent must be a lexical scope. Valid NSDI lexical scopes are
1231 // DebugCompilationUnit, DebugFunction, DebugLexicalBlock, or
1232 // DebugTypeComposite.
1233 auto ParentRegOpt = resolveScope(TD->getScope());
1234 if (!ParentRegOpt)
1235 return std::nullopt;
1236 MCRegister ParentReg = *ParentRegOpt;
1237
1238 return emitExtInst(
1239 SPIRV::NonSemanticExtInst::DebugTypedef, VoidTypeReg, ExtInstSetReg,
1240 {NameReg, *BaseRegOpt, SrcReg, LineReg, ColReg, ParentReg}, MAI);
1241}
1242
1245 if (CompileUnits.empty())
1246 return;
1247 // Check that prepareModuleOutput() registered the extended instruction set.
1248 // If the subtarget does not support the extension, neither strings nor ext
1249 // insts are emitted.
1250 if (!MAI.getExtInstSetReg(NSSet).isValid())
1251 return;
1252
1253 for (const CompileUnitInfo &Info : CompileUnits) {
1254 if (Info.TheCU) {
1255 MCRegister PathReg = emitOpStringIfNew(Info.FilePath, MAI);
1256 ScopeToPathOpStringReg[Info.TheCU] = PathReg;
1257 if (const DIFile *F = Info.TheCU->getFile())
1258 ScopeToPathOpStringReg[F] = PathReg;
1259 }
1260 }
1261
1262 for (const DIBasicType *BT : BasicTypes)
1263 emitOpStringIfNew(BT->getName(), MAI);
1264
1266 SubprogramDeclarations, SubprogramDefinitions)) {
1267 emitOpStringIfNew(SP->getName(), MAI);
1268 emitOpStringIfNew(SP->getLinkageName(), MAI);
1269 emitAndCacheScopePathOpStringReg(SP, MAI);
1270 }
1271
1272 // Cache the OpStrings each DebugTypeComposite and its DebugTypeMembers use:
1273 // the composite name, identifier (linkage name), and path, plus each member
1274 // name and path.
1275 for (const DICompositeType *CT : CompositeTypes) {
1276 emitOpStringIfNew(CT->getName(), MAI);
1277 emitOpStringIfNew(CT->getIdentifier(), MAI);
1278 emitAndCacheScopePathOpStringReg(CT->getFile(), MAI);
1279 for (const DINode *Element : CT->getElements()) {
1280 const auto *M = dyn_cast<DIDerivedType>(Element);
1281 if (!M || M->getTag() != dwarf::DW_TAG_member)
1282 continue;
1283 emitOpStringIfNew(M->getName(), MAI);
1284 emitAndCacheScopePathOpStringReg(M->getFile(), MAI);
1285 }
1286 }
1287
1288 // Cache the name and path OpStrings each DebugTypedef uses.
1289 for (const DIDerivedType *TD : TypedefTypes) {
1290 emitOpStringIfNew(TD->getName(), MAI);
1291 emitAndCacheScopePathOpStringReg(TD->getFile(), MAI);
1292 }
1293
1294 for (const auto &[GV, _] : GlobalVariableDebugInfoMap) {
1295 emitOpStringIfNew(GV->getName(), MAI);
1296 emitOpStringIfNew(GV->getLinkageName(), MAI);
1297 emitAndCacheScopePathOpStringReg(GV->getFile(), MAI);
1298 }
1299
1300 for (const DILocalVariable *LV : LocalVariables) {
1301 emitOpStringIfNew(LV->getName(), MAI);
1302 emitAndCacheScopePathOpStringReg(LV->getFile(), MAI);
1303 }
1304
1305 // Cache the path OpString each DebugLexicalBlock uses (source file), plus
1306 // the Name OpString for the DINamespace case.
1307 for (const DIScope *S : LexicalBlocks) {
1308 emitAndCacheScopePathOpStringReg(S->getFile(), MAI);
1309 if (const auto *NS = dyn_cast<DINamespace>(S))
1310 emitOpStringIfNew(NS->getName(), MAI);
1311 }
1312
1313 for (const DILocation *DL : UniqueDebugLocations)
1314 emitAndCacheScopePathOpStringReg(DL->getScope(), MAI);
1315
1316 CachedEmptyStringReg = emitOpStringIfNew("", MAI);
1317
1318#ifndef NDEBUG
1319 NonSemanticOpStringsSectionEmitted = true;
1320#endif
1321}
1322
1323void SPIRVNonSemanticDebugHandler::emitDebugFunctionDefinition(
1324 MCRegister DebugFunctionReg, MCRegister OpFunctionReg,
1326 assert(DebugFunctionReg.isValid() && OpFunctionReg.isValid() &&
1327 "DebugFunctionDefinition operands must be valid");
1328 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1329 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1330 emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDefinition, VoidTypeReg,
1331 ExtInstSetReg, {DebugFunctionReg, OpFunctionReg}, MAI);
1332}
1333
1334void SPIRVNonSemanticDebugHandler::resetPerFunctionDebugState() {
1335 CurrentMF = nullptr;
1336 LastFunctionOpVariable = nullptr;
1337 DebugFunctionDefinitionEmitted = false;
1338 LastLineMI = nullptr;
1339 LastScopeMI = nullptr;
1340}
1341
1342void SPIRVNonSemanticDebugHandler::preparePerFunctionDebug(
1343 const MachineFunction *MF) {
1344 resetPerFunctionDebugState();
1345 if (!GlobalNSDIEnabled || !CurrentMAI)
1346 return;
1347
1348 CurrentMF = MF;
1349
1350 if (MF->getFunction()
1352 .isValid())
1353 return;
1354
1355 const DISubprogram *SP = MF->getFunction().getSubprogram();
1356 if (!SP || !SP->isDefinition())
1357 return;
1358
1359 // DebugFunctionDefinition is emitted after the last function-level
1360 // OpVariable. If there are none, it is emitted after the entry OpLabel.
1361 LastFunctionOpVariable =
1362 findLastFunctionOpVariableDeclaration(*MF, *CurrentMAI);
1363}
1364
1365void SPIRVNonSemanticDebugHandler::tryEmitDebugFunctionDefinition(
1367 if (DebugFunctionDefinitionEmitted || !GlobalNSDIEnabled)
1368 return;
1369
1370 assert(CurrentMF && "no current MachineFunction");
1371 const Function &F = CurrentMF->getFunction();
1372 const DISubprogram *SP = F.getSubprogram();
1373 if (!SP || !SP->isDefinition())
1374 return;
1375
1376 auto DFIt = DebugScopeRegs.find(SP);
1377 if (DFIt == DebugScopeRegs.end())
1378 return;
1379
1380 MCRegister OpFunctionReg = MAI.getGlobalObjReg(&F);
1381 if (!OpFunctionReg.isValid())
1382 return;
1383
1384 emitDebugFunctionDefinition(DFIt->second, OpFunctionReg, MAI);
1385 DebugFunctionDefinitionEmitted = true;
1386}
1387
1389 const MachineFunction *MF) {
1390 preparePerFunctionDebug(MF);
1391}
1392
1394 (void)MF;
1395 resetPerFunctionDebugState();
1396}
1397
1399 assert(CurMI == nullptr && "CurMI must be null");
1400 CurMI = MI;
1401
1402 if (!DebugFunctionDefinitionEmitted)
1403 return;
1404
1405 std::optional<const MachineInstr *> Target = resolveDebugLocTarget(MI);
1406 if (!Target)
1407 return;
1408
1409 emitDebugScopeForInstruction(*Target);
1410 emitDebugLineForInstruction(*Target);
1411
1412 emitDebugDeclare(MI);
1413}
1414
1415// The register that holds the variable's address in \p MI, or std::nullopt
1416// when \p MI is not a declare this backend can describe.
1417//
1418// The spec requires DebugDeclare's Variable operand to be "the <id> of an
1419// OpVariable instruction that defines the local variable". MIR has no
1420// DBG_DECLARE, so what this looks for is an indirect DBG_VALUE whose location
1421// register an OpVariable defines.
1422static std::optional<Register>
1424 // #dbg_declare is an indirect DBG_VALUE in MIR; #dbg_value is normally a
1425 // direct one except for the variadic case.
1426 if (!MI.isIndirectDebugValue())
1427 return std::nullopt;
1428
1429 // A variadic #dbg_value becomes DBG_VALUE $noreg, 0, ... which is indirect
1430 // too, and $noreg is not virtual.
1431 Register LocReg = MI.getDebugOperand(0).getReg();
1432 if (!LocReg.isVirtual())
1433 return std::nullopt;
1434
1435 // DebugDeclare can only encode the address of an OpVariable.
1436 // Other legitimate #dbg_declare cannot be encoded.
1437 // Examples: an access chain for a field, an OpFunctionParameter for a byval
1438 // argument, or a module-scope constant for a null or fixed address.
1439
1440 // LocReg may also have no def at all: erasing dead storage leaves the
1441 // DBG_VALUE pointing at an undefined register. MachineVerifier permits that
1442 // because LiveDebugVariables normally clears it, but this pipeline has no
1443 // register allocation, so LiveDebugVariables never runs.
1444 const MachineInstr *Def = MI.getMF()->getRegInfo().getUniqueVRegDef(LocReg);
1445 if (!Def || Def->getOpcode() != SPIRV::OpVariable)
1446 return std::nullopt;
1447
1448 return LocReg;
1449}
1450
1451void SPIRVNonSemanticDebugHandler::emitDebugDeclare(const MachineInstr *MI) {
1452 assert(DebugFunctionDefinitionEmitted &&
1453 "DebugFunctionDefinition must be emitted");
1454 assert(CurrentMAI && "CurrentMAI must be set");
1455
1456 std::optional<Register> LocReg = getDebugDeclareStorageReg(*MI);
1457 if (!LocReg)
1458 return;
1459
1460 auto VarRegOpt = lookupOptReg(DebugLocalVariableRegs, MI->getDebugVariable());
1461 if (!VarRegOpt)
1462 return;
1463
1464 auto ExprRegOpt = lookupOptReg(DebugExpressionRegs, MI->getDebugExpression());
1465 if (!ExprRegOpt)
1466 return;
1467
1468 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1469 MCRegister StorageReg = MAI.getRegisterAlias(MI->getMF(), *LocReg);
1470 if (!StorageReg.isValid())
1471 return;
1472
1473 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1474 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1475 emitExtInst(SPIRV::NonSemanticExtInst::DebugDeclare, VoidTypeReg,
1476 ExtInstSetReg, {*VarRegOpt, StorageReg, *ExprRegOpt}, MAI);
1477}
1478
1479static bool isMergeInstruction(unsigned Opcode) {
1480 return Opcode == SPIRV::OpSelectionMerge || Opcode == SPIRV::OpLoopMerge ||
1481 Opcode == SPIRV::OpLoopControlINTEL;
1482}
1483
1486 if (MAI.getSkipEmission(MI))
1487 return false;
1488 switch (MI->getOpcode()) {
1489 case SPIRV::OpFunction:
1490 case SPIRV::OpFunctionParameter:
1491 case SPIRV::OpFunctionEnd:
1492 case SPIRV::OpLabel:
1493 case SPIRV::OpPhi:
1494 return false;
1495 default:
1496 return true;
1497 }
1498}
1499
1500static const MachineInstr *
1502 SPIRV::ModuleAnalysisInfo &MAI, bool Forward) {
1503 for (const MachineInstr *Adj = Forward ? MI->getNextNode()
1504 : MI->getPrevNode();
1505 Adj; Adj = Forward ? Adj->getNextNode() : Adj->getPrevNode()) {
1506 if (MAI.getSkipEmission(Adj))
1507 continue;
1508 return Adj;
1509 }
1510 return nullptr;
1511}
1512
1513std::optional<const MachineInstr *>
1514SPIRVNonSemanticDebugHandler::resolveDebugLocTarget(const MachineInstr *MI) {
1515 assert(CurrentMAI && "CurrentMAI must be set");
1516 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1517
1518 // Structural opcodes don't require a DebugLine/DebugScope, other opcodes
1519 // might have already been emitted in the module scope.
1520 if (!isDebugLocTarget(MI, MAI))
1521 return std::nullopt;
1522
1523 // DebugLine/DebugScope can be emitted before a merge instruction, but not
1524 // after it (nothing may sit between the merge and its terminator). We can
1525 // use either the merge's or the terminator's debug info; we emit the
1526 // terminator's one.
1527 const MachineInstr *Prev = findAdjacentEmittedInstruction(MI, MAI, false);
1528 if (Prev && isMergeInstruction(Prev->getOpcode()))
1529 return std::nullopt;
1530
1531 if (isMergeInstruction(MI->getOpcode())) {
1532 // Use the terminator's debug info; when we reach it later, the check
1533 // above skips it.
1534 MI = findAdjacentEmittedInstruction(MI, MAI, true);
1535 assert(MI && "Merge instruction must be followed by a terminator");
1536 }
1537
1538 return MI;
1539}
1540
1541void SPIRVNonSemanticDebugHandler::emitDebugScopeForInstruction(
1542 const MachineInstr *MI) {
1543 assert(DebugFunctionDefinitionEmitted &&
1544 "DebugFunctionDefinition must be emitted");
1545 assert(CurrentMAI && "CurrentMAI must be set");
1546
1547 // The region is implicitly closed at each basic block boundary, so a
1548 // LastScopeMI from another block must be dropped before it is read below:
1549 // the new block needs its own DebugScope, and has no region left to close.
1550 if (LastScopeMI && MI->getParent() != LastScopeMI->getParent())
1551 LastScopeMI = nullptr;
1552
1553 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1554 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1555 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1556
1557 const DILocation *CurDL = MI->getDebugLoc().get();
1558 if (!CurDL) {
1559 // No location for the current instruction.
1560 if (LastScopeMI) {
1561 // Close the current DebugScope region.
1562 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoScope, VoidTypeReg,
1563 ExtInstSetReg, {}, MAI);
1564 LastScopeMI = nullptr;
1565 }
1566 return;
1567 }
1568
1569 const DIScope *CurScope = CurDL->getScope();
1570 const DILocation *CurInlinedAt = CurDL->getInlinedAt();
1571
1572 if (LastScopeMI) {
1573 const DILocation *LastDL = LastScopeMI->getDebugLoc().get();
1574 if (LastDL->getScope() == CurScope &&
1575 LastDL->getInlinedAt() == CurInlinedAt)
1576 return;
1577 }
1578
1579 auto CurScopeRegOpt = resolveScope(CurScope);
1580 if (!CurScopeRegOpt)
1581 return;
1582
1583 SmallVector<MCRegister, 2> Ops{*CurScopeRegOpt};
1584 if (CurInlinedAt) {
1585 // If the global emission did not include this inlined-at case, we skip it.
1586 MCRegister InlinedReg = DebugInlinedAtRegs.lookup(CurInlinedAt);
1587 if (!InlinedReg.isValid())
1588 return;
1589 Ops.push_back(InlinedReg);
1590 }
1591
1592 // A new DebugScope region is needed.
1593 emitExtInst(SPIRV::NonSemanticExtInst::DebugScope, VoidTypeReg, ExtInstSetReg,
1594 Ops, MAI);
1595
1596 LastScopeMI = MI;
1597}
1598
1599void SPIRVNonSemanticDebugHandler::emitDebugLineForInstruction(
1600 const MachineInstr *MI) {
1601 assert(DebugFunctionDefinitionEmitted &&
1602 "DebugFunctionDefinition must be emitted");
1603 assert(CurrentMAI && "CurrentMAI must be set");
1604
1605 // The region is implicitly closed at each basic block boundary, so a
1606 // LastLineMI from another block must be dropped before it is read below:
1607 // the new block needs its own DebugLine, and has no region left to close.
1608 if (LastLineMI && MI->getParent() != LastLineMI->getParent())
1609 LastLineMI = nullptr;
1610
1611 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1612 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1613 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1614
1615 const DILocation *DL = MI->getDebugLoc().get();
1616 if (!DL) {
1617 // No location for the current instruction
1618 if (LastLineMI) {
1619 // Close the current DebugLine region.
1620 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoLine, VoidTypeReg,
1621 ExtInstSetReg, {}, MAI);
1622 LastLineMI = nullptr;
1623 }
1624 // No DebugLine region to close.
1625 return;
1626 }
1627
1628 // At this point, there is a location for the current instruction.
1629 // If it matches the last emitted DebugLine, no new DebugLine region is
1630 // needed. Otherwise, emit a new DebugLine region and update LastLineMI.
1631
1632 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1633 DL->getScope(), /*UseEmptyPathIfNullScope=*/true);
1634 unsigned Line = DL->getLine();
1635 unsigned Col = DL->getColumn();
1636
1637 MCRegister SrcReg = DebugSourceRegByFileStr.lookup(FileStrReg.id());
1638 MCRegister LineReg = I32ConstantCache.lookup(Line);
1639 MCRegister ColStartReg = I32ConstantCache.lookup(Col);
1640 MCRegister ColEndReg = I32ConstantCache.lookup(Col + 1);
1641
1642 // The elements of each collected DILocation (DebugSource, line/column
1643 // constants) are pre-emitted from LLVM-IR instruction !dbg attachments and
1644 // debug-program records; MIR is expected to reuse those same locations (or
1645 // carry none). A lookup miss means codegen attached a source position whose
1646 // elements were never pre-emitted, and debug-line emission is skipped.
1647 if (!SrcReg.isValid() || !LineReg.isValid() || !ColStartReg.isValid() ||
1648 !ColEndReg.isValid())
1649 return;
1650
1651 // Current location matches the last emitted DebugLine region.
1652 if (LastLineMI && MI->getDebugLoc() == LastLineMI->getDebugLoc())
1653 return;
1654
1655 // A new DebugLine region is needed.
1656 emitExtInst(SPIRV::NonSemanticExtInst::DebugLine, VoidTypeReg, ExtInstSetReg,
1657 {SrcReg, LineReg, LineReg, ColStartReg, ColEndReg}, MAI);
1658
1659 LastLineMI = MI;
1660}
1661
1663 const MachineInstr *MI = CurMI;
1664 CurMI = nullptr;
1665
1666 if (!MI || !GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
1667 return;
1668
1669 if (MI != LastFunctionOpVariable)
1670 return;
1671
1672 // If this is the last function-level OpVariable, emit the
1673 // DebugFunctionDefinition. Otherwise, we had already done it before right
1674 // after the OpLabel (see notifyEntryLabelEmitted).
1675 assert(CurrentMAI && "CurrentMAI must be set");
1676 tryEmitDebugFunctionDefinition(*CurrentMAI);
1677}
1678
1680 const MachineFunction &MF) {
1681 if (!GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
1682 return;
1683
1684 assert(CurrentMF == &MF &&
1685 "notification does not match the current MachineFunction");
1686
1687 if (LastFunctionOpVariable)
1688 return;
1689
1690 // If there are no function-level OpVariables, emit the
1691 // DebugFunctionDefinition. Otherwise, DebugFunctionDefinition is emitted
1692 // after the last OpVariable (see endInstruction).
1693 tryEmitDebugFunctionDefinition(*CurrentMAI);
1694}
1695
1696void SPIRVNonSemanticDebugHandler::collectDebugExpressions(
1698 MachineModuleInfo *ModuleInfo = Asm->MMI;
1699 assert(ModuleInfo && "MachineModuleInfo must be set during module output");
1700
1701 for (const Function &F : *ModuleInfo->getModule()) {
1702 const MachineFunction *MF = ModuleInfo->getMachineFunction(F);
1703 if (!MF)
1704 continue;
1705 for (const MachineBasicBlock &MBB : *MF)
1706 for (const MachineInstr &MI : MBB)
1707 if (MI.isDebugValueLike())
1708 Out.insert(MI.getDebugExpression());
1709 }
1710}
1711
1714 if (GlobalDIEmitted)
1715 return;
1716
1717 GlobalDIEmitted = true;
1718
1719 if (CompileUnits.empty()) {
1720 GlobalNSDIEnabled = false;
1721 return;
1722 }
1723
1724 // Retrieve the ext inst set register allocated by prepareModuleOutput().
1725 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1726 if (!ExtInstSetReg.isValid()) {
1727 GlobalNSDIEnabled = false;
1728 return;
1729 }
1730
1731#ifndef NDEBUG
1732 assert(NonSemanticOpStringsSectionEmitted &&
1733 "emitNonSemanticDebugStrings() must run before "
1734 "emitNonSemanticGlobalDebugInfo()");
1735#endif
1736
1737 CurrentMAI = &MAI;
1738
1739 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1740 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1741
1742 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
1743 VoidTypeReg, ExtInstSetReg, {}, MAI);
1744
1745 // Emit integer constants shared across all NSDI instructions. The constant
1746 // cache ensures each value is emitted at most once even when referenced from
1747 // multiple instructions. All constants are pre-emitted before any DebugSource
1748 // so that the output order is: constants, then
1749 // DebugSource+DebugCompilationUnit pairs. This keeps OpConstant instructions
1750 // grouped before the OpExtInst instructions.
1751
1752 // The Version operand of DebugCompilationUnit is the version of the
1753 // NonSemantic.Shader.DebugInfo instruction set, which is 100 for
1754 // "NonSemantic.Shader.DebugInfo.100" (NonSemanticShaderDebugInfo100Version).
1755 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
1756 MCRegister DwarfVersionReg =
1757 emitOpConstantI32(static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
1758
1759 // Pre-emit source language constants for all compile units before entering
1760 // the DebugSource loop.
1761 SmallVector<MCRegister> SrcLangRegs =
1762 map_to_vector(CompileUnits, [&](const CompileUnitInfo &Info) {
1763 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
1764 });
1765
1766 // Emit DebugSource and DebugCompilationUnit for each compile unit.
1767 for (auto [Info, SrcLangReg] : llvm::zip(CompileUnits, SrcLangRegs)) {
1768 MCRegister FileStrReg = ScopeToPathOpStringReg.lookup(Info.TheCU);
1769 assert(FileStrReg.isValid() &&
1770 "CU path OpString must be emitted in emitNonSemanticDebugStrings");
1771 MCRegister DebugSourceReg = getOrEmitDebugSourceForFileStrReg(
1772 FileStrReg, VoidTypeReg, ExtInstSetReg, MAI);
1773 MCRegister CUDbgReg = emitExtInst(
1774 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
1775 ExtInstSetReg,
1776 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
1777 MAI);
1778 if (Info.TheCU)
1779 DebugScopeRegs[Info.TheCU] = CUDbgReg;
1780 }
1781
1782 // Zero constant used as the Flags operand in DebugTypeBasic and
1783 // DebugTypePointer. Cached with other i32 constants.
1784 MCRegister I32ZeroReg = emitOpConstantI32(0, I32TypeReg, MAI);
1785
1786 for (const DIBasicType *BT : BasicTypes) {
1787 MCRegister NameReg = getCachedOpStringReg(BT->getName());
1788 MCRegister SizeReg = emitOpConstantI32(
1789 static_cast<uint32_t>(BT->getSizeInBits()), I32TypeReg, MAI);
1790
1791 // Map DWARF base type encodings to NSDI encoding codes per
1792 // NonSemantic.Shader.DebugInfo.100 specification, section 4.5.
1793 unsigned Encoding = 0; // Unspecified
1794 switch (BT->getEncoding()) {
1795 case dwarf::DW_ATE_address:
1796 Encoding = 1;
1797 break;
1798 case dwarf::DW_ATE_boolean:
1799 Encoding = 2;
1800 break;
1801 case dwarf::DW_ATE_float:
1802 Encoding = 3;
1803 break;
1804 case dwarf::DW_ATE_signed:
1805 Encoding = 4;
1806 break;
1807 case dwarf::DW_ATE_signed_char:
1808 Encoding = 5;
1809 break;
1810 case dwarf::DW_ATE_unsigned:
1811 Encoding = 6;
1812 break;
1813 case dwarf::DW_ATE_unsigned_char:
1814 Encoding = 7;
1815 break;
1816 }
1817 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
1818
1819 MCRegister BTReg = emitExtInst(
1820 SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
1821 {NameReg, SizeReg, EncodingReg, I32ZeroReg}, MAI);
1822 DebugScopeRegs[BT] = BTReg;
1823 }
1824
1825 // Emit DebugTypeVector for each collected vector type.
1826 for (const DICompositeType *VT : VectorTypes) {
1827 if (auto VecReg = emitDebugTypeVector(VT, ExtInstSetReg, MAI))
1828 DebugScopeRegs[VT] = *VecReg;
1829 }
1830
1831 // Emit DebugTypePointer for each referenced pointer type.
1832 for (const DIDerivedType *PT : PointerTypes) {
1833 if (auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
1834 DebugScopeRegs[PT] = *PtrReg;
1835 }
1836
1837 // Emit DebugTypeArray for each collected array type. Placed after the basic,
1838 // vector, and pointer types so an array over any of them can resolve its
1839 // element id. An array whose element type was not emitted is skipped.
1840 for (const DICompositeType *AT : ArrayTypes) {
1841 if (auto ArrReg = emitDebugTypeArray(AT, ExtInstSetReg, MAI))
1842 DebugScopeRegs[AT] = *ArrReg;
1843 }
1844
1845 // Emit DebugTypeFunction for each distinct DISubroutineType.
1846 for (const DISubroutineType *ST : SubroutineTypes) {
1847 if (auto FnTyReg =
1848 emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI))
1849 DebugScopeRegs[ST] = *FnTyReg;
1850 }
1851
1852 // Emit DebugLexicalBlock for each collected DINamespace, in parent-before-
1853 // child order. Placed before any DINamespace-scoped entity (typedefs,
1854 // function declarations, composite types, functions, global variables) so
1855 // their Parent operand can reference an already-emitted DebugLexicalBlock.
1856 // DINamespace never chains through a DISubprogram (DINamespace::getScope()
1857 // returns DIScope, not DILocalScope), so this never depends on
1858 // DebugScopeRegs.
1859 for (const DIScope *S :
1860 make_filter_range(LexicalBlocks, IsaPred<DINamespace>)) {
1861 if (auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
1862 ExtInstSetReg, MAI))
1863 DebugScopeRegs[S] = *LBReg;
1864 }
1865
1866 // Emit DebugTypedef for each typedef. Placed after the other type loops so a
1867 // typedef can resolve its underlying type. A typedef whose base type is not
1868 // emitted is skipped. A typedef whose base is another typedef emitted later
1869 // in this same pass is also skipped, the emission-order gap tracked in
1870 // https://github.com/llvm/llvm-project/issues/211850.
1871 for (const DIDerivedType *TD : TypedefTypes) {
1872 if (auto TDReg =
1873 emitDebugTypedef(TD, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
1874 DebugScopeRegs[TD] = *TDReg;
1875 }
1876
1877 // Emit DebugFunctionDeclaration for DISubprogram declarations.
1878 for (const DISubprogram *SP : SubprogramDeclarations) {
1879 if (auto DeclReg = emitDebugFunctionDeclaration(SP, VoidTypeReg, I32TypeReg,
1880 ExtInstSetReg, MAI))
1881 DebugScopeRegs[SP] = *DeclReg;
1882 }
1883
1884 // Emit DebugTypeMember and DebugTypeComposite for each struct, class, or
1885 // union. Each member is emitted before the composite that lists it, so the
1886 // Members operand references already-defined ids. A member whose type is not
1887 // in DebugScopeRegs is skipped.
1888 for (const DICompositeType *CT : CompositeTypes) {
1889 SmallVector<MCRegister> MemberRegs;
1890 for (const DINode *Element : CT->getElements()) {
1891 const auto *M = dyn_cast<DIDerivedType>(Element);
1892 if (!M || M->getTag() != dwarf::DW_TAG_member)
1893 continue;
1894 if (auto MemberReg = emitDebugTypeMember(M, VoidTypeReg, I32TypeReg,
1895 ExtInstSetReg, MAI))
1896 MemberRegs.push_back(*MemberReg);
1897 }
1898 if (auto CompReg = emitDebugTypeComposite(CT, MemberRegs, VoidTypeReg,
1899 I32TypeReg, ExtInstSetReg, MAI))
1900 DebugScopeRegs[CT] = *CompReg;
1901 }
1902
1903 // Emit DebugFunction for DISubprogram definitions.
1904 for (const DISubprogram *SP : SubprogramDefinitions) {
1905 if (auto FnReg =
1906 emitDebugFunction(SP, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
1907 DebugScopeRegs[SP] = *FnReg;
1908 }
1909
1910 // Emit DebugLexicalBlock for each collected DILexicalBlock, in parent-
1911 // before-child order. Placed after DebugFunction so a block directly
1912 // enclosed by a function (the common case) can resolve its Parent operand;
1913 // DINamespace entries were already emitted above.
1914 for (const DIScope *S :
1916 if (auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
1917 ExtInstSetReg, MAI))
1918 DebugScopeRegs[S] = *LBReg;
1919 }
1920
1921 // Emit DebugLocalVariable after DebugFunction and their lexical blocks so the
1922 // Parent operand can resolve. Record the ids for DebugDeclare.
1923 for (const DILocalVariable *LV : LocalVariables)
1924 if (auto LVReg = emitDebugLocalVariable(LV, VoidTypeReg, I32TypeReg,
1925 ExtInstSetReg, MAI))
1926 DebugLocalVariableRegs[LV] = *LVReg;
1927
1928 // Opcodes like DebugDeclare are part of the function body, but
1929 // DebugExpression is not. For such opcodes, we collect the expressions
1930 // directly from the MIR to avoid inconsistencies with those in the LLVM IR
1931 // module.
1933 collectDebugExpressions(Expressions);
1934 for (const DIExpression *Expr : Expressions)
1935 if (auto ExprReg = emitDebugExpression(Expr, VoidTypeReg, I32TypeReg,
1936 ExtInstSetReg, MAI))
1937 DebugExpressionRegs[Expr] = *ExprReg;
1938
1939 // Emit DebugGlobalVariable for each collected DIGlobalVariable.
1940 for (const auto &[GV, Info] : GlobalVariableDebugInfoMap)
1941 emitDebugGlobalVariable(GV, Info, VoidTypeReg, I32TypeReg, ExtInstSetReg,
1942 MAI);
1943
1944 // Emit DebugInlinedAt allowing recursive inlining.
1945 for (const DILocation *DL : UniqueDebugLocations)
1946 if (const DILocation *IA = DL->getInlinedAt())
1947 getOrEmitDebugInlinedAt(IA, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
1948
1949 for (const DILocation *DL : UniqueDebugLocations) {
1950 emitOpConstantI32(DL->getLine(), I32TypeReg, MAI);
1951 emitOpConstantI32(DL->getColumn(), I32TypeReg, MAI);
1952 emitOpConstantI32(DL->getColumn() + 1, I32TypeReg, MAI);
1953 MCRegister FileStrReg =
1954 getCachedScopePathOpStringReg(DL->getScope(),
1955 /*UseEmptyPathIfNullScope=*/true);
1956 getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg, ExtInstSetReg,
1957 MAI);
1958 }
1959
1960 GlobalNSDIEnabled = true;
1961}
1962
1964SPIRVNonSemanticDebugHandler::getDebugFullPath(const DIScope *Scope) const {
1965 SmallString<128> Out;
1966 if (!Scope)
1967 return Out;
1968 StringRef Filename = Scope->getFilename();
1969 const auto Style = sys::path::Style::native;
1970 if (sys::path::is_absolute(Filename, Style))
1971 Out.assign(Filename.begin(), Filename.end());
1972 else {
1973 StringRef Dir = Scope->getDirectory();
1974 Out.assign(Dir.begin(), Dir.end());
1975 sys::path::append(Out, Style, Filename);
1976 }
1977 return Out;
1978}
1979
1980MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugSourceForFileStrReg(
1981 MCRegister FileStrReg, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
1983 const unsigned Key = FileStrReg.id();
1984 auto It = DebugSourceRegByFileStr.find(Key);
1985 if (It != DebugSourceRegByFileStr.end())
1986 return It->second;
1987
1988 MCRegister DS = emitExtInst(SPIRV::NonSemanticExtInst::DebugSource,
1989 VoidTypeReg, ExtInstSetReg, {FileStrReg}, MAI);
1990 DebugSourceRegByFileStr[Key] = DS;
1991 return DS;
1992}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
MachineBasicBlock & MBB
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 isDebugLocTarget(const MachineInstr *MI, SPIRV::ModuleAnalysisInfo &MAI)
static std::optional< Register > getDebugDeclareStorageReg(const MachineInstr &MI)
static std::optional< NonSemanticDebugOp > mapDwarfOpToNonSemanticOp(uint64_t DwarfOp)
static void collectDebugLocationsAndLocalVariables(const Module &M, SetVector< const DILocation * > &Locations, SetVector< const DILocalVariable * > &LVs)
#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
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition AsmPrinter.h:112
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:266
Basic type, like 'int' or 'float'.
StringRef getIdentifier() const
DINodeArray getElements() const
DIType * getBaseType() const
A lightweight wrapper around an expression operand.
DWARF expression.
iterator_range< expr_op_iterator > expr_ops() const
A pair of DIGlobalVariable and DIExpression.
DIDerivedType * getStaticDataMemberDeclaration() const
StringRef getLinkageName() const
DILocalScope * getScope() const
Get the local scope for this variable.
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:278
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:341
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
Metadata node.
Definition Metadata.h:1079
Tracking metadata reference owned by Metadata.
Definition Metadata.h:900
bool equalsStr(StringRef Str) const
Definition Metadata.h:922
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.
This class contains meta information specific to a module.
const Module * getModule() const
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
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:1765
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
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 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 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
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM Value Representation.
Definition Value.h:75
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
Definition Dwarf.h:144
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
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
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
#define N
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)