summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2016-01-29 18:16:43 +0000
committerReid Kleckner <rnk@google.com>2016-01-29 18:16:43 +0000
commitf3b9ba49419b9d541f639414eadfb0efd4e2a784 (patch)
treee76201034a61c5eefea60762b45cf889ce7037ae /llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
parent0647dbb1d8d808e26165547ed056dd221d6cb0f3 (diff)
downloadbcm5719-llvm-f3b9ba49419b9d541f639414eadfb0efd4e2a784.tar.gz
bcm5719-llvm-f3b9ba49419b9d541f639414eadfb0efd4e2a784.zip
[codeview] Begin to add support for inlined call sites
Summary: There are three parts to inlined call frames: 1. The inlinee line subsection 2. The inline site symbol record 3. The function ids referenced by both This change starts by emitting function ids (3) for all subprograms and emitting the base inline site symbol record (2). The actual line numbers in (2) use an encoded format that will come next, along with the inlinee line subsection. Reviewers: majnemer Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D16333 llvm-svn: 259217
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp139
1 files changed, 138 insertions, 1 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));
OpenPOWER on IntegriCloud