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
910 return lookupOptReg(DebugScopeRegs, Scope);
911
912 // For a file, compile-unit, or absent scope, fall back to a compile unit.
913 if (FallbackCU)
914 return lookupOptReg(DebugScopeRegs, FallbackCU);
915
916 if (CompileUnits.empty())
917 return std::nullopt;
918
919 return lookupOptReg(DebugScopeRegs, CompileUnits[0].TheCU);
920}
921
922std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLexicalBlock(
923 const DIScope *S, MCRegister VoidTypeReg, MCRegister I32TypeReg,
924 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
926 "S must be a DILexicalBlock or DINamespace in emitDebugLexicalBlock");
927 auto ParentRegOpt = resolveScope(S->getScope());
928 if (!ParentRegOpt)
929 return std::nullopt;
930
931 MCRegister FileStrReg = getCachedScopePathOpStringReg(
932 S->getFile(), /*UseEmptyPathIfNullScope=*/true);
933 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
934 ExtInstSetReg, MAI);
935
937 if (const auto *LB = dyn_cast<DILexicalBlock>(S)) {
938 MCRegister LineReg = emitOpConstantI32(static_cast<uint32_t>(LB->getLine()),
939 I32TypeReg, MAI);
940 MCRegister ColReg = emitOpConstantI32(
941 static_cast<uint32_t>(LB->getColumn()), I32TypeReg, MAI);
942 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt};
943 } else {
944 const auto *NS = cast<DINamespace>(S);
945 // DINamespace carries no line/column info.
946 MCRegister LineReg = emitOpConstantI32(0, I32TypeReg, MAI);
947 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
948 MCRegister NameReg = getCachedOpStringReg(NS->getName());
949 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt, NameReg};
950 }
951
952 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLexicalBlock, VoidTypeReg,
953 ExtInstSetReg, Ops, MAI);
954}
955
956MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugInlinedAt(
957 const DILocation *IA, MCRegister VoidTypeReg, MCRegister I32TypeReg,
958 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
959 assert(IA && "IA must not be null in getOrEmitDebugInlinedAt");
960
961 if (MCRegister Cached = DebugInlinedAtRegs.lookup(IA))
962 return Cached;
963
964 auto ScopeRegOpt = resolveScope(IA->getScope());
965 if (!ScopeRegOpt)
966 return MCRegister();
967
968 MCRegister LineReg =
969 emitOpConstantI32(static_cast<uint32_t>(IA->getLine()), I32TypeReg, MAI);
970
971 SmallVector<MCRegister, 3> Ops{LineReg, *ScopeRegOpt};
972 // Recurse before building this instruction's operands so an outer
973 // inlined-at link is always available.
974 if (const DILocation *Outer = IA->getInlinedAt()) {
975 MCRegister OuterReg = getOrEmitDebugInlinedAt(
976 Outer, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
977 if (!OuterReg.isValid())
978 return MCRegister();
979 Ops.push_back(OuterReg);
980 }
981
982 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInlinedAt,
983 VoidTypeReg, ExtInstSetReg, Ops, MAI);
984 DebugInlinedAtRegs[IA] = Reg;
985 return Reg;
986}
987
988std::optional<MCRegister>
989SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
990 const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
991 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
992 assert(SP && "SP must not be null in emitDebugFunctionDeclaration");
993 assert(!SP->isDefinition() &&
994 "SP must not be a definition in emitDebugFunctionDeclaration");
995
996 // The IR verifier already enforces that this cannot be null.
997 const DISubroutineType *ST = SP->getType();
998
999 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
1000 if (!FnTyRegOpt)
1001 return std::nullopt;
1002 MCRegister FnTyReg = *FnTyRegOpt;
1003
1004 auto ParentRegOpt = resolveScope(SP->getScope(), SP->getUnit());
1005 if (!ParentRegOpt)
1006 return std::nullopt;
1007
1008 MCRegister ParentReg = *ParentRegOpt;
1009
1010 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
1011
1012 MCRegister NameReg = getCachedOpStringReg(SP->getName());
1013 MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
1014 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1015 ExtInstSetReg, MAI);
1016
1017 MCRegister LineReg =
1018 emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
1019 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1020
1021 uint32_t FlagsVal = transDebugFlags(SP);
1022 // TODO: When composite scopes are DebugFunctionDeclaration parents (available
1023 // in DebugScopeRegs), sync declaration Flags with SPIRV-LLVM-Translator.
1024 FlagsVal &= ~NSDIFlagIsDefinition;
1025 MCRegister FlagsReg = emitOpConstantI32(FlagsVal, I32TypeReg, MAI);
1026
1027 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
1028 VoidTypeReg, ExtInstSetReg,
1029 {NameReg, FnTyReg, SrcReg, LineReg, ColReg, ParentReg,
1030 LinkageReg, FlagsReg},
1031 MAI);
1032}
1033
1034std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugFunction(
1035 const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1036 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1037 assert(SP && "SP must not be null in emitDebugFunction");
1038 assert(SP->isDefinition() && "SP must be a definition in emitDebugFunction");
1039
1040 const DISubroutineType *ST = SP->getType();
1041 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
1042 if (!FnTyRegOpt)
1043 return std::nullopt;
1044
1045 auto ParentRegOpt = resolveScope(SP->getScope(), SP->getUnit());
1046 if (!ParentRegOpt)
1047 return std::nullopt;
1048
1049 MCRegister NameReg = getCachedOpStringReg(SP->getName());
1050 MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
1051 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
1052 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1053 ExtInstSetReg, MAI);
1054
1055 MCRegister LineReg =
1056 emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
1057 // LLVM's DISubprogram has no column field but SPIR-V expects one in
1058 // DebugFunction.
1059 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1060 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(SP), I32TypeReg, MAI);
1061 MCRegister ScopeLineReg = emitOpConstantI32(
1062 static_cast<uint32_t>(SP->getScopeLine()), I32TypeReg, MAI);
1063
1064 SmallVector<MCRegister, 10> Ops = {NameReg, *FnTyRegOpt, SrcReg,
1065 LineReg, ColReg, *ParentRegOpt,
1066 LinkageReg, FlagsReg, ScopeLineReg};
1067
1068 if (const DISubprogram *Decl = SP->getDeclaration()) {
1069 if (auto DeclRegOpt = lookupOptReg(DebugScopeRegs, Decl))
1070 Ops.push_back(*DeclRegOpt);
1071 }
1072
1073 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunction, VoidTypeReg,
1074 ExtInstSetReg, Ops, MAI);
1075}
1076
1077std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
1078 const DIType *Ty, MCRegister VoidTypeReg, bool ReturnType) {
1079 if (!Ty) {
1080 if (ReturnType)
1081 return VoidTypeReg;
1082 assert(CachedDebugInfoNoneReg.isValid() &&
1083 "DebugInfoNone must be emitted before DISubroutineType operands");
1084 return CachedDebugInfoNoneReg;
1085 }
1086 return lookupOptReg(DebugScopeRegs, Ty);
1087}
1088
1089// NonSemantic.Shader.DebugInfo.100 debug operation encodings
1090// (section 4.5, "Debug Operations").
1103
1104static std::optional<NonSemanticDebugOp>
1106 switch (DwarfOp) {
1107 case dwarf::DW_OP_deref:
1109 case dwarf::DW_OP_plus:
1111 case dwarf::DW_OP_minus:
1113 case dwarf::DW_OP_plus_uconst:
1115 case dwarf::DW_OP_bit_piece:
1117 case dwarf::DW_OP_swap:
1119 case dwarf::DW_OP_xderef:
1121 case dwarf::DW_OP_stack_value:
1123 case dwarf::DW_OP_constu:
1127 default:
1128 return std::nullopt;
1129 }
1130}
1131
1132// The DebugOperation operand values for \p Op. Each becomes an OpConstant of
1133// OpTypeInt 32 0, so every argument must fit in 32 bits.
1134static std::optional<SmallVector<uint32_t, 3>>
1136 std::optional<NonSemanticDebugOp> NSOp =
1138 if (!NSOp)
1139 return std::nullopt;
1140
1141 SmallVector<uint32_t, 3> Operands{static_cast<uint32_t>(*NSOp)};
1142 for (unsigned I = 0, E = Op.getNumArgs(); I != E; ++I) {
1143 uint64_t Arg = Op.getArg(I);
1144 if (!isUInt<32>(Arg))
1145 return std::nullopt;
1146 Operands.push_back(static_cast<uint32_t>(Arg));
1147 }
1148 return Operands;
1149}
1150
1151std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugOperation(
1152 const DIExpression::ExprOperand &Op, MCRegister VoidTypeReg,
1153 MCRegister I32TypeReg, MCRegister ExtInstSetReg,
1155 std::optional<SmallVector<uint32_t, 3>> Key = mapExprOperand(Op);
1156 if (!Key)
1157 return std::nullopt;
1158
1159 auto [It, Inserted] = DebugOperationCache.try_emplace(std::move(*Key));
1160 if (!Inserted)
1161 return It->second;
1162
1164 for (uint32_t V : It->first)
1165 Operands.push_back(emitOpConstantI32(V, I32TypeReg, MAI));
1166 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugOperation,
1167 VoidTypeReg, ExtInstSetReg, Operands, MAI);
1168 It->second = Reg;
1169 return Reg;
1170}
1171
1172std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugExpression(
1173 const DIExpression *Expr, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1174 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1175 assert(Expr && "Expr must not be null in emitDebugExpression");
1176
1177 SmallVector<MCRegister> OperationRegs;
1178 for (const DIExpression::ExprOperand &Op : Expr->expr_ops()) {
1179 std::optional<MCRegister> OpReg =
1180 emitDebugOperation(Op, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
1181 if (!OpReg)
1182 return std::nullopt;
1183 OperationRegs.push_back(*OpReg);
1184 }
1185
1186 auto [It, Inserted] =
1187 DebugExpressionCache.try_emplace(std::move(OperationRegs));
1188 if (!Inserted)
1189 return It->second;
1190
1191 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugExpression,
1192 VoidTypeReg, ExtInstSetReg, It->first, MAI);
1193 It->second = Reg;
1194 return Reg;
1195}
1196
1197std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugGlobalVariable(
1198 const DIGlobalVariable *GV, const GlobalVariableDebugInfo &Info,
1199 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
1201 assert(GV && "GV must not be null in emitDebugGlobalVariable");
1202
1203 auto ParentRegOpt = resolveScope(GV->getScope());
1204 if (!ParentRegOpt)
1205 return std::nullopt;
1206
1207 MCRegister ParentReg = *ParentRegOpt;
1208
1209 // TyReg: DebugInfoNone when GV has no DI type (as done in
1210 // SPIRV-LLVM-Translator). Declarations (isDefinition: false) can have null
1211 // getType() while definitions must have a non-null one (enforced by the IR
1212 // verifier).
1213 MCRegister TyReg = CachedDebugInfoNoneReg;
1214 if (const DIType *Ty = GV->getType()) {
1215 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1216 if (!TyRegOpt)
1217 return std::nullopt;
1218 TyReg = *TyRegOpt;
1219 }
1220
1221 std::optional<MCRegister> StaticMemberRegOpt;
1222 if (const DIDerivedType *SM = GV->getStaticDataMemberDeclaration()) {
1223 StaticMemberRegOpt = lookupOptReg(DebugScopeRegs, SM);
1224 if (!StaticMemberRegOpt)
1225 return std::nullopt;
1226 }
1227
1228 MCRegister NameReg = getCachedOpStringReg(GV->getName());
1229 MCRegister LinkageReg = getCachedOpStringReg(GV->getLinkageName());
1230 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1231 GV->getFile(), /*UseEmptyPathIfNullScope=*/true);
1232 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1233 ExtInstSetReg, MAI);
1234
1235 MCRegister LineReg =
1236 emitOpConstantI32(static_cast<uint32_t>(GV->getLine()), I32TypeReg, MAI);
1237 // DIGlobalVariable or DIGlobalVariableExpression metadata carry no column
1238 // field. Column is hardcoded to 0 (because it can't be determined), matching
1239 // SPIRV-LLVM-Translator.
1240 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1241
1242 // Variable: @g OpVariable id when !dbg matches; else a DebugExpression for
1243 // the GVE init value when no @g exists and the expression is non-empty; else
1244 // DebugInfoNone. As per spec, the DebugExpression must contain the constant
1245 // value of the variable that was optimized out. An empty expression contains
1246 // no value, so we emit DebugInfoNone instead.
1247 MCRegister VariableReg = CachedDebugInfoNoneReg;
1248 if (const GlobalVariable *LLVMGV = Info.LLVMGV) {
1249 MCRegister GVReg = MAI.getGlobalObjReg(LLVMGV);
1250 if (GVReg.isValid())
1251 VariableReg = GVReg;
1252 } else if (Info.Expr && Info.Expr->getNumElements() != 0) {
1253 if (auto ExprReg = emitDebugExpression(Info.Expr, VoidTypeReg, I32TypeReg,
1254 ExtInstSetReg, MAI))
1255 VariableReg = *ExprReg;
1256 }
1257
1258 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(GV), I32TypeReg, MAI);
1259
1260 SmallVector<MCRegister, 10> Ops = {NameReg, TyReg, SrcReg,
1261 LineReg, ColReg, ParentReg,
1262 LinkageReg, VariableReg, FlagsReg};
1263
1264 if (StaticMemberRegOpt)
1265 Ops.push_back(*StaticMemberRegOpt);
1266
1267 return emitExtInst(SPIRV::NonSemanticExtInst::DebugGlobalVariable,
1268 VoidTypeReg, ExtInstSetReg, Ops, MAI);
1269}
1270
1271std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLocalVariable(
1272 const DILocalVariable *LV, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1273 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1274 assert(LV && "LV must not be null in emitDebugLocalVariable");
1275
1276 auto ParentRegOpt = resolveScope(LV->getScope());
1277 if (!ParentRegOpt)
1278 return std::nullopt;
1279
1280 MCRegister TyReg = CachedDebugInfoNoneReg;
1281 if (const DIType *Ty = LV->getType()) {
1282 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1283 if (!TyRegOpt)
1284 return std::nullopt;
1285 TyReg = *TyRegOpt;
1286 }
1287
1288 MCRegister NameReg = getCachedOpStringReg(LV->getName());
1289 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1290 LV->getFile(), /*UseEmptyPathIfNullScope=*/true);
1291 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1292 ExtInstSetReg, MAI);
1293 MCRegister LineReg =
1294 emitOpConstantI32(static_cast<uint32_t>(LV->getLine()), I32TypeReg, MAI);
1295 // DILocalVariable has no column field. Column is hardcoded to 0.
1296 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1297 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(LV), I32TypeReg, MAI);
1298
1299 SmallVector<MCRegister, 8> Ops = {NameReg, TyReg, SrcReg, LineReg,
1300 ColReg, *ParentRegOpt, FlagsReg};
1301 if (unsigned Arg = LV->getArg())
1302 Ops.push_back(emitOpConstantI32(Arg, I32TypeReg, MAI));
1303
1304 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLocalVariable, VoidTypeReg,
1305 ExtInstSetReg, Ops, MAI);
1306}
1307
1308std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
1309 const DICompositeType *VT, MCRegister ExtInstSetReg,
1311 const auto *BaseTy = dyn_cast_or_null<DIBasicType>(VT->getBaseType());
1312 if (!BaseTy)
1313 return std::nullopt;
1314 auto BTIt = DebugScopeRegs.find(BaseTy);
1315 if (BTIt == DebugScopeRegs.end())
1316 return std::nullopt;
1317
1318 // DebugTypeVector models only 1D vectors (multi-subrange types cannot be
1319 // encoded).
1320 DINodeArray Elements = VT->getElements();
1321 if (Elements.size() != 1)
1322 return std::nullopt;
1323 const auto *SR = cast<DISubrange>(Elements[0]);
1324 const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount());
1325 if (!CI)
1326 return std::nullopt;
1327
1328 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1329 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1330 MCRegister CountReg = emitOpConstantI32(
1331 static_cast<uint32_t>(CI->getZExtValue()), I32TypeReg, MAI);
1332 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeVector, VoidTypeReg,
1333 ExtInstSetReg, {BTIt->second, CountReg}, MAI);
1334}
1335
1336std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeArray(
1337 const DICompositeType *AT, MCRegister ExtInstSetReg,
1339 // The element (base) type must already be in DebugScopeRegs. Unlike
1340 // DebugTypeVector, the element may be any debug type, not only a basic type.
1341 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, AT->getBaseType());
1342 if (!BaseRegOpt)
1343 return std::nullopt;
1344
1345 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1346 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1347
1349 Ops.push_back(*BaseRegOpt);
1350
1351 // One component count per DISubrange, in DWARF subrange order. Emit 0 for
1352 // counts that are not a compile-time constant (dynamic arrays). This matches
1353 // OpTypeRuntimeArray.
1354 for (const DINode *Element : AT->getElements()) {
1355 const auto *SR = dyn_cast<DISubrange>(Element);
1356 if (!SR)
1357 continue;
1358 // A DIVariable count (a variable-length array) is not a ConstantInt, so it
1359 // maps to 0 here. DebugTypeArray also allows a DebugLocalVariable or
1360 // DebugGlobalVariable id for it, but no frontend we target emits one. A
1361 // constant wider than 32 bits maps to 0 too, since the count operand is a
1362 // 32-bit OpConstant and such an array cannot occur in a shader.
1363 uint32_t Count = 0;
1364 if (const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount())) {
1365 const APInt &Value = CI->getValue();
1366 if (Value.getActiveBits() <= 32)
1367 Count = static_cast<uint32_t>(Value.getZExtValue());
1368 }
1369 Ops.push_back(emitOpConstantI32(Count, I32TypeReg, MAI));
1370 }
1371
1372 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeArray, VoidTypeReg,
1373 ExtInstSetReg, Ops, MAI);
1374}
1375
1376std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeMember(
1377 const DIDerivedType *M, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1378 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1379 // The member type must already be in DebugScopeRegs.
1380 auto TyRegOpt = lookupOptReg(DebugScopeRegs, M->getBaseType());
1381 if (!TyRegOpt)
1382 return std::nullopt;
1383
1384 if (!isUInt<32>(M->getOffsetInBits()) || !isUInt<32>(M->getSizeInBits()))
1385 return std::nullopt;
1386
1387 MCRegister NameReg = getCachedOpStringReg(M->getName());
1388 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1389 M->getFile(), /*UseEmptyPathIfNullScope=*/true);
1390 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1391 ExtInstSetReg, MAI);
1392 MCRegister LineReg =
1393 emitOpConstantI32(static_cast<uint32_t>(M->getLine()), I32TypeReg, MAI);
1394
1395 // DIDerivedType members carry no column, so emit 0.
1396 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1397 MCRegister OffsetReg = emitOpConstantI32(
1398 static_cast<uint32_t>(M->getOffsetInBits()), I32TypeReg, MAI);
1399 MCRegister SizeReg = emitOpConstantI32(
1400 static_cast<uint32_t>(M->getSizeInBits()), I32TypeReg, MAI);
1401 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(M), I32TypeReg, MAI);
1402
1403 // In NonSemantic.Shader.DebugInfo a DebugTypeMember has no Parent operand:
1404 // only the composite references its members. This is by design, it drops the
1405 // Parent that OpenCL.DebugInfo.100 had, and it avoids a composite/member
1406 // reference cycle.
1407 //
1408 // FIXME: Static members are not handled yet: their constant initializer is
1409 // available but is not emitted as the optional Value operand, and under DWARF
1410 // 5 a static member is tagged DW_TAG_variable, which the caller's member loop
1411 // skips.
1412 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeMember, VoidTypeReg,
1413 ExtInstSetReg,
1414 {NameReg, *TyRegOpt, SrcReg, LineReg, ColReg, OffsetReg,
1415 SizeReg, FlagsReg},
1416 MAI);
1417}
1418
1419std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeComposite(
1420 const DICompositeType *CT, ArrayRef<MCRegister> MemberRegs,
1421 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
1423 auto ParentRegOpt = resolveScope(CT->getScope());
1424 if (!ParentRegOpt)
1425 return std::nullopt;
1426
1427 if (!isUInt<32>(CT->getSizeInBits()))
1428 return std::nullopt;
1429
1430 MCRegister NameReg = getCachedOpStringReg(CT->getName());
1431 MCRegister LinkageReg = getCachedOpStringReg(CT->getIdentifier());
1432 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1433 CT->getFile(), /*UseEmptyPathIfNullScope=*/true);
1434 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1435 ExtInstSetReg, MAI);
1436
1437 MCRegister TagReg =
1438 emitOpConstantI32(mapCompositeTypeTag(CT->getTag()), I32TypeReg, MAI);
1439 MCRegister LineReg =
1440 emitOpConstantI32(static_cast<uint32_t>(CT->getLine()), I32TypeReg, MAI);
1441 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1442
1443 // A forward declaration has no known size or members: Size is DebugInfoNone.
1444 MCRegister SizeReg = CachedDebugInfoNoneReg;
1445 if (!CT->isForwardDecl())
1446 SizeReg = emitOpConstantI32(static_cast<uint32_t>(CT->getSizeInBits()),
1447 I32TypeReg, MAI);
1448
1449 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(CT), I32TypeReg, MAI);
1450
1451 SmallVector<MCRegister> Ops = {NameReg, TagReg, SrcReg,
1452 LineReg, ColReg, *ParentRegOpt,
1453 LinkageReg, SizeReg, FlagsReg};
1454 Ops.append(MemberRegs.begin(), MemberRegs.end());
1455 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeComposite, VoidTypeReg,
1456 ExtInstSetReg, Ops, MAI);
1457}
1458
1459std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypedef(
1460 const DIDerivedType *TD, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1461 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1462 // The underlying (base) type must already be in DebugScopeRegs.
1463 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, TD->getBaseType());
1464 if (!BaseRegOpt)
1465 return std::nullopt;
1466
1467 MCRegister NameReg = getCachedOpStringReg(TD->getName());
1468 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1469 TD->getFile(), /*UseEmptyPathIfNullScope=*/true);
1470 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1471 ExtInstSetReg, MAI);
1472 MCRegister LineReg =
1473 emitOpConstantI32(static_cast<uint32_t>(TD->getLine()), I32TypeReg, MAI);
1474 // DIDerivedType typedefs carry no column, so emit 0.
1475 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1476
1477 // Parent must be a lexical scope. Valid NSDI lexical scopes are
1478 // DebugCompilationUnit, DebugFunction, DebugLexicalBlock, or
1479 // DebugTypeComposite.
1480 auto ParentRegOpt = resolveScope(TD->getScope());
1481 if (!ParentRegOpt)
1482 return std::nullopt;
1483 MCRegister ParentReg = *ParentRegOpt;
1484
1485 return emitExtInst(
1486 SPIRV::NonSemanticExtInst::DebugTypedef, VoidTypeReg, ExtInstSetReg,
1487 {NameReg, *BaseRegOpt, SrcReg, LineReg, ColReg, ParentReg}, MAI);
1488}
1489
1492 if (CompileUnits.empty())
1493 return;
1494 // Check that prepareModuleOutput() registered the extended instruction set.
1495 // If the subtarget does not support the extension, neither strings nor ext
1496 // insts are emitted.
1497 if (!MAI.getExtInstSetReg(NSSet).isValid())
1498 return;
1499
1500 for (const CompileUnitInfo &Info : CompileUnits) {
1501 if (Info.TheCU) {
1502 MCRegister PathReg = emitOpStringIfNew(Info.FilePath, MAI);
1503 ScopeToPathOpStringReg[Info.TheCU] = PathReg;
1504 if (const DIFile *F = Info.TheCU->getFile())
1505 ScopeToPathOpStringReg[F] = PathReg;
1506 }
1507 }
1508
1509 for (const DIBasicType *BT : BasicTypes)
1510 emitOpStringIfNew(BT->getName(), MAI);
1511
1513 SubprogramDeclarations, SubprogramDefinitions)) {
1514 emitOpStringIfNew(SP->getName(), MAI);
1515 emitOpStringIfNew(SP->getLinkageName(), MAI);
1516 emitAndCacheScopePathOpStringReg(SP, MAI);
1517 }
1518
1519 // Cache the OpStrings each DebugTypeComposite and its DebugTypeMembers use:
1520 // the composite name, identifier (linkage name), and path, plus each member
1521 // name and path.
1522 for (const DICompositeType *CT : CompositeTypes) {
1523 emitOpStringIfNew(CT->getName(), MAI);
1524 emitOpStringIfNew(CT->getIdentifier(), MAI);
1525 emitAndCacheScopePathOpStringReg(CT->getFile(), MAI);
1526 for (const DINode *Element : CT->getElements()) {
1527 const auto *M = dyn_cast<DIDerivedType>(Element);
1528 if (!M || M->getTag() != dwarf::DW_TAG_member)
1529 continue;
1530 emitOpStringIfNew(M->getName(), MAI);
1531 emitAndCacheScopePathOpStringReg(M->getFile(), MAI);
1532 }
1533 }
1534
1535 // Cache the name and path OpStrings each DebugTypedef uses.
1536 for (const DIDerivedType *TD : TypedefTypes) {
1537 emitOpStringIfNew(TD->getName(), MAI);
1538 emitAndCacheScopePathOpStringReg(TD->getFile(), MAI);
1539 }
1540
1541 for (const auto &[GV, _] : GlobalVariableDebugInfoMap) {
1542 emitOpStringIfNew(GV->getName(), MAI);
1543 emitOpStringIfNew(GV->getLinkageName(), MAI);
1544 emitAndCacheScopePathOpStringReg(GV->getFile(), MAI);
1545 }
1546
1547 for (const DILocalVariable *LV : LocalVariables) {
1548 emitOpStringIfNew(LV->getName(), MAI);
1549 emitAndCacheScopePathOpStringReg(LV->getFile(), MAI);
1550 }
1551
1552 // Cache the path OpString each DebugLexicalBlock uses (source file), plus
1553 // the Name OpString for the DINamespace case.
1554 for (const DIScope *S : LexicalBlocks) {
1555 emitAndCacheScopePathOpStringReg(S->getFile(), MAI);
1556 if (const auto *NS = dyn_cast<DINamespace>(S))
1557 emitOpStringIfNew(NS->getName(), MAI);
1558 }
1559
1560 for (const DILocation *DL : UniqueDebugLocations)
1561 emitAndCacheScopePathOpStringReg(DL->getScope(), MAI);
1562
1563 CachedEmptyStringReg = emitOpStringIfNew("", MAI);
1564
1565#ifndef NDEBUG
1566 NonSemanticOpStringsSectionEmitted = true;
1567#endif
1568}
1569
1570void SPIRVNonSemanticDebugHandler::emitDebugFunctionDefinition(
1571 MCRegister DebugFunctionReg, MCRegister OpFunctionReg,
1573 assert(DebugFunctionReg.isValid() && OpFunctionReg.isValid() &&
1574 "DebugFunctionDefinition operands must be valid");
1575 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1576 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1577 emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDefinition, VoidTypeReg,
1578 ExtInstSetReg, {DebugFunctionReg, OpFunctionReg}, MAI);
1579}
1580
1581void SPIRVNonSemanticDebugHandler::resetPerFunctionDebugState() {
1582 CurrentMF = nullptr;
1583 LastFunctionOpVariable = nullptr;
1584 DebugFunctionDefinitionEmitted = false;
1585 LastLineMI = nullptr;
1586 LastScopeMI = nullptr;
1587 Records.clear();
1588}
1589
1590void SPIRVNonSemanticDebugHandler::preparePerFunctionDebug(
1591 const MachineFunction *MF) {
1592 resetPerFunctionDebugState();
1593 if (!GlobalNSDIEnabled || !CurrentMAI)
1594 return;
1595
1596 CurrentMF = MF;
1597
1598 if (MF->getFunction()
1600 .isValid())
1601 return;
1602
1603 const DISubprogram *SP = MF->getFunction().getSubprogram();
1604 if (!SP || !SP->isDefinition())
1605 return;
1606
1607 // DebugFunctionDefinition is emitted after the last function-level
1608 // OpVariable. If there are none, it is emitted after the entry OpLabel.
1609 LastFunctionOpVariable =
1610 findLastFunctionOpVariableDeclaration(*MF, *CurrentMAI);
1611
1612 analyzeDebugRecords(*MF);
1613}
1614
1615void SPIRVNonSemanticDebugHandler::tryEmitDebugFunctionDefinition(
1617 if (DebugFunctionDefinitionEmitted || !GlobalNSDIEnabled)
1618 return;
1619
1620 assert(CurrentMF && "no current MachineFunction");
1621 const Function &F = CurrentMF->getFunction();
1622 const DISubprogram *SP = F.getSubprogram();
1623 if (!SP || !SP->isDefinition())
1624 return;
1625
1626 auto DFIt = DebugScopeRegs.find(SP);
1627 if (DFIt == DebugScopeRegs.end())
1628 return;
1629
1630 MCRegister OpFunctionReg = MAI.getGlobalObjReg(&F);
1631 if (!OpFunctionReg.isValid())
1632 return;
1633
1634 emitDebugFunctionDefinition(DFIt->second, OpFunctionReg, MAI);
1635 DebugFunctionDefinitionEmitted = true;
1636}
1637
1639 const MachineFunction *MF) {
1640 preparePerFunctionDebug(MF);
1641}
1642
1644 (void)MF;
1645 resetPerFunctionDebugState();
1646}
1647
1649 assert(CurMI == nullptr && "CurMI must be null");
1650 CurMI = MI;
1651
1652 if (!DebugFunctionDefinitionEmitted)
1653 return;
1654
1655 emitAnalyzedRecords(MI);
1656
1657 std::optional<const MachineInstr *> Target = resolveDebugLocTarget(MI);
1658 if (!Target)
1659 return;
1660
1661 (void)emitDebugScopeForInstruction(*Target);
1662 emitDebugLineForInstruction(*Target);
1663}
1664
1665// The register that holds the variable's address in \p MI, or std::nullopt
1666// when \p MI is not a declare this backend can describe.
1667//
1668// The spec requires DebugDeclare's Variable operand to be "the <id> of an
1669// OpVariable instruction that defines the local variable". MIR has no
1670// DBG_DECLARE, so what this looks for is an indirect DBG_VALUE whose location
1671// register an OpVariable defines.
1672static std::optional<Register>
1674 // #dbg_declare is an indirect DBG_VALUE in MIR; #dbg_value is normally a
1675 // direct one except for the variadic case.
1676 if (!MI.isIndirectDebugValue())
1677 return std::nullopt;
1678
1679 // A variadic #dbg_value becomes DBG_VALUE $noreg, 0, ... which is indirect
1680 // too, and $noreg is not virtual.
1681 Register LocReg = MI.getDebugOperand(0).getReg();
1682 if (!LocReg.isVirtual())
1683 return std::nullopt;
1684
1685 // DebugDeclare can only encode the address of an OpVariable.
1686 // Other legitimate #dbg_declare cannot be encoded.
1687 // Examples: an access chain for a field, an OpFunctionParameter for a byval
1688 // argument, or a module-scope constant for a null or fixed address.
1689
1690 // LocReg may also have no def at all: erasing dead storage leaves the
1691 // DBG_VALUE pointing at an undefined register. MachineVerifier permits that
1692 // because LiveDebugVariables normally clears it, but this pipeline has no
1693 // register allocation, so LiveDebugVariables never runs.
1694 const MachineInstr *Def = MI.getMF()->getRegInfo().getUniqueVRegDef(LocReg);
1695 if (!Def || Def->getOpcode() != SPIRV::OpVariable)
1696 return std::nullopt;
1697
1698 return LocReg;
1699}
1700
1701void SPIRVNonSemanticDebugHandler::emitDebugBinding(
1702 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
1703 const MachineInstr *MI, MCRegister LocationReg) {
1704 assert(DebugFunctionDefinitionEmitted &&
1705 "DebugFunctionDefinition must be emitted");
1706 assert(CurrentMAI && "CurrentMAI must be set");
1707
1708 auto VarRegOpt = lookupOptReg(DebugLocalVariableRegs, MI->getDebugVariable());
1709 if (!VarRegOpt)
1710 return;
1711
1712 auto ExprRegOpt = lookupOptReg(DebugExpressionRegs, MI->getDebugExpression());
1713 if (!ExprRegOpt)
1714 return;
1715
1716 if (!emitDebugScopeForInstruction(MI))
1717 return;
1718 emitDebugLineForInstruction(MI);
1719
1720 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1721 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1722 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1723 emitExtInst(Opcode, VoidTypeReg, ExtInstSetReg,
1724 {*VarRegOpt, LocationReg, *ExprRegOpt}, MAI);
1725}
1726
1727// The scalar type and value of the constant \p MI assigns, or nullopt when
1728// this backend cannot name it.
1729static std::optional<std::pair<const DIBasicType *, uint64_t>>
1731 if (!MI.isNonListDebugValue() || MI.isIndirectDebugValue())
1732 return std::nullopt;
1733
1734 const MachineOperand &Value = MI.getDebugOperand(0);
1735 if (!Value.isImm() && !Value.isCImm() && !Value.isFPImm())
1736 return std::nullopt;
1737
1738 const DILocalVariable *LV = MI.getDebugVariable();
1739 const DIBasicType *BT = LV ? stripToScalarType(LV->getType()) : nullptr;
1740 if (!BT)
1741 return std::nullopt;
1742
1743 uint64_t Bits;
1744 if (Value.isImm())
1745 Bits = constantBits(static_cast<uint64_t>(Value.getImm()), BT);
1746 else if (Value.isCImm())
1747 Bits = constantBits(Value.getCImm()->getValue(), BT);
1748 else
1749 Bits = constantBits(Value.getFPImm()->getValueAPF().bitcastToAPInt(), BT);
1750 return std::make_pair(BT, Bits);
1751}
1752
1753std::optional<MCRegister> SPIRVNonSemanticDebugHandler::getConstantValueReg(
1754 const MachineInstr &MI) const {
1755 std::optional<std::pair<const DIBasicType *, uint64_t>> Const =
1757 if (!Const)
1758 return std::nullopt;
1759
1760 auto It = ConstantValueRegs.find(*Const);
1761 if (It == ConstantValueRegs.end() || !It->second.isValid())
1762 return std::nullopt;
1763 return It->second;
1764}
1765
1766static std::optional<Register> getDebugValueReg(const MachineInstr &MI) {
1767 if (!MI.isNonListDebugValue() || MI.isIndirectDebugValue())
1768 return std::nullopt;
1769
1770 const MachineOperand &Value = MI.getDebugOperand(0);
1771 if (!Value.isReg())
1772 return std::nullopt;
1773
1774 Register ValueReg = Value.getReg();
1775 if (!ValueReg.isVirtual())
1776 return std::nullopt;
1777
1778 const MachineInstr *Def = MI.getMF()->getRegInfo().getUniqueVRegDef(ValueReg);
1779 if (!Def || Def->isPseudo() || Def->isMetaInstruction() ||
1780 Def->getNumOperands() == 0 || !Def->getOperand(0).isReg() ||
1781 !Def->getOperand(0).isDef() || Def->getOperand(0).getReg() != ValueReg)
1782 return std::nullopt;
1783
1784 return ValueReg;
1785}
1786
1787static bool isMergeInstruction(unsigned Opcode) {
1788 return Opcode == SPIRV::OpSelectionMerge || Opcode == SPIRV::OpLoopMerge ||
1789 Opcode == SPIRV::OpLoopControlINTEL;
1790}
1791
1792// Whether \p MI becomes a SPIR-V instruction in the output.
1794 return !MI->isMetaInstruction() && !MAI.getSkipEmission(MI);
1795}
1796
1799 if (!isEmitted(MI, MAI))
1800 return false;
1801 switch (MI->getOpcode()) {
1802 case SPIRV::OpFunction:
1803 case SPIRV::OpFunctionParameter:
1804 case SPIRV::OpFunctionEnd:
1805 case SPIRV::OpLabel:
1806 case SPIRV::OpPhi:
1807 return false;
1808 default:
1809 return true;
1810 }
1811}
1812
1813static const MachineInstr *
1815 SPIRV::ModuleAnalysisInfo &MAI, bool Forward) {
1816 for (const MachineInstr *Adj = Forward ? MI->getNextNode()
1817 : MI->getPrevNode();
1818 Adj; Adj = Forward ? Adj->getNextNode() : Adj->getPrevNode()) {
1819 if (!isEmitted(Adj, MAI))
1820 continue;
1821 return Adj;
1822 }
1823 return nullptr;
1824}
1825
1826std::optional<const MachineInstr *>
1827SPIRVNonSemanticDebugHandler::resolveDebugLocTarget(const MachineInstr *MI) {
1828 assert(CurrentMAI && "CurrentMAI must be set");
1829 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1830
1831 // Structural opcodes don't require a DebugLine/DebugScope, other opcodes
1832 // might have already been emitted in the module scope.
1833 if (!isDebugLocTarget(MI, MAI))
1834 return std::nullopt;
1835
1836 // DebugLine/DebugScope can be emitted before a merge instruction, but not
1837 // after it (nothing may sit between the merge and its terminator). We can
1838 // use either the merge's or the terminator's debug info; we emit the
1839 // terminator's one.
1840 const MachineInstr *Prev = findAdjacentEmittedInstruction(MI, MAI, false);
1841 if (Prev && isMergeInstruction(Prev->getOpcode()))
1842 return std::nullopt;
1843
1844 if (isMergeInstruction(MI->getOpcode())) {
1845 // Use the terminator's debug info; when we reach it later, the check
1846 // above skips it.
1847 MI = findAdjacentEmittedInstruction(MI, MAI, true);
1848 assert(MI && "Merge instruction must be followed by a terminator");
1849 // The assert is compiled out in a release build, and returning MI there
1850 // would give an engaged optional holding null.
1851 if (!MI)
1852 return std::nullopt;
1853 }
1854
1855 return MI;
1856}
1857
1858void SPIRVNonSemanticDebugHandler::resolveDebugRecord(
1859 const MachineInstr &MI, const MachineInstr *LastEmitted,
1860 const MachineDominatorTree &DomTree) {
1861 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1862 const MachineFunction &MF = *MI.getMF();
1863
1864 // A record sits at its own position, except in a merge region: nothing may
1865 // be emitted between a merge and its terminator, so it belongs ahead of the
1866 // merge.
1867 const MachineInstr *Anchor =
1868 LastEmitted && isMergeInstruction(LastEmitted->getOpcode()) ? LastEmitted
1869 : &MI;
1870
1871 // A #dbg_declare reaches Machine IR as an indirect DBG_VALUE. Its storage is
1872 // an OpVariable in the entry block, so it is in the output by the time any
1873 // record naming it is reached.
1874 if (std::optional<Register> LocReg = getDebugDeclareStorageReg(MI)) {
1875 MCRegister StorageReg = MAI.getRegisterAlias(&MF, *LocReg);
1876 if (StorageReg.isValid())
1877 placeRecord(SPIRV::NonSemanticExtInst::DebugDeclare, MI, StorageReg,
1878 Anchor);
1879 return;
1880 }
1881
1882 if (std::optional<MCRegister> ConstReg = getConstantValueReg(MI)) {
1883 placeRecord(SPIRV::NonSemanticExtInst::DebugValue, MI, *ConstReg, Anchor);
1884 return;
1885 }
1886
1887 std::optional<Register> ValReg = getDebugValueReg(MI);
1888 if (!ValReg)
1889 return;
1890 MCRegister ValueReg = MAI.getRegisterAlias(&MF, *ValReg);
1891 if (!ValueReg.isValid())
1892 return;
1893
1894 // NonSemantic.Shader.DebugInfo states that "Forward references are not
1895 // allowed, to be compliant with SPV_KHR_non_semantic_info", so the id has to
1896 // be in the output already. A module section precedes every function body.
1897 //
1898 // For anything else, SPIR-V requires a definition in a function block to
1899 // dominate a non-phi use, and requires a block to precede every block it
1900 // dominates, so a dominating definition is also one already printed. A
1901 // record naming a definition that does not dominate it is dropped.
1902 const MachineInstr *Def = MF.getRegInfo().getUniqueVRegDef(*ValReg);
1903 if (ModuleScopeIds.contains(ValueReg) ||
1904 (isEmitted(Def, MAI) && DomTree.dominates(Def, &MI)))
1905 placeRecord(SPIRV::NonSemanticExtInst::DebugValue, MI, ValueReg, Anchor);
1906}
1907
1908void SPIRVNonSemanticDebugHandler::analyzeDebugRecords(
1909 const MachineFunction &MF) {
1910 assert(CurrentMAI && "CurrentMAI must be set");
1911
1912 // Built on the first record rather than required as an analysis pass, which
1913 // would build a tree for every SPIR-V compilation.
1914 std::optional<MachineDominatorTree> DomTree;
1915
1916 for (const MachineBasicBlock &MBB : MF) {
1917 const MachineInstr *LastEmitted = nullptr;
1918 for (const MachineInstr &MI : MBB) {
1919 if (MI.isDebugValueLike()) {
1920 if (!DomTree)
1921 DomTree.emplace(const_cast<MachineFunction &>(MF));
1922 resolveDebugRecord(MI, LastEmitted, *DomTree);
1923 }
1924
1925 if (isEmitted(&MI, *CurrentMAI))
1926 LastEmitted = &MI;
1927 }
1928 }
1929}
1930
1931void SPIRVNonSemanticDebugHandler::placeRecord(
1932 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
1933 const MachineInstr &MI, MCRegister LocationReg,
1934 const MachineInstr *Anchor) {
1935 Records[Anchor].push_back({&MI, Opcode, LocationReg});
1936}
1937
1938void SPIRVNonSemanticDebugHandler::emitAnalyzedRecords(
1939 const MachineInstr *Anchor) {
1940 auto It = Records.find(Anchor);
1941 if (It == Records.end())
1942 return;
1943 for (const DebugRecord &R : It->second)
1944 emitDebugBinding(R.Opcode, R.MI, R.LocationReg);
1945}
1946
1947bool SPIRVNonSemanticDebugHandler::emitDebugScopeForInstruction(
1948 const MachineInstr *MI) {
1949 assert(DebugFunctionDefinitionEmitted &&
1950 "DebugFunctionDefinition must be emitted");
1951 assert(CurrentMAI && "CurrentMAI must be set");
1952
1953 // The region is implicitly closed at each basic block boundary, so a
1954 // LastScopeMI from another block must be dropped before it is read below:
1955 // the new block needs its own DebugScope, and has no region left to close.
1956 if (LastScopeMI && MI->getParent() != LastScopeMI->getParent())
1957 LastScopeMI = nullptr;
1958
1959 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1960 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1961 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1962
1963 const DILocation *CurDL = MI->getDebugLoc().get();
1964 if (!CurDL) {
1965 // No location for the current instruction.
1966 if (LastScopeMI) {
1967 // Close the current DebugScope region.
1968 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoScope, VoidTypeReg,
1969 ExtInstSetReg, {}, MAI);
1970 LastScopeMI = nullptr;
1971 }
1972 return true;
1973 }
1974
1975 const DIScope *CurScope = CurDL->getScope();
1976 const DILocation *CurInlinedAt = CurDL->getInlinedAt();
1977
1978 if (LastScopeMI) {
1979 const DILocation *LastDL = LastScopeMI->getDebugLoc().get();
1980 if (LastDL->getScope() == CurScope &&
1981 LastDL->getInlinedAt() == CurInlinedAt)
1982 return true;
1983 }
1984
1985 auto CurScopeRegOpt = resolveScope(CurScope);
1986 if (!CurScopeRegOpt)
1987 return false;
1988
1989 SmallVector<MCRegister, 2> Ops{*CurScopeRegOpt};
1990 if (CurInlinedAt) {
1991 // If the global emission did not include this inlined-at case, we skip it.
1992 MCRegister InlinedReg = DebugInlinedAtRegs.lookup(CurInlinedAt);
1993 if (!InlinedReg.isValid())
1994 return false;
1995 Ops.push_back(InlinedReg);
1996 }
1997
1998 // A new DebugScope region is needed.
1999 emitExtInst(SPIRV::NonSemanticExtInst::DebugScope, VoidTypeReg, ExtInstSetReg,
2000 Ops, MAI);
2001
2002 LastScopeMI = MI;
2003 return true;
2004}
2005
2006void SPIRVNonSemanticDebugHandler::emitDebugLineForInstruction(
2007 const MachineInstr *MI) {
2008 assert(DebugFunctionDefinitionEmitted &&
2009 "DebugFunctionDefinition must be emitted");
2010 assert(CurrentMAI && "CurrentMAI must be set");
2011
2012 // The region is implicitly closed at each basic block boundary, so a
2013 // LastLineMI from another block must be dropped before it is read below:
2014 // the new block needs its own DebugLine, and has no region left to close.
2015 if (LastLineMI && MI->getParent() != LastLineMI->getParent())
2016 LastLineMI = nullptr;
2017
2018 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2019 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2020 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
2021
2022 const DILocation *DL = MI->getDebugLoc().get();
2023 if (!DL) {
2024 // No location for the current instruction
2025 if (LastLineMI) {
2026 // Close the current DebugLine region.
2027 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoLine, VoidTypeReg,
2028 ExtInstSetReg, {}, MAI);
2029 LastLineMI = nullptr;
2030 }
2031 // No DebugLine region to close.
2032 return;
2033 }
2034
2035 // At this point, there is a location for the current instruction.
2036 // If it matches the last emitted DebugLine, no new DebugLine region is
2037 // needed. Otherwise, emit a new DebugLine region and update LastLineMI.
2038
2039 MCRegister FileStrReg = getCachedScopePathOpStringReg(
2040 DL->getScope(), /*UseEmptyPathIfNullScope=*/true);
2041 unsigned Line = DL->getLine();
2042 unsigned Col = DL->getColumn();
2043
2044 unsigned I32TypeId = CachedOpTypeInt32Reg.id();
2045 MCRegister SrcReg = DebugSourceRegByFileStr.lookup(FileStrReg.id());
2046 MCRegister LineReg = ScalarConstantCache.lookup({I32TypeId, Line});
2047 MCRegister ColStartReg = ScalarConstantCache.lookup({I32TypeId, Col});
2048 MCRegister ColEndReg = ScalarConstantCache.lookup({I32TypeId, Col + 1});
2049
2050 // The elements of each collected DILocation (DebugSource, line/column
2051 // constants) are pre-emitted from LLVM-IR instruction !dbg attachments and
2052 // debug-program records; MIR is expected to reuse those same locations (or
2053 // carry none). A lookup miss means codegen attached a source position whose
2054 // elements were never pre-emitted, and debug-line emission is skipped.
2055 if (!SrcReg.isValid() || !LineReg.isValid() || !ColStartReg.isValid() ||
2056 !ColEndReg.isValid())
2057 return;
2058
2059 // Current location matches the last emitted DebugLine region.
2060 if (LastLineMI && MI->getDebugLoc() == LastLineMI->getDebugLoc())
2061 return;
2062
2063 // A new DebugLine region is needed.
2064 emitExtInst(SPIRV::NonSemanticExtInst::DebugLine, VoidTypeReg, ExtInstSetReg,
2065 {SrcReg, LineReg, LineReg, ColStartReg, ColEndReg}, MAI);
2066
2067 LastLineMI = MI;
2068}
2069
2071 const MachineInstr *MI = CurMI;
2072 CurMI = nullptr;
2073
2074 if (!MI || !GlobalNSDIEnabled || !CurrentMF)
2075 return;
2076
2077 if (DebugFunctionDefinitionEmitted || MI != LastFunctionOpVariable)
2078 return;
2079
2080 // If this is the last function-level OpVariable, emit the
2081 // DebugFunctionDefinition. Otherwise, we had already done it before right
2082 // after the OpLabel (see notifyEntryLabelEmitted).
2083 assert(CurrentMAI && "CurrentMAI must be set");
2084 tryEmitDebugFunctionDefinition(*CurrentMAI);
2085}
2086
2088 const MachineFunction &MF) {
2089 if (!GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
2090 return;
2091
2092 assert(CurrentMF == &MF &&
2093 "notification does not match the current MachineFunction");
2094
2095 if (LastFunctionOpVariable)
2096 return;
2097
2098 // If there are no function-level OpVariables, emit the
2099 // DebugFunctionDefinition. Otherwise, DebugFunctionDefinition is emitted
2100 // after the last OpVariable (see endInstruction).
2101 tryEmitDebugFunctionDefinition(*CurrentMAI);
2102}
2103
2104static void forEachDebugValueLike(const MachineModuleInfo &ModuleInfo,
2105 function_ref<void(const MachineInstr &)> Fn) {
2106 for (const Function &F : *ModuleInfo.getModule()) {
2107 const MachineFunction *MF = ModuleInfo.getMachineFunction(F);
2108 if (!MF)
2109 continue;
2110 for (const MachineBasicBlock &MBB : *MF)
2111 for (const MachineInstr &MI : MBB)
2112 if (MI.isDebugValueLike())
2113 Fn(MI);
2114 }
2115}
2116
2117void SPIRVNonSemanticDebugHandler::collectDebugExpressions(
2119 MachineModuleInfo *ModuleInfo = Asm->MMI;
2120 assert(ModuleInfo && "MachineModuleInfo must be set during module output");
2121
2122 forEachDebugValueLike(*ModuleInfo, [&](const MachineInstr &MI) {
2123 Out.insert(MI.getDebugExpression());
2124 });
2125}
2126
2129 if (GlobalDIEmitted)
2130 return;
2131
2132 GlobalDIEmitted = true;
2133
2134 if (CompileUnits.empty()) {
2135 GlobalNSDIEnabled = false;
2136 return;
2137 }
2138
2139 // Retrieve the ext inst set register allocated by prepareModuleOutput().
2140 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
2141 if (!ExtInstSetReg.isValid()) {
2142 GlobalNSDIEnabled = false;
2143 return;
2144 }
2145
2146#ifndef NDEBUG
2147 assert(NonSemanticOpStringsSectionEmitted &&
2148 "emitNonSemanticDebugStrings() must run before "
2149 "emitNonSemanticGlobalDebugInfo()");
2150#endif
2151
2152 CurrentMAI = &MAI;
2153
2154 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2155 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
2156
2157 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
2158 VoidTypeReg, ExtInstSetReg, {}, MAI);
2159
2160 // Emit integer constants shared across all NSDI instructions. The constant
2161 // cache ensures each value is emitted at most once even when referenced from
2162 // multiple instructions. All constants are pre-emitted before any DebugSource
2163 // so that the output order is: constants, then
2164 // DebugSource+DebugCompilationUnit pairs. This keeps OpConstant instructions
2165 // grouped before the OpExtInst instructions.
2166
2167 // The Version operand of DebugCompilationUnit is the version of the
2168 // NonSemantic.Shader.DebugInfo instruction set, which is 100 for
2169 // "NonSemantic.Shader.DebugInfo.100" (NonSemanticShaderDebugInfo100Version).
2170 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
2171 MCRegister DwarfVersionReg =
2172 emitOpConstantI32(static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
2173
2174 // Pre-emit source language constants for all compile units before entering
2175 // the DebugSource loop.
2176 SmallVector<MCRegister> SrcLangRegs =
2177 map_to_vector(CompileUnits, [&](const CompileUnitInfo &Info) {
2178 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
2179 });
2180
2181 // Emit DebugSource and DebugCompilationUnit for each compile unit.
2182 for (auto [Info, SrcLangReg] : llvm::zip(CompileUnits, SrcLangRegs)) {
2183 MCRegister FileStrReg = ScopeToPathOpStringReg.lookup(Info.TheCU);
2184 assert(FileStrReg.isValid() &&
2185 "CU path OpString must be emitted in emitNonSemanticDebugStrings");
2186 MCRegister DebugSourceReg = getOrEmitDebugSourceForFileStrReg(
2187 FileStrReg, VoidTypeReg, ExtInstSetReg, MAI);
2188 MCRegister CUDbgReg = emitExtInst(
2189 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
2190 ExtInstSetReg,
2191 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
2192 MAI);
2193 if (Info.TheCU)
2194 DebugScopeRegs[Info.TheCU] = CUDbgReg;
2195 }
2196
2197 // Zero constant used as the Flags operand in DebugTypeBasic and
2198 // DebugTypePointer. Cached with other i32 constants.
2199 MCRegister I32ZeroReg = emitOpConstantI32(0, I32TypeReg, MAI);
2200
2201 for (const DIBasicType *BT : BasicTypes) {
2202 if (!isUInt<32>(BT->getSizeInBits()))
2203 continue;
2204
2205 MCRegister NameReg = getCachedOpStringReg(BT->getName());
2206 MCRegister SizeReg = emitOpConstantI32(
2207 static_cast<uint32_t>(BT->getSizeInBits()), I32TypeReg, MAI);
2208
2209 // Map DWARF base type encodings to NSDI encoding codes per
2210 // NonSemantic.Shader.DebugInfo.100 specification, section 4.5.
2211 unsigned Encoding = 0; // Unspecified
2212 switch (BT->getEncoding()) {
2213 case dwarf::DW_ATE_address:
2214 Encoding = 1;
2215 break;
2216 case dwarf::DW_ATE_boolean:
2217 Encoding = 2;
2218 break;
2219 case dwarf::DW_ATE_float:
2220 Encoding = 3;
2221 break;
2222 case dwarf::DW_ATE_signed:
2223 Encoding = 4;
2224 break;
2225 case dwarf::DW_ATE_signed_char:
2226 Encoding = 5;
2227 break;
2228 case dwarf::DW_ATE_unsigned:
2229 Encoding = 6;
2230 break;
2231 case dwarf::DW_ATE_unsigned_char:
2232 Encoding = 7;
2233 break;
2234 }
2235 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
2236
2237 MCRegister BTReg = emitExtInst(
2238 SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
2239 {NameReg, SizeReg, EncodingReg, I32ZeroReg}, MAI);
2240 DebugScopeRegs[BT] = BTReg;
2241 }
2242
2243 // Emit DebugTypeVector for each collected vector type.
2244 for (const DICompositeType *VT : VectorTypes) {
2245 if (auto VecReg = emitDebugTypeVector(VT, ExtInstSetReg, MAI))
2246 DebugScopeRegs[VT] = *VecReg;
2247 }
2248
2249 // Emit DebugTypePointer for each referenced pointer type.
2250 for (const DIDerivedType *PT : PointerTypes) {
2251 if (auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
2252 DebugScopeRegs[PT] = *PtrReg;
2253 }
2254
2255 // Emit DebugTypeArray for each collected array type. Placed after the basic,
2256 // vector, and pointer types so an array over any of them can resolve its
2257 // element id. An array whose element type was not emitted is skipped.
2258 for (const DICompositeType *AT : ArrayTypes) {
2259 if (auto ArrReg = emitDebugTypeArray(AT, ExtInstSetReg, MAI))
2260 DebugScopeRegs[AT] = *ArrReg;
2261 }
2262
2263 // Emit DebugTypeFunction for each distinct DISubroutineType.
2264 for (const DISubroutineType *ST : SubroutineTypes) {
2265 if (auto FnTyReg =
2266 emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI))
2267 DebugScopeRegs[ST] = *FnTyReg;
2268 }
2269
2270 // Emit DebugLexicalBlock for each collected DINamespace, in parent-before-
2271 // child order. Placed before any DINamespace-scoped entity (typedefs,
2272 // function declarations, composite types, functions, global variables) so
2273 // their Parent operand can reference an already-emitted DebugLexicalBlock.
2274 // DINamespace never chains through a DISubprogram (DINamespace::getScope()
2275 // returns DIScope, not DILocalScope), so this never depends on
2276 // DebugScopeRegs.
2277 for (const DIScope *S :
2278 make_filter_range(LexicalBlocks, IsaPred<DINamespace>)) {
2279 if (auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
2280 ExtInstSetReg, MAI))
2281 DebugScopeRegs[S] = *LBReg;
2282 }
2283
2284 // Emit DebugTypedef for each typedef. Placed after the other type loops so a
2285 // typedef can resolve its underlying type. A typedef whose base type is not
2286 // emitted is skipped. A typedef whose base is another typedef emitted later
2287 // in this same pass is also skipped, the emission-order gap tracked in
2288 // https://github.com/llvm/llvm-project/issues/211850.
2289 for (const DIDerivedType *TD : TypedefTypes) {
2290 if (auto TDReg =
2291 emitDebugTypedef(TD, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
2292 DebugScopeRegs[TD] = *TDReg;
2293 }
2294
2295 // Emit DebugFunctionDeclaration for DISubprogram declarations.
2296 for (const DISubprogram *SP : SubprogramDeclarations) {
2297 if (auto DeclReg = emitDebugFunctionDeclaration(SP, VoidTypeReg, I32TypeReg,
2298 ExtInstSetReg, MAI))
2299 DebugScopeRegs[SP] = *DeclReg;
2300 }
2301
2302 // Emit DebugTypeMember and DebugTypeComposite for each struct, class, or
2303 // union. Each member is emitted before the composite that lists it, so the
2304 // Members operand references already-defined ids. A member whose type is not
2305 // in DebugScopeRegs is skipped.
2306 for (const DICompositeType *CT : CompositeTypes) {
2307 SmallVector<MCRegister> MemberRegs;
2308 for (const DINode *Element : CT->getElements()) {
2309 const auto *M = dyn_cast<DIDerivedType>(Element);
2310 if (!M || M->getTag() != dwarf::DW_TAG_member)
2311 continue;
2312 if (auto MemberReg = emitDebugTypeMember(M, VoidTypeReg, I32TypeReg,
2313 ExtInstSetReg, MAI))
2314 MemberRegs.push_back(*MemberReg);
2315 }
2316 if (auto CompReg = emitDebugTypeComposite(CT, MemberRegs, VoidTypeReg,
2317 I32TypeReg, ExtInstSetReg, MAI))
2318 DebugScopeRegs[CT] = *CompReg;
2319 }
2320
2321 // Emit DebugFunction for DISubprogram definitions.
2322 for (const DISubprogram *SP : SubprogramDefinitions) {
2323 if (auto FnReg =
2324 emitDebugFunction(SP, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
2325 DebugScopeRegs[SP] = *FnReg;
2326 }
2327
2328 // Emit DebugLexicalBlock for each collected DILexicalBlock, in parent-
2329 // before-child order. Placed after DebugFunction so a block directly
2330 // enclosed by a function (the common case) can resolve its Parent operand;
2331 // DINamespace entries were already emitted above.
2332 for (const DIScope *S :
2334 if (auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
2335 ExtInstSetReg, MAI))
2336 DebugScopeRegs[S] = *LBReg;
2337 }
2338
2339 // Emit DebugLocalVariable after DebugFunction and their lexical blocks so the
2340 // Parent operand can resolve. Record the ids for DebugDeclare.
2341 for (const DILocalVariable *LV : LocalVariables)
2342 if (auto LVReg = emitDebugLocalVariable(LV, VoidTypeReg, I32TypeReg,
2343 ExtInstSetReg, MAI))
2344 DebugLocalVariableRegs[LV] = *LVReg;
2345
2346 // Opcodes like DebugDeclare are part of the function body, but
2347 // DebugExpression is not. For such opcodes, we collect the expressions
2348 // directly from the MIR to avoid inconsistencies with those in the LLVM IR
2349 // module.
2351 collectDebugExpressions(Expressions);
2352 for (const DIExpression *Expr : Expressions)
2353 if (auto ExprReg = emitDebugExpression(Expr, VoidTypeReg, I32TypeReg,
2354 ExtInstSetReg, MAI))
2355 DebugExpressionRegs[Expr] = *ExprReg;
2356
2357 // Emit DebugGlobalVariable for each collected DIGlobalVariable.
2358 for (const auto &[GV, Info] : GlobalVariableDebugInfoMap)
2359 emitDebugGlobalVariable(GV, Info, VoidTypeReg, I32TypeReg, ExtInstSetReg,
2360 MAI);
2361
2362 // Emit DebugInlinedAt allowing recursive inlining.
2363 for (const DILocation *DL : UniqueDebugLocations)
2364 if (const DILocation *IA = DL->getInlinedAt())
2365 getOrEmitDebugInlinedAt(IA, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
2366
2367 // Repeating the lookups emitDebugBinding() performs emits a type and a
2368 // constant only for an assignment that will reach a DebugValue.
2369 MachineModuleInfo *ModuleInfo = Asm->MMI;
2370 assert(ModuleInfo && "MachineModuleInfo must be set during module output");
2371 forEachDebugValueLike(*ModuleInfo, [&](const MachineInstr &MI) {
2372 std::optional<std::pair<const DIBasicType *, uint64_t>> Const =
2374 if (!Const)
2375 return;
2376 if (!DebugLocalVariableRegs.contains(MI.getDebugVariable()) ||
2377 !DebugExpressionRegs.contains(MI.getDebugExpression()))
2378 return;
2379 auto [It, Inserted] = ConstantValueRegs.try_emplace(*Const, MCRegister());
2380 if (Inserted)
2381 It->second = findOrEmitScalarConstant(Const->first, Const->second, MAI);
2382 if (!It->second.isValid())
2383 ConstantValueRegs.erase(It);
2384 });
2385
2386 for (const DILocation *DL : UniqueDebugLocations) {
2387 emitOpConstantI32(DL->getLine(), I32TypeReg, MAI);
2388 emitOpConstantI32(DL->getColumn(), I32TypeReg, MAI);
2389 emitOpConstantI32(DL->getColumn() + 1, I32TypeReg, MAI);
2390 MCRegister FileStrReg =
2391 getCachedScopePathOpStringReg(DL->getScope(),
2392 /*UseEmptyPathIfNullScope=*/true);
2393 getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg, ExtInstSetReg,
2394 MAI);
2395 }
2396
2397 GlobalNSDIEnabled = true;
2398}
2399
2401SPIRVNonSemanticDebugHandler::getDebugFullPath(const DIScope *Scope) const {
2402 SmallString<128> Out;
2403 if (!Scope)
2404 return Out;
2405 StringRef Filename = Scope->getFilename();
2406 const auto Style = sys::path::Style::native;
2407 if (sys::path::is_absolute(Filename, Style))
2408 Out.assign(Filename.begin(), Filename.end());
2409 else {
2410 StringRef Dir = Scope->getDirectory();
2411 Out.assign(Dir.begin(), Dir.end());
2412 sys::path::append(Out, Style, Filename);
2413 }
2414 return Out;
2415}
2416
2417MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugSourceForFileStrReg(
2418 MCRegister FileStrReg, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
2420 const unsigned Key = FileStrReg.id();
2421 auto It = DebugSourceRegByFileStr.find(Key);
2422 if (It != DebugSourceRegByFileStr.end())
2423 return It->second;
2424
2425 MCRegister DS = emitExtInst(SPIRV::NonSemanticExtInst::DebugSource,
2426 VoidTypeReg, ExtInstSetReg, {FileStrReg}, MAI);
2427 DebugSourceRegByFileStr[Key] = DS;
2428 return DS;
2429}
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:809
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:872
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:765
DISubprogram * getSubprogram() const
Get the attached subprogram.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void 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)