File indexing completed on 2026-05-10 08:43:10
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_ADT_TINYPTRVECTOR_H
0010 #define LLVM_ADT_TINYPTRVECTOR_H
0011
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/PointerUnion.h"
0014 #include "llvm/ADT/SmallVector.h"
0015 #include <cassert>
0016 #include <cstddef>
0017 #include <iterator>
0018 #include <type_traits>
0019
0020 namespace llvm {
0021
0022
0023
0024
0025
0026
0027
0028 template <typename EltTy>
0029 class TinyPtrVector {
0030 public:
0031 using VecTy = SmallVector<EltTy, 4>;
0032 using value_type = typename VecTy::value_type;
0033
0034
0035
0036
0037 using PtrUnion = PointerUnion<EltTy, VecTy *>;
0038
0039 private:
0040 PtrUnion Val;
0041
0042 public:
0043 TinyPtrVector() = default;
0044
0045 ~TinyPtrVector() {
0046 if (VecTy *V = dyn_cast_if_present<VecTy *>(Val))
0047 delete V;
0048 }
0049
0050 TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) {
0051 if (VecTy *V = dyn_cast_if_present<VecTy *>(Val))
0052 Val = new VecTy(*V);
0053 }
0054
0055 TinyPtrVector &operator=(const TinyPtrVector &RHS) {
0056 if (this == &RHS)
0057 return *this;
0058 if (RHS.empty()) {
0059 this->clear();
0060 return *this;
0061 }
0062
0063
0064
0065 if (isa<EltTy>(Val)) {
0066 if (RHS.size() == 1)
0067 Val = RHS.front();
0068 else
0069 Val = new VecTy(*cast<VecTy *>(RHS.Val));
0070 return *this;
0071 }
0072
0073
0074 if (isa<EltTy>(RHS.Val)) {
0075 cast<VecTy *>(Val)->clear();
0076 cast<VecTy *>(Val)->push_back(RHS.front());
0077 } else {
0078 *cast<VecTy *>(Val) = *cast<VecTy *>(RHS.Val);
0079 }
0080 return *this;
0081 }
0082
0083 TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) {
0084 RHS.Val = (EltTy)nullptr;
0085 }
0086
0087 TinyPtrVector &operator=(TinyPtrVector &&RHS) {
0088 if (this == &RHS)
0089 return *this;
0090 if (RHS.empty()) {
0091 this->clear();
0092 return *this;
0093 }
0094
0095
0096
0097
0098 if (VecTy *V = dyn_cast_if_present<VecTy *>(Val)) {
0099 if (isa<EltTy>(RHS.Val)) {
0100 V->clear();
0101 V->push_back(RHS.front());
0102 RHS.Val = EltTy();
0103 return *this;
0104 }
0105 delete V;
0106 }
0107
0108 Val = RHS.Val;
0109 RHS.Val = EltTy();
0110 return *this;
0111 }
0112
0113 TinyPtrVector(std::initializer_list<EltTy> IL)
0114 : Val(IL.size() == 0
0115 ? PtrUnion()
0116 : IL.size() == 1 ? PtrUnion(*IL.begin())
0117 : PtrUnion(new VecTy(IL.begin(), IL.end()))) {}
0118
0119
0120
0121
0122
0123 explicit TinyPtrVector(ArrayRef<EltTy> Elts)
0124 : Val(Elts.empty()
0125 ? PtrUnion()
0126 : Elts.size() == 1
0127 ? PtrUnion(Elts[0])
0128 : PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {}
0129
0130 TinyPtrVector(size_t Count, EltTy Value)
0131 : Val(Count == 0 ? PtrUnion()
0132 : Count == 1 ? PtrUnion(Value)
0133 : PtrUnion(new VecTy(Count, Value))) {}
0134
0135
0136 operator ArrayRef<EltTy>() const {
0137 if (Val.isNull())
0138 return {};
0139 if (isa<EltTy>(Val))
0140 return *Val.getAddrOfPtr1();
0141 return *cast<VecTy *>(Val);
0142 }
0143
0144
0145 operator MutableArrayRef<EltTy>() {
0146 if (Val.isNull())
0147 return {};
0148 if (isa<EltTy>(Val))
0149 return *Val.getAddrOfPtr1();
0150 return *cast<VecTy *>(Val);
0151 }
0152
0153
0154 template <
0155 typename U,
0156 std::enable_if_t<std::is_convertible<ArrayRef<EltTy>, ArrayRef<U>>::value,
0157 bool> = false>
0158 operator ArrayRef<U>() const {
0159 return operator ArrayRef<EltTy>();
0160 }
0161
0162 bool empty() const {
0163
0164
0165 if (Val.isNull()) return true;
0166 if (VecTy *Vec = dyn_cast_if_present<VecTy *>(Val))
0167 return Vec->empty();
0168 return false;
0169 }
0170
0171 unsigned size() const {
0172 if (empty())
0173 return 0;
0174 if (isa<EltTy>(Val))
0175 return 1;
0176 return cast<VecTy *>(Val)->size();
0177 }
0178
0179 using iterator = EltTy *;
0180 using const_iterator = const EltTy *;
0181 using reverse_iterator = std::reverse_iterator<iterator>;
0182 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
0183
0184 iterator begin() {
0185 if (isa<EltTy>(Val))
0186 return Val.getAddrOfPtr1();
0187
0188 return cast<VecTy *>(Val)->begin();
0189 }
0190
0191 iterator end() {
0192 if (isa<EltTy>(Val))
0193 return begin() + (Val.isNull() ? 0 : 1);
0194
0195 return cast<VecTy *>(Val)->end();
0196 }
0197
0198 const_iterator begin() const {
0199 return (const_iterator)const_cast<TinyPtrVector*>(this)->begin();
0200 }
0201
0202 const_iterator end() const {
0203 return (const_iterator)const_cast<TinyPtrVector*>(this)->end();
0204 }
0205
0206 reverse_iterator rbegin() { return reverse_iterator(end()); }
0207 reverse_iterator rend() { return reverse_iterator(begin()); }
0208
0209 const_reverse_iterator rbegin() const {
0210 return const_reverse_iterator(end());
0211 }
0212
0213 const_reverse_iterator rend() const {
0214 return const_reverse_iterator(begin());
0215 }
0216
0217 EltTy operator[](unsigned i) const {
0218 assert(!Val.isNull() && "can't index into an empty vector");
0219 if (isa<EltTy>(Val)) {
0220 assert(i == 0 && "tinyvector index out of range");
0221 return cast<EltTy>(Val);
0222 }
0223
0224 assert(i < cast<VecTy *>(Val)->size() && "tinyvector index out of range");
0225 return (*cast<VecTy *>(Val))[i];
0226 }
0227
0228 EltTy front() const {
0229 assert(!empty() && "vector empty");
0230 if (isa<EltTy>(Val))
0231 return cast<EltTy>(Val);
0232 return cast<VecTy *>(Val)->front();
0233 }
0234
0235 EltTy back() const {
0236 assert(!empty() && "vector empty");
0237 if (isa<EltTy>(Val))
0238 return cast<EltTy>(Val);
0239 return cast<VecTy *>(Val)->back();
0240 }
0241
0242 void push_back(EltTy NewVal) {
0243
0244 if (Val.isNull()) {
0245 Val = NewVal;
0246 assert(!Val.isNull() && "Can't add a null value");
0247 return;
0248 }
0249
0250
0251 if (isa<EltTy>(Val)) {
0252 EltTy V = cast<EltTy>(Val);
0253 Val = new VecTy();
0254 cast<VecTy *>(Val)->push_back(V);
0255 }
0256
0257
0258 cast<VecTy *>(Val)->push_back(NewVal);
0259 }
0260
0261 void pop_back() {
0262
0263 if (isa<EltTy>(Val))
0264 Val = (EltTy)nullptr;
0265 else if (VecTy *Vec = cast<VecTy *>(Val))
0266 Vec->pop_back();
0267 }
0268
0269 void clear() {
0270
0271 if (isa<EltTy>(Val)) {
0272 Val = EltTy();
0273 } else if (VecTy *Vec = dyn_cast_if_present<VecTy *>(Val)) {
0274
0275 Vec->clear();
0276 }
0277
0278 }
0279
0280 iterator erase(iterator I) {
0281 assert(I >= begin() && "Iterator to erase is out of bounds.");
0282 assert(I < end() && "Erasing at past-the-end iterator.");
0283
0284
0285 if (isa<EltTy>(Val)) {
0286 if (I == begin())
0287 Val = EltTy();
0288 } else if (VecTy *Vec = dyn_cast_if_present<VecTy *>(Val)) {
0289
0290
0291 return Vec->erase(I);
0292 }
0293 return end();
0294 }
0295
0296 iterator erase(iterator S, iterator E) {
0297 assert(S >= begin() && "Range to erase is out of bounds.");
0298 assert(S <= E && "Trying to erase invalid range.");
0299 assert(E <= end() && "Trying to erase past the end.");
0300
0301 if (isa<EltTy>(Val)) {
0302 if (S == begin() && S != E)
0303 Val = EltTy();
0304 } else if (VecTy *Vec = dyn_cast_if_present<VecTy *>(Val)) {
0305 return Vec->erase(S, E);
0306 }
0307 return end();
0308 }
0309
0310 iterator insert(iterator I, const EltTy &Elt) {
0311 assert(I >= this->begin() && "Insertion iterator is out of bounds.");
0312 assert(I <= this->end() && "Inserting past the end of the vector.");
0313 if (I == end()) {
0314 push_back(Elt);
0315 return std::prev(end());
0316 }
0317 assert(!Val.isNull() && "Null value with non-end insert iterator.");
0318 if (isa<EltTy>(Val)) {
0319 EltTy V = cast<EltTy>(Val);
0320 assert(I == begin());
0321 Val = Elt;
0322 push_back(V);
0323 return begin();
0324 }
0325
0326 return cast<VecTy *>(Val)->insert(I, Elt);
0327 }
0328
0329 template<typename ItTy>
0330 iterator insert(iterator I, ItTy From, ItTy To) {
0331 assert(I >= this->begin() && "Insertion iterator is out of bounds.");
0332 assert(I <= this->end() && "Inserting past the end of the vector.");
0333 if (From == To)
0334 return I;
0335
0336
0337 ptrdiff_t Offset = I - begin();
0338 if (Val.isNull()) {
0339 if (std::next(From) == To) {
0340 Val = *From;
0341 return begin();
0342 }
0343
0344 Val = new VecTy();
0345 } else if (isa<EltTy>(Val)) {
0346 EltTy V = cast<EltTy>(Val);
0347 Val = new VecTy();
0348 cast<VecTy *>(Val)->push_back(V);
0349 }
0350 return cast<VecTy *>(Val)->insert(begin() + Offset, From, To);
0351 }
0352 };
0353
0354 }
0355
0356 #endif