33#include "llvm/Config/llvm-config.h"
80 "Use the *2 versions for tag records in CodeView (LF_CLASS2, etc.)"),
87 : OS(&OS), TypeTable(TypeTable) {}
89 void emitBytes(StringRef
Data)
override { OS->emitBytes(
Data); }
95 void emitBinaryData(StringRef
Data)
override { OS->emitBinaryData(
Data); }
97 void AddComment(
const Twine &
T)
override { OS->AddComment(
T); }
99 void AddRawComment(
const Twine &
T)
override { OS->emitRawComment(
T); }
101 bool isVerboseAsm()
override {
return OS->isVerboseAsm(); }
109 TypeName = std::string(TypeTable.getTypeName(TI));
115 MCStreamer *OS =
nullptr;
116 TypeCollection &TypeTable;
145 std::string &Filepath = FileToFilepathMap[File];
146 if (!Filepath.empty())
156 Filepath = std::string(Dir);
157 if (Dir.
back() !=
'/')
170 Filepath = (Dir +
"\\" +
Filename).str();
179 while ((Cursor = Filepath.find(
"\\.\\", Cursor)) != std::string::npos)
180 Filepath.erase(Cursor, 2);
185 while ((Cursor = Filepath.find(
"\\..\\", Cursor)) != std::string::npos) {
190 size_t PrevSlash = Filepath.rfind(
'\\', Cursor - 1);
191 if (PrevSlash == std::string::npos)
195 Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
202 while ((Cursor = Filepath.find(
"\\\\", Cursor)) != std::string::npos)
203 Filepath.erase(Cursor, 1);
208unsigned CodeViewDebug::maybeRecordFile(
const DIFile *
F) {
209 StringRef FullPath = getFullFilepath(
F);
210 unsigned NextId = FileIdMap.size() + 1;
211 auto Insertion = FileIdMap.insert(std::make_pair(FullPath, NextId));
212 if (Insertion.second) {
214 ArrayRef<uint8_t> ChecksumAsBytes;
216 if (
F->getChecksum()) {
217 std::string Checksum =
fromHex(
F->getChecksum()->Value);
218 void *CKMem = OS.getContext().allocate(Checksum.size(), 1);
219 memcpy(CKMem, Checksum.data(), Checksum.size());
220 ChecksumAsBytes = ArrayRef<uint8_t>(
221 reinterpret_cast<const uint8_t *
>(CKMem), Checksum.size());
222 switch (
F->getChecksum()->Kind) {
224 CSKind = FileChecksumKind::MD5;
227 CSKind = FileChecksumKind::SHA1;
230 CSKind = FileChecksumKind::SHA256;
234 bool Success = OS.emitCVFileDirective(NextId, FullPath, ChecksumAsBytes,
235 static_cast<unsigned>(CSKind));
239 return Insertion.first->second;
242CodeViewDebug::InlineSite &
243CodeViewDebug::getInlineSite(
const DILocation *InlinedAt,
245 auto SiteInsertion = CurFn->InlineSites.try_emplace(InlinedAt);
246 InlineSite *Site = &SiteInsertion.first->second;
247 if (SiteInsertion.second) {
248 unsigned ParentFuncId = CurFn->FuncId;
249 if (
const DILocation *OuterIA = InlinedAt->getInlinedAt())
251 getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())
254 Site->SiteFuncId = NextFuncId++;
255 OS.emitCVInlineSiteIdDirective(
256 Site->SiteFuncId, ParentFuncId, maybeRecordFile(InlinedAt->getFile()),
257 InlinedAt->getLine(), InlinedAt->getColumn(), SMLoc());
259 InlinedSubprograms.insert(
Inlinee);
260 auto InlineeIdx = getFuncIdForSubprogram(
Inlinee);
262 if (InlinedAt->getInlinedAt() ==
nullptr)
263 CurFn->Inlinees.insert(InlineeIdx);
270 if (!ScopeName.
empty())
273 switch (Scope->getTag()) {
274 case dwarf::DW_TAG_enumeration_type:
275 case dwarf::DW_TAG_class_type:
276 case dwarf::DW_TAG_structure_type:
277 case dwarf::DW_TAG_union_type:
278 return "<unnamed-tag>";
279 case dwarf::DW_TAG_namespace:
280 return "`anonymous namespace'";
286const DISubprogram *CodeViewDebug::collectParentScopeNames(
288 const DISubprogram *ClosestSubprogram =
nullptr;
289 while (Scope !=
nullptr) {
290 if (ClosestSubprogram ==
nullptr)
297 DeferredCompleteTypes.push_back(Ty);
300 if (!ScopeName.
empty())
301 QualifiedNameComponents.
push_back(ScopeName);
304 return ClosestSubprogram;
309 std::string FullyQualifiedName;
312 FullyQualifiedName.append(std::string(QualifiedNameComponent));
313 FullyQualifiedName.append(
"::");
315 FullyQualifiedName.append(std::string(TypeName));
316 return FullyQualifiedName;
324 if (
CVD.TypeEmissionLevel == 1)
325 CVD.emitDeferredCompleteTypes();
326 --
CVD.TypeEmissionLevel;
331std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Scope,
338 collectParentScopeNames(Scope, QualifiedNameComponents);
342std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Ty) {
364 auto I = TypeIndices.find({Scope,
nullptr});
365 if (
I != TypeIndices.end())
369 std::string ScopeName = getFullyQualifiedName(Scope);
370 StringIdRecord SID(TypeIndex(), ScopeName);
371 auto TI = TypeTable.writeLeafType(SID);
372 return recordTypeIndexForDINode(Scope, TI);
378 if (Name.empty() || Name.back() !=
'>')
381 int OpenBrackets = 0;
382 for (
int i = Name.size() - 1; i >= 0; --i) {
385 else if (Name[i] ==
'<') {
387 if (OpenBrackets == 0)
388 return Name.substr(0, i);
394TypeIndex CodeViewDebug::getFuncIdForSubprogram(
const DISubprogram *SP) {
398 auto I = TypeIndices.find({
SP,
nullptr});
399 if (
I != TypeIndices.end())
407 const DIScope *
Scope =
SP->getScope();
413 TypeIndex ClassType = getTypeIndex(Class);
414 MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class),
416 TI = TypeTable.writeLeafType(MFuncId);
419 TypeIndex ParentScope = getScopeIndex(Scope);
420 FuncIdRecord FuncId(ParentScope, getTypeIndex(
SP->getType()), DisplayName);
421 TI = TypeTable.writeLeafType(FuncId);
424 return recordTypeIndexForDINode(SP, TI);
428 return ((DCTy->
getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);
436 const DIType *ReturnTy =
nullptr;
437 if (
auto TypeArray = Ty->getTypeArray()) {
438 if (TypeArray.size())
439 ReturnTy = TypeArray[0];
449 if (ClassTy &&
isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {
458TypeIndex CodeViewDebug::getMemberFunctionType(
const DISubprogram *SP,
462 if (
SP->getDeclaration())
463 SP =
SP->getDeclaration();
464 assert(!
SP->getDeclaration() &&
"should use declaration as key");
468 auto I = TypeIndices.find({
SP,
Class});
469 if (
I != TypeIndices.end())
476 const bool IsStaticMethod = (
SP->getFlags() & DINode::FlagStaticMember) != 0;
479 TypeIndex TI = lowerTypeMemberFunction(
480 SP->getType(), Class,
SP->getThisAdjustment(), IsStaticMethod, FO);
481 return recordTypeIndexForDINode(SP, TI, Class);
484TypeIndex CodeViewDebug::recordTypeIndexForDINode(
const DINode *Node,
487 auto InsertResult = TypeIndices.insert({{
Node, ClassTy}, TI});
489 assert(InsertResult.second &&
"DINode was already assigned a type index");
493unsigned CodeViewDebug::getPointerSizeInBytes() {
494 return MMI->getModule()->getDataLayout().getPointerSizeInBits() / 8;
497void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
499 if (
const DILocation *InlinedAt =
LS->getInlinedAt()) {
501 const DISubprogram *
Inlinee = Var.DIVar->getScope()->getSubprogram();
502 InlineSite &Site = getInlineSite(InlinedAt,
Inlinee);
503 Site.InlinedLocals.emplace_back(std::move(Var));
506 ScopeVariables[
LS].emplace_back(std::move(Var));
516void CodeViewDebug::maybeRecordLocation(
const DebugLoc &
DL,
522 const DIScope *
Scope =
DL->getScope();
527 LineInfo LI(
DL.getLine(),
DL.getLine(),
true);
528 if (LI.getStartLine() !=
DL.getLine() || LI.isAlwaysStepInto() ||
529 LI.isNeverStepInto())
532 ColumnInfo CI(
DL.getCol(), 0);
533 if (CI.getStartColumn() !=
DL.getCol())
536 if (!CurFn->HaveLineInfo)
537 CurFn->HaveLineInfo =
true;
540 FileId = CurFn->LastFileId;
542 FileId = CurFn->LastFileId = maybeRecordFile(
DL->getFile());
545 unsigned FuncId = CurFn->FuncId;
546 if (
const DILocation *SiteLoc =
DL->getInlinedAt()) {
547 const DILocation *Loc =
DL.get();
552 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
555 bool FirstLoc =
true;
556 while ((SiteLoc = Loc->getInlinedAt())) {
558 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
567 OS.emitCVLocDirective(FuncId, FileId,
DL.getLine(),
DL.getCol(),
569 DL->getFilename(), SMLoc());
572void CodeViewDebug::emitCodeViewMagicVersion() {
573 OS.emitValueToAlignment(
Align(4));
574 OS.AddComment(
"Debug section magic");
581 case dwarf::DW_LNAME_C:
582 return SourceLanguage::C;
583 case dwarf::DW_LNAME_C_plus_plus:
584 return SourceLanguage::Cpp;
585 case dwarf::DW_LNAME_Fortran:
586 return SourceLanguage::Fortran;
587 case dwarf::DW_LNAME_Pascal:
588 return SourceLanguage::Pascal;
589 case dwarf::DW_LNAME_Cobol:
590 return SourceLanguage::Cobol;
591 case dwarf::DW_LNAME_Java:
592 return SourceLanguage::Java;
593 case dwarf::DW_LNAME_D:
594 return SourceLanguage::D;
595 case dwarf::DW_LNAME_Swift:
596 return SourceLanguage::Swift;
597 case dwarf::DW_LNAME_Rust:
598 return SourceLanguage::Rust;
599 case dwarf::DW_LNAME_ObjC:
600 return SourceLanguage::ObjC;
601 case dwarf::DW_LNAME_ObjC_plus_plus:
602 return SourceLanguage::ObjCpp;
607 return SourceLanguage::Masm;
621 if (!
Asm->getObjFileLowering().getCOFFDebugSymbolsSection()) {
626 CompilerInfoAsm =
Asm;
631 if (
Asm->hasDebugInfo()) {
632 Node = *M->debug_compile_units_begin();
636 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
646 CurrentSourceLanguage =
652 if (!M->getCodeViewFlag() ||
658 collectGlobalVariableInfo();
663 EmitDebugGlobalHashes = GH && !GH->
isZero();
667 if (!CompilerInfoAsm)
677 switchToDebugSectionForSymbol(
nullptr);
681 emitCompilerInformation();
682 endCVSubsection(CompilerInfo);
686 emitSecureHotPatchInformation();
688 emitInlineeLinesSubsection();
691 for (
auto &
P : FnDebugInfo)
692 if (!
P.first->isDeclarationForLinker())
693 emitDebugInfoForFunction(
P.first, *
P.second);
698 collectDebugInfoForGlobals();
701 emitDebugInfoForRetainedTypes();
704 setCurrentSubprogram(
nullptr);
705 emitDebugInfoForGlobals();
709 switchToDebugSectionForSymbol(
nullptr);
712 if (!GlobalUDTs.empty()) {
714 emitDebugInfoForUDTs(GlobalUDTs);
715 endCVSubsection(SymbolsEnd);
719 OS.AddComment(
"File index to string table offset subsection");
720 OS.emitCVFileChecksumsDirective();
723 OS.AddComment(
"String table");
724 OS.emitCVStringTableDirective();
733 emitTypeInformation();
735 if (EmitDebugGlobalHashes)
736 emitTypeGlobalHashes();
743 unsigned MaxFixedRecordLength = 0xF00) {
754void CodeViewDebug::emitTypeInformation() {
755 if (TypeTable.empty())
759 OS.switchSection(
Asm->getObjFileLowering().getCOFFDebugTypesSection());
760 emitCodeViewMagicVersion();
762 TypeTableCollection
Table(TypeTable.records());
763 TypeVisitorCallbackPipeline Pipeline;
766 CVMCAdapter CVMCOS(OS,
Table);
767 TypeRecordMapping typeMapping(CVMCOS);
770 std::optional<TypeIndex>
B =
Table.getFirst();
786void CodeViewDebug::emitTypeGlobalHashes() {
787 if (TypeTable.empty())
792 OS.switchSection(
Asm->getObjFileLowering().getCOFFGlobalTypeHashesSection());
794 OS.emitValueToAlignment(
Align(4));
795 OS.AddComment(
"Magic");
797 OS.AddComment(
"Section Version");
799 OS.AddComment(
"Hash Algorithm");
800 OS.emitInt16(uint16_t(GlobalTypeHashAlg::BLAKE3));
803 for (
const auto &GHR : TypeTable.hashes()) {
804 if (OS.isVerboseAsm()) {
808 raw_svector_ostream CommentOS(Comment);
810 OS.AddComment(Comment);
813 assert(GHR.Hash.size() == 8);
814 StringRef S(
reinterpret_cast<const char *
>(GHR.Hash.data()),
816 OS.emitBinaryData(S);
820void CodeViewDebug::emitObjName() {
821 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);
823 StringRef PathRef(CompilerInfoAsm->TM.Options.ObjectFilenameForDebug);
824 llvm::SmallString<256> PathStore(PathRef);
826 if (PathRef.empty() || PathRef ==
"-") {
833 OS.AddComment(
"Signature");
834 OS.emitIntValue(0, 4);
836 OS.AddComment(
"Object name");
839 endSymbolRecord(CompilerEnd);
842void CodeViewDebug::emitSecureHotPatchInformation() {
845 for (
const auto &
F :
MMI->getModule()->functions()) {
846 if (!
F.isDeclarationForLinker() &&
847 F.hasFnAttribute(
"marked_for_windows_hot_patching")) {
848 if (hotPatchInfo ==
nullptr)
849 hotPatchInfo = beginCVSubsection(DebugSubsectionKind::Symbols);
850 MCSymbol *HotPatchEnd = beginSymbolRecord(SymbolKind::S_HOTPATCHFUNC);
851 auto *
SP =
F.getSubprogram();
852 OS.AddComment(
"Function");
853 OS.emitInt32(getFuncIdForSubprogram(SP).getIndex());
854 OS.AddComment(
"Name");
856 endSymbolRecord(HotPatchEnd);
860 if (hotPatchInfo !=
nullptr)
861 endCVSubsection(hotPatchInfo);
875 for (
const char C : Name) {
878 V.Part[
N] +=
C -
'0';
880 std::min<int>(V.Part[
N], std::numeric_limits<uint16_t>::max());
881 }
else if (
C ==
'.') {
891void CodeViewDebug::emitCompilerInformation() {
892 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
896 Flags = CurrentSourceLanguage;
898 if (
MMI->getModule()->getProfileSummary(
false) !=
nullptr) {
899 Flags |=
static_cast<uint32_t
>(CompileSym3Flags::PGO);
903 ArchType Arch =
M->getTargetTriple().getArch();
908 if ((HotpatchFlag && HotpatchFlag->isOne()) || Arch == ArchType::thumb ||
909 Arch == ArchType::aarch64) {
910 Flags |=
static_cast<uint32_t
>(CompileSym3Flags::HotPatch);
913 OS.AddComment(
"Flags and language");
916 OS.AddComment(
"CPUType");
917 OS.emitInt16(
static_cast<uint64_t>(TheCPU));
919 StringRef CompilerVersion =
"0";
921 CompilerVersion = TheCU->getProducer();
924 OS.AddComment(
"Frontend version");
925 for (
int N : FrontVer.Part) {
932 int Major = 1000 * LLVM_VERSION_MAJOR +
933 10 * LLVM_VERSION_MINOR +
936 Major = std::min<int>(Major, std::numeric_limits<uint16_t>::max());
937 Version BackVer = {{ Major, 0, 0, 0 }};
938 OS.AddComment(
"Backend version");
939 for (
int N : BackVer.Part)
942 OS.AddComment(
"Null-terminated compiler version string");
945 endSymbolRecord(CompilerEnd);
954void CodeViewDebug::emitBuildInfo() {
966 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
969 const DIFile *MainSourceFile = CU->getFile();
980 TypeTable,
Asm->TM.Options.MCOptions.CommandlineArgs);
982 BuildInfoRecord BIR(BuildInfoArgs);
983 TypeIndex BuildInfoIndex = TypeTable.writeLeafType(BIR);
987 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
988 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
989 OS.AddComment(
"LF_BUILDINFO index");
990 OS.emitInt32(BuildInfoIndex.
getIndex());
991 endSymbolRecord(BIEnd);
992 endCVSubsection(BISubsecEnd);
995void CodeViewDebug::emitInlineeLinesSubsection() {
996 if (InlinedSubprograms.empty())
999 OS.AddComment(
"Inlinee lines subsection");
1000 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
1006 OS.AddComment(
"Inlinee lines signature");
1007 OS.emitInt32(
unsigned(InlineeLinesSignature::Normal));
1009 for (
const DISubprogram *SP : InlinedSubprograms) {
1010 assert(TypeIndices.count({SP, nullptr}));
1011 TypeIndex InlineeIdx = TypeIndices[{
SP,
nullptr}];
1014 unsigned FileId = maybeRecordFile(
SP->getFile());
1015 OS.AddComment(
"Inlined function " +
SP->getName() +
" starts at " +
1016 SP->getFilename() + Twine(
':') + Twine(
SP->getLine()));
1018 OS.AddComment(
"Type index of inlined function");
1019 OS.emitInt32(InlineeIdx.
getIndex());
1020 OS.AddComment(
"Offset into filechecksum table");
1021 OS.emitCVFileChecksumOffsetDirective(FileId);
1022 OS.AddComment(
"Starting line number");
1023 OS.emitInt32(
SP->getLine());
1026 endCVSubsection(InlineEnd);
1029void CodeViewDebug::emitInlinedCallSite(
const FunctionInfo &FI,
1032 assert(TypeIndices.count({Site.Inlinee, nullptr}));
1033 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee,
nullptr}];
1036 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
1038 OS.AddComment(
"PtrParent");
1040 OS.AddComment(
"PtrEnd");
1042 OS.AddComment(
"Inlinee type index");
1043 OS.emitInt32(InlineeIdx.
getIndex());
1045 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
1046 unsigned StartLineNum = Site.Inlinee->getLine();
1048 OS.emitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum,
1051 endSymbolRecord(InlineEnd);
1053 emitLocalVariableList(FI, Site.InlinedLocals);
1056 for (
const DILocation *ChildSite : Site.ChildSites) {
1057 auto I = FI.InlineSites.find(ChildSite);
1058 assert(
I != FI.InlineSites.end() &&
1059 "child site not in function inline site map");
1060 emitInlinedCallSite(FI, ChildSite,
I->second);
1064 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1067void CodeViewDebug::switchToDebugSectionForSymbol(
const MCSymbol *GVSym) {
1071 MCSectionCOFF *GVSec =
1072 GVSym ?
static_cast<MCSectionCOFF *
>(&GVSym->
getSection()) : nullptr;
1075 auto *DebugSec =
static_cast<MCSectionCOFF *
>(
1076 CompilerInfoAsm->getObjFileLowering().getCOFFDebugSymbolsSection());
1077 DebugSec = OS.getContext().getAssociativeCOFFSection(DebugSec, KeySym);
1079 OS.switchSection(DebugSec);
1083 if (ComdatDebugSections.insert(DebugSec).second)
1084 emitCodeViewMagicVersion();
1089void CodeViewDebug::emitDebugInfoForThunk(
const Function *GV,
1092 std::string FuncName =
1096 OS.AddComment(
"Symbol subsection for " + Twine(FuncName));
1097 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1100 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1101 OS.AddComment(
"PtrParent");
1103 OS.AddComment(
"PtrEnd");
1105 OS.AddComment(
"PtrNext");
1107 OS.AddComment(
"Thunk section relative address");
1108 OS.emitCOFFSecRel32(Fn, 0);
1109 OS.AddComment(
"Thunk section index");
1110 OS.emitCOFFSectionIndex(Fn);
1111 OS.AddComment(
"Code size");
1112 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 2);
1113 OS.AddComment(
"Ordinal");
1114 OS.emitInt8(
unsigned(ordinal));
1115 OS.AddComment(
"Function name");
1118 endSymbolRecord(ThunkRecordEnd);
1124 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1126 endCVSubsection(SymbolsEnd);
1129void CodeViewDebug::emitDebugInfoForFunction(
const Function *GV,
1137 switchToDebugSectionForSymbol(Fn);
1139 std::string FuncName;
1142 setCurrentSubprogram(SP);
1144 if (
SP->isThunk()) {
1145 emitDebugInfoForThunk(GV, FI, Fn);
1151 if (!
SP->getName().empty())
1152 FuncName = getFullyQualifiedName(
SP->getScope(),
SP->getName());
1155 if (FuncName.empty())
1159 if (
MMI->getModule()->getTargetTriple().getArch() ==
Triple::x86)
1160 OS.emitCVFPOData(Fn);
1163 OS.AddComment(
"Symbol subsection for " + Twine(FuncName));
1164 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1167 : SymbolKind::S_GPROC32_ID;
1168 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1171 OS.AddComment(
"PtrParent");
1173 OS.AddComment(
"PtrEnd");
1175 OS.AddComment(
"PtrNext");
1179 OS.AddComment(
"Code size");
1180 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 4);
1181 OS.AddComment(
"Offset after prologue");
1183 OS.AddComment(
"Offset before epilogue");
1185 OS.AddComment(
"Function type index");
1186 OS.emitInt32(getFuncIdForSubprogram(GV->
getSubprogram()).getIndex());
1187 OS.AddComment(
"Function section relative address");
1188 OS.emitCOFFSecRel32(Fn, 0);
1189 OS.AddComment(
"Function section index");
1190 OS.emitCOFFSectionIndex(Fn);
1191 OS.AddComment(
"Flags");
1192 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;
1193 if (FI.HasFramePointer)
1194 ProcFlags |= ProcSymFlags::HasFP;
1196 ProcFlags |= ProcSymFlags::IsNoReturn;
1198 ProcFlags |= ProcSymFlags::IsNoInline;
1199 OS.emitInt8(
static_cast<uint8_t
>(ProcFlags));
1201 OS.AddComment(
"Function name");
1204 endSymbolRecord(ProcRecordEnd);
1206 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1208 OS.AddComment(
"FrameSize");
1209 OS.emitInt32(FI.FrameSize - FI.CSRSize);
1210 OS.AddComment(
"Padding");
1212 OS.AddComment(
"Offset of padding");
1214 OS.AddComment(
"Bytes of callee saved registers");
1215 OS.emitInt32(FI.CSRSize);
1216 OS.AddComment(
"Exception handler offset");
1218 OS.AddComment(
"Exception handler section");
1220 OS.AddComment(
"Flags (defines frame register)");
1221 OS.emitInt32(uint32_t(FI.FrameProcOpts));
1222 endSymbolRecord(FrameProcEnd);
1224 emitInlinees(FI.Inlinees);
1225 emitLocalVariableList(FI, FI.Locals);
1226 emitGlobalVariableList(FI.Globals);
1227 emitLexicalBlockList(FI.ChildBlocks, FI);
1232 for (
const DILocation *InlinedAt : FI.ChildSites) {
1233 auto I = FI.InlineSites.find(InlinedAt);
1234 assert(
I != FI.InlineSites.end() &&
1235 "child site not in function inline site map");
1236 emitInlinedCallSite(FI, InlinedAt,
I->second);
1239 for (
auto Annot : FI.Annotations) {
1242 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1243 OS.emitCOFFSecRel32(Label, 0);
1245 OS.emitCOFFSectionIndex(Label);
1251 assert(Str.data()[Str.size()] ==
'\0' &&
"non-nullterminated MDString");
1252 OS.emitBytes(StringRef(Str.data(), Str.size() + 1));
1254 endSymbolRecord(AnnotEnd);
1257 for (
auto HeapAllocSite : FI.HeapAllocSites) {
1258 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1259 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1260 const DIType *DITy = std::get<2>(HeapAllocSite);
1261 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1262 OS.AddComment(
"Call site offset");
1263 OS.emitCOFFSecRel32(BeginLabel, 0);
1264 OS.AddComment(
"Call site section index");
1265 OS.emitCOFFSectionIndex(BeginLabel);
1266 OS.AddComment(
"Call instruction length");
1267 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
1268 OS.AddComment(
"Type index");
1269 OS.emitInt32(getCompleteTypeIndex(DITy).getIndex());
1270 endSymbolRecord(HeapAllocEnd);
1274 emitDebugInfoForUDTs(LocalUDTs);
1276 emitDebugInfoForJumpTables(FI);
1279 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1281 endCVSubsection(SymbolsEnd);
1284 OS.emitCVLinetableDirective(FI.FuncId, Fn, FI.End);
1288CodeViewDebug::createDefRangeMem(uint16_t CVRegister,
int Offset,
1289 int32_t DerefOffset) {
1295 DR.StructOffset = 0;
1296 DR.CVRegister = CVRegister;
1297 DR.DerefOffset = DerefOffset;
1301void CodeViewDebug::collectVariableInfoFromMFTable(
1308 for (
const MachineFunction::VariableDbgInfo &VI :
1312 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1313 "Expected inlined-at fields to agree");
1315 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1323 int64_t ExprOffset = 0;
1327 if (!
VI.Expr->extractLeadingOffset(ExprOffset, FirstRemaining))
1329 if (!FirstRemaining.
empty()) {
1330 if (FirstRemaining.
front() != dwarf::DW_OP_deref)
1332 SmallVector<uint64_t, 1> LastRemaining;
1334 ArrayRef(FirstRemaining).drop_front(), DerefOffset,
1337 if (!LastRemaining.
empty())
1344 StackOffset FrameOffset =
1346 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1352 if (DerefOffset < INT32_MIN || DerefOffset > INT32_MAX)
1357 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset,
1358 static_cast<int32_t
>(DerefOffset));
1366 End = End ? End :
Asm->getFunctionEnd();
1367 Var.DefRanges[DefRange].emplace_back(Begin, End);
1370 recordLocalVariable(std::move(Var), Scope);
1374void CodeViewDebug::calculateRanges(
1376 const TargetRegisterInfo *
TRI =
Asm->MF->getSubtarget().getRegisterInfo();
1379 for (
auto I = Entries.
begin(),
E = Entries.
end();
I !=
E; ++
I) {
1381 if (!
Entry.isDbgValue())
1383 const MachineInstr *DVInst =
Entry.getInstr();
1387 std::optional<DbgVariableLocation>
Location =
1398 Var.ConstantValue =
APSInt(APInt(64,
Op.getImm()),
false);
1410 if (
Location->FragmentInfo->OffsetInBits % 8)
1420 DR.InMemory = !
Location->LoadChain.empty();
1423 if (!
Location->LoadChain.empty()) {
1424 DR.DataOffset =
Location->LoadChain[0];
1425 if (
Location->LoadChain.size() >= 2)
1426 DR.DerefOffset =
Location->LoadChain[1];
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);
1465 for (
const MDNode *
N :
SP->getRetainedNodes())
1467 collectGlobalOrStaticLocalVariableInfo(GVE);
1470 InlinedEntity
IV =
I.first;
1474 const DILocation *InlinedAt =
IV.second;
1477 const auto &Entries =
I.second;
1479 LexicalScope *
Scope =
nullptr;
1491 calculateRanges(Var, Entries);
1492 recordLocalVariable(std::move(Var), Scope);
1501 auto Insertion = FnDebugInfo.
insert({&GV, std::make_unique<FunctionInfo>()});
1502 assert(Insertion.second &&
"function already has info");
1503 CurFn = Insertion.first->second.get();
1504 CurFn->FuncId = NextFuncId++;
1505 CurFn->Begin =
Asm->getFunctionBegin();
1513 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1519 if (CurFn->FrameSize > 0) {
1524 CurFn->HasFramePointer =
true;
1527 if (CurFn->HasStackRealignment) {
1578 CurFn->FrameProcOpts = FPO;
1580 OS.emitCVFuncIdDirective(CurFn->FuncId);
1587 bool EmptyPrologue =
true;
1588 for (
const auto &
MBB : *MF) {
1589 for (
const auto &
MI :
MBB) {
1594 }
else if (!
MI.isMetaInstruction()) {
1595 EmptyPrologue =
false;
1603 maybeRecordLocation(FnStartDL, MF);
1607 for (
const auto &
MBB : *MF) {
1608 for (
const auto &
MI :
MBB) {
1609 if (
MI.getHeapAllocMarker()) {
1617 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
1619 discoverJumpTableBranches(MF,
isThumb);
1627 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1628 if (
DIScope *Scope =
T->getScope()) {
1629 switch (Scope->getTag()) {
1630 case dwarf::DW_TAG_structure_type:
1631 case dwarf::DW_TAG_class_type:
1632 case dwarf::DW_TAG_union_type:
1642 if (!
T ||
T->isForwardDecl())
1648 T = DT->getBaseType();
1653void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1661 const DISubprogram *ClosestSubprogram =
1662 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1664 std::string FullyQualifiedName =
1667 if (ClosestSubprogram ==
nullptr) {
1668 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1669 }
else if (ClosestSubprogram == CurrentSubprogram) {
1670 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1681TypeIndex CodeViewDebug::lowerType(
const DIType *Ty,
const DIType *ClassTy) {
1684 case dwarf::DW_TAG_array_type:
1686 case dwarf::DW_TAG_typedef:
1688 case dwarf::DW_TAG_base_type:
1690 case dwarf::DW_TAG_pointer_type:
1694 case dwarf::DW_TAG_reference_type:
1695 case dwarf::DW_TAG_rvalue_reference_type:
1697 case dwarf::DW_TAG_ptr_to_member_type:
1699 case dwarf::DW_TAG_restrict_type:
1700 case dwarf::DW_TAG_const_type:
1701 case dwarf::DW_TAG_volatile_type:
1704 case dwarf::DW_TAG_subroutine_type:
1713 case dwarf::DW_TAG_enumeration_type:
1715 case dwarf::DW_TAG_class_type:
1716 case dwarf::DW_TAG_structure_type:
1718 case dwarf::DW_TAG_union_type:
1720 case dwarf::DW_TAG_string_type:
1722 case dwarf::DW_TAG_unspecified_type:
1723 if (Ty->
getName() ==
"decltype(nullptr)")
1732TypeIndex CodeViewDebug::lowerTypeAlias(
const DIDerivedType *Ty) {
1733 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1738 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) &&
1739 TypeName ==
"HRESULT")
1740 return TypeIndex(SimpleTypeKind::HResult);
1741 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::UInt16Short) &&
1742 TypeName ==
"wchar_t")
1743 return TypeIndex(SimpleTypeKind::WideCharacter);
1745 return UnderlyingTypeIndex;
1750 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1752 TypeIndex IndexType = getPointerSizeInBytes() == 8
1753 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1760 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1761 const DINode *Element =
Elements[i];
1762 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1772 Count = CI->getSExtValue();
1778 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1779 Count = UI->getSExtValue() - Lowerbound + 1;
1790 ElementSize *=
Count;
1795 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1798 ArrayRecord AR(ElementTypeIndex, IndexType, ArraySize, Name);
1799 ElementTypeIndex = TypeTable.writeLeafType(AR);
1802 return ElementTypeIndex;
1810TypeIndex CodeViewDebug::lowerTypeString(
const DIStringType *Ty) {
1811 TypeIndex CharType = TypeIndex(SimpleTypeKind::NarrowCharacter);
1815 TypeIndex IndexType = getPointerSizeInBytes() == 8
1816 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1820 ArrayRecord AR(CharType, IndexType, ArraySize, Name);
1822 return TypeTable.writeLeafType(AR);
1825TypeIndex CodeViewDebug::lowerTypeBasic(
const DIBasicType *Ty) {
1835 case dwarf::DW_ATE_address:
1838 case dwarf::DW_ATE_boolean:
1840 case 1: STK = SimpleTypeKind::Boolean8;
break;
1841 case 2: STK = SimpleTypeKind::Boolean16;
break;
1842 case 4: STK = SimpleTypeKind::Boolean32;
break;
1843 case 8: STK = SimpleTypeKind::Boolean64;
break;
1844 case 16: STK = SimpleTypeKind::Boolean128;
break;
1847 case dwarf::DW_ATE_complex_float:
1851 case 4: STK = SimpleTypeKind::Complex16;
break;
1852 case 8: STK = SimpleTypeKind::Complex32;
break;
1853 case 16: STK = SimpleTypeKind::Complex64;
break;
1854 case 20: STK = SimpleTypeKind::Complex80;
break;
1855 case 32: STK = SimpleTypeKind::Complex128;
break;
1858 case dwarf::DW_ATE_float:
1860 case 2: STK = SimpleTypeKind::Float16;
break;
1861 case 4: STK = SimpleTypeKind::Float32;
break;
1862 case 6: STK = SimpleTypeKind::Float48;
break;
1863 case 8: STK = SimpleTypeKind::Float64;
break;
1864 case 10: STK = SimpleTypeKind::Float80;
break;
1865 case 16: STK = SimpleTypeKind::Float128;
break;
1868 case dwarf::DW_ATE_signed:
1870 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1871 case 2: STK = SimpleTypeKind::Int16Short;
break;
1872 case 4: STK = SimpleTypeKind::Int32;
break;
1873 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1874 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1877 case dwarf::DW_ATE_unsigned:
1879 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1880 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1881 case 4: STK = SimpleTypeKind::UInt32;
break;
1882 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1883 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1886 case dwarf::DW_ATE_UTF:
1888 case 1: STK = SimpleTypeKind::Character8;
break;
1889 case 2: STK = SimpleTypeKind::Character16;
break;
1890 case 4: STK = SimpleTypeKind::Character32;
break;
1893 case dwarf::DW_ATE_signed_char:
1895 STK = SimpleTypeKind::SignedCharacter;
1897 case dwarf::DW_ATE_unsigned_char:
1899 STK = SimpleTypeKind::UnsignedCharacter;
1909 if (STK == SimpleTypeKind::Int32 &&
1911 STK = SimpleTypeKind::Int32Long;
1912 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1913 Ty->
getName() ==
"unsigned long"))
1914 STK = SimpleTypeKind::UInt32Long;
1915 if (STK == SimpleTypeKind::UInt16Short &&
1917 STK = SimpleTypeKind::WideCharacter;
1918 if ((STK == SimpleTypeKind::SignedCharacter ||
1919 STK == SimpleTypeKind::UnsignedCharacter) &&
1921 STK = SimpleTypeKind::NarrowCharacter;
1923 return TypeIndex(STK);
1926TypeIndex CodeViewDebug::lowerTypePointer(
const DIDerivedType *Ty,
1928 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1932 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1934 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1936 ? SimpleTypeMode::NearPointer64
1937 : SimpleTypeMode::NearPointer32;
1942 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1946 case dwarf::DW_TAG_pointer_type:
1947 PM = PointerMode::Pointer;
1949 case dwarf::DW_TAG_reference_type:
1950 PM = PointerMode::LValueReference;
1952 case dwarf::DW_TAG_rvalue_reference_type:
1953 PM = PointerMode::RValueReference;
1958 PO |= PointerOptions::Const;
1960 PointerRecord PR(PointeeTI, PK, PM, PO, Ty->
getSizeInBits() / 8);
1961 return TypeTable.writeLeafType(PR);
1974 case DINode::FlagSingleInheritance:
1976 case DINode::FlagMultipleInheritance:
1978 case DINode::FlagVirtualInheritance:
1986 case DINode::FlagSingleInheritance:
1988 case DINode::FlagMultipleInheritance:
1990 case DINode::FlagVirtualInheritance:
1997TypeIndex CodeViewDebug::lowerTypeMemberPointer(
const DIDerivedType *Ty,
1999 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
2002 TypeIndex PointeeTI =
2003 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->
getClassType() :
nullptr);
2004 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2005 : PointerKind::Near32;
2006 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
2007 : PointerMode::PointerToDataMember;
2011 MemberPointerInfo MPI(
2013 PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);
2014 return TypeTable.writeLeafType(PR);
2031TypeIndex CodeViewDebug::lowerTypeModifier(
const DIDerivedType *Ty) {
2035 const DIType *BaseTy = Ty;
2036 while (IsModifier && BaseTy) {
2038 switch (BaseTy->
getTag()) {
2039 case dwarf::DW_TAG_const_type:
2040 Mods |= ModifierOptions::Const;
2041 PO |= PointerOptions::Const;
2043 case dwarf::DW_TAG_volatile_type:
2044 Mods |= ModifierOptions::Volatile;
2045 PO |= PointerOptions::Volatile;
2047 case dwarf::DW_TAG_restrict_type:
2050 PO |= PointerOptions::Restrict;
2065 switch (BaseTy->
getTag()) {
2066 case dwarf::DW_TAG_pointer_type:
2067 case dwarf::DW_TAG_reference_type:
2068 case dwarf::DW_TAG_rvalue_reference_type:
2070 case dwarf::DW_TAG_ptr_to_member_type:
2077 TypeIndex ModifiedTI = getTypeIndex(BaseTy);
2081 if (Mods == ModifierOptions::None)
2084 ModifierRecord MR(ModifiedTI, Mods);
2085 return TypeTable.writeLeafType(MR);
2091 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2094 if (ReturnAndArgTypeIndices.
size() > 1 &&
2100 if (!ReturnAndArgTypeIndices.
empty()) {
2101 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2102 ReturnTypeIndex = ReturnAndArgTypesRef.consume_front();
2103 ArgTypeIndices = ReturnAndArgTypesRef;
2106 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2107 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2112 ProcedureRecord Procedure(ReturnTypeIndex, CC, FO, ArgTypeIndices.
size(),
2114 return TypeTable.writeLeafType(Procedure);
2117TypeIndex CodeViewDebug::lowerTypeMemberFunction(
const DISubroutineType *Ty,
2120 bool IsStaticMethod,
2123 TypeIndex ClassType = getTypeIndex(ClassTy);
2130 if (ReturnAndArgs.size() > Index) {
2131 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
2137 TypeIndex ThisTypeIndex;
2138 if (!IsStaticMethod && ReturnAndArgs.size() > Index) {
2139 if (
const DIDerivedType *PtrTy =
2141 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2142 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2148 while (Index < ReturnAndArgs.size())
2149 ArgTypeIndices.
push_back(getTypeIndex(ReturnAndArgs[Index++]));
2155 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2156 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2160 MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FO,
2161 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2162 return TypeTable.writeLeafType(MFR);
2165TypeIndex CodeViewDebug::lowerTypeVFTableShape(
const DIDerivedType *Ty) {
2166 unsigned VSlotCount =
2170 VFTableShapeRecord VFTSR(Slots);
2171 return TypeTable.writeLeafType(VFTSR);
2188 if (SP->isArtificial())
2198 if (SP->getFlags() & DINode::FlagStaticMember)
2201 switch (SP->getVirtuality()) {
2202 case dwarf::DW_VIRTUALITY_none:
2204 case dwarf::DW_VIRTUALITY_virtual:
2206 case dwarf::DW_VIRTUALITY_pure_virtual:
2217 switch (Ty->getTag()) {
2218 case dwarf::DW_TAG_class_type:
2219 return UseTagRecord2 ? TypeRecordKind::Class2 : TypeRecordKind::Class;
2220 case dwarf::DW_TAG_structure_type:
2221 return UseTagRecord2 ? TypeRecordKind::Struct2 : TypeRecordKind::Struct;
2235 if (!Ty->getIdentifier().empty())
2249 if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) {
2253 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2265void CodeViewDebug::addUDTSrcLine(
const DIType *Ty, TypeIndex TI) {
2267 case dwarf::DW_TAG_class_type:
2268 case dwarf::DW_TAG_structure_type:
2269 case dwarf::DW_TAG_union_type:
2270 case dwarf::DW_TAG_enumeration_type:
2276 if (
const auto *File = Ty->
getFile()) {
2277 StringIdRecord SIDR(TypeIndex(0x0), getFullFilepath(File));
2278 TypeIndex SIDI = TypeTable.writeLeafType(SIDR);
2280 UdtSourceLineRecord USLR(TI, SIDI, Ty->
getLine());
2281 TypeTable.writeLeafType(USLR);
2288 unsigned EnumeratorCount = 0;
2291 CO |= ClassOptions::ForwardReference;
2293 ContinuationRecordBuilder ContinuationBuilder;
2294 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2299 EnumeratorRecord ER(
2300 MemberAccess::Public,
2307 FTI = TypeTable.insertRecord(ContinuationBuilder);
2310 std::string FullName = getFullyQualifiedName(Ty);
2312 EnumRecord ER(EnumeratorCount, CO, FTI, FullName, Ty->
getIdentifier(),
2314 TypeIndex EnumTI = TypeTable.writeLeafType(ER);
2316 addUDTSrcLine(Ty, EnumTI);
2350void CodeViewDebug::clear() {
2351 assert(CurFn ==
nullptr);
2353 FnDebugInfo.clear();
2354 FileToFilepathMap.clear();
2357 TypeIndices.clear();
2358 CompleteTypeIndices.clear();
2359 ScopeGlobals.clear();
2360 CVGlobalVariableOffsets.clear();
2363void CodeViewDebug::collectMemberInfo(
ClassInfo &Info,
2366 Info.Members.push_back({DDTy, 0});
2369 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2370 DINode::FlagStaticMember) {
2373 StaticConstMembers.push_back(DDTy);
2385 const DIType *Ty = DDTy->getBaseType();
2386 bool FullyResolved =
false;
2387 while (!FullyResolved) {
2389 case dwarf::DW_TAG_const_type:
2390 case dwarf::DW_TAG_volatile_type:
2396 FullyResolved =
true;
2405 ClassInfo NestedInfo = collectClassInfo(DCTy);
2406 for (
const ClassInfo::MemberInfo &IndirectField : NestedInfo.
Members)
2407 Info.Members.push_back(
2415 for (
auto *Element : Elements) {
2421 Info.Methods[
SP->getRawName()].push_back(SP);
2423 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2424 collectMemberInfo(Info, DDTy);
2425 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2426 Info.Inheritance.push_back(DDTy);
2427 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2428 DDTy->
getName() ==
"__vtbl_ptr_type") {
2429 Info.VShapeTI = getTypeIndex(DDTy);
2430 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2431 Info.NestedTypes.push_back(DDTy);
2432 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2437 Info.NestedTypes.push_back(Composite);
2447 return Ty->getName().empty() && Ty->getIdentifier().empty() &&
2448 !Ty->isForwardDecl();
2460 auto I = CompleteTypeIndices.find(Ty);
2461 if (
I != CompleteTypeIndices.end() &&
I->second == TypeIndex())
2463 return getCompleteTypeIndex(Ty);
2471 std::string FullName = getFullyQualifiedName(Ty);
2472 ClassRecord CR(Kind, 0, CO, TypeIndex(), TypeIndex(), TypeIndex(), 0,
2474 TypeIndex FwdDeclTI = TypeTable.writeLeafType(CR);
2476 DeferredCompleteTypes.push_back(Ty);
2480TypeIndex CodeViewDebug::lowerCompleteTypeClass(
const DICompositeType *Ty) {
2486 unsigned FieldCount;
2489 lowerRecordFieldList(Ty);
2492 CO |= ClassOptions::ContainsNestedClass;
2500 CO |= ClassOptions::HasConstructorOrDestructor;
2502 std::string FullName = getFullyQualifiedName(Ty);
2506 ClassRecord CR(Kind, FieldCount, CO, FieldTI, TypeIndex(), VShapeTI,
2508 TypeIndex ClassTI = TypeTable.writeLeafType(CR);
2510 addUDTSrcLine(Ty, ClassTI);
2520 return getCompleteTypeIndex(Ty);
2524 std::string FullName = getFullyQualifiedName(Ty);
2526 UseTagRecord2 ? TypeRecordKind::Union2 : TypeRecordKind::Union;
2527 UnionRecord UR(Kind, 0, CO, TypeIndex(), 0, FullName, Ty->
getIdentifier());
2528 TypeIndex FwdDeclTI = TypeTable.writeLeafType(UR);
2530 DeferredCompleteTypes.push_back(Ty);
2534TypeIndex CodeViewDebug::lowerCompleteTypeUnion(
const DICompositeType *Ty) {
2537 unsigned FieldCount;
2540 lowerRecordFieldList(Ty);
2543 CO |= ClassOptions::ContainsNestedClass;
2546 std::string FullName = getFullyQualifiedName(Ty);
2549 UseTagRecord2 ? TypeRecordKind::Union2 : TypeRecordKind::Union;
2550 UnionRecord UR(Kind, FieldCount, CO, FieldTI, SizeInBytes, FullName,
2552 TypeIndex UnionTI = TypeTable.writeLeafType(UR);
2554 addUDTSrcLine(Ty, UnionTI);
2561std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2567 unsigned MemberCount = 0;
2568 ClassInfo
Info = collectClassInfo(Ty);
2569 ContinuationRecordBuilder ContinuationBuilder;
2570 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2573 for (
const DIDerivedType *
I :
Info.Inheritance) {
2574 if (
I->getFlags() & DINode::FlagVirtual) {
2576 unsigned VBPtrOffset =
I->getVBPtrOffset();
2578 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2579 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2580 ? TypeRecordKind::IndirectVirtualBaseClass
2581 : TypeRecordKind::VirtualBaseClass;
2582 VirtualBaseClassRecord VBCR(
2584 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2590 assert(
I->getOffsetInBits() % 8 == 0 &&
2591 "bases must be on byte boundaries");
2593 getTypeIndex(
I->getBaseType()),
2594 I->getOffsetInBits() / 8);
2601 for (ClassInfo::MemberInfo &MemberInfo :
Info.Members) {
2603 TypeIndex MemberBaseType = getTypeIndex(
Member->getBaseType());
2604 StringRef MemberName =
Member->getName();
2608 if (
Member->isStaticMember()) {
2609 StaticDataMemberRecord SDMR(
Access, MemberBaseType, MemberName);
2616 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2617 Member->getName().starts_with(
"_vptr$")) {
2618 VFPtrRecord VFPR(getTypeIndex(
Member->getBaseType()));
2627 if (
Member->isBitField()) {
2628 uint64_t StartBitOffset = MemberOffsetInBits;
2629 if (
const auto *CI =
2631 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2633 StartBitOffset -= MemberOffsetInBits;
2634 BitFieldRecord BFR(MemberBaseType,
Member->getSizeInBits(),
2636 MemberBaseType = TypeTable.writeLeafType(BFR);
2638 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2639 DataMemberRecord DMR(
Access, MemberBaseType, MemberOffsetInBytes,
2646 for (
auto &MethodItr :
Info.Methods) {
2647 StringRef
Name = MethodItr.first->getString();
2649 std::vector<OneMethodRecord> Methods;
2650 for (
const DISubprogram *SP : MethodItr.second) {
2651 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2652 bool Introduced =
SP->getFlags() & DINode::FlagIntroducedVirtual;
2654 unsigned VFTableOffset = -1;
2656 VFTableOffset =
SP->getVirtualIndex() * getPointerSizeInBytes();
2658 Methods.push_back(OneMethodRecord(
2664 assert(!Methods.empty() &&
"Empty methods map entry");
2665 if (Methods.size() == 1)
2670 MethodOverloadListRecord MOLR(Methods);
2671 TypeIndex MethodList = TypeTable.writeLeafType(MOLR);
2673 OverloadedMethodRecord OMR(Methods.size(), MethodList, Name);
2679 for (
const DIType *
Nested :
Info.NestedTypes) {
2680 NestedTypeRecord
R(getTypeIndex(
Nested),
Nested->getName());
2685 TypeIndex FieldTI = TypeTable.insertRecord(ContinuationBuilder);
2686 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2687 !
Info.NestedTypes.empty());
2690TypeIndex CodeViewDebug::getVBPTypeIndex() {
2691 if (!VBPType.getIndex()) {
2694 TypeIndex ModifiedTI = TypeTable.writeLeafType(MR);
2696 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2697 : PointerKind::Near32;
2700 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2701 VBPType = TypeTable.writeLeafType(PR);
2707TypeIndex CodeViewDebug::getTypeIndex(
const DIType *Ty,
const DIType *ClassTy) {
2715 auto I = TypeIndices.find({Ty, ClassTy});
2716 if (
I != TypeIndices.end())
2720 TypeIndex TI = lowerType(Ty, ClassTy);
2721 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2725CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2727 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2728 "this type must be a pointer type");
2731 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2732 Options = PointerOptions::LValueRefThisPointer;
2733 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2734 Options = PointerOptions::RValueRefThisPointer;
2741 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2742 if (
I != TypeIndices.end())
2746 TypeIndex TI = lowerTypePointer(PtrTy,
Options);
2747 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2750TypeIndex CodeViewDebug::getCompleteTypeIndex(
const DIType *Ty) {
2758 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2759 (void)getTypeIndex(Ty);
2760 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2766 case dwarf::DW_TAG_class_type:
2767 case dwarf::DW_TAG_structure_type:
2768 case dwarf::DW_TAG_union_type:
2771 return getTypeIndex(Ty);
2782 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2783 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2788 if (CTy->isForwardDecl())
2795 auto InsertResult = CompleteTypeIndices.try_emplace(CTy);
2796 if (!InsertResult.second)
2797 return InsertResult.first->second;
2800 switch (CTy->getTag()) {
2801 case dwarf::DW_TAG_class_type:
2802 case dwarf::DW_TAG_structure_type:
2803 TI = lowerCompleteTypeClass(CTy);
2805 case dwarf::DW_TAG_union_type:
2806 TI = lowerCompleteTypeUnion(CTy);
2816 CompleteTypeIndices[CTy] = TI;
2824void CodeViewDebug::emitDeferredCompleteTypes() {
2826 while (!DeferredCompleteTypes.empty()) {
2827 std::swap(DeferredCompleteTypes, TypesToEmit);
2828 for (
const DICompositeType *RecordTy : TypesToEmit)
2829 getCompleteTypeIndex(RecordTy);
2830 TypesToEmit.clear();
2834void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2838 for (
const LocalVariable &L : Locals)
2839 if (
L.DIVar->isParameter())
2841 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2842 return L->DIVar->getArg() <
R->DIVar->getArg();
2844 for (
const LocalVariable *L : Params)
2845 emitLocalVariable(FI, *L);
2848 for (
const LocalVariable &L : Locals) {
2849 if (!
L.DIVar->isParameter()) {
2850 if (
L.ConstantValue) {
2853 const DIType *Ty =
L.DIVar->getType();
2855 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2857 emitLocalVariable(FI, L);
2863void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2864 const LocalVariable &Var) {
2866 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2869 if (Var.DIVar->isParameter())
2870 Flags |= LocalSymFlags::IsParameter;
2871 if (Var.DefRanges.empty())
2872 Flags |= LocalSymFlags::IsOptimizedOut;
2874 OS.AddComment(
"TypeIndex");
2875 TypeIndex TI = 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) {
2889 const auto &
Ranges = Pair.second;
2891 if (DefRange.InMemory) {
2892 int Offset = DefRange.DataOffset;
2893 unsigned Reg = DefRange.CVRegister;
2899 Reg = unsigned(RegisterId::VFRAME);
2900 Offset += FI.OffsetAdjustment;
2906 uint16_t RegRelFlags = 0;
2907 if (DefRange.IsSubfield) {
2909 (DefRange.StructOffset
2912 DefRangeRegisterRelIndirHeader DRHdr;
2914 DRHdr.
Flags = RegRelFlags;
2917 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2918 }
else if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2919 (
bool(Flags & LocalSymFlags::IsParameter)
2920 ? (EncFP == FI.EncodedParamFramePtrReg)
2921 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2925 DefRangeFramePointerRelHeader DRHdr;
2927 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2929 uint16_t RegRelFlags = 0;
2930 if (DefRange.IsSubfield) {
2932 (DefRange.StructOffset
2935 DefRangeRegisterRelHeader DRHdr;
2937 DRHdr.
Flags = RegRelFlags;
2939 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2942 assert(DefRange.DataOffset == 0 &&
2944 "unexpected offset into register");
2945 if (DefRange.IsSubfield) {
2946 DefRangeSubfieldRegisterHeader DRHdr;
2947 DRHdr.
Register = DefRange.CVRegister;
2950 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2952 DefRangeRegisterHeader DRHdr;
2953 DRHdr.
Register = DefRange.CVRegister;
2955 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2962 const FunctionInfo& FI) {
2963 for (LexicalBlock *
Block : Blocks)
2964 emitLexicalBlock(*
Block, FI);
2969void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2970 const FunctionInfo& FI) {
2971 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2972 OS.AddComment(
"PtrParent");
2974 OS.AddComment(
"PtrEnd");
2976 OS.AddComment(
"Code size");
2977 OS.emitAbsoluteSymbolDiff(
Block.End,
Block.Begin, 4);
2978 OS.AddComment(
"Function section relative address");
2979 OS.emitCOFFSecRel32(
Block.Begin, 0);
2980 OS.AddComment(
"Function section index");
2981 OS.emitCOFFSectionIndex(FI.Begin);
2982 OS.AddComment(
"Lexical block name");
2984 endSymbolRecord(RecordEnd);
2987 emitLocalVariableList(FI,
Block.Locals);
2988 emitGlobalVariableList(
Block.Globals);
2991 emitLexicalBlockList(
Block.Children, FI);
2994 emitEndSymbolRecord(SymbolKind::S_END);
2999void CodeViewDebug::collectLexicalBlockInfo(
3004 for (LexicalScope *Scope : Scopes)
3005 collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
3010void CodeViewDebug::collectLexicalBlockInfo(
3015 if (
Scope.isAbstractScope())
3020 bool IgnoreScope =
false;
3021 auto LI = ScopeVariables.find(&Scope);
3022 SmallVectorImpl<LocalVariable> *
Locals =
3023 LI != ScopeVariables.end() ? &LI->second :
nullptr;
3024 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
3025 SmallVectorImpl<CVGlobalVariable> *Globals =
3026 GI != ScopeGlobals.
end() ? GI->second.get() :
nullptr;
3028 const SmallVectorImpl<InsnRange> &
Ranges =
Scope.getRanges();
3031 if (!Locals && !Globals)
3061 collectLexicalBlockInfo(
Scope.getChildren(),
3071 auto BlockInsertion = CurFn->LexicalBlocks.try_emplace(DILB);
3072 if (!BlockInsertion.second)
3079 LexicalBlock &
Block = BlockInsertion.first->second;
3082 assert(
Block.Begin &&
"missing label for scope begin");
3083 assert(
Block.End &&
"missing label for scope end");
3086 Block.Locals = std::move(*Locals);
3088 Block.Globals = std::move(*Globals);
3090 collectLexicalBlockInfo(
Scope.getChildren(),
3098 assert(FnDebugInfo.count(&GV));
3099 assert(CurFn == FnDebugInfo[&GV].
get());
3105 collectLexicalBlockInfo(*CFS,
3113 ScopeVariables.clear();
3117 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3118 FnDebugInfo.erase(&GV);
3124 for (
const auto &
MBB : *MF) {
3125 for (
const auto &
MI :
MBB) {
3126 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3134 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
3136 collectDebugInfoForJumpTables(MF,
isThumb);
3140 CurFn->End =
Asm->getFunctionEnd();
3157 if (
DL.getLine() != 0)
3160 return Scope->getSubprogram()->isArtificial();
3168 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3176 for (
const auto &NextMI : *
MI->getParent()) {
3177 if (NextMI.isDebugInstr())
3179 DL = NextMI.getDebugLoc();
3192 maybeRecordLocation(
DL,
Asm->MF);
3205void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3212 MCSymbol *BeginLabel =
MMI->getContext().createTempSymbol(),
3213 *EndLabel =
MMI->getContext().createTempSymbol();
3214 OS.AddComment(
"Record length");
3215 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
3216 OS.emitLabel(BeginLabel);
3217 if (OS.isVerboseAsm())
3219 OS.emitInt16(
unsigned(SymKind));
3223void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3228 OS.emitValueToAlignment(
Align(4));
3229 OS.emitLabel(SymEnd);
3232void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3233 OS.AddComment(
"Record length");
3235 if (OS.isVerboseAsm())
3237 OS.emitInt16(uint16_t(EndKind));
3240void CodeViewDebug::emitDebugInfoForUDTs(
3241 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3243 size_t OriginalSize = UDTs.size();
3245 for (
const auto &UDT : UDTs) {
3246 const DIType *
T =
UDT.second;
3248 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3249 OS.AddComment(
"Type");
3250 OS.emitInt32(getCompleteTypeIndex(
T).getIndex());
3251 assert(OriginalSize == UDTs.size() &&
3252 "getCompleteTypeIndex found new UDTs!");
3254 endSymbolRecord(UDTRecordEnd);
3258void CodeViewDebug::collectGlobalOrStaticLocalVariableInfo(
3260 const DIGlobalVariable *DIGV = GVE->
getVariable();
3270 (DIE->
getElement(0) == dwarf::DW_OP_plus_uconst))
3275 CVGlobalVariableOffsets.insert(std::make_pair(DIGV, DIE->
getElement(1)));
3278 if (!GlobalMap.count(GVE) && DIE->
isConstant())
3279 GlobalVariables.emplace_back(CVGlobalVariable{DIGV, DIE});
3281 const auto *GV = GlobalMap.lookup(GVE);
3286 SmallVector<CVGlobalVariable, 1> *VariableList;
3291 ScopeGlobals.insert({
Scope, std::unique_ptr<GlobalVariableList>()});
3292 if (Insertion.second)
3293 Insertion.first->second = std::make_unique<GlobalVariableList>();
3294 VariableList = Insertion.first->second.get();
3297 VariableList = &ComdatVariables;
3300 VariableList = &GlobalVariables;
3302 VariableList->
emplace_back(CVGlobalVariable{DIGV, GV});
3305void CodeViewDebug::collectGlobalVariableInfo() {
3306 for (
const GlobalVariable &GV :
MMI->getModule()->globals()) {
3308 GV.getDebugInfo(GVEs);
3309 for (
const auto *GVE : GVEs)
3310 GlobalMap[GVE] = &GV;
3313 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3314 for (
const MDNode *Node : CUs->
operands()) {
3316 for (
const auto *GVE : CU->getGlobalVariables()) {
3317 collectGlobalOrStaticLocalVariableInfo(GVE);
3322void CodeViewDebug::collectDebugInfoForGlobals() {
3323 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3324 const DIGlobalVariable *DIGV = CVGV.DIGV;
3326 getCompleteTypeIndex(DIGV->
getType());
3327 getFullyQualifiedName(Scope, DIGV->
getName());
3330 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3331 const DIGlobalVariable *DIGV = CVGV.DIGV;
3333 getCompleteTypeIndex(DIGV->
getType());
3334 getFullyQualifiedName(Scope, DIGV->
getName());
3338void CodeViewDebug::emitDebugInfoForGlobals() {
3342 switchToDebugSectionForSymbol(
nullptr);
3343 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3344 OS.AddComment(
"Symbol subsection for globals");
3345 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3346 emitGlobalVariableList(GlobalVariables);
3347 emitStaticConstMemberList();
3348 endCVSubsection(EndLabel);
3353 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3356 OS.AddComment(
"Symbol subsection for " +
3358 switchToDebugSectionForSymbol(GVSym);
3359 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3361 emitDebugInfoForGlobal(CVGV);
3362 endCVSubsection(EndLabel);
3366void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3367 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3368 for (
const MDNode *Node : CUs->
operands()) {
3380 for (
const CVGlobalVariable &CVGV : Globals) {
3382 emitDebugInfoForGlobal(CVGV);
3387 const std::string &QualifiedName) {
3388 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3389 OS.AddComment(
"Type");
3390 OS.emitInt32(getTypeIndex(DTy).getIndex());
3392 OS.AddComment(
"Value");
3397 CodeViewRecordIO IO(Writer);
3399 StringRef SRef((
char *)
Data, Writer.getOffset());
3400 OS.emitBinaryData(SRef);
3402 OS.AddComment(
"Name");
3404 endSymbolRecord(SConstantEnd);
3407void CodeViewDebug::emitStaticConstMemberList() {
3408 for (
const DIDerivedType *DTy : StaticConstMembers) {
3412 if (
const ConstantInt *CI =
3416 else if (
const ConstantFP *CFP =
3418 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3422 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3423 getFullyQualifiedName(Scope, DTy->
getName()));
3433 if (
T == dwarf::DW_TAG_pointer_type ||
3434 T == dwarf::DW_TAG_ptr_to_member_type ||
3435 T == dwarf::DW_TAG_reference_type ||
3436 T == dwarf::DW_TAG_rvalue_reference_type)
3438 assert(DTy->getBaseType() &&
"Expected valid base type");
3443 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3446void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3447 const DIGlobalVariable *DIGV = CVGV.DIGV;
3453 Scope = MemberDecl->getScope();
3459 ? std::string(DIGV->
getName())
3462 if (
const GlobalVariable *GV =
3466 MCSymbol *GVSym = Asm->getSymbol(GV);
3467 SymbolKind DataSym = GV->isThreadLocal()
3468 ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32
3469 : SymbolKind::S_GTHREAD32)
3470 : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32
3471 : SymbolKind::S_GDATA32);
3472 MCSymbol *DataEnd = beginSymbolRecord(DataSym);
3473 OS.AddComment(
"Type");
3474 OS.emitInt32(getCompleteTypeIndex(DIGV->getType()).getIndex());
3475 OS.AddComment(
"DataOffset");
3478 uint64_t Offset = CVGlobalVariableOffsets.lookup(DIGV);
3479 OS.emitCOFFSecRel32(GVSym, Offset);
3481 OS.AddComment(
"Segment");
3482 OS.emitCOFFSectionIndex(GVSym);
3483 OS.AddComment(
"Name");
3484 const unsigned LengthOfDataRecord = 12;
3485 emitNullTerminatedSymbolName(OS, QualifiedName, LengthOfDataRecord);
3486 endSymbolRecord(DataEnd);
3488 const DIExpression *DIE = cast<const DIExpression *>(CVGV.GVInfo);
3489 assert(DIE->isConstant() &&
3490 "Global constant variables must contain a constant expression.");
3493 bool isUnsigned = isFloatDIType(DIGV->getType())
3495 : DebugHandlerBase::isUnsignedDIType(DIGV->getType());
3496 APSInt Value(APInt(64, DIE->getElement(1)), isUnsigned);
3497 emitConstantSymbolRecord(DIGV->getType(), Value, QualifiedName);
3504 int64_t)> &Callback) {
3506 if (JTI && !JTI->isEmpty()) {
3510 for (
const auto &
MBB : *MF) {
3512 const auto LastMI =
MBB.getFirstTerminator();
3513 if (LastMI !=
MBB.end() && LastMI->isIndirectBranch()) {
3521 for (
const auto &MO : LastMI->operands()) {
3523 unsigned Index = MO.getIndex();
3527 Callback(*JTI, *LastMI, Index);
3535 for (
auto I =
MBB.instr_rbegin(),
E =
MBB.instr_rend();
I !=
E; ++
I) {
3536 if (
I->isJumpTableDebugInfo()) {
3537 unsigned Index =
I->getOperand(0).getImm();
3541 Callback(*JTI, *LastMI, Index);
3550 "Some of jump tables were not used in a debug info instruction");
3555void CodeViewDebug::discoverJumpTableBranches(
const MachineFunction *MF,
3559 [
this](
const MachineJumpTableInfo &,
const MachineInstr &BranchMI,
3563void CodeViewDebug::collectDebugInfoForJumpTables(
const MachineFunction *MF,
3567 [
this, MF](
const MachineJumpTableInfo &JTI,
const MachineInstr &BranchMI,
3568 int64_t JumpTableIndex) {
3581 "EK_Custom32, EK_GPRel32BlockAddress, and "
3582 "EK_GPRel64BlockAddress should never be emitted for COFF");
3585 EntrySize = JumpTableEntrySize::Pointer;
3592 std::tie(
Base, BaseOffset, Branch, EntrySize) =
3593 Asm->getCodeViewJumpTableInfo(JumpTableIndex, &BranchMI, Branch);
3597 const MachineJumpTableEntry &JTE = JTI.
getJumpTables()[JumpTableIndex];
3598 JumpTableInfo CVJTI{EntrySize,
3605 for (
const auto &
MBB : JTE.
MBBs)
3607 CurFn->JumpTables.push_back(std::move(CVJTI));
3611void CodeViewDebug::emitDebugInfoForJumpTables(
const FunctionInfo &FI) {
3613 for (
const auto &JumpTable : FI.JumpTables) {
3614 for (
const auto &CaseSym :
JumpTable.Cases) {
3615 MCSymbol *LabelEnd = beginSymbolRecord(SymbolKind::S_LABEL32);
3616 OS.AddComment(
"Offset and segment");
3617 OS.emitCOFFSecRel32(CaseSym, 0);
3618 OS.AddComment(
"Flags");
3621 endSymbolRecord(LabelEnd);
3625 for (
const auto &JumpTable : FI.JumpTables) {
3626 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3628 OS.AddComment(
"Base offset");
3630 OS.AddComment(
"Base section index");
3631 OS.emitCOFFSectionIndex(
JumpTable.Base);
3633 OS.AddComment(
"Base offset");
3635 OS.AddComment(
"Base section index");
3638 OS.AddComment(
"Switch type");
3639 OS.emitInt16(
static_cast<uint16_t
>(
JumpTable.EntrySize));
3640 OS.AddComment(
"Branch offset");
3641 OS.emitCOFFSecRel32(
JumpTable.Branch, 0);
3642 OS.AddComment(
"Table offset");
3643 OS.emitCOFFSecRel32(
JumpTable.Table, 0);
3644 OS.AddComment(
"Branch section index");
3645 OS.emitCOFFSectionIndex(
JumpTable.Branch);
3646 OS.AddComment(
"Table section index");
3647 OS.emitCOFFSectionIndex(
JumpTable.Table);
3648 OS.AddComment(
"Entries count");
3650 endSymbolRecord(JumpTableEnd);
3654void CodeViewDebug::emitInlinees(
3658 constexpr size_t ChunkSize =
3665 size_t CurrentIndex = 0;
3666 while (CurrentIndex < SortedInlinees.
size()) {
3667 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3668 auto CurrentChunkSize =
3669 std::min(ChunkSize, SortedInlinees.
size() - CurrentIndex);
3670 OS.AddComment(
"Count");
3671 OS.emitInt32(CurrentChunkSize);
3673 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3674 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3675 OS.AddComment(
"Inlinee");
3676 OS.emitInt32(SortedInlinees[CurrentIndex].getIndex());
3678 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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 cl::opt< bool > UseTagRecord2("use-codeview-tagrecord2", cl::Hidden, cl::desc("Use the *2 versions for tag records in CodeView (LF_CLASS2, etc.)"), cl::init(false))
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 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 constexpr StringLiteral Filename
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.
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
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
static LLVM_ABI bool extractLeadingOffset(ArrayRef< uint64_t > Ops, int64_t &OffsetInBytes, SmallVectorImpl< uint64_t > &RemainingOps)
LLVM_ABI std::optional< SignedOrUnsignedConstant > isConstant() const
Determine whether this represents a constant value, if so.
A pair of DIGlobalVariable and DIExpression.
DIGlobalVariable * getVariable() const
DIExpression * getExpression() const
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 source language identity metadata that includes language name,...
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.
DITypeArray 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.
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 hasOptNone() const
Do not optimize this function (-O0).
bool hasProfileData() const
Return true if the function is annotated with profile data.
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)
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
Check if the string is empty.
char back() const
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
initializer< Ty > init(const Ty &Val)
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.
MemberAccess
Source-level access specifier. (CV_access_e)
ThunkOrdinal
These values correspond to the THUNK_ORDINAL enumeration.
LLVM_ABI EnumStrings< SymbolKind, 1 > getSymbolTypeNames()
EncodedFramePtrReg
Two-bit value indicating which register is the designated frame pointer register.
TypeRecordKind
Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.
SymbolKind
Duplicate copy of the above enum, but using the official CV names.
ModifierOptions
Equivalent to CV_modifier_t.
@ ProfileGuidedOptimization
@ HasStructuredExceptionHandling
LLVM_ABI EncodedFramePtrReg encodeFramePtrReg(RegisterId Reg, CPUType CPU)
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.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
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.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
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.
static constexpr int32_t NoDeref
Value for DerefOffset indicating this is not an indirect load.
static LLVM_ABI 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.