33#include "llvm/Config/llvm-config.h"
80 "Use the *2 versions for tag records in CodeView (LF_CLASS2, etc.)"),
87 : OS(&OS), TypeTable(TypeTable) {}
89 void emitBytes(StringRef
Data)
override { OS->emitBytes(
Data); }
95 void emitBinaryData(StringRef
Data)
override { OS->emitBinaryData(
Data); }
97 void AddComment(
const Twine &
T)
override { OS->AddComment(
T); }
99 void AddRawComment(
const Twine &
T)
override { OS->emitRawComment(
T); }
101 bool isVerboseAsm()
override {
return OS->isVerboseAsm(); }
109 TypeName = std::string(TypeTable.getTypeName(TI));
115 MCStreamer *OS =
nullptr;
116 TypeCollection &TypeTable;
145 std::string &Filepath = FileToFilepathMap[File];
146 if (!Filepath.empty())
156 Filepath = std::string(Dir);
157 if (Dir.
back() !=
'/')
170 Filepath = (Dir +
"\\" +
Filename).str();
179 while ((Cursor = Filepath.find(
"\\.\\", Cursor)) != std::string::npos)
180 Filepath.erase(Cursor, 2);
185 while ((Cursor = Filepath.find(
"\\..\\", Cursor)) != std::string::npos) {
190 size_t PrevSlash = Filepath.rfind(
'\\', Cursor - 1);
191 if (PrevSlash == std::string::npos)
195 Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
202 while ((Cursor = Filepath.find(
"\\\\", Cursor)) != std::string::npos)
203 Filepath.erase(Cursor, 1);
208unsigned CodeViewDebug::maybeRecordFile(
const DIFile *
F) {
209 StringRef FullPath = getFullFilepath(
F);
210 unsigned NextId = FileIdMap.size() + 1;
211 auto Insertion = FileIdMap.insert(std::make_pair(FullPath, NextId));
212 if (Insertion.second) {
214 ArrayRef<uint8_t> ChecksumAsBytes;
216 if (
F->getChecksum()) {
217 std::string Checksum =
fromHex(
F->getChecksum()->Value);
218 void *CKMem = OS.getContext().allocate(Checksum.size(), 1);
219 memcpy(CKMem, Checksum.data(), Checksum.size());
220 ChecksumAsBytes = ArrayRef<uint8_t>(
221 reinterpret_cast<const uint8_t *
>(CKMem), Checksum.size());
222 switch (
F->getChecksum()->Kind) {
224 CSKind = FileChecksumKind::MD5;
227 CSKind = FileChecksumKind::SHA1;
230 CSKind = FileChecksumKind::SHA256;
234 bool Success = OS.emitCVFileDirective(NextId, FullPath, ChecksumAsBytes,
235 static_cast<unsigned>(CSKind));
239 return Insertion.first->second;
242CodeViewDebug::InlineSite &
243CodeViewDebug::getInlineSite(
const DILocation *InlinedAt,
245 auto SiteInsertion = CurFn->InlineSites.try_emplace(InlinedAt);
246 InlineSite *Site = &SiteInsertion.first->second;
247 if (SiteInsertion.second) {
248 unsigned ParentFuncId = CurFn->FuncId;
249 if (
const DILocation *OuterIA = InlinedAt->getInlinedAt())
251 getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())
254 Site->SiteFuncId = NextFuncId++;
255 OS.emitCVInlineSiteIdDirective(
256 Site->SiteFuncId, ParentFuncId, maybeRecordFile(InlinedAt->getFile()),
257 InlinedAt->getLine(), InlinedAt->getColumn(), SMLoc());
259 InlinedSubprograms.insert(
Inlinee);
260 auto InlineeIdx = getFuncIdForSubprogram(
Inlinee);
262 if (InlinedAt->getInlinedAt() ==
nullptr)
263 CurFn->Inlinees.insert(InlineeIdx);
270 if (!ScopeName.
empty())
273 switch (Scope->getTag()) {
274 case dwarf::DW_TAG_enumeration_type:
275 case dwarf::DW_TAG_class_type:
276 case dwarf::DW_TAG_structure_type:
277 case dwarf::DW_TAG_union_type:
278 return "<unnamed-tag>";
279 case dwarf::DW_TAG_namespace:
280 return "`anonymous namespace'";
286const DISubprogram *CodeViewDebug::collectParentScopeNames(
288 const DISubprogram *ClosestSubprogram =
nullptr;
289 while (Scope !=
nullptr) {
290 if (ClosestSubprogram ==
nullptr)
297 DeferredCompleteTypes.push_back(Ty);
300 if (!ScopeName.
empty())
301 QualifiedNameComponents.
push_back(ScopeName);
304 return ClosestSubprogram;
309 std::string FullyQualifiedName;
312 FullyQualifiedName.append(std::string(QualifiedNameComponent));
313 FullyQualifiedName.append(
"::");
315 FullyQualifiedName.append(std::string(TypeName));
316 return FullyQualifiedName;
324 if (
CVD.TypeEmissionLevel == 1)
325 CVD.emitDeferredCompleteTypes();
326 --
CVD.TypeEmissionLevel;
331std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Scope,
338 collectParentScopeNames(Scope, QualifiedNameComponents);
342std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Ty) {
364 auto I = TypeIndices.find({Scope,
nullptr});
365 if (
I != TypeIndices.end())
369 std::string ScopeName = getFullyQualifiedName(Scope);
370 StringIdRecord SID(TypeIndex(), ScopeName);
371 auto TI = TypeTable.writeLeafType(SID);
372 return recordTypeIndexForDINode(Scope, TI);
378 if (Name.empty() || Name.back() !=
'>')
381 int OpenBrackets = 0;
382 for (
int i = Name.size() - 1; i >= 0; --i) {
385 else if (Name[i] ==
'<') {
387 if (OpenBrackets == 0)
388 return Name.substr(0, i);
394TypeIndex CodeViewDebug::getFuncIdForSubprogram(
const DISubprogram *SP) {
398 auto I = TypeIndices.find({
SP,
nullptr});
399 if (
I != TypeIndices.end())
407 const DIScope *
Scope =
SP->getScope();
413 TypeIndex ClassType = getTypeIndex(Class);
414 MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class),
416 TI = TypeTable.writeLeafType(MFuncId);
419 TypeIndex ParentScope = getScopeIndex(Scope);
420 FuncIdRecord FuncId(ParentScope, getTypeIndex(
SP->getType()), DisplayName);
421 TI = TypeTable.writeLeafType(FuncId);
424 return recordTypeIndexForDINode(SP, TI);
428 return ((DCTy->
getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);
436 const DIType *ReturnTy =
nullptr;
437 if (
auto TypeArray = Ty->getTypeArray()) {
438 if (TypeArray.size())
439 ReturnTy = TypeArray[0];
449 if (ClassTy &&
isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {
458TypeIndex CodeViewDebug::getMemberFunctionType(
const DISubprogram *SP,
462 if (
SP->getDeclaration())
463 SP =
SP->getDeclaration();
464 assert(!
SP->getDeclaration() &&
"should use declaration as key");
468 auto I = TypeIndices.find({
SP,
Class});
469 if (
I != TypeIndices.end())
476 const bool IsStaticMethod = (
SP->getFlags() & DINode::FlagStaticMember) != 0;
479 TypeIndex TI = lowerTypeMemberFunction(
480 SP->getType(), Class,
SP->getThisAdjustment(), IsStaticMethod, FO);
481 return recordTypeIndexForDINode(SP, TI, Class);
484TypeIndex CodeViewDebug::recordTypeIndexForDINode(
const DINode *Node,
487 auto InsertResult = TypeIndices.insert({{
Node, ClassTy}, TI});
489 assert(InsertResult.second &&
"DINode was already assigned a type index");
493unsigned CodeViewDebug::getPointerSizeInBytes() {
494 return MMI->getModule()->getDataLayout().getPointerSizeInBits() / 8;
497void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
499 if (
const DILocation *InlinedAt =
LS->getInlinedAt()) {
501 const DISubprogram *
Inlinee = Var.DIVar->getScope()->getSubprogram();
502 InlineSite &Site = getInlineSite(InlinedAt,
Inlinee);
503 Site.InlinedLocals.emplace_back(std::move(Var));
506 ScopeVariables[
LS].emplace_back(std::move(Var));
516void CodeViewDebug::maybeRecordLocation(
const DebugLoc &
DL,
522 const DIScope *
Scope =
DL->getScope();
527 LineInfo LI(
DL.getLine(),
DL.getLine(),
true);
528 if (LI.getStartLine() !=
DL.getLine() || LI.isAlwaysStepInto() ||
529 LI.isNeverStepInto())
532 ColumnInfo CI(
DL.getCol(), 0);
533 if (CI.getStartColumn() !=
DL.getCol())
536 if (!CurFn->HaveLineInfo)
537 CurFn->HaveLineInfo =
true;
540 FileId = CurFn->LastFileId;
542 FileId = CurFn->LastFileId = maybeRecordFile(
DL->getFile());
545 unsigned FuncId = CurFn->FuncId;
546 if (
const DILocation *SiteLoc =
DL->getInlinedAt()) {
547 const DILocation *Loc =
DL.get();
552 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
555 bool FirstLoc =
true;
556 while ((SiteLoc = Loc->getInlinedAt())) {
558 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
567 OS.emitCVLocDirective(FuncId, FileId,
DL.getLine(),
DL.getCol(),
569 DL->getFilename(), SMLoc());
572void CodeViewDebug::emitCodeViewMagicVersion() {
573 OS.emitValueToAlignment(
Align(4));
574 OS.AddComment(
"Debug section magic");
581 case dwarf::DW_LNAME_C:
582 return SourceLanguage::C;
583 case dwarf::DW_LNAME_C_plus_plus:
584 return SourceLanguage::Cpp;
585 case dwarf::DW_LNAME_Fortran:
586 return SourceLanguage::Fortran;
587 case dwarf::DW_LNAME_Pascal:
588 return SourceLanguage::Pascal;
589 case dwarf::DW_LNAME_Cobol:
590 return SourceLanguage::Cobol;
591 case dwarf::DW_LNAME_Java:
592 return SourceLanguage::Java;
593 case dwarf::DW_LNAME_D:
594 return SourceLanguage::D;
595 case dwarf::DW_LNAME_Swift:
596 return SourceLanguage::Swift;
597 case dwarf::DW_LNAME_Rust:
598 return SourceLanguage::Rust;
599 case dwarf::DW_LNAME_ObjC:
600 return SourceLanguage::ObjC;
601 case dwarf::DW_LNAME_ObjC_plus_plus:
602 return SourceLanguage::ObjCpp;
607 return SourceLanguage::Masm;
621 if (!
Asm->getObjFileLowering().getCOFFDebugSymbolsSection()) {
626 CompilerInfoAsm =
Asm;
631 if (
Asm->hasDebugInfo()) {
632 Node = *M->debug_compile_units_begin();
636 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
646 CurrentSourceLanguage =
652 if (!M->getCodeViewFlag() ||
658 collectGlobalVariableInfo();
663 EmitDebugGlobalHashes = GH && !GH->
isZero();
667 if (!CompilerInfoAsm)
677 switchToDebugSectionForSymbol(
nullptr);
681 emitCompilerInformation();
682 endCVSubsection(CompilerInfo);
686 emitSecureHotPatchInformation();
688 emitInlineeLinesSubsection();
691 for (
auto &
P : FnDebugInfo)
692 if (!
P.first->isDeclarationForLinker())
693 emitDebugInfoForFunction(
P.first, *
P.second);
698 collectDebugInfoForGlobals();
701 emitDebugInfoForRetainedTypes();
704 setCurrentSubprogram(
nullptr);
705 emitDebugInfoForGlobals();
709 switchToDebugSectionForSymbol(
nullptr);
712 if (!GlobalUDTs.empty()) {
714 emitDebugInfoForUDTs(GlobalUDTs);
715 endCVSubsection(SymbolsEnd);
719 OS.AddComment(
"File index to string table offset subsection");
720 OS.emitCVFileChecksumsDirective();
723 OS.AddComment(
"String table");
724 OS.emitCVStringTableDirective();
733 emitTypeInformation();
735 if (EmitDebugGlobalHashes)
736 emitTypeGlobalHashes();
743 unsigned MaxFixedRecordLength = 0xF00) {
754void CodeViewDebug::emitTypeInformation() {
755 if (TypeTable.empty())
759 OS.switchSection(
Asm->getObjFileLowering().getCOFFDebugTypesSection());
760 emitCodeViewMagicVersion();
765 if (!OS.isVerboseAsm()) {
766 for (ArrayRef<uint8_t> Record : TypeTable.records())
771 TypeTableCollection
Table(TypeTable.records());
772 TypeVisitorCallbackPipeline Pipeline;
775 CVMCAdapter CVMCOS(OS,
Table);
776 TypeRecordMapping typeMapping(CVMCOS);
779 std::optional<TypeIndex>
B =
Table.getFirst();
795void CodeViewDebug::emitTypeGlobalHashes() {
796 if (TypeTable.empty())
801 OS.switchSection(
Asm->getObjFileLowering().getCOFFGlobalTypeHashesSection());
803 OS.emitValueToAlignment(
Align(4));
804 OS.AddComment(
"Magic");
806 OS.AddComment(
"Section Version");
808 OS.AddComment(
"Hash Algorithm");
809 OS.emitInt16(uint16_t(GlobalTypeHashAlg::BLAKE3));
812 for (
const auto &GHR : TypeTable.hashes()) {
813 if (OS.isVerboseAsm()) {
817 raw_svector_ostream CommentOS(Comment);
819 OS.AddComment(Comment);
822 assert(GHR.Hash.size() == 8);
823 StringRef S(
reinterpret_cast<const char *
>(GHR.Hash.data()),
825 OS.emitBinaryData(S);
829void CodeViewDebug::emitObjName() {
830 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);
832 StringRef PathRef(CompilerInfoAsm->TM.Options.ObjectFilenameForDebug);
833 llvm::SmallString<256> PathStore(PathRef);
835 if (PathRef.empty() || PathRef ==
"-") {
842 OS.AddComment(
"Signature");
843 OS.emitIntValue(0, 4);
845 OS.AddComment(
"Object name");
848 endSymbolRecord(CompilerEnd);
851void CodeViewDebug::emitSecureHotPatchInformation() {
854 for (
const auto &
F :
MMI->getModule()->functions()) {
855 if (!
F.isDeclarationForLinker() &&
856 F.hasFnAttribute(
"marked_for_windows_hot_patching")) {
857 if (hotPatchInfo ==
nullptr)
858 hotPatchInfo = beginCVSubsection(DebugSubsectionKind::Symbols);
859 MCSymbol *HotPatchEnd = beginSymbolRecord(SymbolKind::S_HOTPATCHFUNC);
860 auto *
SP =
F.getSubprogram();
861 OS.AddComment(
"Function");
862 OS.emitInt32(getFuncIdForSubprogram(SP).getIndex());
863 OS.AddComment(
"Name");
865 endSymbolRecord(HotPatchEnd);
869 if (hotPatchInfo !=
nullptr)
870 endCVSubsection(hotPatchInfo);
884 for (
const char C : Name) {
887 V.Part[
N] +=
C -
'0';
889 std::min<int>(V.Part[
N], std::numeric_limits<uint16_t>::max());
890 }
else if (
C ==
'.') {
900void CodeViewDebug::emitCompilerInformation() {
901 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
905 Flags = CurrentSourceLanguage;
907 if (
MMI->getModule()->getProfileSummary(
false) !=
nullptr) {
908 Flags |=
static_cast<uint32_t
>(CompileSym3Flags::PGO);
912 ArchType Arch =
M->getTargetTriple().getArch();
917 if ((HotpatchFlag && HotpatchFlag->isOne()) || Arch == ArchType::thumb ||
918 Arch == ArchType::aarch64) {
919 Flags |=
static_cast<uint32_t
>(CompileSym3Flags::HotPatch);
922 OS.AddComment(
"Flags and language");
925 OS.AddComment(
"CPUType");
926 OS.emitInt16(
static_cast<uint64_t>(TheCPU));
928 StringRef CompilerVersion =
"0";
930 CompilerVersion = TheCU->getProducer();
933 OS.AddComment(
"Frontend version");
934 for (
int N : FrontVer.Part) {
941 int Major = 1000 * LLVM_VERSION_MAJOR +
942 10 * LLVM_VERSION_MINOR +
945 Major = std::min<int>(Major, std::numeric_limits<uint16_t>::max());
946 Version BackVer = {{ Major, 0, 0, 0 }};
947 OS.AddComment(
"Backend version");
948 for (
int N : BackVer.Part)
951 OS.AddComment(
"Null-terminated compiler version string");
954 endSymbolRecord(CompilerEnd);
963void CodeViewDebug::emitBuildInfo() {
975 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
978 const DIFile *MainSourceFile = CU->getFile();
989 TypeTable,
Asm->TM.Options.MCOptions.CommandlineArgs);
991 BuildInfoRecord BIR(BuildInfoArgs);
992 TypeIndex BuildInfoIndex = TypeTable.writeLeafType(BIR);
996 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
997 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
998 OS.AddComment(
"LF_BUILDINFO index");
999 OS.emitInt32(BuildInfoIndex.
getIndex());
1000 endSymbolRecord(BIEnd);
1001 endCVSubsection(BISubsecEnd);
1004void CodeViewDebug::emitInlineeLinesSubsection() {
1005 if (InlinedSubprograms.empty())
1008 OS.AddComment(
"Inlinee lines subsection");
1009 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
1015 OS.AddComment(
"Inlinee lines signature");
1016 OS.emitInt32(
unsigned(InlineeLinesSignature::Normal));
1018 for (
const DISubprogram *SP : InlinedSubprograms) {
1019 assert(TypeIndices.count({SP, nullptr}));
1020 TypeIndex InlineeIdx = TypeIndices[{
SP,
nullptr}];
1023 unsigned FileId = maybeRecordFile(
SP->getFile());
1024 OS.AddComment(
"Inlined function " +
SP->getName() +
" starts at " +
1025 SP->getFilename() + Twine(
':') + Twine(
SP->getLine()));
1027 OS.AddComment(
"Type index of inlined function");
1028 OS.emitInt32(InlineeIdx.
getIndex());
1029 OS.AddComment(
"Offset into filechecksum table");
1030 OS.emitCVFileChecksumOffsetDirective(FileId);
1031 OS.AddComment(
"Starting line number");
1032 OS.emitInt32(
SP->getLine());
1035 endCVSubsection(InlineEnd);
1038void CodeViewDebug::emitInlinedCallSite(
const FunctionInfo &FI,
1041 assert(TypeIndices.count({Site.Inlinee, nullptr}));
1042 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee,
nullptr}];
1045 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
1047 OS.AddComment(
"PtrParent");
1049 OS.AddComment(
"PtrEnd");
1051 OS.AddComment(
"Inlinee type index");
1052 OS.emitInt32(InlineeIdx.
getIndex());
1054 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
1055 unsigned StartLineNum = Site.Inlinee->getLine();
1057 OS.emitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum,
1060 endSymbolRecord(InlineEnd);
1062 emitLocalVariableList(FI, Site.InlinedLocals);
1065 for (
const DILocation *ChildSite : Site.ChildSites) {
1066 auto I = FI.InlineSites.find(ChildSite);
1067 assert(
I != FI.InlineSites.end() &&
1068 "child site not in function inline site map");
1069 emitInlinedCallSite(FI, ChildSite,
I->second);
1073 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1076void CodeViewDebug::switchToDebugSectionForSymbol(
const MCSymbol *GVSym) {
1080 MCSectionCOFF *GVSec =
1081 GVSym ?
static_cast<MCSectionCOFF *
>(&GVSym->
getSection()) : nullptr;
1084 auto *DebugSec =
static_cast<MCSectionCOFF *
>(
1085 CompilerInfoAsm->getObjFileLowering().getCOFFDebugSymbolsSection());
1086 DebugSec = OS.getContext().getAssociativeCOFFSection(DebugSec, KeySym);
1088 OS.switchSection(DebugSec);
1092 if (ComdatDebugSections.insert(DebugSec).second)
1093 emitCodeViewMagicVersion();
1098void CodeViewDebug::emitDebugInfoForThunk(
const Function *GV,
1101 std::string FuncName =
1105 OS.AddComment(
"Symbol subsection for " + Twine(FuncName));
1106 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1109 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1110 OS.AddComment(
"PtrParent");
1112 OS.AddComment(
"PtrEnd");
1114 OS.AddComment(
"PtrNext");
1116 OS.AddComment(
"Thunk section relative address");
1117 OS.emitCOFFSecRel32(Fn, 0);
1118 OS.AddComment(
"Thunk section index");
1119 OS.emitCOFFSectionIndex(Fn);
1120 OS.AddComment(
"Code size");
1121 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 2);
1122 OS.AddComment(
"Ordinal");
1123 OS.emitInt8(
unsigned(ordinal));
1124 OS.AddComment(
"Function name");
1127 endSymbolRecord(ThunkRecordEnd);
1133 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1135 endCVSubsection(SymbolsEnd);
1138void CodeViewDebug::emitDebugInfoForFunction(
const Function *GV,
1146 switchToDebugSectionForSymbol(Fn);
1148 std::string FuncName;
1151 setCurrentSubprogram(SP);
1153 if (
SP->isThunk()) {
1154 emitDebugInfoForThunk(GV, FI, Fn);
1160 if (!
SP->getName().empty())
1161 FuncName = getFullyQualifiedName(
SP->getScope(),
SP->getName());
1164 if (FuncName.empty())
1168 if (
MMI->getModule()->getTargetTriple().getArch() ==
Triple::x86)
1169 OS.emitCVFPOData(Fn);
1172 OS.AddComment(
"Symbol subsection for " + Twine(FuncName));
1173 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1176 : SymbolKind::S_GPROC32_ID;
1177 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1180 OS.AddComment(
"PtrParent");
1182 OS.AddComment(
"PtrEnd");
1184 OS.AddComment(
"PtrNext");
1188 OS.AddComment(
"Code size");
1189 OS.emitAbsoluteSymbolDiff(FI.End, Fn, 4);
1190 OS.AddComment(
"Offset after prologue");
1192 OS.AddComment(
"Offset before epilogue");
1194 OS.AddComment(
"Function type index");
1195 OS.emitInt32(getFuncIdForSubprogram(GV->
getSubprogram()).getIndex());
1196 OS.AddComment(
"Function section relative address");
1197 OS.emitCOFFSecRel32(Fn, 0);
1198 OS.AddComment(
"Function section index");
1199 OS.emitCOFFSectionIndex(Fn);
1200 OS.AddComment(
"Flags");
1201 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;
1202 if (FI.HasFramePointer)
1203 ProcFlags |= ProcSymFlags::HasFP;
1205 ProcFlags |= ProcSymFlags::IsNoReturn;
1207 ProcFlags |= ProcSymFlags::IsNoInline;
1208 OS.emitInt8(
static_cast<uint8_t
>(ProcFlags));
1210 OS.AddComment(
"Function name");
1213 endSymbolRecord(ProcRecordEnd);
1215 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1217 OS.AddComment(
"FrameSize");
1218 OS.emitInt32(FI.FrameSize - FI.CSRSize);
1219 OS.AddComment(
"Padding");
1221 OS.AddComment(
"Offset of padding");
1223 OS.AddComment(
"Bytes of callee saved registers");
1224 OS.emitInt32(FI.CSRSize);
1225 OS.AddComment(
"Exception handler offset");
1227 OS.AddComment(
"Exception handler section");
1229 OS.AddComment(
"Flags (defines frame register)");
1230 OS.emitInt32(uint32_t(FI.FrameProcOpts));
1231 endSymbolRecord(FrameProcEnd);
1233 emitInlinees(FI.Inlinees);
1234 emitLocalVariableList(FI, FI.Locals);
1235 emitGlobalVariableList(FI.Globals);
1236 emitLexicalBlockList(FI.ChildBlocks, FI);
1241 for (
const DILocation *InlinedAt : FI.ChildSites) {
1242 auto I = FI.InlineSites.find(InlinedAt);
1243 assert(
I != FI.InlineSites.end() &&
1244 "child site not in function inline site map");
1245 emitInlinedCallSite(FI, InlinedAt,
I->second);
1248 for (
auto Annot : FI.Annotations) {
1251 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1252 OS.emitCOFFSecRel32(Label, 0);
1254 OS.emitCOFFSectionIndex(Label);
1260 assert(Str.data()[Str.size()] ==
'\0' &&
"non-nullterminated MDString");
1261 OS.emitBytes(StringRef(Str.data(), Str.size() + 1));
1263 endSymbolRecord(AnnotEnd);
1266 for (
auto HeapAllocSite : FI.HeapAllocSites) {
1267 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1268 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1269 const DIType *DITy = std::get<2>(HeapAllocSite);
1270 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1271 OS.AddComment(
"Call site offset");
1272 OS.emitCOFFSecRel32(BeginLabel, 0);
1273 OS.AddComment(
"Call site section index");
1274 OS.emitCOFFSectionIndex(BeginLabel);
1275 OS.AddComment(
"Call instruction length");
1276 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
1277 OS.AddComment(
"Type index");
1278 OS.emitInt32(getCompleteTypeIndex(DITy).getIndex());
1279 endSymbolRecord(HeapAllocEnd);
1283 emitDebugInfoForUDTs(LocalUDTs);
1285 emitDebugInfoForJumpTables(FI);
1288 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1290 endCVSubsection(SymbolsEnd);
1293 OS.emitCVLinetableDirective(FI.FuncId, Fn, FI.End);
1297CodeViewDebug::createDefRangeMem(uint16_t CVRegister,
int Offset,
1298 int32_t DerefOffset) {
1304 DR.StructOffset = 0;
1305 DR.CVRegister = CVRegister;
1306 DR.DerefOffset = DerefOffset;
1310void CodeViewDebug::collectVariableInfoFromMFTable(
1317 for (
const MachineFunction::VariableDbgInfo &VI :
1321 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1322 "Expected inlined-at fields to agree");
1324 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1332 int64_t ExprOffset = 0;
1336 if (!
VI.Expr->extractLeadingOffset(ExprOffset, FirstRemaining))
1338 if (!FirstRemaining.
empty()) {
1339 if (FirstRemaining.
front() != dwarf::DW_OP_deref)
1341 SmallVector<uint64_t, 1> LastRemaining;
1343 ArrayRef(FirstRemaining).drop_front(), DerefOffset,
1346 if (!LastRemaining.
empty())
1353 StackOffset FrameOffset =
1355 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1361 if (DerefOffset < INT32_MIN || DerefOffset > INT32_MAX)
1366 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset,
1367 static_cast<int32_t
>(DerefOffset));
1376 Var.DefRanges[DefRange].emplace_back(Begin,
End);
1379 recordLocalVariable(std::move(Var), Scope);
1383void CodeViewDebug::calculateRanges(
1385 const TargetRegisterInfo *
TRI =
Asm->MF->getSubtarget().getRegisterInfo();
1388 for (
auto I = Entries.
begin(),
E = Entries.
end();
I !=
E; ++
I) {
1390 if (!
Entry.isDbgValue())
1392 const MachineInstr *DVInst =
Entry.getInstr();
1396 std::optional<DbgVariableLocation>
Location =
1407 Var.ConstantValue =
APSInt(APInt(64,
Op.getImm()),
false);
1419 if (
Location->FragmentInfo->OffsetInBits % 8)
1429 DR.InMemory = !
Location->LoadChain.empty();
1432 if (!
Location->LoadChain.empty()) {
1433 DR.DataOffset =
Location->LoadChain[0];
1434 if (
Location->LoadChain.size() >= 2)
1435 DR.DerefOffset =
Location->LoadChain[1];
1438 DR.IsSubfield =
true;
1439 DR.StructOffset =
Location->FragmentInfo->OffsetInBits / 8;
1441 DR.IsSubfield =
false;
1442 DR.StructOffset = 0;
1449 auto &EndingEntry = Entries[
Entry.getEndIndex()];
1450 End = EndingEntry.isDbgValue()
1454 End =
Asm->getFunctionEnd();
1458 SmallVectorImpl<std::pair<const MCSymbol *, const MCSymbol *>> &
R =
1460 if (!
R.empty() &&
R.back().second == Begin)
1461 R.back().second =
End;
1463 R.emplace_back(Begin,
End);
1469void CodeViewDebug::collectVariableInfo(
const DISubprogram *SP) {
1470 DenseSet<InlinedEntity> Processed;
1472 collectVariableInfoFromMFTable(Processed);
1474 for (
const MDNode *
N :
SP->getRetainedNodes())
1476 collectGlobalOrStaticLocalVariableInfo(GVE);
1479 InlinedEntity
IV =
I.first;
1483 const DILocation *InlinedAt =
IV.second;
1486 const auto &Entries =
I.second;
1488 LexicalScope *
Scope =
nullptr;
1500 calculateRanges(Var, Entries);
1501 recordLocalVariable(std::move(Var), Scope);
1510 auto Insertion = FnDebugInfo.
insert({&GV, std::make_unique<FunctionInfo>()});
1511 assert(Insertion.second &&
"function already has info");
1512 CurFn = Insertion.first->second.get();
1513 CurFn->FuncId = NextFuncId++;
1514 CurFn->Begin =
Asm->getFunctionBegin();
1522 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1528 if (CurFn->FrameSize > 0) {
1533 CurFn->HasFramePointer =
true;
1536 if (CurFn->HasStackRealignment) {
1587 CurFn->FrameProcOpts = FPO;
1589 OS.emitCVFuncIdDirective(CurFn->FuncId);
1596 bool EmptyPrologue =
true;
1597 for (
const auto &
MBB : *MF) {
1598 for (
const auto &
MI :
MBB) {
1603 }
else if (!
MI.isMetaInstruction()) {
1604 EmptyPrologue =
false;
1612 maybeRecordLocation(FnStartDL, MF);
1616 for (
const auto &
MBB : *MF) {
1617 for (
const auto &
MI :
MBB) {
1618 if (
MI.getHeapAllocMarker()) {
1626 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
1628 discoverJumpTableBranches(MF,
isThumb);
1636 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1637 if (
DIScope *Scope =
T->getScope()) {
1638 switch (Scope->getTag()) {
1639 case dwarf::DW_TAG_structure_type:
1640 case dwarf::DW_TAG_class_type:
1641 case dwarf::DW_TAG_union_type:
1651 if (!
T ||
T->isForwardDecl())
1657 T = DT->getBaseType();
1662void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1670 const DISubprogram *ClosestSubprogram =
1671 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1673 std::string FullyQualifiedName =
1676 if (ClosestSubprogram ==
nullptr) {
1677 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1678 }
else if (ClosestSubprogram == CurrentSubprogram) {
1679 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1690TypeIndex CodeViewDebug::lowerType(
const DIType *Ty,
const DIType *ClassTy) {
1693 case dwarf::DW_TAG_array_type:
1695 case dwarf::DW_TAG_typedef:
1697 case dwarf::DW_TAG_base_type:
1699 case dwarf::DW_TAG_pointer_type:
1703 case dwarf::DW_TAG_reference_type:
1704 case dwarf::DW_TAG_rvalue_reference_type:
1706 case dwarf::DW_TAG_ptr_to_member_type:
1708 case dwarf::DW_TAG_restrict_type:
1709 case dwarf::DW_TAG_const_type:
1710 case dwarf::DW_TAG_volatile_type:
1713 case dwarf::DW_TAG_subroutine_type:
1722 case dwarf::DW_TAG_enumeration_type:
1724 case dwarf::DW_TAG_class_type:
1725 case dwarf::DW_TAG_structure_type:
1727 case dwarf::DW_TAG_union_type:
1729 case dwarf::DW_TAG_string_type:
1731 case dwarf::DW_TAG_unspecified_type:
1732 if (Ty->
getName() ==
"decltype(nullptr)")
1741TypeIndex CodeViewDebug::lowerTypeAlias(
const DIDerivedType *Ty) {
1742 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1747 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) &&
1748 TypeName ==
"HRESULT")
1749 return TypeIndex(SimpleTypeKind::HResult);
1750 if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::UInt16Short) &&
1751 TypeName ==
"wchar_t")
1752 return TypeIndex(SimpleTypeKind::WideCharacter);
1754 return UnderlyingTypeIndex;
1759 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1761 TypeIndex IndexType = getPointerSizeInBytes() == 8
1762 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1769 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1770 const DINode *Element =
Elements[i];
1771 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1781 Count = CI->getSExtValue();
1787 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1788 Count = UI->getSExtValue() - Lowerbound + 1;
1799 ElementSize *=
Count;
1804 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1807 ArrayRecord AR(ElementTypeIndex, IndexType, ArraySize, Name);
1808 ElementTypeIndex = TypeTable.writeLeafType(AR);
1811 return ElementTypeIndex;
1819TypeIndex CodeViewDebug::lowerTypeString(
const DIStringType *Ty) {
1820 TypeIndex CharType = TypeIndex(SimpleTypeKind::NarrowCharacter);
1824 TypeIndex IndexType = getPointerSizeInBytes() == 8
1825 ? TypeIndex(SimpleTypeKind::UInt64Quad)
1829 ArrayRecord AR(CharType, IndexType, ArraySize, Name);
1831 return TypeTable.writeLeafType(AR);
1834TypeIndex CodeViewDebug::lowerTypeBasic(
const DIBasicType *Ty) {
1844 case dwarf::DW_ATE_address:
1847 case dwarf::DW_ATE_boolean:
1849 case 1: STK = SimpleTypeKind::Boolean8;
break;
1850 case 2: STK = SimpleTypeKind::Boolean16;
break;
1851 case 4: STK = SimpleTypeKind::Boolean32;
break;
1852 case 8: STK = SimpleTypeKind::Boolean64;
break;
1853 case 16: STK = SimpleTypeKind::Boolean128;
break;
1856 case dwarf::DW_ATE_complex_float:
1860 case 4: STK = SimpleTypeKind::Complex16;
break;
1861 case 8: STK = SimpleTypeKind::Complex32;
break;
1862 case 16: STK = SimpleTypeKind::Complex64;
break;
1863 case 20: STK = SimpleTypeKind::Complex80;
break;
1864 case 32: STK = SimpleTypeKind::Complex128;
break;
1867 case dwarf::DW_ATE_float:
1869 case 2: STK = SimpleTypeKind::Float16;
break;
1870 case 4: STK = SimpleTypeKind::Float32;
break;
1871 case 6: STK = SimpleTypeKind::Float48;
break;
1872 case 8: STK = SimpleTypeKind::Float64;
break;
1873 case 10: STK = SimpleTypeKind::Float80;
break;
1874 case 16: STK = SimpleTypeKind::Float128;
break;
1877 case dwarf::DW_ATE_signed:
1879 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1880 case 2: STK = SimpleTypeKind::Int16Short;
break;
1881 case 4: STK = SimpleTypeKind::Int32;
break;
1882 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1883 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1886 case dwarf::DW_ATE_unsigned:
1888 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1889 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1890 case 4: STK = SimpleTypeKind::UInt32;
break;
1891 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1892 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1895 case dwarf::DW_ATE_UTF:
1897 case 1: STK = SimpleTypeKind::Character8;
break;
1898 case 2: STK = SimpleTypeKind::Character16;
break;
1899 case 4: STK = SimpleTypeKind::Character32;
break;
1902 case dwarf::DW_ATE_signed_char:
1904 STK = SimpleTypeKind::SignedCharacter;
1906 case dwarf::DW_ATE_unsigned_char:
1908 STK = SimpleTypeKind::UnsignedCharacter;
1918 if (STK == SimpleTypeKind::Int32 &&
1920 STK = SimpleTypeKind::Int32Long;
1921 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1922 Ty->
getName() ==
"unsigned long"))
1923 STK = SimpleTypeKind::UInt32Long;
1924 if (STK == SimpleTypeKind::UInt16Short &&
1926 STK = SimpleTypeKind::WideCharacter;
1927 if ((STK == SimpleTypeKind::SignedCharacter ||
1928 STK == SimpleTypeKind::UnsignedCharacter) &&
1930 STK = SimpleTypeKind::NarrowCharacter;
1932 return TypeIndex(STK);
1935TypeIndex CodeViewDebug::lowerTypePointer(
const DIDerivedType *Ty,
1937 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1941 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1943 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1945 ? SimpleTypeMode::NearPointer64
1946 : SimpleTypeMode::NearPointer32;
1951 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1955 case dwarf::DW_TAG_pointer_type:
1956 PM = PointerMode::Pointer;
1958 case dwarf::DW_TAG_reference_type:
1959 PM = PointerMode::LValueReference;
1961 case dwarf::DW_TAG_rvalue_reference_type:
1962 PM = PointerMode::RValueReference;
1967 PO |= PointerOptions::Const;
1969 PointerRecord PR(PointeeTI, PK, PM, PO, Ty->
getSizeInBits() / 8);
1970 return TypeTable.writeLeafType(PR);
1983 case DINode::FlagSingleInheritance:
1985 case DINode::FlagMultipleInheritance:
1987 case DINode::FlagVirtualInheritance:
1995 case DINode::FlagSingleInheritance:
1997 case DINode::FlagMultipleInheritance:
1999 case DINode::FlagVirtualInheritance:
2006TypeIndex CodeViewDebug::lowerTypeMemberPointer(
const DIDerivedType *Ty,
2008 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
2011 TypeIndex PointeeTI =
2012 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->
getClassType() :
nullptr);
2013 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2014 : PointerKind::Near32;
2015 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
2016 : PointerMode::PointerToDataMember;
2020 MemberPointerInfo MPI(
2022 PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);
2023 return TypeTable.writeLeafType(PR);
2040TypeIndex CodeViewDebug::lowerTypeModifier(
const DIDerivedType *Ty) {
2044 const DIType *BaseTy = Ty;
2045 while (IsModifier && BaseTy) {
2047 switch (BaseTy->
getTag()) {
2048 case dwarf::DW_TAG_const_type:
2049 Mods |= ModifierOptions::Const;
2050 PO |= PointerOptions::Const;
2052 case dwarf::DW_TAG_volatile_type:
2053 Mods |= ModifierOptions::Volatile;
2054 PO |= PointerOptions::Volatile;
2056 case dwarf::DW_TAG_restrict_type:
2059 PO |= PointerOptions::Restrict;
2074 switch (BaseTy->
getTag()) {
2075 case dwarf::DW_TAG_pointer_type:
2076 case dwarf::DW_TAG_reference_type:
2077 case dwarf::DW_TAG_rvalue_reference_type:
2079 case dwarf::DW_TAG_ptr_to_member_type:
2086 TypeIndex ModifiedTI = getTypeIndex(BaseTy);
2090 if (Mods == ModifierOptions::None)
2093 ModifierRecord MR(ModifiedTI, Mods);
2094 return TypeTable.writeLeafType(MR);
2100 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2103 if (ReturnAndArgTypeIndices.
size() > 1 &&
2109 if (!ReturnAndArgTypeIndices.
empty()) {
2110 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2111 ReturnTypeIndex = ReturnAndArgTypesRef.consume_front();
2112 ArgTypeIndices = ReturnAndArgTypesRef;
2115 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2116 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2121 ProcedureRecord Procedure(ReturnTypeIndex, CC, FO, ArgTypeIndices.
size(),
2123 return TypeTable.writeLeafType(Procedure);
2126TypeIndex CodeViewDebug::lowerTypeMemberFunction(
const DISubroutineType *Ty,
2129 bool IsStaticMethod,
2132 TypeIndex ClassType = getTypeIndex(ClassTy);
2139 if (ReturnAndArgs.size() > Index) {
2140 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
2146 TypeIndex ThisTypeIndex;
2147 if (!IsStaticMethod && ReturnAndArgs.size() > Index) {
2148 if (
const DIDerivedType *PtrTy =
2150 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2151 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2157 while (Index < ReturnAndArgs.size())
2158 ArgTypeIndices.
push_back(getTypeIndex(ReturnAndArgs[Index++]));
2164 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2165 TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
2169 MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FO,
2170 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2171 return TypeTable.writeLeafType(MFR);
2174TypeIndex CodeViewDebug::lowerTypeVFTableShape(
const DIDerivedType *Ty) {
2175 unsigned VSlotCount =
2179 VFTableShapeRecord VFTSR(Slots);
2180 return TypeTable.writeLeafType(VFTSR);
2197 if (SP->isArtificial())
2207 if (SP->getFlags() & DINode::FlagStaticMember)
2210 switch (SP->getVirtuality()) {
2211 case dwarf::DW_VIRTUALITY_none:
2213 case dwarf::DW_VIRTUALITY_virtual:
2215 case dwarf::DW_VIRTUALITY_pure_virtual:
2226 switch (Ty->getTag()) {
2227 case dwarf::DW_TAG_class_type:
2228 return UseTagRecord2 ? TypeRecordKind::Class2 : TypeRecordKind::Class;
2229 case dwarf::DW_TAG_structure_type:
2230 return UseTagRecord2 ? TypeRecordKind::Struct2 : TypeRecordKind::Struct;
2244 if (!Ty->getIdentifier().empty())
2258 if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) {
2262 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2274void CodeViewDebug::addUDTSrcLine(
const DIType *Ty, TypeIndex TI) {
2276 case dwarf::DW_TAG_class_type:
2277 case dwarf::DW_TAG_structure_type:
2278 case dwarf::DW_TAG_union_type:
2279 case dwarf::DW_TAG_enumeration_type:
2285 if (
const auto *File = Ty->
getFile()) {
2286 StringIdRecord SIDR(TypeIndex(0x0), getFullFilepath(File));
2287 TypeIndex SIDI = TypeTable.writeLeafType(SIDR);
2289 UdtSourceLineRecord USLR(TI, SIDI, Ty->
getLine());
2290 TypeTable.writeLeafType(USLR);
2297 unsigned EnumeratorCount = 0;
2300 CO |= ClassOptions::ForwardReference;
2302 ContinuationRecordBuilder ContinuationBuilder;
2303 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2308 EnumeratorRecord ER(
2309 MemberAccess::Public,
2316 FTI = TypeTable.insertRecord(ContinuationBuilder);
2319 std::string FullName = getFullyQualifiedName(Ty);
2321 EnumRecord ER(EnumeratorCount, CO, FTI, FullName, Ty->
getIdentifier(),
2323 TypeIndex EnumTI = TypeTable.writeLeafType(ER);
2325 addUDTSrcLine(Ty, EnumTI);
2359void CodeViewDebug::clear() {
2360 assert(CurFn ==
nullptr);
2362 FnDebugInfo.clear();
2363 FileToFilepathMap.clear();
2366 TypeIndices.clear();
2367 CompleteTypeIndices.clear();
2368 ScopeGlobals.clear();
2369 CVGlobalVariableOffsets.clear();
2372void CodeViewDebug::collectMemberInfo(
ClassInfo &Info,
2375 Info.Members.push_back({DDTy, 0});
2378 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2379 DINode::FlagStaticMember) {
2382 StaticConstMembers.push_back(DDTy);
2394 const DIType *Ty = DDTy->getBaseType();
2395 bool FullyResolved =
false;
2396 while (!FullyResolved) {
2398 case dwarf::DW_TAG_const_type:
2399 case dwarf::DW_TAG_volatile_type:
2405 FullyResolved =
true;
2414 ClassInfo NestedInfo = collectClassInfo(DCTy);
2415 for (
const ClassInfo::MemberInfo &IndirectField : NestedInfo.
Members)
2416 Info.Members.push_back(
2424 for (
auto *Element : Elements) {
2430 Info.Methods[
SP->getRawName()].push_back(SP);
2432 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2433 collectMemberInfo(Info, DDTy);
2434 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2435 Info.Inheritance.push_back(DDTy);
2436 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2437 DDTy->
getName() ==
"__vtbl_ptr_type") {
2438 Info.VShapeTI = getTypeIndex(DDTy);
2439 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2440 Info.NestedTypes.push_back(DDTy);
2441 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2446 Info.NestedTypes.push_back(Composite);
2456 return Ty->getName().empty() && Ty->getIdentifier().empty() &&
2457 !Ty->isForwardDecl();
2469 auto I = CompleteTypeIndices.find(Ty);
2470 if (
I != CompleteTypeIndices.end() &&
I->second == TypeIndex())
2472 return getCompleteTypeIndex(Ty);
2480 std::string FullName = getFullyQualifiedName(Ty);
2481 ClassRecord CR(Kind, 0, CO, TypeIndex(), TypeIndex(), TypeIndex(), 0,
2483 TypeIndex FwdDeclTI = TypeTable.writeLeafType(CR);
2485 DeferredCompleteTypes.push_back(Ty);
2489TypeIndex CodeViewDebug::lowerCompleteTypeClass(
const DICompositeType *Ty) {
2495 unsigned FieldCount;
2498 lowerRecordFieldList(Ty);
2501 CO |= ClassOptions::ContainsNestedClass;
2509 CO |= ClassOptions::HasConstructorOrDestructor;
2511 std::string FullName = getFullyQualifiedName(Ty);
2515 ClassRecord CR(Kind, FieldCount, CO, FieldTI, TypeIndex(), VShapeTI,
2517 TypeIndex ClassTI = TypeTable.writeLeafType(CR);
2519 addUDTSrcLine(Ty, ClassTI);
2529 return getCompleteTypeIndex(Ty);
2533 std::string FullName = getFullyQualifiedName(Ty);
2535 UseTagRecord2 ? TypeRecordKind::Union2 : TypeRecordKind::Union;
2536 UnionRecord UR(Kind, 0, CO, TypeIndex(), 0, FullName, Ty->
getIdentifier());
2537 TypeIndex FwdDeclTI = TypeTable.writeLeafType(UR);
2539 DeferredCompleteTypes.push_back(Ty);
2543TypeIndex CodeViewDebug::lowerCompleteTypeUnion(
const DICompositeType *Ty) {
2546 unsigned FieldCount;
2549 lowerRecordFieldList(Ty);
2552 CO |= ClassOptions::ContainsNestedClass;
2555 std::string FullName = getFullyQualifiedName(Ty);
2558 UseTagRecord2 ? TypeRecordKind::Union2 : TypeRecordKind::Union;
2559 UnionRecord UR(Kind, FieldCount, CO, FieldTI, SizeInBytes, FullName,
2561 TypeIndex UnionTI = TypeTable.writeLeafType(UR);
2563 addUDTSrcLine(Ty, UnionTI);
2570std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2576 unsigned MemberCount = 0;
2577 ClassInfo
Info = collectClassInfo(Ty);
2578 ContinuationRecordBuilder ContinuationBuilder;
2579 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2582 for (
const DIDerivedType *
I :
Info.Inheritance) {
2583 if (
I->getFlags() & DINode::FlagVirtual) {
2585 unsigned VBPtrOffset =
I->getVBPtrOffset();
2587 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2588 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2589 ? TypeRecordKind::IndirectVirtualBaseClass
2590 : TypeRecordKind::VirtualBaseClass;
2591 VirtualBaseClassRecord VBCR(
2593 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2599 assert(
I->getOffsetInBits() % 8 == 0 &&
2600 "bases must be on byte boundaries");
2602 getTypeIndex(
I->getBaseType()),
2603 I->getOffsetInBits() / 8);
2610 for (ClassInfo::MemberInfo &MemberInfo :
Info.Members) {
2612 TypeIndex MemberBaseType = getTypeIndex(
Member->getBaseType());
2613 StringRef MemberName =
Member->getName();
2617 if (
Member->isStaticMember()) {
2618 StaticDataMemberRecord SDMR(
Access, MemberBaseType, MemberName);
2625 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2626 Member->getName().starts_with(
"_vptr$")) {
2627 VFPtrRecord VFPR(getTypeIndex(
Member->getBaseType()));
2636 if (
Member->isBitField()) {
2637 uint64_t StartBitOffset = MemberOffsetInBits;
2638 if (
const auto *CI =
2640 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2642 StartBitOffset -= MemberOffsetInBits;
2643 BitFieldRecord BFR(MemberBaseType,
Member->getSizeInBits(),
2645 MemberBaseType = TypeTable.writeLeafType(BFR);
2647 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2648 DataMemberRecord DMR(
Access, MemberBaseType, MemberOffsetInBytes,
2655 for (
auto &MethodItr :
Info.Methods) {
2656 StringRef
Name = MethodItr.first->getString();
2658 std::vector<OneMethodRecord> Methods;
2659 for (
const DISubprogram *SP : MethodItr.second) {
2660 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2661 bool Introduced =
SP->getFlags() & DINode::FlagIntroducedVirtual;
2663 unsigned VFTableOffset = -1;
2665 VFTableOffset =
SP->getVirtualIndex() * getPointerSizeInBytes();
2667 Methods.push_back(OneMethodRecord(
2673 assert(!Methods.empty() &&
"Empty methods map entry");
2674 if (Methods.size() == 1)
2679 MethodOverloadListRecord MOLR(Methods);
2680 TypeIndex MethodList = TypeTable.writeLeafType(MOLR);
2682 OverloadedMethodRecord OMR(Methods.size(), MethodList, Name);
2688 for (
const DIType *
Nested :
Info.NestedTypes) {
2689 NestedTypeRecord
R(getTypeIndex(
Nested),
Nested->getName());
2694 TypeIndex FieldTI = TypeTable.insertRecord(ContinuationBuilder);
2695 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2696 !
Info.NestedTypes.empty());
2699TypeIndex CodeViewDebug::getVBPTypeIndex() {
2700 if (!VBPType.getIndex()) {
2703 TypeIndex ModifiedTI = TypeTable.writeLeafType(MR);
2705 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2706 : PointerKind::Near32;
2709 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2710 VBPType = TypeTable.writeLeafType(PR);
2716TypeIndex CodeViewDebug::getTypeIndex(
const DIType *Ty,
const DIType *ClassTy) {
2724 auto I = TypeIndices.find({Ty, ClassTy});
2725 if (
I != TypeIndices.end())
2729 TypeIndex TI = lowerType(Ty, ClassTy);
2730 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2734CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2736 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2737 "this type must be a pointer type");
2740 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2741 Options = PointerOptions::LValueRefThisPointer;
2742 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2743 Options = PointerOptions::RValueRefThisPointer;
2750 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2751 if (
I != TypeIndices.end())
2755 TypeIndex TI = lowerTypePointer(PtrTy,
Options);
2756 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2759TypeIndex CodeViewDebug::getCompleteTypeIndex(
const DIType *Ty) {
2767 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2768 (void)getTypeIndex(Ty);
2769 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2775 case dwarf::DW_TAG_class_type:
2776 case dwarf::DW_TAG_structure_type:
2777 case dwarf::DW_TAG_union_type:
2780 return getTypeIndex(Ty);
2791 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2792 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2797 if (CTy->isForwardDecl())
2804 auto InsertResult = CompleteTypeIndices.try_emplace(CTy);
2805 if (!InsertResult.second)
2806 return InsertResult.first->second;
2809 switch (CTy->getTag()) {
2810 case dwarf::DW_TAG_class_type:
2811 case dwarf::DW_TAG_structure_type:
2812 TI = lowerCompleteTypeClass(CTy);
2814 case dwarf::DW_TAG_union_type:
2815 TI = lowerCompleteTypeUnion(CTy);
2825 CompleteTypeIndices[CTy] = TI;
2833void CodeViewDebug::emitDeferredCompleteTypes() {
2835 while (!DeferredCompleteTypes.empty()) {
2836 std::swap(DeferredCompleteTypes, TypesToEmit);
2837 for (
const DICompositeType *RecordTy : TypesToEmit)
2838 getCompleteTypeIndex(RecordTy);
2839 TypesToEmit.clear();
2843void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2847 for (
const LocalVariable &L : Locals)
2848 if (
L.DIVar->isParameter())
2850 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2851 return L->DIVar->getArg() <
R->DIVar->getArg();
2853 for (
const LocalVariable *L : Params)
2854 emitLocalVariable(FI, *L);
2857 for (
const LocalVariable &L : Locals) {
2858 if (!
L.DIVar->isParameter()) {
2859 if (
L.ConstantValue) {
2862 const DIType *Ty =
L.DIVar->getType();
2864 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2866 emitLocalVariable(FI, L);
2872void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2873 const LocalVariable &Var) {
2875 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2878 if (Var.DIVar->isParameter())
2879 Flags |= LocalSymFlags::IsParameter;
2880 if (Var.DefRanges.empty())
2881 Flags |= LocalSymFlags::IsOptimizedOut;
2883 OS.AddComment(
"TypeIndex");
2884 TypeIndex TI = getCompleteTypeIndex(Var.DIVar->getType());
2886 OS.AddComment(
"Flags");
2887 OS.emitInt16(
static_cast<uint16_t
>(Flags));
2890 endSymbolRecord(LocalEnd);
2895 SmallString<20> BytePrefix;
2896 for (
const auto &Pair : Var.DefRanges) {
2898 const auto &
Ranges = Pair.second;
2900 if (DefRange.InMemory) {
2901 int Offset = DefRange.DataOffset;
2902 unsigned Reg = DefRange.CVRegister;
2908 Reg = unsigned(RegisterId::VFRAME);
2909 Offset += FI.OffsetAdjustment;
2915 uint16_t RegRelFlags = 0;
2916 if (DefRange.IsSubfield) {
2918 (DefRange.StructOffset
2921 DefRangeRegisterRelIndirHeader DRHdr;
2923 DRHdr.
Flags = RegRelFlags;
2926 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2927 }
else if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2928 (
bool(Flags & LocalSymFlags::IsParameter)
2929 ? (EncFP == FI.EncodedParamFramePtrReg)
2930 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2934 DefRangeFramePointerRelHeader DRHdr;
2936 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2938 uint16_t RegRelFlags = 0;
2939 if (DefRange.IsSubfield) {
2941 (DefRange.StructOffset
2944 DefRangeRegisterRelHeader DRHdr;
2946 DRHdr.
Flags = RegRelFlags;
2948 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2951 assert(DefRange.DataOffset == 0 &&
2953 "unexpected offset into register");
2954 if (DefRange.IsSubfield) {
2955 DefRangeSubfieldRegisterHeader DRHdr;
2956 DRHdr.
Register = DefRange.CVRegister;
2959 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2961 DefRangeRegisterHeader DRHdr;
2962 DRHdr.
Register = DefRange.CVRegister;
2964 OS.emitCVDefRangeDirective(Ranges, DRHdr);
2971 const FunctionInfo& FI) {
2972 for (LexicalBlock *
Block : Blocks)
2973 emitLexicalBlock(*
Block, FI);
2978void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2979 const FunctionInfo& FI) {
2980 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2981 OS.AddComment(
"PtrParent");
2983 OS.AddComment(
"PtrEnd");
2985 OS.AddComment(
"Code size");
2986 OS.emitAbsoluteSymbolDiff(
Block.End,
Block.Begin, 4);
2987 OS.AddComment(
"Function section relative address");
2988 OS.emitCOFFSecRel32(
Block.Begin, 0);
2989 OS.AddComment(
"Function section index");
2990 OS.emitCOFFSectionIndex(FI.Begin);
2991 OS.AddComment(
"Lexical block name");
2993 endSymbolRecord(RecordEnd);
2996 emitLocalVariableList(FI,
Block.Locals);
2997 emitGlobalVariableList(
Block.Globals);
3000 emitLexicalBlockList(
Block.Children, FI);
3003 emitEndSymbolRecord(SymbolKind::S_END);
3008void CodeViewDebug::collectLexicalBlockInfo(
3013 for (LexicalScope *Scope : Scopes)
3014 collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
3019void CodeViewDebug::collectLexicalBlockInfo(
3024 if (
Scope.isAbstractScope())
3029 bool IgnoreScope =
false;
3030 auto LI = ScopeVariables.find(&Scope);
3031 SmallVectorImpl<LocalVariable> *
Locals =
3032 LI != ScopeVariables.end() ? &LI->second :
nullptr;
3033 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
3034 SmallVectorImpl<CVGlobalVariable> *Globals =
3035 GI != ScopeGlobals.
end() ? GI->second.get() :
nullptr;
3037 const SmallVectorImpl<InsnRange> &
Ranges =
Scope.getRanges();
3040 if (!Locals && !Globals)
3070 collectLexicalBlockInfo(
Scope.getChildren(),
3080 auto BlockInsertion = CurFn->LexicalBlocks.try_emplace(DILB);
3081 if (!BlockInsertion.second)
3088 LexicalBlock &
Block = BlockInsertion.first->second;
3091 assert(
Block.Begin &&
"missing label for scope begin");
3092 assert(
Block.End &&
"missing label for scope end");
3095 Block.Locals = std::move(*Locals);
3097 Block.Globals = std::move(*Globals);
3099 collectLexicalBlockInfo(
Scope.getChildren(),
3107 assert(FnDebugInfo.count(&GV));
3108 assert(CurFn == FnDebugInfo[&GV].
get());
3114 collectLexicalBlockInfo(*CFS,
3122 ScopeVariables.clear();
3126 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3127 FnDebugInfo.erase(&GV);
3133 for (
const auto &
MBB : *MF) {
3134 for (
const auto &
MI :
MBB) {
3135 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3143 bool isThumb =
MMI->getModule()->getTargetTriple().getArch() ==
3145 collectDebugInfoForJumpTables(MF,
isThumb);
3149 CurFn->End =
Asm->getFunctionEnd();
3166 if (
DL.getLine() != 0)
3169 return Scope->getSubprogram()->isArtificial();
3177 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3185 for (
const auto &NextMI : *
MI->getParent()) {
3186 if (NextMI.isDebugInstr())
3188 DL = NextMI.getDebugLoc();
3201 maybeRecordLocation(
DL,
Asm->MF);
3214void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3221 MCSymbol *BeginLabel =
MMI->getContext().createTempSymbol(),
3222 *EndLabel =
MMI->getContext().createTempSymbol();
3223 OS.AddComment(
"Record length");
3224 OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
3225 OS.emitLabel(BeginLabel);
3226 if (OS.isVerboseAsm())
3228 OS.emitInt16(
unsigned(SymKind));
3232void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3237 OS.emitValueToAlignment(
Align(4));
3238 OS.emitLabel(SymEnd);
3241void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3242 OS.AddComment(
"Record length");
3244 if (OS.isVerboseAsm())
3246 OS.emitInt16(uint16_t(EndKind));
3249void CodeViewDebug::emitDebugInfoForUDTs(
3250 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3252 size_t OriginalSize = UDTs.size();
3254 for (
const auto &UDT : UDTs) {
3255 const DIType *
T =
UDT.second;
3257 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3258 OS.AddComment(
"Type");
3259 OS.emitInt32(getCompleteTypeIndex(
T).getIndex());
3260 assert(OriginalSize == UDTs.size() &&
3261 "getCompleteTypeIndex found new UDTs!");
3263 endSymbolRecord(UDTRecordEnd);
3267void CodeViewDebug::collectGlobalOrStaticLocalVariableInfo(
3269 const DIGlobalVariable *DIGV = GVE->
getVariable();
3279 (DIE->
getElement(0) == dwarf::DW_OP_plus_uconst))
3284 CVGlobalVariableOffsets.insert(std::make_pair(DIGV, DIE->
getElement(1)));
3287 if (!GlobalMap.count(GVE) && DIE->
isConstant())
3288 GlobalVariables.emplace_back(CVGlobalVariable{DIGV, DIE});
3290 const auto *GV = GlobalMap.lookup(GVE);
3295 SmallVector<CVGlobalVariable, 1> *VariableList;
3300 ScopeGlobals.insert({
Scope, std::unique_ptr<GlobalVariableList>()});
3301 if (Insertion.second)
3302 Insertion.first->second = std::make_unique<GlobalVariableList>();
3303 VariableList = Insertion.first->second.get();
3306 VariableList = &ComdatVariables;
3309 VariableList = &GlobalVariables;
3311 VariableList->
emplace_back(CVGlobalVariable{DIGV, GV});
3314void CodeViewDebug::collectGlobalVariableInfo() {
3315 for (
const GlobalVariable &GV :
MMI->getModule()->globals()) {
3317 GV.getDebugInfo(GVEs);
3318 for (
const auto *GVE : GVEs)
3319 GlobalMap[GVE] = &GV;
3322 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3323 for (
const MDNode *Node : CUs->
operands()) {
3325 for (
const auto *GVE : CU->getGlobalVariables()) {
3326 collectGlobalOrStaticLocalVariableInfo(GVE);
3331void CodeViewDebug::collectDebugInfoForGlobals() {
3332 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3333 const DIGlobalVariable *DIGV = CVGV.DIGV;
3335 getCompleteTypeIndex(DIGV->
getType());
3336 getFullyQualifiedName(Scope, DIGV->
getName());
3339 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3340 const DIGlobalVariable *DIGV = CVGV.DIGV;
3342 getCompleteTypeIndex(DIGV->
getType());
3343 getFullyQualifiedName(Scope, DIGV->
getName());
3347void CodeViewDebug::emitDebugInfoForGlobals() {
3351 switchToDebugSectionForSymbol(
nullptr);
3352 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3353 OS.AddComment(
"Symbol subsection for globals");
3354 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3355 emitGlobalVariableList(GlobalVariables);
3356 emitStaticConstMemberList();
3357 endCVSubsection(EndLabel);
3362 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3365 OS.AddComment(
"Symbol subsection for " +
3367 switchToDebugSectionForSymbol(GVSym);
3368 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3370 emitDebugInfoForGlobal(CVGV);
3371 endCVSubsection(EndLabel);
3375void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3376 NamedMDNode *CUs =
MMI->getModule()->getNamedMetadata(
"llvm.dbg.cu");
3377 for (
const MDNode *Node : CUs->
operands()) {
3389 for (
const CVGlobalVariable &CVGV : Globals) {
3391 emitDebugInfoForGlobal(CVGV);
3396 const std::string &QualifiedName) {
3397 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3398 OS.AddComment(
"Type");
3399 OS.emitInt32(getTypeIndex(DTy).getIndex());
3401 OS.AddComment(
"Value");
3406 CodeViewRecordIO IO(Writer);
3408 StringRef SRef((
char *)
Data, Writer.getOffset());
3409 OS.emitBinaryData(SRef);
3411 OS.AddComment(
"Name");
3413 endSymbolRecord(SConstantEnd);
3416void CodeViewDebug::emitStaticConstMemberList() {
3417 for (
const DIDerivedType *DTy : StaticConstMembers) {
3421 if (
const ConstantInt *CI =
3425 else if (
const ConstantFP *CFP =
3427 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3431 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3432 getFullyQualifiedName(Scope, DTy->
getName()));
3442 if (
T == dwarf::DW_TAG_pointer_type ||
3443 T == dwarf::DW_TAG_ptr_to_member_type ||
3444 T == dwarf::DW_TAG_reference_type ||
3445 T == dwarf::DW_TAG_rvalue_reference_type)
3447 assert(DTy->getBaseType() &&
"Expected valid base type");
3452 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3455void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3456 const DIGlobalVariable *DIGV = CVGV.DIGV;
3462 Scope = MemberDecl->getScope();
3468 ? std::string(DIGV->
getName())
3471 if (
const GlobalVariable *GV =
3475 MCSymbol *GVSym = Asm->getSymbol(GV);
3476 SymbolKind DataSym = GV->isThreadLocal()
3477 ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32
3478 : SymbolKind::S_GTHREAD32)
3479 : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32
3480 : SymbolKind::S_GDATA32);
3481 MCSymbol *DataEnd = beginSymbolRecord(DataSym);
3482 OS.AddComment(
"Type");
3483 OS.emitInt32(getCompleteTypeIndex(DIGV->getType()).getIndex());
3484 OS.AddComment(
"DataOffset");
3487 uint64_t Offset = CVGlobalVariableOffsets.lookup(DIGV);
3488 OS.emitCOFFSecRel32(GVSym, Offset);
3490 OS.AddComment(
"Segment");
3491 OS.emitCOFFSectionIndex(GVSym);
3492 OS.AddComment(
"Name");
3493 const unsigned LengthOfDataRecord = 12;
3494 emitNullTerminatedSymbolName(OS, QualifiedName, LengthOfDataRecord);
3495 endSymbolRecord(DataEnd);
3497 const DIExpression *DIE = cast<const DIExpression *>(CVGV.GVInfo);
3498 assert(DIE->isConstant() &&
3499 "Global constant variables must contain a constant expression.");
3502 bool isUnsigned = isFloatDIType(DIGV->getType())
3504 : DebugHandlerBase::isUnsignedDIType(DIGV->getType());
3505 APSInt Value(APInt(64, DIE->getConstantValue()), isUnsigned);
3506 emitConstantSymbolRecord(DIGV->getType(), Value, QualifiedName);
3513 int64_t)> &Callback) {
3515 if (JTI && !JTI->isEmpty()) {
3519 for (
const auto &
MBB : *MF) {
3521 const auto LastMI =
MBB.getFirstTerminator();
3522 if (LastMI !=
MBB.end() && LastMI->isIndirectBranch()) {
3530 for (
const auto &MO : LastMI->operands()) {
3532 unsigned Index = MO.getIndex();
3536 Callback(*JTI, *LastMI, Index);
3544 for (
auto I =
MBB.instr_rbegin(),
E =
MBB.instr_rend();
I !=
E; ++
I) {
3545 if (
I->isJumpTableDebugInfo()) {
3546 unsigned Index =
I->getOperand(0).getImm();
3550 Callback(*JTI, *LastMI, Index);
3559 "Some of jump tables were not used in a debug info instruction");
3564void CodeViewDebug::discoverJumpTableBranches(
const MachineFunction *MF,
3568 [
this](
const MachineJumpTableInfo &,
const MachineInstr &BranchMI,
3572void CodeViewDebug::collectDebugInfoForJumpTables(
const MachineFunction *MF,
3576 [
this, MF](
const MachineJumpTableInfo &JTI,
const MachineInstr &BranchMI,
3577 int64_t JumpTableIndex) {
3590 "EK_Custom32, EK_GPRel32BlockAddress, and "
3591 "EK_GPRel64BlockAddress should never be emitted for COFF");
3594 EntrySize = JumpTableEntrySize::Pointer;
3601 std::tie(
Base, BaseOffset, Branch, EntrySize) =
3602 Asm->getCodeViewJumpTableInfo(JumpTableIndex, &BranchMI, Branch);
3606 const MachineJumpTableEntry &JTE = JTI.
getJumpTables()[JumpTableIndex];
3607 JumpTableInfo CVJTI{EntrySize,
3614 for (
const auto &
MBB : JTE.
MBBs)
3616 CurFn->JumpTables.push_back(std::move(CVJTI));
3620void CodeViewDebug::emitDebugInfoForJumpTables(
const FunctionInfo &FI) {
3622 for (
const auto &JumpTable : FI.JumpTables) {
3623 for (
const auto &CaseSym :
JumpTable.Cases) {
3624 MCSymbol *LabelEnd = beginSymbolRecord(SymbolKind::S_LABEL32);
3625 OS.AddComment(
"Offset and segment");
3626 OS.emitCOFFSecRel32(CaseSym, 0);
3627 OS.AddComment(
"Flags");
3630 endSymbolRecord(LabelEnd);
3634 for (
const auto &JumpTable : FI.JumpTables) {
3635 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3637 OS.AddComment(
"Base offset");
3639 OS.AddComment(
"Base section index");
3640 OS.emitCOFFSectionIndex(
JumpTable.Base);
3642 OS.AddComment(
"Base offset");
3644 OS.AddComment(
"Base section index");
3647 OS.AddComment(
"Switch type");
3648 OS.emitInt16(
static_cast<uint16_t
>(
JumpTable.EntrySize));
3649 OS.AddComment(
"Branch offset");
3650 OS.emitCOFFSecRel32(
JumpTable.Branch, 0);
3651 OS.AddComment(
"Table offset");
3652 OS.emitCOFFSecRel32(
JumpTable.Table, 0);
3653 OS.AddComment(
"Branch section index");
3654 OS.emitCOFFSectionIndex(
JumpTable.Branch);
3655 OS.AddComment(
"Table section index");
3656 OS.emitCOFFSectionIndex(
JumpTable.Table);
3657 OS.AddComment(
"Entries count");
3659 endSymbolRecord(JumpTableEnd);
3663void CodeViewDebug::emitInlinees(
3667 constexpr size_t ChunkSize =
3674 size_t CurrentIndex = 0;
3675 while (CurrentIndex < SortedInlinees.
size()) {
3676 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3677 auto CurrentChunkSize =
3678 std::min(ChunkSize, SortedInlinees.
size() - CurrentIndex);
3679 OS.AddComment(
"Count");
3680 OS.emitInt32(CurrentChunkSize);
3682 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3683 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3684 OS.AddComment(
"Inlinee");
3685 OS.emitInt32(SortedInlinees[CurrentIndex].getIndex());
3687 endSymbolRecord(Symbol);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
static bool isThumb(const MCSubtargetInfo &STI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static MethodKind translateMethodKindFlags(const DISubprogram *SP, bool Introduced)
static bool isUsableDebugLoc(DebugLoc DL)
static TypeIndex getStringIdTypeIdx(GlobalTypeTableBuilder &TypeTable, StringRef S)
static CPUType mapArchToCVCPUType(Triple::ArchType Type)
static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S, unsigned MaxFixedRecordLength=0xF00)
static Version parseVersion(StringRef Name)
static MethodOptions translateMethodOptionFlags(const DISubprogram *SP)
static bool isNonTrivial(const DICompositeType *DCTy)
static std::string formatNestedName(ArrayRef< StringRef > QualifiedNameComponents, StringRef TypeName)
static ClassOptions getCommonClassOptions(const DICompositeType *Ty)
Return ClassOptions that should be present on both the forward declaration and the defintion of a tag...
static cl::opt< bool > UseTagRecord2("use-codeview-tagrecord2", cl::Hidden, cl::desc("Use the *2 versions for tag records in CodeView (LF_CLASS2, etc.)"), cl::init(false))
static PointerToMemberRepresentation translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags)
static FunctionOptions getFunctionOptions(const DISubroutineType *Ty, const DICompositeType *ClassTy=nullptr, StringRef SPName=StringRef(""))
static StringRef removeTemplateArgs(StringRef Name)
static TypeRecordKind getRecordKind(const DICompositeType *Ty)
void forEachJumpTableBranch(const MachineFunction *MF, bool isThumb, const std::function< void(const MachineJumpTableInfo &, const MachineInstr &, int64_t)> &Callback)
static CallingConvention dwarfCCToCodeView(unsigned DwarfCC)
Given a DWARF calling convention, get the CodeView equivalent.
static SourceLanguage MapDWARFLanguageToCVLang(dwarf::SourceLanguageName DWLName)
static bool isFloatDIType(const DIType *Ty)
static void addLocIfNotPresent(SmallVectorImpl< const DILocation * > &Locs, const DILocation *Loc)
static bool shouldEmitUdt(const DIType *T)
static StringRef getPrettyScopeName(const DIScope *Scope)
static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty)
static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file contains constants used for implementing Dwarf debug support.
Module.h This file contains the declarations for the Module class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static constexpr StringLiteral Filename
static StringRef getName(Value *V)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
This file implements the SmallBitVector class.
This file defines the SmallString class.
This file describes how to lower LLVM code to machine code.
static const uint32_t IV[8]
An arbitrary precision integer that knows its signedness.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
This class is intended to be used as a driving class for all asm writers.
CodeViewDebug(AsmPrinter *AP)
void beginModule(Module *M) override
bool moduleIsInFortran()
Check if the current module is in Fortran.
void endFunctionImpl(const MachineFunction *) override
Gather post-function debug information.
void endModule() override
Emit the COFF section that holds the line table information.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
void beginFunctionImpl(const MachineFunction *MF) override
Gather pre-function debug information.
This is the shared class of boolean and integer constants.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Basic type, like 'int' or 'float'.
unsigned getEncoding() const
StringRef getIdentifier() const
DINodeArray getElements() const
DIType * getBaseType() const
LLVM_ABI DIType * getClassType() const
Get casted version of extra data.
LLVM_ABI Constant * getConstant() const
unsigned getNumElements() const
uint64_t getElement(unsigned I) const
static LLVM_ABI bool extractLeadingOffset(ArrayRef< uint64_t > Ops, int64_t &OffsetInBytes, SmallVectorImpl< uint64_t > &RemainingOps)
LLVM_ABI std::optional< SignedOrUnsignedConstant > isConstant() const
Determine whether this represents a constant value, if so.
A pair of DIGlobalVariable and DIExpression.
DIGlobalVariable * getVariable() const
DIExpression * getExpression() const
Metadata * getRawStaticDataMemberDeclaration() const
DILocalScope * getScope() const
Get the local scope for this variable.
Tagged DWARF-like metadata node.
LLVM_ABI dwarf::Tag getTag() const
Base class for scope-like contexts.
StringRef getFilename() const
LLVM_ABI StringRef getName() const
StringRef getDirectory() const
LLVM_ABI DIScope * getScope() const
Wrapper structure that holds source language identity metadata that includes language name,...
bool hasVersionedName() const
uint16_t getName() const
Returns a versioned or unversioned language name.
String type, Fortran CHARACTER(n)
Subprogram description. Uses SubclassData1.
Type array for a subprogram.
DITypeArray getTypeArray() const
uint64_t getOffsetInBits() const
bool isObjectPointer() const
StringRef getName() const
bool isForwardDecl() const
uint64_t getSizeInBits() const
DIScope * getScope() const
DIScope * getScope() const
StringRef getName() const
SmallVector< Entry, 4 > Entries
static const EntryIndex NoEntry
Special value to indicate that an entry is valid until the end of the function.
static bool isUnsignedDIType(const DIType *Ty)
Return true if type encoding is unsigned.
AsmPrinter * Asm
Target of debug info emission.
MCSymbol * getLabelBeforeInsn(const MachineInstr *MI)
Return Label preceding the instruction.
MachineModuleInfo * MMI
Collected machine module information.
DebugLoc PrevInstLoc
Previous instruction's location information.
MCSymbol * getLabelAfterInsn(const MachineInstr *MI)
Return Label immediately following the instruction.
DebugHandlerBase(AsmPrinter *A)
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
const MachineBasicBlock * PrevInstBB
void requestLabelAfterInsn(const MachineInstr *MI)
Ensure that a label will be emitted after MI.
DbgValueHistoryMap DbgValues
History of DBG_VALUE and clobber instructions for each user variable.
void requestLabelBeforeInsn(const MachineInstr *MI)
Ensure that a label will be emitted before MI.
const MachineInstr * PrologEndLoc
This location indicates end of function prologue and beginning of function body.
static uint64_t getBaseTypeSize(const DIType *Ty)
If this type is derived from a base type then return base type size.
Implements a dense probed hash-table based set.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool hasStackProtectorFnAttr() const
Returns true if the function has ssp, sspstrong, or sspreq fn attrs.
DISubprogram * getSubprogram() const
Get the attached subprogram.
bool hasPersonalityFn() const
Check whether this function has a personality function.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
bool hasOptNone() const
Do not optimize this function (-O0).
bool hasProfileData() const
Return true if the function is annotated with profile data.
Function::iterator insert(Function::iterator Position, BasicBlock *BB)
Insert BB in the basic block list at Position.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool hasLocalLinkage() const
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
bool isDeclarationForLinker() const
This class is used to track scope information.
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSymbol * getCOMDATSymbol() const
Streaming machine code generation interface.
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size)
Emit the absolute difference between two symbols.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitValueToAlignment(Align Alignment, int64_t Fill=0, uint8_t FillLen=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
void emitInt32(uint64_t Value)
virtual void emitBytes(StringRef Data)
Emit the bytes in Data into the output.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
ArrayRef< MDOperand > operands() const
unsigned getNumOperands() const
Return number of MDNode operands.
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
int64_t getOffsetAdjustment() const
Return the correction for frame offsets.
unsigned getCVBytesOfCalleeSavedRegisters() const
Returns how many bytes of callee-saved registers the target pushed in the prologue.
bool hasStackProtectorIndex() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool hasInlineAsm() const
Returns true if the function contains any inline assembly.
bool exposesReturnsTwice() const
exposesReturnsTwice - Returns true if the function calls setjmp or any other similar functions with a...
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCSymbol * getJTISymbol(unsigned JTI, MCContext &Ctx, bool isLinkerPrivate=false) const
getJTISymbol - Return the MCSymbol for the specified non-empty jump table.
auto getInStackSlotVariableDbgInfo()
Returns the collection of variables for which we have debug info and that have been assigned a stack ...
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
ArrayRef< std::pair< MCSymbol *, MDNode * > > getCodeViewAnnotations() const
Representation of each machine instruction.
bool isDebugValue() const
MachineOperand & getDebugOperand(unsigned Index)
@ EK_GPRel32BlockAddress
EK_GPRel32BlockAddress - Each entry is an address of block, encoded with a relocation as gp-relative,...
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
@ EK_LabelDifference32
EK_LabelDifference32 - Each entry is the address of the block minus the address of the jump table.
@ EK_Custom32
EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the TargetLowering::LowerCustomJ...
@ EK_LabelDifference64
EK_LabelDifference64 - Each entry is the address of the block minus the address of the jump table.
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
@ EK_GPRel64BlockAddress
EK_GPRel64BlockAddress - Each entry is an address of block, encoded with a relocation as gp-relative,...
JTEntryKind getEntryKind() const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
const MCContext & getContext() const
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
iterator_range< op_iterator > operands()
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
const_iterator begin() const
const_iterator end() const
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static StackOffset getScalable(int64_t Scalable)
static StackOffset getFixed(int64_t Fixed)
Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
Check if the string is empty.
char back() const
Get the last character in the string.
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
@ CurrentDirectory
Absolute CWD path.
@ SourceFile
Path to main source file, relative or absolute.
@ BuildTool
Absolute compiler path.
@ CommandLine
Full canonical command line (maybe -cc1)
@ TypeServerPDB
Absolute path of type server PDB (/Fd)
LLVM_ABI void begin(ContinuationRecordKind RecordKind)
void writeMemberType(RecordType &Record)
TypeIndex writeLeafType(T &Record)
SimpleTypeKind getSimpleKind() const
SimpleTypeMode getSimpleMode() const
static const uint32_t FirstNonSimpleIndex
static LLVM_ABI StringRef simpleTypeName(TypeIndex TI)
uint32_t getIndex() const
static TypeIndex NullptrT()
void addCallbackToPipeline(TypeVisitorCallbacks &Callbacks)
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
@ DEBUG_HASHES_SECTION_MAGIC
initializer< Ty > init(const Ty &Val)
PointerMode
Equivalent to CV_ptrmode_e.
ProcSymFlags
Corresponds to the CV_PROCFLAGS bitfield.
PointerOptions
Equivalent to misc lfPointerAttr bitfields.
LocalSymFlags
Corresponds to CV_LVARFLAGS bitfield.
MethodKind
Part of member attribute flags. (CV_methodprop_e)
CVRecord< TypeLeafKind > CVType
PointerKind
Equivalent to CV_ptrtype_e.
CPUType
These values correspond to the CV_CPU_TYPE_e enumeration, and are documented here: https://msdn....
PointerToMemberRepresentation
Equivalent to CV_pmtype_e.
@ MultipleInheritanceData
@ SingleInheritanceFunction
@ VirtualInheritanceFunction
@ MultipleInheritanceFunction
CallingConvention
These values correspond to the CV_call_e enumeration, and are documented at the following locations: ...
MethodOptions
Equivalent to CV_fldattr_t bitfield.
MemberAccess
Source-level access specifier. (CV_access_e)
ThunkOrdinal
These values correspond to the THUNK_ORDINAL enumeration.
LLVM_ABI EnumStrings< SymbolKind, 1 > getSymbolTypeNames()
EncodedFramePtrReg
Two-bit value indicating which register is the designated frame pointer register.
TypeRecordKind
Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.
SymbolKind
Duplicate copy of the above enum, but using the official CV names.
ModifierOptions
Equivalent to CV_modifier_t.
@ ProfileGuidedOptimization
@ HasStructuredExceptionHandling
LLVM_ABI EncodedFramePtrReg encodeFramePtrReg(RegisterId Reg, CPUType CPU)
LLVM_ABI Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
SourceLanguage
These values correspond to the CV_CFL_LANG enumeration in the Microsoft Debug Interface Access SDK,...
std::optional< std::pair< SourceLanguageName, uint32_t > > toDW_LNAME(SourceLanguage language)
Convert a DWARF 5 DW_LANG to a DWARF 6 pair of language name and version.
ElementType
The element type of an SRV or UAV resource.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
NodeAddr< NodeBase * > Node
LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
std::string fromHex(StringRef Input)
Convert hexadecimal string Input to its binary representation. The return string is half the size of ...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
std::tuple< uint64_t, uint32_t > InlineSite
LLVM_GET_TYPE_NAME_CONSTEXPR StringRef getTypeName()
We provide a function which tries to compute the (demangled) name of a type statically.
std::pair< const MachineInstr *, const MachineInstr * > InsnRange
This is used to track range of instructions with identical lexical scope.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Success
The lock was released successfully.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
@ End
Run the machine verifier once, at the end of the pipeline.
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
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.