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/STLExtras.h"
16#include "llvm/ADT/SetVector.h"
19#include "llvm/ADT/Twine.h"
26#include "llvm/IR/DebugInfo.h"
32#include "llvm/IR/Module.h"
33#include "llvm/MC/MCInst.h"
34#include "llvm/MC/MCStreamer.h"
37#include "llvm/Support/Path.h"
38#include <cassert>
39
40using namespace llvm;
41
42namespace {
43
44/// Look up \p Key in a register map and return its value, or std::nullopt when
45/// the key is absent.
46template <typename MapT>
47static std::optional<MCRegister> lookupOptReg(const MapT &Map,
48 typename MapT::key_type Key) {
49 auto It = Map.find(Key);
50 if (It == Map.end())
51 return std::nullopt;
52 assert(It->second.isValid() && "invalid register stored in map");
53 return It->second;
54}
55
56/// Partition \p Ty into \p BasicTypes, \p PointerTypes, \p SubroutineTypes,
57/// \p VectorTypes, \p ArrayTypes, \p CompositeTypes, and \p TypedefTypes for
58/// NSDI emission. Used when iterating DebugInfoFinder.types(); each DI node is
59/// seen once, so no recursion into pointer bases. Other composites and the
60/// remaining derived kinds are ignored because they are not yet supported.
61/// Only types that are supported (later used) are partitioned.
62static void
63partitionTypes(const DIType *Ty, SmallVector<const DIBasicType *> &BasicTypes,
70 if (const auto *BT = dyn_cast<DIBasicType>(Ty)) {
71 BasicTypes.push_back(BT);
72 return;
73 }
74 if (const auto *ST = dyn_cast<DISubroutineType>(Ty)) {
75 SubroutineTypes.push_back(ST);
76 return;
77 }
78 if (const auto *CT = dyn_cast<DICompositeType>(Ty)) {
79 if (CT->getTag() == dwarf::DW_TAG_array_type) {
80 // A vector is an array with DINode::FlagVector. A plain array is the
81 // same tag without it. A matrix is also lowered to a DW_TAG_array_type
82 // (two subranges), so it is indistinguishable from a 2D array here and
83 // is emitted as a DebugTypeArray.
84 //
85 // FIXME: Emitting a matrix as a DebugTypeArray is valid but loses the
86 // matrix shape. DWARF has no matrix tag, so distinguishing a matrix needs
87 // a new DINode flag analogous to FlagVector, set on the array, plus a way
88 // to carry column-major vs row-major traits. Array-of-vectors alone would
89 // not disambiguate a matrix from a genuine array of vectors. Once the
90 // frontend marks matrices, route them to a DebugTypeMatrix path here.
91 if (CT->isVector())
92 VectorTypes.push_back(CT);
93 else
94 ArrayTypes.push_back(CT);
95 } else if (CT->getTag() == dwarf::DW_TAG_structure_type ||
96 CT->getTag() == dwarf::DW_TAG_class_type ||
97 CT->getTag() == dwarf::DW_TAG_union_type) {
98 CompositeTypes.push_back(CT);
99 }
100 return;
101 }
102 const auto *DT = dyn_cast<DIDerivedType>(Ty);
103 if (DT && DT->getTag() == dwarf::DW_TAG_pointer_type)
104 PointerTypes.push_back(DT);
105 else if (DT && DT->getTag() == dwarf::DW_TAG_typedef)
106 TypedefTypes.push_back(DT);
107}
108
109enum : uint32_t {
110 NSDIFlagIsProtected = 1u << 0,
111 NSDIFlagIsPrivate = 1u << 1,
112 NSDIFlagIsPublic = NSDIFlagIsPrivate | NSDIFlagIsProtected,
113 NSDIFlagIsLocal = 1u << 2,
114 NSDIFlagIsDefinition = 1u << 3,
115 NSDIFlagFwdDecl = 1u << 4,
116 NSDIFlagArtificial = 1u << 5,
117 NSDIFlagExplicit = 1u << 6,
118 NSDIFlagPrototyped = 1u << 7,
119 NSDIFlagObjectPointer = 1u << 8,
120 NSDIFlagStaticMember = 1u << 9,
121 NSDIFlagIndirectVariable = 1u << 10,
122 NSDIFlagLValueReference = 1u << 11,
123 NSDIFlagRValueReference = 1u << 12,
124 NSDIFlagIsOptimized = 1u << 13,
125 NSDIFlagIsEnumClass = 1u << 14,
126 NSDIFlagTypePassByValue = 1u << 15,
127 NSDIFlagTypePassByReference = 1u << 16,
128 NSDIFlagUnknownPhysicalLayout = 1u << 17,
129};
130
131static uint32_t mapDIFlagsToNonSemantic(DINode::DIFlags DFlags) {
132 uint32_t Flags = 0;
133 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPublic)
134 Flags |= NSDIFlagIsPublic;
135 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagProtected)
136 Flags |= NSDIFlagIsProtected;
137 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPrivate)
138 Flags |= NSDIFlagIsPrivate;
139 if (DFlags & DINode::FlagFwdDecl)
140 Flags |= NSDIFlagFwdDecl;
141 if (DFlags & DINode::FlagArtificial)
142 Flags |= NSDIFlagArtificial;
143 if (DFlags & DINode::FlagExplicit)
144 Flags |= NSDIFlagExplicit;
145 if (DFlags & DINode::FlagPrototyped)
146 Flags |= NSDIFlagPrototyped;
147 if (DFlags & DINode::FlagObjectPointer)
148 Flags |= NSDIFlagObjectPointer;
149 if (DFlags & DINode::FlagStaticMember)
150 Flags |= NSDIFlagStaticMember;
151 if (DFlags & DINode::FlagLValueReference)
152 Flags |= NSDIFlagLValueReference;
153 if (DFlags & DINode::FlagRValueReference)
154 Flags |= NSDIFlagRValueReference;
155 if (DFlags & DINode::FlagTypePassByValue)
156 Flags |= NSDIFlagTypePassByValue;
157 if (DFlags & DINode::FlagTypePassByReference)
158 Flags |= NSDIFlagTypePassByReference;
159 if (DFlags & DINode::FlagEnumClass)
160 Flags |= NSDIFlagIsEnumClass;
161 return Flags;
162}
163
164static uint32_t transDebugFlags(const DINode *DN) {
165 uint32_t Flags = 0;
166 if (const auto *GV = dyn_cast<DIGlobalVariable>(DN)) {
167 if (GV->isLocalToUnit())
168 Flags |= NSDIFlagIsLocal;
169 if (GV->isDefinition())
170 Flags |= NSDIFlagIsDefinition;
171 }
172 if (const auto *SP = dyn_cast<DISubprogram>(DN)) {
173 if (SP->isLocalToUnit())
174 Flags |= NSDIFlagIsLocal;
175 if (SP->isOptimized())
176 Flags |= NSDIFlagIsOptimized;
177 if (SP->isDefinition())
178 Flags |= NSDIFlagIsDefinition;
179 Flags |= mapDIFlagsToNonSemantic(SP->getFlags());
180 }
181 if (DN->getTag() == dwarf::DW_TAG_reference_type)
182 Flags |= NSDIFlagLValueReference;
183 if (DN->getTag() == dwarf::DW_TAG_rvalue_reference_type)
184 Flags |= NSDIFlagRValueReference;
185 if (const auto *Ty = dyn_cast<DIType>(DN))
186 Flags |= mapDIFlagsToNonSemantic(Ty->getFlags());
187 if (const auto *LV = dyn_cast<DILocalVariable>(DN))
188 Flags |= mapDIFlagsToNonSemantic(LV->getFlags());
189 return Flags;
190}
191
192// Map a DWARF composite tag to a NonSemantic.Shader.DebugInfo Composite Type
193// value: Class 0, Structure 1, Union 2.
194static uint32_t mapCompositeTypeTag(unsigned Tag) {
195 switch (Tag) {
196 case dwarf::DW_TAG_class_type:
197 return 0;
198 case dwarf::DW_TAG_structure_type:
199 return 1;
200 case dwarf::DW_TAG_union_type:
201 return 2;
202 default:
203 reportFatalInternalError("unexpected DWARF composite tag " + Twine(Tag) +
204 ". Expecting 0, 1 or 2");
205 }
206}
207
208static const MachineInstr *
209findLastFunctionOpVariableDeclaration(const MachineFunction &MF,
211
212 // We iterate over the instructions to find the last OpVariable instruction if
213 // any. The following SPIRV rule is used to terminate the traversal earlier:
214 // SPIR-V 2.16.1, Function Structure: "All OpVariable instructions in a
215 // function must be in the first block in the function. These instructions,
216 // together with any intermixed OpLine and OpNoLine instructions, must be the
217 // first instructions in that block."
218 const MachineInstr *LastOpVariable = nullptr;
219 bool SeenOpVariable = false;
220 for (const MachineInstr &MI : MF.front()) {
221 if (MI.getOpcode() == SPIRV::OpVariable) {
222 SeenOpVariable = true;
223 if (!MAI.getSkipEmission(&MI))
224 LastOpVariable = &MI;
225 continue;
226 }
227
228 bool CanInterleaveWithOpVariable =
229 MI.getOpcode() == SPIRV::OpLine || MI.getOpcode() == SPIRV::OpNoLine;
230 if (SeenOpVariable && !CanInterleaveWithOpVariable &&
231 !MAI.getSkipEmission(&MI))
232 break;
233 }
234 return LastOpVariable;
235}
236
237} // namespace
238
241
242// Map DWARF source language codes to NonSemantic.Shader.DebugInfo.100 source
243// language codes. Values are from the SourceLanguage enum in the
244// NonSemantic.Shader.DebugInfo.100 specification, section 4.3.
245unsigned SPIRVNonSemanticDebugHandler::toNSDISrcLang(unsigned DwarfSrcLang) {
246 switch (DwarfSrcLang) {
247 case dwarf::DW_LANG_OpenCL:
248 return 3; // OpenCL_C
249 case dwarf::DW_LANG_OpenCL_CPP:
250 return 4; // OpenCL_CPP
251 case dwarf::DW_LANG_CPP_for_OpenCL:
252 return 6; // CPP_for_OpenCL
253 case dwarf::DW_LANG_GLSL:
254 return 2; // GLSL
255 case dwarf::DW_LANG_HLSL:
256 return 5; // HLSL
257 case dwarf::DW_LANG_SYCL:
258 return 7; // SYCL
259 case dwarf::DW_LANG_Zig:
260 return 12; // Zig
261 default:
262 return 0; // Unknown
263 }
264}
265
266static bool isBooleanType(const DIBasicType *BT) {
267 return BT->getEncoding() == dwarf::DW_ATE_boolean;
268}
269
270// \p Value truncated to the width of \p BT, or 0 or 1 for a boolean.
272 // A boolean is one of two values and a DIBasicType may give it no size, so
273 // masking to its width would turn every true into a false.
274 if (isBooleanType(BT))
275 return Value != 0;
276 unsigned Width = BT->getSizeInBits();
277 return Width >= 64 ? Value : Value & ((uint64_t(1) << Width) - 1);
278}
279
280// \p Value truncated to the width of \p BT. APInt::getZExtValue() asserts
281// above 64 bits, so the truncation comes first.
283 unsigned Width = isBooleanType(BT) ? 1 : BT->getSizeInBits();
284 return constantBits(Value.getActiveBits() > 64
285 ? Value.trunc(std::min(Width, 64u)).getZExtValue()
286 : Value.getZExtValue(),
287 BT);
288}
289
290// The DIBasicType that \p Ty resolves to through any typedefs, or null.
291static const DIBasicType *stripToScalarType(const DIType *Ty) {
292 // A cv-qualified type gets no DebugType, so its variable has no
293 // DebugLocalVariable and its records are dropped.
294 //
295 // Since visitDIDerivedType accepts a cyclic typedef chain, this stops once it
296 // reaches an already seen type.
298 while (const auto *DT = dyn_cast_or_null<DIDerivedType>(Ty)) {
299 if (DT->getTag() != dwarf::DW_TAG_typedef || !Seen.insert(DT).second)
300 return nullptr;
301 Ty = DT->getBaseType();
302 }
303
304 const auto *BT = dyn_cast_or_null<DIBasicType>(Ty);
305 if (!BT)
306 return nullptr;
307
308 // OpTypeBool carries no width, so a boolean of any size is accepted.
309 if (isBooleanType(BT))
310 return BT;
311
312 unsigned Size = BT->getSizeInBits();
313 switch (BT->getEncoding()) {
314 case dwarf::DW_ATE_signed:
315 case dwarf::DW_ATE_unsigned:
316 case dwarf::DW_ATE_signed_char:
317 case dwarf::DW_ATE_unsigned_char:
318 return Size == 8 || Size == 16 || Size == 32 || Size == 64 ? BT : nullptr;
319 case dwarf::DW_ATE_float:
320 // SPIR-V has no 8-bit float.
321 return Size == 16 || Size == 32 || Size == 64 ? BT : nullptr;
322 default:
323 return nullptr;
324 }
325}
326
327// Collect distinct DILocations and DILocalVariables from LLVM IR.
328//
329// DILocations come from instruction debug locations and from the debug records
330// attached to them. DebugLine pre-emission and MIR lookups assume every
331// machine-instruction debug location already appeared here; a codegen-only
332// location would not be collected and emission will be skipped.
333//
334// DILocalVariables come from the DbgVariableRecords attached to instructions
335// and from the retained nodes of each DISubprogram. Retained nodes are needed
336// because a variable with no remaining debug record (e.g. optimized away) must
337// still get a DebugLocalVariable.
339 const Module &M, SetVector<const DILocation *> &Locations,
341 for (const Function &F : M) {
342 const DISubprogram *SP = F.getSubprogram();
343 if (!SP)
344 continue;
345 for (const MDNode *N : SP->getRetainedNodes())
346 if (const auto *LV = dyn_cast_or_null<DILocalVariable>(N))
347 LVs.insert(LV);
348 for (const Instruction &I : instructions(F)) {
349 if (const DILocation *DL = I.getDebugLoc().get())
350 Locations.insert(DL);
351 for (DbgRecord &DR : I.getDbgRecordRange()) {
352 if (const DILocation *DL = DR.getDebugLoc().get())
353 Locations.insert(DL);
354 if (const auto *DVR = dyn_cast<DbgVariableRecord>(&DR))
355 if (const DILocalVariable *LV = DVR->getVariable())
356 LVs.insert(LV);
357 }
358 }
359 }
360}
361
362// Insert \p S and its enclosing DILexicalBlock/DINamespace chain into \p Out,
363// parent before child, so single-pass emission never needs a forward
364// reference for the Parent operand.
367 // Walk up child-first, then insert in reverse to get parents in first.
369 while (S && !Out.contains(S) && isa<DILexicalBlock, DINamespace>(S)) {
370 Chain.push_back(S);
371 S = S->getScope();
372 }
373 Out.insert(Chain.rbegin(), Chain.rend());
374}
375
377 // The base class sets Asm = nullptr when the module has no compile units,
378 // and initializes lexical scope tracking otherwise.
380
381 if (!Asm)
382 return;
383
384 CompileUnits.clear();
385 BasicTypes.clear();
386 PointerTypes.clear();
387 SubroutineTypes.clear();
388 VectorTypes.clear();
389 ArrayTypes.clear();
390 CompositeTypes.clear();
391 TypedefTypes.clear();
392 SubprogramDeclarations.clear();
393 SubprogramDefinitions.clear();
394 UniqueDebugLocations.clear();
395 GlobalVariableDebugInfoMap.clear();
396 LocalVariables.clear();
397 DebugLocalVariableRegs.clear();
398 DebugExpressionRegs.clear();
399 LexicalBlocks.clear();
400 DebugScopeRegs.clear();
401 DebugInlinedAtRegs.clear();
402 ScopeToPathOpStringReg.clear();
403 DebugSourceRegByFileStr.clear();
404 OpStringContentCache.clear();
405 ScalarTypeCache.clear();
406 ScalarConstantCache.clear();
407 ConstantValueRegs.clear();
408 DebugTypeFunctionCache.clear();
409 DebugOperationCache.clear();
410 DebugExpressionCache.clear();
411 ModuleScopeIds.clear();
412 GlobalDIEmitted = false;
413 GlobalNSDIEnabled = false;
414 CurrentMAI = nullptr;
415#ifndef NDEBUG
416 NonSemanticOpStringsSectionEmitted = false;
417#endif
418 CachedDebugInfoNoneReg = MCRegister();
419 CachedEmptyStringReg = MCRegister();
420 CachedOpTypeVoidReg = MCRegister();
421 CachedOpTypeInt32Reg = MCRegister();
422
423 // Collect compile-unit info: file paths and source languages.
424 for (const DICompileUnit *CU : M->debug_compile_units()) {
425 const DIFile *File = CU->getFile();
426 CompileUnitInfo Info;
427 Info.TheCU = CU;
428 if (sys::path::is_absolute(File->getFilename()))
429 Info.FilePath = File->getFilename();
430 else
431 sys::path::append(Info.FilePath, File->getDirectory(),
432 File->getFilename());
433 // getName() returns the language code regardless of whether the name is
434 // versioned. getUnversionedName() would assert on versioned names.
435 Info.SpirvSourceLanguage = toNSDISrcLang(CU->getSourceLanguage().getName());
436 CompileUnits.push_back(std::move(Info));
437 }
438
439 // Collect DWARF version from module flags. For CodeView modules there is no
440 // "Dwarf Version" flag; DwarfVersion remains 0, which is the correct value
441 // for the DebugCompilationUnit DWARF Version operand in that case.
442 if (const NamedMDNode *Flags = M->getNamedMetadata("llvm.module.flags")) {
443 for (const auto *Op : Flags->operands()) {
444 const MDOperand &NameOp = Op->getOperand(1);
445 if (NameOp.equalsStr("Dwarf Version"))
446 DwarfVersion =
448 cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
449 ->getSExtValue();
450 }
451 }
452
453 // Find all debug info types that may be referenced by NSDI instructions.
454 DebugInfoFinder Finder;
455 Finder.processModule(*M);
456 llvm::for_each(Finder.types(), [&](DIType *Ty) {
457 partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes, VectorTypes,
458 ArrayTypes, CompositeTypes, TypedefTypes);
459 });
460
461 for (const DISubprogram *SP : Finder.subprograms()) {
462 if (SP->isDefinition())
463 SubprogramDefinitions.push_back(SP);
464 else
465 SubprogramDeclarations.push_back(SP);
466 }
467
468 // Walk LLVM globals to map each DIGlobalVariable to its llvm::GlobalVariable.
470 for (const GlobalVariable &G : M->globals()) {
472 G.getDebugInfo(GVEs);
473 for (DIGlobalVariableExpression *GVE : GVEs) {
474 if (const DIGlobalVariable *GV = GVE->getVariable()) {
475 DIGVToLLVMGV.try_emplace(GV, &G);
476 }
477 }
478 }
479
480 for (const DIGlobalVariableExpression *GVE : Finder.global_variables()) {
481 const DIGlobalVariable *GV = GVE->getVariable();
482 const DIExpression *Expr = GVE->getExpression();
483 GlobalVariableDebugInfoMap.try_emplace(
484 GV, GlobalVariableDebugInfo{Expr, DIGVToLLVMGV.lookup(GV)});
485 }
486
487 collectDebugLocationsAndLocalVariables(*M, UniqueDebugLocations,
488 LocalVariables);
489
490 // DILexicalBlock and DINamespace scopes are lowered to DebugLexicalBlock.
491 // Collect them in parent-before-child order so they can be later emitted in a
492 // single pass.
493 for (const DIScope *S : Finder.scopes())
494 collectLexicalBlockChain(S, LexicalBlocks);
495}
496
497// The emitted SPIR-V id of \p MI, or an invalid register when \p MI defines
498// no result.
501 if (MI.getNumOperands() == 0 || !MI.getOperand(0).isReg() ||
502 !MI.getOperand(0).isDef())
503 return MCRegister();
504 return MAI.getRegisterAlias(MI.getMF(), MI.getOperand(0).getReg());
505}
506
509 if (CompileUnits.empty())
510 return;
511 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_non_semantic_info))
512 return;
513
514 // Add the extension to requirements so OpExtension is output.
515 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
516
517 // Add the NonSemantic.Shader.DebugInfo.100 entry to ExtInstSetMap so that
518 // outputOpExtInstImports() emits the OpExtInstImport instruction. Allocate a
519 // fresh result ID for it now; the same ID is used in emitExtInst() operands.
520 if (!MAI.ExtInstSetMap.count(NSSet))
521 MAI.ExtInstSetMap[NSSet] = MAI.getNextIDRegister();
522
524 if (MCRegister Id = getResultId(*MI, MAI))
525 ModuleScopeIds.insert(Id);
526 }
527}
528
529void SPIRVNonSemanticDebugHandler::emitMCInst(MCInst &Inst) {
530 Asm->OutStreamer->emitInstruction(Inst, Asm->getSubtargetInfo());
531}
532
534SPIRVNonSemanticDebugHandler::emitOpString(StringRef S,
537 MCInst Inst;
538 Inst.setOpcode(SPIRV::OpString);
540 addStringImm(S, Inst);
541 emitMCInst(Inst);
542 return Reg;
543}
544
545MCRegister SPIRVNonSemanticDebugHandler::emitOpStringIfNew(
547#ifndef NDEBUG
548 assert(!NonSemanticOpStringsSectionEmitted &&
549 "emitOpStringIfNew is only valid while emitting SPIR-V section 7");
550#endif
551 auto [It, Inserted] = OpStringContentCache.try_emplace(S, MCRegister());
552 if (Inserted)
553 It->second = emitOpString(S, MAI);
554
555 return It->second;
556}
557
558MCRegister SPIRVNonSemanticDebugHandler::getCachedOpStringReg(StringRef S) {
559#ifndef NDEBUG
560 assert(NonSemanticOpStringsSectionEmitted &&
561 "getCachedOpStringReg requires emitNonSemanticDebugStrings() first");
562#endif
563 auto It = OpStringContentCache.find(S);
564 assert(It != OpStringContentCache.end() &&
565 "NSDI OpString missing from cache; emitNonSemanticDebugStrings must "
566 "cache every string used in section 10");
567 return It->second;
568}
569
570MCRegister SPIRVNonSemanticDebugHandler::emitAndCacheScopePathOpStringReg(
571 const DIScope *Scope, SPIRV::ModuleAnalysisInfo &MAI) {
572 auto [It, Inserted] = ScopeToPathOpStringReg.try_emplace(Scope, MCRegister());
573 if (Inserted)
574 It->second = emitOpStringIfNew(getDebugFullPath(Scope), MAI);
575 return It->second;
576}
577
578MCRegister SPIRVNonSemanticDebugHandler::getCachedScopePathOpStringReg(
579 const DIScope *Scope, bool UseEmptyPathIfNullScope) {
580 if (!Scope) {
581 assert(UseEmptyPathIfNullScope &&
582 "null scope path lookup requires UseEmptyPathIfNullScope");
583 assert(CachedEmptyStringReg.isValid() &&
584 "empty path OpString must be cached in emitNonSemanticDebugStrings");
585 return CachedEmptyStringReg;
586 }
587 auto It = ScopeToPathOpStringReg.find(Scope);
588 assert(It != ScopeToPathOpStringReg.end() &&
589 "path OpString must be cached in emitNonSemanticDebugStrings");
590 MCRegister FileStrReg = It->second;
591 assert(FileStrReg.isValid() && "path OpString id must be valid once cached");
592 return FileStrReg;
593}
594
595MCRegister SPIRVNonSemanticDebugHandler::emitOpConstantI32(
596 uint32_t Value, MCRegister I32TypeReg, SPIRV::ModuleAnalysisInfo &MAI) {
597 return findOrEmitConstant(SPIRV::OpConstantI, I32TypeReg, Value,
598 /*Width=*/32, MAI);
599}
600
601MCRegister SPIRVNonSemanticDebugHandler::emitExtInst(
602 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
603 MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
605 MCRegister Reg = MAI.getNextIDRegister();
606 MCInst Inst;
607 Inst.setOpcode(SPIRV::OpExtInst);
609 Inst.addOperand(MCOperand::createReg(VoidTypeReg));
610 Inst.addOperand(MCOperand::createReg(ExtInstSetReg));
611 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Opcode)));
612 for (MCRegister R : Operands)
614 emitMCInst(Inst);
615 return Reg;
616}
617
618MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugTypeFunction(
619 ArrayRef<MCRegister> Ops, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
621 auto [It, Inserted] =
622 DebugTypeFunctionCache.try_emplace(SmallVector<MCRegister, 8>(Ops));
623 if (!Inserted)
624 return It->second;
625
626 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeFunction,
627 VoidTypeReg, ExtInstSetReg, Ops, MAI);
628 It->second = Reg;
629 return Reg;
630}
631
632MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeVoidReg(
634 if (!CachedOpTypeVoidReg.isValid())
635 CachedOpTypeVoidReg = findOrEmitOpTypeVoid(MAI);
636 return CachedOpTypeVoidReg;
637}
638
639MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeInt32Reg(
641 if (!CachedOpTypeInt32Reg.isValid())
642 CachedOpTypeInt32Reg = findOrEmitOpTypeInt32(MAI);
643 return CachedOpTypeInt32Reg;
644}
645
646MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
648 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
649 if (MI->getOpcode() == SPIRV::OpTypeVoid)
650 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
651 }
652 MCRegister Reg = MAI.getNextIDRegister();
653 MCInst Inst;
654 Inst.setOpcode(SPIRV::OpTypeVoid);
656 emitMCInst(Inst);
657 return Reg;
658}
659
660// Whether declaring \p BT's SPIR-V type would require a capability. The type
661// width determines the requirement: Int8, Int16, Int64, Float16 and Float64 in
662// SPIRVModuleAnalysis::collectReqs(). A boolean and a 32-bit scalar are free.
664 if (isBooleanType(BT))
665 return false;
666 unsigned Width = BT->getSizeInBits();
667 return Width != 32;
668}
669
670MCRegister SPIRVNonSemanticDebugHandler::findOrEmitScalarType(
672 bool IsBool = isBooleanType(BT);
673 bool IsFloat = BT->getEncoding() == dwarf::DW_ATE_float;
674 unsigned Opcode = IsBool ? SPIRV::OpTypeBool
675 : IsFloat ? SPIRV::OpTypeFloat
676 : SPIRV::OpTypeInt;
677 // Two DIBasicTypes can describe one SPIR-V type, and OpTypeBool has no
678 // width, so the key is the opcode and the width rather than the node.
679 int64_t Width = IsBool ? 0 : BT->getSizeInBits();
680
681 // OpTypeInt 32 0 is already owned by getOrEmitOpTypeInt32Reg(), which every
682 // line and column constant needs. Declaring a second one is a duplicate type
683 // declaration, which the validator rejects.
684 if (Opcode == SPIRV::OpTypeInt && Width == 32)
685 return getOrEmitOpTypeInt32Reg(MAI);
686
687 auto [CacheIt, Inserted] =
688 ScalarTypeCache.try_emplace({Opcode, Width}, MCRegister());
689 if (!Inserted)
690 return CacheIt->second;
691
692 // The backend writes every integer type with signedness 0, so a signed and
693 // an unsigned DIBasicType of the same width share one OpTypeInt.
694 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
695 if (MI->getOpcode() != Opcode)
696 continue;
697 if (IsBool || (MI->getOperand(1).getImm() == Width &&
698 (IsFloat || MI->getOperand(2).getImm() == 0))) {
699 CacheIt->second =
700 MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
701 return CacheIt->second;
702 }
703 }
704
705 // A non-semantic instruction "has no semantic impact, and can be safely
706 // removed from the module", so debug info must leave the module's
707 // requirements alone. Declaring OpTypeInt 64 forces Int64, which Vulkan ties
708 // to a device feature, so this returns nothing if the type requires a new
709 // capability.
711 return MCRegister();
712
713 MCRegister Reg = MAI.getNextIDRegister();
714 MCInst Inst;
715 Inst.setOpcode(Opcode);
717 if (!IsBool) {
718 Inst.addOperand(MCOperand::createImm(Width));
719 if (!IsFloat)
721 }
722 emitMCInst(Inst);
723 CacheIt->second = Reg;
724 return Reg;
725}
726
727// Whether the constant \p MI holds \p Value, read as two words when \p IsWide.
729 bool IsWide) {
730 unsigned Words = IsWide ? 2 : 1;
731 if (MI.getNumOperands() < 2 + Words)
732 return false;
733 uint64_t Found = 0;
734 for (unsigned I = 0; I < Words; ++I) {
735 if (!MI.getOperand(2 + I).isImm())
736 return false;
737 Found |= static_cast<uint64_t>(
738 static_cast<uint32_t>(MI.getOperand(2 + I).getImm()))
739 << (32 * I);
740 }
741 return Found == Value;
742}
743
744MCRegister SPIRVNonSemanticDebugHandler::findModuleConstant(
745 unsigned Opcode, MCRegister TypeReg, uint64_t Value, bool IsBool,
746 bool IsWide, SPIRV::ModuleAnalysisInfo &MAI) {
747 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
748 if (MI->getOpcode() != Opcode || MI->getNumOperands() < 2)
749 continue;
750 if (MAI.getRegisterAlias(MI->getMF(), MI->getOperand(1).getReg()) !=
751 TypeReg)
752 continue;
753 // A boolean holds its value in its opcode, so there is nothing to compare.
754 if (!IsBool && !constantHasValue(*MI, Value, IsWide))
755 continue;
756 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
757 }
758 return MCRegister();
759}
760
761// \p Width is 0 for a boolean, whose value lives in \p Opcode.
762MCRegister SPIRVNonSemanticDebugHandler::findOrEmitConstant(
763 unsigned Opcode, MCRegister TypeReg, uint64_t Value, unsigned Width,
765 bool IsBool = Width == 0;
766 bool IsWide = Width == 64;
767
768 auto [CacheIt, Inserted] =
769 ScalarConstantCache.try_emplace({TypeReg.id(), Value}, MCRegister());
770 if (!Inserted)
771 return CacheIt->second;
772
773 MCRegister Found =
774 findModuleConstant(Opcode, TypeReg, Value, IsBool, IsWide, MAI);
775 if (Found.isValid()) {
776 CacheIt->second = Found;
777 return Found;
778 }
779
780 MCRegister Reg = MAI.getNextIDRegister();
781 MCInst Inst;
782 Inst.setOpcode(Opcode);
784 Inst.addOperand(MCOperand::createReg(TypeReg));
785 if (!IsBool) {
786 // OpConstant's Value is "the bit pattern for the constant. Types 32 bits
787 // wide or smaller take one word. Larger types take multiple words, with
788 // low-order words appearing first" (SPIR-V specification, OpConstant).
789 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Lo_32(Value))));
790 if (IsWide) {
791 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Hi_32(Value))));
792 } else if (Width == 16) {
793 // A 16-bit float takes one word, the same as a 32-bit one, so the text
794 // printer needs the width to pick the right APFloat semantics.
796 }
797 }
798 emitMCInst(Inst);
799 CacheIt->second = Reg;
800 return Reg;
801}
802
803MCRegister SPIRVNonSemanticDebugHandler::findOrEmitScalarConstant(
805 MCRegister TypeReg = findOrEmitScalarType(BT, MAI);
806 if (!TypeReg.isValid())
807 return MCRegister();
808
809 bool IsBool = isBooleanType(BT);
810 bool IsFloat = BT->getEncoding() == dwarf::DW_ATE_float;
811 unsigned Opcode =
812 IsBool ? (Value ? SPIRV::OpConstantTrue : SPIRV::OpConstantFalse)
813 : IsFloat ? SPIRV::OpConstantF
814 : SPIRV::OpConstantI;
815 return findOrEmitConstant(Opcode, TypeReg, Value,
816 IsBool ? 0 : BT->getSizeInBits(), MAI);
817}
818
819MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
821 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
822 if (MI->getOpcode() == SPIRV::OpTypeInt &&
823 MI->getOperand(1).getImm() == 32 && MI->getOperand(2).getImm() == 0)
824 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
825 }
826 MCRegister Reg = MAI.getNextIDRegister();
827 MCInst Inst;
828 Inst.setOpcode(SPIRV::OpTypeInt);
830 Inst.addOperand(MCOperand::createImm(32)); // width
831 Inst.addOperand(MCOperand::createImm(0)); // signedness (unsigned)
832 emitMCInst(Inst);
833 return Reg;
834}
835
836std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
837 const DIDerivedType *PT, MCRegister ExtInstSetReg,
839 // A DWARF address space is required to determine the SPIR-V storage class.
840 // Skip pointer types that do not carry one.
841 if (!PT->getDWARFAddressSpace().has_value())
842 return std::nullopt;
843
844 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
845 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
846 MCRegister DebugTypePointerFlagsReg =
847 emitOpConstantI32(transDebugFlags(PT), I32TypeReg, MAI);
848
849 // For SPIR-V targets, Clang sets DwarfAddressSpace to the LLVM IR address
850 // space, which addressSpaceToStorageClass expects.
851 const auto &ST = static_cast<const SPIRVSubtarget &>(Asm->getSubtargetInfo());
852 MCRegister StorageClassReg = emitOpConstantI32(
853 addressSpaceToStorageClass(PT->getDWARFAddressSpace().value(), ST),
854 I32TypeReg, MAI);
855
856 if (const DIType *BaseTy = PT->getBaseType()) {
857 auto BaseIt = DebugScopeRegs.find(BaseTy);
858 if (BaseIt != DebugScopeRegs.end())
859 return emitExtInst(
860 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
861 ExtInstSetReg,
862 {BaseIt->second, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
863 // Unsupported type, no DebugType* id available.
864 return std::nullopt;
865 }
866 // No getBaseType() (typical for void*): use DebugInfoNone as Base Type,
867 // same as SPIRV-LLVM-Translator (see issue #109287 and the DISABLED
868 // spirv-val run in debug-type-pointer.ll). spirv-val may still reject this
869 // encoding; see https://github.com/KhronosGroup/SPIRV-Registry/pull/287.
870 return emitExtInst(
871 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg, ExtInstSetReg,
872 {CachedDebugInfoNoneReg, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
873}
874
875std::optional<MCRegister>
876SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
877 const DISubroutineType *ST, MCRegister ExtInstSetReg,
879 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
880 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
881 MCRegister DebugTypeFunctionFlagsReg =
882 emitOpConstantI32(transDebugFlags(ST), I32TypeReg, MAI);
883 DITypeArray TA = ST->getTypeArray();
885 Ops.push_back(DebugTypeFunctionFlagsReg);
886 // Empty DI type tuple: no explicit return or parameter slots (hand-written IR
887 // may use !{}). Emit void-only prototype. Same as SPIRV-LLVM-Translator when
888 // DISubroutineType::getTypeArray() has zero elements.
889 if (TA.empty()) {
890 Ops.push_back(VoidTypeReg);
891 } else {
892 for (unsigned I = 0, E = TA.size(); I != E; ++I) {
893 bool IsReturnType = (I == 0);
894 auto OptReg = mapDISignatureTypeToReg(TA[I], VoidTypeReg, IsReturnType);
895 // No emitted DebugType* id for this slot (e.g., pointer that
896 // was skipped due missing address space, etc.).
897 if (!OptReg)
898 return std::nullopt;
899 Ops.push_back(*OptReg);
900 }
901 }
902 return getOrEmitDebugTypeFunction(Ops, VoidTypeReg, ExtInstSetReg, MAI);
903}
904
905// Match SPIRV-LLVM-Translator's selection logic for the Parent operand.
906std::optional<MCRegister> SPIRVNonSemanticDebugHandler::resolveScope(
907 const DIScope *Scope, const DICompileUnit *FallbackCU) const {
908
909 // DebugLexicalBlockDiscriminator cannot be used as a scope, so unwrap it.
910 while (const auto *DLBF = dyn_cast_or_null<DILexicalBlockFile>(Scope))
911 Scope = DLBF->getScope();
912
914 return lookupOptReg(DebugScopeRegs, Scope);
915
916 // For a file, compile-unit, or absent scope, fall back to a compile unit.
917 if (FallbackCU)
918 return lookupOptReg(DebugScopeRegs, FallbackCU);
919
920 if (CompileUnits.empty())
921 return std::nullopt;
922
923 return lookupOptReg(DebugScopeRegs, CompileUnits[0].TheCU);
924}
925
926std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLexicalBlock(
927 const DIScope *S, MCRegister VoidTypeReg, MCRegister I32TypeReg,
928 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
930 "S must be a DILexicalBlock or DINamespace in emitDebugLexicalBlock");
931 auto ParentRegOpt = resolveScope(S->getScope());
932 if (!ParentRegOpt)
933 return std::nullopt;
934
935 MCRegister FileStrReg = getCachedScopePathOpStringReg(
936 S->getFile(), /*UseEmptyPathIfNullScope=*/true);
937 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
938 ExtInstSetReg, MAI);
939
941 if (const auto *LB = dyn_cast<DILexicalBlock>(S)) {
942 MCRegister LineReg = emitOpConstantI32(static_cast<uint32_t>(LB->getLine()),
943 I32TypeReg, MAI);
944 MCRegister ColReg = emitOpConstantI32(
945 static_cast<uint32_t>(LB->getColumn()), I32TypeReg, MAI);
946 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt};
947 } else {
948 const auto *NS = cast<DINamespace>(S);
949 // DINamespace carries no line/column info.
950 MCRegister LineReg = emitOpConstantI32(0, I32TypeReg, MAI);
951 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
952 MCRegister NameReg = getCachedOpStringReg(NS->getName());
953 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt, NameReg};
954 }
955
956 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLexicalBlock, VoidTypeReg,
957 ExtInstSetReg, Ops, MAI);
958}
959
960MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugInlinedAt(
961 const DILocation *IA, MCRegister VoidTypeReg, MCRegister I32TypeReg,
962 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
963 assert(IA && "IA must not be null in getOrEmitDebugInlinedAt");
964
965 if (MCRegister Cached = DebugInlinedAtRegs.lookup(IA))
966 return Cached;
967
968 auto ScopeRegOpt = resolveScope(IA->getScope());
969 if (!ScopeRegOpt)
970 return MCRegister();
971
972 MCRegister LineReg =
973 emitOpConstantI32(static_cast<uint32_t>(IA->getLine()), I32TypeReg, MAI);
974
975 SmallVector<MCRegister, 3> Ops{LineReg, *ScopeRegOpt};
976 // Recurse before building this instruction's operands so an outer
977 // inlined-at link is always available.
978 if (const DILocation *Outer = IA->getInlinedAt()) {
979 MCRegister OuterReg = getOrEmitDebugInlinedAt(
980 Outer, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
981 if (!OuterReg.isValid())
982 return MCRegister();
983 Ops.push_back(OuterReg);
984 }
985
986 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInlinedAt,
987 VoidTypeReg, ExtInstSetReg, Ops, MAI);
988 DebugInlinedAtRegs[IA] = Reg;
989 return Reg;
990}
991
992std::optional<MCRegister>
993SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
994 const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
995 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
996 assert(SP && "SP must not be null in emitDebugFunctionDeclaration");
997 assert(!SP->isDefinition() &&
998 "SP must not be a definition in emitDebugFunctionDeclaration");
999
1000 // The IR verifier already enforces that this cannot be null.
1001 const DISubroutineType *ST = SP->getType();
1002
1003 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
1004 if (!FnTyRegOpt)
1005 return std::nullopt;
1006 MCRegister FnTyReg = *FnTyRegOpt;
1007
1008 auto ParentRegOpt = resolveScope(SP->getScope(), SP->getUnit());
1009 if (!ParentRegOpt)
1010 return std::nullopt;
1011
1012 MCRegister ParentReg = *ParentRegOpt;
1013
1014 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
1015
1016 MCRegister NameReg = getCachedOpStringReg(SP->getName());
1017 MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
1018 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1019 ExtInstSetReg, MAI);
1020
1021 MCRegister LineReg =
1022 emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
1023 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1024
1025 uint32_t FlagsVal = transDebugFlags(SP);
1026 // TODO: When composite scopes are DebugFunctionDeclaration parents (available
1027 // in DebugScopeRegs), sync declaration Flags with SPIRV-LLVM-Translator.
1028 FlagsVal &= ~NSDIFlagIsDefinition;
1029 MCRegister FlagsReg = emitOpConstantI32(FlagsVal, I32TypeReg, MAI);
1030
1031 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
1032 VoidTypeReg, ExtInstSetReg,
1033 {NameReg, FnTyReg, SrcReg, LineReg, ColReg, ParentReg,
1034 LinkageReg, FlagsReg},
1035 MAI);
1036}
1037
1038std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugFunction(
1039 const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1040 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1041 assert(SP && "SP must not be null in emitDebugFunction");
1042 assert(SP->isDefinition() && "SP must be a definition in emitDebugFunction");
1043
1044 const DISubroutineType *ST = SP->getType();
1045 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
1046 if (!FnTyRegOpt)
1047 return std::nullopt;
1048
1049 auto ParentRegOpt = resolveScope(SP->getScope(), SP->getUnit());
1050 if (!ParentRegOpt)
1051 return std::nullopt;
1052
1053 MCRegister NameReg = getCachedOpStringReg(SP->getName());
1054 MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
1055 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
1056 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1057 ExtInstSetReg, MAI);
1058
1059 MCRegister LineReg =
1060 emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
1061 // LLVM's DISubprogram has no column field but SPIR-V expects one in
1062 // DebugFunction.
1063 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1064 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(SP), I32TypeReg, MAI);
1065 MCRegister ScopeLineReg = emitOpConstantI32(
1066 static_cast<uint32_t>(SP->getScopeLine()), I32TypeReg, MAI);
1067
1068 SmallVector<MCRegister, 10> Ops = {NameReg, *FnTyRegOpt, SrcReg,
1069 LineReg, ColReg, *ParentRegOpt,
1070 LinkageReg, FlagsReg, ScopeLineReg};
1071
1072 if (const DISubprogram *Decl = SP->getDeclaration()) {
1073 if (auto DeclRegOpt = lookupOptReg(DebugScopeRegs, Decl))
1074 Ops.push_back(*DeclRegOpt);
1075 }
1076
1077 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunction, VoidTypeReg,
1078 ExtInstSetReg, Ops, MAI);
1079}
1080
1081std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
1082 const DIType *Ty, MCRegister VoidTypeReg, bool ReturnType) {
1083 if (!Ty) {
1084 if (ReturnType)
1085 return VoidTypeReg;
1086 assert(CachedDebugInfoNoneReg.isValid() &&
1087 "DebugInfoNone must be emitted before DISubroutineType operands");
1088 return CachedDebugInfoNoneReg;
1089 }
1090 return lookupOptReg(DebugScopeRegs, Ty);
1091}
1092
1093// NonSemantic.Shader.DebugInfo.100 debug operation encodings
1094// (section 4.5, "Debug Operations").
1107
1108static std::optional<NonSemanticDebugOp>
1110 switch (DwarfOp) {
1111 case dwarf::DW_OP_deref:
1113 case dwarf::DW_OP_plus:
1115 case dwarf::DW_OP_minus:
1117 case dwarf::DW_OP_plus_uconst:
1119 case dwarf::DW_OP_bit_piece:
1121 case dwarf::DW_OP_swap:
1123 case dwarf::DW_OP_xderef:
1125 case dwarf::DW_OP_stack_value:
1127 case dwarf::DW_OP_constu:
1131 default:
1132 return std::nullopt;
1133 }
1134}
1135
1136// The DebugOperation operand values for \p Op. Each becomes an OpConstant of
1137// OpTypeInt 32 0, so every argument must fit in 32 bits.
1138static std::optional<SmallVector<uint32_t, 3>>
1140 std::optional<NonSemanticDebugOp> NSOp =
1142 if (!NSOp)
1143 return std::nullopt;
1144
1145 SmallVector<uint32_t, 3> Operands{static_cast<uint32_t>(*NSOp)};
1146 for (unsigned I = 0, E = Op.getNumArgs(); I != E; ++I) {
1147 uint64_t Arg = Op.getArg(I);
1148 if (!isUInt<32>(Arg))
1149 return std::nullopt;
1150 Operands.push_back(static_cast<uint32_t>(Arg));
1151 }
1152 return Operands;
1153}
1154
1155std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugOperation(
1156 const DIExpression::ExprOperand &Op, MCRegister VoidTypeReg,
1157 MCRegister I32TypeReg, MCRegister ExtInstSetReg,
1159 std::optional<SmallVector<uint32_t, 3>> Key = mapExprOperand(Op);
1160 if (!Key)
1161 return std::nullopt;
1162
1163 auto [It, Inserted] = DebugOperationCache.try_emplace(std::move(*Key));
1164 if (!Inserted)
1165 return It->second;
1166
1168 for (uint32_t V : It->first)
1169 Operands.push_back(emitOpConstantI32(V, I32TypeReg, MAI));
1170 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugOperation,
1171 VoidTypeReg, ExtInstSetReg, Operands, MAI);
1172 It->second = Reg;
1173 return Reg;
1174}
1175
1176std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugExpression(
1177 const DIExpression *Expr, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1178 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1179 assert(Expr && "Expr must not be null in emitDebugExpression");
1180
1181 SmallVector<MCRegister> OperationRegs;
1182 for (const DIExpression::ExprOperand &Op : Expr->expr_ops()) {
1183 std::optional<MCRegister> OpReg =
1184 emitDebugOperation(Op, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
1185 if (!OpReg)
1186 return std::nullopt;
1187 OperationRegs.push_back(*OpReg);
1188 }
1189
1190 auto [It, Inserted] =
1191 DebugExpressionCache.try_emplace(std::move(OperationRegs));
1192 if (!Inserted)
1193 return It->second;
1194
1195 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugExpression,
1196 VoidTypeReg, ExtInstSetReg, It->first, MAI);
1197 It->second = Reg;
1198 return Reg;
1199}
1200
1201std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugGlobalVariable(
1202 const DIGlobalVariable *GV, const GlobalVariableDebugInfo &Info,
1203 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
1205 assert(GV && "GV must not be null in emitDebugGlobalVariable");
1206
1207 auto ParentRegOpt = resolveScope(GV->getScope());
1208 if (!ParentRegOpt)
1209 return std::nullopt;
1210
1211 MCRegister ParentReg = *ParentRegOpt;
1212
1213 // TyReg: DebugInfoNone when GV has no DI type (as done in
1214 // SPIRV-LLVM-Translator). Declarations (isDefinition: false) can have null
1215 // getType() while definitions must have a non-null one (enforced by the IR
1216 // verifier).
1217 MCRegister TyReg = CachedDebugInfoNoneReg;
1218 if (const DIType *Ty = GV->getType()) {
1219 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1220 if (!TyRegOpt)
1221 return std::nullopt;
1222 TyReg = *TyRegOpt;
1223 }
1224
1225 std::optional<MCRegister> StaticMemberRegOpt;
1226 if (const DIDerivedType *SM = GV->getStaticDataMemberDeclaration()) {
1227 StaticMemberRegOpt = lookupOptReg(DebugScopeRegs, SM);
1228 if (!StaticMemberRegOpt)
1229 return std::nullopt;
1230 }
1231
1232 MCRegister NameReg = getCachedOpStringReg(GV->getName());
1233 MCRegister LinkageReg = getCachedOpStringReg(GV->getLinkageName());
1234 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1235 GV->getFile(), /*UseEmptyPathIfNullScope=*/true);
1236 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1237 ExtInstSetReg, MAI);
1238
1239 MCRegister LineReg =
1240 emitOpConstantI32(static_cast<uint32_t>(GV->getLine()), I32TypeReg, MAI);
1241 // DIGlobalVariable or DIGlobalVariableExpression metadata carry no column
1242 // field. Column is hardcoded to 0 (because it can't be determined), matching
1243 // SPIRV-LLVM-Translator.
1244 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1245
1246 // Variable: @g OpVariable id when !dbg matches; else a DebugExpression for
1247 // the GVE init value when no @g exists and the expression is non-empty; else
1248 // DebugInfoNone. As per spec, the DebugExpression must contain the constant
1249 // value of the variable that was optimized out. An empty expression contains
1250 // no value, so we emit DebugInfoNone instead.
1251 MCRegister VariableReg = CachedDebugInfoNoneReg;
1252 if (const GlobalVariable *LLVMGV = Info.LLVMGV) {
1253 MCRegister GVReg = MAI.getGlobalObjReg(LLVMGV);
1254 if (GVReg.isValid())
1255 VariableReg = GVReg;
1256 } else if (Info.Expr && Info.Expr->getNumElements() != 0) {
1257 if (auto ExprReg = emitDebugExpression(Info.Expr, VoidTypeReg, I32TypeReg,
1258 ExtInstSetReg, MAI))
1259 VariableReg = *ExprReg;
1260 }
1261
1262 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(GV), I32TypeReg, MAI);
1263
1264 SmallVector<MCRegister, 10> Ops = {NameReg, TyReg, SrcReg,
1265 LineReg, ColReg, ParentReg,
1266 LinkageReg, VariableReg, FlagsReg};
1267
1268 if (StaticMemberRegOpt)
1269 Ops.push_back(*StaticMemberRegOpt);
1270
1271 return emitExtInst(SPIRV::NonSemanticExtInst::DebugGlobalVariable,
1272 VoidTypeReg, ExtInstSetReg, Ops, MAI);
1273}
1274
1275std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLocalVariable(
1276 const DILocalVariable *LV, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1277 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1278 assert(LV && "LV must not be null in emitDebugLocalVariable");
1279
1280 auto ParentRegOpt = resolveScope(LV->getScope());
1281 if (!ParentRegOpt)
1282 return std::nullopt;
1283
1284 MCRegister TyReg = CachedDebugInfoNoneReg;
1285 if (const DIType *Ty = LV->getType()) {
1286 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1287 if (!TyRegOpt)
1288 return std::nullopt;
1289 TyReg = *TyRegOpt;
1290 }
1291
1292 MCRegister NameReg = getCachedOpStringReg(LV->getName());
1293 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1294 LV->getFile(), /*UseEmptyPathIfNullScope=*/true);
1295 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1296 ExtInstSetReg, MAI);
1297 MCRegister LineReg =
1298 emitOpConstantI32(static_cast<uint32_t>(LV->getLine()), I32TypeReg, MAI);
1299 // DILocalVariable has no column field. Column is hardcoded to 0.
1300 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1301 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(LV), I32TypeReg, MAI);
1302
1303 SmallVector<MCRegister, 8> Ops = {NameReg, TyReg, SrcReg, LineReg,
1304 ColReg, *ParentRegOpt, FlagsReg};
1305 if (unsigned Arg = LV->getArg())
1306 Ops.push_back(emitOpConstantI32(Arg, I32TypeReg, MAI));
1307
1308 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLocalVariable, VoidTypeReg,
1309 ExtInstSetReg, Ops, MAI);
1310}
1311
1312std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
1313 const DICompositeType *VT, MCRegister ExtInstSetReg,
1315 const auto *BaseTy = dyn_cast_or_null<DIBasicType>(VT->getBaseType());
1316 if (!BaseTy)
1317 return std::nullopt;
1318 auto BTIt = DebugScopeRegs.find(BaseTy);
1319 if (BTIt == DebugScopeRegs.end())
1320 return std::nullopt;
1321
1322 // DebugTypeVector models only 1D vectors (multi-subrange types cannot be
1323 // encoded).
1324 DINodeArray Elements = VT->getElements();
1325 if (Elements.size() != 1)
1326 return std::nullopt;
1327 const auto *SR = cast<DISubrange>(Elements[0]);
1328 const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount());
1329 if (!CI)
1330 return std::nullopt;
1331
1332 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1333 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1334 MCRegister CountReg = emitOpConstantI32(
1335 static_cast<uint32_t>(CI->getZExtValue()), I32TypeReg, MAI);
1336 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeVector, VoidTypeReg,
1337 ExtInstSetReg, {BTIt->second, CountReg}, MAI);
1338}
1339
1340std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeArray(
1341 const DICompositeType *AT, MCRegister ExtInstSetReg,
1343 // The element (base) type must already be in DebugScopeRegs. Unlike
1344 // DebugTypeVector, the element may be any debug type, not only a basic type.
1345 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, AT->getBaseType());
1346 if (!BaseRegOpt)
1347 return std::nullopt;
1348
1349 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1350 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1351
1353 Ops.push_back(*BaseRegOpt);
1354
1355 // One component count per DISubrange, in DWARF subrange order. Emit 0 for
1356 // counts that are not a compile-time constant (dynamic arrays). This matches
1357 // OpTypeRuntimeArray.
1358 for (const DINode *Element : AT->getElements()) {
1359 const auto *SR = dyn_cast<DISubrange>(Element);
1360 if (!SR)
1361 continue;
1362 // A DIVariable count (a variable-length array) is not a ConstantInt, so it
1363 // maps to 0 here. DebugTypeArray also allows a DebugLocalVariable or
1364 // DebugGlobalVariable id for it, but no frontend we target emits one. A
1365 // constant wider than 32 bits maps to 0 too, since the count operand is a
1366 // 32-bit OpConstant and such an array cannot occur in a shader.
1367 uint32_t Count = 0;
1368 if (const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount())) {
1369 const APInt &Value = CI->getValue();
1370 if (Value.getActiveBits() <= 32)
1371 Count = static_cast<uint32_t>(Value.getZExtValue());
1372 }
1373 Ops.push_back(emitOpConstantI32(Count, I32TypeReg, MAI));
1374 }
1375
1376 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeArray, VoidTypeReg,
1377 ExtInstSetReg, Ops, MAI);
1378}
1379
1380std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeMember(
1381 const DIDerivedType *M, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1382 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1383 // The member type must already be in DebugScopeRegs.
1384 auto TyRegOpt = lookupOptReg(DebugScopeRegs, M->getBaseType());
1385 if (!TyRegOpt)
1386 return std::nullopt;
1387
1388 if (!isUInt<32>(M->getOffsetInBits()) || !isUInt<32>(M->getSizeInBits()))
1389 return std::nullopt;
1390
1391 MCRegister NameReg = getCachedOpStringReg(M->getName());
1392 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1393 M->getFile(), /*UseEmptyPathIfNullScope=*/true);
1394 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1395 ExtInstSetReg, MAI);
1396 MCRegister LineReg =
1397 emitOpConstantI32(static_cast<uint32_t>(M->getLine()), I32TypeReg, MAI);
1398
1399 // DIDerivedType members carry no column, so emit 0.
1400 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1401 MCRegister OffsetReg = emitOpConstantI32(
1402 static_cast<uint32_t>(M->getOffsetInBits()), I32TypeReg, MAI);
1403 MCRegister SizeReg = emitOpConstantI32(
1404 static_cast<uint32_t>(M->getSizeInBits()), I32TypeReg, MAI);
1405 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(M), I32TypeReg, MAI);
1406
1407 // In NonSemantic.Shader.DebugInfo a DebugTypeMember has no Parent operand:
1408 // only the composite references its members. This is by design, it drops the
1409 // Parent that OpenCL.DebugInfo.100 had, and it avoids a composite/member
1410 // reference cycle.
1411 //
1412 // FIXME: Static members are not handled yet: their constant initializer is
1413 // available but is not emitted as the optional Value operand, and under DWARF
1414 // 5 a static member is tagged DW_TAG_variable, which the caller's member loop
1415 // skips.
1416 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeMember, VoidTypeReg,
1417 ExtInstSetReg,
1418 {NameReg, *TyRegOpt, SrcReg, LineReg, ColReg, OffsetReg,
1419 SizeReg, FlagsReg},
1420 MAI);
1421}
1422
1423std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeComposite(
1424 const DICompositeType *CT, ArrayRef<MCRegister> MemberRegs,
1425 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
1427 auto ParentRegOpt = resolveScope(CT->getScope());
1428 if (!ParentRegOpt)
1429 return std::nullopt;
1430
1431 if (!isUInt<32>(CT->getSizeInBits()))
1432 return std::nullopt;
1433
1434 MCRegister NameReg = getCachedOpStringReg(CT->getName());
1435 MCRegister LinkageReg = getCachedOpStringReg(CT->getIdentifier());
1436 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1437 CT->getFile(), /*UseEmptyPathIfNullScope=*/true);
1438 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1439 ExtInstSetReg, MAI);
1440
1441 MCRegister TagReg =
1442 emitOpConstantI32(mapCompositeTypeTag(CT->getTag()), I32TypeReg, MAI);
1443 MCRegister LineReg =
1444 emitOpConstantI32(static_cast<uint32_t>(CT->getLine()), I32TypeReg, MAI);
1445 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1446
1447 // A forward declaration has no known size or members: Size is DebugInfoNone.
1448 MCRegister SizeReg = CachedDebugInfoNoneReg;
1449 if (!CT->isForwardDecl())
1450 SizeReg = emitOpConstantI32(static_cast<uint32_t>(CT->getSizeInBits()),
1451 I32TypeReg, MAI);
1452
1453 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(CT), I32TypeReg, MAI);
1454
1455 SmallVector<MCRegister> Ops = {NameReg, TagReg, SrcReg,
1456 LineReg, ColReg, *ParentRegOpt,
1457 LinkageReg, SizeReg, FlagsReg};
1458 Ops.append(MemberRegs.begin(), MemberRegs.end());
1459 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeComposite, VoidTypeReg,
1460 ExtInstSetReg, Ops, MAI);
1461}
1462
1463std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypedef(
1464 const DIDerivedType *TD, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1465 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1466 // The underlying (base) type must already be in DebugScopeRegs.
1467 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, TD->getBaseType());
1468 if (!BaseRegOpt)
1469 return std::nullopt;
1470
1471 MCRegister NameReg = getCachedOpStringReg(TD->getName());
1472 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1473 TD->getFile(), /*UseEmptyPathIfNullScope=*/true);
1474 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1475 ExtInstSetReg, MAI);
1476 MCRegister LineReg =
1477 emitOpConstantI32(static_cast<uint32_t>(TD->getLine()), I32TypeReg, MAI);
1478 // DIDerivedType typedefs carry no column, so emit 0.
1479 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1480
1481 // Parent must be a lexical scope. Valid NSDI lexical scopes are
1482 // DebugCompilationUnit, DebugFunction, DebugLexicalBlock, or
1483 // DebugTypeComposite.
1484 auto ParentRegOpt = resolveScope(TD->getScope());
1485 if (!ParentRegOpt)
1486 return std::nullopt;
1487 MCRegister ParentReg = *ParentRegOpt;
1488
1489 return emitExtInst(
1490 SPIRV::NonSemanticExtInst::DebugTypedef, VoidTypeReg, ExtInstSetReg,
1491 {NameReg, *BaseRegOpt, SrcReg, LineReg, ColReg, ParentReg}, MAI);
1492}
1493
1496 if (CompileUnits.empty())
1497 return;
1498 // Check that prepareModuleOutput() registered the extended instruction set.
1499 // If the subtarget does not support the extension, neither strings nor ext
1500 // insts are emitted.
1501 if (!MAI.getExtInstSetReg(NSSet).isValid())
1502 return;
1503
1504 for (const CompileUnitInfo &Info : CompileUnits) {
1505 if (Info.TheCU) {
1506 MCRegister PathReg = emitOpStringIfNew(Info.FilePath, MAI);
1507 ScopeToPathOpStringReg[Info.TheCU] = PathReg;
1508 if (const DIFile *F = Info.TheCU->getFile())
1509 ScopeToPathOpStringReg[F] = PathReg;
1510 }
1511 }
1512
1513 for (const DIBasicType *BT : BasicTypes)
1514 emitOpStringIfNew(BT->getName(), MAI);
1515
1517 SubprogramDeclarations, SubprogramDefinitions)) {
1518 emitOpStringIfNew(SP->getName(), MAI);
1519 emitOpStringIfNew(SP->getLinkageName(), MAI);
1520 emitAndCacheScopePathOpStringReg(SP, MAI);
1521 }
1522
1523 // Cache the OpStrings each DebugTypeComposite and its DebugTypeMembers use:
1524 // the composite name, identifier (linkage name), and path, plus each member
1525 // name and path.
1526 for (const DICompositeType *CT : CompositeTypes) {
1527 emitOpStringIfNew(CT->getName(), MAI);
1528 emitOpStringIfNew(CT->getIdentifier(), MAI);
1529 emitAndCacheScopePathOpStringReg(CT->getFile(), MAI);
1530 for (const DINode *Element : CT->getElements()) {
1531 const auto *M = dyn_cast<DIDerivedType>(Element);
1532 if (!M || M->getTag() != dwarf::DW_TAG_member)
1533 continue;
1534 emitOpStringIfNew(M->getName(), MAI);
1535 emitAndCacheScopePathOpStringReg(M->getFile(), MAI);
1536 }
1537 }
1538
1539 // Cache the name and path OpStrings each DebugTypedef uses.
1540 for (const DIDerivedType *TD : TypedefTypes) {
1541 emitOpStringIfNew(TD->getName(), MAI);
1542 emitAndCacheScopePathOpStringReg(TD->getFile(), MAI);
1543 }
1544
1545 for (const auto &[GV, _] : GlobalVariableDebugInfoMap) {
1546 emitOpStringIfNew(GV->getName(), MAI);
1547 emitOpStringIfNew(GV->getLinkageName(), MAI);
1548 emitAndCacheScopePathOpStringReg(GV->getFile(), MAI);
1549 }
1550
1551 for (const DILocalVariable *LV : LocalVariables) {
1552 emitOpStringIfNew(LV->getName(), MAI);
1553 emitAndCacheScopePathOpStringReg(LV->getFile(), MAI);
1554 }
1555
1556 // Cache the path OpString each DebugLexicalBlock uses (source file), plus
1557 // the Name OpString for the DINamespace case.
1558 for (const DIScope *S : LexicalBlocks) {
1559 emitAndCacheScopePathOpStringReg(S->getFile(), MAI);
1560 if (const auto *NS = dyn_cast<DINamespace>(S))
1561 emitOpStringIfNew(NS->getName(), MAI);
1562 }
1563
1564 for (const DILocation *DL : UniqueDebugLocations)
1565 emitAndCacheScopePathOpStringReg(DL->getScope(), MAI);
1566
1567 CachedEmptyStringReg = emitOpStringIfNew("", MAI);
1568
1569#ifndef NDEBUG
1570 NonSemanticOpStringsSectionEmitted = true;
1571#endif
1572}
1573
1574void SPIRVNonSemanticDebugHandler::emitDebugFunctionDefinition(
1575 MCRegister DebugFunctionReg, MCRegister OpFunctionReg,
1577 assert(DebugFunctionReg.isValid() && OpFunctionReg.isValid() &&
1578 "DebugFunctionDefinition operands must be valid");
1579 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1580 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1581 emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDefinition, VoidTypeReg,
1582 ExtInstSetReg, {DebugFunctionReg, OpFunctionReg}, MAI);
1583}
1584
1585void SPIRVNonSemanticDebugHandler::resetPerFunctionDebugState() {
1586 CurrentMF = nullptr;
1587 LastFunctionOpVariable = nullptr;
1588 DebugFunctionDefinitionEmitted = false;
1589 LastLineMI = nullptr;
1590 LastScopeMI = nullptr;
1591 Records.clear();
1592}
1593
1594void SPIRVNonSemanticDebugHandler::preparePerFunctionDebug(
1595 const MachineFunction *MF) {
1596 resetPerFunctionDebugState();
1597 if (!GlobalNSDIEnabled || !CurrentMAI)
1598 return;
1599
1600 CurrentMF = MF;
1601
1602 if (MF->getFunction()
1604 .isValid())
1605 return;
1606
1607 const DISubprogram *SP = MF->getFunction().getSubprogram();
1608 if (!SP || !SP->isDefinition())
1609 return;
1610
1611 // DebugFunctionDefinition is emitted after the last function-level
1612 // OpVariable. If there are none, it is emitted after the entry OpLabel.
1613 LastFunctionOpVariable =
1614 findLastFunctionOpVariableDeclaration(*MF, *CurrentMAI);
1615
1616 analyzeDebugRecords(*MF);
1617}
1618
1619void SPIRVNonSemanticDebugHandler::tryEmitDebugFunctionDefinition(
1621 if (DebugFunctionDefinitionEmitted || !GlobalNSDIEnabled)
1622 return;
1623
1624 assert(CurrentMF && "no current MachineFunction");
1625 const Function &F = CurrentMF->getFunction();
1626 const DISubprogram *SP = F.getSubprogram();
1627 if (!SP || !SP->isDefinition())
1628 return;
1629
1630 auto DFIt = DebugScopeRegs.find(SP);
1631 if (DFIt == DebugScopeRegs.end())
1632 return;
1633
1634 MCRegister OpFunctionReg = MAI.getGlobalObjReg(&F);
1635 if (!OpFunctionReg.isValid())
1636 return;
1637
1638 emitDebugFunctionDefinition(DFIt->second, OpFunctionReg, MAI);
1639 DebugFunctionDefinitionEmitted = true;
1640}
1641
1643 const MachineFunction *MF) {
1644 preparePerFunctionDebug(MF);
1645}
1646
1648 (void)MF;
1649 resetPerFunctionDebugState();
1650}
1651
1653 assert(CurMI == nullptr && "CurMI must be null");
1654 CurMI = MI;
1655
1656 if (!DebugFunctionDefinitionEmitted)
1657 return;
1658
1659 emitAnalyzedRecords(MI);
1660
1661 std::optional<const MachineInstr *> Target = resolveDebugLocTarget(MI);
1662 if (!Target)
1663 return;
1664
1665 (void)emitDebugScopeForInstruction(*Target);
1666 emitDebugLineForInstruction(*Target);
1667}
1668
1669// The register that holds the variable's address in \p MI, or std::nullopt
1670// when \p MI is not a declare this backend can describe.
1671//
1672// The spec requires DebugDeclare's Variable operand to be "the <id> of an
1673// OpVariable instruction that defines the local variable". MIR has no
1674// DBG_DECLARE, so what this looks for is an indirect DBG_VALUE whose location
1675// register an OpVariable defines.
1676static std::optional<Register>
1678 // #dbg_declare is an indirect DBG_VALUE in MIR; #dbg_value is normally a
1679 // direct one except for the variadic case.
1680 if (!MI.isIndirectDebugValue())
1681 return std::nullopt;
1682
1683 // A variadic #dbg_value becomes DBG_VALUE $noreg, 0, ... which is indirect
1684 // too, and $noreg is not virtual.
1685 Register LocReg = MI.getDebugOperand(0).getReg();
1686 if (!LocReg.isVirtual())
1687 return std::nullopt;
1688
1689 // DebugDeclare can only encode the address of an OpVariable.
1690 // Other legitimate #dbg_declare cannot be encoded.
1691 // Examples: an access chain for a field, an OpFunctionParameter for a byval
1692 // argument, or a module-scope constant for a null or fixed address.
1693
1694 // LocReg may also have no def at all: erasing dead storage leaves the
1695 // DBG_VALUE pointing at an undefined register. MachineVerifier permits that
1696 // because LiveDebugVariables normally clears it, but this pipeline has no
1697 // register allocation, so LiveDebugVariables never runs.
1698 const MachineInstr *Def = MI.getMF()->getRegInfo().getUniqueVRegDef(LocReg);
1699 if (!Def || Def->getOpcode() != SPIRV::OpVariable)
1700 return std::nullopt;
1701
1702 return LocReg;
1703}
1704
1705void SPIRVNonSemanticDebugHandler::emitDebugBinding(
1706 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
1707 const MachineInstr *MI, MCRegister LocationReg) {
1708 assert(DebugFunctionDefinitionEmitted &&
1709 "DebugFunctionDefinition must be emitted");
1710 assert(CurrentMAI && "CurrentMAI must be set");
1711
1712 auto VarRegOpt = lookupOptReg(DebugLocalVariableRegs, MI->getDebugVariable());
1713 if (!VarRegOpt)
1714 return;
1715
1716 auto ExprRegOpt = lookupOptReg(DebugExpressionRegs, MI->getDebugExpression());
1717 if (!ExprRegOpt)
1718 return;
1719
1720 if (!emitDebugScopeForInstruction(MI))
1721 return;
1722 emitDebugLineForInstruction(MI);
1723
1724 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1725 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1726 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1727 emitExtInst(Opcode, VoidTypeReg, ExtInstSetReg,
1728 {*VarRegOpt, LocationReg, *ExprRegOpt}, MAI);
1729}
1730
1731// The scalar type and value of the constant \p MI assigns, or nullopt when
1732// this backend cannot name it.
1733static std::optional<std::pair<const DIBasicType *, uint64_t>>
1735 if (!MI.isNonListDebugValue() || MI.isIndirectDebugValue())
1736 return std::nullopt;
1737
1738 const MachineOperand &Value = MI.getDebugOperand(0);
1739 if (!Value.isImm() && !Value.isCImm() && !Value.isFPImm())
1740 return std::nullopt;
1741
1742 const DILocalVariable *LV = MI.getDebugVariable();
1743 const DIBasicType *BT = LV ? stripToScalarType(LV->getType()) : nullptr;
1744 if (!BT)
1745 return std::nullopt;
1746
1747 uint64_t Bits;
1748 if (Value.isImm())
1749 Bits = constantBits(static_cast<uint64_t>(Value.getImm()), BT);
1750 else if (Value.isCImm())
1751 Bits = constantBits(Value.getCImm()->getValue(), BT);
1752 else
1753 Bits = constantBits(Value.getFPImm()->getValueAPF().bitcastToAPInt(), BT);
1754 return std::make_pair(BT, Bits);
1755}
1756
1757std::optional<MCRegister> SPIRVNonSemanticDebugHandler::getConstantValueReg(
1758 const MachineInstr &MI) const {
1759 std::optional<std::pair<const DIBasicType *, uint64_t>> Const =
1761 if (!Const)
1762 return std::nullopt;
1763
1764 auto It = ConstantValueRegs.find(*Const);
1765 if (It == ConstantValueRegs.end() || !It->second.isValid())
1766 return std::nullopt;
1767 return It->second;
1768}
1769
1770static std::optional<Register> getDebugValueReg(const MachineInstr &MI) {
1771 if (!MI.isNonListDebugValue() || MI.isIndirectDebugValue())
1772 return std::nullopt;
1773
1774 const MachineOperand &Value = MI.getDebugOperand(0);
1775 if (!Value.isReg())
1776 return std::nullopt;
1777
1778 Register ValueReg = Value.getReg();
1779 if (!ValueReg.isVirtual())
1780 return std::nullopt;
1781
1782 const MachineInstr *Def = MI.getMF()->getRegInfo().getUniqueVRegDef(ValueReg);
1783 if (!Def || Def->isPseudo() || Def->isMetaInstruction() ||
1784 Def->getNumOperands() == 0 || !Def->getOperand(0).isReg() ||
1785 !Def->getOperand(0).isDef() || Def->getOperand(0).getReg() != ValueReg)
1786 return std::nullopt;
1787
1788 return ValueReg;
1789}
1790
1791static bool isMergeInstruction(unsigned Opcode) {
1792 return Opcode == SPIRV::OpSelectionMerge || Opcode == SPIRV::OpLoopMerge ||
1793 Opcode == SPIRV::OpLoopControlINTEL;
1794}
1795
1796// Whether \p MI becomes a SPIR-V instruction in the output.
1798 return !MI->isMetaInstruction() && !MAI.getSkipEmission(MI);
1799}
1800
1803 if (!isEmitted(MI, MAI))
1804 return false;
1805 switch (MI->getOpcode()) {
1806 case SPIRV::OpFunction:
1807 case SPIRV::OpFunctionParameter:
1808 case SPIRV::OpFunctionEnd:
1809 case SPIRV::OpLabel:
1810 case SPIRV::OpPhi:
1811 return false;
1812 default:
1813 return true;
1814 }
1815}
1816
1817static const MachineInstr *
1819 SPIRV::ModuleAnalysisInfo &MAI, bool Forward) {
1820 for (const MachineInstr *Adj = Forward ? MI->getNextNode()
1821 : MI->getPrevNode();
1822 Adj; Adj = Forward ? Adj->getNextNode() : Adj->getPrevNode()) {
1823 if (!isEmitted(Adj, MAI))
1824 continue;
1825 return Adj;
1826 }
1827 return nullptr;
1828}
1829
1830std::optional<const MachineInstr *>
1831SPIRVNonSemanticDebugHandler::resolveDebugLocTarget(const MachineInstr *MI) {
1832 assert(CurrentMAI && "CurrentMAI must be set");
1833 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1834
1835 // Structural opcodes don't require a DebugLine/DebugScope, other opcodes
1836 // might have already been emitted in the module scope.
1837 if (!isDebugLocTarget(MI, MAI))
1838 return std::nullopt;
1839
1840 // DebugLine/DebugScope can be emitted before a merge instruction, but not
1841 // after it (nothing may sit between the merge and its terminator). We can
1842 // use either the merge's or the terminator's debug info; we emit the
1843 // terminator's one.
1844 const MachineInstr *Prev = findAdjacentEmittedInstruction(MI, MAI, false);
1845 if (Prev && isMergeInstruction(Prev->getOpcode()))
1846 return std::nullopt;
1847
1848 if (isMergeInstruction(MI->getOpcode())) {
1849 // Use the terminator's debug info; when we reach it later, the check
1850 // above skips it.
1851 MI = findAdjacentEmittedInstruction(MI, MAI, true);
1852 assert(MI && "Merge instruction must be followed by a terminator");
1853 // The assert is compiled out in a release build, and returning MI there
1854 // would give an engaged optional holding null.
1855 if (!MI)
1856 return std::nullopt;
1857 }
1858
1859 return MI;
1860}
1861
1862void SPIRVNonSemanticDebugHandler::resolveDebugRecord(
1863 const MachineInstr &MI, const MachineInstr *LastEmitted,
1864 const MachineDominatorTree &DomTree) {
1865 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1866 const MachineFunction &MF = *MI.getMF();
1867
1868 // A record sits at its own position, except in a merge region: nothing may
1869 // be emitted between a merge and its terminator, so it belongs ahead of the
1870 // merge.
1871 const MachineInstr *Anchor =
1872 LastEmitted && isMergeInstruction(LastEmitted->getOpcode()) ? LastEmitted
1873 : &MI;
1874
1875 // A #dbg_declare reaches Machine IR as an indirect DBG_VALUE. Its storage is
1876 // an OpVariable in the entry block, so it is in the output by the time any
1877 // record naming it is reached.
1878 if (std::optional<Register> LocReg = getDebugDeclareStorageReg(MI)) {
1879 MCRegister StorageReg = MAI.getRegisterAlias(&MF, *LocReg);
1880 if (StorageReg.isValid())
1881 placeRecord(SPIRV::NonSemanticExtInst::DebugDeclare, MI, StorageReg,
1882 Anchor);
1883 return;
1884 }
1885
1886 if (std::optional<MCRegister> ConstReg = getConstantValueReg(MI)) {
1887 placeRecord(SPIRV::NonSemanticExtInst::DebugValue, MI, *ConstReg, Anchor);
1888 return;
1889 }
1890
1891 std::optional<Register> ValReg = getDebugValueReg(MI);
1892 if (!ValReg)
1893 return;
1894 MCRegister ValueReg = MAI.getRegisterAlias(&MF, *ValReg);
1895 if (!ValueReg.isValid())
1896 return;
1897
1898 // NonSemantic.Shader.DebugInfo states that "Forward references are not
1899 // allowed, to be compliant with SPV_KHR_non_semantic_info", so the id has to
1900 // be in the output already. A module section precedes every function body.
1901 //
1902 // For anything else, SPIR-V requires a definition in a function block to
1903 // dominate a non-phi use, and requires a block to precede every block it
1904 // dominates, so a dominating definition is also one already printed. A
1905 // record naming a definition that does not dominate it is dropped.
1906 const MachineInstr *Def = MF.getRegInfo().getUniqueVRegDef(*ValReg);
1907 if (ModuleScopeIds.contains(ValueReg) ||
1908 (isEmitted(Def, MAI) && DomTree.dominates(Def, &MI)))
1909 placeRecord(SPIRV::NonSemanticExtInst::DebugValue, MI, ValueReg, Anchor);
1910}
1911
1912void SPIRVNonSemanticDebugHandler::analyzeDebugRecords(
1913 const MachineFunction &MF) {
1914 assert(CurrentMAI && "CurrentMAI must be set");
1915
1916 // Built on the first record rather than required as an analysis pass, which
1917 // would build a tree for every SPIR-V compilation.
1918 std::optional<MachineDominatorTree> DomTree;
1919
1920 for (const MachineBasicBlock &MBB : MF) {
1921 const MachineInstr *LastEmitted = nullptr;
1922 for (const MachineInstr &MI : MBB) {
1923 if (MI.isDebugValueLike()) {
1924 if (!DomTree)
1925 DomTree.emplace(const_cast<MachineFunction &>(MF));
1926 resolveDebugRecord(MI, LastEmitted, *DomTree);
1927 }
1928
1929 if (isEmitted(&MI, *CurrentMAI))
1930 LastEmitted = &MI;
1931 }
1932 }
1933}
1934
1935void SPIRVNonSemanticDebugHandler::placeRecord(
1936 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
1937 const MachineInstr &MI, MCRegister LocationReg,
1938 const MachineInstr *Anchor) {
1939 Records[Anchor].push_back({&MI, Opcode, LocationReg});
1940}
1941
1942void SPIRVNonSemanticDebugHandler::emitAnalyzedRecords(
1943 const MachineInstr *Anchor) {
1944 auto It = Records.find(Anchor);
1945 if (It == Records.end())
1946 return;
1947 for (const DebugRecord &R : It->second)
1948 emitDebugBinding(R.Opcode, R.MI, R.LocationReg);
1949}
1950
1951bool SPIRVNonSemanticDebugHandler::emitDebugScopeForInstruction(
1952 const MachineInstr *MI) {
1953 assert(DebugFunctionDefinitionEmitted &&
1954 "DebugFunctionDefinition must be emitted");
1955 assert(CurrentMAI && "CurrentMAI must be set");
1956
1957 // The region is implicitly closed at each basic block boundary, so a
1958 // LastScopeMI from another block must be dropped before it is read below:
1959 // the new block needs its own DebugScope, and has no region left to close.
1960 if (LastScopeMI && MI->getParent() != LastScopeMI->getParent())
1961 LastScopeMI = nullptr;
1962
1963 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1964 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1965 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1966
1967 const DILocation *CurDL = MI->getDebugLoc().get();
1968 if (!CurDL) {
1969 // No location for the current instruction.
1970 if (LastScopeMI) {
1971 // Close the current DebugScope region.
1972 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoScope, VoidTypeReg,
1973 ExtInstSetReg, {}, MAI);
1974 LastScopeMI = nullptr;
1975 }
1976 return true;
1977 }
1978
1979 const DIScope *CurScope = CurDL->getScope();
1980 const DILocation *CurInlinedAt = CurDL->getInlinedAt();
1981
1982 if (LastScopeMI) {
1983 const DILocation *LastDL = LastScopeMI->getDebugLoc().get();
1984 if (LastDL->getScope() == CurScope &&
1985 LastDL->getInlinedAt() == CurInlinedAt)
1986 return true;
1987 }
1988
1989 auto CurScopeRegOpt = resolveScope(CurScope);
1990 if (!CurScopeRegOpt)
1991 return false;
1992
1993 SmallVector<MCRegister, 2> Ops{*CurScopeRegOpt};
1994 if (CurInlinedAt) {
1995 // If the global emission did not include this inlined-at case, we skip it.
1996 MCRegister InlinedReg = DebugInlinedAtRegs.lookup(CurInlinedAt);
1997 if (!InlinedReg.isValid())
1998 return false;
1999 Ops.push_back(InlinedReg);
2000 }
2001
2002 // A new DebugScope region is needed.
2003 emitExtInst(SPIRV::NonSemanticExtInst::DebugScope, VoidTypeReg, ExtInstSetReg,
2004 Ops, MAI);
2005
2006 LastScopeMI = MI;
2007 return true;
2008}
2009
2010void SPIRVNonSemanticDebugHandler::emitDebugLineForInstruction(
2011 const MachineInstr *MI) {
2012 assert(DebugFunctionDefinitionEmitted &&
2013 "DebugFunctionDefinition must be emitted");
2014 assert(CurrentMAI && "CurrentMAI must be set");
2015
2016 // The region is implicitly closed at each basic block boundary, so a
2017 // LastLineMI from another block must be dropped before it is read below:
2018 // the new block needs its own DebugLine, and has no region left to close.
2019 if (LastLineMI && MI->getParent() != LastLineMI->getParent())
2020 LastLineMI = nullptr;
2021
2022 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2023 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2024 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
2025
2026 const DILocation *DL = MI->getDebugLoc().get();
2027 if (!DL) {
2028 // No location for the current instruction
2029 if (LastLineMI) {
2030 // Close the current DebugLine region.
2031 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoLine, VoidTypeReg,
2032 ExtInstSetReg, {}, MAI);
2033 LastLineMI = nullptr;
2034 }
2035 // No DebugLine region to close.
2036 return;
2037 }
2038
2039 // At this point, there is a location for the current instruction.
2040 // If it matches the last emitted DebugLine, no new DebugLine region is
2041 // needed. Otherwise, emit a new DebugLine region and update LastLineMI.
2042
2043 MCRegister FileStrReg = getCachedScopePathOpStringReg(
2044 DL->getScope(), /*UseEmptyPathIfNullScope=*/true);
2045 unsigned Line = DL->getLine();
2046 unsigned Col = DL->getColumn();
2047
2048 unsigned I32TypeId = CachedOpTypeInt32Reg.id();
2049 MCRegister SrcReg = DebugSourceRegByFileStr.lookup(FileStrReg.id());
2050 MCRegister LineReg = ScalarConstantCache.lookup({I32TypeId, Line});
2051 MCRegister ColStartReg = ScalarConstantCache.lookup({I32TypeId, Col});
2052 MCRegister ColEndReg = ScalarConstantCache.lookup({I32TypeId, Col + 1});
2053
2054 // The elements of each collected DILocation (DebugSource, line/column
2055 // constants) are pre-emitted from LLVM-IR instruction !dbg attachments and
2056 // debug-program records; MIR is expected to reuse those same locations (or
2057 // carry none). A lookup miss means codegen attached a source position whose
2058 // elements were never pre-emitted, and debug-line emission is skipped.
2059 if (!SrcReg.isValid() || !LineReg.isValid() || !ColStartReg.isValid() ||
2060 !ColEndReg.isValid())
2061 return;
2062
2063 // Current location matches the last emitted DebugLine region.
2064 if (LastLineMI && MI->getDebugLoc() == LastLineMI->getDebugLoc())
2065 return;
2066
2067 // A new DebugLine region is needed.
2068 emitExtInst(SPIRV::NonSemanticExtInst::DebugLine, VoidTypeReg, ExtInstSetReg,
2069 {SrcReg, LineReg, LineReg, ColStartReg, ColEndReg}, MAI);
2070
2071 LastLineMI = MI;
2072}
2073
2075 const MachineInstr *MI = CurMI;
2076 CurMI = nullptr;
2077
2078 if (!MI || !GlobalNSDIEnabled || !CurrentMF)
2079 return;
2080
2081 if (DebugFunctionDefinitionEmitted || MI != LastFunctionOpVariable)
2082 return;
2083
2084 // If this is the last function-level OpVariable, emit the
2085 // DebugFunctionDefinition. Otherwise, we had already done it before right
2086 // after the OpLabel (see notifyEntryLabelEmitted).
2087 assert(CurrentMAI && "CurrentMAI must be set");
2088 tryEmitDebugFunctionDefinition(*CurrentMAI);
2089}
2090
2092 const MachineFunction &MF) {
2093 if (!GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
2094 return;
2095
2096 assert(CurrentMF == &MF &&
2097 "notification does not match the current MachineFunction");
2098
2099 if (LastFunctionOpVariable)
2100 return;
2101
2102 // If there are no function-level OpVariables, emit the
2103 // DebugFunctionDefinition. Otherwise, DebugFunctionDefinition is emitted
2104 // after the last OpVariable (see endInstruction).
2105 tryEmitDebugFunctionDefinition(*CurrentMAI);
2106}
2107
2108static void forEachDebugValueLike(const MachineModuleInfo &ModuleInfo,
2109 function_ref<void(const MachineInstr &)> Fn) {
2110 for (const Function &F : *ModuleInfo.getModule()) {
2111 const MachineFunction *MF = ModuleInfo.getMachineFunction(F);
2112 if (!MF)
2113 continue;
2114 for (const MachineBasicBlock &MBB : *MF)
2115 for (const MachineInstr &MI : MBB)
2116 if (MI.isDebugValueLike())
2117 Fn(MI);
2118 }
2119}
2120
2121void SPIRVNonSemanticDebugHandler::collectDebugExpressions(
2123 MachineModuleInfo *ModuleInfo = Asm->MMI;
2124 assert(ModuleInfo && "MachineModuleInfo must be set during module output");
2125
2126 forEachDebugValueLike(*ModuleInfo, [&](const MachineInstr &MI) {
2127 Out.insert(MI.getDebugExpression());
2128 });
2129}
2130
2133 if (GlobalDIEmitted)
2134 return;
2135
2136 GlobalDIEmitted = true;
2137
2138 if (CompileUnits.empty()) {
2139 GlobalNSDIEnabled = false;
2140 return;
2141 }
2142
2143 // Retrieve the ext inst set register allocated by prepareModuleOutput().
2144 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
2145 if (!ExtInstSetReg.isValid()) {
2146 GlobalNSDIEnabled = false;
2147 return;
2148 }
2149
2150#ifndef NDEBUG
2151 assert(NonSemanticOpStringsSectionEmitted &&
2152 "emitNonSemanticDebugStrings() must run before "
2153 "emitNonSemanticGlobalDebugInfo()");
2154#endif
2155
2156 CurrentMAI = &MAI;
2157
2158 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2159 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
2160
2161 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
2162 VoidTypeReg, ExtInstSetReg, {}, MAI);
2163
2164 // Emit integer constants shared across all NSDI instructions. The constant
2165 // cache ensures each value is emitted at most once even when referenced from
2166 // multiple instructions. All constants are pre-emitted before any DebugSource
2167 // so that the output order is: constants, then
2168 // DebugSource+DebugCompilationUnit pairs. This keeps OpConstant instructions
2169 // grouped before the OpExtInst instructions.
2170
2171 // The Version operand of DebugCompilationUnit is the version of the
2172 // NonSemantic.Shader.DebugInfo instruction set, which is 100 for
2173 // "NonSemantic.Shader.DebugInfo.100" (NonSemanticShaderDebugInfo100Version).
2174 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
2175 MCRegister DwarfVersionReg =
2176 emitOpConstantI32(static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
2177
2178 // Pre-emit source language constants for all compile units before entering
2179 // the DebugSource loop.
2180 SmallVector<MCRegister> SrcLangRegs =
2181 map_to_vector(CompileUnits, [&](const CompileUnitInfo &Info) {
2182 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
2183 });
2184
2185 // Emit DebugSource and DebugCompilationUnit for each compile unit.
2186 for (auto [Info, SrcLangReg] : llvm::zip(CompileUnits, SrcLangRegs)) {
2187 MCRegister FileStrReg = ScopeToPathOpStringReg.lookup(Info.TheCU);
2188 assert(FileStrReg.isValid() &&
2189 "CU path OpString must be emitted in emitNonSemanticDebugStrings");
2190 MCRegister DebugSourceReg = getOrEmitDebugSourceForFileStrReg(
2191 FileStrReg, VoidTypeReg, ExtInstSetReg, MAI);
2192 MCRegister CUDbgReg = emitExtInst(
2193 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
2194 ExtInstSetReg,
2195 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
2196 MAI);
2197 if (Info.TheCU)
2198 DebugScopeRegs[Info.TheCU] = CUDbgReg;
2199 }
2200
2201 // Zero constant used as the Flags operand in DebugTypeBasic and
2202 // DebugTypePointer. Cached with other i32 constants.
2203 MCRegister I32ZeroReg = emitOpConstantI32(0, I32TypeReg, MAI);
2204
2205 for (const DIBasicType *BT : BasicTypes) {
2206 if (!isUInt<32>(BT->getSizeInBits()))
2207 continue;
2208
2209 MCRegister NameReg = getCachedOpStringReg(BT->getName());
2210 MCRegister SizeReg = emitOpConstantI32(
2211 static_cast<uint32_t>(BT->getSizeInBits()), I32TypeReg, MAI);
2212
2213 // Map DWARF base type encodings to NSDI encoding codes per
2214 // NonSemantic.Shader.DebugInfo.100 specification, section 4.5.
2215 unsigned Encoding = 0; // Unspecified
2216 switch (BT->getEncoding()) {
2217 case dwarf::DW_ATE_address:
2218 Encoding = 1;
2219 break;
2220 case dwarf::DW_ATE_boolean:
2221 Encoding = 2;
2222 break;
2223 case dwarf::DW_ATE_float:
2224 Encoding = 3;
2225 break;
2226 case dwarf::DW_ATE_signed:
2227 Encoding = 4;
2228 break;
2229 case dwarf::DW_ATE_signed_char:
2230 Encoding = 5;
2231 break;
2232 case dwarf::DW_ATE_unsigned:
2233 Encoding = 6;
2234 break;
2235 case dwarf::DW_ATE_unsigned_char:
2236 Encoding = 7;
2237 break;
2238 }
2239 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
2240
2241 MCRegister BTReg = emitExtInst(
2242 SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
2243 {NameReg, SizeReg, EncodingReg, I32ZeroReg}, MAI);
2244 DebugScopeRegs[BT] = BTReg;
2245 }
2246
2247 // Emit DebugTypeVector for each collected vector type.
2248 for (const DICompositeType *VT : VectorTypes) {
2249 if (auto VecReg = emitDebugTypeVector(VT, ExtInstSetReg, MAI))
2250 DebugScopeRegs[VT] = *VecReg;
2251 }
2252
2253 // Emit DebugTypePointer for each referenced pointer type.
2254 for (const DIDerivedType *PT : PointerTypes) {
2255 if (auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
2256 DebugScopeRegs[PT] = *PtrReg;
2257 }
2258
2259 // Emit DebugTypeArray for each collected array type. Placed after the basic,
2260 // vector, and pointer types so an array over any of them can resolve its
2261 // element id. An array whose element type was not emitted is skipped.
2262 for (const DICompositeType *AT : ArrayTypes) {
2263 if (auto ArrReg = emitDebugTypeArray(AT, ExtInstSetReg, MAI))
2264 DebugScopeRegs[AT] = *ArrReg;
2265 }
2266
2267 // Emit DebugTypeFunction for each distinct DISubroutineType.
2268 for (const DISubroutineType *ST : SubroutineTypes) {
2269 if (auto FnTyReg =
2270 emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI))
2271 DebugScopeRegs[ST] = *FnTyReg;
2272 }
2273
2274 // Emit DebugLexicalBlock for each collected DINamespace, in parent-before-
2275 // child order. Placed before any DINamespace-scoped entity (typedefs,
2276 // function declarations, composite types, functions, global variables) so
2277 // their Parent operand can reference an already-emitted DebugLexicalBlock.
2278 // DINamespace never chains through a DISubprogram (DINamespace::getScope()
2279 // returns DIScope, not DILocalScope), so this never depends on
2280 // DebugScopeRegs.
2281 for (const DIScope *S :
2282 make_filter_range(LexicalBlocks, IsaPred<DINamespace>)) {
2283 if (auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
2284 ExtInstSetReg, MAI))
2285 DebugScopeRegs[S] = *LBReg;
2286 }
2287
2288 // Emit DebugTypedef for each typedef. Placed after the other type loops so a
2289 // typedef can resolve its underlying type. A typedef whose base type is not
2290 // emitted is skipped. A typedef whose base is another typedef emitted later
2291 // in this same pass is also skipped, the emission-order gap tracked in
2292 // https://github.com/llvm/llvm-project/issues/211850.
2293 for (const DIDerivedType *TD : TypedefTypes) {
2294 if (auto TDReg =
2295 emitDebugTypedef(TD, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
2296 DebugScopeRegs[TD] = *TDReg;
2297 }
2298
2299 // Emit DebugFunctionDeclaration for DISubprogram declarations.
2300 for (const DISubprogram *SP : SubprogramDeclarations) {
2301 if (auto DeclReg = emitDebugFunctionDeclaration(SP, VoidTypeReg, I32TypeReg,
2302 ExtInstSetReg, MAI))
2303 DebugScopeRegs[SP] = *DeclReg;
2304 }
2305
2306 // Emit DebugTypeMember and DebugTypeComposite for each struct, class, or
2307 // union. Each member is emitted before the composite that lists it, so the
2308 // Members operand references already-defined ids. A member whose type is not
2309 // in DebugScopeRegs is skipped.
2310 for (const DICompositeType *CT : CompositeTypes) {
2311 SmallVector<MCRegister> MemberRegs;
2312 for (const DINode *Element : CT->getElements()) {
2313 const auto *M = dyn_cast<DIDerivedType>(Element);
2314 if (!M || M->getTag() != dwarf::DW_TAG_member)
2315 continue;
2316 if (auto MemberReg = emitDebugTypeMember(M, VoidTypeReg, I32TypeReg,
2317 ExtInstSetReg, MAI))
2318 MemberRegs.push_back(*MemberReg);
2319 }
2320 if (auto CompReg = emitDebugTypeComposite(CT, MemberRegs, VoidTypeReg,
2321 I32TypeReg, ExtInstSetReg, MAI))
2322 DebugScopeRegs[CT] = *CompReg;
2323 }
2324
2325 // Emit DebugFunction for DISubprogram definitions.
2326 for (const DISubprogram *SP : SubprogramDefinitions) {
2327 if (auto FnReg =
2328 emitDebugFunction(SP, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
2329 DebugScopeRegs[SP] = *FnReg;
2330 }
2331
2332 // Emit DebugLexicalBlock for each collected DILexicalBlock, in parent-
2333 // before-child order. Placed after DebugFunction so a block directly
2334 // enclosed by a function (the common case) can resolve its Parent operand;
2335 // DINamespace entries were already emitted above.
2336 for (const DIScope *S :
2338 if (auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
2339 ExtInstSetReg, MAI))
2340 DebugScopeRegs[S] = *LBReg;
2341 }
2342
2343 // Emit DebugLocalVariable after DebugFunction and their lexical blocks so the
2344 // Parent operand can resolve. Record the ids for DebugDeclare.
2345 for (const DILocalVariable *LV : LocalVariables)
2346 if (auto LVReg = emitDebugLocalVariable(LV, VoidTypeReg, I32TypeReg,
2347 ExtInstSetReg, MAI))
2348 DebugLocalVariableRegs[LV] = *LVReg;
2349
2350 // Opcodes like DebugDeclare are part of the function body, but
2351 // DebugExpression is not. For such opcodes, we collect the expressions
2352 // directly from the MIR to avoid inconsistencies with those in the LLVM IR
2353 // module.
2355 collectDebugExpressions(Expressions);
2356 for (const DIExpression *Expr : Expressions)
2357 if (auto ExprReg = emitDebugExpression(Expr, VoidTypeReg, I32TypeReg,
2358 ExtInstSetReg, MAI))
2359 DebugExpressionRegs[Expr] = *ExprReg;
2360
2361 // Emit DebugGlobalVariable for each collected DIGlobalVariable.
2362 for (const auto &[GV, Info] : GlobalVariableDebugInfoMap)
2363 emitDebugGlobalVariable(GV, Info, VoidTypeReg, I32TypeReg, ExtInstSetReg,
2364 MAI);
2365
2366 // Emit DebugInlinedAt allowing recursive inlining.
2367 for (const DILocation *DL : UniqueDebugLocations)
2368 if (const DILocation *IA = DL->getInlinedAt())
2369 getOrEmitDebugInlinedAt(IA, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
2370
2371 // Repeating the lookups emitDebugBinding() performs emits a type and a
2372 // constant only for an assignment that will reach a DebugValue.
2373 MachineModuleInfo *ModuleInfo = Asm->MMI;
2374 assert(ModuleInfo && "MachineModuleInfo must be set during module output");
2375 forEachDebugValueLike(*ModuleInfo, [&](const MachineInstr &MI) {
2376 std::optional<std::pair<const DIBasicType *, uint64_t>> Const =
2378 if (!Const)
2379 return;
2380 if (!DebugLocalVariableRegs.contains(MI.getDebugVariable()) ||
2381 !DebugExpressionRegs.contains(MI.getDebugExpression()))
2382 return;
2383 auto [It, Inserted] = ConstantValueRegs.try_emplace(*Const, MCRegister());
2384 if (Inserted)
2385 It->second = findOrEmitScalarConstant(Const->first, Const->second, MAI);
2386 if (!It->second.isValid())
2387 ConstantValueRegs.erase(It);
2388 });
2389
2390 for (const DILocation *DL : UniqueDebugLocations) {
2391 emitOpConstantI32(DL->getLine(), I32TypeReg, MAI);
2392 emitOpConstantI32(DL->getColumn(), I32TypeReg, MAI);
2393 emitOpConstantI32(DL->getColumn() + 1, I32TypeReg, MAI);
2394 MCRegister FileStrReg =
2395 getCachedScopePathOpStringReg(DL->getScope(),
2396 /*UseEmptyPathIfNullScope=*/true);
2397 getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg, ExtInstSetReg,
2398 MAI);
2399 }
2400
2401 GlobalNSDIEnabled = true;
2402}
2403
2405SPIRVNonSemanticDebugHandler::getDebugFullPath(const DIScope *Scope) const {
2406 SmallString<128> Out;
2407 if (!Scope)
2408 return Out;
2409 StringRef Filename = Scope->getFilename();
2410 const auto Style = sys::path::Style::native;
2411 if (sys::path::is_absolute(Filename, Style))
2412 Out.assign(Filename.begin(), Filename.end());
2413 else {
2414 StringRef Dir = Scope->getDirectory();
2415 Out.assign(Dir.begin(), Dir.end());
2416 sys::path::append(Out, Style, Filename);
2417 }
2418 return Out;
2419}
2420
2421MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugSourceForFileStrReg(
2422 MCRegister FileStrReg, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
2424 const unsigned Key = FileStrReg.id();
2425 auto It = DebugSourceRegByFileStr.find(Key);
2426 if (It != DebugSourceRegByFileStr.end())
2427 return It->second;
2428
2429 MCRegister DS = emitExtInst(SPIRV::NonSemanticExtInst::DebugSource,
2430 VoidTypeReg, ExtInstSetReg, {FileStrReg}, MAI);
2431 DebugSourceRegByFileStr[Key] = DS;
2432 return DS;
2433}
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 std::optional< SmallVector< uint32_t, 3 > > mapExprOperand(const DIExpression::ExprOperand &Op)
static bool scalarTypeNeedsCapability(const DIBasicType *BT)
static bool isBooleanType(const DIBasicType *BT)
static bool constantHasValue(const MachineInstr &MI, uint64_t Value, bool IsWide)
static void collectLexicalBlockChain(const DIScope *S, SetVector< const DIScope * > &Out)
static bool isMergeInstruction(unsigned Opcode)
static std::optional< std::pair< const DIBasicType *, uint64_t > > getConstantDbgValueBits(const MachineInstr &MI)
static void forEachDebugValueLike(const MachineModuleInfo &ModuleInfo, function_ref< void(const MachineInstr &)> Fn)
static MCRegister getResultId(const MachineInstr &MI, SPIRV::ModuleAnalysisInfo &MAI)
static bool isEmitted(const MachineInstr *MI, SPIRV::ModuleAnalysisInfo &MAI)
static std::optional< Register > getDebugValueReg(const MachineInstr &MI)
static bool isDebugLocTarget(const MachineInstr *MI, SPIRV::ModuleAnalysisInfo &MAI)
static uint64_t constantBits(uint64_t Value, const DIBasicType *BT)
static std::optional< Register > getDebugDeclareStorageReg(const MachineInstr &MI)
static std::optional< NonSemanticDebugOp > mapDwarfOpToNonSemanticOp(uint64_t DwarfOp)
static const DIBasicType * stripToScalarType(const DIType *Ty)
static void collectDebugLocationsAndLocalVariables(const Module &M, SetVector< const DILocation * > &Locations, SetVector< const DILocalVariable * > &LVs)
spirv structurize SPIRV
#define SPIRV_BACKEND_SERVICE_FUN_NAME
Definition SPIRVUtils.h:567
This file contains some templates that are useful if you are working with the STL at all.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines less commonly used SmallVector utilities.
Class for arbitrary precision integers.
Definition APInt.h:78
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: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:794
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:857
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:769
DISubprogram * getSubprogram() const
Get the attached subprogram.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void setFlags(unsigned F)
Definition MCInst.h:204
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:1081
Tracking metadata reference owned by Metadata.
Definition Metadata.h:902
bool equalsStr(StringRef Str) const
Definition Metadata.h:924
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool dominates(const MachineInstr *A, const MachineInstr *B) const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
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.
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
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:1797
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
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
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
An efficient, type-erasing, non-owning reference to a callable.
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
Definition Dwarf.h:144
NodeAddr< DefNode * > Def
Definition RDFGraph.h:384
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:846
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:1748
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:1167
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
Definition MathExtras.h:151
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:552
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
Definition MathExtras.h:156
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)