Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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