33#include "llvm/Config/llvm-config.h"
84 :
OS(&
OS), TypeTable(TypeTable) {}
106 TypeName = std::string(TypeTable.getTypeName(TI));
119 case Triple::ArchType::x86:
120 return CPUType::Pentium3;
121 case Triple::ArchType::x86_64:
123 case Triple::ArchType::thumb:
126 return CPUType::ARMNT;
127 case Triple::ArchType::aarch64:
128 return CPUType::ARM64;
138 std::string &Filepath = FileToFilepathMap[File];
139 if (!Filepath.empty())
142 StringRef Dir = File->getDirectory(), Filename = File->getFilename();
146 if (Dir.
startswith(
"/") || Filename.startswith(
"/")) {
149 Filepath = std::string(Dir);
150 if (Dir.
back() !=
'/')
152 Filepath += Filename;
160 if (Filename.find(
':') == 1)
161 Filepath = std::string(Filename);
163 Filepath = (Dir +
"\\" + Filename).str();
168 std::replace(Filepath.begin(), Filepath.end(),
'/',
'\\');
172 while ((Cursor = Filepath.find(
"\\.\\", Cursor)) != std::string::npos)
173 Filepath.erase(Cursor, 2);
178 while ((Cursor = Filepath.find(
"\\..\\", Cursor)) != std::string::npos) {
183 size_t PrevSlash = Filepath.rfind(
'\\', Cursor - 1);
184 if (PrevSlash == std::string::npos)
188 Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
195 while ((Cursor = Filepath.find(
"\\\\", Cursor)) != std::string::npos)
196 Filepath.erase(Cursor, 1);
201unsigned CodeViewDebug::maybeRecordFile(
const DIFile *
F) {
203 unsigned NextId = FileIdMap.
size() + 1;
204 auto Insertion = FileIdMap.
insert(std::make_pair(FullPath, NextId));
205 if (Insertion.second) {
209 if (
F->getChecksum()) {
210 std::string Checksum = fromHex(
F->getChecksum()->Value);
212 memcpy(CKMem, Checksum.data(), Checksum.size());
214 reinterpret_cast<const uint8_t *
>(CKMem), Checksum.size());
215 switch (
F->getChecksum()->Kind) {
217 CSKind = FileChecksumKind::MD5;
220 CSKind = FileChecksumKind::SHA1;
223 CSKind = FileChecksumKind::SHA256;
228 static_cast<unsigned>(CSKind));
232 return Insertion.first->second;
235CodeViewDebug::InlineSite &
236CodeViewDebug::getInlineSite(
const DILocation *InlinedAt,
238 auto SiteInsertion = CurFn->InlineSites.insert({InlinedAt,
InlineSite()});
239 InlineSite *Site = &SiteInsertion.first->second;
240 if (SiteInsertion.second) {
241 unsigned ParentFuncId = CurFn->FuncId;
242 if (
const DILocation *OuterIA = InlinedAt->getInlinedAt())
244 getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())
247 Site->SiteFuncId = NextFuncId++;
249 Site->SiteFuncId, ParentFuncId, maybeRecordFile(InlinedAt->getFile()),
250 InlinedAt->getLine(), InlinedAt->getColumn(),
SMLoc());
252 InlinedSubprograms.insert(Inlinee);
253 auto InlineeIdx = getFuncIdForSubprogram(Inlinee);
255 if (InlinedAt->getInlinedAt() ==
nullptr)
256 CurFn->Inlinees.insert(InlineeIdx);
263 if (!ScopeName.
empty())
266 switch (Scope->getTag()) {
267 case dwarf::DW_TAG_enumeration_type:
268 case dwarf::DW_TAG_class_type:
269 case dwarf::DW_TAG_structure_type:
270 case dwarf::DW_TAG_union_type:
271 return "<unnamed-tag>";
272 case dwarf::DW_TAG_namespace:
273 return "`anonymous namespace'";
279const DISubprogram *CodeViewDebug::collectParentScopeNames(
282 while (Scope !=
nullptr) {
283 if (ClosestSubprogram ==
nullptr)
284 ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
289 if (
const auto *Ty = dyn_cast<DICompositeType>(Scope))
290 DeferredCompleteTypes.push_back(Ty);
293 if (!ScopeName.
empty())
294 QualifiedNameComponents.
push_back(ScopeName);
297 return ClosestSubprogram;
302 std::string FullyQualifiedName;
305 FullyQualifiedName.append(std::string(QualifiedNameComponent));
306 FullyQualifiedName.append(
"::");
308 FullyQualifiedName.append(std::string(TypeName));
309 return FullyQualifiedName;
317 if (
CVD.TypeEmissionLevel == 1)
318 CVD.emitDeferredCompleteTypes();
319 --
CVD.TypeEmissionLevel;
324std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Scope,
331 collectParentScopeNames(Scope, QualifiedNameComponents);
335std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Ty) {
351 if (!Scope || isa<DIFile>(Scope) || isa<DISubprogram>(Scope))
354 assert(!isa<DIType>(Scope) &&
"shouldn't make a namespace scope for a type");
357 auto I = TypeIndices.find({Scope,
nullptr});
358 if (
I != TypeIndices.end())
362 std::string ScopeName = getFullyQualifiedName(Scope);
365 return recordTypeIndexForDINode(Scope, TI);
371 if (
Name.empty() ||
Name.back() !=
'>')
374 int OpenBrackets = 0;
375 for (
int i =
Name.size() - 1; i >= 0; --i) {
378 else if (
Name[i] ==
'<') {
380 if (OpenBrackets == 0)
381 return Name.substr(0, i);
391 auto I = TypeIndices.find({SP,
nullptr});
392 if (
I != TypeIndices.end())
402 if (
const auto *Class = dyn_cast_or_null<DICompositeType>(Scope)) {
406 TypeIndex ClassType = getTypeIndex(Class);
412 TypeIndex ParentScope = getScopeIndex(Scope);
417 return recordTypeIndexForDINode(SP, TI);
421 return ((DCTy->
getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);
429 const DIType *ReturnTy =
nullptr;
431 if (TypeArray.size())
432 ReturnTy = TypeArray[0];
437 if (
auto *ReturnDCTy = dyn_cast_or_null<DICompositeType>(ReturnTy))
439 FO |= FunctionOptions::CxxReturnUdt;
442 if (ClassTy &&
isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {
443 FO |= FunctionOptions::Constructor;
455 if (SP->getDeclaration())
456 SP = SP->getDeclaration();
457 assert(!SP->getDeclaration() &&
"should use declaration as key");
461 auto I = TypeIndices.find({SP,
Class});
462 if (
I != TypeIndices.end())
468 TypeLoweringScope S(*
this);
469 const bool IsStaticMethod = (SP->getFlags() & DINode::FlagStaticMember) != 0;
473 SP->getType(), Class, SP->getThisAdjustment(), IsStaticMethod, FO);
474 return recordTypeIndexForDINode(SP, TI, Class);
480 auto InsertResult = TypeIndices.insert({{
Node, ClassTy}, TI});
482 assert(InsertResult.second &&
"DINode was already assigned a type index");
486unsigned CodeViewDebug::getPointerSizeInBytes() {
490void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
495 InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
496 Site.InlinedLocals.emplace_back(std::move(Var));
499 ScopeVariables[
LS].emplace_back(std::move(Var));
509void CodeViewDebug::maybeRecordLocation(
const DebugLoc &
DL,
521 if (LI.getStartLine() !=
DL.getLine() || LI.isAlwaysStepInto() ||
522 LI.isNeverStepInto())
526 if (CI.getStartColumn() !=
DL.getCol())
529 if (!CurFn->HaveLineInfo)
530 CurFn->HaveLineInfo =
true;
533 FileId = CurFn->LastFileId;
535 FileId = CurFn->LastFileId = maybeRecordFile(
DL->getFile());
538 unsigned FuncId = CurFn->FuncId;
545 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
548 bool FirstLoc =
true;
549 while ((SiteLoc = Loc->getInlinedAt())) {
551 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
565void CodeViewDebug::emitCodeViewMagicVersion() {
573 case dwarf::DW_LANG_C:
574 case dwarf::DW_LANG_C89:
575 case dwarf::DW_LANG_C99:
576 case dwarf::DW_LANG_C11:
577 return SourceLanguage::C;
578 case dwarf::DW_LANG_C_plus_plus:
579 case dwarf::DW_LANG_C_plus_plus_03:
580 case dwarf::DW_LANG_C_plus_plus_11:
581 case dwarf::DW_LANG_C_plus_plus_14:
582 return SourceLanguage::Cpp;
583 case dwarf::DW_LANG_Fortran77:
584 case dwarf::DW_LANG_Fortran90:
585 case dwarf::DW_LANG_Fortran95:
586 case dwarf::DW_LANG_Fortran03:
587 case dwarf::DW_LANG_Fortran08:
588 return SourceLanguage::Fortran;
589 case dwarf::DW_LANG_Pascal83:
590 return SourceLanguage::Pascal;
591 case dwarf::DW_LANG_Cobol74:
592 case dwarf::DW_LANG_Cobol85:
593 return SourceLanguage::Cobol;
594 case dwarf::DW_LANG_Java:
595 return SourceLanguage::Java;
596 case dwarf::DW_LANG_D:
597 return SourceLanguage::D;
598 case dwarf::DW_LANG_Swift:
599 return SourceLanguage::Swift;
600 case dwarf::DW_LANG_Rust:
601 return SourceLanguage::Rust;
602 case dwarf::DW_LANG_ObjC:
603 return SourceLanguage::ObjC;
604 case dwarf::DW_LANG_ObjC_plus_plus:
605 return SourceLanguage::ObjCpp;
610 return SourceLanguage::Masm;
626 const MDNode *Node = *M->debug_compile_units_begin();
627 const auto *
CU = cast<DICompileUnit>(Node);
631 collectGlobalVariableInfo();
635 mdconst::extract_or_null<ConstantInt>(M->getModuleFlag(
"CodeViewGHash"));
636 EmitDebugGlobalHashes = GH && !GH->
isZero();
650 switchToDebugSectionForSymbol(
nullptr);
652 MCSymbol *CompilerInfo = beginCVSubsection(DebugSubsectionKind::Symbols);
654 emitCompilerInformation();
655 endCVSubsection(CompilerInfo);
657 emitInlineeLinesSubsection();
660 for (
auto &
P : FnDebugInfo)
661 if (!
P.first->isDeclarationForLinker())
662 emitDebugInfoForFunction(
P.first, *
P.second);
667 collectDebugInfoForGlobals();
670 emitDebugInfoForRetainedTypes();
673 setCurrentSubprogram(
nullptr);
674 emitDebugInfoForGlobals();
678 switchToDebugSectionForSymbol(
nullptr);
681 if (!GlobalUDTs.empty()) {
682 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
683 emitDebugInfoForUDTs(GlobalUDTs);
684 endCVSubsection(SymbolsEnd);
688 OS.
AddComment(
"File index to string table offset subsection");
702 emitTypeInformation();
704 if (EmitDebugGlobalHashes)
705 emitTypeGlobalHashes();
712 unsigned MaxFixedRecordLength = 0xF00) {
720 OS.emitBytes(NullTerminatedString);
723void CodeViewDebug::emitTypeInformation() {
724 if (TypeTable.
empty())
729 emitCodeViewMagicVersion();
735 CVMCAdapter CVMCOS(OS, Table);
739 std::optional<TypeIndex>
B = Table.getFirst();
751 B = Table.getNext(*
B);
755void CodeViewDebug::emitTypeGlobalHashes() {
756 if (TypeTable.
empty())
772 for (
const auto &GHR : TypeTable.
hashes()) {
782 assert(GHR.Hash.size() == 8);
783 StringRef S(
reinterpret_cast<const char *
>(GHR.Hash.data()),
789void CodeViewDebug::emitObjName() {
790 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);
795 if (PathRef.empty() || PathRef ==
"-") {
808 endSymbolRecord(CompilerEnd);
822 for (
const char C :
Name) {
825 V.Part[
N] +=
C -
'0';
827 std::min<int>(V.Part[
N], std::numeric_limits<uint16_t>::max());
828 }
else if (
C ==
'.') {
838void CodeViewDebug::emitCompilerInformation() {
839 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
843 Flags = CurrentSourceLanguage;
851 Arch == ArchType::aarch64) {
863 const auto *
CU = cast<DICompileUnit>(
Node);
868 for (
int N : FrontVer.Part) {
875 int Major = 1000 * LLVM_VERSION_MAJOR +
876 10 * LLVM_VERSION_MINOR +
879 Major = std::min<int>(Major, std::numeric_limits<uint16_t>::max());
880 Version BackVer = {{ Major, 0, 0, 0 }};
882 for (
int N : BackVer.Part)
885 OS.
AddComment(
"Null-terminated compiler version string");
888 endSymbolRecord(CompilerEnd);
899 std::string FlatCmdLine;
901 bool PrintedOneArg =
false;
904 PrintedOneArg =
true;
906 for (
unsigned i = 0; i < Args.size(); i++) {
910 if (Arg ==
"-main-file-name" || Arg ==
"-o") {
914 if (Arg.
startswith(
"-object-file-name") || Arg == MainFilename)
922 PrintedOneArg =
true;
928void CodeViewDebug::emitBuildInfo() {
942 const auto *
CU = cast<DICompileUnit>(
Node);
943 const DIFile *MainSourceFile =
CU->getFile();
963 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
964 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
967 endSymbolRecord(BIEnd);
968 endCVSubsection(BISubsecEnd);
971void CodeViewDebug::emitInlineeLinesSubsection() {
972 if (InlinedSubprograms.empty())
976 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
983 OS.
emitInt32(
unsigned(InlineeLinesSignature::Normal));
986 assert(TypeIndices.count({SP, nullptr}));
987 TypeIndex InlineeIdx = TypeIndices[{SP,
nullptr}];
990 unsigned FileId = maybeRecordFile(SP->
getFile());
994 OS.
AddComment(
"Type index of inlined function");
996 OS.
AddComment(
"Offset into filechecksum table");
1002 endCVSubsection(InlineEnd);
1005void CodeViewDebug::emitInlinedCallSite(
const FunctionInfo &FI,
1008 assert(TypeIndices.count({Site.Inlinee, nullptr}));
1009 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee,
nullptr}];
1012 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
1021 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
1022 unsigned StartLineNum = Site.Inlinee->getLine();
1027 endSymbolRecord(InlineEnd);
1029 emitLocalVariableList(FI, Site.InlinedLocals);
1032 for (
const DILocation *ChildSite : Site.ChildSites) {
1033 auto I = FI.InlineSites.find(ChildSite);
1034 assert(
I != FI.InlineSites.end() &&
1035 "child site not in function inline site map");
1036 emitInlinedCallSite(FI, ChildSite,
I->second);
1040 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1043void CodeViewDebug::switchToDebugSectionForSymbol(
const MCSymbol *GVSym) {
1048 GVSym ? dyn_cast<MCSectionCOFF>(&GVSym->
getSection()) : nullptr;
1059 if (ComdatDebugSections.insert(DebugSec).second)
1060 emitCodeViewMagicVersion();
1065void CodeViewDebug::emitDebugInfoForThunk(
const Function *GV,
1068 std::string FuncName =
1073 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1076 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1083 OS.
AddComment(
"Thunk section relative address");
1094 endSymbolRecord(ThunkRecordEnd);
1100 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1102 endCVSubsection(SymbolsEnd);
1105void CodeViewDebug::emitDebugInfoForFunction(
const Function *GV,
1113 switchToDebugSectionForSymbol(Fn);
1115 std::string FuncName;
1118 setCurrentSubprogram(SP);
1120 if (SP->isThunk()) {
1121 emitDebugInfoForThunk(GV, FI, Fn);
1131 if (FuncName.empty())
1140 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1143 : SymbolKind::S_GPROC32_ID;
1144 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1163 OS.
AddComment(
"Function section relative address");
1168 ProcSymFlags ProcFlags = ProcSymFlags::HasOptimizedDebugInfo;
1169 if (FI.HasFramePointer)
1170 ProcFlags |= ProcSymFlags::HasFP;
1172 ProcFlags |= ProcSymFlags::IsNoReturn;
1174 ProcFlags |= ProcSymFlags::IsNoInline;
1175 OS.
emitInt8(
static_cast<uint8_t
>(ProcFlags));
1180 endSymbolRecord(ProcRecordEnd);
1182 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1185 OS.
emitInt32(FI.FrameSize - FI.CSRSize);
1190 OS.
AddComment(
"Bytes of callee saved registers");
1196 OS.
AddComment(
"Flags (defines frame register)");
1198 endSymbolRecord(FrameProcEnd);
1200 emitInlinees(FI.Inlinees);
1201 emitLocalVariableList(FI, FI.Locals);
1202 emitGlobalVariableList(FI.Globals);
1203 emitLexicalBlockList(FI.ChildBlocks, FI);
1208 for (
const DILocation *InlinedAt : FI.ChildSites) {
1209 auto I = FI.InlineSites.find(InlinedAt);
1210 assert(
I != FI.InlineSites.end() &&
1211 "child site not in function inline site map");
1212 emitInlinedCallSite(FI, InlinedAt,
I->second);
1215 for (
auto Annot : FI.Annotations) {
1217 MDTuple *Strs = cast<MDTuple>(Annot.second);
1218 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1226 StringRef Str = cast<MDString>(MD)->getString();
1227 assert(Str.data()[Str.size()] ==
'\0' &&
"non-nullterminated MDString");
1230 endSymbolRecord(AnnotEnd);
1233 for (
auto HeapAllocSite : FI.HeapAllocSites) {
1234 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1235 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1236 const DIType *DITy = std::get<2>(HeapAllocSite);
1237 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1245 OS.
emitInt32(getCompleteTypeIndex(DITy).getIndex());
1246 endSymbolRecord(HeapAllocEnd);
1250 emitDebugInfoForUDTs(LocalUDTs);
1252 emitDebugInfoForJumpTables(FI);
1255 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1257 endCVSubsection(SymbolsEnd);
1264CodeViewDebug::createDefRangeMem(
uint16_t CVRegister,
int Offset) {
1270 DR.StructOffset = 0;
1271 DR.CVRegister = CVRegister;
1275void CodeViewDebug::collectVariableInfoFromMFTable(
1286 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1287 "Expected inlined-at fields to agree");
1289 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1298 int64_t ExprOffset = 0;
1302 if (
VI.Expr->getNumElements() == 1 &&
1303 VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)
1305 else if (!
VI.Expr->extractIfOffset(ExprOffset))
1313 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1316 "Frame offsets with a scalable component are not supported");
1319 LocalVarDef DefRange =
1320 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset);
1329 Var.DefRanges[DefRange].emplace_back(Begin,
End);
1333 Var.UseReferenceType =
true;
1335 recordLocalVariable(std::move(Var), Scope);
1347void CodeViewDebug::calculateRanges(
1352 for (
auto I = Entries.begin(),
E = Entries.end();
I !=
E; ++
I) {
1353 const auto &Entry = *
I;
1354 if (!Entry.isDbgValue())
1360 std::optional<DbgVariableLocation>
Location =
1382 if (Var.UseReferenceType) {
1391 Var.UseReferenceType =
true;
1392 Var.DefRanges.clear();
1393 calculateRanges(Var, Entries);
1402 DR.CVRegister =
TRI->getCodeViewRegNum(
Location->Register);
1403 DR.InMemory = !
Location->LoadChain.empty();
1407 DR.IsSubfield =
true;
1408 DR.StructOffset =
Location->FragmentInfo->OffsetInBits / 8;
1410 DR.IsSubfield =
false;
1411 DR.StructOffset = 0;
1418 auto &EndingEntry = Entries[Entry.getEndIndex()];
1419 End = EndingEntry.isDbgValue()
1429 if (!
R.empty() &&
R.back().second == Begin)
1430 R.back().second =
End;
1432 R.emplace_back(Begin,
End);
1438void CodeViewDebug::collectVariableInfo(
const DISubprogram *SP) {
1441 collectVariableInfoFromMFTable(Processed);
1444 InlinedEntity
IV =
I.first;
1451 const auto &Entries =
I.second;
1465 calculateRanges(Var, Entries);
1466 recordLocalVariable(std::move(Var), Scope);
1475 auto Insertion = FnDebugInfo.insert({&GV, std::make_unique<FunctionInfo>()});
1476 assert(Insertion.second &&
"function already has info");
1477 CurFn = Insertion.first->second.get();
1478 CurFn->FuncId = NextFuncId++;
1487 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1491 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::None;
1492 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::None;
1493 if (CurFn->FrameSize > 0) {
1495 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1496 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr;
1498 CurFn->HasFramePointer =
true;
1500 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr;
1501 if (CurFn->HasStackRealignment) {
1503 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1507 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::FramePtr;
1515 FPO |= FrameProcedureOptions::HasAlloca;
1517 FPO |= FrameProcedureOptions::HasSetJmp;
1520 FPO |= FrameProcedureOptions::HasInlineAssembly;
1524 FPO |= FrameProcedureOptions::HasStructuredExceptionHandling;
1526 FPO |= FrameProcedureOptions::HasExceptionHandling;
1529 FPO |= FrameProcedureOptions::MarkedInline;
1531 FPO |= FrameProcedureOptions::Naked;
1533 FPO |= FrameProcedureOptions::SecurityChecks;
1536 FPO |= FrameProcedureOptions::StrictSecurityChecks;
1540 FPO |= FrameProcedureOptions::SafeBuffers;
1546 FPO |= FrameProcedureOptions::OptimizedForSpeed;
1548 FPO |= FrameProcedureOptions::ValidProfileCounts;
1549 FPO |= FrameProcedureOptions::ProfileGuidedOptimization;
1552 CurFn->FrameProcOpts = FPO;
1561 bool EmptyPrologue =
true;
1562 for (
const auto &
MBB : *MF) {
1563 for (
const auto &
MI :
MBB) {
1568 }
else if (!
MI.isMetaInstruction()) {
1569 EmptyPrologue =
false;
1577 maybeRecordLocation(FnStartDL, MF);
1581 for (
const auto &
MBB : *MF) {
1582 for (
const auto &
MI :
MBB) {
1583 if (
MI.getHeapAllocMarker()) {
1593 discoverJumpTableBranches(MF,
isThumb);
1601 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1602 if (
DIScope *Scope =
T->getScope()) {
1603 switch (Scope->getTag()) {
1604 case dwarf::DW_TAG_structure_type:
1605 case dwarf::DW_TAG_class_type:
1606 case dwarf::DW_TAG_union_type:
1616 if (!
T ||
T->isForwardDecl())
1622 T = DT->getBaseType();
1627void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1636 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1638 std::string FullyQualifiedName =
1641 if (ClosestSubprogram ==
nullptr) {
1642 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1643 }
else if (ClosestSubprogram == CurrentSubprogram) {
1644 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1658 case dwarf::DW_TAG_array_type:
1659 return lowerTypeArray(cast<DICompositeType>(Ty));
1660 case dwarf::DW_TAG_typedef:
1661 return lowerTypeAlias(cast<DIDerivedType>(Ty));
1662 case dwarf::DW_TAG_base_type:
1663 return lowerTypeBasic(cast<DIBasicType>(Ty));
1664 case dwarf::DW_TAG_pointer_type:
1665 if (cast<DIDerivedType>(Ty)->
getName() ==
"__vtbl_ptr_type")
1666 return lowerTypeVFTableShape(cast<DIDerivedType>(Ty));
1668 case dwarf::DW_TAG_reference_type:
1669 case dwarf::DW_TAG_rvalue_reference_type:
1670 return lowerTypePointer(cast<DIDerivedType>(Ty));
1671 case dwarf::DW_TAG_ptr_to_member_type:
1672 return lowerTypeMemberPointer(cast<DIDerivedType>(Ty));
1673 case dwarf::DW_TAG_restrict_type:
1674 case dwarf::DW_TAG_const_type:
1675 case dwarf::DW_TAG_volatile_type:
1677 return lowerTypeModifier(cast<DIDerivedType>(Ty));
1678 case dwarf::DW_TAG_subroutine_type:
1682 return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy,
1686 return lowerTypeFunction(cast<DISubroutineType>(Ty));
1687 case dwarf::DW_TAG_enumeration_type:
1688 return lowerTypeEnum(cast<DICompositeType>(Ty));
1689 case dwarf::DW_TAG_class_type:
1690 case dwarf::DW_TAG_structure_type:
1691 return lowerTypeClass(cast<DICompositeType>(Ty));
1692 case dwarf::DW_TAG_union_type:
1693 return lowerTypeUnion(cast<DICompositeType>(Ty));
1694 case dwarf::DW_TAG_string_type:
1695 return lowerTypeString(cast<DIStringType>(Ty));
1696 case dwarf::DW_TAG_unspecified_type:
1697 if (Ty->
getName() ==
"decltype(nullptr)")
1707 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1712 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::Int32Long) &&
1713 TypeName ==
"HRESULT")
1714 return TypeIndex(SimpleTypeKind::HResult);
1715 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::UInt16Short) &&
1716 TypeName ==
"wchar_t")
1717 return TypeIndex(SimpleTypeKind::WideCharacter);
1719 return UnderlyingTypeIndex;
1724 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1726 TypeIndex IndexType = getPointerSizeInBytes() == 8
1734 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1736 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1745 if (
auto *CI = dyn_cast_if_present<ConstantInt *>(
Subrange->getCount()))
1746 Count = CI->getSExtValue();
1747 else if (
auto *UI = dyn_cast_if_present<ConstantInt *>(
1751 auto *LI = dyn_cast_if_present<ConstantInt *>(
Subrange->getLowerBound());
1752 Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1753 Count = UI->getSExtValue() - Lowerbound + 1;
1764 ElementSize *= Count;
1769 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1776 return ElementTypeIndex;
1789 TypeIndex IndexType = getPointerSizeInBytes() == 8
1809 case dwarf::DW_ATE_address:
1812 case dwarf::DW_ATE_boolean:
1814 case 1: STK = SimpleTypeKind::Boolean8;
break;
1815 case 2: STK = SimpleTypeKind::Boolean16;
break;
1816 case 4: STK = SimpleTypeKind::Boolean32;
break;
1817 case 8: STK = SimpleTypeKind::Boolean64;
break;
1818 case 16: STK = SimpleTypeKind::Boolean128;
break;
1821 case dwarf::DW_ATE_complex_float:
1825 case 4: STK = SimpleTypeKind::Complex16;
break;
1826 case 8: STK = SimpleTypeKind::Complex32;
break;
1827 case 16: STK = SimpleTypeKind::Complex64;
break;
1828 case 20: STK = SimpleTypeKind::Complex80;
break;
1829 case 32: STK = SimpleTypeKind::Complex128;
break;
1832 case dwarf::DW_ATE_float:
1834 case 2: STK = SimpleTypeKind::Float16;
break;
1835 case 4: STK = SimpleTypeKind::Float32;
break;
1836 case 6: STK = SimpleTypeKind::Float48;
break;
1837 case 8: STK = SimpleTypeKind::Float64;
break;
1838 case 10: STK = SimpleTypeKind::Float80;
break;
1839 case 16: STK = SimpleTypeKind::Float128;
break;
1842 case dwarf::DW_ATE_signed:
1844 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1845 case 2: STK = SimpleTypeKind::Int16Short;
break;
1846 case 4: STK = SimpleTypeKind::Int32;
break;
1847 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1848 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1851 case dwarf::DW_ATE_unsigned:
1853 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1854 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1855 case 4: STK = SimpleTypeKind::UInt32;
break;
1856 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1857 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1860 case dwarf::DW_ATE_UTF:
1862 case 1: STK = SimpleTypeKind::Character8;
break;
1863 case 2: STK = SimpleTypeKind::Character16;
break;
1864 case 4: STK = SimpleTypeKind::Character32;
break;
1867 case dwarf::DW_ATE_signed_char:
1869 STK = SimpleTypeKind::SignedCharacter;
1871 case dwarf::DW_ATE_unsigned_char:
1873 STK = SimpleTypeKind::UnsignedCharacter;
1883 if (STK == SimpleTypeKind::Int32 &&
1885 STK = SimpleTypeKind::Int32Long;
1886 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1887 Ty->
getName() ==
"unsigned long"))
1888 STK = SimpleTypeKind::UInt32Long;
1889 if (STK == SimpleTypeKind::UInt16Short &&
1891 STK = SimpleTypeKind::WideCharacter;
1892 if ((STK == SimpleTypeKind::SignedCharacter ||
1893 STK == SimpleTypeKind::UnsignedCharacter) &&
1895 STK = SimpleTypeKind::NarrowCharacter;
1902 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1906 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1908 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1910 ? SimpleTypeMode::NearPointer64
1911 : SimpleTypeMode::NearPointer32;
1916 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1920 case dwarf::DW_TAG_pointer_type:
1921 PM = PointerMode::Pointer;
1923 case dwarf::DW_TAG_reference_type:
1924 PM = PointerMode::LValueReference;
1926 case dwarf::DW_TAG_rvalue_reference_type:
1927 PM = PointerMode::RValueReference;
1932 PO |= PointerOptions::Const;
1946 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1947 : PointerToMemberRepresentation::GeneralFunction;
1948 case DINode::FlagSingleInheritance:
1949 return PointerToMemberRepresentation::SingleInheritanceFunction;
1950 case DINode::FlagMultipleInheritance:
1951 return PointerToMemberRepresentation::MultipleInheritanceFunction;
1952 case DINode::FlagVirtualInheritance:
1953 return PointerToMemberRepresentation::VirtualInheritanceFunction;
1958 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1959 : PointerToMemberRepresentation::GeneralData;
1960 case DINode::FlagSingleInheritance:
1961 return PointerToMemberRepresentation::SingleInheritanceData;
1962 case DINode::FlagMultipleInheritance:
1963 return PointerToMemberRepresentation::MultipleInheritanceData;
1964 case DINode::FlagVirtualInheritance:
1965 return PointerToMemberRepresentation::VirtualInheritanceData;
1973 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
1974 bool IsPMF = isa<DISubroutineType>(Ty->getBaseType());
1975 TypeIndex ClassTI = getTypeIndex(Ty->getClassType());
1977 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->getClassType() :
nullptr);
1978 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
1979 : PointerKind::Near32;
1980 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
1981 : PointerMode::PointerToDataMember;
1995 case dwarf::DW_CC_normal:
return CallingConvention::NearC;
1996 case dwarf::DW_CC_BORLAND_msfastcall:
return CallingConvention::NearFast;
1997 case dwarf::DW_CC_BORLAND_thiscall:
return CallingConvention::ThisCall;
1998 case dwarf::DW_CC_BORLAND_stdcall:
return CallingConvention::NearStdCall;
1999 case dwarf::DW_CC_BORLAND_pascal:
return CallingConvention::NearPascal;
2000 case dwarf::DW_CC_LLVM_vectorcall:
return CallingConvention::NearVector;
2002 return CallingConvention::NearC;
2010 while (IsModifier &&
BaseTy) {
2012 switch (
BaseTy->getTag()) {
2013 case dwarf::DW_TAG_const_type:
2014 Mods |= ModifierOptions::Const;
2015 PO |= PointerOptions::Const;
2017 case dwarf::DW_TAG_volatile_type:
2018 Mods |= ModifierOptions::Volatile;
2019 PO |= PointerOptions::Volatile;
2021 case dwarf::DW_TAG_restrict_type:
2024 PO |= PointerOptions::Restrict;
2039 switch (
BaseTy->getTag()) {
2040 case dwarf::DW_TAG_pointer_type:
2041 case dwarf::DW_TAG_reference_type:
2042 case dwarf::DW_TAG_rvalue_reference_type:
2043 return lowerTypePointer(cast<DIDerivedType>(
BaseTy), PO);
2044 case dwarf::DW_TAG_ptr_to_member_type:
2045 return lowerTypeMemberPointer(cast<DIDerivedType>(
BaseTy), PO);
2055 if (Mods == ModifierOptions::None)
2065 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2068 if (ReturnAndArgTypeIndices.
size() > 1 &&
2074 if (!ReturnAndArgTypeIndices.
empty()) {
2075 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2076 ReturnTypeIndex = ReturnAndArgTypesRef.front();
2077 ArgTypeIndices = ReturnAndArgTypesRef.
drop_front();
2080 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2094 bool IsStaticMethod,
2097 TypeIndex ClassType = getTypeIndex(ClassTy);
2105 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[
Index++]);
2112 if (!IsStaticMethod && ReturnAndArgs.
size() >
Index) {
2114 dyn_cast_or_null<DIDerivedType>(ReturnAndArgs[
Index])) {
2115 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2116 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2129 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2135 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2140 unsigned VSlotCount =
2150 case DINode::FlagPrivate:
return MemberAccess::Private;
2151 case DINode::FlagPublic:
return MemberAccess::Public;
2152 case DINode::FlagProtected:
return MemberAccess::Protected;
2155 return RecordTag == dwarf::DW_TAG_class_type ? MemberAccess::Private
2156 : MemberAccess::Public;
2162 if (SP->isArtificial())
2163 return MethodOptions::CompilerGenerated;
2167 return MethodOptions::None;
2172 if (SP->getFlags() & DINode::FlagStaticMember)
2173 return MethodKind::Static;
2175 switch (SP->getVirtuality()) {
2176 case dwarf::DW_VIRTUALITY_none:
2178 case dwarf::DW_VIRTUALITY_virtual:
2179 return Introduced ? MethodKind::IntroducingVirtual : MethodKind::Virtual;
2180 case dwarf::DW_VIRTUALITY_pure_virtual:
2181 return Introduced ? MethodKind::PureIntroducingVirtual
2182 : MethodKind::PureVirtual;
2187 return MethodKind::Vanilla;
2192 case dwarf::DW_TAG_class_type:
2193 return TypeRecordKind::Class;
2194 case dwarf::DW_TAG_structure_type:
2195 return TypeRecordKind::Struct;
2210 CO |= ClassOptions::HasUniqueName;
2216 if (ImmediateScope && isa<DICompositeType>(ImmediateScope))
2217 CO |= ClassOptions::Nested;
2223 if (Ty->
getTag() == dwarf::DW_TAG_enumeration_type) {
2224 if (ImmediateScope && isa<DISubprogram>(ImmediateScope))
2225 CO |= ClassOptions::Scoped;
2227 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2228 Scope = Scope->getScope()) {
2229 if (isa<DISubprogram>(Scope)) {
2230 CO |= ClassOptions::Scoped;
2241 case dwarf::DW_TAG_class_type:
2242 case dwarf::DW_TAG_structure_type:
2243 case dwarf::DW_TAG_union_type:
2244 case dwarf::DW_TAG_enumeration_type:
2250 if (
const auto *File = Ty->
getFile()) {
2262 unsigned EnumeratorCount = 0;
2265 CO |= ClassOptions::ForwardReference;
2268 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2272 if (
auto *
Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) {
2284 std::string FullName = getFullyQualifiedName(Ty);
2290 addUDTSrcLine(Ty, EnumTI);
2324void CodeViewDebug::clear() {
2325 assert(CurFn ==
nullptr);
2327 FnDebugInfo.clear();
2328 FileToFilepathMap.clear();
2331 TypeIndices.clear();
2332 CompleteTypeIndices.clear();
2333 ScopeGlobals.clear();
2334 CVGlobalVariableOffsets.clear();
2337void CodeViewDebug::collectMemberInfo(
ClassInfo &Info,
2340 Info.Members.push_back({DDTy, 0});
2343 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2344 DINode::FlagStaticMember) {
2347 StaticConstMembers.push_back(DDTy);
2359 const DIType *Ty = DDTy->getBaseType();
2360 bool FullyResolved =
false;
2361 while (!FullyResolved) {
2363 case dwarf::DW_TAG_const_type:
2364 case dwarf::DW_TAG_volatile_type:
2367 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2370 FullyResolved =
true;
2379 ClassInfo NestedInfo = collectClassInfo(DCTy);
2381 Info.Members.push_back(
2389 for (
auto *Element : Elements) {
2394 if (
auto *SP = dyn_cast<DISubprogram>(Element)) {
2395 Info.Methods[SP->getRawName()].push_back(SP);
2396 }
else if (
auto *DDTy = dyn_cast<DIDerivedType>(Element)) {
2397 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2398 collectMemberInfo(Info, DDTy);
2399 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2400 Info.Inheritance.push_back(DDTy);
2401 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2402 DDTy->
getName() ==
"__vtbl_ptr_type") {
2403 Info.VShapeTI = getTypeIndex(DDTy);
2404 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2405 Info.NestedTypes.push_back(DDTy);
2406 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2410 }
else if (
auto *Composite = dyn_cast<DICompositeType>(Element)) {
2411 Info.NestedTypes.push_back(Composite);
2434 auto I = CompleteTypeIndices.find(Ty);
2435 if (
I != CompleteTypeIndices.end() &&
I->second ==
TypeIndex())
2437 return getCompleteTypeIndex(Ty);
2445 std::string FullName = getFullyQualifiedName(Ty);
2450 DeferredCompleteTypes.push_back(Ty);
2460 unsigned FieldCount;
2463 lowerRecordFieldList(Ty);
2466 CO |= ClassOptions::ContainsNestedClass;
2474 CO |= ClassOptions::HasConstructorOrDestructor;
2476 std::string FullName = getFullyQualifiedName(Ty);
2484 addUDTSrcLine(Ty, ClassTI);
2494 return getCompleteTypeIndex(Ty);
2498 std::string FullName = getFullyQualifiedName(Ty);
2502 DeferredCompleteTypes.push_back(Ty);
2509 unsigned FieldCount;
2512 lowerRecordFieldList(Ty);
2515 CO |= ClassOptions::ContainsNestedClass;
2518 std::string FullName = getFullyQualifiedName(Ty);
2520 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2524 addUDTSrcLine(Ty, UnionTI);
2531std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2537 unsigned MemberCount = 0;
2540 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2544 if (
I->getFlags() & DINode::FlagVirtual) {
2546 unsigned VBPtrOffset =
I->getVBPtrOffset();
2548 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2549 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2550 ? TypeRecordKind::IndirectVirtualBaseClass
2551 : TypeRecordKind::VirtualBaseClass;
2554 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2560 assert(
I->getOffsetInBits() % 8 == 0 &&
2561 "bases must be on byte boundaries");
2563 getTypeIndex(
I->getBaseType()),
2564 I->getOffsetInBits() / 8);
2578 if (
Member->isStaticMember()) {
2586 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2587 Member->getName().startswith(
"_vptr$")) {
2597 if (
Member->isBitField()) {
2598 uint64_t StartBitOffset = MemberOffsetInBits;
2599 if (
const auto *CI =
2600 dyn_cast_or_null<ConstantInt>(
Member->getStorageOffsetInBits())) {
2601 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2603 StartBitOffset -= MemberOffsetInBits;
2608 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2616 for (
auto &MethodItr :
Info.Methods) {
2619 std::vector<OneMethodRecord> Methods;
2621 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2622 bool Introduced = SP->getFlags() & DINode::FlagIntroducedVirtual;
2624 unsigned VFTableOffset = -1;
2626 VFTableOffset = SP->getVirtualIndex() * getPointerSizeInBytes();
2634 assert(!Methods.empty() &&
"Empty methods map entry");
2635 if (Methods.size() == 1)
2656 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2657 !
Info.NestedTypes.empty());
2660TypeIndex CodeViewDebug::getVBPTypeIndex() {
2666 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2667 : PointerKind::Near32;
2670 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2685 auto I = TypeIndices.find({Ty, ClassTy});
2686 if (
I != TypeIndices.end())
2689 TypeLoweringScope S(*
this);
2691 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2695CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2697 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2698 "this type must be a pointer type");
2701 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2702 Options = PointerOptions::LValueRefThisPointer;
2703 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2704 Options = PointerOptions::RValueRefThisPointer;
2711 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2712 if (
I != TypeIndices.end())
2715 TypeLoweringScope S(*
this);
2717 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2720TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(
const DIType *Ty) {
2722 getPointerSizeInBytes() == 8 ? PointerKind::Near64
2723 : PointerKind::Near32,
2724 PointerMode::LValueReference, PointerOptions::None,
2737 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2738 (void)getTypeIndex(Ty);
2739 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2740 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2745 case dwarf::DW_TAG_class_type:
2746 case dwarf::DW_TAG_structure_type:
2747 case dwarf::DW_TAG_union_type:
2750 return getTypeIndex(Ty);
2753 const auto *CTy = cast<DICompositeType>(Ty);
2755 TypeLoweringScope S(*
this);
2761 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2762 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2767 if (CTy->isForwardDecl())
2774 auto InsertResult = CompleteTypeIndices.insert({CTy,
TypeIndex()});
2775 if (!InsertResult.second)
2776 return InsertResult.first->second;
2779 switch (CTy->getTag()) {
2780 case dwarf::DW_TAG_class_type:
2781 case dwarf::DW_TAG_structure_type:
2782 TI = lowerCompleteTypeClass(CTy);
2784 case dwarf::DW_TAG_union_type:
2785 TI = lowerCompleteTypeUnion(CTy);
2795 CompleteTypeIndices[CTy] = TI;
2803void CodeViewDebug::emitDeferredCompleteTypes() {
2805 while (!DeferredCompleteTypes.empty()) {
2806 std::swap(DeferredCompleteTypes, TypesToEmit);
2808 getCompleteTypeIndex(RecordTy);
2809 TypesToEmit.clear();
2813void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2817 for (
const LocalVariable &L : Locals)
2818 if (
L.DIVar->isParameter())
2820 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2821 return L->DIVar->getArg() <
R->DIVar->getArg();
2823 for (
const LocalVariable *L : Params)
2824 emitLocalVariable(FI, *L);
2827 for (
const LocalVariable &L : Locals) {
2828 if (!
L.DIVar->isParameter()) {
2829 if (
L.ConstantValue) {
2832 const DIType *Ty =
L.DIVar->getType();
2834 emitConstantSymbolRecord(Ty, Val, std::string(
L.DIVar->getName()));
2836 emitLocalVariable(FI, L);
2842void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2843 const LocalVariable &Var) {
2845 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2848 if (Var.DIVar->isParameter())
2849 Flags |= LocalSymFlags::IsParameter;
2850 if (Var.DefRanges.empty())
2851 Flags |= LocalSymFlags::IsOptimizedOut;
2855 ? getTypeIndexForReferenceTo(Var.DIVar->getType())
2856 : getCompleteTypeIndex(Var.DIVar->
getType());
2862 endSymbolRecord(LocalEnd);
2868 for (
const auto &Pair : Var.DefRanges) {
2869 LocalVarDef DefRange = Pair.first;
2870 const auto &
Ranges = Pair.second;
2872 if (DefRange.InMemory) {
2873 int Offset = DefRange.DataOffset;
2874 unsigned Reg = DefRange.CVRegister;
2881 Offset += FI.OffsetAdjustment;
2888 if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2889 (
bool(Flags & LocalSymFlags::IsParameter)
2890 ? (EncFP == FI.EncodedParamFramePtrReg)
2891 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2897 if (DefRange.IsSubfield) {
2899 (DefRange.StructOffset
2904 DRHdr.
Flags = RegRelFlags;
2909 assert(DefRange.DataOffset == 0 &&
"unexpected offset into register");
2910 if (DefRange.IsSubfield) {
2912 DRHdr.
Register = DefRange.CVRegister;
2918 DRHdr.
Register = DefRange.CVRegister;
2927 const FunctionInfo& FI) {
2929 emitLexicalBlock(*
Block, FI);
2934void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2935 const FunctionInfo& FI) {
2936 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2943 OS.
AddComment(
"Function section relative address");
2949 endSymbolRecord(RecordEnd);
2952 emitLocalVariableList(FI,
Block.Locals);
2953 emitGlobalVariableList(
Block.Globals);
2956 emitLexicalBlockList(
Block.Children, FI);
2959 emitEndSymbolRecord(SymbolKind::S_END);
2964void CodeViewDebug::collectLexicalBlockInfo(
2970 collectLexicalBlockInfo(*Scope,
Blocks, Locals, Globals);
2975void CodeViewDebug::collectLexicalBlockInfo(
2980 if (
Scope.isAbstractScope())
2985 bool IgnoreScope =
false;
2986 auto LI = ScopeVariables.find(&Scope);
2988 LI != ScopeVariables.end() ? &LI->second :
nullptr;
2989 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
2991 GI != ScopeGlobals.end() ? GI->second.get() :
nullptr;
2996 if (!Locals && !Globals)
3026 collectLexicalBlockInfo(
Scope.getChildren(),
3036 auto BlockInsertion = CurFn->LexicalBlocks.insert({DILB, LexicalBlock()});
3037 if (!BlockInsertion.second)
3044 LexicalBlock &
Block = BlockInsertion.first->second;
3047 assert(
Block.Begin &&
"missing label for scope begin");
3048 assert(
Block.End &&
"missing label for scope end");
3051 Block.Locals = std::move(*Locals);
3053 Block.Globals = std::move(*Globals);
3055 collectLexicalBlockInfo(
Scope.getChildren(),
3063 assert(FnDebugInfo.count(&GV));
3064 assert(CurFn == FnDebugInfo[&GV].
get());
3070 collectLexicalBlockInfo(*CFS,
3078 ScopeVariables.clear();
3082 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3083 FnDebugInfo.erase(&GV);
3089 for (
const auto &
MBB : *MF) {
3090 for (
const auto &
MI :
MBB) {
3091 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3094 dyn_cast<DIType>(MD)));
3101 collectDebugInfoForJumpTables(MF,
isThumb);
3115 return DL &&
DL.getLine() != 0;
3122 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3130 for (
const auto &NextMI : *
MI->getParent()) {
3131 if (NextMI.isDebugInstr())
3133 DL = NextMI.getDebugLoc();
3146 maybeRecordLocation(
DL,
Asm->
MF);
3159void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3167 if (EE.Value == SymKind)
3184void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3193void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3201void CodeViewDebug::emitDebugInfoForUDTs(
3202 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3204 size_t OriginalSize = UDTs.size();
3206 for (
const auto &UDT : UDTs) {
3209 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3211 OS.
emitInt32(getCompleteTypeIndex(
T).getIndex());
3212 assert(OriginalSize == UDTs.size() &&
3213 "getCompleteTypeIndex found new UDTs!");
3215 endSymbolRecord(UDTRecordEnd);
3219void CodeViewDebug::collectGlobalVariableInfo() {
3224 GV.getDebugInfo(GVEs);
3225 for (
const auto *GVE : GVEs)
3226 GlobalMap[GVE] = &GV;
3231 const auto *
CU = cast<DICompileUnit>(
Node);
3232 for (
const auto *GVE :
CU->getGlobalVariables()) {
3241 if ((
DIE->getNumElements() == 2) &&
3242 (
DIE->getElement(0) == dwarf::DW_OP_plus_uconst))
3247 CVGlobalVariableOffsets.insert(
3248 std::make_pair(DIGV,
DIE->getElement(1)));
3251 if (GlobalMap.
count(GVE) == 0 &&
DIE->isConstant()) {
3252 CVGlobalVariable CVGV = {DIGV,
DIE};
3256 const auto *GV = GlobalMap.
lookup(GVE);
3262 if (Scope && isa<DILocalScope>(Scope)) {
3265 auto Insertion = ScopeGlobals.insert(
3266 {
Scope, std::unique_ptr<GlobalVariableList>()});
3267 if (Insertion.second)
3268 Insertion.first->second = std::make_unique<GlobalVariableList>();
3269 VariableList = Insertion.first->second.get();
3272 VariableList = &ComdatVariables;
3275 VariableList = &GlobalVariables;
3276 CVGlobalVariable CVGV = {DIGV, GV};
3282void CodeViewDebug::collectDebugInfoForGlobals() {
3283 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3286 getCompleteTypeIndex(DIGV->
getType());
3287 getFullyQualifiedName(Scope, DIGV->
getName());
3290 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3293 getCompleteTypeIndex(DIGV->
getType());
3294 getFullyQualifiedName(Scope, DIGV->
getName());
3298void CodeViewDebug::emitDebugInfoForGlobals() {
3302 switchToDebugSectionForSymbol(
nullptr);
3303 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3304 OS.
AddComment(
"Symbol subsection for globals");
3305 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3306 emitGlobalVariableList(GlobalVariables);
3307 emitStaticConstMemberList();
3308 endCVSubsection(EndLabel);
3313 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3314 const GlobalVariable *GV = cast<const GlobalVariable *>(CVGV.GVInfo);
3318 switchToDebugSectionForSymbol(GVSym);
3319 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3321 emitDebugInfoForGlobal(CVGV);
3322 endCVSubsection(EndLabel);
3326void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3329 for (
auto *Ty : cast<DICompileUnit>(
Node)->getRetainedTypes()) {
3330 if (
DIType *RT = dyn_cast<DIType>(Ty)) {
3340 for (
const CVGlobalVariable &CVGV : Globals) {
3342 emitDebugInfoForGlobal(CVGV);
3348 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3350 OS.
emitInt32(getTypeIndex(DTy).getIndex());
3364 endSymbolRecord(SConstantEnd);
3367void CodeViewDebug::emitStaticConstMemberList() {
3373 dyn_cast_or_null<ConstantInt>(DTy->getConstant()))
3377 dyn_cast_or_null<ConstantFP>(DTy->getConstant()))
3378 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3382 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3383 getFullyQualifiedName(Scope, DTy->
getName()));
3388 if (isa<DICompositeType>(Ty))
3391 if (
auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
3393 if (
T == dwarf::DW_TAG_pointer_type ||
3394 T == dwarf::DW_TAG_ptr_to_member_type ||
3395 T == dwarf::DW_TAG_reference_type ||
3396 T == dwarf::DW_TAG_rvalue_reference_type)
3398 assert(DTy->getBaseType() &&
"Expected valid base type");
3402 auto *BTy = cast<DIBasicType>(Ty);
3403 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3406void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3411 if (
const auto *MemberDecl = dyn_cast_or_null<DIDerivedType>(
3413 Scope = MemberDecl->getScope();
3419 ? std::string(DIGV->
getName())
3423 dyn_cast_if_present<const GlobalVariable *>(CVGV.GVInfo)) {
3429 : SymbolKind::S_GTHREAD32)
3431 : SymbolKind::S_GDATA32);
3438 if (CVGlobalVariableOffsets.contains(DIGV))
3440 Offset = CVGlobalVariableOffsets[DIGV];
3446 const unsigned LengthOfDataRecord = 12;
3448 endSymbolRecord(DataEnd);
3452 "Global constant variables must contain a constant expression.");
3466 int64_t)> &Callback) {
3468 if (JTI && !JTI->isEmpty()) {
3472 for (
const auto &
MBB : *MF) {
3475 if (LastMI !=
MBB.
end() && LastMI->isIndirectBranch()) {
3483 for (
const auto &MO : LastMI->operands()) {
3485 unsigned Index = MO.getIndex();
3489 Callback(*JTI, *LastMI,
Index);
3498 if (
I->isJumpTableDebugInfo()) {
3499 unsigned Index =
I->getOperand(0).getImm();
3503 Callback(*JTI, *LastMI,
Index);
3512 "Some of jump tables were not used in a debug info instruction");
3517void CodeViewDebug::discoverJumpTableBranches(
const MachineFunction *MF,
3525void CodeViewDebug::collectDebugInfoForJumpTables(
const MachineFunction *MF,
3530 int64_t JumpTableIndex) {
3543 "EK_Custom32, EK_GPRel32BlockAddress, and "
3544 "EK_GPRel64BlockAddress should never be emitted for COFF");
3547 EntrySize = JumpTableEntrySize::Pointer;
3554 std::tie(
Base, BaseOffset, Branch, EntrySize) =
3559 CurFn->JumpTables.push_back(
3566void CodeViewDebug::emitDebugInfoForJumpTables(
const FunctionInfo &FI) {
3567 for (
auto JumpTable : FI.JumpTables) {
3568 MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
3592 endSymbolRecord(JumpTableEnd);
3596void CodeViewDebug::emitInlinees(
3600 constexpr size_t ChunkSize =
3607 size_t CurrentIndex = 0;
3608 while (CurrentIndex < SortedInlinees.size()) {
3609 auto Symbol = beginSymbolRecord(SymbolKind::S_INLINEES);
3610 auto CurrentChunkSize =
3611 std::min(ChunkSize, SortedInlinees.size() - CurrentIndex);
3615 const size_t CurrentChunkEnd = CurrentIndex + CurrentChunkSize;
3616 for (; CurrentIndex < CurrentChunkEnd; ++CurrentIndex) {
3618 OS.
emitInt32(SortedInlinees[CurrentIndex].getIndex());
3620 endSymbolRecord(Symbol);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
static bool isThumb(const MCSubtargetInfo &STI)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
static bool canUseReferenceType(const DbgVariableLocation &Loc)
static SourceLanguage MapDWLangToCVLang(unsigned DWLang)
static MethodKind translateMethodKindFlags(const DISubprogram *SP, bool Introduced)
static bool isUsableDebugLoc(DebugLoc DL)
static TypeIndex getStringIdTypeIdx(GlobalTypeTableBuilder &TypeTable, StringRef S)
static CPUType mapArchToCVCPUType(Triple::ArchType Type)
static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S, unsigned MaxFixedRecordLength=0xF00)
static Version parseVersion(StringRef Name)
static MethodOptions translateMethodOptionFlags(const DISubprogram *SP)
static bool isNonTrivial(const DICompositeType *DCTy)
static std::string formatNestedName(ArrayRef< StringRef > QualifiedNameComponents, StringRef TypeName)
static ClassOptions getCommonClassOptions(const DICompositeType *Ty)
Return ClassOptions that should be present on both the forward declaration and the defintion of a tag...
static PointerToMemberRepresentation translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags)
static FunctionOptions getFunctionOptions(const DISubroutineType *Ty, const DICompositeType *ClassTy=nullptr, StringRef SPName=StringRef(""))
static StringRef removeTemplateArgs(StringRef Name)
static TypeRecordKind getRecordKind(const DICompositeType *Ty)
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.
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.
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
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.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
const MachineBasicBlock * PrevInstBB
void requestLabelAfterInsn(const MachineInstr *MI)
Ensure that a label will be emitted after MI.
DbgValueHistoryMap DbgValues
History of DBG_VALUE and clobber instructions for each user variable.
void requestLabelBeforeInsn(const MachineInstr *MI)
Ensure that a label will be emitted before MI.
static uint64_t getBaseTypeSize(const DIType *Ty)
If this type is derived from a base type then return base type size.
DebugLoc getFnDebugLoc() const
Find the debug info location for the start of the function.
DILocation * get() const
Get the underlying DILocation.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Implements a dense probed hash-table based set.
Lightweight error class with error context and mandatory checking.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool hasStackProtectorFnAttr() const
Returns true if the function has ssp, sspstrong, or sspreq fn attrs.
DISubprogram * getSubprogram() const
Get the attached subprogram.
bool hasPersonalityFn() const
Check whether this function has a personality function.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
bool hasProfileData(bool IncludeSynthetic=false) const
Return true if the function is annotated with profile data.
bool hasOptNone() const
Do not optimize this function (-O0).
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
bool hasLocalLinkage() const
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
bool isDeclarationForLinker() const
LexicalScope - This class is used to track scope information.
LexicalScope * findLexicalScope(const DILocation *DL)
findLexicalScope - Find lexical scope, either regular or inlined, for the given DebugLoc.
LexicalScope * findInlinedScope(const DILocalScope *N, const DILocation *IA)
findInlinedScope - Find an inlined scope for the given scope/inlined-at.
LexicalScope * getCurrentFunctionScope() const
getCurrentFunctionScope - Return lexical scope for the current function.
unsigned getCodePointerSize() const
Get the code pointer size in bytes.
void * allocate(unsigned Size, unsigned Align=8)
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSectionCOFF * getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym, unsigned UniqueID=GenericSectionID)
Gets or creates a section equivalent to Sec that is associated with the section containing KeySym.
MCSection * getCOFFDebugSymbolsSection() const
MCSection * getCOFFDebugTypesSection() const
MCSection * getCOFFGlobalTypeHashesSection() const
This represents a section on Windows.
MCSymbol * getCOMDATSymbol() const
Streaming machine code generation interface.
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
virtual bool emitCVFuncIdDirective(unsigned FunctionId)
Introduces a function id for use with .cv_loc.
virtual void emitBinaryData(StringRef Data)
Functionally identical to EmitBytes.
virtual bool emitCVFileDirective(unsigned FileNo, StringRef Filename, ArrayRef< uint8_t > Checksum, unsigned ChecksumKind)
Associate a filename with a specified logical file number, and also specify that file's checksum info...
virtual void emitCVStringTableDirective()
This implements the CodeView '.cv_stringtable' assembler directive.
virtual bool isVerboseAsm() const
Return true if this streamer supports verbose assembly and if it is enabled.
virtual void emitCVFileChecksumOffsetDirective(unsigned FileNo)
This implements the CodeView '.cv_filechecksumoffset' assembler directive.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitCVFPOData(const MCSymbol *ProcSym, SMLoc Loc={})
This implements the CodeView '.cv_fpo_data' assembler directive.
virtual void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset)
Emits a COFF section relative relocation.
virtual void emitCVFileChecksumsDirective()
This implements the CodeView '.cv_filechecksums' assembler directive.
virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size)
Emit the absolute difference between two symbols.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitCOFFSectionIndex(MCSymbol const *Symbol)
Emits a COFF section index.
virtual void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, const MCSymbol *FnEnd)
This implements the CodeView '.cv_linetable' assembler directive.
virtual void emitValueToAlignment(Align Alignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
virtual void emitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers.
void emitInt16(uint64_t Value)
virtual void switchSection(MCSection *Section, const MCExpr *Subsection=nullptr)
Set the current section where code is being emitted to Section.
virtual void emitCVDefRangeDirective(ArrayRef< std::pair< const MCSymbol *, const MCSymbol * > > Ranges, StringRef FixedSizePortion)
This implements the CodeView '.cv_def_range' assembler directive.
void emitInt32(uint64_t Value)
virtual void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, unsigned Column, bool PrologueEnd, bool IsStmt, StringRef FileName, SMLoc Loc)
This implements the CodeView '.cv_loc' assembler directive.
virtual bool emitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc, unsigned IAFile, unsigned IALine, unsigned IACol, SMLoc Loc)
Introduces an inline call site id for use with .cv_loc.
void emitInt8(uint64_t Value)
virtual void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym)
This implements the CodeView '.cv_inline_linetable' assembler directive.
virtual void emitBytes(StringRef Data)
Emit the bytes in Data into the output.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
ArrayRef< std::string > CommandLineArgs
ArrayRef< MDOperand > operands() const
unsigned getNumOperands() const
Return number of MDNode operands.
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.
int getOffsetAdjustment() const
Return the correction for frame offsets.
unsigned getCVBytesOfCalleeSavedRegisters() const
Returns how many bytes of callee-saved registers the target pushed in the prologue.
bool hasStackProtectorIndex() const
Description of the location of a variable whose Address is valid and unchanging during function execu...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool hasInlineAsm() const
Returns true if the function contains any inline assembly.
bool exposesReturnsTwice() const
exposesReturnsTwice - Returns true if the function calls setjmp or any other similar functions with a...
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
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
bool hasDebugInfo() const
Returns true if valid debug info is present.
A Module instance is used to store all the information related to an LLVM module.
NamedMDNode * getNamedMetadata(const Twine &Name) const
Return the first NamedMDNode in the module with the specified name.
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
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.
constexpr bool empty() const
empty - Check if the string is empty.
char back() const
back - Get the last character in the string.
bool startswith(StringRef Prefix) const
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Information about stack frame layout on the target.
virtual bool hasFP(const MachineFunction &MF) const =0
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
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)
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote)
Print a command argument, and optionally quote it.
This is an optimization pass for GlobalISel generic memory operations.
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
std::tuple< uint64_t, uint32_t > InlineSite
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
StringRef getTypeName()
We provide a function which tries to compute the (demangled) name of a type statically.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
std::pair< const MachineInstr *, const MachineInstr * > InsnRange
InsnRange - This is used to track range of instructions with identical lexical scope.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
TypeLoweringScope(CodeViewDebug &CVD)
This struct is a compact representation of a valid (non-zero power of two) alignment.
const DIDerivedType * MemberTypeNode
std::vector< MemberInfo > MemberList
MemberList Members
Direct members.
std::vector< const DIType * > NestedTypes
std::vector< const DIDerivedType * > Inheritance
Base classes.
int InMemory
Indicates that variable data is stored in memory relative to the specified register.
Represents the location at which a variable is stored.
static std::optional< DbgVariableLocation > extractFromMachineInstruction(const MachineInstr &Instruction)
Extract a VariableLocation from a MachineInstr.
SmallVector< int64_t, 1 > LoadChain
Chain of offsetted loads necessary to load the value if it lives in memory.