48 if (DT && DT->getTag() == dwarf::DW_TAG_pointer_type)
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,
77 Flags |= NSDIFlagIsPublic;
79 Flags |= NSDIFlagIsProtected;
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;
110 if (GV->isLocalToUnit())
111 Flags |= NSDIFlagIsLocal;
112 if (GV->isDefinition())
113 Flags |= NSDIFlagIsDefinition;
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());
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;
129 Flags |= mapDIFlagsToNonSemantic(Ty->getFlags());
131 Flags |= mapDIFlagsToNonSemantic(LV->getFlags());
143unsigned SPIRVNonSemanticDebugHandler::toNSDISrcLang(
unsigned DwarfSrcLang) {
144 switch (DwarfSrcLang) {
145 case dwarf::DW_LANG_OpenCL:
147 case dwarf::DW_LANG_OpenCL_CPP:
149 case dwarf::DW_LANG_CPP_for_OpenCL:
151 case dwarf::DW_LANG_GLSL:
153 case dwarf::DW_LANG_HLSL:
155 case dwarf::DW_LANG_SYCL:
157 case dwarf::DW_LANG_Zig:
172 CompileUnits.clear();
174 PointerTypes.clear();
175 SubroutineTypes.clear();
176 DebugTypeRegs.clear();
177 OpStringContentCache.clear();
178 I32ConstantCache.clear();
179 DebugTypeFunctionCache.clear();
180 GlobalDIEmitted =
false;
182 NonSemanticOpStringsSectionEmitted =
false;
191 CompileUnitInfo Info;
193 Info.FilePath = File->getFilename();
196 File->getFilename());
199 Info.SpirvSourceLanguage = toNSDISrcLang(
CU->getSourceLanguage().getName());
200 CompileUnits.push_back(std::move(Info));
206 if (
const NamedMDNode *Flags = M->getNamedMetadata(
"llvm.module.flags")) {
207 for (
const auto *
Op : Flags->operands()) {
221 partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes);
227 if (CompileUnits.empty())
229 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_non_semantic_info))
238 constexpr unsigned NSSet =
static_cast<unsigned>(
239 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100);
244void SPIRVNonSemanticDebugHandler::emitMCInst(
MCInst &Inst) {
249SPIRVNonSemanticDebugHandler::emitOpString(
StringRef S,
260void SPIRVNonSemanticDebugHandler::emitOpStringIfNew(
263 assert(!NonSemanticOpStringsSectionEmitted &&
264 "emitOpStringIfNew is only valid while emitting SPIR-V section 7");
266 auto [It,
Inserted] = OpStringContentCache.try_emplace(S, MCRegister());
270 It->second = emitOpString(S, MAI);
275 assert(NonSemanticOpStringsSectionEmitted &&
276 "getCachedOpStringReg requires emitNonSemanticDebugStrings() first");
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");
285MCRegister SPIRVNonSemanticDebugHandler::emitOpConstantI32(
302MCRegister SPIRVNonSemanticDebugHandler::emitExtInst(
303 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
313 for (MCRegister R : Operands)
319MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugTypeFunction(
327 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeFunction,
328 VoidTypeReg, ExtInstSetReg,
Ops, MAI);
333MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeVoidReg(
335 if (!CachedOpTypeVoidReg.isValid())
336 CachedOpTypeVoidReg = findOrEmitOpTypeVoid(MAI);
337 return CachedOpTypeVoidReg;
340MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeInt32Reg(
342 if (!CachedOpTypeInt32Reg.isValid())
343 CachedOpTypeInt32Reg = findOrEmitOpTypeInt32(MAI);
344 return CachedOpTypeInt32Reg;
347MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
350 if (
MI->getOpcode() == SPIRV::OpTypeVoid)
361MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
364 if (
MI->getOpcode() == SPIRV::OpTypeInt &&
365 MI->getOperand(1).getImm() == 32 &&
MI->getOperand(2).getImm() == 0)
378std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
383 if (!PT->getDWARFAddressSpace().has_value())
386 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
387 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
388 MCRegister DebugTypePointerFlagsReg =
389 emitOpConstantI32(transDebugFlags(PT), I32TypeReg, MAI);
393 const auto &
ST =
static_cast<const SPIRVSubtarget &
>(
Asm->getSubtargetInfo());
394 MCRegister StorageClassReg = emitOpConstantI32(
398 if (
const DIType *BaseTy = PT->getBaseType()) {
399 auto BaseIt = DebugTypeRegs.find(BaseTy);
400 if (BaseIt != DebugTypeRegs.end())
402 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
404 {BaseIt->second, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
413 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg, ExtInstSetReg,
414 {CachedDebugInfoNoneReg, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
417std::optional<MCRegister>
418SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
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);
432 Ops.push_back(VoidTypeReg);
434 for (
unsigned I = 0,
E =
TA.size();
I !=
E; ++
I) {
435 bool IsReturnType = (
I == 0);
436 auto OptReg = mapDISignatureTypeToReg(TA[
I], VoidTypeReg, IsReturnType);
441 Ops.push_back(*OptReg);
444 return getOrEmitDebugTypeFunction(
Ops, VoidTypeReg, ExtInstSetReg, MAI);
447std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
452 assert(CachedDebugInfoNoneReg.isValid() &&
453 "DebugInfoNone must be emitted before DISubroutineType operands");
454 return CachedDebugInfoNoneReg;
456 auto It = DebugTypeRegs.find(Ty);
457 if (It != DebugTypeRegs.end())
465 if (CompileUnits.empty())
470 constexpr unsigned NSSet =
static_cast<unsigned>(
471 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100);
475 for (
const CompileUnitInfo &Info : CompileUnits)
476 emitOpStringIfNew(Info.FilePath, MAI);
479 emitOpStringIfNew(
BT->getName(), MAI);
482 NonSemanticOpStringsSectionEmitted =
true;
488 if (GlobalDIEmitted || CompileUnits.empty())
490 GlobalDIEmitted =
true;
493 constexpr unsigned NSSet =
static_cast<unsigned>(
494 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100);
500 assert(NonSemanticOpStringsSectionEmitted &&
501 "emitNonSemanticDebugStrings() must run before "
502 "emitNonSemanticGlobalDebugInfo()");
505 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
506 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
508 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
509 VoidTypeReg, ExtInstSetReg, {}, MAI);
521 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
523 emitOpConstantI32(
static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
528 map_to_vector(CompileUnits, [&](
const CompileUnitInfo &Info) {
529 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
533 for (
auto [Info, SrcLangReg] :
llvm::zip(CompileUnits, SrcLangRegs)) {
534 MCRegister FileStrReg = getCachedOpStringReg(Info.FilePath);
536 emitExtInst(SPIRV::NonSemanticExtInst::DebugSource, VoidTypeReg,
537 ExtInstSetReg, {FileStrReg}, MAI);
539 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
541 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
547 MCRegister I32ZeroReg = emitOpConstantI32(0, I32TypeReg, MAI);
549 DebugTypeRegs.clear();
552 MCRegister NameReg = getCachedOpStringReg(
BT->getName());
554 static_cast<uint32_t>(
BT->getSizeInBits()), I32TypeReg, MAI);
558 unsigned Encoding = 0;
559 switch (
BT->getEncoding()) {
560 case dwarf::DW_ATE_address:
563 case dwarf::DW_ATE_boolean:
566 case dwarf::DW_ATE_float:
569 case dwarf::DW_ATE_signed:
572 case dwarf::DW_ATE_signed_char:
575 case dwarf::DW_ATE_unsigned:
578 case dwarf::DW_ATE_unsigned_char:
582 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
585 SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
586 {NameReg, SizeReg, EncodingReg, I32ZeroReg}, MAI);
587 DebugTypeRegs[
BT] = BTReg;
592 if (
auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
593 DebugTypeRegs[PT] = *PtrReg;
599 emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI))
600 DebugTypeRegs[ST] = *FnTyReg;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains constants used for implementing Dwarf debug support.
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Represent a constant reference to an array (0 or more elements consecutively in memory),...
This class is intended to be used as a driving class for all asm writers.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
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
Type array for a subprogram.
AsmPrinter * Asm
Target of debug info emission.
DebugHandlerBase(AsmPrinter *A)
void beginModule(Module *M) override
Utility to find all debug info in a module.
LLVM_ABI void processModule(const Module &M)
Process entire module and collect debug info anchors.
iterator_range< type_iterator > types() const
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isValid() const
Tracking metadata reference owned by Metadata.
bool equalsStr(StringRef Str) const
A Module instance is used to store all the information related to an LLVM module.
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...
SPIRVNonSemanticDebugHandler(AsmPrinter &AP)
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.
LLVM Value Representation.
LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
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.
FunctionAddr VTableAddr Value
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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.
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)
MCRegister getNextIDRegister()
void addExtension(Extension::Extension ToAdd)