diff options
Diffstat (limited to 'lib/CodeGen/LiveDebugVariables.cpp')
-rw-r--r-- | lib/CodeGen/LiveDebugVariables.cpp | 181 |
1 files changed, 138 insertions, 43 deletions
diff --git a/lib/CodeGen/LiveDebugVariables.cpp b/lib/CodeGen/LiveDebugVariables.cpp index d0d889782a35..656ec7d4bdfd 100644 --- a/lib/CodeGen/LiveDebugVariables.cpp +++ b/lib/CodeGen/LiveDebugVariables.cpp @@ -1,9 +1,8 @@ //===- LiveDebugVariables.cpp - Tracking debug info variables -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -23,6 +22,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntervalMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" @@ -71,6 +71,7 @@ EnableLDV("live-debug-variables", cl::init(true), cl::desc("Enable the live debug variables pass"), cl::Hidden); STATISTIC(NumInsertedDebugValues, "Number of DBG_VALUEs inserted"); +STATISTIC(NumInsertedDebugLabels, "Number of DBG_LABELs inserted"); char LiveDebugVariables::ID = 0; @@ -166,10 +167,6 @@ class UserValue { /// Map of slot indices where this value is live. LocMap locInts; - /// Set of interval start indexes that have been trimmed to the - /// lexical scope. - SmallSet<SlotIndex, 2> trimmedDefs; - /// Insert a DBG_VALUE into MBB at Idx for LocNo. void insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx, SlotIndex StopIdx, DbgValueLocation Loc, bool Spilled, @@ -339,6 +336,37 @@ public: void print(raw_ostream &, const TargetRegisterInfo *); }; +/// A user label is a part of a debug info user label. +class UserLabel { + const DILabel *Label; ///< The debug info label we are part of. + DebugLoc dl; ///< The debug location for the label. This is + ///< used by dwarf writer to find lexical scope. + SlotIndex loc; ///< Slot used by the debug label. + + /// Insert a DBG_LABEL into MBB at Idx. + void insertDebugLabel(MachineBasicBlock *MBB, SlotIndex Idx, + LiveIntervals &LIS, const TargetInstrInfo &TII); + +public: + /// Create a new UserLabel. + UserLabel(const DILabel *label, DebugLoc L, SlotIndex Idx) + : Label(label), dl(std::move(L)), loc(Idx) {} + + /// Does this UserLabel match the parameters? + bool match(const DILabel *L, const DILocation *IA, + const SlotIndex Index) const { + return Label == L && dl->getInlinedAt() == IA && loc == Index; + } + + /// Recreate DBG_LABEL instruction from data structures. + void emitDebugLabel(LiveIntervals &LIS, const TargetInstrInfo &TII); + + /// Return DebugLoc of this UserLabel. + DebugLoc getDebugLoc() { return dl; } + + void print(raw_ostream &, const TargetRegisterInfo *); +}; + /// Implementation of the LiveDebugVariables pass. class LDVImpl { LiveDebugVariables &pass; @@ -356,6 +384,9 @@ class LDVImpl { /// All allocated UserValue instances. SmallVector<std::unique_ptr<UserValue>, 8> userValues; + /// All allocated UserLabel instances. + SmallVector<std::unique_ptr<UserLabel>, 2> userLabels; + /// Map virtual register to eq class leader. using VRMap = DenseMap<unsigned, UserValue *>; VRMap virtRegToEqClass; @@ -379,6 +410,14 @@ class LDVImpl { /// \returns True if the DBG_VALUE instruction should be deleted. bool handleDebugValue(MachineInstr &MI, SlotIndex Idx); + /// Add DBG_LABEL instruction to UserLabel. + /// + /// \param MI DBG_LABEL instruction + /// \param Idx Last valid SlotIndex before instruction. + /// + /// \returns True if the DBG_LABEL instruction should be deleted. + bool handleDebugLabel(MachineInstr &MI, SlotIndex Idx); + /// Collect and erase all DBG_VALUE instructions, adding a UserValue def /// for each instruction. /// @@ -400,6 +439,7 @@ public: void clear() { MF = nullptr; userValues.clear(); + userLabels.clear(); virtRegToEqClass.clear(); userVarMap.clear(); // Make sure we call emitDebugValues if the machine function was modified. @@ -445,13 +485,23 @@ static void printDebugLoc(const DebugLoc &DL, raw_ostream &CommentOS, CommentOS << " ]"; } -static void printExtendedName(raw_ostream &OS, const DILocalVariable *V, +static void printExtendedName(raw_ostream &OS, const DINode *Node, const DILocation *DL) { - const LLVMContext &Ctx = V->getContext(); - StringRef Res = V->getName(); + const LLVMContext &Ctx = Node->getContext(); + StringRef Res; + unsigned Line; + if (const auto *V = dyn_cast<const DILocalVariable>(Node)) { + Res = V->getName(); + Line = V->getLine(); + } else if (const auto *L = dyn_cast<const DILabel>(Node)) { + Res = L->getName(); + Line = L->getLine(); + } + if (!Res.empty()) - OS << Res << "," << V->getLine(); - if (auto *InlinedAt = DL->getInlinedAt()) { + OS << Res << "," << Line; + auto *InlinedAt = DL ? DL->getInlinedAt() : nullptr; + if (InlinedAt) { if (DebugLoc InlinedAtDL = InlinedAt) { OS << " @["; printDebugLoc(InlinedAtDL, OS, Ctx); @@ -461,9 +511,8 @@ static void printExtendedName(raw_ostream &OS, const DILocalVariable *V, } void UserValue::print(raw_ostream &OS, const TargetRegisterInfo *TRI) { - auto *DV = cast<DILocalVariable>(Variable); OS << "!\""; - printExtendedName(OS, DV, dl); + printExtendedName(OS, Variable, dl); OS << "\"\t"; for (LocMap::const_iterator I = locInts.begin(); I.valid(); ++I) { @@ -483,10 +532,22 @@ void UserValue::print(raw_ostream &OS, const TargetRegisterInfo *TRI) { OS << '\n'; } +void UserLabel::print(raw_ostream &OS, const TargetRegisterInfo *TRI) { + OS << "!\""; + printExtendedName(OS, Label, dl); + + OS << "\"\t"; + OS << loc; + OS << '\n'; +} + void LDVImpl::print(raw_ostream &OS) { OS << "********** DEBUG VARIABLES **********\n"; - for (unsigned i = 0, e = userValues.size(); i != e; ++i) - userValues[i]->print(OS, TRI); + for (auto &userValue : userValues) + userValue->print(OS, TRI); + OS << "********** DEBUG LABELS **********\n"; + for (auto &userLabel : userLabels) + userLabel->print(OS, TRI); } #endif @@ -556,7 +617,7 @@ bool LDVImpl::handleDebugValue(MachineInstr &MI, SlotIndex Idx) { } else { // The DBG_VALUE is only valid if either Reg is live out from Idx, or Reg // is defined dead at Idx (where Idx is the slot index for the instruction - // preceeding the DBG_VALUE). + // preceding the DBG_VALUE). const LiveInterval &LI = LIS->getInterval(Reg); LiveQueryResult LRQ = LI.Query(Idx); if (!LRQ.valueOutOrDead()) { @@ -587,6 +648,29 @@ bool LDVImpl::handleDebugValue(MachineInstr &MI, SlotIndex Idx) { return true; } +bool LDVImpl::handleDebugLabel(MachineInstr &MI, SlotIndex Idx) { + // DBG_LABEL label + if (MI.getNumOperands() != 1 || !MI.getOperand(0).isMetadata()) { + LLVM_DEBUG(dbgs() << "Can't handle " << MI); + return false; + } + + // Get or create the UserLabel for label here. + const DILabel *Label = MI.getDebugLabel(); + const DebugLoc &DL = MI.getDebugLoc(); + bool Found = false; + for (auto const &L : userLabels) { + if (L->match(Label, DL->getInlinedAt(), Idx)) { + Found = true; + break; + } + } + if (!Found) + userLabels.push_back(llvm::make_unique<UserLabel>(Label, DL, Idx)); + + return true; +} + bool LDVImpl::collectDebugValues(MachineFunction &mf) { bool Changed = false; for (MachineFunction::iterator MFI = mf.begin(), MFE = mf.end(); MFI != MFE; @@ -610,7 +694,8 @@ bool LDVImpl::collectDebugValues(MachineFunction &mf) { do { // Only handle DBG_VALUE in handleDebugValue(). Skip all other // kinds of debug instructions. - if (MBBI->isDebugValue() && handleDebugValue(*MBBI, Idx)) { + if ((MBBI->isDebugValue() && handleDebugValue(*MBBI, Idx)) || + (MBBI->isDebugLabel() && handleDebugLabel(*MBBI, Idx))) { MBBI = MBB->erase(MBBI); Changed = true; } else @@ -655,10 +740,8 @@ void UserValue::extendDef(SlotIndex Idx, DbgValueLocation Loc, LiveRange *LR, } // Limited by the next def. - if (I.valid() && I.start() < Stop) { + if (I.valid() && I.start() < Stop) Stop = I.start(); - ToEnd = false; - } // Limited by VNI's live range. else if (!ToEnd && Kills) Kills->push_back(Stop); @@ -826,8 +909,7 @@ void UserValue::computeIntervals(MachineRegisterInfo &MRI, ++I; // If the interval also overlaps the start of the "next" (i.e. - // current) range create a new interval for the remainder (which - // may be further trimmed). + // current) range create a new interval for the remainder if (RStart < IStop) I.insert(RStart, IStop, Loc); } @@ -837,13 +919,6 @@ void UserValue::computeIntervals(MachineRegisterInfo &MRI, if (!I.valid()) return; - if (I.start() < RStart) { - // Interval start overlaps range - trim to the scope range. - I.setStartUnchecked(RStart); - // Remember that this interval was trimmed. - trimmedDefs.insert(RStart); - } - // The end of a lexical scope range is the last instruction in the // range. To convert to an interval we need the index of the // instruction after it. @@ -1227,11 +1302,13 @@ void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx, // that the original virtual register was a pointer. Also, add the stack slot // offset for the spilled register to the expression. const DIExpression *Expr = Expression; + uint8_t DIExprFlags = DIExpression::ApplyOffset; bool IsIndirect = Loc.wasIndirect(); if (Spilled) { - auto Deref = IsIndirect ? DIExpression::WithDeref : DIExpression::NoDeref; + if (IsIndirect) + DIExprFlags |= DIExpression::DerefAfter; Expr = - DIExpression::prepend(Expr, DIExpression::NoDeref, SpillOffset, Deref); + DIExpression::prepend(Expr, DIExprFlags, SpillOffset); IsIndirect = true; } @@ -1247,6 +1324,15 @@ void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx, } while (I != MBB->end()); } +void UserLabel::insertDebugLabel(MachineBasicBlock *MBB, SlotIndex Idx, + LiveIntervals &LIS, + const TargetInstrInfo &TII) { + MachineBasicBlock::iterator I = findInsertLocation(MBB, Idx, LIS); + ++NumInsertedDebugLabels; + BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_LABEL)) + .addMetadata(Label); +} + void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, @@ -1262,12 +1348,6 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS, bool Spilled = SpillIt != SpillOffsets.end(); unsigned SpillOffset = Spilled ? SpillIt->second : 0; - // If the interval start was trimmed to the lexical scope insert the - // DBG_VALUE at the previous index (otherwise it appears after the - // first instruction in the range). - if (trimmedDefs.count(Start)) - Start = Start.getPrevIndex(); - LLVM_DEBUG(dbgs() << "\t[" << Start << ';' << Stop << "):" << Loc.locNo()); MachineFunction::iterator MBB = LIS.getMBBFromIndex(Start)->getIterator(); SlotIndex MBBEnd = LIS.getMBBEndIdx(&*MBB); @@ -1295,16 +1375,31 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS, } } +void UserLabel::emitDebugLabel(LiveIntervals &LIS, const TargetInstrInfo &TII) { + LLVM_DEBUG(dbgs() << "\t" << loc); + MachineFunction::iterator MBB = LIS.getMBBFromIndex(loc)->getIterator(); + + LLVM_DEBUG(dbgs() << ' ' << printMBBReference(*MBB)); + insertDebugLabel(&*MBB, loc, LIS, TII); + + LLVM_DEBUG(dbgs() << '\n'); +} + void LDVImpl::emitDebugValues(VirtRegMap *VRM) { LLVM_DEBUG(dbgs() << "********** EMITTING LIVE DEBUG VARIABLES **********\n"); if (!MF) return; const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo(); SpillOffsetMap SpillOffsets; - for (unsigned i = 0, e = userValues.size(); i != e; ++i) { - LLVM_DEBUG(userValues[i]->print(dbgs(), TRI)); - userValues[i]->rewriteLocations(*VRM, *MF, *TII, *TRI, SpillOffsets); - userValues[i]->emitDebugValues(VRM, *LIS, *TII, *TRI, SpillOffsets); + for (auto &userValue : userValues) { + LLVM_DEBUG(userValue->print(dbgs(), TRI)); + userValue->rewriteLocations(*VRM, *MF, *TII, *TRI, SpillOffsets); + userValue->emitDebugValues(VRM, *LIS, *TII, *TRI, SpillOffsets); + } + LLVM_DEBUG(dbgs() << "********** EMITTING LIVE DEBUG LABELS **********\n"); + for (auto &userLabel : userLabels) { + LLVM_DEBUG(userLabel->print(dbgs(), TRI)); + userLabel->emitDebugLabel(*LIS, *TII); } EmitDone = true; } |