TinyPtrVector.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_ADT_TINYPTRVECTOR_H
  14. #define LLVM_ADT_TINYPTRVECTOR_H
  15. #include "llvm/ADT/ArrayRef.h"
  16. #include "llvm/ADT/None.h"
  17. #include "llvm/ADT/PointerUnion.h"
  18. #include "llvm/ADT/SmallVector.h"
  19. #include <cassert>
  20. #include <cstddef>
  21. #include <iterator>
  22. #include <type_traits>
  23. namespace llvm {
  24. /// TinyPtrVector - This class is specialized for cases where there are
  25. /// normally 0 or 1 element in a vector, but is general enough to go beyond that
  26. /// when required.
  27. ///
  28. /// NOTE: This container doesn't allow you to store a null pointer into it.
  29. ///
  30. template <typename EltTy>
  31. class TinyPtrVector {
  32. public:
  33. using VecTy = SmallVector<EltTy, 4>;
  34. using value_type = typename VecTy::value_type;
  35. // EltTy must be the first pointer type so that is<EltTy> is true for the
  36. // default-constructed PtrUnion. This allows an empty TinyPtrVector to
  37. // naturally vend a begin/end iterator of type EltTy* without an additional
  38. // check for the empty state.
  39. using PtrUnion = PointerUnion<EltTy, VecTy *>;
  40. private:
  41. PtrUnion Val;
  42. public:
  43. TinyPtrVector() = default;
  44. ~TinyPtrVector() {
  45. if (VecTy *V = Val.template dyn_cast<VecTy*>())
  46. delete V;
  47. }
  48. TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) {
  49. if (VecTy *V = Val.template dyn_cast<VecTy*>())
  50. Val = new VecTy(*V);
  51. }
  52. TinyPtrVector &operator=(const TinyPtrVector &RHS) {
  53. if (this == &RHS)
  54. return *this;
  55. if (RHS.empty()) {
  56. this->clear();
  57. return *this;
  58. }
  59. // Try to squeeze into the single slot. If it won't fit, allocate a copied
  60. // vector.
  61. if (Val.template is<EltTy>()) {
  62. if (RHS.size() == 1)
  63. Val = RHS.front();
  64. else
  65. Val = new VecTy(*RHS.Val.template get<VecTy*>());
  66. return *this;
  67. }
  68. // If we have a full vector allocated, try to re-use it.
  69. if (RHS.Val.template is<EltTy>()) {
  70. Val.template get<VecTy*>()->clear();
  71. Val.template get<VecTy*>()->push_back(RHS.front());
  72. } else {
  73. *Val.template get<VecTy*>() = *RHS.Val.template get<VecTy*>();
  74. }
  75. return *this;
  76. }
  77. TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) {
  78. RHS.Val = (EltTy)nullptr;
  79. }
  80. TinyPtrVector &operator=(TinyPtrVector &&RHS) {
  81. if (this == &RHS)
  82. return *this;
  83. if (RHS.empty()) {
  84. this->clear();
  85. return *this;
  86. }
  87. // If this vector has been allocated on the heap, re-use it if cheap. If it
  88. // would require more copying, just delete it and we'll steal the other
  89. // side.
  90. if (VecTy *V = Val.template dyn_cast<VecTy*>()) {
  91. if (RHS.Val.template is<EltTy>()) {
  92. V->clear();
  93. V->push_back(RHS.front());
  94. RHS.Val = EltTy();
  95. return *this;
  96. }
  97. delete V;
  98. }
  99. Val = RHS.Val;
  100. RHS.Val = EltTy();
  101. return *this;
  102. }
  103. TinyPtrVector(std::initializer_list<EltTy> IL)
  104. : Val(IL.size() == 0
  105. ? PtrUnion()
  106. : IL.size() == 1 ? PtrUnion(*IL.begin())
  107. : PtrUnion(new VecTy(IL.begin(), IL.end()))) {}
  108. /// Constructor from an ArrayRef.
  109. ///
  110. /// This also is a constructor for individual array elements due to the single
  111. /// element constructor for ArrayRef.
  112. explicit TinyPtrVector(ArrayRef<EltTy> Elts)
  113. : Val(Elts.empty()
  114. ? PtrUnion()
  115. : Elts.size() == 1
  116. ? PtrUnion(Elts[0])
  117. : PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {}
  118. TinyPtrVector(size_t Count, EltTy Value)
  119. : Val(Count == 0 ? PtrUnion()
  120. : Count == 1 ? PtrUnion(Value)
  121. : PtrUnion(new VecTy(Count, Value))) {}
  122. // implicit conversion operator to ArrayRef.
  123. operator ArrayRef<EltTy>() const {
  124. if (Val.isNull())
  125. return None;
  126. if (Val.template is<EltTy>())
  127. return *Val.getAddrOfPtr1();
  128. return *Val.template get<VecTy*>();
  129. }
  130. // implicit conversion operator to MutableArrayRef.
  131. operator MutableArrayRef<EltTy>() {
  132. if (Val.isNull())
  133. return None;
  134. if (Val.template is<EltTy>())
  135. return *Val.getAddrOfPtr1();
  136. return *Val.template get<VecTy*>();
  137. }
  138. // Implicit conversion to ArrayRef<U> if EltTy* implicitly converts to U*.
  139. template <
  140. typename U,
  141. std::enable_if_t<std::is_convertible<ArrayRef<EltTy>, ArrayRef<U>>::value,
  142. bool> = false>
  143. operator ArrayRef<U>() const {
  144. return operator ArrayRef<EltTy>();
  145. }
  146. bool empty() const {
  147. // This vector can be empty if it contains no element, or if it
  148. // contains a pointer to an empty vector.
  149. if (Val.isNull()) return true;
  150. if (VecTy *Vec = Val.template dyn_cast<VecTy*>())
  151. return Vec->empty();
  152. return false;
  153. }
  154. unsigned size() const {
  155. if (empty())
  156. return 0;
  157. if (Val.template is<EltTy>())
  158. return 1;
  159. return Val.template get<VecTy*>()->size();
  160. }
  161. using iterator = EltTy *;
  162. using const_iterator = const EltTy *;
  163. using reverse_iterator = std::reverse_iterator<iterator>;
  164. using const_reverse_iterator = std::reverse_iterator<const_iterator>;
  165. iterator begin() {
  166. if (Val.template is<EltTy>())
  167. return Val.getAddrOfPtr1();
  168. return Val.template get<VecTy *>()->begin();
  169. }
  170. iterator end() {
  171. if (Val.template is<EltTy>())
  172. return begin() + (Val.isNull() ? 0 : 1);
  173. return Val.template get<VecTy *>()->end();
  174. }
  175. const_iterator begin() const {
  176. return (const_iterator)const_cast<TinyPtrVector*>(this)->begin();
  177. }
  178. const_iterator end() const {
  179. return (const_iterator)const_cast<TinyPtrVector*>(this)->end();
  180. }
  181. reverse_iterator rbegin() { return reverse_iterator(end()); }
  182. reverse_iterator rend() { return reverse_iterator(begin()); }
  183. const_reverse_iterator rbegin() const {
  184. return const_reverse_iterator(end());
  185. }
  186. const_reverse_iterator rend() const {
  187. return const_reverse_iterator(begin());
  188. }
  189. EltTy operator[](unsigned i) const {
  190. assert(!Val.isNull() && "can't index into an empty vector");
  191. if (Val.template is<EltTy>()) {
  192. assert(i == 0 && "tinyvector index out of range");
  193. return Val.template get<EltTy>();
  194. }
  195. assert(i < Val.template get<VecTy*>()->size() &&
  196. "tinyvector index out of range");
  197. return (*Val.template get<VecTy*>())[i];
  198. }
  199. EltTy front() const {
  200. assert(!empty() && "vector empty");
  201. if (Val.template is<EltTy>())
  202. return Val.template get<EltTy>();
  203. return Val.template get<VecTy*>()->front();
  204. }
  205. EltTy back() const {
  206. assert(!empty() && "vector empty");
  207. if (Val.template is<EltTy>())
  208. return Val.template get<EltTy>();
  209. return Val.template get<VecTy*>()->back();
  210. }
  211. void push_back(EltTy NewVal) {
  212. // If we have nothing, add something.
  213. if (Val.isNull()) {
  214. Val = NewVal;
  215. assert(!Val.isNull() && "Can't add a null value");
  216. return;
  217. }
  218. // If we have a single value, convert to a vector.
  219. if (Val.template is<EltTy>()) {
  220. EltTy V = Val.template get<EltTy>();
  221. Val = new VecTy();
  222. Val.template get<VecTy*>()->push_back(V);
  223. }
  224. // Add the new value, we know we have a vector.
  225. Val.template get<VecTy*>()->push_back(NewVal);
  226. }
  227. void pop_back() {
  228. // If we have a single value, convert to empty.
  229. if (Val.template is<EltTy>())
  230. Val = (EltTy)nullptr;
  231. else if (VecTy *Vec = Val.template get<VecTy*>())
  232. Vec->pop_back();
  233. }
  234. void clear() {
  235. // If we have a single value, convert to empty.
  236. if (Val.template is<EltTy>()) {
  237. Val = EltTy();
  238. } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
  239. // If we have a vector form, just clear it.
  240. Vec->clear();
  241. }
  242. // Otherwise, we're already empty.
  243. }
  244. iterator erase(iterator I) {
  245. assert(I >= begin() && "Iterator to erase is out of bounds.");
  246. assert(I < end() && "Erasing at past-the-end iterator.");
  247. // If we have a single value, convert to empty.
  248. if (Val.template is<EltTy>()) {
  249. if (I == begin())
  250. Val = EltTy();
  251. } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
  252. // multiple items in a vector; just do the erase, there is no
  253. // benefit to collapsing back to a pointer
  254. return Vec->erase(I);
  255. }
  256. return end();
  257. }
  258. iterator erase(iterator S, iterator E) {
  259. assert(S >= begin() && "Range to erase is out of bounds.");
  260. assert(S <= E && "Trying to erase invalid range.");
  261. assert(E <= end() && "Trying to erase past the end.");
  262. if (Val.template is<EltTy>()) {
  263. if (S == begin() && S != E)
  264. Val = EltTy();
  265. } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
  266. return Vec->erase(S, E);
  267. }
  268. return end();
  269. }
  270. iterator insert(iterator I, const EltTy &Elt) {
  271. assert(I >= this->begin() && "Insertion iterator is out of bounds.");
  272. assert(I <= this->end() && "Inserting past the end of the vector.");
  273. if (I == end()) {
  274. push_back(Elt);
  275. return std::prev(end());
  276. }
  277. assert(!Val.isNull() && "Null value with non-end insert iterator.");
  278. if (Val.template is<EltTy>()) {
  279. EltTy V = Val.template get<EltTy>();
  280. assert(I == begin());
  281. Val = Elt;
  282. push_back(V);
  283. return begin();
  284. }
  285. return Val.template get<VecTy*>()->insert(I, Elt);
  286. }
  287. template<typename ItTy>
  288. iterator insert(iterator I, ItTy From, ItTy To) {
  289. assert(I >= this->begin() && "Insertion iterator is out of bounds.");
  290. assert(I <= this->end() && "Inserting past the end of the vector.");
  291. if (From == To)
  292. return I;
  293. // If we have a single value, convert to a vector.
  294. ptrdiff_t Offset = I - begin();
  295. if (Val.isNull()) {
  296. if (std::next(From) == To) {
  297. Val = *From;
  298. return begin();
  299. }
  300. Val = new VecTy();
  301. } else if (Val.template is<EltTy>()) {
  302. EltTy V = Val.template get<EltTy>();
  303. Val = new VecTy();
  304. Val.template get<VecTy*>()->push_back(V);
  305. }
  306. return Val.template get<VecTy*>()->insert(begin() + Offset, From, To);
  307. }
  308. };
  309. } // end namespace llvm
  310. #endif // LLVM_ADT_TINYPTRVECTOR_H
  311. #ifdef __GNUC__
  312. #pragma GCC diagnostic pop
  313. #endif