summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-01-13 20:44:56 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-01-13 20:44:56 +0000
commitde03ff572138c56dab846f26d1a4bde1aa1f59d9 (patch)
treed2f2837f400366db02f2563bd8444e0ebd2d64d6
parentb56d8433483b9b5a99ef5f3b3540193561e54670 (diff)
downloadbcm5719-llvm-de03ff572138c56dab846f26d1a4bde1aa1f59d9.tar.gz
bcm5719-llvm-de03ff572138c56dab846f26d1a4bde1aa1f59d9.zip
IR: Add MDLocation class
Add a new subclass of `UniquableMDNode`, `MDLocation`. This will be the IR version of `DebugLoc` and `DILocation`. The goal is to rename this to `DILocation` once the IR classes supersede the `DI`-prefixed wrappers. This isn't used anywhere yet. Part of PR21433. llvm-svn: 225824
-rw-r--r--llvm/include/llvm/IR/Metadata.def1
-rw-r--r--llvm/include/llvm/IR/Metadata.h59
-rw-r--r--llvm/lib/IR/AsmWriter.cpp33
-rw-r--r--llvm/lib/IR/LLVMContextImpl.cpp4
-rw-r--r--llvm/lib/IR/LLVMContextImpl.h43
-rw-r--r--llvm/lib/IR/Metadata.cpp93
-rw-r--r--llvm/unittests/IR/MetadataTest.cpp37
7 files changed, 266 insertions, 4 deletions
diff --git a/llvm/include/llvm/IR/Metadata.def b/llvm/include/llvm/IR/Metadata.def
index 2d5d91eb12a..2098bb57eb5 100644
--- a/llvm/include/llvm/IR/Metadata.def
+++ b/llvm/include/llvm/IR/Metadata.def
@@ -50,6 +50,7 @@ HANDLE_METADATA_BRANCH(MDNode)
HANDLE_METADATA_LEAF(MDNodeFwdDecl)
HANDLE_UNIQUABLE_BRANCH(UniquableMDNode)
HANDLE_UNIQUABLE_LEAF(MDTuple)
+HANDLE_UNIQUABLE_LEAF(MDLocation)
#undef HANDLE_METADATA
#undef HANDLE_METADATA_LEAF
diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h
index da6521bbf3e..10fc99f7b11 100644
--- a/llvm/include/llvm/IR/Metadata.h
+++ b/llvm/include/llvm/IR/Metadata.h
@@ -57,6 +57,7 @@ protected:
public:
enum MetadataKind {
MDTupleKind,
+ MDLocationKind,
MDNodeFwdDeclKind,
ConstantAsMetadataKind,
LocalAsMetadataKind,
@@ -670,6 +671,7 @@ public:
/// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == MDTupleKind ||
+ MD->getMetadataID() == MDLocationKind ||
MD->getMetadataID() == MDNodeFwdDeclKind;
}
@@ -726,7 +728,8 @@ protected:
public:
static bool classof(const Metadata *MD) {
- return MD->getMetadataID() == MDTupleKind;
+ return MD->getMetadataID() == MDTupleKind ||
+ MD->getMetadataID() == MDLocationKind;
}
/// \brief Check whether any operands are forward declarations.
@@ -812,6 +815,60 @@ MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
return MDTuple::getDistinct(Context, MDs);
}
+/// \brief Debug location.
+///
+/// A debug location in source code, used for debug info and otherwise.
+class MDLocation : public UniquableMDNode {
+ friend class LLVMContextImpl;
+ friend class UniquableMDNode;
+
+ MDLocation(LLVMContext &C, unsigned Line, unsigned Column,
+ ArrayRef<Metadata *> MDs, bool AllowRAUW);
+ ~MDLocation() { dropAllReferences(); }
+
+ static MDLocation *constructHelper(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt, bool AllowRAUW);
+
+ static MDLocation *getImpl(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt, bool ShouldCreate);
+
+ // Disallow replacing operands.
+ void replaceOperandWith(unsigned I, Metadata *New) LLVM_DELETED_FUNCTION;
+
+public:
+ static MDLocation *get(LLVMContext &Context, unsigned Line, unsigned Column,
+ Metadata *Scope, Metadata *InlinedAt = nullptr) {
+ return getImpl(Context, Line, Column, Scope, InlinedAt,
+ /* ShouldCreate */ true);
+ }
+ static MDLocation *getIfExists(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt = nullptr) {
+ return getImpl(Context, Line, Column, Scope, InlinedAt,
+ /* ShouldCreate */ false);
+ }
+ static MDLocation *getDistinct(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt = nullptr);
+
+ unsigned getLine() const { return MDNodeSubclassData; }
+ unsigned getColumn() const { return SubclassData16; }
+ Metadata *getScope() const { return getOperand(0); }
+ Metadata *getInlinedAt() const {
+ return getNumOperands() == 2 ? getOperand(1) : nullptr;
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDLocationKind;
+ }
+
+private:
+ MDLocation *uniquifyImpl();
+ void eraseFromStoreImpl();
+};
+
/// \brief Forward declaration of metadata.
///
/// Forward declaration of metadata, in the form of a basic tuple. Unlike \a
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index ea7e0aa5266..215332b8256 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -1272,6 +1272,39 @@ static void writeMDTuple(raw_ostream &Out, const MDTuple *Node,
Out << "}";
}
+namespace {
+struct FieldSeparator {
+ bool Skip;
+ FieldSeparator() : Skip(true) {}
+};
+raw_ostream &operator<<(raw_ostream &OS, FieldSeparator &FS) {
+ if (FS.Skip) {
+ FS.Skip = false;
+ return OS;
+ }
+ return OS << ", ";
+}
+} // end namespace
+
+static void writeMDLocation(raw_ostream &Out, const MDLocation *DL,
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDLocation(";
+ FieldSeparator FS;
+ if (DL->getLine())
+ Out << FS << "line: " << DL->getLine();
+ if (DL->getColumn())
+ Out << FS << "column: " << DL->getColumn();
+ Out << FS << "scope: ";
+ WriteAsOperandInternal(Out, DL->getScope(), TypePrinter, Machine, Context);
+ if (DL->getInlinedAt()) {
+ Out << FS << "inlinedAt: ";
+ WriteAsOperandInternal(Out, DL->getInlinedAt(), TypePrinter, Machine,
+ Context);
+ }
+ Out << ")";
+}
+
static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node,
TypePrinting *TypePrinter,
SlotTracker *Machine,
diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp
index d47a0d332fb..1fa080b8133 100644
--- a/llvm/lib/IR/LLVMContextImpl.cpp
+++ b/llvm/lib/IR/LLVMContextImpl.cpp
@@ -140,11 +140,15 @@ LLVMContextImpl::~LLVMContextImpl() {
I->dropAllReferences();
for (auto *I : MDTuples)
I->dropAllReferences();
+ for (auto *I : MDLocations)
+ I->dropAllReferences();
for (UniquableMDNode *I : DistinctMDNodes)
I->deleteAsSubclass();
for (MDTuple *I : MDTuples)
delete I;
+ for (MDLocation *I : MDLocations)
+ delete I;
// Destroy MDStrings.
MDStringCache.clear();
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 11b8d38f9af..6ebc567f808 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -215,6 +215,48 @@ struct MDTupleInfo {
}
};
+/// \brief DenseMapInfo for MDLocation.
+struct MDLocationInfo {
+ struct KeyTy {
+ unsigned Line;
+ unsigned Column;
+ Metadata *Scope;
+ Metadata *InlinedAt;
+
+ KeyTy(unsigned Line, unsigned Column, Metadata *Scope, Metadata *InlinedAt)
+ : Line(Line), Column(Column), Scope(Scope), InlinedAt(InlinedAt) {}
+
+ KeyTy(const MDLocation *L)
+ : Line(L->getLine()), Column(L->getColumn()), Scope(L->getScope()),
+ InlinedAt(L->getInlinedAt()) {}
+
+ bool operator==(const MDLocation *RHS) const {
+ if (RHS == getEmptyKey() || RHS == getTombstoneKey())
+ return false;
+ return Line == RHS->getLine() && Column == RHS->getColumn() &&
+ Scope == RHS->getScope() && InlinedAt == RHS->getInlinedAt();
+ }
+ };
+ static inline MDLocation *getEmptyKey() {
+ return DenseMapInfo<MDLocation *>::getEmptyKey();
+ }
+ static inline MDLocation *getTombstoneKey() {
+ return DenseMapInfo<MDLocation *>::getTombstoneKey();
+ }
+ static unsigned getHashValue(const KeyTy &Key) {
+ return hash_combine(Key.Line, Key.Column, Key.Scope, Key.InlinedAt);
+ }
+ static unsigned getHashValue(const MDLocation *U) {
+ return getHashValue(KeyTy(U));
+ }
+ static bool isEqual(const KeyTy &LHS, const MDLocation *RHS) {
+ return LHS == RHS;
+ }
+ static bool isEqual(const MDLocation *LHS, const MDLocation *RHS) {
+ return LHS == RHS;
+ }
+};
+
class LLVMContextImpl {
public:
/// OwnedModules - The set of modules instantiated in this context, and which
@@ -246,6 +288,7 @@ public:
DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues;
DenseSet<MDTuple *, MDTupleInfo> MDTuples;
+ DenseSet<MDLocation *, MDLocationInfo> MDLocations;
// MDNodes may be uniqued or not uniqued. When they're not uniqued, they
// aren't in the MDNodeSet, but they're still shared between objects, so no
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index 852f1dc2041..ab83252bfda 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -640,6 +640,93 @@ MDTuple *MDTuple::uniquifyImpl() {
void MDTuple::eraseFromStoreImpl() { getContext().pImpl->MDTuples.erase(this); }
+MDLocation::MDLocation(LLVMContext &C, unsigned Line, unsigned Column,
+ ArrayRef<Metadata *> MDs, bool AllowRAUW)
+ : UniquableMDNode(C, MDLocationKind, MDs, AllowRAUW) {
+ assert((MDs.size() == 1 || MDs.size() == 2) &&
+ "Expected a scope and optional inlined-at");
+
+ // Set line and column.
+ assert(Line < (1u << 24) && "Expected 24-bit line");
+ assert(Column < (1u << 8) && "Expected 8-bit column");
+
+ MDNodeSubclassData = Line;
+ SubclassData16 = Column;
+}
+
+MDLocation *MDLocation::constructHelper(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt, bool AllowRAUW) {
+ SmallVector<Metadata *, 2> Ops;
+ Ops.push_back(Scope);
+ if (InlinedAt)
+ Ops.push_back(InlinedAt);
+ return new (Ops.size()) MDLocation(Context, Line, Column, Ops, AllowRAUW);
+}
+
+static void adjustLine(unsigned &Line) {
+ // Set to unknown on overflow. Still use 24 bits for now.
+ if (Line >= (1u << 24))
+ Line = 0;
+}
+
+static void adjustColumn(unsigned &Column) {
+ // Set to unknown on overflow. Still use 8 bits for now.
+ if (Column >= (1u << 8))
+ Column = 0;
+}
+
+MDLocation *MDLocation::getImpl(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt, bool ShouldCreate) {
+ // Fixup line/column.
+ adjustLine(Line);
+ adjustColumn(Column);
+
+ MDLocationInfo::KeyTy Key(Line, Column, Scope, InlinedAt);
+
+ auto &Store = Context.pImpl->MDLocations;
+ auto I = Store.find_as(Key);
+ if (I != Store.end())
+ return *I;
+ if (!ShouldCreate)
+ return nullptr;
+
+ auto *N = constructHelper(Context, Line, Column, Scope, InlinedAt,
+ /* AllowRAUW */ true);
+ Store.insert(N);
+ return N;
+}
+
+MDLocation *MDLocation::getDistinct(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt) {
+ // Fixup line/column.
+ adjustLine(Line);
+ adjustColumn(Column);
+
+ auto *N = constructHelper(Context, Line, Column, Scope, InlinedAt,
+ /* AllowRAUW */ false);
+ N->storeDistinctInContext();
+ return N;
+}
+
+MDLocation *MDLocation::uniquifyImpl() {
+ MDLocationInfo::KeyTy Key(this);
+
+ auto &Store = getContext().pImpl->MDLocations;
+ auto I = Store.find_as(Key);
+ if (I == Store.end()) {
+ Store.insert(this);
+ return this;
+ }
+ return *I;
+}
+
+void MDLocation::eraseFromStoreImpl() {
+ getContext().pImpl->MDLocations.erase(this);
+}
+
MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
ArrayRef<Metadata *> MDs) {
return MDNodeFwdDecl::get(Context, MDs);
@@ -650,9 +737,9 @@ void MDNode::deleteTemporary(MDNode *N) { delete cast<MDNodeFwdDecl>(N); }
void UniquableMDNode::storeDistinctInContext() {
assert(!IsDistinctInContext && "Expected newly distinct metadata");
IsDistinctInContext = true;
- auto *T = cast<MDTuple>(this);
- T->setHash(0);
- getContext().pImpl->DistinctMDNodes.insert(T);
+ if (auto *T = dyn_cast<MDTuple>(this))
+ T->setHash(0);
+ getContext().pImpl->DistinctMDNodes.insert(this);
}
void MDNode::replaceOperandWith(unsigned I, Metadata *New) {
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 9f5d133943b..8c5c312a2f7 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -387,6 +387,43 @@ TEST_F(MDNodeTest, replaceResolvedOperand) {
Temp->replaceAllUsesWith(nullptr);
}
+typedef MetadataTest MDLocationTest;
+
+TEST_F(MDLocationTest, Overflow) {
+ MDNode *N = MDNode::get(Context, None);
+ {
+ MDLocation *L = MDLocation::get(Context, 2, 7, N);
+ EXPECT_EQ(2u, L->getLine());
+ EXPECT_EQ(7u, L->getColumn());
+ }
+ unsigned U24 = 1u << 24;
+ unsigned U8 = 1u << 8;
+ {
+ MDLocation *L = MDLocation::get(Context, U24 - 1, U8 - 1, N);
+ EXPECT_EQ(U24 - 1, L->getLine());
+ EXPECT_EQ(U8 - 1, L->getColumn());
+ }
+ {
+ MDLocation *L = MDLocation::get(Context, U24, U8, N);
+ EXPECT_EQ(0u, L->getLine());
+ EXPECT_EQ(0u, L->getColumn());
+ }
+ {
+ MDLocation *L = MDLocation::get(Context, U24 + 1, U8 + 1, N);
+ EXPECT_EQ(0u, L->getLine());
+ EXPECT_EQ(0u, L->getColumn());
+ }
+}
+
+TEST_F(MDLocationTest, getDistinct) {
+ MDNode *N = MDNode::get(Context, None);
+ MDLocation *L0 = MDLocation::getDistinct(Context, 2, 7, N);
+ EXPECT_TRUE(L0->isDistinct());
+ MDLocation *L1 = MDLocation::get(Context, 2, 7, N);
+ EXPECT_FALSE(L1->isDistinct());
+ EXPECT_EQ(L1, MDLocation::get(Context, 2, 7, N));
+}
+
typedef MetadataTest MetadataAsValueTest;
TEST_F(MetadataAsValueTest, MDNode) {
OpenPOWER on IntegriCloud