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"
21#include "llvm/IR/DebugInfo.h"
27#include "llvm/IR/Module.h"
28#include "llvm/MC/MCInst.h"
29#include "llvm/MC/MCStreamer.h"
31#include "llvm/Support/Path.h"
32#include <cassert>
33
34using namespace llvm;
35
36namespace {
37
38/// Look up \p Key in a register map and return its value, or std::nullopt when
39/// the key is absent.
40template <typename MapT>
41static std::optional<MCRegister> lookupOptReg(const MapT &Map,
42 typename MapT::key_type Key) {
43 auto It = Map.find(Key);
44 if (It == Map.end())
45 return std::nullopt;
46 assert(It->second.isValid() && "invalid register stored in map");
47 return It->second;
48}
49
50/// Partition \p Ty into \p BasicTypes, \p PointerTypes, \p SubroutineTypes,
51/// \p VectorTypes, \p ArrayTypes, \p CompositeTypes, and \p TypedefTypes for
52/// NSDI emission. Used when iterating DebugInfoFinder.types(); each DI node is
53/// seen once, so no recursion into pointer bases. Other composites and the
54/// remaining derived kinds are ignored because they are not yet supported.
55/// Only types that are supported (later used) are partitioned.
56static void
57partitionTypes(const DIType *Ty, SmallVector<const DIBasicType *> &BasicTypes,
64 if (const auto *BT = dyn_cast<DIBasicType>(Ty)) {
65 BasicTypes.push_back(BT);
66 return;
67 }
68 if (const auto *ST = dyn_cast<DISubroutineType>(Ty)) {
69 SubroutineTypes.push_back(ST);
70 return;
71 }
72 if (const auto *CT = dyn_cast<DICompositeType>(Ty)) {
73 if (CT->getTag() == dwarf::DW_TAG_array_type) {
74 // A vector is an array with DINode::FlagVector. A plain array is the
75 // same tag without it. A matrix is also lowered to a DW_TAG_array_type
76 // (two subranges), so it is indistinguishable from a 2D array here and
77 // is emitted as a DebugTypeArray.
78 //
79 // FIXME: Emitting a matrix as a DebugTypeArray is valid but loses the
80 // matrix shape. DWARF has no matrix tag, so distinguishing a matrix needs
81 // a new DINode flag analogous to FlagVector, set on the array, plus a way
82 // to carry column-major vs row-major traits. Array-of-vectors alone would
83 // not disambiguate a matrix from a genuine array of vectors. Once the
84 // frontend marks matrices, route them to a DebugTypeMatrix path here.
85 if (CT->isVector())
86 VectorTypes.push_back(CT);
87 else
88 ArrayTypes.push_back(CT);
89 } else if (CT->getTag() == dwarf::DW_TAG_structure_type ||
90 CT->getTag() == dwarf::DW_TAG_class_type ||
91 CT->getTag() == dwarf::DW_TAG_union_type) {
92 CompositeTypes.push_back(CT);
93 }
94 return;
95 }
96 const auto *DT = dyn_cast<DIDerivedType>(Ty);
97 if (DT && DT->getTag() == dwarf::DW_TAG_pointer_type)
98 PointerTypes.push_back(DT);
99 else if (DT && DT->getTag() == dwarf::DW_TAG_typedef)
100 TypedefTypes.push_back(DT);
101}
102
103enum : uint32_t {
104 NSDIFlagIsProtected = 1u << 0,
105 NSDIFlagIsPrivate = 1u << 1,
106 NSDIFlagIsPublic = NSDIFlagIsPrivate | NSDIFlagIsProtected,
107 NSDIFlagIsLocal = 1u << 2,
108 NSDIFlagIsDefinition = 1u << 3,
109 NSDIFlagFwdDecl = 1u << 4,
110 NSDIFlagArtificial = 1u << 5,
111 NSDIFlagExplicit = 1u << 6,
112 NSDIFlagPrototyped = 1u << 7,
113 NSDIFlagObjectPointer = 1u << 8,
114 NSDIFlagStaticMember = 1u << 9,
115 NSDIFlagIndirectVariable = 1u << 10,
116 NSDIFlagLValueReference = 1u << 11,
117 NSDIFlagRValueReference = 1u << 12,
118 NSDIFlagIsOptimized = 1u << 13,
119 NSDIFlagIsEnumClass = 1u << 14,
120 NSDIFlagTypePassByValue = 1u << 15,
121 NSDIFlagTypePassByReference = 1u << 16,
122 NSDIFlagUnknownPhysicalLayout = 1u << 17,
123};
124
125static uint32_t mapDIFlagsToNonSemantic(DINode::DIFlags DFlags) {
126 uint32_t Flags = 0;
127 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPublic)
128 Flags |= NSDIFlagIsPublic;
129 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagProtected)
130 Flags |= NSDIFlagIsProtected;
131 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPrivate)
132 Flags |= NSDIFlagIsPrivate;
133 if (DFlags & DINode::FlagFwdDecl)
134 Flags |= NSDIFlagFwdDecl;
135 if (DFlags & DINode::FlagArtificial)
136 Flags |= NSDIFlagArtificial;
137 if (DFlags & DINode::FlagExplicit)
138 Flags |= NSDIFlagExplicit;
139 if (DFlags & DINode::FlagPrototyped)
140 Flags |= NSDIFlagPrototyped;
141 if (DFlags & DINode::FlagObjectPointer)
142 Flags |= NSDIFlagObjectPointer;
143 if (DFlags & DINode::FlagStaticMember)
144 Flags |= NSDIFlagStaticMember;
145 if (DFlags & DINode::FlagLValueReference)
146 Flags |= NSDIFlagLValueReference;
147 if (DFlags & DINode::FlagRValueReference)
148 Flags |= NSDIFlagRValueReference;
149 if (DFlags & DINode::FlagTypePassByValue)
150 Flags |= NSDIFlagTypePassByValue;
151 if (DFlags & DINode::FlagTypePassByReference)
152 Flags |= NSDIFlagTypePassByReference;
153 if (DFlags & DINode::FlagEnumClass)
154 Flags |= NSDIFlagIsEnumClass;
155 return Flags;
156}
157
158static uint32_t transDebugFlags(const DINode *DN) {
159 uint32_t Flags = 0;
160 if (const auto *GV = dyn_cast<DIGlobalVariable>(DN)) {
161 if (GV->isLocalToUnit())
162 Flags |= NSDIFlagIsLocal;
163 if (GV->isDefinition())
164 Flags |= NSDIFlagIsDefinition;
165 }
166 if (const auto *SP = dyn_cast<DISubprogram>(DN)) {
167 if (SP->isLocalToUnit())
168 Flags |= NSDIFlagIsLocal;
169 if (SP->isOptimized())
170 Flags |= NSDIFlagIsOptimized;
171 if (SP->isDefinition())
172 Flags |= NSDIFlagIsDefinition;
173 Flags |= mapDIFlagsToNonSemantic(SP->getFlags());
174 }
175 if (DN->getTag() == dwarf::DW_TAG_reference_type)
176 Flags |= NSDIFlagLValueReference;
177 if (DN->getTag() == dwarf::DW_TAG_rvalue_reference_type)
178 Flags |= NSDIFlagRValueReference;
179 if (const auto *Ty = dyn_cast<DIType>(DN))
180 Flags |= mapDIFlagsToNonSemantic(Ty->getFlags());
181 if (const auto *LV = dyn_cast<DILocalVariable>(DN))
182 Flags |= mapDIFlagsToNonSemantic(LV->getFlags());
183 return Flags;
184}
185
186// Map a DWARF composite tag to a NonSemantic.Shader.DebugInfo Composite Type
187// value: Class 0, Structure 1, Union 2.
188static uint32_t mapCompositeTypeTag(unsigned Tag) {
189 switch (Tag) {
190 case dwarf::DW_TAG_class_type:
191 return 0;
192 case dwarf::DW_TAG_structure_type:
193 return 1;
194 case dwarf::DW_TAG_union_type:
195 return 2;
196 default:
197 reportFatalInternalError("unexpected DWARF composite tag " + Twine(Tag) +
198 ". Expecting 0, 1 or 2");
199 }
200}
201
202static const MachineInstr *
203findLastFunctionOpVariableDeclaration(const MachineFunction &MF,
205
206 // We iterate over the instructions to find the last OpVariable instruction if
207 // any. The following SPIRV rule is used to terminate the traversal earlier:
208 // SPIR-V 2.16.1, Function Structure: "All OpVariable instructions in a
209 // function must be in the first block in the function. These instructions,
210 // together with any intermixed OpLine and OpNoLine instructions, must be the
211 // first instructions in that block."
212 const MachineInstr *LastOpVariable = nullptr;
213 bool SeenOpVariable = false;
214 for (const MachineInstr &MI : MF.front()) {
215 if (MI.getOpcode() == SPIRV::OpVariable) {
216 SeenOpVariable = true;
217 if (!MAI.getSkipEmission(&MI))
218 LastOpVariable = &MI;
219 continue;
220 }
221
222 bool CanInterleaveWithOpVariable =
223 MI.getOpcode() == SPIRV::OpLine || MI.getOpcode() == SPIRV::OpNoLine;
224 if (SeenOpVariable && !CanInterleaveWithOpVariable &&
225 !MAI.getSkipEmission(&MI))
226 break;
227 }
228 return LastOpVariable;
229}
230
231} // namespace
232
235
236// Map DWARF source language codes to NonSemantic.Shader.DebugInfo.100 source
237// language codes. Values are from the SourceLanguage enum in the
238// NonSemantic.Shader.DebugInfo.100 specification, section 4.3.
239unsigned SPIRVNonSemanticDebugHandler::toNSDISrcLang(unsigned DwarfSrcLang) {
240 switch (DwarfSrcLang) {
241 case dwarf::DW_LANG_OpenCL:
242 return 3; // OpenCL_C
243 case dwarf::DW_LANG_OpenCL_CPP:
244 return 4; // OpenCL_CPP
245 case dwarf::DW_LANG_CPP_for_OpenCL:
246 return 6; // CPP_for_OpenCL
247 case dwarf::DW_LANG_GLSL:
248 return 2; // GLSL
249 case dwarf::DW_LANG_HLSL:
250 return 5; // HLSL
251 case dwarf::DW_LANG_SYCL:
252 return 7; // SYCL
253 case dwarf::DW_LANG_Zig:
254 return 12; // Zig
255 default:
256 return 0; // Unknown
257 }
258}
259
260// Collect distinct DILocations from LLVM IR. DebugLine pre-emission and MIR
261// lookups assume every machine-instruction debug location already appeared
262// here; a codegen-only location would not be collected and emission will be
263// skipped.
266 for (const Function &F : M) {
267 if (!F.getSubprogram())
268 continue;
269 for (const Instruction &I : instructions(F)) {
270 if (const DILocation *DL = I.getDebugLoc().get())
271 Out.insert(DL);
272 for (DbgRecord &DR : I.getDbgRecordRange())
273 if (const DILocation *DL = DR.getDebugLoc().get())
274 Out.insert(DL);
275 }
276 }
277}
278
280 // The base class sets Asm = nullptr when the module has no compile units,
281 // and initializes lexical scope tracking otherwise.
283
284 if (!Asm)
285 return;
286
287 CompileUnits.clear();
288 BasicTypes.clear();
289 PointerTypes.clear();
290 SubroutineTypes.clear();
291 VectorTypes.clear();
292 ArrayTypes.clear();
293 CompositeTypes.clear();
294 TypedefTypes.clear();
295 SubprogramDeclarations.clear();
296 SubprogramDefinitions.clear();
297 UniqueDebugLocations.clear();
298 GlobalVariableDebugInfoMap.clear();
299 DebugFunctionDeclarationRegs.clear();
300 DebugFunctionRegs.clear();
301 ScopeToPathOpStringReg.clear();
302 CUToCompilationUnitDbgReg.clear();
303 DebugSourceRegByFileStr.clear();
304 DebugTypeRegs.clear();
305 OpStringContentCache.clear();
306 I32ConstantCache.clear();
307 DebugTypeFunctionCache.clear();
308 GlobalDIEmitted = false;
309 GlobalNSDIEnabled = false;
310 CurrentMAI = nullptr;
311#ifndef NDEBUG
312 NonSemanticOpStringsSectionEmitted = false;
313#endif
314 CachedDebugInfoNoneReg = MCRegister();
315 CachedEmptyStringReg = MCRegister();
316 CachedOpTypeVoidReg = MCRegister();
317 CachedOpTypeInt32Reg = MCRegister();
318
319 // Collect compile-unit info: file paths and source languages.
320 for (const DICompileUnit *CU : M->debug_compile_units()) {
321 const DIFile *File = CU->getFile();
322 CompileUnitInfo Info;
323 Info.TheCU = CU;
324 if (sys::path::is_absolute(File->getFilename()))
325 Info.FilePath = File->getFilename();
326 else
327 sys::path::append(Info.FilePath, File->getDirectory(),
328 File->getFilename());
329 // getName() returns the language code regardless of whether the name is
330 // versioned. getUnversionedName() would assert on versioned names.
331 Info.SpirvSourceLanguage = toNSDISrcLang(CU->getSourceLanguage().getName());
332 CompileUnits.push_back(std::move(Info));
333 }
334
335 // Collect DWARF version from module flags. For CodeView modules there is no
336 // "Dwarf Version" flag; DwarfVersion remains 0, which is the correct value
337 // for the DebugCompilationUnit DWARF Version operand in that case.
338 if (const NamedMDNode *Flags = M->getNamedMetadata("llvm.module.flags")) {
339 for (const auto *Op : Flags->operands()) {
340 const MDOperand &NameOp = Op->getOperand(1);
341 if (NameOp.equalsStr("Dwarf Version"))
342 DwarfVersion =
344 cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
345 ->getSExtValue();
346 }
347 }
348
349 // Find all debug info types that may be referenced by NSDI instructions.
350 DebugInfoFinder Finder;
351 Finder.processModule(*M);
352 llvm::for_each(Finder.types(), [&](DIType *Ty) {
353 partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes, VectorTypes,
354 ArrayTypes, CompositeTypes, TypedefTypes);
355 });
356
357 for (const DISubprogram *SP : Finder.subprograms()) {
358 if (SP->isDefinition())
359 SubprogramDefinitions.push_back(SP);
360 else
361 SubprogramDeclarations.push_back(SP);
362 }
363
364 // Walk LLVM globals to map each DIGlobalVariable to its llvm::GlobalVariable.
366 for (const GlobalVariable &G : M->globals()) {
368 G.getDebugInfo(GVEs);
369 for (DIGlobalVariableExpression *GVE : GVEs) {
370 if (const DIGlobalVariable *GV = GVE->getVariable()) {
371 DIGVToLLVMGV.try_emplace(GV, &G);
372 }
373 }
374 }
375
376 for (const DIGlobalVariableExpression *GVE : Finder.global_variables()) {
377 const DIGlobalVariable *GV = GVE->getVariable();
378 const DIExpression *Expr = GVE->getExpression();
379 GlobalVariableDebugInfoMap.try_emplace(
380 GV, GlobalVariableDebugInfo{Expr, DIGVToLLVMGV.lookup(GV)});
381 }
382
383 collectUniqueDebugLocations(*M, UniqueDebugLocations);
384}
385
388 if (CompileUnits.empty())
389 return;
390 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_non_semantic_info))
391 return;
392
393 // Add the extension to requirements so OpExtension is output.
394 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
395
396 // Add the NonSemantic.Shader.DebugInfo.100 entry to ExtInstSetMap so that
397 // outputOpExtInstImports() emits the OpExtInstImport instruction. Allocate a
398 // fresh result ID for it now; the same ID is used in emitExtInst() operands.
399 if (!MAI.ExtInstSetMap.count(NSSet))
400 MAI.ExtInstSetMap[NSSet] = MAI.getNextIDRegister();
401}
402
403void SPIRVNonSemanticDebugHandler::emitMCInst(MCInst &Inst) {
404 Asm->OutStreamer->emitInstruction(Inst, Asm->getSubtargetInfo());
405}
406
408SPIRVNonSemanticDebugHandler::emitOpString(StringRef S,
411 MCInst Inst;
412 Inst.setOpcode(SPIRV::OpString);
414 addStringImm(S, Inst);
415 emitMCInst(Inst);
416 return Reg;
417}
418
419MCRegister SPIRVNonSemanticDebugHandler::emitOpStringIfNew(
421#ifndef NDEBUG
422 assert(!NonSemanticOpStringsSectionEmitted &&
423 "emitOpStringIfNew is only valid while emitting SPIR-V section 7");
424#endif
425 auto [It, Inserted] = OpStringContentCache.try_emplace(S, MCRegister());
426 if (Inserted)
427 It->second = emitOpString(S, MAI);
428
429 return It->second;
430}
431
432MCRegister SPIRVNonSemanticDebugHandler::getCachedOpStringReg(StringRef S) {
433#ifndef NDEBUG
434 assert(NonSemanticOpStringsSectionEmitted &&
435 "getCachedOpStringReg requires emitNonSemanticDebugStrings() first");
436#endif
437 auto It = OpStringContentCache.find(S);
438 assert(It != OpStringContentCache.end() &&
439 "NSDI OpString missing from cache; emitNonSemanticDebugStrings must "
440 "cache every string used in section 10");
441 return It->second;
442}
443
444MCRegister SPIRVNonSemanticDebugHandler::emitAndCacheScopePathOpStringReg(
445 const DIScope *Scope, SPIRV::ModuleAnalysisInfo &MAI) {
446 auto [It, Inserted] = ScopeToPathOpStringReg.try_emplace(Scope, MCRegister());
447 if (Inserted)
448 It->second = emitOpStringIfNew(getDebugFullPath(Scope), MAI);
449 return It->second;
450}
451
452MCRegister SPIRVNonSemanticDebugHandler::getCachedScopePathOpStringReg(
453 const DIScope *Scope, bool UseEmptyPathIfNullScope) {
454 if (!Scope) {
455 assert(UseEmptyPathIfNullScope &&
456 "null scope path lookup requires UseEmptyPathIfNullScope");
457 assert(CachedEmptyStringReg.isValid() &&
458 "empty path OpString must be cached in emitNonSemanticDebugStrings");
459 return CachedEmptyStringReg;
460 }
461 auto It = ScopeToPathOpStringReg.find(Scope);
462 assert(It != ScopeToPathOpStringReg.end() &&
463 "path OpString must be cached in emitNonSemanticDebugStrings");
464 MCRegister FileStrReg = It->second;
465 assert(FileStrReg.isValid() && "path OpString id must be valid once cached");
466 return FileStrReg;
467}
468
469MCRegister SPIRVNonSemanticDebugHandler::emitOpConstantI32(
470 uint32_t Value, MCRegister I32TypeReg, SPIRV::ModuleAnalysisInfo &MAI) {
471 auto [It, Inserted] = I32ConstantCache.try_emplace(Value);
472 if (!Inserted)
473 return It->second;
474
475 MCRegister Reg = MAI.getNextIDRegister();
476 It->second = Reg;
477 MCInst Inst;
478 Inst.setOpcode(SPIRV::OpConstantI);
480 Inst.addOperand(MCOperand::createReg(I32TypeReg));
481 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Value)));
482 emitMCInst(Inst);
483 return Reg;
484}
485
486MCRegister SPIRVNonSemanticDebugHandler::emitExtInst(
487 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
488 MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
490 MCRegister Reg = MAI.getNextIDRegister();
491 MCInst Inst;
492 Inst.setOpcode(SPIRV::OpExtInst);
494 Inst.addOperand(MCOperand::createReg(VoidTypeReg));
495 Inst.addOperand(MCOperand::createReg(ExtInstSetReg));
496 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Opcode)));
497 for (MCRegister R : Operands)
499 emitMCInst(Inst);
500 return Reg;
501}
502
503MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugTypeFunction(
504 ArrayRef<MCRegister> Ops, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
506 auto [It, Inserted] =
507 DebugTypeFunctionCache.try_emplace(SmallVector<MCRegister, 8>(Ops));
508 if (!Inserted)
509 return It->second;
510
511 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeFunction,
512 VoidTypeReg, ExtInstSetReg, Ops, MAI);
513 It->second = Reg;
514 return Reg;
515}
516
517MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeVoidReg(
519 if (!CachedOpTypeVoidReg.isValid())
520 CachedOpTypeVoidReg = findOrEmitOpTypeVoid(MAI);
521 return CachedOpTypeVoidReg;
522}
523
524MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeInt32Reg(
526 if (!CachedOpTypeInt32Reg.isValid())
527 CachedOpTypeInt32Reg = findOrEmitOpTypeInt32(MAI);
528 return CachedOpTypeInt32Reg;
529}
530
531MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
533 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
534 if (MI->getOpcode() == SPIRV::OpTypeVoid)
535 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
536 }
537 MCRegister Reg = MAI.getNextIDRegister();
538 MCInst Inst;
539 Inst.setOpcode(SPIRV::OpTypeVoid);
541 emitMCInst(Inst);
542 return Reg;
543}
544
545MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
547 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
548 if (MI->getOpcode() == SPIRV::OpTypeInt &&
549 MI->getOperand(1).getImm() == 32 && MI->getOperand(2).getImm() == 0)
550 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
551 }
552 MCRegister Reg = MAI.getNextIDRegister();
553 MCInst Inst;
554 Inst.setOpcode(SPIRV::OpTypeInt);
556 Inst.addOperand(MCOperand::createImm(32)); // width
557 Inst.addOperand(MCOperand::createImm(0)); // signedness (unsigned)
558 emitMCInst(Inst);
559 return Reg;
560}
561
562std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
563 const DIDerivedType *PT, MCRegister ExtInstSetReg,
565 // A DWARF address space is required to determine the SPIR-V storage class.
566 // Skip pointer types that do not carry one.
567 if (!PT->getDWARFAddressSpace().has_value())
568 return std::nullopt;
569
570 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
571 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
572 MCRegister DebugTypePointerFlagsReg =
573 emitOpConstantI32(transDebugFlags(PT), I32TypeReg, MAI);
574
575 // For SPIR-V targets, Clang sets DwarfAddressSpace to the LLVM IR address
576 // space, which addressSpaceToStorageClass expects.
577 const auto &ST = static_cast<const SPIRVSubtarget &>(Asm->getSubtargetInfo());
578 MCRegister StorageClassReg = emitOpConstantI32(
579 addressSpaceToStorageClass(PT->getDWARFAddressSpace().value(), ST),
580 I32TypeReg, MAI);
581
582 if (const DIType *BaseTy = PT->getBaseType()) {
583 auto BaseIt = DebugTypeRegs.find(BaseTy);
584 if (BaseIt != DebugTypeRegs.end())
585 return emitExtInst(
586 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
587 ExtInstSetReg,
588 {BaseIt->second, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
589 // Unsupported type, no DebugType* id available.
590 return std::nullopt;
591 }
592 // No getBaseType() (typical for void*): use DebugInfoNone as Base Type,
593 // same as SPIRV-LLVM-Translator (see issue #109287 and the DISABLED
594 // spirv-val run in debug-type-pointer.ll). spirv-val may still reject this
595 // encoding; see https://github.com/KhronosGroup/SPIRV-Registry/pull/287.
596 return emitExtInst(
597 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg, ExtInstSetReg,
598 {CachedDebugInfoNoneReg, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
599}
600
601std::optional<MCRegister>
602SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
603 const DISubroutineType *ST, MCRegister ExtInstSetReg,
605 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
606 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
607 MCRegister DebugTypeFunctionFlagsReg =
608 emitOpConstantI32(transDebugFlags(ST), I32TypeReg, MAI);
609 DITypeArray TA = ST->getTypeArray();
611 Ops.push_back(DebugTypeFunctionFlagsReg);
612 // Empty DI type tuple: no explicit return or parameter slots (hand-written IR
613 // may use !{}). Emit void-only prototype. Same as SPIRV-LLVM-Translator when
614 // DISubroutineType::getTypeArray() has zero elements.
615 if (TA.empty()) {
616 Ops.push_back(VoidTypeReg);
617 } else {
618 for (unsigned I = 0, E = TA.size(); I != E; ++I) {
619 bool IsReturnType = (I == 0);
620 auto OptReg = mapDISignatureTypeToReg(TA[I], VoidTypeReg, IsReturnType);
621 // No emitted DebugType* id for this slot (e.g., pointer that
622 // was skipped due missing address space, etc.).
623 if (!OptReg)
624 return std::nullopt;
625 Ops.push_back(*OptReg);
626 }
627 }
628 return getOrEmitDebugTypeFunction(Ops, VoidTypeReg, ExtInstSetReg, MAI);
629}
630
631// Match SPIRV-LLVM-Translator's selection logic for the Parent operand.
632std::optional<MCRegister>
633SPIRVNonSemanticDebugHandler::resolveDebugFunctionParent(
634 const DISubprogram *SP) const {
635 const DIScope *Scope = SP->getScope();
636 if (Scope && !isa<DIFile>(Scope)) {
637 // TODO: Complete with other lookups once other scopes are supported
638 // (subclasses of DIScope).
639 const DIType *Ty = dyn_cast<DIType>(Scope);
640 if (!Ty)
641 return std::nullopt;
642 return lookupOptReg(DebugTypeRegs, Ty);
643 }
644
645 const DICompileUnit *ParentCU = SP->getUnit();
646 if (!ParentCU && !CompileUnits.empty())
647 ParentCU = CompileUnits[0].TheCU;
648 if (!ParentCU)
649 return std::nullopt;
650 return lookupOptReg(CUToCompilationUnitDbgReg, ParentCU);
651}
652
653std::optional<MCRegister> SPIRVNonSemanticDebugHandler::resolveTypeScopeParent(
654 const DIScope *Scope) const {
655 // When the scope is itself a type (e.g. a struct nested in another struct),
656 // the parent is that enclosing type's debug id.
657 if (const auto *Ty = dyn_cast_or_null<DIType>(Scope))
658 return lookupOptReg(DebugTypeRegs, Ty);
659
660 // For a file, compile-unit, namespace, or absent scope, the parent is the
661 // first module DebugCompilationUnit.
662 if (CompileUnits.empty())
663 return std::nullopt;
664
665 return lookupOptReg(CUToCompilationUnitDbgReg, CompileUnits[0].TheCU);
666}
667
668std::optional<MCRegister>
669SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
670 const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
671 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
672 assert(SP && "SP must not be null in emitDebugFunctionDeclaration");
673 assert(!SP->isDefinition() &&
674 "SP must not be a definition in emitDebugFunctionDeclaration");
675
676 // The IR verifier already enforces that this cannot be null.
677 const DISubroutineType *ST = SP->getType();
678
679 auto FnTyRegOpt = lookupOptReg(DebugTypeRegs, ST);
680 if (!FnTyRegOpt)
681 return std::nullopt;
682 MCRegister FnTyReg = *FnTyRegOpt;
683
684 auto ParentRegOpt = resolveDebugFunctionParent(SP);
685 if (!ParentRegOpt)
686 return std::nullopt;
687
688 MCRegister ParentReg = *ParentRegOpt;
689
690 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
691
692 MCRegister NameReg = getCachedOpStringReg(SP->getName());
693 MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
694 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
695 ExtInstSetReg, MAI);
696
697 MCRegister LineReg =
698 emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
699 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
700
701 uint32_t FlagsVal = transDebugFlags(SP);
702 // TODO: When composite scopes are DebugFunctionDeclaration parents (available
703 // in DebugTypeRegs), sync declaration Flags with SPIRV-LLVM-Translator.
704 FlagsVal &= ~NSDIFlagIsDefinition;
705 MCRegister FlagsReg = emitOpConstantI32(FlagsVal, I32TypeReg, MAI);
706
707 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
708 VoidTypeReg, ExtInstSetReg,
709 {NameReg, FnTyReg, SrcReg, LineReg, ColReg, ParentReg,
710 LinkageReg, FlagsReg},
711 MAI);
712}
713
714std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugFunction(
715 const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
716 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
717 assert(SP && "SP must not be null in emitDebugFunction");
718 assert(SP->isDefinition() && "SP must be a definition in emitDebugFunction");
719
720 const DISubroutineType *ST = SP->getType();
721 auto FnTyRegOpt = lookupOptReg(DebugTypeRegs, ST);
722 if (!FnTyRegOpt)
723 return std::nullopt;
724
725 auto ParentRegOpt = resolveDebugFunctionParent(SP);
726 if (!ParentRegOpt)
727 return std::nullopt;
728
729 MCRegister NameReg = getCachedOpStringReg(SP->getName());
730 MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
731 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
732 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
733 ExtInstSetReg, MAI);
734
735 MCRegister LineReg =
736 emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
737 // LLVM's DISubprogram has no column field but SPIR-V expects one in
738 // DebugFunction.
739 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
740 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(SP), I32TypeReg, MAI);
741 MCRegister ScopeLineReg = emitOpConstantI32(
742 static_cast<uint32_t>(SP->getScopeLine()), I32TypeReg, MAI);
743
744 SmallVector<MCRegister, 10> Ops = {NameReg, *FnTyRegOpt, SrcReg,
745 LineReg, ColReg, *ParentRegOpt,
746 LinkageReg, FlagsReg, ScopeLineReg};
747
748 if (const DISubprogram *Decl = SP->getDeclaration()) {
749 if (auto DeclRegOpt = lookupOptReg(DebugFunctionDeclarationRegs, Decl))
750 Ops.push_back(*DeclRegOpt);
751 }
752
753 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunction, VoidTypeReg,
754 ExtInstSetReg, Ops, MAI);
755}
756
757std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
758 const DIType *Ty, MCRegister VoidTypeReg, bool ReturnType) {
759 if (!Ty) {
760 if (ReturnType)
761 return VoidTypeReg;
762 assert(CachedDebugInfoNoneReg.isValid() &&
763 "DebugInfoNone must be emitted before DISubroutineType operands");
764 return CachedDebugInfoNoneReg;
765 }
766 return lookupOptReg(DebugTypeRegs, Ty);
767}
768
769MCRegister SPIRVNonSemanticDebugHandler::resolveGlobalVariableParent(
770 const DIGlobalVariable *) const {
771 // TODO: When this backend emits debug instructions for namespace, subprogram,
772 // compilation units, and module scopes return GV->getScope()'s debug id.
773
774 // !CompileUnits.empty() was already checked before staring the emission of
775 // NSDI instructions.
776 assert(!CompileUnits.empty() &&
777 "resolveGlobalVariableParent requires non-empty CompileUnits");
778 std::optional<MCRegister> ParentRegOpt =
779 lookupOptReg(CUToCompilationUnitDbgReg, CompileUnits[0].TheCU);
780 assert(ParentRegOpt && "DebugCompilationUnit must be emitted before "
781 "resolveGlobalVariableParent");
782 // Fallback: first module compile unit (SPIRV-LLVM-Translator default).
783 return *ParentRegOpt;
784}
785
786// Unimplemented no-op; see emitDebugExpression declaration.
787std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugExpression(
789 return std::nullopt;
790}
791
792std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugGlobalVariable(
793 const DIGlobalVariable *GV, const GlobalVariableDebugInfo &Info,
794 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
796 assert(GV && "GV must not be null in emitDebugGlobalVariable");
797
798 MCRegister ParentReg = resolveGlobalVariableParent(GV);
799
800 // TyReg: DebugInfoNone when GV has no DI type (as done in
801 // SPIRV-LLVM-Translator). Declarations (isDefinition: false) can have null
802 // getType() while definitions must have a non-null one (enforced by the IR
803 // verifier).
804 MCRegister TyReg = CachedDebugInfoNoneReg;
805 if (const DIType *Ty = GV->getType()) {
806 auto TyRegOpt = lookupOptReg(DebugTypeRegs, Ty);
807 if (!TyRegOpt)
808 return std::nullopt;
809 TyReg = *TyRegOpt;
810 }
811
812 std::optional<MCRegister> StaticMemberRegOpt;
813 if (const DIDerivedType *SM = GV->getStaticDataMemberDeclaration()) {
814 StaticMemberRegOpt = lookupOptReg(DebugTypeRegs, SM);
815 if (!StaticMemberRegOpt)
816 return std::nullopt;
817 }
818
819 MCRegister NameReg = getCachedOpStringReg(GV->getName());
820 MCRegister LinkageReg = getCachedOpStringReg(GV->getLinkageName());
821 MCRegister FileStrReg = getCachedScopePathOpStringReg(
822 GV->getFile(), /*UseEmptyPathIfNullScope=*/true);
823 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
824 ExtInstSetReg, MAI);
825
826 MCRegister LineReg =
827 emitOpConstantI32(static_cast<uint32_t>(GV->getLine()), I32TypeReg, MAI);
828 // DIGlobalVariable or DIGlobalVariableExpression metadata carry no column
829 // field. Column is hardcoded to 0 (because it can't be determined), matching
830 // SPIRV-LLVM-Translator.
831 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
832
833 // Variable: @g OpVariable id when !dbg matches; else a DebugExpression for
834 // the GVE init value when no @g exists; else DebugInfoNone.
835 MCRegister VariableReg = CachedDebugInfoNoneReg;
836 if (const GlobalVariable *LLVMGV = Info.LLVMGV) {
837 MCRegister GVReg = MAI.getGlobalObjReg(LLVMGV);
838 if (GVReg.isValid())
839 VariableReg = GVReg;
840 } else if (Info.Expr) {
841 if (auto ExprReg =
842 emitDebugExpression(Info.Expr, VoidTypeReg, ExtInstSetReg, MAI))
843 VariableReg = *ExprReg;
844 }
845
846 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(GV), I32TypeReg, MAI);
847
848 SmallVector<MCRegister, 10> Ops = {NameReg, TyReg, SrcReg,
849 LineReg, ColReg, ParentReg,
850 LinkageReg, VariableReg, FlagsReg};
851
852 if (StaticMemberRegOpt)
853 Ops.push_back(*StaticMemberRegOpt);
854
855 return emitExtInst(SPIRV::NonSemanticExtInst::DebugGlobalVariable,
856 VoidTypeReg, ExtInstSetReg, Ops, MAI);
857}
858
859std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
860 const DICompositeType *VT, MCRegister ExtInstSetReg,
862 const auto *BaseTy = dyn_cast_or_null<DIBasicType>(VT->getBaseType());
863 if (!BaseTy)
864 return std::nullopt;
865 auto BTIt = DebugTypeRegs.find(BaseTy);
866 if (BTIt == DebugTypeRegs.end())
867 return std::nullopt;
868
869 // DebugTypeVector models only 1D vectors (multi-subrange types cannot be
870 // encoded).
871 DINodeArray Elements = VT->getElements();
872 if (Elements.size() != 1)
873 return std::nullopt;
874 const auto *SR = cast<DISubrange>(Elements[0]);
875 const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount());
876 if (!CI)
877 return std::nullopt;
878
879 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
880 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
881 MCRegister CountReg = emitOpConstantI32(
882 static_cast<uint32_t>(CI->getZExtValue()), I32TypeReg, MAI);
883 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeVector, VoidTypeReg,
884 ExtInstSetReg, {BTIt->second, CountReg}, MAI);
885}
886
887std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeArray(
888 const DICompositeType *AT, MCRegister ExtInstSetReg,
890 // The element (base) type must already be in DebugTypeRegs. Unlike
891 // DebugTypeVector, the element may be any debug type, not only a basic type.
892 auto BaseRegOpt = lookupOptReg(DebugTypeRegs, AT->getBaseType());
893 if (!BaseRegOpt)
894 return std::nullopt;
895
896 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
897 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
898
900 Ops.push_back(*BaseRegOpt);
901
902 // One component count per DISubrange, in DWARF subrange order. Emit 0 for
903 // counts that are not a compile-time constant (dynamic arrays). This matches
904 // OpTypeRuntimeArray.
905 for (const DINode *Element : AT->getElements()) {
906 const auto *SR = dyn_cast<DISubrange>(Element);
907 if (!SR)
908 continue;
909 // A DIVariable count (a variable-length array) is not a ConstantInt, so it
910 // maps to 0 here. DebugTypeArray also allows a DebugLocalVariable or
911 // DebugGlobalVariable id for it, but no frontend we target emits one. A
912 // constant wider than 32 bits maps to 0 too, since the count operand is a
913 // 32-bit OpConstant and such an array cannot occur in a shader.
914 uint32_t Count = 0;
915 if (const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount())) {
916 const APInt &Value = CI->getValue();
917 if (Value.getActiveBits() <= 32)
918 Count = static_cast<uint32_t>(Value.getZExtValue());
919 }
920 Ops.push_back(emitOpConstantI32(Count, I32TypeReg, MAI));
921 }
922
923 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeArray, VoidTypeReg,
924 ExtInstSetReg, Ops, MAI);
925}
926
927std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeMember(
928 const DIDerivedType *M, MCRegister VoidTypeReg, MCRegister I32TypeReg,
929 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
930 // The member type must already be in DebugTypeRegs.
931 auto TyRegOpt = lookupOptReg(DebugTypeRegs, M->getBaseType());
932 if (!TyRegOpt)
933 return std::nullopt;
934
935 MCRegister NameReg = getCachedOpStringReg(M->getName());
936 MCRegister FileStrReg = getCachedScopePathOpStringReg(
937 M->getFile(), /*UseEmptyPathIfNullScope=*/true);
938 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
939 ExtInstSetReg, MAI);
940 MCRegister LineReg =
941 emitOpConstantI32(static_cast<uint32_t>(M->getLine()), I32TypeReg, MAI);
942
943 // DIDerivedType members carry no column, so emit 0.
944 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
945 MCRegister OffsetReg = emitOpConstantI32(
946 static_cast<uint32_t>(M->getOffsetInBits()), I32TypeReg, MAI);
947 MCRegister SizeReg = emitOpConstantI32(
948 static_cast<uint32_t>(M->getSizeInBits()), I32TypeReg, MAI);
949 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(M), I32TypeReg, MAI);
950
951 // In NonSemantic.Shader.DebugInfo a DebugTypeMember has no Parent operand:
952 // only the composite references its members. This is by design, it drops the
953 // Parent that OpenCL.DebugInfo.100 had, and it avoids a composite/member
954 // reference cycle.
955 //
956 // FIXME: Static members are not handled yet: their constant initializer is
957 // available but is not emitted as the optional Value operand, and under DWARF
958 // 5 a static member is tagged DW_TAG_variable, which the caller's member loop
959 // skips.
960 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeMember, VoidTypeReg,
961 ExtInstSetReg,
962 {NameReg, *TyRegOpt, SrcReg, LineReg, ColReg, OffsetReg,
963 SizeReg, FlagsReg},
964 MAI);
965}
966
967std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeComposite(
968 const DICompositeType *CT, ArrayRef<MCRegister> MemberRegs,
969 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
971 auto ParentRegOpt = resolveTypeScopeParent(CT->getScope());
972 if (!ParentRegOpt)
973 return std::nullopt;
974
975 MCRegister NameReg = getCachedOpStringReg(CT->getName());
976 MCRegister LinkageReg = getCachedOpStringReg(CT->getIdentifier());
977 MCRegister FileStrReg = getCachedScopePathOpStringReg(
978 CT->getFile(), /*UseEmptyPathIfNullScope=*/true);
979 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
980 ExtInstSetReg, MAI);
981
982 MCRegister TagReg =
983 emitOpConstantI32(mapCompositeTypeTag(CT->getTag()), I32TypeReg, MAI);
984 MCRegister LineReg =
985 emitOpConstantI32(static_cast<uint32_t>(CT->getLine()), I32TypeReg, MAI);
986 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
987
988 // A forward declaration has no known size or members: Size is DebugInfoNone.
989 MCRegister SizeReg = CachedDebugInfoNoneReg;
990 if (!CT->isForwardDecl())
991 SizeReg = emitOpConstantI32(static_cast<uint32_t>(CT->getSizeInBits()),
992 I32TypeReg, MAI);
993
994 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(CT), I32TypeReg, MAI);
995
996 SmallVector<MCRegister> Ops = {NameReg, TagReg, SrcReg,
997 LineReg, ColReg, *ParentRegOpt,
998 LinkageReg, SizeReg, FlagsReg};
999 Ops.append(MemberRegs.begin(), MemberRegs.end());
1000 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeComposite, VoidTypeReg,
1001 ExtInstSetReg, Ops, MAI);
1002}
1003
1004std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypedef(
1005 const DIDerivedType *TD, MCRegister VoidTypeReg, MCRegister I32TypeReg,
1006 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
1007 // The underlying (base) type must already be in DebugTypeRegs.
1008 auto BaseRegOpt = lookupOptReg(DebugTypeRegs, TD->getBaseType());
1009 if (!BaseRegOpt)
1010 return std::nullopt;
1011
1012 MCRegister NameReg = getCachedOpStringReg(TD->getName());
1013 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1014 TD->getFile(), /*UseEmptyPathIfNullScope=*/true);
1015 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1016 ExtInstSetReg, MAI);
1017 MCRegister LineReg =
1018 emitOpConstantI32(static_cast<uint32_t>(TD->getLine()), I32TypeReg, MAI);
1019 // DIDerivedType typedefs carry no column, so emit 0.
1020 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1021
1022 // Parent must be a lexical scope. Valid NSDI lexical scopes are
1023 // DebugCompilationUnit, DebugFunction, DebugLexicalBlock, or
1024 // DebugTypeComposite.
1025 //
1026 // FIXME: We currently only emit DebugCompilationUnit, so the compile unit is
1027 // the only parent available today.
1028 MCRegister ParentReg;
1029 if (const auto *Ty = dyn_cast_or_null<DIType>(TD->getScope()))
1030 if (auto TyRegOpt = lookupOptReg(DebugTypeRegs, Ty))
1031 ParentReg = *TyRegOpt;
1032 if (!ParentReg.isValid()) {
1033 assert(!CompileUnits.empty() &&
1034 "emitDebugTypedef requires a compile unit for the Parent operand");
1035 auto CURegOpt =
1036 lookupOptReg(CUToCompilationUnitDbgReg, CompileUnits[0].TheCU);
1037 assert(CURegOpt && "DebugCompilationUnit must be emitted before typedefs");
1038 ParentReg = *CURegOpt;
1039 }
1040
1041 return emitExtInst(
1042 SPIRV::NonSemanticExtInst::DebugTypedef, VoidTypeReg, ExtInstSetReg,
1043 {NameReg, *BaseRegOpt, SrcReg, LineReg, ColReg, ParentReg}, MAI);
1044}
1045
1048 if (CompileUnits.empty())
1049 return;
1050 // Check that prepareModuleOutput() registered the extended instruction set.
1051 // If the subtarget does not support the extension, neither strings nor ext
1052 // insts are emitted.
1053 if (!MAI.getExtInstSetReg(NSSet).isValid())
1054 return;
1055
1056 for (const CompileUnitInfo &Info : CompileUnits) {
1057 if (Info.TheCU) {
1058 MCRegister PathReg = emitOpStringIfNew(Info.FilePath, MAI);
1059 ScopeToPathOpStringReg[Info.TheCU] = PathReg;
1060 if (const DIFile *F = Info.TheCU->getFile())
1061 ScopeToPathOpStringReg[F] = PathReg;
1062 }
1063 }
1064
1065 for (const DIBasicType *BT : BasicTypes)
1066 emitOpStringIfNew(BT->getName(), MAI);
1067
1069 SubprogramDeclarations, SubprogramDefinitions)) {
1070 emitOpStringIfNew(SP->getName(), MAI);
1071 emitOpStringIfNew(SP->getLinkageName(), MAI);
1072 emitAndCacheScopePathOpStringReg(SP, MAI);
1073 }
1074
1075 // Cache the OpStrings each DebugTypeComposite and its DebugTypeMembers use:
1076 // the composite name, identifier (linkage name), and path, plus each member
1077 // name and path.
1078 for (const DICompositeType *CT : CompositeTypes) {
1079 emitOpStringIfNew(CT->getName(), MAI);
1080 emitOpStringIfNew(CT->getIdentifier(), MAI);
1081 emitAndCacheScopePathOpStringReg(CT->getFile(), MAI);
1082 for (const DINode *Element : CT->getElements()) {
1083 const auto *M = dyn_cast<DIDerivedType>(Element);
1084 if (!M || M->getTag() != dwarf::DW_TAG_member)
1085 continue;
1086 emitOpStringIfNew(M->getName(), MAI);
1087 emitAndCacheScopePathOpStringReg(M->getFile(), MAI);
1088 }
1089 }
1090
1091 // Cache the name and path OpStrings each DebugTypedef uses.
1092 for (const DIDerivedType *TD : TypedefTypes) {
1093 emitOpStringIfNew(TD->getName(), MAI);
1094 emitAndCacheScopePathOpStringReg(TD->getFile(), MAI);
1095 }
1096
1097 for (const auto &[GV, _] : GlobalVariableDebugInfoMap) {
1098 emitOpStringIfNew(GV->getName(), MAI);
1099 emitOpStringIfNew(GV->getLinkageName(), MAI);
1100 emitAndCacheScopePathOpStringReg(GV->getFile(), MAI);
1101 }
1102
1103 for (const DILocation *DL : UniqueDebugLocations)
1104 emitAndCacheScopePathOpStringReg(DL->getScope(), MAI);
1105
1106 CachedEmptyStringReg = emitOpStringIfNew("", MAI);
1107
1108#ifndef NDEBUG
1109 NonSemanticOpStringsSectionEmitted = true;
1110#endif
1111}
1112
1113void SPIRVNonSemanticDebugHandler::emitDebugFunctionDefinition(
1114 MCRegister DebugFunctionReg, MCRegister OpFunctionReg,
1116 assert(DebugFunctionReg.isValid() && OpFunctionReg.isValid() &&
1117 "DebugFunctionDefinition operands must be valid");
1118 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1119 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1120 emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDefinition, VoidTypeReg,
1121 ExtInstSetReg, {DebugFunctionReg, OpFunctionReg}, MAI);
1122}
1123
1124void SPIRVNonSemanticDebugHandler::resetPerFunctionDebugState() {
1125 CurrentMF = nullptr;
1126 LastFunctionOpVariable = nullptr;
1127 DebugFunctionDefinitionEmitted = false;
1128 LastLineMI = nullptr;
1129}
1130
1131void SPIRVNonSemanticDebugHandler::preparePerFunctionDebug(
1132 const MachineFunction *MF) {
1133 resetPerFunctionDebugState();
1134 if (!GlobalNSDIEnabled || !CurrentMAI)
1135 return;
1136
1137 CurrentMF = MF;
1138
1139 if (MF->getFunction()
1141 .isValid())
1142 return;
1143
1144 const DISubprogram *SP = MF->getFunction().getSubprogram();
1145 if (!SP || !SP->isDefinition())
1146 return;
1147
1148 // DebugFunctionDefinition is emitted after the last function-level
1149 // OpVariable. If there are none, it is emitted after the entry OpLabel.
1150 LastFunctionOpVariable =
1151 findLastFunctionOpVariableDeclaration(*MF, *CurrentMAI);
1152}
1153
1154void SPIRVNonSemanticDebugHandler::tryEmitDebugFunctionDefinition(
1156 if (DebugFunctionDefinitionEmitted || !GlobalNSDIEnabled)
1157 return;
1158
1159 assert(CurrentMF && "no current MachineFunction");
1160 const Function &F = CurrentMF->getFunction();
1161 const DISubprogram *SP = F.getSubprogram();
1162 if (!SP || !SP->isDefinition())
1163 return;
1164
1165 auto DFIt = DebugFunctionRegs.find(SP);
1166 if (DFIt == DebugFunctionRegs.end())
1167 return;
1168
1169 MCRegister OpFunctionReg = MAI.getGlobalObjReg(&F);
1170 if (!OpFunctionReg.isValid())
1171 return;
1172
1173 emitDebugFunctionDefinition(DFIt->second, OpFunctionReg, MAI);
1174 DebugFunctionDefinitionEmitted = true;
1175}
1176
1178 const MachineFunction *MF) {
1179 preparePerFunctionDebug(MF);
1180}
1181
1183 (void)MF;
1184 resetPerFunctionDebugState();
1185}
1186
1188 assert(CurMI == nullptr && "CurMI must be null");
1189 CurMI = MI;
1190
1191 if (!DebugFunctionDefinitionEmitted)
1192 return;
1193 emitDebugLineForInstruction(MI);
1194}
1195
1196static bool isMergeInstruction(unsigned Opcode) {
1197 return Opcode == SPIRV::OpSelectionMerge || Opcode == SPIRV::OpLoopMerge ||
1198 Opcode == SPIRV::OpLoopControlINTEL;
1199}
1200
1203 if (MAI.getSkipEmission(MI))
1204 return false;
1205 switch (MI->getOpcode()) {
1206 case SPIRV::OpFunction:
1207 case SPIRV::OpFunctionParameter:
1208 case SPIRV::OpFunctionEnd:
1209 case SPIRV::OpLabel:
1210 case SPIRV::OpPhi:
1211 return false;
1212 default:
1213 return true;
1214 }
1215}
1216
1217static const MachineInstr *
1219 SPIRV::ModuleAnalysisInfo &MAI, bool Forward) {
1220 for (const MachineInstr *Adj = Forward ? MI->getNextNode()
1221 : MI->getPrevNode();
1222 Adj; Adj = Forward ? Adj->getNextNode() : Adj->getPrevNode()) {
1223 if (MAI.getSkipEmission(Adj))
1224 continue;
1225 return Adj;
1226 }
1227 return nullptr;
1228}
1229
1230void SPIRVNonSemanticDebugHandler::emitDebugLineForInstruction(
1231 const MachineInstr *MI) {
1232 assert(DebugFunctionDefinitionEmitted &&
1233 "DebugFunctionDefinition must be emitted");
1234 assert(CurrentMAI && "CurrentMAI must be set");
1235
1236 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1237
1238 // Structural opcodes don't require a DebugLine, other opcodes might have
1239 // already been emitted in the module scope.
1240 if (!isDebugLineTarget(MI, MAI))
1241 return;
1242
1243 // DebugLine can be emitted before a merge instruction, but not after it
1244 // (nothing may sit between the merge and its terminator). We can use either
1245 // the merge's or the terminator's debug info; we emit the terminator's one.
1246 const MachineInstr *Prev = findAdjacentEmittedInstruction(MI, MAI, false);
1247 if (Prev && isMergeInstruction(Prev->getOpcode()))
1248 return;
1249
1250 if (isMergeInstruction(MI->getOpcode())) {
1251 // Use the terminator's debug info; when we reach it later, the check
1252 // above skips it.
1253 MI = findAdjacentEmittedInstruction(MI, MAI, true);
1254 assert(MI && "Merge instruction must be followed by a terminator");
1255 }
1256
1257 // The range of DebugLine must be reset at each basic block boundary.
1258 if (LastLineMI && MI->getParent() != LastLineMI->getParent())
1259 LastLineMI = nullptr;
1260
1261 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1262 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1263
1264 const DILocation *DL = MI->getDebugLoc().get();
1265 if (!DL) {
1266 // No location for the current instruction
1267 if (LastLineMI) {
1268 // Close the current DebugLine region.
1269 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoLine, VoidTypeReg,
1270 ExtInstSetReg, {}, MAI);
1271 LastLineMI = nullptr;
1272 }
1273 // No DebugLine region to close.
1274 return;
1275 }
1276
1277 // At this point, there is a location for the current instruction.
1278 // If it matches the last emitted DebugLine, no new DebugLine region is
1279 // needed. Otherwise, emit a new DebugLine region and update LastLineMI.
1280
1281 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1282 DL->getScope(), /*UseEmptyPathIfNullScope=*/true);
1283 unsigned Line = DL->getLine();
1284 unsigned Col = DL->getColumn();
1285
1286 MCRegister SrcReg = DebugSourceRegByFileStr.lookup(FileStrReg.id());
1287 MCRegister LineReg = I32ConstantCache.lookup(Line);
1288 MCRegister ColStartReg = I32ConstantCache.lookup(Col);
1289 MCRegister ColEndReg = I32ConstantCache.lookup(Col + 1);
1290
1291 // The elements of each collected DILocation (DebugSource, line/column
1292 // constants) are pre-emitted from LLVM-IR instruction !dbg attachments and
1293 // debug-program records; MIR is expected to reuse those same locations (or
1294 // carry none). A lookup miss means codegen attached a source position whose
1295 // elements were never pre-emitted, and debug-line emission is skipped.
1296 if (!SrcReg.isValid() || !LineReg.isValid() || !ColStartReg.isValid() ||
1297 !ColEndReg.isValid())
1298 return;
1299
1300 // Current location matches the last emitted DebugLine region.
1301 if (LastLineMI && MI->getDebugLoc() == LastLineMI->getDebugLoc())
1302 return;
1303
1304 // A new DebugLine region is needed. Emit it and update LastLineMI.
1305 emitExtInst(SPIRV::NonSemanticExtInst::DebugLine, VoidTypeReg, ExtInstSetReg,
1306 {SrcReg, LineReg, LineReg, ColStartReg, ColEndReg}, MAI);
1307
1308 LastLineMI = MI;
1309}
1310
1312 const MachineInstr *MI = CurMI;
1313 CurMI = nullptr;
1314
1315 if (!MI || !GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
1316 return;
1317
1318 if (MI != LastFunctionOpVariable)
1319 return;
1320
1321 // If this is the last function-level OpVariable, emit the
1322 // DebugFunctionDefinition. Otherwise, we had already done it before right
1323 // after the OpLabel (see notifyEntryLabelEmitted).
1324 assert(CurrentMAI && "CurrentMAI must be set");
1325 tryEmitDebugFunctionDefinition(*CurrentMAI);
1326}
1327
1329 const MachineFunction &MF) {
1330 if (!GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
1331 return;
1332
1333 assert(CurrentMF == &MF &&
1334 "notification does not match the current MachineFunction");
1335
1336 if (LastFunctionOpVariable)
1337 return;
1338
1339 // If there are no function-level OpVariables, emit the
1340 // DebugFunctionDefinition. Otherwise, DebugFunctionDefinition is emitted
1341 // after the last OpVariable (see endInstruction).
1342 tryEmitDebugFunctionDefinition(*CurrentMAI);
1343}
1344
1347 if (GlobalDIEmitted)
1348 return;
1349
1350 GlobalDIEmitted = true;
1351
1352 if (CompileUnits.empty()) {
1353 GlobalNSDIEnabled = false;
1354 return;
1355 }
1356
1357 // Retrieve the ext inst set register allocated by prepareModuleOutput().
1358 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
1359 if (!ExtInstSetReg.isValid()) {
1360 GlobalNSDIEnabled = false;
1361 return;
1362 }
1363
1364#ifndef NDEBUG
1365 assert(NonSemanticOpStringsSectionEmitted &&
1366 "emitNonSemanticDebugStrings() must run before "
1367 "emitNonSemanticGlobalDebugInfo()");
1368#endif
1369
1370 CurrentMAI = &MAI;
1371
1372 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1373 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1374
1375 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
1376 VoidTypeReg, ExtInstSetReg, {}, MAI);
1377
1378 // Emit integer constants shared across all NSDI instructions. The constant
1379 // cache ensures each value is emitted at most once even when referenced from
1380 // multiple instructions. All constants are pre-emitted before any DebugSource
1381 // so that the output order is: constants, then
1382 // DebugSource+DebugCompilationUnit pairs. This keeps OpConstant instructions
1383 // grouped before the OpExtInst instructions.
1384
1385 // The Version operand of DebugCompilationUnit is the version of the
1386 // NonSemantic.Shader.DebugInfo instruction set, which is 100 for
1387 // "NonSemantic.Shader.DebugInfo.100" (NonSemanticShaderDebugInfo100Version).
1388 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
1389 MCRegister DwarfVersionReg =
1390 emitOpConstantI32(static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
1391
1392 // Pre-emit source language constants for all compile units before entering
1393 // the DebugSource loop.
1394 SmallVector<MCRegister> SrcLangRegs =
1395 map_to_vector(CompileUnits, [&](const CompileUnitInfo &Info) {
1396 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
1397 });
1398
1399 // Emit DebugSource and DebugCompilationUnit for each compile unit.
1400 for (auto [Info, SrcLangReg] : llvm::zip(CompileUnits, SrcLangRegs)) {
1401 MCRegister FileStrReg = ScopeToPathOpStringReg.lookup(Info.TheCU);
1402 assert(FileStrReg.isValid() &&
1403 "CU path OpString must be emitted in emitNonSemanticDebugStrings");
1404 MCRegister DebugSourceReg = getOrEmitDebugSourceForFileStrReg(
1405 FileStrReg, VoidTypeReg, ExtInstSetReg, MAI);
1406 MCRegister CUDbgReg = emitExtInst(
1407 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
1408 ExtInstSetReg,
1409 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
1410 MAI);
1411 if (Info.TheCU)
1412 CUToCompilationUnitDbgReg[Info.TheCU] = CUDbgReg;
1413 }
1414
1415 // Zero constant used as the Flags operand in DebugTypeBasic and
1416 // DebugTypePointer. Cached with other i32 constants.
1417 MCRegister I32ZeroReg = emitOpConstantI32(0, I32TypeReg, MAI);
1418
1419 DebugTypeRegs.clear();
1420
1421 for (const DIBasicType *BT : BasicTypes) {
1422 MCRegister NameReg = getCachedOpStringReg(BT->getName());
1423 MCRegister SizeReg = emitOpConstantI32(
1424 static_cast<uint32_t>(BT->getSizeInBits()), I32TypeReg, MAI);
1425
1426 // Map DWARF base type encodings to NSDI encoding codes per
1427 // NonSemantic.Shader.DebugInfo.100 specification, section 4.5.
1428 unsigned Encoding = 0; // Unspecified
1429 switch (BT->getEncoding()) {
1430 case dwarf::DW_ATE_address:
1431 Encoding = 1;
1432 break;
1433 case dwarf::DW_ATE_boolean:
1434 Encoding = 2;
1435 break;
1436 case dwarf::DW_ATE_float:
1437 Encoding = 3;
1438 break;
1439 case dwarf::DW_ATE_signed:
1440 Encoding = 4;
1441 break;
1442 case dwarf::DW_ATE_signed_char:
1443 Encoding = 5;
1444 break;
1445 case dwarf::DW_ATE_unsigned:
1446 Encoding = 6;
1447 break;
1448 case dwarf::DW_ATE_unsigned_char:
1449 Encoding = 7;
1450 break;
1451 }
1452 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
1453
1454 MCRegister BTReg = emitExtInst(
1455 SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
1456 {NameReg, SizeReg, EncodingReg, I32ZeroReg}, MAI);
1457 DebugTypeRegs[BT] = BTReg;
1458 }
1459
1460 // Emit DebugTypeVector for each collected vector type.
1461 for (const DICompositeType *VT : VectorTypes) {
1462 if (auto VecReg = emitDebugTypeVector(VT, ExtInstSetReg, MAI))
1463 DebugTypeRegs[VT] = *VecReg;
1464 }
1465
1466 // Emit DebugTypePointer for each referenced pointer type.
1467 for (const DIDerivedType *PT : PointerTypes) {
1468 if (auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
1469 DebugTypeRegs[PT] = *PtrReg;
1470 }
1471
1472 // Emit DebugTypeArray for each collected array type. Placed after the basic,
1473 // vector, and pointer types so an array over any of them can resolve its
1474 // element id. An array whose element type was not emitted is skipped.
1475 for (const DICompositeType *AT : ArrayTypes) {
1476 if (auto ArrReg = emitDebugTypeArray(AT, ExtInstSetReg, MAI))
1477 DebugTypeRegs[AT] = *ArrReg;
1478 }
1479
1480 // Emit DebugTypeFunction for each distinct DISubroutineType.
1481 for (const DISubroutineType *ST : SubroutineTypes) {
1482 if (auto FnTyReg =
1483 emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI))
1484 DebugTypeRegs[ST] = *FnTyReg;
1485 }
1486
1487 // Emit DebugTypedef for each typedef. Placed after the other type loops so a
1488 // typedef can resolve its underlying type. A typedef whose base type is not
1489 // emitted is skipped. A typedef whose base is another typedef emitted later
1490 // in this same pass is also skipped, the emission-order gap tracked in
1491 // https://github.com/llvm/llvm-project/issues/211850.
1492 for (const DIDerivedType *TD : TypedefTypes) {
1493 if (auto TDReg =
1494 emitDebugTypedef(TD, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
1495 DebugTypeRegs[TD] = *TDReg;
1496 }
1497
1498 // Emit DebugFunctionDeclaration for DISubprogram declarations.
1499 for (const DISubprogram *SP : SubprogramDeclarations) {
1500 if (auto DeclReg = emitDebugFunctionDeclaration(SP, VoidTypeReg, I32TypeReg,
1501 ExtInstSetReg, MAI))
1502 DebugFunctionDeclarationRegs[SP] = *DeclReg;
1503 }
1504
1505 // Emit DebugTypeMember and DebugTypeComposite for each struct, class, or
1506 // union. Each member is emitted before the composite that lists it, so the
1507 // Members operand references already-defined ids. A member whose type is not
1508 // in DebugTypeRegs is skipped.
1509 for (const DICompositeType *CT : CompositeTypes) {
1510 SmallVector<MCRegister> MemberRegs;
1511 for (const DINode *Element : CT->getElements()) {
1512 const auto *M = dyn_cast<DIDerivedType>(Element);
1513 if (!M || M->getTag() != dwarf::DW_TAG_member)
1514 continue;
1515 if (auto MemberReg = emitDebugTypeMember(M, VoidTypeReg, I32TypeReg,
1516 ExtInstSetReg, MAI))
1517 MemberRegs.push_back(*MemberReg);
1518 }
1519 if (auto CompReg = emitDebugTypeComposite(CT, MemberRegs, VoidTypeReg,
1520 I32TypeReg, ExtInstSetReg, MAI))
1521 DebugTypeRegs[CT] = *CompReg;
1522 }
1523
1524 // Emit DebugFunction for DISubprogram definitions.
1525 for (const DISubprogram *SP : SubprogramDefinitions) {
1526 if (auto FnReg =
1527 emitDebugFunction(SP, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
1528 DebugFunctionRegs[SP] = *FnReg;
1529 }
1530
1531 // Emit DebugGlobalVariable for each collected DIGlobalVariable.
1532 for (const auto &[GV, Info] : GlobalVariableDebugInfoMap)
1533 emitDebugGlobalVariable(GV, Info, VoidTypeReg, I32TypeReg, ExtInstSetReg,
1534 MAI);
1535
1536 for (const DILocation *DL : UniqueDebugLocations) {
1537 emitOpConstantI32(DL->getLine(), I32TypeReg, MAI);
1538 emitOpConstantI32(DL->getColumn(), I32TypeReg, MAI);
1539 emitOpConstantI32(DL->getColumn() + 1, I32TypeReg, MAI);
1540 MCRegister FileStrReg =
1541 getCachedScopePathOpStringReg(DL->getScope(),
1542 /*UseEmptyPathIfNullScope=*/true);
1543 getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg, ExtInstSetReg,
1544 MAI);
1545 }
1546
1547 GlobalNSDIEnabled = true;
1548}
1549
1551SPIRVNonSemanticDebugHandler::getDebugFullPath(const DIScope *Scope) const {
1552 SmallString<128> Out;
1553 if (!Scope)
1554 return Out;
1555 StringRef Filename = Scope->getFilename();
1556 const auto Style = sys::path::Style::native;
1557 if (sys::path::is_absolute(Filename, Style))
1558 Out.assign(Filename.begin(), Filename.end());
1559 else {
1560 StringRef Dir = Scope->getDirectory();
1561 Out.assign(Dir.begin(), Dir.end());
1562 sys::path::append(Out, Style, Filename);
1563 }
1564 return Out;
1565}
1566
1567MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugSourceForFileStrReg(
1568 MCRegister FileStrReg, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
1570 const unsigned Key = FileStrReg.id();
1571 auto It = DebugSourceRegByFileStr.find(Key);
1572 if (It != DebugSourceRegByFileStr.end())
1573 return It->second;
1574
1575 MCRegister DS = emitExtInst(SPIRV::NonSemanticExtInst::DebugSource,
1576 VoidTypeReg, ExtInstSetReg, {FileStrReg}, MAI);
1577 DebugSourceRegByFileStr[Key] = DS;
1578 return DS;
1579}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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 bool isMergeInstruction(unsigned Opcode)
static bool isDebugLineTarget(const MachineInstr *MI, SPIRV::ModuleAnalysisInfo &MAI)
static void collectUniqueDebugLocations(const Module &M, SetVector< const DILocation * > &Out)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
Definition SPIRVUtils.h:546
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
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:261
Basic type, like 'int' or 'float'.
StringRef getIdentifier() const
DINodeArray getElements() const
DIType * getBaseType() const
DWARF expression.
A pair of DIGlobalVariable and DIExpression.
DIDerivedType * getStaticDataMemberDeclaration() const
StringRef getLinkageName() const
Tagged DWARF-like metadata node.
LLVM_ABI dwarf::Tag getTag() const
DIFlags
Debug info flags.
Base class for scope-like contexts.
DIFile * getFile() 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
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
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:250
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:299
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:762
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
Tracking metadata reference owned by Metadata.
Definition Metadata.h:891
bool equalsStr(StringRef Str) const
Definition Metadata.h:913
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.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
A tuple of MDNodes.
Definition Metadata.h:1755
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 assign(StringRef RHS)
Assign from a StringRef.
Definition SmallString.h:51
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
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM Value Representation.
Definition Value.h:75
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:830
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:1732
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
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:1151
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
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
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)