[DIE] Make DIE.h NDEBUG conditional-free.
[oota-llvm.git] / include / llvm / CodeGen / DIE.h
index 5d589f7619be867175d995e82f762bb6a11bbb0d..fa612d981dec15e5349c7d62640c5abf53b9802a 100644 (file)
@@ -100,10 +100,8 @@ public:
   ///
   void Emit(const AsmPrinter *AP) const;
 
-#ifndef NDEBUG
   void print(raw_ostream &O);
   void dump();
-#endif
 };
 
 //===--------------------------------------------------------------------===//
@@ -143,9 +141,7 @@ public:
   void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
   unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
 
-#ifndef NDEBUG
   void print(raw_ostream &O) const;
-#endif
 };
 
 //===--------------------------------------------------------------------===//
@@ -164,9 +160,7 @@ public:
   void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
   unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
 
-#ifndef NDEBUG
   void print(raw_ostream &O) const;
-#endif
 };
 
 //===--------------------------------------------------------------------===//
@@ -185,9 +179,7 @@ public:
   void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
   unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
 
-#ifndef NDEBUG
   void print(raw_ostream &O) const;
-#endif
 };
 
 //===--------------------------------------------------------------------===//
@@ -203,9 +195,7 @@ public:
   void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
   unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
 
-#ifndef NDEBUG
   void print(raw_ostream &O) const;
-#endif
 };
 
 //===--------------------------------------------------------------------===//
@@ -223,9 +213,7 @@ public:
   void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
   unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
 
-#ifndef NDEBUG
   void print(raw_ostream &O) const;
-#endif
 };
 
 //===--------------------------------------------------------------------===//
@@ -252,9 +240,7 @@ public:
                                            : sizeof(int32_t);
   }
 
-#ifndef NDEBUG
   void print(raw_ostream &O) const;
-#endif
 };
 
 //===--------------------------------------------------------------------===//
@@ -273,9 +259,7 @@ public:
     return 8;
   }
 
-#ifndef NDEBUG
   void print(raw_ostream &O) const;
-#endif
 };
 
 //===--------------------------------------------------------------------===//
@@ -295,9 +279,7 @@ public:
   void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
   unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
 
-#ifndef NDEBUG
   void print(raw_ostream &O) const;
-#endif
 };
 
 //===--------------------------------------------------------------------===//
@@ -444,10 +426,8 @@ public:
   ///
   unsigned SizeOf(const AsmPrinter *AP) const;
 
-#ifndef NDEBUG
   void print(raw_ostream &O) const;
   void dump() const;
