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