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(
910 return lookupOptReg(DebugScopeRegs, Scope);
914 return lookupOptReg(DebugScopeRegs, FallbackCU);
916 if (CompileUnits.empty())
919 return lookupOptReg(DebugScopeRegs, CompileUnits[0].TheCU);
922std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLexicalBlock(
926 "S must be a DILexicalBlock or DINamespace in emitDebugLexicalBlock");
927 auto ParentRegOpt = resolveScope(S->
getScope());
931 MCRegister FileStrReg = getCachedScopePathOpStringReg(
933 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
938 MCRegister LineReg = emitOpConstantI32(
static_cast<uint32_t
>(LB->getLine()),
940 MCRegister ColReg = emitOpConstantI32(
941 static_cast<uint32_t
>(LB->getColumn()), I32TypeReg, MAI);
942 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt};
946 MCRegister LineReg = emitOpConstantI32(0, I32TypeReg, MAI);
947 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
948 MCRegister NameReg = getCachedOpStringReg(NS->getName());
949 Ops = {SrcReg, LineReg, ColReg, *ParentRegOpt, NameReg};
952 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLexicalBlock, VoidTypeReg,
953 ExtInstSetReg,
Ops, MAI);
956MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugInlinedAt(
959 assert(IA &&
"IA must not be null in getOrEmitDebugInlinedAt");
961 if (MCRegister Cached = DebugInlinedAtRegs.lookup(IA))
964 auto ScopeRegOpt = resolveScope(
IA->getScope());
969 emitOpConstantI32(
static_cast<uint32_t
>(
IA->getLine()), I32TypeReg, MAI);
974 if (
const DILocation *Outer =
IA->getInlinedAt()) {
975 MCRegister OuterReg = getOrEmitDebugInlinedAt(
976 Outer, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
979 Ops.push_back(OuterReg);
982 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInlinedAt,
983 VoidTypeReg, ExtInstSetReg,
Ops, MAI);
984 DebugInlinedAtRegs[
IA] =
Reg;
988std::optional<MCRegister>
989SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
992 assert(SP &&
"SP must not be null in emitDebugFunctionDeclaration");
994 "SP must not be a definition in emitDebugFunctionDeclaration");
997 const DISubroutineType *
ST =
SP->getType();
999 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
1001 return std::nullopt;
1002 MCRegister FnTyReg = *FnTyRegOpt;
1004 auto ParentRegOpt = resolveScope(
SP->getScope(),
SP->getUnit());
1006 return std::nullopt;
1008 MCRegister ParentReg = *ParentRegOpt;
1010 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
1012 MCRegister NameReg = getCachedOpStringReg(
SP->getName());
1013 MCRegister LinkageReg = getCachedOpStringReg(
SP->getLinkageName());
1014 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1015 ExtInstSetReg, MAI);
1017 MCRegister LineReg =
1018 emitOpConstantI32(
static_cast<uint32_t
>(
SP->getLine()), I32TypeReg, MAI);
1019 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1021 uint32_t FlagsVal = transDebugFlags(SP);
1024 FlagsVal &= ~NSDIFlagIsDefinition;
1025 MCRegister FlagsReg = emitOpConstantI32(FlagsVal, I32TypeReg, MAI);
1027 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
1028 VoidTypeReg, ExtInstSetReg,
1029 {NameReg, FnTyReg, SrcReg, LineReg, ColReg, ParentReg,
1030 LinkageReg, FlagsReg},
1034std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugFunction(
1037 assert(SP &&
"SP must not be null in emitDebugFunction");
1038 assert(
SP->isDefinition() &&
"SP must be a definition in emitDebugFunction");
1040 const DISubroutineType *
ST =
SP->getType();
1041 auto FnTyRegOpt = lookupOptReg(DebugScopeRegs, ST);
1043 return std::nullopt;
1045 auto ParentRegOpt = resolveScope(
SP->getScope(),
SP->getUnit());
1047 return std::nullopt;
1049 MCRegister NameReg = getCachedOpStringReg(
SP->getName());
1050 MCRegister LinkageReg = getCachedOpStringReg(
SP->getLinkageName());
1051 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
1052 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1053 ExtInstSetReg, MAI);
1055 MCRegister LineReg =
1056 emitOpConstantI32(
static_cast<uint32_t
>(
SP->getLine()), I32TypeReg, MAI);
1059 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1060 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(SP), I32TypeReg, MAI);
1061 MCRegister ScopeLineReg = emitOpConstantI32(
1062 static_cast<uint32_t
>(
SP->getScopeLine()), I32TypeReg, MAI);
1065 LineReg, ColReg, *ParentRegOpt,
1066 LinkageReg, FlagsReg, ScopeLineReg};
1068 if (
const DISubprogram *Decl =
SP->getDeclaration()) {
1069 if (
auto DeclRegOpt = lookupOptReg(DebugScopeRegs, Decl))
1070 Ops.push_back(*DeclRegOpt);
1073 return emitExtInst(SPIRV::NonSemanticExtInst::DebugFunction, VoidTypeReg,
1074 ExtInstSetReg,
Ops, MAI);
1077std::optional<MCRegister> SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
1082 assert(CachedDebugInfoNoneReg.isValid() &&
1083 "DebugInfoNone must be emitted before DISubroutineType operands");
1084 return CachedDebugInfoNoneReg;
1086 return lookupOptReg(DebugScopeRegs, Ty);
1104static std::optional<NonSemanticDebugOp>
1107 case dwarf::DW_OP_deref:
1109 case dwarf::DW_OP_plus:
1111 case dwarf::DW_OP_minus:
1113 case dwarf::DW_OP_plus_uconst:
1115 case dwarf::DW_OP_bit_piece:
1117 case dwarf::DW_OP_swap:
1119 case dwarf::DW_OP_xderef:
1121 case dwarf::DW_OP_stack_value:
1123 case dwarf::DW_OP_constu:
1128 return std::nullopt;
1134static std::optional<SmallVector<uint32_t, 3>>
1136 std::optional<NonSemanticDebugOp> NSOp =
1139 return std::nullopt;
1142 for (
unsigned I = 0,
E =
Op.getNumArgs();
I !=
E; ++
I) {
1145 return std::nullopt;
1151std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugOperation(
1157 return std::nullopt;
1159 auto [It,
Inserted] = DebugOperationCache.try_emplace(std::move(*
Key));
1164 for (uint32_t V : It->first)
1165 Operands.push_back(emitOpConstantI32(V, I32TypeReg, MAI));
1166 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugOperation,
1167 VoidTypeReg, ExtInstSetReg,
Operands, MAI);
1172std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugExpression(
1175 assert(Expr &&
"Expr must not be null in emitDebugExpression");
1178 for (
const DIExpression::ExprOperand &
Op : Expr->
expr_ops()) {
1179 std::optional<MCRegister> OpReg =
1180 emitDebugOperation(
Op, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
1182 return std::nullopt;
1187 DebugExpressionCache.try_emplace(std::move(OperationRegs));
1191 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugExpression,
1192 VoidTypeReg, ExtInstSetReg, It->first, MAI);
1197std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugGlobalVariable(
1201 assert(GV &&
"GV must not be null in emitDebugGlobalVariable");
1203 auto ParentRegOpt = resolveScope(GV->
getScope());
1205 return std::nullopt;
1207 MCRegister ParentReg = *ParentRegOpt;
1213 MCRegister TyReg = CachedDebugInfoNoneReg;
1214 if (
const DIType *Ty = GV->
getType()) {
1215 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1217 return std::nullopt;
1221 std::optional<MCRegister> StaticMemberRegOpt;
1223 StaticMemberRegOpt = lookupOptReg(DebugScopeRegs, SM);
1224 if (!StaticMemberRegOpt)
1225 return std::nullopt;
1228 MCRegister NameReg = getCachedOpStringReg(GV->
getName());
1229 MCRegister LinkageReg = getCachedOpStringReg(GV->
getLinkageName());
1230 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1232 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1233 ExtInstSetReg, MAI);
1235 MCRegister LineReg =
1236 emitOpConstantI32(
static_cast<uint32_t
>(GV->
getLine()), I32TypeReg, MAI);
1240 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1247 MCRegister VariableReg = CachedDebugInfoNoneReg;
1248 if (
const GlobalVariable *LLVMGV =
Info.LLVMGV) {
1251 VariableReg = GVReg;
1252 }
else if (
Info.Expr &&
Info.Expr->getNumElements() != 0) {
1253 if (
auto ExprReg = emitDebugExpression(
Info.Expr, VoidTypeReg, I32TypeReg,
1254 ExtInstSetReg, MAI))
1255 VariableReg = *ExprReg;
1258 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(GV), I32TypeReg, MAI);
1261 LineReg, ColReg, ParentReg,
1262 LinkageReg, VariableReg, FlagsReg};
1264 if (StaticMemberRegOpt)
1265 Ops.push_back(*StaticMemberRegOpt);
1267 return emitExtInst(SPIRV::NonSemanticExtInst::DebugGlobalVariable,
1268 VoidTypeReg, ExtInstSetReg,
Ops, MAI);
1271std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLocalVariable(
1274 assert(LV &&
"LV must not be null in emitDebugLocalVariable");
1276 auto ParentRegOpt = resolveScope(LV->
getScope());
1278 return std::nullopt;
1280 MCRegister TyReg = CachedDebugInfoNoneReg;
1281 if (
const DIType *Ty = LV->
getType()) {
1282 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1284 return std::nullopt;
1288 MCRegister NameReg = getCachedOpStringReg(LV->
getName());
1289 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1291 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1292 ExtInstSetReg, MAI);
1293 MCRegister LineReg =
1294 emitOpConstantI32(
static_cast<uint32_t
>(LV->
getLine()), I32TypeReg, MAI);
1296 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1297 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(LV), I32TypeReg, MAI);
1300 ColReg, *ParentRegOpt, FlagsReg};
1301 if (
unsigned Arg = LV->
getArg())
1302 Ops.push_back(emitOpConstantI32(Arg, I32TypeReg, MAI));
1304 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLocalVariable, VoidTypeReg,
1305 ExtInstSetReg,
Ops, MAI);
1308std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
1313 return std::nullopt;
1314 auto BTIt = DebugScopeRegs.find(BaseTy);
1315 if (BTIt == DebugScopeRegs.end())
1316 return std::nullopt;
1322 return std::nullopt;
1326 return std::nullopt;
1328 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1329 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1330 MCRegister CountReg = emitOpConstantI32(
1331 static_cast<uint32_t
>(CI->getZExtValue()), I32TypeReg, MAI);
1332 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeVector, VoidTypeReg,
1333 ExtInstSetReg, {BTIt->second, CountReg}, MAI);
1336std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeArray(
1341 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, AT->
getBaseType());
1343 return std::nullopt;
1345 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1346 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1349 Ops.push_back(*BaseRegOpt);
1365 const APInt &
Value = CI->getValue();
1366 if (
Value.getActiveBits() <= 32)
1367 Count =
static_cast<uint32_t
>(
Value.getZExtValue());
1369 Ops.push_back(emitOpConstantI32(
Count, I32TypeReg, MAI));
1372 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeArray, VoidTypeReg,
1373 ExtInstSetReg,
Ops, MAI);
1376std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeMember(
1380 auto TyRegOpt = lookupOptReg(DebugScopeRegs,
M->getBaseType());
1382 return std::nullopt;
1385 return std::nullopt;
1387 MCRegister NameReg = getCachedOpStringReg(
M->getName());
1388 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1389 M->getFile(),
true);
1390 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1391 ExtInstSetReg, MAI);
1392 MCRegister LineReg =
1393 emitOpConstantI32(
static_cast<uint32_t
>(
M->getLine()), I32TypeReg, MAI);
1396 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1397 MCRegister OffsetReg = emitOpConstantI32(
1398 static_cast<uint32_t
>(
M->getOffsetInBits()), I32TypeReg, MAI);
1399 MCRegister SizeReg = emitOpConstantI32(
1400 static_cast<uint32_t
>(
M->getSizeInBits()), I32TypeReg, MAI);
1401 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(M), I32TypeReg, MAI);
1412 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeMember, VoidTypeReg,
1414 {NameReg, *TyRegOpt, SrcReg, LineReg, ColReg, OffsetReg,
1419std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypeComposite(
1423 auto ParentRegOpt = resolveScope(CT->
getScope());
1425 return std::nullopt;
1428 return std::nullopt;
1430 MCRegister NameReg = getCachedOpStringReg(CT->
getName());
1431 MCRegister LinkageReg = getCachedOpStringReg(CT->
getIdentifier());
1432 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1434 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1435 ExtInstSetReg, MAI);
1438 emitOpConstantI32(mapCompositeTypeTag(CT->
getTag()), I32TypeReg, MAI);
1439 MCRegister LineReg =
1440 emitOpConstantI32(
static_cast<uint32_t
>(CT->
getLine()), I32TypeReg, MAI);
1441 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1444 MCRegister SizeReg = CachedDebugInfoNoneReg;
1446 SizeReg = emitOpConstantI32(
static_cast<uint32_t
>(CT->
getSizeInBits()),
1449 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(CT), I32TypeReg, MAI);
1452 LineReg, ColReg, *ParentRegOpt,
1453 LinkageReg, SizeReg, FlagsReg};
1455 return emitExtInst(SPIRV::NonSemanticExtInst::DebugTypeComposite, VoidTypeReg,
1456 ExtInstSetReg,
Ops, MAI);
1459std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugTypedef(
1463 auto BaseRegOpt = lookupOptReg(DebugScopeRegs, TD->getBaseType());
1465 return std::nullopt;
1467 MCRegister NameReg = getCachedOpStringReg(TD->
getName());
1468 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1470 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1471 ExtInstSetReg, MAI);
1472 MCRegister LineReg =
1473 emitOpConstantI32(
static_cast<uint32_t
>(TD->
getLine()), I32TypeReg, MAI);
1475 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1480 auto ParentRegOpt = resolveScope(TD->
getScope());
1482 return std::nullopt;
1483 MCRegister ParentReg = *ParentRegOpt;
1486 SPIRV::NonSemanticExtInst::DebugTypedef, VoidTypeReg, ExtInstSetReg,
1487 {NameReg, *BaseRegOpt, SrcReg, LineReg, ColReg, ParentReg}, MAI);
1492 if (CompileUnits.empty())
1500 for (
const CompileUnitInfo &Info : CompileUnits) {
1502 MCRegister PathReg = emitOpStringIfNew(Info.FilePath, MAI);
1503 ScopeToPathOpStringReg[Info.TheCU] = PathReg;
1504 if (
const DIFile *
F = Info.TheCU->getFile())
1505 ScopeToPathOpStringReg[
F] = PathReg;
1510 emitOpStringIfNew(
BT->getName(), MAI);
1513 SubprogramDeclarations, SubprogramDefinitions)) {
1514 emitOpStringIfNew(SP->getName(), MAI);
1515 emitOpStringIfNew(SP->getLinkageName(), MAI);
1516 emitAndCacheScopePathOpStringReg(SP, MAI);
1523 emitOpStringIfNew(CT->
getName(), MAI);
1525 emitAndCacheScopePathOpStringReg(CT->
getFile(), MAI);
1528 if (!M || M->getTag() != dwarf::DW_TAG_member)
1530 emitOpStringIfNew(M->getName(), MAI);
1531 emitAndCacheScopePathOpStringReg(M->getFile(), MAI);
1537 emitOpStringIfNew(TD->
getName(), MAI);
1538 emitAndCacheScopePathOpStringReg(TD->
getFile(), MAI);
1541 for (
const auto &[GV,
_] : GlobalVariableDebugInfoMap) {
1542 emitOpStringIfNew(GV->
getName(), MAI);
1544 emitAndCacheScopePathOpStringReg(GV->
getFile(), MAI);
1548 emitOpStringIfNew(LV->
getName(), MAI);
1549 emitAndCacheScopePathOpStringReg(LV->
getFile(), MAI);
1554 for (
const DIScope *S : LexicalBlocks) {
1555 emitAndCacheScopePathOpStringReg(S->
getFile(), MAI);
1557 emitOpStringIfNew(NS->getName(), MAI);
1561 emitAndCacheScopePathOpStringReg(
DL->getScope(), MAI);
1563 CachedEmptyStringReg = emitOpStringIfNew(
"", MAI);
1566 NonSemanticOpStringsSectionEmitted =
true;
1570void SPIRVNonSemanticDebugHandler::emitDebugFunctionDefinition(
1574 "DebugFunctionDefinition operands must be valid");
1575 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1577 emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDefinition, VoidTypeReg,
1578 ExtInstSetReg, {DebugFunctionReg, OpFunctionReg}, MAI);
1581void SPIRVNonSemanticDebugHandler::resetPerFunctionDebugState() {
1582 CurrentMF =
nullptr;
1583 LastFunctionOpVariable =
nullptr;
1584 DebugFunctionDefinitionEmitted =
false;
1585 LastLineMI =
nullptr;
1586 LastScopeMI =
nullptr;
1590void SPIRVNonSemanticDebugHandler::preparePerFunctionDebug(
1592 resetPerFunctionDebugState();
1593 if (!GlobalNSDIEnabled || !CurrentMAI)
1604 if (!SP || !
SP->isDefinition())
1609 LastFunctionOpVariable =
1610 findLastFunctionOpVariableDeclaration(*MF, *CurrentMAI);
1612 analyzeDebugRecords(*MF);
1615void SPIRVNonSemanticDebugHandler::tryEmitDebugFunctionDefinition(
1617 if (DebugFunctionDefinitionEmitted || !GlobalNSDIEnabled)
1620 assert(CurrentMF &&
"no current MachineFunction");
1621 const Function &
F = CurrentMF->getFunction();
1622 const DISubprogram *
SP =
F.getSubprogram();
1623 if (!SP || !
SP->isDefinition())
1626 auto DFIt = DebugScopeRegs.find(SP);
1627 if (DFIt == DebugScopeRegs.end())
1634 emitDebugFunctionDefinition(DFIt->second, OpFunctionReg, MAI);
1635 DebugFunctionDefinitionEmitted =
true;
1640 preparePerFunctionDebug(MF);
1645 resetPerFunctionDebugState();
1652 if (!DebugFunctionDefinitionEmitted)
1655 emitAnalyzedRecords(
MI);
1657 std::optional<const MachineInstr *>
Target = resolveDebugLocTarget(
MI);
1661 (void)emitDebugScopeForInstruction(*
Target);
1662 emitDebugLineForInstruction(*
Target);
1672static std::optional<Register>
1676 if (!
MI.isIndirectDebugValue())
1677 return std::nullopt;
1681 Register LocReg =
MI.getDebugOperand(0).getReg();
1683 return std::nullopt;
1694 const MachineInstr *Def =
MI.getMF()->getRegInfo().getUniqueVRegDef(LocReg);
1695 if (!Def || Def->getOpcode() != SPIRV::OpVariable)
1696 return std::nullopt;
1701void SPIRVNonSemanticDebugHandler::emitDebugBinding(
1702 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
1704 assert(DebugFunctionDefinitionEmitted &&
1705 "DebugFunctionDefinition must be emitted");
1706 assert(CurrentMAI &&
"CurrentMAI must be set");
1708 auto VarRegOpt = lookupOptReg(DebugLocalVariableRegs,
MI->getDebugVariable());
1712 auto ExprRegOpt = lookupOptReg(DebugExpressionRegs,
MI->getDebugExpression());
1716 if (!emitDebugScopeForInstruction(
MI))
1718 emitDebugLineForInstruction(
MI);
1720 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1721 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1723 emitExtInst(Opcode, VoidTypeReg, ExtInstSetReg,
1724 {*VarRegOpt, LocationReg, *ExprRegOpt}, MAI);
1729static std::optional<std::pair<const DIBasicType *, uint64_t>>
1731 if (!
MI.isNonListDebugValue() ||
MI.isIndirectDebugValue())
1732 return std::nullopt;
1736 return std::nullopt;
1741 return std::nullopt;
1746 else if (
Value.isCImm())
1750 return std::make_pair(
BT, Bits);
1753std::optional<MCRegister> SPIRVNonSemanticDebugHandler::getConstantValueReg(
1755 std::optional<std::pair<const DIBasicType *, uint64_t>>
Const =
1758 return std::nullopt;
1760 auto It = ConstantValueRegs.find(*Const);
1761 if (It == ConstantValueRegs.end() || !It->second.isValid())
1762 return std::nullopt;
1767 if (!
MI.isNonListDebugValue() ||
MI.isIndirectDebugValue())
1768 return std::nullopt;
1772 return std::nullopt;
1776 return std::nullopt;
1778 const MachineInstr *Def =
MI.getMF()->getRegInfo().getUniqueVRegDef(ValueReg);
1779 if (!Def || Def->isPseudo() || Def->isMetaInstruction() ||
1780 Def->getNumOperands() == 0 || !Def->getOperand(0).isReg() ||
1781 !Def->getOperand(0).isDef() || Def->getOperand(0).getReg() != ValueReg)
1782 return std::nullopt;
1788 return Opcode == SPIRV::OpSelectionMerge || Opcode == SPIRV::OpLoopMerge ||
1789 Opcode == SPIRV::OpLoopControlINTEL;
1801 switch (
MI->getOpcode()) {
1802 case SPIRV::OpFunction:
1803 case SPIRV::OpFunctionParameter:
1804 case SPIRV::OpFunctionEnd:
1805 case SPIRV::OpLabel:
1817 :
MI->getPrevNode();
1818 Adj; Adj = Forward ? Adj->getNextNode() : Adj->getPrevNode()) {
1826std::optional<const MachineInstr *>
1827SPIRVNonSemanticDebugHandler::resolveDebugLocTarget(
const MachineInstr *
MI) {
1828 assert(CurrentMAI &&
"CurrentMAI must be set");
1829 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1834 return std::nullopt;
1842 return std::nullopt;
1848 assert(
MI &&
"Merge instruction must be followed by a terminator");
1852 return std::nullopt;
1858void SPIRVNonSemanticDebugHandler::resolveDebugRecord(
1861 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1867 const MachineInstr *Anchor =
1877 placeRecord(SPIRV::NonSemanticExtInst::DebugDeclare,
MI, StorageReg,
1882 if (std::optional<MCRegister> ConstReg = getConstantValueReg(
MI)) {
1883 placeRecord(SPIRV::NonSemanticExtInst::DebugValue,
MI, *ConstReg, Anchor);
1903 if (ModuleScopeIds.contains(ValueReg) ||
1905 placeRecord(SPIRV::NonSemanticExtInst::DebugValue,
MI, ValueReg, Anchor);
1908void SPIRVNonSemanticDebugHandler::analyzeDebugRecords(
1910 assert(CurrentMAI &&
"CurrentMAI must be set");
1914 std::optional<MachineDominatorTree> DomTree;
1916 for (
const MachineBasicBlock &
MBB : MF) {
1917 const MachineInstr *LastEmitted =
nullptr;
1918 for (
const MachineInstr &
MI :
MBB) {
1919 if (
MI.isDebugValueLike()) {
1922 resolveDebugRecord(
MI, LastEmitted, *DomTree);
1931void SPIRVNonSemanticDebugHandler::placeRecord(
1932 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
1935 Records[Anchor].push_back({&
MI, Opcode, LocationReg});
1938void SPIRVNonSemanticDebugHandler::emitAnalyzedRecords(
1940 auto It = Records.find(Anchor);
1941 if (It == Records.end())
1943 for (
const DebugRecord &R : It->second)
1944 emitDebugBinding(
R.Opcode,
R.MI,
R.LocationReg);
1947bool SPIRVNonSemanticDebugHandler::emitDebugScopeForInstruction(
1949 assert(DebugFunctionDefinitionEmitted &&
1950 "DebugFunctionDefinition must be emitted");
1951 assert(CurrentMAI &&
"CurrentMAI must be set");
1956 if (LastScopeMI &&
MI->getParent() != LastScopeMI->getParent())
1957 LastScopeMI =
nullptr;
1959 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
1960 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1963 const DILocation *CurDL =
MI->getDebugLoc().get();
1968 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoScope, VoidTypeReg,
1969 ExtInstSetReg, {}, MAI);
1970 LastScopeMI =
nullptr;
1975 const DIScope *CurScope = CurDL->getScope();
1976 const DILocation *CurInlinedAt = CurDL->getInlinedAt();
1979 const DILocation *LastDL = LastScopeMI->getDebugLoc().get();
1980 if (LastDL->getScope() == CurScope &&
1981 LastDL->getInlinedAt() == CurInlinedAt)
1985 auto CurScopeRegOpt = resolveScope(CurScope);
1986 if (!CurScopeRegOpt)
1992 MCRegister InlinedReg = DebugInlinedAtRegs.lookup(CurInlinedAt);
1995 Ops.push_back(InlinedReg);
1999 emitExtInst(SPIRV::NonSemanticExtInst::DebugScope, VoidTypeReg, ExtInstSetReg,
2006void SPIRVNonSemanticDebugHandler::emitDebugLineForInstruction(
2008 assert(DebugFunctionDefinitionEmitted &&
2009 "DebugFunctionDefinition must be emitted");
2010 assert(CurrentMAI &&
"CurrentMAI must be set");
2015 if (LastLineMI &&
MI->getParent() != LastLineMI->getParent())
2016 LastLineMI =
nullptr;
2018 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2019 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2022 const DILocation *
DL =
MI->getDebugLoc().get();
2027 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoLine, VoidTypeReg,
2028 ExtInstSetReg, {}, MAI);
2029 LastLineMI =
nullptr;
2039 MCRegister FileStrReg = getCachedScopePathOpStringReg(
2040 DL->getScope(),
true);
2041 unsigned Line =
DL->getLine();
2042 unsigned Col =
DL->getColumn();
2044 unsigned I32TypeId = CachedOpTypeInt32Reg.id();
2045 MCRegister SrcReg = DebugSourceRegByFileStr.lookup(FileStrReg.
id());
2046 MCRegister LineReg = ScalarConstantCache.lookup({I32TypeId,
Line});
2047 MCRegister ColStartReg = ScalarConstantCache.lookup({I32TypeId, Col});
2048 MCRegister ColEndReg = ScalarConstantCache.lookup({I32TypeId, Col + 1});
2060 if (LastLineMI &&
MI->getDebugLoc() == LastLineMI->getDebugLoc())
2064 emitExtInst(SPIRV::NonSemanticExtInst::DebugLine, VoidTypeReg, ExtInstSetReg,
2065 {SrcReg, LineReg, LineReg, ColStartReg, ColEndReg}, MAI);
2074 if (!
MI || !GlobalNSDIEnabled || !CurrentMF)
2077 if (DebugFunctionDefinitionEmitted ||
MI != LastFunctionOpVariable)
2083 assert(CurrentMAI &&
"CurrentMAI must be set");
2084 tryEmitDebugFunctionDefinition(*CurrentMAI);
2089 if (!GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
2092 assert(CurrentMF == &MF &&
2093 "notification does not match the current MachineFunction");
2095 if (LastFunctionOpVariable)
2101 tryEmitDebugFunctionDefinition(*CurrentMAI);
2112 if (
MI.isDebugValueLike())
2117void SPIRVNonSemanticDebugHandler::collectDebugExpressions(
2119 MachineModuleInfo *ModuleInfo =
Asm->MMI;
2120 assert(ModuleInfo &&
"MachineModuleInfo must be set during module output");
2123 Out.insert(
MI.getDebugExpression());
2129 if (GlobalDIEmitted)
2132 GlobalDIEmitted =
true;
2134 if (CompileUnits.empty()) {
2135 GlobalNSDIEnabled =
false;
2141 if (!ExtInstSetReg.
isValid()) {
2142 GlobalNSDIEnabled =
false;
2147 assert(NonSemanticOpStringsSectionEmitted &&
2148 "emitNonSemanticDebugStrings() must run before "
2149 "emitNonSemanticGlobalDebugInfo()");
2154 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2155 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
2157 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
2158 VoidTypeReg, ExtInstSetReg, {}, MAI);
2170 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
2172 emitOpConstantI32(
static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
2177 map_to_vector(CompileUnits, [&](
const CompileUnitInfo &Info) {
2178 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
2182 for (
auto [Info, SrcLangReg] :
llvm::zip(CompileUnits, SrcLangRegs)) {
2183 MCRegister FileStrReg = ScopeToPathOpStringReg.lookup(Info.TheCU);
2185 "CU path OpString must be emitted in emitNonSemanticDebugStrings");
2186 MCRegister DebugSourceReg = getOrEmitDebugSourceForFileStrReg(
2187 FileStrReg, VoidTypeReg, ExtInstSetReg, MAI);
2189 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
2191 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
2194 DebugScopeRegs[Info.TheCU] = CUDbgReg;
2199 MCRegister I32ZeroReg = emitOpConstantI32(0, I32TypeReg, MAI);
2205 MCRegister NameReg = getCachedOpStringReg(
BT->getName());
2207 static_cast<uint32_t>(
BT->getSizeInBits()), I32TypeReg, MAI);
2211 unsigned Encoding = 0;
2212 switch (
BT->getEncoding()) {
2213 case dwarf::DW_ATE_address:
2216 case dwarf::DW_ATE_boolean:
2219 case dwarf::DW_ATE_float:
2222 case dwarf::DW_ATE_signed:
2225 case dwarf::DW_ATE_signed_char:
2228 case dwarf::DW_ATE_unsigned:
2231 case dwarf::DW_ATE_unsigned_char:
2235 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
2238 SPIRV::NonSemanticExtInst::DebugTypeBasic, VoidTypeReg, ExtInstSetReg,
2239 {NameReg, SizeReg, EncodingReg, I32ZeroReg}, MAI);
2240 DebugScopeRegs[
BT] = BTReg;
2245 if (
auto VecReg = emitDebugTypeVector(VT, ExtInstSetReg, MAI))
2246 DebugScopeRegs[VT] = *VecReg;
2251 if (
auto PtrReg = emitDebugTypePointer(PT, ExtInstSetReg, MAI))
2252 DebugScopeRegs[PT] = *PtrReg;
2259 if (
auto ArrReg = emitDebugTypeArray(AT, ExtInstSetReg, MAI))
2260 DebugScopeRegs[AT] = *ArrReg;
2266 emitDebugTypeFunctionForSubroutineType(ST, ExtInstSetReg, MAI))
2267 DebugScopeRegs[ST] = *FnTyReg;
2279 if (
auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
2280 ExtInstSetReg, MAI))
2281 DebugScopeRegs[S] = *LBReg;
2291 emitDebugTypedef(TD, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
2292 DebugScopeRegs[TD] = *TDReg;
2296 for (
const DISubprogram *SP : SubprogramDeclarations) {
2297 if (
auto DeclReg = emitDebugFunctionDeclaration(SP, VoidTypeReg, I32TypeReg,
2298 ExtInstSetReg, MAI))
2299 DebugScopeRegs[SP] = *DeclReg;
2310 if (!M || M->getTag() != dwarf::DW_TAG_member)
2312 if (
auto MemberReg = emitDebugTypeMember(M, VoidTypeReg, I32TypeReg,
2313 ExtInstSetReg, MAI))
2316 if (
auto CompReg = emitDebugTypeComposite(CT, MemberRegs, VoidTypeReg,
2317 I32TypeReg, ExtInstSetReg, MAI))
2318 DebugScopeRegs[CT] = *CompReg;
2324 emitDebugFunction(SP, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI))
2325 DebugScopeRegs[SP] = *FnReg;
2334 if (
auto LBReg = emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg,
2335 ExtInstSetReg, MAI))
2336 DebugScopeRegs[S] = *LBReg;
2342 if (
auto LVReg = emitDebugLocalVariable(LV, VoidTypeReg, I32TypeReg,
2343 ExtInstSetReg, MAI))
2344 DebugLocalVariableRegs[LV] = *LVReg;
2351 collectDebugExpressions(Expressions);
2353 if (
auto ExprReg = emitDebugExpression(Expr, VoidTypeReg, I32TypeReg,
2354 ExtInstSetReg, MAI))
2355 DebugExpressionRegs[Expr] = *ExprReg;
2358 for (
const auto &[GV, Info] : GlobalVariableDebugInfoMap)
2359 emitDebugGlobalVariable(GV, Info, VoidTypeReg, I32TypeReg, ExtInstSetReg,
2365 getOrEmitDebugInlinedAt(IA, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
2370 assert(ModuleInfo &&
"MachineModuleInfo must be set during module output");
2372 std::optional<std::pair<const DIBasicType *, uint64_t>> Const =
2376 if (!DebugLocalVariableRegs.contains(
MI.getDebugVariable()) ||
2377 !DebugExpressionRegs.contains(
MI.getDebugExpression()))
2379 auto [It, Inserted] = ConstantValueRegs.try_emplace(*Const,
MCRegister());
2381 It->second = findOrEmitScalarConstant(Const->first, Const->second, MAI);
2382 if (!It->second.isValid())
2383 ConstantValueRegs.erase(It);
2387 emitOpConstantI32(
DL->getLine(), I32TypeReg, MAI);
2388 emitOpConstantI32(
DL->getColumn(), I32TypeReg, MAI);
2389 emitOpConstantI32(
DL->getColumn() + 1, I32TypeReg, MAI);
2391 getCachedScopePathOpStringReg(
DL->getScope(),
2393 getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg, ExtInstSetReg,
2397 GlobalNSDIEnabled =
true;
2401SPIRVNonSemanticDebugHandler::getDebugFullPath(
const DIScope *Scope)
const {
2411 Out.assign(Dir.
begin(), Dir.
end());
2417MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugSourceForFileStrReg(
2420 const unsigned Key = FileStrReg.
id();
2421 auto It = DebugSourceRegByFileStr.find(
Key);
2422 if (It != DebugSourceRegByFileStr.end())
2425 MCRegister
DS = emitExtInst(SPIRV::NonSemanticExtInst::DebugSource,
2426 VoidTypeReg, ExtInstSetReg, {FileStrReg}, MAI);
2427 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.
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)