From 79185d80dc8affac84c7bbb0ea65d71720273277 Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Tue, 30 Aug 2016 01:37:58 +0000 Subject: [PATCH] ADT: Explode include/llvm/ADT/{ilist,ilist_node}.h, NFC I'm working on a lower-level intrusive list that can be used stand-alone, and splitting the files up a bit will make the code easier to organize. Explode the ilist headers in advance to improve blame lists in the future. - Move ilist_node_base from ilist_node.h to ilist_node_base.h. - Move ilist_base from ilist.h to ilist_base.h. - Move ilist_iterator from ilist.h to ilist_iterator.h. - Move ilist_node_access from ilist.h to ilist_node.h to support ilist_iterator. - Update unit tests to #include smaller headers. - Clang-format the moved things. I noticed in transit that there is a simplify_type specialization for ilist_iterator. Since there is no longer an implicit conversion from ilist::iterator to T*, this doesn't make sense (effectively it's a form of implicit conversion). For now I've added a FIXME. llvm-svn: 280047 --- llvm/include/llvm/ADT/ilist.h | 240 +---------------------- llvm/include/llvm/ADT/ilist_base.h | 78 ++++++++ llvm/include/llvm/ADT/ilist_iterator.h | 172 ++++++++++++++++ llvm/include/llvm/ADT/ilist_node.h | 58 +++--- llvm/include/llvm/ADT/ilist_node_base.h | 47 +++++ llvm/unittests/ADT/IListBaseTest.cpp | 2 +- llvm/unittests/ADT/IListNodeBaseTest.cpp | 2 +- 7 files changed, 330 insertions(+), 269 deletions(-) create mode 100644 llvm/include/llvm/ADT/ilist_base.h create mode 100644 llvm/include/llvm/ADT/ilist_iterator.h create mode 100644 llvm/include/llvm/ADT/ilist_node_base.h diff --git a/llvm/include/llvm/ADT/ilist.h b/llvm/include/llvm/ADT/ilist.h index 1a8f67fd4700..5c031a832f7b 100644 --- a/llvm/include/llvm/ADT/ilist.h +++ b/llvm/include/llvm/ADT/ilist.h @@ -24,6 +24,8 @@ #ifndef LLVM_ADT_ILIST_H #define LLVM_ADT_ILIST_H +#include "llvm/ADT/ilist_base.h" +#include "llvm/ADT/ilist_iterator.h" #include "llvm/ADT/ilist_node.h" #include "llvm/Support/Compiler.h" #include @@ -35,36 +37,6 @@ namespace llvm { template class iplist; -template class ilist_iterator; - -/// An access class for ilist_node private API. -/// -/// This gives access to the private parts of ilist nodes. Nodes for an ilist -/// should friend this class if they inherit privately from ilist_node. -/// -/// It's strongly discouraged to *use* this class outside of the ilist -/// implementation. -struct ilist_node_access { - template static ilist_node *getNodePtr(T *N) { return N; } - template static const ilist_node *getNodePtr(const T *N) { - return N; - } - - template static ilist_node *getPrev(ilist_node &N) { - return N.getPrev(); - } - template static ilist_node *getNext(ilist_node &N) { - return N.getNext(); - } - template - static const ilist_node *getPrev(const ilist_node &N) { - return N.getPrev(); - } - template - static const ilist_node *getNext(const ilist_node &N) { - return N.getNext(); - } -}; namespace ilist_detail { @@ -139,214 +111,6 @@ struct ilist_traits : public ilist_default_traits {}; template struct ilist_traits : public ilist_traits {}; -namespace ilist_detail { -template struct ConstCorrectNodeType { - typedef ilist_node type; -}; -template struct ConstCorrectNodeType { - typedef const ilist_node type; -}; - -template struct IteratorHelper { - template static void increment(T *&I) { - I = ilist_node_access::getNext(*I); - } - template static void decrement(T *&I) { - I = ilist_node_access::getPrev(*I); - } -}; -template <> struct IteratorHelper { - template static void increment(T *&I) { - IteratorHelper::decrement(I); - } - template static void decrement(T *&I) { - IteratorHelper::increment(I); - } -}; - -} // end namespace ilist_detail - -//===----------------------------------------------------------------------===// -// Iterator for intrusive list. -// -template -class ilist_iterator - : public std::iterator { -public: - typedef std::iterator - super; - - typedef typename super::value_type value_type; - typedef typename super::difference_type difference_type; - typedef typename super::pointer pointer; - typedef typename super::reference reference; - - typedef typename std::add_const::type *const_pointer; - typedef typename std::add_const::type &const_reference; - - typedef typename ilist_detail::ConstCorrectNodeType::type node_type; - typedef node_type *node_pointer; - typedef node_type &node_reference; - -private: - node_pointer NodePtr; - -public: - /// Create from an ilist_node. - explicit ilist_iterator(node_reference N) : NodePtr(&N) {} - - explicit ilist_iterator(pointer NP) : NodePtr(NP) {} - explicit ilist_iterator(reference NR) : NodePtr(&NR) {} - ilist_iterator() : NodePtr(nullptr) {} - - // This is templated so that we can allow constructing a const iterator from - // a nonconst iterator... - template - ilist_iterator( - const ilist_iterator &RHS, - typename std::enable_if::value, - void *>::type = nullptr) - : NodePtr(RHS.getNodePtr()) {} - - // This is templated so that we can allow assigning to a const iterator from - // a nonconst iterator... - template - const ilist_iterator & - operator=(const ilist_iterator &RHS) { - NodePtr = RHS.getNodePtr(); - return *this; - } - - /// Convert from an iterator to its reverse. - /// - /// TODO: Roll this into the implicit constructor once we're sure that no one - /// is relying on the std::reverse_iterator off-by-one semantics. - ilist_iterator getReverse() const { - if (NodePtr) - return ilist_iterator(*NodePtr); - return ilist_iterator(); - } - - void reset(pointer NP) { NodePtr = NP; } - - // Accessors... - reference operator*() const { - assert(!NodePtr->isKnownSentinel()); - return static_cast(*getNodePtr()); - } - pointer operator->() const { return &operator*(); } - - // Comparison operators - friend bool operator==(const ilist_iterator &LHS, const ilist_iterator &RHS) { - return LHS.NodePtr == RHS.NodePtr; - } - friend bool operator!=(const ilist_iterator &LHS, const ilist_iterator &RHS) { - return LHS.NodePtr != RHS.NodePtr; - } - - // Increment and decrement operators... - ilist_iterator &operator--() { - ilist_detail::IteratorHelper::decrement(NodePtr); - return *this; - } - ilist_iterator &operator++() { - ilist_detail::IteratorHelper::increment(NodePtr); - return *this; - } - ilist_iterator operator--(int) { - ilist_iterator tmp = *this; - --*this; - return tmp; - } - ilist_iterator operator++(int) { - ilist_iterator tmp = *this; - ++*this; - return tmp; - } - - /// Get the underlying ilist_node. - node_pointer getNodePtr() const { return static_cast(NodePtr); } -}; - -// Allow ilist_iterators to convert into pointers to a node automatically when -// used by the dyn_cast, cast, isa mechanisms... - -template struct simplify_type; - -template struct simplify_type > { - typedef NodeTy* SimpleType; - - static SimpleType getSimplifiedValue(ilist_iterator &Node) { - return &*Node; - } -}; -template struct simplify_type > { - typedef /*const*/ NodeTy* SimpleType; - - static SimpleType getSimplifiedValue(const ilist_iterator &Node) { - return &*Node; - } -}; - -/// Implementations of list algorithms using ilist_node_base. -class ilist_base { -public: - static void insertBeforeImpl(ilist_node_base &Next, ilist_node_base &N) { - ilist_node_base &Prev = *Next.getPrev(); - N.setNext(&Next); - N.setPrev(&Prev); - Prev.setNext(&N); - Next.setPrev(&N); - } - - static void removeImpl(ilist_node_base &N) { - ilist_node_base *Prev = N.getPrev(); - ilist_node_base *Next = N.getNext(); - Next->setPrev(Prev); - Prev->setNext(Next); - - // Not strictly necessary, but helps catch a class of bugs. - N.setPrev(nullptr); - N.setNext(nullptr); - } - - static void transferBeforeImpl(ilist_node_base &Next, ilist_node_base &First, - ilist_node_base &Last) { - assert(&Next != &Last && "Should be checked by callers"); - assert(&First != &Last && "Should be checked by callers"); - // Position cannot be contained in the range to be transferred. - assert(&Next != &First && - // Check for the most common mistake. - "Insertion point can't be one of the transferred nodes"); - - ilist_node_base &Final = *Last.getPrev(); - - // Detach from old list/position. - First.getPrev()->setNext(&Last); - Last.setPrev(First.getPrev()); - - // Splice [First, Final] into its new list/position. - ilist_node_base &Prev = *Next.getPrev(); - Final.setNext(&Next); - First.setPrev(&Prev); - Prev.setNext(&First); - Next.setPrev(&Final); - } - - template - static void insertBefore(ilist_node &Next, ilist_node &N) { - insertBeforeImpl(Next, N); - } - - template static void remove(ilist_node &N) { removeImpl(N); } - - template - static void transferBefore(ilist_node &Next, ilist_node &First, - ilist_node &Last) { - transferBeforeImpl(Next, First, Last); - } -}; - //===----------------------------------------------------------------------===// // /// The subset of list functionality that can safely be used on nodes of diff --git a/llvm/include/llvm/ADT/ilist_base.h b/llvm/include/llvm/ADT/ilist_base.h new file mode 100644 index 000000000000..27a39bedef0e --- /dev/null +++ b/llvm/include/llvm/ADT/ilist_base.h @@ -0,0 +1,78 @@ +//===- llvm/ADT/ilist_base.h - Intrusive List Base ---------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_BASE_H +#define LLVM_ADT_ILIST_BASE_H + +#include "llvm/ADT/ilist_node_base.h" +#include +#include +#include + +namespace llvm { + +/// Implementations of list algorithms using ilist_node_base. +class ilist_base { +public: + static void insertBeforeImpl(ilist_node_base &Next, ilist_node_base &N) { + ilist_node_base &Prev = *Next.getPrev(); + N.setNext(&Next); + N.setPrev(&Prev); + Prev.setNext(&N); + Next.setPrev(&N); + } + + static void removeImpl(ilist_node_base &N) { + ilist_node_base *Prev = N.getPrev(); + ilist_node_base *Next = N.getNext(); + Next->setPrev(Prev); + Prev->setNext(Next); + + // Not strictly necessary, but helps catch a class of bugs. + N.setPrev(nullptr); + N.setNext(nullptr); + } + + static void transferBeforeImpl(ilist_node_base &Next, ilist_node_base &First, + ilist_node_base &Last) { + assert(&Next != &Last && "Should be checked by callers"); + assert(&First != &Last && "Should be checked by callers"); + // Position cannot be contained in the range to be transferred. + assert(&Next != &First && + // Check for the most common mistake. + "Insertion point can't be one of the transferred nodes"); + + ilist_node_base &Final = *Last.getPrev(); + + // Detach from old list/position. + First.getPrev()->setNext(&Last); + Last.setPrev(First.getPrev()); + + // Splice [First, Final] into its new list/position. + ilist_node_base &Prev = *Next.getPrev(); + Final.setNext(&Next); + First.setPrev(&Prev); + Prev.setNext(&First); + Next.setPrev(&Final); + } + + template static void insertBefore(T &Next, T &N) { + insertBeforeImpl(Next, N); + } + + template static void remove(T &N) { removeImpl(N); } + + template static void transferBefore(T &Next, T &First, T &Last) { + transferBeforeImpl(Next, First, Last); + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_ILIST_BASE_H diff --git a/llvm/include/llvm/ADT/ilist_iterator.h b/llvm/include/llvm/ADT/ilist_iterator.h new file mode 100644 index 000000000000..c39bca314bdd --- /dev/null +++ b/llvm/include/llvm/ADT/ilist_iterator.h @@ -0,0 +1,172 @@ +//===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator -------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_ITERATOR_H +#define LLVM_ADT_ILIST_ITERATOR_H + +#include "llvm/ADT/ilist_node.h" +#include +#include +#include +#include + +namespace llvm { + +namespace ilist_detail { + +template struct ConstCorrectNodeType { + typedef ilist_node type; +}; +template struct ConstCorrectNodeType { + typedef const ilist_node type; +}; + +template struct IteratorHelper { + template static void increment(T *&I) { + I = ilist_node_access::getNext(*I); + } + template static void decrement(T *&I) { + I = ilist_node_access::getPrev(*I); + } +}; +template <> struct IteratorHelper { + template static void increment(T *&I) { + IteratorHelper::decrement(I); + } + template static void decrement(T *&I) { + IteratorHelper::increment(I); + } +}; + +} // end namespace ilist_detail + +/// Iterator for intrusive lists based on ilist_node. +template +class ilist_iterator + : public std::iterator { +public: + typedef std::iterator + super; + + typedef typename super::value_type value_type; + typedef typename super::difference_type difference_type; + typedef typename super::pointer pointer; + typedef typename super::reference reference; + + typedef typename std::add_const::type *const_pointer; + typedef typename std::add_const::type &const_reference; + + typedef typename ilist_detail::ConstCorrectNodeType::type node_type; + typedef node_type *node_pointer; + typedef node_type &node_reference; + +private: + node_pointer NodePtr; + +public: + /// Create from an ilist_node. + explicit ilist_iterator(node_reference N) : NodePtr(&N) {} + + explicit ilist_iterator(pointer NP) : NodePtr(NP) {} + explicit ilist_iterator(reference NR) : NodePtr(&NR) {} + ilist_iterator() : NodePtr(nullptr) {} + + // This is templated so that we can allow constructing a const iterator from + // a nonconst iterator... + template + ilist_iterator( + const ilist_iterator &RHS, + typename std::enable_if::value, + void *>::type = nullptr) + : NodePtr(RHS.getNodePtr()) {} + + // This is templated so that we can allow assigning to a const iterator from + // a nonconst iterator... + template + const ilist_iterator & + operator=(const ilist_iterator &RHS) { + NodePtr = RHS.getNodePtr(); + return *this; + } + + /// Convert from an iterator to its reverse. + /// + /// TODO: Roll this into the implicit constructor once we're sure that no one + /// is relying on the std::reverse_iterator off-by-one semantics. + ilist_iterator getReverse() const { + if (NodePtr) + return ilist_iterator(*NodePtr); + return ilist_iterator(); + } + + void reset(pointer NP) { NodePtr = NP; } + + // Accessors... + reference operator*() const { + assert(!NodePtr->isKnownSentinel()); + return static_cast(*getNodePtr()); + } + pointer operator->() const { return &operator*(); } + + // Comparison operators + friend bool operator==(const ilist_iterator &LHS, const ilist_iterator &RHS) { + return LHS.NodePtr == RHS.NodePtr; + } + friend bool operator!=(const ilist_iterator &LHS, const ilist_iterator &RHS) { + return LHS.NodePtr != RHS.NodePtr; + } + + // Increment and decrement operators... + ilist_iterator &operator--() { + ilist_detail::IteratorHelper::decrement(NodePtr); + return *this; + } + ilist_iterator &operator++() { + ilist_detail::IteratorHelper::increment(NodePtr); + return *this; + } + ilist_iterator operator--(int) { + ilist_iterator tmp = *this; + --*this; + return tmp; + } + ilist_iterator operator++(int) { + ilist_iterator tmp = *this; + ++*this; + return tmp; + } + + /// Get the underlying ilist_node. + node_pointer getNodePtr() const { return static_cast(NodePtr); } +}; + +template struct simplify_type; + +/// Allow ilist_iterators to convert into pointers to a node automatically when +/// used by the dyn_cast, cast, isa mechanisms... +/// +/// FIXME: remove this, since there is no implicit conversion to NodeTy. +template struct simplify_type> { + typedef NodeTy *SimpleType; + + static SimpleType getSimplifiedValue(ilist_iterator &Node) { + return &*Node; + } +}; +template struct simplify_type> { + typedef /*const*/ NodeTy *SimpleType; + + static SimpleType getSimplifiedValue(const ilist_iterator &Node) { + return &*Node; + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_ILIST_ITERATOR_H diff --git a/llvm/include/llvm/ADT/ilist_node.h b/llvm/include/llvm/ADT/ilist_node.h index 0e4bd9722924..4c69c71b7441 100644 --- a/llvm/include/llvm/ADT/ilist_node.h +++ b/llvm/include/llvm/ADT/ilist_node.h @@ -15,41 +15,13 @@ #ifndef LLVM_ADT_ILIST_NODE_H #define LLVM_ADT_ILIST_NODE_H -#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/ilist_node_base.h" namespace llvm { template struct ilist_traits; -/// Base class for ilist nodes. -class ilist_node_base { -#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS - PointerIntPair PrevAndSentinel; -#else - ilist_node_base *Prev = nullptr; -#endif - ilist_node_base *Next = nullptr; - -public: -#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS - void setPrev(ilist_node_base *Prev) { PrevAndSentinel.setPointer(Prev); } - ilist_node_base *getPrev() const { return PrevAndSentinel.getPointer(); } - - bool isKnownSentinel() const { return PrevAndSentinel.getInt(); } - void initializeSentinel() { PrevAndSentinel.setInt(true); } -#else - void setPrev(ilist_node_base *Prev) { this->Prev = Prev; } - ilist_node_base *getPrev() const { return Prev; } - - bool isKnownSentinel() const { return false; } - void initializeSentinel() {} -#endif - - void setNext(ilist_node_base *Next) { this->Next = Next; } - ilist_node_base *getNext() const { return Next; } -}; - struct ilist_node_access; template class ilist_iterator; template class ilist_sentinel; @@ -93,6 +65,34 @@ public: using ilist_node_base::isKnownSentinel; }; +/// An access class for ilist_node private API. +/// +/// This gives access to the private parts of ilist nodes. Nodes for an ilist +/// should friend this class if they inherit privately from ilist_node. +/// +/// Using this class outside of the ilist implementation is unsupported. +struct ilist_node_access { + template static ilist_node *getNodePtr(T *N) { return N; } + template static const ilist_node *getNodePtr(const T *N) { + return N; + } + + template static ilist_node *getPrev(ilist_node &N) { + return N.getPrev(); + } + template static ilist_node *getNext(ilist_node &N) { + return N.getNext(); + } + template + static const ilist_node *getPrev(const ilist_node &N) { + return N.getPrev(); + } + template + static const ilist_node *getNext(const ilist_node &N) { + return N.getNext(); + } +}; + template class ilist_sentinel : public ilist_node { public: ilist_sentinel() { diff --git a/llvm/include/llvm/ADT/ilist_node_base.h b/llvm/include/llvm/ADT/ilist_node_base.h new file mode 100644 index 000000000000..6a46876c6392 --- /dev/null +++ b/llvm/include/llvm/ADT/ilist_node_base.h @@ -0,0 +1,47 @@ +//===- llvm/ADT/ilist_node_base.h - Intrusive List Node Base -----*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_NODE_BASE_H +#define LLVM_ADT_ILIST_NODE_BASE_H + +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + +/// Base class for ilist nodes. +class ilist_node_base { +#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS + PointerIntPair PrevAndSentinel; +#else + ilist_node_base *Prev = nullptr; +#endif + ilist_node_base *Next = nullptr; + +public: +#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS + void setPrev(ilist_node_base *Prev) { PrevAndSentinel.setPointer(Prev); } + ilist_node_base *getPrev() const { return PrevAndSentinel.getPointer(); } + + bool isKnownSentinel() const { return PrevAndSentinel.getInt(); } + void initializeSentinel() { PrevAndSentinel.setInt(true); } +#else + void setPrev(ilist_node_base *Prev) { this->Prev = Prev; } + ilist_node_base *getPrev() const { return Prev; } + + bool isKnownSentinel() const { return false; } + void initializeSentinel() {} +#endif + + void setNext(ilist_node_base *Next) { this->Next = Next; } + ilist_node_base *getNext() const { return Next; } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_ILIST_NODE_BASE_H diff --git a/llvm/unittests/ADT/IListBaseTest.cpp b/llvm/unittests/ADT/IListBaseTest.cpp index 1cb8fff55610..192233277859 100644 --- a/llvm/unittests/ADT/IListBaseTest.cpp +++ b/llvm/unittests/ADT/IListBaseTest.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_base.h" #include "gtest/gtest.h" using namespace llvm; diff --git a/llvm/unittests/ADT/IListNodeBaseTest.cpp b/llvm/unittests/ADT/IListNodeBaseTest.cpp index 1e9c2a1fa040..0fb1282b21da 100644 --- a/llvm/unittests/ADT/IListNodeBaseTest.cpp +++ b/llvm/unittests/ADT/IListNodeBaseTest.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/ilist_node_base.h" #include "gtest/gtest.h" using namespace llvm;