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 ==
"-") {
803 endSymbolRecord(CompilerEnd);
817 for (
const char C :
Name) {
820 V.Part[
N] +=
C -
'0';
822 std::min<int>(V.Part[
N], std::numeric_limits<uint16_t>::max());
823 }
else if (
C ==
'.') {
833void CodeViewDebug::emitCompilerInformation() {
834 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
838 Flags = CurrentSourceLanguage;
846 Arch == ArchType::aarch64) {
858 const auto *
CU = cast<DICompileUnit>(
Node);
863 for (
int N : FrontVer.Part) {
870 int Major = 1000 * LLVM_VERSION_MAJOR +
871 10 * LLVM_VERSION_MINOR +
874 Major = std::min<int>(Major, std::numeric_limits<uint16_t>::max());
875 Version BackVer = {{ Major, 0, 0, 0 }};
877 for (
int N : BackVer.Part)
880 OS.
AddComment(
"Null-terminated compiler version string");
883 endSymbolRecord(CompilerEnd);
894 std::string FlatCmdLine;
896 bool PrintedOneArg =
false;
899 PrintedOneArg =
true;
901 for (
unsigned i = 0; i < Args.size(); i++) {
905 if (
Arg ==
"-main-file-name" ||
Arg ==
"-o") {
909 if (
Arg.startswith(
"-object-file-name") ||
Arg == MainFilename)
912 if (
Arg.startswith(
"-fmessage-length"))
917 PrintedOneArg =
true;
923void CodeViewDebug::emitBuildInfo() {
937 const auto *
CU = cast<DICompileUnit>(
Node);
938 const DIFile *MainSourceFile =
CU->getFile();
958 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
959 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
962 endSymbolRecord(BIEnd);
963 endCVSubsection(BISubsecEnd);
966void CodeViewDebug::emitInlineeLinesSubsection() {
967 if (InlinedSubprograms.empty())
971 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
978 OS.
emitInt32(
unsigned(InlineeLinesSignature::Normal));
981 assert(TypeIndices.count({SP, nullptr}));
982 TypeIndex InlineeIdx = TypeIndices[{SP,
nullptr}];
985 unsigned FileId = maybeRecordFile(SP->
getFile());
989 OS.
AddComment(
"Type index of inlined function");
991 OS.
AddComment(
"Offset into filechecksum table");
997 endCVSubsection(InlineEnd);
1000void CodeViewDebug::emitInlinedCallSite(
const FunctionInfo &FI,
1003 assert(TypeIndices.count({Site.Inlinee, nullptr}));
1004 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee,
nullptr}];
1007 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
1016 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
1017 unsigned StartLineNum = Site.Inlinee->getLine();
1022 endSymbolRecord(InlineEnd);
1024 emitLocalVariableList(FI, Site.InlinedLocals);
1027 for (
const DILocation *ChildSite : Site.ChildSites) {
1028 auto I = FI.InlineSites.find(ChildSite);
1029 assert(
I != FI.InlineSites.end() &&
1030 "child site not in function inline site map");
1031 emitInlinedCallSite(FI, ChildSite,
I->second);
1035 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1038void CodeViewDebug::switchToDebugSectionForSymbol(
const MCSymbol *GVSym) {
1043 GVSym ? dyn_cast<MCSectionCOFF>(&GVSym->
getSection()) : nullptr;
1054 if (ComdatDebugSections.insert(DebugSec).second)
1055 emitCodeViewMagicVersion();
1060void CodeViewDebug::emitDebugInfoForThunk(
const Function *GV,
1063 std::string FuncName =
1068 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1071 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1078 OS.
AddComment(
"Thunk section relative address");
1089 endSymbolRecord(ThunkRecordEnd);
1095 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1097 endCVSubsection(SymbolsEnd);
1100void CodeViewDebug::emitDebugInfoForFunction(
const Function *GV,
1108 switchToDebugSectionForSymbol(Fn);
1110 std::string FuncName;
1113 setCurrentSubprogram(SP);
1115 if (SP->isThunk()) {
1116 emitDebugInfoForThunk(GV, FI, Fn);
1126 if (FuncName.empty())
1135 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1138 : SymbolKind::S_GPROC32_ID;
1139 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1158 OS.
AddComment(
"Function section relative address");
1163 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;
1164 if (FI.HasFramePointer)
1165 ProcFlags |= ProcSymFlags::HasFP;
1167 ProcFlags |= ProcSymFlags::IsNoReturn;
1169 ProcFlags |= ProcSymFlags::IsNoInline;
1170 OS.
emitInt8(
static_cast<uint8_t
>(ProcFlags));
1175 endSymbolRecord(ProcRecordEnd);
1177 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1180 OS.
emitInt32(FI.FrameSize - FI.CSRSize);
1185 OS.
AddComment(
"Bytes of callee saved registers");
1191 OS.
AddComment(
"Flags (defines frame register)");
1193 endSymbolRecord(FrameProcEnd);
1195 emitLocalVariableList(FI, FI.Locals);
1196 emitGlobalVariableList(FI.Globals);
1197 emitLexicalBlockList(FI.ChildBlocks, FI);
1202 for (
const DILocation *InlinedAt : FI.ChildSites) {
1203 auto I = FI.InlineSites.find(InlinedAt);
1204 assert(
I != FI.InlineSites.end() &&
1205 "child site not in function inline site map");
1206 emitInlinedCallSite(FI, InlinedAt,
I->second);
1209 for (
auto Annot : FI.Annotations) {
1211 MDTuple *Strs = cast<MDTuple>(Annot.second);
1212 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1220 StringRef Str = cast<MDString>(MD)->getString();
1221 assert(Str.data()[Str.size()] ==
'\0' &&
"non-nullterminated MDString");
1224 endSymbolRecord(AnnotEnd);
1227 for (
auto HeapAllocSite : FI.HeapAllocSites) {
1228 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1229 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1230 const DIType *DITy = std::get<2>(HeapAllocSite);
1231 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1239 OS.
emitInt32(getCompleteTypeIndex(DITy).getIndex());
1240 endSymbolRecord(HeapAllocEnd);
1244 emitDebugInfoForUDTs(LocalUDTs);
1247 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1249 endCVSubsection(SymbolsEnd);
1256CodeViewDebug::createDefRangeMem(
uint16_t CVRegister,
int Offset) {
1262 DR.StructOffset = 0;
1263 DR.CVRegister = CVRegister;
1267void CodeViewDebug::collectVariableInfoFromMFTable(
1278 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1279 "Expected inlined-at fields to agree");
1281 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1290 int64_t ExprOffset = 0;
1294 if (
VI.Expr->getNumElements() == 1 &&
1295 VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)
1297 else if (!
VI.Expr->extractIfOffset(ExprOffset))
1305 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1308 "Frame offsets with a scalable component are not supported");
1311 LocalVarDef DefRange =
1312 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset);
1321 Var.DefRanges[DefRange].emplace_back(Begin,
End);
1325 Var.UseReferenceType =
true;
1327 recordLocalVariable(std::move(Var), Scope);
1339void CodeViewDebug::calculateRanges(
1344 for (
auto I = Entries.begin(),
E = Entries.end();
I !=
E; ++
I) {
1345 const auto &Entry = *
I;
1346 if (!Entry.isDbgValue())
1352 std::optional<DbgVariableLocation>
Location =
1374 if (Var.UseReferenceType) {
1383 Var.UseReferenceType =
true;
1384 Var.DefRanges.clear();
1385 calculateRanges(Var, Entries);
1394 DR.CVRegister =
TRI->getCodeViewRegNum(
Location->Register);
1395 DR.InMemory = !
Location->LoadChain.empty();
1399 DR.IsSubfield =
true;
1400 DR.StructOffset =
Location->FragmentInfo->OffsetInBits / 8;
1402 DR.IsSubfield =
false;
1403 DR.StructOffset = 0;
1410 auto &EndingEntry = Entries[Entry.getEndIndex()];
1411 End = EndingEntry.isDbgValue()
1421 if (!
R.empty() &&
R.back().second == Begin)
1422 R.back().second =
End;
1424 R.emplace_back(Begin,
End);
1430void CodeViewDebug::collectVariableInfo(
const DISubprogram *SP) {
1433 collectVariableInfoFromMFTable(Processed);
1436 InlinedEntity
IV =
I.first;
1443 const auto &Entries =
I.second;
1457 calculateRanges(Var, Entries);
1458 recordLocalVariable(std::move(Var), Scope);
1467 auto Insertion = FnDebugInfo.insert({&GV, std::make_unique<FunctionInfo>()});
1468 assert(Insertion.second &&
"function already has info");
1469 CurFn = Insertion.first->second.get();
1470 CurFn->FuncId = NextFuncId++;
1479 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1483 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::None;
1484 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::None;
1485 if (CurFn->FrameSize > 0) {
1487 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1488 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr;
1490 CurFn->HasFramePointer =
true;
1492 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr;
1493 if (CurFn->HasStackRealignment) {
1495 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1499 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::FramePtr;
1507 FPO |= FrameProcedureOptions::HasAlloca;
1509 FPO |= FrameProcedureOptions::HasSetJmp;
1512 FPO |= FrameProcedureOptions::HasInlineAssembly;
1516 FPO |= FrameProcedureOptions::HasStructuredExceptionHandling;
1518 FPO |= FrameProcedureOptions::HasExceptionHandling;
1521 FPO |= FrameProcedureOptions::MarkedInline;
1523 FPO |= FrameProcedureOptions::Naked;
1525 FPO |= FrameProcedureOptions::SecurityChecks;
1528 FPO |= FrameProcedureOptions::StrictSecurityChecks;
1532 FPO |= FrameProcedureOptions::SafeBuffers;
1538 FPO |= FrameProcedureOptions::OptimizedForSpeed;
1540 FPO |= FrameProcedureOptions::ValidProfileCounts;
1541 FPO |= FrameProcedureOptions::ProfileGuidedOptimization;
1544 CurFn->FrameProcOpts = FPO;
1553 bool EmptyPrologue =
true;
1554 for (
const auto &
MBB : *MF) {
1555 for (
const auto &
MI :
MBB) {
1560 }
else if (!
MI.isMetaInstruction()) {
1561 EmptyPrologue =
false;
1569 maybeRecordLocation(FnStartDL, MF);
1573 for (
const auto &
MBB : *MF) {
1574 for (
const auto &
MI :
MBB) {
1575 if (
MI.getHeapAllocMarker()) {
1588 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1589 if (
DIScope *Scope =
T->getScope()) {
1590 switch (Scope->getTag()) {
1591 case dwarf::DW_TAG_structure_type:
1592 case dwarf::DW_TAG_class_type:
1593 case dwarf::DW_TAG_union_type:
1603 if (!
T ||
T->isForwardDecl())
1609 T = DT->getBaseType();
1614void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1623 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1625 std::string FullyQualifiedName =
1628 if (ClosestSubprogram ==
nullptr) {
1629 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1630 }
else if (ClosestSubprogram == CurrentSubprogram) {
1631 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1645 case dwarf::DW_TAG_array_type:
1646 return lowerTypeArray(cast<DICompositeType>(Ty));
1647 case dwarf::DW_TAG_typedef:
1648 return lowerTypeAlias(cast<DIDerivedType>(Ty));
1649 case dwarf::DW_TAG_base_type:
1650 return lowerTypeBasic(cast<DIBasicType>(Ty));
1651 case dwarf::DW_TAG_pointer_type:
1652 if (cast<DIDerivedType>(Ty)->
getName() ==
"__vtbl_ptr_type")
1653 return lowerTypeVFTableShape(cast<DIDerivedType>(Ty));
1655 case dwarf::DW_TAG_reference_type:
1656 case dwarf::DW_TAG_rvalue_reference_type:
1657 return lowerTypePointer(cast<DIDerivedType>(Ty));
1658 case dwarf::DW_TAG_ptr_to_member_type:
1659 return lowerTypeMemberPointer(cast<DIDerivedType>(Ty));
1660 case dwarf::DW_TAG_restrict_type:
1661 case dwarf::DW_TAG_const_type:
1662 case dwarf::DW_TAG_volatile_type:
1664 return lowerTypeModifier(cast<DIDerivedType>(Ty));
1665 case dwarf::DW_TAG_subroutine_type:
1669 return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy,
1673 return lowerTypeFunction(cast<DISubroutineType>(Ty));
1674 case dwarf::DW_TAG_enumeration_type:
1675 return lowerTypeEnum(cast<DICompositeType>(Ty));
1676 case dwarf::DW_TAG_class_type:
1677 case dwarf::DW_TAG_structure_type:
1678 return lowerTypeClass(cast<DICompositeType>(Ty));
1679 case dwarf::DW_TAG_union_type:
1680 return lowerTypeUnion(cast<DICompositeType>(Ty));
1681 case dwarf::DW_TAG_string_type:
1682 return lowerTypeString(cast<DIStringType>(Ty));
1683 case dwarf::DW_TAG_unspecified_type:
1684 if (Ty->
getName() ==
"decltype(nullptr)")
1694 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1699 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::Int32Long) &&
1700 TypeName ==
"HRESULT")
1701 return TypeIndex(SimpleTypeKind::HResult);
1702 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::UInt16Short) &&
1703 TypeName ==
"wchar_t")
1704 return TypeIndex(SimpleTypeKind::WideCharacter);
1706 return UnderlyingTypeIndex;
1711 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1713 TypeIndex IndexType = getPointerSizeInBytes() == 8
1721 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1723 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1732 if (
auto *CI = dyn_cast_if_present<ConstantInt *>(
Subrange->getCount()))
1733 Count = CI->getSExtValue();
1734 else if (
auto *UI = dyn_cast_if_present<ConstantInt *>(
1738 auto *LI = dyn_cast_if_present<ConstantInt *>(
Subrange->getLowerBound());
1739 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1740 Count = UI->getSExtValue() - Lowerbound + 1;
1751 ElementSize *= Count;
1756 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1763 return ElementTypeIndex;
1776 TypeIndex IndexType = getPointerSizeInBytes() == 8
1796 case dwarf::DW_ATE_address:
1799 case dwarf::DW_ATE_boolean:
1801 case 1: STK = SimpleTypeKind::Boolean8;
break;
1802 case 2: STK = SimpleTypeKind::Boolean16;
break;
1803 case 4: STK = SimpleTypeKind::Boolean32;
break;
1804 case 8: STK = SimpleTypeKind::Boolean64;
break;
1805 case 16: STK = SimpleTypeKind::Boolean128;
break;
1808 case dwarf::DW_ATE_complex_float:
1812 case 4: STK = SimpleTypeKind::Complex16;
break;
1813 case 8: STK = SimpleTypeKind::Complex32;
break;
1814 case 16: STK = SimpleTypeKind::Complex64;
break;
1815 case 20: STK = SimpleTypeKind::Complex80;
break;
1816 case 32: STK = SimpleTypeKind::Complex128;
break;
1819 case dwarf::DW_ATE_float:
1821 case 2: STK = SimpleTypeKind::Float16;
break;
1822 case 4: STK = SimpleTypeKind::Float32;
break;
1823 case 6: STK = SimpleTypeKind::Float48;
break;
1824 case 8: STK = SimpleTypeKind::Float64;
break;
1825 case 10: STK = SimpleTypeKind::Float80;
break;
1826 case 16: STK = SimpleTypeKind::Float128;
break;
1829 case dwarf::DW_ATE_signed:
1831 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1832 case 2: STK = SimpleTypeKind::Int16Short;
break;
1833 case 4: STK = SimpleTypeKind::Int32;
break;
1834 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1835 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1838 case dwarf::DW_ATE_unsigned:
1840 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1841 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1842 case 4: STK = SimpleTypeKind::UInt32;
break;
1843 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1844 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1847 case dwarf::DW_ATE_UTF:
1849 case 1: STK = SimpleTypeKind::Character8;
break;
1850 case 2: STK = SimpleTypeKind::Character16;
break;
1851 case 4: STK = SimpleTypeKind::Character32;
break;
1854 case dwarf::DW_ATE_signed_char:
1856 STK = SimpleTypeKind::SignedCharacter;
1858 case dwarf::DW_ATE_unsigned_char:
1860 STK = SimpleTypeKind::UnsignedCharacter;
1870 if (STK == SimpleTypeKind::Int32 &&
1872 STK = SimpleTypeKind::Int32Long;
1873 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1874 Ty->
getName() ==
"unsigned long"))
1875 STK = SimpleTypeKind::UInt32Long;
1876 if (STK == SimpleTypeKind::UInt16Short &&
1878 STK = SimpleTypeKind::WideCharacter;
1879 if ((STK == SimpleTypeKind::SignedCharacter ||
1880 STK == SimpleTypeKind::UnsignedCharacter) &&
1882 STK = SimpleTypeKind::NarrowCharacter;
1889 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1893 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1895 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1897 ? SimpleTypeMode::NearPointer64
1898 : SimpleTypeMode::NearPointer32;
1903 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1907 case dwarf::DW_TAG_pointer_type:
1908 PM = PointerMode::Pointer;
1910 case dwarf::DW_TAG_reference_type:
1911 PM = PointerMode::LValueReference;
1913 case dwarf::DW_TAG_rvalue_reference_type:
1914 PM = PointerMode::RValueReference;
1919 PO |= PointerOptions::Const;
1933 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1934 : PointerToMemberRepresentation::GeneralFunction;
1935 case DINode::FlagSingleInheritance:
1936 return PointerToMemberRepresentation::SingleInheritanceFunction;
1937 case DINode::FlagMultipleInheritance:
1938 return PointerToMemberRepresentation::MultipleInheritanceFunction;
1939 case DINode::FlagVirtualInheritance:
1940 return PointerToMemberRepresentation::VirtualInheritanceFunction;
1945 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1946 : PointerToMemberRepresentation::GeneralData;
1947 case DINode::FlagSingleInheritance:
1948 return PointerToMemberRepresentation::SingleInheritanceData;
1949 case DINode::FlagMultipleInheritance:
1950 return PointerToMemberRepresentation::MultipleInheritanceData;
1951 case DINode::FlagVirtualInheritance:
1952 return PointerToMemberRepresentation::VirtualInheritanceData;
1960 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
1961 bool IsPMF = isa<DISubroutineType>(Ty->getBaseType());
1962 TypeIndex ClassTI = getTypeIndex(Ty->getClassType());
1964 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->getClassType() :
nullptr);
1965 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
1966 : PointerKind::Near32;
1967 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
1968 : PointerMode::PointerToDataMember;
1982 case dwarf::DW_CC_normal:
return CallingConvention::NearC;
1983 case dwarf::DW_CC_BORLAND_msfastcall:
return CallingConvention::NearFast;
1984 case dwarf::DW_CC_BORLAND_thiscall:
return CallingConvention::ThisCall;
1985 case dwarf::DW_CC_BORLAND_stdcall:
return CallingConvention::NearStdCall;
1986 case dwarf::DW_CC_BORLAND_pascal:
return CallingConvention::NearPascal;
1987 case dwarf::DW_CC_LLVM_vectorcall:
return CallingConvention::NearVector;
1989 return CallingConvention::NearC;
1997 while (IsModifier &&
BaseTy) {
1999 switch (
BaseTy->getTag()) {
2000 case dwarf::DW_TAG_const_type:
2001 Mods |= ModifierOptions::Const;
2002 PO |= PointerOptions::Const;
2004 case dwarf::DW_TAG_volatile_type:
2005 Mods |= ModifierOptions::Volatile;
2006 PO |= PointerOptions::Volatile;
2008 case dwarf::DW_TAG_restrict_type:
2011 PO |= PointerOptions::Restrict;
2026 switch (
BaseTy->getTag()) {
2027 case dwarf::DW_TAG_pointer_type:
2028 case dwarf::DW_TAG_reference_type:
2029 case dwarf::DW_TAG_rvalue_reference_type:
2030 return lowerTypePointer(cast<DIDerivedType>(
BaseTy), PO);
2031 case dwarf::DW_TAG_ptr_to_member_type:
2032 return lowerTypeMemberPointer(cast<DIDerivedType>(
BaseTy), PO);
2042 if (Mods == ModifierOptions::None)
2052 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2055 if (ReturnAndArgTypeIndices.
size() > 1 &&
2061 if (!ReturnAndArgTypeIndices.
empty()) {
2062 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2063 ReturnTypeIndex = ReturnAndArgTypesRef.front();
2064 ArgTypeIndices = ReturnAndArgTypesRef.
drop_front();
2067 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2081 bool IsStaticMethod,
2084 TypeIndex ClassType = getTypeIndex(ClassTy);
2092 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[
Index++]);
2099 if (!IsStaticMethod && ReturnAndArgs.
size() >
Index) {
2101 dyn_cast_or_null<DIDerivedType>(ReturnAndArgs[
Index])) {
2102 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2103 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2116 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2122 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2127 unsigned VSlotCount =
2137 case DINode::FlagPrivate:
return MemberAccess::Private;
2138 case DINode::FlagPublic:
return MemberAccess::Public;
2139 case DINode::FlagProtected:
return MemberAccess::Protected;
2142 return RecordTag == dwarf::DW_TAG_class_type ? MemberAccess::Private
2143 : MemberAccess::Public;
2149 if (SP->isArtificial())
2150 return MethodOptions::CompilerGenerated;
2154 return MethodOptions::None;
2159 if (SP->getFlags() & DINode::FlagStaticMember)
2160 return MethodKind::Static;
2162 switch (SP->getVirtuality()) {
2163 case dwarf::DW_VIRTUALITY_none:
2165 case dwarf::DW_VIRTUALITY_virtual:
2166 return Introduced ? MethodKind::IntroducingVirtual : MethodKind::Virtual;
2167 case dwarf::DW_VIRTUALITY_pure_virtual:
2168 return Introduced ? MethodKind::PureIntroducingVirtual
2169 : MethodKind::PureVirtual;
2174 return MethodKind::Vanilla;
2179 case dwarf::DW_TAG_class_type:
2180 return TypeRecordKind::Class;
2181 case dwarf::DW_TAG_structure_type:
2182 return TypeRecordKind::Struct;
2197 CO |= ClassOptions::HasUniqueName;
2203 if (ImmediateScope && isa<DICompositeType>(ImmediateScope))
2204 CO |= ClassOptions::Nested;
2210 if (Ty->
getTag() == dwarf::DW_TAG_enumeration_type) {
2211 if (ImmediateScope && isa<DISubprogram>(ImmediateScope))
2212 CO |= ClassOptions::Scoped;
2214 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2215 Scope = Scope->getScope()) {
2216 if (isa<DISubprogram>(Scope)) {
2217 CO |= ClassOptions::Scoped;
2228 case dwarf::DW_TAG_class_type:
2229 case dwarf::DW_TAG_structure_type:
2230 case dwarf::DW_TAG_union_type:
2231 case dwarf::DW_TAG_enumeration_type:
2237 if (
const auto *File = Ty->
getFile()) {
2249 unsigned EnumeratorCount = 0;
2252 CO |= ClassOptions::ForwardReference;
2255 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2259 if (
auto *
Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) {
2271 std::string FullName = getFullyQualifiedName(Ty);
2277 addUDTSrcLine(Ty, EnumTI);
2311void CodeViewDebug::clear() {
2312 assert(CurFn ==
nullptr);
2314 FnDebugInfo.clear();
2315 FileToFilepathMap.clear();
2318 TypeIndices.clear();
2319 CompleteTypeIndices.clear();
2320 ScopeGlobals.clear();
2321 CVGlobalVariableOffsets.clear();
2324void CodeViewDebug::collectMemberInfo(
ClassInfo &Info,
2327 Info.Members.push_back({DDTy, 0});
2330 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2331 DINode::FlagStaticMember) {
2334 StaticConstMembers.push_back(DDTy);
2346 const DIType *Ty = DDTy->getBaseType();
2347 bool FullyResolved =
false;
2348 while (!FullyResolved) {
2350 case dwarf::DW_TAG_const_type:
2351 case dwarf::DW_TAG_volatile_type:
2354 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2357 FullyResolved =
true;
2366 ClassInfo NestedInfo = collectClassInfo(DCTy);
2368 Info.Members.push_back(
2376 for (
auto *Element : Elements) {
2381 if (
auto *SP = dyn_cast<DISubprogram>(Element)) {
2382 Info.Methods[SP->getRawName()].push_back(SP);
2383 }
else if (
auto *DDTy = dyn_cast<DIDerivedType>(Element)) {
2384 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2385 collectMemberInfo(Info, DDTy);
2386 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2387 Info.Inheritance.push_back(DDTy);
2388 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2389 DDTy->
getName() ==
"__vtbl_ptr_type") {
2390 Info.VShapeTI = getTypeIndex(DDTy);
2391 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2392 Info.NestedTypes.push_back(DDTy);
2393 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2397 }
else if (
auto *Composite = dyn_cast<DICompositeType>(Element)) {
2398 Info.NestedTypes.push_back(Composite);
2421 auto I = CompleteTypeIndices.find(Ty);
2422 if (
I != CompleteTypeIndices.end() &&
I->second ==
TypeIndex())
2424 return getCompleteTypeIndex(Ty);
2432 std::string FullName = getFullyQualifiedName(Ty);
2437 DeferredCompleteTypes.push_back(Ty);
2447 unsigned FieldCount;
2450 lowerRecordFieldList(Ty);
2453 CO |= ClassOptions::ContainsNestedClass;
2461 CO |= ClassOptions::HasConstructorOrDestructor;
2463 std::string FullName = getFullyQualifiedName(Ty);
2471 addUDTSrcLine(Ty, ClassTI);
2481 return getCompleteTypeIndex(Ty);
2485 std::string FullName = getFullyQualifiedName(Ty);
2489 DeferredCompleteTypes.push_back(Ty);
2496 unsigned FieldCount;
2499 lowerRecordFieldList(Ty);
2502 CO |= ClassOptions::ContainsNestedClass;
2505 std::string FullName = getFullyQualifiedName(Ty);
2507 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2511 addUDTSrcLine(Ty, UnionTI);
2518std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2524 unsigned MemberCount = 0;
2527 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2531 if (
I->getFlags() & DINode::FlagVirtual) {
2533 unsigned VBPtrOffset =
I->getVBPtrOffset();
2535 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2536 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2537 ? TypeRecordKind::IndirectVirtualBaseClass
2538 : TypeRecordKind::VirtualBaseClass;
2541 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2547 assert(
I->getOffsetInBits() % 8 == 0 &&
2548 "bases must be on byte boundaries");
2550 getTypeIndex(
I->getBaseType()),
2551 I->getOffsetInBits() / 8);
2565 if (
Member->isStaticMember()) {
2573 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2574 Member->getName().startswith(
"_vptr$")) {
2584 if (
Member->isBitField()) {
2585 uint64_t StartBitOffset = MemberOffsetInBits;
2586 if (
const auto *CI =
2587 dyn_cast_or_null<ConstantInt>(
Member->getStorageOffsetInBits())) {
2588 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2590 StartBitOffset -= MemberOffsetInBits;
2595 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2603 for (
auto &MethodItr :
Info.Methods) {
2606 std::vector<OneMethodRecord> Methods;
2608 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2609 bool Introduced = SP->getFlags() & DINode::FlagIntroducedVirtual;
2611 unsigned VFTableOffset = -1;
2613 VFTableOffset = SP->getVirtualIndex() * getPointerSizeInBytes();
2621 assert(!Methods.empty() &&
"Empty methods map entry");
2622 if (Methods.size() == 1)
2643 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2644 !
Info.NestedTypes.empty());
2647TypeIndex CodeViewDebug::getVBPTypeIndex() {
2653 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2654 : PointerKind::Near32;
2657 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2672 auto I = TypeIndices.find({Ty, ClassTy});
2673 if (
I != TypeIndices.end())
2676 TypeLoweringScope S(*
this);
2678 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2682CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2684 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2685 "this type must be a pointer type");
2688 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2689 Options = PointerOptions::LValueRefThisPointer;
2690 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2691 Options = PointerOptions::RValueRefThisPointer;
2698 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2699 if (
I != TypeIndices.end())
2702 TypeLoweringScope S(*
this);
2704 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2707TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(
const DIType *Ty) {
2709 getPointerSizeInBytes() == 8 ? PointerKind::Near64
2710 : PointerKind::Near32,
2711 PointerMode::LValueReference, PointerOptions::None,
2724 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2725 (void)getTypeIndex(Ty);
2726 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2727 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2732 case dwarf::DW_TAG_class_type:
2733 case dwarf::DW_TAG_structure_type:
2734 case dwarf::DW_TAG_union_type:
2737 return getTypeIndex(Ty);
2740 const auto *CTy = cast<DICompositeType>(Ty);
2742 TypeLoweringScope S(*
this);
2748 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2749 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2754 if (CTy->isForwardDecl())
2761 auto InsertResult = CompleteTypeIndices.insert({CTy,
TypeIndex()});
2762 if (!InsertResult.second)
2763 return InsertResult.first->second;
2766 switch (CTy->getTag()) {
2767 case dwarf::DW_TAG_class_type:
2768 case dwarf::DW_TAG_structure_type:
2769 TI = lowerCompleteTypeClass(CTy);
2771 case dwarf::DW_TAG_union_type:
2772 TI = lowerCompleteTypeUnion(CTy);
2782 CompleteTypeIndices[CTy] = TI;
2790void CodeViewDebug::emitDeferredCompleteTypes() {
2792 while (!DeferredCompleteTypes.empty()) {
2793 std::swap(DeferredCompleteTypes, TypesToEmit);
2795 getCompleteTypeIndex(RecordTy);
2796 TypesToEmit.clear();
2800void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2804 for (
const LocalVariable &L : Locals)
2805 if (
L.DIVar->isParameter())
2807 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2808 return L->DIVar->getArg() <
R->DIVar->getArg();
2810 for (
const LocalVariable *L : Params)
2811 emitLocalVariable(FI, *L);
2814 for (
const LocalVariable &L : Locals) {
2815 if (!
L.DIVar->isParameter()) {
2816 if (
L.ConstantValue) {
2819 const DIType *Ty =
L.DIVar->getType();
2821 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2823 emitLocalVariable(FI, L);
2829void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2830 const LocalVariable &Var) {
2832 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2835 if (Var.DIVar->isParameter())
2836 Flags |= LocalSymFlags::IsParameter;
2837 if (Var.DefRanges.empty())
2838 Flags |= LocalSymFlags::IsOptimizedOut;
2842 ? getTypeIndexForReferenceTo(Var.DIVar->getType())
2843 : getCompleteTypeIndex(Var.DIVar->
getType());
2849 endSymbolRecord(LocalEnd);
2855 for (
const auto &Pair : Var.DefRanges) {
2856 LocalVarDef DefRange = Pair.first;
2857 const auto &
Ranges = Pair.second;
2859 if (DefRange.InMemory) {
2860 int Offset = DefRange.DataOffset;
2861 unsigned Reg = DefRange.CVRegister;
2868 Offset += FI.OffsetAdjustment;
2875 if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2876 (
bool(Flags & LocalSymFlags::IsParameter)
2877 ? (EncFP == FI.EncodedParamFramePtrReg)
2878 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2884 if (DefRange.IsSubfield) {
2886 (DefRange.StructOffset
2891 DRHdr.
Flags = RegRelFlags;
2896 assert(DefRange.DataOffset == 0 &&
"unexpected offset into register");
2897 if (DefRange.IsSubfield) {
2899 DRHdr.
Register = DefRange.CVRegister;
2905 DRHdr.
Register = DefRange.CVRegister;
2914 const FunctionInfo& FI) {
2916 emitLexicalBlock(*
Block, FI);
2921void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2922 const FunctionInfo& FI) {
2923 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2930 OS.
AddComment(
"Function section relative address");
2936 endSymbolRecord(RecordEnd);
2939 emitLocalVariableList(FI,
Block.Locals);
2940 emitGlobalVariableList(
Block.Globals);
2943 emitLexicalBlockList(
Block.Children, FI);
2946 emitEndSymbolRecord(SymbolKind::S_END);
2951void CodeViewDebug::collectLexicalBlockInfo(
2957 collectLexicalBlockInfo(*Scope,
Blocks, Locals, Globals);
2962void CodeViewDebug::collectLexicalBlockInfo(
2967 if (
Scope.isAbstractScope())
2972 bool IgnoreScope =
false;
2973 auto LI = ScopeVariables.find(&Scope);
2975 LI != ScopeVariables.end() ? &LI->second :
nullptr;
2976 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
2978 GI != ScopeGlobals.end() ? GI->second.get() :
nullptr;
2983 if (!Locals && !Globals)
3013 collectLexicalBlockInfo(
Scope.getChildren(),
3023 auto BlockInsertion = CurFn->LexicalBlocks.insert({DILB, LexicalBlock()});
3024 if (!BlockInsertion.second)
3031 LexicalBlock &
Block = BlockInsertion.first->second;
3034 assert(
Block.Begin &&
"missing label for scope begin");
3035 assert(
Block.End &&
"missing label for scope end");
3038 Block.Locals = std::move(*Locals);
3040 Block.Globals = std::move(*Globals);
3042 collectLexicalBlockInfo(
Scope.getChildren(),
3050 assert(FnDebugInfo.count(&GV));
3051 assert(CurFn == FnDebugInfo[&GV].
get());
3057 collectLexicalBlockInfo(*CFS,
3065 ScopeVariables.clear();
3069 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3070 FnDebugInfo.erase(&GV);
3076 for (
const auto &
MBB : *MF) {
3077 for (
const auto &
MI :
MBB) {
3078 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3081 dyn_cast<DIType>(MD)));
3098 return DL &&
DL.getLine() != 0;
3105 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3113 for (
const auto &NextMI : *
MI->getParent()) {
3114 if (NextMI.isDebugInstr())
3116 DL = NextMI.getDebugLoc();
3129 maybeRecordLocation(
DL,
Asm->
MF);
3142void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3150 if (EE.Value == SymKind)
3167void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3176void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3184void CodeViewDebug::emitDebugInfoForUDTs(
3185 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3187 size_t OriginalSize = UDTs.size();
3189 for (
const auto &UDT : UDTs) {
3192 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3194 OS.
emitInt32(getCompleteTypeIndex(
T).getIndex());
3195 assert(OriginalSize == UDTs.size() &&
3196 "getCompleteTypeIndex found new UDTs!");
3198 endSymbolRecord(UDTRecordEnd);
3202void CodeViewDebug::collectGlobalVariableInfo() {
3207 GV.getDebugInfo(GVEs);
3208 for (
const auto *GVE : GVEs)
3209 GlobalMap[GVE] = &GV;
3214 const auto *
CU = cast<DICompileUnit>(
Node);
3215 for (
const auto *GVE :
CU->getGlobalVariables()) {
3224 if ((
DIE->getNumElements() == 2) &&
3225 (
DIE->getElement(0) == dwarf::DW_OP_plus_uconst))
3230 CVGlobalVariableOffsets.insert(
3231 std::make_pair(DIGV,
DIE->getElement(1)));
3234 if (GlobalMap.
count(GVE) == 0 &&
DIE->isConstant()) {
3235 CVGlobalVariable CVGV = {DIGV,
DIE};
3239 const auto *GV = GlobalMap.
lookup(GVE);
3245 if (Scope && isa<DILocalScope>(Scope)) {
3248 auto Insertion = ScopeGlobals.insert(
3249 {
Scope, std::unique_ptr<GlobalVariableList>()});
3250 if (Insertion.second)
3251 Insertion.first->second = std::make_unique<GlobalVariableList>();
3252 VariableList = Insertion.first->second.get();
3255 VariableList = &ComdatVariables;
3258 VariableList = &GlobalVariables;
3259 CVGlobalVariable CVGV = {DIGV, GV};
3265void CodeViewDebug::collectDebugInfoForGlobals() {
3266 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3269 getCompleteTypeIndex(DIGV->
getType());
3270 getFullyQualifiedName(Scope, DIGV->
getName());
3273 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3276 getCompleteTypeIndex(DIGV->
getType());
3277 getFullyQualifiedName(Scope, DIGV->
getName());
3281void CodeViewDebug::emitDebugInfoForGlobals() {
3285 switchToDebugSectionForSymbol(
nullptr);
3286 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3287 OS.
AddComment(
"Symbol subsection for globals");
3288 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3289 emitGlobalVariableList(GlobalVariables);
3290 emitStaticConstMemberList();
3291 endCVSubsection(EndLabel);
3296 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3297 const GlobalVariable *GV = cast<const GlobalVariable *>(CVGV.GVInfo);
3301 switchToDebugSectionForSymbol(GVSym);
3302 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3304 emitDebugInfoForGlobal(CVGV);
3305 endCVSubsection(EndLabel);
3309void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3312 for (
auto *Ty : cast<DICompileUnit>(
Node)->getRetainedTypes()) {
3313 if (
DIType *RT = dyn_cast<DIType>(Ty)) {
3323 for (
const CVGlobalVariable &CVGV : Globals) {
3325 emitDebugInfoForGlobal(CVGV);
3331 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3333 OS.
emitInt32(getTypeIndex(DTy).getIndex());
3347 endSymbolRecord(SConstantEnd);
3350void CodeViewDebug::emitStaticConstMemberList() {
3356 dyn_cast_or_null<ConstantInt>(DTy->getConstant()))
3360 dyn_cast_or_null<ConstantFP>(DTy->getConstant()))
3361 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3365 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3366 getFullyQualifiedName(Scope, DTy->
getName()));
3371 if (isa<DICompositeType>(Ty))
3374 if (
auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
3376 if (
T == dwarf::DW_TAG_pointer_type ||
3377 T == dwarf::DW_TAG_ptr_to_member_type ||
3378 T == dwarf::DW_TAG_reference_type ||
3379 T == dwarf::DW_TAG_rvalue_reference_type)
3381 assert(DTy->getBaseType() &&
"Expected valid base type");
3385 auto *BTy = cast<DIBasicType>(Ty);
3386 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3389void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3394 if (
const auto *MemberDecl = dyn_cast_or_null<DIDerivedType>(
3396 Scope = MemberDecl->getScope();
3402 ? std::string(DIGV->
getName())
3406 dyn_cast_if_present<const GlobalVariable *>(CVGV.GVInfo)) {
3412 : SymbolKind::S_GTHREAD32)
3414 : SymbolKind::S_GDATA32);
3421 if (CVGlobalVariableOffsets.contains(DIGV))
3423 Offset = CVGlobalVariableOffsets[DIGV];
3429 const unsigned LengthOfDataRecord = 12;
3431 endSymbolRecord(DataEnd);
3435 "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.
DenseMap< Block *, BlockRelaxAux > Blocks
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.
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.
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
Description of the location of a variable whose Address is valid and unchanging during function execu...
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.
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.
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.
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)
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 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.