LLVM: lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
33#include "llvm/Config/llvm-config.h"
68#include
69#include
70#include
71#include
72#include
73
74using namespace llvm;
76
77namespace {
79public:
81 : OS(&OS), TypeTable(TypeTable) {}
82
84
87 }
88
90
92
94
95 bool isVerboseAsm() override { return OS->isVerboseAsm(); }
96
102 else
103 TypeName = std::string(TypeTable.getTypeName(TI));
104 }
106 }
107
108private:
111};
112}
113
115 switch (Type) {
116 case Triple::ArchType::x86:
117 return CPUType::Pentium3;
118 case Triple::ArchType::x86_64:
119 return CPUType::X64;
120 case Triple::ArchType::thumb:
121
122
123 return CPUType::ARMNT;
124 case Triple::ArchType::aarch64:
125 return CPUType::ARM64;
126 case Triple::ArchType::mipsel:
127 return CPUType::MIPS;
128 default:
129 report_fatal_error("target architecture doesn't map to a CodeView CPUType");
130 }
131}
132
135
136StringRef CodeViewDebug::getFullFilepath(const DIFile *File) {
137 std::string &Filepath = FileToFilepathMap[File];
138 if (!Filepath.empty())
139 return Filepath;
140
141 StringRef Dir = File->getDirectory(), Filename = File->getFilename();
142
143
144
145 if (Dir.starts_with("/") || Filename.starts_with("/")) {
147 return Filename;
148 Filepath = std::string(Dir);
149 if (Dir.back() != '/')
150 Filepath += '/';
151 Filepath += Filename;
152 return Filepath;
153 }
154
155
156
157
158
159 if (Filename.find(':') == 1)
160 Filepath = std::string(Filename);
161 else
162 Filepath = (Dir + "\\" + Filename).str();
163
164
165
166
167 std::replace(Filepath.begin(), Filepath.end(), '/', '\\');
168
169
170 size_t Cursor = 0;
171 while ((Cursor = Filepath.find("\\.\\", Cursor)) != std:🧵:npos)
172 Filepath.erase(Cursor, 2);
173
174
175
176 Cursor = 0;
177 while ((Cursor = Filepath.find("\\..\\", Cursor)) != std:🧵:npos) {
178
179 if (Cursor == 0)
180 break;
181
182 size_t PrevSlash = Filepath.rfind('\\', Cursor - 1);
183 if (PrevSlash == std:🧵:npos)
184
185 break;
186
187 Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
188
189 Cursor = PrevSlash;
190 }
191
192
193 Cursor = 0;
194 while ((Cursor = Filepath.find("\\\\", Cursor)) != std:🧵:npos)
195 Filepath.erase(Cursor, 1);
196
197 return Filepath;
198}
199
200unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) {
201 StringRef FullPath = getFullFilepath(F);
202 unsigned NextId = FileIdMap.size() + 1;
203 auto Insertion = FileIdMap.insert(std::make_pair(FullPath, NextId));
204 if (Insertion.second) {
205
208 if (F->getChecksum()) {
209 std::string Checksum = fromHex(F->getChecksum()->Value);
211 memcpy(CKMem, Checksum.data(), Checksum.size());
213 reinterpret_cast<const uint8_t *>(CKMem), Checksum.size());
214 switch (F->getChecksum()->Kind) {
216 CSKind = FileChecksumKind::MD5;
217 break;
219 CSKind = FileChecksumKind::SHA1;
220 break;
222 CSKind = FileChecksumKind::SHA256;
223 break;
224 }
225 }
227 static_cast<unsigned>(CSKind));
230 }
231 return Insertion.first->second;
232}
233
234CodeViewDebug::InlineSite &
235CodeViewDebug::getInlineSite(const DILocation *InlinedAt,
237 auto SiteInsertion = CurFn->InlineSites.insert({InlinedAt, InlineSite()});
238 InlineSite *Site = &SiteInsertion.first->second;
239 if (SiteInsertion.second) {
240 unsigned ParentFuncId = CurFn->FuncId;
241 if (const DILocation *OuterIA = InlinedAt->getInlinedAt())
242 ParentFuncId =
243 getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())
244 .SiteFuncId;
245
246 Site->SiteFuncId = NextFuncId++;
248 Site->SiteFuncId, ParentFuncId, maybeRecordFile(InlinedAt->getFile()),
249 InlinedAt->getLine(), InlinedAt->getColumn(), SMLoc());
251 InlinedSubprograms.insert(Inlinee);
252 auto InlineeIdx = getFuncIdForSubprogram(Inlinee);
253
254 if (InlinedAt->getInlinedAt() == nullptr)
255 CurFn->Inlinees.insert(InlineeIdx);
256 }
257 return *Site;
258}
259
261 StringRef ScopeName = Scope->getName();
262 if (!ScopeName.empty())
263 return ScopeName;
264
265 switch (Scope->getTag()) {
266 case dwarf::DW_TAG_enumeration_type:
267 case dwarf::DW_TAG_class_type:
268 case dwarf::DW_TAG_structure_type:
269 case dwarf::DW_TAG_union_type:
270 return "";
271 case dwarf::DW_TAG_namespace:
272 return "`anonymous namespace'";
273 default:
275 }
276}
277
278const DISubprogram *CodeViewDebug::collectParentScopeNames(
280 const DISubprogram *ClosestSubprogram = nullptr;
281 while (Scope != nullptr) {
282 if (ClosestSubprogram == nullptr)
283 ClosestSubprogram = dyn_cast(Scope);
284
285
286
287
288 if (const auto *Ty = dyn_cast(Scope))
289 DeferredCompleteTypes.push_back(Ty);
290
292 if (!ScopeName.empty())
293 QualifiedNameComponents.push_back(ScopeName);
295 }
296 return ClosestSubprogram;
297}
298
301 std::string FullyQualifiedName;
302 for (StringRef QualifiedNameComponent :
304 FullyQualifiedName.append(std::string(QualifiedNameComponent));
305 FullyQualifiedName.append("::");
306 }
307 FullyQualifiedName.append(std::string(TypeName));
308 return FullyQualifiedName;
309}
310
314
315
316 if (CVD.TypeEmissionLevel == 1)
317 CVD.emitDeferredCompleteTypes();
318 --CVD.TypeEmissionLevel;
319 }
321};
322
323std::string CodeViewDebug::getFullyQualifiedName(const DIScope *Scope,
325
326
327
330 collectParentScopeNames(Scope, QualifiedNameComponents);
332}
333
334std::string CodeViewDebug::getFullyQualifiedName(const DIScope *Ty) {
337}
338
339TypeIndex CodeViewDebug::getScopeIndex(const DIScope *Scope) {
340
341
342
343
344
345
346
347
348
349
350 if (!Scope || isa(Scope) || isa(Scope))
352
353 assert(!isa(Scope) && "shouldn't make a namespace scope for a type");
354
355
356 auto I = TypeIndices.find({Scope, nullptr});
357 if (I != TypeIndices.end())
358 return I->second;
359
360
361 std::string ScopeName = getFullyQualifiedName(Scope);
364 return recordTypeIndexForDINode(Scope, TI);
365}
366
368
369
370 if (Name.empty() || Name.back() != '>')
372
373 int OpenBrackets = 0;
374 for (int i = Name.size() - 1; i >= 0; --i) {
375 if (Name[i] == '>')
376 ++OpenBrackets;
377 else if (Name[i] == '<') {
378 --OpenBrackets;
379 if (OpenBrackets == 0)
380 return Name.substr(0, i);
381 }
382 }
384}
385
388
389
390 auto I = TypeIndices.find({SP, nullptr});
391 if (I != TypeIndices.end())
392 return I->second;
393
394
395
396
398
401 if (const auto *Class = dyn_cast_or_null(Scope)) {
402
403
404
405 TypeIndex ClassType = getTypeIndex(Class);
406 MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class),
407 DisplayName);
409 } else {
410
411 TypeIndex ParentScope = getScopeIndex(Scope);
412 FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName);
414 }
415
416 return recordTypeIndexForDINode(SP, TI);
417}
418
420 return ((DCTy->getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);
421}
422
428 const DIType *ReturnTy = nullptr;
430 if (TypeArray.size())
431 ReturnTy = TypeArray[0];
432 }
433
434
435
436 if (auto *ReturnDCTy = dyn_cast_or_null(ReturnTy))
438 FO |= FunctionOptions::CxxReturnUdt;
439
440
441 if (ClassTy && isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {
442 FO |= FunctionOptions::Constructor;
443
444
445
446 }
447 return FO;
448}
449
452
453
454 if (SP->getDeclaration())
455 SP = SP->getDeclaration();
456 assert(!SP->getDeclaration() && "should use declaration as key");
457
458
459
460 auto I = TypeIndices.find({SP, Class});
461 if (I != TypeIndices.end())
462 return I->second;
463
464
465
466
467 TypeLoweringScope S(*this);
468 const bool IsStaticMethod = (SP->getFlags() & DINode::FlagStaticMember) != 0;
469
471 TypeIndex TI = lowerTypeMemberFunction(
472 SP->getType(), Class, SP->getThisAdjustment(), IsStaticMethod, FO);
473 return recordTypeIndexForDINode(SP, TI, Class);
474}
475
478 const DIType *ClassTy) {
479 auto InsertResult = TypeIndices.insert({{Node, ClassTy}, TI});
480 (void)InsertResult;
481 assert(InsertResult.second && "DINode was already assigned a type index");
482 return TI;
483}
484
485unsigned CodeViewDebug::getPointerSizeInBytes() {
487}
488
489void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
491 if (const DILocation *InlinedAt = LS->getInlinedAt()) {
492
494 InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
495 Site.InlinedLocals.emplace_back(std::move(Var));
496 } else {
497
498 ScopeVariables[LS].emplace_back(std::move(Var));
499 }
500}
501
506}
507
508void CodeViewDebug::maybeRecordLocation(const DebugLoc &DL,
510
512 return;
513
515 if (!Scope)
516 return;
517
518
519 LineInfo LI(DL.getLine(), DL.getLine(), true);
520 if (LI.getStartLine() != DL.getLine() || LI.isAlwaysStepInto() ||
521 LI.isNeverStepInto())
522 return;
523
525 if (CI.getStartColumn() != DL.getCol())
526 return;
527
528 if (!CurFn->HaveLineInfo)
529 CurFn->HaveLineInfo = true;
530 unsigned FileId = 0;
532 FileId = CurFn->LastFileId;
533 else
534 FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile());
536
537 unsigned FuncId = CurFn->FuncId;
538 if (const DILocation *SiteLoc = DL->getInlinedAt()) {
540
541
542
544 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
545
546
547 bool FirstLoc = true;
548 while ((SiteLoc = Loc->getInlinedAt())) {
550 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
551 if (!FirstLoc)
553 FirstLoc = false;
554 Loc = SiteLoc;
555 }
557 }
558
560 false, false,
561 DL->getFilename(), SMLoc());
562}
563
564void CodeViewDebug::emitCodeViewMagicVersion() {
566 OS.AddComment("Debug section magic");
568}
569
571 switch (DWLang) {
572 case dwarf::DW_LANG_C:
573 case dwarf::DW_LANG_C89:
574 case dwarf::DW_LANG_C99:
575 case dwarf::DW_LANG_C11:
576 return SourceLanguage::C;
577 case dwarf::DW_LANG_C_plus_plus:
578 case dwarf::DW_LANG_C_plus_plus_03:
579 case dwarf::DW_LANG_C_plus_plus_11:
580 case dwarf::DW_LANG_C_plus_plus_14:
581 return SourceLanguage::Cpp;
582 case dwarf::DW_LANG_Fortran77:
583 case dwarf::DW_LANG_Fortran90:
584 case dwarf::DW_LANG_Fortran95:
585 case dwarf::DW_LANG_Fortran03:
586 case dwarf::DW_LANG_Fortran08:
587 return SourceLanguage::Fortran;
588 case dwarf::DW_LANG_Pascal83:
589 return SourceLanguage::Pascal;
590 case dwarf::DW_LANG_Cobol74:
591 case dwarf::DW_LANG_Cobol85:
592 return SourceLanguage::Cobol;
593 case dwarf::DW_LANG_Java:
594 return SourceLanguage::Java;
595 case dwarf::DW_LANG_D:
596 return SourceLanguage::D;
597 case dwarf::DW_LANG_Swift:
598 return SourceLanguage::Swift;
599 case dwarf::DW_LANG_Rust:
600 return SourceLanguage::Rust;
601 case dwarf::DW_LANG_ObjC:
602 return SourceLanguage::ObjC;
603 case dwarf::DW_LANG_ObjC_plus_plus:
604 return SourceLanguage::ObjCpp;
605 default:
606
607
608
609 return SourceLanguage::Masm;
610 }
611}
612
614
615
618 Asm = nullptr;
619 return;
620 }
621
623
624
625 const MDNode *Node = *M->debug_compile_units_begin();
626 const auto *CU = cast(Node);
627
629
630 collectGlobalVariableInfo();
631
632
634 mdconst::extract_or_null(M->getModuleFlag("CodeViewGHash"));
635 EmitDebugGlobalHashes = GH && !GH->isZero();
636}
637
640 return;
641
642
643
644
645
646
647
648
649 switchToDebugSectionForSymbol(nullptr);
650
651 MCSymbol *CompilerInfo = beginCVSubsection(DebugSubsectionKind::Symbols);
652 emitObjName();
653 emitCompilerInformation();
654 endCVSubsection(CompilerInfo);
655
656 emitInlineeLinesSubsection();
657
658
659 for (auto &P : FnDebugInfo)
660 if (.first->isDeclarationForLinker())
661 emitDebugInfoForFunction(P.first, *P.second);
662
663
664
665
666 collectDebugInfoForGlobals();
667
668
669 emitDebugInfoForRetainedTypes();
670
671
672 setCurrentSubprogram(nullptr);
673 emitDebugInfoForGlobals();
674
675
676
677 switchToDebugSectionForSymbol(nullptr);
678
679
680 if (!GlobalUDTs.empty()) {
681 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
682 emitDebugInfoForUDTs(GlobalUDTs);
683 endCVSubsection(SymbolsEnd);
684 }
685
686
687 OS.AddComment("File index to string table offset subsection");
689
690
693
694
695
696
697 emitBuildInfo();
698
699
700
701 emitTypeInformation();
702
703 if (EmitDebugGlobalHashes)
704 emitTypeGlobalHashes();
705
706 clear();
707}
708
709static void
711 unsigned MaxFixedRecordLength = 0xF00) {
712
713
714
715
718 NullTerminatedString.push_back('\0');
719 OS.emitBytes(NullTerminatedString);
720}
721
722void CodeViewDebug::emitTypeInformation() {
723 if (TypeTable.empty())
724 return;
725
726
728 emitCodeViewMagicVersion();
729
732
733
734 CVMCAdapter CVMCOS(OS, Table);
737
738 std::optional B = Table.getFirst();
739 while (B) {
740
742
744
745 if (E) {
748 }
749
751 }
752}
753
754void CodeViewDebug::emitTypeGlobalHashes() {
755 if (TypeTable.empty())
756 return;
757
758
759
761
769
771 for (const auto &GHR : TypeTable.hashes()) {
773
774
777 CommentOS << formatv("{0:X+} [{1}]", TI.getIndex(), GHR);
779 ++TI;
780 }
781 assert(GHR.Hash.size() == 8);
782 StringRef S(reinterpret_cast<const char *>(GHR.Hash.data()),
783 GHR.Hash.size());
785 }
786}
787
788void CodeViewDebug::emitObjName() {
789 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);
790
793
794 if (PathRef.empty() || PathRef == "-") {
795
796 PathRef = {};
797 } else {
798 PathRef = PathStore;
799 }
800
803
806
807 endSymbolRecord(CompilerEnd);
808}
809
810namespace {
812 int Part[4];
813};
814}
815
816
817
820 int N = 0;
821 for (const char C : Name) {
822 if (isdigit(C)) {
823 V.Part[N] *= 10;
825 V.Part[N] =
826 std::min(V.Part[N], std::numeric_limits<uint16_t>::max());
827 } else if (C == '.') {
828 ++N;
829 if (N >= 4)
830 return V;
831 } else if (N > 0)
832 return V;
833 }
834 return V;
835}
836
837void CodeViewDebug::emitCompilerInformation() {
838 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
840
841
842 Flags = CurrentSourceLanguage;
843
845 Flags |= static_cast<uint32_t>(CompileSym3Flags::PGO);
846 }
850 Arch == ArchType::aarch64) {
851 Flags |= static_cast<uint32_t>(CompileSym3Flags::HotPatch);
852 }
853
856
859
862 const auto *CU = cast(Node);
863
864 StringRef CompilerVersion = CU->getProducer();
867 for (int N : FrontVer.Part) {
869 }
870
871
872
873
874 int Major = 1000 * LLVM_VERSION_MAJOR +
875 10 * LLVM_VERSION_MINOR +
876 LLVM_VERSION_PATCH;
877
878 Major = std::min(Major, std::numeric_limits<uint16_t>::max());
879 Version BackVer = {{ Major, 0, 0, 0 }};
881 for (int N : BackVer.Part)
883
884 OS.AddComment("Null-terminated compiler version string");
886
887 endSymbolRecord(CompilerEnd);
888}
889
894}
895
896void CodeViewDebug::emitBuildInfo() {
897
898
899
900
901
902
903
904
905
906
909 const MDNode *Node = *CUs->operands().begin();
910 const auto *CU = cast(Node);
911 const DIFile *MainSourceFile = CU->getFile();
916
923
926
927
928
929 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
930 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
933 endSymbolRecord(BIEnd);
934 endCVSubsection(BISubsecEnd);
935}
936
937void CodeViewDebug::emitInlineeLinesSubsection() {
938 if (InlinedSubprograms.empty())
939 return;
940
941 OS.AddComment("Inlinee lines subsection");
942 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
943
944
945
946
947
948 OS.AddComment("Inlinee lines signature");
949 OS.emitInt32(unsigned(InlineeLinesSignature::Normal));
950
951 for (const DISubprogram *SP : InlinedSubprograms) {
952 assert(TypeIndices.count({SP, nullptr}));
953 TypeIndex InlineeIdx = TypeIndices[{SP, nullptr}];
954
956 unsigned FileId = maybeRecordFile(SP->getFile());
957 OS.AddComment("Inlined function " + SP->getName() + " starts at " +
960 OS.AddComment("Type index of inlined function");
962 OS.AddComment("Offset into filechecksum table");
964 OS.AddComment("Starting line number");
966 }
967
968 endCVSubsection(InlineEnd);
969}
970
971void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
974 assert(TypeIndices.count({Site.Inlinee, nullptr}));
975 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee, nullptr}];
976
977
978 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
979
986
987 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
988 unsigned StartLineNum = Site.Inlinee->getLine();
989
991 FI.Begin, FI.End);
992
993 endSymbolRecord(InlineEnd);
994
995 emitLocalVariableList(FI, Site.InlinedLocals);
996
997
998 for (const DILocation *ChildSite : Site.ChildSites) {
999 auto I = FI.InlineSites.find(ChildSite);
1000 assert(I != FI.InlineSites.end() &&
1001 "child site not in function inline site map");
1002 emitInlinedCallSite(FI, ChildSite, I->second);
1003 }
1004
1005
1006 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1007}
1008
1009void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) {
1010
1011
1012
1014 GVSym ? dyn_cast(&GVSym->getSection()) : nullptr;
1016
1020
1022
1023
1024
1025 if (ComdatDebugSections.insert(DebugSec).second)
1026 emitCodeViewMagicVersion();
1027}
1028
1029
1030
1031void CodeViewDebug::emitDebugInfoForThunk(const Function *GV,
1032 FunctionInfo &FI,
1034 std::string FuncName =
1036 const ThunkOrdinal ordinal = ThunkOrdinal::Standard;
1037
1038 OS.AddComment("Symbol subsection for " + Twine(FuncName));
1039 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1040
1041
1042 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1049 OS.AddComment("Thunk section relative address");
1051 OS.AddComment("Thunk section index");
1056 OS.emitInt8(unsigned(ordinal));
1059
1060 endSymbolRecord(ThunkRecordEnd);
1061
1062
1063
1064
1065
1066 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1067
1068 endCVSubsection(SymbolsEnd);
1069}
1070
1071void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
1072 FunctionInfo &FI) {
1073
1074
1077
1078
1079 switchToDebugSectionForSymbol(Fn);
1080
1081 std::string FuncName;
1084 setCurrentSubprogram(SP);
1085
1086 if (SP->isThunk()) {
1087 emitDebugInfoForThunk(GV, FI, Fn);
1088 return;
1089 }
1090
1091
1092
1094 FuncName = getFullyQualifiedName(SP->getScope(), SP->getName());
1095
1096
1097 if (FuncName.empty())
1099
1100
1103
1104
1105 OS.AddComment("Symbol subsection for " + Twine(FuncName));
1106 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1107 {
1109 : SymbolKind::S_GPROC32_ID;
1110 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1111
1112
1119
1120
1123 OS.AddComment("Offset after prologue");
1125 OS.AddComment("Offset before epilogue");
1127 OS.AddComment("Function type index");
1129 OS.AddComment("Function section relative address");
1131 OS.AddComment("Function section index");
1134 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;
1135 if (FI.HasFramePointer)
1136 ProcFlags |= ProcSymFlags::HasFP;
1138 ProcFlags |= ProcSymFlags::IsNoReturn;
1140 ProcFlags |= ProcSymFlags::IsNoInline;
1142
1144
1146 endSymbolRecord(ProcRecordEnd);
1147
1148 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1149
1151 OS.emitInt32(FI.FrameSize - FI.CSRSize);
1156 OS.AddComment("Bytes of callee saved registers");
1158 OS.AddComment("Exception handler offset");
1160 OS.AddComment("Exception handler section");
1162 OS.AddComment("Flags (defines frame register)");
1164 endSymbolRecord(FrameProcEnd);
1165
1166 emitInlinees(FI.Inlinees);
1167 emitLocalVariableList(FI, FI.Locals);
1168 emitGlobalVariableList(FI.Globals);
1169 emitLexicalBlockList(FI.ChildBlocks, FI);
1170
1171
1172
1173
1174 for (const DILocation *InlinedAt : FI.ChildSites) {
1175 auto I = FI.InlineSites.find(InlinedAt);
1176 assert(I != FI.InlineSites.end() &&
1177 "child site not in function inline site map");
1178 emitInlinedCallSite(FI, InlinedAt, I->second);
1179 }
1180
1181 for (auto Annot : FI.Annotations) {
1183 MDTuple *Strs = cast(Annot.second);
1184 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1186
1190
1191
1192 StringRef Str = cast(MD)->getString();
1193 assert(Str.data()[Str.size()] == '\0' && "non-nullterminated MDString");
1195 }
1196 endSymbolRecord(AnnotEnd);
1197 }
1198
1199 for (auto HeapAllocSite : FI.HeapAllocSites) {
1200 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1201 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1202 const DIType *DITy = std::get<2>(HeapAllocSite);
1203 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1206 OS.AddComment("Call site section index");
1208 OS.AddComment("Call instruction length");
1211 OS.emitInt32(getCompleteTypeIndex(DITy).getIndex());
1212 endSymbolRecord(HeapAllocEnd);
1213 }
1214
1215 if (SP != nullptr)
1216 emitDebugInfoForUDTs(LocalUDTs);
1217
1218 emitDebugInfoForJumpTables(FI);
1219
1220
1221 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1222 }
1223 endCVSubsection(SymbolsEnd);
1224
1225
1227}
1228
1230CodeViewDebug::createDefRangeMem(uint16_t CVRegister, int Offset) {
1231 LocalVarDef DR;
1233 DR.DataOffset = Offset;
1234 assert(DR.DataOffset == Offset && "truncation");
1235 DR.IsSubfield = 0;
1236 DR.StructOffset = 0;
1237 DR.CVRegister = CVRegister;
1238 return DR;
1239}
1240
1241void CodeViewDebug::collectVariableInfoFromMFTable(
1247
1250 if (.Var)
1251 continue;
1252 assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&
1253 "Expected inlined-at fields to agree");
1254
1255 Processed.insert(InlinedEntity(VI.Var, VI.Loc->getInlinedAt()));
1257
1258
1259 if (!Scope)
1260 continue;
1261
1262
1263
1264 int64_t ExprOffset = 0;
1265 bool Deref = false;
1266 if (VI.Expr) {
1267
1268 if (VI.Expr->getNumElements() == 1 &&
1269 VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)
1270 Deref = true;
1271 else if (.Expr->extractIfOffset(ExprOffset))
1272 continue;
1273 }
1274
1275
1279 uint16_t CVReg = TRI->getCodeViewRegNum(FrameReg);
1280
1282 "Frame offsets with a scalable component are not supported");
1283
1284
1285 LocalVarDef DefRange =
1286 createDefRangeMem(CVReg, FrameOffset.getFixed() + ExprOffset);
1287
1288 LocalVariable Var;
1289 Var.DIVar = VI.Var;
1290
1295 Var.DefRanges[DefRange].emplace_back(Begin, End);
1296 }
1297
1298 if (Deref)
1299 Var.UseReferenceType = true;
1300
1301 recordLocalVariable(std::move(Var), Scope);
1302 }
1303}
1304
1307}
1308
1311}
1312
1313void CodeViewDebug::calculateRanges(
1316
1317
1318 for (auto I = Entries.begin(), E = Entries.end(); I != E; ++I) {
1320 if (.isDbgValue())
1321 continue;
1324
1325
1326 std::optional Location =
1328 if (!Location)
1329 {
1330
1331
1332
1333
1334
1336 if (Op.isImm())
1337 Var.ConstantValue = APSInt(APInt(64, Op.getImm()), false);
1338 continue;
1339 }
1340
1341
1342
1343
1344
1345
1346
1347
1348 if (Var.UseReferenceType) {
1349
1351 Location->LoadChain.pop_back();
1352 else
1353 continue;
1355
1356
1357 Var.UseReferenceType = true;
1358 Var.DefRanges.clear();
1359 calculateRanges(Var, Entries);
1360 return;
1361 }
1362
1363
1364 if (Location->Register == 0 || Location->LoadChain.size() > 1)
1365 continue;
1366
1367
1368
1370 if (Location->FragmentInfo->OffsetInBits % 8)
1371 continue;
1372
1373 LocalVarDef DR;
1374 DR.CVRegister = TRI->getCodeViewRegNum(Location->Register);
1375 DR.InMemory = ->LoadChain.empty();
1376 DR.DataOffset =
1377 ->LoadChain.empty() ? Location->LoadChain.back() : 0;
1378 if (Location->FragmentInfo) {
1379 DR.IsSubfield = true;
1380 DR.StructOffset = Location->FragmentInfo->OffsetInBits / 8;
1381 } else {
1382 DR.IsSubfield = false;
1383 DR.StructOffset = 0;
1384 }
1385
1386
1390 auto &EndingEntry = Entries[Entry.getEndIndex()];
1391 End = EndingEntry.isDbgValue()
1394 } else
1396
1397
1398
1400 Var.DefRanges[DR];
1401 if (.empty() && R.back().second == Begin)
1403 else
1404 R.emplace_back(Begin, End);
1405
1406
1407 }
1408}
1409
1410void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
1412
1413 collectVariableInfoFromMFTable(Processed);
1414
1416 InlinedEntity IV = I.first;
1418 continue;
1421
1422
1423 const auto &Entries = I.second;
1424
1426 if (InlinedAt)
1428 else
1430
1431 if (!Scope)
1432 continue;
1433
1434 LocalVariable Var;
1435 Var.DIVar = DIVar;
1436
1437 calculateRanges(Var, Entries);
1438 recordLocalVariable(std::move(Var), Scope);
1439 }
1440}
1441
1447 auto Insertion = FnDebugInfo.insert({&GV, std::make_unique()});
1448 assert(Insertion.second && "function already has info");
1449 CurFn = Insertion.first->second.get();
1450 CurFn->FuncId = NextFuncId++;
1452
1453
1454
1455
1459 CurFn->HasStackRealignment = TRI->hasStackRealignment(*MF);
1460
1461
1462
1463 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::None;
1464 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::None;
1465 if (CurFn->FrameSize > 0) {
1467 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1468 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr;
1469 } else {
1470 CurFn->HasFramePointer = true;
1471
1472 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr;
1473 if (CurFn->HasStackRealignment) {
1474
1475 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1476 } else {
1477
1478
1479 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::FramePtr;
1480 }
1481 }
1482 }
1483
1484
1487 FPO |= FrameProcedureOptions::HasAlloca;
1489 FPO |= FrameProcedureOptions::HasSetJmp;
1490
1492 FPO |= FrameProcedureOptions::HasInlineAssembly;
1496 FPO |= FrameProcedureOptions::HasStructuredExceptionHandling;
1497 else
1498 FPO |= FrameProcedureOptions::HasExceptionHandling;
1499 }
1501 FPO |= FrameProcedureOptions::MarkedInline;
1503 FPO |= FrameProcedureOptions::Naked;
1505 FPO |= FrameProcedureOptions::SecurityChecks;
1506 if (GV.hasFnAttribute(Attribute::StackProtectStrong) ||
1508 FPO |= FrameProcedureOptions::StrictSecurityChecks;
1509 }
1511
1512 FPO |= FrameProcedureOptions::SafeBuffers;
1513 }
1518 FPO |= FrameProcedureOptions::OptimizedForSpeed;
1520 FPO |= FrameProcedureOptions::ValidProfileCounts;
1521 FPO |= FrameProcedureOptions::ProfileGuidedOptimization;
1522 }
1523
1524 CurFn->FrameProcOpts = FPO;
1525
1527
1528
1529
1530
1531
1533 bool EmptyPrologue = true;
1534 for (const auto &MBB : *MF) {
1535 for (const auto &MI : MBB) {
1537 MI.getDebugLoc()) {
1539 break;
1540 } else if (.isMetaInstruction()) {
1541 EmptyPrologue = false;
1542 }
1543 }
1544 }
1545
1546
1549 maybeRecordLocation(FnStartDL, MF);
1550 }
1551
1552
1553 for (const auto &MBB : *MF) {
1554 for (const auto &MI : MBB) {
1555 if (MI.getHeapAllocMarker()) {
1558 }
1559 }
1560 }
1561
1562
1565 discoverJumpTableBranches(MF, isThumb);
1566}
1567
1569 if ()
1570 return false;
1571
1572
1573 if (T->getTag() == dwarf::DW_TAG_typedef) {
1574 if (DIScope *Scope = T->getScope()) {
1575 switch (Scope->getTag()) {
1576 case dwarf::DW_TAG_structure_type:
1577 case dwarf::DW_TAG_class_type:
1578 case dwarf::DW_TAG_union_type:
1579 return false;
1580 default:
1581
1582 ;
1583 }
1584 }
1585 }
1586
1587 while (true) {
1588 if ( || T->isForwardDecl())
1589 return false;
1590
1591 const DIDerivedType *DT = dyn_cast(T);
1592 if (!DT)
1593 return true;
1594 T = DT->getBaseType();
1595 }
1596 return true;
1597}
1598
1599void CodeViewDebug::addToUDTs(const DIType *Ty) {
1600
1602 return;
1604 return;
1605
1608 collectParentScopeNames(Ty->getScope(), ParentScopeNames);
1609
1610 std::string FullyQualifiedName =
1612
1613 if (ClosestSubprogram == nullptr) {
1614 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1615 } else if (ClosestSubprogram == CurrentSubprogram) {
1616 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1617 }
1618
1619
1620
1621
1622
1623
1624
1625}
1626
1628
1629 switch (Ty->getTag()) {
1630 case dwarf::DW_TAG_array_type:
1631 return lowerTypeArray(cast(Ty));
1632 case dwarf::DW_TAG_typedef:
1633 return lowerTypeAlias(cast(Ty));
1634 case dwarf::DW_TAG_base_type:
1635 return lowerTypeBasic(cast(Ty));
1636 case dwarf::DW_TAG_pointer_type:
1637 if (cast(Ty)->getName() == "__vtbl_ptr_type")
1638 return lowerTypeVFTableShape(cast(Ty));
1639 [[fallthrough]];
1640 case dwarf::DW_TAG_reference_type:
1641 case dwarf::DW_TAG_rvalue_reference_type:
1642 return lowerTypePointer(cast(Ty));
1643 case dwarf::DW_TAG_ptr_to_member_type:
1644 return lowerTypeMemberPointer(cast(Ty));
1645 case dwarf::DW_TAG_restrict_type:
1646 case dwarf::DW_TAG_const_type:
1647 case dwarf::DW_TAG_volatile_type:
1648
1649 return lowerTypeModifier(cast(Ty));
1650 case dwarf::DW_TAG_subroutine_type:
1651 if (ClassTy) {
1652
1653
1654 return lowerTypeMemberFunction(cast(Ty), ClassTy,
1655 0,
1656 false);
1657 }
1658 return lowerTypeFunction(cast(Ty));
1659 case dwarf::DW_TAG_enumeration_type:
1660 return lowerTypeEnum(cast(Ty));
1661 case dwarf::DW_TAG_class_type:
1662 case dwarf::DW_TAG_structure_type:
1663 return lowerTypeClass(cast(Ty));
1664 case dwarf::DW_TAG_union_type:
1665 return lowerTypeUnion(cast(Ty));
1666 case dwarf::DW_TAG_string_type:
1667 return lowerTypeString(cast(Ty));
1668 case dwarf::DW_TAG_unspecified_type:
1669 if (Ty->getName() == "decltype(nullptr)")
1672 default:
1673
1675 }
1676}
1677
1679 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1681
1682 addToUDTs(Ty);
1683
1684 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) &&
1685 TypeName == "HRESULT")
1686 return TypeIndex(SimpleTypeKind::HResult);
1687 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::UInt16Short) &&
1688 TypeName == "wchar_t")
1689 return TypeIndex(SimpleTypeKind::WideCharacter);
1690
1691 return UnderlyingTypeIndex;
1692}
1693
1696 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1697
1698 TypeIndex IndexType = getPointerSizeInBytes() == 8
1699 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1701
1703
1704
1706 for (int i = Elements.size() - 1; i >= 0; --i) {
1708 assert(Element->getTag() == dwarf::DW_TAG_subrange_type);
1709
1711 int64_t Count = -1;
1712
1713
1714
1715
1716
1717 if (auto *CI = dyn_cast_if_present<ConstantInt *>(Subrange->getCount()))
1718 Count = CI->getSExtValue();
1719 else if (auto *UI = dyn_cast_if_present<ConstantInt *>(
1720 Subrange->getUpperBound())) {
1721
1723 auto *LI = dyn_cast_if_present<ConstantInt *>(Subrange->getLowerBound());
1724 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1725 Count = UI->getSExtValue() - Lowerbound + 1;
1726 }
1727
1728
1729
1730
1731
1732 if (Count == -1)
1733 Count = 0;
1734
1735
1736 ElementSize *= Count;
1737
1738
1739
1741 (i == 0 && ElementSize == 0) ? Ty->getSizeInBits() / 8 : ElementSize;
1742
1744 ArrayRecord AR(ElementTypeIndex, IndexType, ArraySize, Name);
1746 }
1747
1748 return ElementTypeIndex;
1749}
1750
1751
1752
1753
1754
1755
1760
1761 TypeIndex IndexType = getPointerSizeInBytes() == 8
1762 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1764
1765
1767
1769}
1770
1775
1778
1780 switch (Kind) {
1781 case dwarf::DW_ATE_address:
1782
1783 break;
1784 case dwarf::DW_ATE_boolean:
1785 switch (ByteSize) {
1786 case 1: STK = SimpleTypeKind::Boolean8; break;
1787 case 2: STK = SimpleTypeKind::Boolean16; break;
1788 case 4: STK = SimpleTypeKind::Boolean32; break;
1789 case 8: STK = SimpleTypeKind::Boolean64; break;
1790 case 16: STK = SimpleTypeKind::Boolean128; break;
1791 }
1792 break;
1793 case dwarf::DW_ATE_complex_float:
1794
1795
1796 switch (ByteSize) {
1797 case 4: STK = SimpleTypeKind::Complex16; break;
1798 case 8: STK = SimpleTypeKind::Complex32; break;
1799 case 16: STK = SimpleTypeKind::Complex64; break;
1800 case 20: STK = SimpleTypeKind::Complex80; break;
1801 case 32: STK = SimpleTypeKind::Complex128; break;
1802 }
1803 break;
1804 case dwarf::DW_ATE_float:
1805 switch (ByteSize) {
1806 case 2: STK = SimpleTypeKind::Float16; break;
1807 case 4: STK = SimpleTypeKind::Float32; break;
1808 case 6: STK = SimpleTypeKind::Float48; break;
1809 case 8: STK = SimpleTypeKind::Float64; break;
1810 case 10: STK = SimpleTypeKind::Float80; break;
1811 case 16: STK = SimpleTypeKind::Float128; break;
1812 }
1813 break;
1814 case dwarf::DW_ATE_signed:
1815 switch (ByteSize) {
1816 case 1: STK = SimpleTypeKind::SignedCharacter; break;
1817 case 2: STK = SimpleTypeKind::Int16Short; break;
1818 case 4: STK = SimpleTypeKind::Int32; break;
1819 case 8: STK = SimpleTypeKind::Int64Quad; break;
1820 case 16: STK = SimpleTypeKind::Int128Oct; break;
1821 }
1822 break;
1823 case dwarf::DW_ATE_unsigned:
1824 switch (ByteSize) {
1825 case 1: STK = SimpleTypeKind::UnsignedCharacter; break;
1826 case 2: STK = SimpleTypeKind::UInt16Short; break;
1827 case 4: STK = SimpleTypeKind::UInt32; break;
1828 case 8: STK = SimpleTypeKind::UInt64Quad; break;
1829 case 16: STK = SimpleTypeKind::UInt128Oct; break;
1830 }
1831 break;
1832 case dwarf::DW_ATE_UTF:
1833 switch (ByteSize) {
1834 case 1: STK = SimpleTypeKind::Character8; break;
1835 case 2: STK = SimpleTypeKind::Character16; break;
1836 case 4: STK = SimpleTypeKind::Character32; break;
1837 }
1838 break;
1839 case dwarf::DW_ATE_signed_char:
1840 if (ByteSize == 1)
1841 STK = SimpleTypeKind::SignedCharacter;
1842 break;
1843 case dwarf::DW_ATE_unsigned_char:
1844 if (ByteSize == 1)
1845 STK = SimpleTypeKind::UnsignedCharacter;
1846 break;
1847 default:
1848 break;
1849 }
1850
1851
1852
1853
1854
1855 if (STK == SimpleTypeKind::Int32 &&
1856 (Ty->getName() == "long int" || Ty->getName() == "long"))
1857 STK = SimpleTypeKind::Int32Long;
1858 if (STK == SimpleTypeKind::UInt32 && (Ty->getName() == "long unsigned int" ||
1859 Ty->getName() == "unsigned long"))
1860 STK = SimpleTypeKind::UInt32Long;
1861 if (STK == SimpleTypeKind::UInt16Short &&
1862 (Ty->getName() == "wchar_t" || Ty->getName() == "__wchar_t"))
1863 STK = SimpleTypeKind::WideCharacter;
1864 if ((STK == SimpleTypeKind::SignedCharacter ||
1865 STK == SimpleTypeKind::UnsignedCharacter) &&
1866 Ty->getName() == "char")
1867 STK = SimpleTypeKind::NarrowCharacter;
1868
1870}
1871
1874 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1875
1876
1877
1878 if (PointeeTI.isSimple() && PO == PointerOptions::None &&
1879 PointeeTI.getSimpleMode() == SimpleTypeMode::Direct &&
1880 Ty->getTag() == dwarf::DW_TAG_pointer_type) {
1882 ? SimpleTypeMode::NearPointer64
1883 : SimpleTypeMode::NearPointer32;
1885 }
1886
1888 Ty->getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1890 switch (Ty->getTag()) {
1892 case dwarf::DW_TAG_pointer_type:
1893 PM = PointerMode::Pointer;
1894 break;
1895 case dwarf::DW_TAG_reference_type:
1896 PM = PointerMode::LValueReference;
1897 break;
1898 case dwarf::DW_TAG_rvalue_reference_type:
1899 PM = PointerMode::RValueReference;
1900 break;
1901 }
1902
1904 PO |= PointerOptions::Const;
1905
1908}
1909
1912
1913
1914
1915 if (IsPMF) {
1917 case 0:
1918 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1919 : PointerToMemberRepresentation::GeneralFunction;
1920 case DINode::FlagSingleInheritance:
1921 return PointerToMemberRepresentation::SingleInheritanceFunction;
1922 case DINode::FlagMultipleInheritance:
1923 return PointerToMemberRepresentation::MultipleInheritanceFunction;
1924 case DINode::FlagVirtualInheritance:
1925 return PointerToMemberRepresentation::VirtualInheritanceFunction;
1926 }
1927 } else {
1929 case 0:
1930 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1931 : PointerToMemberRepresentation::GeneralData;
1932 case DINode::FlagSingleInheritance:
1933 return PointerToMemberRepresentation::SingleInheritanceData;
1934 case DINode::FlagMultipleInheritance:
1935 return PointerToMemberRepresentation::MultipleInheritanceData;
1936 case DINode::FlagVirtualInheritance:
1937 return PointerToMemberRepresentation::VirtualInheritanceData;
1938 }
1939 }
1941}
1942
1945 assert(Ty->getTag() == dwarf::DW_TAG_ptr_to_member_type);
1946 bool IsPMF = isa(Ty->getBaseType());
1949 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->getClassType() : nullptr);
1950 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
1951 : PointerKind::Near32;
1952 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
1953 : PointerMode::PointerToDataMember;
1954
1959 PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);
1961}
1962
1963
1964
1966 switch (DwarfCC) {
1967 case dwarf::DW_CC_normal: return CallingConvention::NearC;
1968 case dwarf::DW_CC_BORLAND_msfastcall: return CallingConvention::NearFast;
1969 case dwarf::DW_CC_BORLAND_thiscall: return CallingConvention::ThisCall;
1970 case dwarf::DW_CC_BORLAND_stdcall: return CallingConvention::NearStdCall;
1971 case dwarf::DW_CC_BORLAND_pascal: return CallingConvention::NearPascal;
1972 case dwarf::DW_CC_LLVM_vectorcall: return CallingConvention::NearVector;
1973 }
1974 return CallingConvention::NearC;
1975}
1976
1982 while (IsModifier && BaseTy) {
1983
1984 switch (BaseTy->getTag()) {
1985 case dwarf::DW_TAG_const_type:
1986 Mods |= ModifierOptions::Const;
1987 PO |= PointerOptions::Const;
1988 break;
1989 case dwarf::DW_TAG_volatile_type:
1990 Mods |= ModifierOptions::Volatile;
1991 PO |= PointerOptions::Volatile;
1992 break;
1993 case dwarf::DW_TAG_restrict_type:
1994
1995
1996 PO |= PointerOptions::Restrict;
1997 break;
1998 default:
2000 break;
2001 }
2002 if (IsModifier)
2003 BaseTy = cast(BaseTy)->getBaseType();
2004 }
2005
2006
2007
2008
2009
2011 switch (BaseTy->getTag()) {
2012 case dwarf::DW_TAG_pointer_type:
2013 case dwarf::DW_TAG_reference_type:
2014 case dwarf::DW_TAG_rvalue_reference_type:
2015 return lowerTypePointer(cast(BaseTy), PO);
2016 case dwarf::DW_TAG_ptr_to_member_type:
2017 return lowerTypeMemberPointer(cast(BaseTy), PO);
2018 default:
2019 break;
2020 }
2021 }
2022
2024
2025
2026
2027 if (Mods == ModifierOptions::None)
2028 return ModifiedTI;
2029
2032}
2033
2037 ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgType));
2038
2039
2040 if (ReturnAndArgTypeIndices.size() > 1 &&
2043 }
2046 if (!ReturnAndArgTypeIndices.empty()) {
2047 auto ReturnAndArgTypesRef = ArrayRef(ReturnAndArgTypeIndices);
2048 ReturnTypeIndex = ReturnAndArgTypesRef.front();
2049 ArgTypeIndices = ReturnAndArgTypesRef.drop_front();
2050 }
2051
2052 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2054
2056
2059 ArgListIndex);
2061}
2062
2064 const DIType *ClassTy,
2065 int ThisAdjustment,
2066 bool IsStaticMethod,
2068
2069 TypeIndex ClassType = getTypeIndex(ClassTy);
2070
2072
2073 unsigned Index = 0;
2076 if (ReturnAndArgs.size() > Index) {
2077 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
2078 }
2079
2080
2081
2082
2084 if (!IsStaticMethod && ReturnAndArgs.size() > Index) {
2086 dyn_cast_or_null(ReturnAndArgs[Index])) {
2087 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2088 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2090 }
2091 }
2092 }
2093
2094 while (Index < ReturnAndArgs.size())
2095 ArgTypeIndices.push_back(getTypeIndex(ReturnAndArgs[Index++]));
2096
2097
2100
2101 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2103
2105
2107 ArgTypeIndices.size(), ArgListIndex, ThisAdjustment);
2109}
2110
2112 unsigned VSlotCount =
2115
2118}
2119
2122 case DINode::FlagPrivate: return MemberAccess::Private;
2123 case DINode::FlagPublic: return MemberAccess::Public;
2124 case DINode::FlagProtected: return MemberAccess::Protected;
2125 case 0:
2126
2127 return RecordTag == dwarf::DW_TAG_class_type ? MemberAccess::Private
2128 : MemberAccess::Public;
2129 }
2131}
2132
2134 if (SP->isArtificial())
2135 return MethodOptions::CompilerGenerated;
2136
2137
2138
2139 return MethodOptions::None;
2140}
2141
2143 bool Introduced) {
2144 if (SP->getFlags() & DINode::FlagStaticMember)
2145 return MethodKind::Static;
2146
2147 switch (SP->getVirtuality()) {
2148 case dwarf::DW_VIRTUALITY_none:
2149 break;
2150 case dwarf::DW_VIRTUALITY_virtual:
2151 return Introduced ? MethodKind::IntroducingVirtual : MethodKind::Virtual;
2152 case dwarf::DW_VIRTUALITY_pure_virtual:
2153 return Introduced ? MethodKind::PureIntroducingVirtual
2154 : MethodKind::PureVirtual;
2155 default:
2157 }
2158
2159 return MethodKind::Vanilla;
2160}
2161
2163 switch (Ty->getTag()) {
2164 case dwarf::DW_TAG_class_type:
2165 return TypeRecordKind::Class;
2166 case dwarf::DW_TAG_structure_type:
2167 return TypeRecordKind::Struct;
2168 default:
2170 }
2171}
2172
2173
2174
2177
2178
2179
2180
2182 CO |= ClassOptions::HasUniqueName;
2183
2184
2185
2186
2188 if (ImmediateScope && isa(ImmediateScope))
2189 CO |= ClassOptions::Nested;
2190
2191
2192
2193
2194
2195 if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) {
2196 if (ImmediateScope && isa(ImmediateScope))
2197 CO |= ClassOptions::Scoped;
2198 } else {
2199 for (const DIScope *Scope = ImmediateScope; Scope != nullptr;
2200 Scope = Scope->getScope()) {
2201 if (isa(Scope)) {
2202 CO |= ClassOptions::Scoped;
2203 break;
2204 }
2205 }
2206 }
2207
2208 return CO;
2209}
2210
2211void CodeViewDebug::addUDTSrcLine(const DIType *Ty, TypeIndex TI) {
2212 switch (Ty->getTag()) {
2213 case dwarf::DW_TAG_class_type:
2214 case dwarf::DW_TAG_structure_type:
2215 case dwarf::DW_TAG_union_type:
2216 case dwarf::DW_TAG_enumeration_type:
2217 break;
2218 default:
2219 return;
2220 }
2221
2222 if (const auto *File = Ty->getFile()) {
2225
2228 }
2229}
2230
2234 unsigned EnumeratorCount = 0;
2235
2237 CO |= ClassOptions::ForwardReference;
2238 } else {
2240 ContinuationBuilder.begin(ContinuationRecordKind::FieldList);
2242
2243
2244 if (auto *Enumerator = dyn_cast_or_null(Element)) {
2245
2250 EnumeratorCount++;
2251 }
2252 }
2253 FTI = TypeTable.insertRecord(ContinuationBuilder);
2254 }
2255
2256 std::string FullName = getFullyQualifiedName(Ty);
2257
2261
2262 addUDTSrcLine(Ty, EnumTI);
2263
2264 return EnumTI;
2265}
2266
2267
2268
2269
2270
2275 };
2276
2278
2280
2282
2283
2285
2286
2288
2290
2292
2294};
2295
2296void CodeViewDebug::clear() {
2297 assert(CurFn == nullptr);
2298 FileIdMap.clear();
2299 FnDebugInfo.clear();
2300 FileToFilepathMap.clear();
2301 LocalUDTs.clear();
2302 GlobalUDTs.clear();
2303 TypeIndices.clear();
2304 CompleteTypeIndices.clear();
2305 ScopeGlobals.clear();
2306 CVGlobalVariableOffsets.clear();
2307}
2308
2309void CodeViewDebug::collectMemberInfo(ClassInfo &Info,
2312 Info.Members.push_back({DDTy, 0});
2313
2314
2315 if ((DDTy->getFlags() & DINode::FlagStaticMember) ==
2316 DINode::FlagStaticMember) {
2319 StaticConstMembers.push_back(DDTy);
2320 }
2321
2322 return;
2323 }
2324
2325
2326
2327
2328
2331 const DIType *Ty = DDTy->getBaseType();
2332 bool FullyResolved = false;
2333 while (!FullyResolved) {
2334 switch (Ty->getTag()) {
2335 case dwarf::DW_TAG_const_type:
2336 case dwarf::DW_TAG_volatile_type:
2337
2338
2339 Ty = cast(Ty)->getBaseType();
2340 break;
2341 default:
2342 FullyResolved = true;
2343 break;
2344 }
2345 }
2346
2347 const DICompositeType *DCTy = dyn_cast(Ty);
2348 if (!DCTy)
2349 return;
2350
2351 ClassInfo NestedInfo = collectClassInfo(DCTy);
2353 Info.Members.push_back(
2355}
2356
2359
2361 for (auto *Element : Elements) {
2362
2363
2364 if (!Element)
2365 continue;
2366 if (auto *SP = dyn_cast(Element)) {
2367 Info.Methods[SP->getRawName()].push_back(SP);
2368 } else if (auto *DDTy = dyn_cast(Element)) {
2369 if (DDTy->getTag() == dwarf::DW_TAG_member) {
2370 collectMemberInfo(Info, DDTy);
2371 } else if (DDTy->getTag() == dwarf::DW_TAG_inheritance) {
2372 Info.Inheritance.push_back(DDTy);
2373 } else if (DDTy->getTag() == dwarf::DW_TAG_pointer_type &&
2374 DDTy->getName() == "__vtbl_ptr_type") {
2375 Info.VShapeTI = getTypeIndex(DDTy);
2376 } else if (DDTy->getTag() == dwarf::DW_TAG_typedef) {
2377 Info.NestedTypes.push_back(DDTy);
2378 } else if (DDTy->getTag() == dwarf::DW_TAG_friend) {
2379
2380
2381 }
2382 } else if (auto *Composite = dyn_cast(Element)) {
2383 Info.NestedTypes.push_back(Composite);
2384 }
2385
2386 }
2387 return Info;
2388}
2389
2391
2392
2395}
2396
2398
2399
2400
2401
2403
2404
2405
2406 auto I = CompleteTypeIndices.find(Ty);
2407 if (I != CompleteTypeIndices.end() && I->second == TypeIndex())
2408 report_fatal_error("cannot debug circular reference to unnamed type");
2409 return getCompleteTypeIndex(Ty);
2410 }
2411
2412
2413
2417 std::string FullName = getFullyQualifiedName(Ty);
2422 DeferredCompleteTypes.push_back(Ty);
2423 return FwdDeclTI;
2424}
2425
2427
2432 unsigned FieldCount;
2435 lowerRecordFieldList(Ty);
2436
2438 CO |= ClassOptions::ContainsNestedClass;
2439
2440
2441
2442
2443
2444
2446 CO |= ClassOptions::HasConstructorOrDestructor;
2447
2448 std::string FullName = getFullyQualifiedName(Ty);
2449
2451
2455
2456 addUDTSrcLine(Ty, ClassTI);
2457
2458 addToUDTs(Ty);
2459
2460 return ClassTI;
2461}
2462
2464
2466 return getCompleteTypeIndex(Ty);
2467
2470 std::string FullName = getFullyQualifiedName(Ty);
2474 DeferredCompleteTypes.push_back(Ty);
2475 return FwdDeclTI;
2476}
2477
2481 unsigned FieldCount;
2484 lowerRecordFieldList(Ty);
2485
2487 CO |= ClassOptions::ContainsNestedClass;
2488
2490 std::string FullName = getFullyQualifiedName(Ty);
2491
2492 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2495
2496 addUDTSrcLine(Ty, UnionTI);
2497
2498 addToUDTs(Ty);
2499
2500 return UnionTI;
2501}
2502
2503std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2504CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
2505
2506
2507
2508
2509 unsigned MemberCount = 0;
2512 ContinuationBuilder.begin(ContinuationRecordKind::FieldList);
2513
2514
2516 if (I->getFlags() & DINode::FlagVirtual) {
2517
2518 unsigned VBPtrOffset = I->getVBPtrOffset();
2519
2520 unsigned VBTableIndex = I->getOffsetInBits() / 4;
2521 auto RecordKind = (I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2522 ? TypeRecordKind::IndirectVirtualBaseClass
2523 : TypeRecordKind::VirtualBaseClass;
2526 getTypeIndex(I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2527 VBTableIndex);
2528
2530 MemberCount++;
2531 } else {
2532 assert(I->getOffsetInBits() % 8 == 0 &&
2533 "bases must be on byte boundaries");
2535 getTypeIndex(I->getBaseType()),
2536 I->getOffsetInBits() / 8);
2538 MemberCount++;
2539 }
2540 }
2541
2542
2545 TypeIndex MemberBaseType = getTypeIndex(Member->getBaseType());
2549
2550 if (Member->isStaticMember()) {
2553 MemberCount++;
2554 continue;
2555 }
2556
2557
2558 if ((Member->getFlags() & DINode::FlagArtificial) &&
2559 Member->getName().starts_with("_vptr$")) {
2562 MemberCount++;
2563 continue;
2564 }
2565
2566
2567 uint64_t MemberOffsetInBits =
2569 if (Member->isBitField()) {
2570 uint64_t StartBitOffset = MemberOffsetInBits;
2571 if (const auto *CI =
2572 dyn_cast_or_null(Member->getStorageOffsetInBits())) {
2573 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.BaseOffset;
2574 }
2575 StartBitOffset -= MemberOffsetInBits;
2577 StartBitOffset);
2579 }
2580 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2582 MemberName);
2584 MemberCount++;
2585 }
2586
2587
2588 for (auto &MethodItr : Info.Methods) {
2590
2591 std::vector Methods;
2592 for (const DISubprogram *SP : MethodItr.second) {
2593 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2594 bool Introduced = SP->getFlags() & DINode::FlagIntroducedVirtual;
2595
2596 unsigned VFTableOffset = -1;
2597 if (Introduced)
2598 VFTableOffset = SP->getVirtualIndex() * getPointerSizeInBytes();
2599
2604 MemberCount++;
2605 }
2606 assert(!Methods.empty() && "Empty methods map entry");
2607 if (Methods.size() == 1)
2609 else {
2610
2611
2614
2617 }
2618 }
2619
2620
2624 MemberCount++;
2625 }
2626
2628 return std::make_tuple(FieldTI, Info.VShapeTI, MemberCount,
2629 .NestedTypes.empty());
2630}
2631
2632TypeIndex CodeViewDebug::getVBPTypeIndex() {
2634
2637
2638 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2639 : PointerKind::Near32;
2642 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2644 }
2645
2646 return VBPType;
2647}
2648
2650
2651 if (!Ty)
2653
2654
2655
2656
2657 auto I = TypeIndices.find({Ty, ClassTy});
2658 if (I != TypeIndices.end())
2659 return I->second;
2660
2661 TypeLoweringScope S(*this);
2662 TypeIndex TI = lowerType(Ty, ClassTy);
2663 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2664}
2665
2667CodeViewDebug::getTypeIndexForThisPtr(const DIDerivedType *PtrTy,
2669 assert(PtrTy->getTag() == dwarf::DW_TAG_pointer_type &&
2670 "this type must be a pointer type");
2671
2673 if (SubroutineTy->getFlags() & DINode::DIFlags::FlagLValueReference)
2674 Options = PointerOptions::LValueRefThisPointer;
2675 else if (SubroutineTy->getFlags() & DINode::DIFlags::FlagRValueReference)
2676 Options = PointerOptions::RValueRefThisPointer;
2677
2678
2679
2680
2681
2682
2683 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2684 if (I != TypeIndices.end())
2685 return I->second;
2686
2687 TypeLoweringScope S(*this);
2689 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2690}
2691
2692TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(const DIType *Ty) {
2694 getPointerSizeInBytes() == 8 ? PointerKind::Near64
2695 : PointerKind::Near32,
2696 PointerMode::LValueReference, PointerOptions::None,
2699}
2700
2701TypeIndex CodeViewDebug::getCompleteTypeIndex(const DIType *Ty) {
2702
2703 if (!Ty)
2705
2706
2707
2708
2709 if (Ty->getTag() == dwarf::DW_TAG_typedef)
2710 (void)getTypeIndex(Ty);
2711 while (Ty->getTag() == dwarf::DW_TAG_typedef)
2712 Ty = cast(Ty)->getBaseType();
2713
2714
2715
2716 switch (Ty->getTag()) {
2717 case dwarf::DW_TAG_class_type:
2718 case dwarf::DW_TAG_structure_type:
2719 case dwarf::DW_TAG_union_type:
2720 break;
2721 default:
2722 return getTypeIndex(Ty);
2723 }
2724
2725 const auto *CTy = cast(Ty);
2726
2727 TypeLoweringScope S(*this);
2728
2729
2730
2731
2732
2733 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2734 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2735
2736
2737
2738
2739 if (CTy->isForwardDecl())
2740 return FwdDeclTI;
2741 }
2742
2743
2744
2745
2746 auto InsertResult = CompleteTypeIndices.insert({CTy, TypeIndex()});
2747 if (!InsertResult.second)
2748 return InsertResult.first->second;
2749
2751 switch (CTy->getTag()) {
2752 case dwarf::DW_TAG_class_type:
2753 case dwarf::DW_TAG_structure_type:
2754 TI = lowerCompleteTypeClass(CTy);
2755 break;
2756 case dwarf::DW_TAG_union_type:
2757 TI = lowerCompleteTypeUnion(CTy);
2758 break;
2759 default:
2761 }
2762
2763
2764
2765
2766
2767 CompleteTypeIndices[CTy] = TI;
2768 return TI;
2769}
2770
2771
2772
2773
2774
2775void CodeViewDebug::emitDeferredCompleteTypes() {
2777 while (!DeferredCompleteTypes.empty()) {
2778 std::swap(DeferredCompleteTypes, TypesToEmit);
2780 getCompleteTypeIndex(RecordTy);
2781 TypesToEmit.clear();
2782 }
2783}
2784
2785void CodeViewDebug::emitLocalVariableList(const FunctionInfo &FI,
2787
2789 for (const LocalVariable &L : Locals)
2790 if (L.DIVar->isParameter())
2792 llvm::sort(Params, [](const LocalVariable *L, const LocalVariable *R) {
2793 return L->DIVar->getArg() < R->DIVar->getArg();
2794 });
2795 for (const LocalVariable *L : Params)
2796 emitLocalVariable(FI, *L);
2797
2798
2799 for (const LocalVariable &L : Locals) {
2800 if (.DIVar->isParameter()) {
2801 if (L.ConstantValue) {
2802
2803
2804 const DIType *Ty = L.DIVar->getType();
2805 APSInt Val(*L.ConstantValue);
2806 emitConstantSymbolRecord(Ty, Val, std::string(L.DIVar->getName()));
2807 } else {
2808 emitLocalVariable(FI, L);
2809 }
2810 }
2811 }
2812}
2813
2814void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI,
2815 const LocalVariable &Var) {
2816
2817 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2818
2820 if (Var.DIVar->isParameter())
2821 Flags |= LocalSymFlags::IsParameter;
2822 if (Var.DefRanges.empty())
2823 Flags |= LocalSymFlags::IsOptimizedOut;
2824
2826 TypeIndex TI = Var.UseReferenceType
2827 ? getTypeIndexForReferenceTo(Var.DIVar->getType())
2828 : getCompleteTypeIndex(Var.DIVar->getType());
2832
2834 endSymbolRecord(LocalEnd);
2835
2836
2837
2838
2840 for (const auto &Pair : Var.DefRanges) {
2841 LocalVarDef DefRange = Pair.first;
2842 const auto &Ranges = Pair.second;
2843 BytePrefix.clear();
2844 if (DefRange.InMemory) {
2845 int Offset = DefRange.DataOffset;
2846 unsigned Reg = DefRange.CVRegister;
2847
2848
2849
2850
2851 if (RegisterId(Reg) == RegisterId::ESP) {
2853 Offset += FI.OffsetAdjustment;
2854 }
2855
2856
2857
2858
2860 if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2861 (bool(Flags & LocalSymFlags::IsParameter)
2862 ? (EncFP == FI.EncodedParamFramePtrReg)
2863 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2867 } else {
2869 if (DefRange.IsSubfield) {
2871 (DefRange.StructOffset
2873 }
2876 DRHdr.Flags = RegRelFlags;
2879 }
2880 } else {
2881 assert(DefRange.DataOffset == 0 && "unexpected offset into register");
2882 if (DefRange.IsSubfield) {
2884 DRHdr.Register = DefRange.CVRegister;
2888 } else {
2890 DRHdr.Register = DefRange.CVRegister;
2893 }
2894 }
2895 }
2896}
2897
2899 const FunctionInfo& FI) {
2901 emitLexicalBlock(*Block, FI);
2902}
2903
2904
2905
2906void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,
2907 const FunctionInfo& FI) {
2908 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2915 OS.AddComment("Function section relative address");
2917 OS.AddComment("Function section index");
2919 OS.AddComment("Lexical block name");
2921 endSymbolRecord(RecordEnd);
2922
2923
2924 emitLocalVariableList(FI, Block.Locals);
2925 emitGlobalVariableList(Block.Globals);
2926
2927
2928 emitLexicalBlockList(Block.Children, FI);
2929
2930
2931 emitEndSymbolRecord(SymbolKind::S_END);
2932}
2933
2934
2935
2936void CodeViewDebug::collectLexicalBlockInfo(
2942 collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
2943}
2944
2945
2946
2947void CodeViewDebug::collectLexicalBlockInfo(
2952 if (Scope.isAbstractScope())
2953 return;
2954
2955
2956
2957 bool IgnoreScope = false;
2958 auto LI = ScopeVariables.find(&Scope);
2960 LI != ScopeVariables.end() ? &LI->second : nullptr;
2961 auto GI = ScopeGlobals.find(Scope.getScopeNode());
2963 GI != ScopeGlobals.end() ? GI->second.get() : nullptr;
2964 const DILexicalBlock *DILB = dyn_cast(Scope.getScopeNode());
2966
2967
2968 if (!Locals && !Globals)
2969 IgnoreScope = true;
2970
2971
2972 if (!DILB)
2973 IgnoreScope = true;
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2987 IgnoreScope = true;
2988
2989 if (IgnoreScope) {
2990
2991
2992
2993
2994 if (Locals)
2996 if (Globals)
2997 ParentGlobals.append(Globals->begin(), Globals->end());
2998 collectLexicalBlockInfo(Scope.getChildren(),
2999 ParentBlocks,
3000 ParentLocals,
3001 ParentGlobals);
3002 return;
3003 }
3004
3005
3006
3007
3008 auto BlockInsertion = CurFn->LexicalBlocks.insert({DILB, LexicalBlock()});
3009 if (!BlockInsertion.second)
3010 return;
3011
3012
3013
3016 LexicalBlock &Block = BlockInsertion.first->second;
3019 assert(Block.Begin && "missing label for scope begin");
3020 assert(Block.End && "missing label for scope end");
3022 if (Locals)
3023 Block.Locals = std::move(*Locals);
3024 if (Globals)
3025 Block.Globals = std::move(*Globals);
3027 collectLexicalBlockInfo(Scope.getChildren(),
3031}
3032
3035 assert(FnDebugInfo.count(&GV));
3036 assert(CurFn == FnDebugInfo[&GV].get());
3037
3039
3040
3042 collectLexicalBlockInfo(*CFS,
3043 CurFn->ChildBlocks,
3044 CurFn->Locals,
3045 CurFn->Globals);
3046
3047
3048
3049
3050 ScopeVariables.clear();
3051
3052
3053
3054 if (!CurFn->HaveLineInfo && !GV.getSubprogram()->isThunk()) {
3055 FnDebugInfo.erase(&GV);
3056 CurFn = nullptr;
3057 return;
3058 }
3059
3060
3061 for (const auto &MBB : *MF) {
3062 for (const auto &MI : MBB) {
3063 if (MDNode *MD = MI.getHeapAllocMarker()) {
3066 dyn_cast(MD)));
3067 }
3068 }
3069 }
3070
3073 collectDebugInfoForJumpTables(MF, isThumb);
3074
3076
3078
3079 CurFn = nullptr;
3080}
3081
3082
3083
3084
3085
3087 return DL && DL.getLine() != 0;
3088}
3089
3092
3093
3094 if ( || !CurFn || MI->isDebugInstr() ||
3096 return;
3097
3098
3099
3102 for (const auto &NextMI : *MI->getParent()) {
3103 if (NextMI.isDebugInstr())
3104 continue;
3105 DL = NextMI.getDebugLoc();
3107 break;
3108 }
3109
3110
3111 }
3113
3114
3116 return;
3117
3118 maybeRecordLocation(DL, Asm->MF);
3119}
3120
3128 return EndLabel;
3129}
3130
3131void CodeViewDebug::endCVSubsection(MCSymbol *EndLabel) {
3133
3135}
3136
3139 if (EE.Value == SymKind)
3140 return EE.Name;
3141 return "";
3142}
3143
3152 OS.emitInt16(unsigned(SymKind));
3153 return EndLabel;
3154}
3155
3156void CodeViewDebug::endSymbolRecord(MCSymbol *SymEnd) {
3157
3158
3159
3160
3163}
3164
3165void CodeViewDebug::emitEndSymbolRecord(SymbolKind EndKind) {
3171}
3172
3173void CodeViewDebug::emitDebugInfoForUDTs(
3174 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3175#ifndef NDEBUG
3176 size_t OriginalSize = UDTs.size();
3177#endif
3178 for (const auto &UDT : UDTs) {
3181 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3183 OS.emitInt32(getCompleteTypeIndex(T).getIndex());
3184 assert(OriginalSize == UDTs.size() &&
3185 "getCompleteTypeIndex found new UDTs!");
3187 endSymbolRecord(UDTRecordEnd);
3188 }
3189}
3190
3191void CodeViewDebug::collectGlobalVariableInfo() {
3193 GlobalMap;
3196 GV.getDebugInfo(GVEs);
3197 for (const auto *GVE : GVEs)
3198 GlobalMap[GVE] = &GV;
3199 }
3200
3203 const auto *CU = cast(Node);
3204 for (const auto *GVE : CU->getGlobalVariables()) {
3207
3208
3209
3210
3212
3213 if ((DIE->getNumElements() == 2) &&
3214 (DIE->getElement(0) == dwarf::DW_OP_plus_uconst))
3215
3216
3217
3218
3219 CVGlobalVariableOffsets.insert(
3220 std::make_pair(DIGV, DIE->getElement(1)));
3221
3222
3223 if (GlobalMap.count(GVE) == 0 && DIE->isConstant()) {
3224 CVGlobalVariable CVGV = {DIGV, DIE};
3225 GlobalVariables.emplace_back(std::move(CVGV));
3226 }
3227
3228 const auto *GV = GlobalMap.lookup(GVE);
3230 continue;
3231
3234 if (Scope && isa(Scope)) {
3235
3236
3237 auto Insertion = ScopeGlobals.insert(
3238 {Scope, std::unique_ptr()});
3239 if (Insertion.second)
3240 Insertion.first->second = std::make_unique();
3241 VariableList = Insertion.first->second.get();
3243
3244 VariableList = &ComdatVariables;
3245 else
3246
3247 VariableList = &GlobalVariables;
3248 CVGlobalVariable CVGV = {DIGV, GV};
3249 VariableList->emplace_back(std::move(CVGV));
3250 }
3251 }
3252}
3253
3254void CodeViewDebug::collectDebugInfoForGlobals() {
3255 for (const CVGlobalVariable &CVGV : GlobalVariables) {
3258 getCompleteTypeIndex(DIGV->getType());
3259 getFullyQualifiedName(Scope, DIGV->getName());
3260 }
3261
3262 for (const CVGlobalVariable &CVGV : ComdatVariables) {
3265 getCompleteTypeIndex(DIGV->getType());
3266 getFullyQualifiedName(Scope, DIGV->getName());
3267 }
3268}
3269
3270void CodeViewDebug::emitDebugInfoForGlobals() {
3271
3272
3273
3274 switchToDebugSectionForSymbol(nullptr);
3275 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3276 OS.AddComment("Symbol subsection for globals");
3277 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3278 emitGlobalVariableList(GlobalVariables);
3279 emitStaticConstMemberList();
3280 endCVSubsection(EndLabel);
3281 }
3282
3283
3284
3285 for (const CVGlobalVariable &CVGV : ComdatVariables) {
3286 const GlobalVariable *GV = cast<const GlobalVariable *>(CVGV.GVInfo);
3288 OS.AddComment("Symbol subsection for " +
3290 switchToDebugSectionForSymbol(GVSym);
3291 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3292
3293 emitDebugInfoForGlobal(CVGV);
3294 endCVSubsection(EndLabel);
3295 }
3296}
3297
3298void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3301 for (auto *Ty : cast(Node)->getRetainedTypes()) {
3302 if (DIType *RT = dyn_cast(Ty)) {
3303 getTypeIndex(RT);
3304
3305 }
3306 }
3307 }
3308}
3309
3310
3312 for (const CVGlobalVariable &CVGV : Globals) {
3313
3314 emitDebugInfoForGlobal(CVGV);
3315 }
3316}
3317
3318void CodeViewDebug::emitConstantSymbolRecord(const DIType *DTy, APSInt &Value,
3320 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3322 OS.emitInt32(getTypeIndex(DTy).getIndex());
3323
3325
3326
3331 StringRef SRef((char *)Data, Writer.getOffset());
3333
3336 endSymbolRecord(SConstantEnd);
3337}
3338
3339void CodeViewDebug::emitStaticConstMemberList() {
3340 for (const DIDerivedType *DTy : StaticConstMembers) {
3342
3345 dyn_cast_or_null(DTy->getConstant()))
3349 dyn_cast_or_null(DTy->getConstant()))
3350 Value = APSInt(CFP->getValueAPF().bitcastToAPInt(), true);
3351 else
3353
3354 emitConstantSymbolRecord(DTy->getBaseType(), Value,
3355 getFullyQualifiedName(Scope, DTy->getName()));
3356 }
3357}
3358
3360 if (isa(Ty))
3361 return false;
3362
3363 if (auto *DTy = dyn_cast(Ty)) {
3365 if (T == dwarf::DW_TAG_pointer_type ||
3366 T == dwarf::DW_TAG_ptr_to_member_type ||
3367 T == dwarf::DW_TAG_reference_type ||
3368 T == dwarf::DW_TAG_rvalue_reference_type)
3369 return false;
3370 assert(DTy->getBaseType() && "Expected valid base type");
3372 }
3373
3374 auto *BTy = cast(Ty);
3375 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3376}
3377
3378void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) {
3380
3382
3383 if (const auto *MemberDecl = dyn_cast_or_null(
3385 Scope = MemberDecl->getScope();
3386
3387
3388
3391 ? std::string(DIGV->getName())
3392 : getFullyQualifiedName(Scope, DIGV->getName());
3393
3395 dyn_cast_if_present<const GlobalVariable *>(CVGV.GVInfo)) {
3396
3397
3400 ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32
3401 : SymbolKind::S_GTHREAD32)
3402 : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32
3403 : SymbolKind::S_GDATA32);
3408
3409
3410 uint64_t Offset = CVGlobalVariableOffsets.lookup(DIGV);
3412
3416 const unsigned LengthOfDataRecord = 12;
3418 endSymbolRecord(DataEnd);
3419 } else {
3420 const DIExpression *DIE = cast<const DIExpression *>(CVGV.GVInfo);
3422 "Global constant variables must contain a constant expression.");
3423
3424
3430 }
3431}
3432
3436 int64_t)> &Callback) {
3438 if (JTI && !JTI->isEmpty()) {
3439#ifndef NDEBUG
3441#endif
3442 for (const auto &MBB : *MF) {
3443
3445 if (LastMI != MBB.end() && LastMI->isIndirectBranch()) {
3447
3448
3449
3450
3451
3452
3453 for (const auto &MO : LastMI->operands()) {
3454 if (MO.isJTI()) {
3455 unsigned Index = MO.getIndex();
3456#ifndef NDEBUG
3457 UsedJTs.set(Index);
3458#endif
3459 Callback(*JTI, *LastMI, Index);
3460 break;
3461 }
3462 }
3463 } else {
3464
3465
3466
3468 if (I->isJumpTableDebugInfo()) {
3469 unsigned Index = I->getOperand(0).getImm();
3470#ifndef NDEBUG
3471 UsedJTs.set(Index);
3472#endif
3473 Callback(*JTI, *LastMI, Index);
3474 break;
3475 }
3476 }
3477 }
3478 }
3479 }
3480#ifndef NDEBUG
3481 assert(UsedJTs.all() &&
3482 "Some of jump tables were not used in a debug info instruction");
3483#endif
3484 }
3485}
3486
3487void CodeViewDebug::discoverJumpTableBranches(const MachineFunction *MF,
3493}
3494
3495void CodeViewDebug::collectDebugInfoForJumpTables(const MachineFunction *MF,
3500 int64_t JumpTableIndex) {
3501
3502
3503
3513 "EK_Custom32, EK_GPRel32BlockAddress, and "
3514 "EK_GPRel64BlockAddress should never be emitted for COFF");
3516
3517 EntrySize = JumpTableEntrySize::Pointer;
3518 Base = nullptr;
3519 break;
3523
3524 std::tie(Base, BaseOffset, Branch, EntrySize) =
3526 break;
3527 }
3528
3529 CurFn->JumpTables.push_back(
3530 {EntrySize, Base, BaseOffset, Branch,
3532 JTI.getJumpTables()[JumpTableIndex].MBBs.size()});
3533 });
3534}
3535
3536void CodeViewDebug::emitDebugInfoForJumpTables(const FunctionInfo &FI) {
3537 for (auto JumpTable : FI.JumpTables) {
3538 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3542 OS.AddComment("Base section index");
3544 } else {
3547 OS.AddComment("Base section index");
3549 }
3556 OS.AddComment("Branch section index");
3558 OS.AddComment("Table section index");
3562 endSymbolRecord(JumpTableEnd);
3563 }
3564}
3565
3566void CodeViewDebug::emitInlinees(
3568
3569
3570 constexpr size_t ChunkSize =
3573
3576
3577 size_t CurrentIndex = 0;
3578 while (CurrentIndex < SortedInlinees.size()) {
3579 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3580 auto CurrentChunkSize =
3581 std::min(ChunkSize, SortedInlinees.size() - CurrentIndex);
3584
3585 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3586 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3588 OS.emitInt32(SortedInlinees[CurrentIndex].getIndex());
3589 }
3590 endSymbolRecord(Symbol);
3591 }
3592}
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
static bool isThumb(const MCSubtargetInfo &STI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
static bool canUseReferenceType(const DbgVariableLocation &Loc)
static SourceLanguage MapDWLangToCVLang(unsigned DWLang)
static MethodKind translateMethodKindFlags(const DISubprogram *SP, bool Introduced)
static bool isUsableDebugLoc(DebugLoc DL)
static TypeIndex getStringIdTypeIdx(GlobalTypeTableBuilder &TypeTable, StringRef S)
static CPUType mapArchToCVCPUType(Triple::ArchType Type)
static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S, unsigned MaxFixedRecordLength=0xF00)
static Version parseVersion(StringRef Name)
static MethodOptions translateMethodOptionFlags(const DISubprogram *SP)
static bool isNonTrivial(const DICompositeType *DCTy)
static std::string formatNestedName(ArrayRef< StringRef > QualifiedNameComponents, StringRef TypeName)
static ClassOptions getCommonClassOptions(const DICompositeType *Ty)
Return ClassOptions that should be present on both the forward declaration and the defintion of a tag...
static PointerToMemberRepresentation translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags)
static FunctionOptions getFunctionOptions(const DISubroutineType *Ty, const DICompositeType *ClassTy=nullptr, StringRef SPName=StringRef(""))
static StringRef removeTemplateArgs(StringRef Name)
static TypeRecordKind getRecordKind(const DICompositeType *Ty)
void forEachJumpTableBranch(const MachineFunction *MF, bool isThumb, const std::function< void(const MachineJumpTableInfo &, const MachineInstr &, int64_t)> &Callback)
static CallingConvention dwarfCCToCodeView(unsigned DwarfCC)
Given a DWARF calling convention, get the CodeView equivalent.
static bool isFloatDIType(const DIType *Ty)
static void addLocIfNotPresent(SmallVectorImpl< const DILocation * > &Locs, const DILocation *Loc)
static bool shouldEmitUdt(const DIType *T)
static StringRef getPrettyScopeName(const DIScope *Scope)
static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty)
static bool needsReferenceType(const DbgVariableLocation &Loc)
static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file contains constants used for implementing Dwarf debug support.
DenseMap< Block *, BlockRelaxAux > Blocks
Module.h This file contains the declarations for the Module class.
unsigned const TargetRegisterInfo * TRI
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the SmallBitVector class.
This file defines the SmallString class.
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static const uint32_t IV[8]
Class for arbitrary precision integers.
An arbitrary precision integer that knows its signedness.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
size - Get the array size.
This class is intended to be used as a driving class for all asm writers.
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
MCSymbol * getSymbol(const GlobalValue *GV) const
TargetMachine & TM
Target machine description.
MCSymbol * getFunctionBegin() const
const MCAsmInfo * MAI
Target Asm Printer information.
MachineFunction * MF
The current machine function.
bool hasDebugInfo() const
Returns true if valid debug info is present.
MCSymbol * getFunctionEnd() const
virtual std::tuple< const MCSymbol *, uint64_t, const MCSymbol *, codeview::JumpTableEntrySize > getCodeViewJumpTableInfo(int JTI, const MachineInstr *BranchInstr, const MCSymbol *BranchLabel) const
Gets information required to create a CodeView debug symbol for a jump table.
Provides write only access to a subclass of WritableBinaryStream.
Collects and handles line tables information in a CodeView format.
CodeViewDebug(AsmPrinter *AP)
void beginModule(Module *M) override
bool moduleIsInFortran()
Check if the current module is in Fortran.
void endFunctionImpl(const MachineFunction *) override
Gather post-function debug information.
void endModule() override
Emit the COFF section that holds the line table information.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
void beginFunctionImpl(const MachineFunction *MF) override
Gather pre-function debug information.
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Basic type, like 'int' or 'float'.
unsigned getEncoding() const
StringRef getIdentifier() const
DINodeArray getElements() const
DIType * getBaseType() const
DIType * getClassType() const
Get casted version of extra data.
Constant * getConstant() const
A structured debug information entry.
bool isLocalToUnit() const
Metadata * getRawStaticDataMemberDeclaration() const
DILocalScope * getScope() const
Get the local scope for this variable.
Tagged DWARF-like metadata node.
dwarf::Tag getTag() const
Base class for scope-like contexts.
StringRef getFilename() const
StringRef getName() const
StringRef getDirectory() const
DIScope * getScope() const
String type, Fortran CHARACTER(n)
Type array for a subprogram.
DITypeRefArray getTypeArray() const
uint64_t getOffsetInBits() const
bool isObjectPointer() const
StringRef getName() const
bool isForwardDecl() const
uint64_t getSizeInBits() const
DIScope * getScope() const
DIScope * getScope() const
StringRef getName() const
This class represents an Operation in the Expression.
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
static const EntryIndex NoEntry
Special value to indicate that an entry is valid until the end of the function.
Base class for debug information backends.
static bool isUnsignedDIType(const DIType *Ty)
Return true if type encoding is unsigned.
AsmPrinter * Asm
Target of debug info emission.
MCSymbol * getLabelBeforeInsn(const MachineInstr *MI)
Return Label preceding the instruction.
MachineModuleInfo * MMI
Collected machine module information.
DebugLoc PrevInstLoc
Previous instruction's location information.
MCSymbol * getLabelAfterInsn(const MachineInstr *MI)
Return Label immediately following the instruction.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
const MachineBasicBlock * PrevInstBB
void requestLabelAfterInsn(const MachineInstr *MI)
Ensure that a label will be emitted after MI.
DbgValueHistoryMap DbgValues
History of DBG_VALUE and clobber instructions for each user variable.
void requestLabelBeforeInsn(const MachineInstr *MI)
Ensure that a label will be emitted before MI.
const MachineInstr * PrologEndLoc
This location indicates end of function prologue and beginning of function body.
static uint64_t getBaseTypeSize(const DIType *Ty)
If this type is derived from a base type then return base type size.
DILocation * get() const
Get the underlying DILocation.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Implements a dense probed hash-table based set.
Lightweight error class with error context and mandatory checking.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool hasStackProtectorFnAttr() const
Returns true if the function has ssp, sspstrong, or sspreq fn attrs.
DISubprogram * getSubprogram() const
Get the attached subprogram.
bool hasPersonalityFn() const
Check whether this function has a personality function.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
bool hasProfileData(bool IncludeSynthetic=false) const
Return true if the function is annotated with profile data.
bool hasOptNone() const
Do not optimize this function (-O0).
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
bool hasLocalLinkage() const
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
bool isDeclarationForLinker() const
LexicalScope - This class is used to track scope information.
LexicalScope * findLexicalScope(const DILocation *DL)
findLexicalScope - Find lexical scope, either regular or inlined, for the given DebugLoc.
LexicalScope * findInlinedScope(const DILocalScope *N, const DILocation *IA)
findInlinedScope - Find an inlined scope for the given scope/inlined-at.
LexicalScope * getCurrentFunctionScope() const
getCurrentFunctionScope - Return lexical scope for the current function.
unsigned getCodePointerSize() const
Get the code pointer size in bytes.
void * allocate(unsigned Size, unsigned Align=8)
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSectionCOFF * getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym, unsigned UniqueID=GenericSectionID)
Gets or creates a section equivalent to Sec that is associated with the section containing KeySym.
MCSection * getCOFFDebugSymbolsSection() const
MCSection * getCOFFDebugTypesSection() const
MCSection * getCOFFGlobalTypeHashesSection() const
This represents a section on Windows.
MCSymbol * getCOMDATSymbol() const
Streaming machine code generation interface.
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
virtual bool emitCVFuncIdDirective(unsigned FunctionId)
Introduces a function id for use with .cv_loc.
virtual void emitBinaryData(StringRef Data)
Functionally identical to EmitBytes.
virtual bool emitCVFileDirective(unsigned FileNo, StringRef Filename, ArrayRef< uint8_t > Checksum, unsigned ChecksumKind)
Associate a filename with a specified logical file number, and also specify that file's checksum info...
virtual void emitCVStringTableDirective()
This implements the CodeView '.cv_stringtable' assembler directive.
virtual bool isVerboseAsm() const
Return true if this streamer supports verbose assembly and if it is enabled.
virtual void emitCVFileChecksumOffsetDirective(unsigned FileNo)
This implements the CodeView '.cv_filechecksumoffset' assembler directive.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitCVFPOData(const MCSymbol *ProcSym, SMLoc Loc={})
This implements the CodeView '.cv_fpo_data' assembler directive.
virtual void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset)
Emits a COFF section relative relocation.
virtual void emitCVFileChecksumsDirective()
This implements the CodeView '.cv_filechecksums' assembler directive.
virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size)
Emit the absolute difference between two symbols.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitCOFFSectionIndex(MCSymbol const *Symbol)
Emits a COFF section index.
virtual void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, const MCSymbol *FnEnd)
This implements the CodeView '.cv_linetable' assembler directive.
virtual void emitValueToAlignment(Align Alignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
virtual void emitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers.
void emitInt16(uint64_t Value)
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
virtual void emitCVDefRangeDirective(ArrayRef< std::pair< const MCSymbol *, const MCSymbol * > > Ranges, StringRef FixedSizePortion)
This implements the CodeView '.cv_def_range' assembler directive.
void emitInt32(uint64_t Value)
virtual void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, unsigned Column, bool PrologueEnd, bool IsStmt, StringRef FileName, SMLoc Loc)
This implements the CodeView '.cv_loc' assembler directive.
virtual bool emitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc, unsigned IAFile, unsigned IALine, unsigned IACol, SMLoc Loc)
Introduces an inline call site id for use with .cv_loc.
void emitInt8(uint64_t Value)
virtual void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym)
This implements the CodeView '.cv_inline_linetable' assembler directive.
virtual void emitBytes(StringRef Data)
Emit the bytes in Data into the output.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
std::string CommandlineArgs
ArrayRef< MDOperand > operands() const
unsigned getNumOperands() const
Return number of MDNode operands.
reverse_instr_iterator instr_rbegin()
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
reverse_instr_iterator instr_rend()
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
int64_t getOffsetAdjustment() const
Return the correction for frame offsets.
unsigned getCVBytesOfCalleeSavedRegisters() const
Returns how many bytes of callee-saved registers the target pushed in the prologue.
bool hasStackProtectorIndex() const
Description of the location of a variable whose Address is valid and unchanging during function execu...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool hasInlineAsm() const
Returns true if the function contains any inline assembly.
bool exposesReturnsTwice() const
exposesReturnsTwice - Returns true if the function calls setjmp or any other similar functions with a...
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCSymbol * getJTISymbol(unsigned JTI, MCContext &Ctx, bool isLinkerPrivate=false) const
getJTISymbol - Return the MCSymbol for the specified non-empty jump table.
auto getInStackSlotVariableDbgInfo()
Returns the collection of variables for which we have debug info and that have been assigned a stack ...
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
ArrayRef< std::pair< MCSymbol *, MDNode * > > getCodeViewAnnotations() const
Representation of each machine instruction.
bool isDebugValue() const
MachineOperand & getDebugOperand(unsigned Index)
@ EK_GPRel32BlockAddress
EK_GPRel32BlockAddress - Each entry is an address of block, encoded with a relocation as gp-relative,...
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
@ EK_LabelDifference32
EK_LabelDifference32 - Each entry is the address of the block minus the address of the jump table.
@ EK_Custom32
EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the TargetLowering::LowerCustomJ...
@ EK_LabelDifference64
EK_LabelDifference64 - Each entry is the address of the block minus the address of the jump table.
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
@ EK_GPRel64BlockAddress
EK_GPRel64BlockAddress - Each entry is an address of block, encoded with a relocation as gp-relative,...
JTEntryKind getEntryKind() const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
const MCContext & getContext() const
const Module * getModule() const
A Module instance is used to store all the information related to an LLVM module.
NamedMDNode * getNamedMetadata(StringRef Name) const
Return the first NamedMDNode in the module with the specified name.
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
iterator_range< global_iterator > globals()
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Metadata * getProfileSummary(bool IsCS) const
Returns profile summary metadata.
iterator_range< op_iterator > operands()
const RecordRecTy * getType() const
Wrapper class representing virtual and physical registers.
Represents a location in source code.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
const_iterator begin() const
const_iterator end() const
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
static StackOffset getScalable(int64_t Scalable)
static StackOffset getFixed(int64_t Fixed)
StringRef - Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
char back() const
back - Get the last character in the string.
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Information about stack frame layout on the target.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
MCTargetOptions MCOptions
Machine level options.
std::string ObjectFilenameForDebug
Stores the filename/path of the final .o/.obj file, to be written in the debug information.
unsigned Hotpatch
Emit the hotpatch flag in CodeView debug.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetFrameLowering * getFrameLowering() const
TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...
Triple - Helper class for working with autoconf configuration names.
ArchType getArch() const
Get the parsed architecture type of this triple.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
StringRef getName() const
Return a constant reference to the value's name.
@ CurrentDirectory
Absolute CWD path.
@ SourceFile
Path to main source file, relative or absolute.
@ BuildTool
Absolute compiler path.
@ CommandLine
Full canonical command line (maybe -cc1)
@ TypeServerPDB
Absolute path of type server PDB (/Fd)
virtual void emitBytes(StringRef Data)=0
virtual bool isVerboseAsm()=0
virtual void AddComment(const Twine &T)=0
virtual void emitIntValue(uint64_t Value, unsigned Size)=0
virtual void emitBinaryData(StringRef Data)=0
virtual void AddRawComment(const Twine &T)=0
void begin(ContinuationRecordKind RecordKind)
void writeMemberType(RecordType &Record)
ArrayRef< ArrayRef< uint8_t > > records() const
TypeIndex insertRecord(ContinuationRecordBuilder &Builder)
ArrayRef< GloballyHashedType > hashes() const
TypeIndex writeLeafType(T &Record)
For method overload sets. LF_METHOD.
SimpleTypeKind getSimpleKind() const
SimpleTypeMode getSimpleMode() const
static const uint32_t FirstNonSimpleIndex
static StringRef simpleTypeName(TypeIndex TI)
uint32_t getIndex() const
static TypeIndex NullptrT()
void addCallbackToPipeline(TypeVisitorCallbacks &Callbacks)
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
@ DEBUG_HASHES_SECTION_MAGIC
@ C
The default llvm calling convention, compatible with C.
Reg
All possible values of the reg field in the ModR/M byte.
PointerMode
Equivalent to CV_ptrmode_e.
ProcSymFlags
Corresponds to the CV_PROCFLAGS bitfield.
PointerOptions
Equivalent to misc lfPointerAttr bitfields.
LocalSymFlags
Corresponds to CV_LVARFLAGS bitfield.
MethodKind
Part of member attribute flags. (CV_methodprop_e)
PointerKind
Equivalent to CV_ptrtype_e.
CPUType
These values correspond to the CV_CPU_TYPE_e enumeration, and are documented here: https://msdn....
PointerToMemberRepresentation
Equivalent to CV_pmtype_e.
CallingConvention
These values correspond to the CV_call_e enumeration, and are documented at the following locations: ...
MethodOptions
Equivalent to CV_fldattr_t bitfield.
ArrayRef< EnumEntry< SymbolKind > > getSymbolTypeNames()
MemberAccess
Source-level access specifier. (CV_access_e)
ThunkOrdinal
These values correspond to the THUNK_ORDINAL enumeration.
EncodedFramePtrReg
Two-bit value indicating which register is the designated frame pointer register.
TypeRecordKind
Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.
SymbolKind
Duplicate copy of the above enum, but using the official CV names.
ModifierOptions
Equivalent to CV_modifier_t.
StringRef getSymbolName(CVSymbol Sym)
EncodedFramePtrReg encodeFramePtrReg(RegisterId Reg, CPUType CPU)
Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
SourceLanguage
These values correspond to the CV_CFL_LANG enumeration in the Microsoft Debug Interface Access SDK,...
ElementType
The element type of an SRV or UAV resource.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
This is an optimization pass for GlobalISel generic memory operations.
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
std::tuple< uint64_t, uint32_t > InlineSite
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
StringRef getTypeName()
We provide a function which tries to compute the (demangled) name of a type statically.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
std::pair< const MachineInstr *, const MachineInstr * > InsnRange
InsnRange - This is used to track range of instructions with identical lexical scope.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
TypeLoweringScope(CodeViewDebug &CVD)
This struct is a compact representation of a valid (non-zero power of two) alignment.
const DIDerivedType * MemberTypeNode
std::vector< MemberInfo > MemberList
MemberList Members
Direct members.
std::vector< const DIType * > NestedTypes
std::vector< const DIDerivedType * > Inheritance
Base classes.
int InMemory
Indicates that variable data is stored in memory relative to the specified register.
Represents the location at which a variable is stored.
static std::optional< DbgVariableLocation > extractFromMachineInstruction(const MachineInstr &Instruction)
Extract a VariableLocation from a MachineInstr.
SmallVector< int64_t, 1 > LoadChain
Chain of offsetted loads necessary to load the value if it lives in memory.