33#define DEBUG_TYPE "dwarfdebug"
56 unsigned Position = 0;
59 InstNumberMap[&
MI] =
MI.isMetaInstruction() ? Position : ++Position;
64 assert(
A->getParent() &&
B->getParent() &&
"Operands must have a parent");
66 "Operands must be in the same MachineFunction");
67 return InstNumberMap.lookup(
A) < InstNumberMap.lookup(
B);
75 assert(
MI.isDebugValue() &&
"not a DBG_VALUE");
76 auto &
Entries = VarEntries[Var];
79 Entries.back().getInstr()->isEquivalentDbgInstr(
MI)) {
81 <<
"\t" <<
Entries.back().getInstr() <<
"\t" <<
MI
92 auto &
Entries = VarEntries[Var];
113static std::optional<ArrayRef<InsnRange>::iterator>
116 for (
auto RangesI = Ranges.begin(), RangesE = Ranges.end();
117 RangesI != RangesE; ++RangesI) {
118 if (EndMI && Ordering.isBefore(EndMI, RangesI->first))
120 if (EndMI && !Ordering.isBefore(RangesI->second, EndMI))
122 if (Ordering.isBefore(StartMI, RangesI->second))
143 for (
auto &
Record : VarEntries) {
144 auto &HistoryMapEntries =
Record.second;
145 if (HistoryMapEntries.empty())
152 if (
const DILocation *InlinedAt = Entity.second) {
164 (Scope->getScopeNode() == Scope->getScopeNode()->getSubprogram()) &&
165 (Scope->getScopeNode() == LocalVar->getScope()))
176 ReferenceCount.
assign(HistoryMapEntries.size(), 0);
181 for (
auto EI = HistoryMapEntries.begin(), EE = HistoryMapEntries.end();
182 EI != EE; ++EI, ++StartIndex) {
184 if (!EI->isDbgValue())
191 ReferenceCount[EndIndex] += 1;
196 if (ReferenceCount[StartIndex] > 0)
201 ? HistoryMapEntries[EndIndex].getInstr()
205 if (
auto R =
intersects(StartMI, EndMI, ScopeRanges, Ordering)) {
217 ReferenceCount[EndIndex] -= 1;
218 LLVM_DEBUG(
dbgs() <<
"Dropping value outside scope range of variable: ";
228 for (
size_t i = 0; i < HistoryMapEntries.size(); ++i)
229 if (ReferenceCount[i] <= 0 && HistoryMapEntries[i].isClobber())
237 Offsets.assign(HistoryMapEntries.size(), 0);
238 size_t CurOffset = 0;
239 auto ToRemoveItr =
ToRemove.begin();
240 for (
size_t EntryIdx = *ToRemoveItr; EntryIdx < HistoryMapEntries.size();
243 if (ToRemoveItr !=
ToRemove.end() && *ToRemoveItr == EntryIdx) {
247 Offsets[EntryIdx] = CurOffset;
252 for (
auto &
Entry : HistoryMapEntries)
259 HistoryMapEntries.erase(HistoryMapEntries.begin() + Idx);
261 <<
"') size: " << HistoryMapEntries.size() <<
"\n");
273 if (
MI->isUndefDebugValue())
283 assert(
MI.isDebugLabel() &&
"not a DBG_LABEL");
284 LabelInstr[Label] = &
MI;
291using RegDescribedVarsMap = std::map<unsigned, SmallVector<InlinedEntity, 1>>;
297using DbgValueEntriesMap = std::map<InlinedEntity, SmallSet<EntryIndex, 1>>;
304 const auto &
I = RegVars.find(RegNo);
305 assert(RegNo != 0U &&
I != RegVars.end());
306 auto &VarSet =
I->second;
308 assert(VarPos != VarSet.end());
309 VarSet.erase(VarPos);
319 auto &VarSet = RegVars[RegNo];
321 VarSet.push_back(Var);
330 DbgValueEntriesMap &LiveEntries,
341 for (
auto Index : LiveEntries[Var]) {
342 auto &Entry = HistMap.
getEntry(Var, Index);
343 assert(Entry.isDbgValue() &&
"Not a DBG_VALUE in LiveEntries");
344 if (Entry.getInstr()->isDebugEntryValue())
346 if (Entry.getInstr()->hasDebugOperandForReg(RegNo)) {
348 Entry.endEntry(ClobberIndex);
349 for (
const auto &MO : Entry.getInstr()->debug_operands())
350 if (MO.isReg() && MO.getReg() && MO.getReg() != RegNo)
351 MaybeRemovedRegisters.
insert(MO.getReg());
353 for (
const auto &MO : Entry.getInstr()->debug_operands())
354 if (MO.isReg() && MO.getReg())
355 KeepRegisters.
insert(MO.getReg());
364 auto &
Entries = LiveEntries[Var];
365 for (
auto Index : IndicesToErase)
371 RegDescribedVarsMap &RegVars,
372 DbgValueEntriesMap &LiveEntries,
394 for (
auto Index : LiveEntries[Var]) {
395 auto &Entry = HistMap.
getEntry(Var, Index);
396 assert(Entry.isDbgValue() &&
"Not a DBG_VALUE in LiveEntries");
401 Entry.endEntry(NewIndex);
405 if (
Op.isReg() &&
Op.getReg())
406 TrackedRegs[
Op.getReg()] |= !Overlaps;
413 if (
Op.isReg() &&
Op.getReg()) {
417 LiveEntries[Var].insert(NewIndex);
423 for (
auto I : TrackedRegs)
428 auto &
Entries = LiveEntries[Var];
429 for (
auto Index : IndicesToErase)
438 RegDescribedVarsMap::iterator
I,
440 DbgValueEntriesMap &LiveEntries,
446 for (
const auto &Var :
I->second) {
450 for (
Register RegNo : FellowRegisters)
460 DbgValueEntriesMap &LiveEntries,
462 const auto &
I = RegVars.find(RegNo);
463 if (
I == RegVars.end())
475 RegDescribedVarsMap RegVars;
476 DbgValueEntriesMap LiveEntries;
477 for (
const auto &
MBB : *MF) {
478 for (
const auto &
MI :
MBB) {
479 if (
MI.isDebugValue()) {
480 assert(
MI.getNumOperands() > 1 &&
"Invalid DBG_VALUE instruction!");
483 "Expected inlined-at fields to agree");
487 }
else if (
MI.isDebugLabel()) {
488 assert(
MI.getNumOperands() == 1 &&
"Invalid DBG_LABEL instruction!");
489 const DILabel *RawLabel =
MI.getDebugLabel();
491 "Expected inlined-at fields to agree");
501 if (
MI.isMetaInstruction())
506 if (MO.isReg() && MO.isDef() && MO.getReg()) {
509 if (
MI.isCall() && MO.getReg() == SP)
513 if (MO.getReg().isVirtual())
520 else if (MO.getReg() != FrameReg ||
527 }
else if (MO.isRegMask()) {
532 for (
auto It : RegVars) {
533 unsigned int Reg = It.first;
535 MO.clobbersPhysReg(Reg))
539 for (
unsigned Reg : RegsToClobber) {
551 for (
auto &Pair : LiveEntries) {
552 if (Pair.second.empty())
572#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
574 dbgs() <<
"DbgValueHistoryMap('" << FuncName <<
"'):\n";
575 for (
const auto &VarRangePair : *
this) {
582 dbgs() <<
" - " << LocalVar->getName() <<
" at ";
585 dbgs() << Location->getFilename() <<
":" << Location->getLine() <<
":"
586 << Location->getColumn();
588 dbgs() <<
"<unknown location>";
593 const auto &
Entry = E.value();
594 dbgs() <<
" Entry[" << E.index() <<
"]: ";
596 dbgs() <<
"Debug value\n";
598 dbgs() <<
"Clobber\n";
602 dbgs() <<
" - Valid until end of function\n";
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static void addRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo, InlinedEntity Var)
static void clobberRegEntries(InlinedEntity Var, unsigned RegNo, const MachineInstr &ClobberingInstr, DbgValueEntriesMap &LiveEntries, DbgValueHistoryMap &HistMap, SmallVectorImpl< Register > &FellowRegisters)
Create a clobbering entry and end all open debug value entries for Var that are described by RegNo us...
static std::optional< ArrayRef< InsnRange >::iterator > intersects(const MachineInstr *StartMI, const MachineInstr *EndMI, ArrayRef< InsnRange > Ranges, const InstructionOrdering &Ordering)
Check if the instruction range [StartMI, EndMI] intersects any instruction range in Ranges.
static void handleNewDebugValue(InlinedEntity Var, const MachineInstr &DV, RegDescribedVarsMap &RegVars, DbgValueEntriesMap &LiveEntries, DbgValueHistoryMap &HistMap)
Add a new debug value for Var. Closes all overlapping debug values.
static void dropRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo, InlinedEntity Var)
static void clobberRegisterUses(RegDescribedVarsMap &RegVars, RegDescribedVarsMap::iterator I, DbgValueHistoryMap &HistMap, DbgValueEntriesMap &LiveEntries, const MachineInstr &ClobberingInstr)
Register const TargetRegisterInfo * TRI
This file defines the SmallSet class.
This file defines the SmallVector class.
This file describes how to lower LLVM code to machine code.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
static bool fragmentsOverlap(const FragmentInfo &A, const FragmentInfo &B)
Check if fragments overlap between a pair of FragmentInfos.
bool isValidLocationForIntrinsic(const DILocation *DL) const
Check that a location is valid for this label.
bool isValidLocationForIntrinsic(const DILocation *DL) const
Check that a location is valid for this variable.
For each inlined instance of a source-level label, keep the corresponding DBG_LABEL instruction.
std::pair< const DINode *, const DILocation * > InlinedEntity
void addInstr(InlinedEntity Label, const MachineInstr &MI)
Specifies a change in a variable's debug value history.
const MachineInstr * getInstr() const
EntryIndex getEndIndex() const
void endEntry(EntryIndex EndIndex)
For each user variable, keep a list of instruction ranges where this variable is accessible.
bool startDbgValue(InlinedEntity Var, const MachineInstr &MI, EntryIndex &NewIndex)
void trimLocationRanges(const MachineFunction &MF, LexicalScopes &LScopes, const InstructionOrdering &Ordering)
Drop location ranges which exist entirely outside each variable's scope.
size_t EntryIndex
Index in the entry vector.
EntryIndex startClobber(InlinedEntity Var, const MachineInstr &MI)
SmallVector< Entry, 4 > Entries
Entry & getEntry(InlinedEntity Var, EntryIndex Index)
LLVM_DUMP_METHOD void dump(StringRef FuncName) const
static const EntryIndex NoEntry
Special value to indicate that an entry is valid until the end of the function.
bool hasNonEmptyLocation(const Entries &Entries) const
Test whether a vector of entries features any non-empty locations.
std::pair< const DINode *, const DILocation * > InlinedEntity
std::pair< iterator, bool > insert_or_assign(const KeyT &Key, V &&Val)
Record instruction ordering so we can query their relative positions within a function.
void initialize(const MachineFunction &MF)
bool isBefore(const MachineInstr *A, const MachineInstr *B) const
Check if instruction A comes before B, where A and B both belong to the MachineFunction passed to ini...
This class is used to track scope information.
This class provides interface to collect and use lexical scoping information from machine instruction...
LLVM_ABI LexicalScope * findLexicalScope(const DILocation *DL)
Find lexical scope, either regular or inlined, for the given DebugLoc.
LexicalScope * findInlinedScope(const DILocalScope *N, const DILocation *IA)
Find an inlined scope for the given scope/inlined-at.
MCRegAliasIterator enumerates all registers aliasing Reg.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
const MachineBasicBlock & back() const
Representation of each machine instruction.
mop_range debug_operands()
Returns all operands that are used to determine the variable location for this DBG_VALUE instruction.
LLVM_ABI const DIExpression * getDebugExpression() const
Return the complex address expression referenced by this DBG_VALUE instruction.
LLVM_ABI void print(raw_ostream &OS, bool IsStandalone=true, bool SkipOpers=false, bool SkipDebugLoc=false, bool AddNewLine=true, const TargetInstrInfo *TII=nullptr) const
Print this MI to OS.
LLVM_ABI bool isDebugEntryValue() const
A DBG_VALUE is an entry value iff its debug expression contains the DW_OP_LLVM_entry_value operation.
MachineOperand class - Representation of each machine instruction operand.
Wrapper class representing virtual and physical registers.
static constexpr bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
bool contains(const T &V) const
Check if the SmallSet contains the given element.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
iterator erase(const_iterator CI)
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetLowering * getTargetLowering() const
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
void calculateDbgEntityHistory(const MachineFunction *MF, const TargetRegisterInfo *TRI, DbgValueHistoryMap &DbgValues, DbgLabelInstrMap &DbgLabels)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.