summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp139
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h30
-rw-r--r--llvm/lib/MC/MCObjectFileInfo.cpp13
3 files changed, 177 insertions, 5 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index b503f1dc31e..e3c48296f34 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -15,6 +15,8 @@
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/COFF.h"
@@ -87,6 +89,17 @@ unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) {
return Insertion.first->second;
}
+CodeViewDebug::InlineSite &CodeViewDebug::getInlineSite(const DILocation *Loc) {
+ const DILocation *InlinedAt = Loc->getInlinedAt();
+ auto Insertion = CurFn->InlineSites.insert({InlinedAt, InlineSite()});
+ if (Insertion.second) {
+ InlineSite &Site = Insertion.first->second;
+ Site.SiteFuncId = NextFuncId++;
+ Site.Inlinee = Loc->getScope()->getSubprogram();
+ }
+ return Insertion.first->second;
+}
+
void CodeViewDebug::maybeRecordLocation(DebugLoc DL,
const MachineFunction *MF) {
// Skip this instruction if it has the same location as the previous one.
@@ -115,7 +128,28 @@ void CodeViewDebug::maybeRecordLocation(DebugLoc DL,
else
FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile());
CurFn->LastLoc = DL;
- Asm->OutStreamer->EmitCVLocDirective(CurFn->FuncId, FileId, DL.getLine(),
+
+ unsigned FuncId = CurFn->FuncId;
+ if (const DILocation *Loc = DL->getInlinedAt()) {
+ // If this location was actually inlined from somewhere else, give it the ID
+ // of the inline call site.
+ FuncId = getInlineSite(DL.get()).SiteFuncId;
+ // Ensure we have links in the tree of inline call sites.
+ const DILocation *ChildLoc = nullptr;
+ while (Loc->getInlinedAt()) {
+ InlineSite &Site = getInlineSite(Loc);
+ if (ChildLoc) {
+ // Record the child inline site if not already present.
+ auto B = Site.ChildSites.begin(), E = Site.ChildSites.end();
+ if (std::find(B, E, Loc) != E)
+ break;
+ Site.ChildSites.push_back(Loc);
+ }
+ ChildLoc = Loc;
+ }
+ }
+
+ Asm->OutStreamer->EmitCVLocDirective(FuncId, FileId, DL.getLine(),
DL.getCol(), /*PrologueEnd=*/false,
/*IsStmt=*/false, DL->getFilename());
}
@@ -139,6 +173,8 @@ void CodeViewDebug::endModule() {
if (FnDebugInfo.empty())
return;
+ emitTypeInformation();
+
// FIXME: For functions that are comdat, we should emit separate .debug$S
// sections that are comdat associative with the main function instead of
// having one big .debug$S section.
@@ -167,6 +203,60 @@ void CodeViewDebug::endModule() {
clear();
}
+template <typename T> static void emitRecord(MCStreamer &OS, const T &Rec) {
+ OS.EmitBytes(StringRef(reinterpret_cast<const char *>(&Rec), sizeof(Rec)));
+}
+
+void CodeViewDebug::emitTypeInformation() {
+ // Start the .debug$T section with 0x4.
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getCOFFDebugTypesSection());
+ Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC);
+
+ NamedMDNode *CU_Nodes =
+ Asm->MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
+ if (!CU_Nodes)
+ return;
+
+ // This type info currently only holds function ids for use with inline call
+ // frame info. All functions are assigned a simple 'void ()' type. Emit that
+ // type here.
+ TypeIndex ArgListIdx = getNextTypeIndex();
+ Asm->EmitInt16(2 + sizeof(ArgList));
+ Asm->EmitInt16(LF_ARGLIST);
+ Asm->EmitInt32(0);
+
+ TypeIndex VoidProcIdx = getNextTypeIndex();
+ Asm->EmitInt16(2 + sizeof(ProcedureType));
+ Asm->EmitInt16(LF_PROCEDURE);
+ ProcedureType Proc{}; // Zero initialize.
+ Proc.ReturnType = TypeIndex::Void();
+ Proc.CallConv = CallingConvention::NearC;
+ Proc.Options = FunctionOptions::None;
+ Proc.NumParameters = 0;
+ Proc.ArgListType = ArgListIdx;
+ emitRecord(*Asm->OutStreamer, Proc);
+
+ for (MDNode *N : CU_Nodes->operands()) {
+ auto *CUNode = cast<DICompileUnit>(N);
+ for (auto *SP : CUNode->getSubprograms()) {
+ StringRef DisplayName = SP->getDisplayName();
+ Asm->EmitInt16(2 + sizeof(FuncId) + DisplayName.size() + 1);
+ Asm->EmitInt16(LF_FUNC_ID);
+
+ FuncId Func{}; // Zero initialize.
+ Func.ParentScope = TypeIndex();
+ Func.FunctionType = VoidProcIdx;
+ emitRecord(*Asm->OutStreamer, Func);
+ Asm->OutStreamer->EmitBytes(DisplayName);
+ Asm->EmitInt8(0);
+
+ TypeIndex FuncIdIdx = getNextTypeIndex();
+ SubprogramToFuncId.insert(std::make_pair(SP, FuncIdIdx));
+ }
+ }
+}
+
static void EmitLabelDiff(MCStreamer &Streamer,
const MCSymbol *From, const MCSymbol *To,
unsigned int Size = 4) {
@@ -179,6 +269,44 @@ static void EmitLabelDiff(MCStreamer &Streamer,
Streamer.EmitValue(AddrDelta, Size);
}
+void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
+ const DILocation *InlinedAt,
+ const InlineSite &Site) {
+ MCStreamer &OS = *Asm->OutStreamer;
+
+ MCSymbol *InlineBegin = Asm->MMI->getContext().createTempSymbol(),
+ *InlineEnd = Asm->MMI->getContext().createTempSymbol();
+
+ assert(SubprogramToFuncId.count(Site.Inlinee));
+ TypeIndex InlineeIdx = SubprogramToFuncId[Site.Inlinee];
+
+ // SymbolRecord
+ EmitLabelDiff(OS, InlineBegin, InlineEnd, 2); // RecordLength
+ OS.EmitLabel(InlineBegin);
+ Asm->EmitInt16(SymbolRecordKind::S_INLINESITE); // RecordKind
+
+ InlineSiteSym SiteBytes{};
+ SiteBytes.Inlinee = InlineeIdx;
+ Asm->OutStreamer->EmitBytes(
+ StringRef(reinterpret_cast<const char *>(&SiteBytes), sizeof(SiteBytes)));
+
+ // FIXME: annotations
+
+ OS.EmitLabel(InlineEnd);
+
+ // Recurse on child inlined call sites before closing the scope.
+ for (const DILocation *ChildSite : Site.ChildSites) {
+ auto I = FI.InlineSites.find(ChildSite);
+ assert(I != FI.InlineSites.end() &&
+ "child site not in function inline site map");
+ emitInlinedCallSite(FI, ChildSite, I->second);
+ }
+
+ // Close the scope.
+ Asm->EmitInt16(2); // RecordLength
+ Asm->EmitInt16(SymbolRecordKind::S_INLINESITE_END); // RecordKind
+}
+
void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
FunctionInfo &FI) {
// For each function there is a separate subsection
@@ -224,6 +352,15 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
Asm->EmitInt8(0);
Asm->OutStreamer->EmitLabel(ProcSegmentEnd);
+ // Emit inlined call site information. Only emit functions inlined directly
+ // into the parent function. We'll emit the other sites recursively as part
+ // of their parent inline site.
+ for (auto &KV : FI.InlineSites) {
+ const DILocation *InlinedAt = KV.first;
+ if (!InlinedAt->getInlinedAt())
+ emitInlinedCallSite(FI, InlinedAt, KV.second);
+ }
+
// We're done with this function.
Asm->EmitInt16(0x0002);
Asm->EmitInt16(unsigned(SymbolRecordKind::S_PROC_ID_END));
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index 77b5ed39c1f..4883905e907 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -22,6 +22,7 @@
#include "llvm/CodeGen/LexicalScopes.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/MC/MCStreamer.h"
@@ -33,19 +34,31 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler {
AsmPrinter *Asm;
DebugLoc PrevInstLoc;
+ struct InlineSite {
+ TinyPtrVector<const DILocation *> ChildSites;
+ const DISubprogram *Inlinee = nullptr;
+ unsigned SiteFuncId = 0;
+ };
+
// For each function, store a vector of labels to its instructions, as well as
// to the end of the function.
struct FunctionInfo {
+ /// Map from inlined call site to inlined instructions and child inlined
+ /// call sites. Listed in program order.
+ MapVector<const DILocation *, InlineSite> InlineSites;
+
DebugLoc LastLoc;
MCSymbol *End = nullptr;
unsigned FuncId = 0;
- unsigned LastFileId;
+ unsigned LastFileId = 0;
bool HaveLineInfo = false;
};
FunctionInfo *CurFn;
unsigned NextFuncId = 0;
+ InlineSite &getInlineSite(const DILocation *Loc);
+
/// Remember some debug info about each function. Keep it in a stable order to
/// emit at the end of the TU.
MapVector<const Function *, FunctionInfo> FnDebugInfo;
@@ -53,6 +66,16 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler {
/// Map from DIFile to .cv_file id.
DenseMap<const DIFile *, unsigned> FileIdMap;
+ DenseMap<const DISubprogram *, codeview::TypeIndex> SubprogramToFuncId;
+
+ unsigned TypeCount = 0;
+
+ /// Gets the next type index and increments the count of types streamed so
+ /// far.
+ codeview::TypeIndex getNextTypeIndex() {
+ return codeview::TypeIndex(codeview::TypeIndex::FirstNonSimpleIndex + TypeCount++);
+ }
+
typedef std::map<const DIFile *, std::string> FileToFilepathMapTy;
FileToFilepathMapTy FileToFilepathMap;
StringRef getFullFilepath(const DIFile *S);
@@ -68,8 +91,13 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public AsmPrinterHandler {
FileToFilepathMap.clear();
}
+ void emitTypeInformation();
+
void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI);
+ void emitInlinedCallSite(const FunctionInfo &FI, const DILocation *InlinedAt,
+ const InlineSite &Site);
+
public:
CodeViewDebug(AsmPrinter *Asm);
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index 0c86fa81c1b..05eadeb44a5 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -191,6 +191,7 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(Triple T) {
SectionKind::getReadOnlyWithRel());
COFFDebugSymbolsSection = nullptr;
+ COFFDebugTypesSection = nullptr;
if (useCompactUnwind(T)) {
CompactUnwindSection =
@@ -484,6 +485,7 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) {
ELF::SHF_ALLOC);
COFFDebugSymbolsSection = nullptr;
+ COFFDebugTypesSection = nullptr;
// Debug Info Sections.
DwarfAbbrevSection = Ctx->getELFSection(".debug_abbrev", ELF::SHT_PROGBITS, 0,
@@ -623,9 +625,14 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(Triple T) {
// Debug info.
COFFDebugSymbolsSection =
- Ctx->getCOFFSection(".debug$S", COFF::IMAGE_SCN_MEM_DISCARDABLE |
- COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- COFF::IMAGE_SCN_MEM_READ,
+ Ctx->getCOFFSection(".debug$S", (COFF::IMAGE_SCN_MEM_DISCARDABLE |
+ COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ),
+ SectionKind::getMetadata());
+ COFFDebugTypesSection =
+ Ctx->getCOFFSection(".debug$T", (COFF::IMAGE_SCN_MEM_DISCARDABLE |
+ COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+ COFF::IMAGE_SCN_MEM_READ),
SectionKind::getMetadata());
DwarfAbbrevSection = Ctx->getCOFFSection(
OpenPOWER on IntegriCloud