summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2016-02-10 20:55:49 +0000
committerReid Kleckner <rnk@google.com>2016-02-10 20:55:49 +0000
commitf9c275fe0a57c7a3af6f791e1c6e3e908697dedb (patch)
tree3aa12eee1f461fe1c7f7c22688f1b20ac320d3d6 /llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
parent75d0dcfde74dcdb2aacfbfa0a52d8bf72416336b (diff)
downloadbcm5719-llvm-f9c275fe0a57c7a3af6f791e1c6e3e908697dedb.tar.gz
bcm5719-llvm-f9c275fe0a57c7a3af6f791e1c6e3e908697dedb.zip
[codeview] Describe int local variables using .cv_def_range
Summary: Refactor common value, scope, and label tracking logic out of DwarfDebug into a common base class called DebugHandlerBase. Update an old LLVM IR test case to avoid an assertion in LexicalScopes. Reviewers: dblaikie, majnemer Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D16931 llvm-svn: 260432
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp208
1 files changed, 152 insertions, 56 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index d571f19a44f..5473228d0b7 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -20,10 +20,26 @@
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/COFF.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetFrameLowering.h"
+using namespace llvm;
using namespace llvm::codeview;
-namespace llvm {
+CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
+ : DebugHandlerBase(AP), OS(*Asm->OutStreamer), CurFn(nullptr) {
+ // If module doesn't have named metadata anchors or COFF debug section
+ // is not available, skip any debug info related stuff.
+ if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") ||
+ !AP->getObjFileLowering().getCOFFDebugSymbolsSection()) {
+ Asm = nullptr;
+ return;
+ }
+
+ // Tell MMI that we have debug info.
+ MMI->setDebugInfoAvailability(true);
+}
StringRef CodeViewDebug::getFullFilepath(const DIFile *File) {
std::string &Filepath = FileToFilepathMap[File];
@@ -92,13 +108,13 @@ unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) {
CodeViewDebug::InlineSite &CodeViewDebug::getInlineSite(const DILocation *Loc) {
const DILocation *InlinedAt = Loc->getInlinedAt();
auto Insertion = CurFn->InlineSites.insert({InlinedAt, InlineSite()});
+ InlineSite *Site = &Insertion.first->second;
if (Insertion.second) {
- InlineSite &Site = Insertion.first->second;
- Site.SiteFuncId = NextFuncId++;
- Site.Inlinee = Loc->getScope()->getSubprogram();
+ Site->SiteFuncId = NextFuncId++;
+ Site->Inlinee = Loc->getScope()->getSubprogram();
InlinedSubprograms.insert(Loc->getScope()->getSubprogram());
}
- return Insertion.first->second;
+ return *Site;
}
void CodeViewDebug::maybeRecordLocation(DebugLoc DL,
@@ -135,6 +151,7 @@ void CodeViewDebug::maybeRecordLocation(DebugLoc DL,
// If this location was actually inlined from somewhere else, give it the ID
// of the inline call site.
FuncId = getInlineSite(DL.get()).SiteFuncId;
+ CurFn->ChildSites.push_back(Loc);
// Ensure we have links in the tree of inline call sites.
const DILocation *ChildLoc = nullptr;
while (Loc->getInlinedAt()) {
@@ -155,22 +172,6 @@ void CodeViewDebug::maybeRecordLocation(DebugLoc DL,
/*IsStmt=*/false, DL->getFilename());
}
-CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
- : Asm(AP), OS(*Asm->OutStreamer), CurFn(nullptr) {
- MachineModuleInfo *MMI = AP->MMI;
-
- // If module doesn't have named metadata anchors or COFF debug section
- // is not available, skip any debug info related stuff.
- if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") ||
- !AP->getObjFileLowering().getCOFFDebugSymbolsSection()) {
- Asm = nullptr;
- return;
- }
-
- // Tell MMI that we have debug info.
- MMI->setDebugInfoAvailability(true);
-}
-
void CodeViewDebug::endModule() {
if (FnDebugInfo.empty())
return;
@@ -215,7 +216,7 @@ void CodeViewDebug::emitTypeInformation() {
OS.EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4);
NamedMDNode *CU_Nodes =
- Asm->MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
+ MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
if (!CU_Nodes)
return;
@@ -277,8 +278,8 @@ void CodeViewDebug::emitInlineeLinesSubsection() {
if (InlinedSubprograms.empty())
return;
- MCSymbol *InlineBegin = Asm->MMI->getContext().createTempSymbol(),
- *InlineEnd = Asm->MMI->getContext().createTempSymbol();
+ MCSymbol *InlineBegin = MMI->getContext().createTempSymbol(),
+ *InlineEnd = MMI->getContext().createTempSymbol();
OS.AddComment("Inlinee lines subsection");
OS.EmitIntValue(unsigned(ModuleSubstreamKind::InlineeLines), 4);
@@ -317,7 +318,6 @@ void CodeViewDebug::collectInlineSiteChildren(
const InlineSite &Site) {
for (const DILocation *ChildSiteLoc : Site.ChildSites) {
auto I = FI.InlineSites.find(ChildSiteLoc);
- assert(I != FI.InlineSites.end());
const InlineSite &ChildSite = I->second;
Children.push_back(ChildSite.SiteFuncId);
collectInlineSiteChildren(Children, FI, ChildSite);
@@ -327,8 +327,8 @@ void CodeViewDebug::collectInlineSiteChildren(
void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
const DILocation *InlinedAt,
const InlineSite &Site) {
- MCSymbol *InlineBegin = Asm->MMI->getContext().createTempSymbol(),
- *InlineEnd = Asm->MMI->getContext().createTempSymbol();
+ MCSymbol *InlineBegin = MMI->getContext().createTempSymbol(),
+ *InlineEnd = MMI->getContext().createTempSymbol();
assert(SubprogramToFuncId.count(Site.Inlinee));
TypeIndex InlineeIdx = SubprogramToFuncId[Site.Inlinee];
@@ -357,6 +357,9 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
OS.EmitLabel(InlineEnd);
+ for (const LocalVariable &Var : Site.InlinedLocals)
+ emitLocalVariable(Var);
+
// Recurse on child inlined call sites before closing the scope.
for (const DILocation *ChildSite : Site.ChildSites) {
auto I = FI.InlineSites.find(ChildSite);
@@ -372,6 +375,13 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
OS.EmitIntValue(SymbolRecordKind::S_INLINESITE_END, 2); // RecordKind
}
+static void emitNullTerminatedString(MCStreamer &OS, StringRef S) {
+ SmallString<32> NullTerminatedString(S);
+ if (NullTerminatedString.empty() || NullTerminatedString.back() != '\0')
+ NullTerminatedString.push_back('\0');
+ OS.EmitBytes(NullTerminatedString);
+}
+
void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
FunctionInfo &FI) {
// For each function there is a separate subsection
@@ -388,16 +398,16 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
FuncName = GlobalValue::getRealLinkageName(GV->getName());
// Emit a symbol subsection, required by VS2012+ to find function boundaries.
- MCSymbol *SymbolsBegin = Asm->MMI->getContext().createTempSymbol(),
- *SymbolsEnd = Asm->MMI->getContext().createTempSymbol();
+ MCSymbol *SymbolsBegin = MMI->getContext().createTempSymbol(),
+ *SymbolsEnd = MMI->getContext().createTempSymbol();
OS.AddComment("Symbol subsection for " + Twine(FuncName));
OS.EmitIntValue(unsigned(ModuleSubstreamKind::Symbols), 4);
OS.AddComment("Subsection size");
OS.emitAbsoluteSymbolDiff(SymbolsEnd, SymbolsBegin, 4);
OS.EmitLabel(SymbolsBegin);
{
- MCSymbol *ProcRecordBegin = Asm->MMI->getContext().createTempSymbol(),
- *ProcRecordEnd = Asm->MMI->getContext().createTempSymbol();
+ MCSymbol *ProcRecordBegin = MMI->getContext().createTempSymbol(),
+ *ProcRecordEnd = MMI->getContext().createTempSymbol();
OS.AddComment("Record length");
OS.emitAbsoluteSymbolDiff(ProcRecordEnd, ProcRecordBegin, 2);
OS.EmitLabel(ProcRecordBegin);
@@ -430,21 +440,20 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
OS.EmitIntValue(0, 1);
// Emit the function display name as a null-terminated string.
OS.AddComment("Function name");
- {
- SmallString<32> NullTerminatedString(FuncName);
- if (NullTerminatedString.empty() || NullTerminatedString.back() != '\0')
- NullTerminatedString.push_back('\0');
- OS.EmitBytes(NullTerminatedString);
- }
+ emitNullTerminatedString(OS, FuncName);
OS.EmitLabel(ProcRecordEnd);
+ for (const LocalVariable &Var : FI.Locals)
+ emitLocalVariable(Var);
+
// 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);
+ for (const DILocation *InlinedAt : FI.ChildSites) {
+ auto I = FI.InlineSites.find(InlinedAt);
+ assert(I != FI.InlineSites.end() &&
+ "child site not in function inline site map");
+ emitInlinedCallSite(FI, InlinedAt, I->second);
}
// We're done with this function.
@@ -461,40 +470,80 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
OS.EmitCVLinetableDirective(FI.FuncId, Fn, FI.End);
}
+void CodeViewDebug::collectVariableInfoFromMMITable() {
+ for (const auto &VI : MMI->getVariableDbgInfo()) {
+ if (!VI.Var)
+ continue;
+ assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&
+ "Expected inlined-at fields to agree");
+
+ LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc);
+
+ // If variable scope is not found then skip this variable.
+ if (!Scope)
+ continue;
+
+ LocalVariable Var;
+ Var.DIVar = VI.Var;
+
+ // Get the frame register used and the offset.
+ unsigned FrameReg = 0;
+ const TargetSubtargetInfo &TSI = Asm->MF->getSubtarget();
+ const TargetFrameLowering *TFI = TSI.getFrameLowering();
+ const TargetRegisterInfo *TRI = TSI.getRegisterInfo();
+ Var.RegisterOffset = TFI->getFrameIndexReference(*Asm->MF, VI.Slot, FrameReg);
+ Var.CVRegister = TRI->getCodeViewRegNum(FrameReg);
+
+ // Calculate the label ranges.
+ for (const InsnRange &Range : Scope->getRanges()) {
+ const MCSymbol *Begin = getLabelBeforeInsn(Range.first);
+ const MCSymbol *End = getLabelAfterInsn(Range.second);
+ Var.Ranges.push_back({Begin, End});
+ }
+
+ if (VI.Loc->getInlinedAt()) {
+ // This variable was inlined. Associate it with the InlineSite.
+ InlineSite &Site = getInlineSite(VI.Loc);
+ Site.InlinedLocals.emplace_back(std::move(Var));
+ } else {
+ // This variable goes in the main ProcSym.
+ CurFn->Locals.emplace_back(std::move(Var));
+ }
+ }
+}
+
void CodeViewDebug::beginFunction(const MachineFunction *MF) {
assert(!CurFn && "Can't process two functions at once!");
- if (!Asm || !Asm->MMI->hasDebugInfo())
+ if (!Asm || !MMI->hasDebugInfo())
return;
+ DebugHandlerBase::beginFunction(MF);
+
const Function *GV = MF->getFunction();
assert(FnDebugInfo.count(GV) == false);
CurFn = &FnDebugInfo[GV];
CurFn->FuncId = NextFuncId++;
CurFn->Begin = Asm->getFunctionBegin();
- // Find the end of the function prolog.
+ // Find the end of the function prolog. First known non-DBG_VALUE and
+ // non-frame setup location marks the beginning of the function body.
// FIXME: is there a simpler a way to do this? Can we just search
// for the first instruction of the function, not the last of the prolog?
DebugLoc PrologEndLoc;
bool EmptyPrologue = true;
for (const auto &MBB : *MF) {
- if (PrologEndLoc)
- break;
for (const auto &MI : MBB) {
- if (MI.isDebugValue())
- continue;
-
- // First known non-DBG_VALUE and non-frame setup location marks
- // the beginning of the function body.
- // FIXME: do we need the first subcondition?
- if (!MI.getFlag(MachineInstr::FrameSetup) && MI.getDebugLoc()) {
+ if (!MI.isDebugValue() && !MI.getFlag(MachineInstr::FrameSetup) &&
+ MI.getDebugLoc()) {
PrologEndLoc = MI.getDebugLoc();
break;
+ } else if (!MI.isDebugValue()) {
+ EmptyPrologue = false;
}
- EmptyPrologue = false;
}
}
+
// Record beginning of function if we have a non-empty prologue.
if (PrologEndLoc && !EmptyPrologue) {
DebugLoc FnStartDL = PrologEndLoc.getFnDebugLoc();
@@ -502,7 +551,50 @@ void CodeViewDebug::beginFunction(const MachineFunction *MF) {
}
}
+void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) {
+ // LocalSym record, see SymbolRecord.h for more info.
+ MCSymbol *LocalBegin = MMI->getContext().createTempSymbol(),
+ *LocalEnd = MMI->getContext().createTempSymbol();
+ OS.AddComment("Record length");
+ OS.emitAbsoluteSymbolDiff(LocalEnd, LocalBegin, 2);
+ OS.EmitLabel(LocalBegin);
+
+ OS.AddComment("Record kind: S_LOCAL");
+ OS.EmitIntValue(unsigned(SymbolRecordKind::S_LOCAL), 2);
+
+ uint16_t Flags = 0;
+ if (Var.DIVar->isParameter())
+ Flags |= LocalSym::IsParameter;
+
+ OS.AddComment("TypeIndex");
+ OS.EmitIntValue(TypeIndex::Int32().getIndex(), 4);
+ OS.AddComment("Flags");
+ OS.EmitIntValue(Flags, 2);
+ emitNullTerminatedString(OS, Var.DIVar->getName());
+ OS.EmitLabel(LocalEnd);
+
+ // DefRangeRegisterRelSym record, see SymbolRecord.h for more info. Omit the
+ // LocalVariableAddrRange field from the record. The directive will emit that.
+ DefRangeRegisterRelSym Sym{};
+ ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER_REL);
+ Sym.BaseRegister = Var.CVRegister;
+ Sym.Flags = 0; // Unclear what matters here.
+ Sym.BasePointerOffset = Var.RegisterOffset;
+ SmallString<sizeof(Sym) + sizeof(SymKind) - sizeof(LocalVariableAddrRange)>
+ BytePrefix;
+ BytePrefix += StringRef(reinterpret_cast<const char *>(&SymKind),
+ sizeof(SymKind));
+ BytePrefix += StringRef(reinterpret_cast<const char *>(&Sym),
+ sizeof(Sym) - sizeof(LocalVariableAddrRange));
+
+ OS.EmitCVDefRangeDirective(Var.Ranges, BytePrefix);
+}
+
void CodeViewDebug::endFunction(const MachineFunction *MF) {
+ collectVariableInfoFromMMITable();
+
+ DebugHandlerBase::endFunction(MF);
+
if (!Asm || !CurFn) // We haven't created any debug info for this function.
return;
@@ -513,13 +605,18 @@ void CodeViewDebug::endFunction(const MachineFunction *MF) {
// Don't emit anything if we don't have any line tables.
if (!CurFn->HaveLineInfo) {
FnDebugInfo.erase(GV);
- } else {
- CurFn->End = Asm->getFunctionEnd();
+ CurFn = nullptr;
+ return;
}
+
+ CurFn->End = Asm->getFunctionEnd();
+
CurFn = nullptr;
}
void CodeViewDebug::beginInstruction(const MachineInstr *MI) {
+ DebugHandlerBase::beginInstruction(MI);
+
// Ignore DBG_VALUE locations and function prologue.
if (!Asm || MI->isDebugValue() || MI->getFlag(MachineInstr::FrameSetup))
return;
@@ -528,4 +625,3 @@ void CodeViewDebug::beginInstruction(const MachineInstr *MI) {
return;
maybeRecordLocation(DL, Asm->MF);
}
-}
OpenPOWER on IntegriCloud