33#include "llvm/Config/llvm-config.h"
81 :
OS(&
OS), TypeTable(TypeTable) {}
103 TypeName = std::string(TypeTable.getTypeName(TI));
116 case Triple::ArchType::x86:
117 return CPUType::Pentium3;
118 case Triple::ArchType::x86_64:
120 case Triple::ArchType::thumb:
123 return CPUType::ARMNT;
124 case Triple::ArchType::aarch64:
125 return CPUType::ARM64;
135 std::string &Filepath = FileToFilepathMap[File];
136 if (!Filepath.empty())
139 StringRef Dir = File->getDirectory(), Filename = File->getFilename();
143 if (Dir.
starts_with(
"/") || Filename.starts_with(
"/")) {
146 Filepath = std::string(Dir);
147 if (Dir.
back() !=
'/')
149 Filepath += Filename;
157 if (Filename.find(
':') == 1)
158 Filepath = std::string(Filename);
160 Filepath = (Dir +
"\\" + Filename).str();
165 std::replace(Filepath.begin(), Filepath.end(),
'/',
'\\');
169 while ((Cursor = Filepath.find(
"\\.\\", Cursor)) != std::string::npos)
170 Filepath.erase(Cursor, 2);
175 while ((Cursor = Filepath.find(
"\\..\\", Cursor)) != std::string::npos) {
180 size_t PrevSlash = Filepath.rfind(
'\\', Cursor - 1);
181 if (PrevSlash == std::string::npos)
185 Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
192 while ((Cursor = Filepath.find(
"\\\\", Cursor)) != std::string::npos)
193 Filepath.erase(Cursor, 1);
198unsigned CodeViewDebug::maybeRecordFile(
const DIFile *
F) {
200 unsigned NextId = FileIdMap.
size() + 1;
201 auto Insertion = FileIdMap.
insert(std::make_pair(FullPath, NextId));
202 if (Insertion.second) {
206 if (
F->getChecksum()) {
207 std::string Checksum = fromHex(
F->getChecksum()->Value);
209 memcpy(CKMem, Checksum.data(), Checksum.size());
211 reinterpret_cast<const uint8_t *
>(CKMem), Checksum.size());
212 switch (
F->getChecksum()->Kind) {
214 CSKind = FileChecksumKind::MD5;
217 CSKind = FileChecksumKind::SHA1;
220 CSKind = FileChecksumKind::SHA256;
225 static_cast<unsigned>(CSKind));
229 return Insertion.first->second;
232CodeViewDebug::InlineSite &
233CodeViewDebug::getInlineSite(
const DILocation *InlinedAt,
235 auto SiteInsertion = CurFn->InlineSites.insert({InlinedAt,
InlineSite()});
236 InlineSite *Site = &SiteInsertion.first->second;
237 if (SiteInsertion.second) {
238 unsigned ParentFuncId = CurFn->FuncId;
239 if (
const DILocation *OuterIA = InlinedAt->getInlinedAt())
241 getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())
244 Site->SiteFuncId = NextFuncId++;
246 Site->SiteFuncId, ParentFuncId, maybeRecordFile(InlinedAt->getFile()),
247 InlinedAt->getLine(), InlinedAt->getColumn(),
SMLoc());
249 InlinedSubprograms.insert(Inlinee);
250 auto InlineeIdx = getFuncIdForSubprogram(Inlinee);
252 if (InlinedAt->getInlinedAt() ==
nullptr)
253 CurFn->Inlinees.insert(InlineeIdx);
260 if (!ScopeName.
empty())
263 switch (Scope->getTag()) {
264 case dwarf::DW_TAG_enumeration_type:
265 case dwarf::DW_TAG_class_type:
266 case dwarf::DW_TAG_structure_type:
267 case dwarf::DW_TAG_union_type:
268 return "<unnamed-tag>";
269 case dwarf::DW_TAG_namespace:
270 return "`anonymous namespace'";
276const DISubprogram *CodeViewDebug::collectParentScopeNames(
279 while (Scope !=
nullptr) {
280 if (ClosestSubprogram ==
nullptr)
281 ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
286 if (
const auto *Ty = dyn_cast<DICompositeType>(Scope))
287 DeferredCompleteTypes.push_back(Ty);
290 if (!ScopeName.
empty())
291 QualifiedNameComponents.
push_back(ScopeName);
294 return ClosestSubprogram;
299 std::string FullyQualifiedName;
302 FullyQualifiedName.append(std::string(QualifiedNameComponent));
303 FullyQualifiedName.append(
"::");
305 FullyQualifiedName.append(std::string(TypeName));
306 return FullyQualifiedName;
314 if (
CVD.TypeEmissionLevel == 1)
315 CVD.emitDeferredCompleteTypes();
316 --
CVD.TypeEmissionLevel;
321std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Scope,
328 collectParentScopeNames(Scope, QualifiedNameComponents);
332std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Ty) {
348 if (!Scope || isa<DIFile>(Scope) || isa<DISubprogram>(Scope))
351 assert(!isa<DIType>(Scope) &&
"shouldn't make a namespace scope for a type");
354 auto I = TypeIndices.find({Scope,
nullptr});
355 if (
I != TypeIndices.end())
359 std::string ScopeName = getFullyQualifiedName(Scope);
362 return recordTypeIndexForDINode(Scope, TI);
368 if (
Name.empty() ||
Name.back() !=
'>')
371 int OpenBrackets = 0;
372 for (
int i =
Name.size() - 1; i >= 0; --i) {
375 else if (
Name[i] ==
'<') {
377 if (OpenBrackets == 0)
378 return Name.substr(0, i);
388 auto I = TypeIndices.find({SP,
nullptr});
389 if (
I != TypeIndices.end())
399 if (
const auto *Class = dyn_cast_or_null<DICompositeType>(Scope)) {
403 TypeIndex ClassType = getTypeIndex(Class);
409 TypeIndex ParentScope = getScopeIndex(Scope);
414 return recordTypeIndexForDINode(SP, TI);
418 return ((DCTy->
getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);
426 const DIType *ReturnTy =
nullptr;
428 if (TypeArray.size())
429 ReturnTy = TypeArray[0];
434 if (
auto *ReturnDCTy = dyn_cast_or_null<DICompositeType>(ReturnTy))
436 FO |= FunctionOptions::CxxReturnUdt;
439 if (ClassTy &&
isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {
440 FO |= FunctionOptions::Constructor;
452 if (SP->getDeclaration())
453 SP = SP->getDeclaration();
454 assert(!SP->getDeclaration() &&
"should use declaration as key");
458 auto I = TypeIndices.find({SP,
Class});
459 if (
I != TypeIndices.end())
465 TypeLoweringScope S(*
this);
466 const bool IsStaticMethod = (SP->getFlags() & DINode::FlagStaticMember) != 0;
470 SP->getType(), Class, SP->getThisAdjustment(), IsStaticMethod, FO);
471 return recordTypeIndexForDINode(SP, TI, Class);
477 auto InsertResult = TypeIndices.insert({{
Node, ClassTy}, TI});
479 assert(InsertResult.second &&
"DINode was already assigned a type index");
483unsigned CodeViewDebug::getPointerSizeInBytes() {
487void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
492 InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
493 Site.InlinedLocals.emplace_back(std::move(Var));
496 ScopeVariables[
LS].emplace_back(std::move(Var));
506void CodeViewDebug::maybeRecordLocation(
const DebugLoc &
DL,
518 if (LI.getStartLine() !=
DL.getLine() || LI.isAlwaysStepInto() ||
519 LI.isNeverStepInto())
523 if (CI.getStartColumn() !=
DL.getCol())
526 if (!CurFn->HaveLineInfo)
527 CurFn->HaveLineInfo =
true;
530 FileId = CurFn->LastFileId;
532 FileId = CurFn->LastFileId = maybeRecordFile(
DL->getFile());
535 unsigned FuncId = CurFn->FuncId;
542 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
545 bool FirstLoc =
true;
546 while ((SiteLoc = Loc->getInlinedAt())) {
548 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
562void CodeViewDebug::emitCodeViewMagicVersion() {
570 case dwarf::DW_LANG_C:
571 case dwarf::DW_LANG_C89:
572 case dwarf::DW_LANG_C99:
573 case dwarf::DW_LANG_C11:
574 return SourceLanguage::C;
575 case dwarf::DW_LANG_C_plus_plus:
576 case dwarf::DW_LANG_C_plus_plus_03:
577 case dwarf::DW_LANG_C_plus_plus_11:
578 case dwarf::DW_LANG_C_plus_plus_14:
579 return SourceLanguage::Cpp;
580 case dwarf::DW_LANG_Fortran77:
581 case dwarf::DW_LANG_Fortran90:
582 case dwarf::DW_LANG_Fortran95:
583 case dwarf::DW_LANG_Fortran03:
584 case dwarf::DW_LANG_Fortran08:
585 return SourceLanguage::Fortran;
586 case dwarf::DW_LANG_Pascal83:
587 return SourceLanguage::Pascal;
588 case dwarf::DW_LANG_Cobol74:
589 case dwarf::DW_LANG_Cobol85:
590 return SourceLanguage::Cobol;
591 case dwarf::DW_LANG_Java:
592 return SourceLanguage::Java;
593 case dwarf::DW_LANG_D:
594 return SourceLanguage::D;
595 case dwarf::DW_LANG_Swift:
596 return SourceLanguage::Swift;
597 case dwarf::DW_LANG_Rust:
598 return SourceLanguage::Rust;
599 case dwarf::DW_LANG_ObjC:
600 return SourceLanguage::ObjC;
601 case dwarf::DW_LANG_ObjC_plus_plus:
602 return SourceLanguage::ObjCpp;
607 return SourceLanguage::Masm;
623 const MDNode *Node = *M->debug_compile_units_begin();
624 const auto *
CU = cast<DICompileUnit>(Node);
628 collectGlobalVariableInfo();
632 mdconst::extract_or_null<ConstantInt>(M->getModuleFlag(
"CodeViewGHash"));
633 EmitDebugGlobalHashes = GH && !GH->
isZero();
647 switchToDebugSectionForSymbol(
nullptr);
649 MCSymbol *CompilerInfo = beginCVSubsection(DebugSubsectionKind::Symbols);
651 emitCompilerInformation();
652 endCVSubsection(CompilerInfo);
654 emitInlineeLinesSubsection();
657 for (
auto &
P : FnDebugInfo)
658 if (!
P.first->isDeclarationForLinker())
659 emitDebugInfoForFunction(
P.first, *
P.second);
664 collectDebugInfoForGlobals();
667 emitDebugInfoForRetainedTypes();
670 setCurrentSubprogram(
nullptr);
671 emitDebugInfoForGlobals();
675 switchToDebugSectionForSymbol(
nullptr);
678 if (!GlobalUDTs.empty()) {
679 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
680 emitDebugInfoForUDTs(GlobalUDTs);
681 endCVSubsection(SymbolsEnd);
685 OS.
AddComment(
"File index to string table offset subsection");
699 emitTypeInformation();
701 if (EmitDebugGlobalHashes)
702 emitTypeGlobalHashes();
709 unsigned MaxFixedRecordLength = 0xF00) {
717 OS.emitBytes(NullTerminatedString);
720void CodeViewDebug::emitTypeInformation() {
721 if (TypeTable.
empty())
726 emitCodeViewMagicVersion();
732 CVMCAdapter CVMCOS(OS, Table);
736 std::optional<TypeIndex>
B = Table.getFirst();
748 B = Table.getNext(*
B);
752void CodeViewDebug::emitTypeGlobalHashes() {
753 if (TypeTable.
empty())
769 for (
const auto &GHR : TypeTable.
hashes()) {
779 assert(GHR.Hash.size() == 8);
780 StringRef S(
reinterpret_cast<const char *
>(GHR.Hash.data()),
786void CodeViewDebug::emitObjName() {
787 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);
792 if (PathRef.empty() || PathRef ==
"-") {
805 endSymbolRecord(CompilerEnd);
819 for (
const char C :
Name) {
822 V.Part[
N] +=
C -
'0';
824 std::min<int>(V.Part[
N], std::numeric_limits<uint16_t>::max());
825 }
else if (
C ==
'.') {
835void CodeViewDebug::emitCompilerInformation() {
836 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
840 Flags = CurrentSourceLanguage;
848 Arch == ArchType::aarch64) {
860 const auto *
CU = cast<DICompileUnit>(
Node);
865 for (
int N : FrontVer.Part) {
872 int Major = 1000 * LLVM_VERSION_MAJOR +
873 10 * LLVM_VERSION_MINOR +
876 Major = std::min<int>(Major, std::numeric_limits<uint16_t>::max());
877 Version BackVer = {{ Major, 0, 0, 0 }};
879 for (
int N : BackVer.Part)
882 OS.
AddComment(
"Null-terminated compiler version string");
885 endSymbolRecord(CompilerEnd);
894void CodeViewDebug::emitBuildInfo() {
908 const auto *
CU = cast<DICompileUnit>(
Node);
909 const DIFile *MainSourceFile =
CU->getFile();
927 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
928 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
931 endSymbolRecord(BIEnd);
932 endCVSubsection(BISubsecEnd);
935void CodeViewDebug::emitInlineeLinesSubsection() {
936 if (InlinedSubprograms.empty())
940 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
947 OS.
emitInt32(
unsigned(InlineeLinesSignature::Normal));
950 assert(TypeIndices.count({SP, nullptr}));
951 TypeIndex InlineeIdx = TypeIndices[{SP,
nullptr}];
954 unsigned FileId = maybeRecordFile(SP->
getFile());
958 OS.
AddComment(
"Type index of inlined function");
960 OS.
AddComment(
"Offset into filechecksum table");
966 endCVSubsection(InlineEnd);
969void CodeViewDebug::emitInlinedCallSite(
const FunctionInfo &FI,
972 assert(TypeIndices.count({Site.Inlinee, nullptr}));
973 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee,
nullptr}];
976 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
985 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
986 unsigned StartLineNum = Site.Inlinee->getLine();
991 endSymbolRecord(InlineEnd);
993 emitLocalVariableList(FI, Site.InlinedLocals);
996 for (
const DILocation *ChildSite : Site.ChildSites) {
997 auto I = FI.InlineSites.find(ChildSite);
998 assert(
I != FI.InlineSites.end() &&
999 "child site not in function inline site map");
1000 emitInlinedCallSite(FI, ChildSite,
I->second);
1004 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1007void CodeViewDebug::switchToDebugSectionForSymbol(
const MCSymbol *GVSym) {
1012 GVSym ? dyn_cast<MCSectionCOFF>(&GVSym->
getSection()) : nullptr;
1023 if (ComdatDebugSections.insert(DebugSec).second)
1024 emitCodeViewMagicVersion();
1029void CodeViewDebug::emitDebugInfoForThunk(
const Function *GV,
1032 std::string FuncName =
1037 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1040 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1047 OS.
AddComment(
"Thunk section relative address");
1058 endSymbolRecord(ThunkRecordEnd);
1064 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1066 endCVSubsection(SymbolsEnd);
1069void CodeViewDebug::emitDebugInfoForFunction(
const Function *GV,
1077 switchToDebugSectionForSymbol(Fn);
1079 std::string FuncName;
1082 setCurrentSubprogram(SP);
1084 if (SP->isThunk()) {
1085 emitDebugInfoForThunk(GV, FI, Fn);
1095 if (FuncName.empty())
1104 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1107 : SymbolKind::S_GPROC32_ID;
1108 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1127 OS.
AddComment(
"Function section relative address");
1132 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;
1133 if (FI.HasFramePointer)
1134 ProcFlags |= ProcSymFlags::HasFP;
1136 ProcFlags |= ProcSymFlags::IsNoReturn;
1138 ProcFlags |= ProcSymFlags::IsNoInline;
1144 endSymbolRecord(ProcRecordEnd);
1146 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1149 OS.
emitInt32(FI.FrameSize - FI.CSRSize);
1154 OS.
AddComment(
"Bytes of callee saved registers");
1160 OS.
AddComment(
"Flags (defines frame register)");
1162 endSymbolRecord(FrameProcEnd);
1164 emitInlinees(FI.Inlinees);
1165 emitLocalVariableList(FI, FI.Locals);
1166 emitGlobalVariableList(FI.Globals);
1167 emitLexicalBlockList(FI.ChildBlocks, FI);
1172 for (
const DILocation *InlinedAt : FI.ChildSites) {
1173 auto I = FI.InlineSites.find(InlinedAt);
1174 assert(
I != FI.InlineSites.end() &&
1175 "child site not in function inline site map");
1176 emitInlinedCallSite(FI, InlinedAt,
I->second);
1179 for (
auto Annot : FI.Annotations) {
1181 MDTuple *Strs = cast<MDTuple>(Annot.second);
1182 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1190 StringRef Str = cast<MDString>(MD)->getString();
1191 assert(Str.data()[Str.size()] ==
'\0' &&
"non-nullterminated MDString");
1194 endSymbolRecord(AnnotEnd);
1197 for (
auto HeapAllocSite : FI.HeapAllocSites) {
1198 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1199 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1200 const DIType *DITy = std::get<2>(HeapAllocSite);
1201 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1209 OS.
emitInt32(getCompleteTypeIndex(DITy).getIndex());
1210 endSymbolRecord(HeapAllocEnd);
1214 emitDebugInfoForUDTs(LocalUDTs);
1216 emitDebugInfoForJumpTables(FI);
1219 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1221 endCVSubsection(SymbolsEnd);
1228CodeViewDebug::createDefRangeMem(
uint16_t CVRegister,
int Offset) {
1234 DR.StructOffset = 0;
1235 DR.CVRegister = CVRegister;
1239void CodeViewDebug::collectVariableInfoFromMFTable(
1250 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1251 "Expected inlined-at fields to agree");
1253 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1262 int64_t ExprOffset = 0;
1266 if (
VI.Expr->getNumElements() == 1 &&
1267 VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)
1269 else if (!
VI.Expr->extractIfOffset(ExprOffset))
1277 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1280 "Frame offsets with a scalable component are not supported");
1283 LocalVarDef DefRange =
1284 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset);
1293 Var.DefRanges[DefRange].emplace_back(Begin,
End);
1297 Var.UseReferenceType =
true;
1299 recordLocalVariable(std::move(Var), Scope);
1311void CodeViewDebug::calculateRanges(
1316 for (
auto I = Entries.begin(), E = Entries.end();
I != E; ++
I) {
1318 if (!
Entry.isDbgValue())
1324 std::optional<DbgVariableLocation>
Location =
1346 if (Var.UseReferenceType) {
1355 Var.UseReferenceType =
true;
1356 Var.DefRanges.clear();
1357 calculateRanges(Var, Entries);
1368 if (
Location->FragmentInfo->OffsetInBits % 8)
1372 DR.CVRegister =
TRI->getCodeViewRegNum(
Location->Register);
1373 DR.InMemory = !
Location->LoadChain.empty();
1377 DR.IsSubfield =
true;
1378 DR.StructOffset =
Location->FragmentInfo->OffsetInBits / 8;
1380 DR.IsSubfield =
false;
1381 DR.StructOffset = 0;
1388 auto &EndingEntry = Entries[
Entry.getEndIndex()];
1389 End = EndingEntry.isDbgValue()
1399 if (!
R.empty() &&
R.back().second == Begin)
1400 R.back().second =
End;
1402 R.emplace_back(Begin,
End);
1408void CodeViewDebug::collectVariableInfo(
const DISubprogram *SP) {
1411 collectVariableInfoFromMFTable(Processed);
1414 InlinedEntity
IV =
I.first;
1421 const auto &Entries =
I.second;
1435 calculateRanges(Var, Entries);
1436 recordLocalVariable(std::move(Var), Scope);
1445 auto Insertion = FnDebugInfo.insert({&GV, std::make_unique<FunctionInfo>()});
1446 assert(Insertion.second &&
"function already has info");
1447 CurFn = Insertion.first->second.get();
1448 CurFn->FuncId = NextFuncId++;
1457 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1461 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::None;
1462 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::None;
1463 if (CurFn->FrameSize > 0) {
1465 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1466 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr;
1468 CurFn->HasFramePointer =
true;
1470 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr;
1471 if (CurFn->HasStackRealignment) {
1473 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1477 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::FramePtr;
1485 FPO |= FrameProcedureOptions::HasAlloca;
1487 FPO |= FrameProcedureOptions::HasSetJmp;
1490 FPO |= FrameProcedureOptions::HasInlineAssembly;
1494 FPO |= FrameProcedureOptions::HasStructuredExceptionHandling;
1496 FPO |= FrameProcedureOptions::HasExceptionHandling;
1499 FPO |= FrameProcedureOptions::MarkedInline;
1501 FPO |= FrameProcedureOptions::Naked;
1503 FPO |= FrameProcedureOptions::SecurityChecks;
1506 FPO |= FrameProcedureOptions::StrictSecurityChecks;
1510 FPO |= FrameProcedureOptions::SafeBuffers;
1516 FPO |= FrameProcedureOptions::OptimizedForSpeed;
1518 FPO |= FrameProcedureOptions::ValidProfileCounts;
1519 FPO |= FrameProcedureOptions::ProfileGuidedOptimization;
1522 CurFn->FrameProcOpts = FPO;
1531 bool EmptyPrologue =
true;
1532 for (
const auto &
MBB : *MF) {
1533 for (
const auto &
MI :
MBB) {
1538 }
else if (!
MI.isMetaInstruction()) {
1539 EmptyPrologue =
false;
1547 maybeRecordLocation(FnStartDL, MF);
1551 for (
const auto &
MBB : *MF) {
1552 for (
const auto &
MI :
MBB) {
1553 if (
MI.getHeapAllocMarker()) {
1563 discoverJumpTableBranches(MF,
isThumb);
1571 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1572 if (
DIScope *Scope =
T->getScope()) {
1573 switch (Scope->getTag()) {
1574 case dwarf::DW_TAG_structure_type:
1575 case dwarf::DW_TAG_class_type:
1576 case dwarf::DW_TAG_union_type:
1586 if (!
T ||
T->isForwardDecl())
1592 T = DT->getBaseType();
1597void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1606 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1608 std::string FullyQualifiedName =
1611 if (ClosestSubprogram ==
nullptr) {
1612 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1613 }
else if (ClosestSubprogram == CurrentSubprogram) {
1614 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1628 case dwarf::DW_TAG_array_type:
1629 return lowerTypeArray(cast<DICompositeType>(Ty));
1630 case dwarf::DW_TAG_typedef:
1631 return lowerTypeAlias(cast<DIDerivedType>(Ty));
1632 case dwarf::DW_TAG_base_type:
1633 return lowerTypeBasic(cast<DIBasicType>(Ty));
1634 case dwarf::DW_TAG_pointer_type:
1635 if (cast<DIDerivedType>(Ty)->
getName() ==
"__vtbl_ptr_type")
1636 return lowerTypeVFTableShape(cast<DIDerivedType>(Ty));
1638 case dwarf::DW_TAG_reference_type:
1639 case dwarf::DW_TAG_rvalue_reference_type:
1640 return lowerTypePointer(cast<DIDerivedType>(Ty));
1641 case dwarf::DW_TAG_ptr_to_member_type:
1642 return lowerTypeMemberPointer(cast<DIDerivedType>(Ty));
1643 case dwarf::DW_TAG_restrict_type:
1644 case dwarf::DW_TAG_const_type:
1645 case dwarf::DW_TAG_volatile_type:
1647 return lowerTypeModifier(cast<DIDerivedType>(Ty));
1648 case dwarf::DW_TAG_subroutine_type:
1652 return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy,
1656 return lowerTypeFunction(cast<DISubroutineType>(Ty));
1657 case dwarf::DW_TAG_enumeration_type:
1658 return lowerTypeEnum(cast<DICompositeType>(Ty));
1659 case dwarf::DW_TAG_class_type:
1660 case dwarf::DW_TAG_structure_type:
1661 return lowerTypeClass(cast<DICompositeType>(Ty));
1662 case dwarf::DW_TAG_union_type:
1663 return lowerTypeUnion(cast<DICompositeType>(Ty));
1664 case dwarf::DW_TAG_string_type:
1665 return lowerTypeString(cast<DIStringType>(Ty));
1666 case dwarf::DW_TAG_unspecified_type:
1667 if (Ty->
getName() ==
"decltype(nullptr)")
1677 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1682 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::Int32Long) &&
1683 TypeName ==
"HRESULT")
1684 return TypeIndex(SimpleTypeKind::HResult);
1685 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::UInt16Short) &&
1686 TypeName ==
"wchar_t")
1687 return TypeIndex(SimpleTypeKind::WideCharacter);
1689 return UnderlyingTypeIndex;
1694 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1696 TypeIndex IndexType = getPointerSizeInBytes() == 8
1704 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1706 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1715 if (
auto *CI = dyn_cast_if_present<ConstantInt *>(
Subrange->getCount()))
1716 Count = CI->getSExtValue();
1717 else if (
auto *UI = dyn_cast_if_present<ConstantInt *>(
1721 auto *LI = dyn_cast_if_present<ConstantInt *>(
Subrange->getLowerBound());
1722 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1723 Count = UI->getSExtValue() - Lowerbound + 1;
1734 ElementSize *= Count;
1739 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1746 return ElementTypeIndex;
1759 TypeIndex IndexType = getPointerSizeInBytes() == 8
1779 case dwarf::DW_ATE_address:
1782 case dwarf::DW_ATE_boolean:
1784 case 1: STK = SimpleTypeKind::Boolean8;
break;
1785 case 2: STK = SimpleTypeKind::Boolean16;
break;
1786 case 4: STK = SimpleTypeKind::Boolean32;
break;
1787 case 8: STK = SimpleTypeKind::Boolean64;
break;
1788 case 16: STK = SimpleTypeKind::Boolean128;
break;
1791 case dwarf::DW_ATE_complex_float:
1795 case 4: STK = SimpleTypeKind::Complex16;
break;
1796 case 8: STK = SimpleTypeKind::Complex32;
break;
1797 case 16: STK = SimpleTypeKind::Complex64;
break;
1798 case 20: STK = SimpleTypeKind::Complex80;
break;
1799 case 32: STK = SimpleTypeKind::Complex128;
break;
1802 case dwarf::DW_ATE_float:
1804 case 2: STK = SimpleTypeKind::Float16;
break;
1805 case 4: STK = SimpleTypeKind::Float32;
break;
1806 case 6: STK = SimpleTypeKind::Float48;
break;
1807 case 8: STK = SimpleTypeKind::Float64;
break;
1808 case 10: STK = SimpleTypeKind::Float80;
break;
1809 case 16: STK = SimpleTypeKind::Float128;
break;
1812 case dwarf::DW_ATE_signed:
1814 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1815 case 2: STK = SimpleTypeKind::Int16Short;
break;
1816 case 4: STK = SimpleTypeKind::Int32;
break;
1817 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1818 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1821 case dwarf::DW_ATE_unsigned:
1823 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1824 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1825 case 4: STK = SimpleTypeKind::UInt32;
break;
1826 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1827 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1830 case dwarf::DW_ATE_UTF:
1832 case 1: STK = SimpleTypeKind::Character8;
break;
1833 case 2: STK = SimpleTypeKind::Character16;
break;
1834 case 4: STK = SimpleTypeKind::Character32;
break;
1837 case dwarf::DW_ATE_signed_char:
1839 STK = SimpleTypeKind::SignedCharacter;
1841 case dwarf::DW_ATE_unsigned_char:
1843 STK = SimpleTypeKind::UnsignedCharacter;
1853 if (STK == SimpleTypeKind::Int32 &&
1855 STK = SimpleTypeKind::Int32Long;
1856 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1857 Ty->
getName() ==
"unsigned long"))
1858 STK = SimpleTypeKind::UInt32Long;
1859 if (STK == SimpleTypeKind::UInt16Short &&
1861 STK = SimpleTypeKind::WideCharacter;
1862 if ((STK == SimpleTypeKind::SignedCharacter ||
1863 STK == SimpleTypeKind::UnsignedCharacter) &&
1865 STK = SimpleTypeKind::NarrowCharacter;
1872 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1876 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1878 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1880 ? SimpleTypeMode::NearPointer64
1881 : SimpleTypeMode::NearPointer32;
1886 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1890 case dwarf::DW_TAG_pointer_type:
1891 PM = PointerMode::Pointer;
1893 case dwarf::DW_TAG_reference_type:
1894 PM = PointerMode::LValueReference;
1896 case dwarf::DW_TAG_rvalue_reference_type:
1897 PM = PointerMode::RValueReference;
1902 PO |= PointerOptions::Const;
1916 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1917 : PointerToMemberRepresentation::GeneralFunction;
1918 case DINode::FlagSingleInheritance:
1919 return PointerToMemberRepresentation::SingleInheritanceFunction;
1920 case DINode::FlagMultipleInheritance:
1921 return PointerToMemberRepresentation::MultipleInheritanceFunction;
1922 case DINode::FlagVirtualInheritance:
1923 return PointerToMemberRepresentation::VirtualInheritanceFunction;
1928 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1929 : PointerToMemberRepresentation::GeneralData;
1930 case DINode::FlagSingleInheritance:
1931 return PointerToMemberRepresentation::SingleInheritanceData;
1932 case DINode::FlagMultipleInheritance:
1933 return PointerToMemberRepresentation::MultipleInheritanceData;
1934 case DINode::FlagVirtualInheritance:
1935 return PointerToMemberRepresentation::VirtualInheritanceData;
1943 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
1944 bool IsPMF = isa<DISubroutineType>(Ty->getBaseType());
1947 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->
getClassType() :
nullptr);
1948 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
1949 : PointerKind::Near32;
1950 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
1951 : PointerMode::PointerToDataMember;
1965 case dwarf::DW_CC_normal:
return CallingConvention::NearC;
1966 case dwarf::DW_CC_BORLAND_msfastcall:
return CallingConvention::NearFast;
1967 case dwarf::DW_CC_BORLAND_thiscall:
return CallingConvention::ThisCall;
1968 case dwarf::DW_CC_BORLAND_stdcall:
return CallingConvention::NearStdCall;
1969 case dwarf::DW_CC_BORLAND_pascal:
return CallingConvention::NearPascal;
1970 case dwarf::DW_CC_LLVM_vectorcall:
return CallingConvention::NearVector;
1972 return CallingConvention::NearC;
1980 while (IsModifier &&
BaseTy) {
1982 switch (
BaseTy->getTag()) {
1983 case dwarf::DW_TAG_const_type:
1984 Mods |= ModifierOptions::Const;
1985 PO |= PointerOptions::Const;
1987 case dwarf::DW_TAG_volatile_type:
1988 Mods |= ModifierOptions::Volatile;
1989 PO |= PointerOptions::Volatile;
1991 case dwarf::DW_TAG_restrict_type:
1994 PO |= PointerOptions::Restrict;
2009 switch (
BaseTy->getTag()) {
2010 case dwarf::DW_TAG_pointer_type:
2011 case dwarf::DW_TAG_reference_type:
2012 case dwarf::DW_TAG_rvalue_reference_type:
2013 return lowerTypePointer(cast<DIDerivedType>(
BaseTy), PO);
2014 case dwarf::DW_TAG_ptr_to_member_type:
2015 return lowerTypeMemberPointer(cast<DIDerivedType>(
BaseTy), PO);
2025 if (Mods == ModifierOptions::None)
2035 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2038 if (ReturnAndArgTypeIndices.
size() > 1 &&
2044 if (!ReturnAndArgTypeIndices.
empty()) {
2045 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2046 ReturnTypeIndex = ReturnAndArgTypesRef.front();
2047 ArgTypeIndices = ReturnAndArgTypesRef.
drop_front();
2050 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2064 bool IsStaticMethod,
2067 TypeIndex ClassType = getTypeIndex(ClassTy);
2074 if (ReturnAndArgs.
size() > Index) {
2075 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
2082 if (!IsStaticMethod && ReturnAndArgs.
size() > Index) {
2084 dyn_cast_or_null<DIDerivedType>(ReturnAndArgs[Index])) {
2085 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2086 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2092 while (Index < ReturnAndArgs.
size())
2093 ArgTypeIndices.
push_back(getTypeIndex(ReturnAndArgs[Index++]));
2099 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2105 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2110 unsigned VSlotCount =
2120 case DINode::FlagPrivate:
return MemberAccess::Private;
2121 case DINode::FlagPublic:
return MemberAccess::Public;
2122 case DINode::FlagProtected:
return MemberAccess::Protected;
2125 return RecordTag == dwarf::DW_TAG_class_type ? MemberAccess::Private
2126 : MemberAccess::Public;
2132 if (SP->isArtificial())
2133 return MethodOptions::CompilerGenerated;
2137 return MethodOptions::None;
2142 if (SP->getFlags() & DINode::FlagStaticMember)
2143 return MethodKind::Static;
2145 switch (SP->getVirtuality()) {
2146 case dwarf::DW_VIRTUALITY_none:
2148 case dwarf::DW_VIRTUALITY_virtual:
2149 return Introduced ? MethodKind::IntroducingVirtual : MethodKind::Virtual;
2150 case dwarf::DW_VIRTUALITY_pure_virtual:
2151 return Introduced ? MethodKind::PureIntroducingVirtual
2152 : MethodKind::PureVirtual;
2157 return MethodKind::Vanilla;
2162 case dwarf::DW_TAG_class_type:
2163 return TypeRecordKind::Class;
2164 case dwarf::DW_TAG_structure_type:
2165 return TypeRecordKind::Struct;
2180 CO |= ClassOptions::HasUniqueName;
2186 if (ImmediateScope && isa<DICompositeType>(ImmediateScope))
2187 CO |= ClassOptions::Nested;
2193 if (Ty->
getTag() == dwarf::DW_TAG_enumeration_type) {
2194 if (ImmediateScope && isa<DISubprogram>(ImmediateScope))
2195 CO |= ClassOptions::Scoped;
2197 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2198 Scope = Scope->getScope()) {
2199 if (isa<DISubprogram>(Scope)) {
2200 CO |= ClassOptions::Scoped;
2211 case dwarf::DW_TAG_class_type:
2212 case dwarf::DW_TAG_structure_type:
2213 case dwarf::DW_TAG_union_type:
2214 case dwarf::DW_TAG_enumeration_type:
2220 if (
const auto *File = Ty->
getFile()) {
2232 unsigned EnumeratorCount = 0;
2235 CO |= ClassOptions::ForwardReference;
2238 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2242 if (
auto *
Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) {
2254 std::string FullName = getFullyQualifiedName(Ty);
2260 addUDTSrcLine(Ty, EnumTI);
2294void CodeViewDebug::clear() {
2295 assert(CurFn ==
nullptr);
2297 FnDebugInfo.clear();
2298 FileToFilepathMap.clear();
2301 TypeIndices.clear();
2302 CompleteTypeIndices.clear();
2303 ScopeGlobals.clear();
2304 CVGlobalVariableOffsets.clear();
2307void CodeViewDebug::collectMemberInfo(
ClassInfo &Info,
2310 Info.Members.push_back({DDTy, 0});
2313 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2314 DINode::FlagStaticMember) {
2317 StaticConstMembers.push_back(DDTy);
2329 const DIType *Ty = DDTy->getBaseType();
2330 bool FullyResolved =
false;
2331 while (!FullyResolved) {
2333 case dwarf::DW_TAG_const_type:
2334 case dwarf::DW_TAG_volatile_type:
2337 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2340 FullyResolved =
true;
2349 ClassInfo NestedInfo = collectClassInfo(DCTy);
2351 Info.Members.push_back(
2359 for (
auto *Element : Elements) {
2364 if (
auto *SP = dyn_cast<DISubprogram>(Element)) {
2365 Info.Methods[SP->getRawName()].push_back(SP);
2366 }
else if (
auto *DDTy = dyn_cast<DIDerivedType>(Element)) {
2367 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2368 collectMemberInfo(Info, DDTy);
2369 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2370 Info.Inheritance.push_back(DDTy);
2371 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2372 DDTy->
getName() ==
"__vtbl_ptr_type") {
2373 Info.VShapeTI = getTypeIndex(DDTy);
2374 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2375 Info.NestedTypes.push_back(DDTy);
2376 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2380 }
else if (
auto *Composite = dyn_cast<DICompositeType>(Element)) {
2381 Info.NestedTypes.push_back(Composite);
2404 auto I = CompleteTypeIndices.find(Ty);
2405 if (
I != CompleteTypeIndices.end() &&
I->second ==
TypeIndex())
2407 return getCompleteTypeIndex(Ty);
2415 std::string FullName = getFullyQualifiedName(Ty);
2420 DeferredCompleteTypes.push_back(Ty);
2430 unsigned FieldCount;
2433 lowerRecordFieldList(Ty);
2436 CO |= ClassOptions::ContainsNestedClass;
2444 CO |= ClassOptions::HasConstructorOrDestructor;
2446 std::string FullName = getFullyQualifiedName(Ty);
2454 addUDTSrcLine(Ty, ClassTI);
2464 return getCompleteTypeIndex(Ty);
2468 std::string FullName = getFullyQualifiedName(Ty);
2472 DeferredCompleteTypes.push_back(Ty);
2479 unsigned FieldCount;
2482 lowerRecordFieldList(Ty);
2485 CO |= ClassOptions::ContainsNestedClass;
2488 std::string FullName = getFullyQualifiedName(Ty);
2490 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2494 addUDTSrcLine(Ty, UnionTI);
2501std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2507 unsigned MemberCount = 0;
2510 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2514 if (
I->getFlags() & DINode::FlagVirtual) {
2516 unsigned VBPtrOffset =
I->getVBPtrOffset();
2518 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2519 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2520 ? TypeRecordKind::IndirectVirtualBaseClass
2521 : TypeRecordKind::VirtualBaseClass;
2524 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2530 assert(
I->getOffsetInBits() % 8 == 0 &&
2531 "bases must be on byte boundaries");
2533 getTypeIndex(
I->getBaseType()),
2534 I->getOffsetInBits() / 8);
2548 if (
Member->isStaticMember()) {
2556 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2557 Member->getName().starts_with(
"_vptr$")) {
2567 if (
Member->isBitField()) {
2568 uint64_t StartBitOffset = MemberOffsetInBits;
2569 if (
const auto *CI =
2570 dyn_cast_or_null<ConstantInt>(
Member->getStorageOffsetInBits())) {
2571 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2573 StartBitOffset -= MemberOffsetInBits;
2578 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2586 for (
auto &MethodItr :
Info.Methods) {
2589 std::vector<OneMethodRecord> Methods;
2591 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2592 bool Introduced = SP->getFlags() & DINode::FlagIntroducedVirtual;
2594 unsigned VFTableOffset = -1;
2596 VFTableOffset = SP->getVirtualIndex() * getPointerSizeInBytes();
2604 assert(!Methods.empty() &&
"Empty methods map entry");
2605 if (Methods.size() == 1)
2626 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2627 !
Info.NestedTypes.empty());
2630TypeIndex CodeViewDebug::getVBPTypeIndex() {
2636 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2637 : PointerKind::Near32;
2640 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2655 auto I = TypeIndices.find({Ty, ClassTy});
2656 if (
I != TypeIndices.end())
2659 TypeLoweringScope S(*
this);
2661 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2665CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2667 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2668 "this type must be a pointer type");
2671 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2672 Options = PointerOptions::LValueRefThisPointer;
2673 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2674 Options = PointerOptions::RValueRefThisPointer;
2681 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2682 if (
I != TypeIndices.end())
2685 TypeLoweringScope S(*
this);
2687 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2690TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(
const DIType *Ty) {
2692 getPointerSizeInBytes() == 8 ? PointerKind::Near64
2693 : PointerKind::Near32,
2694 PointerMode::LValueReference, PointerOptions::None,
2707 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2708 (void)getTypeIndex(Ty);
2709 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2710 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2715 case dwarf::DW_TAG_class_type:
2716 case dwarf::DW_TAG_structure_type:
2717 case dwarf::DW_TAG_union_type:
2720 return getTypeIndex(Ty);
2723 const auto *CTy = cast<DICompositeType>(Ty);
2725 TypeLoweringScope S(*
this);
2731 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2732 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2737 if (CTy->isForwardDecl())
2744 auto InsertResult = CompleteTypeIndices.insert({CTy,
TypeIndex()});
2745 if (!InsertResult.second)
2746 return InsertResult.first->second;
2749 switch (CTy->getTag()) {
2750 case dwarf::DW_TAG_class_type:
2751 case dwarf::DW_TAG_structure_type:
2752 TI = lowerCompleteTypeClass(CTy);
2754 case dwarf::DW_TAG_union_type:
2755 TI = lowerCompleteTypeUnion(CTy);
2765 CompleteTypeIndices[CTy] = TI;
2773void CodeViewDebug::emitDeferredCompleteTypes() {
2775 while (!DeferredCompleteTypes.empty()) {
2776 std::swap(DeferredCompleteTypes, TypesToEmit);
2778 getCompleteTypeIndex(RecordTy);
2779 TypesToEmit.clear();
2783void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2787 for (
const LocalVariable &L : Locals)
2788 if (
L.DIVar->isParameter())
2790 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2791 return L->DIVar->getArg() <
R->DIVar->getArg();
2793 for (
const LocalVariable *L : Params)
2794 emitLocalVariable(FI, *L);
2797 for (
const LocalVariable &L : Locals) {
2798 if (!
L.DIVar->isParameter()) {
2799 if (
L.ConstantValue) {
2802 const DIType *Ty =
L.DIVar->getType();
2804 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2806 emitLocalVariable(FI, L);
2812void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2813 const LocalVariable &Var) {
2815 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2818 if (Var.DIVar->isParameter())
2819 Flags |= LocalSymFlags::IsParameter;
2820 if (Var.DefRanges.empty())
2821 Flags |= LocalSymFlags::IsOptimizedOut;
2825 ? getTypeIndexForReferenceTo(Var.DIVar->getType())
2826 : getCompleteTypeIndex(Var.DIVar->
getType());
2832 endSymbolRecord(LocalEnd);
2838 for (
const auto &Pair : Var.DefRanges) {
2839 LocalVarDef DefRange = Pair.first;
2840 const auto &
Ranges = Pair.second;
2842 if (DefRange.InMemory) {
2843 int Offset = DefRange.DataOffset;
2844 unsigned Reg = DefRange.CVRegister;
2851 Offset += FI.OffsetAdjustment;
2858 if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2859 (
bool(Flags & LocalSymFlags::IsParameter)
2860 ? (EncFP == FI.EncodedParamFramePtrReg)
2861 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2867 if (DefRange.IsSubfield) {
2869 (DefRange.StructOffset
2874 DRHdr.
Flags = RegRelFlags;
2879 assert(DefRange.DataOffset == 0 &&
"unexpected offset into register");
2880 if (DefRange.IsSubfield) {
2882 DRHdr.
Register = DefRange.CVRegister;
2888 DRHdr.
Register = DefRange.CVRegister;
2897 const FunctionInfo& FI) {
2899 emitLexicalBlock(*
Block, FI);
2904void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2905 const FunctionInfo& FI) {
2906 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2913 OS.
AddComment(
"Function section relative address");
2919 endSymbolRecord(RecordEnd);
2922 emitLocalVariableList(FI,
Block.Locals);
2923 emitGlobalVariableList(
Block.Globals);
2926 emitLexicalBlockList(
Block.Children, FI);
2929 emitEndSymbolRecord(SymbolKind::S_END);
2934void CodeViewDebug::collectLexicalBlockInfo(
2940 collectLexicalBlockInfo(*Scope,
Blocks, Locals, Globals);
2945void CodeViewDebug::collectLexicalBlockInfo(
2950 if (
Scope.isAbstractScope())
2955 bool IgnoreScope =
false;
2956 auto LI = ScopeVariables.find(&Scope);
2958 LI != ScopeVariables.end() ? &LI->second :
nullptr;
2959 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
2961 GI != ScopeGlobals.end() ? GI->second.get() :
nullptr;
2966 if (!Locals && !Globals)
2996 collectLexicalBlockInfo(
Scope.getChildren(),
3006 auto BlockInsertion = CurFn->LexicalBlocks.insert({DILB, LexicalBlock()});
3007 if (!BlockInsertion.second)
3014 LexicalBlock &
Block = BlockInsertion.first->second;
3017 assert(
Block.Begin &&
"missing label for scope begin");
3018 assert(
Block.End &&
"missing label for scope end");
3021 Block.Locals = std::move(*Locals);
3023 Block.Globals = std::move(*Globals);
3025 collectLexicalBlockInfo(
Scope.getChildren(),
3033 assert(FnDebugInfo.count(&GV));
3034 assert(CurFn == FnDebugInfo[&GV].
get());
3040 collectLexicalBlockInfo(*CFS,
3048 ScopeVariables.clear();
3052 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3053 FnDebugInfo.erase(&GV);
3059 for (
const auto &
MBB : *MF) {
3060 for (
const auto &
MI :
MBB) {
3061 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3064 dyn_cast<DIType>(MD)));
3071 collectDebugInfoForJumpTables(MF,
isThumb);
3085 return DL &&
DL.getLine() != 0;
3092 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3100 for (
const auto &NextMI : *
MI->getParent()) {
3101 if (NextMI.isDebugInstr())
3103 DL = NextMI.getDebugLoc();
3116 maybeRecordLocation(
DL,
Asm->
MF);
3129void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3137 if (EE.Value == SymKind)
3154void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3163void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3171void CodeViewDebug::emitDebugInfoForUDTs(
3172 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3174 size_t OriginalSize = UDTs.size();
3176 for (
const auto &UDT : UDTs) {
3179 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3181 OS.
emitInt32(getCompleteTypeIndex(
T).getIndex());
3182 assert(OriginalSize == UDTs.size() &&
3183 "getCompleteTypeIndex found new UDTs!");
3185 endSymbolRecord(UDTRecordEnd);
3189void CodeViewDebug::collectGlobalVariableInfo() {
3194 GV.getDebugInfo(GVEs);
3195 for (
const auto *GVE : GVEs)
3196 GlobalMap[GVE] = &GV;
3201 const auto *
CU = cast<DICompileUnit>(
Node);
3202 for (
const auto *GVE :
CU->getGlobalVariables()) {
3211 if ((
DIE->getNumElements() == 2) &&
3212 (
DIE->getElement(0) == dwarf::DW_OP_plus_uconst))
3217 CVGlobalVariableOffsets.insert(
3218 std::make_pair(DIGV,
DIE->getElement(1)));
3221 if (GlobalMap.
count(GVE) == 0 &&
DIE->isConstant()) {
3222 CVGlobalVariable CVGV = {DIGV,
DIE};
3226 const auto *GV = GlobalMap.
lookup(GVE);
3232 if (Scope && isa<DILocalScope>(Scope)) {
3235 auto Insertion = ScopeGlobals.insert(
3236 {
Scope, std::unique_ptr<GlobalVariableList>()});
3237 if (Insertion.second)
3238 Insertion.first->second = std::make_unique<GlobalVariableList>();
3239 VariableList = Insertion.first->second.get();
3242 VariableList = &ComdatVariables;
3245 VariableList = &GlobalVariables;
3246 CVGlobalVariable CVGV = {DIGV, GV};
3252void CodeViewDebug::collectDebugInfoForGlobals() {
3253 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3256 getCompleteTypeIndex(DIGV->
getType());
3257 getFullyQualifiedName(Scope, DIGV->
getName());
3260 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3263 getCompleteTypeIndex(DIGV->
getType());
3264 getFullyQualifiedName(Scope, DIGV->
getName());
3268void CodeViewDebug::emitDebugInfoForGlobals() {
3272 switchToDebugSectionForSymbol(
nullptr);
3273 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3274 OS.
AddComment(
"Symbol subsection for globals");
3275 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3276 emitGlobalVariableList(GlobalVariables);
3277 emitStaticConstMemberList();
3278 endCVSubsection(EndLabel);
3283 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3284 const GlobalVariable *GV = cast<const GlobalVariable *>(CVGV.GVInfo);
3288 switchToDebugSectionForSymbol(GVSym);
3289 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3291 emitDebugInfoForGlobal(CVGV);
3292 endCVSubsection(EndLabel);
3296void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3299 for (
auto *Ty : cast<DICompileUnit>(
Node)->getRetainedTypes()) {
3300 if (
DIType *RT = dyn_cast<DIType>(Ty)) {
3310 for (
const CVGlobalVariable &CVGV : Globals) {
3312 emitDebugInfoForGlobal(CVGV);
3318 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3320 OS.
emitInt32(getTypeIndex(DTy).getIndex());
3334 endSymbolRecord(SConstantEnd);
3337void CodeViewDebug::emitStaticConstMemberList() {
3343 dyn_cast_or_null<ConstantInt>(DTy->getConstant()))
3347 dyn_cast_or_null<ConstantFP>(DTy->getConstant()))
3348 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3352 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3353 getFullyQualifiedName(Scope, DTy->
getName()));
3358 if (isa<DICompositeType>(Ty))
3361 if (
auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
3363 if (
T == dwarf::DW_TAG_pointer_type ||
3364 T == dwarf::DW_TAG_ptr_to_member_type ||
3365 T == dwarf::DW_TAG_reference_type ||
3366 T == dwarf::DW_TAG_rvalue_reference_type)
3368 assert(DTy->getBaseType() &&
"Expected valid base type");
3372 auto *BTy = cast<DIBasicType>(Ty);
3373 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3376void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3381 if (
const auto *MemberDecl = dyn_cast_or_null<DIDerivedType>(
3383 Scope = MemberDecl->getScope();
3389 ? std::string(DIGV->
getName())
3393 dyn_cast_if_present<const GlobalVariable *>(CVGV.GVInfo)) {
3399 : SymbolKind::S_GTHREAD32)
3401 : SymbolKind::S_GDATA32);
3414 const unsigned LengthOfDataRecord = 12;
3416 endSymbolRecord(DataEnd);
3420 "Global constant variables must contain a constant expression.");
3434 int64_t)> &Callback) {
3436 if (JTI && !JTI->isEmpty()) {
3440 for (
const auto &
MBB : *MF) {
3443 if (LastMI !=
MBB.
end() && LastMI->isIndirectBranch()) {
3451 for (
const auto &MO : LastMI->operands()) {
3453 unsigned Index = MO.getIndex();
3457 Callback(*JTI, *LastMI, Index);
3466 if (
I->isJumpTableDebugInfo()) {
3467 unsigned Index =
I->getOperand(0).getImm();
3471 Callback(*JTI, *LastMI, Index);
3480 "Some of jump tables were not used in a debug info instruction");
3485void CodeViewDebug::discoverJumpTableBranches(
const MachineFunction *MF,
3493void CodeViewDebug::collectDebugInfoForJumpTables(
const MachineFunction *MF,
3498 int64_t JumpTableIndex) {
3511 "EK_Custom32, EK_GPRel32BlockAddress, and "
3512 "EK_GPRel64BlockAddress should never be emitted for COFF");
3515 EntrySize = JumpTableEntrySize::Pointer;
3522 std::tie(
Base, BaseOffset, Branch, EntrySize) =
3527 CurFn->JumpTables.push_back(
3534void CodeViewDebug::emitDebugInfoForJumpTables(
const FunctionInfo &FI) {
3535 for (
auto JumpTable : FI.JumpTables) {
3536 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3560 endSymbolRecord(JumpTableEnd);
3564void CodeViewDebug::emitInlinees(
3568 constexpr size_t ChunkSize =
3575 size_t CurrentIndex = 0;
3576 while (CurrentIndex < SortedInlinees.size()) {
3577 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3578 auto CurrentChunkSize =
3579 std::min(ChunkSize, SortedInlinees.size() - CurrentIndex);
3583 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3584 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3586 OS.
emitInt32(SortedInlinees[CurrentIndex].getIndex());
3588 endSymbolRecord(Symbol);
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
static bool isThumb(const MCSubtargetInfo &STI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-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)
void forEachJumpTableBranch(const MachineFunction *MF, bool isThumb, const std::function< void(const MachineJumpTableInfo &, const MachineInstr &, int64_t)> &Callback)
static CallingConvention dwarfCCToCodeView(unsigned DwarfCC)
Given a DWARF calling convention, get the CodeView equivalent.
static bool isFloatDIType(const DIType *Ty)
static void addLocIfNotPresent(SmallVectorImpl< const DILocation * > &Locs, const DILocation *Loc)
static bool shouldEmitUdt(const DIType *T)
static StringRef getPrettyScopeName(const DIScope *Scope)
static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty)
static 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
Module.h This file contains the declarations for the Module class.
unsigned const TargetRegisterInfo * TRI
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the SmallBitVector class.
This file defines the SmallString class.
static SymbolRef::Type getType(const Symbol *Sym)
This file describes how to lower LLVM code to machine code.
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.
bool hasDebugInfo() const
Returns true if valid debug info is present.
MCSymbol * getFunctionEnd() const
virtual std::tuple< const MCSymbol *, uint64_t, const MCSymbol *, codeview::JumpTableEntrySize > getCodeViewJumpTableInfo(int JTI, const MachineInstr *BranchInstr, const MCSymbol *BranchLabel) const
Gets information required to create a CodeView debug symbol for a jump table.
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
DIType * getClassType() const
Get casted version of extra data.
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
This class represents an Operation in the Expression.
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.
MCSymbol * getLabelAfterInsn(const MachineInstr *MI)
Return Label immediately following the 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.
virtual void beginInstruction(const MachineInstr *MI)
const MachineInstr * PrologEndLoc
This location indicates end of function prologue and beginning of function body.
static uint64_t getBaseTypeSize(const DIType *Ty)
If this type is derived from a base type then return base type size.
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, uint32_t Subsec=0)
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.
std::string CommandlineArgs
ArrayRef< MDOperand > operands() const
unsigned getNumOperands() const
Return number of MDNode operands.
reverse_instr_iterator instr_rbegin()
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
reverse_instr_iterator instr_rend()
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
int64_t getOffsetAdjustment() const
Return the correction for frame offsets.
unsigned getCVBytesOfCalleeSavedRegisters() const
Returns how many bytes of callee-saved registers the target pushed in the prologue.
bool hasStackProtectorIndex() const
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.
MCSymbol * getJTISymbol(unsigned JTI, MCContext &Ctx, bool isLinkerPrivate=false) const
getJTISymbol - Return the MCSymbol for the specified non-empty jump table.
auto getInStackSlotVariableDbgInfo()
Returns the collection of variables for which we have debug info and that have been assigned a stack ...
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
ArrayRef< std::pair< MCSymbol *, MDNode * > > getCodeViewAnnotations() const
Representation of each machine instruction.
bool isDebugValue() const
MachineOperand & getDebugOperand(unsigned Index)
@ EK_GPRel32BlockAddress
EK_GPRel32BlockAddress - Each entry is an address of block, encoded with a relocation as gp-relative,...
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
@ EK_LabelDifference32
EK_LabelDifference32 - Each entry is the address of the block minus the address of the jump table.
@ EK_Custom32
EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the TargetLowering::LowerCustomJ...
@ EK_LabelDifference64
EK_LabelDifference64 - Each entry is the address of the block minus the address of the jump table.
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
@ EK_GPRel64BlockAddress
EK_GPRel64BlockAddress - Each entry is an address of block, encoded with a relocation as gp-relative,...
JTEntryKind getEntryKind() const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
const MCContext & getContext() const
const Module * getModule() const
A Module instance is used to store all the information related to an LLVM module.
NamedMDNode * getNamedMetadata(StringRef 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.
iterator_range< global_iterator > globals()
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Metadata * getProfileSummary(bool IsCS) const
Returns profile summary metadata.
iterator_range< op_iterator > operands()
const RecordRecTy * getType() const
Wrapper class representing virtual and physical registers.
Represents a location in source code.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
const_iterator begin() const
const_iterator end() const
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
char back() const
back - Get the last character in the string.
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Information about stack frame layout on the target.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
CodeGenOptLevel 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 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.
CallingConvention
These values correspond to the CV_call_e enumeration, and are documented at the following locations: ...
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)
SourceLanguage
These values correspond to the CV_CFL_LANG enumeration in the Microsoft Debug Interface Access SDK,...
ElementType
The element type of an SRV or UAV resource.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
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.
std::tuple< uint64_t, uint32_t > InlineSite
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
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.