31#include "llvm/Config/llvm-config.h"
82 :
OS(&
OS), TypeTable(TypeTable) {}
104 TypeName = std::string(TypeTable.getTypeName(TI));
117 case Triple::ArchType::x86:
118 return CPUType::Pentium3;
119 case Triple::ArchType::x86_64:
121 case Triple::ArchType::thumb:
124 return CPUType::ARMNT;
125 case Triple::ArchType::aarch64:
126 return CPUType::ARM64;
136 std::string &Filepath = FileToFilepathMap[File];
137 if (!Filepath.empty())
140 StringRef Dir = File->getDirectory(), Filename = File->getFilename();
144 if (Dir.
startswith(
"/") || Filename.startswith(
"/")) {
147 Filepath = std::string(Dir);
148 if (Dir.
back() !=
'/')
150 Filepath += Filename;
158 if (Filename.find(
':') == 1)
159 Filepath = std::string(Filename);
161 Filepath = (Dir +
"\\" + Filename).str();
166 std::replace(Filepath.begin(), Filepath.end(),
'/',
'\\');
170 while ((Cursor = Filepath.find(
"\\.\\", Cursor)) != std::string::npos)
171 Filepath.erase(Cursor, 2);
176 while ((Cursor = Filepath.find(
"\\..\\", Cursor)) != std::string::npos) {
181 size_t PrevSlash = Filepath.rfind(
'\\', Cursor - 1);
182 if (PrevSlash == std::string::npos)
186 Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
193 while ((Cursor = Filepath.find(
"\\\\", Cursor)) != std::string::npos)
194 Filepath.erase(Cursor, 1);
199unsigned CodeViewDebug::maybeRecordFile(
const DIFile *
F) {
201 unsigned NextId = FileIdMap.
size() + 1;
202 auto Insertion = FileIdMap.
insert(std::make_pair(FullPath, NextId));
203 if (Insertion.second) {
207 if (
F->getChecksum()) {
208 std::string Checksum = fromHex(
F->getChecksum()->Value);
210 memcpy(CKMem, Checksum.data(), Checksum.size());
212 reinterpret_cast<const uint8_t *
>(CKMem), Checksum.size());
213 switch (
F->getChecksum()->Kind) {
215 CSKind = FileChecksumKind::MD5;
218 CSKind = FileChecksumKind::SHA1;
221 CSKind = FileChecksumKind::SHA256;
226 static_cast<unsigned>(CSKind));
230 return Insertion.first->second;
233CodeViewDebug::InlineSite &
234CodeViewDebug::getInlineSite(
const DILocation *InlinedAt,
236 auto SiteInsertion = CurFn->InlineSites.insert({InlinedAt,
InlineSite()});
237 InlineSite *Site = &SiteInsertion.first->second;
238 if (SiteInsertion.second) {
239 unsigned ParentFuncId = CurFn->FuncId;
240 if (
const DILocation *OuterIA = InlinedAt->getInlinedAt())
242 getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())
245 Site->SiteFuncId = NextFuncId++;
247 Site->SiteFuncId, ParentFuncId, maybeRecordFile(InlinedAt->getFile()),
248 InlinedAt->getLine(), InlinedAt->getColumn(),
SMLoc());
250 InlinedSubprograms.insert(Inlinee);
251 getFuncIdForSubprogram(Inlinee);
258 if (!ScopeName.
empty())
261 switch (Scope->getTag()) {
262 case dwarf::DW_TAG_enumeration_type:
263 case dwarf::DW_TAG_class_type:
264 case dwarf::DW_TAG_structure_type:
265 case dwarf::DW_TAG_union_type:
266 return "<unnamed-tag>";
267 case dwarf::DW_TAG_namespace:
268 return "`anonymous namespace'";
274const DISubprogram *CodeViewDebug::collectParentScopeNames(
277 while (Scope !=
nullptr) {
278 if (ClosestSubprogram ==
nullptr)
279 ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
284 if (
const auto *Ty = dyn_cast<DICompositeType>(Scope))
285 DeferredCompleteTypes.push_back(Ty);
288 if (!ScopeName.
empty())
289 QualifiedNameComponents.
push_back(ScopeName);
292 return ClosestSubprogram;
297 std::string FullyQualifiedName;
300 FullyQualifiedName.append(std::string(QualifiedNameComponent));
301 FullyQualifiedName.append(
"::");
303 FullyQualifiedName.append(std::string(TypeName));
304 return FullyQualifiedName;
312 if (
CVD.TypeEmissionLevel == 1)
313 CVD.emitDeferredCompleteTypes();
314 --
CVD.TypeEmissionLevel;
319std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Scope,
326 collectParentScopeNames(Scope, QualifiedNameComponents);
330std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Ty) {
346 if (!Scope || isa<DIFile>(Scope) || isa<DISubprogram>(Scope))
349 assert(!isa<DIType>(Scope) &&
"shouldn't make a namespace scope for a type");
352 auto I = TypeIndices.find({Scope,
nullptr});
353 if (
I != TypeIndices.end())
357 std::string ScopeName = getFullyQualifiedName(Scope);
360 return recordTypeIndexForDINode(Scope, TI);
366 if (
Name.empty() ||
Name.back() !=
'>')
369 int OpenBrackets = 0;
370 for (
int i =
Name.size() - 1; i >= 0; --i) {
373 else if (
Name[i] ==
'<') {
375 if (OpenBrackets == 0)
376 return Name.substr(0, i);
386 auto I = TypeIndices.find({SP,
nullptr});
387 if (
I != TypeIndices.end())
397 if (
const auto *Class = dyn_cast_or_null<DICompositeType>(Scope)) {
401 TypeIndex ClassType = getTypeIndex(Class);
407 TypeIndex ParentScope = getScopeIndex(Scope);
412 return recordTypeIndexForDINode(SP, TI);
416 return ((DCTy->
getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);
424 const DIType *ReturnTy =
nullptr;
426 if (TypeArray.size())
427 ReturnTy = TypeArray[0];
432 if (
auto *ReturnDCTy = dyn_cast_or_null<DICompositeType>(ReturnTy))
434 FO |= FunctionOptions::CxxReturnUdt;
437 if (ClassTy &&
isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {
438 FO |= FunctionOptions::Constructor;
450 if (SP->getDeclaration())
451 SP = SP->getDeclaration();
452 assert(!SP->getDeclaration() &&
"should use declaration as key");
456 auto I = TypeIndices.find({SP,
Class});
457 if (
I != TypeIndices.end())
463 TypeLoweringScope S(*
this);
464 const bool IsStaticMethod = (SP->getFlags() & DINode::FlagStaticMember) != 0;
468 SP->getType(), Class, SP->getThisAdjustment(), IsStaticMethod, FO);
469 return recordTypeIndexForDINode(SP, TI, Class);
475 auto InsertResult = TypeIndices.insert({{
Node, ClassTy}, TI});
477 assert(InsertResult.second &&
"DINode was already assigned a type index");
481unsigned CodeViewDebug::getPointerSizeInBytes() {
485void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
490 InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
491 Site.InlinedLocals.emplace_back(std::move(Var));
494 ScopeVariables[
LS].emplace_back(std::move(Var));
504void CodeViewDebug::maybeRecordLocation(
const DebugLoc &
DL,
516 if (LI.getStartLine() !=
DL.getLine() || LI.isAlwaysStepInto() ||
517 LI.isNeverStepInto())
521 if (CI.getStartColumn() !=
DL.getCol())
524 if (!CurFn->HaveLineInfo)
525 CurFn->HaveLineInfo =
true;
528 FileId = CurFn->LastFileId;
530 FileId = CurFn->LastFileId = maybeRecordFile(
DL->getFile());
533 unsigned FuncId = CurFn->FuncId;
540 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
543 bool FirstLoc =
true;
544 while ((SiteLoc = Loc->getInlinedAt())) {
546 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
560void CodeViewDebug::emitCodeViewMagicVersion() {
568 case dwarf::DW_LANG_C:
569 case dwarf::DW_LANG_C89:
570 case dwarf::DW_LANG_C99:
571 case dwarf::DW_LANG_C11:
572 return SourceLanguage::C;
573 case dwarf::DW_LANG_C_plus_plus:
574 case dwarf::DW_LANG_C_plus_plus_03:
575 case dwarf::DW_LANG_C_plus_plus_11:
576 case dwarf::DW_LANG_C_plus_plus_14:
577 return SourceLanguage::Cpp;
578 case dwarf::DW_LANG_Fortran77:
579 case dwarf::DW_LANG_Fortran90:
580 case dwarf::DW_LANG_Fortran95:
581 case dwarf::DW_LANG_Fortran03:
582 case dwarf::DW_LANG_Fortran08:
583 return SourceLanguage::Fortran;
584 case dwarf::DW_LANG_Pascal83:
585 return SourceLanguage::Pascal;
586 case dwarf::DW_LANG_Cobol74:
587 case dwarf::DW_LANG_Cobol85:
588 return SourceLanguage::Cobol;
589 case dwarf::DW_LANG_Java:
590 return SourceLanguage::Java;
591 case dwarf::DW_LANG_D:
592 return SourceLanguage::D;
593 case dwarf::DW_LANG_Swift:
594 return SourceLanguage::Swift;
595 case dwarf::DW_LANG_Rust:
596 return SourceLanguage::Rust;
597 case dwarf::DW_LANG_ObjC:
598 return SourceLanguage::ObjC;
599 case dwarf::DW_LANG_ObjC_plus_plus:
600 return SourceLanguage::ObjCpp;
605 return SourceLanguage::Masm;
621 const MDNode *Node = *M->debug_compile_units_begin();
622 const auto *
CU = cast<DICompileUnit>(Node);
626 collectGlobalVariableInfo();
630 mdconst::extract_or_null<ConstantInt>(M->getModuleFlag(
"CodeViewGHash"));
631 EmitDebugGlobalHashes = GH && !GH->
isZero();
645 switchToDebugSectionForSymbol(
nullptr);
647 MCSymbol *CompilerInfo = beginCVSubsection(DebugSubsectionKind::Symbols);
649 emitCompilerInformation();
650 endCVSubsection(CompilerInfo);
652 emitInlineeLinesSubsection();
655 for (
auto &
P : FnDebugInfo)
656 if (!
P.first->isDeclarationForLinker())
657 emitDebugInfoForFunction(
P.first, *
P.second);
662 collectDebugInfoForGlobals();
665 emitDebugInfoForRetainedTypes();
668 setCurrentSubprogram(
nullptr);
669 emitDebugInfoForGlobals();
673 switchToDebugSectionForSymbol(
nullptr);
676 if (!GlobalUDTs.empty()) {
677 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
678 emitDebugInfoForUDTs(GlobalUDTs);
679 endCVSubsection(SymbolsEnd);
683 OS.
AddComment(
"File index to string table offset subsection");
697 emitTypeInformation();
699 if (EmitDebugGlobalHashes)
700 emitTypeGlobalHashes();
707 unsigned MaxFixedRecordLength = 0xF00) {
715 OS.emitBytes(NullTerminatedString);
718void CodeViewDebug::emitTypeInformation() {
719 if (TypeTable.
empty())
724 emitCodeViewMagicVersion();
730 CVMCAdapter CVMCOS(OS, Table);
734 std::optional<TypeIndex>
B = Table.getFirst();
746 B = Table.getNext(*
B);
750void CodeViewDebug::emitTypeGlobalHashes() {
751 if (TypeTable.
empty())
767 for (
const auto &GHR : TypeTable.
hashes()) {
777 assert(GHR.Hash.size() == 8);
778 StringRef S(
reinterpret_cast<const char *
>(GHR.Hash.data()),
784void CodeViewDebug::emitObjName() {
785 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);
790 if (PathRef.empty() || PathRef ==
"-") {
804 endSymbolRecord(CompilerEnd);
818 for (
const char C :
Name) {
821 V.Part[
N] +=
C -
'0';
823 std::min<int>(V.Part[
N], std::numeric_limits<uint16_t>::max());
824 }
else if (
C ==
'.') {
834void CodeViewDebug::emitCompilerInformation() {
835 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
839 Flags = CurrentSourceLanguage;
847 Arch == ArchType::aarch64) {
859 const auto *
CU = cast<DICompileUnit>(
Node);
864 for (
int N : FrontVer.Part) {
871 int Major = 1000 * LLVM_VERSION_MAJOR +
872 10 * LLVM_VERSION_MINOR +
875 Major = std::min<int>(Major, std::numeric_limits<uint16_t>::max());
876 Version BackVer = {{ Major, 0, 0, 0 }};
878 for (
int N : BackVer.Part)
881 OS.
AddComment(
"Null-terminated compiler version string");
884 endSymbolRecord(CompilerEnd);
895 std::string FlatCmdLine;
897 bool PrintedOneArg =
false;
900 PrintedOneArg =
true;
902 for (
unsigned i = 0; i < Args.size(); i++) {
906 if (
Arg ==
"-main-file-name" ||
Arg ==
"-o") {
910 if (
Arg.startswith(
"-object-file-name") ||
Arg == MainFilename)
913 if (
Arg.startswith(
"-fmessage-length"))
918 PrintedOneArg =
true;
924void CodeViewDebug::emitBuildInfo() {
938 const auto *
CU = cast<DICompileUnit>(
Node);
939 const DIFile *MainSourceFile =
CU->getFile();
959 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
960 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
963 endSymbolRecord(BIEnd);
964 endCVSubsection(BISubsecEnd);
967void CodeViewDebug::emitInlineeLinesSubsection() {
968 if (InlinedSubprograms.empty())
972 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
979 OS.
emitInt32(
unsigned(InlineeLinesSignature::Normal));
982 assert(TypeIndices.count({SP, nullptr}));
983 TypeIndex InlineeIdx = TypeIndices[{SP,
nullptr}];
986 unsigned FileId = maybeRecordFile(SP->
getFile());
990 OS.
AddComment(
"Type index of inlined function");
992 OS.
AddComment(
"Offset into filechecksum table");
998 endCVSubsection(InlineEnd);
1001void CodeViewDebug::emitInlinedCallSite(
const FunctionInfo &FI,
1004 assert(TypeIndices.count({Site.Inlinee, nullptr}));
1005 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee,
nullptr}];
1008 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
1017 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
1018 unsigned StartLineNum = Site.Inlinee->getLine();
1023 endSymbolRecord(InlineEnd);
1025 emitLocalVariableList(FI, Site.InlinedLocals);
1028 for (
const DILocation *ChildSite : Site.ChildSites) {
1029 auto I = FI.InlineSites.find(ChildSite);
1030 assert(
I != FI.InlineSites.end() &&
1031 "child site not in function inline site map");
1032 emitInlinedCallSite(FI, ChildSite,
I->second);
1036 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1039void CodeViewDebug::switchToDebugSectionForSymbol(
const MCSymbol *GVSym) {
1044 GVSym ? dyn_cast<MCSectionCOFF>(&GVSym->
getSection()) : nullptr;
1055 if (ComdatDebugSections.insert(DebugSec).second)
1056 emitCodeViewMagicVersion();
1061void CodeViewDebug::emitDebugInfoForThunk(
const Function *GV,
1064 std::string FuncName =
1069 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1072 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1079 OS.
AddComment(
"Thunk section relative address");
1090 endSymbolRecord(ThunkRecordEnd);
1096 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1098 endCVSubsection(SymbolsEnd);
1101void CodeViewDebug::emitDebugInfoForFunction(
const Function *GV,
1109 switchToDebugSectionForSymbol(Fn);
1111 std::string FuncName;
1114 setCurrentSubprogram(SP);
1116 if (SP->isThunk()) {
1117 emitDebugInfoForThunk(GV, FI, Fn);
1127 if (FuncName.empty())
1136 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1139 : SymbolKind::S_GPROC32_ID;
1140 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1159 OS.
AddComment(
"Function section relative address");
1169 endSymbolRecord(ProcRecordEnd);
1171 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1174 OS.
emitInt32(FI.FrameSize - FI.CSRSize);
1179 OS.
AddComment(
"Bytes of callee saved registers");
1185 OS.
AddComment(
"Flags (defines frame register)");
1187 endSymbolRecord(FrameProcEnd);
1189 emitLocalVariableList(FI, FI.Locals);
1190 emitGlobalVariableList(FI.Globals);
1191 emitLexicalBlockList(FI.ChildBlocks, FI);
1196 for (
const DILocation *InlinedAt : FI.ChildSites) {
1197 auto I = FI.InlineSites.find(InlinedAt);
1198 assert(
I != FI.InlineSites.end() &&
1199 "child site not in function inline site map");
1200 emitInlinedCallSite(FI, InlinedAt,
I->second);
1203 for (
auto Annot : FI.Annotations) {
1205 MDTuple *Strs = cast<MDTuple>(Annot.second);
1206 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1214 StringRef Str = cast<MDString>(MD)->getString();
1215 assert(Str.data()[Str.size()] ==
'\0' &&
"non-nullterminated MDString");
1218 endSymbolRecord(AnnotEnd);
1221 for (
auto HeapAllocSite : FI.HeapAllocSites) {
1222 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1223 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1224 const DIType *DITy = std::get<2>(HeapAllocSite);
1225 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1233 OS.
emitInt32(getCompleteTypeIndex(DITy).getIndex());
1234 endSymbolRecord(HeapAllocEnd);
1238 emitDebugInfoForUDTs(LocalUDTs);
1241 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1243 endCVSubsection(SymbolsEnd);
1250CodeViewDebug::createDefRangeMem(
uint16_t CVRegister,
int Offset) {
1256 DR.StructOffset = 0;
1257 DR.CVRegister = CVRegister;
1261void CodeViewDebug::collectVariableInfoFromMFTable(
1271 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1272 "Expected inlined-at fields to agree");
1274 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1283 int64_t ExprOffset = 0;
1287 if (
VI.Expr->getNumElements() == 1 &&
1288 VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)
1290 else if (!
VI.Expr->extractIfOffset(ExprOffset))
1297 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1300 "Frame offsets with a scalable component are not supported");
1303 LocalVarDef DefRange =
1304 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset);
1313 Var.DefRanges[DefRange].emplace_back(Begin, End);
1317 Var.UseReferenceType =
true;
1319 recordLocalVariable(std::move(Var), Scope);
1331void CodeViewDebug::calculateRanges(
1336 for (
auto I = Entries.begin(),
E = Entries.end();
I !=
E; ++
I) {
1337 const auto &Entry = *
I;
1338 if (!Entry.isDbgValue())
1344 std::optional<DbgVariableLocation>
Location =
1366 if (Var.UseReferenceType) {
1375 Var.UseReferenceType =
true;
1376 Var.DefRanges.clear();
1377 calculateRanges(Var, Entries);
1386 DR.CVRegister =
TRI->getCodeViewRegNum(
Location->Register);
1387 DR.InMemory = !
Location->LoadChain.empty();
1391 DR.IsSubfield =
true;
1392 DR.StructOffset =
Location->FragmentInfo->OffsetInBits / 8;
1394 DR.IsSubfield =
false;
1395 DR.StructOffset = 0;
1402 auto &EndingEntry = Entries[Entry.getEndIndex()];
1403 End = EndingEntry.isDbgValue()
1413 if (!
R.empty() &&
R.back().second == Begin)
1414 R.back().second = End;
1416 R.emplace_back(Begin, End);
1422void CodeViewDebug::collectVariableInfo(
const DISubprogram *SP) {
1425 collectVariableInfoFromMFTable(Processed);
1428 InlinedEntity
IV =
I.first;
1435 const auto &Entries =
I.second;
1449 calculateRanges(Var, Entries);
1450 recordLocalVariable(std::move(Var), Scope);
1459 auto Insertion = FnDebugInfo.insert({&GV, std::make_unique<FunctionInfo>()});
1460 assert(Insertion.second &&
"function already has info");
1461 CurFn = Insertion.first->second.get();
1462 CurFn->FuncId = NextFuncId++;
1471 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1475 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::None;
1476 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::None;
1477 if (CurFn->FrameSize > 0) {
1479 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1480 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr;
1483 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr;
1484 if (CurFn->HasStackRealignment) {
1486 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1490 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::FramePtr;
1498 FPO |= FrameProcedureOptions::HasAlloca;
1500 FPO |= FrameProcedureOptions::HasSetJmp;
1503 FPO |= FrameProcedureOptions::HasInlineAssembly;
1507 FPO |= FrameProcedureOptions::HasStructuredExceptionHandling;
1509 FPO |= FrameProcedureOptions::HasExceptionHandling;
1512 FPO |= FrameProcedureOptions::MarkedInline;
1514 FPO |= FrameProcedureOptions::Naked;
1516 FPO |= FrameProcedureOptions::SecurityChecks;
1519 FPO |= FrameProcedureOptions::StrictSecurityChecks;
1523 FPO |= FrameProcedureOptions::SafeBuffers;
1529 FPO |= FrameProcedureOptions::OptimizedForSpeed;
1531 FPO |= FrameProcedureOptions::ValidProfileCounts;
1532 FPO |= FrameProcedureOptions::ProfileGuidedOptimization;
1535 CurFn->FrameProcOpts = FPO;
1544 bool EmptyPrologue =
true;
1545 for (
const auto &
MBB : *MF) {
1546 for (
const auto &
MI :
MBB) {
1551 }
else if (!
MI.isMetaInstruction()) {
1552 EmptyPrologue =
false;
1560 maybeRecordLocation(FnStartDL, MF);
1564 for (
const auto &
MBB : *MF) {
1565 for (
const auto &
MI :
MBB) {
1566 if (
MI.getHeapAllocMarker()) {
1579 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1580 if (
DIScope *Scope =
T->getScope()) {
1581 switch (Scope->getTag()) {
1582 case dwarf::DW_TAG_structure_type:
1583 case dwarf::DW_TAG_class_type:
1584 case dwarf::DW_TAG_union_type:
1594 if (!
T ||
T->isForwardDecl())
1600 T = DT->getBaseType();
1605void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1614 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1616 std::string FullyQualifiedName =
1619 if (ClosestSubprogram ==
nullptr) {
1620 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1621 }
else if (ClosestSubprogram == CurrentSubprogram) {
1622 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1636 case dwarf::DW_TAG_array_type:
1637 return lowerTypeArray(cast<DICompositeType>(Ty));
1638 case dwarf::DW_TAG_typedef:
1639 return lowerTypeAlias(cast<DIDerivedType>(Ty));
1640 case dwarf::DW_TAG_base_type:
1641 return lowerTypeBasic(cast<DIBasicType>(Ty));
1642 case dwarf::DW_TAG_pointer_type:
1643 if (cast<DIDerivedType>(Ty)->
getName() ==
"__vtbl_ptr_type")
1644 return lowerTypeVFTableShape(cast<DIDerivedType>(Ty));
1646 case dwarf::DW_TAG_reference_type:
1647 case dwarf::DW_TAG_rvalue_reference_type:
1648 return lowerTypePointer(cast<DIDerivedType>(Ty));
1649 case dwarf::DW_TAG_ptr_to_member_type:
1650 return lowerTypeMemberPointer(cast<DIDerivedType>(Ty));
1651 case dwarf::DW_TAG_restrict_type:
1652 case dwarf::DW_TAG_const_type:
1653 case dwarf::DW_TAG_volatile_type:
1655 return lowerTypeModifier(cast<DIDerivedType>(Ty));
1656 case dwarf::DW_TAG_subroutine_type:
1660 return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy,
1664 return lowerTypeFunction(cast<DISubroutineType>(Ty));
1665 case dwarf::DW_TAG_enumeration_type:
1666 return lowerTypeEnum(cast<DICompositeType>(Ty));
1667 case dwarf::DW_TAG_class_type:
1668 case dwarf::DW_TAG_structure_type:
1669 return lowerTypeClass(cast<DICompositeType>(Ty));
1670 case dwarf::DW_TAG_union_type:
1671 return lowerTypeUnion(cast<DICompositeType>(Ty));
1672 case dwarf::DW_TAG_string_type:
1673 return lowerTypeString(cast<DIStringType>(Ty));
1674 case dwarf::DW_TAG_unspecified_type:
1675 if (Ty->
getName() ==
"decltype(nullptr)")
1685 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1690 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::Int32Long) &&
1691 TypeName ==
"HRESULT")
1692 return TypeIndex(SimpleTypeKind::HResult);
1693 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::UInt16Short) &&
1694 TypeName ==
"wchar_t")
1695 return TypeIndex(SimpleTypeKind::WideCharacter);
1697 return UnderlyingTypeIndex;
1702 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1704 TypeIndex IndexType = getPointerSizeInBytes() == 8
1712 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1714 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1724 Count = CI->getSExtValue();
1741 ElementSize *= Count;
1746 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1753 return ElementTypeIndex;
1766 TypeIndex IndexType = getPointerSizeInBytes() == 8
1786 case dwarf::DW_ATE_address:
1789 case dwarf::DW_ATE_boolean:
1791 case 1: STK = SimpleTypeKind::Boolean8;
break;
1792 case 2: STK = SimpleTypeKind::Boolean16;
break;
1793 case 4: STK = SimpleTypeKind::Boolean32;
break;
1794 case 8: STK = SimpleTypeKind::Boolean64;
break;
1795 case 16: STK = SimpleTypeKind::Boolean128;
break;
1798 case dwarf::DW_ATE_complex_float:
1802 case 4: STK = SimpleTypeKind::Complex16;
break;
1803 case 8: STK = SimpleTypeKind::Complex32;
break;
1804 case 16: STK = SimpleTypeKind::Complex64;
break;
1805 case 20: STK = SimpleTypeKind::Complex80;
break;
1806 case 32: STK = SimpleTypeKind::Complex128;
break;
1809 case dwarf::DW_ATE_float:
1811 case 2: STK = SimpleTypeKind::Float16;
break;
1812 case 4: STK = SimpleTypeKind::Float32;
break;
1813 case 6: STK = SimpleTypeKind::Float48;
break;
1814 case 8: STK = SimpleTypeKind::Float64;
break;
1815 case 10: STK = SimpleTypeKind::Float80;
break;
1816 case 16: STK = SimpleTypeKind::Float128;
break;
1819 case dwarf::DW_ATE_signed:
1821 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1822 case 2: STK = SimpleTypeKind::Int16Short;
break;
1823 case 4: STK = SimpleTypeKind::Int32;
break;
1824 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1825 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1828 case dwarf::DW_ATE_unsigned:
1830 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1831 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1832 case 4: STK = SimpleTypeKind::UInt32;
break;
1833 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1834 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1837 case dwarf::DW_ATE_UTF:
1839 case 1: STK = SimpleTypeKind::Character8;
break;
1840 case 2: STK = SimpleTypeKind::Character16;
break;
1841 case 4: STK = SimpleTypeKind::Character32;
break;
1844 case dwarf::DW_ATE_signed_char:
1846 STK = SimpleTypeKind::SignedCharacter;
1848 case dwarf::DW_ATE_unsigned_char:
1850 STK = SimpleTypeKind::UnsignedCharacter;
1860 if (STK == SimpleTypeKind::Int32 &&
1862 STK = SimpleTypeKind::Int32Long;
1863 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1864 Ty->
getName() ==
"unsigned long"))
1865 STK = SimpleTypeKind::UInt32Long;
1866 if (STK == SimpleTypeKind::UInt16Short &&
1868 STK = SimpleTypeKind::WideCharacter;
1869 if ((STK == SimpleTypeKind::SignedCharacter ||
1870 STK == SimpleTypeKind::UnsignedCharacter) &&
1872 STK = SimpleTypeKind::NarrowCharacter;
1879 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1883 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1885 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1887 ? SimpleTypeMode::NearPointer64
1888 : SimpleTypeMode::NearPointer32;
1893 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1897 case dwarf::DW_TAG_pointer_type:
1898 PM = PointerMode::Pointer;
1900 case dwarf::DW_TAG_reference_type:
1901 PM = PointerMode::LValueReference;
1903 case dwarf::DW_TAG_rvalue_reference_type:
1904 PM = PointerMode::RValueReference;
1909 PO |= PointerOptions::Const;
1923 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1924 : PointerToMemberRepresentation::GeneralFunction;
1925 case DINode::FlagSingleInheritance:
1926 return PointerToMemberRepresentation::SingleInheritanceFunction;
1927 case DINode::FlagMultipleInheritance:
1928 return PointerToMemberRepresentation::MultipleInheritanceFunction;
1929 case DINode::FlagVirtualInheritance:
1930 return PointerToMemberRepresentation::VirtualInheritanceFunction;
1935 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1936 : PointerToMemberRepresentation::GeneralData;
1937 case DINode::FlagSingleInheritance:
1938 return PointerToMemberRepresentation::SingleInheritanceData;
1939 case DINode::FlagMultipleInheritance:
1940 return PointerToMemberRepresentation::MultipleInheritanceData;
1941 case DINode::FlagVirtualInheritance:
1942 return PointerToMemberRepresentation::VirtualInheritanceData;
1950 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
1951 bool IsPMF = isa<DISubroutineType>(Ty->getBaseType());
1952 TypeIndex ClassTI = getTypeIndex(Ty->getClassType());
1954 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->getClassType() :
nullptr);
1955 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
1956 : PointerKind::Near32;
1957 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
1958 : PointerMode::PointerToDataMember;
1972 case dwarf::DW_CC_normal:
return CallingConvention::NearC;
1973 case dwarf::DW_CC_BORLAND_msfastcall:
return CallingConvention::NearFast;
1974 case dwarf::DW_CC_BORLAND_thiscall:
return CallingConvention::ThisCall;
1975 case dwarf::DW_CC_BORLAND_stdcall:
return CallingConvention::NearStdCall;
1976 case dwarf::DW_CC_BORLAND_pascal:
return CallingConvention::NearPascal;
1977 case dwarf::DW_CC_LLVM_vectorcall:
return CallingConvention::NearVector;
1979 return CallingConvention::NearC;
1987 while (IsModifier &&
BaseTy) {
1989 switch (
BaseTy->getTag()) {
1990 case dwarf::DW_TAG_const_type:
1991 Mods |= ModifierOptions::Const;
1992 PO |= PointerOptions::Const;
1994 case dwarf::DW_TAG_volatile_type:
1995 Mods |= ModifierOptions::Volatile;
1996 PO |= PointerOptions::Volatile;
1998 case dwarf::DW_TAG_restrict_type:
2001 PO |= PointerOptions::Restrict;
2016 switch (
BaseTy->getTag()) {
2017 case dwarf::DW_TAG_pointer_type:
2018 case dwarf::DW_TAG_reference_type:
2019 case dwarf::DW_TAG_rvalue_reference_type:
2020 return lowerTypePointer(cast<DIDerivedType>(
BaseTy), PO);
2021 case dwarf::DW_TAG_ptr_to_member_type:
2022 return lowerTypeMemberPointer(cast<DIDerivedType>(
BaseTy), PO);
2032 if (Mods == ModifierOptions::None)
2042 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2045 if (ReturnAndArgTypeIndices.
size() > 1 &&
2051 if (!ReturnAndArgTypeIndices.
empty()) {
2052 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2053 ReturnTypeIndex = ReturnAndArgTypesRef.front();
2054 ArgTypeIndices = ReturnAndArgTypesRef.
drop_front();
2057 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2071 bool IsStaticMethod,
2074 TypeIndex ClassType = getTypeIndex(ClassTy);
2082 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[
Index++]);
2089 if (!IsStaticMethod && ReturnAndArgs.
size() >
Index) {
2091 dyn_cast_or_null<DIDerivedType>(ReturnAndArgs[
Index])) {
2092 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2093 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2106 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2112 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2117 unsigned VSlotCount =
2127 case DINode::FlagPrivate:
return MemberAccess::Private;
2128 case DINode::FlagPublic:
return MemberAccess::Public;
2129 case DINode::FlagProtected:
return MemberAccess::Protected;
2132 return RecordTag == dwarf::DW_TAG_class_type ? MemberAccess::Private
2133 : MemberAccess::Public;
2139 if (SP->isArtificial())
2140 return MethodOptions::CompilerGenerated;
2144 return MethodOptions::None;
2149 if (SP->getFlags() & DINode::FlagStaticMember)
2150 return MethodKind::Static;
2152 switch (SP->getVirtuality()) {
2153 case dwarf::DW_VIRTUALITY_none:
2155 case dwarf::DW_VIRTUALITY_virtual:
2156 return Introduced ? MethodKind::IntroducingVirtual : MethodKind::Virtual;
2157 case dwarf::DW_VIRTUALITY_pure_virtual:
2158 return Introduced ? MethodKind::PureIntroducingVirtual
2159 : MethodKind::PureVirtual;
2164 return MethodKind::Vanilla;
2169 case dwarf::DW_TAG_class_type:
2170 return TypeRecordKind::Class;
2171 case dwarf::DW_TAG_structure_type:
2172 return TypeRecordKind::Struct;
2187 CO |= ClassOptions::HasUniqueName;
2193 if (ImmediateScope && isa<DICompositeType>(ImmediateScope))
2194 CO |= ClassOptions::Nested;
2200 if (Ty->
getTag() == dwarf::DW_TAG_enumeration_type) {
2201 if (ImmediateScope && isa<DISubprogram>(ImmediateScope))
2202 CO |= ClassOptions::Scoped;
2204 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2205 Scope = Scope->getScope()) {
2206 if (isa<DISubprogram>(Scope)) {
2207 CO |= ClassOptions::Scoped;
2218 case dwarf::DW_TAG_class_type:
2219 case dwarf::DW_TAG_structure_type:
2220 case dwarf::DW_TAG_union_type:
2221 case dwarf::DW_TAG_enumeration_type:
2227 if (
const auto *File = Ty->
getFile()) {
2239 unsigned EnumeratorCount = 0;
2242 CO |= ClassOptions::ForwardReference;
2245 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2249 if (
auto *
Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) {
2261 std::string FullName = getFullyQualifiedName(Ty);
2267 addUDTSrcLine(Ty, EnumTI);
2301void CodeViewDebug::clear() {
2302 assert(CurFn ==
nullptr);
2304 FnDebugInfo.clear();
2305 FileToFilepathMap.clear();
2308 TypeIndices.clear();
2309 CompleteTypeIndices.clear();
2310 ScopeGlobals.clear();
2311 CVGlobalVariableOffsets.clear();
2314void CodeViewDebug::collectMemberInfo(
ClassInfo &Info,
2317 Info.Members.push_back({DDTy, 0});
2320 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2321 DINode::FlagStaticMember) {
2324 StaticConstMembers.push_back(DDTy);
2336 const DIType *Ty = DDTy->getBaseType();
2337 bool FullyResolved =
false;
2338 while (!FullyResolved) {
2340 case dwarf::DW_TAG_const_type:
2341 case dwarf::DW_TAG_volatile_type:
2344 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2347 FullyResolved =
true;
2356 ClassInfo NestedInfo = collectClassInfo(DCTy);
2358 Info.Members.push_back(
2366 for (
auto *Element : Elements) {
2371 if (
auto *SP = dyn_cast<DISubprogram>(Element)) {
2372 Info.Methods[SP->getRawName()].push_back(SP);
2373 }
else if (
auto *DDTy = dyn_cast<DIDerivedType>(Element)) {
2374 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2375 collectMemberInfo(Info, DDTy);
2376 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2377 Info.Inheritance.push_back(DDTy);
2378 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2379 DDTy->
getName() ==
"__vtbl_ptr_type") {
2380 Info.VShapeTI = getTypeIndex(DDTy);
2381 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2382 Info.NestedTypes.push_back(DDTy);
2383 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2387 }
else if (
auto *Composite = dyn_cast<DICompositeType>(Element)) {
2388 Info.NestedTypes.push_back(Composite);
2411 auto I = CompleteTypeIndices.find(Ty);
2412 if (
I != CompleteTypeIndices.end() &&
I->second ==
TypeIndex())
2414 return getCompleteTypeIndex(Ty);
2422 std::string FullName = getFullyQualifiedName(Ty);
2427 DeferredCompleteTypes.push_back(Ty);
2437 unsigned FieldCount;
2440 lowerRecordFieldList(Ty);
2443 CO |= ClassOptions::ContainsNestedClass;
2451 CO |= ClassOptions::HasConstructorOrDestructor;
2453 std::string FullName = getFullyQualifiedName(Ty);
2461 addUDTSrcLine(Ty, ClassTI);
2471 return getCompleteTypeIndex(Ty);
2475 std::string FullName = getFullyQualifiedName(Ty);
2479 DeferredCompleteTypes.push_back(Ty);
2486 unsigned FieldCount;
2489 lowerRecordFieldList(Ty);
2492 CO |= ClassOptions::ContainsNestedClass;
2495 std::string FullName = getFullyQualifiedName(Ty);
2497 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2501 addUDTSrcLine(Ty, UnionTI);
2508std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2514 unsigned MemberCount = 0;
2517 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2521 if (
I->getFlags() & DINode::FlagVirtual) {
2523 unsigned VBPtrOffset =
I->getVBPtrOffset();
2525 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2526 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2527 ? TypeRecordKind::IndirectVirtualBaseClass
2528 : TypeRecordKind::VirtualBaseClass;
2531 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2537 assert(
I->getOffsetInBits() % 8 == 0 &&
2538 "bases must be on byte boundaries");
2540 getTypeIndex(
I->getBaseType()),
2541 I->getOffsetInBits() / 8);
2555 if (
Member->isStaticMember()) {
2563 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2564 Member->getName().startswith(
"_vptr$")) {
2574 if (
Member->isBitField()) {
2575 uint64_t StartBitOffset = MemberOffsetInBits;
2576 if (
const auto *CI =
2577 dyn_cast_or_null<ConstantInt>(
Member->getStorageOffsetInBits())) {
2578 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2580 StartBitOffset -= MemberOffsetInBits;
2585 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2593 for (
auto &MethodItr :
Info.Methods) {
2596 std::vector<OneMethodRecord> Methods;
2598 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2599 bool Introduced = SP->getFlags() & DINode::FlagIntroducedVirtual;
2601 unsigned VFTableOffset = -1;
2603 VFTableOffset = SP->getVirtualIndex() * getPointerSizeInBytes();
2611 assert(!Methods.empty() &&
"Empty methods map entry");
2612 if (Methods.size() == 1)
2633 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2634 !
Info.NestedTypes.empty());
2637TypeIndex CodeViewDebug::getVBPTypeIndex() {
2643 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2644 : PointerKind::Near32;
2647 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2662 auto I = TypeIndices.find({Ty, ClassTy});
2663 if (
I != TypeIndices.end())
2666 TypeLoweringScope S(*
this);
2668 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2672CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2674 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2675 "this type must be a pointer type");
2678 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2679 Options = PointerOptions::LValueRefThisPointer;
2680 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2681 Options = PointerOptions::RValueRefThisPointer;
2688 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2689 if (
I != TypeIndices.end())
2692 TypeLoweringScope S(*
this);
2694 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2697TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(
const DIType *Ty) {
2699 getPointerSizeInBytes() == 8 ? PointerKind::Near64
2700 : PointerKind::Near32,
2701 PointerMode::LValueReference, PointerOptions::None,
2714 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2715 (void)getTypeIndex(Ty);
2716 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2717 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2722 case dwarf::DW_TAG_class_type:
2723 case dwarf::DW_TAG_structure_type:
2724 case dwarf::DW_TAG_union_type:
2727 return getTypeIndex(Ty);
2730 const auto *CTy = cast<DICompositeType>(Ty);
2732 TypeLoweringScope S(*
this);
2738 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2739 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2744 if (CTy->isForwardDecl())
2751 auto InsertResult = CompleteTypeIndices.insert({CTy,
TypeIndex()});
2752 if (!InsertResult.second)
2753 return InsertResult.first->second;
2756 switch (CTy->getTag()) {
2757 case dwarf::DW_TAG_class_type:
2758 case dwarf::DW_TAG_structure_type:
2759 TI = lowerCompleteTypeClass(CTy);
2761 case dwarf::DW_TAG_union_type:
2762 TI = lowerCompleteTypeUnion(CTy);
2772 CompleteTypeIndices[CTy] = TI;
2780void CodeViewDebug::emitDeferredCompleteTypes() {
2782 while (!DeferredCompleteTypes.empty()) {
2783 std::swap(DeferredCompleteTypes, TypesToEmit);
2785 getCompleteTypeIndex(RecordTy);
2786 TypesToEmit.clear();
2790void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2794 for (
const LocalVariable &L : Locals)
2795 if (
L.DIVar->isParameter())
2797 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2798 return L->DIVar->getArg() <
R->DIVar->getArg();
2800 for (
const LocalVariable *L : Params)
2801 emitLocalVariable(FI, *L);
2804 for (
const LocalVariable &L : Locals) {
2805 if (!
L.DIVar->isParameter()) {
2806 if (
L.ConstantValue) {
2809 const DIType *Ty =
L.DIVar->getType();
2811 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2813 emitLocalVariable(FI, L);
2819void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2820 const LocalVariable &Var) {
2822 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2825 if (Var.DIVar->isParameter())
2826 Flags |= LocalSymFlags::IsParameter;
2827 if (Var.DefRanges.empty())
2828 Flags |= LocalSymFlags::IsOptimizedOut;
2832 ? getTypeIndexForReferenceTo(Var.DIVar->getType())
2833 : getCompleteTypeIndex(Var.DIVar->
getType());
2839 endSymbolRecord(LocalEnd);
2845 for (
const auto &Pair : Var.DefRanges) {
2846 LocalVarDef DefRange = Pair.first;
2847 const auto &
Ranges = Pair.second;
2849 if (DefRange.InMemory) {
2850 int Offset = DefRange.DataOffset;
2851 unsigned Reg = DefRange.CVRegister;
2858 Offset += FI.OffsetAdjustment;
2865 if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2866 (
bool(Flags & LocalSymFlags::IsParameter)
2867 ? (EncFP == FI.EncodedParamFramePtrReg)
2868 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2874 if (DefRange.IsSubfield) {
2876 (DefRange.StructOffset
2881 DRHdr.
Flags = RegRelFlags;
2886 assert(DefRange.DataOffset == 0 &&
"unexpected offset into register");
2887 if (DefRange.IsSubfield) {
2889 DRHdr.
Register = DefRange.CVRegister;
2895 DRHdr.
Register = DefRange.CVRegister;
2904 const FunctionInfo& FI) {
2905 for (LexicalBlock *
Block : Blocks)
2906 emitLexicalBlock(*
Block, FI);
2911void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2912 const FunctionInfo& FI) {
2913 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2920 OS.
AddComment(
"Function section relative address");
2926 endSymbolRecord(RecordEnd);
2929 emitLocalVariableList(FI,
Block.Locals);
2930 emitGlobalVariableList(
Block.Globals);
2933 emitLexicalBlockList(
Block.Children, FI);
2936 emitEndSymbolRecord(SymbolKind::S_END);
2941void CodeViewDebug::collectLexicalBlockInfo(
2947 collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
2952void CodeViewDebug::collectLexicalBlockInfo(
2957 if (
Scope.isAbstractScope())
2962 bool IgnoreScope =
false;
2963 auto LI = ScopeVariables.find(&Scope);
2965 LI != ScopeVariables.end() ? &LI->second :
nullptr;
2966 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
2968 GI != ScopeGlobals.end() ? GI->second.get() :
nullptr;
2973 if (!Locals && !Globals)
3003 collectLexicalBlockInfo(
Scope.getChildren(),
3013 auto BlockInsertion = CurFn->LexicalBlocks.insert({DILB, LexicalBlock()});
3014 if (!BlockInsertion.second)
3021 LexicalBlock &
Block = BlockInsertion.first->second;
3024 assert(
Block.Begin &&
"missing label for scope begin");
3025 assert(
Block.End &&
"missing label for scope end");
3028 Block.Locals = std::move(*Locals);
3030 Block.Globals = std::move(*Globals);
3032 collectLexicalBlockInfo(
Scope.getChildren(),
3040 assert(FnDebugInfo.count(&GV));
3041 assert(CurFn == FnDebugInfo[&GV].
get());
3047 collectLexicalBlockInfo(*CFS,
3055 ScopeVariables.clear();
3059 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3060 FnDebugInfo.erase(&GV);
3066 for (
const auto &
MBB : *MF) {
3067 for (
const auto &
MI :
MBB) {
3068 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3071 dyn_cast<DIType>(MD)));
3088 return DL &&
DL.getLine() != 0;
3095 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3103 for (
const auto &NextMI : *
MI->getParent()) {
3104 if (NextMI.isDebugInstr())
3106 DL = NextMI.getDebugLoc();
3119 maybeRecordLocation(
DL,
Asm->
MF);
3132void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3140 if (EE.Value == SymKind)
3157void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3166void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3174void CodeViewDebug::emitDebugInfoForUDTs(
3175 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3177 size_t OriginalSize = UDTs.size();
3179 for (
const auto &UDT : UDTs) {
3182 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3184 OS.
emitInt32(getCompleteTypeIndex(
T).getIndex());
3185 assert(OriginalSize == UDTs.size() &&
3186 "getCompleteTypeIndex found new UDTs!");
3188 endSymbolRecord(UDTRecordEnd);
3192void CodeViewDebug::collectGlobalVariableInfo() {
3197 GV.getDebugInfo(GVEs);
3198 for (
const auto *GVE : GVEs)
3199 GlobalMap[GVE] = &GV;
3204 const auto *
CU = cast<DICompileUnit>(
Node);
3205 for (
const auto *GVE :
CU->getGlobalVariables()) {
3214 if ((
DIE->getNumElements() == 2) &&
3215 (
DIE->getElement(0) == dwarf::DW_OP_plus_uconst))
3220 CVGlobalVariableOffsets.insert(
3221 std::make_pair(DIGV,
DIE->getElement(1)));
3224 if (GlobalMap.
count(GVE) == 0 &&
DIE->isConstant()) {
3225 CVGlobalVariable CVGV = {DIGV,
DIE};
3229 const auto *GV = GlobalMap.
lookup(GVE);
3235 if (Scope && isa<DILocalScope>(Scope)) {
3238 auto Insertion = ScopeGlobals.insert(
3239 {
Scope, std::unique_ptr<GlobalVariableList>()});
3240 if (Insertion.second)
3241 Insertion.first->second = std::make_unique<GlobalVariableList>();
3242 VariableList = Insertion.first->second.get();
3245 VariableList = &ComdatVariables;
3248 VariableList = &GlobalVariables;
3249 CVGlobalVariable CVGV = {DIGV, GV};
3255void CodeViewDebug::collectDebugInfoForGlobals() {
3256 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3259 getCompleteTypeIndex(DIGV->
getType());
3260 getFullyQualifiedName(Scope, DIGV->
getName());
3263 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3266 getCompleteTypeIndex(DIGV->
getType());
3267 getFullyQualifiedName(Scope, DIGV->
getName());
3271void CodeViewDebug::emitDebugInfoForGlobals() {
3275 switchToDebugSectionForSymbol(
nullptr);
3276 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3277 OS.
AddComment(
"Symbol subsection for globals");
3278 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3279 emitGlobalVariableList(GlobalVariables);
3280 emitStaticConstMemberList();
3281 endCVSubsection(EndLabel);
3286 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3291 switchToDebugSectionForSymbol(GVSym);
3292 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3294 emitDebugInfoForGlobal(CVGV);
3295 endCVSubsection(EndLabel);
3299void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3302 for (
auto *Ty : cast<DICompileUnit>(
Node)->getRetainedTypes()) {
3303 if (
DIType *RT = dyn_cast<DIType>(Ty)) {
3313 for (
const CVGlobalVariable &CVGV : Globals) {
3315 emitDebugInfoForGlobal(CVGV);
3321 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3323 OS.
emitInt32(getTypeIndex(DTy).getIndex());
3337 endSymbolRecord(SConstantEnd);
3340void CodeViewDebug::emitStaticConstMemberList() {
3346 dyn_cast_or_null<ConstantInt>(DTy->getConstant()))
3350 dyn_cast_or_null<ConstantFP>(DTy->getConstant()))
3351 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3355 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3356 getFullyQualifiedName(Scope, DTy->
getName()));
3361 if (isa<DICompositeType>(Ty))
3364 if (
auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
3366 if (
T == dwarf::DW_TAG_pointer_type ||
3367 T == dwarf::DW_TAG_ptr_to_member_type ||
3368 T == dwarf::DW_TAG_reference_type ||
3369 T == dwarf::DW_TAG_rvalue_reference_type)
3371 assert(DTy->getBaseType() &&
"Expected valid base type");
3375 auto *BTy = cast<DIBasicType>(Ty);
3376 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3379void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3384 if (
const auto *MemberDecl = dyn_cast_or_null<DIDerivedType>(
3386 Scope = MemberDecl->getScope();
3392 ? std::string(DIGV->
getName())
3402 : SymbolKind::S_GTHREAD32)
3404 : SymbolKind::S_GDATA32);
3411 if (CVGlobalVariableOffsets.contains(DIGV))
3413 Offset = CVGlobalVariableOffsets[DIGV];
3419 const unsigned LengthOfDataRecord = 12;
3421 endSymbolRecord(DataEnd);
3425 "Global constant variables must contain a constant expression.");
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
static bool canUseReferenceType(const DbgVariableLocation &Loc)
static SourceLanguage MapDWLangToCVLang(unsigned DWLang)
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)
static CallingConvention dwarfCCToCodeView(unsigned DwarfCC)
Given a DWARF calling convention, get the CodeView equivalent.
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 std::string flattenCommandLine(ArrayRef< std::string > Args, StringRef MainFilename)
static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty)
static bool needsReferenceType(const DbgVariableLocation &Loc)
static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file contains constants used for implementing Dwarf debug support.
unsigned const TargetRegisterInfo * TRI
Module.h This file contains the declarations for the Module class.
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallString class.
static SymbolRef::Type getType(const Symbol *Sym)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static const uint32_t IV[8]
Class for arbitrary precision integers.
An arbitrary precision integer that knows its signedness.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
size - Get the array size.
This class is intended to be used as a driving class for all asm writers.
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
MCSymbol * getSymbol(const GlobalValue *GV) const
TargetMachine & TM
Target machine description.
MCSymbol * getFunctionBegin() const
const MCAsmInfo * MAI
Target Asm Printer information.
MachineFunction * MF
The current machine function.
MCSymbol * getFunctionEnd() const
Provides write only access to a subclass of WritableBinaryStream.
Collects and handles line tables information in a CodeView format.
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.
ConstantFP - Floating Point Values [float, double].
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.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Basic type, like 'int' or 'float'.
unsigned getEncoding() const
StringRef getIdentifier() const
DINodeArray getElements() const
DIType * getBaseType() const
Constant * getConstant() const
A structured debug information entry.
static DIE * get(BumpPtrAllocator &Alloc, dwarf::Tag Tag)
bool isLocalToUnit() const
Metadata * getRawStaticDataMemberDeclaration() const
DILocalScope * getScope() const
Get the local scope for this variable.
Tagged DWARF-like metadata node.
dwarf::Tag getTag() const
Base class for scope-like contexts.
StringRef getFilename() const
StringRef getName() const
StringRef getDirectory() const
DIScope * getScope() const
String type, Fortran CHARACTER(n)
Type array for a subprogram.
DITypeRefArray getTypeArray() const
uint64_t getOffsetInBits() const
bool isObjectPointer() const
StringRef getName() const
bool isForwardDecl() const
uint64_t getSizeInBits() const
DIScope * getScope() const
DIScope * getScope() const
StringRef getName() const
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
static const EntryIndex NoEntry
Special value to indicate that an entry is valid until the end of the function.
Base class for debug information backends.
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.
DebugLoc PrologEndLoc
This location indicates end of function prologue and beginning of function body.
MCSymbol * getLabelAfterInsn(const MachineInstr *MI)
Return Label immediately following the instruction.
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.
static uint64_t getBaseTypeSize(const DIType *Ty)
If this type is derived from a base type then return base type size.
DebugLoc getFnDebugLoc() const
Find the debug info location for the start of the function.
DILocation * get() const
Get the underlying DILocation.
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.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Implements a dense probed hash-table based set.
Lightweight error class with error context and mandatory checking.
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).
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
bool hasLocalLinkage() const
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
bool isDeclarationForLinker() const
LexicalScope - This class is used to track scope information.
LexicalScope * findLexicalScope(const DILocation *DL)
findLexicalScope - Find lexical scope, either regular or inlined, for the given DebugLoc.
LexicalScope * findInlinedScope(const DILocalScope *N, const DILocation *IA)
findInlinedScope - Find an inlined scope for the given scope/inlined-at.
LexicalScope * getCurrentFunctionScope() const
getCurrentFunctionScope - Return lexical scope for the current function.
unsigned getCodePointerSize() const
Get the code pointer size in bytes.
void * allocate(unsigned Size, unsigned Align=8)
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSectionCOFF * getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym, unsigned UniqueID=GenericSectionID)
Gets or creates a section equivalent to Sec that is associated with the section containing KeySym.
MCSection * getCOFFDebugSymbolsSection() const
MCSection * getCOFFDebugTypesSection() const
MCSection * getCOFFGlobalTypeHashesSection() const
This represents a section on Windows.
MCSymbol * getCOMDATSymbol() const
Streaming machine code generation interface.
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
virtual bool emitCVFuncIdDirective(unsigned FunctionId)
Introduces a function id for use with .cv_loc.
virtual void emitBinaryData(StringRef Data)
Functionally identical to EmitBytes.
virtual bool emitCVFileDirective(unsigned FileNo, StringRef Filename, ArrayRef< uint8_t > Checksum, unsigned ChecksumKind)
Associate a filename with a specified logical file number, and also specify that file's checksum info...
virtual void emitCVStringTableDirective()
This implements the CodeView '.cv_stringtable' assembler directive.
virtual bool isVerboseAsm() const
Return true if this streamer supports verbose assembly and if it is enabled.
virtual void emitCVFileChecksumOffsetDirective(unsigned FileNo)
This implements the CodeView '.cv_filechecksumoffset' assembler directive.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitCVFPOData(const MCSymbol *ProcSym, SMLoc Loc={})
This implements the CodeView '.cv_fpo_data' assembler directive.
virtual void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset)
Emits a COFF section relative relocation.
virtual void emitCVFileChecksumsDirective()
This implements the CodeView '.cv_filechecksums' assembler directive.
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 emitCOFFSectionIndex(MCSymbol const *Symbol)
Emits a COFF section index.
virtual void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, const MCSymbol *FnEnd)
This implements the CodeView '.cv_linetable' assembler directive.
virtual void emitValueToAlignment(Align Alignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
virtual void emitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers.
void emitInt16(uint64_t Value)
virtual void switchSection(MCSection *Section, const MCExpr *Subsection=nullptr)
Set the current section where code is being emitted to Section.
virtual void emitCVDefRangeDirective(ArrayRef< std::pair< const MCSymbol *, const MCSymbol * > > Ranges, StringRef FixedSizePortion)
This implements the CodeView '.cv_def_range' assembler directive.
void emitInt32(uint64_t Value)
virtual void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, unsigned Column, bool PrologueEnd, bool IsStmt, StringRef FileName, SMLoc Loc)
This implements the CodeView '.cv_loc' assembler directive.
virtual bool emitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc, unsigned IAFile, unsigned IALine, unsigned IACol, SMLoc Loc)
Introduces an inline call site id for use with .cv_loc.
void emitInt8(uint64_t Value)
virtual void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym)
This implements the CodeView '.cv_inline_linetable' assembler directive.
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< std::string > CommandLineArgs
ArrayRef< MDOperand > operands() const
unsigned getNumOperands() const
Return number of MDNode operands.
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.
int 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.
Function & getFunction()
Return the LLVM function that this machine code represents.
VariableDbgInfoMapTy & getVariableDbgInfo()
ArrayRef< std::pair< MCSymbol *, MDNode * > > getCodeViewAnnotations() const
Representation of each machine instruction.
bool isDebugValue() const
MachineOperand & getDebugOperand(unsigned Index)
const MCContext & getContext() const
const Module * getModule() const
bool hasDebugInfo() const
Returns true if valid debug info is present.
A Module instance is used to store all the information related to an LLVM module.
NamedMDNode * getNamedMetadata(const Twine &Name) const
Return the first NamedMDNode in the module with the specified name.
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
iterator_range< global_iterator > globals()
Metadata * getProfileSummary(bool IsCS) const
Returns profile summary metadata.
iterator_range< op_iterator > operands()
Wrapper class representing virtual and physical registers.
Represents a location in source code.
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.
StackOffset holds a fixed and a scalable offset in bytes.
static StackOffset getScalable(int64_t Scalable)
static StackOffset getFixed(int64_t Fixed)
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
char back() const
back - Get the last character in the string.
bool startswith(StringRef Prefix) const
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Information about stack frame layout on the target.
virtual bool hasFP(const MachineFunction &MF) const =0
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...
CodeGenOpt::Level getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
MCTargetOptions MCOptions
Machine level options.
std::string ObjectFilenameForDebug
Stores the filename/path of the final .o/.obj file, to be written in the debug information.
unsigned Hotpatch
Emit the hotpatch flag in CodeView debug.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetFrameLowering * getFrameLowering() const
TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...
Triple - Helper class for working with autoconf configuration names.
ArchType getArch() const
Get the parsed architecture type of this triple.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
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)
virtual void emitBytes(StringRef Data)=0
virtual bool isVerboseAsm()=0
virtual void AddComment(const Twine &T)=0
virtual void emitIntValue(uint64_t Value, unsigned Size)=0
virtual void emitBinaryData(StringRef Data)=0
virtual void AddRawComment(const Twine &T)=0
void begin(ContinuationRecordKind RecordKind)
void writeMemberType(RecordType &Record)
ArrayRef< ArrayRef< uint8_t > > records() const
TypeIndex insertRecord(ContinuationRecordBuilder &Builder)
ArrayRef< GloballyHashedType > hashes() const
TypeIndex writeLeafType(T &Record)
For method overload sets. LF_METHOD.
SimpleTypeKind getSimpleKind() const
SimpleTypeMode getSimpleMode() const
static const uint32_t FirstNonSimpleIndex
static 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.
A raw_ostream that writes to an std::string.
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
@ DEBUG_HASHES_SECTION_MAGIC
@ C
The default llvm calling convention, compatible with C.
Reg
All possible values of the reg field in the ModR/M byte.
PointerMode
Equivalent to CV_ptrmode_e.
PointerOptions
Equivalent to misc lfPointerAttr bitfields.
LocalSymFlags
Corresponds to CV_LVARFLAGS bitfield.
MethodKind
Part of member attribute flags. (CV_methodprop_e)
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.
MethodOptions
Equivalent to CV_fldattr_t bitfield.
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.
StringRef getSymbolName(CVSymbol Sym)
EncodedFramePtrReg encodeFramePtrReg(RegisterId Reg, CPUType CPU)
Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote)
Print a command argument, and optionally quote it.
This is an optimization pass for GlobalISel generic memory operations.
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
std::tuple< uint64_t, uint32_t > InlineSite
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
StringRef getTypeName()
We provide a function which tries to compute the (demangled) name of a type statically.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
std::pair< const MachineInstr *, const MachineInstr * > InsnRange
InsnRange - This is used to track range of instructions with identical lexical scope.
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
std::vector< const DIDerivedType * > Inheritance
Base classes.
int InMemory
Indicates that variable data is stored in memory relative to the specified register.
Represents the location at which a variable is stored.
static std::optional< DbgVariableLocation > extractFromMachineInstruction(const MachineInstr &Instruction)
Extract a VariableLocation from a MachineInstr.
SmallVector< int64_t, 1 > LoadChain
Chain of offsetted loads necessary to load the value if it lives in memory.