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