diff options
Diffstat (limited to 'include/llvm/ADT')
-rw-r--r-- | include/llvm/ADT/BitVector.h | 18 | ||||
-rw-r--r-- | include/llvm/ADT/SmallBitVector.h | 373 | ||||
-rw-r--r-- | include/llvm/ADT/StringExtras.h | 84 | ||||
-rw-r--r-- | include/llvm/ADT/StringRef.h | 28 | ||||
-rw-r--r-- | include/llvm/ADT/Twine.h | 34 |
5 files changed, 448 insertions, 89 deletions
diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 9c046ef..45108c8 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -95,6 +95,9 @@ public: delete[] Bits; } + /// empty - Tests whether there are no bits in this bitvector. + bool empty() const { return Size == 0; } + /// size - Returns the number of bits in this bitvector. unsigned size() const { return Size; } @@ -341,6 +344,12 @@ public: return *this; } + void swap(BitVector &RHS) { + std::swap(Bits, RHS.Bits); + std::swap(Size, RHS.Size); + std::swap(Capacity, RHS.Capacity); + } + private: unsigned NumBitWords(unsigned S) const { return (S + BITWORD_SIZE-1) / BITWORD_SIZE; @@ -406,4 +415,13 @@ inline BitVector operator^(const BitVector &LHS, const BitVector &RHS) { } } // End llvm namespace + +namespace std { + /// Implement std::swap in terms of BitVector swap. + inline void + swap(llvm::BitVector &LHS, llvm::BitVector &RHS) { + LHS.swap(RHS); + } +} + #endif diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h new file mode 100644 index 0000000..346fb1c --- /dev/null +++ b/include/llvm/ADT/SmallBitVector.h @@ -0,0 +1,373 @@ +//===- llvm/ADT/SmallBitVector.h - 'Normally small' bit vectors -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SmallBitVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLBITVECTOR_H +#define LLVM_ADT_SMALLBITVECTOR_H + +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/MathExtras.h" +#include <cassert> + +namespace llvm { + +/// SmallBitVector - This is a 'bitvector' (really, a variable-sized bit array), +/// optimized for the case when the array is small. It contains one +/// pointer-sized field, which is directly used as a plain collection of bits +/// when possible, or as a pointer to a larger heap-allocated array when +/// necessary. This allows normal "small" cases to be fast without losing +/// generality for large inputs. +/// +class SmallBitVector { + // TODO: In "large" mode, a pointer to a BitVector is used, leading to an + // unnecessary level of indirection. It would be more efficient to use a + // pointer to memory containing size, allocation size, and the array of bits. + PointerIntPair<BitVector *, 1, uintptr_t> X; + + // The number of bits in this class. + static const size_t NumBaseBits = sizeof(uintptr_t) * CHAR_BIT; + + // One bit is used to discriminate between small and large mode. The + // remaining bits are used for the small-mode representation. + static const size_t SmallNumRawBits = NumBaseBits - 1; + + // A few more bits are used to store the size of the bit set in small mode. + // Theoretically this is a ceil-log2. These bits are encoded in the most + // significant bits of the raw bits. + static const size_t SmallNumSizeBits = (NumBaseBits == 32 ? 5 : + NumBaseBits == 64 ? 6 : + SmallNumRawBits); + + // The remaining bits are used to store the actual set in small mode. + static const size_t SmallNumDataBits = SmallNumRawBits - SmallNumSizeBits; + + bool isSmall() const { + return X.getInt(); + } + + void switchToSmall(uintptr_t NewSmallBits, size_t NewSize) { + X.setInt(true); + setSmallSize(NewSize); + setSmallBits(NewSmallBits); + } + + void switchToLarge(BitVector *BV) { + X.setInt(false); + X.setPointer(BV); + } + + // Return all the bits used for the "small" representation; this includes + // bits for the size as well as the element bits. + uintptr_t getSmallRawBits() const { + return reinterpret_cast<uintptr_t>(X.getPointer()) >> 1; + } + + void setSmallRawBits(uintptr_t NewRawBits) { + return X.setPointer(reinterpret_cast<BitVector *>(NewRawBits << 1)); + } + + // Return the size. + size_t getSmallSize() const { + return getSmallRawBits() >> SmallNumDataBits; + } + + void setSmallSize(size_t Size) { + setSmallRawBits(getSmallBits() | (Size << SmallNumDataBits)); + } + + // Return the element bits. + uintptr_t getSmallBits() const { + return getSmallRawBits() & ~(~uintptr_t(0) << SmallNumDataBits); + } + + void setSmallBits(uintptr_t NewBits) { + setSmallRawBits((getSmallRawBits() & (~uintptr_t(0) << SmallNumDataBits)) | + (NewBits & ~(~uintptr_t(0) << getSmallSize()))); + } + +public: + /// SmallBitVector default ctor - Creates an empty bitvector. + SmallBitVector() : X(0, 1) {} + + /// SmallBitVector ctor - Creates a bitvector of specified number of bits. All + /// bits are initialized to the specified value. + explicit SmallBitVector(unsigned s, bool t = false) : X(0, 1) { + if (s <= SmallNumRawBits) + switchToSmall(t ? ~uintptr_t(0) : 0, s); + else + switchToLarge(new BitVector(s, t)); + } + + /// SmallBitVector copy ctor. + SmallBitVector(const SmallBitVector &RHS) { + if (RHS.isSmall()) + X = RHS.X; + else + switchToLarge(new BitVector(*RHS.X.getPointer())); + } + + ~SmallBitVector() { + if (!isSmall()) + delete X.getPointer(); + } + + /// empty - Tests whether there are no bits in this bitvector. + bool empty() const { + return isSmall() ? getSmallSize() == 0 : X.getPointer()->empty(); + } + + /// size - Returns the number of bits in this bitvector. + size_t size() const { + return isSmall() ? getSmallSize() : X.getPointer()->size(); + } + + /// count - Returns the number of bits which are set. + unsigned count() const { + if (isSmall()) { + uintptr_t Bits = getSmallBits(); + if (sizeof(uintptr_t) * CHAR_BIT == 32) + return CountPopulation_32(Bits); + if (sizeof(uintptr_t) * CHAR_BIT == 64) + return CountPopulation_64(Bits); + assert(0 && "Unsupported!"); + } + return X.getPointer()->count(); + } + + /// any - Returns true if any bit is set. + bool any() const { + if (isSmall()) + return getSmallBits() != 0; + return X.getPointer()->any(); + } + + /// none - Returns true if none of the bits are set. + bool none() const { + if (isSmall()) + return getSmallBits() == 0; + return X.getPointer()->none(); + } + + /// find_first - Returns the index of the first set bit, -1 if none + /// of the bits are set. + int find_first() const { + if (isSmall()) { + uintptr_t Bits = getSmallBits(); + if (sizeof(uintptr_t) * CHAR_BIT == 32) + return CountTrailingZeros_32(Bits); + if (sizeof(uintptr_t) * CHAR_BIT == 64) + return CountTrailingZeros_64(Bits); + assert(0 && "Unsupported!"); + } + return X.getPointer()->find_first(); + } + + /// find_next - Returns the index of the next set bit following the + /// "Prev" bit. Returns -1 if the next set bit is not found. + int find_next(unsigned Prev) const { + if (isSmall()) { + uintptr_t Bits = getSmallBits(); + // Mask off previous bits. + Bits &= ~uintptr_t(0) << Prev; + if (sizeof(uintptr_t) * CHAR_BIT == 32) + return CountTrailingZeros_32(Bits); + if (sizeof(uintptr_t) * CHAR_BIT == 64) + return CountTrailingZeros_64(Bits); + assert(0 && "Unsupported!"); + } + return X.getPointer()->find_next(Prev); + } + + /// clear - Clear all bits. + void clear() { + if (!isSmall()) + delete X.getPointer(); + switchToSmall(0, 0); + } + + /// resize - Grow or shrink the bitvector. + void resize(unsigned N, bool t = false) { + if (!isSmall()) { + X.getPointer()->resize(N, t); + } else if (getSmallSize() >= N) { + setSmallSize(N); + setSmallBits(getSmallBits()); + } else { + BitVector *BV = new BitVector(N, t); + uintptr_t OldBits = getSmallBits(); + for (size_t i = 0, e = getSmallSize(); i != e; ++i) + (*BV)[i] = (OldBits >> i) & 1; + switchToLarge(BV); + } + } + + void reserve(unsigned N) { + if (isSmall()) { + if (N > SmallNumDataBits) { + uintptr_t OldBits = getSmallRawBits(); + size_t SmallSize = getSmallSize(); + BitVector *BV = new BitVector(SmallSize); + for (size_t i = 0; i < SmallSize; ++i) + if ((OldBits >> i) & 1) + BV->set(i); + BV->reserve(N); + switchToLarge(BV); + } + } else { + X.getPointer()->reserve(N); + } + } + + // Set, reset, flip + SmallBitVector &set() { + if (isSmall()) + setSmallBits(~uintptr_t(0)); + else + X.getPointer()->set(); + return *this; + } + + SmallBitVector &set(unsigned Idx) { + if (isSmall()) + setSmallBits(getSmallBits() | (uintptr_t(1) << Idx)); + else + X.getPointer()->set(Idx); + return *this; + } + + SmallBitVector &reset() { + if (isSmall()) + setSmallBits(0); + else + X.getPointer()->reset(); + return *this; + } + + SmallBitVector &reset(unsigned Idx) { + if (isSmall()) + setSmallBits(getSmallBits() & ~(uintptr_t(1) << Idx)); + else + X.getPointer()->reset(Idx); + return *this; + } + + SmallBitVector &flip() { + if (isSmall()) + setSmallBits(~getSmallBits()); + else + X.getPointer()->flip(); + return *this; + } + + SmallBitVector &flip(unsigned Idx) { + if (isSmall()) + setSmallBits(getSmallBits() ^ (uintptr_t(1) << Idx)); + else + X.getPointer()->flip(Idx); + return *this; + } + + // No argument flip. + SmallBitVector operator~() const { + return SmallBitVector(*this).flip(); + } + + // Indexing. + // TODO: Add an index operator which returns a "reference" (proxy class). + bool operator[](unsigned Idx) const { + assert(Idx < size() && "Out-of-bounds Bit access."); + if (isSmall()) + return ((getSmallBits() >> Idx) & 1) != 0; + return X.getPointer()->operator[](Idx); + } + + bool test(unsigned Idx) const { + return (*this)[Idx]; + } + + // Comparison operators. + bool operator==(const SmallBitVector &RHS) const { + if (size() != RHS.size()) + return false; + if (isSmall()) + return getSmallBits() == RHS.getSmallBits(); + else + return *X.getPointer() == *RHS.X.getPointer(); + } + + bool operator!=(const SmallBitVector &RHS) const { + return !(*this == RHS); + } + + // Intersection, union, disjoint union. + BitVector &operator&=(const SmallBitVector &RHS); // TODO: implement + + BitVector &operator|=(const SmallBitVector &RHS); // TODO: implement + + BitVector &operator^=(const SmallBitVector &RHS); // TODO: implement + + // Assignment operator. + const SmallBitVector &operator=(const SmallBitVector &RHS) { + if (isSmall()) { + if (RHS.isSmall()) + X = RHS.X; + else + switchToLarge(new BitVector(*RHS.X.getPointer())); + } else { + if (!RHS.isSmall()) + *X.getPointer() = *RHS.X.getPointer(); + else { + delete X.getPointer(); + X = RHS.X; + } + } + return *this; + } + + void swap(SmallBitVector &RHS) { + std::swap(X, RHS.X); + } +}; + +inline SmallBitVector +operator&(const SmallBitVector &LHS, const SmallBitVector &RHS) { + SmallBitVector Result(LHS); + Result &= RHS; + return Result; +} + +inline SmallBitVector +operator|(const SmallBitVector &LHS, const SmallBitVector &RHS) { + SmallBitVector Result(LHS); + Result |= RHS; + return Result; +} + +inline SmallBitVector +operator^(const SmallBitVector &LHS, const SmallBitVector &RHS) { + SmallBitVector Result(LHS); + Result ^= RHS; + return Result; +} + +} // End llvm namespace + +namespace std { + /// Implement std::swap in terms of BitVector swap. + inline void + swap(llvm::SmallBitVector &LHS, llvm::SmallBitVector &RHS) { + LHS.swap(RHS); + } +} + +#endif diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h index 85936c0..1ea546f 100644 --- a/include/llvm/ADT/StringExtras.h +++ b/include/llvm/ADT/StringExtras.h @@ -23,6 +23,7 @@ #include <vector> namespace llvm { +template<typename T> class SmallVectorImpl; /// hexdigit - Return the (uppercase) hexadecimal character for the /// given number \arg X (which should be less than 16). @@ -136,86 +137,25 @@ static inline std::string UppercaseString(const std::string &S) { return result; } -/// StringsEqualNoCase - Return true if the two strings are equal, ignoring -/// case. -static inline bool StringsEqualNoCase(const std::string &LHS, - const std::string &RHS) { - if (LHS.size() != RHS.size()) return false; - for (unsigned i = 0, e = static_cast<unsigned>(LHS.size()); i != e; ++i) - if (tolower(LHS[i]) != tolower(RHS[i])) return false; - return true; -} - -/// StringsEqualNoCase - Return true if the two strings are equal, ignoring -/// case. -static inline bool StringsEqualNoCase(const std::string &LHS, - const char *RHS) { - for (unsigned i = 0, e = static_cast<unsigned>(LHS.size()); i != e; ++i) { - if (RHS[i] == 0) return false; // RHS too short. - if (tolower(LHS[i]) != tolower(RHS[i])) return false; - } - return RHS[LHS.size()] == 0; // Not too long? -} - -/// StringsEqualNoCase - Return true if the two null-terminated C strings are -/// equal, ignoring - -static inline bool StringsEqualNoCase(const char *LHS, const char *RHS, - unsigned len) { - - for (unsigned i = 0; i < len; ++i) { - if (tolower(LHS[i]) != tolower(RHS[i])) - return false; - - // If RHS[i] == 0 then LHS[i] == 0 or otherwise we would have returned - // at the previous branch as tolower('\0') == '\0'. - if (RHS[i] == 0) - return true; - } - - return true; -} - -/// CStrInCStrNoCase - Portable version of strcasestr. Locates the first -/// occurance of c-string 's2' in string 's1', ignoring case. Returns -/// NULL if 's2' cannot be found. -static inline const char* CStrInCStrNoCase(const char *s1, const char *s2) { - - // Are either strings NULL or empty? - if (!s1 || !s2 || s1[0] == '\0' || s2[0] == '\0') - return 0; - - if (s1 == s2) - return s1; - - const char *I1=s1, *I2=s2; - - while (*I1 != '\0' && *I2 != '\0' ) - if (tolower(*I1) != tolower(*I2)) { // No match. Start over. - ++s1; I1 = s1; I2 = s2; - } - else { // Character match. Advance to the next character. - ++I1; ++I2; - } - - // If we exhausted all of the characters in 's2', then 's2' appears in 's1'. - return *I2 == '\0' ? s1 : 0; -} +/// StrInStrNoCase - Portable version of strcasestr. Locates the first +/// occurrence of string 's1' in string 's2', ignoring case. Returns +/// the offset of s2 in s1 or npos if s2 cannot be found. +StringRef::size_type StrInStrNoCase(StringRef s1, StringRef s2); /// getToken - This function extracts one token from source, ignoring any /// leading characters that appear in the Delimiters string, and ending the /// token at any of the characters that appear in the Delimiters string. If /// there are no tokens in the source string, an empty string is returned. -/// The Source source string is updated in place to remove the returned string -/// and any delimiter prefix from it. -std::string getToken(std::string &Source, - const char *Delimiters = " \t\n\v\f\r"); +/// The function returns a pair containing the extracted token and the +/// remaining tail string. +std::pair<StringRef, StringRef> getToken(StringRef Source, + StringRef Delimiters = " \t\n\v\f\r"); /// SplitString - Split up the specified string according to the specified /// delimiters, appending the result fragments to the output list. -void SplitString(const std::string &Source, - std::vector<std::string> &OutFragments, - const char *Delimiters = " \t\n\v\f\r"); +void SplitString(StringRef Source, + SmallVectorImpl<StringRef> &OutFragments, + StringRef Delimiters = " \t\n\v\f\r"); /// HashString - Hash funtion for strings. /// diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index 1c73836..3064af3 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -29,6 +29,7 @@ namespace llvm { class StringRef { public: typedef const char *iterator; + typedef const char *const_iterator; static const size_t npos = ~size_t(0); typedef size_t size_type; @@ -42,15 +43,8 @@ namespace llvm { // Workaround PR5482: nearly all gcc 4.x miscompile StringRef and std::min() // Changing the arg of min to be an integer, instead of a reference to an // integer works around this bug. - size_t min(size_t a, size_t b) const - { - return a < b ? a : b; - } - - size_t max(size_t a, size_t b) const - { - return a > b ? a : b; - } + size_t min(size_t a, size_t b) const { return a < b ? a : b; } + size_t max(size_t a, size_t b) const { return a > b ? a : b; } public: /// @name Constructors @@ -191,7 +185,7 @@ namespace llvm { /// find - Search for the first character \arg C in the string. /// - /// \return - The index of the first occurence of \arg C, or npos if not + /// \return - The index of the first occurrence of \arg C, or npos if not /// found. size_t find(char C, size_t From = 0) const { for (size_t i = min(From, Length), e = Length; i != e; ++i) @@ -202,13 +196,13 @@ namespace llvm { /// find - Search for the first string \arg Str in the string. /// - /// \return - The index of the first occurence of \arg Str, or npos if not + /// \return - The index of the first occurrence of \arg Str, or npos if not /// found. size_t find(StringRef Str, size_t From = 0) const; /// rfind - Search for the last character \arg C in the string. /// - /// \return - The index of the last occurence of \arg C, or npos if not + /// \return - The index of the last occurrence of \arg C, or npos if not /// found. size_t rfind(char C, size_t From = npos) const { From = min(From, Length); @@ -223,7 +217,7 @@ namespace llvm { /// rfind - Search for the last string \arg Str in the string. /// - /// \return - The index of the last occurence of \arg Str, or npos if not + /// \return - The index of the last occurrence of \arg Str, or npos if not /// found. size_t rfind(StringRef Str) const; @@ -313,7 +307,7 @@ namespace llvm { return StringRef(Data + Start, End - Start); } - /// split - Split into two substrings around the first occurence of a + /// split - Split into two substrings around the first occurrence of a /// separator character. /// /// If \arg Separator is in the string, then the result is a pair (LHS, RHS) @@ -330,7 +324,7 @@ namespace llvm { return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); } - /// split - Split into two substrings around the first occurence of a + /// split - Split into two substrings around the first occurrence of a /// separator string. /// /// If \arg Separator is in the string, then the result is a pair (LHS, RHS) @@ -347,7 +341,7 @@ namespace llvm { return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); } - /// split - Split into substrings around the occurences of a separator + /// split - Split into substrings around the occurrences of a separator /// string. /// /// Each substring is stored in \arg A. If \arg MaxSplit is >= 0, at most @@ -366,7 +360,7 @@ namespace llvm { StringRef Separator, int MaxSplit = -1, bool KeepEmpty = true) const; - /// rsplit - Split into two substrings around the last occurence of a + /// rsplit - Split into two substrings around the last occurrence of a /// separator character. /// /// If \arg Separator is in the string, then the result is a pair (LHS, RHS) diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index ca0be53..97e9df4 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -329,6 +329,22 @@ namespace llvm { bool isTriviallyEmpty() const { return isNullary(); } + + /// isSingleStringRef - Return true if this twine can be dynamically + /// accessed as a single StringRef value with getSingleStringRef(). + bool isSingleStringRef() const { + if (getRHSKind() != EmptyKind) return false; + + switch (getLHSKind()) { + case EmptyKind: + case CStringKind: + case StdStringKind: + case StringRefKind: + return true; + default: + return false; + } + } /// @} /// @name String Operations @@ -347,6 +363,24 @@ namespace llvm { /// SmallVector. void toVector(SmallVectorImpl<char> &Out) const; + /// getSingleStringRef - This returns the twine as a single StringRef. This + /// method is only valid if isSingleStringRef() is true. + StringRef getSingleStringRef() const { + assert(isSingleStringRef() &&"This cannot be had as a single stringref!"); + switch (getLHSKind()) { + default: assert(0 && "Out of sync with isSingleStringRef"); + case EmptyKind: return StringRef(); + case CStringKind: return StringRef((const char*)LHS); + case StdStringKind: return StringRef(*(const std::string*)LHS); + case StringRefKind: return *(const StringRef*)LHS; + } + } + + /// toStringRef - This returns the twine as a single StringRef if it can be + /// represented as such. Otherwise the twine is written into the given + /// SmallVector and a StringRef to the SmallVector's data is returned. + StringRef toStringRef(SmallVectorImpl<char> &Out) const; + /// print - Write the concatenated string represented by this twine to the /// stream \arg OS. void print(raw_ostream &OS) const; |