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);
1455 InlinedEntity
IV =
I.first;
1459 const DILocation *InlinedAt =
IV.second;
1462 const auto &Entries =
I.second;
1464 LexicalScope *
Scope =
nullptr;
1476 calculateRanges(Var, Entries);
1477 recordLocalVariable(std::move(Var), Scope);
1486 auto Insertion = FnDebugInfo.
insert({&GV, std::make_unique<FunctionInfo>()});
1487 assert(Insertion.second &&
"function already has info");
1488 CurFn = Insertion.first->second.get();
1489 CurFn->FuncId = NextFuncId++;
1490 CurFn->Begin =
Asm->getFunctionBegin();
1498 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1504 if (CurFn->FrameSize > 0) {
1509 CurFn->HasFramePointer =
true;
1512 if (CurFn->HasStackRealignment) {
1563 CurFn->FrameProcOpts = FPO;
1565 OS.emitCVFuncIdDirective(CurFn->FuncId);
1572 bool EmptyPrologue =
true;
1573 for (
const auto &
MBB : *MF) {
1574 for (
const auto &
MI :
MBB) {
1579 }
else if (!
MI.isMetaInstruction()) {
1580 EmptyPrologue =
false;
1588 maybeRecordLocation(FnStartDL, MF);
1592 for (
const auto &
MBB : *MF) {
1593 for (
const auto &
MI :
MBB) {
1594 if (
MI.getHeapAllocMarker()) {
1602 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
1604 discoverJumpTableBranches(MF,
isThumb);
1612 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1613 if (
DIScope *Scope =
T->getScope()) {
1614 switch (Scope->getTag()) {
1615 case dwarf::DW_TAG_structure_type:
1616 case dwarf::DW_TAG_class_type:
1617 case dwarf::DW_TAG_union_type:
1627 if (!
T ||
T->isForwardDecl())
1633 T = DT->getBaseType();
1638void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1646 const DISubprogram *ClosestSubprogram =
1647 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1649 std::string FullyQualifiedName =
1652 if (ClosestSubprogram ==
nullptr) {
1653 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1654 }
else if (ClosestSubprogram == CurrentSubprogram) {
1655 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1666TypeIndex CodeViewDebug::lowerType(
const DIType *Ty,
const DIType *ClassTy) {
1669 case dwarf::DW_TAG_array_type:
1671 case dwarf::DW_TAG_typedef:
1673 case dwarf::DW_TAG_base_type:
1675 case dwarf::DW_TAG_pointer_type:
1679 case dwarf::DW_TAG_reference_type:
1680 case dwarf::DW_TAG_rvalue_reference_type:
1682 case dwarf::DW_TAG_ptr_to_member_type:
1684 case dwarf::DW_TAG_restrict_type:
1685 case dwarf::DW_TAG_const_type:
1686 case dwarf::DW_TAG_volatile_type:
1689 case dwarf::DW_TAG_subroutine_type:
1698 case dwarf::DW_TAG_enumeration_type:
1700 case dwarf::DW_TAG_class_type:
1701 case dwarf::DW_TAG_structure_type:
1703 case dwarf::DW_TAG_union_type:
1705 case dwarf::DW_TAG_string_type:
1707 case dwarf::DW_TAG_unspecified_type:
1708 if (Ty->
getName() ==
"decltype(nullptr)")
1717TypeIndex CodeViewDebug::lowerTypeAlias(
const DIDerivedType *Ty) {
1718 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1723 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) &&
1724 TypeName ==
"HRESULT")
1725 return TypeIndex(SimpleTypeKind::HResult);
1726 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::UInt16Short) &&
1727 TypeName ==
"wchar_t")
1728 return TypeIndex(SimpleTypeKind::WideCharacter);
1730 return UnderlyingTypeIndex;
1735 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1737 TypeIndex IndexType = getPointerSizeInBytes() == 8
1738 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1745 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1746 const DINode *Element =
Elements[i];
1747 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1757 Count = CI->getSExtValue();
1763 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1764 Count = UI->getSExtValue() - Lowerbound + 1;
1775 ElementSize *=
Count;
1779 uint64_t ArraySize =
1780 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1783 ArrayRecord AR(ElementTypeIndex, IndexType, ArraySize, Name);
1784 ElementTypeIndex = TypeTable.writeLeafType(AR);
1787 return ElementTypeIndex;
1795TypeIndex CodeViewDebug::lowerTypeString(
const DIStringType *Ty) {
1796 TypeIndex CharType = TypeIndex(SimpleTypeKind::NarrowCharacter);
1800 TypeIndex IndexType = getPointerSizeInBytes() == 8
1801 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1805 ArrayRecord AR(CharType, IndexType, ArraySize, Name);
1807 return TypeTable.writeLeafType(AR);
1810TypeIndex CodeViewDebug::lowerTypeBasic(
const DIBasicType *Ty) {
1820 case dwarf::DW_ATE_address:
1823 case dwarf::DW_ATE_boolean:
1825 case 1: STK = SimpleTypeKind::Boolean8;
break;
1826 case 2: STK = SimpleTypeKind::Boolean16;
break;
1827 case 4: STK = SimpleTypeKind::Boolean32;
break;
1828 case 8: STK = SimpleTypeKind::Boolean64;
break;
1829 case 16: STK = SimpleTypeKind::Boolean128;
break;
1832 case dwarf::DW_ATE_complex_float:
1836 case 4: STK = SimpleTypeKind::Complex16;
break;
1837 case 8: STK = SimpleTypeKind::Complex32;
break;
1838 case 16: STK = SimpleTypeKind::Complex64;
break;
1839 case 20: STK = SimpleTypeKind::Complex80;
break;
1840 case 32: STK = SimpleTypeKind::Complex128;
break;
1843 case dwarf::DW_ATE_float:
1845 case 2: STK = SimpleTypeKind::Float16;
break;
1846 case 4: STK = SimpleTypeKind::Float32;
break;
1847 case 6: STK = SimpleTypeKind::Float48;
break;
1848 case 8: STK = SimpleTypeKind::Float64;
break;
1849 case 10: STK = SimpleTypeKind::Float80;
break;
1850 case 16: STK = SimpleTypeKind::Float128;
break;
1853 case dwarf::DW_ATE_signed:
1855 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1856 case 2: STK = SimpleTypeKind::Int16Short;
break;
1857 case 4: STK = SimpleTypeKind::Int32;
break;
1858 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1859 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1862 case dwarf::DW_ATE_unsigned:
1864 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1865 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1866 case 4: STK = SimpleTypeKind::UInt32;
break;
1867 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1868 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1871 case dwarf::DW_ATE_UTF:
1873 case 1: STK = SimpleTypeKind::Character8;
break;
1874 case 2: STK = SimpleTypeKind::Character16;
break;
1875 case 4: STK = SimpleTypeKind::Character32;
break;
1878 case dwarf::DW_ATE_signed_char:
1880 STK = SimpleTypeKind::SignedCharacter;
1882 case dwarf::DW_ATE_unsigned_char:
1884 STK = SimpleTypeKind::UnsignedCharacter;
1894 if (STK == SimpleTypeKind::Int32 &&
1896 STK = SimpleTypeKind::Int32Long;
1897 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1898 Ty->
getName() ==
"unsigned long"))
1899 STK = SimpleTypeKind::UInt32Long;
1900 if (STK == SimpleTypeKind::UInt16Short &&
1902 STK = SimpleTypeKind::WideCharacter;
1903 if ((STK == SimpleTypeKind::SignedCharacter ||
1904 STK == SimpleTypeKind::UnsignedCharacter) &&
1906 STK = SimpleTypeKind::NarrowCharacter;
1908 return TypeIndex(STK);
1911TypeIndex CodeViewDebug::lowerTypePointer(
const DIDerivedType *Ty,
1913 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1917 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1919 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1921 ? SimpleTypeMode::NearPointer64
1922 : SimpleTypeMode::NearPointer32;
1927 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1931 case dwarf::DW_TAG_pointer_type:
1932 PM = PointerMode::Pointer;
1934 case dwarf::DW_TAG_reference_type:
1935 PM = PointerMode::LValueReference;
1937 case dwarf::DW_TAG_rvalue_reference_type:
1938 PM = PointerMode::RValueReference;
1943 PO |= PointerOptions::Const;
1945 PointerRecord PR(PointeeTI, PK, PM, PO, Ty->
getSizeInBits() / 8);
1946 return TypeTable.writeLeafType(PR);
1959 case DINode::FlagSingleInheritance:
1961 case DINode::FlagMultipleInheritance:
1963 case DINode::FlagVirtualInheritance:
1971 case DINode::FlagSingleInheritance:
1973 case DINode::FlagMultipleInheritance:
1975 case DINode::FlagVirtualInheritance:
1982TypeIndex CodeViewDebug::lowerTypeMemberPointer(
const DIDerivedType *Ty,
1984 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
1987 TypeIndex PointeeTI =
1988 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->
getClassType() :
nullptr);
1989 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
1990 : PointerKind::Near32;
1991 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
1992 : PointerMode::PointerToDataMember;
1996 MemberPointerInfo MPI(
1998 PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);
1999 return TypeTable.writeLeafType(PR);
2016TypeIndex CodeViewDebug::lowerTypeModifier(
const DIDerivedType *Ty) {
2020 const DIType *BaseTy = Ty;
2021 while (IsModifier && BaseTy) {
2023 switch (BaseTy->
getTag()) {
2024 case dwarf::DW_TAG_const_type:
2025 Mods |= ModifierOptions::Const;
2026 PO |= PointerOptions::Const;
2028 case dwarf::DW_TAG_volatile_type:
2029 Mods |= ModifierOptions::Volatile;
2030 PO |= PointerOptions::Volatile;
2032 case dwarf::DW_TAG_restrict_type:
2035 PO |= PointerOptions::Restrict;
2050 switch (BaseTy->
getTag()) {
2051 case dwarf::DW_TAG_pointer_type:
2052 case dwarf::DW_TAG_reference_type:
2053 case dwarf::DW_TAG_rvalue_reference_type:
2055 case dwarf::DW_TAG_ptr_to_member_type:
2062 TypeIndex ModifiedTI = getTypeIndex(BaseTy);
2066 if (Mods == ModifierOptions::None)
2069 ModifierRecord MR(ModifiedTI, Mods);
2070 return TypeTable.writeLeafType(MR);
2076 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2079 if (ReturnAndArgTypeIndices.
size() > 1 &&
2085 if (!ReturnAndArgTypeIndices.
empty()) {
2086 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2087 ReturnTypeIndex = ReturnAndArgTypesRef.consume_front();
2088 ArgTypeIndices = ReturnAndArgTypesRef;
2091 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2092 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2097 ProcedureRecord Procedure(ReturnTypeIndex, CC, FO, ArgTypeIndices.
size(),
2099 return TypeTable.writeLeafType(Procedure);
2102TypeIndex CodeViewDebug::lowerTypeMemberFunction(
const DISubroutineType *Ty,
2105 bool IsStaticMethod,
2108 TypeIndex ClassType = getTypeIndex(ClassTy);
2115 if (ReturnAndArgs.size() > Index) {
2116 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
2122 TypeIndex ThisTypeIndex;
2123 if (!IsStaticMethod && ReturnAndArgs.size() > Index) {
2124 if (
const DIDerivedType *PtrTy =
2126 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2127 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2133 while (Index < ReturnAndArgs.size())
2134 ArgTypeIndices.
push_back(getTypeIndex(ReturnAndArgs[Index++]));
2140 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2141 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2145 MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FO,
2146 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2147 return TypeTable.writeLeafType(MFR);
2150TypeIndex CodeViewDebug::lowerTypeVFTableShape(
const DIDerivedType *Ty) {
2151 unsigned VSlotCount =
2155 VFTableShapeRecord VFTSR(Slots);
2156 return TypeTable.writeLeafType(VFTSR);
2173 if (SP->isArtificial())
2183 if (SP->getFlags() & DINode::FlagStaticMember)
2186 switch (SP->getVirtuality()) {
2187 case dwarf::DW_VIRTUALITY_none:
2189 case dwarf::DW_VIRTUALITY_virtual:
2191 case dwarf::DW_VIRTUALITY_pure_virtual:
2202 switch (Ty->getTag()) {
2203 case dwarf::DW_TAG_class_type:
2204 return TypeRecordKind::Class;
2205 case dwarf::DW_TAG_structure_type:
2206 return TypeRecordKind::Struct;
2220 if (!Ty->getIdentifier().empty())
2234 if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) {
2238 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2250void CodeViewDebug::addUDTSrcLine(
const DIType *Ty, TypeIndex TI) {
2252 case dwarf::DW_TAG_class_type:
2253 case dwarf::DW_TAG_structure_type:
2254 case dwarf::DW_TAG_union_type:
2255 case dwarf::DW_TAG_enumeration_type:
2261 if (
const auto *File = Ty->
getFile()) {
2262 StringIdRecord SIDR(TypeIndex(0x0), getFullFilepath(File));
2263 TypeIndex SIDI = TypeTable.writeLeafType(SIDR);
2265 UdtSourceLineRecord USLR(TI, SIDI, Ty->
getLine());
2266 TypeTable.writeLeafType(USLR);
2273 unsigned EnumeratorCount = 0;
2276 CO |= ClassOptions::ForwardReference;
2278 ContinuationRecordBuilder ContinuationBuilder;
2279 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2285 EnumeratorRecord ER(MemberAccess::Public,
2292 FTI = TypeTable.insertRecord(ContinuationBuilder);
2295 std::string FullName = getFullyQualifiedName(Ty);
2297 EnumRecord ER(EnumeratorCount, CO, FTI, FullName, Ty->
getIdentifier(),
2299 TypeIndex EnumTI = TypeTable.writeLeafType(ER);
2301 addUDTSrcLine(Ty, EnumTI);
2335void CodeViewDebug::clear() {
2336 assert(CurFn ==
nullptr);
2338 FnDebugInfo.clear();
2339 FileToFilepathMap.clear();
2342 TypeIndices.clear();
2343 CompleteTypeIndices.clear();
2344 ScopeGlobals.clear();
2345 CVGlobalVariableOffsets.clear();
2348void CodeViewDebug::collectMemberInfo(
ClassInfo &Info,
2351 Info.Members.push_back({DDTy, 0});
2354 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2355 DINode::FlagStaticMember) {
2358 StaticConstMembers.push_back(DDTy);
2370 const DIType *Ty = DDTy->getBaseType();
2371 bool FullyResolved =
false;
2372 while (!FullyResolved) {
2374 case dwarf::DW_TAG_const_type:
2375 case dwarf::DW_TAG_volatile_type:
2381 FullyResolved =
true;
2390 ClassInfo NestedInfo = collectClassInfo(DCTy);
2391 for (
const ClassInfo::MemberInfo &IndirectField : NestedInfo.
Members)
2392 Info.Members.push_back(
2400 for (
auto *Element : Elements) {
2406 Info.Methods[
SP->getRawName()].push_back(SP);
2408 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2409 collectMemberInfo(Info, DDTy);
2410 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2411 Info.Inheritance.push_back(DDTy);
2412 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2413 DDTy->
getName() ==
"__vtbl_ptr_type") {
2414 Info.VShapeTI = getTypeIndex(DDTy);
2415 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2416 Info.NestedTypes.push_back(DDTy);
2417 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2422 Info.NestedTypes.push_back(Composite);
2432 return Ty->getName().empty() && Ty->getIdentifier().empty() &&
2433 !Ty->isForwardDecl();
2445 auto I = CompleteTypeIndices.find(Ty);
2446 if (
I != CompleteTypeIndices.end() &&
I->second == TypeIndex())
2448 return getCompleteTypeIndex(Ty);
2456 std::string FullName = getFullyQualifiedName(Ty);
2457 ClassRecord CR(Kind, 0, CO, TypeIndex(), TypeIndex(), TypeIndex(), 0,
2459 TypeIndex FwdDeclTI = TypeTable.writeLeafType(CR);
2461 DeferredCompleteTypes.push_back(Ty);
2465TypeIndex CodeViewDebug::lowerCompleteTypeClass(
const DICompositeType *Ty) {
2471 unsigned FieldCount;
2474 lowerRecordFieldList(Ty);
2477 CO |= ClassOptions::ContainsNestedClass;
2485 CO |= ClassOptions::HasConstructorOrDestructor;
2487 std::string FullName = getFullyQualifiedName(Ty);
2491 ClassRecord CR(Kind, FieldCount, CO, FieldTI, TypeIndex(), VShapeTI,
2493 TypeIndex ClassTI = TypeTable.writeLeafType(CR);
2495 addUDTSrcLine(Ty, ClassTI);
2505 return getCompleteTypeIndex(Ty);
2509 std::string FullName = getFullyQualifiedName(Ty);
2510 UnionRecord UR(0, CO, TypeIndex(), 0, FullName, Ty->
getIdentifier());
2511 TypeIndex FwdDeclTI = TypeTable.writeLeafType(UR);
2513 DeferredCompleteTypes.push_back(Ty);
2517TypeIndex CodeViewDebug::lowerCompleteTypeUnion(
const DICompositeType *Ty) {
2520 unsigned FieldCount;
2523 lowerRecordFieldList(Ty);
2526 CO |= ClassOptions::ContainsNestedClass;
2529 std::string FullName = getFullyQualifiedName(Ty);
2531 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2533 TypeIndex UnionTI = TypeTable.writeLeafType(UR);
2535 addUDTSrcLine(Ty, UnionTI);
2542std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2548 unsigned MemberCount = 0;
2549 ClassInfo
Info = collectClassInfo(Ty);
2550 ContinuationRecordBuilder ContinuationBuilder;
2551 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2554 for (
const DIDerivedType *
I :
Info.Inheritance) {
2555 if (
I->getFlags() & DINode::FlagVirtual) {
2557 unsigned VBPtrOffset =
I->getVBPtrOffset();
2559 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2560 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2561 ? TypeRecordKind::IndirectVirtualBaseClass
2562 : TypeRecordKind::VirtualBaseClass;
2563 VirtualBaseClassRecord VBCR(
2565 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2571 assert(
I->getOffsetInBits() % 8 == 0 &&
2572 "bases must be on byte boundaries");
2574 getTypeIndex(
I->getBaseType()),
2575 I->getOffsetInBits() / 8);
2582 for (ClassInfo::MemberInfo &MemberInfo :
Info.Members) {
2584 TypeIndex MemberBaseType = getTypeIndex(
Member->getBaseType());
2585 StringRef MemberName =
Member->getName();
2589 if (
Member->isStaticMember()) {
2590 StaticDataMemberRecord SDMR(
Access, MemberBaseType, MemberName);
2597 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2598 Member->getName().starts_with(
"_vptr$")) {
2599 VFPtrRecord VFPR(getTypeIndex(
Member->getBaseType()));
2606 uint64_t MemberOffsetInBits =
2608 if (
Member->isBitField()) {
2609 uint64_t StartBitOffset = MemberOffsetInBits;
2610 if (
const auto *CI =
2612 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2614 StartBitOffset -= MemberOffsetInBits;
2615 BitFieldRecord BFR(MemberBaseType,
Member->getSizeInBits(),
2617 MemberBaseType = TypeTable.writeLeafType(BFR);
2619 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2620 DataMemberRecord DMR(
Access, MemberBaseType, MemberOffsetInBytes,
2627 for (
auto &MethodItr :
Info.Methods) {
2628 StringRef
Name = MethodItr.first->getString();
2630 std::vector<OneMethodRecord> Methods;
2631 for (
const DISubprogram *SP : MethodItr.second) {
2632 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2633 bool Introduced =
SP->getFlags() & DINode::FlagIntroducedVirtual;
2635 unsigned VFTableOffset = -1;
2637 VFTableOffset =
SP->getVirtualIndex() * getPointerSizeInBytes();
2639 Methods.push_back(OneMethodRecord(
2645 assert(!Methods.empty() &&
"Empty methods map entry");
2646 if (Methods.size() == 1)
2651 MethodOverloadListRecord MOLR(Methods);
2652 TypeIndex MethodList = TypeTable.writeLeafType(MOLR);
2654 OverloadedMethodRecord OMR(Methods.size(), MethodList, Name);
2660 for (
const DIType *
Nested :
Info.NestedTypes) {
2661 NestedTypeRecord
R(getTypeIndex(
Nested),
Nested->getName());
2666 TypeIndex FieldTI = TypeTable.insertRecord(ContinuationBuilder);
2667 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2668 !
Info.NestedTypes.empty());
2671TypeIndex CodeViewDebug::getVBPTypeIndex() {
2672 if (!VBPType.getIndex()) {
2675 TypeIndex ModifiedTI = TypeTable.writeLeafType(MR);
2677 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2678 : PointerKind::Near32;
2681 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2682 VBPType = TypeTable.writeLeafType(PR);
2688TypeIndex CodeViewDebug::getTypeIndex(
const DIType *Ty,
const DIType *ClassTy) {
2696 auto I = TypeIndices.find({Ty, ClassTy});
2697 if (
I != TypeIndices.end())
2701 TypeIndex TI = lowerType(Ty, ClassTy);
2702 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2706CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2708 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2709 "this type must be a pointer type");
2712 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2713 Options = PointerOptions::LValueRefThisPointer;
2714 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2715 Options = PointerOptions::RValueRefThisPointer;
2722 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2723 if (
I != TypeIndices.end())
2727 TypeIndex TI = lowerTypePointer(PtrTy,
Options);
2728 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2731TypeIndex CodeViewDebug::getCompleteTypeIndex(
const DIType *Ty) {
2739 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2740 (void)getTypeIndex(Ty);
2741 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2747 case dwarf::DW_TAG_class_type:
2748 case dwarf::DW_TAG_structure_type:
2749 case dwarf::DW_TAG_union_type:
2752 return getTypeIndex(Ty);
2763 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2764 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2769 if (CTy->isForwardDecl())
2776 auto InsertResult = CompleteTypeIndices.try_emplace(CTy);
2777 if (!InsertResult.second)
2778 return InsertResult.first->second;
2781 switch (CTy->getTag()) {
2782 case dwarf::DW_TAG_class_type:
2783 case dwarf::DW_TAG_structure_type:
2784 TI = lowerCompleteTypeClass(CTy);
2786 case dwarf::DW_TAG_union_type:
2787 TI = lowerCompleteTypeUnion(CTy);
2797 CompleteTypeIndices[CTy] = TI;
2805void CodeViewDebug::emitDeferredCompleteTypes() {
2807 while (!DeferredCompleteTypes.empty()) {
2808 std::swap(DeferredCompleteTypes, TypesToEmit);
2809 for (
const DICompositeType *RecordTy : TypesToEmit)
2810 getCompleteTypeIndex(RecordTy);
2811 TypesToEmit.clear();
2815void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2819 for (
const LocalVariable &L : Locals)
2820 if (
L.DIVar->isParameter())
2822 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2823 return L->DIVar->getArg() <
R->DIVar->getArg();
2825 for (
const LocalVariable *L : Params)
2826 emitLocalVariable(FI, *L);
2829 for (
const LocalVariable &L : Locals) {
2830 if (!
L.DIVar->isParameter()) {
2831 if (
L.ConstantValue) {
2834 const DIType *Ty =
L.DIVar->getType();
2836 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2838 emitLocalVariable(FI, L);
2844void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2845 const LocalVariable &Var) {
2847 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2850 if (Var.DIVar->isParameter())
2851 Flags |= LocalSymFlags::IsParameter;
2852 if (Var.DefRanges.empty())
2853 Flags |= LocalSymFlags::IsOptimizedOut;
2855 OS.AddComment(
"TypeIndex");
2856 TypeIndex TI = getCompleteTypeIndex(Var.DIVar->getType());
2858 OS.AddComment(
"Flags");
2859 OS.emitInt16(
static_cast<uint16_t
>(Flags));
2862 endSymbolRecord(LocalEnd);
2867 SmallString<20> BytePrefix;
2868 for (
const auto &Pair : Var.DefRanges) {
2870 const auto &
Ranges = Pair.second;
2872 if (DefRange.InMemory) {
2873 int Offset = DefRange.DataOffset;
2874 unsigned Reg = DefRange.CVRegister;
2880 Reg = unsigned(RegisterId::VFRAME);
2881 Offset += FI.OffsetAdjustment;
2887 uint16_t RegRelFlags = 0;
2888 if (DefRange.IsSubfield) {
2890 (DefRange.StructOffset
2893 DefRangeRegisterRelIndirHeader DRHdr;
2895 DRHdr.
Flags = RegRelFlags;
2898 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2899 }
else if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2900 (
bool(Flags & LocalSymFlags::IsParameter)
2901 ? (EncFP == FI.EncodedParamFramePtrReg)
2902 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2906 DefRangeFramePointerRelHeader DRHdr;
2908 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2910 uint16_t RegRelFlags = 0;
2911 if (DefRange.IsSubfield) {
2913 (DefRange.StructOffset
2916 DefRangeRegisterRelHeader DRHdr;
2918 DRHdr.
Flags = RegRelFlags;
2920 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2923 assert(DefRange.DataOffset == 0 &&
2925 "unexpected offset into register");
2926 if (DefRange.IsSubfield) {
2927 DefRangeSubfieldRegisterHeader DRHdr;
2928 DRHdr.
Register = DefRange.CVRegister;
2931 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2933 DefRangeRegisterHeader DRHdr;
2934 DRHdr.
Register = DefRange.CVRegister;
2936 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2943 const FunctionInfo& FI) {
2944 for (LexicalBlock *
Block : Blocks)
2945 emitLexicalBlock(*
Block, FI);
2950void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2951 const FunctionInfo& FI) {
2952 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2953 OS.AddComment(
"PtrParent");
2955 OS.AddComment(
"PtrEnd");
2957 OS.AddComment(
"Code size");
2958 OS.emitAbsoluteSymbolDiff(
Block.End,
Block.Begin, 4);
2959 OS.AddComment(
"Function section relative address");
2960 OS.emitCOFFSecRel32(
Block.Begin, 0);
2961 OS.AddComment(
"Function section index");
2962 OS.emitCOFFSectionIndex(FI.Begin);
2963 OS.AddComment(
"Lexical block name");
2965 endSymbolRecord(RecordEnd);
2968 emitLocalVariableList(FI,
Block.Locals);
2969 emitGlobalVariableList(
Block.Globals);
2972 emitLexicalBlockList(
Block.Children, FI);
2975 emitEndSymbolRecord(SymbolKind::S_END);
2980void CodeViewDebug::collectLexicalBlockInfo(
2985 for (LexicalScope *Scope : Scopes)
2986 collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
2991void CodeViewDebug::collectLexicalBlockInfo(
2996 if (
Scope.isAbstractScope())
3001 bool IgnoreScope =
false;
3002 auto LI = ScopeVariables.find(&Scope);
3003 SmallVectorImpl<LocalVariable> *
Locals =
3004 LI != ScopeVariables.end() ? &LI->second :
nullptr;
3005 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
3006 SmallVectorImpl<CVGlobalVariable> *Globals =
3007 GI != ScopeGlobals.
end() ? GI->second.get() :
nullptr;
3009 const SmallVectorImpl<InsnRange> &
Ranges =
Scope.getRanges();
3012 if (!Locals && !Globals)
3042 collectLexicalBlockInfo(
Scope.getChildren(),
3052 auto BlockInsertion = CurFn->LexicalBlocks.try_emplace(DILB);
3053 if (!BlockInsertion.second)
3060 LexicalBlock &
Block = BlockInsertion.first->second;
3063 assert(
Block.Begin &&
"missing label for scope begin");
3064 assert(
Block.End &&
"missing label for scope end");
3067 Block.Locals = std::move(*Locals);
3069 Block.Globals = std::move(*Globals);
3071 collectLexicalBlockInfo(
Scope.getChildren(),
3079 assert(FnDebugInfo.count(&GV));
3080 assert(CurFn == FnDebugInfo[&GV].
get());
3086 collectLexicalBlockInfo(*CFS,
3094 ScopeVariables.clear();
3098 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3099 FnDebugInfo.erase(&GV);
3105 for (
const auto &
MBB : *MF) {
3106 for (
const auto &
MI :
MBB) {
3107 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3115 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
3117 collectDebugInfoForJumpTables(MF,
isThumb);
3121 CurFn->End =
Asm->getFunctionEnd();
3131 return DL &&
DL.getLine() != 0;
3138 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3146 for (
const auto &NextMI : *
MI->getParent()) {
3147 if (NextMI.isDebugInstr())
3149 DL = NextMI.getDebugLoc();
3162 maybeRecordLocation(
DL,
Asm->MF);
3175void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3183 if (EE.Value == SymKind)
3189 MCSymbol *BeginLabel =
MMI->getContext().createTempSymbol(),
3190 *EndLabel =
MMI->getContext().createTempSymbol();
3191 OS.AddComment(
"Record length");
3192 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
3193 OS.emitLabel(BeginLabel);
3194 if (OS.isVerboseAsm())
3196 OS.emitInt16(
unsigned(SymKind));
3200void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3205 OS.emitValueToAlignment(
Align(4));
3206 OS.emitLabel(SymEnd);
3209void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3210 OS.AddComment(
"Record length");
3212 if (OS.isVerboseAsm())
3214 OS.emitInt16(uint16_t(EndKind));
3217void CodeViewDebug::emitDebugInfoForUDTs(
3218 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3220 size_t OriginalSize = UDTs.size();
3222 for (
const auto &UDT : UDTs) {
3223 const DIType *
T =
UDT.second;
3225 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3226 OS.AddComment(
"Type");
3227 OS.emitInt32(getCompleteTypeIndex(
T).getIndex());
3228 assert(OriginalSize == UDTs.size() &&
3229 "getCompleteTypeIndex found new UDTs!");
3231 endSymbolRecord(UDTRecordEnd);
3235void CodeViewDebug::collectGlobalVariableInfo() {
3236 DenseMap<const DIGlobalVariableExpression *, const GlobalVariable *>
3238 for (
const GlobalVariable &GV :
MMI->getModule()->globals()) {
3240 GV.getDebugInfo(GVEs);
3241 for (
const auto *GVE : GVEs)
3242 GlobalMap[GVE] = &GV;
3245 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3246 for (
const MDNode *Node : CUs->
operands()) {
3248 for (
const auto *GVE : CU->getGlobalVariables()) {
3249 const DIGlobalVariable *DIGV = GVE->getVariable();
3250 const DIExpression *DIE = GVE->getExpression();
3258 (DIE->
getElement(0) == dwarf::DW_OP_plus_uconst))
3263 CVGlobalVariableOffsets.insert(
3268 CVGlobalVariable CVGV = {DIGV, DIE};
3269 GlobalVariables.emplace_back(std::move(CVGV));
3272 const auto *GV = GlobalMap.
lookup(GVE);
3277 SmallVector<CVGlobalVariable, 1> *VariableList;
3281 auto Insertion = ScopeGlobals.insert(
3282 {
Scope, std::unique_ptr<GlobalVariableList>()});
3283 if (Insertion.second)
3284 Insertion.first->second = std::make_unique<GlobalVariableList>();
3285 VariableList = Insertion.first->second.get();
3288 VariableList = &ComdatVariables;
3291 VariableList = &GlobalVariables;
3292 CVGlobalVariable CVGV = {DIGV, GV};
3298void CodeViewDebug::collectDebugInfoForGlobals() {
3299 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3300 const DIGlobalVariable *DIGV = CVGV.DIGV;
3302 getCompleteTypeIndex(DIGV->
getType());
3303 getFullyQualifiedName(Scope, DIGV->
getName());
3306 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3307 const DIGlobalVariable *DIGV = CVGV.DIGV;
3309 getCompleteTypeIndex(DIGV->
getType());
3310 getFullyQualifiedName(Scope, DIGV->
getName());
3314void CodeViewDebug::emitDebugInfoForGlobals() {
3318 switchToDebugSectionForSymbol(
nullptr);
3319 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3320 OS.AddComment(
"Symbol subsection for globals");
3321 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3322 emitGlobalVariableList(GlobalVariables);
3323 emitStaticConstMemberList();
3324 endCVSubsection(EndLabel);
3329 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3332 OS.AddComment(
"Symbol subsection for " +
3334 switchToDebugSectionForSymbol(GVSym);
3335 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3337 emitDebugInfoForGlobal(CVGV);
3338 endCVSubsection(EndLabel);
3342void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3343 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3344 for (
const MDNode *Node : CUs->
operands()) {
3356 for (
const CVGlobalVariable &CVGV : Globals) {
3358 emitDebugInfoForGlobal(CVGV);
3363 const std::string &QualifiedName) {
3364 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3365 OS.AddComment(
"Type");
3366 OS.emitInt32(getTypeIndex(DTy).getIndex());
3368 OS.AddComment(
"Value");
3373 CodeViewRecordIO IO(Writer);
3375 StringRef SRef((
char *)
Data, Writer.getOffset());
3376 OS.emitBinaryData(SRef);
3378 OS.AddComment(
"Name");
3380 endSymbolRecord(SConstantEnd);
3383void CodeViewDebug::emitStaticConstMemberList() {
3384 for (
const DIDerivedType *DTy : StaticConstMembers) {
3388 if (
const ConstantInt *CI =
3392 else if (
const ConstantFP *CFP =
3394 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3398 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3399 getFullyQualifiedName(Scope, DTy->
getName()));
3409 if (
T == dwarf::DW_TAG_pointer_type ||
3410 T == dwarf::DW_TAG_ptr_to_member_type ||
3411 T == dwarf::DW_TAG_reference_type ||
3412 T == dwarf::DW_TAG_rvalue_reference_type)
3414 assert(DTy->getBaseType() &&
"Expected valid base type");
3419 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3422void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3423 const DIGlobalVariable *DIGV = CVGV.DIGV;
3429 Scope = MemberDecl->getScope();
3435 ? std::string(DIGV->
getName())
3438 if (
const GlobalVariable *GV =
3442 MCSymbol *GVSym = Asm->getSymbol(GV);
3443 SymbolKind DataSym = GV->isThreadLocal()
3444 ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32
3445 : SymbolKind::S_GTHREAD32)
3446 : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32
3447 : SymbolKind::S_GDATA32);
3448 MCSymbol *DataEnd = beginSymbolRecord(DataSym);
3449 OS.AddComment(
"Type");
3450 OS.emitInt32(getCompleteTypeIndex(DIGV->getType()).getIndex());
3451 OS.AddComment(
"DataOffset");
3454 uint64_t Offset = CVGlobalVariableOffsets.lookup(DIGV);
3455 OS.emitCOFFSecRel32(GVSym, Offset);
3457 OS.AddComment(
"Segment");
3458 OS.emitCOFFSectionIndex(GVSym);
3459 OS.AddComment(
"Name");
3460 const unsigned LengthOfDataRecord = 12;
3461 emitNullTerminatedSymbolName(OS, QualifiedName, LengthOfDataRecord);
3462 endSymbolRecord(DataEnd);
3464 const DIExpression *DIE = cast<const DIExpression *>(CVGV.GVInfo);
3465 assert(DIE->isConstant() &&
3466 "Global constant variables must contain a constant expression.");
3469 bool isUnsigned = isFloatDIType(DIGV->getType())
3471 : DebugHandlerBase::isUnsignedDIType(DIGV->getType());
3472 APSInt Value(APInt(64, DIE->getElement(1)), isUnsigned);
3473 emitConstantSymbolRecord(DIGV->getType(), Value, QualifiedName);
3480 int64_t)> &Callback) {
3482 if (JTI && !JTI->isEmpty()) {
3486 for (
const auto &
MBB : *MF) {
3488 const auto LastMI =
MBB.getFirstTerminator();
3489 if (LastMI !=
MBB.end() && LastMI->isIndirectBranch()) {
3497 for (
const auto &MO : LastMI->operands()) {
3499 unsigned Index = MO.getIndex();
3503 Callback(*JTI, *LastMI, Index);
3511 for (
auto I =
MBB.instr_rbegin(),
E =
MBB.instr_rend();
I !=
E; ++
I) {
3512 if (
I->isJumpTableDebugInfo()) {
3513 unsigned Index =
I->getOperand(0).getImm();
3517 Callback(*JTI, *LastMI, Index);
3526 "Some of jump tables were not used in a debug info instruction");
3531void CodeViewDebug::discoverJumpTableBranches(
const MachineFunction *MF,
3535 [
this](
const MachineJumpTableInfo &,
const MachineInstr &BranchMI,
3539void CodeViewDebug::collectDebugInfoForJumpTables(
const MachineFunction *MF,
3543 [
this, MF](
const MachineJumpTableInfo &JTI,
const MachineInstr &BranchMI,
3544 int64_t JumpTableIndex) {
3549 uint64_t BaseOffset = 0;
3557 "EK_Custom32, EK_GPRel32BlockAddress, and "
3558 "EK_GPRel64BlockAddress should never be emitted for COFF");
3561 EntrySize = JumpTableEntrySize::Pointer;
3568 std::tie(
Base, BaseOffset, Branch, EntrySize) =
3569 Asm->getCodeViewJumpTableInfo(JumpTableIndex, &BranchMI, Branch);
3573 const MachineJumpTableEntry &JTE = JTI.
getJumpTables()[JumpTableIndex];
3574 JumpTableInfo CVJTI{EntrySize,
3581 for (
const auto &
MBB : JTE.
MBBs)
3583 CurFn->JumpTables.push_back(std::move(CVJTI));
3587void CodeViewDebug::emitDebugInfoForJumpTables(
const FunctionInfo &FI) {
3589 for (
const auto &JumpTable : FI.JumpTables) {
3590 for (
const auto &CaseSym :
JumpTable.Cases) {
3591 MCSymbol *LabelEnd = beginSymbolRecord(SymbolKind::S_LABEL32);
3592 OS.AddComment(
"Offset and segment");
3593 OS.emitCOFFSecRel32(CaseSym, 0);
3594 OS.AddComment(
"Flags");
3597 endSymbolRecord(LabelEnd);
3601 for (
const auto &JumpTable : FI.JumpTables) {
3602 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3604 OS.AddComment(
"Base offset");
3606 OS.AddComment(
"Base section index");
3607 OS.emitCOFFSectionIndex(
JumpTable.Base);
3609 OS.AddComment(
"Base offset");
3611 OS.AddComment(
"Base section index");
3614 OS.AddComment(
"Switch type");
3615 OS.emitInt16(
static_cast<uint16_t
>(
JumpTable.EntrySize));
3616 OS.AddComment(
"Branch offset");
3617 OS.emitCOFFSecRel32(
JumpTable.Branch, 0);
3618 OS.AddComment(
"Table offset");
3619 OS.emitCOFFSecRel32(
JumpTable.Table, 0);
3620 OS.AddComment(
"Branch section index");
3621 OS.emitCOFFSectionIndex(
JumpTable.Branch);
3622 OS.AddComment(
"Table section index");
3623 OS.emitCOFFSectionIndex(
JumpTable.Table);
3624 OS.AddComment(
"Entries count");
3626 endSymbolRecord(JumpTableEnd);
3630void CodeViewDebug::emitInlinees(
3634 constexpr size_t ChunkSize =
3641 size_t CurrentIndex = 0;
3642 while (CurrentIndex < SortedInlinees.
size()) {
3643 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3644 auto CurrentChunkSize =
3645 std::min(ChunkSize, SortedInlinees.
size() - CurrentIndex);
3646 OS.AddComment(
"Count");
3647 OS.emitInt32(CurrentChunkSize);
3649 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3650 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3651 OS.AddComment(
"Inlinee");
3652 OS.emitInt32(SortedInlinees[CurrentIndex].getIndex());
3654 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.
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
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.
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.
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.
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.
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 StringRef getSymbolName(CVSymbol Sym)
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.
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.
static constexpr int32_t NoDeref
Value for DerefOffset indicating this is not an indirect load.
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.