50 if (CT->getTag() == dwarf::DW_TAG_array_type && CT->isVector())
55 if (DT && DT->getTag() == dwarf::DW_TAG_pointer_type)
60 NSDIFlagIsProtected = 1u << 0,
61 NSDIFlagIsPrivate = 1u << 1,
62 NSDIFlagIsPublic = NSDIFlagIsPrivate | NSDIFlagIsProtected,
63 NSDIFlagIsLocal = 1u << 2,
64 NSDIFlagIsDefinition = 1u << 3,
65 NSDIFlagFwdDecl = 1u << 4,
66 NSDIFlagArtificial = 1u << 5,
67 NSDIFlagExplicit = 1u << 6,
68 NSDIFlagPrototyped = 1u << 7,
69 NSDIFlagObjectPointer = 1u << 8,
70 NSDIFlagStaticMember = 1u << 9,
71 NSDIFlagIndirectVariable = 1u << 10,
72 NSDIFlagLValueReference = 1u << 11,
73 NSDIFlagRValueReference = 1u << 12,
74 NSDIFlagIsOptimized = 1u << 13,
75 NSDIFlagIsEnumClass = 1u << 14,
76 NSDIFlagTypePassByValue = 1u << 15,
77 NSDIFlagTypePassByReference = 1u << 16,
78 NSDIFlagUnknownPhysicalLayout = 1u << 17,
84 Flags |= NSDIFlagIsPublic;
86 Flags |= NSDIFlagIsProtected;
88 Flags |= NSDIFlagIsPrivate;
89 if (DFlags & DINode::FlagFwdDecl)
90 Flags |= NSDIFlagFwdDecl;
91 if (DFlags & DINode::FlagArtificial)
92 Flags |= NSDIFlagArtificial;
93 if (DFlags & DINode::FlagExplicit)
94 Flags |= NSDIFlagExplicit;
95 if (DFlags & DINode::FlagPrototyped)
96 Flags |= NSDIFlagPrototyped;
97 if (DFlags & DINode::FlagObjectPointer)
98 Flags |= NSDIFlagObjectPointer;
99 if (DFlags & DINode::FlagStaticMember)
100 Flags |= NSDIFlagStaticMember;
101 if (DFlags & DINode::FlagLValueReference)
102 Flags |= NSDIFlagLValueReference;
103 if (DFlags & DINode::FlagRValueReference)
104 Flags |= NSDIFlagRValueReference;
105 if (DFlags & DINode::FlagTypePassByValue)
106 Flags |= NSDIFlagTypePassByValue;
107 if (DFlags & DINode::FlagTypePassByReference)
108 Flags |= NSDIFlagTypePassByReference;
109 if (DFlags & DINode::FlagEnumClass)
110 Flags |= NSDIFlagIsEnumClass;
117 if (GV->isLocalToUnit())
118 Flags |= NSDIFlagIsLocal;
119 if (GV->isDefinition())
120 Flags |= NSDIFlagIsDefinition;
123 if (SP->isLocalToUnit())
124 Flags |= NSDIFlagIsLocal;
125 if (SP->isOptimized())
126 Flags |= NSDIFlagIsOptimized;
127 if (SP->isDefinition())
128 Flags |= NSDIFlagIsDefinition;
129 Flags |= mapDIFlagsToNonSemantic(SP->getFlags());
131 if (DN->
getTag() == dwarf::DW_TAG_reference_type)
132 Flags |= NSDIFlagLValueReference;
133 if (DN->
getTag() == dwarf::DW_TAG_rvalue_reference_type)
134 Flags |= NSDIFlagRValueReference;
136 Flags |= mapDIFlagsToNonSemantic(Ty->getFlags());
138 Flags |= mapDIFlagsToNonSemantic(LV->getFlags());
150unsigned SPIRVNonSemanticDebugHandler::toNSDISrcLang(
unsigned DwarfSrcLang) {
151 switch (DwarfSrcLang) {
152 case dwarf::DW_LANG_OpenCL:
154 case dwarf::DW_LANG_OpenCL_CPP:
156 case dwarf::DW_LANG_CPP_for_OpenCL:
158 case dwarf::DW_LANG_GLSL:
160 case dwarf::DW_LANG_HLSL:
162 case dwarf::DW_LANG_SYCL:
164 case dwarf::DW_LANG_Zig:
179 CompileUnits.clear();
181 PointerTypes.clear();
182 SubroutineTypes.clear();
184 DebugTypeRegs.clear();
185 OpStringContentCache.clear();
186 I32ConstantCache.clear();
187 DebugTypeFunctionCache.clear();
188 GlobalDIEmitted =
false;
190 NonSemanticOpStringsSectionEmitted =
false;
199 CompileUnitInfo Info;
201 Info.FilePath = File->getFilename();
204 File->getFilename());
207 Info.SpirvSourceLanguage = toNSDISrcLang(
CU->getSourceLanguage().getName());
208 CompileUnits.push_back(std::move(Info));
214 if (
const NamedMDNode *Flags = M->getNamedMetadata(
"llvm.module.flags")) {
215 for (
const auto *
Op : Flags->operands()) {
229 partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes, VectorTypes);
235 if (CompileUnits.empty())
237 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_non_semantic_info))
246 constexpr unsigned NSSet =
static_cast<unsigned>(
247 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100);
252void SPIRVNonSemanticDebugHandler::emitMCInst(
MCInst &Inst) {
257SPIRVNonSemanticDebugHandler::emitOpString(
StringRef S,
268void SPIRVNonSemanticDebugHandler::emitOpStringIfNew(
271 assert(!NonSemanticOpStringsSectionEmitted &&
272 "emitOpStringIfNew is only valid while emitting SPIR-V section 7");
274 auto [It,
Inserted] = OpStringContentCache.try_emplace(S, MCRegister());
278 It->second = emitOpString(S, MAI);
283 assert(NonSemanticOpStringsSectionEmitted &&
284 "getCachedOpStringReg requires emitNonSemanticDebugStrings() first");
286 auto It = OpStringContentCache.find(S);
287 assert(It != OpStringContentCache.end() &&
288 "NSDI OpString missing from cache; emitNonSemanticDebugStrings must "
289 "cache every string used in section 10");
293MCRegister SPIRVNonSemanticDebugHandler::emitOpConstantI32(
310MCRegister SPIRVNonSemanticDebugHandler::emitExtInst(
311 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
321 for (MCRegister R : Operands)
327MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugTypeFunction(
335 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeFunction,
336 VoidTypeReg, ExtInstSetReg,
Ops, MAI);
341MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeVoidReg(
343 if (!CachedOpTypeVoidReg.isValid())
344 CachedOpTypeVoidReg = findOrEmitOpTypeVoid(MAI);
345 return CachedOpTypeVoidReg;
348MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeInt32Reg(
350 if (!CachedOpTypeInt32Reg.isValid())
351 CachedOpTypeInt32Reg = findOrEmitOpTypeInt32(MAI);
352 return CachedOpTypeInt32Reg;
355MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
358 if (
MI->getOpcode() == SPIRV::OpTypeVoid)
369MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
372 if (
MI->getOpcode() == SPIRV::OpTypeInt &&
373 MI->getOperand(1).getImm() == 32 &&
MI->getOperand(2).getImm() == 0)
386std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
391 if (!PT->getDWARFAddressSpace().has_value())
394 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
395 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
396 MCRegister DebugTypePointerFlagsReg =
397 emitOpConstantI32(transDebugFlags(PT), I32TypeReg, MAI);
401 const auto &
ST =
static_cast<const SPIRVSubtarget &
>(
Asm->getSubtargetInfo());
402 MCRegister StorageClassReg = emitOpConstantI32(
406 if (
const DIType *BaseTy = PT->getBaseType()) {
407 auto BaseIt = DebugTypeRegs.find(BaseTy);
408 if (BaseIt != DebugTypeRegs.end())
410 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
412 {BaseIt->second, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
421 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg, ExtInstSetReg,
422 {CachedDebugInfoNoneReg, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
425std::optional<MCRegister>
426SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
429 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
430 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
431 MCRegister DebugTypeFunctionFlagsReg =
432 emitOpConstantI32(transDebugFlags(ST), I32TypeReg, MAI);
433 DITypeArray
TA =
ST->getTypeArray();
435 Ops.push_back(DebugTypeFunctionFlagsReg);
440 Ops.push_back(VoidTypeReg);
442 for (
unsigned I = 0,
E =
TA.size();
I !=
E; ++
I) {
443 bool IsReturnType = (
I == 0);
444 auto OptReg = mapDISignatureTypeToReg(TA[
I], VoidTypeReg, IsReturnType);
449 Ops.push_back(*OptReg);
452 return getOrEmitDebugTypeFunction(
Ops, VoidTypeReg, ExtInstSetReg, MAI);
455std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
460 assert(CachedDebugInfoNoneReg.isValid() &&
461 "DebugInfoNone must be emitted before DISubroutineType operands");
462 return CachedDebugInfoNoneReg;
464 auto It = DebugTypeRegs.find(Ty);
465 if (It != DebugTypeRegs.end())
471std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
477 auto BTIt = DebugTypeRegs.find(BaseTy);
478 if (BTIt == DebugTypeRegs.end())
491 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
492 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
493 MCRegister CountReg = emitOpConstantI32(
494 static_cast<uint32_t
>(CI->getZExtValue()), I32TypeReg, MAI);
495 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeVector, VoidTypeReg,
496 ExtInstSetReg, {BTIt->second, CountReg}, MAI);
501 if (CompileUnits.empty())
506 constexpr unsigned NSSet =
static_cast<unsigned>(
507 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100);
511 for (
const CompileUnitInfo &Info : CompileUnits)
512 emitOpStringIfNew(Info.FilePath, MAI);
515 emitOpStringIfNew(
BT->getName(), MAI);
518 NonSemanticOpStringsSectionEmitted =
true;
524 if (GlobalDIEmitted || CompileUnits.empty())
526 GlobalDIEmitted =
true;
529 constexpr unsigned NSSet =
static_cast<unsigned>(
530 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100);
536 assert(NonSemanticOpStringsSectionEmitted &&
537 "emitNonSemanticDebugStrings() must run before "
538 "emitNonSemanticGlobalDebugInfo()");
541 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
542 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
544 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
545 VoidTypeReg, ExtInstSetReg, {}, MAI);
557 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
559 emitOpConstantI32(
static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
564 map_to_vector(CompileUnits, [&](
const CompileUnitInfo &Info) {
565 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
569 for (
auto [Info, SrcLangReg] :
llvm::zip(CompileUnits, SrcLangRegs)) {
570 MCRegister FileStrReg = getCachedOpStringReg(Info.FilePath);
572 emitExtInst(SPIRV::NonSemanticExtInst::DebugSource, VoidTypeReg,
573 ExtInstSetReg, {FileStrReg}, MAI);
575 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
577 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
583 MCRegister I32ZeroReg = emitOpConstantI32(0, I32TypeReg, MAI);
585 DebugTypeRegs.clear();
588 MCRegister NameReg = getCachedOpStringReg(
BT->getName());
590 static_cast<uint32_t>(
BT->getSizeInBits()), I32TypeReg, MAI);
594 unsigned Encoding = 0;
595 switch (
BT->getEncoding()) {
596 case dwarf::DW_ATE_address:
599 case dwarf::DW_ATE_boolean:
602 case dwarf::DW_ATE_float:
605 case dwarf::DW_ATE_signed:
608 case dwarf::DW_ATE_signed_char:
611 case dwarf::DW_ATE_unsigned:
614 case dwarf::DW_ATE_unsigned_char:
618 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
621 SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
622 {NameReg, SizeReg, EncodingReg, I32ZeroReg}, MAI);
623 DebugTypeRegs[
BT] = BTReg;
628 if (
auto VecReg = emitDebugTypeVector(VT, ExtInstSetReg, MAI))
629 DebugTypeRegs[VT] = *VecReg;
634 if (
auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
635 DebugTypeRegs[PT] = *PtrReg;
641 emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI))
642 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'.
DINodeArray getElements() const
DIType * getBaseType() const
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.
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 ...
auto dyn_cast_or_null(const Y &Val)
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)