[llvm] 269a9af - [DebugInfo] Make DebugVariable class available in DebugInfoMetadata
via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 3 07:17:45 PST 2019
Author: stozer
Date: 2019-12-03T15:10:56Z
New Revision: 269a9afe25cb0ab7a7c0c62b9d95975ffc653530
URL: https://github.com/llvm/llvm-project/commit/269a9afe25cb0ab7a7c0c62b9d95975ffc653530
DIFF: https://github.com/llvm/llvm-project/commit/269a9afe25cb0ab7a7c0c62b9d95975ffc653530.diff
LOG: [DebugInfo] Make DebugVariable class available in DebugInfoMetadata
The DebugVariable class is a class declared in LiveDebugValues.cpp which
is used to uniquely identify a single variable, using its source
variable, inline location, and fragment info to do so. This patch moves
this class into DebugInfoMetadata.h, making it available in a much
broader scope.
Added:
Modified:
llvm/include/llvm/IR/DebugInfoMetadata.h
llvm/lib/CodeGen/LiveDebugValues.cpp
llvm/lib/IR/DebugInfoMetadata.cpp
llvm/unittests/IR/MetadataTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 0e43a05b318e..d690ccece5fa 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -3253,6 +3253,89 @@ class DIMacroFile : public DIMacroNode {
}
};
+/// Identifies a unique instance of a variable.
+///
+/// Storage for identifying a potentially inlined instance of a variable,
+/// or a fragment thereof. This guarantees that exactly one variable instance
+/// may be identified by this class, even when that variable is a fragment of
+/// an aggregate variable and/or there is another inlined instance of the same
+/// source code variable nearby.
+/// This class does not necessarily uniquely identify that variable: it is
+/// possible that a DebugVariable with
diff erent parameters may point to the
+/// same variable instance, but not that one DebugVariable points to multiple
+/// variable instances.
+class DebugVariable {
+ using FragmentInfo = DIExpression::FragmentInfo;
+
+ const DILocalVariable *Variable;
+ Optional<FragmentInfo> Fragment;
+ const DILocation *InlinedAt;
+
+ /// Fragment that will overlap all other fragments. Used as default when
+ /// caller demands a fragment.
+ static const FragmentInfo DefaultFragment;
+
+public:
+ DebugVariable(const DILocalVariable *Var, Optional<FragmentInfo> FragmentInfo,
+ const DILocation *InlinedAt)
+ : Variable(Var), Fragment(FragmentInfo), InlinedAt(InlinedAt) {}
+
+ DebugVariable(const DILocalVariable *Var, const DIExpression *DIExpr,
+ const DILocation *InlinedAt)
+ : Variable(Var),
+ Fragment(DIExpr ? DIExpr->getFragmentInfo() : NoneType()),
+ InlinedAt(InlinedAt) {}
+
+ const DILocalVariable *getVariable() const { return Variable; }
+ const Optional<FragmentInfo> getFragment() const { return Fragment; }
+ const DILocation *getInlinedAt() const { return InlinedAt; }
+
+ const FragmentInfo getFragmentOrDefault() const {
+ return Fragment.getValueOr(DefaultFragment);
+ }
+
+ static bool isDefaultFragment(const FragmentInfo F) {
+ return F == DefaultFragment;
+ }
+
+ bool operator==(const DebugVariable &Other) const {
+ return std::tie(Variable, Fragment, InlinedAt) ==
+ std::tie(Other.Variable, Other.Fragment, Other.InlinedAt);
+ }
+
+ bool operator<(const DebugVariable &Other) const {
+ return std::tie(Variable, Fragment, InlinedAt) <
+ std::tie(Other.Variable, Other.Fragment, Other.InlinedAt);
+ }
+};
+
+template <> struct DenseMapInfo<DebugVariable> {
+ using FragmentInfo = DIExpression::FragmentInfo;
+
+ /// Empty key: no key should be generated that has no DILocalVariable.
+ static inline DebugVariable getEmptyKey() {
+ return DebugVariable(nullptr, NoneType(), nullptr);
+ }
+
+ /// Difference in tombstone is that the Optional is meaningful.
+ static inline DebugVariable getTombstoneKey() {
+ return DebugVariable(nullptr, {{0, 0}}, nullptr);
+ }
+
+ static unsigned getHashValue(const DebugVariable &D) {
+ unsigned HV = 0;
+ const Optional<FragmentInfo> Fragment = D.getFragment();
+ if (Fragment)
+ HV = DenseMapInfo<FragmentInfo>::getHashValue(*Fragment);
+
+ return hash_combine(D.getVariable(), HV, D.getInlinedAt());
+ }
+
+ static bool isEqual(const DebugVariable &A, const DebugVariable &B) {
+ return A == B;
+ }
+};
+
} // end namespace llvm
#undef DEFINE_MDNODE_GET_UNPACK_IMPL
diff --git a/llvm/lib/CodeGen/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues.cpp
index 7734f5e5ef70..3248b3d18b21 100644
--- a/llvm/lib/CodeGen/LiveDebugValues.cpp
+++ b/llvm/lib/CodeGen/LiveDebugValues.cpp
@@ -144,60 +144,6 @@ class LiveDebugValues : public MachineFunctionPass {
using FragmentInfo = DIExpression::FragmentInfo;
using OptFragmentInfo = Optional<DIExpression::FragmentInfo>;
- /// Storage for identifying a potentially inlined instance of a variable,
- /// or a fragment thereof.
- class DebugVariable {
- const DILocalVariable *Variable;
- OptFragmentInfo Fragment;
- const DILocation *InlinedAt;
-
- /// Fragment that will overlap all other fragments. Used as default when
- /// caller demands a fragment.
- static const FragmentInfo DefaultFragment;
-
- public:
- DebugVariable(const DILocalVariable *Var, OptFragmentInfo &&FragmentInfo,
- const DILocation *InlinedAt)
- : Variable(Var), Fragment(FragmentInfo), InlinedAt(InlinedAt) {}
-
- DebugVariable(const DILocalVariable *Var, OptFragmentInfo &FragmentInfo,
- const DILocation *InlinedAt)
- : Variable(Var), Fragment(FragmentInfo), InlinedAt(InlinedAt) {}
-
- DebugVariable(const DILocalVariable *Var, const DIExpression *DIExpr,
- const DILocation *InlinedAt)
- : DebugVariable(Var, DIExpr->getFragmentInfo(), InlinedAt) {}
-
- DebugVariable(const MachineInstr &MI)
- : DebugVariable(MI.getDebugVariable(),
- MI.getDebugExpression()->getFragmentInfo(),
- MI.getDebugLoc()->getInlinedAt()) {}
-
- const DILocalVariable *getVar() const { return Variable; }
- const OptFragmentInfo &getFragment() const { return Fragment; }
- const DILocation *getInlinedAt() const { return InlinedAt; }
-
- const FragmentInfo getFragmentDefault() const {
- return Fragment.getValueOr(DefaultFragment);
- }
-
- static bool isFragmentDefault(FragmentInfo &F) {
- return F == DefaultFragment;
- }
-
- bool operator==(const DebugVariable &Other) const {
- return std::tie(Variable, Fragment, InlinedAt) ==
- std::tie(Other.Variable, Other.Fragment, Other.InlinedAt);
- }
-
- bool operator<(const DebugVariable &Other) const {
- return std::tie(Variable, Fragment, InlinedAt) <
- std::tie(Other.Variable, Other.Fragment, Other.InlinedAt);
- }
- };
-
- friend struct llvm::DenseMapInfo<DebugVariable>;
-
/// A pair of debug variable and value location.
struct VarLoc {
// The location at which a spilled variable resides. It consists of a
@@ -241,8 +187,9 @@ class LiveDebugValues : public MachineFunctionPass {
} Loc;
VarLoc(const MachineInstr &MI, LexicalScopes &LS)
- : Var(MI), Expr(MI.getDebugExpression()), MI(MI),
- UVS(MI.getDebugLoc(), LS) {
+ : Var(MI.getDebugVariable(), MI.getDebugExpression(),
+ MI.getDebugLoc()->getInlinedAt()),
+ Expr(MI.getDebugExpression()), MI(MI), UVS(MI.getDebugLoc(), LS) {
static_assert((sizeof(Loc) == sizeof(uint64_t)),
"hash does not cover all members of Loc");
assert(MI.isDebugValue() && "not a DBG_VALUE");
@@ -370,7 +317,8 @@ class LiveDebugValues : public MachineFunctionPass {
llvm_unreachable("Invalid VarLoc in dump method");
}
- dbgs() << ", \"" << Var.getVar()->getName() << "\", " << *Expr << ", ";
+ dbgs() << ", \"" << Var.getVariable()->getName() << "\", " << *Expr
+ << ", ";
if (Var.getInlinedAt())
dbgs() << "!" << Var.getInlinedAt()->getMetadataID() << ")\n";
else
@@ -559,46 +507,10 @@ class LiveDebugValues : public MachineFunctionPass {
} // end anonymous namespace
-namespace llvm {
-
-template <> struct DenseMapInfo<LiveDebugValues::DebugVariable> {
- using DV = LiveDebugValues::DebugVariable;
- using OptFragmentInfo = LiveDebugValues::OptFragmentInfo;
- using FragmentInfo = LiveDebugValues::FragmentInfo;
-
- // Empty key: no key should be generated that has no DILocalVariable.
- static inline DV getEmptyKey() {
- return DV(nullptr, OptFragmentInfo(), nullptr);
- }
-
- // Difference in tombstone is that the Optional is meaningful
- static inline DV getTombstoneKey() {
- return DV(nullptr, OptFragmentInfo({0, 0}), nullptr);
- }
-
- static unsigned getHashValue(const DV &D) {
- unsigned HV = 0;
- const OptFragmentInfo &Fragment = D.getFragment();
- if (Fragment)
- HV = DenseMapInfo<FragmentInfo>::getHashValue(*Fragment);
-
- return hash_combine(D.getVar(), HV, D.getInlinedAt());
- }
-
- static bool isEqual(const DV &A, const DV &B) { return A == B; }
-};
-
-} // namespace llvm
-
//===----------------------------------------------------------------------===//
// Implementation
//===----------------------------------------------------------------------===//
-const DIExpression::FragmentInfo
- LiveDebugValues::DebugVariable::DefaultFragment = {
- std::numeric_limits<uint64_t>::max(),
- std::numeric_limits<uint64_t>::min()};
-
char LiveDebugValues::ID = 0;
char &llvm::LiveDebugValuesID = LiveDebugValues::ID;
@@ -636,17 +548,17 @@ void LiveDebugValues::OpenRangesSet::erase(DebugVariable Var) {
// Extract the fragment. Interpret an empty fragment as one that covers all
// possible bits.
- FragmentInfo ThisFragment = Var.getFragmentDefault();
+ FragmentInfo ThisFragment = Var.getFragmentOrDefault();
// There may be fragments that overlap the designated fragment. Look them up
// in the pre-computed overlap map, and erase them too.
- auto MapIt = OverlappingFragments.find({Var.getVar(), ThisFragment});
+ auto MapIt = OverlappingFragments.find({Var.getVariable(), ThisFragment});
if (MapIt != OverlappingFragments.end()) {
for (auto Fragment : MapIt->second) {
LiveDebugValues::OptFragmentInfo FragmentHolder;
- if (!DebugVariable::isFragmentDefault(Fragment))
+ if (!DebugVariable::isDefaultFragment(Fragment))
FragmentHolder = LiveDebugValues::OptFragmentInfo(Fragment);
- DoErase({Var.getVar(), FragmentHolder, Var.getInlinedAt()});
+ DoErase({Var.getVariable(), FragmentHolder, Var.getInlinedAt()});
}
}
}
@@ -669,7 +581,7 @@ void LiveDebugValues::printVarLocInMBB(const MachineFunction &MF,
Out << "MBB: " << BB.getNumber() << ":\n";
for (unsigned VLL : L) {
const VarLoc &VL = VarLocIDs[VLL];
- Out << " Var: " << VL.Var.getVar()->getName();
+ Out << " Var: " << VL.Var.getVariable()->getName();
Out << " MI: ";
VL.dump(TRI, Out);
}
@@ -735,7 +647,7 @@ void LiveDebugValues::emitEntryValues(MachineInstr &MI,
DebugParamMap &DebugEntryVals,
SparseBitVector<> &KillSet) {
for (unsigned ID : KillSet) {
- if (!VarLocIDs[ID].Var.getVar()->isParameter())
+ if (!VarLocIDs[ID].Var.getVariable()->isParameter())
continue;
const MachineInstr *CurrDebugInstr = &VarLocIDs[ID].MI;
@@ -773,7 +685,9 @@ void LiveDebugValues::insertTransferDebugPair(
unsigned LocId = VarLocIDs.insert(VL);
// Close this variable's previous location range.
- DebugVariable V(*DebugInstr);
+ DebugVariable V(DebugInstr->getDebugVariable(),
+ DebugInstr->getDebugExpression(),
+ DebugInstr->getDebugLoc()->getInlinedAt());
OpenRanges.erase(V);
// Record the new location as an open range, and a postponed transfer
@@ -1005,12 +919,12 @@ void LiveDebugValues::transferSpillOrRestoreInst(MachineInstr &MI,
if (TKind == TransferKind::TransferSpill &&
VarLocIDs[ID].isDescribedByReg() == Reg) {
LLVM_DEBUG(dbgs() << "Spilling Register " << printReg(Reg, TRI) << '('
- << VarLocIDs[ID].Var.getVar()->getName() << ")\n");
+ << VarLocIDs[ID].Var.getVariable()->getName() << ")\n");
} else if (TKind == TransferKind::TransferRestore &&
VarLocIDs[ID].Kind == VarLoc::SpillLocKind &&
VarLocIDs[ID].Loc.SpillLocation == *Loc) {
LLVM_DEBUG(dbgs() << "Restoring Register " << printReg(Reg, TRI) << '('
- << VarLocIDs[ID].Var.getVar()->getName() << ")\n");
+ << VarLocIDs[ID].Var.getVariable()->getName() << ")\n");
} else
continue;
insertTransferDebugPair(MI, OpenRanges, Transfers, VarLocIDs, ID, TKind,
@@ -1099,26 +1013,27 @@ bool LiveDebugValues::transferTerminator(MachineBasicBlock *CurMBB,
void LiveDebugValues::accumulateFragmentMap(MachineInstr &MI,
VarToFragments &SeenFragments,
OverlapMap &OverlappingFragments) {
- DebugVariable MIVar(MI);
- FragmentInfo ThisFragment = MIVar.getFragmentDefault();
+ DebugVariable MIVar(MI.getDebugVariable(), MI.getDebugExpression(),
+ MI.getDebugLoc()->getInlinedAt());
+ FragmentInfo ThisFragment = MIVar.getFragmentOrDefault();
// If this is the first sighting of this variable, then we are guaranteed
// there are currently no overlapping fragments either. Initialize the set
// of seen fragments, record no overlaps for the current one, and return.
- auto SeenIt = SeenFragments.find(MIVar.getVar());
+ auto SeenIt = SeenFragments.find(MIVar.getVariable());
if (SeenIt == SeenFragments.end()) {
SmallSet<FragmentInfo, 4> OneFragment;
OneFragment.insert(ThisFragment);
- SeenFragments.insert({MIVar.getVar(), OneFragment});
+ SeenFragments.insert({MIVar.getVariable(), OneFragment});
- OverlappingFragments.insert({{MIVar.getVar(), ThisFragment}, {}});
+ OverlappingFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
return;
}
// If this particular Variable/Fragment pair already exists in the overlap
// map, it has already been accounted for.
auto IsInOLapMap =
- OverlappingFragments.insert({{MIVar.getVar(), ThisFragment}, {}});
+ OverlappingFragments.insert({{MIVar.getVariable(), ThisFragment}, {}});
if (!IsInOLapMap.second)
return;
@@ -1136,7 +1051,7 @@ void LiveDebugValues::accumulateFragmentMap(MachineInstr &MI,
// Mark the previously seen fragment as being overlapped by the current
// one.
auto ASeenFragmentsOverlaps =
- OverlappingFragments.find({MIVar.getVar(), ASeenFragment});
+ OverlappingFragments.find({MIVar.getVariable(), ASeenFragment});
assert(ASeenFragmentsOverlaps != OverlappingFragments.end() &&
"Previously seen var fragment has no vector of overlaps");
ASeenFragmentsOverlaps->second.push_back(ThisFragment);
@@ -1201,7 +1116,7 @@ bool LiveDebugValues::join(
if (!InLocsT.empty()) {
for (auto ID : InLocsT)
dbgs() << " gathered candidate incoming var: "
- << VarLocIDs[ID].Var.getVar()->getName() << "\n";
+ << VarLocIDs[ID].Var.getVariable()->getName() << "\n";
}
});
@@ -1216,7 +1131,7 @@ bool LiveDebugValues::join(
if (!VarLocIDs[ID].dominates(MBB)) {
KillSet.set(ID);
LLVM_DEBUG({
- auto Name = VarLocIDs[ID].Var.getVar()->getName();
+ auto Name = VarLocIDs[ID].Var.getVariable()->getName();
dbgs() << " killing " << Name << ", it doesn't dominate MBB\n";
});
}
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index b0102275b36e..9b42a5a0e1b5 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -23,6 +23,9 @@
using namespace llvm;
+const DIExpression::FragmentInfo DebugVariable::DefaultFragment = {
+ std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::min()};
+
DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line,
unsigned Column, ArrayRef<Metadata *> MDs,
bool ImplicitCode)
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 99295681ec88..b2be82565cfc 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/Metadata.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
@@ -2897,4 +2898,41 @@ TEST_F(DistinctMDOperandPlaceholderTest, TrackingMDRefAndDistinctMDNode) {
}
#endif
+typedef MetadataTest DebugVariableTest;
+TEST_F(DebugVariableTest, DenseMap) {
+ DenseMap<DebugVariable, uint64_t> DebugVariableMap;
+
+ DILocalScope *Scope = getSubprogram();
+ DIFile *File = getFile();
+ DIType *Type = getDerivedType();
+ DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);
+
+ DILocation *InlinedLoc = DILocation::get(Context, 2, 7, Scope);
+
+ DILocalVariable *VarA =
+ DILocalVariable::get(Context, Scope, "A", File, 5, Type, 2, Flags, 8);
+ DILocalVariable *VarB =
+ DILocalVariable::get(Context, Scope, "B", File, 7, Type, 3, Flags, 8);
+
+ DebugVariable DebugVariableA(VarA, NoneType(), nullptr);
+ DebugVariable DebugVariableInlineA(VarA, NoneType(), InlinedLoc);
+ DebugVariable DebugVariableB(VarB, NoneType(), nullptr);
+ DebugVariable DebugVariableFragB(VarB, {{16, 16}}, nullptr);
+
+ DebugVariableMap.insert({DebugVariableA, 2});
+ DebugVariableMap.insert({DebugVariableInlineA, 3});
+ DebugVariableMap.insert({DebugVariableB, 6});
+ DebugVariableMap.insert({DebugVariableFragB, 12});
+
+ EXPECT_EQ(DebugVariableMap.count(DebugVariableA), 1);
+ EXPECT_EQ(DebugVariableMap.count(DebugVariableInlineA), 1);
+ EXPECT_EQ(DebugVariableMap.count(DebugVariableB), 1);
+ EXPECT_EQ(DebugVariableMap.count(DebugVariableFragB), 1);
+
+ EXPECT_EQ(DebugVariableMap.find(DebugVariableA)->second, 2);
+ EXPECT_EQ(DebugVariableMap.find(DebugVariableInlineA)->second, 3);
+ EXPECT_EQ(DebugVariableMap.find(DebugVariableB)->second, 6);
+ EXPECT_EQ(DebugVariableMap.find(DebugVariableFragB)->second, 12);
+}
+
} // end namespace
More information about the llvm-commits
mailing list