43 "spirv-debug-lexical-block-discriminator-scope",
44 cl::desc(
"Use a DebugLexicalBlockDiscriminator as a DebugScope"),
48 "spirv-debug-scope-forward-refs",
49 cl::desc(
"Forward-reference debug scopes when "
50 "SPV_KHR_relaxed_extended_instruction is enabled"),
57template <
typename MapT>
58static std::optional<MCRegister> lookupOptReg(
const MapT &Map,
59 typename MapT::key_type
Key) {
60 auto It = Map.find(
Key);
63 assert(It->second.isValid() &&
"invalid register stored in map");
68 NSDIFlagIsProtected = 1u << 0,
69 NSDIFlagIsPrivate = 1u << 1,
70 NSDIFlagIsPublic = NSDIFlagIsPrivate | NSDIFlagIsProtected,
71 NSDIFlagIsLocal = 1u << 2,
72 NSDIFlagIsDefinition = 1u << 3,
73 NSDIFlagFwdDecl = 1u << 4,
74 NSDIFlagArtificial = 1u << 5,
75 NSDIFlagExplicit = 1u << 6,
76 NSDIFlagPrototyped = 1u << 7,
77 NSDIFlagObjectPointer = 1u << 8,
78 NSDIFlagStaticMember = 1u << 9,
79 NSDIFlagIndirectVariable = 1u << 10,
80 NSDIFlagLValueReference = 1u << 11,
81 NSDIFlagRValueReference = 1u << 12,
82 NSDIFlagIsOptimized = 1u << 13,
83 NSDIFlagIsEnumClass = 1u << 14,
84 NSDIFlagTypePassByValue = 1u << 15,
85 NSDIFlagTypePassByReference = 1u << 16,
86 NSDIFlagUnknownPhysicalLayout = 1u << 17,
92 Flags |= NSDIFlagIsPublic;
94 Flags |= NSDIFlagIsProtected;
96 Flags |= NSDIFlagIsPrivate;
97 if (DFlags & DINode::FlagFwdDecl)
98 Flags |= NSDIFlagFwdDecl;
99 if (DFlags & DINode::FlagArtificial)
100 Flags |= NSDIFlagArtificial;
101 if (DFlags & DINode::FlagExplicit)
102 Flags |= NSDIFlagExplicit;
103 if (DFlags & DINode::FlagPrototyped)
104 Flags |= NSDIFlagPrototyped;
105 if (DFlags & DINode::FlagObjectPointer)
106 Flags |= NSDIFlagObjectPointer;
107 if (DFlags & DINode::FlagStaticMember)
108 Flags |= NSDIFlagStaticMember;
109 if (DFlags & DINode::FlagLValueReference)
110 Flags |= NSDIFlagLValueReference;
111 if (DFlags & DINode::FlagRValueReference)
112 Flags |= NSDIFlagRValueReference;
113 if (DFlags & DINode::FlagTypePassByValue)
114 Flags |= NSDIFlagTypePassByValue;
115 if (DFlags & DINode::FlagTypePassByReference)
116 Flags |= NSDIFlagTypePassByReference;
117 if (DFlags & DINode::FlagEnumClass)
118 Flags |= NSDIFlagIsEnumClass;
125 if (GV->isLocalToUnit())
126 Flags |= NSDIFlagIsLocal;
127 if (GV->isDefinition())
128 Flags |= NSDIFlagIsDefinition;
131 if (SP->isLocalToUnit())
132 Flags |= NSDIFlagIsLocal;
133 if (SP->isOptimized())
134 Flags |= NSDIFlagIsOptimized;
135 if (SP->isDefinition())
136 Flags |= NSDIFlagIsDefinition;
137 Flags |= mapDIFlagsToNonSemantic(SP->getFlags());
139 if (DN->
getTag() == dwarf::DW_TAG_reference_type)
140 Flags |= NSDIFlagLValueReference;
141 if (DN->
getTag() == dwarf::DW_TAG_rvalue_reference_type)
142 Flags |= NSDIFlagRValueReference;
144 Flags |= mapDIFlagsToNonSemantic(Ty->getFlags());
146 Flags |= mapDIFlagsToNonSemantic(LV->getFlags());
152static uint32_t mapCompositeTypeTag(
unsigned Tag) {
154 case dwarf::DW_TAG_class_type:
156 case dwarf::DW_TAG_structure_type:
158 case dwarf::DW_TAG_union_type:
162 ". Expecting 0, 1 or 2");
177 bool SeenOpVariable =
false;
179 if (
MI.getOpcode() == SPIRV::OpVariable) {
180 SeenOpVariable =
true;
182 LastOpVariable = &
MI;
186 bool CanInterleaveWithOpVariable =
187 MI.getOpcode() == SPIRV::OpLine ||
MI.getOpcode() == SPIRV::OpNoLine;
188 if (SeenOpVariable && !CanInterleaveWithOpVariable &&
192 return LastOpVariable;
203unsigned SPIRVNonSemanticDebugHandler::toNSDISrcLang(
unsigned DwarfSrcLang) {
204 switch (DwarfSrcLang) {
205 case dwarf::DW_LANG_OpenCL:
207 case dwarf::DW_LANG_OpenCL_CPP:
209 case dwarf::DW_LANG_CPP_for_OpenCL:
211 case dwarf::DW_LANG_GLSL:
213 case dwarf::DW_LANG_HLSL:
215 case dwarf::DW_LANG_SYCL:
217 case dwarf::DW_LANG_Zig:
225 return BT->getEncoding() == dwarf::DW_ATE_boolean;
234 unsigned Width =
BT->getSizeInBits();
243 ?
Value.trunc(std::min(Width, 64u)).getZExtValue()
244 :
Value.getZExtValue(),
257 if (DT->getTag() != dwarf::DW_TAG_typedef || !Seen.
insert(DT).second)
259 Ty = DT->getBaseType();
270 unsigned Size =
BT->getSizeInBits();
271 switch (
BT->getEncoding()) {
272 case dwarf::DW_ATE_signed:
273 case dwarf::DW_ATE_unsigned:
274 case dwarf::DW_ATE_signed_char:
275 case dwarf::DW_ATE_unsigned_char:
277 case dwarf::DW_ATE_float:
303 for (
const MDNode *
N : SP->getRetainedNodes())
308 Locations.insert(
DL);
311 Locations.insert(
DL);
327 while (S && !Out.contains(S) &&
343 CompileUnits.clear();
345 EnumCompileUnits.clear();
347 UniqueDebugLocations.clear();
348 GlobalVariableDebugInfoMap.clear();
349 LocalVariables.clear();
350 DebugLocalVariableRegs.clear();
351 DebugExpressionRegs.clear();
352 LexicalBlocks.clear();
353 DebugScopeRegs.clear();
354 ScopesInProgress.clear();
355 HasRelaxedExtInst =
false;
356 FailedScopes.clear();
357 DebugInlinedAtRegs.clear();
358 ScopeToPathOpStringReg.clear();
359 DebugSourceRegByFileStr.clear();
360 OpStringContentCache.clear();
361 ScalarTypeCache.clear();
362 ScalarConstantCache.clear();
363 ConstantValueRegs.clear();
364 DebugOperationCache.clear();
365 DebugExpressionCache.clear();
366 ModuleScopeIds.clear();
367 GlobalDIEmitted =
false;
368 GlobalNSDIEnabled =
false;
369 CurrentMAI =
nullptr;
371 NonSemanticOpStringsSectionEmitted =
false;
381 CompileUnitInfo Info;
384 Info.FilePath = File->getFilename();
387 File->getFilename());
390 Info.SpirvSourceLanguage = toNSDISrcLang(
CU->getSourceLanguage().getName());
391 CompileUnits.push_back(std::move(Info));
393 EnumCompileUnits.try_emplace(ET,
CU);
399 if (
const NamedMDNode *Flags = M->getNamedMetadata(
"llvm.module.flags")) {
400 for (
const auto *
Op : Flags->operands()) {
415 return Ty->getTag() != dwarf::DW_TAG_member;
424 G.getDebugInfo(GVEs);
435 GlobalVariableDebugInfoMap.try_emplace(
436 GV, GlobalVariableDebugInfo{Expr, DIGVToLLVMGV.
lookup(GV)});
454 if (
MI.getNumOperands() == 0 || !
MI.getOperand(0).isReg() ||
455 !
MI.getOperand(0).isDef())
462 if (CompileUnits.empty())
464 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_non_semantic_info))
473 SPIRV::Extension::SPV_KHR_relaxed_extended_instruction);
474 if (HasRelaxedExtInst)
476 SPIRV::Extension::SPV_KHR_relaxed_extended_instruction);
486 ModuleScopeIds.insert(Id);
490void SPIRVNonSemanticDebugHandler::emitMCInst(
MCInst &Inst) {
495SPIRVNonSemanticDebugHandler::emitOpString(
StringRef S,
506MCRegister SPIRVNonSemanticDebugHandler::emitOpStringIfNew(
509 assert(!NonSemanticOpStringsSectionEmitted &&
510 "emitOpStringIfNew is only valid while emitting SPIR-V section 7");
512 auto [It,
Inserted] = OpStringContentCache.try_emplace(S, MCRegister());
514 It->second = emitOpString(S, MAI);
521 assert(NonSemanticOpStringsSectionEmitted &&
522 "getCachedOpStringReg requires emitNonSemanticDebugStrings() first");
524 auto It = OpStringContentCache.find(S);
525 assert(It != OpStringContentCache.end() &&
526 "NSDI OpString missing from cache; emitNonSemanticDebugStrings must "
527 "cache every string used in section 10");
531MCRegister SPIRVNonSemanticDebugHandler::emitAndCacheScopePathOpStringReg(
533 auto [It,
Inserted] = ScopeToPathOpStringReg.try_emplace(Scope, MCRegister());
535 It->second = emitOpStringIfNew(getDebugFullPath(Scope), MAI);
539MCRegister SPIRVNonSemanticDebugHandler::getCachedScopePathOpStringReg(
540 const DIScope *Scope,
bool UseEmptyPathIfNullScope) {
542 assert(UseEmptyPathIfNullScope &&
543 "null scope path lookup requires UseEmptyPathIfNullScope");
544 assert(CachedEmptyStringReg.isValid() &&
545 "empty path OpString must be cached in emitNonSemanticDebugStrings");
546 return CachedEmptyStringReg;
548 auto It = ScopeToPathOpStringReg.find(Scope);
549 assert(It != ScopeToPathOpStringReg.end() &&
550 "path OpString must be cached in emitNonSemanticDebugStrings");
551 MCRegister FileStrReg = It->second;
552 assert(FileStrReg.
isValid() &&
"path OpString id must be valid once cached");
556MCRegister SPIRVNonSemanticDebugHandler::emitOpConstantI32(
558 return findOrEmitConstant(SPIRV::OpConstantI, I32TypeReg,
Value,
562bool SPIRVNonSemanticDebugHandler::markForwardReferencedOperands(
564 bool HasForwardRef =
false;
565 for (
auto &Entry : ScopesInProgress) {
566 InProgressScope &InProgress =
Entry.second;
567 assert(InProgress.Id.isValid() &&
568 "in-progress scope must have a reserved id");
571 InProgress.ForwardReferenced =
true;
572 HasForwardRef =
true;
574 return HasForwardRef;
577MCRegister SPIRVNonSemanticDebugHandler::emitExtInst(
578 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
581 std::optional<MCRegister> ResultReg) {
582 assert((!ResultReg || ResultReg->isValid()) &&
583 "ResultReg must be a valid id when provided");
590 HasRelaxedExtInst && markForwardReferencedOperands(
Operands);
593 Inst.
setOpcode(HasForwardRef ? SPIRV::OpExtInstWithForwardRefsKHR
605MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeVoidReg(
607 if (!CachedOpTypeVoidReg.isValid())
608 CachedOpTypeVoidReg = findOrEmitOpTypeVoid(MAI);
609 return CachedOpTypeVoidReg;
612MCRegister SPIRVNonSemanticDebugHandler::getOrEmitOpTypeInt32Reg(
614 if (!CachedOpTypeInt32Reg.isValid())
615 CachedOpTypeInt32Reg = findOrEmitOpTypeInt32(MAI);
616 return CachedOpTypeInt32Reg;
619MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeVoid(
622 if (
MI->getOpcode() == SPIRV::OpTypeVoid)
639 unsigned Width =
BT->getSizeInBits();
643MCRegister SPIRVNonSemanticDebugHandler::findOrEmitScalarType(
646 bool IsFloat =
BT->getEncoding() == dwarf::DW_ATE_float;
647 unsigned Opcode = IsBool ? SPIRV::OpTypeBool
648 : IsFloat ? SPIRV::OpTypeFloat
652 int64_t Width = IsBool ? 0 :
BT->getSizeInBits();
657 if (Opcode == SPIRV::OpTypeInt && Width == 32)
658 return getOrEmitOpTypeInt32Reg(MAI);
661 ScalarTypeCache.try_emplace({Opcode, Width}, MCRegister());
663 return CacheIt->second;
668 if (
MI->getOpcode() != Opcode)
670 if (IsBool || (
MI->getOperand(1).getImm() == Width &&
671 (IsFloat ||
MI->getOperand(2).getImm() == 0))) {
674 return CacheIt->second;
696 CacheIt->second =
Reg;
703 unsigned Words = IsWide ? 2 : 1;
704 if (
MI.getNumOperands() < 2 + Words)
707 for (
unsigned I = 0;
I < Words; ++
I) {
708 if (!
MI.getOperand(2 +
I).isImm())
714 return Found ==
Value;
717MCRegister SPIRVNonSemanticDebugHandler::findModuleConstant(
721 if (
MI->getOpcode() != Opcode ||
MI->getNumOperands() < 2)
735MCRegister SPIRVNonSemanticDebugHandler::findOrEmitConstant(
738 bool IsBool = Width == 0;
739 bool IsWide = Width == 64;
742 ScalarConstantCache.try_emplace({TypeReg.
id(),
Value}, MCRegister());
744 return CacheIt->second;
747 findModuleConstant(Opcode, TypeReg,
Value, IsBool, IsWide, MAI);
749 CacheIt->second = Found;
765 }
else if (Width == 16) {
772 CacheIt->second =
Reg;
776MCRegister SPIRVNonSemanticDebugHandler::findOrEmitScalarConstant(
778 MCRegister TypeReg = findOrEmitScalarType(
BT, MAI);
783 bool IsFloat =
BT->getEncoding() == dwarf::DW_ATE_float;
785 IsBool ? (
Value ? SPIRV::OpConstantTrue : SPIRV::OpConstantFalse)
786 : IsFloat ?
SPIRV::OpConstantF
787 :
SPIRV::OpConstantI;
788 return findOrEmitConstant(Opcode, TypeReg,
Value,
789 IsBool ? 0 :
BT->getSizeInBits(), MAI);
792MCRegister SPIRVNonSemanticDebugHandler::findOrEmitOpTypeInt32(
795 if (
MI->getOpcode() == SPIRV::OpTypeInt &&
796 MI->getOperand(1).getImm() == 32 &&
MI->getOperand(2).getImm() == 0)
815auto SPIRVNonSemanticDebugHandler::getOrCreateDebugScope(
const DIScope *S)
816 -> EmitResult<MCRegister> {
817 if (!S || FailedScopes.contains(S))
818 return EmitResult<MCRegister>::unsupported();
819 if (
auto Reg = lookupOptReg(DebugScopeRegs, S))
820 return EmitResult<MCRegister>::emitted(*
Reg);
824 auto [InProgressIt, FirstVisit] = ScopesInProgress.try_emplace(S);
826 if (!HasRelaxedExtInst)
827 return EmitResult<MCRegister>::inProgress();
831 MCRegister ReservedId = InProgressIt->second.Id;
832 assert(ReservedId.
isValid() &&
"in-progress scope must have a reserved id");
833 return EmitResult<MCRegister>::emitted(ReservedId);
837 assert(CurrentMAI &&
"debug scope id allocation requires CurrentMAI");
839 assert(
Id.isValid() &&
"debug scope id must be a valid register");
840 InProgressIt->second.Id =
Id;
842 EmitResult<PreparedScope>
P = emitDebugScope(S);
843 assert((!HasRelaxedExtInst ||
P.Status != EmitStatus::InProgress) &&
844 "InProgress is only returned when forward references are unsupported");
847 InProgressIt = ScopesInProgress.find(S);
848 assert(InProgressIt != ScopesInProgress.end() &&
849 "scope must stay in progress until its instruction is emitted");
850 bool ForwardReferenced = InProgressIt->second.ForwardReferenced;
851 ScopesInProgress.erase(InProgressIt);
855 if (ForwardReferenced) {
856 assert(HasRelaxedExtInst &&
857 "a forward reference requires relaxed extended instructions");
858 assert(
P.Status == EmitStatus::Unsupported &&
859 "a forward-referenced scope fails as unsupported");
861 emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
870 if (
P.Status == EmitStatus::Unsupported)
871 FailedScopes.insert(S);
872 return P.Status == EmitStatus::InProgress
873 ? EmitResult<MCRegister>::inProgress()
880 emitExtInst(
P.Value->Opcode, getOrEmitOpTypeVoidReg(MAI),
883 "debug scope result id must reuse the id reserved at entry");
884 ScopesInProgress.erase(S);
885 assert(!GlobalNSDIEnabled &&
886 "debug type or scope created after module-scope NSDI emission");
887 DebugScopeRegs[S] =
Reg;
888 return EmitResult<MCRegister>::emitted(
Reg);
891auto SPIRVNonSemanticDebugHandler::emitDebugTypeBasic(
895 return EmitResult<PreparedScope>::unsupported();
897 MCRegister NameReg = getCachedOpStringReg(
BT->getName());
899 static_cast<uint32_t
>(
BT->getSizeInBits()), I32TypeReg, MAI);
903 unsigned Encoding = 0;
904 switch (
BT->getEncoding()) {
905 case dwarf::DW_ATE_address:
908 case dwarf::DW_ATE_boolean:
911 case dwarf::DW_ATE_float:
914 case dwarf::DW_ATE_signed:
917 case dwarf::DW_ATE_signed_char:
920 case dwarf::DW_ATE_unsigned:
923 case dwarf::DW_ATE_unsigned_char:
927 MCRegister EncodingReg = emitOpConstantI32(Encoding, I32TypeReg, MAI);
928 MCRegister FlagsReg = emitOpConstantI32(0, I32TypeReg, MAI);
929 return EmitResult<PreparedScope>::emitted(
930 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypeBasic,
931 {NameReg, SizeReg, EncodingReg, FlagsReg}});
934auto SPIRVNonSemanticDebugHandler::emitDebugScope(
const DIScope *S)
935 -> EmitResult<PreparedScope> {
936 assert(CurrentMAI &&
"emitDebugScope requires CurrentMAI");
939 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
940 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
943 return emitDebugTypeBasic(
BT, I32TypeReg, MAI);
945 return emitDebugTypeFunctionForSubroutineType(ST, MAI);
947 return emitDebugTypeForCompositeType(CT, VoidTypeReg, I32TypeReg,
950 return emitDebugTypeForDerivedType(DT, VoidTypeReg, I32TypeReg,
953 return emitDebugLexicalBlock(S, VoidTypeReg, I32TypeReg, ExtInstSetReg,
956 return emitDebugLexicalBlockDiscriminator(LBF, VoidTypeReg, I32TypeReg,
959 if (
SP->isDefinition())
960 return emitDebugFunction(SP, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
961 return emitDebugFunctionDeclaration(SP, VoidTypeReg, I32TypeReg,
964 return EmitResult<PreparedScope>::unsupported();
967auto SPIRVNonSemanticDebugHandler::emitDebugTypeForCompositeType(
970 -> EmitResult<PreparedScope> {
971 switch (CT->getTag()) {
972 case dwarf::DW_TAG_array_type:
985 return emitDebugTypeVector(CT, MAI);
986 return emitDebugTypeArray(CT, MAI);
987 case dwarf::DW_TAG_structure_type:
988 case dwarf::DW_TAG_class_type:
989 case dwarf::DW_TAG_union_type:
990 return emitDebugTypeComposite(CT, VoidTypeReg, I32TypeReg, ExtInstSetReg,
992 case dwarf::DW_TAG_enumeration_type:
993 return emitDebugTypeEnum(CT, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
995 return EmitResult<PreparedScope>::unsupported();
999auto SPIRVNonSemanticDebugHandler::emitDebugTypeForDerivedType(
1002 -> EmitResult<PreparedScope> {
1003 switch (DT->getTag()) {
1004 case dwarf::DW_TAG_pointer_type:
1005 return emitDebugTypePointer(DT, MAI);
1006 case dwarf::DW_TAG_typedef:
1007 return emitDebugTypedef(DT, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
1008 case dwarf::DW_TAG_member:
1009 return emitDebugTypeMember(DT, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
1011 return EmitResult<PreparedScope>::unsupported();
1015auto SPIRVNonSemanticDebugHandler::emitDebugTypePointer(
1017 -> EmitResult<PreparedScope> {
1020 if (!PT->getDWARFAddressSpace().has_value())
1021 return EmitResult<PreparedScope>::unsupported();
1024 if (
const DIType *BaseTy = PT->getBaseType()) {
1025 EmitResult<MCRegister>
Base = getOrCreateDebugScope(BaseTy);
1027 return EmitResult<PreparedScope>::failure(
Base);
1034 BaseReg = CachedDebugInfoNoneReg;
1037 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1039 emitOpConstantI32(transDebugFlags(PT), I32TypeReg, MAI);
1044 MCRegister StorageClassReg = emitOpConstantI32(
1048 return EmitResult<PreparedScope>::emitted(
1049 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypePointer,
1050 {
BaseReg, StorageClassReg, DebugTypePointerFlagsReg}});
1053auto SPIRVNonSemanticDebugHandler::emitDebugTypeFunctionForSubroutineType(
1055 -> EmitResult<PreparedScope> {
1056 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1057 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1059 emitOpConstantI32(transDebugFlags(ST), I32TypeReg, MAI);
1060 DITypeArray
TA =
ST->getTypeArray();
1067 Ops.push_back(VoidTypeReg);
1069 for (
unsigned I = 0,
E =
TA.size();
I !=
E; ++
I) {
1070 bool IsReturnType = (
I == 0);
1071 EmitResult<MCRegister>
Slot =
1072 mapDISignatureTypeToReg(TA[
I], VoidTypeReg, IsReturnType);
1076 return EmitResult<PreparedScope>::failure(Slot);
1080 return EmitResult<PreparedScope>::emitted(
1081 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypeFunction,
Ops});
1085auto SPIRVNonSemanticDebugHandler::resolveScope(
const DIScope *Scope,
1087 -> EmitResult<MCRegister> {
1090 Scope = LBF->getScope();
1095 return getOrCreateDebugScope(Scope);
1098 auto CUResult = [](std::optional<MCRegister>
Reg) {
1099 return Reg ? EmitResult<MCRegister>::emitted(*
Reg)
1103 return CUResult(lookupOptReg(DebugScopeRegs, FallbackCU));
1105 if (CompileUnits.empty())
1106 return EmitResult<MCRegister>::unsupported();
1108 return CUResult(lookupOptReg(DebugScopeRegs, CompileUnits[0].TheCU));
1111auto SPIRVNonSemanticDebugHandler::emitDebugLexicalBlock(
1114 -> EmitResult<PreparedScope> {
1116 "S must be a DILexicalBlock or DINamespace in emitDebugLexicalBlock");
1117 EmitResult<MCRegister> Parent =
resolveScope(S->getScope());
1119 return EmitResult<PreparedScope>::failure(Parent);
1121 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1122 S->getFile(),
true);
1123 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1124 ExtInstSetReg, MAI);
1128 MCRegister LineReg = emitOpConstantI32(
static_cast<uint32_t
>(LB->getLine()),
1131 static_cast<uint32_t
>(LB->getColumn()), I32TypeReg, MAI);
1132 Ops = {SrcReg, LineReg, ColReg, *Parent.Value};
1136 MCRegister LineReg = emitOpConstantI32(0, I32TypeReg, MAI);
1137 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1138 MCRegister NameReg = getCachedOpStringReg(NS->getName());
1139 Ops = {SrcReg, LineReg, ColReg, *Parent.Value, NameReg};
1142 return EmitResult<PreparedScope>::emitted(
1143 PreparedScope{SPIRV::NonSemanticExtInst::DebugLexicalBlock,
Ops});
1146auto SPIRVNonSemanticDebugHandler::emitDebugLexicalBlockDiscriminator(
1150 assert(LBF &&
"LBF must not be null");
1151 EmitResult<MCRegister> Parent =
resolveScope(LBF->getScope());
1153 return EmitResult<PreparedScope>::failure(Parent);
1155 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1156 LBF->getFile(),
true);
1157 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1158 ExtInstSetReg, MAI);
1160 static_cast<uint32_t
>(LBF->getDiscriminator()), I32TypeReg, MAI);
1161 return EmitResult<PreparedScope>::emitted(
1162 PreparedScope{SPIRV::NonSemanticExtInst::DebugLexicalBlockDiscriminator,
1163 {SrcReg, DiscReg, *Parent.Value}});
1166MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugInlinedAt(
1169 assert(IA &&
"IA must not be null in getOrEmitDebugInlinedAt");
1171 if (MCRegister Cached = DebugInlinedAtRegs.lookup(IA))
1174 EmitResult<MCRegister>
Scope = resolveScope(
IA->getScope());
1176 return MCRegister();
1178 MCRegister LineReg =
1179 emitOpConstantI32(
static_cast<uint32_t
>(
IA->getLine()), I32TypeReg, MAI);
1184 if (
const DILocation *Outer =
IA->getInlinedAt()) {
1185 MCRegister OuterReg = getOrEmitDebugInlinedAt(
1186 Outer, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
1188 return MCRegister();
1189 Ops.push_back(OuterReg);
1192 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInlinedAt,
1193 VoidTypeReg, ExtInstSetReg,
Ops, MAI);
1194 DebugInlinedAtRegs[
IA] =
Reg;
1198auto SPIRVNonSemanticDebugHandler::emitDebugFunctionDeclaration(
1201 -> EmitResult<PreparedScope> {
1202 assert(SP &&
"SP must not be null in emitDebugFunctionDeclaration");
1204 "SP must not be a definition in emitDebugFunctionDeclaration");
1207 EmitResult<MCRegister> FnTy = getOrCreateDebugScope(
SP->getType());
1209 return EmitResult<PreparedScope>::failure(FnTy);
1211 EmitResult<MCRegister> Parent =
resolveScope(
SP->getScope(),
SP->getUnit());
1213 return EmitResult<PreparedScope>::failure(Parent);
1215 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
1217 MCRegister NameReg = getCachedOpStringReg(
SP->getName());
1218 MCRegister LinkageReg = getCachedOpStringReg(
SP->getLinkageName());
1219 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1220 ExtInstSetReg, MAI);
1223 emitOpConstantI32(
static_cast<uint32_t
>(
SP->getLine()), I32TypeReg, MAI);
1224 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1226 uint32_t FlagsVal = transDebugFlags(SP);
1229 FlagsVal &= ~NSDIFlagIsDefinition;
1230 MCRegister FlagsReg = emitOpConstantI32(FlagsVal, I32TypeReg, MAI);
1232 return EmitResult<PreparedScope>::emitted(
1233 PreparedScope{SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
1234 {NameReg, *FnTy.Value, SrcReg, LineReg, ColReg,
1235 *Parent.Value, LinkageReg, FlagsReg}});
1238auto SPIRVNonSemanticDebugHandler::emitDebugFunction(
1241 -> EmitResult<PreparedScope> {
1242 assert(SP &&
"SP must not be null in emitDebugFunction");
1243 assert(
SP->isDefinition() &&
"SP must be a definition in emitDebugFunction");
1245 EmitResult<MCRegister> FnTy = getOrCreateDebugScope(
SP->getType());
1247 return EmitResult<PreparedScope>::failure(FnTy);
1249 EmitResult<MCRegister> Parent =
resolveScope(
SP->getScope(),
SP->getUnit());
1251 return EmitResult<PreparedScope>::failure(Parent);
1253 MCRegister NameReg = getCachedOpStringReg(
SP->getName());
1254 MCRegister LinkageReg = getCachedOpStringReg(
SP->getLinkageName());
1255 MCRegister FileStrReg = getCachedScopePathOpStringReg(SP);
1256 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1257 ExtInstSetReg, MAI);
1260 emitOpConstantI32(
static_cast<uint32_t
>(
SP->getLine()), I32TypeReg, MAI);
1263 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1264 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(SP), I32TypeReg, MAI);
1266 static_cast<uint32_t
>(
SP->getScopeLine()), I32TypeReg, MAI);
1269 LineReg, ColReg, *Parent.Value,
1270 LinkageReg, FlagsReg, ScopeLineReg};
1273 EmitResult<MCRegister> DeclRes = getOrCreateDebugScope(Decl);
1275 Ops.push_back(*DeclRes.Value);
1278 return EmitResult<PreparedScope>::emitted(
1279 PreparedScope{SPIRV::NonSemanticExtInst::DebugFunction,
Ops});
1282auto SPIRVNonSemanticDebugHandler::mapDISignatureTypeToReg(
1284 -> EmitResult<MCRegister> {
1287 return EmitResult<MCRegister>::emitted(VoidTypeReg);
1288 assert(CachedDebugInfoNoneReg.isValid() &&
1289 "DebugInfoNone must be emitted before DISubroutineType operands");
1290 return EmitResult<MCRegister>::emitted(CachedDebugInfoNoneReg);
1292 return getOrCreateDebugScope(Ty);
1310static std::optional<NonSemanticDebugOp>
1313 case dwarf::DW_OP_deref:
1315 case dwarf::DW_OP_plus:
1317 case dwarf::DW_OP_minus:
1319 case dwarf::DW_OP_plus_uconst:
1321 case dwarf::DW_OP_bit_piece:
1323 case dwarf::DW_OP_swap:
1325 case dwarf::DW_OP_xderef:
1327 case dwarf::DW_OP_stack_value:
1329 case dwarf::DW_OP_constu:
1334 return std::nullopt;
1340static std::optional<SmallVector<uint32_t, 3>>
1342 std::optional<NonSemanticDebugOp> NSOp =
1345 return std::nullopt;
1348 for (
unsigned I = 0,
E =
Op.getNumArgs();
I !=
E; ++
I) {
1351 return std::nullopt;
1357std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugOperation(
1363 return std::nullopt;
1365 auto [It,
Inserted] = DebugOperationCache.try_emplace(std::move(*
Key));
1370 for (uint32_t
V : It->first)
1371 Operands.push_back(emitOpConstantI32(
V, I32TypeReg, MAI));
1372 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugOperation,
1373 VoidTypeReg, ExtInstSetReg,
Operands, MAI);
1378std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugExpression(
1381 assert(Expr &&
"Expr must not be null in emitDebugExpression");
1384 for (
const DIExpression::ExprOperand &
Op : Expr->
expr_ops()) {
1385 std::optional<MCRegister> OpReg =
1386 emitDebugOperation(
Op, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
1388 return std::nullopt;
1393 DebugExpressionCache.try_emplace(std::move(OperationRegs));
1397 MCRegister
Reg = emitExtInst(SPIRV::NonSemanticExtInst::DebugExpression,
1398 VoidTypeReg, ExtInstSetReg, It->first, MAI);
1403std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugGlobalVariable(
1407 assert(GV &&
"GV must not be null in emitDebugGlobalVariable");
1409 EmitResult<MCRegister> Parent = resolveScope(GV->
getScope());
1411 return std::nullopt;
1413 MCRegister ParentReg = *Parent.Value;
1419 MCRegister TyReg = CachedDebugInfoNoneReg;
1420 if (
const DIType *Ty = GV->
getType()) {
1421 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1423 return std::nullopt;
1427 std::optional<MCRegister> StaticMemberRegOpt;
1430 StaticMemberRegOpt = lookupOptReg(DebugScopeRegs, SM);
1431 if (!StaticMemberRegOpt)
1432 return std::nullopt;
1435 MCRegister NameReg = getCachedOpStringReg(GV->
getName());
1436 MCRegister LinkageReg = getCachedOpStringReg(GV->
getLinkageName());
1437 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1439 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1440 ExtInstSetReg, MAI);
1442 MCRegister LineReg =
1443 emitOpConstantI32(
static_cast<uint32_t
>(GV->
getLine()), I32TypeReg, MAI);
1447 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1454 MCRegister VariableReg = CachedDebugInfoNoneReg;
1455 if (
const GlobalVariable *LLVMGV =
Info.LLVMGV) {
1458 VariableReg = GVReg;
1459 }
else if (
Info.Expr &&
Info.Expr->getNumElements() != 0) {
1460 if (
auto ExprReg = emitDebugExpression(
Info.Expr, VoidTypeReg, I32TypeReg,
1461 ExtInstSetReg, MAI))
1462 VariableReg = *ExprReg;
1465 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(GV), I32TypeReg, MAI);
1468 LineReg, ColReg, ParentReg,
1469 LinkageReg, VariableReg, FlagsReg};
1471 if (StaticMemberRegOpt)
1472 Ops.push_back(*StaticMemberRegOpt);
1474 return emitExtInst(SPIRV::NonSemanticExtInst::DebugGlobalVariable,
1475 VoidTypeReg, ExtInstSetReg,
Ops, MAI);
1478std::optional<MCRegister> SPIRVNonSemanticDebugHandler::emitDebugLocalVariable(
1481 assert(LV &&
"LV must not be null in emitDebugLocalVariable");
1483 EmitResult<MCRegister> Parent = resolveScope(LV->
getScope());
1485 return std::nullopt;
1487 MCRegister TyReg = CachedDebugInfoNoneReg;
1488 if (
const DIType *Ty = LV->
getType()) {
1489 auto TyRegOpt = lookupOptReg(DebugScopeRegs, Ty);
1491 return std::nullopt;
1495 MCRegister NameReg = getCachedOpStringReg(LV->
getName());
1496 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1498 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1499 ExtInstSetReg, MAI);
1500 MCRegister LineReg =
1501 emitOpConstantI32(
static_cast<uint32_t
>(LV->
getLine()), I32TypeReg, MAI);
1503 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1504 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(LV), I32TypeReg, MAI);
1507 ColReg, *Parent.Value, FlagsReg};
1508 if (
unsigned Arg = LV->
getArg())
1509 Ops.push_back(emitOpConstantI32(Arg, I32TypeReg, MAI));
1511 return emitExtInst(SPIRV::NonSemanticExtInst::DebugLocalVariable, VoidTypeReg,
1512 ExtInstSetReg,
Ops, MAI);
1515auto SPIRVNonSemanticDebugHandler::emitDebugTypeVector(
1517 -> EmitResult<PreparedScope> {
1520 return EmitResult<PreparedScope>::unsupported();
1524 DINodeArray
Elements = VT->getElements();
1526 return EmitResult<PreparedScope>::unsupported();
1530 return EmitResult<PreparedScope>::unsupported();
1532 EmitResult<MCRegister>
Base = getOrCreateDebugScope(BaseTy);
1534 return EmitResult<PreparedScope>::failure(
Base);
1536 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1538 static_cast<uint32_t
>(CI->getZExtValue()), I32TypeReg, MAI);
1539 return EmitResult<PreparedScope>::emitted(PreparedScope{
1540 SPIRV::NonSemanticExtInst::DebugTypeVector, {*
Base.Value, CountReg}});
1543auto SPIRVNonSemanticDebugHandler::emitDebugTypeArray(
1545 -> EmitResult<PreparedScope> {
1548 EmitResult<MCRegister>
Base = getOrCreateDebugScope(AT->getBaseType());
1550 return EmitResult<PreparedScope>::failure(
Base);
1552 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
1560 for (
const DINode *Element : AT->getElements()) {
1572 if (
Value.getActiveBits() <= 32)
1573 Count =
static_cast<uint32_t
>(
Value.getZExtValue());
1575 Ops.push_back(emitOpConstantI32(
Count, I32TypeReg, MAI));
1578 return EmitResult<PreparedScope>::emitted(
1579 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypeArray,
Ops});
1582auto SPIRVNonSemanticDebugHandler::emitDebugTypeMember(
1585 -> EmitResult<PreparedScope> {
1586 EmitResult<MCRegister> Ty = getOrCreateDebugScope(
M->getBaseType());
1588 return EmitResult<PreparedScope>::failure(Ty);
1591 return EmitResult<PreparedScope>::unsupported();
1593 MCRegister NameReg = getCachedOpStringReg(
M->getName());
1594 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1595 M->getFile(),
true);
1596 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1597 ExtInstSetReg, MAI);
1599 emitOpConstantI32(
static_cast<uint32_t
>(
M->getLine()), I32TypeReg, MAI);
1602 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1604 static_cast<uint32_t
>(
M->getOffsetInBits()), I32TypeReg, MAI);
1606 static_cast<uint32_t
>(
M->getSizeInBits()), I32TypeReg, MAI);
1607 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(M), I32TypeReg, MAI);
1618 return EmitResult<PreparedScope>::emitted(
1619 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypeMember,
1620 {NameReg, *Ty.Value, SrcReg, LineReg, ColReg, OffsetReg,
1621 SizeReg, FlagsReg}});
1624auto SPIRVNonSemanticDebugHandler::emitDebugTypeComposite(
1627 -> EmitResult<PreparedScope> {
1630 EmitResult<MCRegister> Parent =
resolveScope(CT->getScope());
1632 return EmitResult<PreparedScope>::failure(Parent);
1635 return EmitResult<PreparedScope>::unsupported();
1638 for (
const DINode *Element : CT->getElements()) {
1640 if (!M ||
M->getTag() != dwarf::DW_TAG_member)
1642 EmitResult<MCRegister>
Member = getOrCreateDebugScope(M);
1647 MCRegister NameReg = getCachedOpStringReg(CT->getName());
1648 MCRegister LinkageReg = getCachedOpStringReg(CT->getIdentifier());
1649 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1650 CT->getFile(),
true);
1651 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1652 ExtInstSetReg, MAI);
1655 emitOpConstantI32(mapCompositeTypeTag(CT->getTag()), I32TypeReg, MAI);
1657 emitOpConstantI32(
static_cast<uint32_t
>(CT->getLine()), I32TypeReg, MAI);
1658 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1662 if (!CT->isForwardDecl())
1663 SizeReg = emitOpConstantI32(
static_cast<uint32_t
>(CT->getSizeInBits()),
1666 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(CT), I32TypeReg, MAI);
1669 LineReg, ColReg, *Parent.Value,
1670 LinkageReg, SizeReg, FlagsReg};
1672 return EmitResult<PreparedScope>::emitted(
1673 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypeComposite,
Ops});
1676auto SPIRVNonSemanticDebugHandler::emitDebugTypeEnum(
1679 -> EmitResult<PreparedScope> {
1683 return EmitResult<PreparedScope>::unsupported();
1685 MCRegister UnderlyingReg = CachedDebugInfoNoneReg;
1686 if (
const DIType *BaseTy = ET->getBaseType()) {
1687 EmitResult<MCRegister>
Base = getOrCreateDebugScope(BaseTy);
1689 return EmitResult<PreparedScope>::failure(
Base);
1690 UnderlyingReg = *
Base.Value;
1693 EmitResult<MCRegister> Parent =
1694 resolveScope(ET->getScope(), EnumCompileUnits.lookup(ET));
1696 return EmitResult<PreparedScope>::failure(Parent);
1698 MCRegister NameReg = getCachedOpStringReg(ET->getName());
1699 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1700 ET->getFile(),
true);
1701 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1702 ExtInstSetReg, MAI);
1704 emitOpConstantI32(
static_cast<uint32_t
>(ET->getLine()), I32TypeReg, MAI);
1706 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1708 emitOpConstantI32(
static_cast<uint32_t
>(
Size), I32TypeReg, MAI);
1709 MCRegister FlagsReg = emitOpConstantI32(transDebugFlags(ET), I32TypeReg, MAI);
1712 ColReg, *Parent.Value, SizeReg, FlagsReg};
1717 for (
const DINode *Element : ET->getElements()) {
1722 if (
E->isUnsigned() ? !
Value.isIntN(32) : !
Value.isSignedIntN(32))
1724 uint32_t
Bits =
E->isUnsigned()
1725 ?
static_cast<uint32_t
>(
Value.getZExtValue())
1726 :
static_cast<uint32_t
>(
Value.getSExtValue());
1727 Ops.push_back(emitOpConstantI32(Bits, I32TypeReg, MAI));
1728 Ops.push_back(getCachedOpStringReg(
E->getName()));
1731 return EmitResult<PreparedScope>::emitted(
1732 PreparedScope{SPIRV::NonSemanticExtInst::DebugTypeEnum,
Ops});
1735auto SPIRVNonSemanticDebugHandler::emitDebugTypedef(
1738 -> EmitResult<PreparedScope> {
1739 EmitResult<MCRegister>
Base = getOrCreateDebugScope(TD->getBaseType());
1741 return EmitResult<PreparedScope>::failure(
Base);
1743 MCRegister NameReg = getCachedOpStringReg(TD->getName());
1744 MCRegister FileStrReg = getCachedScopePathOpStringReg(
1745 TD->getFile(),
true);
1746 MCRegister SrcReg = getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg,
1747 ExtInstSetReg, MAI);
1749 emitOpConstantI32(
static_cast<uint32_t
>(TD->getLine()), I32TypeReg, MAI);
1751 MCRegister ColReg = emitOpConstantI32(0, I32TypeReg, MAI);
1756 EmitResult<MCRegister> Parent =
resolveScope(TD->getScope());
1758 return EmitResult<PreparedScope>::failure(Parent);
1760 return EmitResult<PreparedScope>::emitted(PreparedScope{
1761 SPIRV::NonSemanticExtInst::DebugTypedef,
1762 {NameReg, *
Base.Value, SrcReg, LineReg, ColReg, *Parent.Value}});
1767 if (CompileUnits.empty())
1775 for (
const CompileUnitInfo &Info : CompileUnits) {
1777 MCRegister PathReg = emitOpStringIfNew(Info.FilePath, MAI);
1778 ScopeToPathOpStringReg[Info.TheCU] = PathReg;
1779 if (
const DIFile *
F = Info.TheCU->getFile())
1780 ScopeToPathOpStringReg[
F] = PathReg;
1785 emitOpStringIfNew(SP->getName(), MAI);
1786 emitOpStringIfNew(SP->getLinkageName(), MAI);
1787 emitAndCacheScopePathOpStringReg(SP, MAI);
1790 for (
const DIType *Ty : DebugTypes) {
1792 emitOpStringIfNew(
BT->getName(), MAI);
1798 if (CT->getTag() == dwarf::DW_TAG_enumeration_type) {
1799 emitOpStringIfNew(CT->getName(), MAI);
1800 emitAndCacheScopePathOpStringReg(CT->getFile(), MAI);
1801 for (
const DINode *Element : CT->getElements())
1803 emitOpStringIfNew(E->getName(), MAI);
1809 if (CT->getTag() != dwarf::DW_TAG_structure_type &&
1810 CT->getTag() != dwarf::DW_TAG_class_type &&
1811 CT->getTag() != dwarf::DW_TAG_union_type)
1813 emitOpStringIfNew(CT->getName(), MAI);
1814 emitOpStringIfNew(CT->getIdentifier(), MAI);
1815 emitAndCacheScopePathOpStringReg(CT->getFile(), MAI);
1816 for (
const DINode *Element : CT->getElements()) {
1818 if (!M || M->getTag() != dwarf::DW_TAG_member)
1820 emitOpStringIfNew(M->getName(), MAI);
1821 emitAndCacheScopePathOpStringReg(M->getFile(), MAI);
1827 if (TD && TD->getTag() == dwarf::DW_TAG_typedef) {
1828 emitOpStringIfNew(TD->getName(), MAI);
1829 emitAndCacheScopePathOpStringReg(TD->getFile(), MAI);
1833 for (
const auto &[GV,
_] : GlobalVariableDebugInfoMap) {
1834 emitOpStringIfNew(GV->
getName(), MAI);
1836 emitAndCacheScopePathOpStringReg(GV->
getFile(), MAI);
1840 emitOpStringIfNew(LV->
getName(), MAI);
1841 emitAndCacheScopePathOpStringReg(LV->
getFile(), MAI);
1844 for (
const DIScope *S : LexicalBlocks) {
1845 emitAndCacheScopePathOpStringReg(S->getFile(), MAI);
1847 emitOpStringIfNew(NS->getName(), MAI);
1851 emitAndCacheScopePathOpStringReg(
DL->getScope(), MAI);
1853 CachedEmptyStringReg = emitOpStringIfNew(
"", MAI);
1856 NonSemanticOpStringsSectionEmitted =
true;
1860void SPIRVNonSemanticDebugHandler::emitDebugFunctionDefinition(
1864 "DebugFunctionDefinition operands must be valid");
1865 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
1867 emitExtInst(SPIRV::NonSemanticExtInst::DebugFunctionDefinition, VoidTypeReg,
1868 ExtInstSetReg, {DebugFunctionReg, OpFunctionReg}, MAI);
1871void SPIRVNonSemanticDebugHandler::resetPerFunctionDebugState() {
1872 CurrentMF =
nullptr;
1873 LastFunctionOpVariable =
nullptr;
1874 DebugFunctionDefinitionEmitted =
false;
1875 LastLineMI =
nullptr;
1876 LastScopeMI =
nullptr;
1880void SPIRVNonSemanticDebugHandler::preparePerFunctionDebug(
1882 resetPerFunctionDebugState();
1883 if (!GlobalNSDIEnabled || !CurrentMAI)
1894 if (!SP || !
SP->isDefinition())
1899 LastFunctionOpVariable =
1900 findLastFunctionOpVariableDeclaration(*MF, *CurrentMAI);
1902 analyzeDebugRecords(*MF);
1905void SPIRVNonSemanticDebugHandler::tryEmitDebugFunctionDefinition(
1907 if (DebugFunctionDefinitionEmitted || !GlobalNSDIEnabled)
1910 assert(CurrentMF &&
"no current MachineFunction");
1911 const Function &
F = CurrentMF->getFunction();
1912 const DISubprogram *
SP =
F.getSubprogram();
1913 if (!SP || !
SP->isDefinition())
1916 auto DFIt = DebugScopeRegs.find(SP);
1917 if (DFIt == DebugScopeRegs.end())
1924 emitDebugFunctionDefinition(DFIt->second, OpFunctionReg, MAI);
1925 DebugFunctionDefinitionEmitted =
true;
1930 preparePerFunctionDebug(MF);
1935 resetPerFunctionDebugState();
1942 if (!DebugFunctionDefinitionEmitted)
1945 emitAnalyzedRecords(
MI);
1947 std::optional<const MachineInstr *>
Target = resolveDebugLocTarget(
MI);
1951 (void)emitDebugScopeForInstruction(*
Target);
1952 emitDebugLineForInstruction(*
Target);
1962static std::optional<Register>
1966 if (!
MI.isIndirectDebugValue())
1967 return std::nullopt;
1971 Register LocReg =
MI.getDebugOperand(0).getReg();
1973 return std::nullopt;
1984 const MachineInstr *Def =
MI.getMF()->getRegInfo().getUniqueVRegDef(LocReg);
1985 if (!Def || Def->getOpcode() != SPIRV::OpVariable)
1986 return std::nullopt;
1991void SPIRVNonSemanticDebugHandler::emitDebugBinding(
1992 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
1994 assert(DebugFunctionDefinitionEmitted &&
1995 "DebugFunctionDefinition must be emitted");
1996 assert(CurrentMAI &&
"CurrentMAI must be set");
1998 auto VarRegOpt = lookupOptReg(DebugLocalVariableRegs,
MI->getDebugVariable());
2002 auto ExprRegOpt = lookupOptReg(DebugExpressionRegs,
MI->getDebugExpression());
2006 if (!emitDebugScopeForInstruction(
MI))
2008 emitDebugLineForInstruction(
MI);
2010 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2011 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2013 emitExtInst(Opcode, VoidTypeReg, ExtInstSetReg,
2014 {*VarRegOpt, LocationReg, *ExprRegOpt}, MAI);
2019static std::optional<std::pair<const DIBasicType *, uint64_t>>
2021 if (!
MI.isNonListDebugValue() ||
MI.isIndirectDebugValue())
2022 return std::nullopt;
2026 return std::nullopt;
2031 return std::nullopt;
2036 else if (
Value.isCImm())
2040 return std::make_pair(
BT, Bits);
2043std::optional<MCRegister> SPIRVNonSemanticDebugHandler::getConstantValueReg(
2045 std::optional<std::pair<const DIBasicType *, uint64_t>>
Const =
2048 return std::nullopt;
2050 auto It = ConstantValueRegs.find(*Const);
2051 if (It == ConstantValueRegs.end() || !It->second.isValid())
2052 return std::nullopt;
2057 if (!
MI.isNonListDebugValue() ||
MI.isIndirectDebugValue())
2058 return std::nullopt;
2062 return std::nullopt;
2066 return std::nullopt;
2068 const MachineInstr *Def =
MI.getMF()->getRegInfo().getUniqueVRegDef(ValueReg);
2069 if (!Def || (Def->isPseudo() && !Def->isPHI()) || Def->isMetaInstruction() ||
2070 Def->getNumOperands() == 0 || !Def->getOperand(0).isReg() ||
2071 !Def->getOperand(0).isDef() || Def->getOperand(0).getReg() != ValueReg)
2072 return std::nullopt;
2078 return Opcode == SPIRV::OpSelectionMerge || Opcode == SPIRV::OpLoopMerge ||
2079 Opcode == SPIRV::OpLoopControlINTEL;
2091 switch (
MI->getOpcode()) {
2092 case SPIRV::OpFunction:
2093 case SPIRV::OpFunctionParameter:
2094 case SPIRV::OpFunctionEnd:
2095 case SPIRV::OpLabel:
2096 case TargetOpcode::PHI:
2107 :
MI->getPrevNode();
2108 Adj; Adj = Forward ? Adj->getNextNode() : Adj->getPrevNode()) {
2116std::optional<const MachineInstr *>
2117SPIRVNonSemanticDebugHandler::resolveDebugLocTarget(
const MachineInstr *
MI) {
2118 assert(CurrentMAI &&
"CurrentMAI must be set");
2119 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2124 return std::nullopt;
2132 return std::nullopt;
2138 assert(
MI &&
"Merge instruction must be followed by a terminator");
2142 return std::nullopt;
2148void SPIRVNonSemanticDebugHandler::resolveDebugRecord(
2151 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2157 const MachineInstr *Anchor =
2167 placeRecord(SPIRV::NonSemanticExtInst::DebugDeclare,
MI, StorageReg,
2172 if (std::optional<MCRegister> ConstReg = getConstantValueReg(
MI)) {
2173 placeRecord(SPIRV::NonSemanticExtInst::DebugValue,
MI, *ConstReg, Anchor);
2193 if (ModuleScopeIds.contains(ValueReg) ||
2195 placeRecord(SPIRV::NonSemanticExtInst::DebugValue,
MI, ValueReg, Anchor);
2198void SPIRVNonSemanticDebugHandler::analyzeDebugRecords(
2200 assert(CurrentMAI &&
"CurrentMAI must be set");
2204 std::optional<MachineDominatorTree> DomTree;
2206 for (
const MachineBasicBlock &
MBB : MF) {
2207 const MachineInstr *LastEmitted =
nullptr;
2208 for (
const MachineInstr &
MI :
MBB) {
2209 if (
MI.isDebugValueLike()) {
2212 resolveDebugRecord(
MI, LastEmitted, *DomTree);
2221void SPIRVNonSemanticDebugHandler::placeRecord(
2222 SPIRV::NonSemanticExtInst::NonSemanticExtInst Opcode,
2225 Records[Anchor].push_back({&
MI, Opcode, LocationReg});
2228void SPIRVNonSemanticDebugHandler::emitAnalyzedRecords(
2230 auto It = Records.find(Anchor);
2231 if (It == Records.end())
2233 for (
const DebugRecord &R : It->second)
2234 emitDebugBinding(
R.Opcode,
R.MI,
R.LocationReg);
2237bool SPIRVNonSemanticDebugHandler::emitDebugScopeForInstruction(
2239 assert(DebugFunctionDefinitionEmitted &&
2240 "DebugFunctionDefinition must be emitted");
2241 assert(CurrentMAI &&
"CurrentMAI must be set");
2246 if (LastScopeMI &&
MI->getParent() != LastScopeMI->getParent())
2247 LastScopeMI =
nullptr;
2249 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2250 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2253 const DILocation *CurDL =
MI->getDebugLoc().get();
2258 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoScope, VoidTypeReg,
2259 ExtInstSetReg, {}, MAI);
2260 LastScopeMI =
nullptr;
2265 const DIScope *CurScope = CurDL->getScope();
2266 const DILocation *CurInlinedAt = CurDL->getInlinedAt();
2269 const DILocation *LastDL = LastScopeMI->getDebugLoc().get();
2270 if (LastDL->getScope() == CurScope &&
2271 LastDL->getInlinedAt() == CurInlinedAt)
2275 EmitResult<MCRegister> CurScopeRes = resolveScope(CurScope);
2282 MCRegister InlinedReg = DebugInlinedAtRegs.lookup(CurInlinedAt);
2285 Ops.push_back(InlinedReg);
2289 emitExtInst(SPIRV::NonSemanticExtInst::DebugScope, VoidTypeReg, ExtInstSetReg,
2296void SPIRVNonSemanticDebugHandler::emitDebugLineForInstruction(
2298 assert(DebugFunctionDefinitionEmitted &&
2299 "DebugFunctionDefinition must be emitted");
2300 assert(CurrentMAI &&
"CurrentMAI must be set");
2305 if (LastLineMI &&
MI->getParent() != LastLineMI->getParent())
2306 LastLineMI =
nullptr;
2308 SPIRV::ModuleAnalysisInfo &MAI = *CurrentMAI;
2309 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2312 const DILocation *
DL =
MI->getDebugLoc().get();
2317 emitExtInst(SPIRV::NonSemanticExtInst::DebugNoLine, VoidTypeReg,
2318 ExtInstSetReg, {}, MAI);
2319 LastLineMI =
nullptr;
2329 MCRegister FileStrReg = getCachedScopePathOpStringReg(
2330 DL->getScope(),
true);
2331 unsigned Line =
DL->getLine();
2332 unsigned Col =
DL->getColumn();
2334 unsigned I32TypeId = CachedOpTypeInt32Reg.id();
2335 MCRegister SrcReg = DebugSourceRegByFileStr.lookup(FileStrReg.
id());
2336 MCRegister LineReg = ScalarConstantCache.lookup({I32TypeId,
Line});
2337 MCRegister ColStartReg = ScalarConstantCache.lookup({I32TypeId, Col});
2338 MCRegister ColEndReg = ScalarConstantCache.lookup({I32TypeId, Col + 1});
2350 if (LastLineMI &&
MI->getDebugLoc() == LastLineMI->getDebugLoc())
2354 emitExtInst(SPIRV::NonSemanticExtInst::DebugLine, VoidTypeReg, ExtInstSetReg,
2355 {SrcReg, LineReg, LineReg, ColStartReg, ColEndReg}, MAI);
2364 if (!
MI || !GlobalNSDIEnabled || !CurrentMF)
2367 if (DebugFunctionDefinitionEmitted ||
MI != LastFunctionOpVariable)
2373 assert(CurrentMAI &&
"CurrentMAI must be set");
2374 tryEmitDebugFunctionDefinition(*CurrentMAI);
2379 if (!GlobalNSDIEnabled || DebugFunctionDefinitionEmitted || !CurrentMF)
2382 assert(CurrentMF == &MF &&
2383 "notification does not match the current MachineFunction");
2385 if (LastFunctionOpVariable)
2391 tryEmitDebugFunctionDefinition(*CurrentMAI);
2394void SPIRVNonSemanticDebugHandler::collectDebugExpressions(
2398 Out.insert(
MI->getDebugExpression());
2403 if (GlobalDIEmitted)
2406 GlobalDIEmitted =
true;
2408 if (CompileUnits.empty()) {
2409 GlobalNSDIEnabled =
false;
2415 if (!ExtInstSetReg.
isValid()) {
2416 GlobalNSDIEnabled =
false;
2421 assert(NonSemanticOpStringsSectionEmitted &&
2422 "emitNonSemanticDebugStrings() must run before "
2423 "emitNonSemanticGlobalDebugInfo()");
2428 MCRegister VoidTypeReg = getOrEmitOpTypeVoidReg(MAI);
2429 MCRegister I32TypeReg = getOrEmitOpTypeInt32Reg(MAI);
2431 CachedDebugInfoNoneReg = emitExtInst(SPIRV::NonSemanticExtInst::DebugInfoNone,
2432 VoidTypeReg, ExtInstSetReg, {}, MAI);
2444 MCRegister DebugInfoVersionReg = emitOpConstantI32(100, I32TypeReg, MAI);
2446 emitOpConstantI32(
static_cast<uint32_t>(DwarfVersion), I32TypeReg, MAI);
2451 map_to_vector(CompileUnits, [&](
const CompileUnitInfo &Info) {
2452 return emitOpConstantI32(Info.SpirvSourceLanguage, I32TypeReg, MAI);
2456 for (
auto [Info, SrcLangReg] :
llvm::zip(CompileUnits, SrcLangRegs)) {
2457 MCRegister FileStrReg = ScopeToPathOpStringReg.lookup(Info.TheCU);
2459 "CU path OpString must be emitted in emitNonSemanticDebugStrings");
2460 MCRegister DebugSourceReg = getOrEmitDebugSourceForFileStrReg(
2461 FileStrReg, VoidTypeReg, ExtInstSetReg, MAI);
2463 SPIRV::NonSemanticExtInst::DebugCompilationUnit, VoidTypeReg,
2465 {DebugInfoVersionReg, DwarfVersionReg, DebugSourceReg, SrcLangReg},
2468 DebugScopeRegs[Info.TheCU] = CUDbgReg;
2473 getOrCreateDebugScope(S);
2478 if (
auto LVReg = emitDebugLocalVariable(LV, VoidTypeReg, I32TypeReg,
2479 ExtInstSetReg, MAI))
2480 DebugLocalVariableRegs[LV] = *LVReg;
2487 collectDebugExpressions(MAI, Expressions);
2489 if (
auto ExprReg = emitDebugExpression(Expr, VoidTypeReg, I32TypeReg,
2490 ExtInstSetReg, MAI))
2491 DebugExpressionRegs[Expr] = *ExprReg;
2494 for (
const auto &[GV, Info] : GlobalVariableDebugInfoMap)
2495 emitDebugGlobalVariable(GV, Info, VoidTypeReg, I32TypeReg, ExtInstSetReg,
2501 getOrEmitDebugInlinedAt(IA, VoidTypeReg, I32TypeReg, ExtInstSetReg, MAI);
2506 std::optional<std::pair<const DIBasicType *, uint64_t>> Const =
2510 if (!DebugLocalVariableRegs.contains(
MI->getDebugVariable()) ||
2511 !DebugExpressionRegs.contains(
MI->getDebugExpression()))
2513 auto [It, Inserted] = ConstantValueRegs.try_emplace(*Const,
MCRegister());
2515 It->second = findOrEmitScalarConstant(Const->first, Const->second, MAI);
2516 if (!It->second.isValid())
2517 ConstantValueRegs.erase(It);
2521 emitOpConstantI32(
DL->getLine(), I32TypeReg, MAI);
2522 emitOpConstantI32(
DL->getColumn(), I32TypeReg, MAI);
2523 emitOpConstantI32(
DL->getColumn() + 1, I32TypeReg, MAI);
2525 getCachedScopePathOpStringReg(
DL->getScope(),
2527 getOrEmitDebugSourceForFileStrReg(FileStrReg, VoidTypeReg, ExtInstSetReg,
2531 GlobalNSDIEnabled =
true;
2535SPIRVNonSemanticDebugHandler::getDebugFullPath(
const DIScope *Scope)
const {
2545 Out.assign(Dir.
begin(), Dir.
end());
2551MCRegister SPIRVNonSemanticDebugHandler::getOrEmitDebugSourceForFileStrReg(
2554 const unsigned Key = FileStrReg.
id();
2555 auto It = DebugSourceRegByFileStr.find(
Key);
2556 if (It != DebugSourceRegByFileStr.end())
2559 MCRegister
DS = emitExtInst(SPIRV::NonSemanticExtInst::DebugSource,
2560 VoidTypeReg, ExtInstSetReg, {FileStrReg}, MAI);
2561 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 cl::opt< bool > SPIRVDebugLexicalBlockDiscriminatorScope("spirv-debug-lexical-block-discriminator-scope", cl::desc("Use a DebugLexicalBlockDiscriminator as a DebugScope"), cl::init(false))
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 cl::opt< bool > SPIRVDebugScopeForwardRefs("spirv-debug-scope-forward-refs", cl::desc("Forward-reference debug scopes when " "SPV_KHR_relaxed_extended_instruction is enabled"), cl::init(false))
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.
initializer< Ty > init(const Ty &Val)
@ 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)