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"
17#include "llvm/IR/DebugInfo.h"
20#include "llvm/IR/Module.h"
21#include "llvm/MC/MCInst.h"
22#include "llvm/MC/MCStreamer.h"
24#include "llvm/Support/Path.h"
25#include <cassert>
26
27using namespace llvm;
28
29namespace {
30
31/// Look up \p Key in a register map and return its value, or std::nullopt when
32/// the key is absent.
33template <typename MapT>
34static std::optional<MCRegister> lookupOptReg(const MapT &Map,
35 typename MapT::key_type Key) {
36 auto It = Map.find(Key);
37 if (It == Map.end())
38 return std::nullopt;
39 assert(It->second.isValid() && "invalid register stored in map");
40 return It->second;
41}
42
43/// Partition \p Ty into \p BasicTypes, \p PointerTypes, \p SubroutineTypes,
44/// and \p VectorTypes for NSDI emission. Used when iterating
45/// DebugInfoFinder.types(); each DI node is seen once, so no recursion into
46/// pointer bases. Other composites and non-pointer derived kinds are ignored
47/// because they are not yet supported. Only types that are supported (later
48/// used) are partitioned.
49static void
50partitionTypes(const DIType *Ty, SmallVector<const DIBasicType *> &BasicTypes,
54 if (const auto *BT = dyn_cast<DIBasicType>(Ty)) {
55 BasicTypes.push_back(BT);
56 return;
57 }
58 if (const auto *ST = dyn_cast<DISubroutineType>(Ty)) {
59 SubroutineTypes.push_back(ST);
60 return;
61 }
62 if (const auto *CT = dyn_cast<DICompositeType>(Ty)) {
63 if (CT->getTag() == dwarf::DW_TAG_array_type && CT->isVector())
64 VectorTypes.push_back(CT);
65 return;
66 }
67 const auto *DT = dyn_cast<DIDerivedType>(Ty);
68 if (DT && DT->getTag() == dwarf::DW_TAG_pointer_type)
69 PointerTypes.push_back(DT);
70}
71
72enum : uint32_t {
73 NSDIFlagIsProtected = 1u << 0,
74 NSDIFlagIsPrivate = 1u << 1,
75 NSDIFlagIsPublic = NSDIFlagIsPrivate | NSDIFlagIsProtected,
76 NSDIFlagIsLocal = 1u << 2,
77 NSDIFlagIsDefinition = 1u << 3,
78 NSDIFlagFwdDecl = 1u << 4,
79 NSDIFlagArtificial = 1u << 5,
80 NSDIFlagExplicit = 1u << 6,
81 NSDIFlagPrototyped = 1u << 7,
82 NSDIFlagObjectPointer = 1u << 8,
83 NSDIFlagStaticMember = 1u << 9,
84 NSDIFlagIndirectVariable = 1u << 10,
85 NSDIFlagLValueReference = 1u << 11,
86 NSDIFlagRValueReference = 1u << 12,
87 NSDIFlagIsOptimized = 1u << 13,
88 NSDIFlagIsEnumClass = 1u << 14,
89 NSDIFlagTypePassByValue = 1u << 15,
90 NSDIFlagTypePassByReference = 1u << 16,
91 NSDIFlagUnknownPhysicalLayout = 1u << 17,
92};
93
94static uint32_t mapDIFlagsToNonSemantic(DINode::DIFlags DFlags) {
95 uint32_t Flags = 0;
96 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPublic)
97 Flags |= NSDIFlagIsPublic;
98 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagProtected)
99 Flags |= NSDIFlagIsProtected;
100 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPrivate)
101 Flags |= NSDIFlagIsPrivate;
102 if (DFlags & DINode::FlagFwdDecl)
103 Flags |= NSDIFlagFwdDecl;
104 if (DFlags & DINode::FlagArtificial)
105 Flags |= NSDIFlagArtificial;
106 if (DFlags & DINode::FlagExplicit)
107 Flags |= NSDIFlagExplicit;
108 if (DFlags & DINode::FlagPrototyped)
109 Flags |= NSDIFlagPrototyped;
110 if (DFlags & DINode::FlagObjectPointer)
111 Flags |= NSDIFlagObjectPointer;
112 if (DFlags & DINode::FlagStaticMember)
113 Flags |= NSDIFlagStaticMember;
114 if (DFlags & DINode::FlagLValueReference)
115 Flags |= NSDIFlagLValueReference;
116 if (DFlags & DINode::FlagRValueReference)
117 Flags |= NSDIFlagRValueReference;
118 if (DFlags & DINode::FlagTypePassByValue)
119 Flags |= NSDIFlagTypePassByValue;
120 if (DFlags & DINode::FlagTypePassByReference)
121 Flags |= NSDIFlagTypePassByReference;
122 if (DFlags & DINode::FlagEnumClass)
123 Flags |= NSDIFlagIsEnumClass;
124 return Flags;
125}
126
127static uint32_t transDebugFlags(const DINode *DN) {
128 uint32_t Flags = 0;
129 if (const auto *GV = dyn_cast<DIGlobalVariable>(DN)) {
130 if (GV->isLocalToUnit())
131 Flags |= NSDIFlagIsLocal;
132 if (GV->isDefinition())
133 Flags |= NSDIFlagIsDefinition;
134 }
135 if (const auto *SP = dyn_cast<DISubprogram>(DN)) {
136 if (SP->isLocalToUnit())
137 Flags |= NSDIFlagIsLocal;
138 if (SP->isOptimized())
139 Flags |= NSDIFlagIsOptimized;
140 if (SP->isDefinition())
141 Flags |= NSDIFlagIsDefinition;
142 Flags |= mapDIFlagsToNonSemantic(SP->getFlags());
143 }
144 if (DN->getTag() == dwarf::DW_TAG_reference_type)
145 Flags |= NSDIFlagLValueReference;
146 if (DN->getTag() == dwarf::DW_TAG_rvalue_reference_type)
147 Flags |= NSDIFlagRValueReference;
148 if (const auto *Ty = dyn_cast<DIType>(DN))
149 Flags |= mapDIFlagsToNonSemantic(Ty->getFlags());
150 if (const auto *LV = dyn_cast<DILocalVariable>(DN))
151 Flags |= mapDIFlagsToNonSemantic(LV->getFlags());
152 return Flags;
153}
154
155} // namespace
156
159
160// Map DWARF source language codes to NonSemantic.Shader.DebugInfo.100 source
161// language codes. Values are from the SourceLanguage enum in the
162// NonSemantic.Shader.DebugInfo.100 specification, section 4.3.
163unsigned SPIRVNonSemanticDebugHandler::toNSDISrcLang(unsigned DwarfSrcLang) {
164 switch (DwarfSrcLang) {
165 case dwarf::DW_LANG_OpenCL:
166 return 3; // OpenCL_C
167 case dwarf::DW_LANG_OpenCL_CPP:
168 return 4; // OpenCL_CPP
169 case dwarf::DW_LANG_CPP_for_OpenCL:
170 return 6; // CPP_for_OpenCL
171 case dwarf::DW_LANG_GLSL:
172 return 2; // GLSL
173 case dwarf::DW_LANG_HLSL:
174 return 5; // HLSL
175 case dwarf::DW_LANG_SYCL:
176 return 7; // SYCL
177 case dwarf::DW_LANG_Zig:
178 return 12; // Zig
179 default:
180 return 0; // Unknown
181 }
182}
183
185 // The base class sets Asm = nullptr when the module has no compile units,
186 // and initializes lexical scope tracking otherwise.
188
189 if (!Asm)
190 return;
191
192 CompileUnits.clear();
193 BasicTypes.clear();
194 PointerTypes.clear();
195 SubroutineTypes.clear();
196 VectorTypes.clear();
197 SubprogramDeclarations.clear();
198 GlobalVariableDebugInfoMap.clear();
199 DebugFunctionDeclarationRegs.clear();
200 ScopeToPathOpStringReg.clear();
201 CUToCompilationUnitDbgReg.clear();
202 DebugSourceRegByFileStr.clear();
203 DebugTypeRegs.clear();
204 OpStringContentCache.clear();
205 I32ConstantCache.clear();
206 DebugTypeFunctionCache.clear();
207 GlobalDIEmitted = false;
208#ifndef NDEBUG
209 NonSemanticOpStringsSectionEmitted = false;
210#endif
211 CachedDebugInfoNoneReg = MCRegister();
212 CachedEmptyStringReg = MCRegister();
213 CachedOpTypeVoidReg = MCRegister();
214 CachedOpTypeInt32Reg = MCRegister();
215
216 // Collect compile-unit info: file paths and source languages.
217 for (const DICompileUnit *CU : M->debug_compile_units()) {
218 const DIFile *File = CU->getFile();
219 CompileUnitInfo Info;
220 Info.TheCU = CU;
221 if (sys::path::is_absolute(File->getFilename()))
222 Info.FilePath = File->getFilename();
223 else
224 sys::path::append(Info.FilePath, File->getDirectory(),
225 File->getFilename());
226 // getName() returns the language code regardless of whether the name is
227 // versioned. getUnversionedName() would assert on versioned names.
228 Info.SpirvSourceLanguage = toNSDISrcLang(CU->getSourceLanguage().getName());
229 CompileUnits.push_back(std::move(Info));
230 }
231
232 // Collect DWARF version from module flags. For CodeView modules there is no
233 // "Dwarf Version" flag; DwarfVersion remains 0, which is the correct value
234 // for the DebugCompilationUnit DWARF Version operand in that case.
235 if (const NamedMDNode *Flags = M->getNamedMetadata("llvm.module.flags")) {
236 for (const auto *Op : Flags->operands()) {
237 const MDOperand &NameOp = Op->getOperand(1);
238 if (NameOp.equalsStr("Dwarf Version"))
239 DwarfVersion =
241 cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
242 ->getSExtValue();
243 }
244 }
245
246 // Find all debug info types that may be referenced by NSDI instructions.
247 DebugInfoFinder Finder;
248 Finder.processModule(*M);
249 llvm::for_each(Finder.types(), [&](DIType *Ty) {
250 partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes, VectorTypes);
251 });
252
253 for (const DISubprogram *SP : Finder.subprograms()) {
254 if (!SP->isDefinition())
255 SubprogramDeclarations.push_back(SP);
256 }
257
258 // Walk LLVM globals to map each DIGlobalVariable to its llvm::GlobalVariable.
260 for (const GlobalVariable &G : M->globals()) {
262 G.getDebugInfo(GVEs);
263 for (DIGlobalVariableExpression *GVE : GVEs) {
264 if (const DIGlobalVariable *GV = GVE->getVariable()) {
265 DIGVToLLVMGV.try_emplace(GV, &G);
266 }
267 }
268 }
269
270 for (const DIGlobalVariableExpression *GVE : Finder.global_variables()) {
271 const DIGlobalVariable *GV = GVE->getVariable();
272 const DIExpression *Expr = GVE->getExpression();
273 GlobalVariableDebugInfoMap.try_emplace(
274 GV, GlobalVariableDebugInfo{Expr, DIGVToLLVMGV.lookup(GV)});
275 }
276}
277
280 if (CompileUnits.empty())
281 return;
282 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_non_semantic_info))
283 return;
284
285 // Add the extension to requirements so OpExtension is output.
286 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
287
288 // Add the NonSemantic.Shader.DebugInfo.100 entry to ExtInstSetMap so that
289 // outputOpExtInstImports() emits the OpExtInstImport instruction. Allocate a
290 // fresh result ID for it now; the same ID is used in emitExtInst() operands.
291 constexpr unsigned NSSet = static_cast<unsigned>(
292 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100);
293 if (!MAI.ExtInstSetMap.count(NSSet))
294 MAI.ExtInstSetMap[NSSet] = MAI.getNextIDRegister();
295}
296
297void SPIRVNonSemanticDebugHandler::emitMCInst(MCInst &Inst) {
298 Asm->OutStreamer->emitInstruction(Inst, Asm->getSubtargetInfo());
299}
300
302SPIRVNonSemanticDebugHandler::emitOpString(StringRef S,
305 MCInst Inst;
306 Inst.setOpcode(SPIRV::OpString);
308 addStringImm(S, Inst);
309 emitMCInst(Inst);
310 return Reg;
311}
312
313MCRegister SPIRVNonSemanticDebugHandler::emitOpStringIfNew(
315#ifndef NDEBUG
316 assert(!NonSemanticOpStringsSectionEmitted &&
317 "emitOpStringIfNew is only valid while emitting SPIR-V section 7");
318#endif
319 auto [It, Inserted] = OpStringContentCache.try_emplace(S, MCRegister());
320 if (Inserted)
321 It->second = emitOpString(S, MAI);
322
323 return It->second;
324}
325
326MCRegister SPIRVNonSemanticDebugHandler::getCachedOpStringReg(StringRef S) {
327#ifndef NDEBUG
328 assert(NonSemanticOpStringsSectionEmitted &&
329 "getCachedOpStringReg requires emitNonSemanticDebugStrings() first");
330#endif
331 auto It = OpStringContentCache.find(S);
332 assert(It != OpStringContentCache.end() &&
333 "NSDI OpString missing from cache; emitNonSemanticDebugStrings must "
334 "cache every string used in section 10");
335 return It->second;
336}
337
338MCRegister SPIRVNonSemanticDebugHandler::getCachedScopePathOpStringReg(
339 const DIScope *Scope, bool UseEmptyPathIfNullScope) {
340 if (!Scope) {
341 assert(UseEmptyPathIfNullScope &&
342 "null scope path lookup requires UseEmptyPathIfNullScope");
343 assert(CachedEmptyStringReg.isValid() &&
344 "empty path OpString must be cached in emitNonSemanticDebugStrings");
345 return CachedEmptyStringReg;
346 }
347 auto It = ScopeToPathOpStringReg.find(Scope);
348 assert(It != ScopeToPathOpStringReg.end() &&
349 "path OpString must be cached in emitNonSemanticDebugStrings");
350 MCRegister FileStrReg = It->second;
351 assert(FileStrReg.isValid() && "path OpString id must be valid once cached");
352 return FileStrReg;
353}
354
355MCRegister SPIRVNonSemanticDebugHandler::emitOpConstantI32(
356 uint32_t Value, MCRegister I32TypeReg, SPIRV::ModuleAnalysisInfo &MAI) {
357 auto [It, Inserted] = I32ConstantCache.try_emplace(Value);
358 if (!Inserted)
359 return It->second;
360
361 MCRegister Reg = MAI.getNextIDRegister();
362 It->second = Reg;
363 MCInst Inst;
364 Inst.setOpcode(SPIRV::OpConstantI);
366 Inst.addOperand(MCOperand::createReg(I32TypeReg));
367 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Value)));
368 emitMCInst(Inst);
369 return Reg;
370}
371
372MCRegister SPIRVNonSemanticDebugHandler::emitExtInst(
373 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
374 MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
376 MCRegister Reg = MAI.getNextIDRegister();
377 MCInst Inst;
378 Inst.setOpcode(SPIRV::OpExtInst);
380 Inst.addOperand(MCOperand::createReg(VoidTypeReg));
381 Inst.addOperand(MCOperand::createReg(ExtInstSetReg));
382 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Opcode)));
383 for (MCRegister R : Operands)
385 emitMCInst(Inst);
386 return Reg;
387}
388
389MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugTypeFunction(
390 ArrayRef<MCRegister> Ops, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
392 auto [It, Inserted] =
393 DebugTypeFunctionCache.try_emplace(SmallVector<MCRegister, 8>(Ops));
394 if (!Inserted)
395 return It->second;
396
397 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeFunction,
398 VoidTypeReg, ExtInstSetReg, Ops, MAI);
399 It->second = Reg;
400 return Reg;
401}
402
403MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeVoidReg(
405 if (!CachedOpTypeVoidReg.isValid())
406 CachedOpTypeVoidReg = findOrEmitOpTypeVoid(MAI);
407 return CachedOpTypeVoidReg;
408}
409
410MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeInt32Reg(
412 if (!CachedOpTypeInt32Reg.isValid())
413 CachedOpTypeInt32Reg = findOrEmitOpTypeInt32(MAI);
414 return CachedOpTypeInt32Reg;
415}
416
417MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
419 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
420 if (MI->getOpcode() == SPIRV::OpTypeVoid)
421 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
422 }
423 MCRegister Reg = MAI.getNextIDRegister();
424 MCInst Inst;
425 Inst.setOpcode(SPIRV::OpTypeVoid);
427 emitMCInst(Inst);
428 return Reg;
429}
430
431MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
433 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
434 if (MI->getOpcode() == SPIRV::OpTypeInt &&
435 MI->getOperand(1).getImm() == 32 && MI->getOperand(2).getImm() == 0)
436 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
437 }
438 MCRegister Reg = MAI.getNextIDRegister();
439 MCInst Inst;
440 Inst.setOpcode(SPIRV::OpTypeInt);
442 Inst.addOperand(MCOperand::createImm(32)); // width
443 Inst.addOperand(MCOperand::createImm(0)); // signedness (unsigned)
444 emitMCInst(Inst);
445 return Reg;
446}
447
448std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
449 const DIDerivedType *PT, MCRegister ExtInstSetReg,
451 // A DWARF address space is required to determine the SPIR-V storage class.
452 // Skip pointer types that do not carry one.
453 if (!PT->getDWARFAddressSpace().has_value())
454 return std::nullopt;
455
456 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
457 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
458 MCRegister DebugTypePointerFlagsReg =
459 emitOpConstantI32(transDebugFlags(PT), I32TypeReg, MAI);
460
461 // For SPIR-V targets, Clang sets DwarfAddressSpace to the LLVM IR address
462 // space, which addressSpaceToStorageClass expects.
463 const auto &ST = static_cast<const SPIRVSubtarget &>(Asm->getSubtargetInfo());
464 MCRegister StorageClassReg = emitOpConstantI32(
465 addressSpaceToStorageClass(PT->getDWARFAddressSpace().value(), ST),
466 I32TypeReg, MAI);
467
468 if (const DIType *BaseTy = PT->getBaseType()) {
469 auto BaseIt = DebugTypeRegs.find(BaseTy);
470 if (BaseIt != DebugTypeRegs.end())
471 return emitExtInst(
472 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
473 ExtInstSetReg,
474 {BaseIt->second, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
475 // Unsupported type, no DebugType* id available.
476 return std::nullopt;
477 }
478 // No getBaseType() (typical for void*): use DebugInfoNone as Base Type,
479 // same as SPIRV-LLVM-Translator (see issue #109287 and the DISABLED
480 // spirv-val run in debug-type-pointer.ll). spirv-val may still reject this
481 // encoding; see https://github.com/KhronosGroup/SPIRV-Registry/pull/287.
482 return emitExtInst(
483 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg, ExtInstSetReg,
484 {CachedDebugInfoNoneReg, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
485}
486
487std::optional<MCRegister>
488SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
489 const DISubroutineType *ST, MCRegister ExtInstSetReg,
491 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
492 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
493 MCRegister DebugTypeFunctionFlagsReg =
494 emitOpConstantI32(transDebugFlags(ST), I32TypeReg, MAI);
495 DITypeArray TA = ST->getTypeArray();
497 Ops.push_back(DebugTypeFunctionFlagsReg);
498 // Empty DI type tuple: no explicit return or parameter slots (hand-written IR
499 // may use !{}). Emit void-only prototype. Same as SPIRV-LLVM-Translator when
500 // DISubroutineType::getTypeArray() has zero elements.
501 if (TA.empty()) {
502 Ops.push_back(VoidTypeReg);
503 } else {
504 for (unsigned I = 0, E = TA.size(); I != E; ++I) {
505 bool IsReturnType = (I == 0);
506 auto OptReg = mapDISignatureTypeToReg(TA[I], VoidTypeReg, IsReturnType);
507 // No emitted DebugType* id for this slot (e.g., pointer that
508 // was skipped due missing address space, etc.).
509 if (!OptReg)
510 return std::nullopt;
511 Ops.push_back(*OptReg);
512 }
513 }
514 return getOrEmitDebugTypeFunction(Ops, VoidTypeReg, ExtInstSetReg, MAI);
515}
516
517// Match SPIRV-LLVM-Translator's selection logic for the Parent operand.
518std::optional<MCRegister>
519SPIRVNonSemanticDebugHandler::resolveDebugFunctionDeclarationParent(
520 const DISubprogram *SP) const {
521 const DIScope *Scope = SP->getScope();
522 if (Scope && !isa<DIFile>(Scope)) {
523 // TODO: Complete with other lookups once other scopes are supported
524 // (subclasses of DIScope).
525 const DIType *Ty = dyn_cast<DIType>(Scope);
526 if (!Ty)
527 return std::nullopt;
528 return lookupOptReg(DebugTypeRegs, Ty);
529 }
530
531 const DICompileUnit *ParentCU = SP->getUnit();
532 if (!ParentCU && !CompileUnits.empty())
533 ParentCU = CompileUnits[0].TheCU;
534 if (!ParentCU)
535 return std::nullopt;
536 return lookupOptReg(CUToCompilationUnitDbgReg, ParentCU);
537}
538
539std::optional<MCRegister>
540SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
541 const DISubprogram *SP, MCRegister VoidTypeReg, MCRegister I32TypeReg,
542 MCRegister ExtInstSetReg, SPIRV::ModuleAnalysisInfo &MAI) {
543 assert(SP && "SP must not be null in emitDebugFunctionDeclaration");
544 assert(!SP->isDefinition() &&
545 "SP must not be a definition in emitDebugFunctionDeclaration");
546
547 // The IR verifier already enforces that this cannot be null.
548 const DISubroutineType *ST = SP->getType();
549
550 auto FnTyRegOpt = lookupOptReg(DebugTypeRegs, ST);
551 if (!FnTyRegOpt)
552 return std::nullopt;
553 MCRegister FnTyReg = *FnTyRegOpt;
554
555 auto ParentRegOpt = resolveDebugFunctionDeclarationParent(SP);
556 if (!ParentRegOpt)
557 return std::nullopt;
558
559 MCRegister ParentReg = *ParentRegOpt;
560
561 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
562
563 MCRegister NameReg = getCachedOpStringReg(SP->getName());
564 MCRegister LinkageReg = getCachedOpStringReg(SP->getLinkageName());
565 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
566 ExtInstSetReg, MAI);
567
568 MCRegister LineReg =
569 emitOpConstantI32(static_cast<uint32_t>(SP->getLine()), I32TypeReg, MAI);
570 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
571
572 uint32_t FlagsVal = transDebugFlags(SP);
573 // TODO: When composite scopes are DebugFunctionDeclaration parents (available
574 // in DebugTypeRegs), sync declaration Flags with SPIRV-LLVM-Translator.
575 FlagsVal &= ~NSDIFlagIsDefinition;
576 MCRegister FlagsReg = emitOpConstantI32(FlagsVal, I32TypeReg, MAI);
577
578 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
579 VoidTypeReg, ExtInstSetReg,
580 {NameReg, FnTyReg, SrcReg, LineReg, ColReg, ParentReg,
581 LinkageReg, FlagsReg},
582 MAI);
583}
584
585std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
586 const DIType *Ty, MCRegister VoidTypeReg, bool ReturnType) {
587 if (!Ty) {
588 if (ReturnType)
589 return VoidTypeReg;
590 assert(CachedDebugInfoNoneReg.isValid() &&
591 "DebugInfoNone must be emitted before DISubroutineType operands");
592 return CachedDebugInfoNoneReg;
593 }
594 return lookupOptReg(DebugTypeRegs, Ty);
595}
596
597MCRegister SPIRVNonSemanticDebugHandler::resolveGlobalVariableParent(
598 const DIGlobalVariable *) const {
599 // TODO: When this backend emits debug instructions for namespace, subprogram,
600 // compilation units, and module scopes return GV->getScope()'s debug id.
601
602 // !CompileUnits.empty() was already checked before staring the emission of
603 // NSDI instructions.
604 assert(!CompileUnits.empty() &&
605 "resolveGlobalVariableParent requires non-empty CompileUnits");
606 std::optional<MCRegister> ParentRegOpt =
607 lookupOptReg(CUToCompilationUnitDbgReg, CompileUnits[0].TheCU);
608 assert(ParentRegOpt && "DebugCompilationUnit must be emitted before "
609 "resolveGlobalVariableParent");
610 // Fallback: first module compile unit (SPIRV-LLVM-Translator default).
611 return *ParentRegOpt;
612}
613
614// Unimplemented no-op; see emitDebugExpression declaration.
615std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugExpression(
617 return std::nullopt;
618}
619
620std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugGlobalVariable(
621 const DIGlobalVariable *GV, const GlobalVariableDebugInfo &Info,
622 MCRegister VoidTypeReg, MCRegister I32TypeReg, MCRegister ExtInstSetReg,
624 assert(GV && "GV must not be null in emitDebugGlobalVariable");
625
626 MCRegister ParentReg = resolveGlobalVariableParent(GV);
627
628 // TyReg: DebugInfoNone when GV has no DI type (as done in
629 // SPIRV-LLVM-Translator). Declarations (isDefinition: false) can have null
630 // getType() while definitions must have a non-null one (enforced by the IR
631 // verifier).
632 MCRegister TyReg = CachedDebugInfoNoneReg;
633 if (const DIType *Ty = GV->getType()) {
634 auto TyRegOpt = lookupOptReg(DebugTypeRegs, Ty);
635 if (!TyRegOpt)
636 return std::nullopt;
637 TyReg = *TyRegOpt;
638 }
639
640 std::optional<MCRegister> StaticMemberRegOpt;
641 if (const DIDerivedType *SM = GV->getStaticDataMemberDeclaration()) {
642 StaticMemberRegOpt = lookupOptReg(DebugTypeRegs, SM);
643 if (!StaticMemberRegOpt)
644 return std::nullopt;
645 }
646
647 MCRegister NameReg = getCachedOpStringReg(GV->getName());
648 MCRegister LinkageReg = getCachedOpStringReg(GV->getLinkageName());
649 MCRegister FileStrReg = getCachedScopePathOpStringReg(
650 GV->getFile(), /*UseEmptyPathIfNullScope=*/true);
651 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
652 ExtInstSetReg, MAI);
653
654 MCRegister LineReg =
655 emitOpConstantI32(static_cast<uint32_t>(GV->getLine()), I32TypeReg, MAI);
656 // DIGlobalVariable or DIGlobalVariableExpression metadata carry no column
657 // field. Column is hardcoded to 0 (because it can't be determined), matching
658 // SPIRV-LLVM-Translator.
659 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
660
661 // Variable: @g OpVariable id when !dbg matches; else a DebugExpression for
662 // the GVE init value when no @g exists; else DebugInfoNone.
663 MCRegister VariableReg = CachedDebugInfoNoneReg;
664 if (const GlobalVariable *LLVMGV = Info.LLVMGV) {
665 MCRegister GVReg = MAI.getGlobalObjReg(LLVMGV);
666 if (GVReg.isValid())
667 VariableReg = GVReg;
668 } else if (Info.Expr) {
669 if (auto ExprReg =
670 emitDebugExpression(Info.Expr, VoidTypeReg, ExtInstSetReg, MAI))
671 VariableReg = *ExprReg;
672 }
673
674 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(GV), I32TypeReg, MAI);
675
676 SmallVector<MCRegister, 10> Ops = {NameReg, TyReg, SrcReg,
677 LineReg, ColReg, ParentReg,
678 LinkageReg, VariableReg, FlagsReg};
679
680 if (StaticMemberRegOpt)
681 Ops.push_back(*StaticMemberRegOpt);
682
683 return emitExtInst(SPIRV::NonSemanticExtInst::DebugGlobalVariable,
684 VoidTypeReg, ExtInstSetReg, Ops, MAI);
685}
686
687std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
688 const DICompositeType *VT, MCRegister ExtInstSetReg,
690 const auto *BaseTy = dyn_cast_or_null<DIBasicType>(VT->getBaseType());
691 if (!BaseTy)
692 return std::nullopt;
693 auto BTIt = DebugTypeRegs.find(BaseTy);
694 if (BTIt == DebugTypeRegs.end())
695 return std::nullopt;
696
697 // DebugTypeVector models only 1D vectors (multi-subrange types cannot be
698 // encoded).
699 DINodeArray Elements = VT->getElements();
700 if (Elements.size() != 1)
701 return std::nullopt;
702 const auto *SR = cast<DISubrange>(Elements[0]);
703 const auto *CI = dyn_cast_if_present<ConstantInt *>(SR->getCount());
704 if (!CI)
705 return std::nullopt;
706
707 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
708 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
709 MCRegister CountReg = emitOpConstantI32(
710 static_cast<uint32_t>(CI->getZExtValue()), I32TypeReg, MAI);
711 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeVector, VoidTypeReg,
712 ExtInstSetReg, {BTIt->second, CountReg}, MAI);
713}
714
717 if (CompileUnits.empty())
718 return;
719 // Check that prepareModuleOutput() registered the extended instruction set.
720 // If the subtarget does not support the extension, neither strings nor ext
721 // insts are emitted.
722 constexpr unsigned NSSet = static_cast<unsigned>(
723 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100);
724 if (!MAI.getExtInstSetReg(NSSet).isValid())
725 return;
726
727 for (const CompileUnitInfo &Info : CompileUnits) {
728 if (Info.TheCU) {
729 MCRegister PathReg = emitOpStringIfNew(Info.FilePath, MAI);
730 ScopeToPathOpStringReg[Info.TheCU] = PathReg;
731 if (const DIFile *F = Info.TheCU->getFile())
732 ScopeToPathOpStringReg[F] = PathReg;
733 }
734 }
735
736 for (const DIBasicType *BT : BasicTypes)
737 emitOpStringIfNew(BT->getName(), MAI);
738
739 for (const DISubprogram *SP : SubprogramDeclarations) {
740 emitOpStringIfNew(SP->getName(), MAI);
741 emitOpStringIfNew(SP->getLinkageName(), MAI);
742 ScopeToPathOpStringReg[SP] = emitOpStringIfNew(getDebugFullPath(SP), MAI);
743 }
744
745 for (const auto &[GV, _] : GlobalVariableDebugInfoMap) {
746 emitOpStringIfNew(GV->getName(), MAI);
747 emitOpStringIfNew(GV->getLinkageName(), MAI);
748 SmallString<128> Path = getDebugFullPath(GV->getFile());
749 MCRegister PathReg = emitOpStringIfNew(Path, MAI);
750 if (const DIFile *F = GV->getFile())
751 ScopeToPathOpStringReg[F] = PathReg;
752 }
753
754 CachedEmptyStringReg = emitOpStringIfNew("", MAI);
755
756#ifndef NDEBUG
757 NonSemanticOpStringsSectionEmitted = true;
758#endif
759}
760
763 if (GlobalDIEmitted || CompileUnits.empty())
764 return;
765 GlobalDIEmitted = true;
766
767 // Retrieve the ext inst set register allocated by prepareModuleOutput().
768 constexpr unsigned NSSet = static_cast<unsigned>(
769 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100);
770 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
771 if (!ExtInstSetReg.isValid())
772 return; // Extension not available.
773
774#ifndef NDEBUG
775 assert(NonSemanticOpStringsSectionEmitted &&
776 "emitNonSemanticDebugStrings() must run before "
777 "emitNonSemanticGlobalDebugInfo()");
778#endif
779
780 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
781 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
782
783 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
784 VoidTypeReg, ExtInstSetReg, {}, MAI);
785
786 // Emit integer constants shared across all NSDI instructions. The constant
787 // cache ensures each value is emitted at most once even when referenced from
788 // multiple instructions. All constants are pre-emitted before any DebugSource
789 // so that the output order is: constants, then
790 // DebugSource+DebugCompilationUnit pairs. This keeps OpConstant instructions
791 // grouped before the OpExtInst instructions.
792
793 // The Version operand of DebugCompilationUnit is the version of the
794 // NonSemantic.Shader.DebugInfo instruction set, which is 100 for
795 // "NonSemantic.Shader.DebugInfo.100" (NonSemanticShaderDebugInfo100Version).
796 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
797 MCRegister DwarfVersionReg =
798 emitOpConstantI32(static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
799
800 // Pre-emit source language constants for all compile units before entering
801 // the DebugSource loop.
802 SmallVector<MCRegister> SrcLangRegs =
803 map_to_vector(CompileUnits, [&](const CompileUnitInfo &Info) {
804 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
805 });
806
807 // Emit DebugSource and DebugCompilationUnit for each compile unit.
808 for (auto [Info, SrcLangReg] : llvm::zip(CompileUnits, SrcLangRegs)) {
809 MCRegister FileStrReg = ScopeToPathOpStringReg.lookup(Info.TheCU);
810 assert(FileStrReg.isValid() &&
811 "CU path OpString must be emitted in emitNonSemanticDebugStrings");
812 MCRegister DebugSourceReg = getOrEmitDebugSourceForFileStrReg(
813 FileStrReg, VoidTypeReg, ExtInstSetReg, MAI);
814 MCRegister CUDbgReg = emitExtInst(
815 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
816 ExtInstSetReg,
817 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
818 MAI);
819 if (Info.TheCU)
820 CUToCompilationUnitDbgReg[Info.TheCU] = CUDbgReg;
821 }
822
823 // Zero constant used as the Flags operand in DebugTypeBasic and
824 // DebugTypePointer. Cached with other i32 constants.
825 MCRegister I32ZeroReg = emitOpConstantI32(0, I32TypeReg, MAI);
826
827 DebugTypeRegs.clear();
828
829 for (const DIBasicType *BT : BasicTypes) {
830 MCRegister NameReg = getCachedOpStringReg(BT->getName());
831 MCRegister SizeReg = emitOpConstantI32(
832 static_cast<uint32_t>(BT->getSizeInBits()), I32TypeReg, MAI);
833
834 // Map DWARF base type encodings to NSDI encoding codes per
835 // NonSemantic.Shader.DebugInfo.100 specification, section 4.5.
836 unsigned Encoding = 0; // Unspecified
837 switch (BT->getEncoding()) {
838 case dwarf::DW_ATE_address:
839 Encoding = 1;
840 break;
841 case dwarf::DW_ATE_boolean:
842 Encoding = 2;
843 break;
844 case dwarf::DW_ATE_float:
845 Encoding = 3;
846 break;
847 case dwarf::DW_ATE_signed:
848 Encoding = 4;
849 break;
850 case dwarf::DW_ATE_signed_char:
851 Encoding = 5;
852 break;
853 case dwarf::DW_ATE_unsigned:
854 Encoding = 6;
855 break;
856 case dwarf::DW_ATE_unsigned_char:
857 Encoding = 7;
858 break;
859 }
860 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
861
862 MCRegister BTReg = emitExtInst(
863 SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
864 {NameReg, SizeReg, EncodingReg, I32ZeroReg}, MAI);
865 DebugTypeRegs[BT] = BTReg;
866 }
867
868 // Emit DebugTypeVector for each collected vector type.
869 for (const DICompositeType *VT : VectorTypes) {
870 if (auto VecReg = emitDebugTypeVector(VT, ExtInstSetReg, MAI))
871 DebugTypeRegs[VT] = *VecReg;
872 }
873
874 // Emit DebugTypePointer for each referenced pointer type.
875 for (const DIDerivedType *PT : PointerTypes) {
876 if (auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
877 DebugTypeRegs[PT] = *PtrReg;
878 }
879
880 // Emit DebugTypeFunction for each distinct DISubroutineType.
881 for (const DISubroutineType *ST : SubroutineTypes) {
882 if (auto FnTyReg =
883 emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI))
884 DebugTypeRegs[ST] = *FnTyReg;
885 }
886
887 // Emit DebugFunctionDeclaration for DISubprogram declarations.
888 for (const DISubprogram *SP : SubprogramDeclarations) {
889 if (auto DeclReg = emitDebugFunctionDeclaration(SP, VoidTypeReg, I32TypeReg,
890 ExtInstSetReg, MAI))
891 DebugFunctionDeclarationRegs[SP] = *DeclReg;
892 }
893
894 // Emit DebugGlobalVariable for each collected DIGlobalVariable.
895 for (const auto &[GV, Info] : GlobalVariableDebugInfoMap)
896 emitDebugGlobalVariable(GV, Info, VoidTypeReg, I32TypeReg, ExtInstSetReg,
897 MAI);
898}
899
901SPIRVNonSemanticDebugHandler::getDebugFullPath(const DIScope *Scope) const {
903 if (!Scope)
904 return Out;
905 StringRef Filename = Scope->getFilename();
906 const auto Style = sys::path::Style::native;
908 Out.assign(Filename.begin(), Filename.end());
909 else {
910 StringRef Dir = Scope->getDirectory();
911 Out.assign(Dir.begin(), Dir.end());
912 sys::path::append(Out, Style, Filename);
913 }
914 return Out;
915}
916
917MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugSourceForFileStrReg(
918 MCRegister FileStrReg, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
920 const unsigned Key = FileStrReg.id();
921 auto It = DebugSourceRegByFileStr.find(Key);
922 if (It != DebugSourceRegByFileStr.end())
923 return It->second;
924
925 MCRegister DS = emitExtInst(SPIRV::NonSemanticExtInst::DebugSource,
926 VoidTypeReg, ExtInstSetReg, {FileStrReg}, MAI);
927 DebugSourceRegByFileStr[Key] = DS;
928 return DS;
929}
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
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
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.
Basic type, like 'int' or 'float'.
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.
Subprogram description. Uses SubclassData1.
Type array for a subprogram.
Base class for types.
DIFile * getFile() const
DIType * getType() const
unsigned getLine() const
StringRef getName() const
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
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
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:1753
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 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...
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
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
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)
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)
MCRegister getGlobalObjReg(const GlobalObject *GO)
void addExtension(Extension::Extension ToAdd)