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;
126 case Triple::ArchType::mipsel:
127 return CPUType::MIPS;
137 std::string &Filepath = FileToFilepathMap[File];
138 if (!Filepath.empty())
141 StringRef Dir = File->getDirectory(), Filename = File->getFilename();
145 if (Dir.
starts_with(
"/") || Filename.starts_with(
"/")) {
148 Filepath = std::string(Dir);
149 if (Dir.
back() !=
'/')
151 Filepath += Filename;
159 if (Filename.find(
':') == 1)
160 Filepath = std::string(Filename);
162 Filepath = (Dir +
"\\" + Filename).str();
167 std::replace(Filepath.begin(), Filepath.end(),
'/',
'\\');
171 while ((Cursor = Filepath.find(
"\\.\\", Cursor)) != std::string::npos)
172 Filepath.erase(Cursor, 2);
177 while ((Cursor = Filepath.find(
"\\..\\", Cursor)) != std::string::npos) {
182 size_t PrevSlash = Filepath.rfind(
'\\', Cursor - 1);
183 if (PrevSlash == std::string::npos)
187 Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
194 while ((Cursor = Filepath.find(
"\\\\", Cursor)) != std::string::npos)
195 Filepath.erase(Cursor, 1);
200unsigned CodeViewDebug::maybeRecordFile(
const DIFile *
F) {
202 unsigned NextId = FileIdMap.
size() + 1;
203 auto Insertion = FileIdMap.
insert(std::make_pair(FullPath, NextId));
204 if (Insertion.second) {
208 if (
F->getChecksum()) {
209 std::string Checksum = fromHex(
F->getChecksum()->Value);
211 memcpy(CKMem, Checksum.data(), Checksum.size());
213 reinterpret_cast<const uint8_t *
>(CKMem), Checksum.size());
214 switch (
F->getChecksum()->Kind) {
216 CSKind = FileChecksumKind::MD5;
219 CSKind = FileChecksumKind::SHA1;
222 CSKind = FileChecksumKind::SHA256;
227 static_cast<unsigned>(CSKind));
231 return Insertion.first->second;
234CodeViewDebug::InlineSite &
235CodeViewDebug::getInlineSite(
const DILocation *InlinedAt,
237 auto SiteInsertion = CurFn->InlineSites.insert({InlinedAt,
InlineSite()});
238 InlineSite *Site = &SiteInsertion.first->second;
239 if (SiteInsertion.second) {
240 unsigned ParentFuncId = CurFn->FuncId;
241 if (
const DILocation *OuterIA = InlinedAt->getInlinedAt())
243 getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())
246 Site->SiteFuncId = NextFuncId++;
248 Site->SiteFuncId, ParentFuncId, maybeRecordFile(InlinedAt->getFile()),
249 InlinedAt->getLine(), InlinedAt->getColumn(),
SMLoc());
251 InlinedSubprograms.insert(Inlinee);
252 auto InlineeIdx = getFuncIdForSubprogram(Inlinee);
254 if (InlinedAt->getInlinedAt() ==
nullptr)
255 CurFn->Inlinees.insert(InlineeIdx);
262 if (!ScopeName.
empty())
265 switch (Scope->getTag()) {
266 case dwarf::DW_TAG_enumeration_type:
267 case dwarf::DW_TAG_class_type:
268 case dwarf::DW_TAG_structure_type:
269 case dwarf::DW_TAG_union_type:
270 return "<unnamed-tag>";
271 case dwarf::DW_TAG_namespace:
272 return "`anonymous namespace'";
278const DISubprogram *CodeViewDebug::collectParentScopeNames(
281 while (Scope !=
nullptr) {
282 if (ClosestSubprogram ==
nullptr)
283 ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
288 if (
const auto *Ty = dyn_cast<DICompositeType>(Scope))
289 DeferredCompleteTypes.push_back(Ty);
292 if (!ScopeName.
empty())
293 QualifiedNameComponents.
push_back(ScopeName);
296 return ClosestSubprogram;
301 std::string FullyQualifiedName;
304 FullyQualifiedName.append(std::string(QualifiedNameComponent));
305 FullyQualifiedName.append(
"::");
307 FullyQualifiedName.append(std::string(TypeName));
308 return FullyQualifiedName;
316 if (
CVD.TypeEmissionLevel == 1)
317 CVD.emitDeferredCompleteTypes();
318 --
CVD.TypeEmissionLevel;
323std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Scope,
330 collectParentScopeNames(Scope, QualifiedNameComponents);
334std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Ty) {
350 if (!Scope || isa<DIFile>(Scope) || isa<DISubprogram>(Scope))
353 assert(!isa<DIType>(Scope) &&
"shouldn't make a namespace scope for a type");
356 auto I = TypeIndices.find({Scope,
nullptr});
357 if (
I != TypeIndices.end())
361 std::string ScopeName = getFullyQualifiedName(Scope);
364 return recordTypeIndexForDINode(Scope, TI);
370 if (
Name.empty() ||
Name.back() !=
'>')
373 int OpenBrackets = 0;
374 for (
int i =
Name.size() - 1; i >= 0; --i) {
377 else if (
Name[i] ==
'<') {
379 if (OpenBrackets == 0)
380 return Name.substr(0, i);
390 auto I = TypeIndices.find({SP,
nullptr});
391 if (
I != TypeIndices.end())
401 if (
const auto *Class = dyn_cast_or_null<DICompositeType>(Scope)) {
405 TypeIndex ClassType = getTypeIndex(Class);
411 TypeIndex ParentScope = getScopeIndex(Scope);
416 return recordTypeIndexForDINode(SP, TI);
420 return ((DCTy->
getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);
428 const DIType *ReturnTy =
nullptr;
430 if (TypeArray.size())
431 ReturnTy = TypeArray[0];
436 if (
auto *ReturnDCTy = dyn_cast_or_null<DICompositeType>(ReturnTy))
438 FO |= FunctionOptions::CxxReturnUdt;
441 if (ClassTy &&
isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {
442 FO |= FunctionOptions::Constructor;
454 if (SP->getDeclaration())
455 SP = SP->getDeclaration();
456 assert(!SP->getDeclaration() &&
"should use declaration as key");
460 auto I = TypeIndices.find({SP,
Class});
461 if (
I != TypeIndices.end())
467 TypeLoweringScope S(*
this);
468 const bool IsStaticMethod = (SP->getFlags() & DINode::FlagStaticMember) != 0;
472 SP->getType(), Class, SP->getThisAdjustment(), IsStaticMethod, FO);
473 return recordTypeIndexForDINode(SP, TI, Class);
479 auto InsertResult = TypeIndices.insert({{
Node, ClassTy}, TI});
481 assert(InsertResult.second &&
"DINode was already assigned a type index");
485unsigned CodeViewDebug::getPointerSizeInBytes() {
489void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
494 InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
495 Site.InlinedLocals.emplace_back(std::move(Var));
498 ScopeVariables[
LS].emplace_back(std::move(Var));
508void CodeViewDebug::maybeRecordLocation(
const DebugLoc &
DL,
520 if (LI.getStartLine() !=
DL.getLine() || LI.isAlwaysStepInto() ||
521 LI.isNeverStepInto())
525 if (CI.getStartColumn() !=
DL.getCol())
528 if (!CurFn->HaveLineInfo)
529 CurFn->HaveLineInfo =
true;
532 FileId = CurFn->LastFileId;
534 FileId = CurFn->LastFileId = maybeRecordFile(
DL->getFile());
537 unsigned FuncId = CurFn->FuncId;
544 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
547 bool FirstLoc =
true;
548 while ((SiteLoc = Loc->getInlinedAt())) {
550 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
564void CodeViewDebug::emitCodeViewMagicVersion() {
572 case dwarf::DW_LANG_C:
573 case dwarf::DW_LANG_C89:
574 case dwarf::DW_LANG_C99:
575 case dwarf::DW_LANG_C11:
576 return SourceLanguage::C;
577 case dwarf::DW_LANG_C_plus_plus:
578 case dwarf::DW_LANG_C_plus_plus_03:
579 case dwarf::DW_LANG_C_plus_plus_11:
580 case dwarf::DW_LANG_C_plus_plus_14:
581 return SourceLanguage::Cpp;
582 case dwarf::DW_LANG_Fortran77:
583 case dwarf::DW_LANG_Fortran90:
584 case dwarf::DW_LANG_Fortran95:
585 case dwarf::DW_LANG_Fortran03:
586 case dwarf::DW_LANG_Fortran08:
587 return SourceLanguage::Fortran;
588 case dwarf::DW_LANG_Pascal83:
589 return SourceLanguage::Pascal;
590 case dwarf::DW_LANG_Cobol74:
591 case dwarf::DW_LANG_Cobol85:
592 return SourceLanguage::Cobol;
593 case dwarf::DW_LANG_Java:
594 return SourceLanguage::Java;
595 case dwarf::DW_LANG_D:
596 return SourceLanguage::D;
597 case dwarf::DW_LANG_Swift:
598 return SourceLanguage::Swift;
599 case dwarf::DW_LANG_Rust:
600 return SourceLanguage::Rust;
601 case dwarf::DW_LANG_ObjC:
602 return SourceLanguage::ObjC;
603 case dwarf::DW_LANG_ObjC_plus_plus:
604 return SourceLanguage::ObjCpp;
609 return SourceLanguage::Masm;
625 const MDNode *Node = *M->debug_compile_units_begin();
626 const auto *
CU = cast<DICompileUnit>(Node);
630 collectGlobalVariableInfo();
634 mdconst::extract_or_null<ConstantInt>(M->getModuleFlag(
"CodeViewGHash"));
635 EmitDebugGlobalHashes = GH && !GH->
isZero();
649 switchToDebugSectionForSymbol(
nullptr);
651 MCSymbol *CompilerInfo = beginCVSubsection(DebugSubsectionKind::Symbols);
653 emitCompilerInformation();
654 endCVSubsection(CompilerInfo);
656 emitInlineeLinesSubsection();
659 for (
auto &
P : FnDebugInfo)
660 if (!
P.first->isDeclarationForLinker())
661 emitDebugInfoForFunction(
P.first, *
P.second);
666 collectDebugInfoForGlobals();
669 emitDebugInfoForRetainedTypes();
672 setCurrentSubprogram(
nullptr);
673 emitDebugInfoForGlobals();
677 switchToDebugSectionForSymbol(
nullptr);
680 if (!GlobalUDTs.empty()) {
681 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
682 emitDebugInfoForUDTs(GlobalUDTs);
683 endCVSubsection(SymbolsEnd);
687 OS.
AddComment(
"File index to string table offset subsection");
701 emitTypeInformation();
703 if (EmitDebugGlobalHashes)
704 emitTypeGlobalHashes();
711 unsigned MaxFixedRecordLength = 0xF00) {
719 OS.emitBytes(NullTerminatedString);
722void CodeViewDebug::emitTypeInformation() {
723 if (TypeTable.
empty())
728 emitCodeViewMagicVersion();
734 CVMCAdapter CVMCOS(OS, Table);
738 std::optional<TypeIndex>
B = Table.getFirst();
750 B = Table.getNext(*
B);
754void CodeViewDebug::emitTypeGlobalHashes() {
755 if (TypeTable.
empty())
771 for (
const auto &GHR : TypeTable.
hashes()) {
781 assert(GHR.Hash.size() == 8);
782 StringRef S(
reinterpret_cast<const char *
>(GHR.Hash.data()),
788void CodeViewDebug::emitObjName() {
789 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);
794 if (PathRef.empty() || PathRef ==
"-") {
807 endSymbolRecord(CompilerEnd);
821 for (
const char C :
Name) {
824 V.Part[
N] +=
C -
'0';
826 std::min<int>(V.Part[
N], std::numeric_limits<uint16_t>::max());
827 }
else if (
C ==
'.') {
837void CodeViewDebug::emitCompilerInformation() {
838 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
842 Flags = CurrentSourceLanguage;
850 Arch == ArchType::aarch64) {
862 const auto *
CU = cast<DICompileUnit>(
Node);
867 for (
int N : FrontVer.Part) {
874 int Major = 1000 * LLVM_VERSION_MAJOR +
875 10 * LLVM_VERSION_MINOR +
878 Major = std::min<int>(Major, std::numeric_limits<uint16_t>::max());
879 Version BackVer = {{ Major, 0, 0, 0 }};
881 for (
int N : BackVer.Part)
884 OS.
AddComment(
"Null-terminated compiler version string");
887 endSymbolRecord(CompilerEnd);
896void CodeViewDebug::emitBuildInfo() {
910 const auto *
CU = cast<DICompileUnit>(
Node);
911 const DIFile *MainSourceFile =
CU->getFile();
929 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
930 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
933 endSymbolRecord(BIEnd);
934 endCVSubsection(BISubsecEnd);
937void CodeViewDebug::emitInlineeLinesSubsection() {
938 if (InlinedSubprograms.empty())
942 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
949 OS.
emitInt32(
unsigned(InlineeLinesSignature::Normal));
952 assert(TypeIndices.count({SP, nullptr}));
953 TypeIndex InlineeIdx = TypeIndices[{SP,
nullptr}];
956 unsigned FileId = maybeRecordFile(SP->
getFile());
960 OS.
AddComment(
"Type index of inlined function");
962 OS.
AddComment(
"Offset into filechecksum table");
968 endCVSubsection(InlineEnd);
971void CodeViewDebug::emitInlinedCallSite(
const FunctionInfo &FI,
974 assert(TypeIndices.count({Site.Inlinee, nullptr}));
975 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee,
nullptr}];
978 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
987 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
988 unsigned StartLineNum = Site.Inlinee->getLine();
993 endSymbolRecord(InlineEnd);
995 emitLocalVariableList(FI, Site.InlinedLocals);
998 for (
const DILocation *ChildSite : Site.ChildSites) {
999 auto I = FI.InlineSites.find(ChildSite);
1000 assert(
I != FI.InlineSites.end() &&
1001 "child site not in function inline site map");
1002 emitInlinedCallSite(FI, ChildSite,
I->second);
1006 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1009void CodeViewDebug::switchToDebugSectionForSymbol(
const MCSymbol *GVSym) {
1014 GVSym ? dyn_cast<MCSectionCOFF>(&GVSym->
getSection()) : nullptr;
1025 if (ComdatDebugSections.insert(DebugSec).second)
1026 emitCodeViewMagicVersion();
1031void CodeViewDebug::emitDebugInfoForThunk(
const Function *GV,
1034 std::string FuncName =
1039 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1042 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1049 OS.
AddComment(
"Thunk section relative address");
1060 endSymbolRecord(ThunkRecordEnd);
1066 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1068 endCVSubsection(SymbolsEnd);
1071void CodeViewDebug::emitDebugInfoForFunction(
const Function *GV,
1079 switchToDebugSectionForSymbol(Fn);
1081 std::string FuncName;
1084 setCurrentSubprogram(SP);
1086 if (SP->isThunk()) {
1087 emitDebugInfoForThunk(GV, FI, Fn);
1097 if (FuncName.empty())
1106 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1109 : SymbolKind::S_GPROC32_ID;
1110 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1129 OS.
AddComment(
"Function section relative address");
1134 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;
1135 if (FI.HasFramePointer)
1136 ProcFlags |= ProcSymFlags::HasFP;
1138 ProcFlags |= ProcSymFlags::IsNoReturn;
1140 ProcFlags |= ProcSymFlags::IsNoInline;
1146 endSymbolRecord(ProcRecordEnd);
1148 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1151 OS.
emitInt32(FI.FrameSize - FI.CSRSize);
1156 OS.
AddComment(
"Bytes of callee saved registers");
1162 OS.
AddComment(
"Flags (defines frame register)");
1164 endSymbolRecord(FrameProcEnd);
1166 emitInlinees(FI.Inlinees);
1167 emitLocalVariableList(FI, FI.Locals);
1168 emitGlobalVariableList(FI.Globals);
1169 emitLexicalBlockList(FI.ChildBlocks, FI);
1174 for (
const DILocation *InlinedAt : FI.ChildSites) {
1175 auto I = FI.InlineSites.find(InlinedAt);
1176 assert(
I != FI.InlineSites.end() &&
1177 "child site not in function inline site map");
1178 emitInlinedCallSite(FI, InlinedAt,
I->second);
1181 for (
auto Annot : FI.Annotations) {
1183 MDTuple *Strs = cast<MDTuple>(Annot.second);
1184 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1192 StringRef Str = cast<MDString>(MD)->getString();
1193 assert(Str.data()[Str.size()] ==
'\0' &&
"non-nullterminated MDString");
1196 endSymbolRecord(AnnotEnd);
1199 for (
auto HeapAllocSite : FI.HeapAllocSites) {
1200 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1201 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1202 const DIType *DITy = std::get<2>(HeapAllocSite);
1203 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1211 OS.
emitInt32(getCompleteTypeIndex(DITy).getIndex());
1212 endSymbolRecord(HeapAllocEnd);
1216 emitDebugInfoForUDTs(LocalUDTs);
1218 emitDebugInfoForJumpTables(FI);
1221 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1223 endCVSubsection(SymbolsEnd);
1230CodeViewDebug::createDefRangeMem(
uint16_t CVRegister,
int Offset) {
1236 DR.StructOffset = 0;
1237 DR.CVRegister = CVRegister;
1241void CodeViewDebug::collectVariableInfoFromMFTable(
1252 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1253 "Expected inlined-at fields to agree");
1255 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1264 int64_t ExprOffset = 0;
1268 if (
VI.Expr->getNumElements() == 1 &&
1269 VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)
1271 else if (!
VI.Expr->extractIfOffset(ExprOffset))
1279 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1282 "Frame offsets with a scalable component are not supported");
1285 LocalVarDef DefRange =
1286 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset);
1295 Var.DefRanges[DefRange].emplace_back(Begin,
End);
1299 Var.UseReferenceType =
true;
1301 recordLocalVariable(std::move(Var), Scope);
1313void CodeViewDebug::calculateRanges(
1318 for (
auto I = Entries.begin(), E = Entries.end();
I != E; ++
I) {
1320 if (!
Entry.isDbgValue())
1326 std::optional<DbgVariableLocation>
Location =
1348 if (Var.UseReferenceType) {
1357 Var.UseReferenceType =
true;
1358 Var.DefRanges.clear();
1359 calculateRanges(Var, Entries);
1370 if (
Location->FragmentInfo->OffsetInBits % 8)
1374 DR.CVRegister =
TRI->getCodeViewRegNum(
Location->Register);
1375 DR.InMemory = !
Location->LoadChain.empty();
1379 DR.IsSubfield =
true;
1380 DR.StructOffset =
Location->FragmentInfo->OffsetInBits / 8;
1382 DR.IsSubfield =
false;
1383 DR.StructOffset = 0;
1390 auto &EndingEntry = Entries[
Entry.getEndIndex()];
1391 End = EndingEntry.isDbgValue()
1401 if (!
R.empty() &&
R.back().second == Begin)
1402 R.back().second =
End;
1404 R.emplace_back(Begin,
End);
1410void CodeViewDebug::collectVariableInfo(
const DISubprogram *SP) {
1413 collectVariableInfoFromMFTable(Processed);
1416 InlinedEntity
IV =
I.first;
1423 const auto &Entries =
I.second;
1437 calculateRanges(Var, Entries);
1438 recordLocalVariable(std::move(Var), Scope);
1447 auto Insertion = FnDebugInfo.insert({&GV, std::make_unique<FunctionInfo>()});
1448 assert(Insertion.second &&
"function already has info");
1449 CurFn = Insertion.first->second.get();
1450 CurFn->FuncId = NextFuncId++;
1459 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1463 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::None;
1464 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::None;
1465 if (CurFn->FrameSize > 0) {
1467 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1468 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr;
1470 CurFn->HasFramePointer =
true;
1472 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr;
1473 if (CurFn->HasStackRealignment) {
1475 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1479 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::FramePtr;
1487 FPO |= FrameProcedureOptions::HasAlloca;
1489 FPO |= FrameProcedureOptions::HasSetJmp;
1492 FPO |= FrameProcedureOptions::HasInlineAssembly;
1496 FPO |= FrameProcedureOptions::HasStructuredExceptionHandling;
1498 FPO |= FrameProcedureOptions::HasExceptionHandling;
1501 FPO |= FrameProcedureOptions::MarkedInline;
1503 FPO |= FrameProcedureOptions::Naked;
1505 FPO |= FrameProcedureOptions::SecurityChecks;
1508 FPO |= FrameProcedureOptions::StrictSecurityChecks;
1512 FPO |= FrameProcedureOptions::SafeBuffers;
1518 FPO |= FrameProcedureOptions::OptimizedForSpeed;
1520 FPO |= FrameProcedureOptions::ValidProfileCounts;
1521 FPO |= FrameProcedureOptions::ProfileGuidedOptimization;
1524 CurFn->FrameProcOpts = FPO;
1533 bool EmptyPrologue =
true;
1534 for (
const auto &
MBB : *MF) {
1535 for (
const auto &
MI :
MBB) {
1540 }
else if (!
MI.isMetaInstruction()) {
1541 EmptyPrologue =
false;
1549 maybeRecordLocation(FnStartDL, MF);
1553 for (
const auto &
MBB : *MF) {
1554 for (
const auto &
MI :
MBB) {
1555 if (
MI.getHeapAllocMarker()) {
1565 discoverJumpTableBranches(MF,
isThumb);
1573 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1574 if (
DIScope *Scope =
T->getScope()) {
1575 switch (Scope->getTag()) {
1576 case dwarf::DW_TAG_structure_type:
1577 case dwarf::DW_TAG_class_type:
1578 case dwarf::DW_TAG_union_type:
1588 if (!
T ||
T->isForwardDecl())
1594 T = DT->getBaseType();
1599void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1608 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1610 std::string FullyQualifiedName =
1613 if (ClosestSubprogram ==
nullptr) {
1614 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1615 }
else if (ClosestSubprogram == CurrentSubprogram) {
1616 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1630 case dwarf::DW_TAG_array_type:
1631 return lowerTypeArray(cast<DICompositeType>(Ty));
1632 case dwarf::DW_TAG_typedef:
1633 return lowerTypeAlias(cast<DIDerivedType>(Ty));
1634 case dwarf::DW_TAG_base_type:
1635 return lowerTypeBasic(cast<DIBasicType>(Ty));
1636 case dwarf::DW_TAG_pointer_type:
1637 if (cast<DIDerivedType>(Ty)->
getName() ==
"__vtbl_ptr_type")
1638 return lowerTypeVFTableShape(cast<DIDerivedType>(Ty));
1640 case dwarf::DW_TAG_reference_type:
1641 case dwarf::DW_TAG_rvalue_reference_type:
1642 return lowerTypePointer(cast<DIDerivedType>(Ty));
1643 case dwarf::DW_TAG_ptr_to_member_type:
1644 return lowerTypeMemberPointer(cast<DIDerivedType>(Ty));
1645 case dwarf::DW_TAG_restrict_type:
1646 case dwarf::DW_TAG_const_type:
1647 case dwarf::DW_TAG_volatile_type:
1649 return lowerTypeModifier(cast<DIDerivedType>(Ty));
1650 case dwarf::DW_TAG_subroutine_type:
1654 return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy,
1658 return lowerTypeFunction(cast<DISubroutineType>(Ty));
1659 case dwarf::DW_TAG_enumeration_type:
1660 return lowerTypeEnum(cast<DICompositeType>(Ty));
1661 case dwarf::DW_TAG_class_type:
1662 case dwarf::DW_TAG_structure_type:
1663 return lowerTypeClass(cast<DICompositeType>(Ty));
1664 case dwarf::DW_TAG_union_type:
1665 return lowerTypeUnion(cast<DICompositeType>(Ty));
1666 case dwarf::DW_TAG_string_type:
1667 return lowerTypeString(cast<DIStringType>(Ty));
1668 case dwarf::DW_TAG_unspecified_type:
1669 if (Ty->
getName() ==
"decltype(nullptr)")
1679 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1684 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::Int32Long) &&
1685 TypeName ==
"HRESULT")
1686 return TypeIndex(SimpleTypeKind::HResult);
1687 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::UInt16Short) &&
1688 TypeName ==
"wchar_t")
1689 return TypeIndex(SimpleTypeKind::WideCharacter);
1691 return UnderlyingTypeIndex;
1696 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1698 TypeIndex IndexType = getPointerSizeInBytes() == 8
1706 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1708 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1717 if (
auto *CI = dyn_cast_if_present<ConstantInt *>(
Subrange->getCount()))
1718 Count = CI->getSExtValue();
1719 else if (
auto *UI = dyn_cast_if_present<ConstantInt *>(
1723 auto *LI = dyn_cast_if_present<ConstantInt *>(
Subrange->getLowerBound());
1724 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1725 Count = UI->getSExtValue() - Lowerbound + 1;
1736 ElementSize *= Count;
1741 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1748 return ElementTypeIndex;
1761 TypeIndex IndexType = getPointerSizeInBytes() == 8
1781 case dwarf::DW_ATE_address:
1784 case dwarf::DW_ATE_boolean:
1786 case 1: STK = SimpleTypeKind::Boolean8;
break;
1787 case 2: STK = SimpleTypeKind::Boolean16;
break;
1788 case 4: STK = SimpleTypeKind::Boolean32;
break;
1789 case 8: STK = SimpleTypeKind::Boolean64;
break;
1790 case 16: STK = SimpleTypeKind::Boolean128;
break;
1793 case dwarf::DW_ATE_complex_float:
1797 case 4: STK = SimpleTypeKind::Complex16;
break;
1798 case 8: STK = SimpleTypeKind::Complex32;
break;
1799 case 16: STK = SimpleTypeKind::Complex64;
break;
1800 case 20: STK = SimpleTypeKind::Complex80;
break;
1801 case 32: STK = SimpleTypeKind::Complex128;
break;
1804 case dwarf::DW_ATE_float:
1806 case 2: STK = SimpleTypeKind::Float16;
break;
1807 case 4: STK = SimpleTypeKind::Float32;
break;
1808 case 6: STK = SimpleTypeKind::Float48;
break;
1809 case 8: STK = SimpleTypeKind::Float64;
break;
1810 case 10: STK = SimpleTypeKind::Float80;
break;
1811 case 16: STK = SimpleTypeKind::Float128;
break;
1814 case dwarf::DW_ATE_signed:
1816 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1817 case 2: STK = SimpleTypeKind::Int16Short;
break;
1818 case 4: STK = SimpleTypeKind::Int32;
break;
1819 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1820 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1823 case dwarf::DW_ATE_unsigned:
1825 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1826 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1827 case 4: STK = SimpleTypeKind::UInt32;
break;
1828 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1829 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1832 case dwarf::DW_ATE_UTF:
1834 case 1: STK = SimpleTypeKind::Character8;
break;
1835 case 2: STK = SimpleTypeKind::Character16;
break;
1836 case 4: STK = SimpleTypeKind::Character32;
break;
1839 case dwarf::DW_ATE_signed_char:
1841 STK = SimpleTypeKind::SignedCharacter;
1843 case dwarf::DW_ATE_unsigned_char:
1845 STK = SimpleTypeKind::UnsignedCharacter;
1855 if (STK == SimpleTypeKind::Int32 &&
1857 STK = SimpleTypeKind::Int32Long;
1858 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1859 Ty->
getName() ==
"unsigned long"))
1860 STK = SimpleTypeKind::UInt32Long;
1861 if (STK == SimpleTypeKind::UInt16Short &&
1863 STK = SimpleTypeKind::WideCharacter;
1864 if ((STK == SimpleTypeKind::SignedCharacter ||
1865 STK == SimpleTypeKind::UnsignedCharacter) &&
1867 STK = SimpleTypeKind::NarrowCharacter;
1874 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1878 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1880 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1882 ? SimpleTypeMode::NearPointer64
1883 : SimpleTypeMode::NearPointer32;
1888 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1892 case dwarf::DW_TAG_pointer_type:
1893 PM = PointerMode::Pointer;
1895 case dwarf::DW_TAG_reference_type:
1896 PM = PointerMode::LValueReference;
1898 case dwarf::DW_TAG_rvalue_reference_type:
1899 PM = PointerMode::RValueReference;
1904 PO |= PointerOptions::Const;
1918 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1919 : PointerToMemberRepresentation::GeneralFunction;
1920 case DINode::FlagSingleInheritance:
1921 return PointerToMemberRepresentation::SingleInheritanceFunction;
1922 case DINode::FlagMultipleInheritance:
1923 return PointerToMemberRepresentation::MultipleInheritanceFunction;
1924 case DINode::FlagVirtualInheritance:
1925 return PointerToMemberRepresentation::VirtualInheritanceFunction;
1930 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1931 : PointerToMemberRepresentation::GeneralData;
1932 case DINode::FlagSingleInheritance:
1933 return PointerToMemberRepresentation::SingleInheritanceData;
1934 case DINode::FlagMultipleInheritance:
1935 return PointerToMemberRepresentation::MultipleInheritanceData;
1936 case DINode::FlagVirtualInheritance:
1937 return PointerToMemberRepresentation::VirtualInheritanceData;
1945 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
1946 bool IsPMF = isa<DISubroutineType>(Ty->getBaseType());
1949 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->
getClassType() :
nullptr);
1950 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
1951 : PointerKind::Near32;
1952 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
1953 : PointerMode::PointerToDataMember;
1967 case dwarf::DW_CC_normal:
return CallingConvention::NearC;
1968 case dwarf::DW_CC_BORLAND_msfastcall:
return CallingConvention::NearFast;
1969 case dwarf::DW_CC_BORLAND_thiscall:
return CallingConvention::ThisCall;
1970 case dwarf::DW_CC_BORLAND_stdcall:
return CallingConvention::NearStdCall;
1971 case dwarf::DW_CC_BORLAND_pascal:
return CallingConvention::NearPascal;
1972 case dwarf::DW_CC_LLVM_vectorcall:
return CallingConvention::NearVector;
1974 return CallingConvention::NearC;
1982 while (IsModifier &&
BaseTy) {
1984 switch (
BaseTy->getTag()) {
1985 case dwarf::DW_TAG_const_type:
1986 Mods |= ModifierOptions::Const;
1987 PO |= PointerOptions::Const;
1989 case dwarf::DW_TAG_volatile_type:
1990 Mods |= ModifierOptions::Volatile;
1991 PO |= PointerOptions::Volatile;
1993 case dwarf::DW_TAG_restrict_type:
1996 PO |= PointerOptions::Restrict;
2011 switch (
BaseTy->getTag()) {
2012 case dwarf::DW_TAG_pointer_type:
2013 case dwarf::DW_TAG_reference_type:
2014 case dwarf::DW_TAG_rvalue_reference_type:
2015 return lowerTypePointer(cast<DIDerivedType>(
BaseTy), PO);
2016 case dwarf::DW_TAG_ptr_to_member_type:
2017 return lowerTypeMemberPointer(cast<DIDerivedType>(
BaseTy), PO);
2027 if (Mods == ModifierOptions::None)
2037 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2040 if (ReturnAndArgTypeIndices.
size() > 1 &&
2046 if (!ReturnAndArgTypeIndices.
empty()) {
2047 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2048 ReturnTypeIndex = ReturnAndArgTypesRef.front();
2049 ArgTypeIndices = ReturnAndArgTypesRef.
drop_front();
2052 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2066 bool IsStaticMethod,
2069 TypeIndex ClassType = getTypeIndex(ClassTy);
2076 if (ReturnAndArgs.
size() > Index) {
2077 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
2084 if (!IsStaticMethod && ReturnAndArgs.
size() > Index) {
2086 dyn_cast_or_null<DIDerivedType>(ReturnAndArgs[Index])) {
2087 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2088 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2094 while (Index < ReturnAndArgs.
size())
2095 ArgTypeIndices.
push_back(getTypeIndex(ReturnAndArgs[Index++]));
2101 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2107 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2112 unsigned VSlotCount =
2122 case DINode::FlagPrivate:
return MemberAccess::Private;
2123 case DINode::FlagPublic:
return MemberAccess::Public;
2124 case DINode::FlagProtected:
return MemberAccess::Protected;
2127 return RecordTag == dwarf::DW_TAG_class_type ? MemberAccess::Private
2128 : MemberAccess::Public;
2134 if (SP->isArtificial())
2135 return MethodOptions::CompilerGenerated;
2139 return MethodOptions::None;
2144 if (SP->getFlags() & DINode::FlagStaticMember)
2145 return MethodKind::Static;
2147 switch (SP->getVirtuality()) {
2148 case dwarf::DW_VIRTUALITY_none:
2150 case dwarf::DW_VIRTUALITY_virtual:
2151 return Introduced ? MethodKind::IntroducingVirtual : MethodKind::Virtual;
2152 case dwarf::DW_VIRTUALITY_pure_virtual:
2153 return Introduced ? MethodKind::PureIntroducingVirtual
2154 : MethodKind::PureVirtual;
2159 return MethodKind::Vanilla;
2164 case dwarf::DW_TAG_class_type:
2165 return TypeRecordKind::Class;
2166 case dwarf::DW_TAG_structure_type:
2167 return TypeRecordKind::Struct;
2182 CO |= ClassOptions::HasUniqueName;
2188 if (ImmediateScope && isa<DICompositeType>(ImmediateScope))
2189 CO |= ClassOptions::Nested;
2195 if (Ty->
getTag() == dwarf::DW_TAG_enumeration_type) {
2196 if (ImmediateScope && isa<DISubprogram>(ImmediateScope))
2197 CO |= ClassOptions::Scoped;
2199 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2200 Scope = Scope->getScope()) {
2201 if (isa<DISubprogram>(Scope)) {
2202 CO |= ClassOptions::Scoped;
2213 case dwarf::DW_TAG_class_type:
2214 case dwarf::DW_TAG_structure_type:
2215 case dwarf::DW_TAG_union_type:
2216 case dwarf::DW_TAG_enumeration_type:
2222 if (
const auto *File = Ty->
getFile()) {
2234 unsigned EnumeratorCount = 0;
2237 CO |= ClassOptions::ForwardReference;
2240 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2244 if (
auto *
Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) {
2256 std::string FullName = getFullyQualifiedName(Ty);
2262 addUDTSrcLine(Ty, EnumTI);
2296void CodeViewDebug::clear() {
2297 assert(CurFn ==
nullptr);
2299 FnDebugInfo.clear();
2300 FileToFilepathMap.clear();
2303 TypeIndices.clear();
2304 CompleteTypeIndices.clear();
2305 ScopeGlobals.clear();
2306 CVGlobalVariableOffsets.clear();
2309void CodeViewDebug::collectMemberInfo(
ClassInfo &Info,
2312 Info.Members.push_back({DDTy, 0});
2315 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2316 DINode::FlagStaticMember) {
2319 StaticConstMembers.push_back(DDTy);
2331 const DIType *Ty = DDTy->getBaseType();
2332 bool FullyResolved =
false;
2333 while (!FullyResolved) {
2335 case dwarf::DW_TAG_const_type:
2336 case dwarf::DW_TAG_volatile_type:
2339 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2342 FullyResolved =
true;
2351 ClassInfo NestedInfo = collectClassInfo(DCTy);
2353 Info.Members.push_back(
2361 for (
auto *Element : Elements) {
2366 if (
auto *SP = dyn_cast<DISubprogram>(Element)) {
2367 Info.Methods[SP->getRawName()].push_back(SP);
2368 }
else if (
auto *DDTy = dyn_cast<DIDerivedType>(Element)) {
2369 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2370 collectMemberInfo(Info, DDTy);
2371 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2372 Info.Inheritance.push_back(DDTy);
2373 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2374 DDTy->
getName() ==
"__vtbl_ptr_type") {
2375 Info.VShapeTI = getTypeIndex(DDTy);
2376 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2377 Info.NestedTypes.push_back(DDTy);
2378 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2382 }
else if (
auto *Composite = dyn_cast<DICompositeType>(Element)) {
2383 Info.NestedTypes.push_back(Composite);
2406 auto I = CompleteTypeIndices.find(Ty);
2407 if (
I != CompleteTypeIndices.end() &&
I->second ==
TypeIndex())
2409 return getCompleteTypeIndex(Ty);
2417 std::string FullName = getFullyQualifiedName(Ty);
2422 DeferredCompleteTypes.push_back(Ty);
2432 unsigned FieldCount;
2435 lowerRecordFieldList(Ty);
2438 CO |= ClassOptions::ContainsNestedClass;
2446 CO |= ClassOptions::HasConstructorOrDestructor;
2448 std::string FullName = getFullyQualifiedName(Ty);
2456 addUDTSrcLine(Ty, ClassTI);
2466 return getCompleteTypeIndex(Ty);
2470 std::string FullName = getFullyQualifiedName(Ty);
2474 DeferredCompleteTypes.push_back(Ty);
2481 unsigned FieldCount;
2484 lowerRecordFieldList(Ty);
2487 CO |= ClassOptions::ContainsNestedClass;
2490 std::string FullName = getFullyQualifiedName(Ty);
2492 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2496 addUDTSrcLine(Ty, UnionTI);
2503std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2509 unsigned MemberCount = 0;
2512 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2516 if (
I->getFlags() & DINode::FlagVirtual) {
2518 unsigned VBPtrOffset =
I->getVBPtrOffset();
2520 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2521 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2522 ? TypeRecordKind::IndirectVirtualBaseClass
2523 : TypeRecordKind::VirtualBaseClass;
2526 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2532 assert(
I->getOffsetInBits() % 8 == 0 &&
2533 "bases must be on byte boundaries");
2535 getTypeIndex(
I->getBaseType()),
2536 I->getOffsetInBits() / 8);
2550 if (
Member->isStaticMember()) {
2558 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2559 Member->getName().starts_with(
"_vptr$")) {
2569 if (
Member->isBitField()) {
2570 uint64_t StartBitOffset = MemberOffsetInBits;
2571 if (
const auto *CI =
2572 dyn_cast_or_null<ConstantInt>(
Member->getStorageOffsetInBits())) {
2573 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2575 StartBitOffset -= MemberOffsetInBits;
2580 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2588 for (
auto &MethodItr :
Info.Methods) {
2591 std::vector<OneMethodRecord> Methods;
2593 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2594 bool Introduced = SP->getFlags() & DINode::FlagIntroducedVirtual;
2596 unsigned VFTableOffset = -1;
2598 VFTableOffset = SP->getVirtualIndex() * getPointerSizeInBytes();
2606 assert(!Methods.empty() &&
"Empty methods map entry");
2607 if (Methods.size() == 1)
2628 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2629 !
Info.NestedTypes.empty());
2632TypeIndex CodeViewDebug::getVBPTypeIndex() {
2638 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2639 : PointerKind::Near32;
2642 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2657 auto I = TypeIndices.find({Ty, ClassTy});
2658 if (
I != TypeIndices.end())
2661 TypeLoweringScope S(*
this);
2663 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2667CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2669 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2670 "this type must be a pointer type");
2673 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2674 Options = PointerOptions::LValueRefThisPointer;
2675 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2676 Options = PointerOptions::RValueRefThisPointer;
2683 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2684 if (
I != TypeIndices.end())
2687 TypeLoweringScope S(*
this);
2689 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2692TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(
const DIType *Ty) {
2694 getPointerSizeInBytes() == 8 ? PointerKind::Near64
2695 : PointerKind::Near32,
2696 PointerMode::LValueReference, PointerOptions::None,
2709 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2710 (void)getTypeIndex(Ty);
2711 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2712 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2717 case dwarf::DW_TAG_class_type:
2718 case dwarf::DW_TAG_structure_type:
2719 case dwarf::DW_TAG_union_type:
2722 return getTypeIndex(Ty);
2725 const auto *CTy = cast<DICompositeType>(Ty);
2727 TypeLoweringScope S(*
this);
2733 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2734 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2739 if (CTy->isForwardDecl())
2746 auto InsertResult = CompleteTypeIndices.insert({CTy,
TypeIndex()});
2747 if (!InsertResult.second)
2748 return InsertResult.first->second;
2751 switch (CTy->getTag()) {
2752 case dwarf::DW_TAG_class_type:
2753 case dwarf::DW_TAG_structure_type:
2754 TI = lowerCompleteTypeClass(CTy);
2756 case dwarf::DW_TAG_union_type:
2757 TI = lowerCompleteTypeUnion(CTy);
2767 CompleteTypeIndices[CTy] = TI;
2775void CodeViewDebug::emitDeferredCompleteTypes() {
2777 while (!DeferredCompleteTypes.empty()) {
2778 std::swap(DeferredCompleteTypes, TypesToEmit);
2780 getCompleteTypeIndex(RecordTy);
2781 TypesToEmit.clear();
2785void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2789 for (
const LocalVariable &L : Locals)
2790 if (
L.DIVar->isParameter())
2792 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2793 return L->DIVar->getArg() <
R->DIVar->getArg();
2795 for (
const LocalVariable *L : Params)
2796 emitLocalVariable(FI, *L);
2799 for (
const LocalVariable &L : Locals) {
2800 if (!
L.DIVar->isParameter()) {
2801 if (
L.ConstantValue) {
2804 const DIType *Ty =
L.DIVar->getType();
2806 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2808 emitLocalVariable(FI, L);
2814void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2815 const LocalVariable &Var) {
2817 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2820 if (Var.DIVar->isParameter())
2821 Flags |= LocalSymFlags::IsParameter;
2822 if (Var.DefRanges.empty())
2823 Flags |= LocalSymFlags::IsOptimizedOut;
2827 ? getTypeIndexForReferenceTo(Var.DIVar->getType())
2828 : getCompleteTypeIndex(Var.DIVar->
getType());
2834 endSymbolRecord(LocalEnd);
2840 for (
const auto &Pair : Var.DefRanges) {
2841 LocalVarDef DefRange = Pair.first;
2842 const auto &
Ranges = Pair.second;
2844 if (DefRange.InMemory) {
2845 int Offset = DefRange.DataOffset;
2846 unsigned Reg = DefRange.CVRegister;
2853 Offset += FI.OffsetAdjustment;
2860 if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2861 (
bool(Flags & LocalSymFlags::IsParameter)
2862 ? (EncFP == FI.EncodedParamFramePtrReg)
2863 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2869 if (DefRange.IsSubfield) {
2871 (DefRange.StructOffset
2876 DRHdr.
Flags = RegRelFlags;
2881 assert(DefRange.DataOffset == 0 &&
"unexpected offset into register");
2882 if (DefRange.IsSubfield) {
2884 DRHdr.
Register = DefRange.CVRegister;
2890 DRHdr.
Register = DefRange.CVRegister;
2899 const FunctionInfo& FI) {
2901 emitLexicalBlock(*
Block, FI);
2906void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2907 const FunctionInfo& FI) {
2908 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2915 OS.
AddComment(
"Function section relative address");
2921 endSymbolRecord(RecordEnd);
2924 emitLocalVariableList(FI,
Block.Locals);
2925 emitGlobalVariableList(
Block.Globals);
2928 emitLexicalBlockList(
Block.Children, FI);
2931 emitEndSymbolRecord(SymbolKind::S_END);
2936void CodeViewDebug::collectLexicalBlockInfo(
2942 collectLexicalBlockInfo(*Scope,
Blocks, Locals, Globals);
2947void CodeViewDebug::collectLexicalBlockInfo(
2952 if (
Scope.isAbstractScope())
2957 bool IgnoreScope =
false;
2958 auto LI = ScopeVariables.find(&Scope);
2960 LI != ScopeVariables.end() ? &LI->second :
nullptr;
2961 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
2963 GI != ScopeGlobals.end() ? GI->second.get() :
nullptr;
2968 if (!Locals && !Globals)
2998 collectLexicalBlockInfo(
Scope.getChildren(),
3008 auto BlockInsertion = CurFn->LexicalBlocks.insert({DILB, LexicalBlock()});
3009 if (!BlockInsertion.second)
3016 LexicalBlock &
Block = BlockInsertion.first->second;
3019 assert(
Block.Begin &&
"missing label for scope begin");
3020 assert(
Block.End &&
"missing label for scope end");
3023 Block.Locals = std::move(*Locals);
3025 Block.Globals = std::move(*Globals);
3027 collectLexicalBlockInfo(
Scope.getChildren(),
3035 assert(FnDebugInfo.count(&GV));
3036 assert(CurFn == FnDebugInfo[&GV].
get());
3042 collectLexicalBlockInfo(*CFS,
3050 ScopeVariables.clear();
3054 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3055 FnDebugInfo.erase(&GV);
3061 for (
const auto &
MBB : *MF) {
3062 for (
const auto &
MI :
MBB) {
3063 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3066 dyn_cast<DIType>(MD)));
3073 collectDebugInfoForJumpTables(MF,
isThumb);
3087 return DL &&
DL.getLine() != 0;
3094 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3102 for (
const auto &NextMI : *
MI->getParent()) {
3103 if (NextMI.isDebugInstr())
3105 DL = NextMI.getDebugLoc();
3118 maybeRecordLocation(
DL,
Asm->
MF);
3131void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3139 if (EE.Value == SymKind)
3156void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3165void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3173void CodeViewDebug::emitDebugInfoForUDTs(
3174 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3176 size_t OriginalSize = UDTs.size();
3178 for (
const auto &UDT : UDTs) {
3181 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3183 OS.
emitInt32(getCompleteTypeIndex(
T).getIndex());
3184 assert(OriginalSize == UDTs.size() &&
3185 "getCompleteTypeIndex found new UDTs!");
3187 endSymbolRecord(UDTRecordEnd);
3191void CodeViewDebug::collectGlobalVariableInfo() {
3196 GV.getDebugInfo(GVEs);
3197 for (
const auto *GVE : GVEs)
3198 GlobalMap[GVE] = &GV;
3203 const auto *
CU = cast<DICompileUnit>(
Node);
3204 for (
const auto *GVE :
CU->getGlobalVariables()) {
3213 if ((
DIE->getNumElements() == 2) &&
3214 (
DIE->getElement(0) == dwarf::DW_OP_plus_uconst))
3219 CVGlobalVariableOffsets.insert(
3220 std::make_pair(DIGV,
DIE->getElement(1)));
3223 if (GlobalMap.
count(GVE) == 0 &&
DIE->isConstant()) {
3224 CVGlobalVariable CVGV = {DIGV,
DIE};
3228 const auto *GV = GlobalMap.
lookup(GVE);
3234 if (Scope && isa<DILocalScope>(Scope)) {
3237 auto Insertion = ScopeGlobals.insert(
3238 {
Scope, std::unique_ptr<GlobalVariableList>()});
3239 if (Insertion.second)
3240 Insertion.first->second = std::make_unique<GlobalVariableList>();
3241 VariableList = Insertion.first->second.get();
3244 VariableList = &ComdatVariables;
3247 VariableList = &GlobalVariables;
3248 CVGlobalVariable CVGV = {DIGV, GV};
3254void CodeViewDebug::collectDebugInfoForGlobals() {
3255 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3258 getCompleteTypeIndex(DIGV->
getType());
3259 getFullyQualifiedName(Scope, DIGV->
getName());
3262 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3265 getCompleteTypeIndex(DIGV->
getType());
3266 getFullyQualifiedName(Scope, DIGV->
getName());
3270void CodeViewDebug::emitDebugInfoForGlobals() {
3274 switchToDebugSectionForSymbol(
nullptr);
3275 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3276 OS.
AddComment(
"Symbol subsection for globals");
3277 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3278 emitGlobalVariableList(GlobalVariables);
3279 emitStaticConstMemberList();
3280 endCVSubsection(EndLabel);
3285 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3286 const GlobalVariable *GV = cast<const GlobalVariable *>(CVGV.GVInfo);
3290 switchToDebugSectionForSymbol(GVSym);
3291 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3293 emitDebugInfoForGlobal(CVGV);
3294 endCVSubsection(EndLabel);
3298void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3301 for (
auto *Ty : cast<DICompileUnit>(
Node)->getRetainedTypes()) {
3302 if (
DIType *RT = dyn_cast<DIType>(Ty)) {
3312 for (
const CVGlobalVariable &CVGV : Globals) {
3314 emitDebugInfoForGlobal(CVGV);
3320 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3322 OS.
emitInt32(getTypeIndex(DTy).getIndex());
3336 endSymbolRecord(SConstantEnd);
3339void CodeViewDebug::emitStaticConstMemberList() {
3345 dyn_cast_or_null<ConstantInt>(DTy->getConstant()))
3349 dyn_cast_or_null<ConstantFP>(DTy->getConstant()))
3350 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3354 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3355 getFullyQualifiedName(Scope, DTy->
getName()));
3360 if (isa<DICompositeType>(Ty))
3363 if (
auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
3365 if (
T == dwarf::DW_TAG_pointer_type ||
3366 T == dwarf::DW_TAG_ptr_to_member_type ||
3367 T == dwarf::DW_TAG_reference_type ||
3368 T == dwarf::DW_TAG_rvalue_reference_type)
3370 assert(DTy->getBaseType() &&
"Expected valid base type");
3374 auto *BTy = cast<DIBasicType>(Ty);
3375 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3378void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3383 if (
const auto *MemberDecl = dyn_cast_or_null<DIDerivedType>(
3385 Scope = MemberDecl->getScope();
3391 ? std::string(DIGV->
getName())
3395 dyn_cast_if_present<const GlobalVariable *>(CVGV.GVInfo)) {
3401 : SymbolKind::S_GTHREAD32)
3403 : SymbolKind::S_GDATA32);
3416 const unsigned LengthOfDataRecord = 12;
3418 endSymbolRecord(DataEnd);
3422 "Global constant variables must contain a constant expression.");
3436 int64_t)> &Callback) {
3438 if (JTI && !JTI->isEmpty()) {
3442 for (
const auto &
MBB : *MF) {
3445 if (LastMI !=
MBB.
end() && LastMI->isIndirectBranch()) {
3453 for (
const auto &MO : LastMI->operands()) {
3455 unsigned Index = MO.getIndex();
3459 Callback(*JTI, *LastMI, Index);
3468 if (
I->isJumpTableDebugInfo()) {
3469 unsigned Index =
I->getOperand(0).getImm();
3473 Callback(*JTI, *LastMI, Index);
3482 "Some of jump tables were not used in a debug info instruction");
3487void CodeViewDebug::discoverJumpTableBranches(
const MachineFunction *MF,
3495void CodeViewDebug::collectDebugInfoForJumpTables(
const MachineFunction *MF,
3500 int64_t JumpTableIndex) {
3513 "EK_Custom32, EK_GPRel32BlockAddress, and "
3514 "EK_GPRel64BlockAddress should never be emitted for COFF");
3517 EntrySize = JumpTableEntrySize::Pointer;
3524 std::tie(
Base, BaseOffset, Branch, EntrySize) =
3529 CurFn->JumpTables.push_back(
3536void CodeViewDebug::emitDebugInfoForJumpTables(
const FunctionInfo &FI) {
3537 for (
auto JumpTable : FI.JumpTables) {
3538 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3562 endSymbolRecord(JumpTableEnd);
3566void CodeViewDebug::emitInlinees(
3570 constexpr size_t ChunkSize =
3577 size_t CurrentIndex = 0;
3578 while (CurrentIndex < SortedInlinees.size()) {
3579 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3580 auto CurrentChunkSize =
3581 std::min(ChunkSize, SortedInlinees.size() - CurrentIndex);
3585 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3586 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3588 OS.
emitInt32(SortedInlinees[CurrentIndex].getIndex());
3590 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.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
const MachineBasicBlock * PrevInstBB
void requestLabelAfterInsn(const MachineInstr *MI)
Ensure that a label will be emitted after MI.
DbgValueHistoryMap DbgValues
History of DBG_VALUE and clobber instructions for each user variable.
void requestLabelBeforeInsn(const MachineInstr *MI)
Ensure that a label will be emitted before MI.
const MachineInstr * PrologEndLoc
This location indicates end of function prologue and beginning of function body.
static uint64_t getBaseTypeSize(const DIType *Ty)
If this type is derived from a base type then return base type size.
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.