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