///
void Emit(const AsmPrinter *AP) const;
-#ifndef NDEBUG
void print(raw_ostream &O);
void dump();
-#endif
};
//===--------------------------------------------------------------------===//
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
};
//===--------------------------------------------------------------------===//
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
};
//===--------------------------------------------------------------------===//
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
};
//===--------------------------------------------------------------------===//
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
};
//===--------------------------------------------------------------------===//
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
};
//===--------------------------------------------------------------------===//
: sizeof(int32_t);
}
-#ifndef NDEBUG
void print(raw_ostream &O) const;
-#endif
};
//===--------------------------------------------------------------------===//
return 8;
}
-#ifndef NDEBUG
void print(raw_ostream &O) const;
-#endif
};
//===--------------------------------------------------------------------===//
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
};
//===--------------------------------------------------------------------===//
///
unsigned SizeOf(const AsmPrinter *AP) const;
-#ifndef NDEBUG
void print(raw_ostream &O) const;
void dump() const;
-#endif
};
struct IntrusiveBackListNode {
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++() {
/// 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;
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;
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; }
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; }
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.
/// 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:
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:
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