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