33#include "llvm/Config/llvm-config.h"
80 CVMCAdapter(MCStreamer &OS, TypeCollection &TypeTable)
81 : OS(&OS), TypeTable(TypeTable) {}
83 void emitBytes(StringRef
Data)
override { OS->emitBytes(
Data); }
85 void emitIntValue(uint64_t
Value,
unsigned Size)
override {
89 void emitBinaryData(StringRef
Data)
override { OS->emitBinaryData(
Data); }
91 void AddComment(
const Twine &
T)
override { OS->AddComment(
T); }
93 void AddRawComment(
const Twine &
T)
override { OS->emitRawComment(
T); }
95 bool isVerboseAsm()
override {
return OS->isVerboseAsm(); }
103 TypeName = std::string(TypeTable.getTypeName(TI));
109 MCStreamer *OS =
nullptr;
110 TypeCollection &TypeTable;
139 std::string &Filepath = FileToFilepathMap[File];
140 if (!Filepath.empty())
143 StringRef Dir = File->getDirectory(), Filename = File->getFilename();
147 if (Dir.
starts_with(
"/") || Filename.starts_with(
"/")) {
150 Filepath = std::string(Dir);
151 if (Dir.
back() !=
'/')
153 Filepath += Filename;
161 if (Filename.find(
':') == 1)
162 Filepath = std::string(Filename);
164 Filepath = (Dir +
"\\" + Filename).str();
173 while ((Cursor = Filepath.find(
"\\.\\", Cursor)) != std::string::npos)
174 Filepath.erase(Cursor, 2);
179 while ((Cursor = Filepath.find(
"\\..\\", Cursor)) != std::string::npos) {
184 size_t PrevSlash = Filepath.rfind(
'\\', Cursor - 1);
185 if (PrevSlash == std::string::npos)
189 Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
196 while ((Cursor = Filepath.find(
"\\\\", Cursor)) != std::string::npos)
197 Filepath.erase(Cursor, 1);
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) {
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;
221 CSKind = FileChecksumKind::SHA1;
224 CSKind = FileChecksumKind::SHA256;
228 bool Success = OS.emitCVFileDirective(NextId, FullPath, ChecksumAsBytes,
229 static_cast<unsigned>(CSKind));
233 return Insertion.first->second;
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())
245 getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())
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);
256 if (InlinedAt->getInlinedAt() ==
nullptr)
257 CurFn->Inlinees.insert(InlineeIdx);
264 if (!ScopeName.
empty())
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 "<unnamed-tag>";
273 case dwarf::DW_TAG_namespace:
274 return "`anonymous namespace'";
280const DISubprogram *CodeViewDebug::collectParentScopeNames(
282 const DISubprogram *ClosestSubprogram =
nullptr;
283 while (Scope !=
nullptr) {
284 if (ClosestSubprogram ==
nullptr)
291 DeferredCompleteTypes.push_back(Ty);
294 if (!ScopeName.
empty())
295 QualifiedNameComponents.
push_back(ScopeName);
298 return ClosestSubprogram;
303 std::string FullyQualifiedName;
306 FullyQualifiedName.append(std::string(QualifiedNameComponent));
307 FullyQualifiedName.append(
"::");
309 FullyQualifiedName.append(std::string(TypeName));
310 return FullyQualifiedName;
318 if (
CVD.TypeEmissionLevel == 1)
319 CVD.emitDeferredCompleteTypes();
320 --
CVD.TypeEmissionLevel;
325std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Scope,
332 collectParentScopeNames(Scope, QualifiedNameComponents);
336std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Ty) {
358 auto I = TypeIndices.find({Scope,
nullptr});
359 if (
I != TypeIndices.end())
363 std::string ScopeName = getFullyQualifiedName(Scope);
364 StringIdRecord SID(TypeIndex(), ScopeName);
365 auto TI = TypeTable.writeLeafType(SID);
366 return recordTypeIndexForDINode(Scope, TI);
372 if (Name.empty() || Name.back() !=
'>')
375 int OpenBrackets = 0;
376 for (
int i = Name.size() - 1; i >= 0; --i) {
379 else if (Name[i] ==
'<') {
381 if (OpenBrackets == 0)
382 return Name.substr(0, i);
388TypeIndex CodeViewDebug::getFuncIdForSubprogram(
const DISubprogram *SP) {
392 auto I = TypeIndices.find({
SP,
nullptr});
393 if (
I != TypeIndices.end())
401 const DIScope *
Scope =
SP->getScope();
407 TypeIndex ClassType = getTypeIndex(Class);
408 MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class),
410 TI = TypeTable.writeLeafType(MFuncId);
413 TypeIndex ParentScope = getScopeIndex(Scope);
414 FuncIdRecord FuncId(ParentScope, getTypeIndex(
SP->getType()), DisplayName);
415 TI = TypeTable.writeLeafType(FuncId);
418 return recordTypeIndexForDINode(SP, TI);
422 return ((DCTy->
getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);
430 const DIType *ReturnTy =
nullptr;
431 if (
auto TypeArray = Ty->getTypeArray()) {
432 if (TypeArray.size())
433 ReturnTy = TypeArray[0];
443 if (ClassTy &&
isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {
452TypeIndex CodeViewDebug::getMemberFunctionType(
const DISubprogram *SP,
456 if (
SP->getDeclaration())
457 SP =
SP->getDeclaration();
458 assert(!
SP->getDeclaration() &&
"should use declaration as key");
462 auto I = TypeIndices.find({
SP,
Class});
463 if (
I != TypeIndices.end())
470 const bool IsStaticMethod = (
SP->getFlags() & DINode::FlagStaticMember) != 0;
473 TypeIndex TI = lowerTypeMemberFunction(
474 SP->getType(), Class,
SP->getThisAdjustment(), IsStaticMethod, FO);
475 return recordTypeIndexForDINode(SP, TI, Class);
478TypeIndex CodeViewDebug::recordTypeIndexForDINode(
const DINode *Node,
481 auto InsertResult = TypeIndices.insert({{
Node, ClassTy}, TI});
483 assert(InsertResult.second &&
"DINode was already assigned a type index");
487unsigned CodeViewDebug::getPointerSizeInBytes() {
488 return MMI->getModule()->getDataLayout().getPointerSizeInBits() / 8;
491void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
493 if (
const DILocation *InlinedAt =
LS->getInlinedAt()) {
495 const DISubprogram *
Inlinee = Var.DIVar->getScope()->getSubprogram();
496 InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
497 Site.InlinedLocals.emplace_back(std::move(Var));
500 ScopeVariables[
LS].emplace_back(std::move(Var));
510void CodeViewDebug::maybeRecordLocation(
const DebugLoc &
DL,
516 const DIScope *
Scope =
DL->getScope();
521 LineInfo LI(
DL.getLine(),
DL.getLine(),
true);
522 if (LI.getStartLine() !=
DL.getLine() || LI.isAlwaysStepInto() ||
523 LI.isNeverStepInto())
526 ColumnInfo CI(
DL.getCol(), 0);
527 if (CI.getStartColumn() !=
DL.getCol())
530 if (!CurFn->HaveLineInfo)
531 CurFn->HaveLineInfo =
true;
534 FileId = CurFn->LastFileId;
536 FileId = CurFn->LastFileId = maybeRecordFile(
DL->getFile());
539 unsigned FuncId = CurFn->FuncId;
540 if (
const DILocation *SiteLoc =
DL->getInlinedAt()) {
541 const DILocation *Loc =
DL.get();
546 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
549 bool FirstLoc =
true;
550 while ((SiteLoc = Loc->getInlinedAt())) {
552 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
561 OS.emitCVLocDirective(FuncId, FileId,
DL.getLine(),
DL.getCol(),
563 DL->getFilename(), SMLoc());
566void CodeViewDebug::emitCodeViewMagicVersion() {
567 OS.emitValueToAlignment(
Align(4));
568 OS.AddComment(
"Debug section magic");
574 case dwarf::DW_LANG_C:
575 case dwarf::DW_LANG_C89:
576 case dwarf::DW_LANG_C99:
577 case dwarf::DW_LANG_C11:
578 return SourceLanguage::C;
579 case dwarf::DW_LANG_C_plus_plus:
580 case dwarf::DW_LANG_C_plus_plus_03:
581 case dwarf::DW_LANG_C_plus_plus_11:
582 case dwarf::DW_LANG_C_plus_plus_14:
583 return SourceLanguage::Cpp;
584 case dwarf::DW_LANG_Fortran77:
585 case dwarf::DW_LANG_Fortran90:
586 case dwarf::DW_LANG_Fortran95:
587 case dwarf::DW_LANG_Fortran03:
588 case dwarf::DW_LANG_Fortran08:
589 return SourceLanguage::Fortran;
590 case dwarf::DW_LANG_Pascal83:
591 return SourceLanguage::Pascal;
592 case dwarf::DW_LANG_Cobol74:
593 case dwarf::DW_LANG_Cobol85:
594 return SourceLanguage::Cobol;
595 case dwarf::DW_LANG_Java:
596 return SourceLanguage::Java;
597 case dwarf::DW_LANG_D:
598 return SourceLanguage::D;
599 case dwarf::DW_LANG_Swift:
600 return SourceLanguage::Swift;
601 case dwarf::DW_LANG_Rust:
602 return SourceLanguage::Rust;
603 case dwarf::DW_LANG_ObjC:
604 return SourceLanguage::ObjC;
605 case dwarf::DW_LANG_ObjC_plus_plus:
606 return SourceLanguage::ObjCpp;
611 return SourceLanguage::Masm;
617 if (!
Asm->getObjFileLowering().getCOFFDebugSymbolsSection()) {
622 CompilerInfoAsm =
Asm;
627 if (
Asm->hasDebugInfo()) {
628 Node = *M->debug_compile_units_begin();
632 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
638 if (!M->getCodeViewFlag() ||
644 collectGlobalVariableInfo();
649 EmitDebugGlobalHashes = GH && !GH->
isZero();
653 if (!CompilerInfoAsm)
663 switchToDebugSectionForSymbol(
nullptr);
667 emitCompilerInformation();
668 endCVSubsection(CompilerInfo);
672 emitSecureHotPatchInformation();
674 emitInlineeLinesSubsection();
677 for (
auto &
P : FnDebugInfo)
678 if (!
P.first->isDeclarationForLinker())
679 emitDebugInfoForFunction(
P.first, *
P.second);
684 collectDebugInfoForGlobals();
687 emitDebugInfoForRetainedTypes();
690 setCurrentSubprogram(
nullptr);
691 emitDebugInfoForGlobals();
695 switchToDebugSectionForSymbol(
nullptr);
698 if (!GlobalUDTs.empty()) {
700 emitDebugInfoForUDTs(GlobalUDTs);
701 endCVSubsection(SymbolsEnd);
705 OS.AddComment(
"File index to string table offset subsection");
706 OS.emitCVFileChecksumsDirective();
709 OS.AddComment(
"String table");
710 OS.emitCVStringTableDirective();
719 emitTypeInformation();
721 if (EmitDebugGlobalHashes)
722 emitTypeGlobalHashes();
729 unsigned MaxFixedRecordLength = 0xF00) {
740void CodeViewDebug::emitTypeInformation() {
741 if (TypeTable.empty())
745 OS.switchSection(
Asm->getObjFileLowering().getCOFFDebugTypesSection());
746 emitCodeViewMagicVersion();
748 TypeTableCollection Table(TypeTable.records());
749 TypeVisitorCallbackPipeline Pipeline;
752 CVMCAdapter CVMCOS(OS, Table);
753 TypeRecordMapping typeMapping(CVMCOS);
756 std::optional<TypeIndex>
B = Table.getFirst();
759 CVType Record = Table.getType(*
B);
768 B = Table.getNext(*
B);
772void CodeViewDebug::emitTypeGlobalHashes() {
773 if (TypeTable.empty())
778 OS.switchSection(
Asm->getObjFileLowering().getCOFFGlobalTypeHashesSection());
780 OS.emitValueToAlignment(
Align(4));
781 OS.AddComment(
"Magic");
783 OS.AddComment(
"Section Version");
785 OS.AddComment(
"Hash Algorithm");
786 OS.emitInt16(uint16_t(GlobalTypeHashAlg::BLAKE3));
789 for (
const auto &GHR : TypeTable.hashes()) {
790 if (OS.isVerboseAsm()) {
794 raw_svector_ostream CommentOS(Comment);
796 OS.AddComment(Comment);
799 assert(GHR.Hash.size() == 8);
800 StringRef S(
reinterpret_cast<const char *
>(GHR.Hash.data()),
802 OS.emitBinaryData(S);
806void CodeViewDebug::emitObjName() {
807 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);
809 StringRef PathRef(CompilerInfoAsm->TM.Options.ObjectFilenameForDebug);
810 llvm::SmallString<256> PathStore(PathRef);
812 if (PathRef.empty() || PathRef ==
"-") {
819 OS.AddComment(
"Signature");
820 OS.emitIntValue(0, 4);
822 OS.AddComment(
"Object name");
825 endSymbolRecord(CompilerEnd);
828void CodeViewDebug::emitSecureHotPatchInformation() {
831 for (
const auto &
F :
MMI->getModule()->functions()) {
832 if (!
F.isDeclarationForLinker() &&
833 F.hasFnAttribute(
"marked_for_windows_hot_patching")) {
834 if (hotPatchInfo ==
nullptr)
835 hotPatchInfo = beginCVSubsection(DebugSubsectionKind::Symbols);
836 MCSymbol *HotPatchEnd = beginSymbolRecord(SymbolKind::S_HOTPATCHFUNC);
837 auto *
SP =
F.getSubprogram();
838 OS.AddComment(
"Function");
839 OS.emitInt32(getFuncIdForSubprogram(SP).getIndex());
840 OS.AddComment(
"Name");
842 endSymbolRecord(HotPatchEnd);
846 if (hotPatchInfo !=
nullptr)
847 endCVSubsection(hotPatchInfo);
861 for (
const char C : Name) {
864 V.Part[
N] +=
C -
'0';
866 std::min<int>(V.Part[
N], std::numeric_limits<uint16_t>::max());
867 }
else if (
C ==
'.') {
877void CodeViewDebug::emitCompilerInformation() {
878 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
882 Flags = CurrentSourceLanguage;
884 if (
MMI->getModule()->getProfileSummary(
false) !=
nullptr) {
885 Flags |=
static_cast<uint32_t
>(CompileSym3Flags::PGO);
888 ArchType Arch =
MMI->getModule()->getTargetTriple().getArch();
889 if (CompilerInfoAsm->TM.Options.Hotpatch || Arch == ArchType::thumb ||
890 Arch == ArchType::aarch64) {
891 Flags |=
static_cast<uint32_t
>(CompileSym3Flags::HotPatch);
894 OS.AddComment(
"Flags and language");
897 OS.AddComment(
"CPUType");
898 OS.emitInt16(
static_cast<uint64_t
>(TheCPU));
900 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
904 StringRef CompilerVersion = CU->getProducer();
906 OS.AddComment(
"Frontend version");
907 for (
int N : FrontVer.Part) {
914 int Major = 1000 * LLVM_VERSION_MAJOR +
915 10 * LLVM_VERSION_MINOR +
918 Major = std::min<int>(Major, std::numeric_limits<uint16_t>::max());
919 Version BackVer = {{ Major, 0, 0, 0 }};
920 OS.AddComment(
"Backend version");
921 for (
int N : BackVer.Part)
924 OS.AddComment(
"Null-terminated compiler version string");
927 endSymbolRecord(CompilerEnd);
936void CodeViewDebug::emitBuildInfo() {
948 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
951 const DIFile *MainSourceFile = CU->getFile();
962 TypeTable,
Asm->TM.Options.MCOptions.CommandlineArgs);
964 BuildInfoRecord BIR(BuildInfoArgs);
965 TypeIndex BuildInfoIndex = TypeTable.writeLeafType(BIR);
969 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
970 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
971 OS.AddComment(
"LF_BUILDINFO index");
972 OS.emitInt32(BuildInfoIndex.
getIndex());
973 endSymbolRecord(BIEnd);
974 endCVSubsection(BISubsecEnd);
977void CodeViewDebug::emitInlineeLinesSubsection() {
978 if (InlinedSubprograms.empty())
981 OS.AddComment(
"Inlinee lines subsection");
982 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
988 OS.AddComment(
"Inlinee lines signature");
989 OS.emitInt32(
unsigned(InlineeLinesSignature::Normal));
991 for (
const DISubprogram *SP : InlinedSubprograms) {
992 assert(TypeIndices.count({SP, nullptr}));
993 TypeIndex InlineeIdx = TypeIndices[{
SP,
nullptr}];
996 unsigned FileId = maybeRecordFile(
SP->getFile());
997 OS.AddComment(
"Inlined function " +
SP->getName() +
" starts at " +
998 SP->getFilename() + Twine(
':') + Twine(
SP->getLine()));
1000 OS.AddComment(
"Type index of inlined function");
1001 OS.emitInt32(InlineeIdx.
getIndex());
1002 OS.AddComment(
"Offset into filechecksum table");
1003 OS.emitCVFileChecksumOffsetDirective(FileId);
1004 OS.AddComment(
"Starting line number");
1005 OS.emitInt32(
SP->getLine());
1008 endCVSubsection(InlineEnd);
1011void CodeViewDebug::emitInlinedCallSite(
const FunctionInfo &FI,
1014 assert(TypeIndices.count({Site.Inlinee, nullptr}));
1015 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee,
nullptr}];
1018 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
1020 OS.AddComment(
"PtrParent");
1022 OS.AddComment(
"PtrEnd");
1024 OS.AddComment(
"Inlinee type index");
1025 OS.emitInt32(InlineeIdx.
getIndex());
1027 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
1028 unsigned StartLineNum = Site.Inlinee->getLine();
1030 OS.emitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum,
1033 endSymbolRecord(InlineEnd);
1035 emitLocalVariableList(FI, Site.InlinedLocals);
1038 for (
const DILocation *ChildSite : Site.ChildSites) {
1039 auto I = FI.InlineSites.find(ChildSite);
1040 assert(
I != FI.InlineSites.end() &&
1041 "child site not in function inline site map");
1042 emitInlinedCallSite(FI, ChildSite,
I->second);
1046 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1049void CodeViewDebug::switchToDebugSectionForSymbol(
const MCSymbol *GVSym) {
1053 MCSectionCOFF *GVSec =
1054 GVSym ?
static_cast<MCSectionCOFF *
>(&GVSym->
getSection()) : nullptr;
1057 auto *DebugSec =
static_cast<MCSectionCOFF *
>(
1058 CompilerInfoAsm->getObjFileLowering().getCOFFDebugSymbolsSection());
1059 DebugSec = OS.getContext().getAssociativeCOFFSection(DebugSec, KeySym);
1061 OS.switchSection(DebugSec);
1065 if (ComdatDebugSections.insert(DebugSec).second)
1066 emitCodeViewMagicVersion();
1071void CodeViewDebug::emitDebugInfoForThunk(
const Function *GV,
1074 std::string FuncName =
1078 OS.AddComment(
"Symbol subsection for " + Twine(FuncName));
1079 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1082 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1083 OS.AddComment(
"PtrParent");
1085 OS.AddComment(
"PtrEnd");
1087 OS.AddComment(
"PtrNext");
1089 OS.AddComment(
"Thunk section relative address");
1090 OS.emitCOFFSecRel32(Fn, 0);
1091 OS.AddComment(
"Thunk section index");
1092 OS.emitCOFFSectionIndex(Fn);
1093 OS.AddComment(
"Code size");
1094 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 2);
1095 OS.AddComment(
"Ordinal");
1096 OS.emitInt8(
unsigned(ordinal));
1097 OS.AddComment(
"Function name");
1100 endSymbolRecord(ThunkRecordEnd);
1106 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1108 endCVSubsection(SymbolsEnd);
1111void CodeViewDebug::emitDebugInfoForFunction(
const Function *GV,
1119 switchToDebugSectionForSymbol(Fn);
1121 std::string FuncName;
1124 setCurrentSubprogram(SP);
1126 if (
SP->isThunk()) {
1127 emitDebugInfoForThunk(GV, FI, Fn);
1133 if (!
SP->getName().empty())
1134 FuncName = getFullyQualifiedName(
SP->getScope(),
SP->getName());
1137 if (FuncName.empty())
1141 if (
MMI->getModule()->getTargetTriple().getArch() ==
Triple::x86)
1142 OS.emitCVFPOData(Fn);
1145 OS.AddComment(
"Symbol subsection for " + Twine(FuncName));
1146 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1149 : SymbolKind::S_GPROC32_ID;
1150 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1153 OS.AddComment(
"PtrParent");
1155 OS.AddComment(
"PtrEnd");
1157 OS.AddComment(
"PtrNext");
1161 OS.AddComment(
"Code size");
1162 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 4);
1163 OS.AddComment(
"Offset after prologue");
1165 OS.AddComment(
"Offset before epilogue");
1167 OS.AddComment(
"Function type index");
1168 OS.emitInt32(getFuncIdForSubprogram(GV->
getSubprogram()).getIndex());
1169 OS.AddComment(
"Function section relative address");
1170 OS.emitCOFFSecRel32(Fn, 0);
1171 OS.AddComment(
"Function section index");
1172 OS.emitCOFFSectionIndex(Fn);
1173 OS.AddComment(
"Flags");
1174 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;
1175 if (FI.HasFramePointer)
1176 ProcFlags |= ProcSymFlags::HasFP;
1178 ProcFlags |= ProcSymFlags::IsNoReturn;
1180 ProcFlags |= ProcSymFlags::IsNoInline;
1181 OS.emitInt8(
static_cast<uint8_t
>(ProcFlags));
1183 OS.AddComment(
"Function name");
1186 endSymbolRecord(ProcRecordEnd);
1188 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1190 OS.AddComment(
"FrameSize");
1191 OS.emitInt32(FI.FrameSize - FI.CSRSize);
1192 OS.AddComment(
"Padding");
1194 OS.AddComment(
"Offset of padding");
1196 OS.AddComment(
"Bytes of callee saved registers");
1197 OS.emitInt32(FI.CSRSize);
1198 OS.AddComment(
"Exception handler offset");
1200 OS.AddComment(
"Exception handler section");
1202 OS.AddComment(
"Flags (defines frame register)");
1203 OS.emitInt32(uint32_t(FI.FrameProcOpts));
1204 endSymbolRecord(FrameProcEnd);
1206 emitInlinees(FI.Inlinees);
1207 emitLocalVariableList(FI, FI.Locals);
1208 emitGlobalVariableList(FI.Globals);
1209 emitLexicalBlockList(FI.ChildBlocks, FI);
1214 for (
const DILocation *InlinedAt : FI.ChildSites) {
1215 auto I = FI.InlineSites.find(InlinedAt);
1216 assert(
I != FI.InlineSites.end() &&
1217 "child site not in function inline site map");
1218 emitInlinedCallSite(FI, InlinedAt,
I->second);
1221 for (
auto Annot : FI.Annotations) {
1224 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1225 OS.emitCOFFSecRel32(Label, 0);
1227 OS.emitCOFFSectionIndex(Label);
1233 assert(Str.data()[Str.size()] ==
'\0' &&
"non-nullterminated MDString");
1234 OS.emitBytes(StringRef(Str.data(), Str.size() + 1));
1236 endSymbolRecord(AnnotEnd);
1239 for (
auto HeapAllocSite : FI.HeapAllocSites) {
1240 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1241 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1242 const DIType *DITy = std::get<2>(HeapAllocSite);
1243 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1244 OS.AddComment(
"Call site offset");
1245 OS.emitCOFFSecRel32(BeginLabel, 0);
1246 OS.AddComment(
"Call site section index");
1247 OS.emitCOFFSectionIndex(BeginLabel);
1248 OS.AddComment(
"Call instruction length");
1249 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
1250 OS.AddComment(
"Type index");
1251 OS.emitInt32(getCompleteTypeIndex(DITy).getIndex());
1252 endSymbolRecord(HeapAllocEnd);
1256 emitDebugInfoForUDTs(LocalUDTs);
1258 emitDebugInfoForJumpTables(FI);
1261 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1263 endCVSubsection(SymbolsEnd);
1266 OS.emitCVLinetableDirective(FI.FuncId, Fn, FI.End);
1270CodeViewDebug::createDefRangeMem(uint16_t CVRegister,
int Offset) {
1276 DR.StructOffset = 0;
1277 DR.CVRegister = CVRegister;
1281void CodeViewDebug::collectVariableInfoFromMFTable(
1283 const MachineFunction &MF = *
Asm->MF;
1288 for (
const MachineFunction::VariableDbgInfo &VI :
1292 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1293 "Expected inlined-at fields to agree");
1295 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1304 int64_t ExprOffset = 0;
1308 if (
VI.Expr->getNumElements() == 1 &&
1309 VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)
1311 else if (!
VI.Expr->extractIfOffset(ExprOffset))
1317 StackOffset FrameOffset =
1319 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1328 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset);
1336 End = End ? End :
Asm->getFunctionEnd();
1337 Var.DefRanges[DefRange].emplace_back(Begin, End);
1341 Var.UseReferenceType =
true;
1343 recordLocalVariable(std::move(Var), Scope);
1348 return !
Loc.LoadChain.empty() &&
Loc.LoadChain.back() == 0;
1352 return Loc.LoadChain.size() == 2 &&
Loc.LoadChain.back() == 0;
1355void CodeViewDebug::calculateRanges(
1357 const TargetRegisterInfo *
TRI =
Asm->MF->getSubtarget().getRegisterInfo();
1360 for (
auto I = Entries.
begin(),
E = Entries.
end();
I !=
E; ++
I) {
1362 if (!
Entry.isDbgValue())
1364 const MachineInstr *DVInst =
Entry.getInstr();
1368 std::optional<DbgVariableLocation>
Location =
1379 Var.ConstantValue =
APSInt(APInt(64,
Op.getImm()),
false);
1390 if (Var.UseReferenceType) {
1399 Var.UseReferenceType =
true;
1400 Var.DefRanges.clear();
1401 calculateRanges(Var, Entries);
1412 if (
Location->FragmentInfo->OffsetInBits % 8)
1422 DR.InMemory = !
Location->LoadChain.empty();
1426 DR.IsSubfield =
true;
1427 DR.StructOffset =
Location->FragmentInfo->OffsetInBits / 8;
1429 DR.IsSubfield =
false;
1430 DR.StructOffset = 0;
1437 auto &EndingEntry = Entries[
Entry.getEndIndex()];
1438 End = EndingEntry.isDbgValue()
1442 End =
Asm->getFunctionEnd();
1446 SmallVectorImpl<std::pair<const MCSymbol *, const MCSymbol *>> &
R =
1448 if (!
R.empty() &&
R.back().second == Begin)
1449 R.back().second = End;
1451 R.emplace_back(Begin, End);
1457void CodeViewDebug::collectVariableInfo(
const DISubprogram *SP) {
1458 DenseSet<InlinedEntity> Processed;
1460 collectVariableInfoFromMFTable(Processed);
1463 InlinedEntity
IV =
I.first;
1467 const DILocation *InlinedAt =
IV.second;
1470 const auto &Entries =
I.second;
1472 LexicalScope *
Scope =
nullptr;
1484 calculateRanges(Var, Entries);
1485 recordLocalVariable(std::move(Var), Scope);
1494 auto Insertion = FnDebugInfo.
insert({&GV, std::make_unique<FunctionInfo>()});
1495 assert(Insertion.second &&
"function already has info");
1496 CurFn = Insertion.first->second.get();
1497 CurFn->FuncId = NextFuncId++;
1498 CurFn->Begin =
Asm->getFunctionBegin();
1506 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1512 if (CurFn->FrameSize > 0) {
1517 CurFn->HasFramePointer =
true;
1520 if (CurFn->HasStackRealignment) {
1571 CurFn->FrameProcOpts = FPO;
1573 OS.emitCVFuncIdDirective(CurFn->FuncId);
1580 bool EmptyPrologue =
true;
1581 for (
const auto &
MBB : *MF) {
1582 for (
const auto &
MI :
MBB) {
1587 }
else if (!
MI.isMetaInstruction()) {
1588 EmptyPrologue =
false;
1596 maybeRecordLocation(FnStartDL, MF);
1600 for (
const auto &
MBB : *MF) {
1601 for (
const auto &
MI :
MBB) {
1602 if (
MI.getHeapAllocMarker()) {
1610 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
1612 discoverJumpTableBranches(MF,
isThumb);
1620 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1621 if (
DIScope *Scope =
T->getScope()) {
1622 switch (Scope->getTag()) {
1623 case dwarf::DW_TAG_structure_type:
1624 case dwarf::DW_TAG_class_type:
1625 case dwarf::DW_TAG_union_type:
1635 if (!
T ||
T->isForwardDecl())
1641 T = DT->getBaseType();
1646void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1654 const DISubprogram *ClosestSubprogram =
1655 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1657 std::string FullyQualifiedName =
1660 if (ClosestSubprogram ==
nullptr) {
1661 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1662 }
else if (ClosestSubprogram == CurrentSubprogram) {
1663 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1674TypeIndex CodeViewDebug::lowerType(
const DIType *Ty,
const DIType *ClassTy) {
1677 case dwarf::DW_TAG_array_type:
1679 case dwarf::DW_TAG_typedef:
1681 case dwarf::DW_TAG_base_type:
1683 case dwarf::DW_TAG_pointer_type:
1687 case dwarf::DW_TAG_reference_type:
1688 case dwarf::DW_TAG_rvalue_reference_type:
1690 case dwarf::DW_TAG_ptr_to_member_type:
1692 case dwarf::DW_TAG_restrict_type:
1693 case dwarf::DW_TAG_const_type:
1694 case dwarf::DW_TAG_volatile_type:
1697 case dwarf::DW_TAG_subroutine_type:
1706 case dwarf::DW_TAG_enumeration_type:
1708 case dwarf::DW_TAG_class_type:
1709 case dwarf::DW_TAG_structure_type:
1711 case dwarf::DW_TAG_union_type:
1713 case dwarf::DW_TAG_string_type:
1715 case dwarf::DW_TAG_unspecified_type:
1716 if (Ty->
getName() ==
"decltype(nullptr)")
1725TypeIndex CodeViewDebug::lowerTypeAlias(
const DIDerivedType *Ty) {
1726 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1731 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) &&
1732 TypeName ==
"HRESULT")
1733 return TypeIndex(SimpleTypeKind::HResult);
1734 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::UInt16Short) &&
1735 TypeName ==
"wchar_t")
1736 return TypeIndex(SimpleTypeKind::WideCharacter);
1738 return UnderlyingTypeIndex;
1743 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1745 TypeIndex IndexType = getPointerSizeInBytes() == 8
1746 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1753 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1754 const DINode *Element =
Elements[i];
1755 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1765 Count = CI->getSExtValue();
1771 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1772 Count = UI->getSExtValue() - Lowerbound + 1;
1783 ElementSize *=
Count;
1787 uint64_t ArraySize =
1788 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1791 ArrayRecord AR(ElementTypeIndex, IndexType, ArraySize, Name);
1792 ElementTypeIndex = TypeTable.writeLeafType(AR);
1795 return ElementTypeIndex;
1803TypeIndex CodeViewDebug::lowerTypeString(
const DIStringType *Ty) {
1804 TypeIndex CharType = TypeIndex(SimpleTypeKind::NarrowCharacter);
1808 TypeIndex IndexType = getPointerSizeInBytes() == 8
1809 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1813 ArrayRecord AR(CharType, IndexType, ArraySize, Name);
1815 return TypeTable.writeLeafType(AR);
1818TypeIndex CodeViewDebug::lowerTypeBasic(
const DIBasicType *Ty) {
1828 case dwarf::DW_ATE_address:
1831 case dwarf::DW_ATE_boolean:
1833 case 1: STK = SimpleTypeKind::Boolean8;
break;
1834 case 2: STK = SimpleTypeKind::Boolean16;
break;
1835 case 4: STK = SimpleTypeKind::Boolean32;
break;
1836 case 8: STK = SimpleTypeKind::Boolean64;
break;
1837 case 16: STK = SimpleTypeKind::Boolean128;
break;
1840 case dwarf::DW_ATE_complex_float:
1844 case 4: STK = SimpleTypeKind::Complex16;
break;
1845 case 8: STK = SimpleTypeKind::Complex32;
break;
1846 case 16: STK = SimpleTypeKind::Complex64;
break;
1847 case 20: STK = SimpleTypeKind::Complex80;
break;
1848 case 32: STK = SimpleTypeKind::Complex128;
break;
1851 case dwarf::DW_ATE_float:
1853 case 2: STK = SimpleTypeKind::Float16;
break;
1854 case 4: STK = SimpleTypeKind::Float32;
break;
1855 case 6: STK = SimpleTypeKind::Float48;
break;
1856 case 8: STK = SimpleTypeKind::Float64;
break;
1857 case 10: STK = SimpleTypeKind::Float80;
break;
1858 case 16: STK = SimpleTypeKind::Float128;
break;
1861 case dwarf::DW_ATE_signed:
1863 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1864 case 2: STK = SimpleTypeKind::Int16Short;
break;
1865 case 4: STK = SimpleTypeKind::Int32;
break;
1866 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1867 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1870 case dwarf::DW_ATE_unsigned:
1872 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1873 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1874 case 4: STK = SimpleTypeKind::UInt32;
break;
1875 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1876 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1879 case dwarf::DW_ATE_UTF:
1881 case 1: STK = SimpleTypeKind::Character8;
break;
1882 case 2: STK = SimpleTypeKind::Character16;
break;
1883 case 4: STK = SimpleTypeKind::Character32;
break;
1886 case dwarf::DW_ATE_signed_char:
1888 STK = SimpleTypeKind::SignedCharacter;
1890 case dwarf::DW_ATE_unsigned_char:
1892 STK = SimpleTypeKind::UnsignedCharacter;
1902 if (STK == SimpleTypeKind::Int32 &&
1904 STK = SimpleTypeKind::Int32Long;
1905 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1906 Ty->
getName() ==
"unsigned long"))
1907 STK = SimpleTypeKind::UInt32Long;
1908 if (STK == SimpleTypeKind::UInt16Short &&
1910 STK = SimpleTypeKind::WideCharacter;
1911 if ((STK == SimpleTypeKind::SignedCharacter ||
1912 STK == SimpleTypeKind::UnsignedCharacter) &&
1914 STK = SimpleTypeKind::NarrowCharacter;
1916 return TypeIndex(STK);
1919TypeIndex CodeViewDebug::lowerTypePointer(
const DIDerivedType *Ty,
1921 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1925 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1927 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1929 ? SimpleTypeMode::NearPointer64
1930 : SimpleTypeMode::NearPointer32;
1935 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1939 case dwarf::DW_TAG_pointer_type:
1940 PM = PointerMode::Pointer;
1942 case dwarf::DW_TAG_reference_type:
1943 PM = PointerMode::LValueReference;
1945 case dwarf::DW_TAG_rvalue_reference_type:
1946 PM = PointerMode::RValueReference;
1951 PO |= PointerOptions::Const;
1953 PointerRecord PR(PointeeTI, PK, PM, PO, Ty->
getSizeInBits() / 8);
1954 return TypeTable.writeLeafType(PR);
1967 case DINode::FlagSingleInheritance:
1969 case DINode::FlagMultipleInheritance:
1971 case DINode::FlagVirtualInheritance:
1979 case DINode::FlagSingleInheritance:
1981 case DINode::FlagMultipleInheritance:
1983 case DINode::FlagVirtualInheritance:
1990TypeIndex CodeViewDebug::lowerTypeMemberPointer(
const DIDerivedType *Ty,
1992 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
1995 TypeIndex PointeeTI =
1996 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->
getClassType() :
nullptr);
1997 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
1998 : PointerKind::Near32;
1999 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
2000 : PointerMode::PointerToDataMember;
2004 MemberPointerInfo MPI(
2006 PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);
2007 return TypeTable.writeLeafType(PR);
2024TypeIndex CodeViewDebug::lowerTypeModifier(
const DIDerivedType *Ty) {
2028 const DIType *BaseTy = Ty;
2029 while (IsModifier && BaseTy) {
2031 switch (BaseTy->
getTag()) {
2032 case dwarf::DW_TAG_const_type:
2033 Mods |= ModifierOptions::Const;
2034 PO |= PointerOptions::Const;
2036 case dwarf::DW_TAG_volatile_type:
2037 Mods |= ModifierOptions::Volatile;
2038 PO |= PointerOptions::Volatile;
2040 case dwarf::DW_TAG_restrict_type:
2043 PO |= PointerOptions::Restrict;
2058 switch (BaseTy->
getTag()) {
2059 case dwarf::DW_TAG_pointer_type:
2060 case dwarf::DW_TAG_reference_type:
2061 case dwarf::DW_TAG_rvalue_reference_type:
2063 case dwarf::DW_TAG_ptr_to_member_type:
2070 TypeIndex ModifiedTI = getTypeIndex(BaseTy);
2074 if (Mods == ModifierOptions::None)
2077 ModifierRecord MR(ModifiedTI, Mods);
2078 return TypeTable.writeLeafType(MR);
2084 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2087 if (ReturnAndArgTypeIndices.
size() > 1 &&
2093 if (!ReturnAndArgTypeIndices.
empty()) {
2094 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2095 ReturnTypeIndex = ReturnAndArgTypesRef.consume_front();
2096 ArgTypeIndices = ReturnAndArgTypesRef;
2099 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2100 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2105 ProcedureRecord Procedure(ReturnTypeIndex, CC, FO, ArgTypeIndices.
size(),
2107 return TypeTable.writeLeafType(Procedure);
2110TypeIndex CodeViewDebug::lowerTypeMemberFunction(
const DISubroutineType *Ty,
2113 bool IsStaticMethod,
2116 TypeIndex ClassType = getTypeIndex(ClassTy);
2123 if (ReturnAndArgs.
size() > Index) {
2124 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
2130 TypeIndex ThisTypeIndex;
2131 if (!IsStaticMethod && ReturnAndArgs.
size() > Index) {
2132 if (
const DIDerivedType *PtrTy =
2134 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2135 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2141 while (Index < ReturnAndArgs.
size())
2142 ArgTypeIndices.
push_back(getTypeIndex(ReturnAndArgs[Index++]));
2148 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2149 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2153 MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FO,
2154 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2155 return TypeTable.writeLeafType(MFR);
2158TypeIndex CodeViewDebug::lowerTypeVFTableShape(
const DIDerivedType *Ty) {
2159 unsigned VSlotCount =
2163 VFTableShapeRecord VFTSR(Slots);
2164 return TypeTable.writeLeafType(VFTSR);
2181 if (SP->isArtificial())
2191 if (SP->getFlags() & DINode::FlagStaticMember)
2194 switch (SP->getVirtuality()) {
2195 case dwarf::DW_VIRTUALITY_none:
2197 case dwarf::DW_VIRTUALITY_virtual:
2199 case dwarf::DW_VIRTUALITY_pure_virtual:
2210 switch (Ty->getTag()) {
2211 case dwarf::DW_TAG_class_type:
2212 return TypeRecordKind::Class;
2213 case dwarf::DW_TAG_structure_type:
2214 return TypeRecordKind::Struct;
2228 if (!Ty->getIdentifier().empty())
2242 if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) {
2246 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2258void CodeViewDebug::addUDTSrcLine(
const DIType *Ty, TypeIndex TI) {
2260 case dwarf::DW_TAG_class_type:
2261 case dwarf::DW_TAG_structure_type:
2262 case dwarf::DW_TAG_union_type:
2263 case dwarf::DW_TAG_enumeration_type:
2269 if (
const auto *File = Ty->
getFile()) {
2270 StringIdRecord SIDR(TypeIndex(0x0), getFullFilepath(File));
2271 TypeIndex SIDI = TypeTable.writeLeafType(SIDR);
2273 UdtSourceLineRecord USLR(TI, SIDI, Ty->
getLine());
2274 TypeTable.writeLeafType(USLR);
2281 unsigned EnumeratorCount = 0;
2284 CO |= ClassOptions::ForwardReference;
2286 ContinuationRecordBuilder ContinuationBuilder;
2287 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2293 EnumeratorRecord ER(MemberAccess::Public,
2300 FTI = TypeTable.insertRecord(ContinuationBuilder);
2303 std::string FullName = getFullyQualifiedName(Ty);
2305 EnumRecord ER(EnumeratorCount, CO, FTI, FullName, Ty->
getIdentifier(),
2307 TypeIndex EnumTI = TypeTable.writeLeafType(ER);
2309 addUDTSrcLine(Ty, EnumTI);
2343void CodeViewDebug::clear() {
2344 assert(CurFn ==
nullptr);
2346 FnDebugInfo.clear();
2347 FileToFilepathMap.clear();
2350 TypeIndices.clear();
2351 CompleteTypeIndices.clear();
2352 ScopeGlobals.clear();
2353 CVGlobalVariableOffsets.clear();
2359 Info.Members.push_back({DDTy, 0});
2362 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2363 DINode::FlagStaticMember) {
2366 StaticConstMembers.push_back(DDTy);
2378 const DIType *Ty = DDTy->getBaseType();
2379 bool FullyResolved =
false;
2380 while (!FullyResolved) {
2382 case dwarf::DW_TAG_const_type:
2383 case dwarf::DW_TAG_volatile_type:
2389 FullyResolved =
true;
2398 ClassInfo NestedInfo = collectClassInfo(DCTy);
2399 for (
const ClassInfo::MemberInfo &IndirectField : NestedInfo.
Members)
2400 Info.Members.push_back(
2408 for (
auto *Element : Elements) {
2414 Info.Methods[
SP->getRawName()].push_back(SP);
2416 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2417 collectMemberInfo(
Info, DDTy);
2418 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2419 Info.Inheritance.push_back(DDTy);
2420 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2421 DDTy->
getName() ==
"__vtbl_ptr_type") {
2422 Info.VShapeTI = getTypeIndex(DDTy);
2423 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2424 Info.NestedTypes.push_back(DDTy);
2425 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2430 Info.NestedTypes.push_back(Composite);
2440 return Ty->getName().empty() && Ty->getIdentifier().empty() &&
2441 !Ty->isForwardDecl();
2453 auto I = CompleteTypeIndices.find(Ty);
2454 if (
I != CompleteTypeIndices.end() &&
I->second == TypeIndex())
2456 return getCompleteTypeIndex(Ty);
2464 std::string FullName = getFullyQualifiedName(Ty);
2465 ClassRecord CR(Kind, 0, CO, TypeIndex(), TypeIndex(), TypeIndex(), 0,
2467 TypeIndex FwdDeclTI = TypeTable.writeLeafType(CR);
2469 DeferredCompleteTypes.push_back(Ty);
2473TypeIndex CodeViewDebug::lowerCompleteTypeClass(
const DICompositeType *Ty) {
2479 unsigned FieldCount;
2482 lowerRecordFieldList(Ty);
2485 CO |= ClassOptions::ContainsNestedClass;
2493 CO |= ClassOptions::HasConstructorOrDestructor;
2495 std::string FullName = getFullyQualifiedName(Ty);
2499 ClassRecord CR(Kind, FieldCount, CO, FieldTI, TypeIndex(), VShapeTI,
2501 TypeIndex ClassTI = TypeTable.writeLeafType(CR);
2503 addUDTSrcLine(Ty, ClassTI);
2513 return getCompleteTypeIndex(Ty);
2517 std::string FullName = getFullyQualifiedName(Ty);
2518 UnionRecord UR(0, CO, TypeIndex(), 0, FullName, Ty->
getIdentifier());
2519 TypeIndex FwdDeclTI = TypeTable.writeLeafType(UR);
2521 DeferredCompleteTypes.push_back(Ty);
2525TypeIndex CodeViewDebug::lowerCompleteTypeUnion(
const DICompositeType *Ty) {
2528 unsigned FieldCount;
2531 lowerRecordFieldList(Ty);
2534 CO |= ClassOptions::ContainsNestedClass;
2537 std::string FullName = getFullyQualifiedName(Ty);
2539 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2541 TypeIndex UnionTI = TypeTable.writeLeafType(UR);
2543 addUDTSrcLine(Ty, UnionTI);
2550std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2556 unsigned MemberCount = 0;
2557 ClassInfo
Info = collectClassInfo(Ty);
2558 ContinuationRecordBuilder ContinuationBuilder;
2559 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2562 for (
const DIDerivedType *
I :
Info.Inheritance) {
2563 if (
I->getFlags() & DINode::FlagVirtual) {
2565 unsigned VBPtrOffset =
I->getVBPtrOffset();
2567 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2568 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2569 ? TypeRecordKind::IndirectVirtualBaseClass
2570 : TypeRecordKind::VirtualBaseClass;
2571 VirtualBaseClassRecord VBCR(
2573 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2579 assert(
I->getOffsetInBits() % 8 == 0 &&
2580 "bases must be on byte boundaries");
2582 getTypeIndex(
I->getBaseType()),
2583 I->getOffsetInBits() / 8);
2590 for (ClassInfo::MemberInfo &MemberInfo :
Info.Members) {
2592 TypeIndex MemberBaseType = getTypeIndex(
Member->getBaseType());
2593 StringRef MemberName =
Member->getName();
2597 if (
Member->isStaticMember()) {
2598 StaticDataMemberRecord SDMR(
Access, MemberBaseType, MemberName);
2605 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2606 Member->getName().starts_with(
"_vptr$")) {
2607 VFPtrRecord VFPR(getTypeIndex(
Member->getBaseType()));
2614 uint64_t MemberOffsetInBits =
2616 if (
Member->isBitField()) {
2617 uint64_t StartBitOffset = MemberOffsetInBits;
2618 if (
const auto *CI =
2620 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2622 StartBitOffset -= MemberOffsetInBits;
2623 BitFieldRecord BFR(MemberBaseType,
Member->getSizeInBits(),
2625 MemberBaseType = TypeTable.writeLeafType(BFR);
2627 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2628 DataMemberRecord DMR(
Access, MemberBaseType, MemberOffsetInBytes,
2635 for (
auto &MethodItr :
Info.Methods) {
2636 StringRef
Name = MethodItr.first->getString();
2638 std::vector<OneMethodRecord> Methods;
2639 for (
const DISubprogram *SP : MethodItr.second) {
2640 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2641 bool Introduced =
SP->getFlags() & DINode::FlagIntroducedVirtual;
2643 unsigned VFTableOffset = -1;
2645 VFTableOffset =
SP->getVirtualIndex() * getPointerSizeInBytes();
2647 Methods.push_back(OneMethodRecord(
2653 assert(!Methods.empty() &&
"Empty methods map entry");
2654 if (Methods.size() == 1)
2659 MethodOverloadListRecord MOLR(Methods);
2660 TypeIndex MethodList = TypeTable.writeLeafType(MOLR);
2662 OverloadedMethodRecord OMR(Methods.size(), MethodList, Name);
2668 for (
const DIType *
Nested :
Info.NestedTypes) {
2669 NestedTypeRecord
R(getTypeIndex(
Nested),
Nested->getName());
2674 TypeIndex FieldTI = TypeTable.insertRecord(ContinuationBuilder);
2675 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2676 !
Info.NestedTypes.empty());
2679TypeIndex CodeViewDebug::getVBPTypeIndex() {
2680 if (!VBPType.getIndex()) {
2683 TypeIndex ModifiedTI = TypeTable.writeLeafType(MR);
2685 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2686 : PointerKind::Near32;
2689 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2690 VBPType = TypeTable.writeLeafType(PR);
2696TypeIndex CodeViewDebug::getTypeIndex(
const DIType *Ty,
const DIType *ClassTy) {
2704 auto I = TypeIndices.find({Ty, ClassTy});
2705 if (
I != TypeIndices.end())
2709 TypeIndex TI = lowerType(Ty, ClassTy);
2710 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2714CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2716 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2717 "this type must be a pointer type");
2720 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2721 Options = PointerOptions::LValueRefThisPointer;
2722 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2723 Options = PointerOptions::RValueRefThisPointer;
2730 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2731 if (
I != TypeIndices.end())
2735 TypeIndex TI = lowerTypePointer(PtrTy,
Options);
2736 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2739TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(
const DIType *Ty) {
2740 PointerRecord PR(getTypeIndex(Ty),
2741 getPointerSizeInBytes() == 8 ? PointerKind::Near64
2742 : PointerKind::Near32,
2743 PointerMode::LValueReference, PointerOptions::None,
2745 return TypeTable.writeLeafType(PR);
2748TypeIndex CodeViewDebug::getCompleteTypeIndex(
const DIType *Ty) {
2756 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2757 (void)getTypeIndex(Ty);
2758 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2764 case dwarf::DW_TAG_class_type:
2765 case dwarf::DW_TAG_structure_type:
2766 case dwarf::DW_TAG_union_type:
2769 return getTypeIndex(Ty);
2780 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2781 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2786 if (CTy->isForwardDecl())
2793 auto InsertResult = CompleteTypeIndices.try_emplace(CTy);
2794 if (!InsertResult.second)
2795 return InsertResult.first->second;
2798 switch (CTy->getTag()) {
2799 case dwarf::DW_TAG_class_type:
2800 case dwarf::DW_TAG_structure_type:
2801 TI = lowerCompleteTypeClass(CTy);
2803 case dwarf::DW_TAG_union_type:
2804 TI = lowerCompleteTypeUnion(CTy);
2814 CompleteTypeIndices[CTy] = TI;
2822void CodeViewDebug::emitDeferredCompleteTypes() {
2824 while (!DeferredCompleteTypes.empty()) {
2825 std::swap(DeferredCompleteTypes, TypesToEmit);
2826 for (
const DICompositeType *RecordTy : TypesToEmit)
2827 getCompleteTypeIndex(RecordTy);
2828 TypesToEmit.clear();
2832void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2836 for (
const LocalVariable &L : Locals)
2837 if (
L.DIVar->isParameter())
2839 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2840 return L->DIVar->getArg() <
R->DIVar->getArg();
2842 for (
const LocalVariable *L : Params)
2843 emitLocalVariable(FI, *L);
2846 for (
const LocalVariable &L : Locals) {
2847 if (!
L.DIVar->isParameter()) {
2848 if (
L.ConstantValue) {
2851 const DIType *Ty =
L.DIVar->getType();
2853 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2855 emitLocalVariable(FI, L);
2861void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2862 const LocalVariable &Var) {
2864 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2867 if (Var.DIVar->isParameter())
2868 Flags |= LocalSymFlags::IsParameter;
2869 if (Var.DefRanges.empty())
2870 Flags |= LocalSymFlags::IsOptimizedOut;
2872 OS.AddComment(
"TypeIndex");
2873 TypeIndex TI = Var.UseReferenceType
2874 ? getTypeIndexForReferenceTo(Var.DIVar->getType())
2875 : getCompleteTypeIndex(Var.DIVar->
getType());
2877 OS.AddComment(
"Flags");
2878 OS.emitInt16(
static_cast<uint16_t
>(Flags));
2881 endSymbolRecord(LocalEnd);
2886 SmallString<20> BytePrefix;
2887 for (
const auto &Pair : Var.DefRanges) {
2888 LocalVarDef DefRange = Pair.first;
2889 const auto &Ranges = Pair.second;
2891 if (DefRange.InMemory) {
2892 int Offset = DefRange.DataOffset;
2893 unsigned Reg = DefRange.CVRegister;
2898 if (RegisterId(Reg) == RegisterId::ESP) {
2899 Reg = unsigned(RegisterId::VFRAME);
2900 Offset += FI.OffsetAdjustment;
2906 EncodedFramePtrReg EncFP = encodeFramePtrReg(RegisterId(Reg), TheCPU);
2907 if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2908 (bool(Flags & LocalSymFlags::IsParameter)
2909 ? (EncFP == FI.EncodedParamFramePtrReg)
2910 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2911 DefRangeFramePointerRelHeader DRHdr;
2912 DRHdr.Offset = Offset;
2913 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2915 uint16_t RegRelFlags = 0;
2916 if (DefRange.IsSubfield) {
2917 RegRelFlags = DefRangeRegisterRelSym::IsSubfieldFlag |
2918 (DefRange.StructOffset
2919 << DefRangeRegisterRelSym::OffsetInParentShift);
2921 DefRangeRegisterRelHeader DRHdr;
2922 DRHdr.Register = Reg;
2923 DRHdr.Flags = RegRelFlags;
2924 DRHdr.BasePointerOffset = Offset;
2925 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2928 assert(DefRange.DataOffset == 0 &&
"unexpected offset into register");
2929 if (DefRange.IsSubfield) {
2930 DefRangeSubfieldRegisterHeader DRHdr;
2931 DRHdr.Register = DefRange.CVRegister;
2932 DRHdr.MayHaveNoName = 0;
2933 DRHdr.OffsetInParent = DefRange.StructOffset;
2934 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2936 DefRangeRegisterHeader DRHdr;
2937 DRHdr.Register = DefRange.CVRegister;
2938 DRHdr.MayHaveNoName = 0;
2939 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2946 const FunctionInfo& FI) {
2947 for (LexicalBlock *
Block : Blocks)
2948 emitLexicalBlock(*
Block, FI);
2953void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2954 const FunctionInfo& FI) {
2955 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2956 OS.AddComment(
"PtrParent");
2958 OS.AddComment(
"PtrEnd");
2960 OS.AddComment(
"Code size");
2961 OS.emitAbsoluteSymbolDiff(
Block.End,
Block.Begin, 4);
2962 OS.AddComment(
"Function section relative address");
2963 OS.emitCOFFSecRel32(
Block.Begin, 0);
2964 OS.AddComment(
"Function section index");
2965 OS.emitCOFFSectionIndex(FI.Begin);
2966 OS.AddComment(
"Lexical block name");
2968 endSymbolRecord(RecordEnd);
2971 emitLocalVariableList(FI,
Block.Locals);
2972 emitGlobalVariableList(
Block.Globals);
2975 emitLexicalBlockList(
Block.Children, FI);
2978 emitEndSymbolRecord(SymbolKind::S_END);
2983void CodeViewDebug::collectLexicalBlockInfo(
2988 for (LexicalScope *Scope : Scopes)
2989 collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
2994void CodeViewDebug::collectLexicalBlockInfo(
2999 if (
Scope.isAbstractScope())
3004 bool IgnoreScope =
false;
3005 auto LI = ScopeVariables.find(&Scope);
3006 SmallVectorImpl<LocalVariable> *
Locals =
3007 LI != ScopeVariables.end() ? &LI->second :
nullptr;
3008 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
3009 SmallVectorImpl<CVGlobalVariable> *Globals =
3010 GI != ScopeGlobals.
end() ? GI->second.get() :
nullptr;
3012 const SmallVectorImpl<InsnRange> &
Ranges =
Scope.getRanges();
3015 if (!Locals && !Globals)
3045 collectLexicalBlockInfo(
Scope.getChildren(),
3055 auto BlockInsertion = CurFn->LexicalBlocks.try_emplace(DILB);
3056 if (!BlockInsertion.second)
3063 LexicalBlock &
Block = BlockInsertion.first->second;
3066 assert(
Block.Begin &&
"missing label for scope begin");
3067 assert(
Block.End &&
"missing label for scope end");
3070 Block.Locals = std::move(*Locals);
3072 Block.Globals = std::move(*Globals);
3074 collectLexicalBlockInfo(
Scope.getChildren(),
3082 assert(FnDebugInfo.count(&GV));
3083 assert(CurFn == FnDebugInfo[&GV].
get());
3089 collectLexicalBlockInfo(*CFS,
3097 ScopeVariables.clear();
3101 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3102 FnDebugInfo.erase(&GV);
3108 for (
const auto &
MBB : *MF) {
3109 for (
const auto &
MI :
MBB) {
3110 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3118 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
3120 collectDebugInfoForJumpTables(MF,
isThumb);
3124 CurFn->End =
Asm->getFunctionEnd();
3134 return DL &&
DL.getLine() != 0;
3141 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3149 for (
const auto &NextMI : *
MI->getParent()) {
3150 if (NextMI.isDebugInstr())
3152 DL = NextMI.getDebugLoc();
3165 maybeRecordLocation(
DL,
Asm->MF);
3178void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3186 if (EE.Value == SymKind)
3192 MCSymbol *BeginLabel =
MMI->getContext().createTempSymbol(),
3193 *EndLabel =
MMI->getContext().createTempSymbol();
3194 OS.AddComment(
"Record length");
3195 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
3196 OS.emitLabel(BeginLabel);
3197 if (OS.isVerboseAsm())
3199 OS.emitInt16(
unsigned(SymKind));
3203void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3208 OS.emitValueToAlignment(
Align(4));
3209 OS.emitLabel(SymEnd);
3212void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3213 OS.AddComment(
"Record length");
3215 if (OS.isVerboseAsm())
3217 OS.emitInt16(uint16_t(EndKind));
3220void CodeViewDebug::emitDebugInfoForUDTs(
3221 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3223 size_t OriginalSize = UDTs.size();
3225 for (
const auto &UDT : UDTs) {
3226 const DIType *
T =
UDT.second;
3228 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3229 OS.AddComment(
"Type");
3230 OS.emitInt32(getCompleteTypeIndex(
T).getIndex());
3231 assert(OriginalSize == UDTs.size() &&
3232 "getCompleteTypeIndex found new UDTs!");
3234 endSymbolRecord(UDTRecordEnd);
3238void CodeViewDebug::collectGlobalVariableInfo() {
3239 DenseMap<const DIGlobalVariableExpression *, const GlobalVariable *>
3241 for (
const GlobalVariable &GV :
MMI->getModule()->globals()) {
3243 GV.getDebugInfo(GVEs);
3244 for (
const auto *GVE : GVEs)
3245 GlobalMap[GVE] = &GV;
3248 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3249 for (
const MDNode *Node : CUs->
operands()) {
3251 for (
const auto *GVE : CU->getGlobalVariables()) {
3252 const DIGlobalVariable *DIGV = GVE->getVariable();
3253 const DIExpression *DIE = GVE->getExpression();
3261 (DIE->
getElement(0) == dwarf::DW_OP_plus_uconst))
3266 CVGlobalVariableOffsets.insert(
3271 CVGlobalVariable CVGV = {DIGV, DIE};
3272 GlobalVariables.emplace_back(std::move(CVGV));
3275 const auto *GV = GlobalMap.
lookup(GVE);
3280 SmallVector<CVGlobalVariable, 1> *VariableList;
3284 auto Insertion = ScopeGlobals.insert(
3285 {
Scope, std::unique_ptr<GlobalVariableList>()});
3286 if (Insertion.second)
3287 Insertion.first->second = std::make_unique<GlobalVariableList>();
3288 VariableList = Insertion.first->second.get();
3291 VariableList = &ComdatVariables;
3294 VariableList = &GlobalVariables;
3295 CVGlobalVariable CVGV = {DIGV, GV};
3301void CodeViewDebug::collectDebugInfoForGlobals() {
3302 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3303 const DIGlobalVariable *DIGV = CVGV.DIGV;
3305 getCompleteTypeIndex(DIGV->
getType());
3306 getFullyQualifiedName(Scope, DIGV->
getName());
3309 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3310 const DIGlobalVariable *DIGV = CVGV.DIGV;
3312 getCompleteTypeIndex(DIGV->
getType());
3313 getFullyQualifiedName(Scope, DIGV->
getName());
3317void CodeViewDebug::emitDebugInfoForGlobals() {
3321 switchToDebugSectionForSymbol(
nullptr);
3322 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3323 OS.AddComment(
"Symbol subsection for globals");
3324 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3325 emitGlobalVariableList(GlobalVariables);
3326 emitStaticConstMemberList();
3327 endCVSubsection(EndLabel);
3332 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3335 OS.AddComment(
"Symbol subsection for " +
3337 switchToDebugSectionForSymbol(GVSym);
3338 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3340 emitDebugInfoForGlobal(CVGV);
3341 endCVSubsection(EndLabel);
3345void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3346 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3347 for (
const MDNode *Node : CUs->
operands()) {
3359 for (
const CVGlobalVariable &CVGV : Globals) {
3361 emitDebugInfoForGlobal(CVGV);
3366 const std::string &QualifiedName) {
3367 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3368 OS.AddComment(
"Type");
3369 OS.emitInt32(getTypeIndex(DTy).getIndex());
3371 OS.AddComment(
"Value");
3376 CodeViewRecordIO IO(Writer);
3378 StringRef SRef((
char *)
Data, Writer.getOffset());
3379 OS.emitBinaryData(SRef);
3381 OS.AddComment(
"Name");
3383 endSymbolRecord(SConstantEnd);
3386void CodeViewDebug::emitStaticConstMemberList() {
3387 for (
const DIDerivedType *DTy : StaticConstMembers) {
3391 if (
const ConstantInt *CI =
3395 else if (
const ConstantFP *CFP =
3397 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3401 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3402 getFullyQualifiedName(Scope, DTy->
getName()));
3412 if (
T == dwarf::DW_TAG_pointer_type ||
3413 T == dwarf::DW_TAG_ptr_to_member_type ||
3414 T == dwarf::DW_TAG_reference_type ||
3415 T == dwarf::DW_TAG_rvalue_reference_type)
3417 assert(DTy->getBaseType() &&
"Expected valid base type");
3422 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3425void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3426 const DIGlobalVariable *DIGV = CVGV.DIGV;
3432 Scope = MemberDecl->getScope();
3438 ? std::string(DIGV->
getName())
3441 if (
const GlobalVariable *GV =
3445 MCSymbol *GVSym = Asm->getSymbol(GV);
3446 SymbolKind DataSym = GV->isThreadLocal()
3447 ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32
3448 : SymbolKind::S_GTHREAD32)
3449 : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32
3450 : SymbolKind::S_GDATA32);
3451 MCSymbol *DataEnd = beginSymbolRecord(DataSym);
3452 OS.AddComment(
"Type");
3453 OS.emitInt32(getCompleteTypeIndex(DIGV->getType()).getIndex());
3454 OS.AddComment(
"DataOffset");
3457 uint64_t Offset = CVGlobalVariableOffsets.lookup(DIGV);
3458 OS.emitCOFFSecRel32(GVSym, Offset);
3460 OS.AddComment(
"Segment");
3461 OS.emitCOFFSectionIndex(GVSym);
3462 OS.AddComment(
"Name");
3463 const unsigned LengthOfDataRecord = 12;
3464 emitNullTerminatedSymbolName(OS, QualifiedName, LengthOfDataRecord);
3465 endSymbolRecord(DataEnd);
3467 const DIExpression *DIE = cast<const DIExpression *>(CVGV.GVInfo);
3468 assert(DIE->isConstant() &&
3469 "Global constant variables must contain a constant expression.");
3472 bool isUnsigned = isFloatDIType(DIGV->getType())
3474 : DebugHandlerBase::isUnsignedDIType(DIGV->getType());
3475 APSInt Value(APInt(64, DIE->getElement(1)), isUnsigned);
3476 emitConstantSymbolRecord(DIGV->getType(), Value, QualifiedName);
3483 int64_t)> &Callback) {
3485 if (JTI && !JTI->isEmpty()) {
3489 for (
const auto &
MBB : *MF) {
3491 const auto LastMI =
MBB.getFirstTerminator();
3492 if (LastMI !=
MBB.end() && LastMI->isIndirectBranch()) {
3500 for (
const auto &MO : LastMI->operands()) {
3502 unsigned Index = MO.getIndex();
3506 Callback(*JTI, *LastMI, Index);
3514 for (
auto I =
MBB.instr_rbegin(),
E =
MBB.instr_rend();
I !=
E; ++
I) {
3515 if (
I->isJumpTableDebugInfo()) {
3516 unsigned Index =
I->getOperand(0).getImm();
3520 Callback(*JTI, *LastMI, Index);
3529 "Some of jump tables were not used in a debug info instruction");
3534void CodeViewDebug::discoverJumpTableBranches(
const MachineFunction *MF,
3538 [
this](
const MachineJumpTableInfo &,
const MachineInstr &BranchMI,
3542void CodeViewDebug::collectDebugInfoForJumpTables(
const MachineFunction *MF,
3546 [
this, MF](
const MachineJumpTableInfo &JTI,
const MachineInstr &BranchMI,
3547 int64_t JumpTableIndex) {
3552 uint64_t BaseOffset = 0;
3560 "EK_Custom32, EK_GPRel32BlockAddress, and "
3561 "EK_GPRel64BlockAddress should never be emitted for COFF");
3564 EntrySize = JumpTableEntrySize::Pointer;
3571 std::tie(
Base, BaseOffset, Branch, EntrySize) =
3572 Asm->getCodeViewJumpTableInfo(JumpTableIndex, &BranchMI, Branch);
3576 const MachineJumpTableEntry &JTE = JTI.
getJumpTables()[JumpTableIndex];
3577 JumpTableInfo CVJTI{EntrySize,
3584 for (
const auto &
MBB : JTE.
MBBs)
3586 CurFn->JumpTables.push_back(std::move(CVJTI));
3590void CodeViewDebug::emitDebugInfoForJumpTables(
const FunctionInfo &FI) {
3592 for (
const auto &JumpTable : FI.JumpTables) {
3593 for (
const auto &CaseSym :
JumpTable.Cases) {
3594 MCSymbol *LabelEnd = beginSymbolRecord(SymbolKind::S_LABEL32);
3595 OS.AddComment(
"Offset and segment");
3596 OS.emitCOFFSecRel32(CaseSym, 0);
3597 OS.AddComment(
"Flags");
3600 endSymbolRecord(LabelEnd);
3604 for (
const auto &JumpTable : FI.JumpTables) {
3605 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3607 OS.AddComment(
"Base offset");
3609 OS.AddComment(
"Base section index");
3610 OS.emitCOFFSectionIndex(
JumpTable.Base);
3612 OS.AddComment(
"Base offset");
3614 OS.AddComment(
"Base section index");
3617 OS.AddComment(
"Switch type");
3618 OS.emitInt16(
static_cast<uint16_t
>(
JumpTable.EntrySize));
3619 OS.AddComment(
"Branch offset");
3620 OS.emitCOFFSecRel32(
JumpTable.Branch, 0);
3621 OS.AddComment(
"Table offset");
3622 OS.emitCOFFSecRel32(
JumpTable.Table, 0);
3623 OS.AddComment(
"Branch section index");
3624 OS.emitCOFFSectionIndex(
JumpTable.Branch);
3625 OS.AddComment(
"Table section index");
3626 OS.emitCOFFSectionIndex(
JumpTable.Table);
3627 OS.AddComment(
"Entries count");
3629 endSymbolRecord(JumpTableEnd);
3633void CodeViewDebug::emitInlinees(
3637 constexpr size_t ChunkSize =
3644 size_t CurrentIndex = 0;
3645 while (CurrentIndex < SortedInlinees.
size()) {
3646 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3647 auto CurrentChunkSize =
3648 std::min(ChunkSize, SortedInlinees.
size() - CurrentIndex);
3649 OS.AddComment(
"Count");
3650 OS.emitInt32(CurrentChunkSize);
3652 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3653 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3654 OS.AddComment(
"Inlinee");
3655 OS.emitInt32(SortedInlinees[CurrentIndex].getIndex());
3657 endSymbolRecord(Symbol);
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)
static SourceLanguage MapDWLangToCVLang(unsigned DWLang)
static MethodKind translateMethodKindFlags(const DISubprogram *SP, bool Introduced)
static bool isUsableDebugLoc(DebugLoc DL)
static TypeIndex getStringIdTypeIdx(GlobalTypeTableBuilder &TypeTable, StringRef S)
static CPUType mapArchToCVCPUType(Triple::ArchType Type)
static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S, unsigned MaxFixedRecordLength=0xF00)
static Version parseVersion(StringRef Name)
static MethodOptions translateMethodOptionFlags(const DISubprogram *SP)
static bool isNonTrivial(const DICompositeType *DCTy)
static std::string formatNestedName(ArrayRef< StringRef > QualifiedNameComponents, StringRef TypeName)
static ClassOptions getCommonClassOptions(const DICompositeType *Ty)
Return ClassOptions that should be present on both the forward declaration and the defintion of a tag...
static PointerToMemberRepresentation translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags)
static FunctionOptions getFunctionOptions(const DISubroutineType *Ty, const DICompositeType *ClassTy=nullptr, StringRef SPName=StringRef(""))
static StringRef removeTemplateArgs(StringRef Name)
static TypeRecordKind getRecordKind(const DICompositeType *Ty)
void forEachJumpTableBranch(const MachineFunction *MF, bool isThumb, const std::function< void(const MachineJumpTableInfo &, const MachineInstr &, int64_t)> &Callback)
static CallingConvention dwarfCCToCodeView(unsigned DwarfCC)
Given a DWARF calling convention, get the CodeView equivalent.
static bool isFloatDIType(const DIType *Ty)
static void addLocIfNotPresent(SmallVectorImpl< const DILocation * > &Locs, const DILocation *Loc)
static bool shouldEmitUdt(const DIType *T)
static StringRef getPrettyScopeName(const DIScope *Scope)
static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty)
static bool needsReferenceType(const DbgVariableLocation &Loc)
static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file contains constants used for implementing Dwarf debug support.
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)
void beginModule(Module *M) override
bool moduleIsInFortran()
Check if the current module is in Fortran.
void endFunctionImpl(const MachineFunction *) override
Gather post-function debug information.
void endModule() override
Emit the COFF section that holds the line table information.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
void beginFunctionImpl(const MachineFunction *MF) override
Gather pre-function debug information.
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
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
LexicalScope - 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,...
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<X> - Return the argument parameter cast to the specified type.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
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
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<X> - 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<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
TypeLoweringScope(CodeViewDebug &CVD)
This struct is a compact representation of a valid (non-zero power of two) alignment.
const DIDerivedType * MemberTypeNode
std::vector< MemberInfo > MemberList
MemberList Members
Direct members.
std::vector< const DIType * > NestedTypes
MapVector< MDString *, MethodsList > MethodsMap
std::vector< const DIDerivedType * > Inheritance
Base classes.
TinyPtrVector< const DISubprogram * > MethodsList
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.