From: Anton Korobeynikov Date: Thu, 29 May 2008 17:41:17 +0000 (+0000) Subject: For PR1338: rename include/llvm/ADT/ilist and friends to end with ".h" X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=43d1fd449f1a0ac9d9dafa0b9569bb6b2e976198;p=oota-llvm.git For PR1338: rename include/llvm/ADT/ilist and friends to end with ".h" git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51687 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Makefile b/Makefile index 36031f7cb3d..83b789fa224 100644 --- a/Makefile +++ b/Makefile @@ -77,9 +77,9 @@ debug-opt-prof: dist-hook:: $(Echo) Eliminating files constructed by configure $(Verb) $(RM) -f \ - $(TopDistDir)/include/llvm/ADT/hash_map \ - $(TopDistDir)/include/llvm/ADT/hash_set \ - $(TopDistDir)/include/llvm/ADT/iterator \ + $(TopDistDir)/include/llvm/ADT/hash_map.h \ + $(TopDistDir)/include/llvm/ADT/hash_set.h \ + $(TopDistDir)/include/llvm/ADT/iterator.h \ $(TopDistDir)/include/llvm/Config/config.h \ $(TopDistDir)/include/llvm/Support/DataTypes.h \ $(TopDistDir)/include/llvm/Support/ThreadSupport.h @@ -95,9 +95,9 @@ install-libs: install FilesToConfig := \ include/llvm/Config/config.h \ include/llvm/Support/DataTypes.h \ - include/llvm/ADT/hash_map \ - include/llvm/ADT/hash_set \ - include/llvm/ADT/iterator + include/llvm/ADT/hash_map.h \ + include/llvm/ADT/hash_set.h \ + include/llvm/ADT/iterator.h FilesToConfigPATH := $(addprefix $(LLVM_OBJ_ROOT)/,$(FilesToConfig)) all-local:: $(FilesToConfigPATH) diff --git a/autoconf/configure.ac b/autoconf/configure.ac index 205788e2fd4..15cfa347c3d 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -981,9 +981,9 @@ dnl contains the same list of files as AC_CONFIG_HEADERS below. This ensures the dnl files can be updated automatically when their *.in sources change. AC_CONFIG_HEADERS([include/llvm/Config/config.h]) AC_CONFIG_HEADERS([include/llvm/Support/DataTypes.h]) -AC_CONFIG_HEADERS([include/llvm/ADT/hash_map]) -AC_CONFIG_HEADERS([include/llvm/ADT/hash_set]) -AC_CONFIG_HEADERS([include/llvm/ADT/iterator]) +AC_CONFIG_HEADERS([include/llvm/ADT/hash_map.h]) +AC_CONFIG_HEADERS([include/llvm/ADT/hash_set.h]) +AC_CONFIG_HEADERS([include/llvm/ADT/iterator.h]) dnl Configure the makefile's configuration data AC_CONFIG_FILES([Makefile.config]) diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index 7dba378cf14..28c18856765 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -34,7 +34,7 @@ #define LLVM_ADT_DEPTHFIRSTITERATOR_H #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" #include "llvm/ADT/SmallPtrSet.h" #include #include diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h index 28aacfeccfc..6e00a217beb 100644 --- a/include/llvm/ADT/EquivalenceClasses.h +++ b/include/llvm/ADT/EquivalenceClasses.h @@ -15,7 +15,7 @@ #ifndef LLVM_ADT_EQUIVALENCECLASSES_H #define LLVM_ADT_EQUIVALENCECLASSES_H -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" #include "llvm/Support/DataTypes.h" #include diff --git a/include/llvm/ADT/HashExtras.h b/include/llvm/ADT/HashExtras.h index 2912df264be..fcc50c8510f 100644 --- a/include/llvm/ADT/HashExtras.h +++ b/include/llvm/ADT/HashExtras.h @@ -17,7 +17,7 @@ #ifndef LLVM_ADT_HASHEXTRAS_H #define LLVM_ADT_HASHEXTRAS_H -#include "llvm/ADT/hash_map" +#include "llvm/ADT/hash_map.h" #include // Cannot specialize hash template from outside of the std namespace. diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h index f68de30ff61..cc43d26d348 100644 --- a/include/llvm/ADT/PostOrderIterator.h +++ b/include/llvm/ADT/PostOrderIterator.h @@ -17,7 +17,7 @@ #define LLVM_ADT_POSTORDERITERATOR_H #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" #include #include #include diff --git a/include/llvm/ADT/SCCIterator.h b/include/llvm/ADT/SCCIterator.h index bd18f13ada9..ab5e2f4fc3e 100644 --- a/include/llvm/ADT/SCCIterator.h +++ b/include/llvm/ADT/SCCIterator.h @@ -22,7 +22,7 @@ #define LLVM_ADT_SCCITERATOR_H #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" #include #include diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index dd1b5416330..f1883959d76 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -20,7 +20,7 @@ #include #include // for std::pair #include // for std::size_t -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" namespace llvm { diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index c2e2c17ad28..843d561b6bc 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -14,7 +14,7 @@ #ifndef LLVM_ADT_SMALLVECTOR_H #define LLVM_ADT_SMALLVECTOR_H -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" #include #include diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index 4c28682d399..adeb541d3d0 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -21,7 +21,7 @@ #include "llvm/Support/DataTypes.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/MathExtras.h" -#include "llvm/ADT/ilist" +#include "llvm/ADT/ilist.h" namespace llvm { /// SparseBitVector is an implementation of a bitvector that is sparse by only diff --git a/include/llvm/ADT/hash_map.h.in b/include/llvm/ADT/hash_map.h.in new file mode 100644 index 00000000000..088fe93808c --- /dev/null +++ b/include/llvm/ADT/hash_map.h.in @@ -0,0 +1,150 @@ +//==-- llvm/ADT/hash_map.h - "Portable" wrapper around hash_map --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a wrapper around the mysterious header file +// that seems to move around between GCC releases into and out of namespaces at +// will. #including this header will cause hash_map to be available in the +// global namespace. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_HASH_MAP +#define LLVM_ADT_HASH_MAP + +// Compiler Support Matrix +// +// Version Namespace Header File +// 2.95.x :: hash_map +// 3.0.4 std ext/hash_map +// 3.1 __gnu_cxx ext/hash_map +// HP aCC6 std stdex/rw/hashm*ap.h +// MS VC++ stdext hash_map + +#undef HAVE_GNU_EXT_HASH_MAP +#undef HAVE_STD_EXT_HASH_MAP +#undef HAVE_GLOBAL_HASH_MAP +#undef HAVE_RW_STDEX_HASH_MAP_H + +#if HAVE_GNU_EXT_HASH_MAP +// This is for GCC-3.1+ which puts hash in ext/hash_map +# include +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE __gnu_cxx +# endif + +// GCC 3.0.x puts hash_map in and in the std namespace. +#elif HAVE_STD_EXT_HASH_MAP +# include +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE std +# endif + +// Older compilers such as GCC before version 3.0 do not keep +// extensions in the `ext' directory, and ignore the `std' namespace. +#elif HAVE_GLOBAL_HASH_MAP +# include +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE std +# endif + +// HP aCC doesn't include an SGI-like hash_map. For this platform (or +// any others using Rogue Wave Software's Tools.h++ library), we wrap +// around them in std:: +#elif HAVE_RW_STDEX_HASH_MAP_H +# include +# include +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE std +# endif + +// Support Microsoft VC++. +#elif defined(_MSC_VER) +# include +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE stdext + using std::_Distance; +# endif + +// Give a warning if we couldn't find it, instead of (or in addition to) +// randomly doing something dumb. +#else +# warning "Autoconfiguration failed to find the hash_map header file." +#endif + +// we wrap Rogue Wave Tools.h++ rw_hashmap into something SGI-looking, here: +#ifdef HAVE_RW_STDEX_HASH_MAP_H +namespace HASH_NAMESPACE { + +template struct hash { + unsigned int operator()(const unsigned int& x) const { + return x; + } +}; + +template , + class _EqualKey = equal_to, + class _A = allocator > +class hash_map : public rw_hashmap { +}; + +template , + class _EqualKey = equal_to, + class _A = allocator > +class hash_multimap : public rw_hashmultimap { +}; + +} // end HASH_NAMESPACE; +#endif + +// Include vector because ext/hash_map includes stl_vector.h and leaves +// out specializations like stl_bvector.h, causing link conflicts. +#include + +#ifdef _MSC_VER + +// GCC and VC++ have differing ways of implementing hash_maps. As it's not +// standardized, that's to be expected. This adapter class allows VC++ +// hash_map to use GCC's hash classes. +namespace stdext { + template struct hash; + + // Provide a hash function for unsigned ints... + template<> struct hash { + inline size_t operator()(unsigned int Val) const { + return Val; + } + }; + + template class hash_compare > { + std::less comp; + public: + enum { bucket_size = 4 }; + enum { min_buckets = 8 }; + hash_compare() {} + hash_compare(std::less pred) : comp(pred) {} + size_t operator()(const Key& key) const { return hash()(key); } + bool operator()(const Key& k1, const Key& k2) const { return comp(k1, k2); } + }; +} + +#endif + +using HASH_NAMESPACE::hash_map; +using HASH_NAMESPACE::hash_multimap; +using HASH_NAMESPACE::hash; + +#include "llvm/ADT/HashExtras.h" + +#endif diff --git a/include/llvm/ADT/hash_map.in b/include/llvm/ADT/hash_map.in deleted file mode 100644 index b5c785f1a41..00000000000 --- a/include/llvm/ADT/hash_map.in +++ /dev/null @@ -1,150 +0,0 @@ -//===-- llvm/ADT/hash_map - "Portable" wrapper around hash_map --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides a wrapper around the mysterious header file -// that seems to move around between GCC releases into and out of namespaces at -// will. #including this header will cause hash_map to be available in the -// global namespace. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ADT_HASH_MAP -#define LLVM_ADT_HASH_MAP - -// Compiler Support Matrix -// -// Version Namespace Header File -// 2.95.x :: hash_map -// 3.0.4 std ext/hash_map -// 3.1 __gnu_cxx ext/hash_map -// HP aCC6 std stdex/rw/hashm*ap.h -// MS VC++ stdext hash_map - -#undef HAVE_GNU_EXT_HASH_MAP -#undef HAVE_STD_EXT_HASH_MAP -#undef HAVE_GLOBAL_HASH_MAP -#undef HAVE_RW_STDEX_HASH_MAP_H - -#if HAVE_GNU_EXT_HASH_MAP -// This is for GCC-3.1+ which puts hash in ext/hash_map -# include -# ifndef HASH_NAMESPACE -# define HASH_NAMESPACE __gnu_cxx -# endif - -// GCC 3.0.x puts hash_map in and in the std namespace. -#elif HAVE_STD_EXT_HASH_MAP -# include -# ifndef HASH_NAMESPACE -# define HASH_NAMESPACE std -# endif - -// Older compilers such as GCC before version 3.0 do not keep -// extensions in the `ext' directory, and ignore the `std' namespace. -#elif HAVE_GLOBAL_HASH_MAP -# include -# ifndef HASH_NAMESPACE -# define HASH_NAMESPACE std -# endif - -// HP aCC doesn't include an SGI-like hash_map. For this platform (or -// any others using Rogue Wave Software's Tools.h++ library), we wrap -// around them in std:: -#elif HAVE_RW_STDEX_HASH_MAP_H -# include -# include -# ifndef HASH_NAMESPACE -# define HASH_NAMESPACE std -# endif - -// Support Microsoft VC++. -#elif defined(_MSC_VER) -# include -# ifndef HASH_NAMESPACE -# define HASH_NAMESPACE stdext - using std::_Distance; -# endif - -// Give a warning if we couldn't find it, instead of (or in addition to) -// randomly doing something dumb. -#else -# warning "Autoconfiguration failed to find the hash_map header file." -#endif - -// we wrap Rogue Wave Tools.h++ rw_hashmap into something SGI-looking, here: -#ifdef HAVE_RW_STDEX_HASH_MAP_H -namespace HASH_NAMESPACE { - -template struct hash { - unsigned int operator()(const unsigned int& x) const { - return x; - } -}; - -template , - class _EqualKey = equal_to, - class _A = allocator > -class hash_map : public rw_hashmap { -}; - -template , - class _EqualKey = equal_to, - class _A = allocator > -class hash_multimap : public rw_hashmultimap { -}; - -} // end HASH_NAMESPACE; -#endif - -// Include vector because ext/hash_map includes stl_vector.h and leaves -// out specializations like stl_bvector.h, causing link conflicts. -#include - -#ifdef _MSC_VER - -// GCC and VC++ have differing ways of implementing hash_maps. As it's not -// standardized, that's to be expected. This adapter class allows VC++ -// hash_map to use GCC's hash classes. -namespace stdext { - template struct hash; - - // Provide a hash function for unsigned ints... - template<> struct hash { - inline size_t operator()(unsigned int Val) const { - return Val; - } - }; - - template class hash_compare > { - std::less comp; - public: - enum { bucket_size = 4 }; - enum { min_buckets = 8 }; - hash_compare() {} - hash_compare(std::less pred) : comp(pred) {} - size_t operator()(const Key& key) const { return hash()(key); } - bool operator()(const Key& k1, const Key& k2) const { return comp(k1, k2); } - }; -} - -#endif - -using HASH_NAMESPACE::hash_map; -using HASH_NAMESPACE::hash_multimap; -using HASH_NAMESPACE::hash; - -#include "llvm/ADT/HashExtras.h" - -#endif diff --git a/include/llvm/ADT/hash_set.h.in b/include/llvm/ADT/hash_set.h.in new file mode 100644 index 00000000000..85493297490 --- /dev/null +++ b/include/llvm/ADT/hash_set.h.in @@ -0,0 +1,111 @@ +//==-- llvm/ADT/hash_set.h - "Portable" wrapper around hash_set --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// vim:ft=cpp +// +// This file provides a wrapper around the mysterious header file +// that seems to move around between GCC releases into and out of namespaces at +// will. #including this header will cause hash_set to be available in the +// global namespace. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_HASH_SET +#define LLVM_ADT_HASH_SET + +// Compiler Support Matrix +// +// Version Namespace Header File +// 2.95.x :: hash_set +// 3.0.4 std ext/hash_set +// 3.1 __gnu_cxx ext/hash_set +// HP aCC6 std stdex/rw/hashset.h +// MS VC++ stdext hash_set + +#undef HAVE_GNU_EXT_HASH_SET +#undef HAVE_STD_EXT_HASH_SET +#undef HAVE_GLOBAL_HASH_SET +#undef HAVE_RW_STDEX_HASH_SET_H + +// GCC versions 3.1 and later put hash_set in and in +// the __gnu_cxx namespace. +#if HAVE_GNU_EXT_HASH_SET +# include +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE __gnu_cxx +# endif + +// GCC 3.0.x puts hash_set in and in the std namespace. +#elif HAVE_STD_EXT_HASH_SET +# include +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE std +# endif + +// Older compilers such as GCC before version 3.0 do not keep +// extensions in the `ext' directory, and ignore the `std' namespace. +#elif HAVE_GLOBAL_HASH_SET +# include +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE std +# endif + +// HP aCC doesn't include an SGI-like hash_set. For this platform (or +// any others using Rogue Wave Software's Tools.h++ library), we wrap +// around them in std:: +#elif HAVE_RW_STDEX_HASH_SET_H +# include +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE std +# endif + +// Support Microsoft VC++. +#elif defined(_MSC_VER) +# include +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE stdext +# endif + +// Give a warning if we couldn't find it, instead of (or in addition to) +// randomly doing something dumb. +#else +# warning "Autoconfiguration failed to find the hash_set header file." +#endif + +// we wrap Rogue Wave Tools.h++ rw_hashset into something SGI-looking, here: +#ifdef HAVE_RW_STDEX_HASH_SET_H +namespace HASH_NAMESPACE { + +/* +template struct hash { + unsigned int operator()(const unsigned int& x) const { + return x; + } +}; +*/ + +template , + class _EqualKey = equal_to, + class _A = allocator > +class hash_set : + public rw_hashset { +}; + +} // end HASH_NAMESPACE; +#endif + +using HASH_NAMESPACE::hash_set; + +// Include vector because ext/hash_set includes stl_vector.h and leaves +// out specializations like stl_bvector.h, causing link conflicts. +#include + +#include "llvm/ADT/HashExtras.h" + +#endif diff --git a/include/llvm/ADT/hash_set.in b/include/llvm/ADT/hash_set.in deleted file mode 100644 index a0945ce4ac7..00000000000 --- a/include/llvm/ADT/hash_set.in +++ /dev/null @@ -1,111 +0,0 @@ -//===-- llvm/ADT/hash_set - "Portable" wrapper around hash_set --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// vim:ft=cpp -// -// This file provides a wrapper around the mysterious header file -// that seems to move around between GCC releases into and out of namespaces at -// will. #including this header will cause hash_set to be available in the -// global namespace. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ADT_HASH_SET -#define LLVM_ADT_HASH_SET - -// Compiler Support Matrix -// -// Version Namespace Header File -// 2.95.x :: hash_set -// 3.0.4 std ext/hash_set -// 3.1 __gnu_cxx ext/hash_set -// HP aCC6 std stdex/rw/hashset.h -// MS VC++ stdext hash_set - -#undef HAVE_GNU_EXT_HASH_SET -#undef HAVE_STD_EXT_HASH_SET -#undef HAVE_GLOBAL_HASH_SET -#undef HAVE_RW_STDEX_HASH_SET_H - -// GCC versions 3.1 and later put hash_set in and in -// the __gnu_cxx namespace. -#if HAVE_GNU_EXT_HASH_SET -# include -# ifndef HASH_NAMESPACE -# define HASH_NAMESPACE __gnu_cxx -# endif - -// GCC 3.0.x puts hash_set in and in the std namespace. -#elif HAVE_STD_EXT_HASH_SET -# include -# ifndef HASH_NAMESPACE -# define HASH_NAMESPACE std -# endif - -// Older compilers such as GCC before version 3.0 do not keep -// extensions in the `ext' directory, and ignore the `std' namespace. -#elif HAVE_GLOBAL_HASH_SET -# include -# ifndef HASH_NAMESPACE -# define HASH_NAMESPACE std -# endif - -// HP aCC doesn't include an SGI-like hash_set. For this platform (or -// any others using Rogue Wave Software's Tools.h++ library), we wrap -// around them in std:: -#elif HAVE_RW_STDEX_HASH_SET_H -# include -# ifndef HASH_NAMESPACE -# define HASH_NAMESPACE std -# endif - -// Support Microsoft VC++. -#elif defined(_MSC_VER) -# include -# ifndef HASH_NAMESPACE -# define HASH_NAMESPACE stdext -# endif - -// Give a warning if we couldn't find it, instead of (or in addition to) -// randomly doing something dumb. -#else -# warning "Autoconfiguration failed to find the hash_set header file." -#endif - -// we wrap Rogue Wave Tools.h++ rw_hashset into something SGI-looking, here: -#ifdef HAVE_RW_STDEX_HASH_SET_H -namespace HASH_NAMESPACE { - -/* -template struct hash { - unsigned int operator()(const unsigned int& x) const { - return x; - } -}; -*/ - -template , - class _EqualKey = equal_to, - class _A = allocator > -class hash_set : - public rw_hashset { -}; - -} // end HASH_NAMESPACE; -#endif - -using HASH_NAMESPACE::hash_set; - -// Include vector because ext/hash_set includes stl_vector.h and leaves -// out specializations like stl_bvector.h, causing link conflicts. -#include - -#include "llvm/ADT/HashExtras.h" - -#endif diff --git a/include/llvm/ADT/ilist b/include/llvm/ADT/ilist deleted file mode 100644 index d465cbfc715..00000000000 --- a/include/llvm/ADT/ilist +++ /dev/null @@ -1,634 +0,0 @@ -//===-- llvm/ADT/ilist - Intrusive Linked List Template ---------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines classes to implement an intrusive doubly linked list class -// (i.e. each node of the list must contain a next and previous field for the -// list. -// -// The ilist_traits trait class is used to gain access to the next and previous -// fields of the node type that the list is instantiated with. If it is not -// specialized, the list defaults to using the getPrev(), getNext() method calls -// to get the next and previous pointers. -// -// The ilist class itself, should be a plug in replacement for list, assuming -// that the nodes contain next/prev pointers. This list replacement does not -// provide a constant time size() method, so be careful to use empty() when you -// really want to know if it's empty. -// -// The ilist class is implemented by allocating a 'tail' node when the list is -// created (using ilist_traits<>::createSentinel()). This tail node is -// absolutely required because the user must be able to compute end()-1. Because -// of this, users of the direct next/prev links will see an extra link on the -// end of the list, which should be ignored. -// -// Requirements for a user of this list: -// -// 1. The user must provide {g|s}et{Next|Prev} methods, or specialize -// ilist_traits to provide an alternate way of getting and setting next and -// prev links. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ADT_ILIST -#define LLVM_ADT_ILIST - -#include "llvm/ADT/iterator" -#include -#include - -namespace llvm { - -template class iplist; -template class ilist_iterator; - -// Template traits for intrusive list. By specializing this template class, you -// can change what next/prev fields are used to store the links... -template -struct ilist_traits { - static NodeTy *getPrev(NodeTy *N) { return N->getPrev(); } - static NodeTy *getNext(NodeTy *N) { return N->getNext(); } - static const NodeTy *getPrev(const NodeTy *N) { return N->getPrev(); } - static const NodeTy *getNext(const NodeTy *N) { return N->getNext(); } - - static void setPrev(NodeTy *N, NodeTy *Prev) { N->setPrev(Prev); } - static void setNext(NodeTy *N, NodeTy *Next) { N->setNext(Next); } - - static NodeTy *createNode(const NodeTy &V) { return new NodeTy(V); } - - static NodeTy *createSentinel() { return new NodeTy(); } - static void destroySentinel(NodeTy *N) { delete N; } - - void addNodeToList(NodeTy *NTy) {} - void removeNodeFromList(NodeTy *NTy) {} - void transferNodesFromList(iplist &L2, - ilist_iterator first, - ilist_iterator last) {} -}; - -// Const traits are the same as nonconst traits... -template -struct ilist_traits : public ilist_traits {}; - - -//===----------------------------------------------------------------------===// -// ilist_iterator - Iterator for intrusive list. -// -template -class ilist_iterator - : public bidirectional_iterator { - typedef ilist_traits Traits; - typedef bidirectional_iterator super; - -public: - typedef size_t size_type; - typedef typename super::pointer pointer; - typedef typename super::reference reference; -private: - pointer NodePtr; -public: - - ilist_iterator(pointer NP) : NodePtr(NP) {} - ilist_iterator(reference NR) : NodePtr(&NR) {} - ilist_iterator() : NodePtr(0) {} - - // This is templated so that we can allow constructing a const iterator from - // a nonconst iterator... - template - ilist_iterator(const ilist_iterator &RHS) - : NodePtr(RHS.getNodePtrUnchecked()) {} - - // 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.getNodePtrUnchecked(); - return *this; - } - - // Accessors... - operator pointer() const { - assert(Traits::getNext(NodePtr) != 0 && "Dereferencing end()!"); - return NodePtr; - } - - reference operator*() const { - assert(Traits::getNext(NodePtr) != 0 && "Dereferencing end()!"); - return *NodePtr; - } - pointer operator->() { return &operator*(); } - const pointer operator->() const { return &operator*(); } - - // Comparison operators - bool operator==(const ilist_iterator &RHS) const { - return NodePtr == RHS.NodePtr; - } - bool operator!=(const ilist_iterator &RHS) const { - return NodePtr != RHS.NodePtr; - } - - // Increment and decrement operators... - ilist_iterator &operator--() { // predecrement - Back up - NodePtr = Traits::getPrev(NodePtr); - assert(Traits::getNext(NodePtr) && "--'d off the beginning of an ilist!"); - return *this; - } - ilist_iterator &operator++() { // preincrement - Advance - NodePtr = Traits::getNext(NodePtr); - assert(NodePtr && "++'d off the end of an ilist!"); - return *this; - } - ilist_iterator operator--(int) { // postdecrement operators... - ilist_iterator tmp = *this; - --*this; - return tmp; - } - ilist_iterator operator++(int) { // postincrement operators... - ilist_iterator tmp = *this; - ++*this; - return tmp; - } - - // Internal interface, do not use... - pointer getNodePtrUnchecked() const { return NodePtr; } -}; - -// do not implement. this is to catch errors when people try to use -// them as random access iterators -template -void operator-(int, ilist_iterator); -template -void operator-(ilist_iterator,int); - -template -void operator+(int, ilist_iterator); -template -void operator+(ilist_iterator,int); - -// operator!=/operator== - Allow mixed comparisons without dereferencing -// the iterator, which could very likely be pointing to end(). -template -bool operator!=(const T* LHS, const ilist_iterator &RHS) { - return LHS != RHS.getNodePtrUnchecked(); -} -template -bool operator==(const T* LHS, const ilist_iterator &RHS) { - return LHS == RHS.getNodePtrUnchecked(); -} -template -bool operator!=(T* LHS, const ilist_iterator &RHS) { - return LHS != RHS.getNodePtrUnchecked(); -} -template -bool operator==(T* LHS, const ilist_iterator &RHS) { - return LHS == RHS.getNodePtrUnchecked(); -} - - -// 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(const ilist_iterator &Node) { - return &*Node; - } -}; -template struct simplify_type > { - typedef NodeTy* SimpleType; - - static SimpleType getSimplifiedValue(const ilist_iterator &Node) { - return &*Node; - } -}; - - -//===----------------------------------------------------------------------===// -// -/// iplist - The subset of list functionality that can safely be used on nodes -/// of polymorphic types, i.e. a heterogenous list with a common base class that -/// holds the next/prev pointers. The only state of the list itself is a single -/// pointer to the head of the list. -/// -/// This list can be in one of three interesting states: -/// 1. The list may be completely unconstructed. In this case, the head -/// pointer is null. When in this form, any query for an iterator (e.g. -/// begin() or end()) causes the list to transparently change to state #2. -/// 2. The list may be empty, but contain a sentinal for the end iterator. This -/// sentinal is created by the Traits::createSentinel method and is a link -/// in the list. When the list is empty, the pointer in the iplist points -/// to the sentinal. Once the sentinal is constructed, it -/// is not destroyed until the list is. -/// 3. The list may contain actual objects in it, which are stored as a doubly -/// linked list of nodes. One invariant of the list is that the predecessor -/// of the first node in the list always points to the last node in the list, -/// and the successor pointer for the sentinal (which always stays at the -/// end of the list) is always null. -/// -template > -class iplist : public Traits { - mutable NodeTy *Head; - - // Use the prev node pointer of 'head' as the tail pointer. This is really a - // circularly linked list where we snip the 'next' link from the sentinel node - // back to the first node in the list (to preserve assertions about going off - // the end of the list). - NodeTy *getTail() { return getPrev(Head); } - const NodeTy *getTail() const { return getPrev(Head); } - void setTail(NodeTy *N) const { setPrev(Head, N); } - - /// CreateLazySentinal - This method verifies whether the sentinal for the - /// list has been created and lazily makes it if not. - void CreateLazySentinal() const { - if (Head != 0) return; - Head = Traits::createSentinel(); - setNext(Head, 0); - setTail(Head); - } - - static bool op_less(NodeTy &L, NodeTy &R) { return L < R; } - static bool op_equal(NodeTy &L, NodeTy &R) { return L == R; } -public: - typedef NodeTy *pointer; - typedef const NodeTy *const_pointer; - typedef NodeTy &reference; - typedef const NodeTy &const_reference; - typedef NodeTy value_type; - typedef ilist_iterator iterator; - typedef ilist_iterator const_iterator; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef std::reverse_iterator const_reverse_iterator; - typedef std::reverse_iterator reverse_iterator; - - iplist() : Head(0) {} - ~iplist() { - if (!Head) return; - clear(); - Traits::destroySentinel(getTail()); - } - - // Iterator creation methods. - iterator begin() { - CreateLazySentinal(); - return iterator(Head); - } - const_iterator begin() const { - CreateLazySentinal(); - return const_iterator(Head); - } - iterator end() { - CreateLazySentinal(); - return iterator(getTail()); - } - const_iterator end() const { - CreateLazySentinal(); - return const_iterator(getTail()); - } - - // reverse iterator creation methods. - reverse_iterator rbegin() { return reverse_iterator(end()); } - const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { return const_reverse_iterator(begin());} - - - // Miscellaneous inspection routines. - size_type max_size() const { return size_type(-1); } - bool empty() const { return Head == 0 || Head == getTail(); } - - // Front and back accessor functions... - reference front() { - assert(!empty() && "Called front() on empty list!"); - return *Head; - } - const_reference front() const { - assert(!empty() && "Called front() on empty list!"); - return *Head; - } - reference back() { - assert(!empty() && "Called back() on empty list!"); - return *getPrev(getTail()); - } - const_reference back() const { - assert(!empty() && "Called back() on empty list!"); - return *getPrev(getTail()); - } - - void swap(iplist &RHS) { - abort(); // Swap does not use list traits callback correctly yet! - std::swap(Head, RHS.Head); - } - - iterator insert(iterator where, NodeTy *New) { - NodeTy *CurNode = where.getNodePtrUnchecked(), *PrevNode = getPrev(CurNode); - setNext(New, CurNode); - setPrev(New, PrevNode); - - if (CurNode != Head) // Is PrevNode off the beginning of the list? - setNext(PrevNode, New); - else - Head = New; - setPrev(CurNode, New); - - addNodeToList(New); // Notify traits that we added a node... - return New; - } - - NodeTy *remove(iterator &IT) { - assert(IT != end() && "Cannot remove end of list!"); - NodeTy *Node = &*IT; - NodeTy *NextNode = getNext(Node); - NodeTy *PrevNode = getPrev(Node); - - if (Node != Head) // Is PrevNode off the beginning of the list? - setNext(PrevNode, NextNode); - else - Head = NextNode; - setPrev(NextNode, PrevNode); - IT = NextNode; - removeNodeFromList(Node); // Notify traits that we removed a node... - - // Set the next/prev pointers of the current node to null. This isn't - // strictly required, but this catches errors where a node is removed from - // an ilist (and potentially deleted) with iterators still pointing at it. - // When those iterators are incremented or decremented, they will assert on - // the null next/prev pointer instead of "usually working". - setNext(Node, 0); - setPrev(Node, 0); - return Node; - } - - NodeTy *remove(const iterator &IT) { - iterator MutIt = IT; - return remove(MutIt); - } - - // erase - remove a node from the controlled sequence... and delete it. - iterator erase(iterator where) { - delete remove(where); - return where; - } - - -private: - // transfer - The heart of the splice function. Move linked list nodes from - // [first, last) into position. - // - void transfer(iterator position, iplist &L2, iterator first, iterator last) { - assert(first != last && "Should be checked by callers"); - - if (position != last) { - // Note: we have to be careful about the case when we move the first node - // in the list. This node is the list sentinel node and we can't move it. - NodeTy *ThisSentinel = getTail(); - setTail(0); - NodeTy *L2Sentinel = L2.getTail(); - L2.setTail(0); - - // Remove [first, last) from its old position. - NodeTy *First = &*first, *Prev = getPrev(First); - NodeTy *Next = last.getNodePtrUnchecked(), *Last = getPrev(Next); - if (Prev) - setNext(Prev, Next); - else - L2.Head = Next; - setPrev(Next, Prev); - - // Splice [first, last) into its new position. - NodeTy *PosNext = position.getNodePtrUnchecked(); - NodeTy *PosPrev = getPrev(PosNext); - - // Fix head of list... - if (PosPrev) - setNext(PosPrev, First); - else - Head = First; - setPrev(First, PosPrev); - - // Fix end of list... - setNext(Last, PosNext); - setPrev(PosNext, Last); - - transferNodesFromList(L2, First, PosNext); - - // Now that everything is set, restore the pointers to the list sentinals. - L2.setTail(L2Sentinel); - setTail(ThisSentinel); - } - } - -public: - - //===----------------------------------------------------------------------=== - // Functionality derived from other functions defined above... - // - - size_type size() const { - if (Head == 0) return 0; // Don't require construction of sentinal if empty. -#if __GNUC__ == 2 - // GCC 2.95 has a broken std::distance - size_type Result = 0; - std::distance(begin(), end(), Result); - return Result; -#else - return std::distance(begin(), end()); -#endif - } - - iterator erase(iterator first, iterator last) { - while (first != last) - first = erase(first); - return last; - } - - void clear() { if (Head) erase(begin(), end()); } - - // Front and back inserters... - void push_front(NodeTy *val) { insert(begin(), val); } - void push_back(NodeTy *val) { insert(end(), val); } - void pop_front() { - assert(!empty() && "pop_front() on empty list!"); - erase(begin()); - } - void pop_back() { - assert(!empty() && "pop_back() on empty list!"); - iterator t = end(); erase(--t); - } - - // Special forms of insert... - template void insert(iterator where, InIt first, InIt last) { - for (; first != last; ++first) insert(where, *first); - } - - // Splice members - defined in terms of transfer... - void splice(iterator where, iplist &L2) { - if (!L2.empty()) - transfer(where, L2, L2.begin(), L2.end()); - } - void splice(iterator where, iplist &L2, iterator first) { - iterator last = first; ++last; - if (where == first || where == last) return; // No change - transfer(where, L2, first, last); - } - void splice(iterator where, iplist &L2, iterator first, iterator last) { - if (first != last) transfer(where, L2, first, last); - } - - - - //===----------------------------------------------------------------------=== - // High-Level Functionality that shouldn't really be here, but is part of list - // - - // These two functions are actually called remove/remove_if in list<>, but - // they actually do the job of erase, rename them accordingly. - // - void erase(const NodeTy &val) { - for (iterator I = begin(), E = end(); I != E; ) { - iterator next = I; ++next; - if (*I == val) erase(I); - I = next; - } - } - template void erase_if(Pr1 pred) { - for (iterator I = begin(), E = end(); I != E; ) { - iterator next = I; ++next; - if (pred(*I)) erase(I); - I = next; - } - } - - template void unique(Pr2 pred) { - if (empty()) return; - for (iterator I = begin(), E = end(), Next = begin(); ++Next != E;) { - if (pred(*I)) - erase(Next); - else - I = Next; - Next = I; - } - } - void unique() { unique(op_equal); } - - template void merge(iplist &right, Pr3 pred) { - iterator first1 = begin(), last1 = end(); - iterator first2 = right.begin(), last2 = right.end(); - while (first1 != last1 && first2 != last2) - if (pred(*first2, *first1)) { - iterator next = first2; - transfer(first1, right, first2, ++next); - first2 = next; - } else { - ++first1; - } - if (first2 != last2) transfer(last1, right, first2, last2); - } - void merge(iplist &right) { return merge(right, op_less); } - - template void sort(Pr3 pred); - void sort() { sort(op_less); } - void reverse(); -}; - - -template -struct ilist : public iplist { - typedef typename iplist::size_type size_type; - typedef typename iplist::iterator iterator; - - ilist() {} - ilist(const ilist &right) { - insert(this->begin(), right.begin(), right.end()); - } - explicit ilist(size_type count) { - insert(this->begin(), count, NodeTy()); - } - ilist(size_type count, const NodeTy &val) { - insert(this->begin(), count, val); - } - template ilist(InIt first, InIt last) { - insert(this->begin(), first, last); - } - - - // Forwarding functions: A workaround for GCC 2.95 which does not correctly - // support 'using' declarations to bring a hidden member into scope. - // - iterator insert(iterator a, NodeTy *b){ return iplist::insert(a, b); } - void push_front(NodeTy *a) { iplist::push_front(a); } - void push_back(NodeTy *a) { iplist::push_back(a); } - - - // Main implementation here - Insert for a node passed by value... - iterator insert(iterator where, const NodeTy &val) { - return insert(where, createNode(val)); - } - - - // Front and back inserters... - void push_front(const NodeTy &val) { insert(this->begin(), val); } - void push_back(const NodeTy &val) { insert(this->end(), val); } - - // Special forms of insert... - template void insert(iterator where, InIt first, InIt last) { - for (; first != last; ++first) insert(where, *first); - } - void insert(iterator where, size_type count, const NodeTy &val) { - for (; count != 0; --count) insert(where, val); - } - - // Assign special forms... - void assign(size_type count, const NodeTy &val) { - iterator I = this->begin(); - for (; I != this->end() && count != 0; ++I, --count) - *I = val; - if (count != 0) - insert(this->end(), val, val); - else - erase(I, this->end()); - } - template void assign(InIt first1, InIt last1) { - iterator first2 = this->begin(), last2 = this->end(); - for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) - *first1 = *first2; - if (first2 == last2) - erase(first1, last1); - else - insert(last1, first2, last2); - } - - - // Resize members... - void resize(size_type newsize, NodeTy val) { - iterator i = this->begin(); - size_type len = 0; - for ( ; i != this->end() && len < newsize; ++i, ++len) /* empty*/ ; - - if (len == newsize) - erase(i, this->end()); - else // i == end() - insert(this->end(), newsize - len, val); - } - void resize(size_type newsize) { resize(newsize, NodeTy()); } -}; - -} // End llvm namespace - -namespace std { - // Ensure that swap uses the fast list swap... - template - void swap(llvm::iplist &Left, llvm::iplist &Right) { - Left.swap(Right); - } -} // End 'std' extensions... - -#endif diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h new file mode 100644 index 00000000000..d4bcb5b9040 --- /dev/null +++ b/include/llvm/ADT/ilist.h @@ -0,0 +1,634 @@ +//==-- llvm/ADT/ilist.h - Intrusive Linked List Template ---------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines classes to implement an intrusive doubly linked list class +// (i.e. each node of the list must contain a next and previous field for the +// list. +// +// The ilist_traits trait class is used to gain access to the next and previous +// fields of the node type that the list is instantiated with. If it is not +// specialized, the list defaults to using the getPrev(), getNext() method calls +// to get the next and previous pointers. +// +// The ilist class itself, should be a plug in replacement for list, assuming +// that the nodes contain next/prev pointers. This list replacement does not +// provide a constant time size() method, so be careful to use empty() when you +// really want to know if it's empty. +// +// The ilist class is implemented by allocating a 'tail' node when the list is +// created (using ilist_traits<>::createSentinel()). This tail node is +// absolutely required because the user must be able to compute end()-1. Because +// of this, users of the direct next/prev links will see an extra link on the +// end of the list, which should be ignored. +// +// Requirements for a user of this list: +// +// 1. The user must provide {g|s}et{Next|Prev} methods, or specialize +// ilist_traits to provide an alternate way of getting and setting next and +// prev links. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST +#define LLVM_ADT_ILIST + +#include "llvm/ADT/iterator.h" +#include +#include + +namespace llvm { + +template class iplist; +template class ilist_iterator; + +// Template traits for intrusive list. By specializing this template class, you +// can change what next/prev fields are used to store the links... +template +struct ilist_traits { + static NodeTy *getPrev(NodeTy *N) { return N->getPrev(); } + static NodeTy *getNext(NodeTy *N) { return N->getNext(); } + static const NodeTy *getPrev(const NodeTy *N) { return N->getPrev(); } + static const NodeTy *getNext(const NodeTy *N) { return N->getNext(); } + + static void setPrev(NodeTy *N, NodeTy *Prev) { N->setPrev(Prev); } + static void setNext(NodeTy *N, NodeTy *Next) { N->setNext(Next); } + + static NodeTy *createNode(const NodeTy &V) { return new NodeTy(V); } + + static NodeTy *createSentinel() { return new NodeTy(); } + static void destroySentinel(NodeTy *N) { delete N; } + + void addNodeToList(NodeTy *NTy) {} + void removeNodeFromList(NodeTy *NTy) {} + void transferNodesFromList(iplist &L2, + ilist_iterator first, + ilist_iterator last) {} +}; + +// Const traits are the same as nonconst traits... +template +struct ilist_traits : public ilist_traits {}; + + +//===----------------------------------------------------------------------===// +// ilist_iterator - Iterator for intrusive list. +// +template +class ilist_iterator + : public bidirectional_iterator { + typedef ilist_traits Traits; + typedef bidirectional_iterator super; + +public: + typedef size_t size_type; + typedef typename super::pointer pointer; + typedef typename super::reference reference; +private: + pointer NodePtr; +public: + + ilist_iterator(pointer NP) : NodePtr(NP) {} + ilist_iterator(reference NR) : NodePtr(&NR) {} + ilist_iterator() : NodePtr(0) {} + + // This is templated so that we can allow constructing a const iterator from + // a nonconst iterator... + template + ilist_iterator(const ilist_iterator &RHS) + : NodePtr(RHS.getNodePtrUnchecked()) {} + + // 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.getNodePtrUnchecked(); + return *this; + } + + // Accessors... + operator pointer() const { + assert(Traits::getNext(NodePtr) != 0 && "Dereferencing end()!"); + return NodePtr; + } + + reference operator*() const { + assert(Traits::getNext(NodePtr) != 0 && "Dereferencing end()!"); + return *NodePtr; + } + pointer operator->() { return &operator*(); } + const pointer operator->() const { return &operator*(); } + + // Comparison operators + bool operator==(const ilist_iterator &RHS) const { + return NodePtr == RHS.NodePtr; + } + bool operator!=(const ilist_iterator &RHS) const { + return NodePtr != RHS.NodePtr; + } + + // Increment and decrement operators... + ilist_iterator &operator--() { // predecrement - Back up + NodePtr = Traits::getPrev(NodePtr); + assert(Traits::getNext(NodePtr) && "--'d off the beginning of an ilist!"); + return *this; + } + ilist_iterator &operator++() { // preincrement - Advance + NodePtr = Traits::getNext(NodePtr); + assert(NodePtr && "++'d off the end of an ilist!"); + return *this; + } + ilist_iterator operator--(int) { // postdecrement operators... + ilist_iterator tmp = *this; + --*this; + return tmp; + } + ilist_iterator operator++(int) { // postincrement operators... + ilist_iterator tmp = *this; + ++*this; + return tmp; + } + + // Internal interface, do not use... + pointer getNodePtrUnchecked() const { return NodePtr; } +}; + +// do not implement. this is to catch errors when people try to use +// them as random access iterators +template +void operator-(int, ilist_iterator); +template +void operator-(ilist_iterator,int); + +template +void operator+(int, ilist_iterator); +template +void operator+(ilist_iterator,int); + +// operator!=/operator== - Allow mixed comparisons without dereferencing +// the iterator, which could very likely be pointing to end(). +template +bool operator!=(const T* LHS, const ilist_iterator &RHS) { + return LHS != RHS.getNodePtrUnchecked(); +} +template +bool operator==(const T* LHS, const ilist_iterator &RHS) { + return LHS == RHS.getNodePtrUnchecked(); +} +template +bool operator!=(T* LHS, const ilist_iterator &RHS) { + return LHS != RHS.getNodePtrUnchecked(); +} +template +bool operator==(T* LHS, const ilist_iterator &RHS) { + return LHS == RHS.getNodePtrUnchecked(); +} + + +// 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(const ilist_iterator &Node) { + return &*Node; + } +}; +template struct simplify_type > { + typedef NodeTy* SimpleType; + + static SimpleType getSimplifiedValue(const ilist_iterator &Node) { + return &*Node; + } +}; + + +//===----------------------------------------------------------------------===// +// +/// iplist - The subset of list functionality that can safely be used on nodes +/// of polymorphic types, i.e. a heterogenous list with a common base class that +/// holds the next/prev pointers. The only state of the list itself is a single +/// pointer to the head of the list. +/// +/// This list can be in one of three interesting states: +/// 1. The list may be completely unconstructed. In this case, the head +/// pointer is null. When in this form, any query for an iterator (e.g. +/// begin() or end()) causes the list to transparently change to state #2. +/// 2. The list may be empty, but contain a sentinal for the end iterator. This +/// sentinal is created by the Traits::createSentinel method and is a link +/// in the list. When the list is empty, the pointer in the iplist points +/// to the sentinal. Once the sentinal is constructed, it +/// is not destroyed until the list is. +/// 3. The list may contain actual objects in it, which are stored as a doubly +/// linked list of nodes. One invariant of the list is that the predecessor +/// of the first node in the list always points to the last node in the list, +/// and the successor pointer for the sentinal (which always stays at the +/// end of the list) is always null. +/// +template > +class iplist : public Traits { + mutable NodeTy *Head; + + // Use the prev node pointer of 'head' as the tail pointer. This is really a + // circularly linked list where we snip the 'next' link from the sentinel node + // back to the first node in the list (to preserve assertions about going off + // the end of the list). + NodeTy *getTail() { return getPrev(Head); } + const NodeTy *getTail() const { return getPrev(Head); } + void setTail(NodeTy *N) const { setPrev(Head, N); } + + /// CreateLazySentinal - This method verifies whether the sentinal for the + /// list has been created and lazily makes it if not. + void CreateLazySentinal() const { + if (Head != 0) return; + Head = Traits::createSentinel(); + setNext(Head, 0); + setTail(Head); + } + + static bool op_less(NodeTy &L, NodeTy &R) { return L < R; } + static bool op_equal(NodeTy &L, NodeTy &R) { return L == R; } +public: + typedef NodeTy *pointer; + typedef const NodeTy *const_pointer; + typedef NodeTy &reference; + typedef const NodeTy &const_reference; + typedef NodeTy value_type; + typedef ilist_iterator iterator; + typedef ilist_iterator const_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + iplist() : Head(0) {} + ~iplist() { + if (!Head) return; + clear(); + Traits::destroySentinel(getTail()); + } + + // Iterator creation methods. + iterator begin() { + CreateLazySentinal(); + return iterator(Head); + } + const_iterator begin() const { + CreateLazySentinal(); + return const_iterator(Head); + } + iterator end() { + CreateLazySentinal(); + return iterator(getTail()); + } + const_iterator end() const { + CreateLazySentinal(); + return const_iterator(getTail()); + } + + // reverse iterator creation methods. + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + + + // Miscellaneous inspection routines. + size_type max_size() const { return size_type(-1); } + bool empty() const { return Head == 0 || Head == getTail(); } + + // Front and back accessor functions... + reference front() { + assert(!empty() && "Called front() on empty list!"); + return *Head; + } + const_reference front() const { + assert(!empty() && "Called front() on empty list!"); + return *Head; + } + reference back() { + assert(!empty() && "Called back() on empty list!"); + return *getPrev(getTail()); + } + const_reference back() const { + assert(!empty() && "Called back() on empty list!"); + return *getPrev(getTail()); + } + + void swap(iplist &RHS) { + abort(); // Swap does not use list traits callback correctly yet! + std::swap(Head, RHS.Head); + } + + iterator insert(iterator where, NodeTy *New) { + NodeTy *CurNode = where.getNodePtrUnchecked(), *PrevNode = getPrev(CurNode); + setNext(New, CurNode); + setPrev(New, PrevNode); + + if (CurNode != Head) // Is PrevNode off the beginning of the list? + setNext(PrevNode, New); + else + Head = New; + setPrev(CurNode, New); + + addNodeToList(New); // Notify traits that we added a node... + return New; + } + + NodeTy *remove(iterator &IT) { + assert(IT != end() && "Cannot remove end of list!"); + NodeTy *Node = &*IT; + NodeTy *NextNode = getNext(Node); + NodeTy *PrevNode = getPrev(Node); + + if (Node != Head) // Is PrevNode off the beginning of the list? + setNext(PrevNode, NextNode); + else + Head = NextNode; + setPrev(NextNode, PrevNode); + IT = NextNode; + removeNodeFromList(Node); // Notify traits that we removed a node... + + // Set the next/prev pointers of the current node to null. This isn't + // strictly required, but this catches errors where a node is removed from + // an ilist (and potentially deleted) with iterators still pointing at it. + // When those iterators are incremented or decremented, they will assert on + // the null next/prev pointer instead of "usually working". + setNext(Node, 0); + setPrev(Node, 0); + return Node; + } + + NodeTy *remove(const iterator &IT) { + iterator MutIt = IT; + return remove(MutIt); + } + + // erase - remove a node from the controlled sequence... and delete it. + iterator erase(iterator where) { + delete remove(where); + return where; + } + + +private: + // transfer - The heart of the splice function. Move linked list nodes from + // [first, last) into position. + // + void transfer(iterator position, iplist &L2, iterator first, iterator last) { + assert(first != last && "Should be checked by callers"); + + if (position != last) { + // Note: we have to be careful about the case when we move the first node + // in the list. This node is the list sentinel node and we can't move it. + NodeTy *ThisSentinel = getTail(); + setTail(0); + NodeTy *L2Sentinel = L2.getTail(); + L2.setTail(0); + + // Remove [first, last) from its old position. + NodeTy *First = &*first, *Prev = getPrev(First); + NodeTy *Next = last.getNodePtrUnchecked(), *Last = getPrev(Next); + if (Prev) + setNext(Prev, Next); + else + L2.Head = Next; + setPrev(Next, Prev); + + // Splice [first, last) into its new position. + NodeTy *PosNext = position.getNodePtrUnchecked(); + NodeTy *PosPrev = getPrev(PosNext); + + // Fix head of list... + if (PosPrev) + setNext(PosPrev, First); + else + Head = First; + setPrev(First, PosPrev); + + // Fix end of list... + setNext(Last, PosNext); + setPrev(PosNext, Last); + + transferNodesFromList(L2, First, PosNext); + + // Now that everything is set, restore the pointers to the list sentinals. + L2.setTail(L2Sentinel); + setTail(ThisSentinel); + } + } + +public: + + //===----------------------------------------------------------------------=== + // Functionality derived from other functions defined above... + // + + size_type size() const { + if (Head == 0) return 0; // Don't require construction of sentinal if empty. +#if __GNUC__ == 2 + // GCC 2.95 has a broken std::distance + size_type Result = 0; + std::distance(begin(), end(), Result); + return Result; +#else + return std::distance(begin(), end()); +#endif + } + + iterator erase(iterator first, iterator last) { + while (first != last) + first = erase(first); + return last; + } + + void clear() { if (Head) erase(begin(), end()); } + + // Front and back inserters... + void push_front(NodeTy *val) { insert(begin(), val); } + void push_back(NodeTy *val) { insert(end(), val); } + void pop_front() { + assert(!empty() && "pop_front() on empty list!"); + erase(begin()); + } + void pop_back() { + assert(!empty() && "pop_back() on empty list!"); + iterator t = end(); erase(--t); + } + + // Special forms of insert... + template void insert(iterator where, InIt first, InIt last) { + for (; first != last; ++first) insert(where, *first); + } + + // Splice members - defined in terms of transfer... + void splice(iterator where, iplist &L2) { + if (!L2.empty()) + transfer(where, L2, L2.begin(), L2.end()); + } + void splice(iterator where, iplist &L2, iterator first) { + iterator last = first; ++last; + if (where == first || where == last) return; // No change + transfer(where, L2, first, last); + } + void splice(iterator where, iplist &L2, iterator first, iterator last) { + if (first != last) transfer(where, L2, first, last); + } + + + + //===----------------------------------------------------------------------=== + // High-Level Functionality that shouldn't really be here, but is part of list + // + + // These two functions are actually called remove/remove_if in list<>, but + // they actually do the job of erase, rename them accordingly. + // + void erase(const NodeTy &val) { + for (iterator I = begin(), E = end(); I != E; ) { + iterator next = I; ++next; + if (*I == val) erase(I); + I = next; + } + } + template void erase_if(Pr1 pred) { + for (iterator I = begin(), E = end(); I != E; ) { + iterator next = I; ++next; + if (pred(*I)) erase(I); + I = next; + } + } + + template void unique(Pr2 pred) { + if (empty()) return; + for (iterator I = begin(), E = end(), Next = begin(); ++Next != E;) { + if (pred(*I)) + erase(Next); + else + I = Next; + Next = I; + } + } + void unique() { unique(op_equal); } + + template void merge(iplist &right, Pr3 pred) { + iterator first1 = begin(), last1 = end(); + iterator first2 = right.begin(), last2 = right.end(); + while (first1 != last1 && first2 != last2) + if (pred(*first2, *first1)) { + iterator next = first2; + transfer(first1, right, first2, ++next); + first2 = next; + } else { + ++first1; + } + if (first2 != last2) transfer(last1, right, first2, last2); + } + void merge(iplist &right) { return merge(right, op_less); } + + template void sort(Pr3 pred); + void sort() { sort(op_less); } + void reverse(); +}; + + +template +struct ilist : public iplist { + typedef typename iplist::size_type size_type; + typedef typename iplist::iterator iterator; + + ilist() {} + ilist(const ilist &right) { + insert(this->begin(), right.begin(), right.end()); + } + explicit ilist(size_type count) { + insert(this->begin(), count, NodeTy()); + } + ilist(size_type count, const NodeTy &val) { + insert(this->begin(), count, val); + } + template ilist(InIt first, InIt last) { + insert(this->begin(), first, last); + } + + + // Forwarding functions: A workaround for GCC 2.95 which does not correctly + // support 'using' declarations to bring a hidden member into scope. + // + iterator insert(iterator a, NodeTy *b){ return iplist::insert(a, b); } + void push_front(NodeTy *a) { iplist::push_front(a); } + void push_back(NodeTy *a) { iplist::push_back(a); } + + + // Main implementation here - Insert for a node passed by value... + iterator insert(iterator where, const NodeTy &val) { + return insert(where, createNode(val)); + } + + + // Front and back inserters... + void push_front(const NodeTy &val) { insert(this->begin(), val); } + void push_back(const NodeTy &val) { insert(this->end(), val); } + + // Special forms of insert... + template void insert(iterator where, InIt first, InIt last) { + for (; first != last; ++first) insert(where, *first); + } + void insert(iterator where, size_type count, const NodeTy &val) { + for (; count != 0; --count) insert(where, val); + } + + // Assign special forms... + void assign(size_type count, const NodeTy &val) { + iterator I = this->begin(); + for (; I != this->end() && count != 0; ++I, --count) + *I = val; + if (count != 0) + insert(this->end(), val, val); + else + erase(I, this->end()); + } + template void assign(InIt first1, InIt last1) { + iterator first2 = this->begin(), last2 = this->end(); + for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) + *first1 = *first2; + if (first2 == last2) + erase(first1, last1); + else + insert(last1, first2, last2); + } + + + // Resize members... + void resize(size_type newsize, NodeTy val) { + iterator i = this->begin(); + size_type len = 0; + for ( ; i != this->end() && len < newsize; ++i, ++len) /* empty*/ ; + + if (len == newsize) + erase(i, this->end()); + else // i == end() + insert(this->end(), newsize - len, val); + } + void resize(size_type newsize) { resize(newsize, NodeTy()); } +}; + +} // End llvm namespace + +namespace std { + // Ensure that swap uses the fast list swap... + template + void swap(llvm::iplist &Left, llvm::iplist &Right) { + Left.swap(Right); + } +} // End 'std' extensions... + +#endif diff --git a/include/llvm/ADT/iterator.h.in b/include/llvm/ADT/iterator.h.in new file mode 100644 index 00000000000..86d4be34d41 --- /dev/null +++ b/include/llvm/ADT/iterator.h.in @@ -0,0 +1,76 @@ +//==-- llvm/ADT/iterator.h - Portable wrapper around --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a wrapper around the mysterious header file. +// In GCC 2.95.3, the file defines a bidirectional_iterator class (and other +// friends), instead of the standard iterator class. In GCC 3.1, the +// bidirectional_iterator class got moved out and the new, standards compliant, +// iterator<> class was added. Because there is nothing that we can do to get +// correct behavior on both compilers, we have this header with #ifdef's. Gross +// huh? +// +// By #includ'ing this file, you get the contents of plus the +// following classes in the global namespace: +// +// 1. bidirectional_iterator +// 2. forward_iterator +// +// The #if directives' expressions are filled in by Autoconf. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ITERATOR +#define LLVM_ADT_ITERATOR + +#include + +#undef HAVE_BI_ITERATOR +#undef HAVE_STD_ITERATOR +#undef HAVE_FWD_ITERATOR + +#ifdef _MSC_VER +# define HAVE_BI_ITERATOR 0 +# define HAVE_STD_ITERATOR 1 +# define HAVE_FWD_ITERATOR 0 +#endif + +#if !HAVE_BI_ITERATOR +# if HAVE_STD_ITERATOR +/// If the bidirectional iterator is not defined, we attempt to define it in +/// terms of the C++ standard iterator. Otherwise, we import it with a "using" +/// statement. +/// +template +struct bidirectional_iterator + : public std::iterator { +}; +# else +# error "Need to have standard iterator to define bidirectional iterator!" +# endif +#else +using std::bidirectional_iterator; +#endif + +#if !HAVE_FWD_ITERATOR +# if HAVE_STD_ITERATOR +/// If the forward iterator is not defined, attempt to define it in terms of +/// the C++ standard iterator. Otherwise, we import it with a "using" statement. +/// +template +struct forward_iterator + : public std::iterator { +}; +# else +# error "Need to have standard iterator to define forward iterator!" +# endif +#else +using std::forward_iterator; +#endif + +#endif diff --git a/include/llvm/ADT/iterator.in b/include/llvm/ADT/iterator.in deleted file mode 100644 index 3494c710212..00000000000 --- a/include/llvm/ADT/iterator.in +++ /dev/null @@ -1,76 +0,0 @@ -//===-- llvm/ADT/iterator - Portable wrapper around --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides a wrapper around the mysterious header file. -// In GCC 2.95.3, the file defines a bidirectional_iterator class (and other -// friends), instead of the standard iterator class. In GCC 3.1, the -// bidirectional_iterator class got moved out and the new, standards compliant, -// iterator<> class was added. Because there is nothing that we can do to get -// correct behavior on both compilers, we have this header with #ifdef's. Gross -// huh? -// -// By #includ'ing this file, you get the contents of plus the -// following classes in the global namespace: -// -// 1. bidirectional_iterator -// 2. forward_iterator -// -// The #if directives' expressions are filled in by Autoconf. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ADT_ITERATOR -#define LLVM_ADT_ITERATOR - -#include - -#undef HAVE_BI_ITERATOR -#undef HAVE_STD_ITERATOR -#undef HAVE_FWD_ITERATOR - -#ifdef _MSC_VER -# define HAVE_BI_ITERATOR 0 -# define HAVE_STD_ITERATOR 1 -# define HAVE_FWD_ITERATOR 0 -#endif - -#if !HAVE_BI_ITERATOR -# if HAVE_STD_ITERATOR -/// If the bidirectional iterator is not defined, we attempt to define it in -/// terms of the C++ standard iterator. Otherwise, we import it with a "using" -/// statement. -/// -template -struct bidirectional_iterator - : public std::iterator { -}; -# else -# error "Need to have standard iterator to define bidirectional iterator!" -# endif -#else -using std::bidirectional_iterator; -#endif - -#if !HAVE_FWD_ITERATOR -# if HAVE_STD_ITERATOR -/// If the forward iterator is not defined, attempt to define it in terms of -/// the C++ standard iterator. Otherwise, we import it with a "using" statement. -/// -template -struct forward_iterator - : public std::iterator { -}; -# else -# error "Need to have standard iterator to define forward iterator!" -# endif -#else -using std::forward_iterator; -#endif - -#endif diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index 70c25b0680b..d9e45ce9a1c 100644 --- a/include/llvm/Analysis/AliasSetTracker.h +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -19,9 +19,9 @@ #include "llvm/Support/CallSite.h" #include "llvm/Support/Streams.h" -#include "llvm/ADT/iterator" -#include "llvm/ADT/hash_map" -#include "llvm/ADT/ilist" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/hash_map.h" +#include "llvm/ADT/ilist.h" namespace llvm { diff --git a/include/llvm/Analysis/ConstantsScanner.h b/include/llvm/Analysis/ConstantsScanner.h index 0be54bbfce5..c52b24efe8b 100644 --- a/include/llvm/Analysis/ConstantsScanner.h +++ b/include/llvm/Analysis/ConstantsScanner.h @@ -18,7 +18,7 @@ #include "llvm/Support/InstIterator.h" #include "llvm/Instruction.h" -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" namespace llvm { diff --git a/include/llvm/BasicBlock.h b/include/llvm/BasicBlock.h index edb32833035..108f43a7675 100644 --- a/include/llvm/BasicBlock.h +++ b/include/llvm/BasicBlock.h @@ -16,7 +16,7 @@ #include "llvm/Instruction.h" #include "llvm/SymbolTableListTraits.h" -#include "llvm/ADT/ilist" +#include "llvm/ADT/ilist.h" #include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/Bitcode/Archive.h b/include/llvm/Bitcode/Archive.h index 50562e490ff..91684c62e23 100644 --- a/include/llvm/Bitcode/Archive.h +++ b/include/llvm/Bitcode/Archive.h @@ -17,7 +17,7 @@ #ifndef LLVM_BITCODE_ARCHIVE_H #define LLVM_BITCODE_ARCHIVE_H -#include "llvm/ADT/ilist" +#include "llvm/ADT/ilist.h" #include "llvm/System/Path.h" #include #include diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 6fbe17005cd..cd7c8d5992d 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -16,7 +16,7 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/ilist" +#include "llvm/ADT/ilist.h" #include "llvm/Support/Streams.h" namespace llvm { diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 665b55c4ca0..f5fda9bfc02 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -16,7 +16,7 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/BitVector.h" -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" #include namespace llvm { diff --git a/include/llvm/CodeGen/SchedGraphCommon.h b/include/llvm/CodeGen/SchedGraphCommon.h index eeec617a3e7..514c464dff3 100644 --- a/include/llvm/CodeGen/SchedGraphCommon.h +++ b/include/llvm/CodeGen/SchedGraphCommon.h @@ -16,7 +16,7 @@ #define LLVM_CODEGEN_SCHEDGRAPHCOMMON_H #include "llvm/Value.h" -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" #include "llvm/Support/Streams.h" #include diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 5094f023f5b..b68ed60681c 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -16,7 +16,7 @@ #define LLVM_CODEGEN_SELECTIONDAG_H #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/ilist" +#include "llvm/ADT/ilist.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 8388ab91f29..081b0e19035 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -22,7 +22,7 @@ #include "llvm/Value.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/CodeGen/ValueTypes.h" diff --git a/include/llvm/Support/CFG.h b/include/llvm/Support/CFG.h index 0d49aecb097..b0b857bf028 100644 --- a/include/llvm/Support/CFG.h +++ b/include/llvm/Support/CFG.h @@ -18,7 +18,7 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/Function.h" #include "llvm/InstrTypes.h" -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" namespace llvm { diff --git a/include/llvm/Type.h b/include/llvm/Type.h index b029212de49..c19e34b35dd 100644 --- a/include/llvm/Type.h +++ b/include/llvm/Type.h @@ -16,7 +16,7 @@ #include "llvm/Support/DataTypes.h" #include "llvm/Support/Streams.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" #include #include diff --git a/include/llvm/Use.h b/include/llvm/Use.h index d4152b39df1..0a971d18ce3 100644 --- a/include/llvm/Use.h +++ b/include/llvm/Use.h @@ -17,7 +17,7 @@ #define LLVM_USE_H #include "llvm/Support/Casting.h" -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" namespace llvm { diff --git a/tools/llvmc2/CompilationGraph.h b/tools/llvmc2/CompilationGraph.h index 2169cd39ce7..91a9c77f9a5 100644 --- a/tools/llvmc2/CompilationGraph.h +++ b/tools/llvmc2/CompilationGraph.h @@ -19,7 +19,7 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/iterator" +#include "llvm/ADT/iterator.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/System/Path.h"