diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
commit | d8e91e46262bc44006913e6796843909f1ac7bcd (patch) | |
tree | 7d0c143d9b38190e0fa0180805389da22cd834c5 /include/llvm/ADT | |
parent | b7eb8e35e481a74962664b63dfb09483b200209a (diff) | |
download | src-d8e91e46262bc44006913e6796843909f1ac7bcd.tar.gz src-d8e91e46262bc44006913e6796843909f1ac7bcd.zip |
Vendor import of llvm trunk r351319 (just before the release_80 branchvendor/llvm/llvm-trunk-r351319
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=343171
svn path=/vendor/llvm/llvm-trunk-r351319/; revision=343172; tag=vendor/llvm/llvm-trunk-r351319
Diffstat (limited to 'include/llvm/ADT')
-rw-r--r-- | include/llvm/ADT/APFloat.h | 36 | ||||
-rw-r--r-- | include/llvm/ADT/APInt.h | 64 | ||||
-rw-r--r-- | include/llvm/ADT/Any.h | 10 | ||||
-rw-r--r-- | include/llvm/ADT/BitVector.h | 17 | ||||
-rw-r--r-- | include/llvm/ADT/DenseMap.h | 81 | ||||
-rw-r--r-- | include/llvm/ADT/DenseSet.h | 35 | ||||
-rw-r--r-- | include/llvm/ADT/GraphTraits.h | 7 | ||||
-rw-r--r-- | include/llvm/ADT/Hashing.h | 15 | ||||
-rw-r--r-- | include/llvm/ADT/ImmutableList.h | 36 | ||||
-rw-r--r-- | include/llvm/ADT/IntervalMap.h | 24 | ||||
-rw-r--r-- | include/llvm/ADT/Optional.h | 22 | ||||
-rw-r--r-- | include/llvm/ADT/PointerIntPair.h | 2 | ||||
-rw-r--r-- | include/llvm/ADT/PointerSumType.h | 128 | ||||
-rw-r--r-- | include/llvm/ADT/PostOrderIterator.h | 3 | ||||
-rw-r--r-- | include/llvm/ADT/STLExtras.h | 358 | ||||
-rw-r--r-- | include/llvm/ADT/SmallBitVector.h | 59 | ||||
-rw-r--r-- | include/llvm/ADT/SmallVector.h | 10 | ||||
-rw-r--r-- | include/llvm/ADT/SparseBitVector.h | 75 | ||||
-rw-r--r-- | include/llvm/ADT/StringExtras.h | 11 | ||||
-rw-r--r-- | include/llvm/ADT/Triple.h | 32 | ||||
-rw-r--r-- | include/llvm/ADT/bit.h | 59 | ||||
-rw-r--r-- | include/llvm/ADT/iterator.h | 38 |
22 files changed, 929 insertions, 193 deletions
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 5c59af4c04ba..c6fa5ad674f6 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -870,13 +870,13 @@ public: /// Factory for NaN values. /// /// \param Negative - True iff the NaN generated should be negative. - /// \param type - The unspecified fill bits for creating the NaN, 0 by + /// \param payload - The unspecified fill bits for creating the NaN, 0 by /// default. The value is truncated as necessary. static APFloat getNaN(const fltSemantics &Sem, bool Negative = false, - unsigned type = 0) { - if (type) { - APInt fill(64, type); - return getQNaN(Sem, Negative, &fill); + uint64_t payload = 0) { + if (payload) { + APInt intPayload(64, payload); + return getQNaN(Sem, Negative, &intPayload); } else { return getQNaN(Sem, Negative, nullptr); } @@ -1243,6 +1243,32 @@ inline APFloat maxnum(const APFloat &A, const APFloat &B) { return (A.compare(B) == APFloat::cmpLessThan) ? B : A; } +/// Implements IEEE 754-2018 minimum semantics. Returns the smaller of 2 +/// arguments, propagating NaNs and treating -0 as less than +0. +LLVM_READONLY +inline APFloat minimum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return A; + if (B.isNaN()) + return B; + if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative())) + return A.isNegative() ? A : B; + return (B.compare(A) == APFloat::cmpLessThan) ? B : A; +} + +/// Implements IEEE 754-2018 maximum semantics. Returns the larger of 2 +/// arguments, propagating NaNs and treating -0 as less than +0. +LLVM_READONLY +inline APFloat maximum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return A; + if (B.isNaN()) + return B; + if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative())) + return A.isNegative() ? B : A; + return (A.compare(B) == APFloat::cmpLessThan) ? B : A; +} + } // namespace llvm #undef APFLOAT_DISPATCH_ON_SEMANTICS diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 6bf6b22fb010..6e106ff8bf5d 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -31,6 +31,7 @@ class raw_ostream; template <typename T> class SmallVectorImpl; template <typename T> class ArrayRef; +template <typename T> class Optional; class APInt; @@ -84,7 +85,7 @@ public: UP, }; - static const WordType WORD_MAX = ~WordType(0); + static const WordType WORDTYPE_MAX = ~WordType(0); private: /// This union is used to store the integer value. When the @@ -149,7 +150,7 @@ private: unsigned WordBits = ((BitWidth-1) % APINT_BITS_PER_WORD) + 1; // Mask out the high bits. - uint64_t mask = WORD_MAX >> (APINT_BITS_PER_WORD - WordBits); + uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - WordBits); if (isSingleWord()) U.VAL &= mask; else @@ -394,7 +395,7 @@ public: /// This checks to see if the value has all bits of the APInt are set or not. bool isAllOnesValue() const { if (isSingleWord()) - return U.VAL == WORD_MAX >> (APINT_BITS_PER_WORD - BitWidth); + return U.VAL == WORDTYPE_MAX >> (APINT_BITS_PER_WORD - BitWidth); return countTrailingOnesSlowCase() == BitWidth; } @@ -495,7 +496,7 @@ public: assert(numBits != 0 && "numBits must be non-zero"); assert(numBits <= BitWidth && "numBits out of range"); if (isSingleWord()) - return U.VAL == (WORD_MAX >> (APINT_BITS_PER_WORD - numBits)); + return U.VAL == (WORDTYPE_MAX >> (APINT_BITS_PER_WORD - numBits)); unsigned Ones = countTrailingOnesSlowCase(); return (numBits == Ones) && ((Ones + countLeadingZerosSlowCase()) == BitWidth); @@ -559,7 +560,7 @@ public: /// /// \returns the all-ones value for an APInt of the specified bit-width. static APInt getAllOnesValue(unsigned numBits) { - return APInt(numBits, WORD_MAX, true); + return APInt(numBits, WORDTYPE_MAX, true); } /// Get the '0' value. @@ -1104,6 +1105,12 @@ public: APInt sshl_ov(const APInt &Amt, bool &Overflow) const; APInt ushl_ov(const APInt &Amt, bool &Overflow) const; + // Operations that saturate + APInt sadd_sat(const APInt &RHS) const; + APInt uadd_sat(const APInt &RHS) const; + APInt ssub_sat(const APInt &RHS) const; + APInt usub_sat(const APInt &RHS) const; + /// Array-indexing support. /// /// \returns the bit value at bitPosition @@ -1382,7 +1389,7 @@ public: /// Set every bit to 1. void setAllBits() { if (isSingleWord()) - U.VAL = WORD_MAX; + U.VAL = WORDTYPE_MAX; else // Set all the bits in all the words. memset(U.pVal, -1, getNumWords() * APINT_WORD_SIZE); @@ -1394,7 +1401,7 @@ public: /// /// Set the given bit to 1 whose position is given as "bitPosition". void setBit(unsigned BitPosition) { - assert(BitPosition <= BitWidth && "BitPosition out of range"); + assert(BitPosition < BitWidth && "BitPosition out of range"); WordType Mask = maskBit(BitPosition); if (isSingleWord()) U.VAL |= Mask; @@ -1415,7 +1422,7 @@ public: if (loBit == hiBit) return; if (loBit < APINT_BITS_PER_WORD && hiBit <= APINT_BITS_PER_WORD) { - uint64_t mask = WORD_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit)); + uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit)); mask <<= loBit; if (isSingleWord()) U.VAL |= mask; @@ -1453,7 +1460,7 @@ public: /// /// Set the given bit to 0 whose position is given as "bitPosition". void clearBit(unsigned BitPosition) { - assert(BitPosition <= BitWidth && "BitPosition out of range"); + assert(BitPosition < BitWidth && "BitPosition out of range"); WordType Mask = ~maskBit(BitPosition); if (isSingleWord()) U.VAL &= Mask; @@ -1469,7 +1476,7 @@ public: /// Toggle every bit to its opposite value. void flipAllBits() { if (isSingleWord()) { - U.VAL ^= WORD_MAX; + U.VAL ^= WORDTYPE_MAX; clearUnusedBits(); } else { flipAllBitsSlowCase(); @@ -1758,7 +1765,7 @@ public: /// referencing 2 in a space where 2 does no exist. unsigned nearestLogBase2() const { // Special case when we have a bitwidth of 1. If VAL is 1, then we - // get 0. If VAL is 0, we get WORD_MAX which gets truncated to + // get 0. If VAL is 0, we get WORDTYPE_MAX which gets truncated to // UINT32_MAX. if (BitWidth == 1) return U.VAL - 1; @@ -2166,6 +2173,41 @@ APInt RoundingUDiv(const APInt &A, const APInt &B, APInt::Rounding RM); /// Return A sign-divided by B, rounded by the given rounding mode. APInt RoundingSDiv(const APInt &A, const APInt &B, APInt::Rounding RM); +/// Let q(n) = An^2 + Bn + C, and BW = bit width of the value range +/// (e.g. 32 for i32). +/// This function finds the smallest number n, such that +/// (a) n >= 0 and q(n) = 0, or +/// (b) n >= 1 and q(n-1) and q(n), when evaluated in the set of all +/// integers, belong to two different intervals [Rk, Rk+R), +/// where R = 2^BW, and k is an integer. +/// The idea here is to find when q(n) "overflows" 2^BW, while at the +/// same time "allowing" subtraction. In unsigned modulo arithmetic a +/// subtraction (treated as addition of negated numbers) would always +/// count as an overflow, but here we want to allow values to decrease +/// and increase as long as they are within the same interval. +/// Specifically, adding of two negative numbers should not cause an +/// overflow (as long as the magnitude does not exceed the bith width). +/// On the other hand, given a positive number, adding a negative +/// number to it can give a negative result, which would cause the +/// value to go from [-2^BW, 0) to [0, 2^BW). In that sense, zero is +/// treated as a special case of an overflow. +/// +/// This function returns None if after finding k that minimizes the +/// positive solution to q(n) = kR, both solutions are contained between +/// two consecutive integers. +/// +/// There are cases where q(n) > T, and q(n+1) < T (assuming evaluation +/// in arithmetic modulo 2^BW, and treating the values as signed) by the +/// virtue of *signed* overflow. This function will *not* find such an n, +/// however it may find a value of n satisfying the inequalities due to +/// an *unsigned* overflow (if the values are treated as unsigned). +/// To find a solution for a signed overflow, treat it as a problem of +/// finding an unsigned overflow with a range with of BW-1. +/// +/// The returned value may have a different bit width from the input +/// coefficients. +Optional<APInt> SolveQuadraticEquationWrap(APInt A, APInt B, APInt C, + unsigned RangeWidth); } // End of APIntOps namespace // See friend declaration above. This additional declaration is required in diff --git a/include/llvm/ADT/Any.h b/include/llvm/ADT/Any.h index c64c39987542..7faa4c963d3d 100644 --- a/include/llvm/ADT/Any.h +++ b/include/llvm/ADT/Any.h @@ -65,6 +65,16 @@ public: typename std::enable_if< llvm::conjunction< llvm::negation<std::is_same<typename std::decay<T>::type, Any>>, + // We also disable this overload when an `Any` object can be + // converted to the parameter type because in that case, this + // constructor may combine with that conversion during overload + // resolution for determining copy constructibility, and then + // when we try to determine copy constructibility below we may + // infinitely recurse. This is being evaluated by the standards + // committee as a potential DR in `std::any` as well, but we're + // going ahead and adopting it to work-around usage of `Any` with + // types that need to be implicitly convertible from an `Any`. + llvm::negation<std::is_convertible<Any, typename std::decay<T>::type>>, std::is_copy_constructible<typename std::decay<T>::type>>::value, int>::type = 0> Any(T &&Value) { diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 438c7d84c581..9ab1da7c6913 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -503,6 +503,23 @@ public: return (*this)[Idx]; } + // Push single bit to end of vector. + void push_back(bool Val) { + unsigned OldSize = Size; + unsigned NewSize = Size + 1; + + // Resize, which will insert zeros. + // If we already fit then the unused bits will be already zero. + if (NewSize > getBitCapacity()) + resize(NewSize, false); + else + Size = NewSize; + + // If true, set single bit. + if (Val) + set(OldSize); + } + /// Test if any common bits are set. bool anyCommon(const BitVector &RHS) const { unsigned ThisWords = NumBitWords(size()); diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index ba60b7972a8f..1f50502fff92 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -25,6 +25,7 @@ #include <cassert> #include <cstddef> #include <cstring> +#include <initializer_list> #include <iterator> #include <new> #include <type_traits> @@ -38,6 +39,34 @@ namespace detail { // implementation without requiring two members. template <typename KeyT, typename ValueT> struct DenseMapPair : public std::pair<KeyT, ValueT> { + + // FIXME: Switch to inheriting constructors when we drop support for older + // clang versions. + // NOTE: This default constructor is declared with '{}' rather than + // '= default' to work around a separate bug in clang-3.8. This can + // also go when we switch to inheriting constructors. + DenseMapPair() {} + + DenseMapPair(const KeyT &Key, const ValueT &Value) + : std::pair<KeyT, ValueT>(Key, Value) {} + + DenseMapPair(KeyT &&Key, ValueT &&Value) + : std::pair<KeyT, ValueT>(std::move(Key), std::move(Value)) {} + + template <typename AltKeyT, typename AltValueT> + DenseMapPair(AltKeyT &&AltKey, AltValueT &&AltValue, + typename std::enable_if< + std::is_convertible<AltKeyT, KeyT>::value && + std::is_convertible<AltValueT, ValueT>::value>::type * = 0) + : std::pair<KeyT, ValueT>(std::forward<AltKeyT>(AltKey), + std::forward<AltValueT>(AltValue)) {} + + template <typename AltPairT> + DenseMapPair(AltPairT &&AltPair, + typename std::enable_if<std::is_convertible< + AltPairT, std::pair<KeyT, ValueT>>::value>::type * = 0) + : std::pair<KeyT, ValueT>(std::forward<AltPairT>(AltPair)) {} + KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; } const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; } ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; } @@ -46,9 +75,10 @@ struct DenseMapPair : public std::pair<KeyT, ValueT> { } // end namespace detail -template < - typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo<KeyT>, - typename Bucket = detail::DenseMapPair<KeyT, ValueT>, bool IsConst = false> +template <typename KeyT, typename ValueT, + typename KeyInfoT = DenseMapInfo<KeyT>, + typename Bucket = llvm::detail::DenseMapPair<KeyT, ValueT>, + bool IsConst = false> class DenseMapIterator; template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, @@ -393,7 +423,7 @@ protected: setNumTombstones(other.getNumTombstones()); if (isPodLike<KeyT>::value && isPodLike<ValueT>::value) - memcpy(getBuckets(), other.getBuckets(), + memcpy(reinterpret_cast<void *>(getBuckets()), other.getBuckets(), getNumBuckets() * sizeof(BucketT)); else for (size_t i = 0; i < getNumBuckets(); ++i) { @@ -639,9 +669,43 @@ public: } }; +/// Equality comparison for DenseMap. +/// +/// Iterates over elements of LHS confirming that each (key, value) pair in LHS +/// is also in RHS, and that no additional pairs are in RHS. +/// Equivalent to N calls to RHS.find and N value comparisons. Amortized +/// complexity is linear, worst case is O(N^2) (if every hash collides). +template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, + typename BucketT> +bool operator==( + const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS, + const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) { + if (LHS.size() != RHS.size()) + return false; + + for (auto &KV : LHS) { + auto I = RHS.find(KV.first); + if (I == RHS.end() || I->second != KV.second) + return false; + } + + return true; +} + +/// Inequality comparison for DenseMap. +/// +/// Equivalent to !(LHS == RHS). See operator== for performance notes. +template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, + typename BucketT> +bool operator!=( + const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS, + const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) { + return !(LHS == RHS); +} + template <typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo<KeyT>, - typename BucketT = detail::DenseMapPair<KeyT, ValueT>> + typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>> class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>, KeyT, ValueT, KeyInfoT, BucketT> { friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>; @@ -676,6 +740,11 @@ public: this->insert(I, E); } + DenseMap(std::initializer_list<typename BaseT::value_type> Vals) { + init(Vals.size()); + this->insert(Vals.begin(), Vals.end()); + } + ~DenseMap() { this->destroyAll(); operator delete(Buckets); @@ -798,7 +867,7 @@ private: template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4, typename KeyInfoT = DenseMapInfo<KeyT>, - typename BucketT = detail::DenseMapPair<KeyT, ValueT>> + typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>> class SmallDenseMap : public DenseMapBase< SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT, diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h index b495e25dd5e5..e85a38587e41 100644 --- a/include/llvm/ADT/DenseSet.h +++ b/include/llvm/ADT/DenseSet.h @@ -16,6 +16,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/type_traits.h" #include <algorithm> #include <cstddef> @@ -67,7 +68,7 @@ public: explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {} DenseSetImpl(std::initializer_list<ValueT> Elems) - : DenseSetImpl(Elems.size()) { + : DenseSetImpl(PowerOf2Ceil(Elems.size())) { insert(Elems.begin(), Elems.end()); } @@ -136,8 +137,8 @@ public: public: using difference_type = typename MapTy::const_iterator::difference_type; using value_type = ValueT; - using pointer = value_type *; - using reference = value_type &; + using pointer = const value_type *; + using reference = const value_type &; using iterator_category = std::forward_iterator_tag; ConstIterator() = default; @@ -214,6 +215,34 @@ public: } }; +/// Equality comparison for DenseSet. +/// +/// Iterates over elements of LHS confirming that each element is also a member +/// of RHS, and that RHS contains no additional values. +/// Equivalent to N calls to RHS.count. Amortized complexity is linear, worst +/// case is O(N^2) (if every hash collides). +template <typename ValueT, typename MapTy, typename ValueInfoT> +bool operator==(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS, + const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) { + if (LHS.size() != RHS.size()) + return false; + + for (auto &E : LHS) + if (!RHS.count(E)) + return false; + + return true; +} + +/// Inequality comparison for DenseSet. +/// +/// Equivalent to !(LHS == RHS). See operator== for performance notes. +template <typename ValueT, typename MapTy, typename ValueInfoT> +bool operator!=(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS, + const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) { + return !(LHS == RHS); +} + } // end namespace detail /// Implements a dense probed hash-table based set. diff --git a/include/llvm/ADT/GraphTraits.h b/include/llvm/ADT/GraphTraits.h index 27c647f4bbbd..d39b50fdc488 100644 --- a/include/llvm/ADT/GraphTraits.h +++ b/include/llvm/ADT/GraphTraits.h @@ -25,6 +25,13 @@ namespace llvm { // GraphTraits - This class should be specialized by different graph types... // which is why the default version is empty. // +// This template evolved from supporting `BasicBlock` to also later supporting +// more complex types (e.g. CFG and DomTree). +// +// GraphTraits can be used to create a view over a graph interpreting it +// differently without requiring a copy of the original graph. This could +// be achieved by carrying more data in NodeRef. See LoopBodyTraits for one +// example. template<class GraphType> struct GraphTraits { // Elements to provide: diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index 9f830baa4243..9175c545b7c9 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -133,7 +133,7 @@ hash_code hash_value(const std::basic_string<T> &arg); /// undone. This makes it thread-hostile and very hard to use outside of /// immediately on start of a simple program designed for reproducible /// behavior. -void set_fixed_execution_hash_seed(size_t fixed_value); +void set_fixed_execution_hash_seed(uint64_t fixed_value); // All of the implementation details of actually computing the various hash @@ -316,9 +316,9 @@ struct hash_state { /// This variable can be set using the \see llvm::set_fixed_execution_seed /// function. See that function for details. Do not, under any circumstances, /// set or read this variable. -extern size_t fixed_seed_override; +extern uint64_t fixed_seed_override; -inline size_t get_execution_seed() { +inline uint64_t get_execution_seed() { // FIXME: This needs to be a per-execution seed. This is just a placeholder // implementation. Switching to a per-execution seed is likely to flush out // instability bugs and so will happen as its own commit. @@ -326,8 +326,7 @@ inline size_t get_execution_seed() { // However, if there is a fixed seed override set the first time this is // called, return that instead of the per-execution seed. const uint64_t seed_prime = 0xff51afd7ed558ccdULL; - static size_t seed = fixed_seed_override ? fixed_seed_override - : (size_t)seed_prime; + static uint64_t seed = fixed_seed_override ? fixed_seed_override : seed_prime; return seed; } @@ -402,7 +401,7 @@ bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value, /// combining them, this (as an optimization) directly combines the integers. template <typename InputIteratorT> hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) { - const size_t seed = get_execution_seed(); + const uint64_t seed = get_execution_seed(); char buffer[64], *buffer_ptr = buffer; char *const buffer_end = std::end(buffer); while (first != last && store_and_advance(buffer_ptr, buffer_end, @@ -446,7 +445,7 @@ hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) { template <typename ValueT> typename std::enable_if<is_hashable_data<ValueT>::value, hash_code>::type hash_combine_range_impl(ValueT *first, ValueT *last) { - const size_t seed = get_execution_seed(); + const uint64_t seed = get_execution_seed(); const char *s_begin = reinterpret_cast<const char *>(first); const char *s_end = reinterpret_cast<const char *>(last); const size_t length = std::distance(s_begin, s_end); @@ -496,7 +495,7 @@ namespace detail { struct hash_combine_recursive_helper { char buffer[64]; hash_state state; - const size_t seed; + const uint64_t seed; public: /// Construct a recursive hash combining helper. diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h index 1f5e9813798d..0541dc2566ed 100644 --- a/include/llvm/ADT/ImmutableList.h +++ b/include/llvm/ADT/ImmutableList.h @@ -31,8 +31,9 @@ class ImmutableListImpl : public FoldingSetNode { T Head; const ImmutableListImpl* Tail; - ImmutableListImpl(const T& head, const ImmutableListImpl* tail = nullptr) - : Head(head), Tail(tail) {} + template <typename ElemT> + ImmutableListImpl(ElemT &&head, const ImmutableListImpl *tail = nullptr) + : Head(std::forward<ElemT>(head)), Tail(tail) {} public: ImmutableListImpl(const ImmutableListImpl &) = delete; @@ -66,6 +67,9 @@ public: using value_type = T; using Factory = ImmutableListFactory<T>; + static_assert(std::is_trivially_destructible<T>::value, + "T must be trivially destructible!"); + private: const ImmutableListImpl<T>* X; @@ -90,6 +94,9 @@ public: bool operator==(const iterator& I) const { return L == I.L; } bool operator!=(const iterator& I) const { return L != I.L; } const value_type& operator*() const { return L->getHead(); } + const typename std::remove_reference<value_type>::type* operator->() const { + return &L->getHead(); + } ImmutableList getList() const { return L; } }; @@ -123,14 +130,14 @@ public: bool operator==(const ImmutableList& L) const { return isEqual(L); } /// getHead - Returns the head of the list. - const T& getHead() { + const T& getHead() const { assert(!isEmpty() && "Cannot get the head of an empty list."); return X->getHead(); } /// getTail - Returns the tail of the list, which is another (possibly empty) /// ImmutableList. - ImmutableList getTail() { + ImmutableList getTail() const { return X ? X->getTail() : nullptr; } @@ -166,7 +173,8 @@ public: if (ownsAllocator()) delete &getAllocator(); } - LLVM_NODISCARD ImmutableList<T> concat(const T &Head, ImmutableList<T> Tail) { + template <typename ElemT> + LLVM_NODISCARD ImmutableList<T> concat(ElemT &&Head, ImmutableList<T> Tail) { // Profile the new list to see if it already exists in our cache. FoldingSetNodeID ID; void* InsertPos; @@ -179,7 +187,7 @@ public: // The list does not exist in our cache. Create it. BumpPtrAllocator& A = getAllocator(); L = (ListTy*) A.Allocate<ListTy>(); - new (L) ListTy(Head, TailImpl); + new (L) ListTy(std::forward<ElemT>(Head), TailImpl); // Insert the new list into the cache. Cache.InsertNode(L, InsertPos); @@ -188,16 +196,24 @@ public: return L; } - LLVM_NODISCARD ImmutableList<T> add(const T& D, ImmutableList<T> L) { - return concat(D, L); + template <typename ElemT> + LLVM_NODISCARD ImmutableList<T> add(ElemT &&Data, ImmutableList<T> L) { + return concat(std::forward<ElemT>(Data), L); + } + + template <typename ...CtorArgs> + LLVM_NODISCARD ImmutableList<T> emplace(ImmutableList<T> Tail, + CtorArgs &&...Args) { + return concat(T(std::forward<CtorArgs>(Args)...), Tail); } ImmutableList<T> getEmptyList() const { return ImmutableList<T>(nullptr); } - ImmutableList<T> create(const T& X) { - return Concat(X, getEmptyList()); + template <typename ElemT> + ImmutableList<T> create(ElemT &&Data) { + return concat(std::forward<ElemT>(Data), getEmptyList()); } }; diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h index f71366811218..2af61049e5af 100644 --- a/include/llvm/ADT/IntervalMap.h +++ b/include/llvm/ADT/IntervalMap.h @@ -101,6 +101,7 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/bit.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/RecyclingAllocator.h" @@ -963,6 +964,7 @@ public: private: // The root data is either a RootLeaf or a RootBranchData instance. + LLVM_ALIGNAS(RootLeaf) LLVM_ALIGNAS(RootBranchData) AlignedCharArrayUnion<RootLeaf, RootBranchData> data; // Tree height. @@ -977,15 +979,10 @@ private: // Allocator used for creating external nodes. Allocator &allocator; - /// dataAs - Represent data as a node type without breaking aliasing rules. + /// Represent data as a node type without breaking aliasing rules. template <typename T> T &dataAs() const { - union { - const char *d; - T *t; - } u; - u.d = data.buffer; - return *u.t; + return *bit_cast<T *>(const_cast<char *>(data.buffer)); } const RootLeaf &rootLeaf() const { @@ -1137,6 +1134,19 @@ public: I.find(x); return I; } + + /// overlaps(a, b) - Return true if the intervals in this map overlap with the + /// interval [a;b]. + bool overlaps(KeyT a, KeyT b) { + assert(Traits::nonEmpty(a, b)); + const_iterator I = find(a); + if (!I.valid()) + return false; + // [a;b] and [x;y] overlap iff x<=b and a<=y. The find() call guarantees the + // second part (y = find(a).stop()), so it is sufficient to check the first + // one. + return !Traits::stopLess(b, I.start()); + } }; /// treeSafeLookup - Return the mapped value at x or NotFound, assuming a diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 353e5d0ec9df..76937d632ae1 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -29,7 +29,7 @@ namespace llvm { namespace optional_detail { /// Storage for any type. -template <typename T, bool IsPodLike> struct OptionalStorage { +template <typename T, bool = isPodLike<T>::value> struct OptionalStorage { AlignedCharArrayUnion<T> storage; bool hasVal = false; @@ -108,28 +108,10 @@ template <typename T, bool IsPodLike> struct OptionalStorage { } }; -#if !defined(__GNUC__) || defined(__clang__) // GCC up to GCC7 miscompiles this. -/// Storage for trivially copyable types only. -template <typename T> struct OptionalStorage<T, true> { - AlignedCharArrayUnion<T> storage; - bool hasVal = false; - - OptionalStorage() = default; - - OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); } - OptionalStorage &operator=(const T &y) { - *reinterpret_cast<T *>(storage.buffer) = y; - hasVal = true; - return *this; - } - - void reset() { hasVal = false; } -}; -#endif } // namespace optional_detail template <typename T> class Optional { - optional_detail::OptionalStorage<T, isPodLike<T>::value> Storage; + optional_detail::OptionalStorage<T> Storage; public: using value_type = T; diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index 884d05155bff..6d1b53a90ad2 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -42,6 +42,8 @@ template <typename PointerTy, unsigned IntBits, typename IntType = unsigned, typename PtrTraits = PointerLikeTypeTraits<PointerTy>, typename Info = PointerIntPairInfo<PointerTy, IntBits, PtrTraits>> class PointerIntPair { + // Used by MSVC visualizer and generally helpful for debugging/visualizing. + using InfoTy = Info; intptr_t Value = 0; public: diff --git a/include/llvm/ADT/PointerSumType.h b/include/llvm/ADT/PointerSumType.h index e37957160d98..a19e45a46218 100644 --- a/include/llvm/ADT/PointerSumType.h +++ b/include/llvm/ADT/PointerSumType.h @@ -10,6 +10,7 @@ #ifndef LLVM_ADT_POINTERSUMTYPE_H #define LLVM_ADT_POINTERSUMTYPE_H +#include "llvm/ADT/bit.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include <cassert> @@ -58,56 +59,142 @@ template <typename TagT, typename... MemberTs> struct PointerSumTypeHelper; /// and may be desirable to set to a state that is particularly desirable to /// default construct. /// +/// Having a supported zero-valued tag also enables getting the address of a +/// pointer stored with that tag provided it is stored in its natural bit +/// representation. This works because in the case of a zero-valued tag, the +/// pointer's value is directly stored into this object and we can expose the +/// address of that internal storage. This is especially useful when building an +/// `ArrayRef` of a single pointer stored in a sum type. +/// /// There is no support for constructing or accessing with a dynamic tag as /// that would fundamentally violate the type safety provided by the sum type. template <typename TagT, typename... MemberTs> class PointerSumType { - uintptr_t Value = 0; - using HelperT = detail::PointerSumTypeHelper<TagT, MemberTs...>; + // We keep both the raw value and the min tag value's pointer in a union. When + // the minimum tag value is zero, this allows code below to cleanly expose the + // address of the zero-tag pointer instead of just the zero-tag pointer + // itself. This is especially useful when building `ArrayRef`s out of a single + // pointer. However, we have to carefully access the union due to the active + // member potentially changing. When we *store* a new value, we directly + // access the union to allow us to store using the obvious types. However, + // when we *read* a value, we copy the underlying storage out to avoid relying + // on one member or the other being active. + union StorageT { + // Ensure we get a null default constructed value. We don't use a member + // initializer because some compilers seem to not implement those correctly + // for a union. + StorageT() : Value(0) {} + + uintptr_t Value; + + typename HelperT::template Lookup<HelperT::MinTag>::PointerT MinTagPointer; + }; + + StorageT Storage; + public: constexpr PointerSumType() = default; + /// A typed setter to a given tagged member of the sum type. + template <TagT N> + void set(typename HelperT::template Lookup<N>::PointerT Pointer) { + void *V = HelperT::template Lookup<N>::TraitsT::getAsVoidPointer(Pointer); + assert((reinterpret_cast<uintptr_t>(V) & HelperT::TagMask) == 0 && + "Pointer is insufficiently aligned to store the discriminant!"); + Storage.Value = reinterpret_cast<uintptr_t>(V) | N; + } + /// A typed constructor for a specific tagged member of the sum type. template <TagT N> static PointerSumType create(typename HelperT::template Lookup<N>::PointerT Pointer) { PointerSumType Result; - void *V = HelperT::template Lookup<N>::TraitsT::getAsVoidPointer(Pointer); - assert((reinterpret_cast<uintptr_t>(V) & HelperT::TagMask) == 0 && - "Pointer is insufficiently aligned to store the discriminant!"); - Result.Value = reinterpret_cast<uintptr_t>(V) | N; + Result.set<N>(Pointer); return Result; } - TagT getTag() const { return static_cast<TagT>(Value & HelperT::TagMask); } + /// Clear the value to null with the min tag type. + void clear() { set<HelperT::MinTag>(nullptr); } + + TagT getTag() const { + return static_cast<TagT>(getOpaqueValue() & HelperT::TagMask); + } template <TagT N> bool is() const { return N == getTag(); } template <TagT N> typename HelperT::template Lookup<N>::PointerT get() const { - void *P = is<N>() ? getImpl() : nullptr; + void *P = is<N>() ? getVoidPtr() : nullptr; return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(P); } template <TagT N> typename HelperT::template Lookup<N>::PointerT cast() const { assert(is<N>() && "This instance has a different active member."); - return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(getImpl()); + return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer( + getVoidPtr()); + } + + /// If the tag is zero and the pointer's value isn't changed when being + /// stored, get the address of the stored value type-punned to the zero-tag's + /// pointer type. + typename HelperT::template Lookup<HelperT::MinTag>::PointerT const * + getAddrOfZeroTagPointer() const { + return const_cast<PointerSumType *>(this)->getAddrOfZeroTagPointer(); } - explicit operator bool() const { return Value & HelperT::PointerMask; } - bool operator==(const PointerSumType &R) const { return Value == R.Value; } - bool operator!=(const PointerSumType &R) const { return Value != R.Value; } - bool operator<(const PointerSumType &R) const { return Value < R.Value; } - bool operator>(const PointerSumType &R) const { return Value > R.Value; } - bool operator<=(const PointerSumType &R) const { return Value <= R.Value; } - bool operator>=(const PointerSumType &R) const { return Value >= R.Value; } + /// If the tag is zero and the pointer's value isn't changed when being + /// stored, get the address of the stored value type-punned to the zero-tag's + /// pointer type. + typename HelperT::template Lookup<HelperT::MinTag>::PointerT * + getAddrOfZeroTagPointer() { + static_assert(HelperT::MinTag == 0, "Non-zero minimum tag value!"); + assert(is<HelperT::MinTag>() && "The active tag is not zero!"); + // Store the initial value of the pointer when read out of our storage. + auto InitialPtr = get<HelperT::MinTag>(); + // Now update the active member of the union to be the actual pointer-typed + // member so that accessing it indirectly through the returned address is + // valid. + Storage.MinTagPointer = InitialPtr; + // Finally, validate that this was a no-op as expected by reading it back + // out using the same underlying-storage read as above. + assert(InitialPtr == get<HelperT::MinTag>() && + "Switching to typed storage changed the pointer returned!"); + // Now we can correctly return an address to typed storage. + return &Storage.MinTagPointer; + } + + explicit operator bool() const { + return getOpaqueValue() & HelperT::PointerMask; + } + bool operator==(const PointerSumType &R) const { + return getOpaqueValue() == R.getOpaqueValue(); + } + bool operator!=(const PointerSumType &R) const { + return getOpaqueValue() != R.getOpaqueValue(); + } + bool operator<(const PointerSumType &R) const { + return getOpaqueValue() < R.getOpaqueValue(); + } + bool operator>(const PointerSumType &R) const { + return getOpaqueValue() > R.getOpaqueValue(); + } + bool operator<=(const PointerSumType &R) const { + return getOpaqueValue() <= R.getOpaqueValue(); + } + bool operator>=(const PointerSumType &R) const { + return getOpaqueValue() >= R.getOpaqueValue(); + } - uintptr_t getOpaqueValue() const { return Value; } + uintptr_t getOpaqueValue() const { + // Read the underlying storage of the union, regardless of the active + // member. + return bit_cast<uintptr_t>(Storage); + } protected: - void *getImpl() const { - return reinterpret_cast<void *>(Value & HelperT::PointerMask); + void *getVoidPtr() const { + return reinterpret_cast<void *>(getOpaqueValue() & HelperT::PointerMask); } }; @@ -151,8 +238,9 @@ struct PointerSumTypeHelper : MemberTs... { enum { NumTagBits = Min<MemberTs::TraitsT::NumLowBitsAvailable...>::value }; // Also compute the smallest discriminant and various masks for convenience. + constexpr static TagT MinTag = + static_cast<TagT>(Min<MemberTs::Tag...>::value); enum : uint64_t { - MinTag = Min<MemberTs::Tag...>::value, PointerMask = static_cast<uint64_t>(-1) << NumTagBits, TagMask = ~PointerMask }; diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h index dc8a9b6e78b2..d77b12228cb1 100644 --- a/include/llvm/ADT/PostOrderIterator.h +++ b/include/llvm/ADT/PostOrderIterator.h @@ -296,12 +296,15 @@ class ReversePostOrderTraversal { public: using rpo_iterator = typename std::vector<NodeRef>::reverse_iterator; + using const_rpo_iterator = typename std::vector<NodeRef>::const_reverse_iterator; ReversePostOrderTraversal(GraphT G) { Initialize(GT::getEntryNode(G)); } // Because we want a reverse post order, use reverse iterators from the vector rpo_iterator begin() { return Blocks.rbegin(); } + const_rpo_iterator begin() const { return Blocks.crbegin(); } rpo_iterator end() { return Blocks.rend(); } + const_rpo_iterator end() const { return Blocks.crend(); } }; } // end namespace llvm diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index 94365dd9ced1..f66ca7c08a73 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -21,6 +21,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/Config/abi-breaking.h" #include "llvm/Support/ErrorHandling.h" #include <algorithm> #include <cassert> @@ -70,6 +71,16 @@ template <typename B1, typename... Bn> struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {}; +template <typename T> struct make_const_ptr { + using type = + typename std::add_pointer<typename std::add_const<T>::type>::type; +}; + +template <typename T> struct make_const_ref { + using type = typename std::add_lvalue_reference< + typename std::add_const<T>::type>::type; +}; + //===----------------------------------------------------------------------===// // Extra additions to <functional> //===----------------------------------------------------------------------===// @@ -194,6 +205,12 @@ void adl_swap(T &&lhs, T &&rhs) noexcept( adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs)); } +/// Test whether \p RangeOrContainer is empty. Similar to C++17 std::empty. +template <typename T> +constexpr bool empty(const T &RangeOrContainer) { + return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer); +} + // mapped_iterator - This is a simple iterator adapter that causes a function to // be applied whenever operator* is invoked on the iterator. @@ -418,9 +435,94 @@ make_filter_range(RangeT &&Range, PredicateT Pred) { std::end(std::forward<RangeT>(Range)), Pred)); } -// forward declarations required by zip_shortest/zip_first +/// A pseudo-iterator adaptor that is designed to implement "early increment" +/// style loops. +/// +/// This is *not a normal iterator* and should almost never be used directly. It +/// is intended primarily to be used with range based for loops and some range +/// algorithms. +/// +/// The iterator isn't quite an `OutputIterator` or an `InputIterator` but +/// somewhere between them. The constraints of these iterators are: +/// +/// - On construction or after being incremented, it is comparable and +/// dereferencable. It is *not* incrementable. +/// - After being dereferenced, it is neither comparable nor dereferencable, it +/// is only incrementable. +/// +/// This means you can only dereference the iterator once, and you can only +/// increment it once between dereferences. +template <typename WrappedIteratorT> +class early_inc_iterator_impl + : public iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>, + WrappedIteratorT, std::input_iterator_tag> { + using BaseT = + iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>, + WrappedIteratorT, std::input_iterator_tag>; + + using PointerT = typename std::iterator_traits<WrappedIteratorT>::pointer; + +protected: +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + bool IsEarlyIncremented = false; +#endif + +public: + early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {} + + using BaseT::operator*; + typename BaseT::reference operator*() { +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + assert(!IsEarlyIncremented && "Cannot dereference twice!"); + IsEarlyIncremented = true; +#endif + return *(this->I)++; + } + + using BaseT::operator++; + early_inc_iterator_impl &operator++() { +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + assert(IsEarlyIncremented && "Cannot increment before dereferencing!"); + IsEarlyIncremented = false; +#endif + return *this; + } + + using BaseT::operator==; + bool operator==(const early_inc_iterator_impl &RHS) const { +#if LLVM_ENABLE_ABI_BREAKING_CHECKS + assert(!IsEarlyIncremented && "Cannot compare after dereferencing!"); +#endif + return BaseT::operator==(RHS); + } +}; + +/// Make a range that does early increment to allow mutation of the underlying +/// range without disrupting iteration. +/// +/// The underlying iterator will be incremented immediately after it is +/// dereferenced, allowing deletion of the current node or insertion of nodes to +/// not disrupt iteration provided they do not invalidate the *next* iterator -- +/// the current iterator can be invalidated. +/// +/// This requires a very exact pattern of use that is only really suitable to +/// range based for loops and other range algorithms that explicitly guarantee +/// to dereference exactly once each element, and to increment exactly once each +/// element. +template <typename RangeT> +iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>> +make_early_inc_range(RangeT &&Range) { + using EarlyIncIteratorT = + early_inc_iterator_impl<detail::IterOfRange<RangeT>>; + return make_range(EarlyIncIteratorT(std::begin(std::forward<RangeT>(Range))), + EarlyIncIteratorT(std::end(std::forward<RangeT>(Range)))); +} + +// forward declarations required by zip_shortest/zip_first/zip_longest template <typename R, typename UnaryPredicate> bool all_of(R &&range, UnaryPredicate P); +template <typename R, typename UnaryPredicate> +bool any_of(R &&range, UnaryPredicate P); template <size_t... I> struct index_sequence; @@ -571,6 +673,132 @@ detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u, std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); } +namespace detail { +template <typename Iter> +static Iter next_or_end(const Iter &I, const Iter &End) { + if (I == End) + return End; + return std::next(I); +} + +template <typename Iter> +static auto deref_or_none(const Iter &I, const Iter &End) + -> llvm::Optional<typename std::remove_const< + typename std::remove_reference<decltype(*I)>::type>::type> { + if (I == End) + return None; + return *I; +} + +template <typename Iter> struct ZipLongestItemType { + using type = + llvm::Optional<typename std::remove_const<typename std::remove_reference< + decltype(*std::declval<Iter>())>::type>::type>; +}; + +template <typename... Iters> struct ZipLongestTupleType { + using type = std::tuple<typename ZipLongestItemType<Iters>::type...>; +}; + +template <typename... Iters> +class zip_longest_iterator + : public iterator_facade_base< + zip_longest_iterator<Iters...>, + typename std::common_type< + std::forward_iterator_tag, + typename std::iterator_traits<Iters>::iterator_category...>::type, + typename ZipLongestTupleType<Iters...>::type, + typename std::iterator_traits<typename std::tuple_element< + 0, std::tuple<Iters...>>::type>::difference_type, + typename ZipLongestTupleType<Iters...>::type *, + typename ZipLongestTupleType<Iters...>::type> { +public: + using value_type = typename ZipLongestTupleType<Iters...>::type; + +private: + std::tuple<Iters...> iterators; + std::tuple<Iters...> end_iterators; + + template <size_t... Ns> + bool test(const zip_longest_iterator<Iters...> &other, + index_sequence<Ns...>) const { + return llvm::any_of( + std::initializer_list<bool>{std::get<Ns>(this->iterators) != + std::get<Ns>(other.iterators)...}, + identity<bool>{}); + } + + template <size_t... Ns> value_type deref(index_sequence<Ns...>) const { + return value_type( + deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...); + } + + template <size_t... Ns> + decltype(iterators) tup_inc(index_sequence<Ns...>) const { + return std::tuple<Iters...>( + next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...); + } + +public: + zip_longest_iterator(std::pair<Iters &&, Iters &&>... ts) + : iterators(std::forward<Iters>(ts.first)...), + end_iterators(std::forward<Iters>(ts.second)...) {} + + value_type operator*() { return deref(index_sequence_for<Iters...>{}); } + + value_type operator*() const { return deref(index_sequence_for<Iters...>{}); } + + zip_longest_iterator<Iters...> &operator++() { + iterators = tup_inc(index_sequence_for<Iters...>{}); + return *this; + } + + bool operator==(const zip_longest_iterator<Iters...> &other) const { + return !test(other, index_sequence_for<Iters...>{}); + } +}; + +template <typename... Args> class zip_longest_range { +public: + using iterator = + zip_longest_iterator<decltype(adl_begin(std::declval<Args>()))...>; + using iterator_category = typename iterator::iterator_category; + using value_type = typename iterator::value_type; + using difference_type = typename iterator::difference_type; + using pointer = typename iterator::pointer; + using reference = typename iterator::reference; + +private: + std::tuple<Args...> ts; + + template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) const { + return iterator(std::make_pair(adl_begin(std::get<Ns>(ts)), + adl_end(std::get<Ns>(ts)))...); + } + + template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) const { + return iterator(std::make_pair(adl_end(std::get<Ns>(ts)), + adl_end(std::get<Ns>(ts)))...); + } + +public: + zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {} + + iterator begin() const { return begin_impl(index_sequence_for<Args...>{}); } + iterator end() const { return end_impl(index_sequence_for<Args...>{}); } +}; +} // namespace detail + +/// Iterate over two or more iterators at the same time. Iteration continues +/// until all iterators reach the end. The llvm::Optional only contains a value +/// if the iterator has not reached the end. +template <typename T, typename U, typename... Args> +detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u, + Args &&... args) { + return detail::zip_longest_range<T, U, Args...>( + std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); +} + /// Iterator wrapper that concatenates sequences together. /// /// This can concatenate different iterators, even with different types, into @@ -593,18 +821,20 @@ class concat_iterator /// Note that something like iterator_range seems nice at first here, but the /// range properties are of little benefit and end up getting in the way /// because we need to do mutation on the current iterators. - std::tuple<std::pair<IterTs, IterTs>...> IterPairs; + std::tuple<IterTs...> Begins; + std::tuple<IterTs...> Ends; /// Attempts to increment a specific iterator. /// /// Returns true if it was able to increment the iterator. Returns false if /// the iterator is already at the end iterator. template <size_t Index> bool incrementHelper() { - auto &IterPair = std::get<Index>(IterPairs); - if (IterPair.first == IterPair.second) + auto &Begin = std::get<Index>(Begins); + auto &End = std::get<Index>(Ends); + if (Begin == End) return false; - ++IterPair.first; + ++Begin; return true; } @@ -628,11 +858,12 @@ class concat_iterator /// dereferences the iterator and returns the address of the resulting /// reference. template <size_t Index> ValueT *getHelper() const { - auto &IterPair = std::get<Index>(IterPairs); - if (IterPair.first == IterPair.second) + auto &Begin = std::get<Index>(Begins); + auto &End = std::get<Index>(Ends); + if (Begin == End) return nullptr; - return &*IterPair.first; + return &*Begin; } /// Finds the first non-end iterator, dereferences, and returns the resulting @@ -659,7 +890,7 @@ public: /// iterators. template <typename... RangeTs> explicit concat_iterator(RangeTs &&... Ranges) - : IterPairs({std::begin(Ranges), std::end(Ranges)}...) {} + : Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {} using BaseT::operator++; @@ -671,7 +902,7 @@ public: ValueT &operator*() const { return get(index_sequence_for<IterTs...>()); } bool operator==(const concat_iterator &RHS) const { - return IterPairs == RHS.IterPairs; + return Begins == RHS.Begins && Ends == RHS.Ends; } }; @@ -740,6 +971,19 @@ struct less_second { } }; +/// \brief Function object to apply a binary function to the first component of +/// a std::pair. +template<typename FuncTy> +struct on_first { + FuncTy func; + + template <typename T> + auto operator()(const T &lhs, const T &rhs) const + -> decltype(func(lhs.first, rhs.first)) { + return func(lhs.first, rhs.first); + } +}; + // A subset of N3658. More stuff can be added as-needed. /// Represents a compile-time sequence of integers. @@ -877,6 +1121,10 @@ inline void sort(IteratorTy Start, IteratorTy End) { std::sort(Start, End); } +template <typename Container> inline void sort(Container &&C) { + llvm::sort(adl_begin(C), adl_end(C)); +} + template <typename IteratorTy, typename Compare> inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) { #ifdef EXPENSIVE_CHECKS @@ -886,6 +1134,11 @@ inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) { std::sort(Start, End, Comp); } +template <typename Container, typename Compare> +inline void sort(Container &&C, Compare Comp) { + llvm::sort(adl_begin(C), adl_end(C), Comp); +} + //===----------------------------------------------------------------------===// // Extra additions to <algorithm> //===----------------------------------------------------------------------===// @@ -908,6 +1161,18 @@ void DeleteContainerSeconds(Container &C) { C.clear(); } +/// Get the size of a range. This is a wrapper function around std::distance +/// which is only enabled when the operation is O(1). +template <typename R> +auto size(R &&Range, typename std::enable_if< + std::is_same<typename std::iterator_traits<decltype( + Range.begin())>::iterator_category, + std::random_access_iterator_tag>::value, + void>::type * = nullptr) + -> decltype(std::distance(Range.begin(), Range.end())) { + return std::distance(Range.begin(), Range.end()); +} + /// Provide wrappers to std::for_each which take ranges instead of having to /// pass begin/end explicitly. template <typename R, typename UnaryPredicate> @@ -1018,6 +1283,33 @@ auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) { return std::lower_bound(adl_begin(Range), adl_end(Range), I); } +template <typename R, typename ForwardIt, typename Compare> +auto lower_bound(R &&Range, ForwardIt I, Compare C) + -> decltype(adl_begin(Range)) { + return std::lower_bound(adl_begin(Range), adl_end(Range), I, C); +} + +/// Provide wrappers to std::upper_bound which take ranges instead of having to +/// pass begin/end explicitly. +template <typename R, typename ForwardIt> +auto upper_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) { + return std::upper_bound(adl_begin(Range), adl_end(Range), I); +} + +template <typename R, typename ForwardIt, typename Compare> +auto upper_bound(R &&Range, ForwardIt I, Compare C) + -> decltype(adl_begin(Range)) { + return std::upper_bound(adl_begin(Range), adl_end(Range), I, C); +} +/// Wrapper function around std::equal to detect if all elements +/// in a container are same. +template <typename R> +bool is_splat(R &&Range) { + size_t range_size = size(Range); + return range_size != 0 && (range_size == 1 || + std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range))); +} + /// Given a range of type R, iterate the entire range and return a /// SmallVector with elements of the vector. This is useful, for example, /// when you want to iterate a range and then sort the results. @@ -1039,18 +1331,6 @@ void erase_if(Container &C, UnaryPredicate P) { C.erase(remove_if(C, P), C.end()); } -/// Get the size of a range. This is a wrapper function around std::distance -/// which is only enabled when the operation is O(1). -template <typename R> -auto size(R &&Range, typename std::enable_if< - std::is_same<typename std::iterator_traits<decltype( - Range.begin())>::iterator_category, - std::random_access_iterator_tag>::value, - void>::type * = nullptr) - -> decltype(std::distance(Range.begin(), Range.end())) { - return std::distance(Range.begin(), Range.end()); -} - //===----------------------------------------------------------------------===// // Extra additions to <memory> //===----------------------------------------------------------------------===// @@ -1263,6 +1543,40 @@ auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl( Indices{}); } +/// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N) +/// time. Not meant for use with random-access iterators. +template <typename IterTy> +bool hasNItems( + IterTy &&Begin, IterTy &&End, unsigned N, + typename std::enable_if< + !std::is_same< + typename std::iterator_traits<typename std::remove_reference< + decltype(Begin)>::type>::iterator_category, + std::random_access_iterator_tag>::value, + void>::type * = nullptr) { + for (; N; --N, ++Begin) + if (Begin == End) + return false; // Too few. + return Begin == End; +} + +/// Return true if the sequence [Begin, End) has N or more items. Runs in O(N) +/// time. Not meant for use with random-access iterators. +template <typename IterTy> +bool hasNItemsOrMore( + IterTy &&Begin, IterTy &&End, unsigned N, + typename std::enable_if< + !std::is_same< + typename std::iterator_traits<typename std::remove_reference< + decltype(Begin)>::type>::iterator_category, + std::random_access_iterator_tag>::value, + void>::type * = nullptr) { + for (; N; --N, ++Begin) + if (Begin == End) + return false; // Too few. + return true; +} + } // end namespace llvm #endif // LLVM_ADT_STLEXTRAS_H diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index b6391746639b..0a73dbd60671 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -92,10 +92,6 @@ public: }; private: - bool isSmall() const { - return X & uintptr_t(1); - } - BitVector *getPointer() const { assert(!isSmall()); return reinterpret_cast<BitVector *>(X); @@ -186,6 +182,8 @@ public: return make_range(set_bits_begin(), set_bits_end()); } + bool isSmall() const { return X & uintptr_t(1); } + /// Tests whether there are no bits in this bitvector. bool empty() const { return isSmall() ? getSmallSize() == 0 : getPointer()->empty(); @@ -242,7 +240,7 @@ public: uintptr_t Bits = getSmallBits(); if (Bits == 0) return -1; - return NumBaseBits - countLeadingZeros(Bits); + return NumBaseBits - countLeadingZeros(Bits) - 1; } return getPointer()->find_last(); } @@ -265,7 +263,9 @@ public: return -1; uintptr_t Bits = getSmallBits(); - return NumBaseBits - countLeadingOnes(Bits); + // Set unused bits. + Bits |= ~uintptr_t(0) << getSmallSize(); + return NumBaseBits - countLeadingOnes(Bits) - 1; } return getPointer()->find_last_unset(); } @@ -465,6 +465,11 @@ public: return (*this)[Idx]; } + // Push single bit to end of vector. + void push_back(bool Val) { + resize(size() + 1, Val); + } + /// Test if any common bits are set. bool anyCommon(const SmallBitVector &RHS) const { if (isSmall() && RHS.isSmall()) @@ -482,10 +487,17 @@ public: bool operator==(const SmallBitVector &RHS) const { if (size() != RHS.size()) return false; - if (isSmall()) + if (isSmall() && RHS.isSmall()) return getSmallBits() == RHS.getSmallBits(); - else + else if (!isSmall() && !RHS.isSmall()) return *getPointer() == *RHS.getPointer(); + else { + for (size_t i = 0, e = size(); i != e; ++i) { + if ((*this)[i] != RHS[i]) + return false; + } + return true; + } } bool operator!=(const SmallBitVector &RHS) const { @@ -493,16 +505,19 @@ public: } // Intersection, union, disjoint union. + // FIXME BitVector::operator&= does not resize the LHS but this does SmallBitVector &operator&=(const SmallBitVector &RHS) { resize(std::max(size(), RHS.size())); - if (isSmall()) + if (isSmall() && RHS.isSmall()) setSmallBits(getSmallBits() & RHS.getSmallBits()); - else if (!RHS.isSmall()) + else if (!isSmall() && !RHS.isSmall()) getPointer()->operator&=(*RHS.getPointer()); else { - SmallBitVector Copy = RHS; - Copy.resize(size()); - getPointer()->operator&=(*Copy.getPointer()); + size_t i, e; + for (i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + (*this)[i] = test(i) && RHS.test(i); + for (e = size(); i != e; ++i) + reset(i); } return *this; } @@ -542,28 +557,26 @@ public: SmallBitVector &operator|=(const SmallBitVector &RHS) { resize(std::max(size(), RHS.size())); - if (isSmall()) + if (isSmall() && RHS.isSmall()) setSmallBits(getSmallBits() | RHS.getSmallBits()); - else if (!RHS.isSmall()) + else if (!isSmall() && !RHS.isSmall()) getPointer()->operator|=(*RHS.getPointer()); else { - SmallBitVector Copy = RHS; - Copy.resize(size()); - getPointer()->operator|=(*Copy.getPointer()); + for (size_t i = 0, e = RHS.size(); i != e; ++i) + (*this)[i] = test(i) || RHS.test(i); } return *this; } SmallBitVector &operator^=(const SmallBitVector &RHS) { resize(std::max(size(), RHS.size())); - if (isSmall()) + if (isSmall() && RHS.isSmall()) setSmallBits(getSmallBits() ^ RHS.getSmallBits()); - else if (!RHS.isSmall()) + else if (!isSmall() && !RHS.isSmall()) getPointer()->operator^=(*RHS.getPointer()); else { - SmallBitVector Copy = RHS; - Copy.resize(size()); - getPointer()->operator^=(*Copy.getPointer()); + for (size_t i = 0, e = RHS.size(); i != e; ++i) + (*this)[i] = test(i) != RHS.test(i); } return *this; } diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index acb4426b4f45..0636abbb1fbf 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -182,7 +182,7 @@ public: /// SmallVectorTemplateBase<isPodLike = false> - This is where we put method /// implementations that are designed to work with non-POD-like T's. -template <typename T, bool isPodLike> +template <typename T, bool = isPodLike<T>::value> class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> { protected: SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} @@ -299,7 +299,7 @@ protected: // use memcpy here. Note that I and E are iterators and thus might be // invalid for memcpy if they are equal. if (I != E) - memcpy(Dest, I, (E - I) * sizeof(T)); + memcpy(reinterpret_cast<void *>(Dest), I, (E - I) * sizeof(T)); } /// Double the size of the allocated memory, guaranteeing space for at @@ -310,7 +310,7 @@ public: void push_back(const T &Elt) { if (LLVM_UNLIKELY(this->size() >= this->capacity())) this->grow(); - memcpy(this->end(), &Elt, sizeof(T)); + memcpy(reinterpret_cast<void *>(this->end()), &Elt, sizeof(T)); this->set_size(this->size() + 1); } @@ -320,8 +320,8 @@ public: /// This class consists of common code factored out of the SmallVector class to /// reduce code duplication based on the SmallVector 'N' template parameter. template <typename T> -class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> { - using SuperClass = SmallVectorTemplateBase<T, isPodLike<T>::value>; +class SmallVectorImpl : public SmallVectorTemplateBase<T> { + using SuperClass = SmallVectorTemplateBase<T>; public: using iterator = typename SuperClass::iterator; diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index 4cbf40c76805..84e73bcbace8 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -261,21 +261,33 @@ class SparseBitVector { BITWORD_SIZE = SparseBitVectorElement<ElementSize>::BITWORD_SIZE }; - // Pointer to our current Element. - ElementListIter CurrElementIter; ElementList Elements; + // Pointer to our current Element. This has no visible effect on the external + // state of a SparseBitVector, it's just used to improve performance in the + // common case of testing/modifying bits with similar indices. + mutable ElementListIter CurrElementIter; // This is like std::lower_bound, except we do linear searching from the // current position. - ElementListIter FindLowerBound(unsigned ElementIndex) { + ElementListIter FindLowerBoundImpl(unsigned ElementIndex) const { + + // We cache a non-const iterator so we're forced to resort to const_cast to + // get the begin/end in the case where 'this' is const. To avoid duplication + // of code with the only difference being whether the const cast is present + // 'this' is always const in this particular function and we sort out the + // difference in FindLowerBound and FindLowerBoundConst. + ElementListIter Begin = + const_cast<SparseBitVector<ElementSize> *>(this)->Elements.begin(); + ElementListIter End = + const_cast<SparseBitVector<ElementSize> *>(this)->Elements.end(); if (Elements.empty()) { - CurrElementIter = Elements.begin(); - return Elements.begin(); + CurrElementIter = Begin; + return CurrElementIter; } // Make sure our current iterator is valid. - if (CurrElementIter == Elements.end()) + if (CurrElementIter == End) --CurrElementIter; // Search from our current iterator, either backwards or forwards, @@ -284,17 +296,23 @@ class SparseBitVector { if (CurrElementIter->index() == ElementIndex) { return ElementIter; } else if (CurrElementIter->index() > ElementIndex) { - while (ElementIter != Elements.begin() + while (ElementIter != Begin && ElementIter->index() > ElementIndex) --ElementIter; } else { - while (ElementIter != Elements.end() && + while (ElementIter != End && ElementIter->index() < ElementIndex) ++ElementIter; } CurrElementIter = ElementIter; return ElementIter; } + ElementListConstIter FindLowerBoundConst(unsigned ElementIndex) const { + return FindLowerBoundImpl(ElementIndex); + } + ElementListIter FindLowerBound(unsigned ElementIndex) { + return FindLowerBoundImpl(ElementIndex); + } // Iterator to walk set bits in the bitmap. This iterator is a lot uglier // than it would be, in order to be efficient. @@ -423,22 +441,12 @@ class SparseBitVector { public: using iterator = SparseBitVectorIterator; - SparseBitVector() { - CurrElementIter = Elements.begin(); - } + SparseBitVector() : Elements(), CurrElementIter(Elements.begin()) {} - // SparseBitVector copy ctor. - SparseBitVector(const SparseBitVector &RHS) { - ElementListConstIter ElementIter = RHS.Elements.begin(); - while (ElementIter != RHS.Elements.end()) { - Elements.push_back(SparseBitVectorElement<ElementSize>(*ElementIter)); - ++ElementIter; - } - - CurrElementIter = Elements.begin (); - } - - ~SparseBitVector() = default; + SparseBitVector(const SparseBitVector &RHS) + : Elements(RHS.Elements), CurrElementIter(Elements.begin()) {} + SparseBitVector(SparseBitVector &&RHS) + : Elements(std::move(RHS.Elements)), CurrElementIter(Elements.begin()) {} // Clear. void clear() { @@ -450,26 +458,23 @@ public: if (this == &RHS) return *this; - Elements.clear(); - - ElementListConstIter ElementIter = RHS.Elements.begin(); - while (ElementIter != RHS.Elements.end()) { - Elements.push_back(SparseBitVectorElement<ElementSize>(*ElementIter)); - ++ElementIter; - } - - CurrElementIter = Elements.begin (); - + Elements = RHS.Elements; + CurrElementIter = Elements.begin(); + return *this; + } + SparseBitVector &operator=(SparseBitVector &&RHS) { + Elements = std::move(RHS.Elements); + CurrElementIter = Elements.begin(); return *this; } // Test, Reset, and Set a bit in the bitmap. - bool test(unsigned Idx) { + bool test(unsigned Idx) const { if (Elements.empty()) return false; unsigned ElementIndex = Idx / ElementSize; - ElementListIter ElementIter = FindLowerBound(ElementIndex); + ElementListConstIter ElementIter = FindLowerBoundConst(ElementIndex); // If we can't find an element that is supposed to contain this bit, there // is nothing more to do. diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h index 71b0e7527cb7..60a03633a8a6 100644 --- a/include/llvm/ADT/StringExtras.h +++ b/include/llvm/ADT/StringExtras.h @@ -139,22 +139,23 @@ inline std::string utohexstr(uint64_t X, bool LowerCase = false) { /// Convert buffer \p Input to its hexadecimal representation. /// The returned string is double the size of \p Input. -inline std::string toHex(StringRef Input) { +inline std::string toHex(StringRef Input, bool LowerCase = false) { static const char *const LUT = "0123456789ABCDEF"; + const uint8_t Offset = LowerCase ? 32 : 0; size_t Length = Input.size(); std::string Output; Output.reserve(2 * Length); for (size_t i = 0; i < Length; ++i) { const unsigned char c = Input[i]; - Output.push_back(LUT[c >> 4]); - Output.push_back(LUT[c & 15]); + Output.push_back(LUT[c >> 4] | Offset); + Output.push_back(LUT[c & 15] | Offset); } return Output; } -inline std::string toHex(ArrayRef<uint8_t> Input) { - return toHex(toStringRef(Input)); +inline std::string toHex(ArrayRef<uint8_t> Input, bool LowerCase = false) { + return toHex(toStringRef(Input), LowerCase); } inline uint8_t hexFromNibbles(char MSB, char LSB) { diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index c95b16dd4e8c..e06a68e27317 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -55,12 +55,11 @@ public: bpfel, // eBPF or extended BPF or 64-bit BPF (little endian) bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian) hexagon, // Hexagon: hexagon - mips, // MIPS: mips, mipsallegrex - mipsel, // MIPSEL: mipsel, mipsallegrexel - mips64, // MIPS64: mips64 - mips64el, // MIPS64EL: mips64el + mips, // MIPS: mips, mipsallegrex, mipsr6 + mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el + mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6 + mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el msp430, // MSP430: msp430 - nios2, // NIOSII: nios2 ppc, // PPC: powerpc ppc64, // PPC64: powerpc64, ppu ppc64le, // PPC64LE: powerpc64le @@ -101,6 +100,7 @@ public: enum SubArchType { NoSubArch, + ARMSubArch_v8_5a, ARMSubArch_v8_4a, ARMSubArch_v8_3a, ARMSubArch_v8_2a, @@ -125,7 +125,9 @@ public: KalimbaSubArch_v3, KalimbaSubArch_v4, - KalimbaSubArch_v5 + KalimbaSubArch_v5, + + MipsSubArch_r6 }; enum VendorType { UnknownVendor, @@ -182,7 +184,10 @@ public: Mesa3D, Contiki, AMDPAL, // AMD PAL Runtime - LastOSType = AMDPAL + HermitCore, // HermitCore Unikernel/Multikernel + Hurd, // GNU/Hurd + WASI, // Experimental WebAssembly OS + LastOSType = WASI }; enum EnvironmentType { UnknownEnvironment, @@ -578,9 +583,20 @@ public: return getOS() == Triple::KFreeBSD; } + /// Tests whether the OS is Hurd. + bool isOSHurd() const { + return getOS() == Triple::Hurd; + } + + /// Tests whether the OS is WASI. + bool isOSWASI() const { + return getOS() == Triple::WASI; + } + /// Tests whether the OS uses glibc. bool isOSGlibc() const { - return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD) && + return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD || + getOS() == Triple::Hurd) && !isAndroid(); } diff --git a/include/llvm/ADT/bit.h b/include/llvm/ADT/bit.h new file mode 100644 index 000000000000..a4aba7b6a9ee --- /dev/null +++ b/include/llvm/ADT/bit.h @@ -0,0 +1,59 @@ +//===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- 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 C++20 <bit> header. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_BIT_H +#define LLVM_ADT_BIT_H + +#include "llvm/Support/Compiler.h" +#include <cstring> +#include <type_traits> + +namespace llvm { + +// This implementation of bit_cast is different from the C++17 one in two ways: +// - It isn't constexpr because that requires compiler support. +// - It requires trivially-constructible To, to avoid UB in the implementation. +template <typename To, typename From + , typename = typename std::enable_if<sizeof(To) == sizeof(From)>::type +#if (__has_feature(is_trivially_constructible) && defined(_LIBCPP_VERSION)) || \ + (defined(__GNUC__) && __GNUC__ >= 5) + , typename = typename std::is_trivially_constructible<To>::type +#elif __has_feature(is_trivially_constructible) + , typename = typename std::enable_if<__is_trivially_constructible(To)>::type +#else + // See comment below. +#endif +#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \ + (defined(__GNUC__) && __GNUC__ >= 5) + , typename = typename std::enable_if<std::is_trivially_copyable<To>::value>::type + , typename = typename std::enable_if<std::is_trivially_copyable<From>::value>::type +#elif __has_feature(is_trivially_copyable) + , typename = typename std::enable_if<__is_trivially_copyable(To)>::type + , typename = typename std::enable_if<__is_trivially_copyable(From)>::type +#else + // This case is GCC 4.x. clang with libc++ or libstdc++ never get here. Unlike + // llvm/Support/type_traits.h's isPodLike we don't want to provide a + // good-enough answer here: developers in that configuration will hit + // compilation failures on the bots instead of locally. That's acceptable + // because it's very few developers, and only until we move past C++11. +#endif +> +inline To bit_cast(const From &from) noexcept { + To to; + std::memcpy(&to, &from, sizeof(To)); + return to; +} + +} // namespace llvm + +#endif diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h index 549c5221173d..40e490cf7864 100644 --- a/include/llvm/ADT/iterator.h +++ b/include/llvm/ADT/iterator.h @@ -202,9 +202,7 @@ template < typename ReferenceT = typename std::conditional< std::is_same<T, typename std::iterator_traits< WrappedIteratorT>::value_type>::value, - typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type, - // Don't provide these, they are mostly to act as aliases below. - typename WrappedTraitsT = std::iterator_traits<WrappedIteratorT>> + typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type> class iterator_adaptor_base : public iterator_facade_base<DerivedT, IteratorCategoryT, T, DifferenceTypeT, PointerT, ReferenceT> { @@ -311,8 +309,10 @@ make_pointee_range(RangeT &&Range) { template <typename WrappedIteratorT, typename T = decltype(&*std::declval<WrappedIteratorT>())> class pointer_iterator - : public iterator_adaptor_base<pointer_iterator<WrappedIteratorT, T>, - WrappedIteratorT, T> { + : public iterator_adaptor_base< + pointer_iterator<WrappedIteratorT, T>, WrappedIteratorT, + typename std::iterator_traits<WrappedIteratorT>::iterator_category, + T> { mutable T Ptr; public: @@ -334,6 +334,34 @@ make_pointer_range(RangeT &&Range) { PointerIteratorT(std::end(std::forward<RangeT>(Range)))); } +// Wrapper iterator over iterator ItType, adding DataRef to the type of ItType, +// to create NodeRef = std::pair<InnerTypeOfItType, DataRef>. +template <typename ItType, typename NodeRef, typename DataRef> +class WrappedPairNodeDataIterator + : public iterator_adaptor_base< + WrappedPairNodeDataIterator<ItType, NodeRef, DataRef>, ItType, + typename std::iterator_traits<ItType>::iterator_category, NodeRef, + std::ptrdiff_t, NodeRef *, NodeRef &> { + using BaseT = iterator_adaptor_base< + WrappedPairNodeDataIterator, ItType, + typename std::iterator_traits<ItType>::iterator_category, NodeRef, + std::ptrdiff_t, NodeRef *, NodeRef &>; + + const DataRef DR; + mutable NodeRef NR; + +public: + WrappedPairNodeDataIterator(ItType Begin, const DataRef DR) + : BaseT(Begin), DR(DR) { + NR.first = DR; + } + + NodeRef &operator*() const { + NR.second = *this->I; + return NR; + } +}; + } // end namespace llvm #endif // LLVM_ADT_ITERATOR_H |