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:
80 CVMCAdapter(MCStreamer &OS, TypeCollection &TypeTable)
81 : OS(&OS), TypeTable(TypeTable) {}
82
83 void emitBytes(StringRef Data) override { OS->emitBytes(Data); }
84
85 void emitIntValue(uint64_t Value, unsigned Size) override {
86 OS->emitIntValueInHex(Value, Size);
87 }
88
89 void emitBinaryData(StringRef Data) override { OS->emitBinaryData(Data); }
90
91 void AddComment(const Twine &T) override { OS->AddComment(T); }
92
93 void AddRawComment(const Twine &T) override { OS->emitRawComment(T); }
94
95 bool isVerboseAsm() override { return OS->isVerboseAsm(); }
96
97 std::string getTypeName(TypeIndex TI) override {
102 else
103 TypeName = std::string(TypeTable.getTypeName(TI));
104 }
106 }
107
108private:
109 MCStreamer *OS = nullptr;
110 TypeCollection &TypeTable;
111};
112}
113
115 switch (Type) {
121
122
130 default:
131 report_fatal_error("target architecture doesn't map to a CodeView CPUType");
132 }
133}
134
137
138StringRef CodeViewDebug::getFullFilepath(const DIFile *File) {
139 std::string &Filepath = FileToFilepathMap[File];
140 if (!Filepath.empty())
141 return Filepath;
142
143 StringRef Dir = File->getDirectory(), Filename = File->getFilename();
144
145
146
147 if (Dir.starts_with("/") || Filename.starts_with("/")) {
149 return Filename;
150 Filepath = std::string(Dir);
151 if (Dir.back() != '/')
152 Filepath += '/';
153 Filepath += Filename;
154 return Filepath;
155 }
156
157
158
159
160
161 if (Filename.find(':') == 1)
162 Filepath = std::string(Filename);
163 else
164 Filepath = (Dir + "\\" + Filename).str();
165
166
167
168
170
171
172 size_t Cursor = 0;
173 while ((Cursor = Filepath.find("\\.\\", Cursor)) != std:🧵:npos)
174 Filepath.erase(Cursor, 2);
175
176
177
178 Cursor = 0;
179 while ((Cursor = Filepath.find("\\..\\", Cursor)) != std:🧵:npos) {
180
181 if (Cursor == 0)
182 break;
183
184 size_t PrevSlash = Filepath.rfind('\\', Cursor - 1);
185 if (PrevSlash == std:🧵:npos)
186
187 break;
188
189 Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
190
191 Cursor = PrevSlash;
192 }
193
194
195 Cursor = 0;
196 while ((Cursor = Filepath.find("\\\\", Cursor)) != std:🧵:npos)
197 Filepath.erase(Cursor, 1);
198
199 return Filepath;
200}
201
202unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) {
203 StringRef FullPath = getFullFilepath(F);
204 unsigned NextId = FileIdMap.size() + 1;
205 auto Insertion = FileIdMap.insert(std::make_pair(FullPath, NextId));
206 if (Insertion.second) {
207
208 ArrayRef<uint8_t> ChecksumAsBytes;
210 if (F->getChecksum()) {
211 std::string Checksum = fromHex(F->getChecksum()->Value);
212 void *CKMem = OS.getContext().allocate(Checksum.size(), 1);
213 memcpy(CKMem, Checksum.data(), Checksum.size());
214 ChecksumAsBytes = ArrayRef<uint8_t>(
215 reinterpret_cast<const uint8_t *>(CKMem), Checksum.size());
216 switch (F->getChecksum()->Kind) {
218 CSKind = FileChecksumKind::MD5;
219 break;
221 CSKind = FileChecksumKind::SHA1;
222 break;
224 CSKind = FileChecksumKind::SHA256;
225 break;
226 }
227 }
228 bool Success = OS.emitCVFileDirective(NextId, FullPath, ChecksumAsBytes,
229 static_cast<unsigned>(CSKind));
232 }
233 return Insertion.first->second;
234}
235
236CodeViewDebug::InlineSite &
237CodeViewDebug::getInlineSite(const DILocation *InlinedAt,
239 auto SiteInsertion = CurFn->InlineSites.try_emplace(InlinedAt);
240 InlineSite *Site = &SiteInsertion.first->second;
241 if (SiteInsertion.second) {
242 unsigned ParentFuncId = CurFn->FuncId;
243 if (const DILocation *OuterIA = InlinedAt->getInlinedAt())
244 ParentFuncId =
245 getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())
246 .SiteFuncId;
247
248 Site->SiteFuncId = NextFuncId++;
249 OS.emitCVInlineSiteIdDirective(
250 Site->SiteFuncId, ParentFuncId, maybeRecordFile(InlinedAt->getFile()),
251 InlinedAt->getLine(), InlinedAt->getColumn(), SMLoc());
253 InlinedSubprograms.insert(Inlinee);
254 auto InlineeIdx = getFuncIdForSubprogram(Inlinee);
255
256 if (InlinedAt->getInlinedAt() == nullptr)
257 CurFn->Inlinees.insert(InlineeIdx);
258 }
259 return *Site;
260}
261
263 StringRef ScopeName = Scope->getName();
264 if (!ScopeName.empty())
265 return ScopeName;
266
267 switch (Scope->getTag()) {
268 case dwarf::DW_TAG_enumeration_type:
269 case dwarf::DW_TAG_class_type:
270 case dwarf::DW_TAG_structure_type:
271 case dwarf::DW_TAG_union_type:
272 return "";
273 case dwarf::DW_TAG_namespace:
274 return "`anonymous namespace'";
275 default:
277 }
278}
279
280const DISubprogram *CodeViewDebug::collectParentScopeNames(
282 const DISubprogram *ClosestSubprogram = nullptr;
283 while (Scope != nullptr) {
284 if (ClosestSubprogram == nullptr)
286
287
288
289
291 DeferredCompleteTypes.push_back(Ty);
292
294 if (!ScopeName.empty())
295 QualifiedNameComponents.push_back(ScopeName);
297 }
298 return ClosestSubprogram;
299}
300
303 std::string FullyQualifiedName;
304 for (StringRef QualifiedNameComponent :
306 FullyQualifiedName.append(std::string(QualifiedNameComponent));
307 FullyQualifiedName.append("::");
308 }
309 FullyQualifiedName.append(std::string(TypeName));
310 return FullyQualifiedName;
311}
312
316
317
318 if (CVD.TypeEmissionLevel == 1)
319 CVD.emitDeferredCompleteTypes();
320 --CVD.TypeEmissionLevel;
321 }
323};
324
325std::string CodeViewDebug::getFullyQualifiedName(const DIScope *Scope,
327
328
329
332 collectParentScopeNames(Scope, QualifiedNameComponents);
334}
335
336std::string CodeViewDebug::getFullyQualifiedName(const DIScope *Ty) {
339}
340
341TypeIndex CodeViewDebug::getScopeIndex(const DIScope *Scope) {
342
343
344
345
346
347
348
349
350
351
354
355 assert((Scope) && "shouldn't make a namespace scope for a type");
356
357
358 auto I = TypeIndices.find({Scope, nullptr});
359 if (I != TypeIndices.end())
360 return I->second;
361
362
363 std::string ScopeName = getFullyQualifiedName(Scope);
364 StringIdRecord SID(TypeIndex(), ScopeName);
365 auto TI = TypeTable.writeLeafType(SID);
366 return recordTypeIndexForDINode(Scope, TI);
367}
368
370
371
372 if (Name.empty() || Name.back() != '>')
373 return Name;
374
375 int OpenBrackets = 0;
376 for (int i = Name.size() - 1; i >= 0; --i) {
377 if (Name[i] == '>')
378 ++OpenBrackets;
379 else if (Name[i] == '<') {
380 --OpenBrackets;
381 if (OpenBrackets == 0)
382 return Name.substr(0, i);
383 }
384 }
385 return Name;
386}
387
388TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) {
390
391
392 auto I = TypeIndices.find({SP, nullptr});
393 if (I != TypeIndices.end())
394 return I->second;
395
396
397
398
400
401 const DIScope *Scope = SP->getScope();
402 TypeIndex TI;
404
405
406
407 TypeIndex ClassType = getTypeIndex(Class);
408 MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class),
409 DisplayName);
410 TI = TypeTable.writeLeafType(MFuncId);
411 } else {
412
413 TypeIndex ParentScope = getScopeIndex(Scope);
414 FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName);
415 TI = TypeTable.writeLeafType(FuncId);
416 }
417
418 return recordTypeIndexForDINode(SP, TI);
419}
420
422 return ((DCTy->getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);
423}
424
430 const DIType *ReturnTy = nullptr;
431 if (auto TypeArray = Ty->getTypeArray()) {
432 if (TypeArray.size())
433 ReturnTy = TypeArray[0];
434 }
435
436
437
441
442
443 if (ClassTy && isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {
445
446
447
448 }
449 return FO;
450}
451
452TypeIndex CodeViewDebug::getMemberFunctionType(const DISubprogram *SP,
454
455
456 if (SP->getDeclaration())
457 SP = SP->getDeclaration();
458 assert(->getDeclaration() && "should use declaration as key");
459
460
461
462 auto I = TypeIndices.find({SP, Class});
463 if (I != TypeIndices.end())
464 return I->second;
465
466
467
468
470 const bool IsStaticMethod = (SP->getFlags() & DINode::FlagStaticMember) != 0;
471
473 TypeIndex TI = lowerTypeMemberFunction(
474 SP->getType(), Class, SP->getThisAdjustment(), IsStaticMethod, FO);
475 return recordTypeIndexForDINode(SP, TI, Class);
476}
477
478TypeIndex CodeViewDebug::recordTypeIndexForDINode(const DINode *Node,
479 TypeIndex TI,
480 const DIType *ClassTy) {
481 auto InsertResult = TypeIndices.insert({{Node, ClassTy}, TI});
482 (void)InsertResult;
483 assert(InsertResult.second && "DINode was already assigned a type index");
484 return TI;
485}
486
487unsigned CodeViewDebug::getPointerSizeInBytes() {
488 return MMI->getModule()->getDataLayout().getPointerSizeInBits() / 8;
489}
490
491void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
493 if (const DILocation *InlinedAt = LS->getInlinedAt()) {
494
495 const DISubprogram *Inlinee = Var.DIVar->getScope()->getSubprogram();
496 InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
497 Site.InlinedLocals.emplace_back(std::move(Var));
498 } else {
499
500 ScopeVariables[LS].emplace_back(std::move(Var));
501 }
502}
503
509
510void CodeViewDebug::maybeRecordLocation(const DebugLoc &DL,
512
514 return;
515
516 const DIScope *Scope = DL->getScope();
517 if (!Scope)
518 return;
519
520
521 LineInfo LI(DL.getLine(), DL.getLine(), true);
522 if (LI.getStartLine() != DL.getLine() || LI.isAlwaysStepInto() ||
523 LI.isNeverStepInto())
524 return;
525
526 ColumnInfo CI(DL.getCol(), 0);
527 if (CI.getStartColumn() != DL.getCol())
528 return;
529
530 if (!CurFn->HaveLineInfo)
531 CurFn->HaveLineInfo = true;
532 unsigned FileId = 0;
534 FileId = CurFn->LastFileId;
535 else
536 FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile());
538
539 unsigned FuncId = CurFn->FuncId;
540 if (const DILocation *SiteLoc = DL->getInlinedAt()) {
541 const DILocation *Loc = DL.get();
542
543
544
545 FuncId =
546 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
547
548
549 bool FirstLoc = true;
550 while ((SiteLoc = Loc->getInlinedAt())) {
551 InlineSite &Site =
552 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
553 if (!FirstLoc)
555 FirstLoc = false;
556 Loc = SiteLoc;
557 }
559 }
560
561 OS.emitCVLocDirective(FuncId, FileId, DL.getLine(), DL.getCol(),
562 false, false,
563 DL->getFilename(), SMLoc());
564}
565
566void CodeViewDebug::emitCodeViewMagicVersion() {
567 OS.emitValueToAlignment(Align(4));
568 OS.AddComment("Debug section magic");
570}
571
574 switch (DWLName) {
575 case dwarf::DW_LNAME_C:
576 return SourceLanguage::C;
577 case dwarf::DW_LNAME_C_plus_plus:
578 return SourceLanguage::Cpp;
579 case dwarf::DW_LNAME_Fortran:
580 return SourceLanguage::Fortran;
581 case dwarf::DW_LNAME_Pascal:
582 return SourceLanguage::Pascal;
583 case dwarf::DW_LNAME_Cobol:
584 return SourceLanguage::Cobol;
585 case dwarf::DW_LNAME_Java:
586 return SourceLanguage::Java;
587 case dwarf::DW_LNAME_D:
588 return SourceLanguage::D;
589 case dwarf::DW_LNAME_Swift:
590 return SourceLanguage::Swift;
591 case dwarf::DW_LNAME_Rust:
592 return SourceLanguage::Rust;
593 case dwarf::DW_LNAME_ObjC:
594 return SourceLanguage::ObjC;
595 case dwarf::DW_LNAME_ObjC_plus_plus:
596 return SourceLanguage::ObjCpp;
597 default:
598
599
600
601 return SourceLanguage::Masm;
602 }
603}
604
607 if (!MaybeLName)
609
611}
612
614
615 if (->getObjFileLowering().getCOFFDebugSymbolsSection()) {
616 Asm = nullptr;
617 return;
618 }
619
620 CompilerInfoAsm = Asm;
622
623
625 if (Asm->hasDebugInfo()) {
626 Node = *M->debug_compile_units_begin();
627 } else {
628
629
630 NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
632 Asm = nullptr;
633 return;
634 }
636 }
637
640 CurrentSourceLanguage =
646 if (!M->getCodeViewFlag() ||
648 Asm = nullptr;
649 return;
650 }
651
652 collectGlobalVariableInfo();
653
654
657 EmitDebugGlobalHashes = GH && !GH->isZero();
658}
659
661 if (!CompilerInfoAsm)
662 return;
663
664
665
666
667
668
669
670
671 switchToDebugSectionForSymbol(nullptr);
672
674 emitObjName();
675 emitCompilerInformation();
676 endCVSubsection(CompilerInfo);
677 if ()
678 return;
679
680 emitSecureHotPatchInformation();
681
682 emitInlineeLinesSubsection();
683
684
685 for (auto &P : FnDebugInfo)
686 if (.first->isDeclarationForLinker())
687 emitDebugInfoForFunction(P.first, *P.second);
688
689
690
691
692 collectDebugInfoForGlobals();
693
694
695 emitDebugInfoForRetainedTypes();
696
697
698 setCurrentSubprogram(nullptr);
699 emitDebugInfoForGlobals();
700
701
702
703 switchToDebugSectionForSymbol(nullptr);
704
705
706 if (!GlobalUDTs.empty()) {
708 emitDebugInfoForUDTs(GlobalUDTs);
709 endCVSubsection(SymbolsEnd);
710 }
711
712
713 OS.AddComment("File index to string table offset subsection");
714 OS.emitCVFileChecksumsDirective();
715
716
717 OS.AddComment("String table");
718 OS.emitCVStringTableDirective();
719
720
721
722
723 emitBuildInfo();
724
725
726
727 emitTypeInformation();
728
729 if (EmitDebugGlobalHashes)
730 emitTypeGlobalHashes();
731
732 clear();
733}
734
735static void
737 unsigned MaxFixedRecordLength = 0xF00) {
738
739
740
741
744 NullTerminatedString.push_back('\0');
745 OS.emitBytes(NullTerminatedString);
746}
747
748void CodeViewDebug::emitTypeInformation() {
749 if (TypeTable.empty())
750 return;
751
752
753 OS.switchSection(Asm->getObjFileLowering().getCOFFDebugTypesSection());
754 emitCodeViewMagicVersion();
755
756 TypeTableCollection Table(TypeTable.records());
757 TypeVisitorCallbackPipeline Pipeline;
758
759
760 CVMCAdapter CVMCOS(OS, Table);
761 TypeRecordMapping typeMapping(CVMCOS);
763
764 std::optional B = Table.getFirst();
765 while (B) {
766
767 CVType Record = Table.getType(*B);
768
770
771 if (E) {
774 }
775
777 }
778}
779
780void CodeViewDebug::emitTypeGlobalHashes() {
781 if (TypeTable.empty())
782 return;
783
784
785
786 OS.switchSection(Asm->getObjFileLowering().getCOFFGlobalTypeHashesSection());
787
788 OS.emitValueToAlignment(Align(4));
789 OS.AddComment("Magic");
791 OS.AddComment("Section Version");
792 OS.emitInt16(0);
793 OS.AddComment("Hash Algorithm");
794 OS.emitInt16(uint16_t(GlobalTypeHashAlg::BLAKE3));
795
797 for (const auto &GHR : TypeTable.hashes()) {
798 if (OS.isVerboseAsm()) {
799
800
802 raw_svector_ostream CommentOS(Comment);
803 CommentOS << formatv("{0:X+} [{1}]", TI.getIndex(), GHR);
804 OS.AddComment(Comment);
805 ++TI;
806 }
807 assert(GHR.Hash.size() == 8);
808 StringRef S(reinterpret_cast<const char *>(GHR.Hash.data()),
809 GHR.Hash.size());
810 OS.emitBinaryData(S);
811 }
812}
813
814void CodeViewDebug::emitObjName() {
815 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);
816
817 StringRef PathRef(CompilerInfoAsm->TM.Options.ObjectFilenameForDebug);
818 llvm::SmallString<256> PathStore(PathRef);
819
820 if (PathRef.empty() || PathRef == "-") {
821
822 PathRef = {};
823 } else {
824 PathRef = PathStore;
825 }
826
827 OS.AddComment("Signature");
828 OS.emitIntValue(0, 4);
829
830 OS.AddComment("Object name");
832
833 endSymbolRecord(CompilerEnd);
834}
835
836void CodeViewDebug::emitSecureHotPatchInformation() {
837 MCSymbol *hotPatchInfo = nullptr;
838
839 for (const auto &F : MMI->getModule()->functions()) {
840 if (.isDeclarationForLinker() &&
841 F.hasFnAttribute("marked_for_windows_hot_patching")) {
842 if (hotPatchInfo == nullptr)
843 hotPatchInfo = beginCVSubsection(DebugSubsectionKind::Symbols);
844 MCSymbol *HotPatchEnd = beginSymbolRecord(SymbolKind::S_HOTPATCHFUNC);
845 auto *SP = F.getSubprogram();
846 OS.AddComment("Function");
847 OS.emitInt32(getFuncIdForSubprogram(SP).getIndex());
848 OS.AddComment("Name");
850 endSymbolRecord(HotPatchEnd);
851 }
852 }
853
854 if (hotPatchInfo != nullptr)
855 endCVSubsection(hotPatchInfo);
856}
857
858namespace {
860 int Part[4];
861};
862}
863
864
865
867 Version V = {{0}};
868 int N = 0;
869 for (const char C : Name) {
870 if (isdigit(C)) {
871 V.Part[N] *= 10;
873 V.Part[N] =
874 std::min(V.Part[N], std::numeric_limits<uint16_t>::max());
875 } else if (C == '.') {
876 ++N;
877 if (N >= 4)
878 return V;
879 } else if (N > 0)
880 return V;
881 }
882 return V;
883}
884
885void CodeViewDebug::emitCompilerInformation() {
886 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
887 uint32_t Flags = 0;
888
889
890 Flags = CurrentSourceLanguage;
891
892 if (MMI->getModule()->getProfileSummary( false) != nullptr) {
893 Flags |= static_cast<uint32_t>(CompileSym3Flags::PGO);
894 }
896 ArchType Arch = MMI->getModule()->getTargetTriple().getArch();
897 if (CompilerInfoAsm->TM.Options.Hotpatch || Arch == ArchType::thumb ||
898 Arch == ArchType::aarch64) {
899 Flags |= static_cast<uint32_t>(CompileSym3Flags::HotPatch);
900 }
901
902 OS.AddComment("Flags and language");
903 OS.emitInt32(Flags);
904
905 OS.AddComment("CPUType");
906 OS.emitInt16(static_cast<uint64_t>(TheCPU));
907
908 StringRef CompilerVersion = "0";
909 if (TheCU)
910 CompilerVersion = TheCU->getProducer();
911
913 OS.AddComment("Frontend version");
914 for (int N : FrontVer.Part) {
915 OS.emitInt16(N);
916 }
917
918
919
920
921 int Major = 1000 * LLVM_VERSION_MAJOR +
922 10 * LLVM_VERSION_MINOR +
923 LLVM_VERSION_PATCH;
924
925 Major = std::min(Major, std::numeric_limits<uint16_t>::max());
926 Version BackVer = {{ Major, 0, 0, 0 }};
927 OS.AddComment("Backend version");
928 for (int N : BackVer.Part)
929 OS.emitInt16(N);
930
931 OS.AddComment("Null-terminated compiler version string");
933
934 endSymbolRecord(CompilerEnd);
935}
936
942
943void CodeViewDebug::emitBuildInfo() {
944
945
946
947
948
949
950
951
952
953
955 NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
956 const MDNode *Node = *CUs->operands().begin();
958 const DIFile *MainSourceFile = CU->getFile();
963
969 TypeTable, Asm->TM.Options.MCOptions.CommandlineArgs);
970
971 BuildInfoRecord BIR(BuildInfoArgs);
972 TypeIndex BuildInfoIndex = TypeTable.writeLeafType(BIR);
973
974
975
976 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
977 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
978 OS.AddComment("LF_BUILDINFO index");
979 OS.emitInt32(BuildInfoIndex.getIndex());
980 endSymbolRecord(BIEnd);
981 endCVSubsection(BISubsecEnd);
982}
983
984void CodeViewDebug::emitInlineeLinesSubsection() {
985 if (InlinedSubprograms.empty())
986 return;
987
988 OS.AddComment("Inlinee lines subsection");
989 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
990
991
992
993
994
995 OS.AddComment("Inlinee lines signature");
996 OS.emitInt32(unsigned(InlineeLinesSignature::Normal));
997
998 for (const DISubprogram *SP : InlinedSubprograms) {
999 assert(TypeIndices.count({SP, nullptr}));
1000 TypeIndex InlineeIdx = TypeIndices[{SP, nullptr}];
1001
1002 OS.addBlankLine();
1003 unsigned FileId = maybeRecordFile(SP->getFile());
1004 OS.AddComment("Inlined function " + SP->getName() + " starts at " +
1005 SP->getFilename() + Twine(':') + Twine(SP->getLine()));
1006 OS.addBlankLine();
1007 OS.AddComment("Type index of inlined function");
1008 OS.emitInt32(InlineeIdx.getIndex());
1009 OS.AddComment("Offset into filechecksum table");
1010 OS.emitCVFileChecksumOffsetDirective(FileId);
1011 OS.AddComment("Starting line number");
1012 OS.emitInt32(SP->getLine());
1013 }
1014
1015 endCVSubsection(InlineEnd);
1016}
1017
1018void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
1021 assert(TypeIndices.count({Site.Inlinee, nullptr}));
1022 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee, nullptr}];
1023
1024
1025 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
1026
1027 OS.AddComment("PtrParent");
1028 OS.emitInt32(0);
1029 OS.AddComment("PtrEnd");
1030 OS.emitInt32(0);
1031 OS.AddComment("Inlinee type index");
1032 OS.emitInt32(InlineeIdx.getIndex());
1033
1034 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
1035 unsigned StartLineNum = Site.Inlinee->getLine();
1036
1037 OS.emitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum,
1038 FI.Begin, FI.End);
1039
1040 endSymbolRecord(InlineEnd);
1041
1042 emitLocalVariableList(FI, Site.InlinedLocals);
1043
1044
1045 for (const DILocation *ChildSite : Site.ChildSites) {
1046 auto I = FI.InlineSites.find(ChildSite);
1047 assert(I != FI.InlineSites.end() &&
1048 "child site not in function inline site map");
1049 emitInlinedCallSite(FI, ChildSite, I->second);
1050 }
1051
1052
1053 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1054}
1055
1056void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) {
1057
1058
1059
1060 MCSectionCOFF *GVSec =
1061 GVSym ? static_cast<MCSectionCOFF *>(&GVSym->getSection()) : nullptr;
1063
1064 auto *DebugSec = static_cast<MCSectionCOFF *>(
1065 CompilerInfoAsm->getObjFileLowering().getCOFFDebugSymbolsSection());
1066 DebugSec = OS.getContext().getAssociativeCOFFSection(DebugSec, KeySym);
1067
1068 OS.switchSection(DebugSec);
1069
1070
1071
1072 if (ComdatDebugSections.insert(DebugSec).second)
1073 emitCodeViewMagicVersion();
1074}
1075
1076
1077
1078void CodeViewDebug::emitDebugInfoForThunk(const Function *GV,
1079 FunctionInfo &FI,
1081 std::string FuncName =
1083 const ThunkOrdinal ordinal = ThunkOrdinal::Standard;
1084
1085 OS.AddComment("Symbol subsection for " + Twine(FuncName));
1086 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1087
1088
1089 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1090 OS.AddComment("PtrParent");
1091 OS.emitInt32(0);
1092 OS.AddComment("PtrEnd");
1093 OS.emitInt32(0);
1094 OS.AddComment("PtrNext");
1095 OS.emitInt32(0);
1096 OS.AddComment("Thunk section relative address");
1097 OS.emitCOFFSecRel32(Fn, 0);
1098 OS.AddComment("Thunk section index");
1099 OS.emitCOFFSectionIndex(Fn);
1100 OS.AddComment("Code size");
1101 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 2);
1102 OS.AddComment("Ordinal");
1103 OS.emitInt8(unsigned(ordinal));
1104 OS.AddComment("Function name");
1106
1107 endSymbolRecord(ThunkRecordEnd);
1108
1109
1110
1111
1112
1113 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1114
1115 endCVSubsection(SymbolsEnd);
1116}
1117
1118void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
1119 FunctionInfo &FI) {
1120
1121
1122 const MCSymbol *Fn = Asm->getSymbol(GV);
1124
1125
1126 switchToDebugSectionForSymbol(Fn);
1127
1128 std::string FuncName;
1131 setCurrentSubprogram(SP);
1132
1133 if (SP->isThunk()) {
1134 emitDebugInfoForThunk(GV, FI, Fn);
1135 return;
1136 }
1137
1138
1139
1140 if (->getName().empty())
1141 FuncName = getFullyQualifiedName(SP->getScope(), SP->getName());
1142
1143
1144 if (FuncName.empty())
1146
1147
1148 if (MMI->getModule()->getTargetTriple().getArch() == Triple::x86)
1149 OS.emitCVFPOData(Fn);
1150
1151
1152 OS.AddComment("Symbol subsection for " + Twine(FuncName));
1153 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1154 {
1156 : SymbolKind::S_GPROC32_ID;
1157 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1158
1159
1160 OS.AddComment("PtrParent");
1161 OS.emitInt32(0);
1162 OS.AddComment("PtrEnd");
1163 OS.emitInt32(0);
1164 OS.AddComment("PtrNext");
1165 OS.emitInt32(0);
1166
1167
1168 OS.AddComment("Code size");
1169 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 4);
1170 OS.AddComment("Offset after prologue");
1171 OS.emitInt32(0);
1172 OS.AddComment("Offset before epilogue");
1173 OS.emitInt32(0);
1174 OS.AddComment("Function type index");
1175 OS.emitInt32(getFuncIdForSubprogram(GV->getSubprogram()).getIndex());
1176 OS.AddComment("Function section relative address");
1177 OS.emitCOFFSecRel32(Fn, 0);
1178 OS.AddComment("Function section index");
1179 OS.emitCOFFSectionIndex(Fn);
1180 OS.AddComment("Flags");
1181 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;
1182 if (FI.HasFramePointer)
1183 ProcFlags |= ProcSymFlags::HasFP;
1185 ProcFlags |= ProcSymFlags::IsNoReturn;
1187 ProcFlags |= ProcSymFlags::IsNoInline;
1188 OS.emitInt8(static_cast<uint8_t>(ProcFlags));
1189
1190 OS.AddComment("Function name");
1191
1193 endSymbolRecord(ProcRecordEnd);
1194
1195 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1196
1197 OS.AddComment("FrameSize");
1198 OS.emitInt32(FI.FrameSize - FI.CSRSize);
1199 OS.AddComment("Padding");
1200 OS.emitInt32(0);
1201 OS.AddComment("Offset of padding");
1202 OS.emitInt32(0);
1203 OS.AddComment("Bytes of callee saved registers");
1204 OS.emitInt32(FI.CSRSize);
1205 OS.AddComment("Exception handler offset");
1206 OS.emitInt32(0);
1207 OS.AddComment("Exception handler section");
1208 OS.emitInt16(0);
1209 OS.AddComment("Flags (defines frame register)");
1210 OS.emitInt32(uint32_t(FI.FrameProcOpts));
1211 endSymbolRecord(FrameProcEnd);
1212
1213 emitInlinees(FI.Inlinees);
1214 emitLocalVariableList(FI, FI.Locals);
1215 emitGlobalVariableList(FI.Globals);
1216 emitLexicalBlockList(FI.ChildBlocks, FI);
1217
1218
1219
1220
1221 for (const DILocation *InlinedAt : FI.ChildSites) {
1222 auto I = FI.InlineSites.find(InlinedAt);
1223 assert(I != FI.InlineSites.end() &&
1224 "child site not in function inline site map");
1225 emitInlinedCallSite(FI, InlinedAt, I->second);
1226 }
1227
1228 for (auto Annot : FI.Annotations) {
1231 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1232 OS.emitCOFFSecRel32(Label, 0);
1233
1234 OS.emitCOFFSectionIndex(Label);
1237
1238
1240 assert(Str.data()[Str.size()] == '\0' && "non-nullterminated MDString");
1241 OS.emitBytes(StringRef(Str.data(), Str.size() + 1));
1242 }
1243 endSymbolRecord(AnnotEnd);
1244 }
1245
1246 for (auto HeapAllocSite : FI.HeapAllocSites) {
1247 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1248 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1249 const DIType *DITy = std::get<2>(HeapAllocSite);
1250 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1251 OS.AddComment("Call site offset");
1252 OS.emitCOFFSecRel32(BeginLabel, 0);
1253 OS.AddComment("Call site section index");
1254 OS.emitCOFFSectionIndex(BeginLabel);
1255 OS.AddComment("Call instruction length");
1256 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
1257 OS.AddComment("Type index");
1258 OS.emitInt32(getCompleteTypeIndex(DITy).getIndex());
1259 endSymbolRecord(HeapAllocEnd);
1260 }
1261
1262 if (SP != nullptr)
1263 emitDebugInfoForUDTs(LocalUDTs);
1264
1265 emitDebugInfoForJumpTables(FI);
1266
1267
1268 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1269 }
1270 endCVSubsection(SymbolsEnd);
1271
1272
1273 OS.emitCVLinetableDirective(FI.FuncId, Fn, FI.End);
1274}
1275
1277CodeViewDebug::createDefRangeMem(uint16_t CVRegister, int Offset) {
1280 DR.DataOffset = Offset;
1281 assert(DR.DataOffset == Offset && "truncation");
1282 DR.IsSubfield = 0;
1283 DR.StructOffset = 0;
1284 DR.CVRegister = CVRegister;
1285 return DR;
1286}
1287
1288void CodeViewDebug::collectVariableInfoFromMFTable(
1290 const MachineFunction &MF = *Asm->MF;
1291 const TargetSubtargetInfo &TSI = MF.getSubtarget();
1294
1295 for (const MachineFunction::VariableDbgInfo &VI :
1297 if (.Var)
1298 continue;
1299 assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&
1300 "Expected inlined-at fields to agree");
1301
1302 Processed.insert(InlinedEntity(VI.Var, VI.Loc->getInlinedAt()));
1303 LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc);
1304
1305
1306 if (!Scope)
1307 continue;
1308
1309
1310
1311 int64_t ExprOffset = 0;
1312 bool Deref = false;
1313 if (VI.Expr) {
1314
1315 if (VI.Expr->getNumElements() == 1 &&
1316 VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)
1317 Deref = true;
1318 else if (.Expr->extractIfOffset(ExprOffset))
1319 continue;
1320 }
1321
1322
1324 StackOffset FrameOffset =
1326 uint16_t CVReg = TRI->getCodeViewRegNum(FrameReg);
1327
1329
1330 continue;
1331 }
1332
1333
1335 createDefRangeMem(CVReg, FrameOffset.getFixed() + ExprOffset);
1336
1337 LocalVariable Var;
1338 Var.DIVar = VI.Var;
1339
1343 End = End ? End : Asm->getFunctionEnd();
1344 Var.DefRanges[DefRange].emplace_back(Begin, End);
1345 }
1346
1347 if (Deref)
1348 Var.UseReferenceType = true;
1349
1350 recordLocalVariable(std::move(Var), Scope);
1351 }
1352}
1353
1355 return .LoadChain.empty() && Loc.LoadChain.back() == 0;
1356}
1357
1359 return Loc.LoadChain.size() == 2 && Loc.LoadChain.back() == 0;
1360}
1361
1362void CodeViewDebug::calculateRanges(
1364 const TargetRegisterInfo *TRI = Asm->MF->getSubtarget().getRegisterInfo();
1365
1366
1367 for (auto I = Entries.begin(), E = Entries.end(); I != E; ++I) {
1369 if (.isDbgValue())
1370 continue;
1371 const MachineInstr *DVInst = Entry.getInstr();
1373
1374
1375 std::optional Location =
1377 if (!Location)
1378 {
1379
1380
1381
1382
1383
1385 if (Op.isImm())
1386 Var.ConstantValue = APSInt(APInt(64, Op.getImm()), false);
1387 continue;
1388 }
1389
1390
1391
1392
1393
1394
1395
1396
1397 if (Var.UseReferenceType) {
1398
1400 Location->LoadChain.pop_back();
1401 else
1402 continue;
1404
1405
1406 Var.UseReferenceType = true;
1407 Var.DefRanges.clear();
1408 calculateRanges(Var, Entries);
1409 return;
1410 }
1411
1412
1414 continue;
1415
1416
1417
1419 if (Location->FragmentInfo->OffsetInBits % 8)
1420 continue;
1421
1422 if (TRI->isIgnoredCVReg(Location->Register)) {
1423
1424 continue;
1425 }
1426
1429 DR.InMemory = ->LoadChain.empty();
1430 DR.DataOffset =
1431 ->LoadChain.empty() ? Location->LoadChain.back() : 0;
1432 if (Location->FragmentInfo) {
1433 DR.IsSubfield = true;
1434 DR.StructOffset = Location->FragmentInfo->OffsetInBits / 8;
1435 } else {
1436 DR.IsSubfield = false;
1437 DR.StructOffset = 0;
1438 }
1439
1440
1444 auto &EndingEntry = Entries[Entry.getEndIndex()];
1445 End = EndingEntry.isDbgValue()
1448 } else
1449 End = Asm->getFunctionEnd();
1450
1451
1452
1453 SmallVectorImpl<std::pair<const MCSymbol *, const MCSymbol *>> &R =
1454 Var.DefRanges[DR];
1455 if (.empty() && R.back().second == Begin)
1456 R.back().second = End;
1457 else
1458 R.emplace_back(Begin, End);
1459
1460
1461 }
1462}
1463
1464void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
1465 DenseSet Processed;
1466
1467 collectVariableInfoFromMFTable(Processed);
1468
1470 InlinedEntity IV = I.first;
1472 continue;
1474 const DILocation *InlinedAt = IV.second;
1475
1476
1477 const auto &Entries = I.second;
1478
1479 LexicalScope *Scope = nullptr;
1480 if (InlinedAt)
1482 else
1484
1485 if (!Scope)
1486 continue;
1487
1488 LocalVariable Var;
1489 Var.DIVar = DIVar;
1490
1491 calculateRanges(Var, Entries);
1492 recordLocalVariable(std::move(Var), Scope);
1493 }
1494}
1495
1501 auto Insertion = FnDebugInfo.insert({&GV, std::make_unique()});
1502 assert(Insertion.second && "function already has info");
1503 CurFn = Insertion.first->second.get();
1504 CurFn->FuncId = NextFuncId++;
1505 CurFn->Begin = Asm->getFunctionBegin();
1506
1507
1508
1509
1513 CurFn->HasStackRealignment = TRI->hasStackRealignment(*MF);
1514
1515
1516
1519 if (CurFn->FrameSize > 0) {
1523 } else {
1524 CurFn->HasFramePointer = true;
1525
1527 if (CurFn->HasStackRealignment) {
1528
1530 } else {
1531
1532
1534 }
1535 }
1536 }
1537
1538
1544
1551 else
1553 }
1560 if (GV.hasFnAttribute(Attribute::StackProtectStrong) ||
1563 }
1565
1567 }
1576 }
1577
1578 CurFn->FrameProcOpts = FPO;
1579
1580 OS.emitCVFuncIdDirective(CurFn->FuncId);
1581
1582
1583
1584
1585
1587 bool EmptyPrologue = true;
1588 for (const auto &MBB : *MF) {
1589 for (const auto &MI : MBB) {
1591 MI.getDebugLoc()) {
1593 break;
1594 } else if (.isMetaInstruction()) {
1595 EmptyPrologue = false;
1596 }
1597 }
1598 }
1599
1600
1603 maybeRecordLocation(FnStartDL, MF);
1604 }
1605
1606
1607 for (const auto &MBB : *MF) {
1608 for (const auto &MI : MBB) {
1609 if (MI.getHeapAllocMarker()) {
1612 }
1613 }
1614 }
1615
1616
1617 bool isThumb = MMI->getModule()->getTargetTriple().getArch() ==
1619 discoverJumpTableBranches(MF, isThumb);
1620}
1621
1623 if ()
1624 return false;
1625
1626
1627 if (T->getTag() == dwarf::DW_TAG_typedef) {
1628 if (DIScope *Scope = T->getScope()) {
1629 switch (Scope->getTag()) {
1630 case dwarf::DW_TAG_structure_type:
1631 case dwarf::DW_TAG_class_type:
1632 case dwarf::DW_TAG_union_type:
1633 return false;
1634 default:
1635
1636 ;
1637 }
1638 }
1639 }
1640
1641 while (true) {
1642 if ( || T->isForwardDecl())
1643 return false;
1644
1646 if (!DT)
1647 return true;
1648 T = DT->getBaseType();
1649 }
1650 return true;
1651}
1652
1653void CodeViewDebug::addToUDTs(const DIType *Ty) {
1654
1656 return;
1658 return;
1659
1661 const DISubprogram *ClosestSubprogram =
1662 collectParentScopeNames(Ty->getScope(), ParentScopeNames);
1663
1664 std::string FullyQualifiedName =
1666
1667 if (ClosestSubprogram == nullptr) {
1668 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1669 } else if (ClosestSubprogram == CurrentSubprogram) {
1670 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1671 }
1672
1673
1674
1675
1676
1677
1678
1679}
1680
1681TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) {
1682
1683 switch (Ty->getTag()) {
1684 case dwarf::DW_TAG_array_type:
1686 case dwarf::DW_TAG_typedef:
1688 case dwarf::DW_TAG_base_type:
1690 case dwarf::DW_TAG_pointer_type:
1693 [[fallthrough]];
1694 case dwarf::DW_TAG_reference_type:
1695 case dwarf::DW_TAG_rvalue_reference_type:
1697 case dwarf::DW_TAG_ptr_to_member_type:
1699 case dwarf::DW_TAG_restrict_type:
1700 case dwarf::DW_TAG_const_type:
1701 case dwarf::DW_TAG_volatile_type:
1702
1704 case dwarf::DW_TAG_subroutine_type:
1705 if (ClassTy) {
1706
1707
1709 0,
1710 false);
1711 }
1713 case dwarf::DW_TAG_enumeration_type:
1715 case dwarf::DW_TAG_class_type:
1716 case dwarf::DW_TAG_structure_type:
1718 case dwarf::DW_TAG_union_type:
1720 case dwarf::DW_TAG_string_type:
1722 case dwarf::DW_TAG_unspecified_type:
1723 if (Ty->getName() == "decltype(nullptr)")
1726 default:
1727
1728 return TypeIndex();
1729 }
1730}
1731
1732TypeIndex CodeViewDebug::lowerTypeAlias(const DIDerivedType *Ty) {
1733 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1735
1736 addToUDTs(Ty);
1737
1738 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) &&
1739 TypeName == "HRESULT")
1740 return TypeIndex(SimpleTypeKind::HResult);
1741 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::UInt16Short) &&
1742 TypeName == "wchar_t")
1743 return TypeIndex(SimpleTypeKind::WideCharacter);
1744
1745 return UnderlyingTypeIndex;
1746}
1747
1748TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) {
1750 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1751
1752 TypeIndex IndexType = getPointerSizeInBytes() == 8
1753 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1755
1756 uint64_t ElementSize = getBaseTypeSize(ElementType) / 8;
1757
1758
1760 for (int i = Elements.size() - 1; i >= 0; --i) {
1761 const DINode *Element = Elements[i];
1762 assert(Element->getTag() == dwarf::DW_TAG_subrange_type);
1763
1765 int64_t Count = -1;
1766
1767
1768
1769
1770
1772 Count = CI->getSExtValue();
1774 Subrange->getUpperBound())) {
1775
1778 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1779 Count = UI->getSExtValue() - Lowerbound + 1;
1780 }
1781
1782
1783
1784
1785
1786 if (Count == -1)
1788
1789
1790 ElementSize *= Count;
1791
1792
1793
1794 uint64_t ArraySize =
1795 (i == 0 && ElementSize == 0) ? Ty->getSizeInBits() / 8 : ElementSize;
1796
1797 StringRef Name = (i == 0) ? Ty->getName() : "";
1798 ArrayRecord AR(ElementTypeIndex, IndexType, ArraySize, Name);
1799 ElementTypeIndex = TypeTable.writeLeafType(AR);
1800 }
1801
1802 return ElementTypeIndex;
1803}
1804
1805
1806
1807
1808
1809
1810TypeIndex CodeViewDebug::lowerTypeString(const DIStringType *Ty) {
1811 TypeIndex CharType = TypeIndex(SimpleTypeKind::NarrowCharacter);
1814
1815 TypeIndex IndexType = getPointerSizeInBytes() == 8
1816 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1818
1819
1820 ArrayRecord AR(CharType, IndexType, ArraySize, Name);
1821
1822 return TypeTable.writeLeafType(AR);
1823}
1824
1825TypeIndex CodeViewDebug::lowerTypeBasic(const DIBasicType *Ty) {
1826 TypeIndex Index;
1828 uint32_t ByteSize;
1829
1832
1834 switch (Kind) {
1835 case dwarf::DW_ATE_address:
1836
1837 break;
1838 case dwarf::DW_ATE_boolean:
1839 switch (ByteSize) {
1840 case 1: STK = SimpleTypeKind::Boolean8; break;
1841 case 2: STK = SimpleTypeKind::Boolean16; break;
1842 case 4: STK = SimpleTypeKind::Boolean32; break;
1843 case 8: STK = SimpleTypeKind::Boolean64; break;
1844 case 16: STK = SimpleTypeKind::Boolean128; break;
1845 }
1846 break;
1847 case dwarf::DW_ATE_complex_float:
1848
1849
1850 switch (ByteSize) {
1851 case 4: STK = SimpleTypeKind::Complex16; break;
1852 case 8: STK = SimpleTypeKind::Complex32; break;
1853 case 16: STK = SimpleTypeKind::Complex64; break;
1854 case 20: STK = SimpleTypeKind::Complex80; break;
1855 case 32: STK = SimpleTypeKind::Complex128; break;
1856 }
1857 break;
1858 case dwarf::DW_ATE_float:
1859 switch (ByteSize) {
1860 case 2: STK = SimpleTypeKind::Float16; break;
1861 case 4: STK = SimpleTypeKind::Float32; break;
1862 case 6: STK = SimpleTypeKind::Float48; break;
1863 case 8: STK = SimpleTypeKind::Float64; break;
1864 case 10: STK = SimpleTypeKind::Float80; break;
1865 case 16: STK = SimpleTypeKind::Float128; break;
1866 }
1867 break;
1868 case dwarf::DW_ATE_signed:
1869 switch (ByteSize) {
1870 case 1: STK = SimpleTypeKind::SignedCharacter; break;
1871 case 2: STK = SimpleTypeKind::Int16Short; break;
1872 case 4: STK = SimpleTypeKind::Int32; break;
1873 case 8: STK = SimpleTypeKind::Int64Quad; break;
1874 case 16: STK = SimpleTypeKind::Int128Oct; break;
1875 }
1876 break;
1877 case dwarf::DW_ATE_unsigned:
1878 switch (ByteSize) {
1879 case 1: STK = SimpleTypeKind::UnsignedCharacter; break;
1880 case 2: STK = SimpleTypeKind::UInt16Short; break;
1881 case 4: STK = SimpleTypeKind::UInt32; break;
1882 case 8: STK = SimpleTypeKind::UInt64Quad; break;
1883 case 16: STK = SimpleTypeKind::UInt128Oct; break;
1884 }
1885 break;
1886 case dwarf::DW_ATE_UTF:
1887 switch (ByteSize) {
1888 case 1: STK = SimpleTypeKind::Character8; break;
1889 case 2: STK = SimpleTypeKind::Character16; break;
1890 case 4: STK = SimpleTypeKind::Character32; break;
1891 }
1892 break;
1893 case dwarf::DW_ATE_signed_char:
1894 if (ByteSize == 1)
1895 STK = SimpleTypeKind::SignedCharacter;
1896 break;
1897 case dwarf::DW_ATE_unsigned_char:
1898 if (ByteSize == 1)
1899 STK = SimpleTypeKind::UnsignedCharacter;
1900 break;
1901 default:
1902 break;
1903 }
1904
1905
1906
1907
1908
1909 if (STK == SimpleTypeKind::Int32 &&
1910 (Ty->getName() == "long int" || Ty->getName() == "long"))
1911 STK = SimpleTypeKind::Int32Long;
1912 if (STK == SimpleTypeKind::UInt32 && (Ty->getName() == "long unsigned int" ||
1913 Ty->getName() == "unsigned long"))
1914 STK = SimpleTypeKind::UInt32Long;
1915 if (STK == SimpleTypeKind::UInt16Short &&
1916 (Ty->getName() == "wchar_t" || Ty->getName() == "__wchar_t"))
1917 STK = SimpleTypeKind::WideCharacter;
1918 if ((STK == SimpleTypeKind::SignedCharacter ||
1919 STK == SimpleTypeKind::UnsignedCharacter) &&
1920 Ty->getName() == "char")
1921 STK = SimpleTypeKind::NarrowCharacter;
1922
1923 return TypeIndex(STK);
1924}
1925
1926TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty,
1928 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1929
1930
1931
1932 if (PointeeTI.isSimple() && PO == PointerOptions::None &&
1933 PointeeTI.getSimpleMode() == SimpleTypeMode::Direct &&
1934 Ty->getTag() == dwarf::DW_TAG_pointer_type) {
1936 ? SimpleTypeMode::NearPointer64
1937 : SimpleTypeMode::NearPointer32;
1939 }
1940
1942 Ty->getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1944 switch (Ty->getTag()) {
1946 case dwarf::DW_TAG_pointer_type:
1947 PM = PointerMode::Pointer;
1948 break;
1949 case dwarf::DW_TAG_reference_type:
1950 PM = PointerMode::LValueReference;
1951 break;
1952 case dwarf::DW_TAG_rvalue_reference_type:
1953 PM = PointerMode::RValueReference;
1954 break;
1955 }
1956
1958 PO |= PointerOptions::Const;
1959
1960 PointerRecord PR(PointeeTI, PK, PM, PO, Ty->getSizeInBits() / 8);
1961 return TypeTable.writeLeafType(PR);
1962}
1963
1966
1967
1968
1969 if (IsPMF) {
1971 case 0:
1974 case DINode::FlagSingleInheritance:
1976 case DINode::FlagMultipleInheritance:
1978 case DINode::FlagVirtualInheritance:
1980 }
1981 } else {
1983 case 0:
1986 case DINode::FlagSingleInheritance:
1988 case DINode::FlagMultipleInheritance:
1990 case DINode::FlagVirtualInheritance:
1992 }
1993 }
1995}
1996
1997TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty,
1999 assert(Ty->getTag() == dwarf::DW_TAG_ptr_to_member_type);
2001 TypeIndex ClassTI = getTypeIndex(Ty->getClassType());
2002 TypeIndex PointeeTI =
2003 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->getClassType() : nullptr);
2004 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2005 : PointerKind::Near32;
2006 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
2007 : PointerMode::PointerToDataMember;
2008
2011 MemberPointerInfo MPI(
2013 PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);
2014 return TypeTable.writeLeafType(PR);
2015}
2016
2017
2018
2020 switch (DwarfCC) {
2027 }
2029}
2030
2031TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) {
2035 const DIType *BaseTy = Ty;
2036 while (IsModifier && BaseTy) {
2037
2038 switch (BaseTy->getTag()) {
2039 case dwarf::DW_TAG_const_type:
2040 Mods |= ModifierOptions::Const;
2041 PO |= PointerOptions::Const;
2042 break;
2043 case dwarf::DW_TAG_volatile_type:
2044 Mods |= ModifierOptions::Volatile;
2045 PO |= PointerOptions::Volatile;
2046 break;
2047 case dwarf::DW_TAG_restrict_type:
2048
2049
2050 PO |= PointerOptions::Restrict;
2051 break;
2052 default:
2054 break;
2055 }
2056 if (IsModifier)
2058 }
2059
2060
2061
2062
2063
2064 if (BaseTy) {
2065 switch (BaseTy->getTag()) {
2066 case dwarf::DW_TAG_pointer_type:
2067 case dwarf::DW_TAG_reference_type:
2068 case dwarf::DW_TAG_rvalue_reference_type:
2070 case dwarf::DW_TAG_ptr_to_member_type:
2072 default:
2073 break;
2074 }
2075 }
2076
2077 TypeIndex ModifiedTI = getTypeIndex(BaseTy);
2078
2079
2080
2081 if (Mods == ModifierOptions::None)
2082 return ModifiedTI;
2083
2084 ModifierRecord MR(ModifiedTI, Mods);
2085 return TypeTable.writeLeafType(MR);
2086}
2087
2088TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) {
2090 for (const DIType *ArgType : Ty->getTypeArray())
2091 ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgType));
2092
2093
2094 if (ReturnAndArgTypeIndices.size() > 1 &&
2097 }
2100 if (!ReturnAndArgTypeIndices.empty()) {
2101 auto ReturnAndArgTypesRef = ArrayRef(ReturnAndArgTypeIndices);
2102 ReturnTypeIndex = ReturnAndArgTypesRef.consume_front();
2103 ArgTypeIndices = ReturnAndArgTypesRef;
2104 }
2105
2106 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2107 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2108
2110
2112 ProcedureRecord Procedure(ReturnTypeIndex, CC, FO, ArgTypeIndices.size(),
2113 ArgListIndex);
2114 return TypeTable.writeLeafType(Procedure);
2115}
2116
2117TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
2118 const DIType *ClassTy,
2119 int ThisAdjustment,
2120 bool IsStaticMethod,
2122
2123 TypeIndex ClassType = getTypeIndex(ClassTy);
2124
2125 DITypeRefArray ReturnAndArgs = Ty->getTypeArray();
2126
2127 unsigned Index = 0;
2130 if (ReturnAndArgs.size() > Index) {
2131 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
2132 }
2133
2134
2135
2136
2137 TypeIndex ThisTypeIndex;
2138 if (!IsStaticMethod && ReturnAndArgs.size() > Index) {
2139 if (const DIDerivedType *PtrTy =
2141 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2142 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2144 }
2145 }
2146 }
2147
2148 while (Index < ReturnAndArgs.size())
2149 ArgTypeIndices.push_back(getTypeIndex(ReturnAndArgs[Index++]));
2150
2151
2154
2155 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2156 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2157
2159
2160 MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FO,
2161 ArgTypeIndices.size(), ArgListIndex, ThisAdjustment);
2162 return TypeTable.writeLeafType(MFR);
2163}
2164
2165TypeIndex CodeViewDebug::lowerTypeVFTableShape(const DIDerivedType *Ty) {
2166 unsigned VSlotCount =
2169
2170 VFTableShapeRecord VFTSR(Slots);
2171 return TypeTable.writeLeafType(VFTSR);
2172}
2173
2179 case 0:
2180
2183 }
2185}
2186
2188 if (SP->isArtificial())
2190
2191
2192
2194}
2195
2197 bool Introduced) {
2198 if (SP->getFlags() & DINode::FlagStaticMember)
2200
2201 switch (SP->getVirtuality()) {
2202 case dwarf::DW_VIRTUALITY_none:
2203 break;
2204 case dwarf::DW_VIRTUALITY_virtual:
2206 case dwarf::DW_VIRTUALITY_pure_virtual:
2209 default:
2211 }
2212
2214}
2215
2217 switch (Ty->getTag()) {
2218 case dwarf::DW_TAG_class_type:
2219 return TypeRecordKind::Class;
2220 case dwarf::DW_TAG_structure_type:
2221 return TypeRecordKind::Struct;
2222 default:
2224 }
2225}
2226
2227
2228
2231
2232
2233
2234
2235 if (!Ty->getIdentifier().empty())
2237
2238
2239
2240
2244
2245
2246
2247
2248
2249 if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) {
2252 } else {
2253 for (const DIScope *Scope = ImmediateScope; Scope != nullptr;
2254 Scope = Scope->getScope()) {
2257 break;
2258 }
2259 }
2260 }
2261
2262 return CO;
2263}
2264
2265void CodeViewDebug::addUDTSrcLine(const DIType *Ty, TypeIndex TI) {
2266 switch (Ty->getTag()) {
2267 case dwarf::DW_TAG_class_type:
2268 case dwarf::DW_TAG_structure_type:
2269 case dwarf::DW_TAG_union_type:
2270 case dwarf::DW_TAG_enumeration_type:
2271 break;
2272 default:
2273 return;
2274 }
2275
2276 if (const auto *File = Ty->getFile()) {
2277 StringIdRecord SIDR(TypeIndex(0x0), getFullFilepath(File));
2278 TypeIndex SIDI = TypeTable.writeLeafType(SIDR);
2279
2280 UdtSourceLineRecord USLR(TI, SIDI, Ty->getLine());
2281 TypeTable.writeLeafType(USLR);
2282 }
2283}
2284
2285TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {
2287 TypeIndex FTI;
2288 unsigned EnumeratorCount = 0;
2289
2291 CO |= ClassOptions::ForwardReference;
2292 } else {
2293 ContinuationRecordBuilder ContinuationBuilder;
2294 ContinuationBuilder.begin(ContinuationRecordKind::FieldList);
2295 for (const DINode *Element : Ty->getElements()) {
2296
2297
2299
2300 EnumeratorRecord ER(MemberAccess::Public,
2304 EnumeratorCount++;
2305 }
2306 }
2307 FTI = TypeTable.insertRecord(ContinuationBuilder);
2308 }
2309
2310 std::string FullName = getFullyQualifiedName(Ty);
2311
2312 EnumRecord ER(EnumeratorCount, CO, FTI, FullName, Ty->getIdentifier(),
2314 TypeIndex EnumTI = TypeTable.writeLeafType(ER);
2315
2316 addUDTSrcLine(Ty, EnumTI);
2317
2318 return EnumTI;
2319}
2320
2321
2322
2323
2324
2330
2332
2334
2336
2337
2339
2340
2342
2344
2346
2348};
2349
2350void CodeViewDebug::clear() {
2351 assert(CurFn == nullptr);
2352 FileIdMap.clear();
2353 FnDebugInfo.clear();
2354 FileToFilepathMap.clear();
2355 LocalUDTs.clear();
2356 GlobalUDTs.clear();
2357 TypeIndices.clear();
2358 CompleteTypeIndices.clear();
2359 ScopeGlobals.clear();
2360 CVGlobalVariableOffsets.clear();
2361}
2362
2363void CodeViewDebug::collectMemberInfo(ClassInfo &Info,
2366 Info.Members.push_back({DDTy, 0});
2367
2368
2369 if ((DDTy->getFlags() & DINode::FlagStaticMember) ==
2370 DINode::FlagStaticMember) {
2373 StaticConstMembers.push_back(DDTy);
2374 }
2375
2376 return;
2377 }
2378
2379
2380
2381
2382
2385 const DIType *Ty = DDTy->getBaseType();
2386 bool FullyResolved = false;
2387 while (!FullyResolved) {
2388 switch (Ty->getTag()) {
2389 case dwarf::DW_TAG_const_type:
2390 case dwarf::DW_TAG_volatile_type:
2391
2392
2394 break;
2395 default:
2396 FullyResolved = true;
2397 break;
2398 }
2399 }
2400
2402 if (!DCTy)
2403 return;
2404
2405 ClassInfo NestedInfo = collectClassInfo(DCTy);
2406 for (const ClassInfo::MemberInfo &IndirectField : NestedInfo.Members)
2407 Info.Members.push_back(
2409}
2410
2412 ClassInfo Info;
2413
2415 for (auto *Element : Elements) {
2416
2417
2418 if (!Element)
2419 continue;
2421 Info.Methods[SP->getRawName()].push_back(SP);
2423 if (DDTy->getTag() == dwarf::DW_TAG_member) {
2424 collectMemberInfo(Info, DDTy);
2425 } else if (DDTy->getTag() == dwarf::DW_TAG_inheritance) {
2426 Info.Inheritance.push_back(DDTy);
2427 } else if (DDTy->getTag() == dwarf::DW_TAG_pointer_type &&
2428 DDTy->getName() == "__vtbl_ptr_type") {
2429 Info.VShapeTI = getTypeIndex(DDTy);
2430 } else if (DDTy->getTag() == dwarf::DW_TAG_typedef) {
2431 Info.NestedTypes.push_back(DDTy);
2432 } else if (DDTy->getTag() == dwarf::DW_TAG_friend) {
2433
2434
2435 }
2437 Info.NestedTypes.push_back(Composite);
2438 }
2439
2440 }
2441 return Info;
2442}
2443
2445
2446
2447 return Ty->getName().empty() && Ty->getIdentifier().empty() &&
2448 !Ty->isForwardDecl();
2449}
2450
2451TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) {
2452
2453
2454
2455
2457
2458
2459
2460 auto I = CompleteTypeIndices.find(Ty);
2461 if (I != CompleteTypeIndices.end() && I->second == TypeIndex())
2462 report_fatal_error("cannot debug circular reference to unnamed type");
2463 return getCompleteTypeIndex(Ty);
2464 }
2465
2466
2467
2471 std::string FullName = getFullyQualifiedName(Ty);
2472 ClassRecord CR(Kind, 0, CO, TypeIndex(), TypeIndex(), TypeIndex(), 0,
2474 TypeIndex FwdDeclTI = TypeTable.writeLeafType(CR);
2476 DeferredCompleteTypes.push_back(Ty);
2477 return FwdDeclTI;
2478}
2479
2480TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) {
2481
2484 TypeIndex FieldTI;
2485 TypeIndex VShapeTI;
2486 unsigned FieldCount;
2489 lowerRecordFieldList(Ty);
2490
2492 CO |= ClassOptions::ContainsNestedClass;
2493
2494
2495
2496
2497
2498
2500 CO |= ClassOptions::HasConstructorOrDestructor;
2501
2502 std::string FullName = getFullyQualifiedName(Ty);
2503
2505
2506 ClassRecord CR(Kind, FieldCount, CO, FieldTI, TypeIndex(), VShapeTI,
2508 TypeIndex ClassTI = TypeTable.writeLeafType(CR);
2509
2510 addUDTSrcLine(Ty, ClassTI);
2511
2512 addToUDTs(Ty);
2513
2514 return ClassTI;
2515}
2516
2517TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) {
2518
2520 return getCompleteTypeIndex(Ty);
2521
2524 std::string FullName = getFullyQualifiedName(Ty);
2525 UnionRecord UR(0, CO, TypeIndex(), 0, FullName, Ty->getIdentifier());
2526 TypeIndex FwdDeclTI = TypeTable.writeLeafType(UR);
2528 DeferredCompleteTypes.push_back(Ty);
2529 return FwdDeclTI;
2530}
2531
2532TypeIndex CodeViewDebug::lowerCompleteTypeUnion(const DICompositeType *Ty) {
2534 TypeIndex FieldTI;
2535 unsigned FieldCount;
2538 lowerRecordFieldList(Ty);
2539
2541 CO |= ClassOptions::ContainsNestedClass;
2542
2544 std::string FullName = getFullyQualifiedName(Ty);
2545
2546 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2548 TypeIndex UnionTI = TypeTable.writeLeafType(UR);
2549
2550 addUDTSrcLine(Ty, UnionTI);
2551
2552 addToUDTs(Ty);
2553
2554 return UnionTI;
2555}
2556
2557std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2558CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
2559
2560
2561
2562
2563 unsigned MemberCount = 0;
2564 ClassInfo Info = collectClassInfo(Ty);
2565 ContinuationRecordBuilder ContinuationBuilder;
2566 ContinuationBuilder.begin(ContinuationRecordKind::FieldList);
2567
2568
2569 for (const DIDerivedType *I : Info.Inheritance) {
2570 if (I->getFlags() & DINode::FlagVirtual) {
2571
2572 unsigned VBPtrOffset = I->getVBPtrOffset();
2573
2574 unsigned VBTableIndex = I->getOffsetInBits() / 4;
2575 auto RecordKind = (I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2576 ? TypeRecordKind::IndirectVirtualBaseClass
2577 : TypeRecordKind::VirtualBaseClass;
2578 VirtualBaseClassRecord VBCR(
2580 getTypeIndex(I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2581 VBTableIndex);
2582
2584 MemberCount++;
2585 } else {
2586 assert(I->getOffsetInBits() % 8 == 0 &&
2587 "bases must be on byte boundaries");
2589 getTypeIndex(I->getBaseType()),
2590 I->getOffsetInBits() / 8);
2592 MemberCount++;
2593 }
2594 }
2595
2596
2597 for (ClassInfo::MemberInfo &MemberInfo : Info.Members) {
2599 TypeIndex MemberBaseType = getTypeIndex(Member->getBaseType());
2600 StringRef MemberName = Member->getName();
2603
2604 if (Member->isStaticMember()) {
2605 StaticDataMemberRecord SDMR(Access, MemberBaseType, MemberName);
2607 MemberCount++;
2608 continue;
2609 }
2610
2611
2612 if ((Member->getFlags() & DINode::FlagArtificial) &&
2613 Member->getName().starts_with("_vptr$")) {
2614 VFPtrRecord VFPR(getTypeIndex(Member->getBaseType()));
2616 MemberCount++;
2617 continue;
2618 }
2619
2620
2621 uint64_t MemberOffsetInBits =
2623 if (Member->isBitField()) {
2624 uint64_t StartBitOffset = MemberOffsetInBits;
2625 if (const auto *CI =
2627 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.BaseOffset;
2628 }
2629 StartBitOffset -= MemberOffsetInBits;
2630 BitFieldRecord BFR(MemberBaseType, Member->getSizeInBits(),
2631 StartBitOffset);
2632 MemberBaseType = TypeTable.writeLeafType(BFR);
2633 }
2634 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2635 DataMemberRecord DMR(Access, MemberBaseType, MemberOffsetInBytes,
2636 MemberName);
2638 MemberCount++;
2639 }
2640
2641
2642 for (auto &MethodItr : Info.Methods) {
2643 StringRef Name = MethodItr.first->getString();
2644
2645 std::vector Methods;
2646 for (const DISubprogram *SP : MethodItr.second) {
2647 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2648 bool Introduced = SP->getFlags() & DINode::FlagIntroducedVirtual;
2649
2650 unsigned VFTableOffset = -1;
2651 if (Introduced)
2652 VFTableOffset = SP->getVirtualIndex() * getPointerSizeInBytes();
2653
2654 Methods.push_back(OneMethodRecord(
2658 MemberCount++;
2659 }
2660 assert(!Methods.empty() && "Empty methods map entry");
2661 if (Methods.size() == 1)
2663 else {
2664
2665
2666 MethodOverloadListRecord MOLR(Methods);
2667 TypeIndex MethodList = TypeTable.writeLeafType(MOLR);
2668
2669 OverloadedMethodRecord OMR(Methods.size(), MethodList, Name);
2671 }
2672 }
2673
2674
2675 for (const DIType *Nested : Info.NestedTypes) {
2676 NestedTypeRecord R(getTypeIndex(Nested), Nested->getName());
2678 MemberCount++;
2679 }
2680
2681 TypeIndex FieldTI = TypeTable.insertRecord(ContinuationBuilder);
2682 return std::make_tuple(FieldTI, Info.VShapeTI, MemberCount,
2683 .NestedTypes.empty());
2684}
2685
2686TypeIndex CodeViewDebug::getVBPTypeIndex() {
2687 if (!VBPType.getIndex()) {
2688
2689 ModifierRecord MR(TypeIndex::Int32(), ModifierOptions::Const);
2690 TypeIndex ModifiedTI = TypeTable.writeLeafType(MR);
2691
2692 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2693 : PointerKind::Near32;
2696 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2697 VBPType = TypeTable.writeLeafType(PR);
2698 }
2699
2700 return VBPType;
2701}
2702
2703TypeIndex CodeViewDebug::getTypeIndex(const DIType *Ty, const DIType *ClassTy) {
2704
2705 if (!Ty)
2707
2708
2709
2710
2711 auto I = TypeIndices.find({Ty, ClassTy});
2712 if (I != TypeIndices.end())
2713 return I->second;
2714
2716 TypeIndex TI = lowerType(Ty, ClassTy);
2717 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2718}
2719
2721CodeViewDebug::getTypeIndexForThisPtr(const DIDerivedType *PtrTy,
2723 assert(PtrTy->getTag() == dwarf::DW_TAG_pointer_type &&
2724 "this type must be a pointer type");
2725
2727 if (SubroutineTy->getFlags() & DINode::DIFlags::FlagLValueReference)
2728 Options = PointerOptions::LValueRefThisPointer;
2729 else if (SubroutineTy->getFlags() & DINode::DIFlags::FlagRValueReference)
2730 Options = PointerOptions::RValueRefThisPointer;
2731
2732
2733
2734
2735
2736
2737 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2738 if (I != TypeIndices.end())
2739 return I->second;
2740
2742 TypeIndex TI = lowerTypePointer(PtrTy, Options);
2743 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2744}
2745
2746TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(const DIType *Ty) {
2747 PointerRecord PR(getTypeIndex(Ty),
2748 getPointerSizeInBytes() == 8 ? PointerKind::Near64
2749 : PointerKind::Near32,
2750 PointerMode::LValueReference, PointerOptions::None,
2752 return TypeTable.writeLeafType(PR);
2753}
2754
2755TypeIndex CodeViewDebug::getCompleteTypeIndex(const DIType *Ty) {
2756
2757 if (!Ty)
2759
2760
2761
2762
2763 if (Ty->getTag() == dwarf::DW_TAG_typedef)
2764 (void)getTypeIndex(Ty);
2765 while (Ty->getTag() == dwarf::DW_TAG_typedef)
2767
2768
2769
2770 switch (Ty->getTag()) {
2771 case dwarf::DW_TAG_class_type:
2772 case dwarf::DW_TAG_structure_type:
2773 case dwarf::DW_TAG_union_type:
2774 break;
2775 default:
2776 return getTypeIndex(Ty);
2777 }
2778
2780
2782
2783
2784
2785
2786
2787 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2788 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2789
2790
2791
2792
2793 if (CTy->isForwardDecl())
2794 return FwdDeclTI;
2795 }
2796
2797
2798
2799
2800 auto InsertResult = CompleteTypeIndices.try_emplace(CTy);
2801 if (!InsertResult.second)
2802 return InsertResult.first->second;
2803
2804 TypeIndex TI;
2805 switch (CTy->getTag()) {
2806 case dwarf::DW_TAG_class_type:
2807 case dwarf::DW_TAG_structure_type:
2808 TI = lowerCompleteTypeClass(CTy);
2809 break;
2810 case dwarf::DW_TAG_union_type:
2811 TI = lowerCompleteTypeUnion(CTy);
2812 break;
2813 default:
2815 }
2816
2817
2818
2819
2820
2821 CompleteTypeIndices[CTy] = TI;
2822 return TI;
2823}
2824
2825
2826
2827
2828
2829void CodeViewDebug::emitDeferredCompleteTypes() {
2831 while (!DeferredCompleteTypes.empty()) {
2832 std::swap(DeferredCompleteTypes, TypesToEmit);
2833 for (const DICompositeType *RecordTy : TypesToEmit)
2834 getCompleteTypeIndex(RecordTy);
2835 TypesToEmit.clear();
2836 }
2837}
2838
2839void CodeViewDebug::emitLocalVariableList(const FunctionInfo &FI,
2841
2843 for (const LocalVariable &L : Locals)
2844 if (L.DIVar->isParameter())
2846 llvm::sort(Params, [](const LocalVariable *L, const LocalVariable *R) {
2847 return L->DIVar->getArg() < R->DIVar->getArg();
2848 });
2849 for (const LocalVariable *L : Params)
2850 emitLocalVariable(FI, *L);
2851
2852
2853 for (const LocalVariable &L : Locals) {
2854 if (.DIVar->isParameter()) {
2855 if (L.ConstantValue) {
2856
2857
2858 const DIType *Ty = L.DIVar->getType();
2859 APSInt Val(*L.ConstantValue);
2860 emitConstantSymbolRecord(Ty, Val, std::string(L.DIVar->getName()));
2861 } else {
2862 emitLocalVariable(FI, L);
2863 }
2864 }
2865 }
2866}
2867
2868void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI,
2869 const LocalVariable &Var) {
2870
2871 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2872
2874 if (Var.DIVar->isParameter())
2875 Flags |= LocalSymFlags::IsParameter;
2876 if (Var.DefRanges.empty())
2877 Flags |= LocalSymFlags::IsOptimizedOut;
2878
2879 OS.AddComment("TypeIndex");
2880 TypeIndex TI = Var.UseReferenceType
2881 ? getTypeIndexForReferenceTo(Var.DIVar->getType())
2882 : getCompleteTypeIndex(Var.DIVar->getType());
2883 OS.emitInt32(TI.getIndex());
2884 OS.AddComment("Flags");
2885 OS.emitInt16(static_cast<uint16_t>(Flags));
2886
2888 endSymbolRecord(LocalEnd);
2889
2890
2891
2892
2893 SmallString<20> BytePrefix;
2894 for (const auto &Pair : Var.DefRanges) {
2895 LocalVarDef DefRange = Pair.first;
2896 const auto &Ranges = Pair.second;
2897 BytePrefix.clear();
2898 if (DefRange.InMemory) {
2899 int Offset = DefRange.DataOffset;
2900 unsigned Reg = DefRange.CVRegister;
2901
2902
2903
2904
2905 if (RegisterId(Reg) == RegisterId::ESP) {
2906 Reg = unsigned(RegisterId::VFRAME);
2907 Offset += FI.OffsetAdjustment;
2908 }
2909
2910
2911
2912
2913 EncodedFramePtrReg EncFP = encodeFramePtrReg(RegisterId(Reg), TheCPU);
2914 if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2915 (bool(Flags & LocalSymFlags::IsParameter)
2916 ? (EncFP == FI.EncodedParamFramePtrReg)
2917 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2918 DefRangeFramePointerRelHeader DRHdr;
2919 DRHdr.Offset = Offset;
2920 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2921 } else {
2922 uint16_t RegRelFlags = 0;
2923 if (DefRange.IsSubfield) {
2924 RegRelFlags = DefRangeRegisterRelSym::IsSubfieldFlag |
2925 (DefRange.StructOffset
2926 << DefRangeRegisterRelSym::OffsetInParentShift);
2927 }
2928 DefRangeRegisterRelHeader DRHdr;
2929 DRHdr.Register = Reg;
2930 DRHdr.Flags = RegRelFlags;
2931 DRHdr.BasePointerOffset = Offset;
2932 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2933 }
2934 } else {
2935 assert(DefRange.DataOffset == 0 && "unexpected offset into register");
2936 if (DefRange.IsSubfield) {
2937 DefRangeSubfieldRegisterHeader DRHdr;
2938 DRHdr.Register = DefRange.CVRegister;
2939 DRHdr.MayHaveNoName = 0;
2940 DRHdr.OffsetInParent = DefRange.StructOffset;
2941 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2942 } else {
2943 DefRangeRegisterHeader DRHdr;
2944 DRHdr.Register = DefRange.CVRegister;
2945 DRHdr.MayHaveNoName = 0;
2946 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2947 }
2948 }
2949 }
2950}
2951
2953 const FunctionInfo& FI) {
2954 for (LexicalBlock *Block : Blocks)
2955 emitLexicalBlock(*Block, FI);
2956}
2957
2958
2959
2960void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,
2961 const FunctionInfo& FI) {
2962 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2963 OS.AddComment("PtrParent");
2964 OS.emitInt32(0);
2965 OS.AddComment("PtrEnd");
2966 OS.emitInt32(0);
2967 OS.AddComment("Code size");
2968 OS.emitAbsoluteSymbolDiff(Block.End, Block.Begin, 4);
2969 OS.AddComment("Function section relative address");
2970 OS.emitCOFFSecRel32(Block.Begin, 0);
2971 OS.AddComment("Function section index");
2972 OS.emitCOFFSectionIndex(FI.Begin);
2973 OS.AddComment("Lexical block name");
2975 endSymbolRecord(RecordEnd);
2976
2977
2978 emitLocalVariableList(FI, Block.Locals);
2979 emitGlobalVariableList(Block.Globals);
2980
2981
2982 emitLexicalBlockList(Block.Children, FI);
2983
2984
2985 emitEndSymbolRecord(SymbolKind::S_END);
2986}
2987
2988
2989
2990void CodeViewDebug::collectLexicalBlockInfo(
2995 for (LexicalScope *Scope : Scopes)
2996 collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
2997}
2998
2999
3000
3001void CodeViewDebug::collectLexicalBlockInfo(
3006 if (Scope.isAbstractScope())
3007 return;
3008
3009
3010
3011 bool IgnoreScope = false;
3012 auto LI = ScopeVariables.find(&Scope);
3013 SmallVectorImpl *Locals =
3014 LI != ScopeVariables.end() ? &LI->second : nullptr;
3015 auto GI = ScopeGlobals.find(Scope.getScopeNode());
3016 SmallVectorImpl *Globals =
3017 GI != ScopeGlobals.end() ? GI->second.get() : nullptr;
3019 const SmallVectorImpl &Ranges = Scope.getRanges();
3020
3021
3022 if (!Locals && !Globals)
3023 IgnoreScope = true;
3024
3025
3026 if (!DILB)
3027 IgnoreScope = true;
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3041 IgnoreScope = true;
3042
3043 if (IgnoreScope) {
3044
3045
3046
3047
3048 if (Locals)
3050 if (Globals)
3051 ParentGlobals.append(Globals->begin(), Globals->end());
3052 collectLexicalBlockInfo(Scope.getChildren(),
3053 ParentBlocks,
3054 ParentLocals,
3055 ParentGlobals);
3056 return;
3057 }
3058
3059
3060
3061
3062 auto BlockInsertion = CurFn->LexicalBlocks.try_emplace(DILB);
3063 if (!BlockInsertion.second)
3064 return;
3065
3066
3067
3070 LexicalBlock &Block = BlockInsertion.first->second;
3073 assert(Block.Begin && "missing label for scope begin");
3074 assert(Block.End && "missing label for scope end");
3076 if (Locals)
3077 Block.Locals = std::move(*Locals);
3078 if (Globals)
3079 Block.Globals = std::move(*Globals);
3081 collectLexicalBlockInfo(Scope.getChildren(),
3085}
3086
3089 assert(FnDebugInfo.count(&GV));
3090 assert(CurFn == FnDebugInfo[&GV].get());
3091
3093
3094
3096 collectLexicalBlockInfo(*CFS,
3097 CurFn->ChildBlocks,
3098 CurFn->Locals,
3099 CurFn->Globals);
3100
3101
3102
3103
3104 ScopeVariables.clear();
3105
3106
3107
3108 if (!CurFn->HaveLineInfo && !GV.getSubprogram()->isThunk()) {
3109 FnDebugInfo.erase(&GV);
3110 CurFn = nullptr;
3111 return;
3112 }
3113
3114
3115 for (const auto &MBB : *MF) {
3116 for (const auto &MI : MBB) {
3117 if (MDNode *MD = MI.getHeapAllocMarker()) {
3121 }
3122 }
3123 }
3124
3125 bool isThumb = MMI->getModule()->getTargetTriple().getArch() ==
3127 collectDebugInfoForJumpTables(MF, isThumb);
3128
3130
3131 CurFn->End = Asm->getFunctionEnd();
3132
3133 CurFn = nullptr;
3134}
3135
3136
3137
3138
3139
3141 return DL && DL.getLine() != 0;
3142}
3143
3146
3147
3148 if ( || !CurFn || MI->isDebugInstr() ||
3150 return;
3151
3152
3153
3156 for (const auto &NextMI : *MI->getParent()) {
3157 if (NextMI.isDebugInstr())
3158 continue;
3159 DL = NextMI.getDebugLoc();
3161 break;
3162 }
3163
3164
3165 }
3167
3168
3170 return;
3171
3172 maybeRecordLocation(DL, Asm->MF);
3173}
3174
3182 return EndLabel;
3183}
3184
3185void CodeViewDebug::endCVSubsection(MCSymbol *EndLabel) {
3187
3189}
3190
3193 if (EE.Value == SymKind)
3194 return EE.Name;
3195 return "";
3196}
3197
3199 MCSymbol *BeginLabel = MMI->getContext().createTempSymbol(),
3200 *EndLabel = MMI->getContext().createTempSymbol();
3201 OS.AddComment("Record length");
3202 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
3203 OS.emitLabel(BeginLabel);
3204 if (OS.isVerboseAsm())
3205 OS.AddComment("Record kind: " + getSymbolName(SymKind));
3206 OS.emitInt16(unsigned(SymKind));
3207 return EndLabel;
3208}
3209
3210void CodeViewDebug::endSymbolRecord(MCSymbol *SymEnd) {
3211
3212
3213
3214
3215 OS.emitValueToAlignment(Align(4));
3216 OS.emitLabel(SymEnd);
3217}
3218
3219void CodeViewDebug::emitEndSymbolRecord(SymbolKind EndKind) {
3220 OS.AddComment("Record length");
3221 OS.emitInt16(2);
3222 if (OS.isVerboseAsm())
3223 OS.AddComment("Record kind: " + getSymbolName(EndKind));
3224 OS.emitInt16(uint16_t(EndKind));
3225}
3226
3227void CodeViewDebug::emitDebugInfoForUDTs(
3228 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3229#ifndef NDEBUG
3230 size_t OriginalSize = UDTs.size();
3231#endif
3232 for (const auto &UDT : UDTs) {
3233 const DIType *T = UDT.second;
3235 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3236 OS.AddComment("Type");
3237 OS.emitInt32(getCompleteTypeIndex(T).getIndex());
3238 assert(OriginalSize == UDTs.size() &&
3239 "getCompleteTypeIndex found new UDTs!");
3241 endSymbolRecord(UDTRecordEnd);
3242 }
3243}
3244
3245void CodeViewDebug::collectGlobalVariableInfo() {
3246 DenseMap<const DIGlobalVariableExpression *, const GlobalVariable *>
3247 GlobalMap;
3248 for (const GlobalVariable &GV : MMI->getModule()->globals()) {
3250 GV.getDebugInfo(GVEs);
3251 for (const auto *GVE : GVEs)
3252 GlobalMap[GVE] = &GV;
3253 }
3254
3255 NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
3256 for (const MDNode *Node : CUs->operands()) {
3258 for (const auto *GVE : CU->getGlobalVariables()) {
3259 const DIGlobalVariable *DIGV = GVE->getVariable();
3260 const DIExpression *DIE = GVE->getExpression();
3261
3262
3263
3264
3266
3268 (DIE->getElement(0) == dwarf::DW_OP_plus_uconst))
3269
3270
3271
3272
3273 CVGlobalVariableOffsets.insert(
3274 std::make_pair(DIGV, DIE->getElement(1)));
3275
3276
3278 CVGlobalVariable CVGV = {DIGV, DIE};
3279 GlobalVariables.emplace_back(std::move(CVGV));
3280 }
3281
3282 const auto *GV = GlobalMap.lookup(GVE);
3284 continue;
3285
3287 SmallVector<CVGlobalVariable, 1> *VariableList;
3289
3290
3291 auto Insertion = ScopeGlobals.insert(
3292 {Scope, std::unique_ptr()});
3293 if (Insertion.second)
3294 Insertion.first->second = std::make_unique();
3295 VariableList = Insertion.first->second.get();
3297
3298 VariableList = &ComdatVariables;
3299 else
3300
3301 VariableList = &GlobalVariables;
3302 CVGlobalVariable CVGV = {DIGV, GV};
3303 VariableList->emplace_back(std::move(CVGV));
3304 }
3305 }
3306}
3307
3308void CodeViewDebug::collectDebugInfoForGlobals() {
3309 for (const CVGlobalVariable &CVGV : GlobalVariables) {
3310 const DIGlobalVariable *DIGV = CVGV.DIGV;
3312 getCompleteTypeIndex(DIGV->getType());
3313 getFullyQualifiedName(Scope, DIGV->getName());
3314 }
3315
3316 for (const CVGlobalVariable &CVGV : ComdatVariables) {
3317 const DIGlobalVariable *DIGV = CVGV.DIGV;
3319 getCompleteTypeIndex(DIGV->getType());
3320 getFullyQualifiedName(Scope, DIGV->getName());
3321 }
3322}
3323
3324void CodeViewDebug::emitDebugInfoForGlobals() {
3325
3326
3327
3328 switchToDebugSectionForSymbol(nullptr);
3329 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3330 OS.AddComment("Symbol subsection for globals");
3331 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3332 emitGlobalVariableList(GlobalVariables);
3333 emitStaticConstMemberList();
3334 endCVSubsection(EndLabel);
3335 }
3336
3337
3338
3339 for (const CVGlobalVariable &CVGV : ComdatVariables) {
3342 OS.AddComment("Symbol subsection for " +
3344 switchToDebugSectionForSymbol(GVSym);
3345 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3346
3347 emitDebugInfoForGlobal(CVGV);
3348 endCVSubsection(EndLabel);
3349 }
3350}
3351
3352void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3353 NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
3354 for (const MDNode *Node : CUs->operands()) {
3357 getTypeIndex(RT);
3358
3359 }
3360 }
3361 }
3362}
3363
3364
3366 for (const CVGlobalVariable &CVGV : Globals) {
3367
3368 emitDebugInfoForGlobal(CVGV);
3369 }
3370}
3371
3372void CodeViewDebug::emitConstantSymbolRecord(const DIType *DTy, APSInt &Value,
3373 const std::string &QualifiedName) {
3374 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3375 OS.AddComment("Type");
3376 OS.emitInt32(getTypeIndex(DTy).getIndex());
3377
3378 OS.AddComment("Value");
3379
3380
3381 uint8_t Data[10];
3383 CodeViewRecordIO IO(Writer);
3385 StringRef SRef((char *)Data, Writer.getOffset());
3386 OS.emitBinaryData(SRef);
3387
3388 OS.AddComment("Name");
3390 endSymbolRecord(SConstantEnd);
3391}
3392
3393void CodeViewDebug::emitStaticConstMemberList() {
3394 for (const DIDerivedType *DTy : StaticConstMembers) {
3396
3398 if (const ConstantInt *CI =
3402 else if (const ConstantFP *CFP =
3404 Value = APSInt(CFP->getValueAPF().bitcastToAPInt(), true);
3405 else
3407
3408 emitConstantSymbolRecord(DTy->getBaseType(), Value,
3409 getFullyQualifiedName(Scope, DTy->getName()));
3410 }
3411}
3412
3415 return false;
3416
3419 if (T == dwarf::DW_TAG_pointer_type ||
3420 T == dwarf::DW_TAG_ptr_to_member_type ||
3421 T == dwarf::DW_TAG_reference_type ||
3422 T == dwarf::DW_TAG_rvalue_reference_type)
3423 return false;
3424 assert(DTy->getBaseType() && "Expected valid base type");
3426 }
3427
3429 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3430}
3431
3432void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) {
3433 const DIGlobalVariable *DIGV = CVGV.DIGV;
3434
3436
3439 Scope = MemberDecl->getScope();
3440
3441
3442
3445 ? std::string(DIGV->getName())
3446 : getFullyQualifiedName(Scope, DIGV->getName());
3447
3448 if (const GlobalVariable *GV =
3450
3451
3452 MCSymbol *GVSym = Asm->getSymbol(GV);
3453 SymbolKind DataSym = GV->isThreadLocal()
3454 ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32
3455 : SymbolKind::S_GTHREAD32)
3456 : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32
3457 : SymbolKind::S_GDATA32);
3458 MCSymbol *DataEnd = beginSymbolRecord(DataSym);
3459 OS.AddComment("Type");
3460 OS.emitInt32(getCompleteTypeIndex(DIGV->getType()).getIndex());
3461 OS.AddComment("DataOffset");
3462
3463
3464 uint64_t Offset = CVGlobalVariableOffsets.lookup(DIGV);
3465 OS.emitCOFFSecRel32(GVSym, Offset);
3466
3467 OS.AddComment("Segment");
3468 OS.emitCOFFSectionIndex(GVSym);
3469 OS.AddComment("Name");
3470 const unsigned LengthOfDataRecord = 12;
3471 emitNullTerminatedSymbolName(OS, QualifiedName, LengthOfDataRecord);
3472 endSymbolRecord(DataEnd);
3473 } else {
3474 const DIExpression *DIE = cast<const DIExpression *>(CVGV.GVInfo);
3475 assert(DIE->isConstant() &&
3476 "Global constant variables must contain a constant expression.");
3477
3478
3479 bool isUnsigned = isFloatDIType(DIGV->getType())
3480 ? true
3481 : DebugHandlerBase::isUnsignedDIType(DIGV->getType());
3482 APSInt Value(APInt(64, DIE->getElement(1)), isUnsigned);
3483 emitConstantSymbolRecord(DIGV->getType(), Value, QualifiedName);
3484 }
3485}
3486
3490 int64_t)> &Callback) {
3492 if (JTI && !JTI->isEmpty()) {
3493#ifndef NDEBUG
3495#endif
3496 for (const auto &MBB : *MF) {
3497
3498 const auto LastMI = MBB.getFirstTerminator();
3499 if (LastMI != MBB.end() && LastMI->isIndirectBranch()) {
3501
3502
3503
3504
3505
3506
3507 for (const auto &MO : LastMI->operands()) {
3508 if (MO.isJTI()) {
3509 unsigned Index = MO.getIndex();
3510#ifndef NDEBUG
3511 UsedJTs.set(Index);
3512#endif
3513 Callback(*JTI, *LastMI, Index);
3514 break;
3515 }
3516 }
3517 } else {
3518
3519
3520
3521 for (auto I = MBB.instr_rbegin(), E = MBB.instr_rend(); I != E; ++I) {
3522 if (I->isJumpTableDebugInfo()) {
3523 unsigned Index = I->getOperand(0).getImm();
3524#ifndef NDEBUG
3525 UsedJTs.set(Index);
3526#endif
3527 Callback(*JTI, *LastMI, Index);
3528 break;
3529 }
3530 }
3531 }
3532 }
3533 }
3534#ifndef NDEBUG
3535 assert(UsedJTs.all() &&
3536 "Some of jump tables were not used in a debug info instruction");
3537#endif
3538 }
3539}
3540
3541void CodeViewDebug::discoverJumpTableBranches(const MachineFunction *MF,
3545 [this](const MachineJumpTableInfo &, const MachineInstr &BranchMI,
3547}
3548
3549void CodeViewDebug::collectDebugInfoForJumpTables(const MachineFunction *MF,
3553 [this, MF](const MachineJumpTableInfo &JTI, const MachineInstr &BranchMI,
3554 int64_t JumpTableIndex) {
3555
3556
3557
3559 uint64_t BaseOffset = 0;
3567 "EK_Custom32, EK_GPRel32BlockAddress, and "
3568 "EK_GPRel64BlockAddress should never be emitted for COFF");
3570
3571 EntrySize = JumpTableEntrySize::Pointer;
3572 Base = nullptr;
3573 break;
3577
3578 std::tie(Base, BaseOffset, Branch, EntrySize) =
3579 Asm->getCodeViewJumpTableInfo(JumpTableIndex, &BranchMI, Branch);
3580 break;
3581 }
3582
3583 const MachineJumpTableEntry &JTE = JTI.getJumpTables()[JumpTableIndex];
3584 JumpTableInfo CVJTI{EntrySize,
3586 BaseOffset,
3589 JTE.MBBs.size(),
3590 {}};
3591 for (const auto &MBB : JTE.MBBs)
3593 CurFn->JumpTables.push_back(std::move(CVJTI));
3594 });
3595}
3596
3597void CodeViewDebug::emitDebugInfoForJumpTables(const FunctionInfo &FI) {
3598
3599 for (const auto &JumpTable : FI.JumpTables) {
3600 for (const auto &CaseSym : JumpTable.Cases) {
3601 MCSymbol *LabelEnd = beginSymbolRecord(SymbolKind::S_LABEL32);
3602 OS.AddComment("Offset and segment");
3603 OS.emitCOFFSecRel32(CaseSym, 0);
3604 OS.AddComment("Flags");
3605 OS.emitInt8(0);
3607 endSymbolRecord(LabelEnd);
3608 }
3609 }
3610
3611 for (const auto &JumpTable : FI.JumpTables) {
3612 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3614 OS.AddComment("Base offset");
3616 OS.AddComment("Base section index");
3617 OS.emitCOFFSectionIndex(JumpTable.Base);
3618 } else {
3619 OS.AddComment("Base offset");
3620 OS.emitInt32(0);
3621 OS.AddComment("Base section index");
3622 OS.emitInt16(0);
3623 }
3624 OS.AddComment("Switch type");
3625 OS.emitInt16(static_cast<uint16_t>(JumpTable.EntrySize));
3626 OS.AddComment("Branch offset");
3627 OS.emitCOFFSecRel32(JumpTable.Branch, 0);
3628 OS.AddComment("Table offset");
3629 OS.emitCOFFSecRel32(JumpTable.Table, 0);
3630 OS.AddComment("Branch section index");
3631 OS.emitCOFFSectionIndex(JumpTable.Branch);
3632 OS.AddComment("Table section index");
3633 OS.emitCOFFSectionIndex(JumpTable.Table);
3634 OS.AddComment("Entries count");
3635 OS.emitInt32(JumpTable.TableSize);
3636 endSymbolRecord(JumpTableEnd);
3637 }
3638}
3639
3640void CodeViewDebug::emitInlinees(
3642
3643
3644 constexpr size_t ChunkSize =
3646 sizeof(uint32_t);
3647
3650
3651 size_t CurrentIndex = 0;
3652 while (CurrentIndex < SortedInlinees.size()) {
3653 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3654 auto CurrentChunkSize =
3655 std::min(ChunkSize, SortedInlinees.size() - CurrentIndex);
3656 OS.AddComment("Count");
3657 OS.emitInt32(CurrentChunkSize);
3658
3659 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3660 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3661 OS.AddComment("Inlinee");
3662 OS.emitInt32(SortedInlinees[CurrentIndex].getIndex());
3663 }
3664 endSymbolRecord(Symbol);
3665 }
3666}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
static bool canUseReferenceType(const DbgVariableLocation &Loc)
Definition CodeViewDebug.cpp:1354
static MethodKind translateMethodKindFlags(const DISubprogram *SP, bool Introduced)
Definition CodeViewDebug.cpp:2196
static bool isUsableDebugLoc(DebugLoc DL)
Definition CodeViewDebug.cpp:3140
static TypeIndex getStringIdTypeIdx(GlobalTypeTableBuilder &TypeTable, StringRef S)
Definition CodeViewDebug.cpp:937
static CPUType mapArchToCVCPUType(Triple::ArchType Type)
Definition CodeViewDebug.cpp:114
static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S, unsigned MaxFixedRecordLength=0xF00)
Definition CodeViewDebug.cpp:736
static Version parseVersion(StringRef Name)
Definition CodeViewDebug.cpp:866
static MethodOptions translateMethodOptionFlags(const DISubprogram *SP)
Definition CodeViewDebug.cpp:2187
static bool isNonTrivial(const DICompositeType *DCTy)
Definition CodeViewDebug.cpp:421
static std::string formatNestedName(ArrayRef< StringRef > QualifiedNameComponents, StringRef TypeName)
Definition CodeViewDebug.cpp:301
static ClassOptions getCommonClassOptions(const DICompositeType *Ty)
Return ClassOptions that should be present on both the forward declaration and the defintion of a tag...
Definition CodeViewDebug.cpp:2229
static PointerToMemberRepresentation translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags)
Definition CodeViewDebug.cpp:1965
static FunctionOptions getFunctionOptions(const DISubroutineType *Ty, const DICompositeType *ClassTy=nullptr, StringRef SPName=StringRef(""))
Definition CodeViewDebug.cpp:426
static StringRef removeTemplateArgs(StringRef Name)
Definition CodeViewDebug.cpp:369
static TypeRecordKind getRecordKind(const DICompositeType *Ty)
Definition CodeViewDebug.cpp:2216
void forEachJumpTableBranch(const MachineFunction *MF, bool isThumb, const std::function< void(const MachineJumpTableInfo &, const MachineInstr &, int64_t)> &Callback)
Definition CodeViewDebug.cpp:3487
static CallingConvention dwarfCCToCodeView(unsigned DwarfCC)
Given a DWARF calling convention, get the CodeView equivalent.
Definition CodeViewDebug.cpp:2019
static SourceLanguage MapDWARFLanguageToCVLang(dwarf::SourceLanguageName DWLName)
Definition CodeViewDebug.cpp:573
static bool isFloatDIType(const DIType *Ty)
Definition CodeViewDebug.cpp:3413
static void addLocIfNotPresent(SmallVectorImpl< const DILocation * > &Locs, const DILocation *Loc)
Definition CodeViewDebug.cpp:504
static bool shouldEmitUdt(const DIType *T)
Definition CodeViewDebug.cpp:1622
static StringRef getPrettyScopeName(const DIScope *Scope)
Definition CodeViewDebug.cpp:262
static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty)
Definition CodeViewDebug.cpp:2444
static bool needsReferenceType(const DbgVariableLocation &Loc)
Definition CodeViewDebug.cpp:1358
static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags)
Definition CodeViewDebug.cpp:2174
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.
Module.h This file contains the declarations for the Module class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static StringRef getName(Value *V)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
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]
An arbitrary precision integer that knows its signedness.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
This class is intended to be used as a driving class for all asm writers.
CodeViewDebug(AsmPrinter *AP)
Definition CodeViewDebug.cpp:135
void beginModule(Module *M) override
Definition CodeViewDebug.cpp:613
bool moduleIsInFortran()
Check if the current module is in Fortran.
void endFunctionImpl(const MachineFunction *) override
Gather post-function debug information.
Definition CodeViewDebug.cpp:3087
void endModule() override
Emit the COFF section that holds the line table information.
Definition CodeViewDebug.cpp:660
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
Definition CodeViewDebug.cpp:3144
void beginFunctionImpl(const MachineFunction *MF) override
Gather pre-function debug information.
Definition CodeViewDebug.cpp:1496
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
LLVM_ABI DIType * getClassType() const
Get casted version of extra data.
LLVM_ABI Constant * getConstant() const
unsigned getNumElements() const
uint64_t getElement(unsigned I) const
LLVM_ABI std::optional< SignedOrUnsignedConstant > isConstant() const
Determine whether this represents a constant value, if so.
Metadata * getRawStaticDataMemberDeclaration() 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.
StringRef getFilename() const
LLVM_ABI StringRef getName() const
StringRef getDirectory() const
LLVM_ABI DIScope * getScope() const
Wrapper structure that holds a language name and its version.
bool hasVersionedName() const
uint16_t getName() const
Returns a versioned or unversioned language name.
String type, Fortran CHARACTER(n)
Subprogram description. Uses SubclassData1.
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
SmallVector< Entry, 4 > Entries
static const EntryIndex NoEntry
Special value to indicate that an entry is valid until the end of the function.
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.
DebugHandlerBase(AsmPrinter *A)
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.
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.
Implements a dense probed hash-table based set.
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).
Function::iterator insert(Function::iterator Position, BasicBlock *BB)
Insert BB in the basic block list at Position.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool hasLocalLinkage() const
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
bool isDeclarationForLinker() const
This class is used to track scope information.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSymbol * getCOMDATSymbol() const
Streaming machine code generation interface.
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
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 emitValueToAlignment(Align Alignment, int64_t Fill=0, uint8_t FillLen=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
void emitInt32(uint64_t Value)
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.
ArrayRef< MDOperand > operands() const
unsigned getNumOperands() const
Return number of MDNode operands.
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
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
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
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
iterator_range< op_iterator > operands()
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.
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.
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...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
LLVM_ABI 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)
LLVM_ABI void begin(ContinuationRecordKind RecordKind)
void writeMemberType(RecordType &Record)
TypeIndex writeLeafType(T &Record)
SimpleTypeKind getSimpleKind() const
SimpleTypeMode getSimpleMode() const
static const uint32_t FirstNonSimpleIndex
static LLVM_ABI 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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
@ DEBUG_HASHES_SECTION_MAGIC
@ C
The default llvm calling convention, compatible with C.
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)
CVRecord< TypeLeafKind > CVType
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.
@ MultipleInheritanceData
@ SingleInheritanceFunction
@ VirtualInheritanceFunction
@ MultipleInheritanceFunction
CallingConvention
These values correspond to the CV_call_e enumeration, and are documented at the following locations: ...
MethodOptions
Equivalent to CV_fldattr_t bitfield.
LLVM_ABI ArrayRef< EnumEntry< SymbolKind > > getSymbolTypeNames()
MemberAccess
Source-level access specifier. (CV_access_e)
ThunkOrdinal
These values correspond to the THUNK_ORDINAL enumeration.
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.
@ ProfileGuidedOptimization
@ HasStructuredExceptionHandling
LLVM_ABI StringRef getSymbolName(CVSymbol Sym)
LLVM_ABI 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,...
std::optional< std::pair< SourceLanguageName, uint32_t > > toDW_LNAME(SourceLanguage language)
Convert a DWARF 5 DW_LANG to a DWARF 6 pair of language name and version.
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...
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
NodeAddr< NodeBase * > Node
LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
FunctionAddr VTableAddr Value
std::string fromHex(StringRef Input)
Convert hexadecimal string Input to its binary representation. The return string is half the size of ...
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present - Functionally identical to dyn_cast, except that a null (or none in the case ...
std::tuple< uint64_t, uint32_t > InlineSite
LLVM_GET_TYPE_NAME_CONSTEXPR StringRef getTypeName()
We provide a function which tries to compute the (demangled) name of a type statically.
std::pair< const MachineInstr *, const MachineInstr * > InsnRange
This is used to track range of instructions with identical lexical scope.
auto dyn_cast_or_null(const Y &Val)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
FunctionAddr VTableAddr uintptr_t uintptr_t Version
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionAddr VTableAddr Count
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
@ Success
The lock was released successfully.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
decltype(auto) cast(const From &Val)
cast - 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.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition CodeViewDebug.cpp:313
CodeViewDebug & CVD
Definition CodeViewDebug.cpp:322
~TypeLoweringScope()
Definition CodeViewDebug.cpp:315
TypeLoweringScope(CodeViewDebug &CVD)
Definition CodeViewDebug.cpp:314
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition CodeViewDebug.cpp:2326
uint64_t BaseOffset
Definition CodeViewDebug.cpp:2328
const DIDerivedType * MemberTypeNode
Definition CodeViewDebug.cpp:2327
Definition CodeViewDebug.cpp:2325
std::vector< MemberInfo > MemberList
Definition CodeViewDebug.cpp:2331
MemberList Members
Direct members.
Definition CodeViewDebug.cpp:2341
std::vector< const DIType * > NestedTypes
Definition CodeViewDebug.cpp:2347
MapVector< MDString *, MethodsList > MethodsMap
Definition CodeViewDebug.cpp:2335
std::vector< const DIDerivedType * > Inheritance
Base classes.
Definition CodeViewDebug.cpp:2338
TypeIndex VShapeTI
Definition CodeViewDebug.cpp:2345
MethodsMap Methods
Definition CodeViewDebug.cpp:2343
TinyPtrVector< const DISubprogram * > MethodsList
Definition CodeViewDebug.cpp:2333
int InMemory
Indicates that variable data is stored in memory relative to the specified register.
uint32_t CVRegister
Register containing the data or the register base of the memory location containing the data.
Represents the location at which a variable is stored.
static std::optional< DbgVariableLocation > extractFromMachineInstruction(const MachineInstr &Instruction)
Extract a VariableLocation from a MachineInstr.
std::vector< MachineBasicBlock * > MBBs
MBBs - The vector of basic blocks from which to create the jump table.