LLVM 23.0.0git
SPIRVNonSemanticDebugHandler.cpp
Go to the documentation of this file.
1//===-- SPIRVNonSemanticDebugHandler.cpp - NSDI AsmPrinter handler -*- C++
2//-*-===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
12#include "SPIRVSubtarget.h"
13#include "SPIRVUtils.h"
17#include "llvm/IR/DebugInfo.h"
19#include "llvm/IR/Module.h"
20#include "llvm/MC/MCInst.h"
21#include "llvm/MC/MCStreamer.h"
23#include "llvm/Support/Path.h"
24#include <cassert>
25
26using namespace llvm;
27
28namespace {
29
30/// Partition \p Ty into \p BasicTypes, \p PointerTypes, and \p SubroutineTypes
31/// for NSDI emission. Used when iterating DebugInfoFinder.types(); each DI
32/// node is seen once, so no recursion into pointer bases. Other composites and
33/// non-pointer derived kinds are ignored because they are not yet supported.
34/// Only types that are supported (later used) are partitioned.
35static void
36partitionTypes(const DIType *Ty, SmallVector<const DIBasicType *> &BasicTypes,
39 if (const auto *BT = dyn_cast<DIBasicType>(Ty)) {
40 BasicTypes.push_back(BT);
41 return;
42 }
43 if (const auto *ST = dyn_cast<DISubroutineType>(Ty)) {
44 SubroutineTypes.push_back(ST);
45 return;
46 }
47 const auto *DT = dyn_cast<DIDerivedType>(Ty);
48 if (DT && DT->getTag() == dwarf::DW_TAG_pointer_type)
49 PointerTypes.push_back(DT);
50}
51
52enum : uint32_t {
53 NSDIFlagIsProtected = 1u << 0,
54 NSDIFlagIsPrivate = 1u << 1,
55 NSDIFlagIsPublic = NSDIFlagIsPrivate | NSDIFlagIsProtected,
56 NSDIFlagIsLocal = 1u << 2,
57 NSDIFlagIsDefinition = 1u << 3,
58 NSDIFlagFwdDecl = 1u << 4,
59 NSDIFlagArtificial = 1u << 5,
60 NSDIFlagExplicit = 1u << 6,
61 NSDIFlagPrototyped = 1u << 7,
62 NSDIFlagObjectPointer = 1u << 8,
63 NSDIFlagStaticMember = 1u << 9,
64 NSDIFlagIndirectVariable = 1u << 10,
65 NSDIFlagLValueReference = 1u << 11,
66 NSDIFlagRValueReference = 1u << 12,
67 NSDIFlagIsOptimized = 1u << 13,
68 NSDIFlagIsEnumClass = 1u << 14,
69 NSDIFlagTypePassByValue = 1u << 15,
70 NSDIFlagTypePassByReference = 1u << 16,
71 NSDIFlagUnknownPhysicalLayout = 1u << 17,
72};
73
74static uint32_t mapDIFlagsToNonSemantic(DINode::DIFlags DFlags) {
75 uint32_t Flags = 0;
76 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPublic)
77 Flags |= NSDIFlagIsPublic;
78 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagProtected)
79 Flags |= NSDIFlagIsProtected;
80 if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPrivate)
81 Flags |= NSDIFlagIsPrivate;
82 if (DFlags & DINode::FlagFwdDecl)
83 Flags |= NSDIFlagFwdDecl;
84 if (DFlags & DINode::FlagArtificial)
85 Flags |= NSDIFlagArtificial;
86 if (DFlags & DINode::FlagExplicit)
87 Flags |= NSDIFlagExplicit;
88 if (DFlags & DINode::FlagPrototyped)
89 Flags |= NSDIFlagPrototyped;
90 if (DFlags & DINode::FlagObjectPointer)
91 Flags |= NSDIFlagObjectPointer;
92 if (DFlags & DINode::FlagStaticMember)
93 Flags |= NSDIFlagStaticMember;
94 if (DFlags & DINode::FlagLValueReference)
95 Flags |= NSDIFlagLValueReference;
96 if (DFlags & DINode::FlagRValueReference)
97 Flags |= NSDIFlagRValueReference;
98 if (DFlags & DINode::FlagTypePassByValue)
99 Flags |= NSDIFlagTypePassByValue;
100 if (DFlags & DINode::FlagTypePassByReference)
101 Flags |= NSDIFlagTypePassByReference;
102 if (DFlags & DINode::FlagEnumClass)
103 Flags |= NSDIFlagIsEnumClass;
104 return Flags;
105}
106
107static uint32_t transDebugFlags(const DINode *DN) {
108 uint32_t Flags = 0;
109 if (const auto *GV = dyn_cast<DIGlobalVariable>(DN)) {
110 if (GV->isLocalToUnit())
111 Flags |= NSDIFlagIsLocal;
112 if (GV->isDefinition())
113 Flags |= NSDIFlagIsDefinition;
114 }
115 if (const auto *SP = dyn_cast<DISubprogram>(DN)) {
116 if (SP->isLocalToUnit())
117 Flags |= NSDIFlagIsLocal;
118 if (SP->isOptimized())
119 Flags |= NSDIFlagIsOptimized;
120 if (SP->isDefinition())
121 Flags |= NSDIFlagIsDefinition;
122 Flags |= mapDIFlagsToNonSemantic(SP->getFlags());
123 }
124 if (DN->getTag() == dwarf::DW_TAG_reference_type)
125 Flags |= NSDIFlagLValueReference;
126 if (DN->getTag() == dwarf::DW_TAG_rvalue_reference_type)
127 Flags |= NSDIFlagRValueReference;
128 if (const auto *Ty = dyn_cast<DIType>(DN))
129 Flags |= mapDIFlagsToNonSemantic(Ty->getFlags());
130 if (const auto *LV = dyn_cast<DILocalVariable>(DN))
131 Flags |= mapDIFlagsToNonSemantic(LV->getFlags());
132 return Flags;
133}
134
135} // namespace
136
139
140// Map DWARF source language codes to NonSemantic.Shader.DebugInfo.100 source
141// language codes. Values are from the SourceLanguage enum in the
142// NonSemantic.Shader.DebugInfo.100 specification, section 4.3.
143unsigned SPIRVNonSemanticDebugHandler::toNSDISrcLang(unsigned DwarfSrcLang) {
144 switch (DwarfSrcLang) {
145 case dwarf::DW_LANG_OpenCL:
146 return 3; // OpenCL_C
147 case dwarf::DW_LANG_OpenCL_CPP:
148 return 4; // OpenCL_CPP
149 case dwarf::DW_LANG_CPP_for_OpenCL:
150 return 6; // CPP_for_OpenCL
151 case dwarf::DW_LANG_GLSL:
152 return 2; // GLSL
153 case dwarf::DW_LANG_HLSL:
154 return 5; // HLSL
155 case dwarf::DW_LANG_SYCL:
156 return 7; // SYCL
157 case dwarf::DW_LANG_Zig:
158 return 12; // Zig
159 default:
160 return 0; // Unknown
161 }
162}
163
165 // The base class sets Asm = nullptr when the module has no compile units,
166 // and initializes lexical scope tracking otherwise.
168
169 if (!Asm)
170 return;
171
172 CompileUnits.clear();
173 BasicTypes.clear();
174 PointerTypes.clear();
175 SubroutineTypes.clear();
176 DebugTypeRegs.clear();
177 OpStringContentCache.clear();
178 I32ConstantCache.clear();
179 DebugTypeFunctionCache.clear();
180 GlobalDIEmitted = false;
181#ifndef NDEBUG
182 NonSemanticOpStringsSectionEmitted = false;
183#endif
184 CachedDebugInfoNoneReg = MCRegister();
185 CachedOpTypeVoidReg = MCRegister();
186 CachedOpTypeInt32Reg = MCRegister();
187
188 // Collect compile-unit info: file paths and source languages.
189 for (const DICompileUnit *CU : M->debug_compile_units()) {
190 const DIFile *File = CU->getFile();
191 CompileUnitInfo Info;
192 if (sys::path::is_absolute(File->getFilename()))
193 Info.FilePath = File->getFilename();
194 else
195 sys::path::append(Info.FilePath, File->getDirectory(),
196 File->getFilename());
197 // getName() returns the language code regardless of whether the name is
198 // versioned. getUnversionedName() would assert on versioned names.
199 Info.SpirvSourceLanguage = toNSDISrcLang(CU->getSourceLanguage().getName());
200 CompileUnits.push_back(std::move(Info));
201 }
202
203 // Collect DWARF version from module flags. For CodeView modules there is no
204 // "Dwarf Version" flag; DwarfVersion remains 0, which is the correct value
205 // for the DebugCompilationUnit DWARF Version operand in that case.
206 if (const NamedMDNode *Flags = M->getNamedMetadata("llvm.module.flags")) {
207 for (const auto *Op : Flags->operands()) {
208 const MDOperand &NameOp = Op->getOperand(1);
209 if (NameOp.equalsStr("Dwarf Version"))
210 DwarfVersion =
212 cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
213 ->getSExtValue();
214 }
215 }
216
217 // Find all debug info types that may be referenced by NSDI instructions.
218 DebugInfoFinder Finder;
219 Finder.processModule(*M);
220 llvm::for_each(Finder.types(), [&](DIType *Ty) {
221 partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes);
222 });
223}
224
227 if (CompileUnits.empty())
228 return;
229 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_non_semantic_info))
230 return;
231
232 // Add the extension to requirements so OpExtension is output.
233 MAI.Reqs.addExtension(SPIRV::Extension::SPV_KHR_non_semantic_info);
234
235 // Add the NonSemantic.Shader.DebugInfo.100 entry to ExtInstSetMap so that
236 // outputOpExtInstImports() emits the OpExtInstImport instruction. Allocate a
237 // fresh result ID for it now; the same ID is used in emitExtInst() operands.
238 constexpr unsigned NSSet = static_cast<unsigned>(
239 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100);
240 if (!MAI.ExtInstSetMap.count(NSSet))
241 MAI.ExtInstSetMap[NSSet] = MAI.getNextIDRegister();
242}
243
244void SPIRVNonSemanticDebugHandler::emitMCInst(MCInst &Inst) {
245 Asm->OutStreamer->emitInstruction(Inst, Asm->getSubtargetInfo());
246}
247
249SPIRVNonSemanticDebugHandler::emitOpString(StringRef S,
252 MCInst Inst;
253 Inst.setOpcode(SPIRV::OpString);
255 addStringImm(S, Inst);
256 emitMCInst(Inst);
257 return Reg;
258}
259
260void SPIRVNonSemanticDebugHandler::emitOpStringIfNew(
262#ifndef NDEBUG
263 assert(!NonSemanticOpStringsSectionEmitted &&
264 "emitOpStringIfNew is only valid while emitting SPIR-V section 7");
265#endif
266 auto [It, Inserted] = OpStringContentCache.try_emplace(S, MCRegister());
267 if (!Inserted)
268 return;
269
270 It->second = emitOpString(S, MAI);
271}
272
273MCRegister SPIRVNonSemanticDebugHandler::getCachedOpStringReg(StringRef S) {
274#ifndef NDEBUG
275 assert(NonSemanticOpStringsSectionEmitted &&
276 "getCachedOpStringReg requires emitNonSemanticDebugStrings() first");
277#endif
278 auto It = OpStringContentCache.find(S);
279 assert(It != OpStringContentCache.end() &&
280 "NSDI OpString missing from cache; emitNonSemanticDebugStrings must "
281 "cache every string used in section 10");
282 return It->second;
283}
284
285MCRegister SPIRVNonSemanticDebugHandler::emitOpConstantI32(
286 uint32_t Value, MCRegister I32TypeReg, SPIRV::ModuleAnalysisInfo &MAI) {
287 auto [It, Inserted] = I32ConstantCache.try_emplace(Value);
288 if (!Inserted)
289 return It->second;
290
291 MCRegister Reg = MAI.getNextIDRegister();
292 It->second = Reg;
293 MCInst Inst;
294 Inst.setOpcode(SPIRV::OpConstantI);
296 Inst.addOperand(MCOperand::createReg(I32TypeReg));
297 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Value)));
298 emitMCInst(Inst);
299 return Reg;
300}
301
302MCRegister SPIRVNonSemanticDebugHandler::emitExtInst(
303 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
304 MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
306 MCRegister Reg = MAI.getNextIDRegister();
307 MCInst Inst;
308 Inst.setOpcode(SPIRV::OpExtInst);
310 Inst.addOperand(MCOperand::createReg(VoidTypeReg));
311 Inst.addOperand(MCOperand::createReg(ExtInstSetReg));
312 Inst.addOperand(MCOperand::createImm(static_cast<int64_t>(Opcode)));
313 for (MCRegister R : Operands)
315 emitMCInst(Inst);
316 return Reg;
317}
318
319MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugTypeFunction(
320 ArrayRef<MCRegister> Ops, MCRegister VoidTypeReg, MCRegister ExtInstSetReg,
322 auto [It, Inserted] =
323 DebugTypeFunctionCache.try_emplace(SmallVector<MCRegister, 8>(Ops));
324 if (!Inserted)
325 return It->second;
326
327 MCRegister Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeFunction,
328 VoidTypeReg, ExtInstSetReg, Ops, MAI);
329 It->second = Reg;
330 return Reg;
331}
332
333MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeVoidReg(
335 if (!CachedOpTypeVoidReg.isValid())
336 CachedOpTypeVoidReg = findOrEmitOpTypeVoid(MAI);
337 return CachedOpTypeVoidReg;
338}
339
340MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeInt32Reg(
342 if (!CachedOpTypeInt32Reg.isValid())
343 CachedOpTypeInt32Reg = findOrEmitOpTypeInt32(MAI);
344 return CachedOpTypeInt32Reg;
345}
346
347MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
349 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
350 if (MI->getOpcode() == SPIRV::OpTypeVoid)
351 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
352 }
353 MCRegister Reg = MAI.getNextIDRegister();
354 MCInst Inst;
355 Inst.setOpcode(SPIRV::OpTypeVoid);
357 emitMCInst(Inst);
358 return Reg;
359}
360
361MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
363 for (const MachineInstr *MI : MAI.getMSInstrs(SPIRV::MB_TypeConstVars)) {
364 if (MI->getOpcode() == SPIRV::OpTypeInt &&
365 MI->getOperand(1).getImm() == 32 && MI->getOperand(2).getImm() == 0)
366 return MAI.getRegisterAlias(MI->getMF(), MI->getOperand(0).getReg());
367 }
368 MCRegister Reg = MAI.getNextIDRegister();
369 MCInst Inst;
370 Inst.setOpcode(SPIRV::OpTypeInt);
372 Inst.addOperand(MCOperand::createImm(32)); // width
373 Inst.addOperand(MCOperand::createImm(0)); // signedness (unsigned)
374 emitMCInst(Inst);
375 return Reg;
376}
377
378std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
379 const DIDerivedType *PT, MCRegister ExtInstSetReg,
381 // A DWARF address space is required to determine the SPIR-V storage class.
382 // Skip pointer types that do not carry one.
383 if (!PT->getDWARFAddressSpace().has_value())
384 return std::nullopt;
385
386 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
387 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
388 MCRegister DebugTypePointerFlagsReg =
389 emitOpConstantI32(transDebugFlags(PT), I32TypeReg, MAI);
390
391 // For SPIR-V targets, Clang sets DwarfAddressSpace to the LLVM IR address
392 // space, which addressSpaceToStorageClass expects.
393 const auto &ST = static_cast<const SPIRVSubtarget &>(Asm->getSubtargetInfo());
394 MCRegister StorageClassReg = emitOpConstantI32(
395 addressSpaceToStorageClass(PT->getDWARFAddressSpace().value(), ST),
396 I32TypeReg, MAI);
397
398 if (const DIType *BaseTy = PT->getBaseType()) {
399 auto BaseIt = DebugTypeRegs.find(BaseTy);
400 if (BaseIt != DebugTypeRegs.end())
401 return emitExtInst(
402 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
403 ExtInstSetReg,
404 {BaseIt->second, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
405 // Unsupported type, no DebugType* id available.
406 return std::nullopt;
407 }
408 // No getBaseType() (typical for void*): use DebugInfoNone as Base Type,
409 // same as SPIRV-LLVM-Translator (see issue #109287 and the DISABLED
410 // spirv-val run in debug-type-pointer.ll). spirv-val may still reject this
411 // encoding; see https://github.com/KhronosGroup/SPIRV-Registry/pull/287.
412 return emitExtInst(
413 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg, ExtInstSetReg,
414 {CachedDebugInfoNoneReg, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
415}
416
417std::optional<MCRegister>
418SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
419 const DISubroutineType *ST, MCRegister ExtInstSetReg,
421 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
422 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
423 MCRegister DebugTypeFunctionFlagsReg =
424 emitOpConstantI32(transDebugFlags(ST), I32TypeReg, MAI);
425 DITypeArray TA = ST->getTypeArray();
427 Ops.push_back(DebugTypeFunctionFlagsReg);
428 // Empty DI type tuple: no explicit return or parameter slots (hand-written IR
429 // may use !{}). Emit void-only prototype. Same as SPIRV-LLVM-Translator when
430 // DISubroutineType::getTypeArray() has zero elements.
431 if (TA.empty()) {
432 Ops.push_back(VoidTypeReg);
433 } else {
434 for (unsigned I = 0, E = TA.size(); I != E; ++I) {
435 bool IsReturnType = (I == 0);
436 auto OptReg = mapDISignatureTypeToReg(TA[I], VoidTypeReg, IsReturnType);
437 // No emitted DebugType* id for this slot (e.g., pointer that
438 // was skipped due missing address space, etc.).
439 if (!OptReg)
440 return std::nullopt;
441 Ops.push_back(*OptReg);
442 }
443 }
444 return getOrEmitDebugTypeFunction(Ops, VoidTypeReg, ExtInstSetReg, MAI);
445}
446
447std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
448 const DIType *Ty, MCRegister VoidTypeReg, bool ReturnType) {
449 if (!Ty) {
450 if (ReturnType)
451 return VoidTypeReg;
452 assert(CachedDebugInfoNoneReg.isValid() &&
453 "DebugInfoNone must be emitted before DISubroutineType operands");
454 return CachedDebugInfoNoneReg;
455 }
456 auto It = DebugTypeRegs.find(Ty);
457 if (It != DebugTypeRegs.end())
458 return It->second;
459
460 return std::nullopt;
461}
462
465 if (CompileUnits.empty())
466 return;
467 // Check that prepareModuleOutput() registered the extended instruction set.
468 // If the subtarget does not support the extension, neither strings nor ext
469 // insts are emitted.
470 constexpr unsigned NSSet = static_cast<unsigned>(
471 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100);
472 if (!MAI.getExtInstSetReg(NSSet).isValid())
473 return;
474
475 for (const CompileUnitInfo &Info : CompileUnits)
476 emitOpStringIfNew(Info.FilePath, MAI);
477
478 for (const DIBasicType *BT : BasicTypes)
479 emitOpStringIfNew(BT->getName(), MAI);
480
481#ifndef NDEBUG
482 NonSemanticOpStringsSectionEmitted = true;
483#endif
484}
485
488 if (GlobalDIEmitted || CompileUnits.empty())
489 return;
490 GlobalDIEmitted = true;
491
492 // Retrieve the ext inst set register allocated by prepareModuleOutput().
493 constexpr unsigned NSSet = static_cast<unsigned>(
494 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100);
495 MCRegister ExtInstSetReg = MAI.getExtInstSetReg(NSSet);
496 if (!ExtInstSetReg.isValid())
497 return; // Extension not available.
498
499#ifndef NDEBUG
500 assert(NonSemanticOpStringsSectionEmitted &&
501 "emitNonSemanticDebugStrings() must run before "
502 "emitNonSemanticGlobalDebugInfo()");
503#endif
504
505 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
506 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
507
508 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
509 VoidTypeReg, ExtInstSetReg, {}, MAI);
510
511 // Emit integer constants shared across all NSDI instructions. The constant
512 // cache ensures each value is emitted at most once even when referenced from
513 // multiple instructions. All constants are pre-emitted before any DebugSource
514 // so that the output order is: constants, then
515 // DebugSource+DebugCompilationUnit pairs. This keeps OpConstant instructions
516 // grouped before the OpExtInst instructions.
517
518 // The Version operand of DebugCompilationUnit is the version of the
519 // NonSemantic.Shader.DebugInfo instruction set, which is 100 for
520 // "NonSemantic.Shader.DebugInfo.100" (NonSemanticShaderDebugInfo100Version).
521 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
522 MCRegister DwarfVersionReg =
523 emitOpConstantI32(static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
524
525 // Pre-emit source language constants for all compile units before entering
526 // the DebugSource loop.
527 SmallVector<MCRegister> SrcLangRegs =
528 map_to_vector(CompileUnits, [&](const CompileUnitInfo &Info) {
529 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
530 });
531
532 // Emit DebugSource and DebugCompilationUnit for each compile unit.
533 for (auto [Info, SrcLangReg] : llvm::zip(CompileUnits, SrcLangRegs)) {
534 MCRegister FileStrReg = getCachedOpStringReg(Info.FilePath);
535 MCRegister DebugSourceReg =
536 emitExtInst(SPIRV::NonSemanticExtInst::DebugSource, VoidTypeReg,
537 ExtInstSetReg, {FileStrReg}, MAI);
538 emitExtInst(
539 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
540 ExtInstSetReg,
541 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
542 MAI);
543 }
544
545 // Zero constant used as the Flags operand in DebugTypeBasic and
546 // DebugTypePointer. Cached with other i32 constants.
547 MCRegister I32ZeroReg = emitOpConstantI32(0, I32TypeReg, MAI);
548
549 DebugTypeRegs.clear();
550
551 for (const DIBasicType *BT : BasicTypes) {
552 MCRegister NameReg = getCachedOpStringReg(BT->getName());
553 MCRegister SizeReg = emitOpConstantI32(
554 static_cast<uint32_t>(BT->getSizeInBits()), I32TypeReg, MAI);
555
556 // Map DWARF base type encodings to NSDI encoding codes per
557 // NonSemantic.Shader.DebugInfo.100 specification, section 4.5.
558 unsigned Encoding = 0; // Unspecified
559 switch (BT->getEncoding()) {
560 case dwarf::DW_ATE_address:
561 Encoding = 1;
562 break;
563 case dwarf::DW_ATE_boolean:
564 Encoding = 2;
565 break;
566 case dwarf::DW_ATE_float:
567 Encoding = 3;
568 break;
569 case dwarf::DW_ATE_signed:
570 Encoding = 4;
571 break;
572 case dwarf::DW_ATE_signed_char:
573 Encoding = 5;
574 break;
575 case dwarf::DW_ATE_unsigned:
576 Encoding = 6;
577 break;
578 case dwarf::DW_ATE_unsigned_char:
579 Encoding = 7;
580 break;
581 }
582 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
583
584 MCRegister BTReg = emitExtInst(
585 SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
586 {NameReg, SizeReg, EncodingReg, I32ZeroReg}, MAI);
587 DebugTypeRegs[BT] = BTReg;
588 }
589
590 // Emit DebugTypePointer for each referenced pointer type.
591 for (const DIDerivedType *PT : PointerTypes) {
592 if (auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
593 DebugTypeRegs[PT] = *PtrReg;
594 }
595
596 // Emit DebugTypeFunction for each distinct DISubroutineType.
597 for (const DISubroutineType *ST : SubroutineTypes) {
598 if (auto FnTyReg =
599 emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI))
600 DebugTypeRegs[ST] = *FnTyReg;
601 }
602}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
BitTracker BT
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains constants used for implementing Dwarf debug support.
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 I(x, y, z)
Definition MD5.cpp:57
Register Reg
This file defines less commonly used SmallVector utilities.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:91
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:106
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
Basic type, like 'int' or 'float'.
Tagged DWARF-like metadata node.
LLVM_ABI dwarf::Tag getTag() const
DIFlags
Debug info flags.
Type array for a subprogram.
Base class for types.
AsmPrinter * Asm
Target of debug info emission.
void beginModule(Module *M) override
Utility to find all debug info in a module.
Definition DebugInfo.h:105
LLVM_ABI void processModule(const Module &M)
Process entire module and collect debug info anchors.
iterator_range< type_iterator > types() const
Definition DebugInfo.h:158
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
constexpr bool isValid() const
Definition MCRegister.h:84
Tracking metadata reference owned by Metadata.
Definition Metadata.h:897
bool equalsStr(StringRef Str) const
Definition Metadata.h:919
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
A tuple of MDNodes.
Definition Metadata.h:1755
void emitNonSemanticDebugStrings(SPIRV::ModuleAnalysisInfo &MAI)
Emit OpString instructions for all NSDI file paths and basic type names into the debug section (secti...
void beginModule(Module *M) override
Collect compile-unit metadata from the module.
void emitNonSemanticGlobalDebugInfo(SPIRV::ModuleAnalysisInfo &MAI)
Emit module-scope NSDI instructions (DebugSource, DebugCompilationUnit, DebugTypeBasic,...
void prepareModuleOutput(const SPIRVSubtarget &ST, SPIRV::ModuleAnalysisInfo &MAI)
Add SPV_KHR_non_semantic_info extension and NonSemantic.Shader.DebugInfo.100 ext inst set entry to MA...
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
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition Path.cpp:688
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition Path.cpp:467
This is an optimization pass for GlobalISel generic memory operations.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
Definition STLExtras.h:830
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1731
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
void addStringImm(const StringRef &Str, MCInst &Inst)
MCRegister getExtInstSetReg(unsigned SetNum)
DenseMap< unsigned, MCRegister > ExtInstSetMap
InstrList & getMSInstrs(unsigned MSType)
MCRegister getRegisterAlias(const MachineFunction *MF, Register Reg)
void addExtension(Extension::Extension ToAdd)