45template <
typename MapT>
46static std::optional<MCRegister> lookupOptReg(
const MapT &Map,
47 typename MapT::key_type
Key) {
51 assert(It->second.isValid() &&
"invalid register stored in map");
56 NSDIFlagIsProtected = 1u << 0,
57 NSDIFlagIsPrivate = 1u << 1,
58 NSDIFlagIsPublic = NSDIFlagIsPrivate | NSDIFlagIsProtected,
59 NSDIFlagIsLocal = 1u << 2,
60 NSDIFlagIsDefinition = 1u << 3,
61 NSDIFlagFwdDecl = 1u << 4,
62 NSDIFlagArtificial = 1u << 5,
63 NSDIFlagExplicit = 1u << 6,
64 NSDIFlagPrototyped = 1u << 7,
65 NSDIFlagObjectPointer = 1u << 8,
66 NSDIFlagStaticMember = 1u << 9,
67 NSDIFlagIndirectVariable = 1u << 10,
68 NSDIFlagLValueReference = 1u << 11,
69 NSDIFlagRValueReference = 1u << 12,
70 NSDIFlagIsOptimized = 1u << 13,
71 NSDIFlagIsEnumClass = 1u << 14,
72 NSDIFlagTypePassByValue = 1u << 15,
73 NSDIFlagTypePassByReference = 1u << 16,
74 NSDIFlagUnknownPhysicalLayout = 1u << 17,
80 Flags |= NSDIFlagIsPublic;
82 Flags |= NSDIFlagIsProtected;
84 Flags |= NSDIFlagIsPrivate;
85 if (DFlags & DINode::FlagFwdDecl)
86 Flags |= NSDIFlagFwdDecl;
87 if (DFlags & DINode::FlagArtificial)
88 Flags |= NSDIFlagArtificial;
89 if (DFlags & DINode::FlagExplicit)
90 Flags |= NSDIFlagExplicit;
91 if (DFlags & DINode::FlagPrototyped)
92 Flags |= NSDIFlagPrototyped;
93 if (DFlags & DINode::FlagObjectPointer)
94 Flags |= NSDIFlagObjectPointer;
95 if (DFlags & DINode::FlagStaticMember)
96 Flags |= NSDIFlagStaticMember;
97 if (DFlags & DINode::FlagLValueReference)
98 Flags |= NSDIFlagLValueReference;
99 if (DFlags & DINode::FlagRValueReference)
100 Flags |= NSDIFlagRValueReference;
101 if (DFlags & DINode::FlagTypePassByValue)
102 Flags |= NSDIFlagTypePassByValue;
103 if (DFlags & DINode::FlagTypePassByReference)
104 Flags |= NSDIFlagTypePassByReference;
105 if (DFlags & DINode::FlagEnumClass)
106 Flags |= NSDIFlagIsEnumClass;
113 if (GV->isLocalToUnit())
114 Flags |= NSDIFlagIsLocal;
115 if (GV->isDefinition())
116 Flags |= NSDIFlagIsDefinition;
119 if (SP->isLocalToUnit())
120 Flags |= NSDIFlagIsLocal;
121 if (SP->isOptimized())
122 Flags |= NSDIFlagIsOptimized;
123 if (SP->isDefinition())
124 Flags |= NSDIFlagIsDefinition;
125 Flags |= mapDIFlagsToNonSemantic(SP->getFlags());
127 if (DN->
getTag() == dwarf::DW_TAG_reference_type)
128 Flags |= NSDIFlagLValueReference;
129 if (DN->
getTag() == dwarf::DW_TAG_rvalue_reference_type)
130 Flags |= NSDIFlagRValueReference;
132 Flags |= mapDIFlagsToNonSemantic(Ty->getFlags());
134 Flags |= mapDIFlagsToNonSemantic(LV->getFlags());
140static uint32_t mapCompositeTypeTag(
unsigned Tag) {
142 case dwarf::DW_TAG_class_type:
144 case dwarf::DW_TAG_structure_type:
146 case dwarf::DW_TAG_union_type:
150 ". Expecting 0, 1 or 2");
165 bool SeenOpVariable =
false;
167 if (
MI.getOpcode() == SPIRV::OpVariable) {
168 SeenOpVariable =
true;
170 LastOpVariable = &
MI;
174 bool CanInterleaveWithOpVariable =
175 MI.getOpcode() == SPIRV::OpLine ||
MI.getOpcode() == SPIRV::OpNoLine;
176 if (SeenOpVariable && !CanInterleaveWithOpVariable &&
180 return LastOpVariable;
192unsigned SPIRVNonSemanticDebugHandler::toNSDISrcLang(
unsigned DwarfSrcLang) {
193 switch (DwarfSrcLang) {
194 case dwarf::DW_LANG_OpenCL:
196 case dwarf::DW_LANG_OpenCL_CPP:
198 case dwarf::DW_LANG_CPP_for_OpenCL:
200 case dwarf::DW_LANG_GLSL:
202 case dwarf::DW_LANG_HLSL:
204 case dwarf::DW_LANG_SYCL:
206 case dwarf::DW_LANG_Zig:
214 return BT->getEncoding() == dwarf::DW_ATE_boolean;
223 unsigned Width =
BT->getSizeInBits();
232 ?
Value.trunc(std::min(Width, 64u)).getZExtValue()
233 :
Value.getZExtValue(),
246 if (DT->getTag() != dwarf::DW_TAG_typedef || !Seen.
insert(DT).second)
248 Ty = DT->getBaseType();
259 unsigned Size =
BT->getSizeInBits();
260 switch (
BT->getEncoding()) {
261 case dwarf::DW_ATE_signed:
262 case dwarf::DW_ATE_unsigned:
263 case dwarf::DW_ATE_signed_char:
264 case dwarf::DW_ATE_unsigned_char:
266 case dwarf::DW_ATE_float:
292 for (
const MDNode *
N : SP->getRetainedNodes())
297 Locations.insert(
DL);
300 Locations.insert(
DL);
316 while (S && !Out.contains(S) &&
332 CompileUnits.clear();
334 EnumCompileUnits.clear();
336 UniqueDebugLocations.clear();
337 GlobalVariableDebugInfoMap.clear();
338 LocalVariables.clear();
339 DebugLocalVariableRegs.clear();
340 DebugExpressionRegs.clear();
341 LexicalBlocks.clear();
342 DebugScopeRegs.clear();
343 ScopesInProgress.clear();
344 HasRelaxedExtInst =
false;
345 FailedScopes.clear();
346 DebugInlinedAtRegs.clear();
347 ScopeToPathOpStringReg.clear();
348 DebugSourceRegByFileStr.clear();
349 OpStringContentCache.clear();
350 ScalarTypeCache.clear();
351 ScalarConstantCache.clear();
352 ConstantValueRegs.clear();
353 DebugOperationCache.clear();
354 DebugExpressionCache.clear();
355 ModuleScopeIds.clear();
356 GlobalDIEmitted =
false;
357 GlobalNSDIEnabled =
false;
358 CurrentMAI =
nullptr;
360 NonSemanticOpStringsSectionEmitted =
false;
370 CompileUnitInfo Info;
373 Info.FilePath = File->getFilename();
376 File->getFilename());
379 Info.SpirvSourceLanguage = toNSDISrcLang(
CU->getSourceLanguage().getName());
380 CompileUnits.push_back(std::move(Info));
382 EnumCompileUnits.try_emplace(ET,
CU);
388 if (
const NamedMDNode *Flags = M->getNamedMetadata(
"llvm.module.flags")) {
389 for (
const auto *
Op : Flags->operands()) {
404 return Ty->getTag() != dwarf::DW_TAG_member;
413 G.getDebugInfo(GVEs);
424 GlobalVariableDebugInfoMap.try_emplace(
425 GV, GlobalVariableDebugInfo{Expr, DIGVToLLVMGV.
lookup(GV)});
443 if (
MI.getNumOperands() == 0 || !
MI.getOperand(0).isReg() ||
444 !
MI.getOperand(0).isDef())
451 if (CompileUnits.empty())
453 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_non_semantic_info))
460 CLOpts.debug_scope_forward_refs &&
462 SPIRV::Extension::SPV_KHR_relaxed_extended_instruction);
463 if (HasRelaxedExtInst)
465 SPIRV::Extension::SPV_KHR_relaxed_extended_instruction);
475 ModuleScopeIds.insert(Id);
479void SPIRVNonSemanticDebugHandler::emitMCInst(
MCInst &Inst) {
484SPIRVNonSemanticDebugHandler::emitOpString(
StringRef S,
495MCRegister SPIRVNonSemanticDebugHandler::emitOpStringIfNew(
498 assert(!NonSemanticOpStringsSectionEmitted &&
499 "emitOpStringIfNew is only valid while emitting SPIR-V section 7");
501 auto [It,
Inserted] = OpStringContentCache.try_emplace(S, MCRegister());
503 It->second = emitOpString(S, MAI);
510 assert(NonSemanticOpStringsSectionEmitted &&
511 "getCachedOpStringReg requires emitNonSemanticDebugStrings() first");
513 auto It = OpStringContentCache.find(S);
514 assert(It != OpStringContentCache.end() &&
515 "NSDI OpString missing from cache; emitNonSemanticDebugStrings must "
516 "cache every string used in section 10");
520MCRegister SPIRVNonSemanticDebugHandler::emitAndCacheScopePathOpStringReg(
522 auto [It,
Inserted] = ScopeToPathOpStringReg.try_emplace(Scope, MCRegister());
524 It->second = emitOpStringIfNew(getDebugFullPath(Scope), MAI);
528MCRegister SPIRVNonSemanticDebugHandler::getCachedScopePathOpStringReg(
529 const DIScope *Scope,
bool UseEmptyPathIfNullScope) {
531 assert(UseEmptyPathIfNullScope &&
532 "null scope path lookup requires UseEmptyPathIfNullScope");
533 assert(CachedEmptyStringReg.isValid() &&
534 "empty path OpString must be cached in emitNonSemanticDebugStrings");
535 return CachedEmptyStringReg;
537 auto It = ScopeToPathOpStringReg.find(Scope);
538 assert(It != ScopeToPathOpStringReg.end() &&
539 "path OpString must be cached in emitNonSemanticDebugStrings");
540 MCRegister FileStrReg = It->second;
541 assert(FileStrReg.
isValid() &&
"path OpString id must be valid once cached");
545MCRegister SPIRVNonSemanticDebugHandler::emitOpConstantI32(
547 return findOrEmitConstant(SPIRV::OpConstantI, I32TypeReg,
Value,
551bool SPIRVNonSemanticDebugHandler::markForwardReferencedOperands(
553 bool HasForwardRef =
false;
554 for (
auto &Entry : ScopesInProgress) {
555 InProgressScope &InProgress =
Entry.second;
556 assert(InProgress.Id.isValid() &&
557 "in-progress scope must have a reserved id");
560 InProgress.ForwardReferenced =
true;
561 HasForwardRef =
true;
563 return HasForwardRef;
566MCRegister SPIRVNonSemanticDebugHandler::emitExtInst(
567 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
570 std::optional<MCRegister> ResultReg) {
571 assert((!ResultReg || ResultReg->isValid()) &&
572 "ResultReg must be a valid id when provided");
579 HasRelaxedExtInst && markForwardReferencedOperands(
Operands);
582 Inst.
setOpcode(HasForwardRef ? SPIRV::OpExtInstWithForwardRefsKHR
594MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeVoidReg(
596 if (!CachedOpTypeVoidReg.isValid())
597 CachedOpTypeVoidReg = findOrEmitOpTypeVoid(MAI);
598 return CachedOpTypeVoidReg;
601MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeInt32Reg(
603 if (!CachedOpTypeInt32Reg.isValid())
604 CachedOpTypeInt32Reg = findOrEmitOpTypeInt32(MAI);
605 return CachedOpTypeInt32Reg;
608MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
611 if (
MI->getOpcode() == SPIRV::OpTypeVoid)
628 unsigned Width =
BT->getSizeInBits();
632MCRegister SPIRVNonSemanticDebugHandler::findOrEmitScalarType(
635 bool IsFloat =
BT->getEncoding() == dwarf::DW_ATE_float;
636 unsigned Opcode = IsBool ? SPIRV::OpTypeBool
637 : IsFloat ? SPIRV::OpTypeFloat
641 int64_t Width = IsBool ? 0 :
BT->getSizeInBits();
646 if (Opcode == SPIRV::OpTypeInt && Width == 32)
647 return getOrEmitOpTypeInt32Reg(MAI);
650 ScalarTypeCache.try_emplace({Opcode, Width}, MCRegister());
652 return CacheIt->second;
657 if (
MI->getOpcode() != Opcode)
659 if (IsBool || (
MI->getOperand(1).getImm() == Width &&
660 (IsFloat ||
MI->getOperand(2).getImm() == 0))) {
663 return CacheIt->second;
685 CacheIt->second =
Reg;
692 unsigned Words = IsWide ? 2 : 1;
693 if (
MI.getNumOperands() < 2 + Words)
696 for (
unsigned I = 0;
I < Words; ++
I) {
697 if (!
MI.getOperand(2 +
I).isImm())
703 return Found ==
Value;
706MCRegister SPIRVNonSemanticDebugHandler::findModuleConstant(
710 if (
MI->getOpcode() != Opcode ||
MI->getNumOperands() < 2)
724MCRegister SPIRVNonSemanticDebugHandler::findOrEmitConstant(
727 bool IsBool = Width == 0;
728 bool IsWide = Width == 64;
731 ScalarConstantCache.try_emplace({TypeReg.
id(),
Value}, MCRegister());
733 return CacheIt->second;
736 findModuleConstant(Opcode, TypeReg,
Value, IsBool, IsWide, MAI);
738 CacheIt->second = Found;
754 }
else if (Width == 16) {
761 CacheIt->second =
Reg;
765MCRegister SPIRVNonSemanticDebugHandler::findOrEmitScalarConstant(
767 MCRegister TypeReg = findOrEmitScalarType(
BT, MAI);
772 bool IsFloat =
BT->getEncoding() == dwarf::DW_ATE_float;
774 IsBool ? (
Value ? SPIRV::OpConstantTrue : SPIRV::OpConstantFalse)
775 : IsFloat ?
SPIRV::OpConstantF
776 :
SPIRV::OpConstantI;
777 return findOrEmitConstant(Opcode, TypeReg,
Value,
778 IsBool ? 0 :
BT->getSizeInBits(), MAI);
781MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
784 if (
MI->getOpcode() == SPIRV::OpTypeInt &&
785 MI->getOperand(1).getImm() == 32 &&
MI->getOperand(2).getImm() == 0)
804auto SPIRVNonSemanticDebugHandler::getOrCreateDebugScope(
const DIScope *S)
805 -> EmitResult<MCRegister> {
806 if (!S || FailedScopes.contains(S))
807 return EmitResult<MCRegister>::unsupported();
808 if (
auto Reg = lookupOptReg(DebugScopeRegs, S))
809 return EmitResult<MCRegister>::emitted(*
Reg);
813 auto [InProgressIt, FirstVisit] = ScopesInProgress.try_emplace(S);
815 if (!HasRelaxedExtInst)
816 return EmitResult<MCRegister>::inProgress();
820 MCRegister ReservedId = InProgressIt->second.Id;
821 assert(ReservedId.
isValid() &&
"in-progress scope must have a reserved id");
822 return EmitResult<MCRegister>::emitted(ReservedId);
826 assert(CurrentMAI &&
"debug scope id allocation requires CurrentMAI");
828 assert(
Id.isValid() &&
"debug scope id must be a valid register");
829 InProgressIt->second.Id =
Id;
831 EmitResult<PreparedScope>
P = emitDebugScope(S);
832 assert((!HasRelaxedExtInst ||
P.Status != EmitStatus::InProgress) &&
833 "InProgress is only returned when forward references are unsupported");
836 InProgressIt = ScopesInProgress.find(S);
837 assert(InProgressIt != ScopesInProgress.end() &&
838 "scope must stay in progress until its instruction is emitted");
839 bool ForwardReferenced = InProgressIt->second.ForwardReferenced;
840 ScopesInProgress.erase(InProgressIt);
844 if (ForwardReferenced) {
845 assert(HasRelaxedExtInst &&
846 "a forward reference requires relaxed extended instructions");
847 assert(
P.Status == EmitStatus::Unsupported &&
848 "a forward-referenced scope fails as unsupported");
850 emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
859 if (
P.Status == EmitStatus::Unsupported)
860 FailedScopes.insert(S);
861 return P.Status == EmitStatus::InProgress
862 ? EmitResult<MCRegister>::inProgress()
869 emitExtInst(
P.Value->Opcode, getOrEmitOpTypeVoidReg(MAI),
872 "debug scope result id must reuse the id reserved at entry");
873 ScopesInProgress.erase(S);
874 assert(!GlobalNSDIEnabled &&
875 "debug type or scope created after module-scope NSDI emission");
876 DebugScopeRegs[S] =
Reg;
877 return EmitResult<MCRegister>::emitted(
Reg);
880auto SPIRVNonSemanticDebugHandler::emitDebugTypeBasic(
884 return EmitResult<PreparedScope>::unsupported();
886 MCRegister NameReg = getCachedOpStringReg(
BT->getName());
888 static_cast<uint32_t
>(
BT->getSizeInBits()), I32TypeReg, MAI);
892 unsigned Encoding = 0;
893 switch (
BT->getEncoding()) {
894 case dwarf::DW_ATE_address:
897 case dwarf::DW_ATE_boolean:
900 case dwarf::DW_ATE_float:
903 case dwarf::DW_ATE_signed:
906 case dwarf::DW_ATE_signed_char:
909 case dwarf::DW_ATE_unsigned:
912 case dwarf::DW_ATE_unsigned_char:
916 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
917 MCRegister FlagsReg = emitOpConstantI32(0, I32TypeReg, MAI);
918 return EmitResult<PreparedScope>::emitted(
919 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypeBasic,
920 {NameReg, SizeReg, EncodingReg, FlagsReg}});
923auto SPIRVNonSemanticDebugHandler::emitDebugScope(
const DIScope *S)
924 -> EmitResult<PreparedScope> {
925 assert(CurrentMAI &&
"emitDebugScope requires CurrentMAI");
928 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
929 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
932 return emitDebugTypeBasic(
BT, I32TypeReg, MAI);
934 return emitDebugTypeFunctionForSubroutineType(ST, MAI);
936 return emitDebugTypeForCompositeType(CT, VoidTypeReg, I32TypeReg,
939 return emitDebugTypeForDerivedType(DT, VoidTypeReg, I32TypeReg,
942 return emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg, ExtInstSetReg,
945 return emitDebugLexicalBlockDiscriminator(LBF, VoidTypeReg, I32TypeReg,
948 if (
SP->isDefinition())
949 return emitDebugFunction(SP, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
950 return emitDebugFunctionDeclaration(SP, VoidTypeReg, I32TypeReg,
953 return EmitResult<PreparedScope>::unsupported();
956auto SPIRVNonSemanticDebugHandler::emitDebugTypeForCompositeType(
959 -> EmitResult<PreparedScope> {
960 switch (CT->getTag()) {
961 case dwarf::DW_TAG_array_type:
974 return emitDebugTypeVector(CT, MAI);
975 return emitDebugTypeArray(CT, MAI);
976 case dwarf::DW_TAG_structure_type:
977 case dwarf::DW_TAG_class_type:
978 case dwarf::DW_TAG_union_type:
979 return emitDebugTypeComposite(CT, VoidTypeReg, I32TypeReg, ExtInstSetReg,
981 case dwarf::DW_TAG_enumeration_type:
982 return emitDebugTypeEnum(CT, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
984 return EmitResult<PreparedScope>::unsupported();
988auto SPIRVNonSemanticDebugHandler::emitDebugTypeForDerivedType(
991 -> EmitResult<PreparedScope> {
992 switch (DT->getTag()) {
993 case dwarf::DW_TAG_pointer_type:
994 return emitDebugTypePointer(DT, MAI);
995 case dwarf::DW_TAG_typedef:
996 return emitDebugTypedef(DT, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
997 case dwarf::DW_TAG_member:
998 return emitDebugTypeMember(DT, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
1000 return EmitResult<PreparedScope>::unsupported();
1004auto SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
1006 -> EmitResult<PreparedScope> {
1009 if (!PT->getDWARFAddressSpace().has_value())
1010 return EmitResult<PreparedScope>::unsupported();
1013 if (
const DIType *BaseTy = PT->getBaseType()) {
1014 EmitResult<MCRegister>
Base = getOrCreateDebugScope(BaseTy);
1016 return EmitResult<PreparedScope>::failure(
Base);
1023 BaseReg = CachedDebugInfoNoneReg;
1026 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1028 emitOpConstantI32(transDebugFlags(PT), I32TypeReg, MAI);
1033 MCRegister StorageClassReg = emitOpConstantI32(
1037 return EmitResult<PreparedScope>::emitted(
1038 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypePointer,
1039 {
BaseReg, StorageClassReg, DebugTypePointerFlagsReg}});
1042auto SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
1044 -> EmitResult<PreparedScope> {
1045 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1046 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1048 emitOpConstantI32(transDebugFlags(ST), I32TypeReg, MAI);
1049 DITypeArray
TA =
ST->getTypeArray();
1056 Ops.push_back(VoidTypeReg);
1058 for (
unsigned I = 0,
E =
TA.size();
I !=
E; ++
I) {
1059 bool IsReturnType = (
I == 0);
1060 EmitResult<MCRegister>
Slot =
1061 mapDISignatureTypeToReg(TA[
I], VoidTypeReg, IsReturnType);
1065 return EmitResult<PreparedScope>::failure(Slot);
1069 return EmitResult<PreparedScope>::emitted(
1070 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypeFunction,
Ops});
1074auto SPIRVNonSemanticDebugHandler::resolveScope(
const DIScope *Scope,
1076 -> EmitResult<MCRegister> {
1077 if (!CLOpts.debug_lexical_block_discriminator_scope)
1079 Scope = LBF->getScope();
1084 return getOrCreateDebugScope(Scope);
1087 auto CUResult = [](std::optional<MCRegister>
Reg) {
1088 return Reg ? EmitResult<MCRegister>::emitted(*
Reg)
1092 return CUResult(lookupOptReg(DebugScopeRegs, FallbackCU));
1094 if (CompileUnits.empty())
1095 return EmitResult<MCRegister>::unsupported();
1097 return CUResult(lookupOptReg(DebugScopeRegs, CompileUnits[0].TheCU));
1100auto SPIRVNonSemanticDebugHandler::emitDebugLexicalBlock(
1103 -> EmitResult<PreparedScope> {
1105 "S must be a DILexicalBlock or DINamespace in emitDebugLexicalBlock");
1106 EmitResult<MCRegister> Parent =
resolveScope(S->getScope());
1108 return EmitResult<PreparedScope>::failure(Parent);
1110 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1111 S->getFile(),
true);
1112 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1113 ExtInstSetReg, MAI);
1117 MCRegister LineReg = emitOpConstantI32(
static_cast<uint32_t
>(LB->getLine()),
1120 static_cast<uint32_t
>(LB->getColumn()), I32TypeReg, MAI);
1121 Ops = {SrcReg, LineReg, ColReg, *Parent.Value};
1125 MCRegister LineReg = emitOpConstantI32(0, I32TypeReg, MAI);
1126 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1127 MCRegister NameReg = getCachedOpStringReg(NS->getName());
1128 Ops = {SrcReg, LineReg, ColReg, *Parent.Value, NameReg};
1131 return EmitResult<PreparedScope>::emitted(
1132 PreparedScope{SPIRV::NonSemanticExtInst::DebugLexicalBlock,
Ops});
1135auto SPIRVNonSemanticDebugHandler::emitDebugLexicalBlockDiscriminator(
1139 assert(LBF &&
"LBF must not be null");
1140 EmitResult<MCRegister> Parent =
resolveScope(LBF->getScope());
1142 return EmitResult<PreparedScope>::failure(Parent);
1144 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1145 LBF->getFile(),
true);
1146 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1147 ExtInstSetReg, MAI);
1149 static_cast<uint32_t
>(LBF->getDiscriminator()), I32TypeReg, MAI);
1150 return EmitResult<PreparedScope>::emitted(
1151 PreparedScope{SPIRV::NonSemanticExtInst::DebugLexicalBlockDiscriminator,
1152 {SrcReg, DiscReg, *Parent.Value}});
1155MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugInlinedAt(
1158 assert(IA &&
"IA must not be null in getOrEmitDebugInlinedAt");
1160 if (MCRegister Cached = DebugInlinedAtRegs.lookup(IA))
1163 EmitResult<MCRegister>
Scope = resolveScope(
IA->getScope());
1165 return MCRegister();
1167 MCRegister LineReg =
1168 emitOpConstantI32(
static_cast<uint32_t
>(
IA->getLine()), I32TypeReg, MAI);
1173 if (
const DILocation *Outer =
IA->getInlinedAt()) {
1174 MCRegister OuterReg = getOrEmitDebugInlinedAt(
1175 Outer, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
1177 return MCRegister();
1178 Ops.push_back(OuterReg);
1181 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInlinedAt,
1182 VoidTypeReg, ExtInstSetReg,
Ops, MAI);
1183 DebugInlinedAtRegs[
IA] =
Reg;
1187auto SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
1190 -> EmitResult<PreparedScope> {
1191 assert(SP &&
"SP must not be null in emitDebugFunctionDeclaration");
1193 "SP must not be a definition in emitDebugFunctionDeclaration");
1196 EmitResult<MCRegister> FnTy = getOrCreateDebugScope(
SP->getType());
1198 return EmitResult<PreparedScope>::failure(FnTy);
1200 EmitResult<MCRegister> Parent =
resolveScope(
SP->getScope(),
SP->getUnit());
1202 return EmitResult<PreparedScope>::failure(Parent);
1204 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
1206 MCRegister NameReg = getCachedOpStringReg(
SP->getName());
1207 MCRegister LinkageReg = getCachedOpStringReg(
SP->getLinkageName());
1208 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1209 ExtInstSetReg, MAI);
1212 emitOpConstantI32(
static_cast<uint32_t
>(
SP->getLine()), I32TypeReg, MAI);
1213 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1215 uint32_t FlagsVal = transDebugFlags(SP);
1218 FlagsVal &= ~NSDIFlagIsDefinition;
1219 MCRegister FlagsReg = emitOpConstantI32(FlagsVal, I32TypeReg, MAI);
1221 return EmitResult<PreparedScope>::emitted(
1222 PreparedScope{SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
1223 {NameReg, *FnTy.Value, SrcReg, LineReg, ColReg,
1224 *Parent.Value, LinkageReg, FlagsReg}});
1227auto SPIRVNonSemanticDebugHandler::emitDebugFunction(
1230 -> EmitResult<PreparedScope> {
1231 assert(SP &&
"SP must not be null in emitDebugFunction");
1232 assert(
SP->isDefinition() &&
"SP must be a definition in emitDebugFunction");
1234 EmitResult<MCRegister> FnTy = getOrCreateDebugScope(
SP->getType());
1236 return EmitResult<PreparedScope>::failure(FnTy);
1238 EmitResult<MCRegister> Parent =
resolveScope(
SP->getScope(),
SP->getUnit());
1240 return EmitResult<PreparedScope>::failure(Parent);
1242 MCRegister NameReg = getCachedOpStringReg(
SP->getName());
1243 MCRegister LinkageReg = getCachedOpStringReg(
SP->getLinkageName());
1244 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
1245 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1246 ExtInstSetReg, MAI);
1249 emitOpConstantI32(
static_cast<uint32_t
>(
SP->getLine()), I32TypeReg, MAI);
1252 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1253 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(SP), I32TypeReg, MAI);
1255 static_cast<uint32_t
>(
SP->getScopeLine()), I32TypeReg, MAI);
1258 LineReg, ColReg, *Parent.Value,
1259 LinkageReg, FlagsReg, ScopeLineReg};
1262 EmitResult<MCRegister> DeclRes = getOrCreateDebugScope(Decl);
1264 Ops.push_back(*DeclRes.Value);
1267 return EmitResult<PreparedScope>::emitted(
1268 PreparedScope{SPIRV::NonSemanticExtInst::DebugFunction,
Ops});
1271auto SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
1273 -> EmitResult<MCRegister> {
1276 return EmitResult<MCRegister>::emitted(VoidTypeReg);
1277 assert(CachedDebugInfoNoneReg.isValid() &&
1278 "DebugInfoNone must be emitted before DISubroutineType operands");
1279 return EmitResult<MCRegister>::emitted(CachedDebugInfoNoneReg);
1281 return getOrCreateDebugScope(Ty);
1299static std::optional<NonSemanticDebugOp>
1302 case dwarf::DW_OP_deref:
1304 case dwarf::DW_OP_plus:
1306 case dwarf::DW_OP_minus:
1308 case dwarf::DW_OP_plus_uconst:
1310 case dwarf::DW_OP_bit_piece:
1312 case dwarf::DW_OP_swap:
1314 case dwarf::DW_OP_xderef:
1316 case dwarf::DW_OP_stack_value:
1318 case dwarf::DW_OP_constu:
1323 return std::nullopt;
1329static std::optional<SmallVector<uint32_t, 3>>
1331 std::optional<NonSemanticDebugOp> NSOp =
1334 return std::nullopt;
1337 for (
unsigned I = 0,
E =
Op.getNumArgs();
I !=
E; ++
I) {
1340 return std::nullopt;
1346std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugOperation(
1352 return std::nullopt;
1354 auto [It,
Inserted] = DebugOperationCache.try_emplace(std::move(*
Key));
1359 for (uint32_t
V : It->first)
1360 Operands.push_back(emitOpConstantI32(
V, I32TypeReg, MAI));
1361 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugOperation,
1362 VoidTypeReg, ExtInstSetReg,
Operands, MAI);
1367std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugExpression(
1370 assert(Expr &&
"Expr must not be null in emitDebugExpression");
1373 for (
const DIExpression::ExprOperand &
Op : Expr->
expr_ops()) {
1374 std::optional<MCRegister> OpReg =
1375 emitDebugOperation(
Op, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
1377 return std::nullopt;
1382 DebugExpressionCache.try_emplace(std::move(OperationRegs));
1386 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugExpression,
1387 VoidTypeReg, ExtInstSetReg, It->first, MAI);
1392std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugGlobalVariable(
1396 assert(GV &&
"GV must not be null in emitDebugGlobalVariable");
1398 EmitResult<MCRegister> Parent = resolveScope(GV->
getScope());
1400 return std::nullopt;
1402 MCRegister ParentReg = *Parent.Value;
1408 MCRegister TyReg = CachedDebugInfoNoneReg;
1409 if (
const DIType *Ty = GV->
getType()) {
1410 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1412 return std::nullopt;
1416 std::optional<MCRegister> StaticMemberRegOpt;
1419 StaticMemberRegOpt = lookupOptReg(DebugScopeRegs, SM);
1420 if (!StaticMemberRegOpt)
1421 return std::nullopt;
1424 MCRegister NameReg = getCachedOpStringReg(GV->
getName());
1425 MCRegister LinkageReg = getCachedOpStringReg(GV->
getLinkageName());
1426 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1428 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1429 ExtInstSetReg, MAI);
1431 MCRegister LineReg =
1432 emitOpConstantI32(
static_cast<uint32_t
>(GV->
getLine()), I32TypeReg, MAI);
1436 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1443 MCRegister VariableReg = CachedDebugInfoNoneReg;
1444 if (
const GlobalVariable *LLVMGV =
Info.LLVMGV) {
1447 VariableReg = GVReg;
1448 }
else if (
Info.Expr &&
Info.Expr->getNumElements() != 0) {
1449 if (
auto ExprReg = emitDebugExpression(
Info.Expr, VoidTypeReg, I32TypeReg,
1450 ExtInstSetReg, MAI))
1451 VariableReg = *ExprReg;
1454 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(GV), I32TypeReg, MAI);
1457 LineReg, ColReg, ParentReg,
1458 LinkageReg, VariableReg, FlagsReg};
1460 if (StaticMemberRegOpt)
1461 Ops.push_back(*StaticMemberRegOpt);
1463 return emitExtInst(SPIRV::NonSemanticExtInst::DebugGlobalVariable,
1464 VoidTypeReg, ExtInstSetReg,
Ops, MAI);
1467std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLocalVariable(
1470 assert(LV &&
"LV must not be null in emitDebugLocalVariable");
1472 EmitResult<MCRegister> Parent = resolveScope(LV->
getScope());
1474 return std::nullopt;
1476 MCRegister TyReg = CachedDebugInfoNoneReg;
1477 if (
const DIType *Ty = LV->
getType()) {
1478 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1480 return std::nullopt;
1484 MCRegister NameReg = getCachedOpStringReg(LV->
getName());
1485 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1487 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1488 ExtInstSetReg, MAI);
1489 MCRegister LineReg =
1490 emitOpConstantI32(
static_cast<uint32_t
>(LV->
getLine()), I32TypeReg, MAI);
1492 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1493 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(LV), I32TypeReg, MAI);
1496 ColReg, *Parent.Value, FlagsReg};
1497 if (
unsigned Arg = LV->
getArg())
1498 Ops.push_back(emitOpConstantI32(Arg, I32TypeReg, MAI));
1500 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLocalVariable, VoidTypeReg,
1501 ExtInstSetReg,
Ops, MAI);
1504auto SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
1506 -> EmitResult<PreparedScope> {
1509 return EmitResult<PreparedScope>::unsupported();
1513 DINodeArray
Elements = VT->getElements();
1515 return EmitResult<PreparedScope>::unsupported();
1519 return EmitResult<PreparedScope>::unsupported();
1521 EmitResult<MCRegister>
Base = getOrCreateDebugScope(BaseTy);
1523 return EmitResult<PreparedScope>::failure(
Base);
1525 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1527 static_cast<uint32_t
>(CI->getZExtValue()), I32TypeReg, MAI);
1528 return EmitResult<PreparedScope>::emitted(PreparedScope{
1529 SPIRV::NonSemanticExtInst::DebugTypeVector, {*
Base.Value, CountReg}});
1532auto SPIRVNonSemanticDebugHandler::emitDebugTypeArray(
1534 -> EmitResult<PreparedScope> {
1537 EmitResult<MCRegister>
Base = getOrCreateDebugScope(AT->getBaseType());
1539 return EmitResult<PreparedScope>::failure(
Base);
1541 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1549 for (
const DINode *Element : AT->getElements()) {
1561 if (
Value.getActiveBits() <= 32)
1562 Count =
static_cast<uint32_t
>(
Value.getZExtValue());
1564 Ops.push_back(emitOpConstantI32(
Count, I32TypeReg, MAI));
1567 return EmitResult<PreparedScope>::emitted(
1568 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypeArray,
Ops});
1571auto SPIRVNonSemanticDebugHandler::emitDebugTypeMember(
1574 -> EmitResult<PreparedScope> {
1575 EmitResult<MCRegister> Ty = getOrCreateDebugScope(
M->getBaseType());
1577 return EmitResult<PreparedScope>::failure(Ty);
1580 return EmitResult<PreparedScope>::unsupported();
1582 MCRegister NameReg = getCachedOpStringReg(
M->getName());
1583 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1584 M->getFile(),
true);
1585 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1586 ExtInstSetReg, MAI);
1588 emitOpConstantI32(
static_cast<uint32_t
>(
M->getLine()), I32TypeReg, MAI);
1591 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1593 static_cast<uint32_t
>(
M->getOffsetInBits()), I32TypeReg, MAI);
1595 static_cast<uint32_t
>(
M->getSizeInBits()), I32TypeReg, MAI);
1596 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(M), I32TypeReg, MAI);
1607 return EmitResult<PreparedScope>::emitted(
1608 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypeMember,
1609 {NameReg, *Ty.Value, SrcReg, LineReg, ColReg, OffsetReg,
1610 SizeReg, FlagsReg}});
1613auto SPIRVNonSemanticDebugHandler::emitDebugTypeComposite(
1616 -> EmitResult<PreparedScope> {
1619 EmitResult<MCRegister> Parent =
resolveScope(CT->getScope());
1621 return EmitResult<PreparedScope>::failure(Parent);
1624 return EmitResult<PreparedScope>::unsupported();
1627 for (
const DINode *Element : CT->getElements()) {
1629 if (!M ||
M->getTag() != dwarf::DW_TAG_member)
1631 EmitResult<MCRegister>
Member = getOrCreateDebugScope(M);
1636 MCRegister NameReg = getCachedOpStringReg(CT->getName());
1637 MCRegister LinkageReg = getCachedOpStringReg(CT->getIdentifier());
1638 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1639 CT->getFile(),
true);
1640 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1641 ExtInstSetReg, MAI);
1644 emitOpConstantI32(mapCompositeTypeTag(CT->getTag()), I32TypeReg, MAI);
1646 emitOpConstantI32(
static_cast<uint32_t
>(CT->getLine()), I32TypeReg, MAI);
1647 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1651 if (!CT->isForwardDecl())
1652 SizeReg = emitOpConstantI32(
static_cast<uint32_t
>(CT->getSizeInBits()),
1655 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(CT), I32TypeReg, MAI);
1658 LineReg, ColReg, *Parent.Value,
1659 LinkageReg, SizeReg, FlagsReg};
1661 return EmitResult<PreparedScope>::emitted(
1662 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypeComposite,
Ops});
1665auto SPIRVNonSemanticDebugHandler::emitDebugTypeEnum(
1668 -> EmitResult<PreparedScope> {
1672 return EmitResult<PreparedScope>::unsupported();
1674 MCRegister UnderlyingReg = CachedDebugInfoNoneReg;
1675 if (
const DIType *BaseTy = ET->getBaseType()) {
1676 EmitResult<MCRegister>
Base = getOrCreateDebugScope(BaseTy);
1678 return EmitResult<PreparedScope>::failure(
Base);
1679 UnderlyingReg = *
Base.Value;
1682 EmitResult<MCRegister> Parent =
1683 resolveScope(ET->getScope(), EnumCompileUnits.lookup(ET));
1685 return EmitResult<PreparedScope>::failure(Parent);
1687 MCRegister NameReg = getCachedOpStringReg(ET->getName());
1688 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1689 ET->getFile(),
true);
1690 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1691 ExtInstSetReg, MAI);
1693 emitOpConstantI32(
static_cast<uint32_t
>(ET->getLine()), I32TypeReg, MAI);
1695 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1697 emitOpConstantI32(
static_cast<uint32_t
>(
Size), I32TypeReg, MAI);
1698 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(ET), I32TypeReg, MAI);
1701 ColReg, *Parent.Value, SizeReg, FlagsReg};
1706 for (
const DINode *Element : ET->getElements()) {
1711 if (
E->isUnsigned() ? !
Value.isIntN(32) : !
Value.isSignedIntN(32))
1713 uint32_t
Bits =
E->isUnsigned()
1714 ?
static_cast<uint32_t
>(
Value.getZExtValue())
1715 :
static_cast<uint32_t
>(
Value.getSExtValue());
1716 Ops.push_back(emitOpConstantI32(Bits, I32TypeReg, MAI));
1717 Ops.push_back(getCachedOpStringReg(
E->getName()));
1720 return EmitResult<PreparedScope>::emitted(
1721 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypeEnum,
Ops});
1724auto SPIRVNonSemanticDebugHandler::emitDebugTypedef(
1727 -> EmitResult<PreparedScope> {
1728 EmitResult<MCRegister>
Base = getOrCreateDebugScope(TD->getBaseType());
1730 return EmitResult<PreparedScope>::failure(
Base);
1732 MCRegister NameReg = getCachedOpStringReg(TD->getName());
1733 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1734 TD->getFile(),
true);
1735 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1736 ExtInstSetReg, MAI);
1738 emitOpConstantI32(
static_cast<uint32_t
>(TD->getLine()), I32TypeReg, MAI);
1740 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1745 EmitResult<MCRegister> Parent =
resolveScope(TD->getScope());
1747 return EmitResult<PreparedScope>::failure(Parent);
1749 return EmitResult<PreparedScope>::emitted(PreparedScope{
1750 SPIRV::NonSemanticExtInst::DebugTypedef,
1751 {NameReg, *
Base.Value, SrcReg, LineReg, ColReg, *Parent.Value}});
1756 if (CompileUnits.empty())
1764 for (
const CompileUnitInfo &Info : CompileUnits) {
1766 MCRegister PathReg = emitOpStringIfNew(Info.FilePath, MAI);
1767 ScopeToPathOpStringReg[Info.TheCU] = PathReg;
1768 if (
const DIFile *
F = Info.TheCU->getFile())
1769 ScopeToPathOpStringReg[
F] = PathReg;
1774 emitOpStringIfNew(SP->getName(), MAI);
1775 emitOpStringIfNew(SP->getLinkageName(), MAI);
1776 emitAndCacheScopePathOpStringReg(SP, MAI);
1779 for (
const DIType *Ty : DebugTypes) {
1781 emitOpStringIfNew(
BT->getName(), MAI);
1787 if (CT->getTag() == dwarf::DW_TAG_enumeration_type) {
1788 emitOpStringIfNew(CT->getName(), MAI);
1789 emitAndCacheScopePathOpStringReg(CT->getFile(), MAI);
1790 for (
const DINode *Element : CT->getElements())
1792 emitOpStringIfNew(E->getName(), MAI);
1798 if (CT->getTag() != dwarf::DW_TAG_structure_type &&
1799 CT->getTag() != dwarf::DW_TAG_class_type &&
1800 CT->getTag() != dwarf::DW_TAG_union_type)
1802 emitOpStringIfNew(CT->getName(), MAI);
1803 emitOpStringIfNew(CT->getIdentifier(), MAI);
1804 emitAndCacheScopePathOpStringReg(CT->getFile(), MAI);
1805 for (
const DINode *Element : CT->getElements()) {
1807 if (!M || M->getTag() != dwarf::DW_TAG_member)
1809 emitOpStringIfNew(M->getName(), MAI);
1810 emitAndCacheScopePathOpStringReg(M->getFile(), MAI);
1816 if (TD && TD->getTag() == dwarf::DW_TAG_typedef) {
1817 emitOpStringIfNew(TD->getName(), MAI);
1818 emitAndCacheScopePathOpStringReg(TD->getFile(), MAI);
1822 for (
const auto &[GV,
_] : GlobalVariableDebugInfoMap) {
1823 emitOpStringIfNew(GV->
getName(), MAI);
1825 emitAndCacheScopePathOpStringReg(GV->
getFile(), MAI);
1829 emitOpStringIfNew(LV->
getName(), MAI);
1830 emitAndCacheScopePathOpStringReg(LV->
getFile(), MAI);
1833 for (
const DIScope *S : LexicalBlocks) {
1834 emitAndCacheScopePathOpStringReg(S->getFile(), MAI);
1836 emitOpStringIfNew(NS->getName(), MAI);
1840 emitAndCacheScopePathOpStringReg(
DL->getScope(), MAI);
1842 CachedEmptyStringReg = emitOpStringIfNew(
"", MAI);
1845 NonSemanticOpStringsSectionEmitted =
true;
1849void SPIRVNonSemanticDebugHandler::emitDebugFunctionDefinition(
1853 "DebugFunctionDefinition operands must be valid");
1854 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1856 emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDefinition, VoidTypeReg,
1857 ExtInstSetReg, {DebugFunctionReg, OpFunctionReg}, MAI);
1860void SPIRVNonSemanticDebugHandler::resetPerFunctionDebugState() {
1861 CurrentMF =
nullptr;
1862 LastFunctionOpVariable =
nullptr;
1863 DebugFunctionDefinitionEmitted =
false;
1864 LastLineMI =
nullptr;
1865 LastScopeMI =
nullptr;
1869void SPIRVNonSemanticDebugHandler::preparePerFunctionDebug(
1871 resetPerFunctionDebugState();
1872 if (!GlobalNSDIEnabled || !CurrentMAI)
1883 if (!SP || !
SP->isDefinition())
1888 LastFunctionOpVariable =
1889 findLastFunctionOpVariableDeclaration(*MF, *CurrentMAI);
1891 analyzeDebugRecords(*MF);
1894void SPIRVNonSemanticDebugHandler::tryEmitDebugFunctionDefinition(
1896 if (DebugFunctionDefinitionEmitted || !GlobalNSDIEnabled)
1899 assert(CurrentMF &&
"no current MachineFunction");
1900 const Function &
F = CurrentMF->getFunction();
1901 const DISubprogram *
SP =
F.getSubprogram();
1902 if (!SP || !
SP->isDefinition())
1905 auto DFIt = DebugScopeRegs.find(SP);
1906 if (DFIt == DebugScopeRegs.end())
1913 emitDebugFunctionDefinition(DFIt->second, OpFunctionReg, MAI);
1914 DebugFunctionDefinitionEmitted =
true;
1919 preparePerFunctionDebug(MF);
1924 resetPerFunctionDebugState();
1931 if (!DebugFunctionDefinitionEmitted)
1934 emitAnalyzedRecords(
MI);
1936 std::optional<const MachineInstr *>
Target = resolveDebugLocTarget(
MI);
1940 (void)emitDebugScopeForInstruction(*
Target);
1941 emitDebugLineForInstruction(*
Target);
1951static std::optional<Register>
1955 if (!
MI.isIndirectDebugValue())
1956 return std::nullopt;
1960 Register LocReg =
MI.getDebugOperand(0).getReg();
1962 return std::nullopt;
1973 const MachineInstr *Def =
MI.getMF()->getRegInfo().getUniqueVRegDef(LocReg);
1974 if (!Def || Def->getOpcode() != SPIRV::OpVariable)
1975 return std::nullopt;
1980void SPIRVNonSemanticDebugHandler::emitDebugBinding(
1981 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
1983 assert(DebugFunctionDefinitionEmitted &&
1984 "DebugFunctionDefinition must be emitted");
1985 assert(CurrentMAI &&
"CurrentMAI must be set");
1987 auto VarRegOpt = lookupOptReg(DebugLocalVariableRegs,
MI->getDebugVariable());
1991 auto ExprRegOpt = lookupOptReg(DebugExpressionRegs,
MI->getDebugExpression());
1995 if (!emitDebugScopeForInstruction(
MI))
1997 emitDebugLineForInstruction(
MI);
1999 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2000 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2002 emitExtInst(Opcode, VoidTypeReg, ExtInstSetReg,
2003 {*VarRegOpt, LocationReg, *ExprRegOpt}, MAI);
2008static std::optional<std::pair<const DIBasicType *, uint64_t>>
2010 if (!
MI.isNonListDebugValue() ||
MI.isIndirectDebugValue())
2011 return std::nullopt;
2015 return std::nullopt;
2020 return std::nullopt;
2025 else if (
Value.isCImm())
2029 return std::make_pair(
BT, Bits);
2032std::optional<MCRegister> SPIRVNonSemanticDebugHandler::getConstantValueReg(
2034 std::optional<std::pair<const DIBasicType *, uint64_t>>
Const =
2037 return std::nullopt;
2039 auto It = ConstantValueRegs.find(*Const);
2040 if (It == ConstantValueRegs.end() || !It->second.isValid())
2041 return std::nullopt;
2046 if (!
MI.isNonListDebugValue() ||
MI.isIndirectDebugValue())
2047 return std::nullopt;
2051 return std::nullopt;
2055 return std::nullopt;
2057 const MachineInstr *Def =
MI.getMF()->getRegInfo().getUniqueVRegDef(ValueReg);
2058 if (!Def || (Def->isPseudo() && !Def->isPHI()) || Def->isMetaInstruction() ||
2059 Def->getNumOperands() == 0 || !Def->getOperand(0).isReg() ||
2060 !Def->getOperand(0).isDef() || Def->getOperand(0).getReg() != ValueReg)
2061 return std::nullopt;
2067 return Opcode == SPIRV::OpSelectionMerge || Opcode == SPIRV::OpLoopMerge ||
2068 Opcode == SPIRV::OpLoopControlINTEL;
2080 switch (
MI->getOpcode()) {
2081 case SPIRV::OpFunction:
2082 case SPIRV::OpFunctionParameter:
2083 case SPIRV::OpFunctionEnd:
2084 case SPIRV::OpLabel:
2085 case TargetOpcode::PHI:
2096 :
MI->getPrevNode();
2097 Adj; Adj = Forward ? Adj->getNextNode() : Adj->getPrevNode()) {
2105std::optional<const MachineInstr *>
2106SPIRVNonSemanticDebugHandler::resolveDebugLocTarget(
const MachineInstr *
MI) {
2107 assert(CurrentMAI &&
"CurrentMAI must be set");
2108 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2113 return std::nullopt;
2121 return std::nullopt;
2127 assert(
MI &&
"Merge instruction must be followed by a terminator");
2131 return std::nullopt;
2137void SPIRVNonSemanticDebugHandler::resolveDebugRecord(
2140 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2146 const MachineInstr *Anchor =
2156 placeRecord(SPIRV::NonSemanticExtInst::DebugDeclare,
MI, StorageReg,
2161 if (std::optional<MCRegister> ConstReg = getConstantValueReg(
MI)) {
2162 placeRecord(SPIRV::NonSemanticExtInst::DebugValue,
MI, *ConstReg, Anchor);
2182 if (ModuleScopeIds.contains(ValueReg) ||
2184 placeRecord(SPIRV::NonSemanticExtInst::DebugValue,
MI, ValueReg, Anchor);
2187void SPIRVNonSemanticDebugHandler::analyzeDebugRecords(
2189 assert(CurrentMAI &&
"CurrentMAI must be set");
2193 std::optional<MachineDominatorTree> DomTree;
2195 for (
const MachineBasicBlock &
MBB : MF) {
2196 const MachineInstr *LastEmitted =
nullptr;
2197 for (
const MachineInstr &
MI :
MBB) {
2198 if (
MI.isDebugValueLike()) {
2201 resolveDebugRecord(
MI, LastEmitted, *DomTree);
2210void SPIRVNonSemanticDebugHandler::placeRecord(
2211 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
2214 Records[Anchor].push_back({&
MI, Opcode, LocationReg});
2217void SPIRVNonSemanticDebugHandler::emitAnalyzedRecords(
2219 auto It = Records.find(Anchor);
2220 if (It == Records.end())
2222 for (
const DebugRecord &R : It->second)
2223 emitDebugBinding(
R.Opcode,
R.MI,
R.LocationReg);
2226bool SPIRVNonSemanticDebugHandler::emitDebugScopeForInstruction(
2228 assert(DebugFunctionDefinitionEmitted &&
2229 "DebugFunctionDefinition must be emitted");
2230 assert(CurrentMAI &&
"CurrentMAI must be set");
2235 if (LastScopeMI &&
MI->getParent() != LastScopeMI->getParent())
2236 LastScopeMI =
nullptr;
2238 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2239 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2242 const DILocation *CurDL =
MI->getDebugLoc().get();
2247 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoScope, VoidTypeReg,
2248 ExtInstSetReg, {}, MAI);
2249 LastScopeMI =
nullptr;
2254 const DIScope *CurScope = CurDL->getScope();
2255 const DILocation *CurInlinedAt = CurDL->getInlinedAt();
2258 const DILocation *LastDL = LastScopeMI->getDebugLoc().get();
2259 if (LastDL->getScope() == CurScope &&
2260 LastDL->getInlinedAt() == CurInlinedAt)
2264 EmitResult<MCRegister> CurScopeRes = resolveScope(CurScope);
2271 MCRegister InlinedReg = DebugInlinedAtRegs.lookup(CurInlinedAt);
2274 Ops.push_back(InlinedReg);
2278 emitExtInst(SPIRV::NonSemanticExtInst::DebugScope, VoidTypeReg, ExtInstSetReg,
2285void SPIRVNonSemanticDebugHandler::emitDebugLineForInstruction(
2287 assert(DebugFunctionDefinitionEmitted &&
2288 "DebugFunctionDefinition must be emitted");
2289 assert(CurrentMAI &&
"CurrentMAI must be set");
2294 if (LastLineMI &&
MI->getParent() != LastLineMI->getParent())
2295 LastLineMI =
nullptr;
2297 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2298 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2301 const DILocation *
DL =
MI->getDebugLoc().get();
2306 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoLine, VoidTypeReg,
2307 ExtInstSetReg, {}, MAI);
2308 LastLineMI =
nullptr;
2318 MCRegister FileStrReg = getCachedScopePathOpStringReg(
2319 DL->getScope(),
true);
2320 unsigned Line =
DL->getLine();
2321 unsigned Col =
DL->getColumn();
2323 unsigned I32TypeId = CachedOpTypeInt32Reg.id();
2324 MCRegister SrcReg = DebugSourceRegByFileStr.lookup(FileStrReg.
id());
2325 MCRegister LineReg = ScalarConstantCache.lookup({I32TypeId,
Line});
2326 MCRegister ColStartReg = ScalarConstantCache.lookup({I32TypeId, Col});
2327 MCRegister ColEndReg = ScalarConstantCache.lookup({I32TypeId, Col + 1});
2339 if (LastLineMI &&
MI->getDebugLoc() == LastLineMI->getDebugLoc())
2343 emitExtInst(SPIRV::NonSemanticExtInst::DebugLine, VoidTypeReg, ExtInstSetReg,
2344 {SrcReg, LineReg, LineReg, ColStartReg, ColEndReg}, MAI);
2353 if (!
MI || !GlobalNSDIEnabled || !CurrentMF)
2356 if (DebugFunctionDefinitionEmitted ||
MI != LastFunctionOpVariable)
2362 assert(CurrentMAI &&
"CurrentMAI must be set");
2363 tryEmitDebugFunctionDefinition(*CurrentMAI);
2368 if (!GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
2371 assert(CurrentMF == &MF &&
2372 "notification does not match the current MachineFunction");
2374 if (LastFunctionOpVariable)
2380 tryEmitDebugFunctionDefinition(*CurrentMAI);
2383void SPIRVNonSemanticDebugHandler::collectDebugExpressions(
2387 Out.insert(
MI->getDebugExpression());
2392 if (GlobalDIEmitted)
2395 GlobalDIEmitted =
true;
2397 if (CompileUnits.empty()) {
2398 GlobalNSDIEnabled =
false;
2404 if (!ExtInstSetReg.
isValid()) {
2405 GlobalNSDIEnabled =
false;
2410 assert(NonSemanticOpStringsSectionEmitted &&
2411 "emitNonSemanticDebugStrings() must run before "
2412 "emitNonSemanticGlobalDebugInfo()");
2417 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2418 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
2420 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
2421 VoidTypeReg, ExtInstSetReg, {}, MAI);
2433 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
2435 emitOpConstantI32(
static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
2440 map_to_vector(CompileUnits, [&](
const CompileUnitInfo &Info) {
2441 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
2445 for (
auto [Info, SrcLangReg] :
llvm::zip(CompileUnits, SrcLangRegs)) {
2446 MCRegister FileStrReg = ScopeToPathOpStringReg.lookup(Info.TheCU);
2448 "CU path OpString must be emitted in emitNonSemanticDebugStrings");
2449 MCRegister DebugSourceReg = getOrEmitDebugSourceForFileStrReg(
2450 FileStrReg, VoidTypeReg, ExtInstSetReg, MAI);
2452 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
2454 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
2457 DebugScopeRegs[Info.TheCU] = CUDbgReg;
2462 getOrCreateDebugScope(S);
2467 if (
auto LVReg = emitDebugLocalVariable(LV, VoidTypeReg, I32TypeReg,
2468 ExtInstSetReg, MAI))
2469 DebugLocalVariableRegs[LV] = *LVReg;
2476 collectDebugExpressions(MAI, Expressions);
2478 if (
auto ExprReg = emitDebugExpression(Expr, VoidTypeReg, I32TypeReg,
2479 ExtInstSetReg, MAI))
2480 DebugExpressionRegs[Expr] = *ExprReg;
2483 for (
const auto &[GV, Info] : GlobalVariableDebugInfoMap)
2484 emitDebugGlobalVariable(GV, Info, VoidTypeReg, I32TypeReg, ExtInstSetReg,
2490 getOrEmitDebugInlinedAt(IA, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
2495 std::optional<std::pair<const DIBasicType *, uint64_t>> Const =
2499 if (!DebugLocalVariableRegs.contains(
MI->getDebugVariable()) ||
2500 !DebugExpressionRegs.contains(
MI->getDebugExpression()))
2502 auto [It, Inserted] = ConstantValueRegs.try_emplace(*Const,
MCRegister());
2504 It->second = findOrEmitScalarConstant(Const->first, Const->second, MAI);
2505 if (!It->second.isValid())
2506 ConstantValueRegs.erase(It);
2510 emitOpConstantI32(
DL->getLine(), I32TypeReg, MAI);
2511 emitOpConstantI32(
DL->getColumn(), I32TypeReg, MAI);
2512 emitOpConstantI32(
DL->getColumn() + 1, I32TypeReg, MAI);
2514 getCachedScopePathOpStringReg(
DL->getScope(),
2516 getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg, ExtInstSetReg,
2520 GlobalNSDIEnabled =
true;
2524SPIRVNonSemanticDebugHandler::getDebugFullPath(
const DIScope *Scope)
const {
2534 Out.assign(Dir.
begin(), Dir.
end());
2540MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugSourceForFileStrReg(
2543 const unsigned Key = FileStrReg.
id();
2544 auto It = DebugSourceRegByFileStr.find(
Key);
2545 if (It != DebugSourceRegByFileStr.end())
2548 MCRegister
DS = emitExtInst(SPIRV::NonSemanticExtInst::DebugSource,
2549 VoidTypeReg, ExtInstSetReg, {FileStrReg}, MAI);
2550 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 NVPTX::Scope resolveScope(NVPTX::Scope S, const NVPTXSubtarget *T)
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 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'.
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.
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.
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 append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
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.
@ 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
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
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.
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)
OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P)
Provide wrappers to std::copy_if which take ranges instead of having to pass begin/end explicitly.
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.
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.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
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)
SmallVector< const MachineInstr * > DebugValueMIs
MCRegister getNextIDRegister()
void addExtension(Extension::Extension ToAdd)