diff options
author | Nikola Prica <nikola.prica@rt-rk.com> | 2019-06-10 08:41:06 +0000 |
---|---|---|
committer | Nikola Prica <nikola.prica@rt-rk.com> | 2019-06-10 08:41:06 +0000 |
commit | abc1dff7e44a9eed6c2cc9a7d9ee366fbe4abcf7 (patch) | |
tree | 53da99a08fdde1c13ce220bc8ca0b9628a371507 /llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | |
parent | 44d908d743d2e42206a8884ab2dea35cd29bb2da (diff) | |
download | llvm-abc1dff7e44a9eed6c2cc9a7d9ee366fbe4abcf7.zip llvm-abc1dff7e44a9eed6c2cc9a7d9ee366fbe4abcf7.tar.gz llvm-abc1dff7e44a9eed6c2cc9a7d9ee366fbe4abcf7.tar.bz2 |
[DebugInfo] More strict debug range for stack variables
Variable's stack location can stretch longer than it should. If a
variable is placed at the stack in a some nested basic block its range
can be calculated to be up to the next occurrence of the variable's
DBG_VALUE, or up to the end of the function, thus covering a basic
blocks that should not be included in the variable’s location range.
This happens because the DbgEntityHistoryCalculator ends register
locations at the end of a basic block only if the variable’s location
register has been changed throughout the function, which is not the
case for the register used to reference stack objects.
This patch also tries to produce a single value location if the location
list builder managed to merge all the locations into one.
Reviewers: aprantl, dstenb, jmorse
Reviewed By: aprantl, dstenb, jmorse
Subscribers: djtodoro, ivanbaev, asowda
Tags: #debug-info
Differential Revision: https://reviews.llvm.org/D61600
llvm-svn: 362923
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 219 |
1 files changed, 131 insertions, 88 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index f5501a1..da4c56f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -244,6 +244,43 @@ const DIType *DbgVariable::getType() const { return Ty; } +/// Get .debug_loc entry for the instruction range starting at MI. +static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { + const DIExpression *Expr = MI->getDebugExpression(); + assert(MI->getNumOperands() == 4); + if (MI->getOperand(0).isReg()) { + auto RegOp = MI->getOperand(0); + auto Op1 = MI->getOperand(1); + // If the second operand is an immediate, this is a + // register-indirect address. + assert((!Op1.isImm() || (Op1.getImm() == 0)) && "unexpected offset"); + MachineLocation MLoc(RegOp.getReg(), Op1.isImm()); + return DebugLocEntry::Value(Expr, MLoc); + } + if (MI->getOperand(0).isImm()) + return DebugLocEntry::Value(Expr, MI->getOperand(0).getImm()); + if (MI->getOperand(0).isFPImm()) + return DebugLocEntry::Value(Expr, MI->getOperand(0).getFPImm()); + if (MI->getOperand(0).isCImm()) + return DebugLocEntry::Value(Expr, MI->getOperand(0).getCImm()); + + llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!"); +} + +void DbgVariable::initializeDbgValue(const MachineInstr *DbgValue) { + assert(FrameIndexExprs.empty() && "Already initialized?"); + assert(!ValueLoc.get() && "Already initialized?"); + + assert(getVariable() == DbgValue->getDebugVariable() && "Wrong variable"); + assert(getInlinedAt() == DbgValue->getDebugLoc()->getInlinedAt() && + "Wrong inlined-at"); + + ValueLoc = llvm::make_unique<DebugLocEntry::Value>(getDebugLocValue(DbgValue)); + if (auto *E = DbgValue->getDebugExpression()) + if (E->getNumElements()) + FrameIndexExprs.push_back({0, E}); +} + ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const { if (FrameIndexExprs.size() == 1) return FrameIndexExprs; @@ -263,8 +300,8 @@ ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const { } void DbgVariable::addMMIEntry(const DbgVariable &V) { - assert(DebugLocListIndex == ~0U && !MInsn && "not an MMI entry"); - assert(V.DebugLocListIndex == ~0U && !V.MInsn && "not an MMI entry"); + assert(DebugLocListIndex == ~0U && !ValueLoc.get() && "not an MMI entry"); + assert(V.DebugLocListIndex == ~0U && !V.ValueLoc.get() && "not an MMI entry"); assert(V.getVariable() == getVariable() && "conflicting variable"); assert(V.getInlinedAt() == getInlinedAt() && "conflicting inlined-at location"); @@ -1075,33 +1112,69 @@ void DwarfDebug::collectVariableInfoFromMFTable( } } -// Get .debug_loc entry for the instruction range starting at MI. -static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { - const DIExpression *Expr = MI->getDebugExpression(); - assert(MI->getNumOperands() == 4); - if (MI->getOperand(0).isReg()) { - auto RegOp = MI->getOperand(0); - auto Op1 = MI->getOperand(1); - // If the second operand is an immediate, this is a - // register-indirect address. - assert((!Op1.isImm() || (Op1.getImm() == 0)) && "unexpected offset"); - MachineLocation MLoc(RegOp.getReg(), Op1.isImm()); - return DebugLocEntry::Value(Expr, MLoc); +/// Determine whether a *singular* DBG_VALUE is valid for the entirety of its +/// enclosing lexical scope. The check ensures there are no other instructions +/// in the same lexical scope preceding the DBG_VALUE and that its range is +/// either open or otherwise rolls off the end of the scope. +static bool validThroughout(LexicalScopes &LScopes, + const MachineInstr *DbgValue, + const MachineInstr *RangeEnd) { + assert(DbgValue->getDebugLoc() && "DBG_VALUE without a debug location"); + auto MBB = DbgValue->getParent(); + auto DL = DbgValue->getDebugLoc(); + auto *LScope = LScopes.findLexicalScope(DL); + // Scope doesn't exist; this is a dead DBG_VALUE. + if (!LScope) + return false; + auto &LSRange = LScope->getRanges(); + if (LSRange.size() == 0) + return false; + + // Determine if the DBG_VALUE is valid at the beginning of its lexical block. + const MachineInstr *LScopeBegin = LSRange.front().first; + // Early exit if the lexical scope begins outside of the current block. + if (LScopeBegin->getParent() != MBB) + return false; + MachineBasicBlock::const_reverse_iterator Pred(DbgValue); + for (++Pred; Pred != MBB->rend(); ++Pred) { + if (Pred->getFlag(MachineInstr::FrameSetup)) + break; + auto PredDL = Pred->getDebugLoc(); + if (!PredDL || Pred->isMetaInstruction()) + continue; + // Check whether the instruction preceding the DBG_VALUE is in the same + // (sub)scope as the DBG_VALUE. + if (DL->getScope() == PredDL->getScope()) + return false; + auto *PredScope = LScopes.findLexicalScope(PredDL); + if (!PredScope || LScope->dominates(PredScope)) + return false; } - if (MI->getOperand(0).isImm()) - return DebugLocEntry::Value(Expr, MI->getOperand(0).getImm()); - if (MI->getOperand(0).isFPImm()) - return DebugLocEntry::Value(Expr, MI->getOperand(0).getFPImm()); - if (MI->getOperand(0).isCImm()) - return DebugLocEntry::Value(Expr, MI->getOperand(0).getCImm()); - llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!"); + // If the range of the DBG_VALUE is open-ended, report success. + if (!RangeEnd) + return true; + + // Fail if there are instructions belonging to our scope in another block. + const MachineInstr *LScopeEnd = LSRange.back().second; + if (LScopeEnd->getParent() != MBB) + return false; + + // Single, constant DBG_VALUEs in the prologue are promoted to be live + // throughout the function. This is a hack, presumably for DWARF v2 and not + // necessarily correct. It would be much better to use a dbg.declare instead + // if we know the constant is live throughout the scope. + if (DbgValue->getOperand(0).isImm() && MBB->pred_empty()) + return true; + + return false; } /// Build the location list for all DBG_VALUEs in the function that /// describe the same variable. The resulting DebugLocEntries will have /// strict monotonically increasing begin addresses and will never -/// overlap. +/// overlap. If the resulting list has only one entry that is valid +/// throughout variable's scope return true. // // See the definition of DbgValueHistoryMap::Entry for an explanation of the // different kinds of history map entries. One thing to be aware of is that if @@ -1130,11 +1203,14 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { // [1-3) [(reg0, fragment 0, 32), (reg1, fragment 32, 32)] // [3-4) [(reg1, fragment 32, 32), (123, fragment 64, 32)] // [4-) [(@g, fragment 0, 96)] -void DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, +bool DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, const DbgValueHistoryMap::Entries &Entries) { using OpenRange = std::pair<DbgValueHistoryMap::EntryIndex, DebugLocEntry::Value>; SmallVector<OpenRange, 4> OpenRanges; + bool isSafeForSingleLocation = true; + const MachineInstr *StartDebugMI = nullptr; + const MachineInstr *EndMI = nullptr; for (auto EB = Entries.begin(), EI = EB, EE = Entries.end(); EI != EE; ++EI) { const MachineInstr *Instr = EI->getInstr(); @@ -1153,8 +1229,11 @@ void DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, "Forgot label before/after instruction starting a range!"); const MCSymbol *EndLabel; - if (std::next(EI) == Entries.end()) + if (std::next(EI) == Entries.end()) { EndLabel = Asm->getFunctionEnd(); + if (EI->isClobber()) + EndMI = EI->getInstr(); + } else if (std::next(EI)->isClobber()) EndLabel = getLabelAfterInsn(std::next(EI)->getInstr()); else @@ -1165,7 +1244,8 @@ void DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, LLVM_DEBUG(dbgs() << "DotDebugLoc: " << *Instr << "\n"); // If this history map entry has a debug value, add that to the list of - // open ranges. + // open ranges and check if its location is valid for a single value + // location. if (EI->isDbgValue()) { // Do not add undef debug values, as they are redundant information in // the location list entries. An undef debug results in an empty location @@ -1176,6 +1256,15 @@ void DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, if (!Instr->isUndefDebugValue()) { auto Value = getDebugLocValue(Instr); OpenRanges.emplace_back(EI->getEndIndex(), Value); + + // TODO: Add support for single value fragment locations. + if (Instr->getDebugExpression()->isFragment()) + isSafeForSingleLocation = false; + + if (!StartDebugMI) + StartDebugMI = Instr; + } else { + isSafeForSingleLocation = false; } } @@ -1209,6 +1298,9 @@ void DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, if (PrevEntry != DebugLoc.rend() && PrevEntry->MergeRanges(*CurEntry)) DebugLoc.pop_back(); } + + return DebugLoc.size() == 1 && isSafeForSingleLocation && + validThroughout(LScopes, StartDebugMI, EndMI); } DbgEntity *DwarfDebug::createConcreteEntity(DwarfCompileUnit &TheCU, @@ -1233,64 +1325,6 @@ DbgEntity *DwarfDebug::createConcreteEntity(DwarfCompileUnit &TheCU, return ConcreteEntities.back().get(); } -/// Determine whether a *singular* DBG_VALUE is valid for the entirety of its -/// enclosing lexical scope. The check ensures there are no other instructions -/// in the same lexical scope preceding the DBG_VALUE and that its range is -/// either open or otherwise rolls off the end of the scope. -static bool validThroughout(LexicalScopes &LScopes, - const MachineInstr *DbgValue, - const MachineInstr *RangeEnd) { - assert(DbgValue->getDebugLoc() && "DBG_VALUE without a debug location"); - auto MBB = DbgValue->getParent(); - auto DL = DbgValue->getDebugLoc(); - auto *LScope = LScopes.findLexicalScope(DL); - // Scope doesn't exist; this is a dead DBG_VALUE. - if (!LScope) - return false; - auto &LSRange = LScope->getRanges(); - if (LSRange.size() == 0) - return false; - - // Determine if the DBG_VALUE is valid at the beginning of its lexical block. - const MachineInstr *LScopeBegin = LSRange.front().first; - // Early exit if the lexical scope begins outside of the current block. - if (LScopeBegin->getParent() != MBB) - return false; - MachineBasicBlock::const_reverse_iterator Pred(DbgValue); - for (++Pred; Pred != MBB->rend(); ++Pred) { - if (Pred->getFlag(MachineInstr::FrameSetup)) - break; - auto PredDL = Pred->getDebugLoc(); - if (!PredDL || Pred->isMetaInstruction()) - continue; - // Check whether the instruction preceding the DBG_VALUE is in the same - // (sub)scope as the DBG_VALUE. - if (DL->getScope() == PredDL->getScope()) - return false; - auto *PredScope = LScopes.findLexicalScope(PredDL); - if (!PredScope || LScope->dominates(PredScope)) - return false; - } - - // If the range of the DBG_VALUE is open-ended, report success. - if (!RangeEnd) - return true; - - // Fail if there are instructions belonging to our scope in another block. - const MachineInstr *LScopeEnd = LSRange.back().second; - if (LScopeEnd->getParent() != MBB) - return false; - - // Single, constant DBG_VALUEs in the prologue are promoted to be live - // throughout the function. This is a hack, presumably for DWARF v2 and not - // necessarily correct. It would be much better to use a dbg.declare instead - // if we know the constant is live throughout the scope. - if (DbgValue->getOperand(0).isImm() && MBB->pred_empty()) - return true; - - return false; -} - // Find variables for each lexical scope. void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP, @@ -1328,9 +1362,10 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, // Check if there is a single DBG_VALUE, valid throughout the var's scope. // If the history map contains a single debug value, there may be an // additional entry which clobbers the debug value. + size_t HistSize = HistoryMapEntries.size(); bool SingleValueWithClobber = - HistoryMapEntries.size() == 2 && HistoryMapEntries[1].isClobber(); - if (HistoryMapEntries.size() == 1 || SingleValueWithClobber) { + HistSize == 2 && HistoryMapEntries[1].isClobber(); + if (HistSize == 1 || SingleValueWithClobber) { const auto *End = SingleValueWithClobber ? HistoryMapEntries[1].getInstr() : nullptr; if (validThroughout(LScopes, MInsn, End)) { @@ -1348,7 +1383,15 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, // Build the location list for this variable. SmallVector<DebugLocEntry, 8> Entries; - buildLocationList(Entries, HistoryMapEntries); + bool isValidSingleLocation = buildLocationList(Entries, HistoryMapEntries); + + // Check whether buildLocationList managed to merge all locations to one + // that is valid throughout the variable's scope. If so, produce single + // value location. + if (isValidSingleLocation) { + RegVar->initializeDbgValue(Entries[0].getValues()[0]); + continue; + } // If the variable has a DIBasicType, extract it. Basic types cannot have // unique identifiers, so don't bother resolving the type with the @@ -1900,8 +1943,8 @@ void DwarfDebug::emitDebugStr() { StringOffsetsSection, /* UseRelativeOffsets = */ true); } -void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, const - DebugLocStream::Entry &Entry, +void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, + const DebugLocStream::Entry &Entry, const DwarfCompileUnit *CU) { auto &&Comments = DebugLocs.getComments(Entry); auto Comment = Comments.begin(); |