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");
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;
601 return SourceLanguage::Masm;
615 if (!
Asm->getObjFileLowering().getCOFFDebugSymbolsSection()) {
620 CompilerInfoAsm =
Asm;
625 if (
Asm->hasDebugInfo()) {
626 Node = *M->debug_compile_units_begin();
630 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
635 CurrentSourceLanguage =
641 if (!M->getCodeViewFlag() ||
647 collectGlobalVariableInfo();
652 EmitDebugGlobalHashes = GH && !GH->
isZero();
656 if (!CompilerInfoAsm)
666 switchToDebugSectionForSymbol(
nullptr);
670 emitCompilerInformation();
671 endCVSubsection(CompilerInfo);
675 emitSecureHotPatchInformation();
677 emitInlineeLinesSubsection();
680 for (
auto &
P : FnDebugInfo)
681 if (!
P.first->isDeclarationForLinker())
682 emitDebugInfoForFunction(
P.first, *
P.second);
687 collectDebugInfoForGlobals();
690 emitDebugInfoForRetainedTypes();
693 setCurrentSubprogram(
nullptr);
694 emitDebugInfoForGlobals();
698 switchToDebugSectionForSymbol(
nullptr);
701 if (!GlobalUDTs.empty()) {
703 emitDebugInfoForUDTs(GlobalUDTs);
704 endCVSubsection(SymbolsEnd);
708 OS.AddComment(
"File index to string table offset subsection");
709 OS.emitCVFileChecksumsDirective();
712 OS.AddComment(
"String table");
713 OS.emitCVStringTableDirective();
722 emitTypeInformation();
724 if (EmitDebugGlobalHashes)
725 emitTypeGlobalHashes();
732 unsigned MaxFixedRecordLength = 0xF00) {
743void CodeViewDebug::emitTypeInformation() {
744 if (TypeTable.empty())
748 OS.switchSection(
Asm->getObjFileLowering().getCOFFDebugTypesSection());
749 emitCodeViewMagicVersion();
751 TypeTableCollection Table(TypeTable.records());
752 TypeVisitorCallbackPipeline Pipeline;
755 CVMCAdapter CVMCOS(OS, Table);
756 TypeRecordMapping typeMapping(CVMCOS);
759 std::optional<TypeIndex>
B = Table.getFirst();
762 CVType Record = Table.getType(*
B);
771 B = Table.getNext(*
B);
775void CodeViewDebug::emitTypeGlobalHashes() {
776 if (TypeTable.empty())
781 OS.switchSection(
Asm->getObjFileLowering().getCOFFGlobalTypeHashesSection());
783 OS.emitValueToAlignment(
Align(4));
784 OS.AddComment(
"Magic");
786 OS.AddComment(
"Section Version");
788 OS.AddComment(
"Hash Algorithm");
789 OS.emitInt16(uint16_t(GlobalTypeHashAlg::BLAKE3));
792 for (
const auto &GHR : TypeTable.hashes()) {
793 if (OS.isVerboseAsm()) {
797 raw_svector_ostream CommentOS(Comment);
799 OS.AddComment(Comment);
802 assert(GHR.Hash.size() == 8);
803 StringRef S(
reinterpret_cast<const char *
>(GHR.Hash.data()),
805 OS.emitBinaryData(S);
809void CodeViewDebug::emitObjName() {
810 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);
812 StringRef PathRef(CompilerInfoAsm->TM.Options.ObjectFilenameForDebug);
813 llvm::SmallString<256> PathStore(PathRef);
815 if (PathRef.empty() || PathRef ==
"-") {
822 OS.AddComment(
"Signature");
823 OS.emitIntValue(0, 4);
825 OS.AddComment(
"Object name");
828 endSymbolRecord(CompilerEnd);
831void CodeViewDebug::emitSecureHotPatchInformation() {
834 for (
const auto &
F :
MMI->getModule()->functions()) {
835 if (!
F.isDeclarationForLinker() &&
836 F.hasFnAttribute(
"marked_for_windows_hot_patching")) {
837 if (hotPatchInfo ==
nullptr)
838 hotPatchInfo = beginCVSubsection(DebugSubsectionKind::Symbols);
839 MCSymbol *HotPatchEnd = beginSymbolRecord(SymbolKind::S_HOTPATCHFUNC);
840 auto *
SP =
F.getSubprogram();
841 OS.AddComment(
"Function");
842 OS.emitInt32(getFuncIdForSubprogram(SP).getIndex());
843 OS.AddComment(
"Name");
845 endSymbolRecord(HotPatchEnd);
849 if (hotPatchInfo !=
nullptr)
850 endCVSubsection(hotPatchInfo);
864 for (
const char C : Name) {
867 V.Part[
N] +=
C -
'0';
869 std::min<int>(V.Part[
N], std::numeric_limits<uint16_t>::max());
870 }
else if (
C ==
'.') {
880void CodeViewDebug::emitCompilerInformation() {
881 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
885 Flags = CurrentSourceLanguage;
887 if (
MMI->getModule()->getProfileSummary(
false) !=
nullptr) {
888 Flags |=
static_cast<uint32_t
>(CompileSym3Flags::PGO);
891 ArchType Arch =
MMI->getModule()->getTargetTriple().getArch();
892 if (CompilerInfoAsm->TM.Options.Hotpatch || Arch == ArchType::thumb ||
893 Arch == ArchType::aarch64) {
894 Flags |=
static_cast<uint32_t
>(CompileSym3Flags::HotPatch);
897 OS.AddComment(
"Flags and language");
900 OS.AddComment(
"CPUType");
901 OS.emitInt16(
static_cast<uint64_t
>(TheCPU));
903 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
907 StringRef CompilerVersion = CU->getProducer();
909 OS.AddComment(
"Frontend version");
910 for (
int N : FrontVer.Part) {
917 int Major = 1000 * LLVM_VERSION_MAJOR +
918 10 * LLVM_VERSION_MINOR +
921 Major = std::min<int>(Major, std::numeric_limits<uint16_t>::max());
922 Version BackVer = {{ Major, 0, 0, 0 }};
923 OS.AddComment(
"Backend version");
924 for (
int N : BackVer.Part)
927 OS.AddComment(
"Null-terminated compiler version string");
930 endSymbolRecord(CompilerEnd);
939void CodeViewDebug::emitBuildInfo() {
951 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
954 const DIFile *MainSourceFile = CU->getFile();
965 TypeTable,
Asm->TM.Options.MCOptions.CommandlineArgs);
967 BuildInfoRecord BIR(BuildInfoArgs);
968 TypeIndex BuildInfoIndex = TypeTable.writeLeafType(BIR);
972 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
973 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
974 OS.AddComment(
"LF_BUILDINFO index");
975 OS.emitInt32(BuildInfoIndex.
getIndex());
976 endSymbolRecord(BIEnd);
977 endCVSubsection(BISubsecEnd);
980void CodeViewDebug::emitInlineeLinesSubsection() {
981 if (InlinedSubprograms.empty())
984 OS.AddComment(
"Inlinee lines subsection");
985 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
991 OS.AddComment(
"Inlinee lines signature");
992 OS.emitInt32(
unsigned(InlineeLinesSignature::Normal));
994 for (
const DISubprogram *SP : InlinedSubprograms) {
995 assert(TypeIndices.count({SP, nullptr}));
996 TypeIndex InlineeIdx = TypeIndices[{
SP,
nullptr}];
999 unsigned FileId = maybeRecordFile(
SP->getFile());
1000 OS.AddComment(
"Inlined function " +
SP->getName() +
" starts at " +
1001 SP->getFilename() + Twine(
':') + Twine(
SP->getLine()));
1003 OS.AddComment(
"Type index of inlined function");
1004 OS.emitInt32(InlineeIdx.
getIndex());
1005 OS.AddComment(
"Offset into filechecksum table");
1006 OS.emitCVFileChecksumOffsetDirective(FileId);
1007 OS.AddComment(
"Starting line number");
1008 OS.emitInt32(
SP->getLine());
1011 endCVSubsection(InlineEnd);
1014void CodeViewDebug::emitInlinedCallSite(
const FunctionInfo &FI,
1017 assert(TypeIndices.count({Site.Inlinee, nullptr}));
1018 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee,
nullptr}];
1021 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
1023 OS.AddComment(
"PtrParent");
1025 OS.AddComment(
"PtrEnd");
1027 OS.AddComment(
"Inlinee type index");
1028 OS.emitInt32(InlineeIdx.
getIndex());
1030 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
1031 unsigned StartLineNum = Site.Inlinee->getLine();
1033 OS.emitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum,
1036 endSymbolRecord(InlineEnd);
1038 emitLocalVariableList(FI, Site.InlinedLocals);
1041 for (
const DILocation *ChildSite : Site.ChildSites) {
1042 auto I = FI.InlineSites.find(ChildSite);
1043 assert(
I != FI.InlineSites.end() &&
1044 "child site not in function inline site map");
1045 emitInlinedCallSite(FI, ChildSite,
I->second);
1049 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1052void CodeViewDebug::switchToDebugSectionForSymbol(
const MCSymbol *GVSym) {
1056 MCSectionCOFF *GVSec =
1057 GVSym ?
static_cast<MCSectionCOFF *
>(&GVSym->
getSection()) : nullptr;
1060 auto *DebugSec =
static_cast<MCSectionCOFF *
>(
1061 CompilerInfoAsm->getObjFileLowering().getCOFFDebugSymbolsSection());
1062 DebugSec = OS.getContext().getAssociativeCOFFSection(DebugSec, KeySym);
1064 OS.switchSection(DebugSec);
1068 if (ComdatDebugSections.insert(DebugSec).second)
1069 emitCodeViewMagicVersion();
1074void CodeViewDebug::emitDebugInfoForThunk(
const Function *GV,
1077 std::string FuncName =
1081 OS.AddComment(
"Symbol subsection for " + Twine(FuncName));
1082 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1085 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1086 OS.AddComment(
"PtrParent");
1088 OS.AddComment(
"PtrEnd");
1090 OS.AddComment(
"PtrNext");
1092 OS.AddComment(
"Thunk section relative address");
1093 OS.emitCOFFSecRel32(Fn, 0);
1094 OS.AddComment(
"Thunk section index");
1095 OS.emitCOFFSectionIndex(Fn);
1096 OS.AddComment(
"Code size");
1097 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 2);
1098 OS.AddComment(
"Ordinal");
1099 OS.emitInt8(
unsigned(ordinal));
1100 OS.AddComment(
"Function name");
1103 endSymbolRecord(ThunkRecordEnd);
1109 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1111 endCVSubsection(SymbolsEnd);
1114void CodeViewDebug::emitDebugInfoForFunction(
const Function *GV,
1122 switchToDebugSectionForSymbol(Fn);
1124 std::string FuncName;
1127 setCurrentSubprogram(SP);
1129 if (
SP->isThunk()) {
1130 emitDebugInfoForThunk(GV, FI, Fn);
1136 if (!
SP->getName().empty())
1137 FuncName = getFullyQualifiedName(
SP->getScope(),
SP->getName());
1140 if (FuncName.empty())
1144 if (
MMI->getModule()->getTargetTriple().getArch() ==
Triple::x86)
1145 OS.emitCVFPOData(Fn);
1148 OS.AddComment(
"Symbol subsection for " + Twine(FuncName));
1149 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1152 : SymbolKind::S_GPROC32_ID;
1153 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1156 OS.AddComment(
"PtrParent");
1158 OS.AddComment(
"PtrEnd");
1160 OS.AddComment(
"PtrNext");
1164 OS.AddComment(
"Code size");
1165 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 4);
1166 OS.AddComment(
"Offset after prologue");
1168 OS.AddComment(
"Offset before epilogue");
1170 OS.AddComment(
"Function type index");
1171 OS.emitInt32(getFuncIdForSubprogram(GV->
getSubprogram()).getIndex());
1172 OS.AddComment(
"Function section relative address");
1173 OS.emitCOFFSecRel32(Fn, 0);
1174 OS.AddComment(
"Function section index");
1175 OS.emitCOFFSectionIndex(Fn);
1176 OS.AddComment(
"Flags");
1177 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;
1178 if (FI.HasFramePointer)
1179 ProcFlags |= ProcSymFlags::HasFP;
1181 ProcFlags |= ProcSymFlags::IsNoReturn;
1183 ProcFlags |= ProcSymFlags::IsNoInline;
1184 OS.emitInt8(
static_cast<uint8_t
>(ProcFlags));
1186 OS.AddComment(
"Function name");
1189 endSymbolRecord(ProcRecordEnd);
1191 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1193 OS.AddComment(
"FrameSize");
1194 OS.emitInt32(FI.FrameSize - FI.CSRSize);
1195 OS.AddComment(
"Padding");
1197 OS.AddComment(
"Offset of padding");
1199 OS.AddComment(
"Bytes of callee saved registers");
1200 OS.emitInt32(FI.CSRSize);
1201 OS.AddComment(
"Exception handler offset");
1203 OS.AddComment(
"Exception handler section");
1205 OS.AddComment(
"Flags (defines frame register)");
1206 OS.emitInt32(uint32_t(FI.FrameProcOpts));
1207 endSymbolRecord(FrameProcEnd);
1209 emitInlinees(FI.Inlinees);
1210 emitLocalVariableList(FI, FI.Locals);
1211 emitGlobalVariableList(FI.Globals);
1212 emitLexicalBlockList(FI.ChildBlocks, FI);
1217 for (
const DILocation *InlinedAt : FI.ChildSites) {
1218 auto I = FI.InlineSites.find(InlinedAt);
1219 assert(
I != FI.InlineSites.end() &&
1220 "child site not in function inline site map");
1221 emitInlinedCallSite(FI, InlinedAt,
I->second);
1224 for (
auto Annot : FI.Annotations) {
1227 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1228 OS.emitCOFFSecRel32(Label, 0);
1230 OS.emitCOFFSectionIndex(Label);
1236 assert(Str.data()[Str.size()] ==
'\0' &&
"non-nullterminated MDString");
1237 OS.emitBytes(StringRef(Str.data(), Str.size() + 1));
1239 endSymbolRecord(AnnotEnd);
1242 for (
auto HeapAllocSite : FI.HeapAllocSites) {
1243 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1244 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1245 const DIType *DITy = std::get<2>(HeapAllocSite);
1246 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1247 OS.AddComment(
"Call site offset");
1248 OS.emitCOFFSecRel32(BeginLabel, 0);
1249 OS.AddComment(
"Call site section index");
1250 OS.emitCOFFSectionIndex(BeginLabel);
1251 OS.AddComment(
"Call instruction length");
1252 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
1253 OS.AddComment(
"Type index");
1254 OS.emitInt32(getCompleteTypeIndex(DITy).getIndex());
1255 endSymbolRecord(HeapAllocEnd);
1259 emitDebugInfoForUDTs(LocalUDTs);
1261 emitDebugInfoForJumpTables(FI);
1264 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1266 endCVSubsection(SymbolsEnd);
1269 OS.emitCVLinetableDirective(FI.FuncId, Fn, FI.End);
1273CodeViewDebug::createDefRangeMem(uint16_t CVRegister,
int Offset) {
1279 DR.StructOffset = 0;
1280 DR.CVRegister = CVRegister;
1284void CodeViewDebug::collectVariableInfoFromMFTable(
1286 const MachineFunction &MF = *
Asm->MF;
1291 for (
const MachineFunction::VariableDbgInfo &VI :
1295 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1296 "Expected inlined-at fields to agree");
1298 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1307 int64_t ExprOffset = 0;
1311 if (
VI.Expr->getNumElements() == 1 &&
1312 VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)
1314 else if (!
VI.Expr->extractIfOffset(ExprOffset))
1320 StackOffset FrameOffset =
1322 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1331 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset);
1339 End = End ? End :
Asm->getFunctionEnd();
1340 Var.DefRanges[DefRange].emplace_back(Begin, End);
1344 Var.UseReferenceType =
true;
1346 recordLocalVariable(std::move(Var), Scope);
1351 return !
Loc.LoadChain.empty() &&
Loc.LoadChain.back() == 0;
1355 return Loc.LoadChain.size() == 2 &&
Loc.LoadChain.back() == 0;
1358void CodeViewDebug::calculateRanges(
1360 const TargetRegisterInfo *
TRI =
Asm->MF->getSubtarget().getRegisterInfo();
1363 for (
auto I = Entries.
begin(),
E = Entries.
end();
I !=
E; ++
I) {
1365 if (!
Entry.isDbgValue())
1367 const MachineInstr *DVInst =
Entry.getInstr();
1371 std::optional<DbgVariableLocation>
Location =
1382 Var.ConstantValue =
APSInt(APInt(64,
Op.getImm()),
false);
1393 if (Var.UseReferenceType) {
1402 Var.UseReferenceType =
true;
1403 Var.DefRanges.clear();
1404 calculateRanges(Var, Entries);
1415 if (
Location->FragmentInfo->OffsetInBits % 8)
1425 DR.InMemory = !
Location->LoadChain.empty();
1429 DR.IsSubfield =
true;
1430 DR.StructOffset =
Location->FragmentInfo->OffsetInBits / 8;
1432 DR.IsSubfield =
false;
1433 DR.StructOffset = 0;
1440 auto &EndingEntry = Entries[
Entry.getEndIndex()];
1441 End = EndingEntry.isDbgValue()
1445 End =
Asm->getFunctionEnd();
1449 SmallVectorImpl<std::pair<const MCSymbol *, const MCSymbol *>> &
R =
1451 if (!
R.empty() &&
R.back().second == Begin)
1452 R.back().second = End;
1454 R.emplace_back(Begin, End);
1460void CodeViewDebug::collectVariableInfo(
const DISubprogram *SP) {
1461 DenseSet<InlinedEntity> Processed;
1463 collectVariableInfoFromMFTable(Processed);
1466 InlinedEntity
IV =
I.first;
1470 const DILocation *InlinedAt =
IV.second;
1473 const auto &Entries =
I.second;
1475 LexicalScope *
Scope =
nullptr;
1487 calculateRanges(Var, Entries);
1488 recordLocalVariable(std::move(Var), Scope);
1497 auto Insertion = FnDebugInfo.
insert({&GV, std::make_unique<FunctionInfo>()});
1498 assert(Insertion.second &&
"function already has info");
1499 CurFn = Insertion.first->second.get();
1500 CurFn->FuncId = NextFuncId++;
1501 CurFn->Begin =
Asm->getFunctionBegin();
1509 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1515 if (CurFn->FrameSize > 0) {
1520 CurFn->HasFramePointer =
true;
1523 if (CurFn->HasStackRealignment) {
1574 CurFn->FrameProcOpts = FPO;
1576 OS.emitCVFuncIdDirective(CurFn->FuncId);
1583 bool EmptyPrologue =
true;
1584 for (
const auto &
MBB : *MF) {
1585 for (
const auto &
MI :
MBB) {
1590 }
else if (!
MI.isMetaInstruction()) {
1591 EmptyPrologue =
false;
1599 maybeRecordLocation(FnStartDL, MF);
1603 for (
const auto &
MBB : *MF) {
1604 for (
const auto &
MI :
MBB) {
1605 if (
MI.getHeapAllocMarker()) {
1613 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
1615 discoverJumpTableBranches(MF,
isThumb);
1623 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1624 if (
DIScope *Scope =
T->getScope()) {
1625 switch (Scope->getTag()) {
1626 case dwarf::DW_TAG_structure_type:
1627 case dwarf::DW_TAG_class_type:
1628 case dwarf::DW_TAG_union_type:
1638 if (!
T ||
T->isForwardDecl())
1644 T = DT->getBaseType();
1649void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1657 const DISubprogram *ClosestSubprogram =
1658 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1660 std::string FullyQualifiedName =
1663 if (ClosestSubprogram ==
nullptr) {
1664 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1665 }
else if (ClosestSubprogram == CurrentSubprogram) {
1666 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1677TypeIndex CodeViewDebug::lowerType(
const DIType *Ty,
const DIType *ClassTy) {
1680 case dwarf::DW_TAG_array_type:
1682 case dwarf::DW_TAG_typedef:
1684 case dwarf::DW_TAG_base_type:
1686 case dwarf::DW_TAG_pointer_type:
1690 case dwarf::DW_TAG_reference_type:
1691 case dwarf::DW_TAG_rvalue_reference_type:
1693 case dwarf::DW_TAG_ptr_to_member_type:
1695 case dwarf::DW_TAG_restrict_type:
1696 case dwarf::DW_TAG_const_type:
1697 case dwarf::DW_TAG_volatile_type:
1700 case dwarf::DW_TAG_subroutine_type:
1709 case dwarf::DW_TAG_enumeration_type:
1711 case dwarf::DW_TAG_class_type:
1712 case dwarf::DW_TAG_structure_type:
1714 case dwarf::DW_TAG_union_type:
1716 case dwarf::DW_TAG_string_type:
1718 case dwarf::DW_TAG_unspecified_type:
1719 if (Ty->
getName() ==
"decltype(nullptr)")
1728TypeIndex CodeViewDebug::lowerTypeAlias(
const DIDerivedType *Ty) {
1729 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1734 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) &&
1735 TypeName ==
"HRESULT")
1736 return TypeIndex(SimpleTypeKind::HResult);
1737 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::UInt16Short) &&
1738 TypeName ==
"wchar_t")
1739 return TypeIndex(SimpleTypeKind::WideCharacter);
1741 return UnderlyingTypeIndex;
1746 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1748 TypeIndex IndexType = getPointerSizeInBytes() == 8
1749 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1756 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1757 const DINode *Element =
Elements[i];
1758 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1768 Count = CI->getSExtValue();
1774 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1775 Count = UI->getSExtValue() - Lowerbound + 1;
1786 ElementSize *=
Count;
1790 uint64_t ArraySize =
1791 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1794 ArrayRecord AR(ElementTypeIndex, IndexType, ArraySize, Name);
1795 ElementTypeIndex = TypeTable.writeLeafType(AR);
1798 return ElementTypeIndex;
1806TypeIndex CodeViewDebug::lowerTypeString(
const DIStringType *Ty) {
1807 TypeIndex CharType = TypeIndex(SimpleTypeKind::NarrowCharacter);
1811 TypeIndex IndexType = getPointerSizeInBytes() == 8
1812 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1816 ArrayRecord AR(CharType, IndexType, ArraySize, Name);
1818 return TypeTable.writeLeafType(AR);
1821TypeIndex CodeViewDebug::lowerTypeBasic(
const DIBasicType *Ty) {
1831 case dwarf::DW_ATE_address:
1834 case dwarf::DW_ATE_boolean:
1836 case 1: STK = SimpleTypeKind::Boolean8;
break;
1837 case 2: STK = SimpleTypeKind::Boolean16;
break;
1838 case 4: STK = SimpleTypeKind::Boolean32;
break;
1839 case 8: STK = SimpleTypeKind::Boolean64;
break;
1840 case 16: STK = SimpleTypeKind::Boolean128;
break;
1843 case dwarf::DW_ATE_complex_float:
1847 case 4: STK = SimpleTypeKind::Complex16;
break;
1848 case 8: STK = SimpleTypeKind::Complex32;
break;
1849 case 16: STK = SimpleTypeKind::Complex64;
break;
1850 case 20: STK = SimpleTypeKind::Complex80;
break;
1851 case 32: STK = SimpleTypeKind::Complex128;
break;
1854 case dwarf::DW_ATE_float:
1856 case 2: STK = SimpleTypeKind::Float16;
break;
1857 case 4: STK = SimpleTypeKind::Float32;
break;
1858 case 6: STK = SimpleTypeKind::Float48;
break;
1859 case 8: STK = SimpleTypeKind::Float64;
break;
1860 case 10: STK = SimpleTypeKind::Float80;
break;
1861 case 16: STK = SimpleTypeKind::Float128;
break;
1864 case dwarf::DW_ATE_signed:
1866 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1867 case 2: STK = SimpleTypeKind::Int16Short;
break;
1868 case 4: STK = SimpleTypeKind::Int32;
break;
1869 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1870 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1873 case dwarf::DW_ATE_unsigned:
1875 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1876 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1877 case 4: STK = SimpleTypeKind::UInt32;
break;
1878 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1879 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1882 case dwarf::DW_ATE_UTF:
1884 case 1: STK = SimpleTypeKind::Character8;
break;
1885 case 2: STK = SimpleTypeKind::Character16;
break;
1886 case 4: STK = SimpleTypeKind::Character32;
break;
1889 case dwarf::DW_ATE_signed_char:
1891 STK = SimpleTypeKind::SignedCharacter;
1893 case dwarf::DW_ATE_unsigned_char:
1895 STK = SimpleTypeKind::UnsignedCharacter;
1905 if (STK == SimpleTypeKind::Int32 &&
1907 STK = SimpleTypeKind::Int32Long;
1908 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1909 Ty->
getName() ==
"unsigned long"))
1910 STK = SimpleTypeKind::UInt32Long;
1911 if (STK == SimpleTypeKind::UInt16Short &&
1913 STK = SimpleTypeKind::WideCharacter;
1914 if ((STK == SimpleTypeKind::SignedCharacter ||
1915 STK == SimpleTypeKind::UnsignedCharacter) &&
1917 STK = SimpleTypeKind::NarrowCharacter;
1919 return TypeIndex(STK);
1922TypeIndex CodeViewDebug::lowerTypePointer(
const DIDerivedType *Ty,
1924 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1928 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1930 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1932 ? SimpleTypeMode::NearPointer64
1933 : SimpleTypeMode::NearPointer32;
1938 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1942 case dwarf::DW_TAG_pointer_type:
1943 PM = PointerMode::Pointer;
1945 case dwarf::DW_TAG_reference_type:
1946 PM = PointerMode::LValueReference;
1948 case dwarf::DW_TAG_rvalue_reference_type:
1949 PM = PointerMode::RValueReference;
1954 PO |= PointerOptions::Const;
1956 PointerRecord PR(PointeeTI, PK, PM, PO, Ty->
getSizeInBits() / 8);
1957 return TypeTable.writeLeafType(PR);
1970 case DINode::FlagSingleInheritance:
1972 case DINode::FlagMultipleInheritance:
1974 case DINode::FlagVirtualInheritance:
1982 case DINode::FlagSingleInheritance:
1984 case DINode::FlagMultipleInheritance:
1986 case DINode::FlagVirtualInheritance:
1993TypeIndex CodeViewDebug::lowerTypeMemberPointer(
const DIDerivedType *Ty,
1995 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
1998 TypeIndex PointeeTI =
1999 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->
getClassType() :
nullptr);
2000 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2001 : PointerKind::Near32;
2002 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
2003 : PointerMode::PointerToDataMember;
2007 MemberPointerInfo MPI(
2009 PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);
2010 return TypeTable.writeLeafType(PR);
2027TypeIndex CodeViewDebug::lowerTypeModifier(
const DIDerivedType *Ty) {
2031 const DIType *BaseTy = Ty;
2032 while (IsModifier && BaseTy) {
2034 switch (BaseTy->
getTag()) {
2035 case dwarf::DW_TAG_const_type:
2036 Mods |= ModifierOptions::Const;
2037 PO |= PointerOptions::Const;
2039 case dwarf::DW_TAG_volatile_type:
2040 Mods |= ModifierOptions::Volatile;
2041 PO |= PointerOptions::Volatile;
2043 case dwarf::DW_TAG_restrict_type:
2046 PO |= PointerOptions::Restrict;
2061 switch (BaseTy->
getTag()) {
2062 case dwarf::DW_TAG_pointer_type:
2063 case dwarf::DW_TAG_reference_type:
2064 case dwarf::DW_TAG_rvalue_reference_type:
2066 case dwarf::DW_TAG_ptr_to_member_type:
2073 TypeIndex ModifiedTI = getTypeIndex(BaseTy);
2077 if (Mods == ModifierOptions::None)
2080 ModifierRecord MR(ModifiedTI, Mods);
2081 return TypeTable.writeLeafType(MR);
2087 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2090 if (ReturnAndArgTypeIndices.
size() > 1 &&
2096 if (!ReturnAndArgTypeIndices.
empty()) {
2097 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2098 ReturnTypeIndex = ReturnAndArgTypesRef.consume_front();
2099 ArgTypeIndices = ReturnAndArgTypesRef;
2102 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2103 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2108 ProcedureRecord Procedure(ReturnTypeIndex, CC, FO, ArgTypeIndices.
size(),
2110 return TypeTable.writeLeafType(Procedure);
2113TypeIndex CodeViewDebug::lowerTypeMemberFunction(
const DISubroutineType *Ty,
2116 bool IsStaticMethod,
2119 TypeIndex ClassType = getTypeIndex(ClassTy);
2126 if (ReturnAndArgs.
size() > Index) {
2127 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
2133 TypeIndex ThisTypeIndex;
2134 if (!IsStaticMethod && ReturnAndArgs.
size() > Index) {
2135 if (
const DIDerivedType *PtrTy =
2137 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2138 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2144 while (Index < ReturnAndArgs.
size())
2145 ArgTypeIndices.
push_back(getTypeIndex(ReturnAndArgs[Index++]));
2151 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2152 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2156 MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FO,
2157 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2158 return TypeTable.writeLeafType(MFR);
2161TypeIndex CodeViewDebug::lowerTypeVFTableShape(
const DIDerivedType *Ty) {
2162 unsigned VSlotCount =
2166 VFTableShapeRecord VFTSR(Slots);
2167 return TypeTable.writeLeafType(VFTSR);
2184 if (SP->isArtificial())
2194 if (SP->getFlags() & DINode::FlagStaticMember)
2197 switch (SP->getVirtuality()) {
2198 case dwarf::DW_VIRTUALITY_none:
2200 case dwarf::DW_VIRTUALITY_virtual:
2202 case dwarf::DW_VIRTUALITY_pure_virtual:
2213 switch (Ty->getTag()) {
2214 case dwarf::DW_TAG_class_type:
2215 return TypeRecordKind::Class;
2216 case dwarf::DW_TAG_structure_type:
2217 return TypeRecordKind::Struct;
2231 if (!Ty->getIdentifier().empty())
2245 if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) {
2249 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2261void CodeViewDebug::addUDTSrcLine(
const DIType *Ty, TypeIndex TI) {
2263 case dwarf::DW_TAG_class_type:
2264 case dwarf::DW_TAG_structure_type:
2265 case dwarf::DW_TAG_union_type:
2266 case dwarf::DW_TAG_enumeration_type:
2272 if (
const auto *File = Ty->
getFile()) {
2273 StringIdRecord SIDR(TypeIndex(0x0), getFullFilepath(File));
2274 TypeIndex SIDI = TypeTable.writeLeafType(SIDR);
2276 UdtSourceLineRecord USLR(TI, SIDI, Ty->
getLine());
2277 TypeTable.writeLeafType(USLR);
2284 unsigned EnumeratorCount = 0;
2287 CO |= ClassOptions::ForwardReference;
2289 ContinuationRecordBuilder ContinuationBuilder;
2290 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2296 EnumeratorRecord ER(MemberAccess::Public,
2303 FTI = TypeTable.insertRecord(ContinuationBuilder);
2306 std::string FullName = getFullyQualifiedName(Ty);
2308 EnumRecord ER(EnumeratorCount, CO, FTI, FullName, Ty->
getIdentifier(),
2310 TypeIndex EnumTI = TypeTable.writeLeafType(ER);
2312 addUDTSrcLine(Ty, EnumTI);
2346void CodeViewDebug::clear() {
2347 assert(CurFn ==
nullptr);
2349 FnDebugInfo.clear();
2350 FileToFilepathMap.clear();
2353 TypeIndices.clear();
2354 CompleteTypeIndices.clear();
2355 ScopeGlobals.clear();
2356 CVGlobalVariableOffsets.clear();
2362 Info.Members.push_back({DDTy, 0});
2365 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2366 DINode::FlagStaticMember) {
2369 StaticConstMembers.push_back(DDTy);
2381 const DIType *Ty = DDTy->getBaseType();
2382 bool FullyResolved =
false;
2383 while (!FullyResolved) {
2385 case dwarf::DW_TAG_const_type:
2386 case dwarf::DW_TAG_volatile_type:
2392 FullyResolved =
true;
2401 ClassInfo NestedInfo = collectClassInfo(DCTy);
2402 for (
const ClassInfo::MemberInfo &IndirectField : NestedInfo.
Members)
2403 Info.Members.push_back(
2411 for (
auto *Element : Elements) {
2417 Info.Methods[
SP->getRawName()].push_back(SP);
2419 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2420 collectMemberInfo(
Info, DDTy);
2421 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2422 Info.Inheritance.push_back(DDTy);
2423 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2424 DDTy->
getName() ==
"__vtbl_ptr_type") {
2425 Info.VShapeTI = getTypeIndex(DDTy);
2426 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2427 Info.NestedTypes.push_back(DDTy);
2428 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2433 Info.NestedTypes.push_back(Composite);
2443 return Ty->getName().empty() && Ty->getIdentifier().empty() &&
2444 !Ty->isForwardDecl();
2456 auto I = CompleteTypeIndices.find(Ty);
2457 if (
I != CompleteTypeIndices.end() &&
I->second == TypeIndex())
2459 return getCompleteTypeIndex(Ty);
2467 std::string FullName = getFullyQualifiedName(Ty);
2468 ClassRecord CR(Kind, 0, CO, TypeIndex(), TypeIndex(), TypeIndex(), 0,
2470 TypeIndex FwdDeclTI = TypeTable.writeLeafType(CR);
2472 DeferredCompleteTypes.push_back(Ty);
2476TypeIndex CodeViewDebug::lowerCompleteTypeClass(
const DICompositeType *Ty) {
2482 unsigned FieldCount;
2485 lowerRecordFieldList(Ty);
2488 CO |= ClassOptions::ContainsNestedClass;
2496 CO |= ClassOptions::HasConstructorOrDestructor;
2498 std::string FullName = getFullyQualifiedName(Ty);
2502 ClassRecord CR(Kind, FieldCount, CO, FieldTI, TypeIndex(), VShapeTI,
2504 TypeIndex ClassTI = TypeTable.writeLeafType(CR);
2506 addUDTSrcLine(Ty, ClassTI);
2516 return getCompleteTypeIndex(Ty);
2520 std::string FullName = getFullyQualifiedName(Ty);
2521 UnionRecord UR(0, CO, TypeIndex(), 0, FullName, Ty->
getIdentifier());
2522 TypeIndex FwdDeclTI = TypeTable.writeLeafType(UR);
2524 DeferredCompleteTypes.push_back(Ty);
2528TypeIndex CodeViewDebug::lowerCompleteTypeUnion(
const DICompositeType *Ty) {
2531 unsigned FieldCount;
2534 lowerRecordFieldList(Ty);
2537 CO |= ClassOptions::ContainsNestedClass;
2540 std::string FullName = getFullyQualifiedName(Ty);
2542 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2544 TypeIndex UnionTI = TypeTable.writeLeafType(UR);
2546 addUDTSrcLine(Ty, UnionTI);
2553std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2559 unsigned MemberCount = 0;
2560 ClassInfo
Info = collectClassInfo(Ty);
2561 ContinuationRecordBuilder ContinuationBuilder;
2562 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2565 for (
const DIDerivedType *
I :
Info.Inheritance) {
2566 if (
I->getFlags() & DINode::FlagVirtual) {
2568 unsigned VBPtrOffset =
I->getVBPtrOffset();
2570 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2571 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2572 ? TypeRecordKind::IndirectVirtualBaseClass
2573 : TypeRecordKind::VirtualBaseClass;
2574 VirtualBaseClassRecord VBCR(
2576 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2582 assert(
I->getOffsetInBits() % 8 == 0 &&
2583 "bases must be on byte boundaries");
2585 getTypeIndex(
I->getBaseType()),
2586 I->getOffsetInBits() / 8);
2593 for (ClassInfo::MemberInfo &MemberInfo :
Info.Members) {
2595 TypeIndex MemberBaseType = getTypeIndex(
Member->getBaseType());
2596 StringRef MemberName =
Member->getName();
2600 if (
Member->isStaticMember()) {
2601 StaticDataMemberRecord SDMR(
Access, MemberBaseType, MemberName);
2608 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2609 Member->getName().starts_with(
"_vptr$")) {
2610 VFPtrRecord VFPR(getTypeIndex(
Member->getBaseType()));
2617 uint64_t MemberOffsetInBits =
2619 if (
Member->isBitField()) {
2620 uint64_t StartBitOffset = MemberOffsetInBits;
2621 if (
const auto *CI =
2623 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2625 StartBitOffset -= MemberOffsetInBits;
2626 BitFieldRecord BFR(MemberBaseType,
Member->getSizeInBits(),
2628 MemberBaseType = TypeTable.writeLeafType(BFR);
2630 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2631 DataMemberRecord DMR(
Access, MemberBaseType, MemberOffsetInBytes,
2638 for (
auto &MethodItr :
Info.Methods) {
2639 StringRef
Name = MethodItr.first->getString();
2641 std::vector<OneMethodRecord> Methods;
2642 for (
const DISubprogram *SP : MethodItr.second) {
2643 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2644 bool Introduced =
SP->getFlags() & DINode::FlagIntroducedVirtual;
2646 unsigned VFTableOffset = -1;
2648 VFTableOffset =
SP->getVirtualIndex() * getPointerSizeInBytes();
2650 Methods.push_back(OneMethodRecord(
2656 assert(!Methods.empty() &&
"Empty methods map entry");
2657 if (Methods.size() == 1)
2662 MethodOverloadListRecord MOLR(Methods);
2663 TypeIndex MethodList = TypeTable.writeLeafType(MOLR);
2665 OverloadedMethodRecord OMR(Methods.size(), MethodList, Name);
2671 for (
const DIType *
Nested :
Info.NestedTypes) {
2672 NestedTypeRecord
R(getTypeIndex(
Nested),
Nested->getName());
2677 TypeIndex FieldTI = TypeTable.insertRecord(ContinuationBuilder);
2678 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2679 !
Info.NestedTypes.empty());
2682TypeIndex CodeViewDebug::getVBPTypeIndex() {
2683 if (!VBPType.getIndex()) {
2686 TypeIndex ModifiedTI = TypeTable.writeLeafType(MR);
2688 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2689 : PointerKind::Near32;
2692 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2693 VBPType = TypeTable.writeLeafType(PR);
2699TypeIndex CodeViewDebug::getTypeIndex(
const DIType *Ty,
const DIType *ClassTy) {
2707 auto I = TypeIndices.find({Ty, ClassTy});
2708 if (
I != TypeIndices.end())
2712 TypeIndex TI = lowerType(Ty, ClassTy);
2713 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2717CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2719 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2720 "this type must be a pointer type");
2723 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2724 Options = PointerOptions::LValueRefThisPointer;
2725 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2726 Options = PointerOptions::RValueRefThisPointer;
2733 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2734 if (
I != TypeIndices.end())
2738 TypeIndex TI = lowerTypePointer(PtrTy,
Options);
2739 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2742TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(
const DIType *Ty) {
2743 PointerRecord PR(getTypeIndex(Ty),
2744 getPointerSizeInBytes() == 8 ? PointerKind::Near64
2745 : PointerKind::Near32,
2746 PointerMode::LValueReference, PointerOptions::None,
2748 return TypeTable.writeLeafType(PR);
2751TypeIndex CodeViewDebug::getCompleteTypeIndex(
const DIType *Ty) {
2759 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2760 (void)getTypeIndex(Ty);
2761 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2767 case dwarf::DW_TAG_class_type:
2768 case dwarf::DW_TAG_structure_type:
2769 case dwarf::DW_TAG_union_type:
2772 return getTypeIndex(Ty);
2783 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2784 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2789 if (CTy->isForwardDecl())
2796 auto InsertResult = CompleteTypeIndices.try_emplace(CTy);
2797 if (!InsertResult.second)
2798 return InsertResult.first->second;
2801 switch (CTy->getTag()) {
2802 case dwarf::DW_TAG_class_type:
2803 case dwarf::DW_TAG_structure_type:
2804 TI = lowerCompleteTypeClass(CTy);
2806 case dwarf::DW_TAG_union_type:
2807 TI = lowerCompleteTypeUnion(CTy);
2817 CompleteTypeIndices[CTy] = TI;
2825void CodeViewDebug::emitDeferredCompleteTypes() {
2827 while (!DeferredCompleteTypes.empty()) {
2828 std::swap(DeferredCompleteTypes, TypesToEmit);
2829 for (
const DICompositeType *RecordTy : TypesToEmit)
2830 getCompleteTypeIndex(RecordTy);
2831 TypesToEmit.clear();
2835void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2839 for (
const LocalVariable &L : Locals)
2840 if (
L.DIVar->isParameter())
2842 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2843 return L->DIVar->getArg() <
R->DIVar->getArg();
2845 for (
const LocalVariable *L : Params)
2846 emitLocalVariable(FI, *L);
2849 for (
const LocalVariable &L : Locals) {
2850 if (!
L.DIVar->isParameter()) {
2851 if (
L.ConstantValue) {
2854 const DIType *Ty =
L.DIVar->getType();
2856 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2858 emitLocalVariable(FI, L);
2864void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2865 const LocalVariable &Var) {
2867 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2870 if (Var.DIVar->isParameter())
2871 Flags |= LocalSymFlags::IsParameter;
2872 if (Var.DefRanges.empty())
2873 Flags |= LocalSymFlags::IsOptimizedOut;
2875 OS.AddComment(
"TypeIndex");
2876 TypeIndex TI = Var.UseReferenceType
2877 ? getTypeIndexForReferenceTo(Var.DIVar->getType())
2878 : getCompleteTypeIndex(Var.DIVar->
getType());
2880 OS.AddComment(
"Flags");
2881 OS.emitInt16(
static_cast<uint16_t
>(Flags));
2884 endSymbolRecord(LocalEnd);
2889 SmallString<20> BytePrefix;
2890 for (
const auto &Pair : Var.DefRanges) {
2891 LocalVarDef DefRange = Pair.first;
2892 const auto &Ranges = Pair.second;
2894 if (DefRange.InMemory) {
2895 int Offset = DefRange.DataOffset;
2896 unsigned Reg = DefRange.CVRegister;
2901 if (RegisterId(Reg) == RegisterId::ESP) {
2902 Reg = unsigned(RegisterId::VFRAME);
2903 Offset += FI.OffsetAdjustment;
2909 EncodedFramePtrReg EncFP = encodeFramePtrReg(RegisterId(Reg), TheCPU);
2910 if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2911 (bool(Flags & LocalSymFlags::IsParameter)
2912 ? (EncFP == FI.EncodedParamFramePtrReg)
2913 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2914 DefRangeFramePointerRelHeader DRHdr;
2915 DRHdr.Offset = Offset;
2916 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2918 uint16_t RegRelFlags = 0;
2919 if (DefRange.IsSubfield) {
2920 RegRelFlags = DefRangeRegisterRelSym::IsSubfieldFlag |
2921 (DefRange.StructOffset
2922 << DefRangeRegisterRelSym::OffsetInParentShift);
2924 DefRangeRegisterRelHeader DRHdr;
2925 DRHdr.Register = Reg;
2926 DRHdr.Flags = RegRelFlags;
2927 DRHdr.BasePointerOffset = Offset;
2928 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2931 assert(DefRange.DataOffset == 0 &&
"unexpected offset into register");
2932 if (DefRange.IsSubfield) {
2933 DefRangeSubfieldRegisterHeader DRHdr;
2934 DRHdr.Register = DefRange.CVRegister;
2935 DRHdr.MayHaveNoName = 0;
2936 DRHdr.OffsetInParent = DefRange.StructOffset;
2937 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2939 DefRangeRegisterHeader DRHdr;
2940 DRHdr.Register = DefRange.CVRegister;
2941 DRHdr.MayHaveNoName = 0;
2942 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2949 const FunctionInfo& FI) {
2950 for (LexicalBlock *
Block : Blocks)
2951 emitLexicalBlock(*
Block, FI);
2956void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2957 const FunctionInfo& FI) {
2958 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2959 OS.AddComment(
"PtrParent");
2961 OS.AddComment(
"PtrEnd");
2963 OS.AddComment(
"Code size");
2964 OS.emitAbsoluteSymbolDiff(
Block.End,
Block.Begin, 4);
2965 OS.AddComment(
"Function section relative address");
2966 OS.emitCOFFSecRel32(
Block.Begin, 0);
2967 OS.AddComment(
"Function section index");
2968 OS.emitCOFFSectionIndex(FI.Begin);
2969 OS.AddComment(
"Lexical block name");
2971 endSymbolRecord(RecordEnd);
2974 emitLocalVariableList(FI,
Block.Locals);
2975 emitGlobalVariableList(
Block.Globals);
2978 emitLexicalBlockList(
Block.Children, FI);
2981 emitEndSymbolRecord(SymbolKind::S_END);
2986void CodeViewDebug::collectLexicalBlockInfo(
2991 for (LexicalScope *Scope : Scopes)
2992 collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
2997void CodeViewDebug::collectLexicalBlockInfo(
3002 if (
Scope.isAbstractScope())
3007 bool IgnoreScope =
false;
3008 auto LI = ScopeVariables.find(&Scope);
3009 SmallVectorImpl<LocalVariable> *
Locals =
3010 LI != ScopeVariables.end() ? &LI->second :
nullptr;
3011 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
3012 SmallVectorImpl<CVGlobalVariable> *Globals =
3013 GI != ScopeGlobals.
end() ? GI->second.get() :
nullptr;
3015 const SmallVectorImpl<InsnRange> &
Ranges =
Scope.getRanges();
3018 if (!Locals && !Globals)
3048 collectLexicalBlockInfo(
Scope.getChildren(),
3058 auto BlockInsertion = CurFn->LexicalBlocks.try_emplace(DILB);
3059 if (!BlockInsertion.second)
3066 LexicalBlock &
Block = BlockInsertion.first->second;
3069 assert(
Block.Begin &&
"missing label for scope begin");
3070 assert(
Block.End &&
"missing label for scope end");
3073 Block.Locals = std::move(*Locals);
3075 Block.Globals = std::move(*Globals);
3077 collectLexicalBlockInfo(
Scope.getChildren(),
3085 assert(FnDebugInfo.count(&GV));
3086 assert(CurFn == FnDebugInfo[&GV].
get());
3092 collectLexicalBlockInfo(*CFS,
3100 ScopeVariables.clear();
3104 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3105 FnDebugInfo.erase(&GV);
3111 for (
const auto &
MBB : *MF) {
3112 for (
const auto &
MI :
MBB) {
3113 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3121 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
3123 collectDebugInfoForJumpTables(MF,
isThumb);
3127 CurFn->End =
Asm->getFunctionEnd();
3137 return DL &&
DL.getLine() != 0;
3144 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3152 for (
const auto &NextMI : *
MI->getParent()) {
3153 if (NextMI.isDebugInstr())
3155 DL = NextMI.getDebugLoc();
3168 maybeRecordLocation(
DL,
Asm->MF);
3181void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3189 if (EE.Value == SymKind)
3195 MCSymbol *BeginLabel =
MMI->getContext().createTempSymbol(),
3196 *EndLabel =
MMI->getContext().createTempSymbol();
3197 OS.AddComment(
"Record length");
3198 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
3199 OS.emitLabel(BeginLabel);
3200 if (OS.isVerboseAsm())
3202 OS.emitInt16(
unsigned(SymKind));
3206void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3211 OS.emitValueToAlignment(
Align(4));
3212 OS.emitLabel(SymEnd);
3215void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3216 OS.AddComment(
"Record length");
3218 if (OS.isVerboseAsm())
3220 OS.emitInt16(uint16_t(EndKind));
3223void CodeViewDebug::emitDebugInfoForUDTs(
3224 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3226 size_t OriginalSize = UDTs.size();
3228 for (
const auto &UDT : UDTs) {
3229 const DIType *
T =
UDT.second;
3231 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3232 OS.AddComment(
"Type");
3233 OS.emitInt32(getCompleteTypeIndex(
T).getIndex());
3234 assert(OriginalSize == UDTs.size() &&
3235 "getCompleteTypeIndex found new UDTs!");
3237 endSymbolRecord(UDTRecordEnd);
3241void CodeViewDebug::collectGlobalVariableInfo() {
3242 DenseMap<const DIGlobalVariableExpression *, const GlobalVariable *>
3244 for (
const GlobalVariable &GV :
MMI->getModule()->globals()) {
3246 GV.getDebugInfo(GVEs);
3247 for (
const auto *GVE : GVEs)
3248 GlobalMap[GVE] = &GV;
3251 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3252 for (
const MDNode *Node : CUs->
operands()) {
3254 for (
const auto *GVE : CU->getGlobalVariables()) {
3255 const DIGlobalVariable *DIGV = GVE->getVariable();
3256 const DIExpression *DIE = GVE->getExpression();
3264 (DIE->
getElement(0) == dwarf::DW_OP_plus_uconst))
3269 CVGlobalVariableOffsets.insert(
3274 CVGlobalVariable CVGV = {DIGV, DIE};
3275 GlobalVariables.emplace_back(std::move(CVGV));
3278 const auto *GV = GlobalMap.
lookup(GVE);
3283 SmallVector<CVGlobalVariable, 1> *VariableList;
3287 auto Insertion = ScopeGlobals.insert(
3288 {
Scope, std::unique_ptr<GlobalVariableList>()});
3289 if (Insertion.second)
3290 Insertion.first->second = std::make_unique<GlobalVariableList>();
3291 VariableList = Insertion.first->second.get();
3294 VariableList = &ComdatVariables;
3297 VariableList = &GlobalVariables;
3298 CVGlobalVariable CVGV = {DIGV, GV};
3304void CodeViewDebug::collectDebugInfoForGlobals() {
3305 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3306 const DIGlobalVariable *DIGV = CVGV.DIGV;
3308 getCompleteTypeIndex(DIGV->
getType());
3309 getFullyQualifiedName(Scope, DIGV->
getName());
3312 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3313 const DIGlobalVariable *DIGV = CVGV.DIGV;
3315 getCompleteTypeIndex(DIGV->
getType());
3316 getFullyQualifiedName(Scope, DIGV->
getName());
3320void CodeViewDebug::emitDebugInfoForGlobals() {
3324 switchToDebugSectionForSymbol(
nullptr);
3325 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3326 OS.AddComment(
"Symbol subsection for globals");
3327 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3328 emitGlobalVariableList(GlobalVariables);
3329 emitStaticConstMemberList();
3330 endCVSubsection(EndLabel);
3335 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3338 OS.AddComment(
"Symbol subsection for " +
3340 switchToDebugSectionForSymbol(GVSym);
3341 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3343 emitDebugInfoForGlobal(CVGV);
3344 endCVSubsection(EndLabel);
3348void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3349 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3350 for (
const MDNode *Node : CUs->
operands()) {
3362 for (
const CVGlobalVariable &CVGV : Globals) {
3364 emitDebugInfoForGlobal(CVGV);
3369 const std::string &QualifiedName) {
3370 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3371 OS.AddComment(
"Type");
3372 OS.emitInt32(getTypeIndex(DTy).getIndex());
3374 OS.AddComment(
"Value");
3379 CodeViewRecordIO IO(Writer);
3381 StringRef SRef((
char *)
Data, Writer.getOffset());
3382 OS.emitBinaryData(SRef);
3384 OS.AddComment(
"Name");
3386 endSymbolRecord(SConstantEnd);
3389void CodeViewDebug::emitStaticConstMemberList() {
3390 for (
const DIDerivedType *DTy : StaticConstMembers) {
3394 if (
const ConstantInt *CI =
3398 else if (
const ConstantFP *CFP =
3400 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3404 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3405 getFullyQualifiedName(Scope, DTy->
getName()));
3415 if (
T == dwarf::DW_TAG_pointer_type ||
3416 T == dwarf::DW_TAG_ptr_to_member_type ||
3417 T == dwarf::DW_TAG_reference_type ||
3418 T == dwarf::DW_TAG_rvalue_reference_type)
3420 assert(DTy->getBaseType() &&
"Expected valid base type");
3425 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3428void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3429 const DIGlobalVariable *DIGV = CVGV.DIGV;
3435 Scope = MemberDecl->getScope();
3441 ? std::string(DIGV->
getName())
3444 if (
const GlobalVariable *GV =
3448 MCSymbol *GVSym = Asm->getSymbol(GV);
3449 SymbolKind DataSym = GV->isThreadLocal()
3450 ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32
3451 : SymbolKind::S_GTHREAD32)
3452 : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32
3453 : SymbolKind::S_GDATA32);
3454 MCSymbol *DataEnd = beginSymbolRecord(DataSym);
3455 OS.AddComment(
"Type");
3456 OS.emitInt32(getCompleteTypeIndex(DIGV->getType()).getIndex());
3457 OS.AddComment(
"DataOffset");
3460 uint64_t Offset = CVGlobalVariableOffsets.lookup(DIGV);
3461 OS.emitCOFFSecRel32(GVSym, Offset);
3463 OS.AddComment(
"Segment");
3464 OS.emitCOFFSectionIndex(GVSym);
3465 OS.AddComment(
"Name");
3466 const unsigned LengthOfDataRecord = 12;
3467 emitNullTerminatedSymbolName(OS, QualifiedName, LengthOfDataRecord);
3468 endSymbolRecord(DataEnd);
3470 const DIExpression *DIE = cast<const DIExpression *>(CVGV.GVInfo);
3471 assert(DIE->isConstant() &&
3472 "Global constant variables must contain a constant expression.");
3475 bool isUnsigned = isFloatDIType(DIGV->getType())
3477 : DebugHandlerBase::isUnsignedDIType(DIGV->getType());
3478 APSInt Value(APInt(64, DIE->getElement(1)), isUnsigned);
3479 emitConstantSymbolRecord(DIGV->getType(), Value, QualifiedName);
3486 int64_t)> &Callback) {
3488 if (JTI && !JTI->isEmpty()) {
3492 for (
const auto &
MBB : *MF) {
3494 const auto LastMI =
MBB.getFirstTerminator();
3495 if (LastMI !=
MBB.end() && LastMI->isIndirectBranch()) {
3503 for (
const auto &MO : LastMI->operands()) {
3505 unsigned Index = MO.getIndex();
3509 Callback(*JTI, *LastMI, Index);
3517 for (
auto I =
MBB.instr_rbegin(),
E =
MBB.instr_rend();
I !=
E; ++
I) {
3518 if (
I->isJumpTableDebugInfo()) {
3519 unsigned Index =
I->getOperand(0).getImm();
3523 Callback(*JTI, *LastMI, Index);
3532 "Some of jump tables were not used in a debug info instruction");
3537void CodeViewDebug::discoverJumpTableBranches(
const MachineFunction *MF,
3541 [
this](
const MachineJumpTableInfo &,
const MachineInstr &BranchMI,
3545void CodeViewDebug::collectDebugInfoForJumpTables(
const MachineFunction *MF,
3549 [
this, MF](
const MachineJumpTableInfo &JTI,
const MachineInstr &BranchMI,
3550 int64_t JumpTableIndex) {
3555 uint64_t BaseOffset = 0;
3563 "EK_Custom32, EK_GPRel32BlockAddress, and "
3564 "EK_GPRel64BlockAddress should never be emitted for COFF");
3567 EntrySize = JumpTableEntrySize::Pointer;
3574 std::tie(
Base, BaseOffset, Branch, EntrySize) =
3575 Asm->getCodeViewJumpTableInfo(JumpTableIndex, &BranchMI, Branch);
3579 const MachineJumpTableEntry &JTE = JTI.
getJumpTables()[JumpTableIndex];
3580 JumpTableInfo CVJTI{EntrySize,
3587 for (
const auto &
MBB : JTE.
MBBs)
3589 CurFn->JumpTables.push_back(std::move(CVJTI));
3593void CodeViewDebug::emitDebugInfoForJumpTables(
const FunctionInfo &FI) {
3595 for (
const auto &JumpTable : FI.JumpTables) {
3596 for (
const auto &CaseSym :
JumpTable.Cases) {
3597 MCSymbol *LabelEnd = beginSymbolRecord(SymbolKind::S_LABEL32);
3598 OS.AddComment(
"Offset and segment");
3599 OS.emitCOFFSecRel32(CaseSym, 0);
3600 OS.AddComment(
"Flags");
3603 endSymbolRecord(LabelEnd);
3607 for (
const auto &JumpTable : FI.JumpTables) {
3608 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3610 OS.AddComment(
"Base offset");
3612 OS.AddComment(
"Base section index");
3613 OS.emitCOFFSectionIndex(
JumpTable.Base);
3615 OS.AddComment(
"Base offset");
3617 OS.AddComment(
"Base section index");
3620 OS.AddComment(
"Switch type");
3621 OS.emitInt16(
static_cast<uint16_t
>(
JumpTable.EntrySize));
3622 OS.AddComment(
"Branch offset");
3623 OS.emitCOFFSecRel32(
JumpTable.Branch, 0);
3624 OS.AddComment(
"Table offset");
3625 OS.emitCOFFSecRel32(
JumpTable.Table, 0);
3626 OS.AddComment(
"Branch section index");
3627 OS.emitCOFFSectionIndex(
JumpTable.Branch);
3628 OS.AddComment(
"Table section index");
3629 OS.emitCOFFSectionIndex(
JumpTable.Table);
3630 OS.AddComment(
"Entries count");
3632 endSymbolRecord(JumpTableEnd);
3636void CodeViewDebug::emitInlinees(
3640 constexpr size_t ChunkSize =
3647 size_t CurrentIndex = 0;
3648 while (CurrentIndex < SortedInlinees.
size()) {
3649 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3650 auto CurrentChunkSize =
3651 std::min(ChunkSize, SortedInlinees.
size() - CurrentIndex);
3652 OS.AddComment(
"Count");
3653 OS.emitInt32(CurrentChunkSize);
3655 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3656 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3657 OS.AddComment(
"Inlinee");
3658 OS.emitInt32(SortedInlinees[CurrentIndex].getIndex());
3660 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 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 SourceLanguage MapDWARFLanguageToCVLang(dwarf::SourceLanguageName DWLName)
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
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<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
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.