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