TinyPtrVector.h 10 KB

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