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/SetVector.h"
16#include "llvm/ADT/Twine.h"
22#include "llvm/IR/DebugInfo.h"
28#include "llvm/IR/Module.h"
29#include "llvm/MC/MCInst.h"
30#include "llvm/MC/MCStreamer.h"
33#include "llvm/Support/Path.h"
34#include <cassert>
35
36using namespace llvm;
37
38namespace {
39
40/// Look up \p Key in a register map and return its value, or std::nullopt when
41/// the key is absent.
42template <typename MapT>
43static std::optional<MCRegister> lookupOptReg(const MapT &Map,
44 typename MapT::key_type Key) {
45 auto It = Map.find(Key);
46 if (It == Map.end())
47 return std::nullopt;
48 assert(It->second.isValid() && "invalid register stored in map");
49 return It->second;
50}
51
52/// Partition \p Ty into \p BasicTypes, \p PointerTypes, \p SubroutineTypes,
53/// \p VectorTypes, \p ArrayTypes, \p CompositeTypes, and \p TypedefTypes for
54/// NSDI emission. Used when iterating DebugInfoFinder.types(); each DI node is
55/// seen once, so no recursion into pointer bases. Other composites and the
56/// remaining derived kinds are ignored because they are not yet supported.
57/// Only types that are supported (later used) are partitioned.
58static void
59partitionTypes(const DIType *Ty, SmallVector<const DIBasicType *> &BasicTypes,
66 if (const auto *BT = dyn_cast<DIBasicType>(Ty)) {
67 BasicTypes.push_back(BT);
68 return;
69 }
70 if (const auto *ST = dyn_cast<DISubroutineType>(Ty)) {
71 SubroutineTypes.push_back(ST);
72 return;
73 }
74 if (const auto *CT = dyn_cast<DICompositeType>(Ty)) {
75 if (CT->getTag() == dwarf::DW_TAG_array_type) {
76 // A vector is an array with DINode::FlagVector. A plain array is the
77 // same tag without it. A matrix is also lowered to a DW_TAG_array_type
78 // (two subranges), so it is indistinguishable from a 2D array here and
79 // is emitted as a DebugTypeArray.
80 //
81 // FIXME: Emitting a matrix as a DebugTypeArray is valid but loses the
82 // matrix shape. DWARF has no matrix tag, so distinguishing a matrix needs
83 // a new DINode flag analogous to FlagVector, set on the array, plus a way
84 // to carry column-major vs row-major traits. Array-of-vectors alone would
85 // not disambiguate a matrix from a genuine array of vectors. Once the
86 // frontend marks matrices, route them to a DebugTypeMatrix path here.
87 if (CT->isVector())
88 VectorTypes.push_back(CT);
89 else
90 ArrayTypes.push_back(CT);
91 } else if (CT->getTag() == dwarf::DW_TAG_structure_type ||
92 CT->getTag() == dwarf::DW_TAG_class_type ||
93 CT->getTag() == dwarf::DW_TAG_union_type) {
94 CompositeTypes.push_back(CT);
95 }
96 return;
97 }
98 const auto *DT = dyn_cast<DIDerivedType>(Ty);
99 if (DT && DT->getTag() == dwarf::DW_TAG_pointer_type)
100 PointerTypes.push_back(DT);
101 else if (DT && DT->getTag() == dwarf::DW_TAG_typedef)
102 TypedefTypes.push_back(DT);
103}
104
105enum : uint32_t {
106 NSDIFlagIsProtected = 1u << 0,
107 NSDIFlagIsPrivate = 1u << 1,
108 NSDIFlagIsPublic = NSDIFlagIsPrivate | NSDIFlagIsProtected,
109 NSDIFlagIsLocal = 1u << 2,
110 NSDIFlagIsDefinition = 1u << 3,
111 NSDIFlagFwdDecl = 1u << 4,
112 NSDIFlagArtificial = 1u << 5,
113 NSDIFlagExplicit = 1u << 6,
114 NSDIFlagPrototyped = 1u << 7,
115 NSDIFlagObjectPointer = 1u << 8,
116 NSDIFlagStaticMember = 1u << 9,
117 NSDIFlagIndirectVariable = 1u << 10,
118 NSDIFlagLValueReference = 1u << 11,
119 NSDIFlagRValueReference = 1u << 12,
120 NSDIFlagIsOptimized = 1u << 13,
121 NSDIFlagIsEnumClass = 1u << 14,
122 NSDIFlagTypePassByValue = 1u << 15,
123 NSDIFlagTypePassByReference = 1u << 16,
124 NSDIFlagUnknownPhysicalLayout = 1u << 17,
125};
126
127static uint32_t mapDIFlagsToNonSemantic(DINode::DIFlags DFlags) {
128 uint32_t Flags = 0;
129 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPublic)
130 Flags |= NSDIFlagIsPublic;
131 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagProtected)
132 Flags |= NSDIFlagIsProtected;
133 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPrivate)
134 Flags |= NSDIFlagIsPrivate;
135 if (DFlags & DINode::FlagFwdDecl)
136 Flags |= NSDIFlagFwdDecl;
137 if (DFlags & DINode::FlagArtificial)
138 Flags |= NSDIFlagArtificial;
139 if (DFlags & DINode::FlagExplicit)
140 Flags |= NSDIFlagExplicit;
141 if (DFlags & DINode::FlagPrototyped)
142 Flags |= NSDIFlagPrototyped;
143 if (DFlags & DINode::FlagObjectPointer)
144 Flags |= NSDIFlagObjectPointer;
145 if (DFlags & DINode::FlagStaticMember)
146 Flags |= NSDIFlagStaticMember;
147 if (DFlags & DINode::FlagLValueReference)
148 Flags |= NSDIFlagLValueReference;
149 if (DFlags & DINode::FlagRValueReference)
150 Flags |= NSDIFlagRValueReference;
151 if (DFlags & DINode::FlagTypePassByValue)
152 Flags |= NSDIFlagTypePassByValue;
153 if (DFlags & DINode::FlagTypePassByReference)
154 Flags |= NSDIFlagTypePassByReference;
155 if (DFlags & DINode::FlagEnumClass)
156 Flags |= NSDIFlagIsEnumClass;
157 return Flags;
158}
159
160static uint32_t transDebugFlags(const DINode *DN) {
161 uint32_t Flags = 0;
162 if (const auto *GV = dyn_cast<DIGlobalVariable>(DN)) {
163 if (GV->isLocalToUnit())
164 Flags |= NSDIFlagIsLocal;
165 if (GV->isDefinition())
166 Flags |= NSDIFlagIsDefinition;
167 }
168 if (const auto *SP = dyn_cast<DISubprogram>(DN)) {
169 if (SP->isLocalToUnit())
170 Flags |= NSDIFlagIsLocal;
171 if (SP->isOptimized())
172 Flags |= NSDIFlagIsOptimized;
173 if (SP->isDefinition())
174 Flags |= NSDIFlagIsDefinition;
175 Flags |= mapDIFlagsToNonSemantic(SP->getFlags());
176 }
177 if (DN->getTag() == dwarf::DW_TAG_reference_type)
178 Flags |= NSDIFlagLValueReference;
179 if (DN->getTag() == dwarf::DW_TAG_rvalue_reference_type)
180 Flags |= NSDIFlagRValueReference;
181 if (const auto *Ty = dyn_cast<DIType>(DN))
182 Flags |= mapDIFlagsToNonSemantic(Ty->getFlags());
183 if (const auto *LV = dyn_cast<DILocalVariable>(DN))
184 Flags |= mapDIFlagsToNonSemantic(LV->getFlags());
185 return Flags;
186}
187
188// Map a DWARF composite tag to a NonSemantic.Shader.DebugInfo Composite Type
189// value: Class 0, Structure 1, Union 2.
190static uint32_t mapCompositeTypeTag(unsigned Tag) {
191 switch (Tag) {
192 case dwarf::DW_TAG_class_type:
193 return 0;
194 case dwarf::DW_TAG_structure_type:
195 return 1;
196 case dwarf::DW_TAG_union_type:
197 return 2;
198 default:
199 reportFatalInternalError("unexpected DWARF composite tag " + Twine(Tag) +
200 ". Expecting 0, 1 or 2");
201 }
202}
203
204static const MachineInstr *
205findLastFunctionOpVariableDeclaration(const MachineFunction &MF,
207
208 // We iterate over the instructions to find the last OpVariable instruction if
209 // any. The following SPIRV rule is used to terminate the traversal earlier:
210 // SPIR-V 2.16.1, Function Structure: "All OpVariable instructions in a
211 // function must be in the first block in the function. These instructions,
212 // together with any intermixed OpLine and OpNoLine instructions, must be the
213 // first instructions in that block."
214 const MachineInstr *LastOpVariable = nullptr;
215 bool SeenOpVariable = false;
216 for (const MachineInstr &MI : MF.front()) {
217 if (MI.getOpcode() == SPIRV::OpVariable) {
218 SeenOpVariable = true;
219 if (!MAI.getSkipEmission(&MI))
220 LastOpVariable = &MI;
221 continue;
222 }
223
224 bool CanInterleaveWithOpVariable =
225 MI.getOpcode() == SPIRV::OpLine || MI.getOpcode() == SPIRV::OpNoLine;
226 if (SeenOpVariable && !CanInterleaveWithOpVariable &&
227 !MAI.getSkipEmission(&MI))
228 break;
229 }
230 return LastOpVariable;
231}
232
233} // namespace
234
237
238// Map DWARF source language codes to NonSemantic.Shader.DebugInfo.100 source
239// language codes. Values are from the SourceLanguage enum in the
240// NonSemantic.Shader.DebugInfo.100 specification, section 4.3.
241unsigned SPIRVNonSemanticDebugHandler::toNSDISrcLang(unsigned DwarfSrcLang) {
242 switch (DwarfSrcLang) {
243 case dwarf::DW_LANG_OpenCL:
244 return 3; // OpenCL_C
245 case dwarf::DW_LANG_OpenCL_CPP:
246 return 4; // OpenCL_CPP
247 case dwarf::DW_LANG_CPP_for_OpenCL:
248 return 6; // CPP_for_OpenCL
249 case dwarf::DW_LANG_GLSL:
250 return 2; // GLSL
251 case dwarf::DW_LANG_HLSL:
252 return 5; // HLSL
253 case dwarf::DW_LANG_SYCL:
254 return 7; // SYCL
255 case dwarf::DW_LANG_Zig:
256 return 12; // Zig
257 default:
258 return 0; // Unknown
259 }
260}
261
262// Collect distinct DILocations and DILocalVariables from LLVM IR.
263//
264// DILocations come from instruction debug locations and from the debug records
265// attached to them. DebugLine pre-emission and MIR lookups assume every
266// machine-instruction debug location already appeared here; a codegen-only
267// location would not be collected and emission will be skipped.
268//
269// DILocalVariables come from the DbgVariableRecords attached to instructions
270// and from the retained nodes of each DISubprogram. Retained nodes are needed
271// because a variable with no remaining debug record (e.g. optimized away) must
272// still get a DebugLocalVariable.
274 const Module &M, SetVector<const DILocation *> &Locations,
276 for (const Function &F : M) {
277 const DISubprogram *SP = F.getSubprogram();
278 if (!SP)
279 continue;
280 for (const MDNode *N : SP->getRetainedNodes())
281 if (const auto *LV = dyn_cast_or_null<DILocalVariable>(N))
282 LVs.insert(LV);
283 for (const Instruction &I : instructions(F)) {
284 if (const DILocation *DL = I.getDebugLoc().get())
285 Locations.insert(DL);
286 for (DbgRecord &DR : I.getDbgRecordRange()) {
287 if (const DILocation *DL = DR.getDebugLoc().get())
288 Locations.insert(DL);
289 if (const auto *DVR = dyn_cast<DbgVariableRecord>(&DR))
290 if (const DILocalVariable *LV = DVR->getVariable())
291 LVs.insert(LV);
292 }
293 }
294 }
295}
296
297// Insert \p S and its enclosing DILexicalBlock/DINamespace chain into \p Out,
298// parent before child, so single-pass emission never needs a forward
299// reference for the Parent operand.
302 // Walk up child-first, then insert in reverse to get parents in first.
304 while (S && !Out.contains(S) && isa<DILexicalBlock, DINamespace>(S)) {
305 Chain.push_back(S);
306 S = S->getScope();
307 }
308 Out.insert(Chain.rbegin(), Chain.rend());
309}
310
312 // The base class sets Asm = nullptr when the module has no compile units,
313 // and initializes lexical scope tracking otherwise.
315
316 if (!Asm)
317 return;
318
319 CompileUnits.clear();
320 BasicTypes.clear();
321 PointerTypes.clear();
322 SubroutineTypes.clear();
323 VectorTypes.clear();
324 ArrayTypes.clear();
325 CompositeTypes.clear();
326 TypedefTypes.clear();
327 SubprogramDeclarations.clear();
328 SubprogramDefinitions.clear();
329 UniqueDebugLocations.clear();
330 GlobalVariableDebugInfoMap.clear();
331 LocalVariables.clear();
332 DebugLocalVariableRegs.clear();
333 DebugExpressionRegs.clear();
334 LexicalBlocks.clear();
335 DebugScopeRegs.clear();
336 DebugInlinedAtRegs.clear();
337 ScopeToPathOpStringReg.clear();
338 DebugSourceRegByFileStr.clear();
339 OpStringContentCache.clear();
340 I32ConstantCache.clear();
341 DebugTypeFunctionCache.clear();
342 DebugOperationCache.clear();
343 DebugExpressionCache.clear();
344 GlobalDIEmitted = false;
345 GlobalNSDIEnabled = false;
346 CurrentMAI = nullptr;
347#ifndef NDEBUG
348 NonSemanticOpStringsSectionEmitted = false;
349#endif
350 CachedDebugInfoNoneReg = MCRegister();
351 CachedEmptyStringReg = MCRegister();
352 CachedOpTypeVoidReg = MCRegister();
353 CachedOpTypeInt32Reg = MCRegister();
354
355 // Collect compile-unit info: file paths and source languages.
356 for (const DICompileUnit *CU : M->debug_compile_units()) {
357 const DIFile *File = CU->getFile();
358 CompileUnitInfo Info;
359 Info.TheCU = CU;
360 if (sys::path::is_absolute(File->getFilename()))
361 Info.FilePath = File->getFilename();
362 else
363 sys::path::append(Info.FilePath, File->getDirectory(),
364 File->getFilename());
365 // getName() returns the language code regardless of whether the name is
366 // versioned. getUnversionedName() would assert on versioned names.
367 Info.SpirvSourceLanguage = toNSDISrcLang(CU->getSourceLanguage().getName());
368 CompileUnits.push_back(std::move(Info));
369 }
370
371 // Collect DWARF version from module flags. For CodeView modules there is no
372 // "Dwarf Version" flag; DwarfVersion remains 0, which is the correct value
373 // for the DebugCompilationUnit DWARF Version operand in that case.
374 if (const NamedMDNode *Flags = M->getNamedMetadata("llvm.module.flags")) {
375 for (const auto *Op : Flags->operands()) {
376 const MDOperand &NameOp = Op->getOperand(1);
377 if (NameOp.equalsStr("Dwarf Version"))
378 DwarfVersion =
380 cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
381 ->getSExtValue();
382 }
383 }
384
385 // Find all debug info types that may be referenced by NSDI instructions.
386 DebugInfoFinder Finder;
387 Finder.processModule(*M);
388 llvm::for_each(Finder.types(), [&](DIType *Ty) {
389 partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes, VectorTypes,
390 ArrayTypes, CompositeTypes, TypedefTypes);
391 });
392
393 for (const DISubprogram *SP : Finder.subprograms()) {
394 if (SP->isDefinition())
395 SubprogramDefinitions.push_back(SP);
396 else
397 SubprogramDeclarations.push_back(SP);
398 }
399
400 // Walk LLVM globals to map each DIGlobalVariable to its llvm::GlobalVariable.
402 for (const GlobalVariable &G : M->globals()) {
404 G.getDebugInfo(GVEs);
405 for (DIGlobalVariableExpression *GVE : GVEs) {
406 if (const DIGlobalVariable *GV = GVE->getVariable()) {
407 DIGVToLLVMGV.try_emplace(GV, &G);
408 }
409 }
410 }
411
412 for (const DIGlobalVariableExpression *GVE : Finder.global_variables()) {
413 const DIGlobalVariable *GV = GVE->getVariable();
414 const DIExpression *Expr = GVE->getExpression();
415 GlobalVariableDebugInfoMap.try_emplace(
416 GV, GlobalVariableDebugInfo{Expr, DIGVToLLVMGV.lookup(GV)});
417 }
418
419 collectDebugLocationsAndLocalVariables(*M, UniqueDebugLocations,
420 LocalVariables);
421
422 // DILexicalBlock and DINamespace scopes are lowered to DebugLexicalBlock.
423 // Collect them in parent-before-child order so they can be later emitted in a
424 // single pass.
425 for (const DIScope *S : Finder.scopes())
426 collectLexicalBlockChain(S, LexicalBlocks);
427}
428
431 if (CompileUnits.empty())
432 return;
433 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_non_semantic_info))
434 return;
435
436 // Add the extension to requirements so OpExtension is output.
437 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
438
439 // Add the NonSemantic.Shader.DebugInfo.100 entry to ExtInstSetMap so that
440 // outputOpExtInstImports() emits the OpExtInstImport instruction. Allocate a
441 // fresh result ID for it now; the same ID is used in emitExtInst() operands.
442 if (!MAI.ExtInstSetMap.count(NSSet))
443 MAI.ExtInstSetMap[NSSet] = MAI.getNextIDRegister();
444}
445
446void SPIRVNonSemanticDebugHandler::emitMCInst(MCInst &Inst) {
447 Asm->OutStreamer->emitInstruction(Inst, Asm->getSubtargetInfo());
448}
449
451SPIRVNonSemanticDebugHandler::emitOpString(StringRef S,
454 MCInst Inst;
455 Inst.setOpcode(SPIRV::OpString);
457 addStringImm(S, Inst);
458 emitMCInst(Inst);
459 return Reg;
460}
461
462MCRegister SPIRVNonSemanticDebugHandler::emitOpStringIfNew(
464#ifndef NDEBUG
465 assert(!NonSemanticOpStringsSectionEmitted &&
466 "emitOpStringIfNew is only valid while emitting SPIR-V section 7");
467#endif
468 auto [It, Inserted] = OpStringContentCache.try_emplace(S, MCRegister());
469 if (Inserted)
470 It->second = emitOpString(S, MAI);
471
472 return It->second;
473}
474
475MCRegister SPIRVNonSemanticDebugHandler::getCachedOpStringReg(StringRef S) {
476#ifndef NDEBUG
477 assert(NonSemanticOpStringsSectionEmitted &&
478 "getCachedOpStringReg requires emitNonSemanticDebugStrings() first");
479#endif
480 auto It = OpStringContentCache.find(S);
481 assert(It != OpStringContentCache.end() &&
482 "NSDI OpString missing from cache; emitNonSemanticDebugStrings must "
483 "cache every string used in section 10");
484 return It->second;
485}
486
487MCRegister SPIRVNonSemanticDebugHandler::emitAndCacheScopePathOpStringReg(
488 const DIScope *Scope, SPIRV::ModuleAnalysisInfo &MAI) {
489 auto [It, Inserted] = ScopeToPathOpStringReg.try_emplace(Scope, MCRegister());
490 if (Inserted)
491 It->second = emitOpStringIfNew(getDebugFullPath(Scope), MAI);
492 return It->second;
493}
494
495MCRegister SPIRVNonSemanticDebugHandler::getCachedScopePathOpStringReg(
496 const DIScope *Scope, bool UseEmptyPathIfNullScope) {
497 if (!Scope) {
498 assert(UseEmptyPathIfNullScope &&
499 "null scope path lookup requires UseEmptyPathIfNullScope");
500 assert(CachedEmptyStringReg.isValid() &&
501 "empty path OpString must be cached in emitNonSemanticDebugStrings");
502 return CachedEmptyStringReg;
503 }
504 auto It = ScopeToPathOpStringReg.find(Scope);
505 assert(It != ScopeToPathOpStringReg.end() &&
506 "path OpString must be cached in emitNonSemanticDebugStrings");
507 MCRegister FileStrReg = It->second;
508 assert(FileStrReg.isValid() && "path OpString id must be valid once cached");
509 return FileStrReg;
510}
511
512MCRegister SPIRVNonSemanticDebugHandler::emitOpConstantI32(
513 uint32_t Value, MCRegister I32TypeReg, SPIRV::ModuleAnalysisInfo &MAI) {
514 auto [It, Inserted] = I32ConstantCache.try_emplace(Value);
515 if (!Inserted)
516 return It->second;
517
518 MCRegister Reg = MAI.getNextIDRegister();
519 It->second = Reg;
520 MCInst Inst;
521 Inst.setOpcode(SPIRV::OpConstantI);
523 Inst.addOperand(MCOperand::createReg(I32TypeReg));
524 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Value)));
525 emitMCInst(Inst);
526 return Reg;
527}
528
529MCRegister SPIRVNonSemanticDebugHandler::emitExtInst(
530 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
531 MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
533 MCRegister Reg = MAI.getNextIDRegister();
534 MCInst Inst;
535 Inst.setOpcode(SPIRV::OpExtInst);
537 Inst.addOperand(MCOperand::createReg(VoidTypeReg));
538 Inst.addOperand(MCOperand::createReg(ExtInstSetReg));
539 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Opcode)));
540 for (MCRegister R : Operands)
542 emitMCInst(Inst);
543 return Reg;
544}
545
546MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugTypeFunction(
547 ArrayRef<MCRegister> Ops, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
549 auto [It, Inserted] =
550 DebugTypeFunctionCache.try_emplace(SmallVector<MCRegister, 8>(Ops));
551 if (!Inserted)
552 return It->second;
553
554 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeFunction,
555 VoidTypeReg, ExtInstSetReg, Ops, MAI);
556 It->second = Reg;
557 return Reg;
558}
559
560MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeVoidReg(
562 if (!CachedOpTypeVoidReg.isValid())
563 CachedOpTypeVoidReg = findOrEmitOpTypeVoid(MAI);
564 return CachedOpTypeVoidReg;
565}
566
567MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeInt32Reg(
569 if (!CachedOpTypeInt32Reg.isValid())
570 CachedOpTypeInt32Reg = findOrEmitOpTypeInt32(MAI);
571 return CachedOpTypeInt32Reg;
572}
573
574MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
576 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
577 if (MI->getOpcode() == SPIRV::OpTypeVoid)
578 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
579 }
580 MCRegister Reg = MAI.getNextIDRegister();
581 MCInst Inst;
582 Inst.setOpcode(SPIRV::OpTypeVoid);
584 emitMCInst(Inst);
585 return Reg;
586}
587
588MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
590 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
591 if (MI->getOpcode() == SPIRV::OpTypeInt &&
592 MI->getOperand(1).getImm() == 32 && MI->getOperand(2).getImm() == 0)
593 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
594 }
595 MCRegister Reg = MAI.getNextIDRegister();
596 MCInst Inst;
597 Inst.setOpcode(SPIRV::OpTypeInt);
599 Inst.addOperand(MCOperand::createImm(32)); // width
600 Inst.addOperand(MCOperand::createImm(0)); // signedness (unsigned)
601 emitMCInst(Inst);
602 return Reg;
603}
604
605std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
606 const DIDerivedType *PT, MCRegister ExtInstSetReg,
608 // A DWARF address space is required to determine the SPIR-V storage class.
609 // Skip pointer types that do not carry one.
610 if (!PT->getDWARFAddressSpace().has_value())
611 return std::nullopt;
612
613 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
614 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
615 MCRegister DebugTypePointerFlagsReg =
616 emitOpConstantI32(transDebugFlags(PT), I32TypeReg, MAI);
617
618 // For SPIR-V targets, Clang sets DwarfAddressSpace to the LLVM IR address
619 // space, which addressSpaceToStorageClass expects.
620 const auto &ST = static_cast<const SPIRVSubtarget &>(Asm->getSubtargetInfo());
621 MCRegister StorageClassReg = emitOpConstantI32(
622 addressSpaceToStorageClass(PT->getDWARFAddressSpace().value(), ST),
623 I32TypeReg, MAI);
624
625 if (const DIType *BaseTy = PT->getBaseType()) {
626 auto BaseIt = DebugScopeRegs.find(BaseTy);
627 if (BaseIt != DebugScopeRegs.end())
628 return emitExtInst(
629 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
630 ExtInstSetReg,
631 {BaseIt->second, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
632 // Unsupported type, no DebugType* id available.
633 return std::nullopt;
634 }
635 // No getBaseType() (typical for void*): use DebugInfoNone as Base Type,
636 // same as SPIRV-LLVM-Translator (see issue #109287 and the DISABLED
637 // spirv-val run in debug-type-pointer.ll). spirv-val may still reject this
638 // encoding; see https://github.com/KhronosGroup/SPIRV-Registry/pull/287.
639 return emitExtInst(
640 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg, ExtInstSetReg,
641 {CachedDebugInfoNoneReg, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
642}
643
644std::optional<MCRegister>
645SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
646 const DISubroutineType *ST, MCRegister ExtInstSetReg,
648 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
649 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
650 MCRegister DebugTypeFunctionFlagsReg =
651 emitOpConstantI32(transDebugFlags(ST), I32TypeReg, MAI);
652 DITypeArray TA = ST->getTypeArray();
654 Ops.push_back(DebugTypeFunctionFlagsReg);
655 // Empty DI type tuple: no explicit return or parameter slots (hand-written IR
656 // may use !{}). Emit void-only prototype. Same as SPIRV-LLVM-Translator when
657 // DISubroutineType::getTypeArray() has zero elements.
658 if (TA.empty()) {
659 Ops.push_back(VoidTypeReg);
660 } else {
661 for (unsigned I = 0, E = TA.size(); I != E; ++I) {
662 bool IsReturnType = (I == 0);
663 auto OptReg = mapDISignatureTypeToReg(TA[I], VoidTypeReg, IsReturnType);
664 // No emitted DebugType* id for this slot (e.g., pointer that
665 // was skipped due missing address space, etc.).
666 if (!OptReg)
667 return std::nullopt;
668 Ops.push_back(*OptReg);
669 }
670 }
671 return getOrEmitDebugTypeFunction(Ops, VoidTypeReg, ExtInstSetReg, MAI);
672}
673
674// Match SPIRV-LLVM-Translator's selection logic for the Parent operand.
675std::optional<MCRegister> SPIRVNonSemanticDebugHandler::resolveScope(
676 const DIScope *Scope, const DICompileUnit *FallbackCU) const {
677
679 return lookupOptReg(DebugScopeRegs, Scope);
680
681 // For a file, compile-unit, or absent scope, fall back to a compile unit.
682 if (FallbackCU)
683 return lookupOptReg(DebugScopeRegs, FallbackCU);
684
685 if (CompileUnits.empty())
686 return std::nullopt;
687
688 return lookupOptReg(DebugScopeRegs, CompileUnits[0].TheCU);
689}
690
691std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLexicalBlock(
692 const DIScope *S, MCRegister VoidTypeReg, MCRegister I32TypeReg,
693 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
695 "S must be a DILexicalBlock or DINamespace in emitDebugLexicalBlock");
696 auto ParentRegOpt = resolveScope(S->getScope());
697 if (!ParentRegOpt)
698 return std::nullopt;
699
700 MCRegister FileStrReg = getCachedScopePathOpStringReg(
701 S->getFile(), /*UseEmptyPathIfNullScope=*/true);
702 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
703 ExtInstSetReg, MAI);
704
706 if (const auto *LB = dyn_cast<DILexicalBlock>(S)) {
707 MCRegister LineReg = emitOpConstantI32(static_cast<uint32_t>(LB->getLine()),
708 I32TypeReg, MAI);
709 MCRegister ColReg = emitOpConstantI32(
710 static_cast<uint32_t>(LB->getColumn()), I32TypeReg, MAI);
711 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt};
712 } else {
713 const auto *NS = cast<DINamespace>(S);
714 // DINamespace carries no line/column info.
715 MCRegister LineReg = emitOpConstantI32(0, I32TypeReg, MAI);
716 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
717 MCRegister NameReg = getCachedOpStringReg(NS->getName());
718 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt, NameReg};
719 }
720
721 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLexicalBlock, VoidTypeReg,
722 ExtInstSetReg, Ops, MAI);
723}
724
725MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugInlinedAt(
726 const DILocation *IA, MCRegister VoidTypeReg, MCRegister I32TypeReg,
727 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
728 assert(IA && "IA must not be null in getOrEmitDebugInlinedAt");
729
730 if (MCRegister Cached = DebugInlinedAtRegs.lookup(IA))
731 return Cached;
732
733 auto ScopeRegOpt = resolveScope(IA->getScope());
734 if (!ScopeRegOpt)
735 return MCRegister();
736
737 MCRegister LineReg =
738 emitOpConstantI32(static_cast<uint32_t>(IA->getLine()), I32TypeReg, MAI);
739
740 SmallVector<MCRegister, 3> Ops{LineReg, *ScopeRegOpt};
741 // Recurse before building this instruction's operands so an outer
742 // inlined-at link is always available.
743 if (const DILocation *Outer = IA->getInlinedAt()) {
744 MCRegister OuterReg = getOrEmitDebugInlinedAt(
745 Outer, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
746 if (!OuterReg.isValid())
747 return MCRegister();
748 Ops.push_back(OuterReg);
749 }
750
751 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInlinedAt,
752 VoidTypeReg, ExtInstSetReg, Ops, MAI);
753 DebugInlinedAtRegs[IA] = Reg;
754 return Reg;
755}
756
757std::optional<MCRegister>
758SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
759 const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
760 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
761 assert(SP && "SP must not be null in emitDebugFunctionDeclaration");
762 assert(!SP->isDefinition() &&
763 "SP must not be a definition in emitDebugFunctionDeclaration");
764
765 // The IR verifier already enforces that this cannot be null.
766 const DISubroutineType *ST = SP->getType();
767
768 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
769 if (!FnTyRegOpt)
770 return std::nullopt;
771 MCRegister FnTyReg = *FnTyRegOpt;
772
773 auto ParentRegOpt = resolveScope(SP->getScope(), SP->getUnit());
774 if (!ParentRegOpt)
775 return std::nullopt;
776
777 MCRegister ParentReg = *ParentRegOpt;
778
779 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
780
781 MCRegister NameReg = getCachedOpStringReg(SP->getName());
782 MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
783 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
784 ExtInstSetReg, MAI);
785
786 MCRegister LineReg =
787 emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
788 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
789
790 uint32_t FlagsVal = transDebugFlags(SP);
791 // TODO: When composite scopes are DebugFunctionDeclaration parents (available
792 // in DebugScopeRegs), sync declaration Flags with SPIRV-LLVM-Translator.
793 FlagsVal &= ~NSDIFlagIsDefinition;
794 MCRegister FlagsReg = emitOpConstantI32(FlagsVal, I32TypeReg, MAI);
795
796 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
797 VoidTypeReg, ExtInstSetReg,
798 {NameReg, FnTyReg, SrcReg, LineReg, ColReg, ParentReg,
799 LinkageReg, FlagsReg},
800 MAI);
801}
802
803std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugFunction(
804 const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
805 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
806 assert(SP && "SP must not be null in emitDebugFunction");
807 assert(SP->isDefinition() && "SP must be a definition in emitDebugFunction");
808
809 const DISubroutineType *ST = SP->getType();
810 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
811 if (!FnTyRegOpt)
812 return std::nullopt;
813
814 auto ParentRegOpt = resolveScope(SP->getScope(), SP->getUnit());
815 if (!ParentRegOpt)
816 return std::nullopt;
817
818 MCRegister NameReg = getCachedOpStringReg(SP->getName());
819 MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
820 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
821 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
822 ExtInstSetReg, MAI);
823
824 MCRegister LineReg =
825 emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
826 // LLVM's DISubprogram has no column field but SPIR-V expects one in
827 // DebugFunction.
828 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
829 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(SP), I32TypeReg, MAI);
830 MCRegister ScopeLineReg = emitOpConstantI32(
831 static_cast<uint32_t>(SP->getScopeLine()), I32TypeReg, MAI);
832
833 SmallVector<MCRegister, 10> Ops = {NameReg, *FnTyRegOpt, SrcReg,
834 LineReg, ColReg, *ParentRegOpt,
835 LinkageReg, FlagsReg, ScopeLineReg};
836
837 if (const DISubprogram *Decl = SP->getDeclaration()) {
838 if (auto DeclRegOpt = lookupOptReg(DebugScopeRegs, Decl))
839 Ops.push_back(*DeclRegOpt);
840 }
841
842 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunction, VoidTypeReg,
843 ExtInstSetReg, Ops, MAI);
844}
845
846std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
847 const DIType *Ty, MCRegister VoidTypeReg, bool ReturnType) {
848 if (!Ty) {
849 if (ReturnType)
850 return VoidTypeReg;
851 assert(CachedDebugInfoNoneReg.isValid() &&
852 "DebugInfoNone must be emitted before DISubroutineType operands");
853 return CachedDebugInfoNoneReg;
854 }
855 return lookupOptReg(DebugScopeRegs, Ty);
856}
857
858// NonSemantic.Shader.DebugInfo.100 debug operation encodings
859// (section 4.5, "Debug Operations").
872
873static std::optional<NonSemanticDebugOp>
875 switch (DwarfOp) {
876 case dwarf::DW_OP_deref:
878 case dwarf::DW_OP_plus:
880 case dwarf::DW_OP_minus:
882 case dwarf::DW_OP_plus_uconst:
884 case dwarf::DW_OP_bit_piece:
886 case dwarf::DW_OP_swap:
888 case dwarf::DW_OP_xderef:
890 case dwarf::DW_OP_stack_value:
892 case dwarf::DW_OP_constu:
896 default:
897 return std::nullopt;
898 }
899}
900
901std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugOperation(
902 const DIExpression::ExprOperand &Op, MCRegister VoidTypeReg,
903 MCRegister I32TypeReg, MCRegister ExtInstSetReg,
905 std::optional<NonSemanticDebugOp> NSOp =
907 if (!NSOp)
908 return std::nullopt;
909
910 SmallVector<uint32_t, 3> Key{static_cast<uint32_t>(*NSOp)};
911 for (unsigned I = 0, E = Op.getNumArgs(); I != E; ++I) {
912 uint64_t Arg = Op.getArg(I);
913 if (!isUInt<32>(Arg))
914 return std::nullopt;
915 Key.push_back(static_cast<uint32_t>(Arg));
916 }
917
918 auto [It, Inserted] = DebugOperationCache.try_emplace(std::move(Key));
919 if (!Inserted)
920 return It->second;
921
923 for (uint32_t V : It->first)
924 Operands.push_back(emitOpConstantI32(V, I32TypeReg, MAI));
925 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugOperation,
926 VoidTypeReg, ExtInstSetReg, Operands, MAI);
927 It->second = Reg;
928 return Reg;
929}
930
931std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugExpression(
932 const DIExpression *Expr, MCRegister VoidTypeReg, MCRegister I32TypeReg,
933 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
934 assert(Expr && "Expr must not be null in emitDebugExpression");
935
936 SmallVector<MCRegister> OperationRegs;
937 for (const DIExpression::ExprOperand &Op : Expr->expr_ops()) {
938 std::optional<MCRegister> OpReg =
939 emitDebugOperation(Op, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
940 if (!OpReg)
941 return std::nullopt;
942 OperationRegs.push_back(*OpReg);
943 }
944
945 auto [It, Inserted] =
946 DebugExpressionCache.try_emplace(std::move(OperationRegs));
947 if (!Inserted)
948 return It->second;
949
950 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugExpression,
951 VoidTypeReg, ExtInstSetReg, It->first, MAI);
952 It->second = Reg;
953 return Reg;
954}
955
956std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugGlobalVariable(
957 const DIGlobalVariable *GV, const GlobalVariableDebugInfo &Info,
958 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
960 assert(GV && "GV must not be null in emitDebugGlobalVariable");
961
962 auto ParentRegOpt = resolveScope(GV->getScope());
963 if (!ParentRegOpt)
964 return std::nullopt;
965
966 MCRegister ParentReg = *ParentRegOpt;
967
968 // TyReg: DebugInfoNone when GV has no DI type (as done in
969 // SPIRV-LLVM-Translator). Declarations (isDefinition: false) can have null
970 // getType() while definitions must have a non-null one (enforced by the IR
971 // verifier).
972 MCRegister TyReg = CachedDebugInfoNoneReg;
973 if (const DIType *Ty = GV->getType()) {
974 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
975 if (!TyRegOpt)
976 return std::nullopt;
977 TyReg = *TyRegOpt;
978 }
979
980 std::optional<MCRegister> StaticMemberRegOpt;
981 if (const DIDerivedType *SM = GV->getStaticDataMemberDeclaration()) {
982 StaticMemberRegOpt = lookupOptReg(DebugScopeRegs, SM);
983 if (!StaticMemberRegOpt)
984 return std::nullopt;
985 }
986
987 MCRegister NameReg = getCachedOpStringReg(GV->getName());
988 MCRegister LinkageReg = getCachedOpStringReg(GV->getLinkageName());
989 MCRegister FileStrReg = getCachedScopePathOpStringReg(
990 GV->getFile(), /*UseEmptyPathIfNullScope=*/true);
991 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
992 ExtInstSetReg, MAI);
993
994 MCRegister LineReg =
995 emitOpConstantI32(static_cast<uint32_t>(GV->getLine()), I32TypeReg, MAI);
996 // DIGlobalVariable or DIGlobalVariableExpression metadata carry no column
997 // field. Column is hardcoded to 0 (because it can't be determined), matching
998 // SPIRV-LLVM-Translator.
999 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1000
1001 // Variable: @g OpVariable id when !dbg matches; else a DebugExpression for
1002 // the GVE init value when no @g exists and the expression is non-empty; else
1003 // DebugInfoNone. As per spec, the DebugExpression must contain the constant
1004 // value of the variable that was optimized out. An empty expression contains
1005 // no value, so we emit DebugInfoNone instead.
1006 MCRegister VariableReg = CachedDebugInfoNoneReg;
1007 if (const GlobalVariable *LLVMGV = Info.LLVMGV) {
1008 MCRegister GVReg = MAI.getGlobalObjReg(LLVMGV);
1009 if (GVReg.isValid())
1010 VariableReg = GVReg;
1011 } else if (Info.Expr && Info.Expr->getNumElements() != 0) {
1012 if (auto ExprReg = emitDebugExpression(Info.Expr, VoidTypeReg, I32TypeReg,
1013 ExtInstSetReg, MAI))
1014 VariableReg = *ExprReg;
1015 }
1016
1017 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(GV), I32TypeReg, MAI);
1018
1019 SmallVector<MCRegister, 10> Ops = {NameReg, TyReg, SrcReg,
1020 LineReg, ColReg, ParentReg,
1021 LinkageReg, VariableReg, FlagsReg};
1022
1023 if (StaticMemberRegOpt)
1024 Ops.push_back(*StaticMemberRegOpt);
1025
1026 return emitExtInst(SPIRV::NonSemanticExtInst::DebugGlobalVariable,
1027 VoidTypeReg, ExtInstSetReg, Ops, MAI);
1028}
1029
1030std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLocalVariable(
1031 const DILocalVariable *LV, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1032 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1033 assert(LV && "LV must not be null in emitDebugLocalVariable");
1034
1035 auto ParentRegOpt = resolveScope(LV->getScope());
1036 if (!ParentRegOpt)
1037 return std::nullopt;
1038
1039 MCRegister TyReg = CachedDebugInfoNoneReg;
1040 if (const DIType *Ty = LV->getType()) {
1041 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1042 if (!TyRegOpt)
1043 return std::nullopt;
1044 TyReg = *TyRegOpt;
1045 }
1046
1047 MCRegister NameReg = getCachedOpStringReg(LV->getName());
1048 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1049 LV->getFile(), /*UseEmptyPathIfNullScope=*/true);
1050 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1051 ExtInstSetReg, MAI);
1052 MCRegister LineReg =
1053 emitOpConstantI32(static_cast<uint32_t>(LV->getLine()), I32TypeReg, MAI);
1054 // DILocalVariable has no column field. Column is hardcoded to 0.
1055 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1056 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(LV), I32TypeReg, MAI);
1057
1058 SmallVector<MCRegister, 8> Ops = {NameReg, TyReg, SrcReg, LineReg,
1059 ColReg, *ParentRegOpt, FlagsReg};
1060 if (unsigned Arg = LV->getArg())
1061 Ops.push_back(emitOpConstantI32(Arg, I32TypeReg, MAI));
1062
1063 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLocalVariable, VoidTypeReg,
1064 ExtInstSetReg, Ops, MAI);
1065}
1066
1067std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
1068 const DICompositeType *VT, MCRegister ExtInstSetReg,
1070 const auto *BaseTy = dyn_cast_or_null<DIBasicType>(VT->getBaseType());
1071 if (!BaseTy)
1072 return std::nullopt;
1073 auto BTIt = DebugScopeRegs.find(BaseTy);
1074 if (BTIt == DebugScopeRegs.end())
1075 return std::nullopt;
1076
1077 // DebugTypeVector models only 1D vectors (multi-subrange types cannot be
1078 // encoded).
1079 DINodeArray Elements = VT->getElements();
1080 if (Elements.size() != 1)
1081 return std::nullopt;
1082 const auto *SR = cast<DISubrange>(Elements[0]);
1083 const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount());
1084 if (!CI)
1085 return std::nullopt;
1086
1087 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1088 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1089 MCRegister CountReg = emitOpConstantI32(
1090 static_cast<uint32_t>(CI->getZExtValue()), I32TypeReg, MAI);
1091 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeVector, VoidTypeReg,
1092 ExtInstSetReg, {BTIt->second, CountReg}, MAI);
1093}
1094
1095std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeArray(
1096 const DICompositeType *AT, MCRegister ExtInstSetReg,
1098 // The element (base) type must already be in DebugScopeRegs. Unlike
1099 // DebugTypeVector, the element may be any debug type, not only a basic type.
1100 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, AT->getBaseType());
1101 if (!BaseRegOpt)
1102 return std::nullopt;
1103
1104 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1105 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1106
1108 Ops.push_back(*BaseRegOpt);
1109
1110 // One component count per DISubrange, in DWARF subrange order. Emit 0 for
1111 // counts that are not a compile-time constant (dynamic arrays). This matches
1112 // OpTypeRuntimeArray.
1113 for (const DINode *Element : AT->getElements()) {
1114 const auto *SR = dyn_cast<DISubrange>(Element);
1115 if (!SR)
1116 continue;
1117 // A DIVariable count (a variable-length array) is not a ConstantInt, so it
1118 // maps to 0 here. DebugTypeArray also allows a DebugLocalVariable or
1119 // DebugGlobalVariable id for it, but no frontend we target emits one. A
1120 // constant wider than 32 bits maps to 0 too, since the count operand is a
1121 // 32-bit OpConstant and such an array cannot occur in a shader.
1122 uint32_t Count = 0;
1123 if (const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount())) {
1124 const APInt &Value = CI->getValue();
1125 if (Value.getActiveBits() <= 32)
1126 Count = static_cast<uint32_t>(Value.getZExtValue());
1127 }
1128 Ops.push_back(emitOpConstantI32(Count, I32TypeReg, MAI));
1129 }
1130
1131 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeArray, VoidTypeReg,
1132 ExtInstSetReg, Ops, MAI);
1133}
1134
1135std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeMember(
1136 const DIDerivedType *M, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1137 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1138 // The member type must already be in DebugScopeRegs.
1139 auto TyRegOpt = lookupOptReg(DebugScopeRegs, M->getBaseType());
1140 if (!TyRegOpt)
1141 return std::nullopt;
1142
1143 if (!isUInt<32>(M->getOffsetInBits()) || !isUInt<32>(M->getSizeInBits()))
1144 return std::nullopt;
1145
1146 MCRegister NameReg = getCachedOpStringReg(M->getName());
1147 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1148 M->getFile(), /*UseEmptyPathIfNullScope=*/true);
1149 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1150 ExtInstSetReg, MAI);
1151 MCRegister LineReg =
1152 emitOpConstantI32(static_cast<uint32_t>(M->getLine()), I32TypeReg, MAI);
1153
1154 // DIDerivedType members carry no column, so emit 0.
1155 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1156 MCRegister OffsetReg = emitOpConstantI32(
1157 static_cast<uint32_t>(M->getOffsetInBits()), I32TypeReg, MAI);
1158 MCRegister SizeReg = emitOpConstantI32(
1159 static_cast<uint32_t>(M->getSizeInBits()), I32TypeReg, MAI);
1160 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(M), I32TypeReg, MAI);
1161
1162 // In NonSemantic.Shader.DebugInfo a DebugTypeMember has no Parent operand:
1163 // only the composite references its members. This is by design, it drops the
1164 // Parent that OpenCL.DebugInfo.100 had, and it avoids a composite/member
1165 // reference cycle.
1166 //
1167 // FIXME: Static members are not handled yet: their constant initializer is
1168 // available but is not emitted as the optional Value operand, and under DWARF
1169 // 5 a static member is tagged DW_TAG_variable, which the caller's member loop
1170 // skips.
1171 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeMember, VoidTypeReg,
1172 ExtInstSetReg,
1173 {NameReg, *TyRegOpt, SrcReg, LineReg, ColReg, OffsetReg,
1174 SizeReg, FlagsReg},
1175 MAI);
1176}
1177
1178std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeComposite(
1179 const DICompositeType *CT, ArrayRef<MCRegister> MemberRegs,
1180 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
1182 auto ParentRegOpt = resolveScope(CT->getScope());
1183 if (!ParentRegOpt)
1184 return std::nullopt;
1185
1186 if (!isUInt<32>(CT->getSizeInBits()))
1187 return std::nullopt;
1188
1189 MCRegister NameReg = getCachedOpStringReg(CT->getName());
1190 MCRegister LinkageReg = getCachedOpStringReg(CT->getIdentifier());
1191 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1192 CT->getFile(), /*UseEmptyPathIfNullScope=*/true);
1193 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1194 ExtInstSetReg, MAI);
1195
1196 MCRegister TagReg =
1197 emitOpConstantI32(mapCompositeTypeTag(CT->getTag()), I32TypeReg, MAI);
1198 MCRegister LineReg =
1199 emitOpConstantI32(static_cast<uint32_t>(CT->getLine()), I32TypeReg, MAI);
1200 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1201
1202 // A forward declaration has no known size or members: Size is DebugInfoNone.
1203 MCRegister SizeReg = CachedDebugInfoNoneReg;
1204 if (!CT->isForwardDecl())
1205 SizeReg = emitOpConstantI32(static_cast<uint32_t>(CT->getSizeInBits()),
1206 I32TypeReg, MAI);
1207
1208 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(CT), I32TypeReg, MAI);
1209
1210 SmallVector<MCRegister> Ops = {NameReg, TagReg, SrcReg,
1211 LineReg, ColReg, *ParentRegOpt,
1212 LinkageReg, SizeReg, FlagsReg};
1213 Ops.append(MemberRegs.begin(), MemberRegs.end());
1214 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeComposite, VoidTypeReg,
1215 ExtInstSetReg, Ops, MAI);
1216}
1217
1218std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypedef(
1219 const DIDerivedType *TD, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1220 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1221 // The underlying (base) type must already be in DebugScopeRegs.
1222 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, TD->getBaseType());
1223 if (!BaseRegOpt)
1224 return std::nullopt;
1225
1226 MCRegister NameReg = getCachedOpStringReg(TD->getName());
1227 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1228 TD->getFile(), /*UseEmptyPathIfNullScope=*/true);
1229 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1230 ExtInstSetReg, MAI);
1231 MCRegister LineReg =
1232 emitOpConstantI32(static_cast<uint32_t>(TD->getLine()), I32TypeReg, MAI);
1233 // DIDerivedType typedefs carry no column, so emit 0.
1234 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1235
1236 // Parent must be a lexical scope. Valid NSDI lexical scopes are
1237 // DebugCompilationUnit, DebugFunction, DebugLexicalBlock, or
1238 // DebugTypeComposite.
1239 auto ParentRegOpt = resolveScope(TD->getScope());
1240 if (!ParentRegOpt)
1241 return std::nullopt;
1242 MCRegister ParentReg = *ParentRegOpt;
1243
1244 return emitExtInst(
1245 SPIRV::NonSemanticExtInst::DebugTypedef, VoidTypeReg, ExtInstSetReg,
1246 {NameReg, *BaseRegOpt, SrcReg, LineReg, ColReg, ParentReg}, MAI);
1247}
1248
1251 if (CompileUnits.empty())
1252 return;
1253 // Check that prepareModuleOutput() registered the extended instruction set.
1254 // If the subtarget does not support the extension, neither strings nor ext
1255 // insts are emitted.
1256 if (!MAI.getExtInstSetReg(NSSet).isValid())
1257 return;
1258
1259 for (const CompileUnitInfo &Info : CompileUnits) {
1260 if (Info.TheCU) {
1261 MCRegister PathReg = emitOpStringIfNew(Info.FilePath, MAI);
1262 ScopeToPathOpStringReg[Info.TheCU] = PathReg;
1263 if (const DIFile *F = Info.TheCU->getFile())
1264 ScopeToPathOpStringReg[F] = PathReg;
1265 }
1266 }
1267
1268 for (const DIBasicType *BT : BasicTypes)
1269 emitOpStringIfNew(BT->getName(), MAI);
1270
1272 SubprogramDeclarations, SubprogramDefinitions)) {
1273 emitOpStringIfNew(SP->getName(), MAI);
1274 emitOpStringIfNew(SP->getLinkageName(), MAI);
1275 emitAndCacheScopePathOpStringReg(SP, MAI);
1276 }
1277
1278 // Cache the OpStrings each DebugTypeComposite and its DebugTypeMembers use:
1279 // the composite name, identifier (linkage name), and path, plus each member
1280 // name and path.
1281 for (const DICompositeType *CT : CompositeTypes) {
1282 emitOpStringIfNew(CT->getName(), MAI);
1283 emitOpStringIfNew(CT->getIdentifier(), MAI);
1284 emitAndCacheScopePathOpStringReg(CT->getFile(), MAI);
1285 for (const DINode *Element : CT->getElements()) {
1286 const auto *M = dyn_cast<DIDerivedType>(Element);
1287 if (!M || M->getTag() != dwarf::DW_TAG_member)
1288 continue;
1289 emitOpStringIfNew(M->getName(), MAI);
1290 emitAndCacheScopePathOpStringReg(M->getFile(), MAI);
1291 }
1292 }
1293
1294 // Cache the name and path OpStrings each DebugTypedef uses.
1295 for (const DIDerivedType *TD : TypedefTypes) {
1296 emitOpStringIfNew(TD->getName(), MAI);
1297 emitAndCacheScopePathOpStringReg(TD->getFile(), MAI);
1298 }
1299
1300 for (const auto &[GV, _] : GlobalVariableDebugInfoMap) {
1301 emitOpStringIfNew(GV->getName(), MAI);
1302 emitOpStringIfNew(GV->getLinkageName(), MAI);
1303 emitAndCacheScopePathOpStringReg(GV->getFile(), MAI);
1304 }
1305
1306 for (const DILocalVariable *LV : LocalVariables) {
1307 emitOpStringIfNew(LV->getName(), MAI);
1308 emitAndCacheScopePathOpStringReg(LV->getFile(), MAI);
1309 }
1310
1311 // Cache the path OpString each DebugLexicalBlock uses (source file), plus
1312 // the Name OpString for the DINamespace case.
1313 for (const DIScope *S : LexicalBlocks) {
1314 emitAndCacheScopePathOpStringReg(S->getFile(), MAI);
1315 if (const auto *NS = dyn_cast<DINamespace>(S))
1316 emitOpStringIfNew(NS->getName(), MAI);
1317 }
1318
1319 for (const DILocation *DL : UniqueDebugLocations)
1320 emitAndCacheScopePathOpStringReg(DL->getScope(), MAI);
1321
1322 CachedEmptyStringReg = emitOpStringIfNew("", MAI);
1323
1324#ifndef NDEBUG
1325 NonSemanticOpStringsSectionEmitted = true;
1326#endif
1327}
1328
1329void SPIRVNonSemanticDebugHandler::emitDebugFunctionDefinition(
1330 MCRegister DebugFunctionReg, MCRegister OpFunctionReg,
1332 assert(DebugFunctionReg.isValid() && OpFunctionReg.isValid() &&
1333 "DebugFunctionDefinition operands must be valid");
1334 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1335 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1336 emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDefinition, VoidTypeReg,
1337 ExtInstSetReg, {DebugFunctionReg, OpFunctionReg}, MAI);
1338}
1339
1340void SPIRVNonSemanticDebugHandler::resetPerFunctionDebugState() {
1341 CurrentMF = nullptr;
1342 LastFunctionOpVariable = nullptr;
1343 DebugFunctionDefinitionEmitted = false;
1344 LastLineMI = nullptr;
1345 LastScopeMI = nullptr;
1346}
1347
1348void SPIRVNonSemanticDebugHandler::preparePerFunctionDebug(
1349 const MachineFunction *MF) {
1350 resetPerFunctionDebugState();
1351 if (!GlobalNSDIEnabled || !CurrentMAI)
1352 return;
1353
1354 CurrentMF = MF;
1355
1356 if (MF->getFunction()
1358 .isValid())
1359 return;
1360
1361 const DISubprogram *SP = MF->getFunction().getSubprogram();
1362 if (!SP || !SP->isDefinition())
1363 return;
1364
1365 // DebugFunctionDefinition is emitted after the last function-level
1366 // OpVariable. If there are none, it is emitted after the entry OpLabel.
1367 LastFunctionOpVariable =
1368 findLastFunctionOpVariableDeclaration(*MF, *CurrentMAI);
1369}
1370
1371void SPIRVNonSemanticDebugHandler::tryEmitDebugFunctionDefinition(
1373 if (DebugFunctionDefinitionEmitted || !GlobalNSDIEnabled)
1374 return;
1375
1376 assert(CurrentMF && "no current MachineFunction");
1377 const Function &F = CurrentMF->getFunction();
1378 const DISubprogram *SP = F.getSubprogram();
1379 if (!SP || !SP->isDefinition())
1380 return;
1381
1382 auto DFIt = DebugScopeRegs.find(SP);
1383 if (DFIt == DebugScopeRegs.end())
1384 return;
1385
1386 MCRegister OpFunctionReg = MAI.getGlobalObjReg(&F);
1387 if (!OpFunctionReg.isValid())
1388 return;
1389
1390 emitDebugFunctionDefinition(DFIt->second, OpFunctionReg, MAI);
1391 DebugFunctionDefinitionEmitted = true;
1392}
1393
1395 const MachineFunction *MF) {
1396 preparePerFunctionDebug(MF);
1397}
1398
1400 (void)MF;
1401 resetPerFunctionDebugState();
1402}
1403
1405 assert(CurMI == nullptr && "CurMI must be null");
1406 CurMI = MI;
1407
1408 if (!DebugFunctionDefinitionEmitted)
1409 return;
1410
1411 std::optional<const MachineInstr *> Target = resolveDebugLocTarget(MI);
1412 if (!Target)
1413 return;
1414
1415 emitDebugScopeForInstruction(*Target);
1416 emitDebugLineForInstruction(*Target);
1417
1418 emitDebugDeclare(MI);
1419}
1420
1421// The register that holds the variable's address in \p MI, or std::nullopt
1422// when \p MI is not a declare this backend can describe.
1423//
1424// The spec requires DebugDeclare's Variable operand to be "the <id> of an
1425// OpVariable instruction that defines the local variable". MIR has no
1426// DBG_DECLARE, so what this looks for is an indirect DBG_VALUE whose location
1427// register an OpVariable defines.
1428static std::optional<Register>
1430 // #dbg_declare is an indirect DBG_VALUE in MIR; #dbg_value is normally a
1431 // direct one except for the variadic case.
1432 if (!MI.isIndirectDebugValue())
1433 return std::nullopt;
1434
1435 // A variadic #dbg_value becomes DBG_VALUE $noreg, 0, ... which is indirect
1436 // too, and $noreg is not virtual.
1437 Register LocReg = MI.getDebugOperand(0).getReg();
1438 if (!LocReg.isVirtual())
1439 return std::nullopt;
1440
1441 // DebugDeclare can only encode the address of an OpVariable.
1442 // Other legitimate #dbg_declare cannot be encoded.
1443 // Examples: an access chain for a field, an OpFunctionParameter for a byval
1444 // argument, or a module-scope constant for a null or fixed address.
1445
1446 // LocReg may also have no def at all: erasing dead storage leaves the
1447 // DBG_VALUE pointing at an undefined register. MachineVerifier permits that
1448 // because LiveDebugVariables normally clears it, but this pipeline has no
1449 // register allocation, so LiveDebugVariables never runs.
1450 const MachineInstr *Def = MI.getMF()->getRegInfo().getUniqueVRegDef(LocReg);
1451 if (!Def || Def->getOpcode() != SPIRV::OpVariable)
1452 return std::nullopt;
1453
1454 return LocReg;
1455}
1456
1457void SPIRVNonSemanticDebugHandler::emitDebugDeclare(const MachineInstr *MI) {
1458 assert(DebugFunctionDefinitionEmitted &&
1459 "DebugFunctionDefinition must be emitted");
1460 assert(CurrentMAI && "CurrentMAI must be set");
1461
1462 std::optional<Register> LocReg = getDebugDeclareStorageReg(*MI);
1463 if (!LocReg)
1464 return;
1465
1466 auto VarRegOpt = lookupOptReg(DebugLocalVariableRegs, MI->getDebugVariable());
1467 if (!VarRegOpt)
1468 return;
1469
1470 auto ExprRegOpt = lookupOptReg(DebugExpressionRegs, MI->getDebugExpression());
1471 if (!ExprRegOpt)
1472 return;
1473
1474 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1475 MCRegister StorageReg = MAI.getRegisterAlias(MI->getMF(), *LocReg);
1476 if (!StorageReg.isValid())
1477 return;
1478
1479 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1480 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1481 emitExtInst(SPIRV::NonSemanticExtInst::DebugDeclare, VoidTypeReg,
1482 ExtInstSetReg, {*VarRegOpt, StorageReg, *ExprRegOpt}, MAI);
1483}
1484
1485static bool isMergeInstruction(unsigned Opcode) {
1486 return Opcode == SPIRV::OpSelectionMerge || Opcode == SPIRV::OpLoopMerge ||
1487 Opcode == SPIRV::OpLoopControlINTEL;
1488}
1489
1492 if (MAI.getSkipEmission(MI))
1493 return false;
1494 switch (MI->getOpcode()) {
1495 case SPIRV::OpFunction:
1496 case SPIRV::OpFunctionParameter:
1497 case SPIRV::OpFunctionEnd:
1498 case SPIRV::OpLabel:
1499 case SPIRV::OpPhi:
1500 return false;
1501 default:
1502 return true;
1503 }
1504}
1505
1506static const MachineInstr *
1508 SPIRV::ModuleAnalysisInfo &MAI, bool Forward) {
1509 for (const MachineInstr *Adj = Forward ? MI->getNextNode()
1510 : MI->getPrevNode();
1511 Adj; Adj = Forward ? Adj->getNextNode() : Adj->getPrevNode()) {
1512 if (MAI.getSkipEmission(Adj))
1513 continue;
1514 return Adj;
1515 }
1516 return nullptr;
1517}
1518
1519std::optional<const MachineInstr *>
1520SPIRVNonSemanticDebugHandler::resolveDebugLocTarget(const MachineInstr *MI) {
1521 assert(CurrentMAI && "CurrentMAI must be set");
1522 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1523
1524 // Structural opcodes don't require a DebugLine/DebugScope, other opcodes
1525 // might have already been emitted in the module scope.
1526 if (!isDebugLocTarget(MI, MAI))
1527 return std::nullopt;
1528
1529 // DebugLine/DebugScope can be emitted before a merge instruction, but not
1530 // after it (nothing may sit between the merge and its terminator). We can
1531 // use either the merge's or the terminator's debug info; we emit the
1532 // terminator's one.
1533 const MachineInstr *Prev = findAdjacentEmittedInstruction(MI, MAI, false);
1534 if (Prev && isMergeInstruction(Prev->getOpcode()))
1535 return std::nullopt;
1536
1537 if (isMergeInstruction(MI->getOpcode())) {
1538 // Use the terminator's debug info; when we reach it later, the check
1539 // above skips it.
1540 MI = findAdjacentEmittedInstruction(MI, MAI, true);
1541 assert(MI && "Merge instruction must be followed by a terminator");
1542 }
1543
1544 return MI;
1545}
1546
1547void SPIRVNonSemanticDebugHandler::emitDebugScopeForInstruction(
1548 const MachineInstr *MI) {
1549 assert(DebugFunctionDefinitionEmitted &&
1550 "DebugFunctionDefinition must be emitted");
1551 assert(CurrentMAI && "CurrentMAI must be set");
1552
1553 // The region is implicitly closed at each basic block boundary, so a
1554 // LastScopeMI from another block must be dropped before it is read below:
1555 // the new block needs its own DebugScope, and has no region left to close.
1556 if (LastScopeMI && MI->getParent() != LastScopeMI->getParent())
1557 LastScopeMI = nullptr;
1558
1559 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1560 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1561 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1562
1563 const DILocation *CurDL = MI->getDebugLoc().get();
1564 if (!CurDL) {
1565 // No location for the current instruction.
1566 if (LastScopeMI) {
1567 // Close the current DebugScope region.
1568 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoScope, VoidTypeReg,
1569 ExtInstSetReg, {}, MAI);
1570 LastScopeMI = nullptr;
1571 }
1572 return;
1573 }
1574
1575 const DIScope *CurScope = CurDL->getScope();
1576 const DILocation *CurInlinedAt = CurDL->getInlinedAt();
1577
1578 if (LastScopeMI) {
1579 const DILocation *LastDL = LastScopeMI->getDebugLoc().get();
1580 if (LastDL->getScope() == CurScope &&
1581 LastDL->getInlinedAt() == CurInlinedAt)
1582 return;
1583 }
1584
1585 auto CurScopeRegOpt = resolveScope(CurScope);
1586 if (!CurScopeRegOpt)
1587 return;
1588
1589 SmallVector<MCRegister, 2> Ops{*CurScopeRegOpt};
1590 if (CurInlinedAt) {
1591 // If the global emission did not include this inlined-at case, we skip it.
1592 MCRegister InlinedReg = DebugInlinedAtRegs.lookup(CurInlinedAt);
1593 if (!InlinedReg.isValid())
1594 return;
1595 Ops.push_back(InlinedReg);
1596 }
1597
1598 // A new DebugScope region is needed.
1599 emitExtInst(SPIRV::NonSemanticExtInst::DebugScope, VoidTypeReg, ExtInstSetReg,
1600 Ops, MAI);
1601
1602 LastScopeMI = MI;
1603}
1604
1605void SPIRVNonSemanticDebugHandler::emitDebugLineForInstruction(
1606 const MachineInstr *MI) {
1607 assert(DebugFunctionDefinitionEmitted &&
1608 "DebugFunctionDefinition must be emitted");
1609 assert(CurrentMAI && "CurrentMAI must be set");
1610
1611 // The region is implicitly closed at each basic block boundary, so a
1612 // LastLineMI from another block must be dropped before it is read below:
1613 // the new block needs its own DebugLine, and has no region left to close.
1614 if (LastLineMI && MI->getParent() != LastLineMI->getParent())
1615 LastLineMI = nullptr;
1616
1617 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1618 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1619 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1620
1621 const DILocation *DL = MI->getDebugLoc().get();
1622 if (!DL) {
1623 // No location for the current instruction
1624 if (LastLineMI) {
1625 // Close the current DebugLine region.
1626 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoLine, VoidTypeReg,
1627 ExtInstSetReg, {}, MAI);
1628 LastLineMI = nullptr;
1629 }
1630 // No DebugLine region to close.
1631 return;
1632 }
1633
1634 // At this point, there is a location for the current instruction.
1635 // If it matches the last emitted DebugLine, no new DebugLine region is
1636 // needed. Otherwise, emit a new DebugLine region and update LastLineMI.
1637
1638 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1639 DL->getScope(), /*UseEmptyPathIfNullScope=*/true);
1640 unsigned Line = DL->getLine();
1641 unsigned Col = DL->getColumn();
1642
1643 MCRegister SrcReg = DebugSourceRegByFileStr.lookup(FileStrReg.id());
1644 MCRegister LineReg = I32ConstantCache.lookup(Line);
1645 MCRegister ColStartReg = I32ConstantCache.lookup(Col);
1646 MCRegister ColEndReg = I32ConstantCache.lookup(Col + 1);
1647
1648 // The elements of each collected DILocation (DebugSource, line/column
1649 // constants) are pre-emitted from LLVM-IR instruction !dbg attachments and
1650 // debug-program records; MIR is expected to reuse those same locations (or
1651 // carry none). A lookup miss means codegen attached a source position whose
1652 // elements were never pre-emitted, and debug-line emission is skipped.
1653 if (!SrcReg.isValid() || !LineReg.isValid() || !ColStartReg.isValid() ||
1654 !ColEndReg.isValid())
1655 return;
1656
1657 // Current location matches the last emitted DebugLine region.
1658 if (LastLineMI && MI->getDebugLoc() == LastLineMI->getDebugLoc())
1659 return;
1660
1661 // A new DebugLine region is needed.
1662 emitExtInst(SPIRV::NonSemanticExtInst::DebugLine, VoidTypeReg, ExtInstSetReg,
1663 {SrcReg, LineReg, LineReg, ColStartReg, ColEndReg}, MAI);
1664
1665 LastLineMI = MI;
1666}
1667
1669 const MachineInstr *MI = CurMI;
1670 CurMI = nullptr;
1671
1672 if (!MI || !GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
1673 return;
1674
1675 if (MI != LastFunctionOpVariable)
1676 return;
1677
1678 // If this is the last function-level OpVariable, emit the
1679 // DebugFunctionDefinition. Otherwise, we had already done it before right
1680 // after the OpLabel (see notifyEntryLabelEmitted).
1681 assert(CurrentMAI && "CurrentMAI must be set");
1682 tryEmitDebugFunctionDefinition(*CurrentMAI);
1683}
1684
1686 const MachineFunction &MF) {
1687 if (!GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
1688 return;
1689
1690 assert(CurrentMF == &MF &&
1691 "notification does not match the current MachineFunction");
1692
1693 if (LastFunctionOpVariable)
1694 return;
1695
1696 // If there are no function-level OpVariables, emit the
1697 // DebugFunctionDefinition. Otherwise, DebugFunctionDefinition is emitted
1698 // after the last OpVariable (see endInstruction).
1699 tryEmitDebugFunctionDefinition(*CurrentMAI);
1700}
1701
1702void SPIRVNonSemanticDebugHandler::collectDebugExpressions(
1704 MachineModuleInfo *ModuleInfo = Asm->MMI;
1705 assert(ModuleInfo && "MachineModuleInfo must be set during module output");
1706
1707 for (const Function &F : *ModuleInfo->getModule()) {
1708 const MachineFunction *MF = ModuleInfo->getMachineFunction(F);
1709 if (!MF)
1710 continue;
1711 for (const MachineBasicBlock &MBB : *MF)
1712 for (const MachineInstr &MI : MBB)
1713 if (MI.isDebugValueLike())
1714 Out.insert(MI.getDebugExpression());
1715 }
1716}
1717
1720 if (GlobalDIEmitted)
1721 return;
1722
1723 GlobalDIEmitted = true;
1724
1725 if (CompileUnits.empty()) {
1726 GlobalNSDIEnabled = false;
1727 return;
1728 }
1729
1730 // Retrieve the ext inst set register allocated by prepareModuleOutput().
1731 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1732 if (!ExtInstSetReg.isValid()) {
1733 GlobalNSDIEnabled = false;
1734 return;
1735 }
1736
1737#ifndef NDEBUG
1738 assert(NonSemanticOpStringsSectionEmitted &&
1739 "emitNonSemanticDebugStrings() must run before "
1740 "emitNonSemanticGlobalDebugInfo()");
1741#endif
1742
1743 CurrentMAI = &MAI;
1744
1745 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1746 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1747
1748 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
1749 VoidTypeReg, ExtInstSetReg, {}, MAI);
1750
1751 // Emit integer constants shared across all NSDI instructions. The constant
1752 // cache ensures each value is emitted at most once even when referenced from
1753 // multiple instructions. All constants are pre-emitted before any DebugSource
1754 // so that the output order is: constants, then
1755 // DebugSource+DebugCompilationUnit pairs. This keeps OpConstant instructions
1756 // grouped before the OpExtInst instructions.
1757
1758 // The Version operand of DebugCompilationUnit is the version of the
1759 // NonSemantic.Shader.DebugInfo instruction set, which is 100 for
1760 // "NonSemantic.Shader.DebugInfo.100" (NonSemanticShaderDebugInfo100Version).
1761 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
1762 MCRegister DwarfVersionReg =
1763 emitOpConstantI32(static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
1764
1765 // Pre-emit source language constants for all compile units before entering
1766 // the DebugSource loop.
1767 SmallVector<MCRegister> SrcLangRegs =
1768 map_to_vector(CompileUnits, [&](const CompileUnitInfo &Info) {
1769 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
1770 });
1771
1772 // Emit DebugSource and DebugCompilationUnit for each compile unit.
1773 for (auto [Info, SrcLangReg] : llvm::zip(CompileUnits, SrcLangRegs)) {
1774 MCRegister FileStrReg = ScopeToPathOpStringReg.lookup(Info.TheCU);
1775 assert(FileStrReg.isValid() &&
1776 "CU path OpString must be emitted in emitNonSemanticDebugStrings");
1777 MCRegister DebugSourceReg = getOrEmitDebugSourceForFileStrReg(
1778 FileStrReg, VoidTypeReg, ExtInstSetReg, MAI);
1779 MCRegister CUDbgReg = emitExtInst(
1780 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
1781 ExtInstSetReg,
1782 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
1783 MAI);
1784 if (Info.TheCU)
1785 DebugScopeRegs[Info.TheCU] = CUDbgReg;
1786 }
1787
1788 // Zero constant used as the Flags operand in DebugTypeBasic and
1789 // DebugTypePointer. Cached with other i32 constants.
1790 MCRegister I32ZeroReg = emitOpConstantI32(0, I32TypeReg, MAI);
1791
1792 for (const DIBasicType *BT : BasicTypes) {
1793 if (!isUInt<32>(BT->getSizeInBits()))
1794 continue;
1795
1796 MCRegister NameReg = getCachedOpStringReg(BT->getName());
1797 MCRegister SizeReg = emitOpConstantI32(
1798 static_cast<uint32_t>(BT->getSizeInBits()), I32TypeReg, MAI);
1799
1800 // Map DWARF base type encodings to NSDI encoding codes per
1801 // NonSemantic.Shader.DebugInfo.100 specification, section 4.5.
1802 unsigned Encoding = 0; // Unspecified
1803 switch (BT->getEncoding()) {
1804 case dwarf::DW_ATE_address:
1805 Encoding = 1;
1806 break;
1807 case dwarf::DW_ATE_boolean:
1808 Encoding = 2;
1809 break;
1810 case dwarf::DW_ATE_float:
1811 Encoding = 3;
1812 break;
1813 case dwarf::DW_ATE_signed:
1814 Encoding = 4;
1815 break;
1816 case dwarf::DW_ATE_signed_char:
1817 Encoding = 5;
1818 break;
1819 case dwarf::DW_ATE_unsigned:
1820 Encoding = 6;
1821 break;
1822 case dwarf::DW_ATE_unsigned_char:
1823 Encoding = 7;
1824 break;
1825 }
1826 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
1827
1828 MCRegister BTReg = emitExtInst(
1829 SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
1830 {NameReg, SizeReg, EncodingReg, I32ZeroReg}, MAI);
1831 DebugScopeRegs[BT] = BTReg;
1832 }
1833
1834 // Emit DebugTypeVector for each collected vector type.
1835 for (const DICompositeType *VT : VectorTypes) {
1836 if (auto VecReg = emitDebugTypeVector(VT, ExtInstSetReg, MAI))
1837 DebugScopeRegs[VT] = *VecReg;
1838 }
1839
1840 // Emit DebugTypePointer for each referenced pointer type.
1841 for (const DIDerivedType *PT : PointerTypes) {
1842 if (auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
1843 DebugScopeRegs[PT] = *PtrReg;
1844 }
1845
1846 // Emit DebugTypeArray for each collected array type. Placed after the basic,
1847 // vector, and pointer types so an array over any of them can resolve its
1848 // element id. An array whose element type was not emitted is skipped.
1849 for (const DICompositeType *AT : ArrayTypes) {
1850 if (auto ArrReg = emitDebugTypeArray(AT, ExtInstSetReg, MAI))
1851 DebugScopeRegs[AT] = *ArrReg;
1852 }
1853
1854 // Emit DebugTypeFunction for each distinct DISubroutineType.
1855 for (const DISubroutineType *ST : SubroutineTypes) {
1856 if (auto FnTyReg =
1857 emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI))
1858 DebugScopeRegs[ST] = *FnTyReg;
1859 }
1860
1861 // Emit DebugLexicalBlock for each collected DINamespace, in parent-before-
1862 // child order. Placed before any DINamespace-scoped entity (typedefs,
1863 // function declarations, composite types, functions, global variables) so
1864 // their Parent operand can reference an already-emitted DebugLexicalBlock.
1865 // DINamespace never chains through a DISubprogram (DINamespace::getScope()
1866 // returns DIScope, not DILocalScope), so this never depends on
1867 // DebugScopeRegs.
1868 for (const DIScope *S :
1869 make_filter_range(LexicalBlocks, IsaPred<DINamespace>)) {
1870 if (auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
1871 ExtInstSetReg, MAI))
1872 DebugScopeRegs[S] = *LBReg;
1873 }
1874
1875 // Emit DebugTypedef for each typedef. Placed after the other type loops so a
1876 // typedef can resolve its underlying type. A typedef whose base type is not
1877 // emitted is skipped. A typedef whose base is another typedef emitted later
1878 // in this same pass is also skipped, the emission-order gap tracked in
1879 // https://github.com/llvm/llvm-project/issues/211850.
1880 for (const DIDerivedType *TD : TypedefTypes) {
1881 if (auto TDReg =
1882 emitDebugTypedef(TD, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
1883 DebugScopeRegs[TD] = *TDReg;
1884 }
1885
1886 // Emit DebugFunctionDeclaration for DISubprogram declarations.
1887 for (const DISubprogram *SP : SubprogramDeclarations) {
1888 if (auto DeclReg = emitDebugFunctionDeclaration(SP, VoidTypeReg, I32TypeReg,
1889 ExtInstSetReg, MAI))
1890 DebugScopeRegs[SP] = *DeclReg;
1891 }
1892
1893 // Emit DebugTypeMember and DebugTypeComposite for each struct, class, or
1894 // union. Each member is emitted before the composite that lists it, so the
1895 // Members operand references already-defined ids. A member whose type is not
1896 // in DebugScopeRegs is skipped.
1897 for (const DICompositeType *CT : CompositeTypes) {
1898 SmallVector<MCRegister> MemberRegs;
1899 for (const DINode *Element : CT->getElements()) {
1900 const auto *M = dyn_cast<DIDerivedType>(Element);
1901 if (!M || M->getTag() != dwarf::DW_TAG_member)
1902 continue;
1903 if (auto MemberReg = emitDebugTypeMember(M, VoidTypeReg, I32TypeReg,
1904 ExtInstSetReg, MAI))
1905 MemberRegs.push_back(*MemberReg);
1906 }
1907 if (auto CompReg = emitDebugTypeComposite(CT, MemberRegs, VoidTypeReg,
1908 I32TypeReg, ExtInstSetReg, MAI))
1909 DebugScopeRegs[CT] = *CompReg;
1910 }
1911
1912 // Emit DebugFunction for DISubprogram definitions.
1913 for (const DISubprogram *SP : SubprogramDefinitions) {
1914 if (auto FnReg =
1915 emitDebugFunction(SP, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
1916 DebugScopeRegs[SP] = *FnReg;
1917 }
1918
1919 // Emit DebugLexicalBlock for each collected DILexicalBlock, in parent-
1920 // before-child order. Placed after DebugFunction so a block directly
1921 // enclosed by a function (the common case) can resolve its Parent operand;
1922 // DINamespace entries were already emitted above.
1923 for (const DIScope *S :
1925 if (auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
1926 ExtInstSetReg, MAI))
1927 DebugScopeRegs[S] = *LBReg;
1928 }
1929
1930 // Emit DebugLocalVariable after DebugFunction and their lexical blocks so the
1931 // Parent operand can resolve. Record the ids for DebugDeclare.
1932 for (const DILocalVariable *LV : LocalVariables)
1933 if (auto LVReg = emitDebugLocalVariable(LV, VoidTypeReg, I32TypeReg,
1934 ExtInstSetReg, MAI))
1935 DebugLocalVariableRegs[LV] = *LVReg;
1936
1937 // Opcodes like DebugDeclare are part of the function body, but
1938 // DebugExpression is not. For such opcodes, we collect the expressions
1939 // directly from the MIR to avoid inconsistencies with those in the LLVM IR
1940 // module.
1942 collectDebugExpressions(Expressions);
1943 for (const DIExpression *Expr : Expressions)
1944 if (auto ExprReg = emitDebugExpression(Expr, VoidTypeReg, I32TypeReg,
1945 ExtInstSetReg, MAI))
1946 DebugExpressionRegs[Expr] = *ExprReg;
1947
1948 // Emit DebugGlobalVariable for each collected DIGlobalVariable.
1949 for (const auto &[GV, Info] : GlobalVariableDebugInfoMap)
1950 emitDebugGlobalVariable(GV, Info, VoidTypeReg, I32TypeReg, ExtInstSetReg,
1951 MAI);
1952
1953 // Emit DebugInlinedAt allowing recursive inlining.
1954 for (const DILocation *DL : UniqueDebugLocations)
1955 if (const DILocation *IA = DL->getInlinedAt())
1956 getOrEmitDebugInlinedAt(IA, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
1957
1958 for (const DILocation *DL : UniqueDebugLocations) {
1959 emitOpConstantI32(DL->getLine(), I32TypeReg, MAI);
1960 emitOpConstantI32(DL->getColumn(), I32TypeReg, MAI);
1961 emitOpConstantI32(DL->getColumn() + 1, I32TypeReg, MAI);
1962 MCRegister FileStrReg =
1963 getCachedScopePathOpStringReg(DL->getScope(),
1964 /*UseEmptyPathIfNullScope=*/true);
1965 getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg, ExtInstSetReg,
1966 MAI);
1967 }
1968
1969 GlobalNSDIEnabled = true;
1970}
1971
1973SPIRVNonSemanticDebugHandler::getDebugFullPath(const DIScope *Scope) const {
1974 SmallString<128> Out;
1975 if (!Scope)
1976 return Out;
1977 StringRef Filename = Scope->getFilename();
1978 const auto Style = sys::path::Style::native;
1979 if (sys::path::is_absolute(Filename, Style))
1980 Out.assign(Filename.begin(), Filename.end());
1981 else {
1982 StringRef Dir = Scope->getDirectory();
1983 Out.assign(Dir.begin(), Dir.end());
1984 sys::path::append(Out, Style, Filename);
1985 }
1986 return Out;
1987}
1988
1989MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugSourceForFileStrReg(
1990 MCRegister FileStrReg, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
1992 const unsigned Key = FileStrReg.id();
1993 auto It = DebugSourceRegByFileStr.find(Key);
1994 if (It != DebugSourceRegByFileStr.end())
1995 return It->second;
1996
1997 MCRegister DS = emitExtInst(SPIRV::NonSemanticExtInst::DebugSource,
1998 VoidTypeReg, ExtInstSetReg, {FileStrReg}, MAI);
1999 DebugSourceRegByFileStr[Key] = DS;
2000 return DS;
2001}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
BitTracker BT
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains constants used for implementing Dwarf debug support.
#define _
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
Register Reg
static constexpr StringLiteral Filename
SI Fold Operands
static const MachineInstr * findAdjacentEmittedInstruction(const MachineInstr *MI, SPIRV::ModuleAnalysisInfo &MAI, bool Forward)
static void collectLexicalBlockChain(const DIScope *S, SetVector< const DIScope * > &Out)
static bool isMergeInstruction(unsigned Opcode)
static bool isDebugLocTarget(const MachineInstr *MI, SPIRV::ModuleAnalysisInfo &MAI)
static std::optional< Register > getDebugDeclareStorageReg(const MachineInstr &MI)
static std::optional< NonSemanticDebugOp > mapDwarfOpToNonSemanticOp(uint64_t DwarfOp)
static void collectDebugLocationsAndLocalVariables(const Module &M, SetVector< const DILocation * > &Locations, SetVector< const DILocalVariable * > &LVs)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
Definition SPIRVUtils.h:567
This file implements a set that has insertion order iteration characteristics.
This file defines less commonly used SmallVector utilities.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
iterator end() const
Definition ArrayRef.h:130
iterator begin() const
Definition ArrayRef.h:129
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:91
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition AsmPrinter.h:112
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:106
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:266
Basic type, like 'int' or 'float'.
StringRef getIdentifier() const
DINodeArray getElements() const
DIType * getBaseType() const
A lightweight wrapper around an expression operand.
DWARF expression.
iterator_range< expr_op_iterator > expr_ops() const
A pair of DIGlobalVariable and DIExpression.
DIDerivedType * getStaticDataMemberDeclaration() const
StringRef getLinkageName() const
DILocalScope * getScope() const
Get the local scope for this variable.
Tagged DWARF-like metadata node.
LLVM_ABI dwarf::Tag getTag() const
DIFlags
Debug info flags.
Base class for scope-like contexts.
DIFile * getFile() const
LLVM_ABI DIScope * getScope() const
Subprogram description. Uses SubclassData1.
Type array for a subprogram.
Base class for types.
StringRef getName() const
bool isForwardDecl() const
uint64_t getSizeInBits() const
unsigned getLine() const
DIScope * getScope() const
DIFile * getFile() const
DIScope * getScope() const
DIType * getType() const
unsigned getLine() const
StringRef getName() const
Base class for non-instruction debug metadata records that have positions within IR.
const MachineInstr * CurMI
If nonnull, stores the current machine instruction we're processing.
AsmPrinter * Asm
Target of debug info emission.
void beginModule(Module *M) override
Utility to find all debug info in a module.
Definition DebugInfo.h:105
LLVM_ABI void processModule(const Module &M)
Process entire module and collect debug info anchors.
iterator_range< global_variable_expression_iterator > global_variables() const
Definition DebugInfo.h:155
iterator_range< subprogram_iterator > subprograms() const
Definition DebugInfo.h:153
iterator_range< type_iterator > types() const
Definition DebugInfo.h:159
iterator_range< scope_iterator > scopes() const
Definition DebugInfo.h:161
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:285
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:348
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:765
DISubprogram * getSubprogram() const
Get the attached subprogram.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void 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
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock & front() const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
This class contains meta information specific to a module.
const Module * getModule() const
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
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:1766
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
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
iterator begin() const
Definition StringRef.h:114
iterator end() const
Definition StringRef.h:116
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM Value Representation.
Definition Value.h:75
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
Definition Dwarf.h:144
LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition Path.cpp:688
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition Path.cpp:467
This is an optimization pass for GlobalISel generic memory operations.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
Definition STLExtras.h:846
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1748
void addStringImm(StringRef Str, MCInst &Inst)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto map_to_vector(ContainerTy &&C, FuncTy &&F)
Map a range to a SmallVector with element types deduced from the mapping.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
bool isa_and_nonnull(const Y &Val)
Definition Casting.h:676
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
Definition Error.cpp:173
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
Definition STLExtras.h:1167
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
Definition STLExtras.h:552
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
Definition Casting.h:866
#define N
MCRegister getExtInstSetReg(unsigned SetNum)
DenseMap< unsigned, MCRegister > ExtInstSetMap
InstrList & getMSInstrs(unsigned MSType)
MCRegister getRegisterAlias(const MachineFunction *MF, Register Reg)
bool getSkipEmission(const MachineInstr *MI)
MCRegister getGlobalObjReg(const GlobalObject *GO)
void addExtension(Extension::Extension ToAdd)