33#include "llvm/Config/llvm-config.h"
83 :
OS(&
OS), TypeTable(TypeTable) {}
105 TypeName = std::string(TypeTable.getTypeName(TI));
118 case Triple::ArchType::x86:
119 return CPUType::Pentium3;
120 case Triple::ArchType::x86_64:
122 case Triple::ArchType::thumb:
125 return CPUType::ARMNT;
126 case Triple::ArchType::aarch64:
127 return CPUType::ARM64;
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);
898 std::string FlatCmdLine;
900 bool PrintedOneArg =
false;
903 PrintedOneArg =
true;
905 for (
unsigned i = 0; i < Args.size(); i++) {
909 if (Arg ==
"-main-file-name" || Arg ==
"-o") {
913 if (Arg.
starts_with(
"-object-file-name") || Arg == MainFilename)
921 PrintedOneArg =
true;
927void CodeViewDebug::emitBuildInfo() {
941 const auto *
CU = cast<DICompileUnit>(
Node);
942 const DIFile *MainSourceFile =
CU->getFile();
962 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
963 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
966 endSymbolRecord(BIEnd);
967 endCVSubsection(BISubsecEnd);
970void CodeViewDebug::emitInlineeLinesSubsection() {
971 if (InlinedSubprograms.empty())
975 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
982 OS.
emitInt32(
unsigned(InlineeLinesSignature::Normal));
985 assert(TypeIndices.count({SP, nullptr}));
986 TypeIndex InlineeIdx = TypeIndices[{SP,
nullptr}];
989 unsigned FileId = maybeRecordFile(SP->
getFile());
993 OS.
AddComment(
"Type index of inlined function");
995 OS.
AddComment(
"Offset into filechecksum table");
1001 endCVSubsection(InlineEnd);
1004void CodeViewDebug::emitInlinedCallSite(
const FunctionInfo &FI,
1007 assert(TypeIndices.count({Site.Inlinee, nullptr}));
1008 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee,
nullptr}];
1011 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
1020 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
1021 unsigned StartLineNum = Site.Inlinee->getLine();
1026 endSymbolRecord(InlineEnd);
1028 emitLocalVariableList(FI, Site.InlinedLocals);
1031 for (
const DILocation *ChildSite : Site.ChildSites) {
1032 auto I = FI.InlineSites.find(ChildSite);
1033 assert(
I != FI.InlineSites.end() &&
1034 "child site not in function inline site map");
1035 emitInlinedCallSite(FI, ChildSite,
I->second);
1039 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1042void CodeViewDebug::switchToDebugSectionForSymbol(
const MCSymbol *GVSym) {
1047 GVSym ? dyn_cast<MCSectionCOFF>(&GVSym->
getSection()) : nullptr;
1058 if (ComdatDebugSections.insert(DebugSec).second)
1059 emitCodeViewMagicVersion();
1064void CodeViewDebug::emitDebugInfoForThunk(
const Function *GV,
1067 std::string FuncName =
1072 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1075 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1082 OS.
AddComment(
"Thunk section relative address");
1093 endSymbolRecord(ThunkRecordEnd);
1099 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1101 endCVSubsection(SymbolsEnd);
1104void CodeViewDebug::emitDebugInfoForFunction(
const Function *GV,
1112 switchToDebugSectionForSymbol(Fn);
1114 std::string FuncName;
1117 setCurrentSubprogram(SP);
1119 if (SP->isThunk()) {
1120 emitDebugInfoForThunk(GV, FI, Fn);
1130 if (FuncName.empty())
1139 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1142 : SymbolKind::S_GPROC32_ID;
1143 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1162 OS.
AddComment(
"Function section relative address");
1167 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;
1168 if (FI.HasFramePointer)
1169 ProcFlags |= ProcSymFlags::HasFP;
1171 ProcFlags |= ProcSymFlags::IsNoReturn;
1173 ProcFlags |= ProcSymFlags::IsNoInline;
1174 OS.
emitInt8(
static_cast<uint8_t
>(ProcFlags));
1179 endSymbolRecord(ProcRecordEnd);
1181 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1184 OS.
emitInt32(FI.FrameSize - FI.CSRSize);
1189 OS.
AddComment(
"Bytes of callee saved registers");
1195 OS.
AddComment(
"Flags (defines frame register)");
1197 endSymbolRecord(FrameProcEnd);
1199 emitInlinees(FI.Inlinees);
1200 emitLocalVariableList(FI, FI.Locals);
1201 emitGlobalVariableList(FI.Globals);
1202 emitLexicalBlockList(FI.ChildBlocks, FI);
1207 for (
const DILocation *InlinedAt : FI.ChildSites) {
1208 auto I = FI.InlineSites.find(InlinedAt);
1209 assert(
I != FI.InlineSites.end() &&
1210 "child site not in function inline site map");
1211 emitInlinedCallSite(FI, InlinedAt,
I->second);
1214 for (
auto Annot : FI.Annotations) {
1216 MDTuple *Strs = cast<MDTuple>(Annot.second);
1217 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1225 StringRef Str = cast<MDString>(MD)->getString();
1226 assert(Str.data()[Str.size()] ==
'\0' &&
"non-nullterminated MDString");
1229 endSymbolRecord(AnnotEnd);
1232 for (
auto HeapAllocSite : FI.HeapAllocSites) {
1233 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1234 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1235 const DIType *DITy = std::get<2>(HeapAllocSite);
1236 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1244 OS.
emitInt32(getCompleteTypeIndex(DITy).getIndex());
1245 endSymbolRecord(HeapAllocEnd);
1249 emitDebugInfoForUDTs(LocalUDTs);
1251 emitDebugInfoForJumpTables(FI);
1254 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1256 endCVSubsection(SymbolsEnd);
1263CodeViewDebug::createDefRangeMem(
uint16_t CVRegister,
int Offset) {
1269 DR.StructOffset = 0;
1270 DR.CVRegister = CVRegister;
1274void CodeViewDebug::collectVariableInfoFromMFTable(
1285 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1286 "Expected inlined-at fields to agree");
1288 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1297 int64_t ExprOffset = 0;
1301 if (
VI.Expr->getNumElements() == 1 &&
1302 VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)
1304 else if (!
VI.Expr->extractIfOffset(ExprOffset))
1312 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1315 "Frame offsets with a scalable component are not supported");
1318 LocalVarDef DefRange =
1319 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset);
1328 Var.DefRanges[DefRange].emplace_back(Begin,
End);
1332 Var.UseReferenceType =
true;
1334 recordLocalVariable(std::move(Var), Scope);
1346void CodeViewDebug::calculateRanges(
1351 for (
auto I = Entries.begin(), E = Entries.end();
I != E; ++
I) {
1353 if (!
Entry.isDbgValue())
1359 std::optional<DbgVariableLocation>
Location =
1381 if (Var.UseReferenceType) {
1390 Var.UseReferenceType =
true;
1391 Var.DefRanges.clear();
1392 calculateRanges(Var, Entries);
1403 if (
Location->FragmentInfo->OffsetInBits % 8)
1407 DR.CVRegister =
TRI->getCodeViewRegNum(
Location->Register);
1408 DR.InMemory = !
Location->LoadChain.empty();
1412 DR.IsSubfield =
true;
1413 DR.StructOffset =
Location->FragmentInfo->OffsetInBits / 8;
1415 DR.IsSubfield =
false;
1416 DR.StructOffset = 0;
1423 auto &EndingEntry = Entries[
Entry.getEndIndex()];
1424 End = EndingEntry.isDbgValue()
1434 if (!
R.empty() &&
R.back().second == Begin)
1435 R.back().second =
End;
1437 R.emplace_back(Begin,
End);
1443void CodeViewDebug::collectVariableInfo(
const DISubprogram *SP) {
1446 collectVariableInfoFromMFTable(Processed);
1449 InlinedEntity
IV =
I.first;
1456 const auto &Entries =
I.second;
1470 calculateRanges(Var, Entries);
1471 recordLocalVariable(std::move(Var), Scope);
1480 auto Insertion = FnDebugInfo.insert({&GV, std::make_unique<FunctionInfo>()});
1481 assert(Insertion.second &&
"function already has info");
1482 CurFn = Insertion.first->second.get();
1483 CurFn->FuncId = NextFuncId++;
1492 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1496 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::None;
1497 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::None;
1498 if (CurFn->FrameSize > 0) {
1500 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1501 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr;
1503 CurFn->HasFramePointer =
true;
1505 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr;
1506 if (CurFn->HasStackRealignment) {
1508 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1512 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::FramePtr;
1520 FPO |= FrameProcedureOptions::HasAlloca;
1522 FPO |= FrameProcedureOptions::HasSetJmp;
1525 FPO |= FrameProcedureOptions::HasInlineAssembly;
1529 FPO |= FrameProcedureOptions::HasStructuredExceptionHandling;
1531 FPO |= FrameProcedureOptions::HasExceptionHandling;
1534 FPO |= FrameProcedureOptions::MarkedInline;
1536 FPO |= FrameProcedureOptions::Naked;
1538 FPO |= FrameProcedureOptions::SecurityChecks;
1541 FPO |= FrameProcedureOptions::StrictSecurityChecks;
1545 FPO |= FrameProcedureOptions::SafeBuffers;
1551 FPO |= FrameProcedureOptions::OptimizedForSpeed;
1553 FPO |= FrameProcedureOptions::ValidProfileCounts;
1554 FPO |= FrameProcedureOptions::ProfileGuidedOptimization;
1557 CurFn->FrameProcOpts = FPO;
1566 bool EmptyPrologue =
true;
1567 for (
const auto &
MBB : *MF) {
1568 for (
const auto &
MI :
MBB) {
1573 }
else if (!
MI.isMetaInstruction()) {
1574 EmptyPrologue =
false;
1582 maybeRecordLocation(FnStartDL, MF);
1586 for (
const auto &
MBB : *MF) {
1587 for (
const auto &
MI :
MBB) {
1588 if (
MI.getHeapAllocMarker()) {
1598 discoverJumpTableBranches(MF,
isThumb);
1606 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1607 if (
DIScope *Scope =
T->getScope()) {
1608 switch (Scope->getTag()) {
1609 case dwarf::DW_TAG_structure_type:
1610 case dwarf::DW_TAG_class_type:
1611 case dwarf::DW_TAG_union_type:
1621 if (!
T ||
T->isForwardDecl())
1627 T = DT->getBaseType();
1632void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1641 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1643 std::string FullyQualifiedName =
1646 if (ClosestSubprogram ==
nullptr) {
1647 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1648 }
else if (ClosestSubprogram == CurrentSubprogram) {
1649 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1663 case dwarf::DW_TAG_array_type:
1664 return lowerTypeArray(cast<DICompositeType>(Ty));
1665 case dwarf::DW_TAG_typedef:
1666 return lowerTypeAlias(cast<DIDerivedType>(Ty));
1667 case dwarf::DW_TAG_base_type:
1668 return lowerTypeBasic(cast<DIBasicType>(Ty));
1669 case dwarf::DW_TAG_pointer_type:
1670 if (cast<DIDerivedType>(Ty)->
getName() ==
"__vtbl_ptr_type")
1671 return lowerTypeVFTableShape(cast<DIDerivedType>(Ty));
1673 case dwarf::DW_TAG_reference_type:
1674 case dwarf::DW_TAG_rvalue_reference_type:
1675 return lowerTypePointer(cast<DIDerivedType>(Ty));
1676 case dwarf::DW_TAG_ptr_to_member_type:
1677 return lowerTypeMemberPointer(cast<DIDerivedType>(Ty));
1678 case dwarf::DW_TAG_restrict_type:
1679 case dwarf::DW_TAG_const_type:
1680 case dwarf::DW_TAG_volatile_type:
1682 return lowerTypeModifier(cast<DIDerivedType>(Ty));
1683 case dwarf::DW_TAG_subroutine_type:
1687 return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy,
1691 return lowerTypeFunction(cast<DISubroutineType>(Ty));
1692 case dwarf::DW_TAG_enumeration_type:
1693 return lowerTypeEnum(cast<DICompositeType>(Ty));
1694 case dwarf::DW_TAG_class_type:
1695 case dwarf::DW_TAG_structure_type:
1696 return lowerTypeClass(cast<DICompositeType>(Ty));
1697 case dwarf::DW_TAG_union_type:
1698 return lowerTypeUnion(cast<DICompositeType>(Ty));
1699 case dwarf::DW_TAG_string_type:
1700 return lowerTypeString(cast<DIStringType>(Ty));
1701 case dwarf::DW_TAG_unspecified_type:
1702 if (Ty->
getName() ==
"decltype(nullptr)")
1712 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1717 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::Int32Long) &&
1718 TypeName ==
"HRESULT")
1719 return TypeIndex(SimpleTypeKind::HResult);
1720 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::UInt16Short) &&
1721 TypeName ==
"wchar_t")
1722 return TypeIndex(SimpleTypeKind::WideCharacter);
1724 return UnderlyingTypeIndex;
1729 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1731 TypeIndex IndexType = getPointerSizeInBytes() == 8
1739 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1741 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1750 if (
auto *CI = dyn_cast_if_present<ConstantInt *>(
Subrange->getCount()))
1751 Count = CI->getSExtValue();
1752 else if (
auto *UI = dyn_cast_if_present<ConstantInt *>(
1756 auto *LI = dyn_cast_if_present<ConstantInt *>(
Subrange->getLowerBound());
1757 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1758 Count = UI->getSExtValue() - Lowerbound + 1;
1769 ElementSize *= Count;
1774 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1781 return ElementTypeIndex;
1794 TypeIndex IndexType = getPointerSizeInBytes() == 8
1814 case dwarf::DW_ATE_address:
1817 case dwarf::DW_ATE_boolean:
1819 case 1: STK = SimpleTypeKind::Boolean8;
break;
1820 case 2: STK = SimpleTypeKind::Boolean16;
break;
1821 case 4: STK = SimpleTypeKind::Boolean32;
break;
1822 case 8: STK = SimpleTypeKind::Boolean64;
break;
1823 case 16: STK = SimpleTypeKind::Boolean128;
break;
1826 case dwarf::DW_ATE_complex_float:
1830 case 4: STK = SimpleTypeKind::Complex16;
break;
1831 case 8: STK = SimpleTypeKind::Complex32;
break;
1832 case 16: STK = SimpleTypeKind::Complex64;
break;
1833 case 20: STK = SimpleTypeKind::Complex80;
break;
1834 case 32: STK = SimpleTypeKind::Complex128;
break;
1837 case dwarf::DW_ATE_float:
1839 case 2: STK = SimpleTypeKind::Float16;
break;
1840 case 4: STK = SimpleTypeKind::Float32;
break;
1841 case 6: STK = SimpleTypeKind::Float48;
break;
1842 case 8: STK = SimpleTypeKind::Float64;
break;
1843 case 10: STK = SimpleTypeKind::Float80;
break;
1844 case 16: STK = SimpleTypeKind::Float128;
break;
1847 case dwarf::DW_ATE_signed:
1849 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1850 case 2: STK = SimpleTypeKind::Int16Short;
break;
1851 case 4: STK = SimpleTypeKind::Int32;
break;
1852 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1853 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1856 case dwarf::DW_ATE_unsigned:
1858 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1859 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1860 case 4: STK = SimpleTypeKind::UInt32;
break;
1861 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1862 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1865 case dwarf::DW_ATE_UTF:
1867 case 1: STK = SimpleTypeKind::Character8;
break;
1868 case 2: STK = SimpleTypeKind::Character16;
break;
1869 case 4: STK = SimpleTypeKind::Character32;
break;
1872 case dwarf::DW_ATE_signed_char:
1874 STK = SimpleTypeKind::SignedCharacter;
1876 case dwarf::DW_ATE_unsigned_char:
1878 STK = SimpleTypeKind::UnsignedCharacter;
1888 if (STK == SimpleTypeKind::Int32 &&
1890 STK = SimpleTypeKind::Int32Long;
1891 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1892 Ty->
getName() ==
"unsigned long"))
1893 STK = SimpleTypeKind::UInt32Long;
1894 if (STK == SimpleTypeKind::UInt16Short &&
1896 STK = SimpleTypeKind::WideCharacter;
1897 if ((STK == SimpleTypeKind::SignedCharacter ||
1898 STK == SimpleTypeKind::UnsignedCharacter) &&
1900 STK = SimpleTypeKind::NarrowCharacter;
1907 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1911 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1913 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1915 ? SimpleTypeMode::NearPointer64
1916 : SimpleTypeMode::NearPointer32;
1921 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1925 case dwarf::DW_TAG_pointer_type:
1926 PM = PointerMode::Pointer;
1928 case dwarf::DW_TAG_reference_type:
1929 PM = PointerMode::LValueReference;
1931 case dwarf::DW_TAG_rvalue_reference_type:
1932 PM = PointerMode::RValueReference;
1937 PO |= PointerOptions::Const;
1951 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1952 : PointerToMemberRepresentation::GeneralFunction;
1953 case DINode::FlagSingleInheritance:
1954 return PointerToMemberRepresentation::SingleInheritanceFunction;
1955 case DINode::FlagMultipleInheritance:
1956 return PointerToMemberRepresentation::MultipleInheritanceFunction;
1957 case DINode::FlagVirtualInheritance:
1958 return PointerToMemberRepresentation::VirtualInheritanceFunction;
1963 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1964 : PointerToMemberRepresentation::GeneralData;
1965 case DINode::FlagSingleInheritance:
1966 return PointerToMemberRepresentation::SingleInheritanceData;
1967 case DINode::FlagMultipleInheritance:
1968 return PointerToMemberRepresentation::MultipleInheritanceData;
1969 case DINode::FlagVirtualInheritance:
1970 return PointerToMemberRepresentation::VirtualInheritanceData;
1978 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
1979 bool IsPMF = isa<DISubroutineType>(Ty->getBaseType());
1982 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->
getClassType() :
nullptr);
1983 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
1984 : PointerKind::Near32;
1985 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
1986 : PointerMode::PointerToDataMember;
2000 case dwarf::DW_CC_normal:
return CallingConvention::NearC;
2001 case dwarf::DW_CC_BORLAND_msfastcall:
return CallingConvention::NearFast;
2002 case dwarf::DW_CC_BORLAND_thiscall:
return CallingConvention::ThisCall;
2003 case dwarf::DW_CC_BORLAND_stdcall:
return CallingConvention::NearStdCall;
2004 case dwarf::DW_CC_BORLAND_pascal:
return CallingConvention::NearPascal;
2005 case dwarf::DW_CC_LLVM_vectorcall:
return CallingConvention::NearVector;
2007 return CallingConvention::NearC;
2015 while (IsModifier &&
BaseTy) {
2017 switch (
BaseTy->getTag()) {
2018 case dwarf::DW_TAG_const_type:
2019 Mods |= ModifierOptions::Const;
2020 PO |= PointerOptions::Const;
2022 case dwarf::DW_TAG_volatile_type:
2023 Mods |= ModifierOptions::Volatile;
2024 PO |= PointerOptions::Volatile;
2026 case dwarf::DW_TAG_restrict_type:
2029 PO |= PointerOptions::Restrict;
2044 switch (
BaseTy->getTag()) {
2045 case dwarf::DW_TAG_pointer_type:
2046 case dwarf::DW_TAG_reference_type:
2047 case dwarf::DW_TAG_rvalue_reference_type:
2048 return lowerTypePointer(cast<DIDerivedType>(
BaseTy), PO);
2049 case dwarf::DW_TAG_ptr_to_member_type:
2050 return lowerTypeMemberPointer(cast<DIDerivedType>(
BaseTy), PO);
2060 if (Mods == ModifierOptions::None)
2070 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2073 if (ReturnAndArgTypeIndices.
size() > 1 &&
2079 if (!ReturnAndArgTypeIndices.
empty()) {
2080 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2081 ReturnTypeIndex = ReturnAndArgTypesRef.front();
2082 ArgTypeIndices = ReturnAndArgTypesRef.
drop_front();
2085 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2099 bool IsStaticMethod,
2102 TypeIndex ClassType = getTypeIndex(ClassTy);
2110 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[
Index++]);
2117 if (!IsStaticMethod && ReturnAndArgs.
size() >
Index) {
2119 dyn_cast_or_null<DIDerivedType>(ReturnAndArgs[
Index])) {
2120 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2121 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2134 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2140 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2145 unsigned VSlotCount =
2155 case DINode::FlagPrivate:
return MemberAccess::Private;
2156 case DINode::FlagPublic:
return MemberAccess::Public;
2157 case DINode::FlagProtected:
return MemberAccess::Protected;
2160 return RecordTag == dwarf::DW_TAG_class_type ? MemberAccess::Private
2161 : MemberAccess::Public;
2167 if (SP->isArtificial())
2168 return MethodOptions::CompilerGenerated;
2172 return MethodOptions::None;
2177 if (SP->getFlags() & DINode::FlagStaticMember)
2178 return MethodKind::Static;
2180 switch (SP->getVirtuality()) {
2181 case dwarf::DW_VIRTUALITY_none:
2183 case dwarf::DW_VIRTUALITY_virtual:
2184 return Introduced ? MethodKind::IntroducingVirtual : MethodKind::Virtual;
2185 case dwarf::DW_VIRTUALITY_pure_virtual:
2186 return Introduced ? MethodKind::PureIntroducingVirtual
2187 : MethodKind::PureVirtual;
2192 return MethodKind::Vanilla;
2197 case dwarf::DW_TAG_class_type:
2198 return TypeRecordKind::Class;
2199 case dwarf::DW_TAG_structure_type:
2200 return TypeRecordKind::Struct;
2215 CO |= ClassOptions::HasUniqueName;
2221 if (ImmediateScope && isa<DICompositeType>(ImmediateScope))
2222 CO |= ClassOptions::Nested;
2228 if (Ty->
getTag() == dwarf::DW_TAG_enumeration_type) {
2229 if (ImmediateScope && isa<DISubprogram>(ImmediateScope))
2230 CO |= ClassOptions::Scoped;
2232 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2233 Scope = Scope->getScope()) {
2234 if (isa<DISubprogram>(Scope)) {
2235 CO |= ClassOptions::Scoped;
2246 case dwarf::DW_TAG_class_type:
2247 case dwarf::DW_TAG_structure_type:
2248 case dwarf::DW_TAG_union_type:
2249 case dwarf::DW_TAG_enumeration_type:
2255 if (
const auto *File = Ty->
getFile()) {
2267 unsigned EnumeratorCount = 0;
2270 CO |= ClassOptions::ForwardReference;
2273 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2277 if (
auto *
Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) {
2289 std::string FullName = getFullyQualifiedName(Ty);
2295 addUDTSrcLine(Ty, EnumTI);
2329void CodeViewDebug::clear() {
2330 assert(CurFn ==
nullptr);
2332 FnDebugInfo.clear();
2333 FileToFilepathMap.clear();
2336 TypeIndices.clear();
2337 CompleteTypeIndices.clear();
2338 ScopeGlobals.clear();
2339 CVGlobalVariableOffsets.clear();
2342void CodeViewDebug::collectMemberInfo(
ClassInfo &Info,
2345 Info.Members.push_back({DDTy, 0});
2348 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2349 DINode::FlagStaticMember) {
2352 StaticConstMembers.push_back(DDTy);
2364 const DIType *Ty = DDTy->getBaseType();
2365 bool FullyResolved =
false;
2366 while (!FullyResolved) {
2368 case dwarf::DW_TAG_const_type:
2369 case dwarf::DW_TAG_volatile_type:
2372 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2375 FullyResolved =
true;
2384 ClassInfo NestedInfo = collectClassInfo(DCTy);
2386 Info.Members.push_back(
2394 for (
auto *Element : Elements) {
2399 if (
auto *SP = dyn_cast<DISubprogram>(Element)) {
2400 Info.Methods[SP->getRawName()].push_back(SP);
2401 }
else if (
auto *DDTy = dyn_cast<DIDerivedType>(Element)) {
2402 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2403 collectMemberInfo(Info, DDTy);
2404 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2405 Info.Inheritance.push_back(DDTy);
2406 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2407 DDTy->
getName() ==
"__vtbl_ptr_type") {
2408 Info.VShapeTI = getTypeIndex(DDTy);
2409 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2410 Info.NestedTypes.push_back(DDTy);
2411 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2415 }
else if (
auto *Composite = dyn_cast<DICompositeType>(Element)) {
2416 Info.NestedTypes.push_back(Composite);
2439 auto I = CompleteTypeIndices.find(Ty);
2440 if (
I != CompleteTypeIndices.end() &&
I->second ==
TypeIndex())
2442 return getCompleteTypeIndex(Ty);
2450 std::string FullName = getFullyQualifiedName(Ty);
2455 DeferredCompleteTypes.push_back(Ty);
2465 unsigned FieldCount;
2468 lowerRecordFieldList(Ty);
2471 CO |= ClassOptions::ContainsNestedClass;
2479 CO |= ClassOptions::HasConstructorOrDestructor;
2481 std::string FullName = getFullyQualifiedName(Ty);
2489 addUDTSrcLine(Ty, ClassTI);
2499 return getCompleteTypeIndex(Ty);
2503 std::string FullName = getFullyQualifiedName(Ty);
2507 DeferredCompleteTypes.push_back(Ty);
2514 unsigned FieldCount;
2517 lowerRecordFieldList(Ty);
2520 CO |= ClassOptions::ContainsNestedClass;
2523 std::string FullName = getFullyQualifiedName(Ty);
2525 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2529 addUDTSrcLine(Ty, UnionTI);
2536std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2542 unsigned MemberCount = 0;
2545 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2549 if (
I->getFlags() & DINode::FlagVirtual) {
2551 unsigned VBPtrOffset =
I->getVBPtrOffset();
2553 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2554 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2555 ? TypeRecordKind::IndirectVirtualBaseClass
2556 : TypeRecordKind::VirtualBaseClass;
2559 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2565 assert(
I->getOffsetInBits() % 8 == 0 &&
2566 "bases must be on byte boundaries");
2568 getTypeIndex(
I->getBaseType()),
2569 I->getOffsetInBits() / 8);
2583 if (
Member->isStaticMember()) {
2591 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2592 Member->getName().starts_with(
"_vptr$")) {
2602 if (
Member->isBitField()) {
2603 uint64_t StartBitOffset = MemberOffsetInBits;
2604 if (
const auto *CI =
2605 dyn_cast_or_null<ConstantInt>(
Member->getStorageOffsetInBits())) {
2606 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2608 StartBitOffset -= MemberOffsetInBits;
2613 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2621 for (
auto &MethodItr :
Info.Methods) {
2624 std::vector<OneMethodRecord> Methods;
2626 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2627 bool Introduced = SP->getFlags() & DINode::FlagIntroducedVirtual;
2629 unsigned VFTableOffset = -1;
2631 VFTableOffset = SP->getVirtualIndex() * getPointerSizeInBytes();
2639 assert(!Methods.empty() &&
"Empty methods map entry");
2640 if (Methods.size() == 1)
2661 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2662 !
Info.NestedTypes.empty());
2665TypeIndex CodeViewDebug::getVBPTypeIndex() {
2671 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2672 : PointerKind::Near32;
2675 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2690 auto I = TypeIndices.find({Ty, ClassTy});
2691 if (
I != TypeIndices.end())
2694 TypeLoweringScope S(*
this);
2696 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2700CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2702 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2703 "this type must be a pointer type");
2706 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2707 Options = PointerOptions::LValueRefThisPointer;
2708 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2709 Options = PointerOptions::RValueRefThisPointer;
2716 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2717 if (
I != TypeIndices.end())
2720 TypeLoweringScope S(*
this);
2722 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2725TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(
const DIType *Ty) {
2727 getPointerSizeInBytes() == 8 ? PointerKind::Near64
2728 : PointerKind::Near32,
2729 PointerMode::LValueReference, PointerOptions::None,
2742 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2743 (void)getTypeIndex(Ty);
2744 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2745 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2750 case dwarf::DW_TAG_class_type:
2751 case dwarf::DW_TAG_structure_type:
2752 case dwarf::DW_TAG_union_type:
2755 return getTypeIndex(Ty);
2758 const auto *CTy = cast<DICompositeType>(Ty);
2760 TypeLoweringScope S(*
this);
2766 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2767 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2772 if (CTy->isForwardDecl())
2779 auto InsertResult = CompleteTypeIndices.insert({CTy,
TypeIndex()});
2780 if (!InsertResult.second)
2781 return InsertResult.first->second;
2784 switch (CTy->getTag()) {
2785 case dwarf::DW_TAG_class_type:
2786 case dwarf::DW_TAG_structure_type:
2787 TI = lowerCompleteTypeClass(CTy);
2789 case dwarf::DW_TAG_union_type:
2790 TI = lowerCompleteTypeUnion(CTy);
2800 CompleteTypeIndices[CTy] = TI;
2808void CodeViewDebug::emitDeferredCompleteTypes() {
2810 while (!DeferredCompleteTypes.empty()) {
2811 std::swap(DeferredCompleteTypes, TypesToEmit);
2813 getCompleteTypeIndex(RecordTy);
2814 TypesToEmit.clear();
2818void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2822 for (
const LocalVariable &L : Locals)
2823 if (
L.DIVar->isParameter())
2825 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2826 return L->DIVar->getArg() <
R->DIVar->getArg();
2828 for (
const LocalVariable *L : Params)
2829 emitLocalVariable(FI, *L);
2832 for (
const LocalVariable &L : Locals) {
2833 if (!
L.DIVar->isParameter()) {
2834 if (
L.ConstantValue) {
2837 const DIType *Ty =
L.DIVar->getType();
2839 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2841 emitLocalVariable(FI, L);
2847void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2848 const LocalVariable &Var) {
2850 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2853 if (Var.DIVar->isParameter())
2854 Flags |= LocalSymFlags::IsParameter;
2855 if (Var.DefRanges.empty())
2856 Flags |= LocalSymFlags::IsOptimizedOut;
2860 ? getTypeIndexForReferenceTo(Var.DIVar->getType())
2861 : getCompleteTypeIndex(Var.DIVar->
getType());
2867 endSymbolRecord(LocalEnd);
2873 for (
const auto &Pair : Var.DefRanges) {
2874 LocalVarDef DefRange = Pair.first;
2875 const auto &
Ranges = Pair.second;
2877 if (DefRange.InMemory) {
2878 int Offset = DefRange.DataOffset;
2879 unsigned Reg = DefRange.CVRegister;
2886 Offset += FI.OffsetAdjustment;
2893 if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2894 (
bool(Flags & LocalSymFlags::IsParameter)
2895 ? (EncFP == FI.EncodedParamFramePtrReg)
2896 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2902 if (DefRange.IsSubfield) {
2904 (DefRange.StructOffset
2909 DRHdr.
Flags = RegRelFlags;
2914 assert(DefRange.DataOffset == 0 &&
"unexpected offset into register");
2915 if (DefRange.IsSubfield) {
2917 DRHdr.
Register = DefRange.CVRegister;
2923 DRHdr.
Register = DefRange.CVRegister;
2932 const FunctionInfo& FI) {
2934 emitLexicalBlock(*
Block, FI);
2939void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2940 const FunctionInfo& FI) {
2941 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2948 OS.
AddComment(
"Function section relative address");
2954 endSymbolRecord(RecordEnd);
2957 emitLocalVariableList(FI,
Block.Locals);
2958 emitGlobalVariableList(
Block.Globals);
2961 emitLexicalBlockList(
Block.Children, FI);
2964 emitEndSymbolRecord(SymbolKind::S_END);
2969void CodeViewDebug::collectLexicalBlockInfo(
2975 collectLexicalBlockInfo(*Scope,
Blocks, Locals, Globals);
2980void CodeViewDebug::collectLexicalBlockInfo(
2985 if (
Scope.isAbstractScope())
2990 bool IgnoreScope =
false;
2991 auto LI = ScopeVariables.find(&Scope);
2993 LI != ScopeVariables.end() ? &LI->second :
nullptr;
2994 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
2996 GI != ScopeGlobals.end() ? GI->second.get() :
nullptr;
3001 if (!Locals && !Globals)
3031 collectLexicalBlockInfo(
Scope.getChildren(),
3041 auto BlockInsertion = CurFn->LexicalBlocks.insert({DILB, LexicalBlock()});
3042 if (!BlockInsertion.second)
3049 LexicalBlock &
Block = BlockInsertion.first->second;
3052 assert(
Block.Begin &&
"missing label for scope begin");
3053 assert(
Block.End &&
"missing label for scope end");
3056 Block.Locals = std::move(*Locals);
3058 Block.Globals = std::move(*Globals);
3060 collectLexicalBlockInfo(
Scope.getChildren(),
3068 assert(FnDebugInfo.count(&GV));
3069 assert(CurFn == FnDebugInfo[&GV].
get());
3075 collectLexicalBlockInfo(*CFS,
3083 ScopeVariables.clear();
3087 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3088 FnDebugInfo.erase(&GV);
3094 for (
const auto &
MBB : *MF) {
3095 for (
const auto &
MI :
MBB) {
3096 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3099 dyn_cast<DIType>(MD)));
3106 collectDebugInfoForJumpTables(MF,
isThumb);
3120 return DL &&
DL.getLine() != 0;
3127 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3135 for (
const auto &NextMI : *
MI->getParent()) {
3136 if (NextMI.isDebugInstr())
3138 DL = NextMI.getDebugLoc();
3151 maybeRecordLocation(
DL,
Asm->
MF);
3164void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3172 if (EE.Value == SymKind)
3189void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3198void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3206void CodeViewDebug::emitDebugInfoForUDTs(
3207 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3209 size_t OriginalSize = UDTs.size();
3211 for (
const auto &UDT : UDTs) {
3214 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3216 OS.
emitInt32(getCompleteTypeIndex(
T).getIndex());
3217 assert(OriginalSize == UDTs.size() &&
3218 "getCompleteTypeIndex found new UDTs!");
3220 endSymbolRecord(UDTRecordEnd);
3224void CodeViewDebug::collectGlobalVariableInfo() {
3229 GV.getDebugInfo(GVEs);
3230 for (
const auto *GVE : GVEs)
3231 GlobalMap[GVE] = &GV;
3236 const auto *
CU = cast<DICompileUnit>(
Node);
3237 for (
const auto *GVE :
CU->getGlobalVariables()) {
3246 if ((
DIE->getNumElements() == 2) &&
3247 (
DIE->getElement(0) == dwarf::DW_OP_plus_uconst))
3252 CVGlobalVariableOffsets.insert(
3253 std::make_pair(DIGV,
DIE->getElement(1)));
3256 if (GlobalMap.
count(GVE) == 0 &&
DIE->isConstant()) {
3257 CVGlobalVariable CVGV = {DIGV,
DIE};
3261 const auto *GV = GlobalMap.
lookup(GVE);
3267 if (Scope && isa<DILocalScope>(Scope)) {
3270 auto Insertion = ScopeGlobals.insert(
3271 {
Scope, std::unique_ptr<GlobalVariableList>()});
3272 if (Insertion.second)
3273 Insertion.first->second = std::make_unique<GlobalVariableList>();
3274 VariableList = Insertion.first->second.get();
3277 VariableList = &ComdatVariables;
3280 VariableList = &GlobalVariables;
3281 CVGlobalVariable CVGV = {DIGV, GV};
3287void CodeViewDebug::collectDebugInfoForGlobals() {
3288 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3291 getCompleteTypeIndex(DIGV->
getType());
3292 getFullyQualifiedName(Scope, DIGV->
getName());
3295 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3298 getCompleteTypeIndex(DIGV->
getType());
3299 getFullyQualifiedName(Scope, DIGV->
getName());
3303void CodeViewDebug::emitDebugInfoForGlobals() {
3307 switchToDebugSectionForSymbol(
nullptr);
3308 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3309 OS.
AddComment(
"Symbol subsection for globals");
3310 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3311 emitGlobalVariableList(GlobalVariables);
3312 emitStaticConstMemberList();
3313 endCVSubsection(EndLabel);
3318 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3319 const GlobalVariable *GV = cast<const GlobalVariable *>(CVGV.GVInfo);
3323 switchToDebugSectionForSymbol(GVSym);
3324 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3326 emitDebugInfoForGlobal(CVGV);
3327 endCVSubsection(EndLabel);
3331void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3334 for (
auto *Ty : cast<DICompileUnit>(
Node)->getRetainedTypes()) {
3335 if (
DIType *RT = dyn_cast<DIType>(Ty)) {
3345 for (
const CVGlobalVariable &CVGV : Globals) {
3347 emitDebugInfoForGlobal(CVGV);
3353 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3355 OS.
emitInt32(getTypeIndex(DTy).getIndex());
3369 endSymbolRecord(SConstantEnd);
3372void CodeViewDebug::emitStaticConstMemberList() {
3378 dyn_cast_or_null<ConstantInt>(DTy->getConstant()))
3382 dyn_cast_or_null<ConstantFP>(DTy->getConstant()))
3383 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3387 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3388 getFullyQualifiedName(Scope, DTy->
getName()));
3393 if (isa<DICompositeType>(Ty))
3396 if (
auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
3398 if (
T == dwarf::DW_TAG_pointer_type ||
3399 T == dwarf::DW_TAG_ptr_to_member_type ||
3400 T == dwarf::DW_TAG_reference_type ||
3401 T == dwarf::DW_TAG_rvalue_reference_type)
3403 assert(DTy->getBaseType() &&
"Expected valid base type");
3407 auto *BTy = cast<DIBasicType>(Ty);
3408 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3411void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3416 if (
const auto *MemberDecl = dyn_cast_or_null<DIDerivedType>(
3418 Scope = MemberDecl->getScope();
3424 ? std::string(DIGV->
getName())
3428 dyn_cast_if_present<const GlobalVariable *>(CVGV.GVInfo)) {
3434 : SymbolKind::S_GTHREAD32)
3436 : SymbolKind::S_GDATA32);
3443 if (CVGlobalVariableOffsets.contains(DIGV))
3445 Offset = CVGlobalVariableOffsets[DIGV];
3451 const unsigned LengthOfDataRecord = 12;
3453 endSymbolRecord(DataEnd);
3457 "Global constant variables must contain a constant expression.");
3471 int64_t)> &Callback) {
3473 if (JTI && !JTI->isEmpty()) {
3477 for (
const auto &
MBB : *MF) {
3480 if (LastMI !=
MBB.
end() && LastMI->isIndirectBranch()) {
3488 for (
const auto &MO : LastMI->operands()) {
3490 unsigned Index = MO.getIndex();
3494 Callback(*JTI, *LastMI,
Index);
3503 if (
I->isJumpTableDebugInfo()) {
3504 unsigned Index =
I->getOperand(0).getImm();
3508 Callback(*JTI, *LastMI,
Index);
3517 "Some of jump tables were not used in a debug info instruction");
3522void CodeViewDebug::discoverJumpTableBranches(
const MachineFunction *MF,
3530void CodeViewDebug::collectDebugInfoForJumpTables(
const MachineFunction *MF,
3535 int64_t JumpTableIndex) {
3548 "EK_Custom32, EK_GPRel32BlockAddress, and "
3549 "EK_GPRel64BlockAddress should never be emitted for COFF");
3552 EntrySize = JumpTableEntrySize::Pointer;
3559 std::tie(
Base, BaseOffset, Branch, EntrySize) =
3564 CurFn->JumpTables.push_back(
3571void CodeViewDebug::emitDebugInfoForJumpTables(
const FunctionInfo &FI) {
3572 for (
auto JumpTable : FI.JumpTables) {
3573 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3597 endSymbolRecord(JumpTableEnd);
3601void CodeViewDebug::emitInlinees(
3605 constexpr size_t ChunkSize =
3612 size_t CurrentIndex = 0;
3613 while (CurrentIndex < SortedInlinees.size()) {
3614 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3615 auto CurrentChunkSize =
3616 std::min(ChunkSize, SortedInlinees.size() - CurrentIndex);
3620 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3621 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3623 OS.
emitInt32(SortedInlinees[CurrentIndex].getIndex());
3625 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 std::string flattenCommandLine(ArrayRef< std::string > Args, StringRef MainFilename)
static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty)
static bool needsReferenceType(const DbgVariableLocation &Loc)
static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file contains constants used for implementing Dwarf debug support.
DenseMap< Block *, BlockRelaxAux > Blocks
unsigned const TargetRegisterInfo * TRI
Module.h This file contains the declarations for the Module class.
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 bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static const uint32_t IV[8]
Class for arbitrary precision integers.
An arbitrary precision integer that knows its signedness.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
size - Get the array size.
This class is intended to be used as a driving class for all asm writers.
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
MCSymbol * getSymbol(const GlobalValue *GV) const
TargetMachine & TM
Target machine description.
MCSymbol * getFunctionBegin() const
const MCAsmInfo * MAI
Target Asm Printer information.
MachineFunction * MF
The current machine function.
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.
DebugLoc PrologEndLoc
This location indicates end of function prologue and beginning of function body.
MCSymbol * getLabelAfterInsn(const MachineInstr *MI)
Return Label immediately following the instruction.
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)
static uint64_t getBaseTypeSize(const DIType *Ty)
If this type is derived from a base type then return base type size.
DebugLoc getFnDebugLoc() const
Find the debug info location for the start of the function.
DILocation * get() const
Get the underlying DILocation.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Implements a dense probed hash-table based set.
Lightweight error class with error context and mandatory checking.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool hasStackProtectorFnAttr() const
Returns true if the function has ssp, sspstrong, or sspreq fn attrs.
DISubprogram * getSubprogram() const
Get the attached subprogram.
bool hasPersonalityFn() const
Check whether this function has a personality function.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
bool hasProfileData(bool IncludeSynthetic=false) const
Return true if the function is annotated with profile data.
bool hasOptNone() const
Do not optimize this function (-O0).
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
bool hasLocalLinkage() const
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
bool isDeclarationForLinker() const
LexicalScope - This class is used to track scope information.
LexicalScope * findLexicalScope(const DILocation *DL)
findLexicalScope - Find lexical scope, either regular or inlined, for the given DebugLoc.
LexicalScope * findInlinedScope(const DILocalScope *N, const DILocation *IA)
findInlinedScope - Find an inlined scope for the given scope/inlined-at.
LexicalScope * getCurrentFunctionScope() const
getCurrentFunctionScope - Return lexical scope for the current function.
unsigned getCodePointerSize() const
Get the code pointer size in bytes.
void * allocate(unsigned Size, unsigned Align=8)
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSectionCOFF * getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym, unsigned UniqueID=GenericSectionID)
Gets or creates a section equivalent to Sec that is associated with the section containing KeySym.
MCSection * getCOFFDebugSymbolsSection() const
MCSection * getCOFFDebugTypesSection() const
MCSection * getCOFFGlobalTypeHashesSection() const
This represents a section on Windows.
MCSymbol * getCOMDATSymbol() const
Streaming machine code generation interface.
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
virtual bool emitCVFuncIdDirective(unsigned FunctionId)
Introduces a function id for use with .cv_loc.
virtual void emitBinaryData(StringRef Data)
Functionally identical to EmitBytes.
virtual bool emitCVFileDirective(unsigned FileNo, StringRef Filename, ArrayRef< uint8_t > Checksum, unsigned ChecksumKind)
Associate a filename with a specified logical file number, and also specify that file's checksum info...
virtual void emitCVStringTableDirective()
This implements the CodeView '.cv_stringtable' assembler directive.
virtual bool isVerboseAsm() const
Return true if this streamer supports verbose assembly and if it is enabled.
virtual void emitCVFileChecksumOffsetDirective(unsigned FileNo)
This implements the CodeView '.cv_filechecksumoffset' assembler directive.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitCVFPOData(const MCSymbol *ProcSym, SMLoc Loc={})
This implements the CodeView '.cv_fpo_data' assembler directive.
virtual void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset)
Emits a COFF section relative relocation.
virtual void emitCVFileChecksumsDirective()
This implements the CodeView '.cv_filechecksums' assembler directive.
virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size)
Emit the absolute difference between two symbols.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitCOFFSectionIndex(MCSymbol const *Symbol)
Emits a COFF section index.
virtual void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, const MCSymbol *FnEnd)
This implements the CodeView '.cv_linetable' assembler directive.
virtual void emitValueToAlignment(Align Alignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
virtual void emitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers.
void emitInt16(uint64_t Value)
virtual void switchSection(MCSection *Section, 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.
ArrayRef< 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()
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.
virtual bool hasFP(const MachineFunction &MF) const =0
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
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 std::string.
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
@ DEBUG_HASHES_SECTION_MAGIC
@ C
The default llvm calling convention, compatible with C.
Reg
All possible values of the reg field in the ModR/M byte.
PointerMode
Equivalent to CV_ptrmode_e.
ProcSymFlags
Corresponds to the CV_PROCFLAGS bitfield.
PointerOptions
Equivalent to misc lfPointerAttr bitfields.
LocalSymFlags
Corresponds to CV_LVARFLAGS bitfield.
MethodKind
Part of member attribute flags. (CV_methodprop_e)
PointerKind
Equivalent to CV_ptrtype_e.
CPUType
These values correspond to the CV_CPU_TYPE_e enumeration, and are documented here: https://msdn....
PointerToMemberRepresentation
Equivalent to CV_pmtype_e.
MethodOptions
Equivalent to CV_fldattr_t bitfield.
ArrayRef< EnumEntry< SymbolKind > > getSymbolTypeNames()
MemberAccess
Source-level access specifier. (CV_access_e)
ThunkOrdinal
These values correspond to the THUNK_ORDINAL enumeration.
EncodedFramePtrReg
Two-bit value indicating which register is the designated frame pointer register.
TypeRecordKind
Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.
SymbolKind
Duplicate copy of the above enum, but using the official CV names.
ModifierOptions
Equivalent to CV_modifier_t.
StringRef getSymbolName(CVSymbol Sym)
EncodedFramePtrReg encodeFramePtrReg(RegisterId Reg, CPUType CPU)
Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
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?
void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote)
Print a command argument, and optionally quote it.
This is an optimization pass for GlobalISel generic memory operations.
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
std::tuple< uint64_t, uint32_t > InlineSite
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< 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.