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