IR: Add MDLocation class
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Tue, 13 Jan 2015 20:44:56 +0000 (20:44 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Tue, 13 Jan 2015 20:44:56 +0000 (20:44 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225824 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/Metadata.def
include/llvm/IR/Metadata.h
lib/IR/AsmWriter.cpp
lib/IR/LLVMContextImpl.cpp
lib/IR/LLVMContextImpl.h
lib/IR/Metadata.cpp
unittests/IR/MetadataTest.cpp

index 2d5d91eb12aa272bdd87e16d4b53cbce6a60feab..2098bb57eb56c352e916771396b8a524affc795b 100644 (file)
@@ -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
index da6521bbf3e15c9a9326bd64f805e3df5ccc71ac..10fc99f7b112de6df5ecd711883ab5e9b545a413 100644 (file)
@@ -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
index ea7e0aa5266b364d6c11bc2558bddd5313a061df..215332b82562f271935e936f1547554e3734613b 100644 (file)
@@ -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,
index d47a0d332fbadf4ef8ab30891864a1cf02c23643..1fa080b8133bf4129f4be606c36514fc1312ed8c 100644 (file)
@@ -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();
index 11b8d38f9afba38752231041d1f5e00a4a4b09de..6ebc567f808ff1788a0eb2bdfa8e0fcd61d4f7a8 100644 (file)
@@ -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
index 852f1dc2041d75c9ab6a0ae9d90f8ae0de8165ca..ab83252bfda338e1711f84d978314185ed3d44e3 100644 (file)
@@ -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) {
index 9f5d133943b54aae4538bf601de30f97d57cf4d0..8c5c312a2f71b870e6e009a078d5df21550057f1 100644 (file)
@@ -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) {