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())
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();
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,
1278 int32_t DerefOffset) {
1284 DR.StructOffset = 0;
1285 DR.CVRegister = CVRegister;
1286 DR.DerefOffset = DerefOffset;
1290void CodeViewDebug::collectVariableInfoFromMFTable(
1292 const MachineFunction &MF = *
Asm->MF;
1297 for (
const MachineFunction::VariableDbgInfo &VI :
1301 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1302 "Expected inlined-at fields to agree");
1304 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1312 int64_t ExprOffset = 0;
1316 if (!
VI.Expr->extractLeadingOffset(ExprOffset, FirstRemaining))
1318 if (!FirstRemaining.
empty()) {
1319 if (FirstRemaining.
front() != dwarf::DW_OP_deref)
1321 SmallVector<uint64_t, 1> LastRemaining;
1323 ArrayRef(FirstRemaining).drop_front(), DerefOffset,
1326 if (!LastRemaining.
empty())
1333 StackOffset FrameOffset =
1335 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1341 if (DerefOffset < INT32_MIN || DerefOffset > INT32_MAX)
1346 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset,
1347 static_cast<int32_t
>(DerefOffset));
1355 End = End ? End :
Asm->getFunctionEnd();
1356 Var.DefRanges[DefRange].emplace_back(Begin, End);
1359 recordLocalVariable(std::move(Var), Scope);
1363void CodeViewDebug::calculateRanges(
1365 const TargetRegisterInfo *
TRI =
Asm->MF->getSubtarget().getRegisterInfo();
1368 for (
auto I = Entries.
begin(),
E = Entries.
end();
I !=
E; ++
I) {
1370 if (!
Entry.isDbgValue())
1372 const MachineInstr *DVInst =
Entry.getInstr();
1376 std::optional<DbgVariableLocation>
Location =
1387 Var.ConstantValue =
APSInt(APInt(64,
Op.getImm()),
false);
1399 if (
Location->FragmentInfo->OffsetInBits % 8)
1409 DR.InMemory = !
Location->LoadChain.empty();
1412 if (!
Location->LoadChain.empty()) {
1413 DR.DataOffset =
Location->LoadChain[0];
1414 if (
Location->LoadChain.size() >= 2)
1415 DR.DerefOffset =
Location->LoadChain[1];
1418 DR.IsSubfield =
true;
1419 DR.StructOffset =
Location->FragmentInfo->OffsetInBits / 8;
1421 DR.IsSubfield =
false;
1422 DR.StructOffset = 0;
1429 auto &EndingEntry = Entries[
Entry.getEndIndex()];
1430 End = EndingEntry.isDbgValue()
1434 End =
Asm->getFunctionEnd();
1438 SmallVectorImpl<std::pair<const MCSymbol *, const MCSymbol *>> &
R =
1440 if (!
R.empty() &&
R.back().second == Begin)
1441 R.back().second = End;
1443 R.emplace_back(Begin, End);
1449void CodeViewDebug::collectVariableInfo(
const DISubprogram *SP) {
1450 DenseSet<InlinedEntity> Processed;
1452 collectVariableInfoFromMFTable(Processed);
1454 for (
const MDNode *
N :
SP->getRetainedNodes())
1456 collectGlobalOrStaticLocalVariableInfo(GVE);
1459 InlinedEntity
IV =
I.first;
1463 const DILocation *InlinedAt =
IV.second;
1466 const auto &Entries =
I.second;
1468 LexicalScope *
Scope =
nullptr;
1480 calculateRanges(Var, Entries);
1481 recordLocalVariable(std::move(Var), Scope);
1490 auto Insertion = FnDebugInfo.
insert({&GV, std::make_unique<FunctionInfo>()});
1491 assert(Insertion.second &&
"function already has info");
1492 CurFn = Insertion.first->second.get();
1493 CurFn->FuncId = NextFuncId++;
1494 CurFn->Begin =
Asm->getFunctionBegin();
1502 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1508 if (CurFn->FrameSize > 0) {
1513 CurFn->HasFramePointer =
true;
1516 if (CurFn->HasStackRealignment) {
1567 CurFn->FrameProcOpts = FPO;
1569 OS.emitCVFuncIdDirective(CurFn->FuncId);
1576 bool EmptyPrologue =
true;
1577 for (
const auto &
MBB : *MF) {
1578 for (
const auto &
MI :
MBB) {
1583 }
else if (!
MI.isMetaInstruction()) {
1584 EmptyPrologue =
false;
1592 maybeRecordLocation(FnStartDL, MF);
1596 for (
const auto &
MBB : *MF) {
1597 for (
const auto &
MI :
MBB) {
1598 if (
MI.getHeapAllocMarker()) {
1606 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
1608 discoverJumpTableBranches(MF,
isThumb);
1616 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1617 if (
DIScope *Scope =
T->getScope()) {
1618 switch (Scope->getTag()) {
1619 case dwarf::DW_TAG_structure_type:
1620 case dwarf::DW_TAG_class_type:
1621 case dwarf::DW_TAG_union_type:
1631 if (!
T ||
T->isForwardDecl())
1637 T = DT->getBaseType();
1642void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1650 const DISubprogram *ClosestSubprogram =
1651 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1653 std::string FullyQualifiedName =
1656 if (ClosestSubprogram ==
nullptr) {
1657 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1658 }
else if (ClosestSubprogram == CurrentSubprogram) {
1659 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1670TypeIndex CodeViewDebug::lowerType(
const DIType *Ty,
const DIType *ClassTy) {
1673 case dwarf::DW_TAG_array_type:
1675 case dwarf::DW_TAG_typedef:
1677 case dwarf::DW_TAG_base_type:
1679 case dwarf::DW_TAG_pointer_type:
1683 case dwarf::DW_TAG_reference_type:
1684 case dwarf::DW_TAG_rvalue_reference_type:
1686 case dwarf::DW_TAG_ptr_to_member_type:
1688 case dwarf::DW_TAG_restrict_type:
1689 case dwarf::DW_TAG_const_type:
1690 case dwarf::DW_TAG_volatile_type:
1693 case dwarf::DW_TAG_subroutine_type:
1702 case dwarf::DW_TAG_enumeration_type:
1704 case dwarf::DW_TAG_class_type:
1705 case dwarf::DW_TAG_structure_type:
1707 case dwarf::DW_TAG_union_type:
1709 case dwarf::DW_TAG_string_type:
1711 case dwarf::DW_TAG_unspecified_type:
1712 if (Ty->
getName() ==
"decltype(nullptr)")
1721TypeIndex CodeViewDebug::lowerTypeAlias(
const DIDerivedType *Ty) {
1722 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1727 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) &&
1728 TypeName ==
"HRESULT")
1729 return TypeIndex(SimpleTypeKind::HResult);
1730 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::UInt16Short) &&
1731 TypeName ==
"wchar_t")
1732 return TypeIndex(SimpleTypeKind::WideCharacter);
1734 return UnderlyingTypeIndex;
1739 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1741 TypeIndex IndexType = getPointerSizeInBytes() == 8
1742 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1749 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1750 const DINode *Element =
Elements[i];
1751 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1761 Count = CI->getSExtValue();
1767 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1768 Count = UI->getSExtValue() - Lowerbound + 1;
1779 ElementSize *=
Count;
1783 uint64_t ArraySize =
1784 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1787 ArrayRecord AR(ElementTypeIndex, IndexType, ArraySize, Name);
1788 ElementTypeIndex = TypeTable.writeLeafType(AR);
1791 return ElementTypeIndex;
1799TypeIndex CodeViewDebug::lowerTypeString(
const DIStringType *Ty) {
1800 TypeIndex CharType = TypeIndex(SimpleTypeKind::NarrowCharacter);
1804 TypeIndex IndexType = getPointerSizeInBytes() == 8
1805 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1809 ArrayRecord AR(CharType, IndexType, ArraySize, Name);
1811 return TypeTable.writeLeafType(AR);
1814TypeIndex CodeViewDebug::lowerTypeBasic(
const DIBasicType *Ty) {
1824 case dwarf::DW_ATE_address:
1827 case dwarf::DW_ATE_boolean:
1829 case 1: STK = SimpleTypeKind::Boolean8;
break;
1830 case 2: STK = SimpleTypeKind::Boolean16;
break;
1831 case 4: STK = SimpleTypeKind::Boolean32;
break;
1832 case 8: STK = SimpleTypeKind::Boolean64;
break;
1833 case 16: STK = SimpleTypeKind::Boolean128;
break;
1836 case dwarf::DW_ATE_complex_float:
1840 case 4: STK = SimpleTypeKind::Complex16;
break;
1841 case 8: STK = SimpleTypeKind::Complex32;
break;
1842 case 16: STK = SimpleTypeKind::Complex64;
break;
1843 case 20: STK = SimpleTypeKind::Complex80;
break;
1844 case 32: STK = SimpleTypeKind::Complex128;
break;
1847 case dwarf::DW_ATE_float:
1849 case 2: STK = SimpleTypeKind::Float16;
break;
1850 case 4: STK = SimpleTypeKind::Float32;
break;
1851 case 6: STK = SimpleTypeKind::Float48;
break;
1852 case 8: STK = SimpleTypeKind::Float64;
break;
1853 case 10: STK = SimpleTypeKind::Float80;
break;
1854 case 16: STK = SimpleTypeKind::Float128;
break;
1857 case dwarf::DW_ATE_signed:
1859 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1860 case 2: STK = SimpleTypeKind::Int16Short;
break;
1861 case 4: STK = SimpleTypeKind::Int32;
break;
1862 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1863 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1866 case dwarf::DW_ATE_unsigned:
1868 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1869 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1870 case 4: STK = SimpleTypeKind::UInt32;
break;
1871 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1872 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1875 case dwarf::DW_ATE_UTF:
1877 case 1: STK = SimpleTypeKind::Character8;
break;
1878 case 2: STK = SimpleTypeKind::Character16;
break;
1879 case 4: STK = SimpleTypeKind::Character32;
break;
1882 case dwarf::DW_ATE_signed_char:
1884 STK = SimpleTypeKind::SignedCharacter;
1886 case dwarf::DW_ATE_unsigned_char:
1888 STK = SimpleTypeKind::UnsignedCharacter;
1898 if (STK == SimpleTypeKind::Int32 &&
1900 STK = SimpleTypeKind::Int32Long;
1901 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1902 Ty->
getName() ==
"unsigned long"))
1903 STK = SimpleTypeKind::UInt32Long;
1904 if (STK == SimpleTypeKind::UInt16Short &&
1906 STK = SimpleTypeKind::WideCharacter;
1907 if ((STK == SimpleTypeKind::SignedCharacter ||
1908 STK == SimpleTypeKind::UnsignedCharacter) &&
1910 STK = SimpleTypeKind::NarrowCharacter;
1912 return TypeIndex(STK);
1915TypeIndex CodeViewDebug::lowerTypePointer(
const DIDerivedType *Ty,
1917 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1921 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1923 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1925 ? SimpleTypeMode::NearPointer64
1926 : SimpleTypeMode::NearPointer32;
1931 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1935 case dwarf::DW_TAG_pointer_type:
1936 PM = PointerMode::Pointer;
1938 case dwarf::DW_TAG_reference_type:
1939 PM = PointerMode::LValueReference;
1941 case dwarf::DW_TAG_rvalue_reference_type:
1942 PM = PointerMode::RValueReference;
1947 PO |= PointerOptions::Const;
1949 PointerRecord PR(PointeeTI, PK, PM, PO, Ty->
getSizeInBits() / 8);
1950 return TypeTable.writeLeafType(PR);
1963 case DINode::FlagSingleInheritance:
1965 case DINode::FlagMultipleInheritance:
1967 case DINode::FlagVirtualInheritance:
1975 case DINode::FlagSingleInheritance:
1977 case DINode::FlagMultipleInheritance:
1979 case DINode::FlagVirtualInheritance:
1986TypeIndex CodeViewDebug::lowerTypeMemberPointer(
const DIDerivedType *Ty,
1988 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
1991 TypeIndex PointeeTI =
1992 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->
getClassType() :
nullptr);
1993 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
1994 : PointerKind::Near32;
1995 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
1996 : PointerMode::PointerToDataMember;
2000 MemberPointerInfo MPI(
2002 PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);
2003 return TypeTable.writeLeafType(PR);
2020TypeIndex CodeViewDebug::lowerTypeModifier(
const DIDerivedType *Ty) {
2024 const DIType *BaseTy = Ty;
2025 while (IsModifier && BaseTy) {
2027 switch (BaseTy->
getTag()) {
2028 case dwarf::DW_TAG_const_type:
2029 Mods |= ModifierOptions::Const;
2030 PO |= PointerOptions::Const;
2032 case dwarf::DW_TAG_volatile_type:
2033 Mods |= ModifierOptions::Volatile;
2034 PO |= PointerOptions::Volatile;
2036 case dwarf::DW_TAG_restrict_type:
2039 PO |= PointerOptions::Restrict;
2054 switch (BaseTy->
getTag()) {
2055 case dwarf::DW_TAG_pointer_type:
2056 case dwarf::DW_TAG_reference_type:
2057 case dwarf::DW_TAG_rvalue_reference_type:
2059 case dwarf::DW_TAG_ptr_to_member_type:
2066 TypeIndex ModifiedTI = getTypeIndex(BaseTy);
2070 if (Mods == ModifierOptions::None)
2073 ModifierRecord MR(ModifiedTI, Mods);
2074 return TypeTable.writeLeafType(MR);
2080 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2083 if (ReturnAndArgTypeIndices.
size() > 1 &&
2089 if (!ReturnAndArgTypeIndices.
empty()) {
2090 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2091 ReturnTypeIndex = ReturnAndArgTypesRef.consume_front();
2092 ArgTypeIndices = ReturnAndArgTypesRef;
2095 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2096 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2101 ProcedureRecord Procedure(ReturnTypeIndex, CC, FO, ArgTypeIndices.
size(),
2103 return TypeTable.writeLeafType(Procedure);
2106TypeIndex CodeViewDebug::lowerTypeMemberFunction(
const DISubroutineType *Ty,
2109 bool IsStaticMethod,
2112 TypeIndex ClassType = getTypeIndex(ClassTy);
2119 if (ReturnAndArgs.size() > Index) {
2120 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
2126 TypeIndex ThisTypeIndex;
2127 if (!IsStaticMethod && ReturnAndArgs.size() > Index) {
2128 if (
const DIDerivedType *PtrTy =
2130 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2131 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2137 while (Index < ReturnAndArgs.size())
2138 ArgTypeIndices.
push_back(getTypeIndex(ReturnAndArgs[Index++]));
2144 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2145 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2149 MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FO,
2150 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2151 return TypeTable.writeLeafType(MFR);
2154TypeIndex CodeViewDebug::lowerTypeVFTableShape(
const DIDerivedType *Ty) {
2155 unsigned VSlotCount =
2159 VFTableShapeRecord VFTSR(Slots);
2160 return TypeTable.writeLeafType(VFTSR);
2177 if (SP->isArtificial())
2187 if (SP->getFlags() & DINode::FlagStaticMember)
2190 switch (SP->getVirtuality()) {
2191 case dwarf::DW_VIRTUALITY_none:
2193 case dwarf::DW_VIRTUALITY_virtual:
2195 case dwarf::DW_VIRTUALITY_pure_virtual:
2206 switch (Ty->getTag()) {
2207 case dwarf::DW_TAG_class_type:
2208 return TypeRecordKind::Class;
2209 case dwarf::DW_TAG_structure_type:
2210 return TypeRecordKind::Struct;
2224 if (!Ty->getIdentifier().empty())
2238 if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) {
2242 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2254void CodeViewDebug::addUDTSrcLine(
const DIType *Ty, TypeIndex TI) {
2256 case dwarf::DW_TAG_class_type:
2257 case dwarf::DW_TAG_structure_type:
2258 case dwarf::DW_TAG_union_type:
2259 case dwarf::DW_TAG_enumeration_type:
2265 if (
const auto *File = Ty->
getFile()) {
2266 StringIdRecord SIDR(TypeIndex(0x0), getFullFilepath(File));
2267 TypeIndex SIDI = TypeTable.writeLeafType(SIDR);
2269 UdtSourceLineRecord USLR(TI, SIDI, Ty->
getLine());
2270 TypeTable.writeLeafType(USLR);
2277 unsigned EnumeratorCount = 0;
2280 CO |= ClassOptions::ForwardReference;
2282 ContinuationRecordBuilder ContinuationBuilder;
2283 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2289 EnumeratorRecord ER(MemberAccess::Public,
2296 FTI = TypeTable.insertRecord(ContinuationBuilder);
2299 std::string FullName = getFullyQualifiedName(Ty);
2301 EnumRecord ER(EnumeratorCount, CO, FTI, FullName, Ty->
getIdentifier(),
2303 TypeIndex EnumTI = TypeTable.writeLeafType(ER);
2305 addUDTSrcLine(Ty, EnumTI);
2339void CodeViewDebug::clear() {
2340 assert(CurFn ==
nullptr);
2342 FnDebugInfo.clear();
2343 FileToFilepathMap.clear();
2346 TypeIndices.clear();
2347 CompleteTypeIndices.clear();
2348 ScopeGlobals.clear();
2349 CVGlobalVariableOffsets.clear();
2352void CodeViewDebug::collectMemberInfo(
ClassInfo &Info,
2355 Info.Members.push_back({DDTy, 0});
2358 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2359 DINode::FlagStaticMember) {
2362 StaticConstMembers.push_back(DDTy);
2374 const DIType *Ty = DDTy->getBaseType();
2375 bool FullyResolved =
false;
2376 while (!FullyResolved) {
2378 case dwarf::DW_TAG_const_type:
2379 case dwarf::DW_TAG_volatile_type:
2385 FullyResolved =
true;
2394 ClassInfo NestedInfo = collectClassInfo(DCTy);
2395 for (
const ClassInfo::MemberInfo &IndirectField : NestedInfo.
Members)
2396 Info.Members.push_back(
2404 for (
auto *Element : Elements) {
2410 Info.Methods[
SP->getRawName()].push_back(SP);
2412 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2413 collectMemberInfo(Info, DDTy);
2414 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2415 Info.Inheritance.push_back(DDTy);
2416 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2417 DDTy->
getName() ==
"__vtbl_ptr_type") {
2418 Info.VShapeTI = getTypeIndex(DDTy);
2419 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2420 Info.NestedTypes.push_back(DDTy);
2421 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2426 Info.NestedTypes.push_back(Composite);
2436 return Ty->getName().empty() && Ty->getIdentifier().empty() &&
2437 !Ty->isForwardDecl();
2449 auto I = CompleteTypeIndices.find(Ty);
2450 if (
I != CompleteTypeIndices.end() &&
I->second == TypeIndex())
2452 return getCompleteTypeIndex(Ty);
2460 std::string FullName = getFullyQualifiedName(Ty);
2461 ClassRecord CR(Kind, 0, CO, TypeIndex(), TypeIndex(), TypeIndex(), 0,
2463 TypeIndex FwdDeclTI = TypeTable.writeLeafType(CR);
2465 DeferredCompleteTypes.push_back(Ty);
2469TypeIndex CodeViewDebug::lowerCompleteTypeClass(
const DICompositeType *Ty) {
2475 unsigned FieldCount;
2478 lowerRecordFieldList(Ty);
2481 CO |= ClassOptions::ContainsNestedClass;
2489 CO |= ClassOptions::HasConstructorOrDestructor;
2491 std::string FullName = getFullyQualifiedName(Ty);
2495 ClassRecord CR(Kind, FieldCount, CO, FieldTI, TypeIndex(), VShapeTI,
2497 TypeIndex ClassTI = TypeTable.writeLeafType(CR);
2499 addUDTSrcLine(Ty, ClassTI);
2509 return getCompleteTypeIndex(Ty);
2513 std::string FullName = getFullyQualifiedName(Ty);
2514 UnionRecord UR(0, CO, TypeIndex(), 0, FullName, Ty->
getIdentifier());
2515 TypeIndex FwdDeclTI = TypeTable.writeLeafType(UR);
2517 DeferredCompleteTypes.push_back(Ty);
2521TypeIndex CodeViewDebug::lowerCompleteTypeUnion(
const DICompositeType *Ty) {
2524 unsigned FieldCount;
2527 lowerRecordFieldList(Ty);
2530 CO |= ClassOptions::ContainsNestedClass;
2533 std::string FullName = getFullyQualifiedName(Ty);
2535 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2537 TypeIndex UnionTI = TypeTable.writeLeafType(UR);
2539 addUDTSrcLine(Ty, UnionTI);
2546std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2552 unsigned MemberCount = 0;
2553 ClassInfo
Info = collectClassInfo(Ty);
2554 ContinuationRecordBuilder ContinuationBuilder;
2555 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2558 for (
const DIDerivedType *
I :
Info.Inheritance) {
2559 if (
I->getFlags() & DINode::FlagVirtual) {
2561 unsigned VBPtrOffset =
I->getVBPtrOffset();
2563 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2564 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2565 ? TypeRecordKind::IndirectVirtualBaseClass
2566 : TypeRecordKind::VirtualBaseClass;
2567 VirtualBaseClassRecord VBCR(
2569 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2575 assert(
I->getOffsetInBits() % 8 == 0 &&
2576 "bases must be on byte boundaries");
2578 getTypeIndex(
I->getBaseType()),
2579 I->getOffsetInBits() / 8);
2586 for (ClassInfo::MemberInfo &MemberInfo :
Info.Members) {
2588 TypeIndex MemberBaseType = getTypeIndex(
Member->getBaseType());
2589 StringRef MemberName =
Member->getName();
2593 if (
Member->isStaticMember()) {
2594 StaticDataMemberRecord SDMR(
Access, MemberBaseType, MemberName);
2601 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2602 Member->getName().starts_with(
"_vptr$")) {
2603 VFPtrRecord VFPR(getTypeIndex(
Member->getBaseType()));
2610 uint64_t MemberOffsetInBits =
2612 if (
Member->isBitField()) {
2613 uint64_t StartBitOffset = MemberOffsetInBits;
2614 if (
const auto *CI =
2616 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2618 StartBitOffset -= MemberOffsetInBits;
2619 BitFieldRecord BFR(MemberBaseType,
Member->getSizeInBits(),
2621 MemberBaseType = TypeTable.writeLeafType(BFR);
2623 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2624 DataMemberRecord DMR(
Access, MemberBaseType, MemberOffsetInBytes,
2631 for (
auto &MethodItr :
Info.Methods) {
2632 StringRef
Name = MethodItr.first->getString();
2634 std::vector<OneMethodRecord> Methods;
2635 for (
const DISubprogram *SP : MethodItr.second) {
2636 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2637 bool Introduced =
SP->getFlags() & DINode::FlagIntroducedVirtual;
2639 unsigned VFTableOffset = -1;
2641 VFTableOffset =
SP->getVirtualIndex() * getPointerSizeInBytes();
2643 Methods.push_back(OneMethodRecord(
2649 assert(!Methods.empty() &&
"Empty methods map entry");
2650 if (Methods.size() == 1)
2655 MethodOverloadListRecord MOLR(Methods);
2656 TypeIndex MethodList = TypeTable.writeLeafType(MOLR);
2658 OverloadedMethodRecord OMR(Methods.size(), MethodList, Name);
2664 for (
const DIType *
Nested :
Info.NestedTypes) {
2665 NestedTypeRecord
R(getTypeIndex(
Nested),
Nested->getName());
2670 TypeIndex FieldTI = TypeTable.insertRecord(ContinuationBuilder);
2671 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2672 !
Info.NestedTypes.empty());
2675TypeIndex CodeViewDebug::getVBPTypeIndex() {
2676 if (!VBPType.getIndex()) {
2679 TypeIndex ModifiedTI = TypeTable.writeLeafType(MR);
2681 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2682 : PointerKind::Near32;
2685 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2686 VBPType = TypeTable.writeLeafType(PR);
2692TypeIndex CodeViewDebug::getTypeIndex(
const DIType *Ty,
const DIType *ClassTy) {
2700 auto I = TypeIndices.find({Ty, ClassTy});
2701 if (
I != TypeIndices.end())
2705 TypeIndex TI = lowerType(Ty, ClassTy);
2706 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2710CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2712 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2713 "this type must be a pointer type");
2716 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2717 Options = PointerOptions::LValueRefThisPointer;
2718 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2719 Options = PointerOptions::RValueRefThisPointer;
2726 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2727 if (
I != TypeIndices.end())
2731 TypeIndex TI = lowerTypePointer(PtrTy,
Options);
2732 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2735TypeIndex CodeViewDebug::getCompleteTypeIndex(
const DIType *Ty) {
2743 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2744 (void)getTypeIndex(Ty);
2745 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2751 case dwarf::DW_TAG_class_type:
2752 case dwarf::DW_TAG_structure_type:
2753 case dwarf::DW_TAG_union_type:
2756 return getTypeIndex(Ty);
2767 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2768 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2773 if (CTy->isForwardDecl())
2780 auto InsertResult = CompleteTypeIndices.try_emplace(CTy);
2781 if (!InsertResult.second)
2782 return InsertResult.first->second;
2785 switch (CTy->getTag()) {
2786 case dwarf::DW_TAG_class_type:
2787 case dwarf::DW_TAG_structure_type:
2788 TI = lowerCompleteTypeClass(CTy);
2790 case dwarf::DW_TAG_union_type:
2791 TI = lowerCompleteTypeUnion(CTy);
2801 CompleteTypeIndices[CTy] = TI;
2809void CodeViewDebug::emitDeferredCompleteTypes() {
2811 while (!DeferredCompleteTypes.empty()) {
2812 std::swap(DeferredCompleteTypes, TypesToEmit);
2813 for (
const DICompositeType *RecordTy : TypesToEmit)
2814 getCompleteTypeIndex(RecordTy);
2815 TypesToEmit.clear();
2819void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2823 for (
const LocalVariable &L : Locals)
2824 if (
L.DIVar->isParameter())
2826 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2827 return L->DIVar->getArg() <
R->DIVar->getArg();
2829 for (
const LocalVariable *L : Params)
2830 emitLocalVariable(FI, *L);
2833 for (
const LocalVariable &L : Locals) {
2834 if (!
L.DIVar->isParameter()) {
2835 if (
L.ConstantValue) {
2838 const DIType *Ty =
L.DIVar->getType();
2840 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2842 emitLocalVariable(FI, L);
2848void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2849 const LocalVariable &Var) {
2851 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2854 if (Var.DIVar->isParameter())
2855 Flags |= LocalSymFlags::IsParameter;
2856 if (Var.DefRanges.empty())
2857 Flags |= LocalSymFlags::IsOptimizedOut;
2859 OS.AddComment(
"TypeIndex");
2860 TypeIndex TI = getCompleteTypeIndex(Var.DIVar->getType());
2862 OS.AddComment(
"Flags");
2863 OS.emitInt16(
static_cast<uint16_t
>(Flags));
2866 endSymbolRecord(LocalEnd);
2871 SmallString<20> BytePrefix;
2872 for (
const auto &Pair : Var.DefRanges) {
2874 const auto &
Ranges = Pair.second;
2876 if (DefRange.InMemory) {
2877 int Offset = DefRange.DataOffset;
2878 unsigned Reg = DefRange.CVRegister;
2884 Reg = unsigned(RegisterId::VFRAME);
2885 Offset += FI.OffsetAdjustment;
2891 uint16_t RegRelFlags = 0;
2892 if (DefRange.IsSubfield) {
2894 (DefRange.StructOffset
2897 DefRangeRegisterRelIndirHeader DRHdr;
2899 DRHdr.
Flags = RegRelFlags;
2902 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2903 }
else if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2904 (
bool(Flags & LocalSymFlags::IsParameter)
2905 ? (EncFP == FI.EncodedParamFramePtrReg)
2906 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2910 DefRangeFramePointerRelHeader DRHdr;
2912 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2914 uint16_t RegRelFlags = 0;
2915 if (DefRange.IsSubfield) {
2917 (DefRange.StructOffset
2920 DefRangeRegisterRelHeader DRHdr;
2922 DRHdr.
Flags = RegRelFlags;
2924 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2927 assert(DefRange.DataOffset == 0 &&
2929 "unexpected offset into register");
2930 if (DefRange.IsSubfield) {
2931 DefRangeSubfieldRegisterHeader DRHdr;
2932 DRHdr.
Register = DefRange.CVRegister;
2935 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2937 DefRangeRegisterHeader DRHdr;
2938 DRHdr.
Register = DefRange.CVRegister;
2940 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2947 const FunctionInfo& FI) {
2948 for (LexicalBlock *
Block : Blocks)
2949 emitLexicalBlock(*
Block, FI);
2954void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2955 const FunctionInfo& FI) {
2956 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2957 OS.AddComment(
"PtrParent");
2959 OS.AddComment(
"PtrEnd");
2961 OS.AddComment(
"Code size");
2962 OS.emitAbsoluteSymbolDiff(
Block.End,
Block.Begin, 4);
2963 OS.AddComment(
"Function section relative address");
2964 OS.emitCOFFSecRel32(
Block.Begin, 0);
2965 OS.AddComment(
"Function section index");
2966 OS.emitCOFFSectionIndex(FI.Begin);
2967 OS.AddComment(
"Lexical block name");
2969 endSymbolRecord(RecordEnd);
2972 emitLocalVariableList(FI,
Block.Locals);
2973 emitGlobalVariableList(
Block.Globals);
2976 emitLexicalBlockList(
Block.Children, FI);
2979 emitEndSymbolRecord(SymbolKind::S_END);
2984void CodeViewDebug::collectLexicalBlockInfo(
2989 for (LexicalScope *Scope : Scopes)
2990 collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
2995void CodeViewDebug::collectLexicalBlockInfo(
3000 if (
Scope.isAbstractScope())
3005 bool IgnoreScope =
false;
3006 auto LI = ScopeVariables.find(&Scope);
3007 SmallVectorImpl<LocalVariable> *
Locals =
3008 LI != ScopeVariables.end() ? &LI->second :
nullptr;
3009 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
3010 SmallVectorImpl<CVGlobalVariable> *Globals =
3011 GI != ScopeGlobals.
end() ? GI->second.get() :
nullptr;
3013 const SmallVectorImpl<InsnRange> &
Ranges =
Scope.getRanges();
3016 if (!Locals && !Globals)
3046 collectLexicalBlockInfo(
Scope.getChildren(),
3056 auto BlockInsertion = CurFn->LexicalBlocks.try_emplace(DILB);
3057 if (!BlockInsertion.second)
3064 LexicalBlock &
Block = BlockInsertion.first->second;
3067 assert(
Block.Begin &&
"missing label for scope begin");
3068 assert(
Block.End &&
"missing label for scope end");
3071 Block.Locals = std::move(*Locals);
3073 Block.Globals = std::move(*Globals);
3075 collectLexicalBlockInfo(
Scope.getChildren(),
3083 assert(FnDebugInfo.count(&GV));
3084 assert(CurFn == FnDebugInfo[&GV].
get());
3090 collectLexicalBlockInfo(*CFS,
3098 ScopeVariables.clear();
3102 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3103 FnDebugInfo.erase(&GV);
3109 for (
const auto &
MBB : *MF) {
3110 for (
const auto &
MI :
MBB) {
3111 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3119 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
3121 collectDebugInfoForJumpTables(MF,
isThumb);
3125 CurFn->End =
Asm->getFunctionEnd();
3142 if (
DL.getLine() != 0)
3145 return Scope->getSubprogram()->isArtificial();
3153 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3161 for (
const auto &NextMI : *
MI->getParent()) {
3162 if (NextMI.isDebugInstr())
3164 DL = NextMI.getDebugLoc();
3177 maybeRecordLocation(
DL,
Asm->MF);
3190void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3197 MCSymbol *BeginLabel =
MMI->getContext().createTempSymbol(),
3198 *EndLabel =
MMI->getContext().createTempSymbol();
3199 OS.AddComment(
"Record length");
3200 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
3201 OS.emitLabel(BeginLabel);
3202 if (OS.isVerboseAsm())
3204 OS.emitInt16(
unsigned(SymKind));
3208void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3213 OS.emitValueToAlignment(
Align(4));
3214 OS.emitLabel(SymEnd);
3217void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3218 OS.AddComment(
"Record length");
3220 if (OS.isVerboseAsm())
3222 OS.emitInt16(uint16_t(EndKind));
3225void CodeViewDebug::emitDebugInfoForUDTs(
3226 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3228 size_t OriginalSize = UDTs.size();
3230 for (
const auto &UDT : UDTs) {
3231 const DIType *
T =
UDT.second;
3233 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3234 OS.AddComment(
"Type");
3235 OS.emitInt32(getCompleteTypeIndex(
T).getIndex());
3236 assert(OriginalSize == UDTs.size() &&
3237 "getCompleteTypeIndex found new UDTs!");
3239 endSymbolRecord(UDTRecordEnd);
3243void CodeViewDebug::collectGlobalOrStaticLocalVariableInfo(
3245 const DIGlobalVariable *DIGV = GVE->
getVariable();
3255 (DIE->
getElement(0) == dwarf::DW_OP_plus_uconst))
3260 CVGlobalVariableOffsets.insert(std::make_pair(DIGV, DIE->
getElement(1)));
3263 if (!GlobalMap.count(GVE) && DIE->
isConstant())
3264 GlobalVariables.emplace_back(CVGlobalVariable{DIGV, DIE});
3266 const auto *GV = GlobalMap.lookup(GVE);
3271 SmallVector<CVGlobalVariable, 1> *VariableList;
3276 ScopeGlobals.insert({
Scope, std::unique_ptr<GlobalVariableList>()});
3277 if (Insertion.second)
3278 Insertion.first->second = std::make_unique<GlobalVariableList>();
3279 VariableList = Insertion.first->second.get();
3282 VariableList = &ComdatVariables;
3285 VariableList = &GlobalVariables;
3287 VariableList->
emplace_back(CVGlobalVariable{DIGV, GV});
3290void CodeViewDebug::collectGlobalVariableInfo() {
3291 for (
const GlobalVariable &GV :
MMI->getModule()->globals()) {
3293 GV.getDebugInfo(GVEs);
3294 for (
const auto *GVE : GVEs)
3295 GlobalMap[GVE] = &GV;
3298 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3299 for (
const MDNode *Node : CUs->
operands()) {
3301 for (
const auto *GVE : CU->getGlobalVariables()) {
3302 collectGlobalOrStaticLocalVariableInfo(GVE);
3307void CodeViewDebug::collectDebugInfoForGlobals() {
3308 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3309 const DIGlobalVariable *DIGV = CVGV.DIGV;
3311 getCompleteTypeIndex(DIGV->
getType());
3312 getFullyQualifiedName(Scope, DIGV->
getName());
3315 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3316 const DIGlobalVariable *DIGV = CVGV.DIGV;
3318 getCompleteTypeIndex(DIGV->
getType());
3319 getFullyQualifiedName(Scope, DIGV->
getName());
3323void CodeViewDebug::emitDebugInfoForGlobals() {
3327 switchToDebugSectionForSymbol(
nullptr);
3328 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3329 OS.AddComment(
"Symbol subsection for globals");
3330 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3331 emitGlobalVariableList(GlobalVariables);
3332 emitStaticConstMemberList();
3333 endCVSubsection(EndLabel);
3338 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3341 OS.AddComment(
"Symbol subsection for " +
3343 switchToDebugSectionForSymbol(GVSym);
3344 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3346 emitDebugInfoForGlobal(CVGV);
3347 endCVSubsection(EndLabel);
3351void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3352 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3353 for (
const MDNode *Node : CUs->
operands()) {
3365 for (
const CVGlobalVariable &CVGV : Globals) {
3367 emitDebugInfoForGlobal(CVGV);
3372 const std::string &QualifiedName) {
3373 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3374 OS.AddComment(
"Type");
3375 OS.emitInt32(getTypeIndex(DTy).getIndex());
3377 OS.AddComment(
"Value");
3382 CodeViewRecordIO IO(Writer);
3384 StringRef SRef((
char *)
Data, Writer.getOffset());
3385 OS.emitBinaryData(SRef);
3387 OS.AddComment(
"Name");
3389 endSymbolRecord(SConstantEnd);
3392void CodeViewDebug::emitStaticConstMemberList() {
3393 for (
const DIDerivedType *DTy : StaticConstMembers) {
3397 if (
const ConstantInt *CI =
3401 else if (
const ConstantFP *CFP =
3403 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3407 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3408 getFullyQualifiedName(Scope, DTy->
getName()));
3418 if (
T == dwarf::DW_TAG_pointer_type ||
3419 T == dwarf::DW_TAG_ptr_to_member_type ||
3420 T == dwarf::DW_TAG_reference_type ||
3421 T == dwarf::DW_TAG_rvalue_reference_type)
3423 assert(DTy->getBaseType() &&
"Expected valid base type");
3428 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3431void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3432 const DIGlobalVariable *DIGV = CVGV.DIGV;
3438 Scope = MemberDecl->getScope();
3444 ? std::string(DIGV->
getName())
3447 if (
const GlobalVariable *GV =
3451 MCSymbol *GVSym = Asm->getSymbol(GV);
3452 SymbolKind DataSym = GV->isThreadLocal()
3453 ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32
3454 : SymbolKind::S_GTHREAD32)
3455 : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32
3456 : SymbolKind::S_GDATA32);
3457 MCSymbol *DataEnd = beginSymbolRecord(DataSym);
3458 OS.AddComment(
"Type");
3459 OS.emitInt32(getCompleteTypeIndex(DIGV->getType()).getIndex());
3460 OS.AddComment(
"DataOffset");
3463 uint64_t Offset = CVGlobalVariableOffsets.lookup(DIGV);
3464 OS.emitCOFFSecRel32(GVSym, Offset);
3466 OS.AddComment(
"Segment");
3467 OS.emitCOFFSectionIndex(GVSym);
3468 OS.AddComment(
"Name");
3469 const unsigned LengthOfDataRecord = 12;
3470 emitNullTerminatedSymbolName(OS, QualifiedName, LengthOfDataRecord);
3471 endSymbolRecord(DataEnd);
3473 const DIExpression *DIE = cast<const DIExpression *>(CVGV.GVInfo);
3474 assert(DIE->isConstant() &&
3475 "Global constant variables must contain a constant expression.");
3478 bool isUnsigned = isFloatDIType(DIGV->getType())
3480 : DebugHandlerBase::isUnsignedDIType(DIGV->getType());
3481 APSInt Value(APInt(64, DIE->getElement(1)), isUnsigned);
3482 emitConstantSymbolRecord(DIGV->getType(), Value, QualifiedName);
3489 int64_t)> &Callback) {
3491 if (JTI && !JTI->isEmpty()) {
3495 for (
const auto &
MBB : *MF) {
3497 const auto LastMI =
MBB.getFirstTerminator();
3498 if (LastMI !=
MBB.end() && LastMI->isIndirectBranch()) {
3506 for (
const auto &MO : LastMI->operands()) {
3508 unsigned Index = MO.getIndex();
3512 Callback(*JTI, *LastMI, Index);
3520 for (
auto I =
MBB.instr_rbegin(),
E =
MBB.instr_rend();
I !=
E; ++
I) {
3521 if (
I->isJumpTableDebugInfo()) {
3522 unsigned Index =
I->getOperand(0).getImm();
3526 Callback(*JTI, *LastMI, Index);
3535 "Some of jump tables were not used in a debug info instruction");
3540void CodeViewDebug::discoverJumpTableBranches(
const MachineFunction *MF,
3544 [
this](
const MachineJumpTableInfo &,
const MachineInstr &BranchMI,
3548void CodeViewDebug::collectDebugInfoForJumpTables(
const MachineFunction *MF,
3552 [
this, MF](
const MachineJumpTableInfo &JTI,
const MachineInstr &BranchMI,
3553 int64_t JumpTableIndex) {
3558 uint64_t BaseOffset = 0;
3566 "EK_Custom32, EK_GPRel32BlockAddress, and "
3567 "EK_GPRel64BlockAddress should never be emitted for COFF");
3570 EntrySize = JumpTableEntrySize::Pointer;
3577 std::tie(
Base, BaseOffset, Branch, EntrySize) =
3578 Asm->getCodeViewJumpTableInfo(JumpTableIndex, &BranchMI, Branch);
3582 const MachineJumpTableEntry &JTE = JTI.
getJumpTables()[JumpTableIndex];
3583 JumpTableInfo CVJTI{EntrySize,
3590 for (
const auto &
MBB : JTE.
MBBs)
3592 CurFn->JumpTables.push_back(std::move(CVJTI));
3596void CodeViewDebug::emitDebugInfoForJumpTables(
const FunctionInfo &FI) {
3598 for (
const auto &JumpTable : FI.JumpTables) {
3599 for (
const auto &CaseSym :
JumpTable.Cases) {
3600 MCSymbol *LabelEnd = beginSymbolRecord(SymbolKind::S_LABEL32);
3601 OS.AddComment(
"Offset and segment");
3602 OS.emitCOFFSecRel32(CaseSym, 0);
3603 OS.AddComment(
"Flags");
3606 endSymbolRecord(LabelEnd);
3610 for (
const auto &JumpTable : FI.JumpTables) {
3611 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3613 OS.AddComment(
"Base offset");
3615 OS.AddComment(
"Base section index");
3616 OS.emitCOFFSectionIndex(
JumpTable.Base);
3618 OS.AddComment(
"Base offset");
3620 OS.AddComment(
"Base section index");
3623 OS.AddComment(
"Switch type");
3624 OS.emitInt16(
static_cast<uint16_t
>(
JumpTable.EntrySize));
3625 OS.AddComment(
"Branch offset");
3626 OS.emitCOFFSecRel32(
JumpTable.Branch, 0);
3627 OS.AddComment(
"Table offset");
3628 OS.emitCOFFSecRel32(
JumpTable.Table, 0);
3629 OS.AddComment(
"Branch section index");
3630 OS.emitCOFFSectionIndex(
JumpTable.Branch);
3631 OS.AddComment(
"Table section index");
3632 OS.emitCOFFSectionIndex(
JumpTable.Table);
3633 OS.AddComment(
"Entries count");
3635 endSymbolRecord(JumpTableEnd);
3639void CodeViewDebug::emitInlinees(
3643 constexpr size_t ChunkSize =
3650 size_t CurrentIndex = 0;
3651 while (CurrentIndex < SortedInlinees.
size()) {
3652 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3653 auto CurrentChunkSize =
3654 std::min(ChunkSize, SortedInlinees.
size() - CurrentIndex);
3655 OS.AddComment(
"Count");
3656 OS.emitInt32(CurrentChunkSize);
3658 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3659 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3660 OS.AddComment(
"Inlinee");
3661 OS.emitInt32(SortedInlinees[CurrentIndex].getIndex());
3663 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")
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
@ 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.
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.