-#endif
 };
 
 struct IntrusiveBackListNode {
@@ -512,7 +492,8 @@ public:
 
   public:
     const_iterator() = default;
-    const_iterator(iterator X) : N(X.N) {}
+    // Placate MSVC by explicitly scoping 'iterator'.
+    const_iterator(typename IntrusiveBackList<T>::iterator X) : N(X.N) {}
     explicit const_iterator(const T *N) : N(N) {}
 
     const_iterator &operator++() {
@@ -545,6 +526,16 @@ public:
 /// This is a singly-linked list, but instead of reversing the order of
 /// insertion, we keep a pointer to the back of the list so we can push in
 /// order.
+///
+/// There are two main reasons to choose a linked list over a customized
+/// vector-like data structure.
+///
+///  1. For teardown efficiency, we want DIEs to be BumpPtrAllocated.  Using a
+///     linked list here makes this way easier to accomplish.
+///  2. Carrying an extra pointer per \a DIEValue isn't expensive.  45% of DIEs
+///     have 2 or fewer values, and 90% have 5 or fewer.  A vector would be
+///     over-allocated by 50% on average anyway, the same cost as the
+///     linked-list node.
 class DIEValueList {
   struct Node : IntrusiveBackListNode {
     DIEValue V;
@@ -555,62 +546,70 @@ class DIEValueList {
   ListTy List;
 
 public:
-  bool empty() const { return List.empty(); }
-
-  class const_iterator;
-  class iterator
-      : public iterator_adaptor_base<iterator, ListTy::iterator,
+  class const_value_iterator;
+  class value_iterator
+      : public iterator_adaptor_base<value_iterator, ListTy::iterator,
                                      std::forward_iterator_tag, DIEValue> {
-    friend class const_iterator;
-    typedef iterator_adaptor_base<iterator, ListTy::iterator,
+    friend class const_value_iterator;
+    typedef iterator_adaptor_base<value_iterator, ListTy::iterator,
                                   std::forward_iterator_tag,
                                   DIEValue> iterator_adaptor;
 
   public:
-    iterator() = default;
-    explicit iterator(ListTy::iterator X) : iterator_adaptor(X) {}
+    value_iterator() = default;
+    explicit value_iterator(ListTy::iterator X) : iterator_adaptor(X) {}
 
     explicit operator bool() const { return bool(wrapped()); }
     DIEValue &operator*() const { return wrapped()->V; }
   };
 
-  class const_iterator
-      : public iterator_adaptor_base<const_iterator, ListTy::const_iterator,
-                                     std::forward_iterator_tag,
-                                     const DIEValue> {
-    typedef iterator_adaptor_base<const_iterator, ListTy::const_iterator,
+  class const_value_iterator : public iterator_adaptor_base<
+                                   const_value_iterator, ListTy::const_iterator,
+                                   std::forward_iterator_tag, const DIEValue> {
+    typedef iterator_adaptor_base<const_value_iterator, ListTy::const_iterator,
                                   std::forward_iterator_tag,
                                   const DIEValue> iterator_adaptor;
 
   public:
-    const_iterator() = default;
-    const_iterator(DIEValueList::iterator X) : iterator_adaptor(X.wrapped()) {}
-    explicit const_iterator(ListTy::const_iterator X) : iterator_adaptor(X) {}
+    const_value_iterator() = default;
+    const_value_iterator(DIEValueList::value_iterator X)
+        : iterator_adaptor(X.wrapped()) {}
+    explicit const_value_iterator(ListTy::const_iterator X)
+        : iterator_adaptor(X) {}
 
     explicit operator bool() const { return bool(wrapped()); }
     const DIEValue &operator*() const { return wrapped()->V; }
   };
 
-  iterator insert(BumpPtrAllocator &Alloc, DIEValue V) {
+  typedef iterator_range<value_iterator> value_range;
+  typedef iterator_range<const_value_iterator> const_value_range;
+
+  value_iterator addValue(BumpPtrAllocator &Alloc, DIEValue V) {
     List.push_back(*new (Alloc) Node(V));
-    return iterator(ListTy::toIterator(List.back()));
+    return value_iterator(ListTy::toIterator(List.back()));
   }
-  template <class... Ts>
-  iterator emplace(BumpPtrAllocator &Alloc, Ts &&... Args) {
-    return insert(Alloc, DIEValue(std::forward<Ts>(Args)...));
+  template <class T>
+  value_iterator addValue(BumpPtrAllocator &Alloc, dwarf::Attribute Attribute,
+                    dwarf::Form Form, T &&Value) {
+    return addValue(Alloc, DIEValue(Attribute, Form, std::forward<T>(Value)));
   }
 
-  iterator begin() { return iterator(List.begin()); }
-  iterator end() { return iterator(List.end()); }
-  const_iterator begin() const { return const_iterator(List.begin()); }
-  const_iterator end() const { return const_iterator(List.end()); }
+  value_range values() {
+    return llvm::make_range(value_iterator(List.begin()),
+                            value_iterator(List.end()));
+  }
+  const_value_range values() const {
+    return llvm::make_range(const_value_iterator(List.begin()),
+                            const_value_iterator(List.end()));
+  }
 };
 
 //===--------------------------------------------------------------------===//
 /// DIE - A structured debug information entry.  Has an abbreviation which
 /// describes its organization.
-class DIE {
-protected:
+class DIE : IntrusiveBackListNode, public DIEValueList {
+  friend class IntrusiveBackList<DIE>;
+
   /// Offset - Offset in debug info section.
   ///
   unsigned Offset;
@@ -626,27 +625,17 @@ protected:
   dwarf::Tag Tag = (dwarf::Tag)0;
 
   /// Children DIEs.
-  ///
-  // This can't be a vector<DIE> because pointer validity is requirent for the
-  // Parent pointer and DIEEntry.
-  // It can't be a list<DIE> because some clients need pointer validity before
-  // the object has been added to any child list
-  // (eg: DwarfUnit::constructVariableDIE). These aren't insurmountable, but may
-  // be more convoluted than beneficial.
-  std::vector<std::unique_ptr<DIE>> Children;
+  IntrusiveBackList<DIE> Children;
 
-  DIE *Parent;
+  DIE *Parent = nullptr;
 
-  /// Attribute values.
-  ///
-  DIEValueList Values;
-
-protected:
-  DIE() : Offset(0), Size(0), Parent(nullptr) {}
+  DIE() = delete;
+  explicit DIE(dwarf::Tag Tag) : Offset(0), Size(0), Tag(Tag) {}
 
 public:
-  explicit DIE(dwarf::Tag Tag)
-      : Offset(0), Size(0), Tag(Tag), Parent(nullptr) {}
+  static DIE *get(BumpPtrAllocator &Alloc, dwarf::Tag Tag) {
+    return new (Alloc) DIE(Tag);
+  }
 
   // Accessors.
   unsigned getAbbrevNumber() const { return AbbrevNumber; }
@@ -655,25 +644,16 @@ public:
   unsigned getSize() const { return Size; }
   bool hasChildren() const { return !Children.empty(); }
 
-  typedef std::vector<std::unique_ptr<DIE>>::const_iterator child_iterator;
+  typedef IntrusiveBackList<DIE>::iterator child_iterator;
+  typedef IntrusiveBackList<DIE>::const_iterator const_child_iterator;
   typedef iterator_range<child_iterator> child_range;
+  typedef iterator_range<const_child_iterator> const_child_range;
 
-  child_range children() const {
+  child_range children() {
     return llvm::make_range(Children.begin(), Children.end());
   }
-
-  typedef DIEValueList::iterator value_iterator;
-  typedef iterator_range<value_iterator> value_range;
-
-  value_range values() {
-    return llvm::make_range(Values.begin(), Values.end());
-  }
-
-  typedef DIEValueList::const_iterator const_value_iterator;
-  typedef iterator_range<const_value_iterator> const_value_range;
-
-  const_value_range values() const {
-    return llvm::make_range(Values.begin(), Values.end());
+  const_child_range children() const {
+    return llvm::make_range(Children.begin(), Children.end());
   }
 
   DIE *getParent() const { return Parent; }
@@ -696,24 +676,12 @@ public:
   void setOffset(unsigned O) { Offset = O; }
   void setSize(unsigned S) { Size = S; }
 
-  /// addValue - Add a value and attributes to a DIE.
-  ///
-  value_iterator addValue(BumpPtrAllocator &Alloc, DIEValue Value) {
-    return Values.insert(Alloc, Value);
-  }
-  template <class T>
-  value_iterator addValue(BumpPtrAllocator &Alloc, dwarf::Attribute Attribute,
-                          dwarf::Form Form, T &&Value) {
-    return Values.emplace(Alloc, Attribute, Form, std::forward<T>(Value));
-  }
-
-  /// addChild - Add a child to the DIE.
-  ///
-  DIE &addChild(std::unique_ptr<DIE> Child) {
-    assert(!Child->getParent());
+  /// Add a child to the DIE.
+  DIE &addChild(DIE *Child) {
+    assert(!Child->getParent() && "Child should be orphaned");
     Child->Parent = this;
-    Children.push_back(std::move(Child));
-    return *Children.back();
+    Children.push_back(*Child);
+    return Children.back();
   }
 
   /// Find a value in the DIE with the attribute given.
@@ -722,16 +690,14 @@ public:
   /// gives \a DIEValue::isNone) if no such attribute exists.
   DIEValue findAttribute(dwarf::Attribute Attribute) const;
 
-#ifndef NDEBUG
   void print(raw_ostream &O, unsigned IndentCount = 0) const;
   void dump();
-#endif
 };
 
 //===--------------------------------------------------------------------===//
 /// DIELoc - Represents an expression location.
 //
-class DIELoc : public DIE {
+class DIELoc : public DIEValueList {
   mutable unsigned Size; // Size in bytes excluding size header.
 
 public:
@@ -759,15 +725,13 @@ public:
   void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
   unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
 
-#ifndef NDEBUG
   void print(raw_ostream &O) const;
-#endif
 };
 
 //===--------------------------------------------------------------------===//
 /// DIEBlock - Represents a block of values.
 //
-class DIEBlock : public DIE {
+class DIEBlock : public DIEValueList {
   mutable unsigned Size; // Size in bytes excluding size header.
 
 public:
@@ -792,9 +756,7 @@ public:
   void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const;
   unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const;
 
-#ifndef NDEBUG
   void print(raw_ostream &O) const;
-#endif
 };
 
 } // end llvm namespace