#ifndef LLVM_ADT_SMALLPTRSET_H
#define LLVM_ADT_SMALLPTRSET_H
-#include <cassert>
-#include <cstring>
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <iterator>
namespace llvm {
class SmallPtrSetImpl {
friend class SmallPtrSetIteratorImpl;
protected:
- /// CurArray - This is the current set of buckets. If it points to
- /// SmallArray, then the set is in 'small mode'.
+ /// SmallArray - Points to a fixed size set of buckets, used in 'small mode'.
+ const void **SmallArray;
+ /// CurArray - This is the current set of buckets. If equal to SmallArray,
+ /// then the set is in 'small mode'.
const void **CurArray;
/// CurArraySize - The allocated size of CurArray, always a power of two.
- /// Note that CurArray points to an array that has CurArraySize+1 elements in
- /// it, so that the end iterator actually points to valid memory.
unsigned CurArraySize;
- // If small, this is # elts allocated consequtively
+ // If small, this is # elts allocated consecutively
unsigned NumElements;
unsigned NumTombstones;
- const void *SmallArray[1]; // Must be last ivar.
// Helper to copy construct a SmallPtrSet.
- SmallPtrSetImpl(const SmallPtrSetImpl& that);
- explicit SmallPtrSetImpl(unsigned SmallSize) {
+ SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl& that);
+ explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize) :
+ SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) {
assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
"Initial size must be a power of two!");
- CurArray = &SmallArray[0];
- CurArraySize = SmallSize;
- // The end pointer, always valid, is set to a valid element to help the
- // iterator.
- CurArray[SmallSize] = 0;
clear();
}
~SmallPtrSetImpl();
}
private:
- bool isSmall() const { return CurArray == &SmallArray[0]; }
+ bool isSmall() const { return CurArray == SmallArray; }
- unsigned Hash(const void *Ptr) const {
- return static_cast<unsigned>(((uintptr_t)Ptr >> 4) & (CurArraySize-1));
- }
const void * const *FindBucketFor(const void *Ptr) const;
void shrink_and_clear();
/// Grow - Allocate a larger backing store for the buckets and move it over.
- void Grow();
+ void Grow(unsigned NewSize);
- void operator=(const SmallPtrSetImpl &RHS); // DO NOT IMPLEMENT.
+ void operator=(const SmallPtrSetImpl &RHS) LLVM_DELETED_FUNCTION;
protected:
+ /// swap - Swaps the elements of two sets.
+ /// Note: This method assumes that both sets have the same small size.
+ void swap(SmallPtrSetImpl &RHS);
+
void CopyFrom(const SmallPtrSetImpl &RHS);
};
class SmallPtrSetIteratorImpl {
protected:
const void *const *Bucket;
+ const void *const *End;
public:
- explicit SmallPtrSetIteratorImpl(const void *const *BP) : Bucket(BP) {
- AdvanceIfNotValid();
+ explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E)
+ : Bucket(BP), End(E) {
+ AdvanceIfNotValid();
}
bool operator==(const SmallPtrSetIteratorImpl &RHS) const {
/// that is. This is guaranteed to stop because the end() bucket is marked
/// valid.
void AdvanceIfNotValid() {
- while (*Bucket == SmallPtrSetImpl::getEmptyMarker() ||
- *Bucket == SmallPtrSetImpl::getTombstoneMarker())
+ assert(Bucket <= End);
+ while (Bucket != End &&
+ (*Bucket == SmallPtrSetImpl::getEmptyMarker() ||
+ *Bucket == SmallPtrSetImpl::getTombstoneMarker()))
++Bucket;
}
};
template<typename PtrTy>
class SmallPtrSetIterator : public SmallPtrSetIteratorImpl {
typedef PointerLikeTypeTraits<PtrTy> PtrTraits;
+
public:
- explicit SmallPtrSetIterator(const void *const *BP)
- : SmallPtrSetIteratorImpl(BP) {}
+ typedef PtrTy value_type;
+ typedef PtrTy reference;
+ typedef PtrTy pointer;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ explicit SmallPtrSetIterator(const void *const *BP, const void *const *E)
+ : SmallPtrSetIteratorImpl(BP, E) {}
// Most methods provided by baseclass.
const PtrTy operator*() const {
+ assert(Bucket < End);
return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket));
}
}
};
-/// NextPowerOfTwo - This is a helper template that rounds N up to the next
-/// power of two.
+/// RoundUpToPowerOfTwo - This is a helper template that rounds N up to the next
+/// power of two (which means N itself if N is already a power of two).
template<unsigned N>
-struct NextPowerOfTwo;
+struct RoundUpToPowerOfTwo;
-/// NextPowerOfTwoH - If N is not a power of two, increase it. This is a helper
-/// template used to implement NextPowerOfTwo.
+/// RoundUpToPowerOfTwoH - If N is not a power of two, increase it. This is a
+/// helper template used to implement RoundUpToPowerOfTwo.
template<unsigned N, bool isPowerTwo>
-struct NextPowerOfTwoH {
+struct RoundUpToPowerOfTwoH {
enum { Val = N };
};
template<unsigned N>
-struct NextPowerOfTwoH<N, false> {
+struct RoundUpToPowerOfTwoH<N, false> {
enum {
// We could just use NextVal = N+1, but this converges faster. N|(N-1) sets
// the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111.
- Val = NextPowerOfTwo<(N|(N-1)) + 1>::Val
+ Val = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val
};
};
template<unsigned N>
-struct NextPowerOfTwo {
- enum { Val = NextPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
+struct RoundUpToPowerOfTwo {
+ enum { Val = RoundUpToPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
};
-/// SmallPtrSet - This class implements a set which is optimizer for holding
+/// SmallPtrSet - This class implements a set which is optimized for holding
/// SmallSize or less elements. This internally rounds up SmallSize to the next
/// power of two if it is not already a power of two. See the comments above
/// SmallPtrSetImpl for details of the algorithm.
template<class PtrType, unsigned SmallSize>
class SmallPtrSet : public SmallPtrSetImpl {
// Make sure that SmallSize is a power of two, round up if not.
- enum { SmallSizePowTwo = NextPowerOfTwo<SmallSize>::Val };
- void *SmallArray[SmallSizePowTwo];
+ enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val };
+ /// SmallStorage - Fixed size storage used in 'small mode'.
+ const void *SmallStorage[SmallSizePowTwo];
typedef PointerLikeTypeTraits<PtrType> PtrTraits;
public:
- SmallPtrSet() : SmallPtrSetImpl(NextPowerOfTwo<SmallSizePowTwo>::Val) {}
- SmallPtrSet(const SmallPtrSet &that) : SmallPtrSetImpl(that) {}
+ SmallPtrSet() : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) {}
+ SmallPtrSet(const SmallPtrSet &that) : SmallPtrSetImpl(SmallStorage, that) {}
template<typename It>
- SmallPtrSet(It I, It E)
- : SmallPtrSetImpl(NextPowerOfTwo<SmallSizePowTwo>::Val) {
+ SmallPtrSet(It I, It E) : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) {
insert(I, E);
}
typedef SmallPtrSetIterator<PtrType> iterator;
typedef SmallPtrSetIterator<PtrType> const_iterator;
inline iterator begin() const {
- return iterator(CurArray);
+ return iterator(CurArray, CurArray+CurArraySize);
}
inline iterator end() const {
- return iterator(CurArray+CurArraySize);
+ return iterator(CurArray+CurArraySize, CurArray+CurArraySize);
}
// Allow assignment from any smallptrset with the same element type even if it
return *this;
}
+ /// swap - Swaps the elements of two sets.
+ void swap(SmallPtrSet<PtrType, SmallSize> &RHS) {
+ SmallPtrSetImpl::swap(RHS);
+ }
};
}
+namespace std {
+ /// Implement std::swap in terms of SmallPtrSet swap.
+ template<class T, unsigned N>
+ inline void swap(llvm::SmallPtrSet<T, N> &LHS, llvm::SmallPtrSet<T, N> &RHS) {
+ LHS.swap(RHS);
+ }
+}
+
#endif