33#include "llvm/Config/llvm-config.h"
80 CVMCAdapter(MCStreamer &OS, TypeCollection &TypeTable)
81 : OS(&OS), TypeTable(TypeTable) {}
83 void emitBytes(StringRef
Data)
override { OS->emitBytes(
Data); }
85 void emitIntValue(uint64_t
Value,
unsigned Size)
override {
89 void emitBinaryData(StringRef
Data)
override { OS->emitBinaryData(
Data); }
91 void AddComment(
const Twine &
T)
override { OS->AddComment(
T); }
93 void AddRawComment(
const Twine &
T)
override { OS->emitRawComment(
T); }
95 bool isVerboseAsm()
override {
return OS->isVerboseAsm(); }
103 TypeName = std::string(TypeTable.getTypeName(TI));
109 MCStreamer *OS =
nullptr;
110 TypeCollection &TypeTable;
139 std::string &Filepath = FileToFilepathMap[File];
140 if (!Filepath.empty())
143 StringRef Dir = File->getDirectory(), Filename = File->getFilename();
147 if (Dir.
starts_with(
"/") || Filename.starts_with(
"/")) {
150 Filepath = std::string(Dir);
151 if (Dir.
back() !=
'/')
153 Filepath += Filename;
161 if (Filename.find(
':') == 1)
162 Filepath = std::string(Filename);
164 Filepath = (Dir +
"\\" + Filename).str();
173 while ((Cursor = Filepath.find(
"\\.\\", Cursor)) != std::string::npos)
174 Filepath.erase(Cursor, 2);
179 while ((Cursor = Filepath.find(
"\\..\\", Cursor)) != std::string::npos) {
184 size_t PrevSlash = Filepath.rfind(
'\\', Cursor - 1);
185 if (PrevSlash == std::string::npos)
189 Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
196 while ((Cursor = Filepath.find(
"\\\\", Cursor)) != std::string::npos)
197 Filepath.erase(Cursor, 1);
202unsigned CodeViewDebug::maybeRecordFile(
const DIFile *
F) {
203 StringRef FullPath = getFullFilepath(
F);
204 unsigned NextId = FileIdMap.size() + 1;
205 auto Insertion = FileIdMap.insert(std::make_pair(FullPath, NextId));
206 if (Insertion.second) {
208 ArrayRef<uint8_t> ChecksumAsBytes;
210 if (
F->getChecksum()) {
211 std::string Checksum =
fromHex(
F->getChecksum()->Value);
212 void *CKMem = OS.getContext().allocate(Checksum.size(), 1);
213 memcpy(CKMem, Checksum.data(), Checksum.size());
214 ChecksumAsBytes = ArrayRef<uint8_t>(
215 reinterpret_cast<const uint8_t *
>(CKMem), Checksum.size());
216 switch (
F->getChecksum()->Kind) {
218 CSKind = FileChecksumKind::MD5;
221 CSKind = FileChecksumKind::SHA1;
224 CSKind = FileChecksumKind::SHA256;
228 bool Success = OS.emitCVFileDirective(NextId, FullPath, ChecksumAsBytes,
229 static_cast<unsigned>(CSKind));
233 return Insertion.first->second;
236CodeViewDebug::InlineSite &
237CodeViewDebug::getInlineSite(
const DILocation *InlinedAt,
239 auto SiteInsertion = CurFn->InlineSites.try_emplace(InlinedAt);
240 InlineSite *Site = &SiteInsertion.first->second;
241 if (SiteInsertion.second) {
242 unsigned ParentFuncId = CurFn->FuncId;
243 if (
const DILocation *OuterIA = InlinedAt->getInlinedAt())
245 getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())
248 Site->SiteFuncId = NextFuncId++;
249 OS.emitCVInlineSiteIdDirective(
250 Site->SiteFuncId, ParentFuncId, maybeRecordFile(InlinedAt->getFile()),
251 InlinedAt->getLine(), InlinedAt->getColumn(), SMLoc());
253 InlinedSubprograms.insert(Inlinee);
254 auto InlineeIdx = getFuncIdForSubprogram(Inlinee);
256 if (InlinedAt->getInlinedAt() ==
nullptr)
257 CurFn->Inlinees.insert(InlineeIdx);
264 if (!ScopeName.
empty())
267 switch (Scope->getTag()) {
268 case dwarf::DW_TAG_enumeration_type:
269 case dwarf::DW_TAG_class_type:
270 case dwarf::DW_TAG_structure_type:
271 case dwarf::DW_TAG_union_type:
272 return "<unnamed-tag>";
273 case dwarf::DW_TAG_namespace:
274 return "`anonymous namespace'";
280const DISubprogram *CodeViewDebug::collectParentScopeNames(
282 const DISubprogram *ClosestSubprogram =
nullptr;
283 while (Scope !=
nullptr) {
284 if (ClosestSubprogram ==
nullptr)
291 DeferredCompleteTypes.push_back(Ty);
294 if (!ScopeName.
empty())
295 QualifiedNameComponents.
push_back(ScopeName);
298 return ClosestSubprogram;
303 std::string FullyQualifiedName;
306 FullyQualifiedName.append(std::string(QualifiedNameComponent));
307 FullyQualifiedName.append(
"::");
309 FullyQualifiedName.append(std::string(TypeName));
310 return FullyQualifiedName;
318 if (
CVD.TypeEmissionLevel == 1)
319 CVD.emitDeferredCompleteTypes();
320 --
CVD.TypeEmissionLevel;
325std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Scope,
332 collectParentScopeNames(Scope, QualifiedNameComponents);
336std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Ty) {
358 auto I = TypeIndices.find({Scope,
nullptr});
359 if (
I != TypeIndices.end())
363 std::string ScopeName = getFullyQualifiedName(Scope);
364 StringIdRecord SID(TypeIndex(), ScopeName);
365 auto TI = TypeTable.writeLeafType(SID);
366 return recordTypeIndexForDINode(Scope, TI);
372 if (Name.empty() || Name.back() !=
'>')
375 int OpenBrackets = 0;
376 for (
int i = Name.size() - 1; i >= 0; --i) {
379 else if (Name[i] ==
'<') {
381 if (OpenBrackets == 0)
382 return Name.substr(0, i);
388TypeIndex CodeViewDebug::getFuncIdForSubprogram(
const DISubprogram *SP) {
392 auto I = TypeIndices.find({
SP,
nullptr});
393 if (
I != TypeIndices.end())
401 const DIScope *
Scope =
SP->getScope();
407 TypeIndex ClassType = getTypeIndex(Class);
408 MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class),
410 TI = TypeTable.writeLeafType(MFuncId);
413 TypeIndex ParentScope = getScopeIndex(Scope);
414 FuncIdRecord FuncId(ParentScope, getTypeIndex(
SP->getType()), DisplayName);
415 TI = TypeTable.writeLeafType(FuncId);
418 return recordTypeIndexForDINode(SP, TI);
422 return ((DCTy->
getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);
430 const DIType *ReturnTy =
nullptr;
431 if (
auto TypeArray = Ty->getTypeArray()) {
432 if (TypeArray.size())
433 ReturnTy = TypeArray[0];
443 if (ClassTy &&
isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {
452TypeIndex CodeViewDebug::getMemberFunctionType(
const DISubprogram *SP,
456 if (
SP->getDeclaration())
457 SP =
SP->getDeclaration();
458 assert(!
SP->getDeclaration() &&
"should use declaration as key");
462 auto I = TypeIndices.find({
SP,
Class});
463 if (
I != TypeIndices.end())
470 const bool IsStaticMethod = (
SP->getFlags() & DINode::FlagStaticMember) != 0;
473 TypeIndex TI = lowerTypeMemberFunction(
474 SP->getType(), Class,
SP->getThisAdjustment(), IsStaticMethod, FO);
475 return recordTypeIndexForDINode(SP, TI, Class);
478TypeIndex CodeViewDebug::recordTypeIndexForDINode(
const DINode *Node,
481 auto InsertResult = TypeIndices.insert({{
Node, ClassTy}, TI});
483 assert(InsertResult.second &&
"DINode was already assigned a type index");
487unsigned CodeViewDebug::getPointerSizeInBytes() {
488 return MMI->getModule()->getDataLayout().getPointerSizeInBits() / 8;
491void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
493 if (
const DILocation *InlinedAt =
LS->getInlinedAt()) {
495 const DISubprogram *
Inlinee = Var.DIVar->getScope()->getSubprogram();
496 InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
497 Site.InlinedLocals.emplace_back(std::move(Var));
500 ScopeVariables[
LS].emplace_back(std::move(Var));
510void CodeViewDebug::maybeRecordLocation(
const DebugLoc &
DL,
516 const DIScope *
Scope =
DL->getScope();
521 LineInfo LI(
DL.getLine(),
DL.getLine(),
true);
522 if (LI.getStartLine() !=
DL.getLine() || LI.isAlwaysStepInto() ||
523 LI.isNeverStepInto())
526 ColumnInfo CI(
DL.getCol(), 0);
527 if (CI.getStartColumn() !=
DL.getCol())
530 if (!CurFn->HaveLineInfo)
531 CurFn->HaveLineInfo =
true;
534 FileId = CurFn->LastFileId;
536 FileId = CurFn->LastFileId = maybeRecordFile(
DL->getFile());
539 unsigned FuncId = CurFn->FuncId;
540 if (
const DILocation *SiteLoc =
DL->getInlinedAt()) {
541 const DILocation *Loc =
DL.get();
546 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
549 bool FirstLoc =
true;
550 while ((SiteLoc = Loc->getInlinedAt())) {
552 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
561 OS.emitCVLocDirective(FuncId, FileId,
DL.getLine(),
DL.getCol(),
563 DL->getFilename(), SMLoc());
566void CodeViewDebug::emitCodeViewMagicVersion() {
567 OS.emitValueToAlignment(
Align(4));
568 OS.AddComment(
"Debug section magic");
575 case dwarf::DW_LNAME_C:
576 return SourceLanguage::C;
577 case dwarf::DW_LNAME_C_plus_plus:
578 return SourceLanguage::Cpp;
579 case dwarf::DW_LNAME_Fortran:
580 return SourceLanguage::Fortran;
581 case dwarf::DW_LNAME_Pascal:
582 return SourceLanguage::Pascal;
583 case dwarf::DW_LNAME_Cobol:
584 return SourceLanguage::Cobol;
585 case dwarf::DW_LNAME_Java:
586 return SourceLanguage::Java;
587 case dwarf::DW_LNAME_D:
588 return SourceLanguage::D;
589 case dwarf::DW_LNAME_Swift:
590 return SourceLanguage::Swift;
591 case dwarf::DW_LNAME_Rust:
592 return SourceLanguage::Rust;
593 case dwarf::DW_LNAME_ObjC:
594 return SourceLanguage::ObjC;
595 case dwarf::DW_LNAME_ObjC_plus_plus:
596 return SourceLanguage::ObjCpp;
601 return SourceLanguage::Masm;
615 if (!
Asm->getObjFileLowering().getCOFFDebugSymbolsSection()) {
620 CompilerInfoAsm =
Asm;
625 if (
Asm->hasDebugInfo()) {
626 Node = *M->debug_compile_units_begin();
630 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
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();
767 CVType Record = Table.getType(*
B);
776 B = Table.getNext(*
B);
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);
896 ArchType Arch =
MMI->getModule()->getTargetTriple().getArch();
897 if (CompilerInfoAsm->TM.Options.Hotpatch || Arch == ArchType::thumb ||
898 Arch == ArchType::aarch64) {
899 Flags |=
static_cast<uint32_t
>(CompileSym3Flags::HotPatch);
902 OS.AddComment(
"Flags and language");
905 OS.AddComment(
"CPUType");
906 OS.emitInt16(
static_cast<uint64_t
>(TheCPU));
908 StringRef CompilerVersion =
"0";
910 CompilerVersion = TheCU->getProducer();
913 OS.AddComment(
"Frontend version");
914 for (
int N : FrontVer.Part) {
921 int Major = 1000 * LLVM_VERSION_MAJOR +
922 10 * LLVM_VERSION_MINOR +
925 Major = std::min<int>(Major, std::numeric_limits<uint16_t>::max());
926 Version BackVer = {{ Major, 0, 0, 0 }};
927 OS.AddComment(
"Backend version");
928 for (
int N : BackVer.Part)
931 OS.AddComment(
"Null-terminated compiler version string");
934 endSymbolRecord(CompilerEnd);
943void CodeViewDebug::emitBuildInfo() {
955 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
958 const DIFile *MainSourceFile = CU->getFile();
969 TypeTable,
Asm->TM.Options.MCOptions.CommandlineArgs);
971 BuildInfoRecord BIR(BuildInfoArgs);
972 TypeIndex BuildInfoIndex = TypeTable.writeLeafType(BIR);
976 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
977 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
978 OS.AddComment(
"LF_BUILDINFO index");
979 OS.emitInt32(BuildInfoIndex.
getIndex());
980 endSymbolRecord(BIEnd);
981 endCVSubsection(BISubsecEnd);
984void CodeViewDebug::emitInlineeLinesSubsection() {
985 if (InlinedSubprograms.empty())
988 OS.AddComment(
"Inlinee lines subsection");
989 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
995 OS.AddComment(
"Inlinee lines signature");
996 OS.emitInt32(
unsigned(InlineeLinesSignature::Normal));
998 for (
const DISubprogram *SP : InlinedSubprograms) {
999 assert(TypeIndices.count({SP, nullptr}));
1000 TypeIndex InlineeIdx = TypeIndices[{
SP,
nullptr}];
1003 unsigned FileId = maybeRecordFile(
SP->getFile());
1004 OS.AddComment(
"Inlined function " +
SP->getName() +
" starts at " +
1005 SP->getFilename() + Twine(
':') + Twine(
SP->getLine()));
1007 OS.AddComment(
"Type index of inlined function");
1008 OS.emitInt32(InlineeIdx.
getIndex());
1009 OS.AddComment(
"Offset into filechecksum table");
1010 OS.emitCVFileChecksumOffsetDirective(FileId);
1011 OS.AddComment(
"Starting line number");
1012 OS.emitInt32(
SP->getLine());
1015 endCVSubsection(InlineEnd);
1018void CodeViewDebug::emitInlinedCallSite(
const FunctionInfo &FI,
1021 assert(TypeIndices.count({Site.Inlinee, nullptr}));
1022 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee,
nullptr}];
1025 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
1027 OS.AddComment(
"PtrParent");
1029 OS.AddComment(
"PtrEnd");
1031 OS.AddComment(
"Inlinee type index");
1032 OS.emitInt32(InlineeIdx.
getIndex());
1034 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
1035 unsigned StartLineNum = Site.Inlinee->getLine();
1037 OS.emitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum,
1040 endSymbolRecord(InlineEnd);
1042 emitLocalVariableList(FI, Site.InlinedLocals);
1045 for (
const DILocation *ChildSite : Site.ChildSites) {
1046 auto I = FI.InlineSites.find(ChildSite);
1047 assert(
I != FI.InlineSites.end() &&
1048 "child site not in function inline site map");
1049 emitInlinedCallSite(FI, ChildSite,
I->second);
1053 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1056void CodeViewDebug::switchToDebugSectionForSymbol(
const MCSymbol *GVSym) {
1060 MCSectionCOFF *GVSec =
1061 GVSym ?
static_cast<MCSectionCOFF *
>(&GVSym->
getSection()) : nullptr;
1064 auto *DebugSec =
static_cast<MCSectionCOFF *
>(
1065 CompilerInfoAsm->getObjFileLowering().getCOFFDebugSymbolsSection());
1066 DebugSec = OS.getContext().getAssociativeCOFFSection(DebugSec, KeySym);
1068 OS.switchSection(DebugSec);
1072 if (ComdatDebugSections.insert(DebugSec).second)
1073 emitCodeViewMagicVersion();
1078void CodeViewDebug::emitDebugInfoForThunk(
const Function *GV,
1081 std::string FuncName =
1085 OS.AddComment(
"Symbol subsection for " + Twine(FuncName));
1086 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1089 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1090 OS.AddComment(
"PtrParent");
1092 OS.AddComment(
"PtrEnd");
1094 OS.AddComment(
"PtrNext");
1096 OS.AddComment(
"Thunk section relative address");
1097 OS.emitCOFFSecRel32(Fn, 0);
1098 OS.AddComment(
"Thunk section index");
1099 OS.emitCOFFSectionIndex(Fn);
1100 OS.AddComment(
"Code size");
1101 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 2);
1102 OS.AddComment(
"Ordinal");
1103 OS.emitInt8(
unsigned(ordinal));
1104 OS.AddComment(
"Function name");
1107 endSymbolRecord(ThunkRecordEnd);
1113 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1115 endCVSubsection(SymbolsEnd);
1118void CodeViewDebug::emitDebugInfoForFunction(
const Function *GV,
1126 switchToDebugSectionForSymbol(Fn);
1128 std::string FuncName;
1131 setCurrentSubprogram(SP);
1133 if (
SP->isThunk()) {
1134 emitDebugInfoForThunk(GV, FI, Fn);
1140 if (!
SP->getName().empty())
1141 FuncName = getFullyQualifiedName(
SP->getScope(),
SP->getName());
1144 if (FuncName.empty())
1148 if (
MMI->getModule()->getTargetTriple().getArch() ==
Triple::x86)
1149 OS.emitCVFPOData(Fn);
1152 OS.AddComment(
"Symbol subsection for " + Twine(FuncName));
1153 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1156 : SymbolKind::S_GPROC32_ID;
1157 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1160 OS.AddComment(
"PtrParent");
1162 OS.AddComment(
"PtrEnd");
1164 OS.AddComment(
"PtrNext");
1168 OS.AddComment(
"Code size");
1169 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 4);
1170 OS.AddComment(
"Offset after prologue");
1172 OS.AddComment(
"Offset before epilogue");
1174 OS.AddComment(
"Function type index");
1175 OS.emitInt32(getFuncIdForSubprogram(GV->
getSubprogram()).getIndex());
1176 OS.AddComment(
"Function section relative address");
1177 OS.emitCOFFSecRel32(Fn, 0);
1178 OS.AddComment(
"Function section index");
1179 OS.emitCOFFSectionIndex(Fn);
1180 OS.AddComment(
"Flags");
1181 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;
1182 if (FI.HasFramePointer)
1183 ProcFlags |= ProcSymFlags::HasFP;
1185 ProcFlags |= ProcSymFlags::IsNoReturn;
1187 ProcFlags |= ProcSymFlags::IsNoInline;
1188 OS.emitInt8(
static_cast<uint8_t
>(ProcFlags));
1190 OS.AddComment(
"Function name");
1193 endSymbolRecord(ProcRecordEnd);
1195 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1197 OS.AddComment(
"FrameSize");
1198 OS.emitInt32(FI.FrameSize - FI.CSRSize);
1199 OS.AddComment(
"Padding");
1201 OS.AddComment(
"Offset of padding");
1203 OS.AddComment(
"Bytes of callee saved registers");
1204 OS.emitInt32(FI.CSRSize);
1205 OS.AddComment(
"Exception handler offset");
1207 OS.AddComment(
"Exception handler section");
1209 OS.AddComment(
"Flags (defines frame register)");
1210 OS.emitInt32(uint32_t(FI.FrameProcOpts));
1211 endSymbolRecord(FrameProcEnd);
1213 emitInlinees(FI.Inlinees);
1214 emitLocalVariableList(FI, FI.Locals);
1215 emitGlobalVariableList(FI.Globals);
1216 emitLexicalBlockList(FI.ChildBlocks, FI);
1221 for (
const DILocation *InlinedAt : FI.ChildSites) {
1222 auto I = FI.InlineSites.find(InlinedAt);
1223 assert(
I != FI.InlineSites.end() &&
1224 "child site not in function inline site map");
1225 emitInlinedCallSite(FI, InlinedAt,
I->second);
1228 for (
auto Annot : FI.Annotations) {
1231 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1232 OS.emitCOFFSecRel32(Label, 0);
1234 OS.emitCOFFSectionIndex(Label);
1240 assert(Str.data()[Str.size()] ==
'\0' &&
"non-nullterminated MDString");
1241 OS.emitBytes(StringRef(Str.data(), Str.size() + 1));
1243 endSymbolRecord(AnnotEnd);
1246 for (
auto HeapAllocSite : FI.HeapAllocSites) {
1247 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1248 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1249 const DIType *DITy = std::get<2>(HeapAllocSite);
1250 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1251 OS.AddComment(
"Call site offset");
1252 OS.emitCOFFSecRel32(BeginLabel, 0);
1253 OS.AddComment(
"Call site section index");
1254 OS.emitCOFFSectionIndex(BeginLabel);
1255 OS.AddComment(
"Call instruction length");
1256 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
1257 OS.AddComment(
"Type index");
1258 OS.emitInt32(getCompleteTypeIndex(DITy).getIndex());
1259 endSymbolRecord(HeapAllocEnd);
1263 emitDebugInfoForUDTs(LocalUDTs);
1265 emitDebugInfoForJumpTables(FI);
1268 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1270 endCVSubsection(SymbolsEnd);
1273 OS.emitCVLinetableDirective(FI.FuncId, Fn, FI.End);
1277CodeViewDebug::createDefRangeMem(uint16_t CVRegister,
int Offset) {
1283 DR.StructOffset = 0;
1284 DR.CVRegister = CVRegister;
1288void CodeViewDebug::collectVariableInfoFromMFTable(
1290 const MachineFunction &MF = *
Asm->MF;
1295 for (
const MachineFunction::VariableDbgInfo &VI :
1299 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1300 "Expected inlined-at fields to agree");
1302 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1311 int64_t ExprOffset = 0;
1315 if (
VI.Expr->getNumElements() == 1 &&
1316 VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)
1318 else if (!
VI.Expr->extractIfOffset(ExprOffset))
1324 StackOffset FrameOffset =
1326 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1335 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset);
1343 End = End ? End :
Asm->getFunctionEnd();
1344 Var.DefRanges[DefRange].emplace_back(Begin, End);
1348 Var.UseReferenceType =
true;
1350 recordLocalVariable(std::move(Var), Scope);
1355 return !
Loc.LoadChain.empty() &&
Loc.LoadChain.back() == 0;
1359 return Loc.LoadChain.size() == 2 &&
Loc.LoadChain.back() == 0;
1362void CodeViewDebug::calculateRanges(
1364 const TargetRegisterInfo *
TRI =
Asm->MF->getSubtarget().getRegisterInfo();
1367 for (
auto I = Entries.
begin(),
E = Entries.
end();
I !=
E; ++
I) {
1369 if (!
Entry.isDbgValue())
1371 const MachineInstr *DVInst =
Entry.getInstr();
1375 std::optional<DbgVariableLocation>
Location =
1386 Var.ConstantValue =
APSInt(APInt(64,
Op.getImm()),
false);
1397 if (Var.UseReferenceType) {
1406 Var.UseReferenceType =
true;
1407 Var.DefRanges.clear();
1408 calculateRanges(Var, Entries);
1419 if (
Location->FragmentInfo->OffsetInBits % 8)
1429 DR.InMemory = !
Location->LoadChain.empty();
1433 DR.IsSubfield =
true;
1434 DR.StructOffset =
Location->FragmentInfo->OffsetInBits / 8;
1436 DR.IsSubfield =
false;
1437 DR.StructOffset = 0;
1444 auto &EndingEntry = Entries[
Entry.getEndIndex()];
1445 End = EndingEntry.isDbgValue()
1449 End =
Asm->getFunctionEnd();
1453 SmallVectorImpl<std::pair<const MCSymbol *, const MCSymbol *>> &
R =
1455 if (!
R.empty() &&
R.back().second == Begin)
1456 R.back().second = End;
1458 R.emplace_back(Begin, End);
1464void CodeViewDebug::collectVariableInfo(
const DISubprogram *SP) {
1465 DenseSet<InlinedEntity> Processed;
1467 collectVariableInfoFromMFTable(Processed);
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;
1794 uint64_t ArraySize =
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 TypeRecordKind::Class;
2220 case dwarf::DW_TAG_structure_type:
2221 return 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);
2300 EnumeratorRecord ER(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();
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);
2525 UnionRecord UR(0, CO, TypeIndex(), 0, FullName, Ty->
getIdentifier());
2526 TypeIndex FwdDeclTI = TypeTable.writeLeafType(UR);
2528 DeferredCompleteTypes.push_back(Ty);
2532TypeIndex CodeViewDebug::lowerCompleteTypeUnion(
const DICompositeType *Ty) {
2535 unsigned FieldCount;
2538 lowerRecordFieldList(Ty);
2541 CO |= ClassOptions::ContainsNestedClass;
2544 std::string FullName = getFullyQualifiedName(Ty);
2546 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2548 TypeIndex UnionTI = TypeTable.writeLeafType(UR);
2550 addUDTSrcLine(Ty, UnionTI);
2557std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2563 unsigned MemberCount = 0;
2564 ClassInfo
Info = collectClassInfo(Ty);
2565 ContinuationRecordBuilder ContinuationBuilder;
2566 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2569 for (
const DIDerivedType *
I :
Info.Inheritance) {
2570 if (
I->getFlags() & DINode::FlagVirtual) {
2572 unsigned VBPtrOffset =
I->getVBPtrOffset();
2574 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2575 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2576 ? TypeRecordKind::IndirectVirtualBaseClass
2577 : TypeRecordKind::VirtualBaseClass;
2578 VirtualBaseClassRecord VBCR(
2580 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2586 assert(
I->getOffsetInBits() % 8 == 0 &&
2587 "bases must be on byte boundaries");
2589 getTypeIndex(
I->getBaseType()),
2590 I->getOffsetInBits() / 8);
2597 for (ClassInfo::MemberInfo &MemberInfo :
Info.Members) {
2599 TypeIndex MemberBaseType = getTypeIndex(
Member->getBaseType());
2600 StringRef MemberName =
Member->getName();
2604 if (
Member->isStaticMember()) {
2605 StaticDataMemberRecord SDMR(
Access, MemberBaseType, MemberName);
2612 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2613 Member->getName().starts_with(
"_vptr$")) {
2614 VFPtrRecord VFPR(getTypeIndex(
Member->getBaseType()));
2621 uint64_t MemberOffsetInBits =
2623 if (
Member->isBitField()) {
2624 uint64_t StartBitOffset = MemberOffsetInBits;
2625 if (
const auto *CI =
2627 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2629 StartBitOffset -= MemberOffsetInBits;
2630 BitFieldRecord BFR(MemberBaseType,
Member->getSizeInBits(),
2632 MemberBaseType = TypeTable.writeLeafType(BFR);
2634 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2635 DataMemberRecord DMR(
Access, MemberBaseType, MemberOffsetInBytes,
2642 for (
auto &MethodItr :
Info.Methods) {
2643 StringRef
Name = MethodItr.first->getString();
2645 std::vector<OneMethodRecord> Methods;
2646 for (
const DISubprogram *SP : MethodItr.second) {
2647 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2648 bool Introduced =
SP->getFlags() & DINode::FlagIntroducedVirtual;
2650 unsigned VFTableOffset = -1;
2652 VFTableOffset =
SP->getVirtualIndex() * getPointerSizeInBytes();
2654 Methods.push_back(OneMethodRecord(
2660 assert(!Methods.empty() &&
"Empty methods map entry");
2661 if (Methods.size() == 1)
2666 MethodOverloadListRecord MOLR(Methods);
2667 TypeIndex MethodList = TypeTable.writeLeafType(MOLR);
2669 OverloadedMethodRecord OMR(Methods.size(), MethodList, Name);
2675 for (
const DIType *
Nested :
Info.NestedTypes) {
2676 NestedTypeRecord
R(getTypeIndex(
Nested),
Nested->getName());
2681 TypeIndex FieldTI = TypeTable.insertRecord(ContinuationBuilder);
2682 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2683 !
Info.NestedTypes.empty());
2686TypeIndex CodeViewDebug::getVBPTypeIndex() {
2687 if (!VBPType.getIndex()) {
2690 TypeIndex ModifiedTI = TypeTable.writeLeafType(MR);
2692 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2693 : PointerKind::Near32;
2696 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2697 VBPType = TypeTable.writeLeafType(PR);
2703TypeIndex CodeViewDebug::getTypeIndex(
const DIType *Ty,
const DIType *ClassTy) {
2711 auto I = TypeIndices.find({Ty, ClassTy});
2712 if (
I != TypeIndices.end())
2716 TypeIndex TI = lowerType(Ty, ClassTy);
2717 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2721CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2723 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2724 "this type must be a pointer type");
2727 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2728 Options = PointerOptions::LValueRefThisPointer;
2729 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2730 Options = PointerOptions::RValueRefThisPointer;
2737 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2738 if (
I != TypeIndices.end())
2742 TypeIndex TI = lowerTypePointer(PtrTy,
Options);
2743 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2746TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(
const DIType *Ty) {
2747 PointerRecord PR(getTypeIndex(Ty),
2748 getPointerSizeInBytes() == 8 ? PointerKind::Near64
2749 : PointerKind::Near32,
2750 PointerMode::LValueReference, PointerOptions::None,
2752 return TypeTable.writeLeafType(PR);
2755TypeIndex CodeViewDebug::getCompleteTypeIndex(
const DIType *Ty) {
2763 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2764 (void)getTypeIndex(Ty);
2765 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2771 case dwarf::DW_TAG_class_type:
2772 case dwarf::DW_TAG_structure_type:
2773 case dwarf::DW_TAG_union_type:
2776 return getTypeIndex(Ty);
2787 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2788 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2793 if (CTy->isForwardDecl())
2800 auto InsertResult = CompleteTypeIndices.try_emplace(CTy);
2801 if (!InsertResult.second)
2802 return InsertResult.first->second;
2805 switch (CTy->getTag()) {
2806 case dwarf::DW_TAG_class_type:
2807 case dwarf::DW_TAG_structure_type:
2808 TI = lowerCompleteTypeClass(CTy);
2810 case dwarf::DW_TAG_union_type:
2811 TI = lowerCompleteTypeUnion(CTy);
2821 CompleteTypeIndices[CTy] = TI;
2829void CodeViewDebug::emitDeferredCompleteTypes() {
2831 while (!DeferredCompleteTypes.empty()) {
2832 std::swap(DeferredCompleteTypes, TypesToEmit);
2833 for (
const DICompositeType *RecordTy : TypesToEmit)
2834 getCompleteTypeIndex(RecordTy);
2835 TypesToEmit.clear();
2839void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2843 for (
const LocalVariable &L : Locals)
2844 if (
L.DIVar->isParameter())
2846 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2847 return L->DIVar->getArg() <
R->DIVar->getArg();
2849 for (
const LocalVariable *L : Params)
2850 emitLocalVariable(FI, *L);
2853 for (
const LocalVariable &L : Locals) {
2854 if (!
L.DIVar->isParameter()) {
2855 if (
L.ConstantValue) {
2858 const DIType *Ty =
L.DIVar->getType();
2860 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2862 emitLocalVariable(FI, L);
2868void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2869 const LocalVariable &Var) {
2871 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2874 if (Var.DIVar->isParameter())
2875 Flags |= LocalSymFlags::IsParameter;
2876 if (Var.DefRanges.empty())
2877 Flags |= LocalSymFlags::IsOptimizedOut;
2879 OS.AddComment(
"TypeIndex");
2880 TypeIndex TI = Var.UseReferenceType
2881 ? getTypeIndexForReferenceTo(Var.DIVar->getType())
2882 : getCompleteTypeIndex(Var.DIVar->
getType());
2884 OS.AddComment(
"Flags");
2885 OS.emitInt16(
static_cast<uint16_t
>(Flags));
2888 endSymbolRecord(LocalEnd);
2893 SmallString<20> BytePrefix;
2894 for (
const auto &Pair : Var.DefRanges) {
2895 LocalVarDef DefRange = Pair.first;
2896 const auto &Ranges = Pair.second;
2898 if (DefRange.InMemory) {
2899 int Offset = DefRange.DataOffset;
2900 unsigned Reg = DefRange.CVRegister;
2905 if (RegisterId(Reg) == RegisterId::ESP) {
2906 Reg = unsigned(RegisterId::VFRAME);
2907 Offset += FI.OffsetAdjustment;
2913 EncodedFramePtrReg EncFP = encodeFramePtrReg(RegisterId(Reg), TheCPU);
2914 if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2915 (bool(Flags & LocalSymFlags::IsParameter)
2916 ? (EncFP == FI.EncodedParamFramePtrReg)
2917 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2918 DefRangeFramePointerRelHeader DRHdr;
2919 DRHdr.Offset = Offset;
2920 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2922 uint16_t RegRelFlags = 0;
2923 if (DefRange.IsSubfield) {
2924 RegRelFlags = DefRangeRegisterRelSym::IsSubfieldFlag |
2925 (DefRange.StructOffset
2926 << DefRangeRegisterRelSym::OffsetInParentShift);
2928 DefRangeRegisterRelHeader DRHdr;
2929 DRHdr.Register = Reg;
2930 DRHdr.Flags = RegRelFlags;
2931 DRHdr.BasePointerOffset = Offset;
2932 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2935 assert(DefRange.DataOffset == 0 &&
"unexpected offset into register");
2936 if (DefRange.IsSubfield) {
2937 DefRangeSubfieldRegisterHeader DRHdr;
2938 DRHdr.Register = DefRange.CVRegister;
2939 DRHdr.MayHaveNoName = 0;
2940 DRHdr.OffsetInParent = DefRange.StructOffset;
2941 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2943 DefRangeRegisterHeader DRHdr;
2944 DRHdr.Register = DefRange.CVRegister;
2945 DRHdr.MayHaveNoName = 0;
2946 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2953 const FunctionInfo& FI) {
2954 for (LexicalBlock *
Block : Blocks)
2955 emitLexicalBlock(*
Block, FI);
2960void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2961 const FunctionInfo& FI) {
2962 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2963 OS.AddComment(
"PtrParent");
2965 OS.AddComment(
"PtrEnd");
2967 OS.AddComment(
"Code size");
2968 OS.emitAbsoluteSymbolDiff(
Block.End,
Block.Begin, 4);
2969 OS.AddComment(
"Function section relative address");
2970 OS.emitCOFFSecRel32(
Block.Begin, 0);
2971 OS.AddComment(
"Function section index");
2972 OS.emitCOFFSectionIndex(FI.Begin);
2973 OS.AddComment(
"Lexical block name");
2975 endSymbolRecord(RecordEnd);
2978 emitLocalVariableList(FI,
Block.Locals);
2979 emitGlobalVariableList(
Block.Globals);
2982 emitLexicalBlockList(
Block.Children, FI);
2985 emitEndSymbolRecord(SymbolKind::S_END);
2990void CodeViewDebug::collectLexicalBlockInfo(
2995 for (LexicalScope *Scope : Scopes)
2996 collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
3001void CodeViewDebug::collectLexicalBlockInfo(
3006 if (
Scope.isAbstractScope())
3011 bool IgnoreScope =
false;
3012 auto LI = ScopeVariables.find(&Scope);
3013 SmallVectorImpl<LocalVariable> *
Locals =
3014 LI != ScopeVariables.end() ? &LI->second :
nullptr;
3015 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
3016 SmallVectorImpl<CVGlobalVariable> *Globals =
3017 GI != ScopeGlobals.
end() ? GI->second.get() :
nullptr;
3019 const SmallVectorImpl<InsnRange> &
Ranges =
Scope.getRanges();
3022 if (!Locals && !Globals)
3052 collectLexicalBlockInfo(
Scope.getChildren(),
3062 auto BlockInsertion = CurFn->LexicalBlocks.try_emplace(DILB);
3063 if (!BlockInsertion.second)
3070 LexicalBlock &
Block = BlockInsertion.first->second;
3073 assert(
Block.Begin &&
"missing label for scope begin");
3074 assert(
Block.End &&
"missing label for scope end");
3077 Block.Locals = std::move(*Locals);
3079 Block.Globals = std::move(*Globals);
3081 collectLexicalBlockInfo(
Scope.getChildren(),
3089 assert(FnDebugInfo.count(&GV));
3090 assert(CurFn == FnDebugInfo[&GV].
get());
3096 collectLexicalBlockInfo(*CFS,
3104 ScopeVariables.clear();
3108 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3109 FnDebugInfo.erase(&GV);
3115 for (
const auto &
MBB : *MF) {
3116 for (
const auto &
MI :
MBB) {
3117 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3125 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
3127 collectDebugInfoForJumpTables(MF,
isThumb);
3131 CurFn->End =
Asm->getFunctionEnd();
3141 return DL &&
DL.getLine() != 0;
3148 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3156 for (
const auto &NextMI : *
MI->getParent()) {
3157 if (NextMI.isDebugInstr())
3159 DL = NextMI.getDebugLoc();
3172 maybeRecordLocation(
DL,
Asm->MF);
3185void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3193 if (EE.Value == SymKind)
3199 MCSymbol *BeginLabel =
MMI->getContext().createTempSymbol(),
3200 *EndLabel =
MMI->getContext().createTempSymbol();
3201 OS.AddComment(
"Record length");
3202 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
3203 OS.emitLabel(BeginLabel);
3204 if (OS.isVerboseAsm())
3206 OS.emitInt16(
unsigned(SymKind));
3210void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3215 OS.emitValueToAlignment(
Align(4));
3216 OS.emitLabel(SymEnd);
3219void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3220 OS.AddComment(
"Record length");
3222 if (OS.isVerboseAsm())
3224 OS.emitInt16(uint16_t(EndKind));
3227void CodeViewDebug::emitDebugInfoForUDTs(
3228 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3230 size_t OriginalSize = UDTs.size();
3232 for (
const auto &UDT : UDTs) {
3233 const DIType *
T =
UDT.second;
3235 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3236 OS.AddComment(
"Type");
3237 OS.emitInt32(getCompleteTypeIndex(
T).getIndex());
3238 assert(OriginalSize == UDTs.size() &&
3239 "getCompleteTypeIndex found new UDTs!");
3241 endSymbolRecord(UDTRecordEnd);
3245void CodeViewDebug::collectGlobalVariableInfo() {
3246 DenseMap<const DIGlobalVariableExpression *, const GlobalVariable *>
3248 for (
const GlobalVariable &GV :
MMI->getModule()->globals()) {
3250 GV.getDebugInfo(GVEs);
3251 for (
const auto *GVE : GVEs)
3252 GlobalMap[GVE] = &GV;
3255 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3256 for (
const MDNode *Node : CUs->
operands()) {
3258 for (
const auto *GVE : CU->getGlobalVariables()) {
3259 const DIGlobalVariable *DIGV = GVE->getVariable();
3260 const DIExpression *DIE = GVE->getExpression();
3268 (DIE->
getElement(0) == dwarf::DW_OP_plus_uconst))
3273 CVGlobalVariableOffsets.insert(
3278 CVGlobalVariable CVGV = {DIGV, DIE};
3279 GlobalVariables.emplace_back(std::move(CVGV));
3282 const auto *GV = GlobalMap.
lookup(GVE);
3287 SmallVector<CVGlobalVariable, 1> *VariableList;
3291 auto Insertion = ScopeGlobals.insert(
3292 {
Scope, std::unique_ptr<GlobalVariableList>()});
3293 if (Insertion.second)
3294 Insertion.first->second = std::make_unique<GlobalVariableList>();
3295 VariableList = Insertion.first->second.get();
3298 VariableList = &ComdatVariables;
3301 VariableList = &GlobalVariables;
3302 CVGlobalVariable CVGV = {DIGV, GV};
3308void CodeViewDebug::collectDebugInfoForGlobals() {
3309 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3310 const DIGlobalVariable *DIGV = CVGV.DIGV;
3312 getCompleteTypeIndex(DIGV->
getType());
3313 getFullyQualifiedName(Scope, DIGV->
getName());
3316 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3317 const DIGlobalVariable *DIGV = CVGV.DIGV;
3319 getCompleteTypeIndex(DIGV->
getType());
3320 getFullyQualifiedName(Scope, DIGV->
getName());
3324void CodeViewDebug::emitDebugInfoForGlobals() {
3328 switchToDebugSectionForSymbol(
nullptr);
3329 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3330 OS.AddComment(
"Symbol subsection for globals");
3331 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3332 emitGlobalVariableList(GlobalVariables);
3333 emitStaticConstMemberList();
3334 endCVSubsection(EndLabel);
3339 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3342 OS.AddComment(
"Symbol subsection for " +
3344 switchToDebugSectionForSymbol(GVSym);
3345 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3347 emitDebugInfoForGlobal(CVGV);
3348 endCVSubsection(EndLabel);
3352void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3353 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3354 for (
const MDNode *Node : CUs->
operands()) {
3366 for (
const CVGlobalVariable &CVGV : Globals) {
3368 emitDebugInfoForGlobal(CVGV);
3373 const std::string &QualifiedName) {
3374 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3375 OS.AddComment(
"Type");
3376 OS.emitInt32(getTypeIndex(DTy).getIndex());
3378 OS.AddComment(
"Value");
3383 CodeViewRecordIO IO(Writer);
3385 StringRef SRef((
char *)
Data, Writer.getOffset());
3386 OS.emitBinaryData(SRef);
3388 OS.AddComment(
"Name");
3390 endSymbolRecord(SConstantEnd);
3393void CodeViewDebug::emitStaticConstMemberList() {
3394 for (
const DIDerivedType *DTy : StaticConstMembers) {
3398 if (
const ConstantInt *CI =
3402 else if (
const ConstantFP *CFP =
3404 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3408 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3409 getFullyQualifiedName(Scope, DTy->
getName()));
3419 if (
T == dwarf::DW_TAG_pointer_type ||
3420 T == dwarf::DW_TAG_ptr_to_member_type ||
3421 T == dwarf::DW_TAG_reference_type ||
3422 T == dwarf::DW_TAG_rvalue_reference_type)
3424 assert(DTy->getBaseType() &&
"Expected valid base type");
3429 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3432void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3433 const DIGlobalVariable *DIGV = CVGV.DIGV;
3439 Scope = MemberDecl->getScope();
3445 ? std::string(DIGV->
getName())
3448 if (
const GlobalVariable *GV =
3452 MCSymbol *GVSym = Asm->getSymbol(GV);
3453 SymbolKind DataSym = GV->isThreadLocal()
3454 ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32
3455 : SymbolKind::S_GTHREAD32)
3456 : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32
3457 : SymbolKind::S_GDATA32);
3458 MCSymbol *DataEnd = beginSymbolRecord(DataSym);
3459 OS.AddComment(
"Type");
3460 OS.emitInt32(getCompleteTypeIndex(DIGV->getType()).getIndex());
3461 OS.AddComment(
"DataOffset");
3464 uint64_t Offset = CVGlobalVariableOffsets.lookup(DIGV);
3465 OS.emitCOFFSecRel32(GVSym, Offset);
3467 OS.AddComment(
"Segment");
3468 OS.emitCOFFSectionIndex(GVSym);
3469 OS.AddComment(
"Name");
3470 const unsigned LengthOfDataRecord = 12;
3471 emitNullTerminatedSymbolName(OS, QualifiedName, LengthOfDataRecord);
3472 endSymbolRecord(DataEnd);
3474 const DIExpression *DIE = cast<const DIExpression *>(CVGV.GVInfo);
3475 assert(DIE->isConstant() &&
3476 "Global constant variables must contain a constant expression.");
3479 bool isUnsigned = isFloatDIType(DIGV->getType())
3481 : DebugHandlerBase::isUnsignedDIType(DIGV->getType());
3482 APSInt Value(APInt(64, DIE->getElement(1)), isUnsigned);
3483 emitConstantSymbolRecord(DIGV->getType(), Value, QualifiedName);
3490 int64_t)> &Callback) {
3492 if (JTI && !JTI->isEmpty()) {
3496 for (
const auto &
MBB : *MF) {
3498 const auto LastMI =
MBB.getFirstTerminator();
3499 if (LastMI !=
MBB.end() && LastMI->isIndirectBranch()) {
3507 for (
const auto &MO : LastMI->operands()) {
3509 unsigned Index = MO.getIndex();
3513 Callback(*JTI, *LastMI, Index);
3521 for (
auto I =
MBB.instr_rbegin(),
E =
MBB.instr_rend();
I !=
E; ++
I) {
3522 if (
I->isJumpTableDebugInfo()) {
3523 unsigned Index =
I->getOperand(0).getImm();
3527 Callback(*JTI, *LastMI, Index);
3536 "Some of jump tables were not used in a debug info instruction");
3541void CodeViewDebug::discoverJumpTableBranches(
const MachineFunction *MF,
3545 [
this](
const MachineJumpTableInfo &,
const MachineInstr &BranchMI,
3549void CodeViewDebug::collectDebugInfoForJumpTables(
const MachineFunction *MF,
3553 [
this, MF](
const MachineJumpTableInfo &JTI,
const MachineInstr &BranchMI,
3554 int64_t JumpTableIndex) {
3559 uint64_t BaseOffset = 0;
3567 "EK_Custom32, EK_GPRel32BlockAddress, and "
3568 "EK_GPRel64BlockAddress should never be emitted for COFF");
3571 EntrySize = JumpTableEntrySize::Pointer;
3578 std::tie(
Base, BaseOffset, Branch, EntrySize) =
3579 Asm->getCodeViewJumpTableInfo(JumpTableIndex, &BranchMI, Branch);
3583 const MachineJumpTableEntry &JTE = JTI.
getJumpTables()[JumpTableIndex];
3584 JumpTableInfo CVJTI{EntrySize,
3591 for (
const auto &
MBB : JTE.
MBBs)
3593 CurFn->JumpTables.push_back(std::move(CVJTI));
3597void CodeViewDebug::emitDebugInfoForJumpTables(
const FunctionInfo &FI) {
3599 for (
const auto &JumpTable : FI.JumpTables) {
3600 for (
const auto &CaseSym :
JumpTable.Cases) {
3601 MCSymbol *LabelEnd = beginSymbolRecord(SymbolKind::S_LABEL32);
3602 OS.AddComment(
"Offset and segment");
3603 OS.emitCOFFSecRel32(CaseSym, 0);
3604 OS.AddComment(
"Flags");
3607 endSymbolRecord(LabelEnd);
3611 for (
const auto &JumpTable : FI.JumpTables) {
3612 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3614 OS.AddComment(
"Base offset");
3616 OS.AddComment(
"Base section index");
3617 OS.emitCOFFSectionIndex(
JumpTable.Base);
3619 OS.AddComment(
"Base offset");
3621 OS.AddComment(
"Base section index");
3624 OS.AddComment(
"Switch type");
3625 OS.emitInt16(
static_cast<uint16_t
>(
JumpTable.EntrySize));
3626 OS.AddComment(
"Branch offset");
3627 OS.emitCOFFSecRel32(
JumpTable.Branch, 0);
3628 OS.AddComment(
"Table offset");
3629 OS.emitCOFFSecRel32(
JumpTable.Table, 0);
3630 OS.AddComment(
"Branch section index");
3631 OS.emitCOFFSectionIndex(
JumpTable.Branch);
3632 OS.AddComment(
"Table section index");
3633 OS.emitCOFFSectionIndex(
JumpTable.Table);
3634 OS.AddComment(
"Entries count");
3636 endSymbolRecord(JumpTableEnd);
3640void CodeViewDebug::emitInlinees(
3644 constexpr size_t ChunkSize =
3651 size_t CurrentIndex = 0;
3652 while (CurrentIndex < SortedInlinees.
size()) {
3653 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3654 auto CurrentChunkSize =
3655 std::min(ChunkSize, SortedInlinees.
size() - CurrentIndex);
3656 OS.AddComment(
"Count");
3657 OS.emitInt32(CurrentChunkSize);
3659 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3660 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3661 OS.AddComment(
"Inlinee");
3662 OS.emitInt32(SortedInlinees[CurrentIndex].getIndex());
3664 endSymbolRecord(Symbol);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
static bool isThumb(const MCSubtargetInfo &STI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
static bool canUseReferenceType(const DbgVariableLocation &Loc)
static MethodKind translateMethodKindFlags(const DISubprogram *SP, bool Introduced)
static bool isUsableDebugLoc(DebugLoc DL)
static TypeIndex getStringIdTypeIdx(GlobalTypeTableBuilder &TypeTable, StringRef S)
static CPUType mapArchToCVCPUType(Triple::ArchType Type)
static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S, unsigned MaxFixedRecordLength=0xF00)
static Version parseVersion(StringRef Name)
static MethodOptions translateMethodOptionFlags(const DISubprogram *SP)
static bool isNonTrivial(const DICompositeType *DCTy)
static std::string formatNestedName(ArrayRef< StringRef > QualifiedNameComponents, StringRef TypeName)
static ClassOptions getCommonClassOptions(const DICompositeType *Ty)
Return ClassOptions that should be present on both the forward declaration and the defintion of a tag...
static PointerToMemberRepresentation translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags)
static FunctionOptions getFunctionOptions(const DISubroutineType *Ty, const DICompositeType *ClassTy=nullptr, StringRef SPName=StringRef(""))
static StringRef removeTemplateArgs(StringRef Name)
static TypeRecordKind getRecordKind(const DICompositeType *Ty)
void forEachJumpTableBranch(const MachineFunction *MF, bool isThumb, const std::function< void(const MachineJumpTableInfo &, const MachineInstr &, int64_t)> &Callback)
static CallingConvention dwarfCCToCodeView(unsigned DwarfCC)
Given a DWARF calling convention, get the CodeView equivalent.
static SourceLanguage MapDWARFLanguageToCVLang(dwarf::SourceLanguageName DWLName)
static bool isFloatDIType(const DIType *Ty)
static void addLocIfNotPresent(SmallVectorImpl< const DILocation * > &Locs, const DILocation *Loc)
static bool shouldEmitUdt(const DIType *T)
static StringRef getPrettyScopeName(const DIScope *Scope)
static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty)
static bool needsReferenceType(const DbgVariableLocation &Loc)
static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file contains constants used for implementing Dwarf debug support.
Module.h This file contains the declarations for the Module class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static StringRef getName(Value *V)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
This file implements the SmallBitVector class.
This file defines the SmallString class.
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
static const uint32_t IV[8]
An arbitrary precision integer that knows its signedness.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
This class is intended to be used as a driving class for all asm writers.
CodeViewDebug(AsmPrinter *AP)
void beginModule(Module *M) override
bool moduleIsInFortran()
Check if the current module is in Fortran.
void endFunctionImpl(const MachineFunction *) override
Gather post-function debug information.
void endModule() override
Emit the COFF section that holds the line table information.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
void beginFunctionImpl(const MachineFunction *MF) override
Gather pre-function debug information.
This is the shared class of boolean and integer constants.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Basic type, like 'int' or 'float'.
unsigned getEncoding() const
StringRef getIdentifier() const
DINodeArray getElements() const
DIType * getBaseType() const
LLVM_ABI DIType * getClassType() const
Get casted version of extra data.
LLVM_ABI Constant * getConstant() const
unsigned getNumElements() const
uint64_t getElement(unsigned I) const
LLVM_ABI std::optional< SignedOrUnsignedConstant > isConstant() const
Determine whether this represents a constant value, if so.
Metadata * getRawStaticDataMemberDeclaration() const
DILocalScope * getScope() const
Get the local scope for this variable.
Tagged DWARF-like metadata node.
LLVM_ABI dwarf::Tag getTag() const
Base class for scope-like contexts.
StringRef getFilename() const
LLVM_ABI StringRef getName() const
StringRef getDirectory() const
LLVM_ABI DIScope * getScope() const
Wrapper structure that holds a language name and its version.
bool hasVersionedName() const
uint16_t getName() const
Returns a versioned or unversioned language name.
String type, Fortran CHARACTER(n)
Subprogram description. Uses SubclassData1.
Type array for a subprogram.
DITypeRefArray getTypeArray() const
uint64_t getOffsetInBits() const
bool isObjectPointer() const
StringRef getName() const
bool isForwardDecl() const
uint64_t getSizeInBits() const
DIScope * getScope() const
DIScope * getScope() const
StringRef getName() const
SmallVector< Entry, 4 > Entries
static const EntryIndex NoEntry
Special value to indicate that an entry is valid until the end of the function.
static bool isUnsignedDIType(const DIType *Ty)
Return true if type encoding is unsigned.
AsmPrinter * Asm
Target of debug info emission.
MCSymbol * getLabelBeforeInsn(const MachineInstr *MI)
Return Label preceding the instruction.
MachineModuleInfo * MMI
Collected machine module information.
DebugLoc PrevInstLoc
Previous instruction's location information.
MCSymbol * getLabelAfterInsn(const MachineInstr *MI)
Return Label immediately following the instruction.
DebugHandlerBase(AsmPrinter *A)
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
const MachineBasicBlock * PrevInstBB
void requestLabelAfterInsn(const MachineInstr *MI)
Ensure that a label will be emitted after MI.
DbgValueHistoryMap DbgValues
History of DBG_VALUE and clobber instructions for each user variable.
void requestLabelBeforeInsn(const MachineInstr *MI)
Ensure that a label will be emitted before MI.
const MachineInstr * PrologEndLoc
This location indicates end of function prologue and beginning of function body.
static uint64_t getBaseTypeSize(const DIType *Ty)
If this type is derived from a base type then return base type size.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Implements a dense probed hash-table based set.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool hasStackProtectorFnAttr() const
Returns true if the function has ssp, sspstrong, or sspreq fn attrs.
DISubprogram * getSubprogram() const
Get the attached subprogram.
bool hasPersonalityFn() const
Check whether this function has a personality function.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
bool hasProfileData(bool IncludeSynthetic=false) const
Return true if the function is annotated with profile data.
bool hasOptNone() const
Do not optimize this function (-O0).
Function::iterator insert(Function::iterator Position, BasicBlock *BB)
Insert BB in the basic block list at Position.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool hasLocalLinkage() const
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
bool isDeclarationForLinker() const
This class is used to track scope information.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSymbol * getCOMDATSymbol() const
Streaming machine code generation interface.
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size)
Emit the absolute difference between two symbols.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitValueToAlignment(Align Alignment, int64_t Fill=0, uint8_t FillLen=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
void emitInt32(uint64_t Value)
virtual void emitBytes(StringRef Data)
Emit the bytes in Data into the output.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
ArrayRef< MDOperand > operands() const
unsigned getNumOperands() const
Return number of MDNode operands.
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
int64_t getOffsetAdjustment() const
Return the correction for frame offsets.
unsigned getCVBytesOfCalleeSavedRegisters() const
Returns how many bytes of callee-saved registers the target pushed in the prologue.
bool hasStackProtectorIndex() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool hasInlineAsm() const
Returns true if the function contains any inline assembly.
bool exposesReturnsTwice() const
exposesReturnsTwice - Returns true if the function calls setjmp or any other similar functions with a...
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCSymbol * getJTISymbol(unsigned JTI, MCContext &Ctx, bool isLinkerPrivate=false) const
getJTISymbol - Return the MCSymbol for the specified non-empty jump table.
auto getInStackSlotVariableDbgInfo()
Returns the collection of variables for which we have debug info and that have been assigned a stack ...
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
ArrayRef< std::pair< MCSymbol *, MDNode * > > getCodeViewAnnotations() const
Representation of each machine instruction.
bool isDebugValue() const
MachineOperand & getDebugOperand(unsigned Index)
@ EK_GPRel32BlockAddress
EK_GPRel32BlockAddress - Each entry is an address of block, encoded with a relocation as gp-relative,...
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
@ EK_LabelDifference32
EK_LabelDifference32 - Each entry is the address of the block minus the address of the jump table.
@ EK_Custom32
EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the TargetLowering::LowerCustomJ...
@ EK_LabelDifference64
EK_LabelDifference64 - Each entry is the address of the block minus the address of the jump table.
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
@ EK_GPRel64BlockAddress
EK_GPRel64BlockAddress - Each entry is an address of block, encoded with a relocation as gp-relative,...
JTEntryKind getEntryKind() const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
const MCContext & getContext() const
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
iterator_range< op_iterator > operands()
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
const_iterator begin() const
const_iterator end() const
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static StackOffset getScalable(int64_t Scalable)
static StackOffset getFixed(int64_t Fixed)
StringRef - Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
char back() const
back - Get the last character in the string.
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
@ CurrentDirectory
Absolute CWD path.
@ SourceFile
Path to main source file, relative or absolute.
@ BuildTool
Absolute compiler path.
@ CommandLine
Full canonical command line (maybe -cc1)
@ TypeServerPDB
Absolute path of type server PDB (/Fd)
LLVM_ABI void begin(ContinuationRecordKind RecordKind)
void writeMemberType(RecordType &Record)
TypeIndex writeLeafType(T &Record)
SimpleTypeKind getSimpleKind() const
SimpleTypeMode getSimpleMode() const
static const uint32_t FirstNonSimpleIndex
static LLVM_ABI StringRef simpleTypeName(TypeIndex TI)
uint32_t getIndex() const
static TypeIndex NullptrT()
void addCallbackToPipeline(TypeVisitorCallbacks &Callbacks)
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
@ DEBUG_HASHES_SECTION_MAGIC
@ C
The default llvm calling convention, compatible with C.
PointerMode
Equivalent to CV_ptrmode_e.
ProcSymFlags
Corresponds to the CV_PROCFLAGS bitfield.
PointerOptions
Equivalent to misc lfPointerAttr bitfields.
LocalSymFlags
Corresponds to CV_LVARFLAGS bitfield.
MethodKind
Part of member attribute flags. (CV_methodprop_e)
CVRecord< TypeLeafKind > CVType
PointerKind
Equivalent to CV_ptrtype_e.
CPUType
These values correspond to the CV_CPU_TYPE_e enumeration, and are documented here: https://msdn....
PointerToMemberRepresentation
Equivalent to CV_pmtype_e.
@ MultipleInheritanceData
@ SingleInheritanceFunction
@ VirtualInheritanceFunction
@ MultipleInheritanceFunction
CallingConvention
These values correspond to the CV_call_e enumeration, and are documented at the following locations: ...
MethodOptions
Equivalent to CV_fldattr_t bitfield.
LLVM_ABI ArrayRef< EnumEntry< SymbolKind > > getSymbolTypeNames()
MemberAccess
Source-level access specifier. (CV_access_e)
ThunkOrdinal
These values correspond to the THUNK_ORDINAL enumeration.
TypeRecordKind
Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.
SymbolKind
Duplicate copy of the above enum, but using the official CV names.
ModifierOptions
Equivalent to CV_modifier_t.
@ ProfileGuidedOptimization
@ HasStructuredExceptionHandling
LLVM_ABI StringRef getSymbolName(CVSymbol Sym)
LLVM_ABI Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
SourceLanguage
These values correspond to the CV_CFL_LANG enumeration in the Microsoft Debug Interface Access SDK,...
std::optional< std::pair< SourceLanguageName, uint32_t > > toDW_LNAME(SourceLanguage language)
Convert a DWARF 5 DW_LANG to a DWARF 6 pair of language name and version.
ElementType
The element type of an SRV or UAV resource.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
NodeAddr< NodeBase * > Node
LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
FunctionAddr VTableAddr Value
std::string fromHex(StringRef Input)
Convert hexadecimal string Input to its binary representation. The return string is half the size of ...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
std::tuple< uint64_t, uint32_t > InlineSite
LLVM_GET_TYPE_NAME_CONSTEXPR StringRef getTypeName()
We provide a function which tries to compute the (demangled) name of a type statically.
std::pair< const MachineInstr *, const MachineInstr * > InsnRange
This is used to track range of instructions with identical lexical scope.
auto dyn_cast_or_null(const Y &Val)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
FunctionAddr VTableAddr uintptr_t uintptr_t Version
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionAddr VTableAddr Count
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Success
The lock was released successfully.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
TypeLoweringScope(CodeViewDebug &CVD)
This struct is a compact representation of a valid (non-zero power of two) alignment.
const DIDerivedType * MemberTypeNode
std::vector< MemberInfo > MemberList
MemberList Members
Direct members.
std::vector< const DIType * > NestedTypes
MapVector< MDString *, MethodsList > MethodsMap
std::vector< const DIDerivedType * > Inheritance
Base classes.
TinyPtrVector< const DISubprogram * > MethodsList
int InMemory
Indicates that variable data is stored in memory relative to the specified register.
uint32_t CVRegister
Register containing the data or the register base of the memory location containing the data.
Represents the location at which a variable is stored.
static std::optional< DbgVariableLocation > extractFromMachineInstruction(const MachineInstr &Instruction)
Extract a VariableLocation from a MachineInstr.
std::vector< MachineBasicBlock * > MBBs
MBBs - The vector of basic blocks from which to create the jump table.