32#include "llvm/Config/llvm-config.h"
82 : OS(&OS), TypeTable(TypeTable) {}
96 bool isVerboseAsm()
override {
return OS->isVerboseAsm(); }
104 TypeName = std::string(TypeTable.getTypeName(TI));
117 case Triple::ArchType::x86:
118 return CPUType::Pentium3;
119 case Triple::ArchType::x86_64:
121 case Triple::ArchType::thumb:
124 return CPUType::ARMNT;
125 case Triple::ArchType::aarch64:
126 return CPUType::ARM64;
136 std::string &Filepath = FileToFilepathMap[File];
137 if (!Filepath.empty())
140 StringRef Dir = File->getDirectory(), Filename = File->getFilename();
144 if (Dir.
startswith(
"/") || Filename.startswith(
"/")) {
147 Filepath = std::string(Dir);
148 if (Dir.
back() !=
'/')
150 Filepath += Filename;
158 if (Filename.find(
':') == 1)
159 Filepath = std::string(Filename);
161 Filepath = (Dir +
"\\" + Filename).str();
166 std::replace(Filepath.begin(), Filepath.end(),
'/',
'\\');
170 while ((Cursor = Filepath.find(
"\\.\\", Cursor)) != std::string::npos)
171 Filepath.erase(Cursor, 2);
176 while ((Cursor = Filepath.find(
"\\..\\", Cursor)) != std::string::npos) {
181 size_t PrevSlash = Filepath.rfind(
'\\', Cursor - 1);
182 if (PrevSlash == std::string::npos)
186 Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
193 while ((Cursor = Filepath.find(
"\\\\", Cursor)) != std::string::npos)
194 Filepath.erase(Cursor, 1);
199unsigned CodeViewDebug::maybeRecordFile(
const DIFile *
F) {
201 unsigned NextId = FileIdMap.
size() + 1;
202 auto Insertion = FileIdMap.
insert(std::make_pair(FullPath, NextId));
203 if (Insertion.second) {
207 if (
F->getChecksum()) {
208 std::string Checksum = fromHex(
F->getChecksum()->Value);
210 memcpy(CKMem, Checksum.data(), Checksum.size());
212 reinterpret_cast<const uint8_t *
>(CKMem), Checksum.size());
213 switch (
F->getChecksum()->Kind) {
215 CSKind = FileChecksumKind::MD5;
218 CSKind = FileChecksumKind::SHA1;
221 CSKind = FileChecksumKind::SHA256;
226 static_cast<unsigned>(CSKind));
230 return Insertion.first->second;
233CodeViewDebug::InlineSite &
234CodeViewDebug::getInlineSite(
const DILocation *InlinedAt,
236 auto SiteInsertion = CurFn->InlineSites.insert({InlinedAt,
InlineSite()});
237 InlineSite *Site = &SiteInsertion.first->second;
238 if (SiteInsertion.second) {
239 unsigned ParentFuncId = CurFn->FuncId;
240 if (
const DILocation *OuterIA = InlinedAt->getInlinedAt())
242 getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())
245 Site->SiteFuncId = NextFuncId++;
247 Site->SiteFuncId, ParentFuncId, maybeRecordFile(InlinedAt->getFile()),
248 InlinedAt->getLine(), InlinedAt->getColumn(),
SMLoc());
250 InlinedSubprograms.insert(Inlinee);
251 getFuncIdForSubprogram(Inlinee);
258 if (!ScopeName.
empty())
261 switch (Scope->getTag()) {
262 case dwarf::DW_TAG_enumeration_type:
263 case dwarf::DW_TAG_class_type:
264 case dwarf::DW_TAG_structure_type:
265 case dwarf::DW_TAG_union_type:
266 return "<unnamed-tag>";
267 case dwarf::DW_TAG_namespace:
268 return "`anonymous namespace'";
274const DISubprogram *CodeViewDebug::collectParentScopeNames(
277 while (Scope !=
nullptr) {
278 if (ClosestSubprogram ==
nullptr)
279 ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
284 if (
const auto *Ty = dyn_cast<DICompositeType>(Scope))
285 DeferredCompleteTypes.push_back(Ty);
288 if (!ScopeName.
empty())
289 QualifiedNameComponents.
push_back(ScopeName);
292 return ClosestSubprogram;
297 std::string FullyQualifiedName;
300 FullyQualifiedName.append(std::string(QualifiedNameComponent));
301 FullyQualifiedName.append(
"::");
303 FullyQualifiedName.append(std::string(TypeName));
304 return FullyQualifiedName;
312 if (
CVD.TypeEmissionLevel == 1)
313 CVD.emitDeferredCompleteTypes();
314 --
CVD.TypeEmissionLevel;
319std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Scope,
326 collectParentScopeNames(Scope, QualifiedNameComponents);
330std::string CodeViewDebug::getFullyQualifiedName(
const DIScope *Ty) {
346 if (!Scope || isa<DIFile>(Scope) || isa<DISubprogram>(Scope))
349 assert(!isa<DIType>(Scope) &&
"shouldn't make a namespace scope for a type");
352 auto I = TypeIndices.find({Scope,
nullptr});
353 if (
I != TypeIndices.end())
357 std::string ScopeName = getFullyQualifiedName(Scope);
360 return recordTypeIndexForDINode(Scope, TI);
366 if (
Name.empty() ||
Name.back() !=
'>')
369 int OpenBrackets = 0;
370 for (
int i =
Name.size() - 1; i >= 0; --i) {
373 else if (
Name[i] ==
'<') {
375 if (OpenBrackets == 0)
376 return Name.substr(0, i);
386 auto I = TypeIndices.find({SP,
nullptr});
387 if (
I != TypeIndices.end())
397 if (
const auto *Class = dyn_cast_or_null<DICompositeType>(Scope)) {
401 TypeIndex ClassType = getTypeIndex(Class);
407 TypeIndex ParentScope = getScopeIndex(Scope);
412 return recordTypeIndexForDINode(SP, TI);
416 return ((DCTy->
getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);
424 const DIType *ReturnTy =
nullptr;
426 if (TypeArray.size())
427 ReturnTy = TypeArray[0];
432 if (
auto *ReturnDCTy = dyn_cast_or_null<DICompositeType>(ReturnTy))
434 FO |= FunctionOptions::CxxReturnUdt;
437 if (ClassTy &&
isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {
438 FO |= FunctionOptions::Constructor;
450 if (SP->getDeclaration())
451 SP = SP->getDeclaration();
452 assert(!SP->getDeclaration() &&
"should use declaration as key");
456 auto I = TypeIndices.find({SP,
Class});
457 if (
I != TypeIndices.end())
463 TypeLoweringScope S(*
this);
464 const bool IsStaticMethod = (SP->getFlags() & DINode::FlagStaticMember) != 0;
468 SP->getType(), Class, SP->getThisAdjustment(), IsStaticMethod, FO);
469 return recordTypeIndexForDINode(SP, TI, Class);
475 auto InsertResult = TypeIndices.insert({{
Node, ClassTy}, TI});
477 assert(InsertResult.second &&
"DINode was already assigned a type index");
481unsigned CodeViewDebug::getPointerSizeInBytes() {
485void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
490 InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
491 Site.InlinedLocals.emplace_back(std::move(Var));
494 ScopeVariables[
LS].emplace_back(std::move(Var));
504void CodeViewDebug::maybeRecordLocation(
const DebugLoc &
DL,
516 if (LI.getStartLine() !=
DL.getLine() || LI.isAlwaysStepInto() ||
517 LI.isNeverStepInto())
521 if (CI.getStartColumn() !=
DL.getCol())
524 if (!CurFn->HaveLineInfo)
525 CurFn->HaveLineInfo =
true;
528 FileId = CurFn->LastFileId;
530 FileId = CurFn->LastFileId = maybeRecordFile(
DL->getFile());
533 unsigned FuncId = CurFn->FuncId;
540 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
543 bool FirstLoc =
true;
544 while ((SiteLoc = Loc->getInlinedAt())) {
546 getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
560void CodeViewDebug::emitCodeViewMagicVersion() {
568 case dwarf::DW_LANG_C:
569 case dwarf::DW_LANG_C89:
570 case dwarf::DW_LANG_C99:
571 case dwarf::DW_LANG_C11:
572 case dwarf::DW_LANG_ObjC:
573 return SourceLanguage::C;
574 case dwarf::DW_LANG_C_plus_plus:
575 case dwarf::DW_LANG_C_plus_plus_03:
576 case dwarf::DW_LANG_C_plus_plus_11:
577 case dwarf::DW_LANG_C_plus_plus_14:
578 return SourceLanguage::Cpp;
579 case dwarf::DW_LANG_Fortran77:
580 case dwarf::DW_LANG_Fortran90:
581 case dwarf::DW_LANG_Fortran95:
582 case dwarf::DW_LANG_Fortran03:
583 case dwarf::DW_LANG_Fortran08:
584 return SourceLanguage::Fortran;
585 case dwarf::DW_LANG_Pascal83:
586 return SourceLanguage::Pascal;
587 case dwarf::DW_LANG_Cobol74:
588 case dwarf::DW_LANG_Cobol85:
589 return SourceLanguage::Cobol;
590 case dwarf::DW_LANG_Java:
591 return SourceLanguage::Java;
592 case dwarf::DW_LANG_D:
593 return SourceLanguage::D;
594 case dwarf::DW_LANG_Swift:
595 return SourceLanguage::Swift;
596 case dwarf::DW_LANG_Rust:
597 return SourceLanguage::Rust;
602 return SourceLanguage::Masm;
618 const MDNode *Node = *M->debug_compile_units_begin();
619 const auto *
CU = cast<DICompileUnit>(Node);
623 collectGlobalVariableInfo();
627 mdconst::extract_or_null<ConstantInt>(M->getModuleFlag(
"CodeViewGHash"));
628 EmitDebugGlobalHashes = GH && !GH->
isZero();
642 switchToDebugSectionForSymbol(
nullptr);
644 MCSymbol *CompilerInfo = beginCVSubsection(DebugSubsectionKind::Symbols);
646 emitCompilerInformation();
647 endCVSubsection(CompilerInfo);
649 emitInlineeLinesSubsection();
652 for (
auto &
P : FnDebugInfo)
653 if (!
P.first->isDeclarationForLinker())
654 emitDebugInfoForFunction(
P.first, *
P.second);
659 collectDebugInfoForGlobals();
662 emitDebugInfoForRetainedTypes();
665 setCurrentSubprogram(
nullptr);
666 emitDebugInfoForGlobals();
670 switchToDebugSectionForSymbol(
nullptr);
673 if (!GlobalUDTs.empty()) {
674 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
675 emitDebugInfoForUDTs(GlobalUDTs);
676 endCVSubsection(SymbolsEnd);
680 OS.
AddComment(
"File index to string table offset subsection");
694 emitTypeInformation();
696 if (EmitDebugGlobalHashes)
697 emitTypeGlobalHashes();
704 unsigned MaxFixedRecordLength = 0xF00) {
715void CodeViewDebug::emitTypeInformation() {
716 if (TypeTable.
empty())
721 emitCodeViewMagicVersion();
727 CVMCAdapter CVMCOS(OS, Table);
731 std::optional<TypeIndex>
B = Table.getFirst();
743 B = Table.getNext(*
B);
747void CodeViewDebug::emitTypeGlobalHashes() {
748 if (TypeTable.
empty())
764 for (
const auto &GHR : TypeTable.
hashes()) {
774 assert(GHR.Hash.size() == 8);
775 StringRef S(
reinterpret_cast<const char *
>(GHR.Hash.data()),
781void CodeViewDebug::emitObjName() {
782 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_OBJNAME);
787 if (PathRef.empty() || PathRef ==
"-") {
801 endSymbolRecord(CompilerEnd);
815 for (
const char C :
Name) {
818 V.Part[
N] +=
C -
'0';
820 std::min<int>(V.Part[
N], std::numeric_limits<uint16_t>::max());
821 }
else if (
C ==
'.') {
831void CodeViewDebug::emitCompilerInformation() {
832 MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
836 Flags = CurrentSourceLanguage;
844 Arch == ArchType::aarch64) {
856 const auto *
CU = cast<DICompileUnit>(
Node);
861 for (
int N : FrontVer.Part) {
868 int Major = 1000 * LLVM_VERSION_MAJOR +
869 10 * LLVM_VERSION_MINOR +
872 Major = std::min<int>(Major, std::numeric_limits<uint16_t>::max());
873 Version BackVer = {{ Major, 0, 0, 0 }};
875 for (
int N : BackVer.Part)
878 OS.
AddComment(
"Null-terminated compiler version string");
881 endSymbolRecord(CompilerEnd);
892 std::string FlatCmdLine;
894 bool PrintedOneArg =
false;
897 PrintedOneArg =
true;
899 for (
unsigned i = 0; i < Args.size(); i++) {
903 if (
Arg ==
"-main-file-name" ||
Arg ==
"-o") {
907 if (
Arg.startswith(
"-object-file-name") ||
Arg == MainFilename)
910 if (
Arg.startswith(
"-fmessage-length"))
915 PrintedOneArg =
true;
921void CodeViewDebug::emitBuildInfo() {
935 const auto *
CU = cast<DICompileUnit>(
Node);
936 const DIFile *MainSourceFile =
CU->getFile();
956 MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
957 MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
960 endSymbolRecord(BIEnd);
961 endCVSubsection(BISubsecEnd);
964void CodeViewDebug::emitInlineeLinesSubsection() {
965 if (InlinedSubprograms.empty())
969 MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
976 OS.
emitInt32(
unsigned(InlineeLinesSignature::Normal));
979 assert(TypeIndices.count({SP, nullptr}));
980 TypeIndex InlineeIdx = TypeIndices[{SP,
nullptr}];
983 unsigned FileId = maybeRecordFile(SP->
getFile());
987 OS.
AddComment(
"Type index of inlined function");
989 OS.
AddComment(
"Offset into filechecksum table");
995 endCVSubsection(InlineEnd);
998void CodeViewDebug::emitInlinedCallSite(
const FunctionInfo &FI,
1001 assert(TypeIndices.count({Site.Inlinee, nullptr}));
1002 TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee,
nullptr}];
1005 MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
1014 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
1015 unsigned StartLineNum = Site.Inlinee->getLine();
1020 endSymbolRecord(InlineEnd);
1022 emitLocalVariableList(FI, Site.InlinedLocals);
1025 for (
const DILocation *ChildSite : Site.ChildSites) {
1026 auto I = FI.InlineSites.find(ChildSite);
1027 assert(
I != FI.InlineSites.end() &&
1028 "child site not in function inline site map");
1029 emitInlinedCallSite(FI, ChildSite,
I->second);
1033 emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
1036void CodeViewDebug::switchToDebugSectionForSymbol(
const MCSymbol *GVSym) {
1041 GVSym ? dyn_cast<MCSectionCOFF>(&GVSym->
getSection()) : nullptr;
1052 if (ComdatDebugSections.insert(DebugSec).second)
1053 emitCodeViewMagicVersion();
1058void CodeViewDebug::emitDebugInfoForThunk(
const Function *GV,
1061 std::string FuncName =
1066 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1069 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
1076 OS.
AddComment(
"Thunk section relative address");
1087 endSymbolRecord(ThunkRecordEnd);
1093 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1095 endCVSubsection(SymbolsEnd);
1098void CodeViewDebug::emitDebugInfoForFunction(
const Function *GV,
1106 switchToDebugSectionForSymbol(Fn);
1108 std::string FuncName;
1111 setCurrentSubprogram(SP);
1113 if (SP->isThunk()) {
1114 emitDebugInfoForThunk(GV, FI, Fn);
1124 if (FuncName.empty())
1133 MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
1136 : SymbolKind::S_GPROC32_ID;
1137 MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
1156 OS.
AddComment(
"Function section relative address");
1166 endSymbolRecord(ProcRecordEnd);
1168 MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
1171 OS.
emitInt32(FI.FrameSize - FI.CSRSize);
1176 OS.
AddComment(
"Bytes of callee saved registers");
1182 OS.
AddComment(
"Flags (defines frame register)");
1184 endSymbolRecord(FrameProcEnd);
1186 emitLocalVariableList(FI, FI.Locals);
1187 emitGlobalVariableList(FI.Globals);
1188 emitLexicalBlockList(FI.ChildBlocks, FI);
1193 for (
const DILocation *InlinedAt : FI.ChildSites) {
1194 auto I = FI.InlineSites.find(InlinedAt);
1195 assert(
I != FI.InlineSites.end() &&
1196 "child site not in function inline site map");
1197 emitInlinedCallSite(FI, InlinedAt,
I->second);
1200 for (
auto Annot : FI.Annotations) {
1202 MDTuple *Strs = cast<MDTuple>(Annot.second);
1203 MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
1211 StringRef Str = cast<MDString>(MD)->getString();
1212 assert(Str.data()[Str.size()] ==
'\0' &&
"non-nullterminated MDString");
1215 endSymbolRecord(AnnotEnd);
1218 for (
auto HeapAllocSite : FI.HeapAllocSites) {
1219 const MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
1220 const MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
1221 const DIType *DITy = std::get<2>(HeapAllocSite);
1222 MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
1230 OS.
emitInt32(getCompleteTypeIndex(DITy).getIndex());
1231 endSymbolRecord(HeapAllocEnd);
1235 emitDebugInfoForUDTs(LocalUDTs);
1238 emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
1240 endCVSubsection(SymbolsEnd);
1247CodeViewDebug::createDefRangeMem(
uint16_t CVRegister,
int Offset) {
1253 DR.StructOffset = 0;
1254 DR.CVRegister = CVRegister;
1258void CodeViewDebug::collectVariableInfoFromMFTable(
1268 assert(
VI.Var->isValidLocationForIntrinsic(
VI.Loc) &&
1269 "Expected inlined-at fields to agree");
1271 Processed.
insert(InlinedEntity(
VI.Var,
VI.Loc->getInlinedAt()));
1280 int64_t ExprOffset = 0;
1284 if (
VI.Expr->getNumElements() == 1 &&
1285 VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)
1287 else if (!
VI.Expr->extractIfOffset(ExprOffset))
1294 uint16_t CVReg =
TRI->getCodeViewRegNum(FrameReg);
1297 "Frame offsets with a scalable component are not supported");
1300 LocalVarDef DefRange =
1301 createDefRangeMem(CVReg, FrameOffset.
getFixed() + ExprOffset);
1310 Var.DefRanges[DefRange].emplace_back(Begin, End);
1314 Var.UseReferenceType =
true;
1316 recordLocalVariable(std::move(Var), Scope);
1328void CodeViewDebug::calculateRanges(
1333 for (
auto I = Entries.begin(),
E = Entries.end();
I !=
E; ++
I) {
1334 const auto &Entry = *
I;
1335 if (!Entry.isDbgValue())
1341 std::optional<DbgVariableLocation>
Location =
1363 if (Var.UseReferenceType) {
1372 Var.UseReferenceType =
true;
1373 Var.DefRanges.clear();
1374 calculateRanges(Var, Entries);
1383 DR.CVRegister =
TRI->getCodeViewRegNum(
Location->Register);
1384 DR.InMemory = !
Location->LoadChain.empty();
1388 DR.IsSubfield =
true;
1389 DR.StructOffset =
Location->FragmentInfo->OffsetInBits / 8;
1391 DR.IsSubfield =
false;
1392 DR.StructOffset = 0;
1399 auto &EndingEntry = Entries[Entry.getEndIndex()];
1400 End = EndingEntry.isDbgValue()
1410 if (!
R.empty() &&
R.back().second == Begin)
1411 R.back().second = End;
1413 R.emplace_back(Begin, End);
1419void CodeViewDebug::collectVariableInfo(
const DISubprogram *SP) {
1422 collectVariableInfoFromMFTable(Processed);
1425 InlinedEntity
IV =
I.first;
1432 const auto &Entries =
I.second;
1446 calculateRanges(Var, Entries);
1447 recordLocalVariable(std::move(Var), Scope);
1456 auto Insertion = FnDebugInfo.insert({&GV, std::make_unique<FunctionInfo>()});
1457 assert(Insertion.second &&
"function already has info");
1458 CurFn = Insertion.first->second.get();
1459 CurFn->FuncId = NextFuncId++;
1468 CurFn->HasStackRealignment =
TRI->hasStackRealignment(*MF);
1472 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::None;
1473 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::None;
1474 if (CurFn->FrameSize > 0) {
1476 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1477 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr;
1480 CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr;
1481 if (CurFn->HasStackRealignment) {
1483 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
1487 CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::FramePtr;
1495 FPO |= FrameProcedureOptions::HasAlloca;
1497 FPO |= FrameProcedureOptions::HasSetJmp;
1500 FPO |= FrameProcedureOptions::HasInlineAssembly;
1504 FPO |= FrameProcedureOptions::HasStructuredExceptionHandling;
1506 FPO |= FrameProcedureOptions::HasExceptionHandling;
1509 FPO |= FrameProcedureOptions::MarkedInline;
1511 FPO |= FrameProcedureOptions::Naked;
1513 FPO |= FrameProcedureOptions::SecurityChecks;
1516 FPO |= FrameProcedureOptions::StrictSecurityChecks;
1520 FPO |= FrameProcedureOptions::SafeBuffers;
1526 FPO |= FrameProcedureOptions::OptimizedForSpeed;
1528 FPO |= FrameProcedureOptions::ValidProfileCounts;
1529 FPO |= FrameProcedureOptions::ProfileGuidedOptimization;
1532 CurFn->FrameProcOpts = FPO;
1541 bool EmptyPrologue =
true;
1542 for (
const auto &
MBB : *MF) {
1543 for (
const auto &
MI :
MBB) {
1548 }
else if (!
MI.isMetaInstruction()) {
1549 EmptyPrologue =
false;
1557 maybeRecordLocation(FnStartDL, MF);
1561 for (
const auto &
MBB : *MF) {
1562 for (
const auto &
MI :
MBB) {
1563 if (
MI.getHeapAllocMarker()) {
1576 if (
T->getTag() == dwarf::DW_TAG_typedef) {
1577 if (
DIScope *Scope =
T->getScope()) {
1578 switch (Scope->getTag()) {
1579 case dwarf::DW_TAG_structure_type:
1580 case dwarf::DW_TAG_class_type:
1581 case dwarf::DW_TAG_union_type:
1591 if (!
T ||
T->isForwardDecl())
1597 T = DT->getBaseType();
1602void CodeViewDebug::addToUDTs(
const DIType *Ty) {
1611 collectParentScopeNames(Ty->
getScope(), ParentScopeNames);
1613 std::string FullyQualifiedName =
1616 if (ClosestSubprogram ==
nullptr) {
1617 GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1618 }
else if (ClosestSubprogram == CurrentSubprogram) {
1619 LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
1633 case dwarf::DW_TAG_array_type:
1634 return lowerTypeArray(cast<DICompositeType>(Ty));
1635 case dwarf::DW_TAG_typedef:
1636 return lowerTypeAlias(cast<DIDerivedType>(Ty));
1637 case dwarf::DW_TAG_base_type:
1638 return lowerTypeBasic(cast<DIBasicType>(Ty));
1639 case dwarf::DW_TAG_pointer_type:
1640 if (cast<DIDerivedType>(Ty)->
getName() ==
"__vtbl_ptr_type")
1641 return lowerTypeVFTableShape(cast<DIDerivedType>(Ty));
1643 case dwarf::DW_TAG_reference_type:
1644 case dwarf::DW_TAG_rvalue_reference_type:
1645 return lowerTypePointer(cast<DIDerivedType>(Ty));
1646 case dwarf::DW_TAG_ptr_to_member_type:
1647 return lowerTypeMemberPointer(cast<DIDerivedType>(Ty));
1648 case dwarf::DW_TAG_restrict_type:
1649 case dwarf::DW_TAG_const_type:
1650 case dwarf::DW_TAG_volatile_type:
1652 return lowerTypeModifier(cast<DIDerivedType>(Ty));
1653 case dwarf::DW_TAG_subroutine_type:
1657 return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy,
1661 return lowerTypeFunction(cast<DISubroutineType>(Ty));
1662 case dwarf::DW_TAG_enumeration_type:
1663 return lowerTypeEnum(cast<DICompositeType>(Ty));
1664 case dwarf::DW_TAG_class_type:
1665 case dwarf::DW_TAG_structure_type:
1666 return lowerTypeClass(cast<DICompositeType>(Ty));
1667 case dwarf::DW_TAG_union_type:
1668 return lowerTypeUnion(cast<DICompositeType>(Ty));
1669 case dwarf::DW_TAG_string_type:
1670 return lowerTypeString(cast<DIStringType>(Ty));
1671 case dwarf::DW_TAG_unspecified_type:
1672 if (Ty->
getName() ==
"decltype(nullptr)")
1682 TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
1687 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::Int32Long) &&
1688 TypeName ==
"HRESULT")
1689 return TypeIndex(SimpleTypeKind::HResult);
1690 if (UnderlyingTypeIndex ==
TypeIndex(SimpleTypeKind::UInt16Short) &&
1691 TypeName ==
"wchar_t")
1692 return TypeIndex(SimpleTypeKind::WideCharacter);
1694 return UnderlyingTypeIndex;
1699 TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
1701 TypeIndex IndexType = getPointerSizeInBytes() == 8
1709 for (
int i =
Elements.size() - 1; i >= 0; --i) {
1711 assert(Element->
getTag() == dwarf::DW_TAG_subrange_type);
1721 Count = CI->getSExtValue();
1738 ElementSize *= Count;
1743 (i == 0 && ElementSize == 0) ? Ty->
getSizeInBits() / 8 : ElementSize;
1750 return ElementTypeIndex;
1763 TypeIndex IndexType = getPointerSizeInBytes() == 8
1783 case dwarf::DW_ATE_address:
1786 case dwarf::DW_ATE_boolean:
1788 case 1: STK = SimpleTypeKind::Boolean8;
break;
1789 case 2: STK = SimpleTypeKind::Boolean16;
break;
1790 case 4: STK = SimpleTypeKind::Boolean32;
break;
1791 case 8: STK = SimpleTypeKind::Boolean64;
break;
1792 case 16: STK = SimpleTypeKind::Boolean128;
break;
1795 case dwarf::DW_ATE_complex_float:
1797 case 2: STK = SimpleTypeKind::Complex16;
break;
1798 case 4: STK = SimpleTypeKind::Complex32;
break;
1799 case 8: STK = SimpleTypeKind::Complex64;
break;
1800 case 10: STK = SimpleTypeKind::Complex80;
break;
1801 case 16: STK = SimpleTypeKind::Complex128;
break;
1804 case dwarf::DW_ATE_float:
1806 case 2: STK = SimpleTypeKind::Float16;
break;
1807 case 4: STK = SimpleTypeKind::Float32;
break;
1808 case 6: STK = SimpleTypeKind::Float48;
break;
1809 case 8: STK = SimpleTypeKind::Float64;
break;
1810 case 10: STK = SimpleTypeKind::Float80;
break;
1811 case 16: STK = SimpleTypeKind::Float128;
break;
1814 case dwarf::DW_ATE_signed:
1816 case 1: STK = SimpleTypeKind::SignedCharacter;
break;
1817 case 2: STK = SimpleTypeKind::Int16Short;
break;
1818 case 4: STK = SimpleTypeKind::Int32;
break;
1819 case 8: STK = SimpleTypeKind::Int64Quad;
break;
1820 case 16: STK = SimpleTypeKind::Int128Oct;
break;
1823 case dwarf::DW_ATE_unsigned:
1825 case 1: STK = SimpleTypeKind::UnsignedCharacter;
break;
1826 case 2: STK = SimpleTypeKind::UInt16Short;
break;
1827 case 4: STK = SimpleTypeKind::UInt32;
break;
1828 case 8: STK = SimpleTypeKind::UInt64Quad;
break;
1829 case 16: STK = SimpleTypeKind::UInt128Oct;
break;
1832 case dwarf::DW_ATE_UTF:
1834 case 1: STK = SimpleTypeKind::Character8;
break;
1835 case 2: STK = SimpleTypeKind::Character16;
break;
1836 case 4: STK = SimpleTypeKind::Character32;
break;
1839 case dwarf::DW_ATE_signed_char:
1841 STK = SimpleTypeKind::SignedCharacter;
1843 case dwarf::DW_ATE_unsigned_char:
1845 STK = SimpleTypeKind::UnsignedCharacter;
1855 if (STK == SimpleTypeKind::Int32 &&
1857 STK = SimpleTypeKind::Int32Long;
1858 if (STK == SimpleTypeKind::UInt32 && (Ty->
getName() ==
"long unsigned int" ||
1859 Ty->
getName() ==
"unsigned long"))
1860 STK = SimpleTypeKind::UInt32Long;
1861 if (STK == SimpleTypeKind::UInt16Short &&
1863 STK = SimpleTypeKind::WideCharacter;
1864 if ((STK == SimpleTypeKind::SignedCharacter ||
1865 STK == SimpleTypeKind::UnsignedCharacter) &&
1867 STK = SimpleTypeKind::NarrowCharacter;
1874 TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
1878 if (PointeeTI.
isSimple() && PO == PointerOptions::None &&
1880 Ty->
getTag() == dwarf::DW_TAG_pointer_type) {
1882 ? SimpleTypeMode::NearPointer64
1883 : SimpleTypeMode::NearPointer32;
1888 Ty->
getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
1892 case dwarf::DW_TAG_pointer_type:
1893 PM = PointerMode::Pointer;
1895 case dwarf::DW_TAG_reference_type:
1896 PM = PointerMode::LValueReference;
1898 case dwarf::DW_TAG_rvalue_reference_type:
1899 PM = PointerMode::RValueReference;
1904 PO |= PointerOptions::Const;
1918 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1919 : PointerToMemberRepresentation::GeneralFunction;
1920 case DINode::FlagSingleInheritance:
1921 return PointerToMemberRepresentation::SingleInheritanceFunction;
1922 case DINode::FlagMultipleInheritance:
1923 return PointerToMemberRepresentation::MultipleInheritanceFunction;
1924 case DINode::FlagVirtualInheritance:
1925 return PointerToMemberRepresentation::VirtualInheritanceFunction;
1930 return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
1931 : PointerToMemberRepresentation::GeneralData;
1932 case DINode::FlagSingleInheritance:
1933 return PointerToMemberRepresentation::SingleInheritanceData;
1934 case DINode::FlagMultipleInheritance:
1935 return PointerToMemberRepresentation::MultipleInheritanceData;
1936 case DINode::FlagVirtualInheritance:
1937 return PointerToMemberRepresentation::VirtualInheritanceData;
1945 assert(Ty->
getTag() == dwarf::DW_TAG_ptr_to_member_type);
1946 bool IsPMF = isa<DISubroutineType>(Ty->getBaseType());
1947 TypeIndex ClassTI = getTypeIndex(Ty->getClassType());
1949 getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->getClassType() :
nullptr);
1950 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
1951 : PointerKind::Near32;
1952 PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
1953 : PointerMode::PointerToDataMember;
1967 case dwarf::DW_CC_normal:
return CallingConvention::NearC;
1968 case dwarf::DW_CC_BORLAND_msfastcall:
return CallingConvention::NearFast;
1969 case dwarf::DW_CC_BORLAND_thiscall:
return CallingConvention::ThisCall;
1970 case dwarf::DW_CC_BORLAND_stdcall:
return CallingConvention::NearStdCall;
1971 case dwarf::DW_CC_BORLAND_pascal:
return CallingConvention::NearPascal;
1972 case dwarf::DW_CC_LLVM_vectorcall:
return CallingConvention::NearVector;
1974 return CallingConvention::NearC;
1982 while (IsModifier &&
BaseTy) {
1984 switch (
BaseTy->getTag()) {
1985 case dwarf::DW_TAG_const_type:
1986 Mods |= ModifierOptions::Const;
1987 PO |= PointerOptions::Const;
1989 case dwarf::DW_TAG_volatile_type:
1990 Mods |= ModifierOptions::Volatile;
1991 PO |= PointerOptions::Volatile;
1993 case dwarf::DW_TAG_restrict_type:
1996 PO |= PointerOptions::Restrict;
2011 switch (
BaseTy->getTag()) {
2012 case dwarf::DW_TAG_pointer_type:
2013 case dwarf::DW_TAG_reference_type:
2014 case dwarf::DW_TAG_rvalue_reference_type:
2015 return lowerTypePointer(cast<DIDerivedType>(
BaseTy), PO);
2016 case dwarf::DW_TAG_ptr_to_member_type:
2017 return lowerTypeMemberPointer(cast<DIDerivedType>(
BaseTy), PO);
2027 if (Mods == ModifierOptions::None)
2037 ReturnAndArgTypeIndices.
push_back(getTypeIndex(ArgType));
2040 if (ReturnAndArgTypeIndices.
size() > 1 &&
2046 if (!ReturnAndArgTypeIndices.
empty()) {
2047 auto ReturnAndArgTypesRef =
ArrayRef(ReturnAndArgTypeIndices);
2048 ReturnTypeIndex = ReturnAndArgTypesRef.front();
2049 ArgTypeIndices = ReturnAndArgTypesRef.
drop_front();
2052 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2066 bool IsStaticMethod,
2069 TypeIndex ClassType = getTypeIndex(ClassTy);
2077 ReturnTypeIndex = getTypeIndex(ReturnAndArgs[
Index++]);
2084 if (!IsStaticMethod && ReturnAndArgs.
size() >
Index) {
2086 dyn_cast_or_null<DIDerivedType>(ReturnAndArgs[
Index])) {
2087 if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
2088 ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
2101 ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
2107 ArgTypeIndices.
size(), ArgListIndex, ThisAdjustment);
2112 unsigned VSlotCount =
2122 case DINode::FlagPrivate:
return MemberAccess::Private;
2123 case DINode::FlagPublic:
return MemberAccess::Public;
2124 case DINode::FlagProtected:
return MemberAccess::Protected;
2127 return RecordTag == dwarf::DW_TAG_class_type ? MemberAccess::Private
2128 : MemberAccess::Public;
2134 if (SP->isArtificial())
2135 return MethodOptions::CompilerGenerated;
2139 return MethodOptions::None;
2144 if (SP->getFlags() & DINode::FlagStaticMember)
2145 return MethodKind::Static;
2147 switch (SP->getVirtuality()) {
2148 case dwarf::DW_VIRTUALITY_none:
2150 case dwarf::DW_VIRTUALITY_virtual:
2151 return Introduced ? MethodKind::IntroducingVirtual : MethodKind::Virtual;
2152 case dwarf::DW_VIRTUALITY_pure_virtual:
2153 return Introduced ? MethodKind::PureIntroducingVirtual
2154 : MethodKind::PureVirtual;
2159 return MethodKind::Vanilla;
2164 case dwarf::DW_TAG_class_type:
2165 return TypeRecordKind::Class;
2166 case dwarf::DW_TAG_structure_type:
2167 return TypeRecordKind::Struct;
2182 CO |= ClassOptions::HasUniqueName;
2188 if (ImmediateScope && isa<DICompositeType>(ImmediateScope))
2189 CO |= ClassOptions::Nested;
2195 if (Ty->
getTag() == dwarf::DW_TAG_enumeration_type) {
2196 if (ImmediateScope && isa<DISubprogram>(ImmediateScope))
2197 CO |= ClassOptions::Scoped;
2199 for (
const DIScope *Scope = ImmediateScope; Scope !=
nullptr;
2200 Scope = Scope->getScope()) {
2201 if (isa<DISubprogram>(Scope)) {
2202 CO |= ClassOptions::Scoped;
2213 case dwarf::DW_TAG_class_type:
2214 case dwarf::DW_TAG_structure_type:
2215 case dwarf::DW_TAG_union_type:
2216 case dwarf::DW_TAG_enumeration_type:
2222 if (
const auto *File = Ty->
getFile()) {
2234 unsigned EnumeratorCount = 0;
2237 CO |= ClassOptions::ForwardReference;
2240 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2244 if (
auto *
Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) {
2256 std::string FullName = getFullyQualifiedName(Ty);
2262 addUDTSrcLine(Ty, EnumTI);
2296void CodeViewDebug::clear() {
2297 assert(CurFn ==
nullptr);
2299 FnDebugInfo.clear();
2300 FileToFilepathMap.clear();
2303 TypeIndices.clear();
2304 CompleteTypeIndices.clear();
2305 ScopeGlobals.clear();
2306 CVGlobalVariableOffsets.clear();
2309void CodeViewDebug::collectMemberInfo(
ClassInfo &Info,
2312 Info.Members.push_back({DDTy, 0});
2315 if ((DDTy->
getFlags() & DINode::FlagStaticMember) ==
2316 DINode::FlagStaticMember) {
2319 StaticConstMembers.push_back(DDTy);
2331 const DIType *Ty = DDTy->getBaseType();
2332 bool FullyResolved =
false;
2333 while (!FullyResolved) {
2335 case dwarf::DW_TAG_const_type:
2336 case dwarf::DW_TAG_volatile_type:
2339 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2342 FullyResolved =
true;
2351 ClassInfo NestedInfo = collectClassInfo(DCTy);
2353 Info.Members.push_back(
2361 for (
auto *Element : Elements) {
2366 if (
auto *SP = dyn_cast<DISubprogram>(Element)) {
2367 Info.Methods[SP->getRawName()].push_back(SP);
2368 }
else if (
auto *DDTy = dyn_cast<DIDerivedType>(Element)) {
2369 if (DDTy->
getTag() == dwarf::DW_TAG_member) {
2370 collectMemberInfo(Info, DDTy);
2371 }
else if (DDTy->
getTag() == dwarf::DW_TAG_inheritance) {
2372 Info.Inheritance.push_back(DDTy);
2373 }
else if (DDTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2374 DDTy->
getName() ==
"__vtbl_ptr_type") {
2375 Info.VShapeTI = getTypeIndex(DDTy);
2376 }
else if (DDTy->
getTag() == dwarf::DW_TAG_typedef) {
2377 Info.NestedTypes.push_back(DDTy);
2378 }
else if (DDTy->
getTag() == dwarf::DW_TAG_friend) {
2382 }
else if (
auto *Composite = dyn_cast<DICompositeType>(Element)) {
2383 Info.NestedTypes.push_back(Composite);
2406 auto I = CompleteTypeIndices.find(Ty);
2407 if (
I != CompleteTypeIndices.end() &&
I->second ==
TypeIndex())
2409 return getCompleteTypeIndex(Ty);
2417 std::string FullName = getFullyQualifiedName(Ty);
2422 DeferredCompleteTypes.push_back(Ty);
2432 unsigned FieldCount;
2435 lowerRecordFieldList(Ty);
2438 CO |= ClassOptions::ContainsNestedClass;
2446 CO |= ClassOptions::HasConstructorOrDestructor;
2448 std::string FullName = getFullyQualifiedName(Ty);
2456 addUDTSrcLine(Ty, ClassTI);
2466 return getCompleteTypeIndex(Ty);
2470 std::string FullName = getFullyQualifiedName(Ty);
2474 DeferredCompleteTypes.push_back(Ty);
2481 unsigned FieldCount;
2484 lowerRecordFieldList(Ty);
2487 CO |= ClassOptions::ContainsNestedClass;
2490 std::string FullName = getFullyQualifiedName(Ty);
2492 UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
2496 addUDTSrcLine(Ty, UnionTI);
2503std::tuple<TypeIndex, TypeIndex, unsigned, bool>
2509 unsigned MemberCount = 0;
2512 ContinuationBuilder.
begin(ContinuationRecordKind::FieldList);
2516 if (
I->getFlags() & DINode::FlagVirtual) {
2518 unsigned VBPtrOffset =
I->getVBPtrOffset();
2520 unsigned VBTableIndex =
I->getOffsetInBits() / 4;
2521 auto RecordKind = (
I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
2522 ? TypeRecordKind::IndirectVirtualBaseClass
2523 : TypeRecordKind::VirtualBaseClass;
2526 getTypeIndex(
I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
2532 assert(
I->getOffsetInBits() % 8 == 0 &&
2533 "bases must be on byte boundaries");
2535 getTypeIndex(
I->getBaseType()),
2536 I->getOffsetInBits() / 8);
2550 if (
Member->isStaticMember()) {
2558 if ((
Member->getFlags() & DINode::FlagArtificial) &&
2559 Member->getName().startswith(
"_vptr$")) {
2569 if (
Member->isBitField()) {
2570 uint64_t StartBitOffset = MemberOffsetInBits;
2571 if (
const auto *CI =
2572 dyn_cast_or_null<ConstantInt>(
Member->getStorageOffsetInBits())) {
2573 MemberOffsetInBits = CI->getZExtValue() + MemberInfo.
BaseOffset;
2575 StartBitOffset -= MemberOffsetInBits;
2580 uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
2588 for (
auto &MethodItr :
Info.Methods) {
2591 std::vector<OneMethodRecord> Methods;
2593 TypeIndex MethodType = getMemberFunctionType(SP, Ty);
2594 bool Introduced = SP->getFlags() & DINode::FlagIntroducedVirtual;
2596 unsigned VFTableOffset = -1;
2598 VFTableOffset = SP->getVirtualIndex() * getPointerSizeInBytes();
2606 assert(!Methods.empty() &&
"Empty methods map entry");
2607 if (Methods.size() == 1)
2628 return std::make_tuple(FieldTI,
Info.VShapeTI, MemberCount,
2629 !
Info.NestedTypes.empty());
2632TypeIndex CodeViewDebug::getVBPTypeIndex() {
2638 PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
2639 : PointerKind::Near32;
2642 PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
2657 auto I = TypeIndices.find({Ty, ClassTy});
2658 if (
I != TypeIndices.end())
2661 TypeLoweringScope S(*
this);
2663 return recordTypeIndexForDINode(Ty, TI, ClassTy);
2667CodeViewDebug::getTypeIndexForThisPtr(
const DIDerivedType *PtrTy,
2669 assert(PtrTy->
getTag() == dwarf::DW_TAG_pointer_type &&
2670 "this type must be a pointer type");
2673 if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagLValueReference)
2674 Options = PointerOptions::LValueRefThisPointer;
2675 else if (SubroutineTy->
getFlags() & DINode::DIFlags::FlagRValueReference)
2676 Options = PointerOptions::RValueRefThisPointer;
2683 auto I = TypeIndices.find({PtrTy, SubroutineTy});
2684 if (
I != TypeIndices.end())
2687 TypeLoweringScope S(*
this);
2689 return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
2692TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(
const DIType *Ty) {
2694 getPointerSizeInBytes() == 8 ? PointerKind::Near64
2695 : PointerKind::Near32,
2696 PointerMode::LValueReference, PointerOptions::None,
2709 if (Ty->
getTag() == dwarf::DW_TAG_typedef)
2710 (void)getTypeIndex(Ty);
2711 while (Ty->
getTag() == dwarf::DW_TAG_typedef)
2712 Ty = cast<DIDerivedType>(Ty)->getBaseType();
2717 case dwarf::DW_TAG_class_type:
2718 case dwarf::DW_TAG_structure_type:
2719 case dwarf::DW_TAG_union_type:
2722 return getTypeIndex(Ty);
2725 const auto *CTy = cast<DICompositeType>(Ty);
2727 TypeLoweringScope S(*
this);
2733 if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
2734 TypeIndex FwdDeclTI = getTypeIndex(CTy);
2739 if (CTy->isForwardDecl())
2746 auto InsertResult = CompleteTypeIndices.insert({CTy,
TypeIndex()});
2747 if (!InsertResult.second)
2748 return InsertResult.first->second;
2751 switch (CTy->getTag()) {
2752 case dwarf::DW_TAG_class_type:
2753 case dwarf::DW_TAG_structure_type:
2754 TI = lowerCompleteTypeClass(CTy);
2756 case dwarf::DW_TAG_union_type:
2757 TI = lowerCompleteTypeUnion(CTy);
2767 CompleteTypeIndices[CTy] = TI;
2775void CodeViewDebug::emitDeferredCompleteTypes() {
2777 while (!DeferredCompleteTypes.empty()) {
2778 std::swap(DeferredCompleteTypes, TypesToEmit);
2780 getCompleteTypeIndex(RecordTy);
2781 TypesToEmit.clear();
2785void CodeViewDebug::emitLocalVariableList(
const FunctionInfo &FI,
2789 for (
const LocalVariable &L : Locals)
2790 if (L.DIVar->isParameter())
2792 llvm::sort(Params, [](
const LocalVariable *L,
const LocalVariable *R) {
2793 return L->DIVar->getArg() <
R->DIVar->getArg();
2795 for (
const LocalVariable *L : Params)
2796 emitLocalVariable(FI, *L);
2799 for (
const LocalVariable &L : Locals) {
2800 if (!L.DIVar->isParameter()) {
2801 if (L.ConstantValue) {
2804 const DIType *Ty = L.DIVar->getType();
2805 APSInt Val(*L.ConstantValue);
2806 emitConstantSymbolRecord(Ty, Val, std::string(L.DIVar->getName()));
2808 emitLocalVariable(FI, L);
2814void CodeViewDebug::emitLocalVariable(
const FunctionInfo &FI,
2815 const LocalVariable &Var) {
2817 MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
2820 if (Var.DIVar->isParameter())
2821 Flags |= LocalSymFlags::IsParameter;
2822 if (Var.DefRanges.empty())
2823 Flags |= LocalSymFlags::IsOptimizedOut;
2827 ? getTypeIndexForReferenceTo(Var.DIVar->getType())
2828 : getCompleteTypeIndex(Var.DIVar->
getType());
2834 endSymbolRecord(LocalEnd);
2840 for (
const auto &Pair : Var.DefRanges) {
2841 LocalVarDef DefRange = Pair.first;
2842 const auto &
Ranges = Pair.second;
2844 if (DefRange.InMemory) {
2845 int Offset = DefRange.DataOffset;
2846 unsigned Reg = DefRange.CVRegister;
2853 Offset += FI.OffsetAdjustment;
2860 if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
2861 (
bool(Flags & LocalSymFlags::IsParameter)
2862 ? (EncFP == FI.EncodedParamFramePtrReg)
2863 : (EncFP == FI.EncodedLocalFramePtrReg))) {
2869 if (DefRange.IsSubfield) {
2871 (DefRange.StructOffset
2876 DRHdr.
Flags = RegRelFlags;
2881 assert(DefRange.DataOffset == 0 &&
"unexpected offset into register");
2882 if (DefRange.IsSubfield) {
2884 DRHdr.
Register = DefRange.CVRegister;
2890 DRHdr.
Register = DefRange.CVRegister;
2899 const FunctionInfo& FI) {
2900 for (LexicalBlock *
Block : Blocks)
2901 emitLexicalBlock(*
Block, FI);
2906void CodeViewDebug::emitLexicalBlock(
const LexicalBlock &
Block,
2907 const FunctionInfo& FI) {
2908 MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
2915 OS.
AddComment(
"Function section relative address");
2921 endSymbolRecord(RecordEnd);
2924 emitLocalVariableList(FI,
Block.Locals);
2925 emitGlobalVariableList(
Block.Globals);
2928 emitLexicalBlockList(
Block.Children, FI);
2931 emitEndSymbolRecord(SymbolKind::S_END);
2936void CodeViewDebug::collectLexicalBlockInfo(
2942 collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
2947void CodeViewDebug::collectLexicalBlockInfo(
2952 if (
Scope.isAbstractScope())
2957 bool IgnoreScope =
false;
2958 auto LI = ScopeVariables.find(&Scope);
2960 LI != ScopeVariables.end() ? &LI->second :
nullptr;
2961 auto GI = ScopeGlobals.find(
Scope.getScopeNode());
2963 GI != ScopeGlobals.end() ? GI->second.get() :
nullptr;
2968 if (!Locals && !Globals)
2998 collectLexicalBlockInfo(
Scope.getChildren(),
3008 auto BlockInsertion = CurFn->LexicalBlocks.insert({DILB, LexicalBlock()});
3009 if (!BlockInsertion.second)
3016 LexicalBlock &
Block = BlockInsertion.first->second;
3019 assert(
Block.Begin &&
"missing label for scope begin");
3020 assert(
Block.End &&
"missing label for scope end");
3023 Block.Locals = std::move(*Locals);
3025 Block.Globals = std::move(*Globals);
3027 collectLexicalBlockInfo(
Scope.getChildren(),
3035 assert(FnDebugInfo.count(&GV));
3036 assert(CurFn == FnDebugInfo[&GV].
get());
3042 collectLexicalBlockInfo(*CFS,
3050 ScopeVariables.clear();
3054 if (!CurFn->HaveLineInfo && !GV.
getSubprogram()->isThunk()) {
3055 FnDebugInfo.erase(&GV);
3061 for (
const auto &
MBB : *MF) {
3062 for (
const auto &
MI :
MBB) {
3063 if (
MDNode *MD =
MI.getHeapAllocMarker()) {
3066 dyn_cast<DIType>(MD)));
3083 return DL &&
DL.getLine() != 0;
3090 if (!
Asm || !CurFn ||
MI->isDebugInstr() ||
3098 for (
const auto &NextMI : *
MI->getParent()) {
3099 if (NextMI.isDebugInstr())
3101 DL = NextMI.getDebugLoc();
3114 maybeRecordLocation(
DL,
Asm->
MF);
3127void CodeViewDebug::endCVSubsection(
MCSymbol *EndLabel) {
3135 if (EE.Value == SymKind)
3152void CodeViewDebug::endSymbolRecord(
MCSymbol *SymEnd) {
3161void CodeViewDebug::emitEndSymbolRecord(
SymbolKind EndKind) {
3169void CodeViewDebug::emitDebugInfoForUDTs(
3170 const std::vector<std::pair<std::string, const DIType *>> &UDTs) {
3172 size_t OriginalSize = UDTs.size();
3174 for (
const auto &UDT : UDTs) {
3177 MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
3179 OS.
emitInt32(getCompleteTypeIndex(
T).getIndex());
3180 assert(OriginalSize == UDTs.size() &&
3181 "getCompleteTypeIndex found new UDTs!");
3183 endSymbolRecord(UDTRecordEnd);
3187void CodeViewDebug::collectGlobalVariableInfo() {
3192 GV.getDebugInfo(GVEs);
3193 for (
const auto *GVE : GVEs)
3194 GlobalMap[GVE] = &GV;
3199 const auto *
CU = cast<DICompileUnit>(
Node);
3200 for (
const auto *GVE :
CU->getGlobalVariables()) {
3209 if ((
DIE->getNumElements() == 2) &&
3210 (
DIE->getElement(0) == dwarf::DW_OP_plus_uconst))
3215 CVGlobalVariableOffsets.insert(
3216 std::make_pair(DIGV,
DIE->getElement(1)));
3219 if (GlobalMap.
count(GVE) == 0 &&
DIE->isConstant()) {
3220 CVGlobalVariable CVGV = {DIGV,
DIE};
3224 const auto *GV = GlobalMap.
lookup(GVE);
3230 if (Scope && isa<DILocalScope>(Scope)) {
3233 auto Insertion = ScopeGlobals.insert(
3234 {
Scope, std::unique_ptr<GlobalVariableList>()});
3235 if (Insertion.second)
3236 Insertion.first->second = std::make_unique<GlobalVariableList>();
3237 VariableList = Insertion.first->second.get();
3240 VariableList = &ComdatVariables;
3243 VariableList = &GlobalVariables;
3244 CVGlobalVariable CVGV = {DIGV, GV};
3250void CodeViewDebug::collectDebugInfoForGlobals() {
3251 for (
const CVGlobalVariable &CVGV : GlobalVariables) {
3254 getCompleteTypeIndex(DIGV->
getType());
3255 getFullyQualifiedName(Scope, DIGV->
getName());
3258 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3261 getCompleteTypeIndex(DIGV->
getType());
3262 getFullyQualifiedName(Scope, DIGV->
getName());
3266void CodeViewDebug::emitDebugInfoForGlobals() {
3270 switchToDebugSectionForSymbol(
nullptr);
3271 if (!GlobalVariables.empty() || !StaticConstMembers.empty()) {
3272 OS.
AddComment(
"Symbol subsection for globals");
3273 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3274 emitGlobalVariableList(GlobalVariables);
3275 emitStaticConstMemberList();
3276 endCVSubsection(EndLabel);
3281 for (
const CVGlobalVariable &CVGV : ComdatVariables) {
3286 switchToDebugSectionForSymbol(GVSym);
3287 MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
3289 emitDebugInfoForGlobal(CVGV);
3290 endCVSubsection(EndLabel);
3294void CodeViewDebug::emitDebugInfoForRetainedTypes() {
3297 for (
auto *Ty : cast<DICompileUnit>(
Node)->getRetainedTypes()) {
3298 if (
DIType *RT = dyn_cast<DIType>(Ty)) {
3308 for (
const CVGlobalVariable &CVGV : Globals) {
3310 emitDebugInfoForGlobal(CVGV);
3316 MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
3318 OS.
emitInt32(getTypeIndex(DTy).getIndex());
3332 endSymbolRecord(SConstantEnd);
3335void CodeViewDebug::emitStaticConstMemberList() {
3341 dyn_cast_or_null<ConstantInt>(DTy->getConstant()))
3345 dyn_cast_or_null<ConstantFP>(DTy->getConstant()))
3346 Value =
APSInt(CFP->getValueAPF().bitcastToAPInt(),
true);
3350 emitConstantSymbolRecord(DTy->getBaseType(),
Value,
3351 getFullyQualifiedName(Scope, DTy->
getName()));
3356 if (isa<DICompositeType>(Ty))
3359 if (
auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
3361 if (
T == dwarf::DW_TAG_pointer_type ||
3362 T == dwarf::DW_TAG_ptr_to_member_type ||
3363 T == dwarf::DW_TAG_reference_type ||
3364 T == dwarf::DW_TAG_rvalue_reference_type)
3366 assert(DTy->getBaseType() &&
"Expected valid base type");
3370 auto *BTy = cast<DIBasicType>(Ty);
3371 return (BTy->getEncoding() == dwarf::DW_ATE_float);
3374void CodeViewDebug::emitDebugInfoForGlobal(
const CVGlobalVariable &CVGV) {
3379 if (
const auto *MemberDecl = dyn_cast_or_null<DIDerivedType>(
3381 Scope = MemberDecl->getScope();
3387 ? std::string(DIGV->
getName())
3397 : SymbolKind::S_GTHREAD32)
3399 : SymbolKind::S_GDATA32);
3406 if (CVGlobalVariableOffsets.find(DIGV) != CVGlobalVariableOffsets.end())
3408 Offset = CVGlobalVariableOffsets[DIGV];
3414 const unsigned LengthOfDataRecord = 12;
3416 endSymbolRecord(DataEnd);
3420 "Global constant variables must contain a constant expression.");
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This header is deprecated in favour of llvm/TargetParser/Triple.h.
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
static bool canUseReferenceType(const DbgVariableLocation &Loc)
static SourceLanguage MapDWLangToCVLang(unsigned DWLang)
static MethodKind translateMethodKindFlags(const DISubprogram *SP, bool Introduced)
static bool isUsableDebugLoc(DebugLoc DL)
static TypeIndex getStringIdTypeIdx(GlobalTypeTableBuilder &TypeTable, StringRef S)
static CPUType mapArchToCVCPUType(Triple::ArchType Type)
static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S, unsigned MaxFixedRecordLength=0xF00)
static Version parseVersion(StringRef Name)
static MethodOptions translateMethodOptionFlags(const DISubprogram *SP)
static bool isNonTrivial(const DICompositeType *DCTy)
static std::string formatNestedName(ArrayRef< StringRef > QualifiedNameComponents, StringRef TypeName)
static ClassOptions getCommonClassOptions(const DICompositeType *Ty)
Return ClassOptions that should be present on both the forward declaration and the defintion of a tag...
static PointerToMemberRepresentation translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags)
static FunctionOptions getFunctionOptions(const DISubroutineType *Ty, const DICompositeType *ClassTy=nullptr, StringRef SPName=StringRef(""))
static StringRef removeTemplateArgs(StringRef Name)
static TypeRecordKind getRecordKind(const DICompositeType *Ty)
static CallingConvention dwarfCCToCodeView(unsigned DwarfCC)
Given a DWARF calling convention, get the CodeView equivalent.
static bool isFloatDIType(const DIType *Ty)
static void addLocIfNotPresent(SmallVectorImpl< const DILocation * > &Locs, const DILocation *Loc)
static bool shouldEmitUdt(const DIType *T)
static StringRef getPrettyScopeName(const DIScope *Scope)
static std::string flattenCommandLine(ArrayRef< std::string > Args, StringRef MainFilename)
static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty)
static bool needsReferenceType(const DbgVariableLocation &Loc)
static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file contains constants used for implementing Dwarf debug support.
static M68kRelType getType(unsigned Kind, MCSymbolRefExpr::VariantKind &Modifier, bool &IsPCRel)
unsigned const TargetRegisterInfo * TRI
Module.h This file contains the declarations for the Module class.
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallString class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static const uint32_t IV[8]
Class for arbitrary precision integers.
An arbitrary precision integer that knows its signedness.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
size - Get the array size.
This class is intended to be used as a driving class for all asm writers.
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
MCSymbol * getSymbol(const GlobalValue *GV) const
TargetMachine & TM
Target machine description.
MCSymbol * getFunctionBegin() const
const MCAsmInfo * MAI
Target Asm Printer information.
MachineFunction * MF
The current machine function.
MCSymbol * getFunctionEnd() const
Provides write only access to a subclass of WritableBinaryStream.
Collects and handles line tables information in a CodeView format.
CodeViewDebug(AsmPrinter *AP)
void beginModule(Module *M) override
bool moduleIsInFortran()
Check if the current module is in Fortran.
void endFunctionImpl(const MachineFunction *) override
Gather post-function debug information.
void endModule() override
Emit the COFF section that holds the line table information.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
void beginFunctionImpl(const MachineFunction *MF) override
Gather pre-function debug information.
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
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.
static DIE * get(BumpPtrAllocator &Alloc, dwarf::Tag Tag)
bool isLocalToUnit() const
Metadata * getRawStaticDataMemberDeclaration() const
DILocalScope * getScope() const
Get the local scope for this variable.
Tagged DWARF-like metadata node.
dwarf::Tag getTag() const
Base class for scope-like contexts.
StringRef getFilename() const
StringRef getName() const
StringRef getDirectory() const
DIScope * getScope() const
String type, Fortran CHARACTER(n)
Type array for a subprogram.
DITypeRefArray getTypeArray() const
uint64_t getOffsetInBits() const
bool isObjectPointer() const
StringRef getName() const
bool isForwardDecl() const
uint64_t getSizeInBits() const
DIScope * getScope() const
DIScope * getScope() const
StringRef getName() const
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
static const EntryIndex NoEntry
Special value to indicate that an entry is valid until the end of the function.
Base class for debug information backends.
static bool isUnsignedDIType(const DIType *Ty)
Return true if type encoding is unsigned.
AsmPrinter * Asm
Target of debug info emission.
MCSymbol * getLabelBeforeInsn(const MachineInstr *MI)
Return Label preceding the instruction.
MachineModuleInfo * MMI
Collected machine module information.
DebugLoc PrevInstLoc
Previous instruction's location information.
DebugLoc PrologEndLoc
This location indicates end of function prologue and beginning of function body.
MCSymbol * getLabelAfterInsn(const MachineInstr *MI)
Return Label immediately following the instruction.
void beginInstruction(const MachineInstr *MI) override
Process beginning of an instruction.
const MachineBasicBlock * PrevInstBB
void requestLabelAfterInsn(const MachineInstr *MI)
Ensure that a label will be emitted after MI.
DbgValueHistoryMap DbgValues
History of DBG_VALUE and clobber instructions for each user variable.
void requestLabelBeforeInsn(const MachineInstr *MI)
Ensure that a label will be emitted before MI.
static uint64_t getBaseTypeSize(const DIType *Ty)
If this type is derived from a base type then return base type size.
DebugLoc getFnDebugLoc() const
Find the debug info location for the start of the function.
DILocation * get() const
Get the underlying DILocation.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Implements a dense probed hash-table based set.
Lightweight error class with error context and mandatory checking.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool hasStackProtectorFnAttr() const
Returns true if the function has ssp, sspstrong, or sspreq fn attrs.
DISubprogram * getSubprogram() const
Get the attached subprogram.
bool hasPersonalityFn() const
Check whether this function has a personality function.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
bool hasProfileData(bool IncludeSynthetic=false) const
Return true if the function is annotated with profile data.
bool hasOptNone() const
Do not optimize this function (-O0).
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
bool hasLocalLinkage() const
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
bool isDeclarationForLinker() const
LexicalScope - This class is used to track scope information.
LexicalScope * findLexicalScope(const DILocation *DL)
findLexicalScope - Find lexical scope, either regular or inlined, for the given DebugLoc.
LexicalScope * findInlinedScope(const DILocalScope *N, const DILocation *IA)
findInlinedScope - Find an inlined scope for the given scope/inlined-at.
LexicalScope * getCurrentFunctionScope() const
getCurrentFunctionScope - Return lexical scope for the current function.
unsigned getCodePointerSize() const
Get the code pointer size in bytes.
void * allocate(unsigned Size, unsigned Align=8)
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
MCSectionCOFF * getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym, unsigned UniqueID=GenericSectionID)
Gets or creates a section equivalent to Sec that is associated with the section containing KeySym.
MCSection * getCOFFDebugSymbolsSection() const
MCSection * getCOFFDebugTypesSection() const
MCSection * getCOFFGlobalTypeHashesSection() const
This represents a section on Windows.
MCSymbol * getCOMDATSymbol() const
Streaming machine code generation interface.
virtual void addBlankLine()
Emit a blank line to a .s file to pretty it up.
virtual bool emitCVFuncIdDirective(unsigned FunctionId)
Introduces a function id for use with .cv_loc.
virtual void emitBinaryData(StringRef Data)
Functionally identical to EmitBytes.
virtual bool emitCVFileDirective(unsigned FileNo, StringRef Filename, ArrayRef< uint8_t > Checksum, unsigned ChecksumKind)
Associate a filename with a specified logical file number, and also specify that file's checksum info...
virtual void emitCVStringTableDirective()
This implements the CodeView '.cv_stringtable' assembler directive.
virtual bool isVerboseAsm() const
Return true if this streamer supports verbose assembly and if it is enabled.
virtual void emitCVFileChecksumOffsetDirective(unsigned FileNo)
This implements the CodeView '.cv_filechecksumoffset' assembler directive.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitCVFPOData(const MCSymbol *ProcSym, SMLoc Loc={})
This implements the CodeView '.cv_fpo_data' assembler directive.
virtual void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset)
Emits a COFF section relative relocation.
virtual void emitCVFileChecksumsDirective()
This implements the CodeView '.cv_filechecksums' assembler directive.
virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size)
Emit the absolute difference between two symbols.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitCOFFSectionIndex(MCSymbol const *Symbol)
Emits a COFF section index.
virtual void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, const MCSymbol *FnEnd)
This implements the CodeView '.cv_linetable' assembler directive.
virtual void emitValueToAlignment(Align Alignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
virtual void emitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers.
void emitInt16(uint64_t Value)
virtual void switchSection(MCSection *Section, const MCExpr *Subsection=nullptr)
Set the current section where code is being emitted to Section.
virtual void emitCVDefRangeDirective(ArrayRef< std::pair< const MCSymbol *, const MCSymbol * > > Ranges, StringRef FixedSizePortion)
This implements the CodeView '.cv_def_range' assembler directive.
void emitInt32(uint64_t Value)
virtual void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, unsigned Column, bool PrologueEnd, bool IsStmt, StringRef FileName, SMLoc Loc)
This implements the CodeView '.cv_loc' assembler directive.
virtual bool emitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc, unsigned IAFile, unsigned IALine, unsigned IACol, SMLoc Loc)
Introduces an inline call site id for use with .cv_loc.
void emitInt8(uint64_t Value)
virtual void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym)
This implements the CodeView '.cv_inline_linetable' assembler directive.
virtual void emitBytes(StringRef Data)
Emit the bytes in Data into the output.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
ArrayRef< std::string > CommandLineArgs
ArrayRef< MDOperand > operands() const
unsigned getNumOperands() const
Return number of MDNode operands.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
int getOffsetAdjustment() const
Return the correction for frame offsets.
unsigned getCVBytesOfCalleeSavedRegisters() const
Returns how many bytes of callee-saved registers the target pushed in the prologue.
bool hasStackProtectorIndex() const
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
VariableDbgInfoMapTy & getVariableDbgInfo()
ArrayRef< std::pair< MCSymbol *, MDNode * > > getCodeViewAnnotations() const
Representation of each machine instruction.
bool isDebugValue() const
MachineOperand & getDebugOperand(unsigned Index)
const MCContext & getContext() const
const Module * getModule() const
bool hasDebugInfo() const
Returns true if valid debug info is present.
A Module instance is used to store all the information related to an LLVM module.
NamedMDNode * getNamedMetadata(const Twine &Name) const
Return the first NamedMDNode in the module with the specified name.
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
iterator_range< global_iterator > globals()
Metadata * getProfileSummary(bool IsCS) const
Returns profile summary metadata.
iterator_range< op_iterator > operands()
Wrapper class representing virtual and physical registers.
Represents a location in source code.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
static StackOffset getScalable(int64_t Scalable)
static StackOffset getFixed(int64_t Fixed)
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
char back() const
back - Get the last character in the string.
bool startswith(StringRef Prefix) const
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Information about stack frame layout on the target.
virtual bool hasFP(const MachineFunction &MF) const =0
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
CodeGenOpt::Level getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
MCTargetOptions MCOptions
Machine level options.
std::string ObjectFilenameForDebug
Stores the filename/path of the final .o/.obj file, to be written in the debug information.
unsigned Hotpatch
Emit the hotpatch flag in CodeView debug.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetFrameLowering * getFrameLowering() const
TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...
Triple - Helper class for working with autoconf configuration names.
ArchType getArch() const
Get the parsed architecture type of this triple.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
StringRef getName() const
Return a constant reference to the value's name.
@ CurrentDirectory
Absolute CWD path.
@ SourceFile
Path to main source file, relative or absolute.
@ BuildTool
Absolute compiler path.
@ CommandLine
Full canonical command line (maybe -cc1)
@ TypeServerPDB
Absolute path of type server PDB (/Fd)
virtual void emitBytes(StringRef Data)=0
virtual bool isVerboseAsm()=0
virtual void AddComment(const Twine &T)=0
virtual void emitIntValue(uint64_t Value, unsigned Size)=0
virtual void emitBinaryData(StringRef Data)=0
virtual void AddRawComment(const Twine &T)=0
void begin(ContinuationRecordKind RecordKind)
void writeMemberType(RecordType &Record)
ArrayRef< ArrayRef< uint8_t > > records() const
TypeIndex insertRecord(ContinuationRecordBuilder &Builder)
ArrayRef< GloballyHashedType > hashes() const
TypeIndex writeLeafType(T &Record)
For method overload sets. LF_METHOD.
SimpleTypeKind getSimpleKind() const
SimpleTypeMode getSimpleMode() const
static const uint32_t FirstNonSimpleIndex
static StringRef simpleTypeName(TypeIndex TI)
uint32_t getIndex() const
static TypeIndex NullptrT()
void addCallbackToPipeline(TypeVisitorCallbacks &Callbacks)
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
A raw_ostream that writes to an std::string.
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
@ DEBUG_HASHES_SECTION_MAGIC
@ C
The default llvm calling convention, compatible with C.
Reg
All possible values of the reg field in the ModR/M byte.
PointerMode
Equivalent to CV_ptrmode_e.
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 remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
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)
Wrapper function around std::find to detect if an element exists in a container.
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.