46template <
typename MapT>
47static std::optional<MCRegister> lookupOptReg(
const MapT &Map,
48 typename MapT::key_type
Key) {
52 assert(It->second.isValid() &&
"invalid register stored in map");
79 if (CT->getTag() == dwarf::DW_TAG_array_type) {
95 }
else if (CT->getTag() == dwarf::DW_TAG_structure_type ||
96 CT->getTag() == dwarf::DW_TAG_class_type ||
97 CT->getTag() == dwarf::DW_TAG_union_type) {
103 if (DT && DT->getTag() == dwarf::DW_TAG_pointer_type)
105 else if (DT && DT->getTag() == dwarf::DW_TAG_typedef)
110 NSDIFlagIsProtected = 1u << 0,
111 NSDIFlagIsPrivate = 1u << 1,
112 NSDIFlagIsPublic = NSDIFlagIsPrivate | NSDIFlagIsProtected,
113 NSDIFlagIsLocal = 1u << 2,
114 NSDIFlagIsDefinition = 1u << 3,
115 NSDIFlagFwdDecl = 1u << 4,
116 NSDIFlagArtificial = 1u << 5,
117 NSDIFlagExplicit = 1u << 6,
118 NSDIFlagPrototyped = 1u << 7,
119 NSDIFlagObjectPointer = 1u << 8,
120 NSDIFlagStaticMember = 1u << 9,
121 NSDIFlagIndirectVariable = 1u << 10,
122 NSDIFlagLValueReference = 1u << 11,
123 NSDIFlagRValueReference = 1u << 12,
124 NSDIFlagIsOptimized = 1u << 13,
125 NSDIFlagIsEnumClass = 1u << 14,
126 NSDIFlagTypePassByValue = 1u << 15,
127 NSDIFlagTypePassByReference = 1u << 16,
128 NSDIFlagUnknownPhysicalLayout = 1u << 17,
134 Flags |= NSDIFlagIsPublic;
136 Flags |= NSDIFlagIsProtected;
138 Flags |= NSDIFlagIsPrivate;
139 if (DFlags & DINode::FlagFwdDecl)
140 Flags |= NSDIFlagFwdDecl;
141 if (DFlags & DINode::FlagArtificial)
142 Flags |= NSDIFlagArtificial;
143 if (DFlags & DINode::FlagExplicit)
144 Flags |= NSDIFlagExplicit;
145 if (DFlags & DINode::FlagPrototyped)
146 Flags |= NSDIFlagPrototyped;
147 if (DFlags & DINode::FlagObjectPointer)
148 Flags |= NSDIFlagObjectPointer;
149 if (DFlags & DINode::FlagStaticMember)
150 Flags |= NSDIFlagStaticMember;
151 if (DFlags & DINode::FlagLValueReference)
152 Flags |= NSDIFlagLValueReference;
153 if (DFlags & DINode::FlagRValueReference)
154 Flags |= NSDIFlagRValueReference;
155 if (DFlags & DINode::FlagTypePassByValue)
156 Flags |= NSDIFlagTypePassByValue;
157 if (DFlags & DINode::FlagTypePassByReference)
158 Flags |= NSDIFlagTypePassByReference;
159 if (DFlags & DINode::FlagEnumClass)
160 Flags |= NSDIFlagIsEnumClass;
167 if (GV->isLocalToUnit())
168 Flags |= NSDIFlagIsLocal;
169 if (GV->isDefinition())
170 Flags |= NSDIFlagIsDefinition;
173 if (SP->isLocalToUnit())
174 Flags |= NSDIFlagIsLocal;
175 if (SP->isOptimized())
176 Flags |= NSDIFlagIsOptimized;
177 if (SP->isDefinition())
178 Flags |= NSDIFlagIsDefinition;
179 Flags |= mapDIFlagsToNonSemantic(SP->getFlags());
181 if (DN->
getTag() == dwarf::DW_TAG_reference_type)
182 Flags |= NSDIFlagLValueReference;
183 if (DN->
getTag() == dwarf::DW_TAG_rvalue_reference_type)
184 Flags |= NSDIFlagRValueReference;
186 Flags |= mapDIFlagsToNonSemantic(Ty->getFlags());
188 Flags |= mapDIFlagsToNonSemantic(LV->getFlags());
194static uint32_t mapCompositeTypeTag(
unsigned Tag) {
196 case dwarf::DW_TAG_class_type:
198 case dwarf::DW_TAG_structure_type:
200 case dwarf::DW_TAG_union_type:
204 ". Expecting 0, 1 or 2");
219 bool SeenOpVariable =
false;
221 if (
MI.getOpcode() == SPIRV::OpVariable) {
222 SeenOpVariable =
true;
224 LastOpVariable = &
MI;
228 bool CanInterleaveWithOpVariable =
229 MI.getOpcode() == SPIRV::OpLine ||
MI.getOpcode() == SPIRV::OpNoLine;
230 if (SeenOpVariable && !CanInterleaveWithOpVariable &&
234 return LastOpVariable;
245unsigned SPIRVNonSemanticDebugHandler::toNSDISrcLang(
unsigned DwarfSrcLang) {
246 switch (DwarfSrcLang) {
247 case dwarf::DW_LANG_OpenCL:
249 case dwarf::DW_LANG_OpenCL_CPP:
251 case dwarf::DW_LANG_CPP_for_OpenCL:
253 case dwarf::DW_LANG_GLSL:
255 case dwarf::DW_LANG_HLSL:
257 case dwarf::DW_LANG_SYCL:
259 case dwarf::DW_LANG_Zig:
267 return BT->getEncoding() == dwarf::DW_ATE_boolean;
276 unsigned Width =
BT->getSizeInBits();
285 ?
Value.trunc(std::min(Width, 64u)).getZExtValue()
286 :
Value.getZExtValue(),
299 if (DT->getTag() != dwarf::DW_TAG_typedef || !Seen.
insert(DT).second)
301 Ty = DT->getBaseType();
312 unsigned Size =
BT->getSizeInBits();
313 switch (
BT->getEncoding()) {
314 case dwarf::DW_ATE_signed:
315 case dwarf::DW_ATE_unsigned:
316 case dwarf::DW_ATE_signed_char:
317 case dwarf::DW_ATE_unsigned_char:
319 case dwarf::DW_ATE_float:
345 for (
const MDNode *
N : SP->getRetainedNodes())
350 Locations.insert(
DL);
353 Locations.insert(
DL);
384 CompileUnits.clear();
386 PointerTypes.clear();
387 SubroutineTypes.clear();
390 CompositeTypes.clear();
391 TypedefTypes.clear();
392 SubprogramDeclarations.clear();
393 SubprogramDefinitions.clear();
394 UniqueDebugLocations.clear();
395 GlobalVariableDebugInfoMap.clear();
396 LocalVariables.clear();
397 DebugLocalVariableRegs.clear();
398 DebugExpressionRegs.clear();
399 LexicalBlocks.clear();
400 DebugScopeRegs.clear();
401 DebugInlinedAtRegs.clear();
402 ScopeToPathOpStringReg.clear();
403 DebugSourceRegByFileStr.clear();
404 OpStringContentCache.clear();
405 ScalarTypeCache.clear();
406 ScalarConstantCache.clear();
407 ConstantValueRegs.clear();
408 DebugTypeFunctionCache.clear();
409 DebugOperationCache.clear();
410 DebugExpressionCache.clear();
411 ModuleScopeIds.clear();
412 GlobalDIEmitted =
false;
413 GlobalNSDIEnabled =
false;
414 CurrentMAI =
nullptr;
416 NonSemanticOpStringsSectionEmitted =
false;
426 CompileUnitInfo Info;
429 Info.FilePath = File->getFilename();
432 File->getFilename());
435 Info.SpirvSourceLanguage = toNSDISrcLang(
CU->getSourceLanguage().getName());
436 CompileUnits.push_back(std::move(Info));
442 if (
const NamedMDNode *Flags = M->getNamedMetadata(
"llvm.module.flags")) {
443 for (
const auto *
Op : Flags->operands()) {
457 partitionTypes(Ty, BasicTypes, PointerTypes, SubroutineTypes, VectorTypes,
458 ArrayTypes, CompositeTypes, TypedefTypes);
462 if (SP->isDefinition())
463 SubprogramDefinitions.push_back(SP);
465 SubprogramDeclarations.push_back(SP);
472 G.getDebugInfo(GVEs);
483 GlobalVariableDebugInfoMap.try_emplace(
484 GV, GlobalVariableDebugInfo{Expr, DIGVToLLVMGV.
lookup(GV)});
501 if (
MI.getNumOperands() == 0 || !
MI.getOperand(0).isReg() ||
502 !
MI.getOperand(0).isDef())
509 if (CompileUnits.empty())
511 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_non_semantic_info))
525 ModuleScopeIds.insert(Id);
529void SPIRVNonSemanticDebugHandler::emitMCInst(
MCInst &Inst) {
534SPIRVNonSemanticDebugHandler::emitOpString(
StringRef S,
545MCRegister SPIRVNonSemanticDebugHandler::emitOpStringIfNew(
548 assert(!NonSemanticOpStringsSectionEmitted &&
549 "emitOpStringIfNew is only valid while emitting SPIR-V section 7");
551 auto [It,
Inserted] = OpStringContentCache.try_emplace(S, MCRegister());
553 It->second = emitOpString(S, MAI);
560 assert(NonSemanticOpStringsSectionEmitted &&
561 "getCachedOpStringReg requires emitNonSemanticDebugStrings() first");
563 auto It = OpStringContentCache.find(S);
564 assert(It != OpStringContentCache.end() &&
565 "NSDI OpString missing from cache; emitNonSemanticDebugStrings must "
566 "cache every string used in section 10");
570MCRegister SPIRVNonSemanticDebugHandler::emitAndCacheScopePathOpStringReg(
572 auto [It,
Inserted] = ScopeToPathOpStringReg.try_emplace(Scope, MCRegister());
574 It->second = emitOpStringIfNew(getDebugFullPath(Scope), MAI);
578MCRegister SPIRVNonSemanticDebugHandler::getCachedScopePathOpStringReg(
579 const DIScope *Scope,
bool UseEmptyPathIfNullScope) {
581 assert(UseEmptyPathIfNullScope &&
582 "null scope path lookup requires UseEmptyPathIfNullScope");
583 assert(CachedEmptyStringReg.isValid() &&
584 "empty path OpString must be cached in emitNonSemanticDebugStrings");
585 return CachedEmptyStringReg;
587 auto It = ScopeToPathOpStringReg.find(Scope);
588 assert(It != ScopeToPathOpStringReg.end() &&
589 "path OpString must be cached in emitNonSemanticDebugStrings");
590 MCRegister FileStrReg = It->second;
591 assert(FileStrReg.
isValid() &&
"path OpString id must be valid once cached");
595MCRegister SPIRVNonSemanticDebugHandler::emitOpConstantI32(
597 return findOrEmitConstant(SPIRV::OpConstantI, I32TypeReg,
Value,
601MCRegister SPIRVNonSemanticDebugHandler::emitExtInst(
602 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
618MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugTypeFunction(
626 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeFunction,
627 VoidTypeReg, ExtInstSetReg,
Ops, MAI);
632MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeVoidReg(
634 if (!CachedOpTypeVoidReg.isValid())
635 CachedOpTypeVoidReg = findOrEmitOpTypeVoid(MAI);
636 return CachedOpTypeVoidReg;
639MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeInt32Reg(
641 if (!CachedOpTypeInt32Reg.isValid())
642 CachedOpTypeInt32Reg = findOrEmitOpTypeInt32(MAI);
643 return CachedOpTypeInt32Reg;
646MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
649 if (
MI->getOpcode() == SPIRV::OpTypeVoid)
666 unsigned Width =
BT->getSizeInBits();
670MCRegister SPIRVNonSemanticDebugHandler::findOrEmitScalarType(
673 bool IsFloat =
BT->getEncoding() == dwarf::DW_ATE_float;
674 unsigned Opcode = IsBool ? SPIRV::OpTypeBool
675 : IsFloat ? SPIRV::OpTypeFloat
679 int64_t Width = IsBool ? 0 :
BT->getSizeInBits();
684 if (Opcode == SPIRV::OpTypeInt && Width == 32)
685 return getOrEmitOpTypeInt32Reg(MAI);
688 ScalarTypeCache.try_emplace({Opcode, Width}, MCRegister());
690 return CacheIt->second;
695 if (
MI->getOpcode() != Opcode)
697 if (IsBool || (
MI->getOperand(1).getImm() == Width &&
698 (IsFloat ||
MI->getOperand(2).getImm() == 0))) {
701 return CacheIt->second;
723 CacheIt->second =
Reg;
730 unsigned Words = IsWide ? 2 : 1;
731 if (
MI.getNumOperands() < 2 + Words)
734 for (
unsigned I = 0;
I < Words; ++
I) {
735 if (!
MI.getOperand(2 +
I).isImm())
741 return Found ==
Value;
744MCRegister SPIRVNonSemanticDebugHandler::findModuleConstant(
748 if (
MI->getOpcode() != Opcode ||
MI->getNumOperands() < 2)
762MCRegister SPIRVNonSemanticDebugHandler::findOrEmitConstant(
765 bool IsBool = Width == 0;
766 bool IsWide = Width == 64;
769 ScalarConstantCache.try_emplace({TypeReg.
id(),
Value}, MCRegister());
771 return CacheIt->second;
774 findModuleConstant(Opcode, TypeReg,
Value, IsBool, IsWide, MAI);
776 CacheIt->second = Found;
792 }
else if (Width == 16) {
799 CacheIt->second =
Reg;
803MCRegister SPIRVNonSemanticDebugHandler::findOrEmitScalarConstant(
805 MCRegister TypeReg = findOrEmitScalarType(
BT, MAI);
810 bool IsFloat =
BT->getEncoding() == dwarf::DW_ATE_float;
812 IsBool ? (
Value ? SPIRV::OpConstantTrue : SPIRV::OpConstantFalse)
813 : IsFloat ?
SPIRV::OpConstantF
814 :
SPIRV::OpConstantI;
815 return findOrEmitConstant(Opcode, TypeReg,
Value,
816 IsBool ? 0 :
BT->getSizeInBits(), MAI);
819MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
822 if (
MI->getOpcode() == SPIRV::OpTypeInt &&
823 MI->getOperand(1).getImm() == 32 &&
MI->getOperand(2).getImm() == 0)
836std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
841 if (!PT->getDWARFAddressSpace().has_value())
844 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
845 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
846 MCRegister DebugTypePointerFlagsReg =
847 emitOpConstantI32(transDebugFlags(PT), I32TypeReg, MAI);
851 const auto &
ST =
static_cast<const SPIRVSubtarget &
>(
Asm->getSubtargetInfo());
852 MCRegister StorageClassReg = emitOpConstantI32(
856 if (
const DIType *BaseTy = PT->getBaseType()) {
857 auto BaseIt = DebugScopeRegs.find(BaseTy);
858 if (BaseIt != DebugScopeRegs.end())
860 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg,
862 {BaseIt->second, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
871 SPIRV::NonSemanticExtInst::DebugTypePointer, VoidTypeReg, ExtInstSetReg,
872 {CachedDebugInfoNoneReg, StorageClassReg, DebugTypePointerFlagsReg}, MAI);
875std::optional<MCRegister>
876SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
879 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
880 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
881 MCRegister DebugTypeFunctionFlagsReg =
882 emitOpConstantI32(transDebugFlags(ST), I32TypeReg, MAI);
883 DITypeArray
TA =
ST->getTypeArray();
885 Ops.push_back(DebugTypeFunctionFlagsReg);
890 Ops.push_back(VoidTypeReg);
892 for (
unsigned I = 0,
E =
TA.size();
I !=
E; ++
I) {
893 bool IsReturnType = (
I == 0);
894 auto OptReg = mapDISignatureTypeToReg(TA[
I], VoidTypeReg, IsReturnType);
899 Ops.push_back(*OptReg);
902 return getOrEmitDebugTypeFunction(
Ops, VoidTypeReg, ExtInstSetReg, MAI);
906std::optional<MCRegister> SPIRVNonSemanticDebugHandler::resolveScope(
911 Scope = DLBF->getScope();
914 return lookupOptReg(DebugScopeRegs, Scope);
918 return lookupOptReg(DebugScopeRegs, FallbackCU);
920 if (CompileUnits.empty())
923 return lookupOptReg(DebugScopeRegs, CompileUnits[0].TheCU);
926std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLexicalBlock(
930 "S must be a DILexicalBlock or DINamespace in emitDebugLexicalBlock");
931 auto ParentRegOpt = resolveScope(S->
getScope());
935 MCRegister FileStrReg = getCachedScopePathOpStringReg(
937 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
942 MCRegister LineReg = emitOpConstantI32(
static_cast<uint32_t
>(LB->getLine()),
944 MCRegister ColReg = emitOpConstantI32(
945 static_cast<uint32_t
>(LB->getColumn()), I32TypeReg, MAI);
946 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt};
950 MCRegister LineReg = emitOpConstantI32(0, I32TypeReg, MAI);
951 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
952 MCRegister NameReg = getCachedOpStringReg(NS->getName());
953 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt, NameReg};
956 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLexicalBlock, VoidTypeReg,
957 ExtInstSetReg,
Ops, MAI);
960MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugInlinedAt(
963 assert(IA &&
"IA must not be null in getOrEmitDebugInlinedAt");
965 if (MCRegister Cached = DebugInlinedAtRegs.lookup(IA))
968 auto ScopeRegOpt = resolveScope(
IA->getScope());
973 emitOpConstantI32(
static_cast<uint32_t
>(
IA->getLine()), I32TypeReg, MAI);
978 if (
const DILocation *Outer =
IA->getInlinedAt()) {
979 MCRegister OuterReg = getOrEmitDebugInlinedAt(
980 Outer, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
983 Ops.push_back(OuterReg);
986 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInlinedAt,
987 VoidTypeReg, ExtInstSetReg,
Ops, MAI);
988 DebugInlinedAtRegs[
IA] =
Reg;
992std::optional<MCRegister>
993SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
996 assert(SP &&
"SP must not be null in emitDebugFunctionDeclaration");
998 "SP must not be a definition in emitDebugFunctionDeclaration");
1001 const DISubroutineType *
ST =
SP->getType();
1003 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
1005 return std::nullopt;
1006 MCRegister FnTyReg = *FnTyRegOpt;
1008 auto ParentRegOpt = resolveScope(
SP->getScope(),
SP->getUnit());
1010 return std::nullopt;
1012 MCRegister ParentReg = *ParentRegOpt;
1014 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
1016 MCRegister NameReg = getCachedOpStringReg(
SP->getName());
1017 MCRegister LinkageReg = getCachedOpStringReg(
SP->getLinkageName());
1018 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1019 ExtInstSetReg, MAI);
1021 MCRegister LineReg =
1022 emitOpConstantI32(
static_cast<uint32_t
>(
SP->getLine()), I32TypeReg, MAI);
1023 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1025 uint32_t FlagsVal = transDebugFlags(SP);
1028 FlagsVal &= ~NSDIFlagIsDefinition;
1029 MCRegister FlagsReg = emitOpConstantI32(FlagsVal, I32TypeReg, MAI);
1031 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
1032 VoidTypeReg, ExtInstSetReg,
1033 {NameReg, FnTyReg, SrcReg, LineReg, ColReg, ParentReg,
1034 LinkageReg, FlagsReg},
1038std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugFunction(
1041 assert(SP &&
"SP must not be null in emitDebugFunction");
1042 assert(
SP->isDefinition() &&
"SP must be a definition in emitDebugFunction");
1044 const DISubroutineType *
ST =
SP->getType();
1045 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
1047 return std::nullopt;
1049 auto ParentRegOpt = resolveScope(
SP->getScope(),
SP->getUnit());
1051 return std::nullopt;
1053 MCRegister NameReg = getCachedOpStringReg(
SP->getName());
1054 MCRegister LinkageReg = getCachedOpStringReg(
SP->getLinkageName());
1055 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
1056 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1057 ExtInstSetReg, MAI);
1059 MCRegister LineReg =
1060 emitOpConstantI32(
static_cast<uint32_t
>(
SP->getLine()), I32TypeReg, MAI);
1063 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1064 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(SP), I32TypeReg, MAI);
1065 MCRegister ScopeLineReg = emitOpConstantI32(
1066 static_cast<uint32_t
>(
SP->getScopeLine()), I32TypeReg, MAI);
1069 LineReg, ColReg, *ParentRegOpt,
1070 LinkageReg, FlagsReg, ScopeLineReg};
1072 if (
const DISubprogram *Decl =
SP->getDeclaration()) {
1073 if (
auto DeclRegOpt = lookupOptReg(DebugScopeRegs, Decl))
1074 Ops.push_back(*DeclRegOpt);
1077 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunction, VoidTypeReg,
1078 ExtInstSetReg,
Ops, MAI);
1081std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
1086 assert(CachedDebugInfoNoneReg.isValid() &&
1087 "DebugInfoNone must be emitted before DISubroutineType operands");
1088 return CachedDebugInfoNoneReg;
1090 return lookupOptReg(DebugScopeRegs, Ty);
1108static std::optional<NonSemanticDebugOp>
1111 case dwarf::DW_OP_deref:
1113 case dwarf::DW_OP_plus:
1115 case dwarf::DW_OP_minus:
1117 case dwarf::DW_OP_plus_uconst:
1119 case dwarf::DW_OP_bit_piece:
1121 case dwarf::DW_OP_swap:
1123 case dwarf::DW_OP_xderef:
1125 case dwarf::DW_OP_stack_value:
1127 case dwarf::DW_OP_constu:
1132 return std::nullopt;
1138static std::optional<SmallVector<uint32_t, 3>>
1140 std::optional<NonSemanticDebugOp> NSOp =
1143 return std::nullopt;
1146 for (
unsigned I = 0,
E =
Op.getNumArgs();
I !=
E; ++
I) {
1149 return std::nullopt;
1155std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugOperation(
1161 return std::nullopt;
1163 auto [It,
Inserted] = DebugOperationCache.try_emplace(std::move(*
Key));
1168 for (uint32_t V : It->first)
1169 Operands.push_back(emitOpConstantI32(V, I32TypeReg, MAI));
1170 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugOperation,
1171 VoidTypeReg, ExtInstSetReg,
Operands, MAI);
1176std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugExpression(
1179 assert(Expr &&
"Expr must not be null in emitDebugExpression");
1182 for (
const DIExpression::ExprOperand &
Op : Expr->
expr_ops()) {
1183 std::optional<MCRegister> OpReg =
1184 emitDebugOperation(
Op, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
1186 return std::nullopt;
1191 DebugExpressionCache.try_emplace(std::move(OperationRegs));
1195 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugExpression,
1196 VoidTypeReg, ExtInstSetReg, It->first, MAI);
1201std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugGlobalVariable(
1205 assert(GV &&
"GV must not be null in emitDebugGlobalVariable");
1207 auto ParentRegOpt = resolveScope(GV->
getScope());
1209 return std::nullopt;
1211 MCRegister ParentReg = *ParentRegOpt;
1217 MCRegister TyReg = CachedDebugInfoNoneReg;
1218 if (
const DIType *Ty = GV->
getType()) {
1219 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1221 return std::nullopt;
1225 std::optional<MCRegister> StaticMemberRegOpt;
1227 StaticMemberRegOpt = lookupOptReg(DebugScopeRegs, SM);
1228 if (!StaticMemberRegOpt)
1229 return std::nullopt;
1232 MCRegister NameReg = getCachedOpStringReg(GV->
getName());
1233 MCRegister LinkageReg = getCachedOpStringReg(GV->
getLinkageName());
1234 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1236 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1237 ExtInstSetReg, MAI);
1239 MCRegister LineReg =
1240 emitOpConstantI32(
static_cast<uint32_t
>(GV->
getLine()), I32TypeReg, MAI);
1244 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1251 MCRegister VariableReg = CachedDebugInfoNoneReg;
1252 if (
const GlobalVariable *LLVMGV =
Info.LLVMGV) {
1255 VariableReg = GVReg;
1256 }
else if (
Info.Expr &&
Info.Expr->getNumElements() != 0) {
1257 if (
auto ExprReg = emitDebugExpression(
Info.Expr, VoidTypeReg, I32TypeReg,
1258 ExtInstSetReg, MAI))
1259 VariableReg = *ExprReg;
1262 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(GV), I32TypeReg, MAI);
1265 LineReg, ColReg, ParentReg,
1266 LinkageReg, VariableReg, FlagsReg};
1268 if (StaticMemberRegOpt)
1269 Ops.push_back(*StaticMemberRegOpt);
1271 return emitExtInst(SPIRV::NonSemanticExtInst::DebugGlobalVariable,
1272 VoidTypeReg, ExtInstSetReg,
Ops, MAI);
1275std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLocalVariable(
1278 assert(LV &&
"LV must not be null in emitDebugLocalVariable");
1280 auto ParentRegOpt = resolveScope(LV->
getScope());
1282 return std::nullopt;
1284 MCRegister TyReg = CachedDebugInfoNoneReg;
1285 if (
const DIType *Ty = LV->
getType()) {
1286 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1288 return std::nullopt;
1292 MCRegister NameReg = getCachedOpStringReg(LV->
getName());
1293 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1295 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1296 ExtInstSetReg, MAI);
1297 MCRegister LineReg =
1298 emitOpConstantI32(
static_cast<uint32_t
>(LV->
getLine()), I32TypeReg, MAI);
1300 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1301 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(LV), I32TypeReg, MAI);
1304 ColReg, *ParentRegOpt, FlagsReg};
1305 if (
unsigned Arg = LV->
getArg())
1306 Ops.push_back(emitOpConstantI32(Arg, I32TypeReg, MAI));
1308 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLocalVariable, VoidTypeReg,
1309 ExtInstSetReg,
Ops, MAI);
1312std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
1317 return std::nullopt;
1318 auto BTIt = DebugScopeRegs.find(BaseTy);
1319 if (BTIt == DebugScopeRegs.end())
1320 return std::nullopt;
1326 return std::nullopt;
1330 return std::nullopt;
1332 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1333 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1334 MCRegister CountReg = emitOpConstantI32(
1335 static_cast<uint32_t
>(CI->getZExtValue()), I32TypeReg, MAI);
1336 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeVector, VoidTypeReg,
1337 ExtInstSetReg, {BTIt->second, CountReg}, MAI);
1340std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeArray(
1345 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, AT->
getBaseType());
1347 return std::nullopt;
1349 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1350 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1353 Ops.push_back(*BaseRegOpt);
1369 const APInt &
Value = CI->getValue();
1370 if (
Value.getActiveBits() <= 32)
1371 Count =
static_cast<uint32_t
>(
Value.getZExtValue());
1373 Ops.push_back(emitOpConstantI32(
Count, I32TypeReg, MAI));
1376 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeArray, VoidTypeReg,
1377 ExtInstSetReg,
Ops, MAI);
1380std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeMember(
1384 auto TyRegOpt = lookupOptReg(DebugScopeRegs,
M->getBaseType());
1386 return std::nullopt;
1389 return std::nullopt;
1391 MCRegister NameReg = getCachedOpStringReg(
M->getName());
1392 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1393 M->getFile(),
true);
1394 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1395 ExtInstSetReg, MAI);
1396 MCRegister LineReg =
1397 emitOpConstantI32(
static_cast<uint32_t
>(
M->getLine()), I32TypeReg, MAI);
1400 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1401 MCRegister OffsetReg = emitOpConstantI32(
1402 static_cast<uint32_t
>(
M->getOffsetInBits()), I32TypeReg, MAI);
1403 MCRegister SizeReg = emitOpConstantI32(
1404 static_cast<uint32_t
>(
M->getSizeInBits()), I32TypeReg, MAI);
1405 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(M), I32TypeReg, MAI);
1416 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeMember, VoidTypeReg,
1418 {NameReg, *TyRegOpt, SrcReg, LineReg, ColReg, OffsetReg,
1423std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeComposite(
1427 auto ParentRegOpt = resolveScope(CT->
getScope());
1429 return std::nullopt;
1432 return std::nullopt;
1434 MCRegister NameReg = getCachedOpStringReg(CT->
getName());
1435 MCRegister LinkageReg = getCachedOpStringReg(CT->
getIdentifier());
1436 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1438 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1439 ExtInstSetReg, MAI);
1442 emitOpConstantI32(mapCompositeTypeTag(CT->
getTag()), I32TypeReg, MAI);
1443 MCRegister LineReg =
1444 emitOpConstantI32(
static_cast<uint32_t
>(CT->
getLine()), I32TypeReg, MAI);
1445 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1448 MCRegister SizeReg = CachedDebugInfoNoneReg;
1450 SizeReg = emitOpConstantI32(
static_cast<uint32_t
>(CT->
getSizeInBits()),
1453 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(CT), I32TypeReg, MAI);
1456 LineReg, ColReg, *ParentRegOpt,
1457 LinkageReg, SizeReg, FlagsReg};
1459 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeComposite, VoidTypeReg,
1460 ExtInstSetReg,
Ops, MAI);
1463std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypedef(
1467 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, TD->getBaseType());
1469 return std::nullopt;
1471 MCRegister NameReg = getCachedOpStringReg(TD->
getName());
1472 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1474 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1475 ExtInstSetReg, MAI);
1476 MCRegister LineReg =
1477 emitOpConstantI32(
static_cast<uint32_t
>(TD->
getLine()), I32TypeReg, MAI);
1479 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1484 auto ParentRegOpt = resolveScope(TD->
getScope());
1486 return std::nullopt;
1487 MCRegister ParentReg = *ParentRegOpt;
1490 SPIRV::NonSemanticExtInst::DebugTypedef, VoidTypeReg, ExtInstSetReg,
1491 {NameReg, *BaseRegOpt, SrcReg, LineReg, ColReg, ParentReg}, MAI);
1496 if (CompileUnits.empty())
1504 for (
const CompileUnitInfo &Info : CompileUnits) {
1506 MCRegister PathReg = emitOpStringIfNew(Info.FilePath, MAI);
1507 ScopeToPathOpStringReg[Info.TheCU] = PathReg;
1508 if (
const DIFile *
F = Info.TheCU->getFile())
1509 ScopeToPathOpStringReg[
F] = PathReg;
1514 emitOpStringIfNew(
BT->getName(), MAI);
1517 SubprogramDeclarations, SubprogramDefinitions)) {
1518 emitOpStringIfNew(SP->getName(), MAI);
1519 emitOpStringIfNew(SP->getLinkageName(), MAI);
1520 emitAndCacheScopePathOpStringReg(SP, MAI);
1527 emitOpStringIfNew(CT->
getName(), MAI);
1529 emitAndCacheScopePathOpStringReg(CT->
getFile(), MAI);
1532 if (!M || M->getTag() != dwarf::DW_TAG_member)
1534 emitOpStringIfNew(M->getName(), MAI);
1535 emitAndCacheScopePathOpStringReg(M->getFile(), MAI);
1541 emitOpStringIfNew(TD->
getName(), MAI);
1542 emitAndCacheScopePathOpStringReg(TD->
getFile(), MAI);
1545 for (
const auto &[GV,
_] : GlobalVariableDebugInfoMap) {
1546 emitOpStringIfNew(GV->
getName(), MAI);
1548 emitAndCacheScopePathOpStringReg(GV->
getFile(), MAI);
1552 emitOpStringIfNew(LV->
getName(), MAI);
1553 emitAndCacheScopePathOpStringReg(LV->
getFile(), MAI);
1558 for (
const DIScope *S : LexicalBlocks) {
1559 emitAndCacheScopePathOpStringReg(S->
getFile(), MAI);
1561 emitOpStringIfNew(NS->getName(), MAI);
1565 emitAndCacheScopePathOpStringReg(
DL->getScope(), MAI);
1567 CachedEmptyStringReg = emitOpStringIfNew(
"", MAI);
1570 NonSemanticOpStringsSectionEmitted =
true;
1574void SPIRVNonSemanticDebugHandler::emitDebugFunctionDefinition(
1578 "DebugFunctionDefinition operands must be valid");
1579 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1581 emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDefinition, VoidTypeReg,
1582 ExtInstSetReg, {DebugFunctionReg, OpFunctionReg}, MAI);
1585void SPIRVNonSemanticDebugHandler::resetPerFunctionDebugState() {
1586 CurrentMF =
nullptr;
1587 LastFunctionOpVariable =
nullptr;
1588 DebugFunctionDefinitionEmitted =
false;
1589 LastLineMI =
nullptr;
1590 LastScopeMI =
nullptr;
1594void SPIRVNonSemanticDebugHandler::preparePerFunctionDebug(
1596 resetPerFunctionDebugState();
1597 if (!GlobalNSDIEnabled || !CurrentMAI)
1608 if (!SP || !
SP->isDefinition())
1613 LastFunctionOpVariable =
1614 findLastFunctionOpVariableDeclaration(*MF, *CurrentMAI);
1616 analyzeDebugRecords(*MF);
1619void SPIRVNonSemanticDebugHandler::tryEmitDebugFunctionDefinition(
1621 if (DebugFunctionDefinitionEmitted || !GlobalNSDIEnabled)
1624 assert(CurrentMF &&
"no current MachineFunction");
1625 const Function &
F = CurrentMF->getFunction();
1626 const DISubprogram *
SP =
F.getSubprogram();
1627 if (!SP || !
SP->isDefinition())
1630 auto DFIt = DebugScopeRegs.find(SP);
1631 if (DFIt == DebugScopeRegs.end())
1638 emitDebugFunctionDefinition(DFIt->second, OpFunctionReg, MAI);
1639 DebugFunctionDefinitionEmitted =
true;
1644 preparePerFunctionDebug(MF);
1649 resetPerFunctionDebugState();
1656 if (!DebugFunctionDefinitionEmitted)
1659 emitAnalyzedRecords(
MI);
1661 std::optional<const MachineInstr *>
Target = resolveDebugLocTarget(
MI);
1665 (void)emitDebugScopeForInstruction(*
Target);
1666 emitDebugLineForInstruction(*
Target);
1676static std::optional<Register>
1680 if (!
MI.isIndirectDebugValue())
1681 return std::nullopt;
1685 Register LocReg =
MI.getDebugOperand(0).getReg();
1687 return std::nullopt;
1698 const MachineInstr *Def =
MI.getMF()->getRegInfo().getUniqueVRegDef(LocReg);
1699 if (!Def || Def->getOpcode() != SPIRV::OpVariable)
1700 return std::nullopt;
1705void SPIRVNonSemanticDebugHandler::emitDebugBinding(
1706 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
1708 assert(DebugFunctionDefinitionEmitted &&
1709 "DebugFunctionDefinition must be emitted");
1710 assert(CurrentMAI &&
"CurrentMAI must be set");
1712 auto VarRegOpt = lookupOptReg(DebugLocalVariableRegs,
MI->getDebugVariable());
1716 auto ExprRegOpt = lookupOptReg(DebugExpressionRegs,
MI->getDebugExpression());
1720 if (!emitDebugScopeForInstruction(
MI))
1722 emitDebugLineForInstruction(
MI);
1724 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1725 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1727 emitExtInst(Opcode, VoidTypeReg, ExtInstSetReg,
1728 {*VarRegOpt, LocationReg, *ExprRegOpt}, MAI);
1733static std::optional<std::pair<const DIBasicType *, uint64_t>>
1735 if (!
MI.isNonListDebugValue() ||
MI.isIndirectDebugValue())
1736 return std::nullopt;
1740 return std::nullopt;
1745 return std::nullopt;
1750 else if (
Value.isCImm())
1754 return std::make_pair(
BT, Bits);
1757std::optional<MCRegister> SPIRVNonSemanticDebugHandler::getConstantValueReg(
1759 std::optional<std::pair<const DIBasicType *, uint64_t>>
Const =
1762 return std::nullopt;
1764 auto It = ConstantValueRegs.find(*Const);
1765 if (It == ConstantValueRegs.end() || !It->second.isValid())
1766 return std::nullopt;
1771 if (!
MI.isNonListDebugValue() ||
MI.isIndirectDebugValue())
1772 return std::nullopt;
1776 return std::nullopt;
1780 return std::nullopt;
1782 const MachineInstr *Def =
MI.getMF()->getRegInfo().getUniqueVRegDef(ValueReg);
1783 if (!Def || Def->isPseudo() || Def->isMetaInstruction() ||
1784 Def->getNumOperands() == 0 || !Def->getOperand(0).isReg() ||
1785 !Def->getOperand(0).isDef() || Def->getOperand(0).getReg() != ValueReg)
1786 return std::nullopt;
1792 return Opcode == SPIRV::OpSelectionMerge || Opcode == SPIRV::OpLoopMerge ||
1793 Opcode == SPIRV::OpLoopControlINTEL;
1805 switch (
MI->getOpcode()) {
1806 case SPIRV::OpFunction:
1807 case SPIRV::OpFunctionParameter:
1808 case SPIRV::OpFunctionEnd:
1809 case SPIRV::OpLabel:
1821 :
MI->getPrevNode();
1822 Adj; Adj = Forward ? Adj->getNextNode() : Adj->getPrevNode()) {
1830std::optional<const MachineInstr *>
1831SPIRVNonSemanticDebugHandler::resolveDebugLocTarget(
const MachineInstr *
MI) {
1832 assert(CurrentMAI &&
"CurrentMAI must be set");
1833 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1838 return std::nullopt;
1846 return std::nullopt;
1852 assert(
MI &&
"Merge instruction must be followed by a terminator");
1856 return std::nullopt;
1862void SPIRVNonSemanticDebugHandler::resolveDebugRecord(
1865 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1871 const MachineInstr *Anchor =
1881 placeRecord(SPIRV::NonSemanticExtInst::DebugDeclare,
MI, StorageReg,
1886 if (std::optional<MCRegister> ConstReg = getConstantValueReg(
MI)) {
1887 placeRecord(SPIRV::NonSemanticExtInst::DebugValue,
MI, *ConstReg, Anchor);
1907 if (ModuleScopeIds.contains(ValueReg) ||
1909 placeRecord(SPIRV::NonSemanticExtInst::DebugValue,
MI, ValueReg, Anchor);
1912void SPIRVNonSemanticDebugHandler::analyzeDebugRecords(
1914 assert(CurrentMAI &&
"CurrentMAI must be set");
1918 std::optional<MachineDominatorTree> DomTree;
1920 for (
const MachineBasicBlock &
MBB : MF) {
1921 const MachineInstr *LastEmitted =
nullptr;
1922 for (
const MachineInstr &
MI :
MBB) {
1923 if (
MI.isDebugValueLike()) {
1926 resolveDebugRecord(
MI, LastEmitted, *DomTree);
1935void SPIRVNonSemanticDebugHandler::placeRecord(
1936 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
1939 Records[Anchor].push_back({&
MI, Opcode, LocationReg});
1942void SPIRVNonSemanticDebugHandler::emitAnalyzedRecords(
1944 auto It = Records.find(Anchor);
1945 if (It == Records.end())
1947 for (
const DebugRecord &R : It->second)
1948 emitDebugBinding(
R.Opcode,
R.MI,
R.LocationReg);
1951bool SPIRVNonSemanticDebugHandler::emitDebugScopeForInstruction(
1953 assert(DebugFunctionDefinitionEmitted &&
1954 "DebugFunctionDefinition must be emitted");
1955 assert(CurrentMAI &&
"CurrentMAI must be set");
1960 if (LastScopeMI &&
MI->getParent() != LastScopeMI->getParent())
1961 LastScopeMI =
nullptr;
1963 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1964 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1967 const DILocation *CurDL =
MI->getDebugLoc().get();
1972 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoScope, VoidTypeReg,
1973 ExtInstSetReg, {}, MAI);
1974 LastScopeMI =
nullptr;
1979 const DIScope *CurScope = CurDL->getScope();
1980 const DILocation *CurInlinedAt = CurDL->getInlinedAt();
1983 const DILocation *LastDL = LastScopeMI->getDebugLoc().get();
1984 if (LastDL->getScope() == CurScope &&
1985 LastDL->getInlinedAt() == CurInlinedAt)
1989 auto CurScopeRegOpt = resolveScope(CurScope);
1990 if (!CurScopeRegOpt)
1996 MCRegister InlinedReg = DebugInlinedAtRegs.lookup(CurInlinedAt);
1999 Ops.push_back(InlinedReg);
2003 emitExtInst(SPIRV::NonSemanticExtInst::DebugScope, VoidTypeReg, ExtInstSetReg,
2010void SPIRVNonSemanticDebugHandler::emitDebugLineForInstruction(
2012 assert(DebugFunctionDefinitionEmitted &&
2013 "DebugFunctionDefinition must be emitted");
2014 assert(CurrentMAI &&
"CurrentMAI must be set");
2019 if (LastLineMI &&
MI->getParent() != LastLineMI->getParent())
2020 LastLineMI =
nullptr;
2022 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2023 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2026 const DILocation *
DL =
MI->getDebugLoc().get();
2031 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoLine, VoidTypeReg,
2032 ExtInstSetReg, {}, MAI);
2033 LastLineMI =
nullptr;
2043 MCRegister FileStrReg = getCachedScopePathOpStringReg(
2044 DL->getScope(),
true);
2045 unsigned Line =
DL->getLine();
2046 unsigned Col =
DL->getColumn();
2048 unsigned I32TypeId = CachedOpTypeInt32Reg.id();
2049 MCRegister SrcReg = DebugSourceRegByFileStr.lookup(FileStrReg.
id());
2050 MCRegister LineReg = ScalarConstantCache.lookup({I32TypeId,
Line});
2051 MCRegister ColStartReg = ScalarConstantCache.lookup({I32TypeId, Col});
2052 MCRegister ColEndReg = ScalarConstantCache.lookup({I32TypeId, Col + 1});
2064 if (LastLineMI &&
MI->getDebugLoc() == LastLineMI->getDebugLoc())
2068 emitExtInst(SPIRV::NonSemanticExtInst::DebugLine, VoidTypeReg, ExtInstSetReg,
2069 {SrcReg, LineReg, LineReg, ColStartReg, ColEndReg}, MAI);
2078 if (!
MI || !GlobalNSDIEnabled || !CurrentMF)
2081 if (DebugFunctionDefinitionEmitted ||
MI != LastFunctionOpVariable)
2087 assert(CurrentMAI &&
"CurrentMAI must be set");
2088 tryEmitDebugFunctionDefinition(*CurrentMAI);
2093 if (!GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
2096 assert(CurrentMF == &MF &&
2097 "notification does not match the current MachineFunction");
2099 if (LastFunctionOpVariable)
2105 tryEmitDebugFunctionDefinition(*CurrentMAI);
2116 if (
MI.isDebugValueLike())
2121void SPIRVNonSemanticDebugHandler::collectDebugExpressions(
2123 MachineModuleInfo *ModuleInfo =
Asm->MMI;
2124 assert(ModuleInfo &&
"MachineModuleInfo must be set during module output");
2127 Out.insert(
MI.getDebugExpression());
2133 if (GlobalDIEmitted)
2136 GlobalDIEmitted =
true;
2138 if (CompileUnits.empty()) {
2139 GlobalNSDIEnabled =
false;
2145 if (!ExtInstSetReg.
isValid()) {
2146 GlobalNSDIEnabled =
false;
2151 assert(NonSemanticOpStringsSectionEmitted &&
2152 "emitNonSemanticDebugStrings() must run before "
2153 "emitNonSemanticGlobalDebugInfo()");
2158 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2159 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
2161 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
2162 VoidTypeReg, ExtInstSetReg, {}, MAI);
2174 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
2176 emitOpConstantI32(
static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
2181 map_to_vector(CompileUnits, [&](
const CompileUnitInfo &Info) {
2182 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
2186 for (
auto [Info, SrcLangReg] :
llvm::zip(CompileUnits, SrcLangRegs)) {
2187 MCRegister FileStrReg = ScopeToPathOpStringReg.lookup(Info.TheCU);
2189 "CU path OpString must be emitted in emitNonSemanticDebugStrings");
2190 MCRegister DebugSourceReg = getOrEmitDebugSourceForFileStrReg(
2191 FileStrReg, VoidTypeReg, ExtInstSetReg, MAI);
2193 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
2195 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
2198 DebugScopeRegs[Info.TheCU] = CUDbgReg;
2203 MCRegister I32ZeroReg = emitOpConstantI32(0, I32TypeReg, MAI);
2209 MCRegister NameReg = getCachedOpStringReg(
BT->getName());
2211 static_cast<uint32_t>(
BT->getSizeInBits()), I32TypeReg, MAI);
2215 unsigned Encoding = 0;
2216 switch (
BT->getEncoding()) {
2217 case dwarf::DW_ATE_address:
2220 case dwarf::DW_ATE_boolean:
2223 case dwarf::DW_ATE_float:
2226 case dwarf::DW_ATE_signed:
2229 case dwarf::DW_ATE_signed_char:
2232 case dwarf::DW_ATE_unsigned:
2235 case dwarf::DW_ATE_unsigned_char:
2239 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
2242 SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
2243 {NameReg, SizeReg, EncodingReg, I32ZeroReg}, MAI);
2244 DebugScopeRegs[
BT] = BTReg;
2249 if (
auto VecReg = emitDebugTypeVector(VT, ExtInstSetReg, MAI))
2250 DebugScopeRegs[VT] = *VecReg;
2255 if (
auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
2256 DebugScopeRegs[PT] = *PtrReg;
2263 if (
auto ArrReg = emitDebugTypeArray(AT, ExtInstSetReg, MAI))
2264 DebugScopeRegs[AT] = *ArrReg;
2270 emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI))
2271 DebugScopeRegs[ST] = *FnTyReg;
2283 if (
auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
2284 ExtInstSetReg, MAI))
2285 DebugScopeRegs[S] = *LBReg;
2295 emitDebugTypedef(TD, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
2296 DebugScopeRegs[TD] = *TDReg;
2300 for (
const DISubprogram *SP : SubprogramDeclarations) {
2301 if (
auto DeclReg = emitDebugFunctionDeclaration(SP, VoidTypeReg, I32TypeReg,
2302 ExtInstSetReg, MAI))
2303 DebugScopeRegs[SP] = *DeclReg;
2314 if (!M || M->getTag() != dwarf::DW_TAG_member)
2316 if (
auto MemberReg = emitDebugTypeMember(M, VoidTypeReg, I32TypeReg,
2317 ExtInstSetReg, MAI))
2320 if (
auto CompReg = emitDebugTypeComposite(CT, MemberRegs, VoidTypeReg,
2321 I32TypeReg, ExtInstSetReg, MAI))
2322 DebugScopeRegs[CT] = *CompReg;
2328 emitDebugFunction(SP, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
2329 DebugScopeRegs[SP] = *FnReg;
2338 if (
auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
2339 ExtInstSetReg, MAI))
2340 DebugScopeRegs[S] = *LBReg;
2346 if (
auto LVReg = emitDebugLocalVariable(LV, VoidTypeReg, I32TypeReg,
2347 ExtInstSetReg, MAI))
2348 DebugLocalVariableRegs[LV] = *LVReg;
2355 collectDebugExpressions(Expressions);
2357 if (
auto ExprReg = emitDebugExpression(Expr, VoidTypeReg, I32TypeReg,
2358 ExtInstSetReg, MAI))
2359 DebugExpressionRegs[Expr] = *ExprReg;
2362 for (
const auto &[GV, Info] : GlobalVariableDebugInfoMap)
2363 emitDebugGlobalVariable(GV, Info, VoidTypeReg, I32TypeReg, ExtInstSetReg,
2369 getOrEmitDebugInlinedAt(IA, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
2374 assert(ModuleInfo &&
"MachineModuleInfo must be set during module output");
2376 std::optional<std::pair<const DIBasicType *, uint64_t>> Const =
2380 if (!DebugLocalVariableRegs.contains(
MI.getDebugVariable()) ||
2381 !DebugExpressionRegs.contains(
MI.getDebugExpression()))
2383 auto [It, Inserted] = ConstantValueRegs.try_emplace(*Const,
MCRegister());
2385 It->second = findOrEmitScalarConstant(Const->first, Const->second, MAI);
2386 if (!It->second.isValid())
2387 ConstantValueRegs.erase(It);
2391 emitOpConstantI32(
DL->getLine(), I32TypeReg, MAI);
2392 emitOpConstantI32(
DL->getColumn(), I32TypeReg, MAI);
2393 emitOpConstantI32(
DL->getColumn() + 1, I32TypeReg, MAI);
2395 getCachedScopePathOpStringReg(
DL->getScope(),
2397 getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg, ExtInstSetReg,
2401 GlobalNSDIEnabled =
true;
2405SPIRVNonSemanticDebugHandler::getDebugFullPath(
const DIScope *Scope)
const {
2415 Out.assign(Dir.
begin(), Dir.
end());
2421MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugSourceForFileStrReg(
2424 const unsigned Key = FileStrReg.
id();
2425 auto It = DebugSourceRegByFileStr.find(
Key);
2426 if (It != DebugSourceRegByFileStr.end())
2429 MCRegister
DS = emitExtInst(SPIRV::NonSemanticExtInst::DebugSource,
2430 VoidTypeReg, ExtInstSetReg, {FileStrReg}, MAI);
2431 DebugSourceRegByFileStr[
Key] =
DS;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
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[]
static constexpr StringLiteral Filename
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 void forEachDebugValueLike(const MachineModuleInfo &ModuleInfo, function_ref< void(const MachineInstr &)> Fn)
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)
#define SPIRV_BACKEND_SERVICE_FUN_NAME
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
Class for arbitrary precision integers.
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.
bool isValid() const
Return true if the attribute is any kind of attribute.
Basic type, like 'int' or 'float'.
StringRef getIdentifier() const
DINodeArray getElements() const
DIType * getBaseType() const
A lightweight wrapper around an expression operand.
iterator_range< expr_op_iterator > expr_ops() const
A pair of DIGlobalVariable and DIExpression.
DIDerivedType * getStaticDataMemberDeclaration() const
StringRef getLinkageName() const
DILocalScope * getScope() const
Get the local scope for this variable.
Tagged DWARF-like metadata node.
LLVM_ABI dwarf::Tag getTag() const
Base class for scope-like contexts.
LLVM_ABI DIScope * getScope() const
Subprogram description. Uses SubclassData1.
Type array for a subprogram.
StringRef getName() const
bool isForwardDecl() const
uint64_t getSizeInBits() const
DIScope * getScope() const
DIScope * getScope() 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.
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< global_variable_expression_iterator > global_variables() const
iterator_range< subprogram_iterator > subprograms() const
iterator_range< type_iterator > types() const
iterator_range< scope_iterator > scopes() const
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.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
DISubprogram * getSubprogram() const
Get the attached subprogram.
Instances of this class represent a single low-level machine instruction.
void setFlags(unsigned F)
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
constexpr unsigned id() const
Tracking metadata reference owned by Metadata.
bool equalsStr(StringRef Str) const
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.
This class contains meta information specific to a module.
const Module * getModule() const
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
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.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
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...
SPIRVNonSemanticDebugHandler(AsmPrinter &AP)
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.
bool insert(const value_type &X)
Insert a new element into the SetVector.
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...
void push_back(const T &Elt)
reverse_iterator rbegin()
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.
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
NodeAddr< DefNode * > Def
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.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
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.
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 ...
bool isa_and_nonnull(const Y &Val)
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
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.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
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.
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...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
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)
MCRegister getNextIDRegister()
void addExtension(Extension::Extension ToAdd)