[Metadata] Extend 'count' field of DISubrange to take a metadata node
Summary:
This patch extends the DISubrange 'count' field to take either a
(signed) constant integer value or a reference to a DILocalVariable
or DIGlobalVariable.
This is patch [1/3] in a series to extend LLVM's DISubrange Metadata
node to support debugging of C99 variable length arrays and vectors with
runtime length like the Scalable Vector Extension for AArch64. It is
also a first step towards representing more complex cases like arrays
in Fortran.
Reviewers: echristo, pcc, aprantl, dexonsmith, clayborg, kristof.beyls, dblaikie
Reviewed By: aprantl
Subscribers: rnk, probinson, fhahn, aemerson, rengolin, JDevlieghere, llvm-commits
Differential Revision: https://reviews.llvm.org/D41695
llvm-svn: 323313
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 7c64760..638b024 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -1621,10 +1621,15 @@
}
static void writeDISubrange(raw_ostream &Out, const DISubrange *N,
- TypePrinting *, SlotTracker *, const Module *) {
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
Out << "!DISubrange(";
- MDFieldPrinter Printer(Out);
- Printer.printInt("count", N->getCount(), /* ShouldSkipZero */ false);
+ MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
+ if (auto *CE = N->getCount().dyn_cast<ConstantInt*>())
+ Printer.printInt("count", CE->getSExtValue(), /* ShouldSkipZero */ false);
+ else
+ Printer.printMetadata("count", N->getCount().dyn_cast<DIVariable*>(),
+ /*ShouldSkipNull */ false);
Printer.printInt("lowerBound", N->getLowerBound());
Out << ")";
}
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index f8ae23d..5ef3cdd 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -582,6 +582,10 @@
return DISubrange::get(VMContext, Count, Lo);
}
+DISubrange *DIBuilder::getOrCreateSubrange(int64_t Lo, Metadata *CountNode) {
+ return DISubrange::get(VMContext, CountNode, Lo);
+}
+
static void checkGlobalVariableScope(DIScope *Context) {
#ifndef NDEBUG
if (auto *CT =
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 75ddd47..b6eda6a 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -249,8 +249,17 @@
DISubrange *DISubrange::getImpl(LLVMContext &Context, int64_t Count, int64_t Lo,
StorageType Storage, bool ShouldCreate) {
- DEFINE_GETIMPL_LOOKUP(DISubrange, (Count, Lo));
- DEFINE_GETIMPL_STORE_NO_OPS(DISubrange, (Count, Lo));
+ auto *CountNode = ConstantAsMetadata::get(
+ ConstantInt::getSigned(Type::getInt64Ty(Context), Count));
+ return getImpl(Context, CountNode, Lo, Storage, ShouldCreate);
+}
+
+DISubrange *DISubrange::getImpl(LLVMContext &Context, Metadata *CountNode,
+ int64_t Lo, StorageType Storage,
+ bool ShouldCreate) {
+ DEFINE_GETIMPL_LOOKUP(DISubrange, (CountNode, Lo));
+ Metadata *Ops[] = { CountNode };
+ DEFINE_GETIMPL_STORE(DISubrange, (CountNode, Lo), Ops);
}
DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, int64_t Value,
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index f41acfa..e981a80 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -321,19 +321,34 @@
};
template <> struct MDNodeKeyImpl<DISubrange> {
- int64_t Count;
+ Metadata *CountNode;
int64_t LowerBound;
- MDNodeKeyImpl(int64_t Count, int64_t LowerBound)
- : Count(Count), LowerBound(LowerBound) {}
+ MDNodeKeyImpl(Metadata *CountNode, int64_t LowerBound)
+ : CountNode(CountNode), LowerBound(LowerBound) {}
MDNodeKeyImpl(const DISubrange *N)
- : Count(N->getCount()), LowerBound(N->getLowerBound()) {}
+ : CountNode(N->getRawCountNode()),
+ LowerBound(N->getLowerBound()) {}
bool isKeyOf(const DISubrange *RHS) const {
- return Count == RHS->getCount() && LowerBound == RHS->getLowerBound();
+ if (LowerBound != RHS->getLowerBound())
+ return false;
+
+ if (auto *RHSCount = RHS->getCount().dyn_cast<ConstantInt*>())
+ if (auto *MD = dyn_cast<ConstantAsMetadata>(CountNode))
+ if (RHSCount->getSExtValue() ==
+ cast<ConstantInt>(MD->getValue())->getSExtValue())
+ return true;
+
+ return CountNode == RHS->getRawCountNode();
}
- unsigned getHashValue() const { return hash_combine(Count, LowerBound); }
+ unsigned getHashValue() const {
+ if (auto *MD = dyn_cast<ConstantAsMetadata>(CountNode))
+ return hash_combine(cast<ConstantInt>(MD->getValue())->getSExtValue(),
+ LowerBound);
+ return hash_combine(CountNode, LowerBound);
+ }
};
template <> struct MDNodeKeyImpl<DIEnumerator> {
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 4dd5aeb..92389b6 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -868,7 +868,12 @@
void Verifier::visitDISubrange(const DISubrange &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N);
- AssertDI(N.getCount() >= -1, "invalid subrange count", &N);
+ auto Count = N.getCount();
+ AssertDI(Count, "Count must either be a signed constant or a DIVariable",
+ &N);
+ AssertDI(!Count.is<ConstantInt*>() ||
+ Count.get<ConstantInt*>()->getSExtValue() >= -1,
+ "invalid subrange count", &N);
}
void Verifier::visitDIEnumerator(const DIEnumerator &N) {