[llvm] r225824 - IR: Add MDLocation class

Duncan P. N. Exon Smith dexonsmith at apple.com
Tue Jan 13 12:44:56 PST 2015


Author: dexonsmith
Date: Tue Jan 13 14:44:56 2015
New Revision: 225824

URL: http://llvm.org/viewvc/llvm-project?rev=225824&view=rev
Log:
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.

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

Modified: llvm/trunk/include/llvm/IR/Metadata.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.def?rev=225824&r1=225823&r2=225824&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Metadata.def (original)
+++ llvm/trunk/include/llvm/IR/Metadata.def Tue Jan 13 14:44:56 2015
@@ -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

Modified: llvm/trunk/include/llvm/IR/Metadata.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.h?rev=225824&r1=225823&r2=225824&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Metadata.h (original)
+++ llvm/trunk/include/llvm/IR/Metadata.h Tue Jan 13 14:44:56 2015
@@ -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
   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

Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=225824&r1=225823&r2=225824&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Tue Jan 13 14:44:56 2015
@@ -1272,6 +1272,39 @@ static void writeMDTuple(raw_ostream &Ou
   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,

Modified: llvm/trunk/lib/IR/LLVMContextImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.cpp?rev=225824&r1=225823&r2=225824&view=diff
==============================================================================
--- llvm/trunk/lib/IR/LLVMContextImpl.cpp (original)
+++ llvm/trunk/lib/IR/LLVMContextImpl.cpp Tue Jan 13 14:44:56 2015
@@ -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();

Modified: llvm/trunk/lib/IR/LLVMContextImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=225824&r1=225823&r2=225824&view=diff
==============================================================================
--- llvm/trunk/lib/IR/LLVMContextImpl.h (original)
+++ llvm/trunk/lib/IR/LLVMContextImpl.h Tue Jan 13 14:44:56 2015
@@ -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

Modified: llvm/trunk/lib/IR/Metadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=225824&r1=225823&r2=225824&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Metadata.cpp (original)
+++ llvm/trunk/lib/IR/Metadata.cpp Tue Jan 13 14:44:56 2015
@@ -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)
 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) {

Modified: llvm/trunk/unittests/IR/MetadataTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=225824&r1=225823&r2=225824&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/MetadataTest.cpp (original)
+++ llvm/trunk/unittests/IR/MetadataTest.cpp Tue Jan 13 14:44:56 2015
@@ -387,6 +387,43 @@ TEST_F(MDNodeTest, replaceResolvedOperan
   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) {





More information about the llvm-commits mailing list