LCOV - code coverage report
Current view: top level - include/llvm/ADT - TinyPtrVector.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 251 278 90.3 %
Date: 2018-10-20 13:21:21 Functions: 88 91 96.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #ifndef LLVM_ADT_TINYPTRVECTOR_H
      11             : #define LLVM_ADT_TINYPTRVECTOR_H
      12             : 
      13             : #include "llvm/ADT/ArrayRef.h"
      14             : #include "llvm/ADT/None.h"
      15             : #include "llvm/ADT/PointerUnion.h"
      16             : #include "llvm/ADT/SmallVector.h"
      17             : #include <cassert>
      18             : #include <cstddef>
      19             : #include <iterator>
      20             : #include <type_traits>
      21             : 
      22             : namespace llvm {
      23             : 
      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             :   using PtrUnion = PointerUnion<EltTy, VecTy *>;
      36             : 
      37             : private:
      38             :   PtrUnion Val;
      39             : 
      40             : public:
      41             :   TinyPtrVector() = default;
      42             : 
      43  1704828822 :   ~TinyPtrVector() {
      44    33371847 :     if (VecTy *V = Val.template dyn_cast<VecTy*>())
      45    33371847 :       delete V;
      46  1704828822 :   }
      47      384943 : 
      48   356323803 :   TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) {
      49    11061318 :     if (VecTy *V = Val.template dyn_cast<VecTy*>())
      50    11446001 :       Val = new VecTy(*V);
      51   364674358 :   }
      52        1660 : 
      53       18940 :   TinyPtrVector &operator=(const TinyPtrVector &RHS) {
      54     8368095 :     if (this == &RHS)
      55             :       return *this;
      56           4 :     if (RHS.empty()) {
      57           2 :       this->clear();
      58       15657 :       return *this;
      59           4 :     }
      60           2 : 
      61           1 :     // Try to squeeze into the single slot. If it won't fit, allocate a copied
      62           1 :     // vector.
      63        1627 :     if (Val.template is<EltTy>()) {
      64           2 :       if (RHS.size() == 1)
      65           1 :         Val = RHS.front();
      66           1 :       else
      67           2 :         Val = new VecTy(*RHS.Val.template get<VecTy*>());
      68        1625 :       return *this;
      69          32 :     }
      70          32 : 
      71             :     // If we have a full vector allocated, try to re-use it.
      72           0 :     if (RHS.Val.template is<EltTy>()) {
      73             :       Val.template get<VecTy*>()->clear();
      74           8 :       Val.template get<VecTy*>()->push_back(RHS.front());
      75             :     } else {
      76             :       *Val.template get<VecTy*>() = *RHS.Val.template get<VecTy*>();
      77             :     }
      78             :     return *this;
      79          24 :   }
      80           0 : 
      81      177549 :   TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) {
      82             :     RHS.Val = (EltTy)nullptr;
      83           0 :   }
      84           0 : 
      85      452946 :   TinyPtrVector &operator=(TinyPtrVector &&RHS) {
      86      452946 :     if (this == &RHS)
      87             :       return *this;
      88          37 :     if (RHS.empty()) {
      89      300162 :       this->clear();
      90      424226 :       return *this;
      91             :     }
      92             : 
      93             :     // If this vector has been allocated on the heap, re-use it if cheap. If it
      94             :     // would require more copying, just delete it and we'll steal the other
      95             :     // side.
      96          16 :     if (VecTy *V = Val.template dyn_cast<VecTy*>()) {
      97          16 :       if (RHS.Val.template is<EltTy>()) {
      98             :         V->clear();
      99           0 :         V->push_back(RHS.front());
     100             :         RHS.Val = (EltTy)nullptr;
     101           4 :         return *this;
     102             :       }
     103           0 :       delete V;
     104             :     }
     105             : 
     106       28748 :     Val = RHS.Val;
     107           0 :     RHS.Val = (EltTy)nullptr;
     108       28736 :     return *this;
     109             :   }
     110           0 : 
     111         144 :   TinyPtrVector(std::initializer_list<EltTy> IL)
     112             :       : Val(IL.size() == 0
     113             :                 ? PtrUnion()
     114             :                 : IL.size() == 1 ? PtrUnion(*IL.begin())
     115         156 :                                  : PtrUnion(new VecTy(IL.begin(), IL.end()))) {}
     116             : 
     117           8 :   /// Constructor from an ArrayRef.
     118             :   ///
     119             :   /// This also is a constructor for individual array elements due to the single
     120             :   /// element constructor for ArrayRef.
     121             :   explicit TinyPtrVector(ArrayRef<EltTy> Elts)
     122             :       : Val(Elts.empty()
     123          16 :                 ? PtrUnion()
     124          16 :                 : Elts.size() == 1
     125             :                       ? PtrUnion(Elts[0])
     126             :                       : PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {}
     127             : 
     128           4 :   TinyPtrVector(size_t Count, EltTy Value)
     129             :       : Val(Count == 0 ? PtrUnion()
     130             :                        : Count == 1 ? PtrUnion(Value)
     131             :                                     : PtrUnion(new VecTy(Count, Value))) {}
     132             : 
     133          12 :   // implicit conversion operator to ArrayRef.
     134           0 :   operator ArrayRef<EltTy>() const {
     135       15353 :     if (Val.isNull())
     136             :       return None;
     137       15353 :     if (Val.template is<EltTy>())
     138           0 :       return *Val.getAddrOfPtr1();
     139             :     return *Val.template get<VecTy*>();
     140             :   }
     141             : 
     142          12 :   // implicit conversion operator to MutableArrayRef.
     143             :   operator MutableArrayRef<EltTy>() {
     144      139584 :     if (Val.isNull())
     145             :       return None;
     146       68219 :     if (Val.template is<EltTy>())
     147             :       return *Val.getAddrOfPtr1();
     148             :     return *Val.template get<VecTy*>();
     149             :   }
     150             : 
     151           2 :   // Implicit conversion to ArrayRef<U> if EltTy* implicitly converts to U*.
     152          99 :   template<typename U,
     153             :            typename std::enable_if<
     154          85 :                std::is_convertible<ArrayRef<EltTy>, ArrayRef<U>>::value,
     155          34 :                bool>::type = false>
     156          34 :   operator ArrayRef<U>() const {
     157             :     return operator ArrayRef<EltTy>();
     158          16 :   }
     159             : 
     160           8 :   bool empty() const {
     161             :     // This vector can be empty if it contains no element, or if it
     162             :     // contains a pointer to an empty vector.
     163   432012791 :     if (Val.isNull()) return true;
     164             :     if (VecTy *Vec = Val.template dyn_cast<VecTy*>())
     165    21841812 :       return Vec->empty();
     166          26 :     return false;
     167          26 :   }
     168             : 
     169          20 :   unsigned size() const {
     170         386 :     if (empty())
     171      136939 :       return 0;
     172        3043 :     if (Val.template is<EltTy>())
     173       21312 :       return 1;
     174         386 :     return Val.template get<VecTy*>()->size();
     175             :   }
     176          16 : 
     177             :   using iterator = EltTy *;
     178        9099 :   using const_iterator = const EltTy *;
     179             :   using reverse_iterator = std::reverse_iterator<iterator>;
     180       37933 :   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
     181          17 : 
     182        9083 :   iterator begin() {
     183  1865932846 :     if (Val.template is<EltTy>())
     184             :       return Val.getAddrOfPtr1();
     185           4 : 
     186             :     return Val.template get<VecTy *>()->begin();
     187             :   }
     188             : 
     189             :   iterator end() {
     190  1839589600 :     if (Val.template is<EltTy>())
     191  1831265613 :       return begin() + (Val.isNull() ? 0 : 1);
     192          13 : 
     193             :     return Val.template get<VecTy *>()->end();
     194          10 :   }
     195             : 
     196           5 :   const_iterator begin() const {
     197             :     return (const_iterator)const_cast<TinyPtrVector*>(this)->begin();
     198    41749201 :   }
     199    37733827 : 
     200             :   const_iterator end() const {
     201           8 :     return (const_iterator)const_cast<TinyPtrVector*>(this)->end();
     202             :   }
     203           8 : 
     204             :   reverse_iterator rbegin() { return reverse_iterator(end()); }
     205          17 :   reverse_iterator rend() { return reverse_iterator(begin()); }
     206          17 : 
     207             :   const_reverse_iterator rbegin() const {
     208           8 :     return const_reverse_iterator(end());
     209             :   }
     210           4 : 
     211             :   const_reverse_iterator rend() const {
     212             :     return const_reverse_iterator(begin());
     213             :   }
     214             : 
     215             :   EltTy operator[](unsigned i) const {
     216          13 :     assert(!Val.isNull() && "can't index into an empty vector");
     217          19 :     if (EltTy V = Val.template dyn_cast<EltTy>()) {
     218             :       assert(i == 0 && "tinyvector index out of range");
     219          10 :       return V;
     220             :     }
     221           5 : 
     222             :     assert(i < Val.template get<VecTy*>()->size() &&
     223           8 :            "tinyvector index out of range");
     224          20 :     return (*Val.template get<VecTy*>())[i];
     225           1 :   }
     226           8 : 
     227             :   EltTy front() const {
     228           8 :     assert(!empty() && "vector empty");
     229        1490 :     if (EltTy V = Val.template dyn_cast<EltTy>())
     230             :       return V;
     231        1037 :     return Val.template get<VecTy*>()->front();
     232          11 :   }
     233             : 
     234             :   EltTy back() const {
     235             :     assert(!empty() && "vector empty");
     236          20 :     if (EltTy V = Val.template dyn_cast<EltTy>())
     237             :       return V;
     238           1 :     return Val.template get<VecTy*>()->back();
     239             :   }
     240             : 
     241    55790003 :   void push_back(EltTy NewVal) {
     242             :     assert(NewVal && "Can't add a null value");
     243             : 
     244             :     // If we have nothing, add something.
     245    55789996 :     if (Val.isNull()) {
     246    31804163 :       Val = NewVal;
     247    31804158 :       return;
     248             :     }
     249      438616 : 
     250             :     // If we have a single value, convert to a vector.
     251    23985840 :     if (EltTy V = Val.template dyn_cast<EltTy>()) {
     252    21736626 :       Val = new VecTy();
     253    22175245 :       Val.template get<VecTy*>()->push_back(V);
     254      432049 :     }
     255      432049 : 
     256             :     // Add the new value, we know we have a vector.
     257    23985840 :     Val.template get<VecTy*>()->push_back(NewVal);
     258           5 :   }
     259        6567 : 
     260        3324 :   void pop_back() {
     261        3324 :     // If we have a single value, convert to empty.
     262             :     if (Val.template is<EltTy>())
     263             :       Val = (EltTy)nullptr;
     264             :     else if (VecTy *Vec = Val.template get<VecTy*>())
     265        6567 :       Vec->pop_back();
     266             :   }
     267      422703 : 
     268             :   void clear() {
     269             :     // If we have a single value, convert to empty.
     270   603406809 :     if (Val.template is<EltTy>()) {
     271      422703 :       Val = (EltTy)nullptr;
     272     1491434 :     } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
     273      421022 :       // If we have a vector form, just clear it.
     274             :       Vec->clear();
     275             :     }
     276           1 :     // Otherwise, we're already empty.
     277        1681 :   }
     278      297804 : 
     279       47541 :   iterator erase(iterator I) {
     280        1439 :     assert(I >= begin() && "Iterator to erase is out of bounds.");
     281             :     assert(I < end() && "Erasing at past-the-end iterator.");
     282             : 
     283        1681 :     // If we have a single value, convert to empty.
     284       45874 :     if (Val.template is<EltTy>()) {
     285       47491 :       if (I == begin())
     286             :         Val = (EltTy)nullptr;
     287        1679 :     } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
     288             :       // multiple items in a vector; just do the erase, there is no
     289        3296 :       // benefit to collapsing back to a pointer
     290        2629 :       return Vec->erase(I);
     291         950 :     }
     292             :     return end();
     293             :   }
     294             : 
     295        2917 :   iterator erase(iterator S, iterator E) {
     296         306 :     assert(S >= begin() && "Range to erase is out of bounds.");
     297         340 :     assert(S <= E && "Trying to erase invalid range.");
     298             :     assert(E <= end() && "Trying to erase past the end.");
     299             : 
     300         499 :     if (Val.template is<EltTy>()) {
     301        2780 :       if (S == begin() && S != E)
     302           2 :         Val = (EltTy)nullptr;
     303         104 :     } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
     304          68 :       return Vec->erase(S, E);
     305             :     }
     306           2 :     return end();
     307             :   }
     308          39 : 
     309           0 :   iterator insert(iterator I, const EltTy &Elt) {
     310             :     assert(I >= this->begin() && "Insertion iterator is out of bounds.");
     311          39 :     assert(I <= this->end() && "Inserting past the end of the vector.");
     312          39 :     if (I == end()) {
     313             :       push_back(Elt);
     314             :       return std::prev(end());
     315          74 :     }
     316             :     assert(!Val.isNull() && "Null value with non-end insert iterator.");
     317             :     if (EltTy V = Val.template dyn_cast<EltTy>()) {
     318             :       assert(I == begin());
     319             :       Val = Elt;
     320             :       push_back(V);
     321             :       return begin();
     322         118 :     }
     323          36 : 
     324             :     return Val.template get<VecTy*>()->insert(I, Elt);
     325             :   }
     326             : 
     327             :   template<typename ItTy>
     328   269992046 :   iterator insert(iterator I, ItTy From, ItTy To) {
     329             :     assert(I >= this->begin() && "Insertion iterator is out of bounds.");
     330             :     assert(I <= this->end() && "Inserting past the end of the vector.");
     331   269992046 :     if (From == To)
     332             :       return I;
     333             : 
     334             :     // If we have a single value, convert to a vector.
     335     4017784 :     ptrdiff_t Offset = I - begin();
     336     4030356 :     if (Val.isNull()) {
     337     3697995 :       if (std::next(From) == To) {
     338     3270149 :         Val = *From;
     339       13138 :         return begin();
     340             :       }
     341             : 
     342      427846 :       Val = new VecTy();
     343      320034 :     } else if (EltTy V = Val.template dyn_cast<EltTy>()) {
     344      145225 :       Val = new VecTy();
     345      144734 :       Val.template get<VecTy*>()->push_back(V);
     346           0 :     }
     347     1495556 :     return Val.template get<VecTy*>()->insert(begin() + Offset, From, To);
     348         286 :   }
     349           0 : };
     350          40 : 
     351         205 : } // end namespace llvm
     352           0 : 
     353           0 : #endif // LLVM_ADT_TINYPTRVECTOR_H

Generated by: LCOV version 1.13