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); }
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())
150 Filepath = std::string(Dir);
151 if (Dir.
back() !=
'/')
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");
640 CurrentSourceLanguage =
646 if (!M->getCodeViewFlag() ||
652 collectGlobalVariableInfo();
657 EmitDebugGlobalHashes = GH && !GH->
isZero();
661 if (!CompilerInfoAsm)
671 switchToDebugSectionForSymbol(
nullptr);
675 emitCompilerInformation();
676 endCVSubsection(CompilerInfo);
680 emitSecureHotPatchInformation();
682 emitInlineeLinesSubsection();
685 for (
auto &
P : FnDebugInfo)
686 if (!
P.first->isDeclarationForLinker())
687 emitDebugInfoForFunction(
P.first, *
P.second);
692 collectDebugInfoForGlobals();
695 emitDebugInfoForRetainedTypes();
698 setCurrentSubprogram(
nullptr);
699 emitDebugInfoForGlobals();
703 switchToDebugSectionForSymbol(
nullptr);
706 if (!GlobalUDTs.empty()) {
708 emitDebugInfoForUDTs(GlobalUDTs);
709 endCVSubsection(SymbolsEnd);
713 OS.AddComment(
"File index to string table offset subsection");
714 OS.emitCVFileChecksumsDirective();
717 OS.AddComment(
"String table");
718 OS.emitCVStringTableDirective();
727 emitTypeInformation();
729 if (EmitDebugGlobalHashes)
730 emitTypeGlobalHashes();
737 unsigned MaxFixedRecordLength = 0xF00) {
748void CodeViewDebug::emitTypeInformation() {
749 if (TypeTable.empty())
753 OS.switchSection(
Asm->getObjFileLowering().getCOFFDebugTypesSection());
754 emitCodeViewMagicVersion();
756 TypeTableCollection
Table(TypeTable.records());
757 TypeVisitorCallbackPipeline Pipeline;
760 CVMCAdapter CVMCOS(OS,
Table);
761 TypeRecordMapping typeMapping(CVMCOS);
764 std::optional<TypeIndex>
B =
Table.getFirst();
780void CodeViewDebug::emitTypeGlobalHashes() {
781 if (TypeTable.empty())
786 OS.switchSection(
Asm->getObjFileLowering().getCOFFGlobalTypeHashesSection());
788 OS.emitValueToAlignment(
Align(4));
789 OS.AddComment(
"Magic");
791 OS.AddComment(
"Section Version");
793 OS.AddComment(
"Hash Algorithm");
794 OS.emitInt16(uint16_t(GlobalTypeHashAlg::BLAKE3));
797 for (
const auto &GHR : TypeTable.hashes()) {
798 if (OS.isVerboseAsm()) {
802 raw_svector_ostream CommentOS(Comment);
804 OS.AddComment(Comment);
807 assert(GHR.Hash.size() == 8);
808 StringRef S(
reinterpret_cast<const char *
>(GHR.Hash.data()),
810 OS.emitBinaryData(S);
814void CodeViewDebug::emitObjName() {
815 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);
817 StringRef PathRef(CompilerInfoAsm->TM.Options.ObjectFilenameForDebug);
818 llvm::SmallString<256> PathStore(PathRef);
820 if (PathRef.empty() || PathRef ==
"-") {
827 OS.AddComment(
"Signature");
828 OS.emitIntValue(0, 4);
830 OS.AddComment(
"Object name");
833 endSymbolRecord(CompilerEnd);
836void CodeViewDebug::emitSecureHotPatchInformation() {
839 for (
const auto &
F :
MMI->getModule()->functions()) {
840 if (!
F.isDeclarationForLinker() &&
841 F.hasFnAttribute(
"marked_for_windows_hot_patching")) {
842 if (hotPatchInfo ==
nullptr)
843 hotPatchInfo = beginCVSubsection(DebugSubsectionKind::Symbols);
844 MCSymbol *HotPatchEnd = beginSymbolRecord(SymbolKind::S_HOTPATCHFUNC);
845 auto *
SP =
F.getSubprogram();
846 OS.AddComment(
"Function");
847 OS.emitInt32(getFuncIdForSubprogram(SP).getIndex());
848 OS.AddComment(
"Name");
850 endSymbolRecord(HotPatchEnd);
854 if (hotPatchInfo !=
nullptr)
855 endCVSubsection(hotPatchInfo);
869 for (
const char C : Name) {
872 V.Part[
N] +=
C -
'0';
874 std::min<int>(V.Part[
N], std::numeric_limits<uint16_t>::max());
875 }
else if (
C ==
'.') {
885void CodeViewDebug::emitCompilerInformation() {
886 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
890 Flags = CurrentSourceLanguage;
892 if (
MMI->getModule()->getProfileSummary(
false) !=
nullptr) {
893 Flags |=
static_cast<uint32_t
>(CompileSym3Flags::PGO);
897 ArchType Arch =
M->getTargetTriple().getArch();
902 if ((HotpatchFlag && HotpatchFlag->isOne()) || Arch == ArchType::thumb ||
903 Arch == ArchType::aarch64) {
904 Flags |=
static_cast<uint32_t
>(CompileSym3Flags::HotPatch);
907 OS.AddComment(
"Flags and language");
910 OS.AddComment(
"CPUType");
911 OS.emitInt16(
static_cast<uint64_t>(TheCPU));
913 StringRef CompilerVersion =
"0";
915 CompilerVersion = TheCU->getProducer();
918 OS.AddComment(
"Frontend version");
919 for (
int N : FrontVer.Part) {
926 int Major = 1000 * LLVM_VERSION_MAJOR +
927 10 * LLVM_VERSION_MINOR +
930 Major = std::min<int>(Major, std::numeric_limits<uint16_t>::max());
931 Version BackVer = {{ Major, 0, 0, 0 }};
932 OS.AddComment(
"Backend version");
933 for (
int N : BackVer.Part)
936 OS.AddComment(
"Null-terminated compiler version string");
939 endSymbolRecord(CompilerEnd);
948void CodeViewDebug::emitBuildInfo() {
960 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
963 const DIFile *MainSourceFile = CU->getFile();
974 TypeTable,
Asm->TM.Options.MCOptions.CommandlineArgs);
976 BuildInfoRecord BIR(BuildInfoArgs);
977 TypeIndex BuildInfoIndex = TypeTable.writeLeafType(BIR);
981 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
982 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
983 OS.AddComment(
"LF_BUILDINFO index");
984 OS.emitInt32(BuildInfoIndex.
getIndex());
985 endSymbolRecord(BIEnd);
986 endCVSubsection(BISubsecEnd);
989void CodeViewDebug::emitInlineeLinesSubsection() {
990 if (InlinedSubprograms.empty())
993 OS.AddComment(
"Inlinee lines subsection");
994 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
1000 OS.AddComment(
"Inlinee lines signature");
1001 OS.emitInt32(
unsigned(InlineeLinesSignature::Normal));
1003 for (
const DISubprogram *SP : InlinedSubprograms) {
1004 assert(TypeIndices.count({SP, nullptr}));
1005 TypeIndex InlineeIdx = TypeIndices[{
SP,
nullptr}];
1008 unsigned FileId = maybeRecordFile(
SP->getFile());
1009 OS.AddComment(
"Inlined function " +
SP->getName() +
" starts at " +
1010 SP->getFilename() + Twine(
':') + Twine(
SP->getLine()));
1012 OS.AddComment(
"Type index of inlined function");
1013 OS.emitInt32(InlineeIdx.
getIndex());
1014 OS.AddComment(
"Offset into filechecksum table");
1015 OS.emitCVFileChecksumOffsetDirective(FileId);
1016 OS.AddComment(
"Starting line number");
1017 OS.emitInt32(
SP->getLine());
1020 endCVSubsection(InlineEnd);
1023void CodeViewDebug::emitInlinedCallSite(
const FunctionInfo &FI,
1026 assert(TypeIndices.count({Site.Inlinee, nullptr}));
1027 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee,
nullptr}];
1030 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
1032 OS.AddComment(
"PtrParent");
1034 OS.AddComment(
"PtrEnd");
1036 OS.AddComment(
"Inlinee type index");
1037 OS.emitInt32(InlineeIdx.
getIndex());
1039 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
1040 unsigned StartLineNum = Site.Inlinee->getLine();
1042 OS.emitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum,
1045 endSymbolRecord(InlineEnd);
1047 emitLocalVariableList(FI, Site.InlinedLocals);
1050 for (
const DILocation *ChildSite : Site.ChildSites) {
1051 auto I = FI.InlineSites.find(ChildSite);
1052 assert(
I != FI.InlineSites.end() &&
1053 "child site not in function inline site map");
1054 emitInlinedCallSite(FI, ChildSite,
I->second);
1058 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1061void CodeViewDebug::switchToDebugSectionForSymbol(
const MCSymbol *GVSym) {
1065 MCSectionCOFF *GVSec =
1066 GVSym ?
static_cast<MCSectionCOFF *
>(&GVSym->
getSection()) : nullptr;
1069 auto *DebugSec =
static_cast<MCSectionCOFF *
>(
1070 CompilerInfoAsm->getObjFileLowering().getCOFFDebugSymbolsSection());
1071 DebugSec = OS.getContext().getAssociativeCOFFSection(DebugSec, KeySym);
1073 OS.switchSection(DebugSec);
1077 if (ComdatDebugSections.insert(DebugSec).second)
1078 emitCodeViewMagicVersion();
1083void CodeViewDebug::emitDebugInfoForThunk(
const Function *GV,
1086 std::string FuncName =
1090 OS.AddComment(
"Symbol subsection for " + Twine(FuncName));
1091 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1094 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1095 OS.AddComment(
"PtrParent");
1097 OS.AddComment(
"PtrEnd");
1099 OS.AddComment(
"PtrNext");
1101 OS.AddComment(
"Thunk section relative address");
1102 OS.emitCOFFSecRel32(Fn, 0);
1103 OS.AddComment(
"Thunk section index");
1104 OS.emitCOFFSectionIndex(Fn);
1105 OS.AddComment(
"Code size");
1106 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 2);
1107 OS.AddComment(
"Ordinal");
1108 OS.emitInt8(
unsigned(ordinal));
1109 OS.AddComment(
"Function name");
1112 endSymbolRecord(ThunkRecordEnd);
1118 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1120 endCVSubsection(SymbolsEnd);
1123void CodeViewDebug::emitDebugInfoForFunction(
const Function *GV,
1131 switchToDebugSectionForSymbol(Fn);
1133 std::string FuncName;
1136 setCurrentSubprogram(SP);
1138 if (
SP->isThunk()) {
1139 emitDebugInfoForThunk(GV, FI, Fn);
1145 if (!
SP->getName().empty())
1146 FuncName = getFullyQualifiedName(
SP->getScope(),
SP->getName());
1149 if (FuncName.empty())
1153 if (
MMI->getModule()->getTargetTriple().getArch() ==
Triple::x86)
1154 OS.emitCVFPOData(Fn);
1157 OS.AddComment(
"Symbol subsection for " + Twine(FuncName));
1158 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1161 : SymbolKind::S_GPROC32_ID;
1162 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1165 OS.AddComment(
"PtrParent");
1167 OS.AddComment(
"PtrEnd");
1169 OS.AddComment(
"PtrNext");
1173 OS.AddComment(
"Code size");
1174 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 4);
1175 OS.AddComment(
"Offset after prologue");
1177 OS.AddComment(
"Offset before epilogue");
1179 OS.AddComment(
"Function type index");
1180 OS.emitInt32(getFuncIdForSubprogram(GV->
getSubprogram()).getIndex());
1181 OS.AddComment(
"Function section relative address");
1182 OS.emitCOFFSecRel32(Fn, 0);
1183 OS.AddComment(
"Function section index");
1184 OS.emitCOFFSectionIndex(Fn);
1185 OS.AddComment(
"Flags");
1186 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;
1187 if (FI.HasFramePointer)
1188 ProcFlags |= ProcSymFlags::HasFP;
1190 ProcFlags |= ProcSymFlags::IsNoReturn;
1192 ProcFlags |= ProcSymFlags::IsNoInline;
1193 OS.emitInt8(
static_cast<uint8_t
>(ProcFlags));
1195 OS.AddComment(
"Function name");
1198 endSymbolRecord(ProcRecordEnd);
1200 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1202 OS.AddComment(
"FrameSize");
1203 OS.emitInt32(FI.FrameSize - FI.CSRSize);
1204 OS.AddComment(
"Padding");
1206 OS.AddComment(
"Offset of padding");
1208 OS.AddComment(
"Bytes of callee saved registers");
1209 OS.emitInt32(FI.CSRSize);
1210 OS.AddComment(
"Exception handler offset");
1212 OS.AddComment(
"Exception handler section");
1214 OS.AddComment(
"Flags (defines frame register)");
1215 OS.emitInt32(uint32_t(FI.FrameProcOpts));
1216 endSymbolRecord(FrameProcEnd);
1218 emitInlinees(FI.Inlinees);
1219 emitLocalVariableList(FI, FI.Locals);
1220 emitGlobalVariableList(FI.Globals);
1221 emitLexicalBlockList(FI.ChildBlocks, FI);
1226 for (
const DILocation *InlinedAt : FI.ChildSites) {
1227 auto I = FI.InlineSites.find(InlinedAt);
1228 assert(
I != FI.InlineSites.end() &&
1229 "child site not in function inline site map");
1230 emitInlinedCallSite(FI, InlinedAt,
I->second);
1233 for (
auto Annot : FI.Annotations) {
1236 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1237 OS.emitCOFFSecRel32(Label, 0);
1239 OS.emitCOFFSectionIndex(Label);
1245 assert(Str.data()[Str.size()] ==
'\0' &&
"non-nullterminated MDString");
1246 OS.emitBytes(StringRef(Str.data(), Str.size() + 1));
1248 endSymbolRecord(AnnotEnd);
1251 for (
auto HeapAllocSite : FI.HeapAllocSites) {
1252 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1253 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1254 const DIType *DITy = std::get<2>(HeapAllocSite);
1255 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1256 OS.AddComment(
"Call site offset");
1257 OS.emitCOFFSecRel32(BeginLabel, 0);
1258 OS.AddComment(
"Call site section index");
1259 OS.emitCOFFSectionIndex(BeginLabel);
1260 OS.AddComment(
"Call instruction length");
1261 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
1262 OS.AddComment(
"Type index");
1263 OS.emitInt32(getCompleteTypeIndex(DITy).getIndex());
1264 endSymbolRecord(HeapAllocEnd);
1268 emitDebugInfoForUDTs(LocalUDTs);
1270 emitDebugInfoForJumpTables(FI);
1273 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1275 endCVSubsection(SymbolsEnd);
1278 OS.emitCVLinetableDirective(FI.FuncId, Fn, FI.End);
1282CodeViewDebug::createDefRangeMem(uint16_t CVRegister,
int Offset,
1283 int32_t DerefOffset) {
1289 DR.StructOffset = 0;
1290 DR.CVRegister = CVRegister;
1291 DR.DerefOffset = DerefOffset;
1295void CodeViewDebug::collectVariableInfoFromMFTable(
1302 for (
const MachineFunction::VariableDbgInfo &VI :
1306 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1307 "Expected inlined-at fields to agree");
1309 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1317 int64_t ExprOffset = 0;
1321 if (!
VI.Expr->extractLeadingOffset(ExprOffset, FirstRemaining))
1323 if (!FirstRemaining.
empty()) {
1324 if (FirstRemaining.
front() != dwarf::DW_OP_deref)
1326 SmallVector<uint64_t, 1> LastRemaining;
1328 ArrayRef(FirstRemaining).drop_front(), DerefOffset,
1331 if (!LastRemaining.
empty())
1338 StackOffset FrameOffset =
1340 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1346 if (DerefOffset < INT32_MIN || DerefOffset > INT32_MAX)
1351 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset,
1352 static_cast<int32_t
>(DerefOffset));
1360 End = End ? End :
Asm->getFunctionEnd();
1361 Var.DefRanges[DefRange].emplace_back(Begin, End);
1364 recordLocalVariable(std::move(Var), Scope);
1368void CodeViewDebug::calculateRanges(
1370 const TargetRegisterInfo *
TRI =
Asm->MF->getSubtarget().getRegisterInfo();
1373 for (
auto I = Entries.
begin(),
E = Entries.
end();
I !=
E; ++
I) {
1375 if (!
Entry.isDbgValue())
1377 const MachineInstr *DVInst =
Entry.getInstr();
1381 std::optional<DbgVariableLocation>
Location =
1392 Var.ConstantValue =
APSInt(APInt(64,
Op.getImm()),
false);
1404 if (
Location->FragmentInfo->OffsetInBits % 8)
1414 DR.InMemory = !
Location->LoadChain.empty();
1417 if (!
Location->LoadChain.empty()) {
1418 DR.DataOffset =
Location->LoadChain[0];
1419 if (
Location->LoadChain.size() >= 2)
1420 DR.DerefOffset =
Location->LoadChain[1];
1423 DR.IsSubfield =
true;
1424 DR.StructOffset =
Location->FragmentInfo->OffsetInBits / 8;
1426 DR.IsSubfield =
false;
1427 DR.StructOffset = 0;
1434 auto &EndingEntry = Entries[
Entry.getEndIndex()];
1435 End = EndingEntry.isDbgValue()
1439 End =
Asm->getFunctionEnd();
1443 SmallVectorImpl<std::pair<const MCSymbol *, const MCSymbol *>> &
R =
1445 if (!
R.empty() &&
R.back().second == Begin)
1446 R.back().second = End;
1448 R.emplace_back(Begin, End);
1454void CodeViewDebug::collectVariableInfo(
const DISubprogram *SP) {
1455 DenseSet<InlinedEntity> Processed;
1457 collectVariableInfoFromMFTable(Processed);
1459 for (
const MDNode *
N :
SP->getRetainedNodes())
1461 collectGlobalOrStaticLocalVariableInfo(GVE);
1464 InlinedEntity
IV =
I.first;
1468 const DILocation *InlinedAt =
IV.second;
1471 const auto &Entries =
I.second;
1473 LexicalScope *
Scope =
nullptr;
1485 calculateRanges(Var, Entries);
1486 recordLocalVariable(std::move(Var), Scope);
1495 auto Insertion = FnDebugInfo.
insert({&GV, std::make_unique<FunctionInfo>()});
1496 assert(Insertion.second &&
"function already has info");
1497 CurFn = Insertion.first->second.get();
1498 CurFn->FuncId = NextFuncId++;
1499 CurFn->Begin =
Asm->getFunctionBegin();
1507 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1513 if (CurFn->FrameSize > 0) {
1518 CurFn->HasFramePointer =
true;
1521 if (CurFn->HasStackRealignment) {
1572 CurFn->FrameProcOpts = FPO;
1574 OS.emitCVFuncIdDirective(CurFn->FuncId);
1581 bool EmptyPrologue =
true;
1582 for (
const auto &
MBB : *MF) {
1583 for (
const auto &
MI :
MBB) {
1588 }
else if (!
MI.isMetaInstruction()) {
1589 EmptyPrologue =
false;
1597 maybeRecordLocation(FnStartDL, MF);
1601 for (
const auto &
MBB : *MF) {
1602 for (
const auto &
MI :
MBB) {
1603 if (
MI.getHeapAllocMarker()) {
1611 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
1613 discoverJumpTableBranches(MF,
isThumb);
1621 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1622 if (
DIScope *Scope =
T->getScope()) {
1623 switch (Scope->getTag()) {
1624 case dwarf::DW_TAG_structure_type:
1625 case dwarf::DW_TAG_class_type:
1626 case dwarf::DW_TAG_union_type:
1636 if (!
T ||
T->isForwardDecl())
1642 T = DT->getBaseType();
1647void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1655 const DISubprogram *ClosestSubprogram =
1656 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1658 std::string FullyQualifiedName =
1661 if (ClosestSubprogram ==
nullptr) {
1662 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1663 }
else if (ClosestSubprogram == CurrentSubprogram) {
1664 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1675TypeIndex CodeViewDebug::lowerType(
const DIType *Ty,
const DIType *ClassTy) {
1678 case dwarf::DW_TAG_array_type:
1680 case dwarf::DW_TAG_typedef:
1682 case dwarf::DW_TAG_base_type:
1684 case dwarf::DW_TAG_pointer_type:
1688 case dwarf::DW_TAG_reference_type:
1689 case dwarf::DW_TAG_rvalue_reference_type:
1691 case dwarf::DW_TAG_ptr_to_member_type:
1693 case dwarf::DW_TAG_restrict_type:
1694 case dwarf::DW_TAG_const_type:
1695 case dwarf::DW_TAG_volatile_type:
1698 case dwarf::DW_TAG_subroutine_type:
1707 case dwarf::DW_TAG_enumeration_type:
1709 case dwarf::DW_TAG_class_type:
1710 case dwarf::DW_TAG_structure_type:
1712 case dwarf::DW_TAG_union_type:
1714 case dwarf::DW_TAG_string_type:
1716 case dwarf::DW_TAG_unspecified_type:
1717 if (Ty->
getName() ==
"decltype(nullptr)")
1726TypeIndex CodeViewDebug::lowerTypeAlias(
const DIDerivedType *Ty) {
1727 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1732 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) &&
1733 TypeName ==
"HRESULT")
1734 return TypeIndex(SimpleTypeKind::HResult);
1735 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::UInt16Short) &&
1736 TypeName ==
"wchar_t")
1737 return TypeIndex(SimpleTypeKind::WideCharacter);
1739 return UnderlyingTypeIndex;
1744 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1746 TypeIndex IndexType = getPointerSizeInBytes() == 8
1747 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1754 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1755 const DINode *Element =
Elements[i];
1756 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1766 Count = CI->getSExtValue();
1772 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1773 Count = UI->getSExtValue() - Lowerbound + 1;
1784 ElementSize *=
Count;
1789 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1792 ArrayRecord AR(ElementTypeIndex, IndexType, ArraySize, Name);
1793 ElementTypeIndex = TypeTable.writeLeafType(AR);
1796 return ElementTypeIndex;
1804TypeIndex CodeViewDebug::lowerTypeString(
const DIStringType *Ty) {
1805 TypeIndex CharType = TypeIndex(SimpleTypeKind::NarrowCharacter);
1809 TypeIndex IndexType = getPointerSizeInBytes() == 8
1810 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1814 ArrayRecord AR(CharType, IndexType, ArraySize, Name);
1816 return TypeTable.writeLeafType(AR);
1819TypeIndex CodeViewDebug::lowerTypeBasic(
const DIBasicType *Ty) {
1829 case dwarf::DW_ATE_address:
1832 case dwarf::DW_ATE_boolean:
1834 case 1: STK = SimpleTypeKind::Boolean8;
break;
1835 case 2: STK = SimpleTypeKind::Boolean16;
break;
1836 case 4: STK = SimpleTypeKind::Boolean32;
break;
1837 case 8: STK = SimpleTypeKind::Boolean64;
break;
1838 case 16: STK = SimpleTypeKind::Boolean128;
break;
1841 case dwarf::DW_ATE_complex_float:
1845 case 4: STK = SimpleTypeKind::Complex16;
break;
1846 case 8: STK = SimpleTypeKind::Complex32;
break;
1847 case 16: STK = SimpleTypeKind::Complex64;
break;
1848 case 20: STK = SimpleTypeKind::Complex80;
break;
1849 case 32: STK = SimpleTypeKind::Complex128;
break;
1852 case dwarf::DW_ATE_float:
1854 case 2: STK = SimpleTypeKind::Float16;
break;
1855 case 4: STK = SimpleTypeKind::Float32;
break;
1856 case 6: STK = SimpleTypeKind::Float48;
break;
1857 case 8: STK = SimpleTypeKind::Float64;
break;
1858 case 10: STK = SimpleTypeKind::Float80;
break;
1859 case 16: STK = SimpleTypeKind::Float128;
break;
1862 case dwarf::DW_ATE_signed:
1864 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1865 case 2: STK = SimpleTypeKind::Int16Short;
break;
1866 case 4: STK = SimpleTypeKind::Int32;
break;
1867 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1868 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1871 case dwarf::DW_ATE_unsigned:
1873 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1874 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1875 case 4: STK = SimpleTypeKind::UInt32;
break;
1876 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1877 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1880 case dwarf::DW_ATE_UTF:
1882 case 1: STK = SimpleTypeKind::Character8;
break;
1883 case 2: STK = SimpleTypeKind::Character16;
break;
1884 case 4: STK = SimpleTypeKind::Character32;
break;
1887 case dwarf::DW_ATE_signed_char:
1889 STK = SimpleTypeKind::SignedCharacter;
1891 case dwarf::DW_ATE_unsigned_char:
1893 STK = SimpleTypeKind::UnsignedCharacter;
1903 if (STK == SimpleTypeKind::Int32 &&
1905 STK = SimpleTypeKind::Int32Long;
1906 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1907 Ty->
getName() ==
"unsigned long"))
1908 STK = SimpleTypeKind::UInt32Long;
1909 if (STK == SimpleTypeKind::UInt16Short &&
1911 STK = SimpleTypeKind::WideCharacter;
1912 if ((STK == SimpleTypeKind::SignedCharacter ||
1913 STK == SimpleTypeKind::UnsignedCharacter) &&
1915 STK = SimpleTypeKind::NarrowCharacter;
1917 return TypeIndex(STK);
1920TypeIndex CodeViewDebug::lowerTypePointer(
const DIDerivedType *Ty,
1922 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1926 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1928 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1930 ? SimpleTypeMode::NearPointer64
1931 : SimpleTypeMode::NearPointer32;
1936 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1940 case dwarf::DW_TAG_pointer_type:
1941 PM = PointerMode::Pointer;
1943 case dwarf::DW_TAG_reference_type:
1944 PM = PointerMode::LValueReference;
1946 case dwarf::DW_TAG_rvalue_reference_type:
1947 PM = PointerMode::RValueReference;
1952 PO |= PointerOptions::Const;
1954 PointerRecord PR(PointeeTI, PK, PM, PO, Ty->
getSizeInBits() / 8);
1955 return TypeTable.writeLeafType(PR);
1968 case DINode::FlagSingleInheritance:
1970 case DINode::FlagMultipleInheritance:
1972 case DINode::FlagVirtualInheritance:
1980 case DINode::FlagSingleInheritance:
1982 case DINode::FlagMultipleInheritance:
1984 case DINode::FlagVirtualInheritance:
1991TypeIndex CodeViewDebug::lowerTypeMemberPointer(
const DIDerivedType *Ty,
1993 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
1996 TypeIndex PointeeTI =
1997 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->
getClassType() :
nullptr);
1998 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
1999 : PointerKind::Near32;
2000 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
2001 : PointerMode::PointerToDataMember;
2005 MemberPointerInfo MPI(
2007 PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);
2008 return TypeTable.writeLeafType(PR);
2025TypeIndex CodeViewDebug::lowerTypeModifier(
const DIDerivedType *Ty) {
2029 const DIType *BaseTy = Ty;
2030 while (IsModifier && BaseTy) {
2032 switch (BaseTy->
getTag()) {
2033 case dwarf::DW_TAG_const_type:
2034 Mods |= ModifierOptions::Const;
2035 PO |= PointerOptions::Const;
2037 case dwarf::DW_TAG_volatile_type:
2038 Mods |= ModifierOptions::Volatile;
2039 PO |= PointerOptions::Volatile;
2041 case dwarf::DW_TAG_restrict_type:
2044 PO |= PointerOptions::Restrict;
2059 switch (BaseTy->
getTag()) {
2060 case dwarf::DW_TAG_pointer_type:
2061 case dwarf::DW_TAG_reference_type:
2062 case dwarf::DW_TAG_rvalue_reference_type:
2064 case dwarf::DW_TAG_ptr_to_member_type:
2071 TypeIndex ModifiedTI = getTypeIndex(BaseTy);
2075 if (Mods == ModifierOptions::None)
2078 ModifierRecord MR(ModifiedTI, Mods);
2079 return TypeTable.writeLeafType(MR);
2085 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2088 if (ReturnAndArgTypeIndices.
size() > 1 &&
2094 if (!ReturnAndArgTypeIndices.
empty()) {
2095 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2096 ReturnTypeIndex = ReturnAndArgTypesRef.consume_front();
2097 ArgTypeIndices = ReturnAndArgTypesRef;
2100 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2101 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2106 ProcedureRecord Procedure(ReturnTypeIndex, CC, FO, ArgTypeIndices.
size(),
2108 return TypeTable.writeLeafType(Procedure);
2111TypeIndex CodeViewDebug::lowerTypeMemberFunction(
const DISubroutineType *Ty,
2114 bool IsStaticMethod,
2117 TypeIndex ClassType = getTypeIndex(ClassTy);
2124 if (ReturnAndArgs.size() > Index) {
2125 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
2131 TypeIndex ThisTypeIndex;
2132 if (!IsStaticMethod && ReturnAndArgs.size() > Index) {
2133 if (
const DIDerivedType *PtrTy =
2135 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2136 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2142 while (Index < ReturnAndArgs.size())
2143 ArgTypeIndices.
push_back(getTypeIndex(ReturnAndArgs[Index++]));
2149 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2150 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2154 MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FO,
2155 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2156 return TypeTable.writeLeafType(MFR);
2159TypeIndex CodeViewDebug::lowerTypeVFTableShape(
const DIDerivedType *Ty) {
2160 unsigned VSlotCount =
2164 VFTableShapeRecord VFTSR(Slots);
2165 return TypeTable.writeLeafType(VFTSR);
2182 if (SP->isArtificial())
2192 if (SP->getFlags() & DINode::FlagStaticMember)
2195 switch (SP->getVirtuality()) {
2196 case dwarf::DW_VIRTUALITY_none:
2198 case dwarf::DW_VIRTUALITY_virtual:
2200 case dwarf::DW_VIRTUALITY_pure_virtual:
2211 switch (Ty->getTag()) {
2212 case dwarf::DW_TAG_class_type:
2213 return TypeRecordKind::Class;
2214 case dwarf::DW_TAG_structure_type:
2215 return TypeRecordKind::Struct;
2229 if (!Ty->getIdentifier().empty())
2243 if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) {
2247 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2259void CodeViewDebug::addUDTSrcLine(
const DIType *Ty, TypeIndex TI) {
2261 case dwarf::DW_TAG_class_type:
2262 case dwarf::DW_TAG_structure_type:
2263 case dwarf::DW_TAG_union_type:
2264 case dwarf::DW_TAG_enumeration_type:
2270 if (
const auto *File = Ty->
getFile()) {
2271 StringIdRecord SIDR(TypeIndex(0x0), getFullFilepath(File));
2272 TypeIndex SIDI = TypeTable.writeLeafType(SIDR);
2274 UdtSourceLineRecord USLR(TI, SIDI, Ty->
getLine());
2275 TypeTable.writeLeafType(USLR);
2282 unsigned EnumeratorCount = 0;
2285 CO |= ClassOptions::ForwardReference;
2287 ContinuationRecordBuilder ContinuationBuilder;
2288 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2293 EnumeratorRecord ER(
2294 MemberAccess::Public,
2301 FTI = TypeTable.insertRecord(ContinuationBuilder);
2304 std::string FullName = getFullyQualifiedName(Ty);
2306 EnumRecord ER(EnumeratorCount, CO, FTI, FullName, Ty->
getIdentifier(),
2308 TypeIndex EnumTI = TypeTable.writeLeafType(ER);
2310 addUDTSrcLine(Ty, EnumTI);
2344void CodeViewDebug::clear() {
2345 assert(CurFn ==
nullptr);
2347 FnDebugInfo.clear();
2348 FileToFilepathMap.clear();
2351 TypeIndices.clear();
2352 CompleteTypeIndices.clear();
2353 ScopeGlobals.clear();
2354 CVGlobalVariableOffsets.clear();
2357void CodeViewDebug::collectMemberInfo(
ClassInfo &Info,
2360 Info.Members.push_back({DDTy, 0});
2363 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2364 DINode::FlagStaticMember) {
2367 StaticConstMembers.push_back(DDTy);
2379 const DIType *Ty = DDTy->getBaseType();
2380 bool FullyResolved =
false;
2381 while (!FullyResolved) {
2383 case dwarf::DW_TAG_const_type:
2384 case dwarf::DW_TAG_volatile_type:
2390 FullyResolved =
true;
2399 ClassInfo NestedInfo = collectClassInfo(DCTy);
2400 for (
const ClassInfo::MemberInfo &IndirectField : NestedInfo.
Members)
2401 Info.Members.push_back(
2409 for (
auto *Element : Elements) {
2415 Info.Methods[
SP->getRawName()].push_back(SP);
2417 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2418 collectMemberInfo(Info, DDTy);
2419 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2420 Info.Inheritance.push_back(DDTy);
2421 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2422 DDTy->
getName() ==
"__vtbl_ptr_type") {
2423 Info.VShapeTI = getTypeIndex(DDTy);
2424 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2425 Info.NestedTypes.push_back(DDTy);
2426 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2431 Info.NestedTypes.push_back(Composite);
2441 return Ty->getName().empty() && Ty->getIdentifier().empty() &&
2442 !Ty->isForwardDecl();
2454 auto I = CompleteTypeIndices.find(Ty);
2455 if (
I != CompleteTypeIndices.end() &&
I->second == TypeIndex())
2457 return getCompleteTypeIndex(Ty);
2465 std::string FullName = getFullyQualifiedName(Ty);
2466 ClassRecord CR(Kind, 0, CO, TypeIndex(), TypeIndex(), TypeIndex(), 0,
2468 TypeIndex FwdDeclTI = TypeTable.writeLeafType(CR);
2470 DeferredCompleteTypes.push_back(Ty);
2474TypeIndex CodeViewDebug::lowerCompleteTypeClass(
const DICompositeType *Ty) {
2480 unsigned FieldCount;
2483 lowerRecordFieldList(Ty);
2486 CO |= ClassOptions::ContainsNestedClass;
2494 CO |= ClassOptions::HasConstructorOrDestructor;
2496 std::string FullName = getFullyQualifiedName(Ty);
2500 ClassRecord CR(Kind, FieldCount, CO, FieldTI, TypeIndex(), VShapeTI,
2502 TypeIndex ClassTI = TypeTable.writeLeafType(CR);
2504 addUDTSrcLine(Ty, ClassTI);
2514 return getCompleteTypeIndex(Ty);
2518 std::string FullName = getFullyQualifiedName(Ty);
2519 UnionRecord UR(0, CO, TypeIndex(), 0, FullName, Ty->
getIdentifier());
2520 TypeIndex FwdDeclTI = TypeTable.writeLeafType(UR);
2522 DeferredCompleteTypes.push_back(Ty);
2526TypeIndex CodeViewDebug::lowerCompleteTypeUnion(
const DICompositeType *Ty) {
2529 unsigned FieldCount;
2532 lowerRecordFieldList(Ty);
2535 CO |= ClassOptions::ContainsNestedClass;
2538 std::string FullName = getFullyQualifiedName(Ty);
2540 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2542 TypeIndex UnionTI = TypeTable.writeLeafType(UR);
2544 addUDTSrcLine(Ty, UnionTI);
2551std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2557 unsigned MemberCount = 0;
2558 ClassInfo
Info = collectClassInfo(Ty);
2559 ContinuationRecordBuilder ContinuationBuilder;
2560 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2563 for (
const DIDerivedType *
I :
Info.Inheritance) {
2564 if (
I->getFlags() & DINode::FlagVirtual) {
2566 unsigned VBPtrOffset =
I->getVBPtrOffset();
2568 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2569 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2570 ? TypeRecordKind::IndirectVirtualBaseClass
2571 : TypeRecordKind::VirtualBaseClass;
2572 VirtualBaseClassRecord VBCR(
2574 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2580 assert(
I->getOffsetInBits() % 8 == 0 &&
2581 "bases must be on byte boundaries");
2583 getTypeIndex(
I->getBaseType()),
2584 I->getOffsetInBits() / 8);
2591 for (ClassInfo::MemberInfo &MemberInfo :
Info.Members) {
2593 TypeIndex MemberBaseType = getTypeIndex(
Member->getBaseType());
2594 StringRef MemberName =
Member->getName();
2598 if (
Member->isStaticMember()) {
2599 StaticDataMemberRecord SDMR(
Access, MemberBaseType, MemberName);
2606 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2607 Member->getName().starts_with(
"_vptr$")) {
2608 VFPtrRecord VFPR(getTypeIndex(
Member->getBaseType()));
2617 if (
Member->isBitField()) {
2618 uint64_t StartBitOffset = MemberOffsetInBits;
2619 if (
const auto *CI =
2621 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2623 StartBitOffset -= MemberOffsetInBits;
2624 BitFieldRecord BFR(MemberBaseType,
Member->getSizeInBits(),
2626 MemberBaseType = TypeTable.writeLeafType(BFR);
2628 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2629 DataMemberRecord DMR(
Access, MemberBaseType, MemberOffsetInBytes,
2636 for (
auto &MethodItr :
Info.Methods) {
2637 StringRef
Name = MethodItr.first->getString();
2639 std::vector<OneMethodRecord> Methods;
2640 for (
const DISubprogram *SP : MethodItr.second) {
2641 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2642 bool Introduced =
SP->getFlags() & DINode::FlagIntroducedVirtual;
2644 unsigned VFTableOffset = -1;
2646 VFTableOffset =
SP->getVirtualIndex() * getPointerSizeInBytes();
2648 Methods.push_back(OneMethodRecord(
2654 assert(!Methods.empty() &&
"Empty methods map entry");
2655 if (Methods.size() == 1)
2660 MethodOverloadListRecord MOLR(Methods);
2661 TypeIndex MethodList = TypeTable.writeLeafType(MOLR);
2663 OverloadedMethodRecord OMR(Methods.size(), MethodList, Name);
2669 for (
const DIType *
Nested :
Info.NestedTypes) {
2670 NestedTypeRecord
R(getTypeIndex(
Nested),
Nested->getName());
2675 TypeIndex FieldTI = TypeTable.insertRecord(ContinuationBuilder);
2676 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2677 !
Info.NestedTypes.empty());
2680TypeIndex CodeViewDebug::getVBPTypeIndex() {
2681 if (!VBPType.getIndex()) {
2684 TypeIndex ModifiedTI = TypeTable.writeLeafType(MR);
2686 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2687 : PointerKind::Near32;
2690 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2691 VBPType = TypeTable.writeLeafType(PR);
2697TypeIndex CodeViewDebug::getTypeIndex(
const DIType *Ty,
const DIType *ClassTy) {
2705 auto I = TypeIndices.find({Ty, ClassTy});
2706 if (
I != TypeIndices.end())
2710 TypeIndex TI = lowerType(Ty, ClassTy);
2711 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2715CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2717 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2718 "this type must be a pointer type");
2721 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2722 Options = PointerOptions::LValueRefThisPointer;
2723 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2724 Options = PointerOptions::RValueRefThisPointer;
2731 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2732 if (
I != TypeIndices.end())
2736 TypeIndex TI = lowerTypePointer(PtrTy,
Options);
2737 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2740TypeIndex CodeViewDebug::getCompleteTypeIndex(
const DIType *Ty) {
2748 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2749 (void)getTypeIndex(Ty);
2750 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2756 case dwarf::DW_TAG_class_type:
2757 case dwarf::DW_TAG_structure_type:
2758 case dwarf::DW_TAG_union_type:
2761 return getTypeIndex(Ty);
2772 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2773 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2778 if (CTy->isForwardDecl())
2785 auto InsertResult = CompleteTypeIndices.try_emplace(CTy);
2786 if (!InsertResult.second)
2787 return InsertResult.first->second;
2790 switch (CTy->getTag()) {
2791 case dwarf::DW_TAG_class_type:
2792 case dwarf::DW_TAG_structure_type:
2793 TI = lowerCompleteTypeClass(CTy);
2795 case dwarf::DW_TAG_union_type:
2796 TI = lowerCompleteTypeUnion(CTy);
2806 CompleteTypeIndices[CTy] = TI;
2814void CodeViewDebug::emitDeferredCompleteTypes() {
2816 while (!DeferredCompleteTypes.empty()) {
2817 std::swap(DeferredCompleteTypes, TypesToEmit);
2818 for (
const DICompositeType *RecordTy : TypesToEmit)
2819 getCompleteTypeIndex(RecordTy);
2820 TypesToEmit.clear();
2824void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2828 for (
const LocalVariable &L : Locals)
2829 if (
L.DIVar->isParameter())
2831 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2832 return L->DIVar->getArg() <
R->DIVar->getArg();
2834 for (
const LocalVariable *L : Params)
2835 emitLocalVariable(FI, *L);
2838 for (
const LocalVariable &L : Locals) {
2839 if (!
L.DIVar->isParameter()) {
2840 if (
L.ConstantValue) {
2843 const DIType *Ty =
L.DIVar->getType();
2845 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2847 emitLocalVariable(FI, L);
2853void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2854 const LocalVariable &Var) {
2856 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2859 if (Var.DIVar->isParameter())
2860 Flags |= LocalSymFlags::IsParameter;
2861 if (Var.DefRanges.empty())
2862 Flags |= LocalSymFlags::IsOptimizedOut;
2864 OS.AddComment(
"TypeIndex");
2865 TypeIndex TI = getCompleteTypeIndex(Var.DIVar->getType());
2867 OS.AddComment(
"Flags");
2868 OS.emitInt16(
static_cast<uint16_t
>(Flags));
2871 endSymbolRecord(LocalEnd);
2876 SmallString<20> BytePrefix;
2877 for (
const auto &Pair : Var.DefRanges) {
2879 const auto &
Ranges = Pair.second;
2881 if (DefRange.InMemory) {
2882 int Offset = DefRange.DataOffset;
2883 unsigned Reg = DefRange.CVRegister;
2889 Reg = unsigned(RegisterId::VFRAME);
2890 Offset += FI.OffsetAdjustment;
2896 uint16_t RegRelFlags = 0;
2897 if (DefRange.IsSubfield) {
2899 (DefRange.StructOffset
2902 DefRangeRegisterRelIndirHeader DRHdr;
2904 DRHdr.
Flags = RegRelFlags;
2907 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2908 }
else if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2909 (
bool(Flags & LocalSymFlags::IsParameter)
2910 ? (EncFP == FI.EncodedParamFramePtrReg)
2911 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2915 DefRangeFramePointerRelHeader DRHdr;
2917 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2919 uint16_t RegRelFlags = 0;
2920 if (DefRange.IsSubfield) {
2922 (DefRange.StructOffset
2925 DefRangeRegisterRelHeader DRHdr;
2927 DRHdr.
Flags = RegRelFlags;
2929 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2932 assert(DefRange.DataOffset == 0 &&
2934 "unexpected offset into register");
2935 if (DefRange.IsSubfield) {
2936 DefRangeSubfieldRegisterHeader DRHdr;
2937 DRHdr.
Register = DefRange.CVRegister;
2940 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2942 DefRangeRegisterHeader DRHdr;
2943 DRHdr.
Register = DefRange.CVRegister;
2945 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2952 const FunctionInfo& FI) {
2953 for (LexicalBlock *
Block : Blocks)
2954 emitLexicalBlock(*
Block, FI);
2959void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2960 const FunctionInfo& FI) {
2961 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2962 OS.AddComment(
"PtrParent");
2964 OS.AddComment(
"PtrEnd");
2966 OS.AddComment(
"Code size");
2967 OS.emitAbsoluteSymbolDiff(
Block.End,
Block.Begin, 4);
2968 OS.AddComment(
"Function section relative address");
2969 OS.emitCOFFSecRel32(
Block.Begin, 0);
2970 OS.AddComment(
"Function section index");
2971 OS.emitCOFFSectionIndex(FI.Begin);
2972 OS.AddComment(
"Lexical block name");
2974 endSymbolRecord(RecordEnd);
2977 emitLocalVariableList(FI,
Block.Locals);
2978 emitGlobalVariableList(
Block.Globals);
2981 emitLexicalBlockList(
Block.Children, FI);
2984 emitEndSymbolRecord(SymbolKind::S_END);
2989void CodeViewDebug::collectLexicalBlockInfo(
2994 for (LexicalScope *Scope : Scopes)
2995 collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
3000void CodeViewDebug::collectLexicalBlockInfo(
3005 if (
Scope.isAbstractScope())
3010 bool IgnoreScope =
false;
3011 auto LI = ScopeVariables.find(&Scope);
3012 SmallVectorImpl<LocalVariable> *
Locals =
3013 LI != ScopeVariables.end() ? &LI->second :
nullptr;
3014 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
3015 SmallVectorImpl<CVGlobalVariable> *Globals =
3016 GI != ScopeGlobals.
end() ? GI->second.get() :
nullptr;
3018 const SmallVectorImpl<InsnRange> &
Ranges =
Scope.getRanges();
3021 if (!Locals && !Globals)
3051 collectLexicalBlockInfo(
Scope.getChildren(),
3061 auto BlockInsertion = CurFn->LexicalBlocks.try_emplace(DILB);
3062 if (!BlockInsertion.second)
3069 LexicalBlock &
Block = BlockInsertion.first->second;
3072 assert(
Block.Begin &&
"missing label for scope begin");
3073 assert(
Block.End &&
"missing label for scope end");
3076 Block.Locals = std::move(*Locals);
3078 Block.Globals = std::move(*Globals);
3080 collectLexicalBlockInfo(
Scope.getChildren(),
3088 assert(FnDebugInfo.count(&GV));
3089 assert(CurFn == FnDebugInfo[&GV].
get());
3095 collectLexicalBlockInfo(*CFS,
3103 ScopeVariables.clear();
3107 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3108 FnDebugInfo.erase(&GV);
3114 for (
const auto &
MBB : *MF) {
3115 for (
const auto &
MI :
MBB) {
3116 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3124 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
3126 collectDebugInfoForJumpTables(MF,
isThumb);
3130 CurFn->End =
Asm->getFunctionEnd();
3147 if (
DL.getLine() != 0)
3150 return Scope->getSubprogram()->isArtificial();
3158 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3166 for (
const auto &NextMI : *
MI->getParent()) {
3167 if (NextMI.isDebugInstr())
3169 DL = NextMI.getDebugLoc();
3182 maybeRecordLocation(
DL,
Asm->MF);
3195void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3202 MCSymbol *BeginLabel =
MMI->getContext().createTempSymbol(),
3203 *EndLabel =
MMI->getContext().createTempSymbol();
3204 OS.AddComment(
"Record length");
3205 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
3206 OS.emitLabel(BeginLabel);
3207 if (OS.isVerboseAsm())
3209 OS.emitInt16(
unsigned(SymKind));
3213void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3218 OS.emitValueToAlignment(
Align(4));
3219 OS.emitLabel(SymEnd);
3222void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3223 OS.AddComment(
"Record length");
3225 if (OS.isVerboseAsm())
3227 OS.emitInt16(uint16_t(EndKind));
3230void CodeViewDebug::emitDebugInfoForUDTs(
3231 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3233 size_t OriginalSize = UDTs.size();
3235 for (
const auto &UDT : UDTs) {
3236 const DIType *
T =
UDT.second;
3238 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3239 OS.AddComment(
"Type");
3240 OS.emitInt32(getCompleteTypeIndex(
T).getIndex());
3241 assert(OriginalSize == UDTs.size() &&
3242 "getCompleteTypeIndex found new UDTs!");
3244 endSymbolRecord(UDTRecordEnd);
3248void CodeViewDebug::collectGlobalOrStaticLocalVariableInfo(
3250 const DIGlobalVariable *DIGV = GVE->
getVariable();
3260 (DIE->
getElement(0) == dwarf::DW_OP_plus_uconst))
3265 CVGlobalVariableOffsets.insert(std::make_pair(DIGV, DIE->
getElement(1)));
3268 if (!GlobalMap.count(GVE) && DIE->
isConstant())
3269 GlobalVariables.emplace_back(CVGlobalVariable{DIGV, DIE});
3271 const auto *GV = GlobalMap.lookup(GVE);
3276 SmallVector<CVGlobalVariable, 1> *VariableList;
3281 ScopeGlobals.insert({
Scope, std::unique_ptr<GlobalVariableList>()});
3282 if (Insertion.second)
3283 Insertion.first->second = std::make_unique<GlobalVariableList>();
3284 VariableList = Insertion.first->second.get();
3287 VariableList = &ComdatVariables;
3290 VariableList = &GlobalVariables;
3292 VariableList->
emplace_back(CVGlobalVariable{DIGV, GV});
3295void CodeViewDebug::collectGlobalVariableInfo() {
3296 for (
const GlobalVariable &GV :
MMI->getModule()->globals()) {
3298 GV.getDebugInfo(GVEs);
3299 for (
const auto *GVE : GVEs)
3300 GlobalMap[GVE] = &GV;
3303 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3304 for (
const MDNode *Node : CUs->
operands()) {
3306 for (
const auto *GVE : CU->getGlobalVariables()) {
3307 collectGlobalOrStaticLocalVariableInfo(GVE);
3312void CodeViewDebug::collectDebugInfoForGlobals() {
3313 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3314 const DIGlobalVariable *DIGV = CVGV.DIGV;
3316 getCompleteTypeIndex(DIGV->
getType());
3317 getFullyQualifiedName(Scope, DIGV->
getName());
3320 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3321 const DIGlobalVariable *DIGV = CVGV.DIGV;
3323 getCompleteTypeIndex(DIGV->
getType());
3324 getFullyQualifiedName(Scope, DIGV->
getName());
3328void CodeViewDebug::emitDebugInfoForGlobals() {
3332 switchToDebugSectionForSymbol(
nullptr);
3333 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3334 OS.AddComment(
"Symbol subsection for globals");
3335 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3336 emitGlobalVariableList(GlobalVariables);
3337 emitStaticConstMemberList();
3338 endCVSubsection(EndLabel);
3343 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3346 OS.AddComment(
"Symbol subsection for " +
3348 switchToDebugSectionForSymbol(GVSym);
3349 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3351 emitDebugInfoForGlobal(CVGV);
3352 endCVSubsection(EndLabel);
3356void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3357 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3358 for (
const MDNode *Node : CUs->
operands()) {
3370 for (
const CVGlobalVariable &CVGV : Globals) {
3372 emitDebugInfoForGlobal(CVGV);
3377 const std::string &QualifiedName) {
3378 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3379 OS.AddComment(
"Type");
3380 OS.emitInt32(getTypeIndex(DTy).getIndex());
3382 OS.AddComment(
"Value");
3387 CodeViewRecordIO IO(Writer);
3389 StringRef SRef((
char *)
Data, Writer.getOffset());
3390 OS.emitBinaryData(SRef);
3392 OS.AddComment(
"Name");
3394 endSymbolRecord(SConstantEnd);
3397void CodeViewDebug::emitStaticConstMemberList() {
3398 for (
const DIDerivedType *DTy : StaticConstMembers) {
3402 if (
const ConstantInt *CI =
3406 else if (
const ConstantFP *CFP =
3408 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3412 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3413 getFullyQualifiedName(Scope, DTy->
getName()));
3423 if (
T == dwarf::DW_TAG_pointer_type ||
3424 T == dwarf::DW_TAG_ptr_to_member_type ||
3425 T == dwarf::DW_TAG_reference_type ||
3426 T == dwarf::DW_TAG_rvalue_reference_type)
3428 assert(DTy->getBaseType() &&
"Expected valid base type");
3433 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3436void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3437 const DIGlobalVariable *DIGV = CVGV.DIGV;
3443 Scope = MemberDecl->getScope();
3449 ? std::string(DIGV->
getName())
3452 if (
const GlobalVariable *GV =
3456 MCSymbol *GVSym = Asm->getSymbol(GV);
3457 SymbolKind DataSym = GV->isThreadLocal()
3458 ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32
3459 : SymbolKind::S_GTHREAD32)
3460 : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32
3461 : SymbolKind::S_GDATA32);
3462 MCSymbol *DataEnd = beginSymbolRecord(DataSym);
3463 OS.AddComment(
"Type");
3464 OS.emitInt32(getCompleteTypeIndex(DIGV->getType()).getIndex());
3465 OS.AddComment(
"DataOffset");
3468 uint64_t Offset = CVGlobalVariableOffsets.lookup(DIGV);
3469 OS.emitCOFFSecRel32(GVSym, Offset);
3471 OS.AddComment(
"Segment");
3472 OS.emitCOFFSectionIndex(GVSym);
3473 OS.AddComment(
"Name");
3474 const unsigned LengthOfDataRecord = 12;
3475 emitNullTerminatedSymbolName(OS, QualifiedName, LengthOfDataRecord);
3476 endSymbolRecord(DataEnd);
3478 const DIExpression *DIE = cast<const DIExpression *>(CVGV.GVInfo);
3479 assert(DIE->isConstant() &&
3480 "Global constant variables must contain a constant expression.");
3483 bool isUnsigned = isFloatDIType(DIGV->getType())
3485 : DebugHandlerBase::isUnsignedDIType(DIGV->getType());
3486 APSInt Value(APInt(64, DIE->getElement(1)), isUnsigned);
3487 emitConstantSymbolRecord(DIGV->getType(), Value, QualifiedName);
3494 int64_t)> &Callback) {
3496 if (JTI && !JTI->isEmpty()) {
3500 for (
const auto &
MBB : *MF) {
3502 const auto LastMI =
MBB.getFirstTerminator();
3503 if (LastMI !=
MBB.end() && LastMI->isIndirectBranch()) {
3511 for (
const auto &MO : LastMI->operands()) {
3513 unsigned Index = MO.getIndex();
3517 Callback(*JTI, *LastMI, Index);
3525 for (
auto I =
MBB.instr_rbegin(),
E =
MBB.instr_rend();
I !=
E; ++
I) {
3526 if (
I->isJumpTableDebugInfo()) {
3527 unsigned Index =
I->getOperand(0).getImm();
3531 Callback(*JTI, *LastMI, Index);
3540 "Some of jump tables were not used in a debug info instruction");
3545void CodeViewDebug::discoverJumpTableBranches(
const MachineFunction *MF,
3549 [
this](
const MachineJumpTableInfo &,
const MachineInstr &BranchMI,
3553void CodeViewDebug::collectDebugInfoForJumpTables(
const MachineFunction *MF,
3557 [
this, MF](
const MachineJumpTableInfo &JTI,
const MachineInstr &BranchMI,
3558 int64_t JumpTableIndex) {
3571 "EK_Custom32, EK_GPRel32BlockAddress, and "
3572 "EK_GPRel64BlockAddress should never be emitted for COFF");
3575 EntrySize = JumpTableEntrySize::Pointer;
3582 std::tie(
Base, BaseOffset, Branch, EntrySize) =
3583 Asm->getCodeViewJumpTableInfo(JumpTableIndex, &BranchMI, Branch);
3587 const MachineJumpTableEntry &JTE = JTI.
getJumpTables()[JumpTableIndex];
3588 JumpTableInfo CVJTI{EntrySize,
3595 for (
const auto &
MBB : JTE.
MBBs)
3597 CurFn->JumpTables.push_back(std::move(CVJTI));
3601void CodeViewDebug::emitDebugInfoForJumpTables(
const FunctionInfo &FI) {
3603 for (
const auto &JumpTable : FI.JumpTables) {
3604 for (
const auto &CaseSym :
JumpTable.Cases) {
3605 MCSymbol *LabelEnd = beginSymbolRecord(SymbolKind::S_LABEL32);
3606 OS.AddComment(
"Offset and segment");
3607 OS.emitCOFFSecRel32(CaseSym, 0);
3608 OS.AddComment(
"Flags");
3611 endSymbolRecord(LabelEnd);
3615 for (
const auto &JumpTable : FI.JumpTables) {
3616 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3618 OS.AddComment(
"Base offset");
3620 OS.AddComment(
"Base section index");
3621 OS.emitCOFFSectionIndex(
JumpTable.Base);
3623 OS.AddComment(
"Base offset");
3625 OS.AddComment(
"Base section index");
3628 OS.AddComment(
"Switch type");
3629 OS.emitInt16(
static_cast<uint16_t
>(
JumpTable.EntrySize));
3630 OS.AddComment(
"Branch offset");
3631 OS.emitCOFFSecRel32(
JumpTable.Branch, 0);
3632 OS.AddComment(
"Table offset");
3633 OS.emitCOFFSecRel32(
JumpTable.Table, 0);
3634 OS.AddComment(
"Branch section index");
3635 OS.emitCOFFSectionIndex(
JumpTable.Branch);
3636 OS.AddComment(
"Table section index");
3637 OS.emitCOFFSectionIndex(
JumpTable.Table);
3638 OS.AddComment(
"Entries count");
3640 endSymbolRecord(JumpTableEnd);
3644void CodeViewDebug::emitInlinees(
3648 constexpr size_t ChunkSize =
3655 size_t CurrentIndex = 0;
3656 while (CurrentIndex < SortedInlinees.
size()) {
3657 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3658 auto CurrentChunkSize =
3659 std::min(ChunkSize, SortedInlinees.
size() - CurrentIndex);
3660 OS.AddComment(
"Count");
3661 OS.emitInt32(CurrentChunkSize);
3663 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3664 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3665 OS.AddComment(
"Inlinee");
3666 OS.emitInt32(SortedInlinees[CurrentIndex].getIndex());
3668 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 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
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.