diff options
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 f5501a1f0ef..da4c56feeb9 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(); |