diff options
author | Jush Lu <jush.msn@gmail.com> | 2011-03-09 19:39:16 +0800 |
---|---|---|
committer | Jush Lu <jush.msn@gmail.com> | 2011-03-09 19:39:16 +0800 |
commit | b5530586d68bd25831a6796b5d3199cb0769a35c (patch) | |
tree | fac4a03b53b6a64b0c00f433e4d8b3c9f2bc67cd /include/llvm | |
parent | b4e17c5bf4361bbdeced39aa071150d7fa9c3c10 (diff) | |
parent | d01f50f42ce60207ed6d27fb1778e456d83be06c (diff) | |
download | external_llvm-b5530586d68bd25831a6796b5d3199cb0769a35c.tar.gz external_llvm-b5530586d68bd25831a6796b5d3199cb0769a35c.tar.bz2 external_llvm-b5530586d68bd25831a6796b5d3199cb0769a35c.zip |
Merge upstream r127116
Diffstat (limited to 'include/llvm')
279 files changed, 11775 insertions, 4426 deletions
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index dfe4e0f49a..ca4138b825 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -246,6 +246,13 @@ namespace llvm { static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative = false); + /// getAllOnesValue - Returns a float which is bitcasted from + /// an all one value int. + /// + /// \param BitWidth - Select float type + /// \param isIEEE - If 128 bit number, select between PPC and IEEE + static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false); + /// Profile - Used to insert APFloat objects, or objects that contain /// APFloat objects, into FoldingSets. void Profile(FoldingSetNodeID& NID) const; diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index d398f8e3f6..d1fd3e5034 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -275,12 +275,6 @@ public: /// objects, into FoldingSets. void Profile(FoldingSetNodeID& id) const; - /// @brief Used by the Bitcode serializer to emit APInts to Bitcode. - void Emit(Serializer& S) const; - - /// @brief Used by the Bitcode deserializer to deserialize APInts. - void Read(Deserializer& D); - /// @} /// @name Value Tests /// @{ @@ -302,7 +296,7 @@ public: /// @returns true if this APInt is positive. /// @brief Determine if this APInt Value is positive. bool isStrictlyPositive() const { - return isNonNegative() && (*this) != 0; + return isNonNegative() && !!*this; } /// This checks to see if the value has all bits of the APInt are set or not. @@ -330,15 +324,14 @@ public: /// value for the APInt's bit width. /// @brief Determine if this is the smallest unsigned value. bool isMinValue() const { - return countPopulation() == 0; + return !*this; } /// This checks to see if the value of this APInt is the minimum signed /// value for the APInt's bit width. /// @brief Determine if this is the smallest signed value. bool isMinSignedValue() const { - return BitWidth == 1 ? VAL == 1 : - isNegative() && countPopulation() == 1; + return BitWidth == 1 ? VAL == 1 : isNegative() && isPowerOf2(); } /// @brief Check if this APInt has an N-bits unsigned integer value. @@ -349,9 +342,7 @@ public: if (isSingleWord()) return isUIntN(N, VAL); - APInt Tmp(N, getNumWords(), pVal); - Tmp.zext(getBitWidth()); - return Tmp == (*this); + return APInt(N, getNumWords(), pVal).zext(getBitWidth()) == (*this); } /// @brief Check if this APInt has an N-bits signed integer value. @@ -361,7 +352,11 @@ public: } /// @returns true if the argument APInt value is a power of two > 0. - bool isPowerOf2() const; + bool isPowerOf2() const { + if (isSingleWord()) + return isPowerOf2_64(VAL); + return countPopulationSlowCase() == 1; + } /// isSignBit - Return true if this is the value returned by getSignBit. bool isSignBit() const { return isMinSignedValue(); } @@ -369,7 +364,7 @@ public: /// This converts the APInt to a boolean value as a test against zero. /// @brief Boolean conversion function. bool getBoolValue() const { - return *this != 0; + return !!*this; } /// getLimitedValue - If this value is smaller than the specified limit, @@ -385,12 +380,14 @@ public: /// @{ /// @brief Gets maximum unsigned value of APInt for specific bit width. static APInt getMaxValue(unsigned numBits) { - return APInt(numBits, 0).set(); + return getAllOnesValue(numBits); } /// @brief Gets maximum signed value of APInt for a specific bit width. static APInt getSignedMaxValue(unsigned numBits) { - return APInt(numBits, 0).set().clear(numBits - 1); + APInt API = getAllOnesValue(numBits); + API.clearBit(numBits - 1); + return API; } /// @brief Gets minimum unsigned value of APInt for a specific bit width. @@ -400,7 +397,9 @@ public: /// @brief Gets minimum signed value of APInt for a specific bit width. static APInt getSignedMinValue(unsigned numBits) { - return APInt(numBits, 0).set(numBits - 1); + APInt API(numBits, 0); + API.setBit(numBits - 1); + return API; } /// getSignBit - This is just a wrapper function of getSignedMinValue(), and @@ -413,7 +412,7 @@ public: /// @returns the all-ones value for an APInt of the specified bit-width. /// @brief Get the all-ones value. static APInt getAllOnesValue(unsigned numBits) { - return APInt(numBits, 0).set(); + return APInt(numBits, -1ULL, true); } /// @returns the '0' value for an APInt of the specified bit-width. @@ -432,6 +431,13 @@ public: /// @returns the low "numBits" bits of this APInt. APInt getLoBits(unsigned numBits) const; + /// getOneBitSet - Return an APInt with exactly one bit set in the result. + static APInt getOneBitSet(unsigned numBits, unsigned BitNo) { + APInt Res(numBits, 0); + Res.setBit(BitNo); + return Res; + } + /// Constructs an APInt value that has a contiguous range of bits set. The /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other /// bits will be zero. For example, with parameters(32, 0, 16) you would get @@ -530,7 +536,7 @@ public: /// @brief Unary bitwise complement operator. APInt operator~() const { APInt Result(*this); - Result.flip(); + Result.flipAllBits(); return Result; } @@ -1012,80 +1018,78 @@ public: /// Truncate the APInt to a specified width. It is an error to specify a width /// that is greater than or equal to the current width. /// @brief Truncate to new width. - APInt &trunc(unsigned width); + APInt trunc(unsigned width) const; /// This operation sign extends the APInt to a new width. If the high order /// bit is set, the fill on the left will be done with 1 bits, otherwise zero. /// It is an error to specify a width that is less than or equal to the /// current width. /// @brief Sign extend to a new width. - APInt &sext(unsigned width); + APInt sext(unsigned width) const; /// This operation zero extends the APInt to a new width. The high order bits /// are filled with 0 bits. It is an error to specify a width that is less /// than or equal to the current width. /// @brief Zero extend to a new width. - APInt &zext(unsigned width); + APInt zext(unsigned width) const; /// Make this APInt have the bit width given by \p width. The value is sign /// extended, truncated, or left alone to make it that width. /// @brief Sign extend or truncate to width - APInt &sextOrTrunc(unsigned width); + APInt sextOrTrunc(unsigned width) const; /// Make this APInt have the bit width given by \p width. The value is zero /// extended, truncated, or left alone to make it that width. /// @brief Zero extend or truncate to width - APInt &zextOrTrunc(unsigned width); + APInt zextOrTrunc(unsigned width) const; /// @} /// @name Bit Manipulation Operators /// @{ /// @brief Set every bit to 1. - APInt &set() { - if (isSingleWord()) { + void setAllBits() { + if (isSingleWord()) VAL = -1ULL; - return clearUnusedBits(); + else { + // Set all the bits in all the words. + for (unsigned i = 0; i < getNumWords(); ++i) + pVal[i] = -1ULL; } - - // Set all the bits in all the words. - for (unsigned i = 0; i < getNumWords(); ++i) - pVal[i] = -1ULL; // Clear the unused ones - return clearUnusedBits(); + clearUnusedBits(); } /// Set the given bit to 1 whose position is given as "bitPosition". /// @brief Set a given bit to 1. - APInt &set(unsigned bitPosition); + void setBit(unsigned bitPosition); /// @brief Set every bit to 0. - APInt &clear() { + void clearAllBits() { if (isSingleWord()) VAL = 0; else memset(pVal, 0, getNumWords() * APINT_WORD_SIZE); - return *this; } /// Set the given bit to 0 whose position is given as "bitPosition". /// @brief Set a given bit to 0. - APInt &clear(unsigned bitPosition); + void clearBit(unsigned bitPosition); /// @brief Toggle every bit to its opposite value. - APInt &flip() { - if (isSingleWord()) { + void flipAllBits() { + if (isSingleWord()) VAL ^= -1ULL; - return clearUnusedBits(); + else { + for (unsigned i = 0; i < getNumWords(); ++i) + pVal[i] ^= -1ULL; } - for (unsigned i = 0; i < getNumWords(); ++i) - pVal[i] ^= -1ULL; - return clearUnusedBits(); + clearUnusedBits(); } /// Toggle a given bit to its opposite value whose position is given /// as "bitPosition". /// @brief Toggles a given bit to its opposite value. - APInt& flip(unsigned bitPosition); + void flipBit(unsigned bitPosition); /// @} /// @name Value Characterization Functions @@ -1189,6 +1193,12 @@ public: /// @brief Count the number of leading one bits. unsigned countLeadingOnes() const; + /// Computes the number of leading bits of this APInt that are equal to its + /// sign bit. + unsigned getNumSignBits() const { + return isNegative() ? countLeadingOnes() : countLeadingZeros(); + } + /// countTrailingZeros - This function is an APInt version of the /// countTrailingZeros_{32,64} functions in MathExtras.h. It counts /// the number of zeros from the least significant bit to the first set bit. @@ -1293,37 +1303,27 @@ public: } /// The conversion does not do a translation from double to integer, it just - /// re-interprets the bits of the double. Note that it is valid to do this on - /// any bit width but bits from V may get truncated. + /// re-interprets the bits of the double. /// @brief Converts a double to APInt bits. - APInt& doubleToBits(double V) { + static APInt doubleToBits(double V) { union { uint64_t I; double D; } T; T.D = V; - if (isSingleWord()) - VAL = T.I; - else - pVal[0] = T.I; - return clearUnusedBits(); + return APInt(sizeof T * CHAR_BIT, T.I); } /// The conversion does not do a translation from float to integer, it just - /// re-interprets the bits of the float. Note that it is valid to do this on - /// any bit width but bits from V may get truncated. + /// re-interprets the bits of the float. /// @brief Converts a float to APInt bits. - APInt& floatToBits(float V) { + static APInt floatToBits(float V) { union { unsigned I; float F; } T; T.F = V; - if (isSingleWord()) - VAL = T.I; - else - pVal[0] = T.I; - return clearUnusedBits(); + return APInt(sizeof T * CHAR_BIT, T.I); } /// @} diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index 1c9931c30f..54a7b601d1 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -68,20 +68,22 @@ public: } using APInt::toString; - APSInt& extend(uint32_t width) { + APSInt trunc(uint32_t width) const { + return APSInt(APInt::trunc(width), IsUnsigned); + } + + APSInt extend(uint32_t width) const { if (IsUnsigned) - zext(width); + return APSInt(zext(width), IsUnsigned); else - sext(width); - return *this; + return APSInt(sext(width), IsUnsigned); } - APSInt& extOrTrunc(uint32_t width) { + APSInt extOrTrunc(uint32_t width) const { if (IsUnsigned) - zextOrTrunc(width); + return APSInt(zextOrTrunc(width), IsUnsigned); else - sextOrTrunc(width); - return *this; + return APSInt(sextOrTrunc(width), IsUnsigned); } const APSInt &operator%=(const APSInt &RHS) { diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h new file mode 100644 index 0000000000..ebddb1287e --- /dev/null +++ b/include/llvm/ADT/ArrayRef.h @@ -0,0 +1,137 @@ +//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ARRAYREF_H +#define LLVM_ADT_ARRAYREF_H + +#include "llvm/ADT/SmallVector.h" +#include <vector> + +namespace llvm { + class APInt; + + /// ArrayRef - Represent a constant reference to an array (0 or more elements + /// consecutively in memory), i.e. a start pointer and a length. It allows + /// various APIs to take consecutive elements easily and conveniently. + /// + /// This class does not own the underlying data, it is expected to be used in + /// situations where the data resides in some other buffer, whose lifetime + /// extends past that of the StringRef. For this reason, it is not in general + /// safe to store a ArrayRef. + /// + /// This is intended to be trivially copyable, so it should be passed by + /// value. + template<typename T> + class ArrayRef { + public: + typedef const T *iterator; + typedef const T *const_iterator; + typedef size_t size_type; + + private: + /// The start of the array, in an external buffer. + const T *Data; + + /// The number of elements. + size_t Length; + + public: + /// @name Constructors + /// @{ + + /// Construct an empty ArrayRef. + /*implicit*/ ArrayRef() : Data(0), Length(0) {} + + /// Construct an ArrayRef from a single element. + /*implicit*/ ArrayRef(const T &OneElt) + : Data(&OneElt), Length(1) {} + + /// Construct an ArrayRef from a pointer and length. + /*implicit*/ ArrayRef(const T *data, size_t length) + : Data(data), Length(length) {} + + /// Construct an ArrayRef from a SmallVector. + /*implicit*/ ArrayRef(const SmallVectorImpl<T> &Vec) + : Data(Vec.data()), Length(Vec.size()) {} + + /// Construct an ArrayRef from a std::vector. + /*implicit*/ ArrayRef(const std::vector<T> &Vec) + : Data(Vec.empty() ? (T*)0 : &Vec[0]), Length(Vec.size()) {} + + /// Construct an ArrayRef from a C array. + template <size_t N> + /*implicit*/ ArrayRef(const T (&Arr)[N]) + : Data(Arr), Length(N) {} + + /// @} + /// @name Simple Operations + /// @{ + + iterator begin() const { return Data; } + iterator end() const { return Data + Length; } + + /// empty - Check if the array is empty. + bool empty() const { return Length == 0; } + + const T *data() const { return Data; } + + /// size - Get the array size. + size_t size() const { return Length; } + + /// front - Get the first element. + const T &front() const { + assert(!empty()); + return Data[0]; + } + + /// back - Get the last element. + const T &back() const { + assert(!empty()); + return Data[Length-1]; + } + + /// slice(n) - Chop off the first N elements of the array. + ArrayRef<T> slice(unsigned N) { + assert(N <= size() && "Invalid specifier"); + return ArrayRef<T>(data()+N, size()-N); + } + + /// slice(n, m) - Chop off the first N elements of the array, and keep M + /// elements in the array. + ArrayRef<T> slice(unsigned N, unsigned M) { + assert(N+M <= size() && "Invalid specifier"); + return ArrayRef<T>(data()+N, M); + } + + /// @} + /// @name Operator Overloads + /// @{ + const T &operator[](size_t Index) const { + assert(Index < Length && "Invalid index!"); + return Data[Index]; + } + + /// @} + /// @name Expensive Operations + /// @{ + std::vector<T> vec() const { + return std::vector<T>(Data, Data+Length); + } + + /// @} + }; + + // ArrayRefs can be treated like a POD type. + template <typename T> struct isPodLike; + template <typename T> struct isPodLike<ArrayRef<T> > { + static const bool value = true; + }; +} + +#endif diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 1940fd3900..ac1cf0c79a 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -18,6 +18,7 @@ #include <algorithm> #include <cassert> #include <climits> +#include <cstdlib> #include <cstring> namespace llvm { @@ -77,7 +78,7 @@ public: /// bits are initialized to the specified value. explicit BitVector(unsigned s, bool t = false) : Size(s) { Capacity = NumBitWords(s); - Bits = new BitWord[Capacity]; + Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); init_words(Bits, Capacity, t); if (t) clear_unused_bits(); @@ -92,12 +93,12 @@ public: } Capacity = NumBitWords(RHS.size()); - Bits = new BitWord[Capacity]; - std::copy(RHS.Bits, &RHS.Bits[Capacity], Bits); + Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); + std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord)); } ~BitVector() { - delete[] Bits; + std::free(Bits); } /// empty - Tests whether there are no bits in this bitvector. @@ -341,18 +342,18 @@ public: unsigned RHSWords = NumBitWords(Size); if (Size <= Capacity * BITWORD_SIZE) { if (Size) - std::copy(RHS.Bits, &RHS.Bits[RHSWords], Bits); + std::memcpy(Bits, RHS.Bits, RHSWords * sizeof(BitWord)); clear_unused_bits(); return *this; } // Grow the bitvector to have enough elements. Capacity = RHSWords; - BitWord *NewBits = new BitWord[Capacity]; - std::copy(RHS.Bits, &RHS.Bits[RHSWords], NewBits); + BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); + std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord)); // Destroy the old bits. - delete[] Bits; + std::free(Bits); Bits = NewBits; return *this; @@ -390,17 +391,8 @@ private: } void grow(unsigned NewSize) { - unsigned OldCapacity = Capacity; - Capacity = NumBitWords(NewSize); - BitWord *NewBits = new BitWord[Capacity]; - - // Copy the old bits over. - if (OldCapacity != 0) - std::copy(Bits, &Bits[OldCapacity], NewBits); - - // Destroy the old bits. - delete[] Bits; - Bits = NewBits; + Capacity = std::max(NumBitWords(NewSize), Capacity * 2); + Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord)); clear_unused_bits(); } diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 06a1575da4..dd341c6a75 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -18,6 +18,7 @@ #include "llvm/Support/PointerLikeTypeTraits.h" #include "llvm/Support/type_traits.h" #include "llvm/ADT/DenseMapInfo.h" +#include <algorithm> #include <iterator> #include <new> #include <utility> @@ -52,13 +53,13 @@ public: CopyFrom(other); } - explicit DenseMap(unsigned NumInitBuckets = 64) { + explicit DenseMap(unsigned NumInitBuckets = 0) { init(NumInitBuckets); } template<typename InputIt> DenseMap(const InputIt &I, const InputIt &E) { - init(64); + init(NextPowerOf2(std::distance(I, E))); insert(I, E); } @@ -97,7 +98,10 @@ public: unsigned size() const { return NumEntries; } /// Grow the densemap so that it has at least Size buckets. Does not shrink - void resize(size_t Size) { grow(Size); } + void resize(size_t Size) { + if (Size > NumBuckets) + grow(Size); + } void clear() { if (NumEntries == 0 && NumTombstones == 0) return; @@ -251,19 +255,25 @@ private: #endif operator delete(Buckets); } - Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT) * - other.NumBuckets)); + + NumBuckets = other.NumBuckets; + + if (NumBuckets == 0) { + Buckets = 0; + return; + } + + Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT) * NumBuckets)); if (isPodLike<KeyInfoT>::value && isPodLike<ValueInfoT>::value) - memcpy(Buckets, other.Buckets, other.NumBuckets * sizeof(BucketT)); + memcpy(Buckets, other.Buckets, NumBuckets * sizeof(BucketT)); else - for (size_t i = 0; i < other.NumBuckets; ++i) { + for (size_t i = 0; i < NumBuckets; ++i) { new (&Buckets[i].first) KeyT(other.Buckets[i].first); if (!KeyInfoT::isEqual(Buckets[i].first, getEmptyKey()) && !KeyInfoT::isEqual(Buckets[i].first, getTombstoneKey())) new (&Buckets[i].second) ValueT(other.Buckets[i].second); } - NumBuckets = other.NumBuckets; } BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value, @@ -312,6 +322,11 @@ private: unsigned ProbeAmt = 1; BucketT *BucketsPtr = Buckets; + if (NumBuckets == 0) { + FoundBucket = 0; + return false; + } + // FoundTombstone - Keep track of whether we find a tombstone while probing. BucketT *FoundTombstone = 0; const KeyT EmptyKey = getEmptyKey(); @@ -353,6 +368,12 @@ private: NumEntries = 0; NumTombstones = 0; NumBuckets = InitBuckets; + + if (InitBuckets == 0) { + Buckets = 0; + return; + } + assert(InitBuckets && (InitBuckets & (InitBuckets-1)) == 0 && "# initial buckets must be a power of two!"); Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT)*InitBuckets)); @@ -366,6 +387,9 @@ private: unsigned OldNumBuckets = NumBuckets; BucketT *OldBuckets = Buckets; + if (NumBuckets < 64) + NumBuckets = 64; + // Double the number of buckets. while (NumBuckets < AtLeast) NumBuckets <<= 1; @@ -385,7 +409,7 @@ private: // Insert the key/value into the new table. BucketT *DestBucket; bool FoundVal = LookupBucketFor(B->first, DestBucket); - FoundVal = FoundVal; // silence warning. + (void)FoundVal; // silence warning. assert(!FoundVal && "Key already in new map?"); DestBucket->first = B->first; new (&DestBucket->second) ValueT(B->second); diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h index 00bcf64a2f..67321f5398 100644 --- a/include/llvm/ADT/DenseSet.h +++ b/include/llvm/ADT/DenseSet.h @@ -33,6 +33,9 @@ public: bool empty() const { return TheMap.empty(); } unsigned size() const { return TheMap.size(); } + /// Grow the denseset so that it has at least Size buckets. Does not shrink + void resize(size_t Size) { TheMap.resize(Size); } + void clear() { TheMap.clear(); } diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index b9e5cbdf8c..dd13a2c020 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -143,8 +143,7 @@ public: static inline _Self end(const GraphT& G, SetType &S) { return _Self(S); } inline bool operator==(const _Self& x) const { - return VisitStack.size() == x.VisitStack.size() && - VisitStack == x.VisitStack; + return VisitStack == x.VisitStack; } inline bool operator!=(const _Self& x) const { return !operator==(x); } diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h index 85910f8939..ec981cd8db 100644 --- a/include/llvm/ADT/EquivalenceClasses.h +++ b/include/llvm/ADT/EquivalenceClasses.h @@ -15,7 +15,7 @@ #ifndef LLVM_ADT_EQUIVALENCECLASSES_H #define LLVM_ADT_EQUIVALENCECLASSES_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> #include <set> diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index 662b5e2735..879dbd05e1 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -16,7 +16,7 @@ #ifndef LLVM_ADT_FOLDINGSET_H #define LLVM_ADT_FOLDINGSET_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" diff --git a/include/llvm/ADT/ImmutableIntervalMap.h b/include/llvm/ADT/ImmutableIntervalMap.h index 968ce15277..0d8fcf3433 100644 --- a/include/llvm/ADT/ImmutableIntervalMap.h +++ b/include/llvm/ADT/ImmutableIntervalMap.h @@ -94,7 +94,7 @@ public: : ImutAVLFactory<ImutInfo>(Alloc) {} TreeTy *Add(TreeTy *T, value_type_ref V) { - T = Add_internal(V,T); + T = add_internal(V,T); this->MarkImmutable(T); return T; } @@ -103,20 +103,20 @@ public: if (!T) return NULL; - key_type_ref CurrentKey = ImutInfo::KeyOfValue(this->Value(T)); + key_type_ref CurrentKey = ImutInfo::KeyOfValue(this->getValue(T)); if (ImutInfo::isContainedIn(K, CurrentKey)) return T; else if (ImutInfo::isLess(K, CurrentKey)) - return Find(this->Left(T), K); + return Find(this->getLeft(T), K); else - return Find(this->Right(T), K); + return Find(this->getRight(T), K); } private: - TreeTy *Add_internal(value_type_ref V, TreeTy *T) { + TreeTy *add_internal(value_type_ref V, TreeTy *T) { key_type_ref K = ImutInfo::KeyOfValue(V); - T = RemoveAllOverlaps(T, K); + T = removeAllOverlaps(T, K); if (this->isEmpty(T)) return this->CreateNode(NULL, V, NULL); @@ -125,38 +125,38 @@ private: key_type_ref KCurrent = ImutInfo::KeyOfValue(this->Value(T)); if (ImutInfo::isLess(K, KCurrent)) - return this->Balance(Add_internal(V, this->Left(T)), this->Value(T), + return this->Balance(add_internal(V, this->Left(T)), this->Value(T), this->Right(T)); else return this->Balance(this->Left(T), this->Value(T), - Add_internal(V, this->Right(T))); + add_internal(V, this->Right(T))); } // Remove all overlaps from T. - TreeTy *RemoveAllOverlaps(TreeTy *T, key_type_ref K) { + TreeTy *removeAllOverlaps(TreeTy *T, key_type_ref K) { bool Changed; do { Changed = false; - T = RemoveOverlap(T, K, Changed); - this->MarkImmutable(T); + T = removeOverlap(T, K, Changed); + this->markImmutable(T); } while (Changed); return T; } // Remove one overlap from T. - TreeTy *RemoveOverlap(TreeTy *T, key_type_ref K, bool &Changed) { + TreeTy *removeOverlap(TreeTy *T, key_type_ref K, bool &Changed) { if (!T) return NULL; Interval CurrentK = ImutInfo::KeyOfValue(this->Value(T)); // If current key does not overlap the inserted key. if (CurrentK.getStart() > K.getEnd()) - return this->Balance(RemoveOverlap(this->Left(T), K, Changed), + return this->Balance(removeOverlap(this->Left(T), K, Changed), this->Value(T), this->Right(T)); else if (CurrentK.getEnd() < K.getStart()) return this->Balance(this->Left(T), this->Value(T), - RemoveOverlap(this->Right(T), K, Changed)); + removeOverlap(this->Right(T), K, Changed)); // Current key overlaps with the inserted key. // Remove the current key. @@ -167,18 +167,18 @@ private: if (CurrentK.getStart() < K.getStart()) { if (CurrentK.getEnd() <= K.getEnd()) { Interval NewK(CurrentK.getStart(), K.getStart()-1); - return Add_internal(std::make_pair(NewK, OldData), T); + return add_internal(std::make_pair(NewK, OldData), T); } else { Interval NewK1(CurrentK.getStart(), K.getStart()-1); - T = Add_internal(std::make_pair(NewK1, OldData), T); + T = add_internal(std::make_pair(NewK1, OldData), T); Interval NewK2(K.getEnd()+1, CurrentK.getEnd()); - return Add_internal(std::make_pair(NewK2, OldData), T); + return add_internal(std::make_pair(NewK2, OldData), T); } } else { if (CurrentK.getEnd() > K.getEnd()) { Interval NewK(K.getEnd()+1, CurrentK.getEnd()); - return Add_internal(std::make_pair(NewK, OldData), T); + return add_internal(std::make_pair(NewK, OldData), T); } else return T; } @@ -209,22 +209,22 @@ public: public: Factory(BumpPtrAllocator& Alloc) : F(Alloc) {} - ImmutableIntervalMap GetEmptyMap() { - return ImmutableIntervalMap(F.GetEmptyTree()); + ImmutableIntervalMap getEmptyMap() { + return ImmutableIntervalMap(F.getEmptyTree()); } - ImmutableIntervalMap Add(ImmutableIntervalMap Old, + ImmutableIntervalMap add(ImmutableIntervalMap Old, key_type_ref K, data_type_ref D) { - TreeTy *T = F.Add(Old.Root, std::make_pair<key_type, data_type>(K, D)); - return ImmutableIntervalMap(F.GetCanonicalTree(T)); + TreeTy *T = F.add(Old.Root, std::pair<key_type, data_type>(K, D)); + return ImmutableIntervalMap(F.getCanonicalTree(T)); } - ImmutableIntervalMap Remove(ImmutableIntervalMap Old, key_type_ref K) { - TreeTy *T = F.Remove(Old.Root, K); - return ImmutableIntervalMap(F.GetCanonicalTree(T)); + ImmutableIntervalMap remove(ImmutableIntervalMap Old, key_type_ref K) { + TreeTy *T = F.remove(Old.Root, K); + return ImmutableIntervalMap(F.getCanonicalTree(T)); } - data_type *Lookup(ImmutableIntervalMap M, key_type_ref K) { + data_type *lookup(ImmutableIntervalMap M, key_type_ref K) { TreeTy *T = F.Find(M.getRoot(), K); if (T) return &T->getValue().second; diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h index 7757c08770..714355b951 100644 --- a/include/llvm/ADT/ImmutableList.h +++ b/include/llvm/ADT/ImmutableList.h @@ -16,7 +16,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { @@ -156,7 +156,7 @@ public: if (ownsAllocator()) delete &getAllocator(); } - ImmutableList<T> Concat(const T& Head, ImmutableList<T> Tail) { + ImmutableList<T> concat(const T& Head, ImmutableList<T> Tail) { // Profile the new list to see if it already exists in our cache. FoldingSetNodeID ID; void* InsertPos; @@ -178,16 +178,16 @@ public: return L; } - ImmutableList<T> Add(const T& D, ImmutableList<T> L) { - return Concat(D, L); + ImmutableList<T> add(const T& D, ImmutableList<T> L) { + return concat(D, L); } - ImmutableList<T> GetEmptyList() const { + ImmutableList<T> getEmptyList() const { return ImmutableList<T>(0); } - ImmutableList<T> Create(const T& X) { - return Concat(X, GetEmptyList()); + ImmutableList<T> create(const T& X) { + return Concat(X, getEmptyList()); } }; diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h index 8af128ef3b..d6cce7ccfa 100644 --- a/include/llvm/ADT/ImmutableMap.h +++ b/include/llvm/ADT/ImmutableMap.h @@ -76,7 +76,23 @@ public: /// should use a Factory object to create maps instead of directly /// invoking the constructor, but there are cases where make this /// constructor public is useful. - explicit ImmutableMap(const TreeTy* R) : Root(const_cast<TreeTy*>(R)) {} + explicit ImmutableMap(const TreeTy* R) : Root(const_cast<TreeTy*>(R)) { + if (Root) { Root->retain(); } + } + ImmutableMap(const ImmutableMap &X) : Root(X.Root) { + if (Root) { Root->retain(); } + } + ImmutableMap &operator=(const ImmutableMap &X) { + if (Root != X.Root) { + if (X.Root) { X.Root->retain(); } + if (Root) { Root->release(); } + Root = X.Root; + } + return *this; + } + ~ImmutableMap() { + if (Root) { Root->release(); } + } class Factory { typename TreeTy::Factory F; @@ -89,16 +105,16 @@ public: Factory(BumpPtrAllocator& Alloc, bool canonicalize = true) : F(Alloc), Canonicalize(canonicalize) {} - ImmutableMap GetEmptyMap() { return ImmutableMap(F.GetEmptyTree()); } + ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); } - ImmutableMap Add(ImmutableMap Old, key_type_ref K, data_type_ref D) { - TreeTy *T = F.Add(Old.Root, std::make_pair<key_type,data_type>(K,D)); - return ImmutableMap(Canonicalize ? F.GetCanonicalTree(T): T); + ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D) { + TreeTy *T = F.add(Old.Root, std::pair<key_type,data_type>(K,D)); + return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); } - ImmutableMap Remove(ImmutableMap Old, key_type_ref K) { - TreeTy *T = F.Remove(Old.Root,K); - return ImmutableMap(Canonicalize ? F.GetCanonicalTree(T): T); + ImmutableMap remove(ImmutableMap Old, key_type_ref K) { + TreeTy *T = F.remove(Old.Root,K); + return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); } private: @@ -110,15 +126,30 @@ public: return Root ? Root->contains(K) : false; } - bool operator==(ImmutableMap RHS) const { + bool operator==(const ImmutableMap &RHS) const { return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; } - bool operator!=(ImmutableMap RHS) const { + bool operator!=(const ImmutableMap &RHS) const { return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; } - TreeTy* getRoot() const { return Root; } + TreeTy *getRoot() const { + if (Root) { Root->retain(); } + return Root; + } + + TreeTy *getRootWithoutRetain() const { + return Root; + } + + void manualRetain() { + if (Root) Root->retain(); + } + + void manualRelease() { + if (Root) Root->release(); + } bool isEmpty() const { return !Root; } diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h index 70c3caf2a0..3ca910ce94 100644 --- a/include/llvm/ADT/ImmutableSet.h +++ b/include/llvm/ADT/ImmutableSet.h @@ -15,10 +15,13 @@ #define LLVM_ADT_IMSET_H #include "llvm/Support/Allocator.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> #include <functional> +#include <vector> +#include <stdio.h> namespace llvm { @@ -32,7 +35,7 @@ template <typename ImutInfo> class ImutAVLTreeInOrderIterator; template <typename ImutInfo> class ImutAVLTreeGenericIterator; template <typename ImutInfo > -class ImutAVLTree : public FoldingSetNode { +class ImutAVLTree { public: typedef typename ImutInfo::key_type_ref key_type_ref; typedef typename ImutInfo::value_type value_type; @@ -43,7 +46,6 @@ public: friend class ImutIntervalAVLFactory<ImutInfo>; friend class ImutAVLTreeGenericIterator<ImutInfo>; - friend class FoldingSet<ImutAVLTree>; typedef ImutAVLTreeInOrderIterator<ImutInfo> iterator; @@ -51,29 +53,27 @@ public: // Public Interface. //===----------------------------------------------------===// - /// getLeft - Returns a pointer to the left subtree. This value + /// Return a pointer to the left subtree. This value /// is NULL if there is no left subtree. - ImutAVLTree *getLeft() const { return Left; } + ImutAVLTree *getLeft() const { return left; } - /// getRight - Returns a pointer to the right subtree. This value is + /// Return a pointer to the right subtree. This value is /// NULL if there is no right subtree. - ImutAVLTree *getRight() const { return Right; } + ImutAVLTree *getRight() const { return right; } /// getHeight - Returns the height of the tree. A tree with no subtrees /// has a height of 1. - unsigned getHeight() const { return Height; } + unsigned getHeight() const { return height; } /// getValue - Returns the data value associated with the tree node. - const value_type& getValue() const { return Value; } + const value_type& getValue() const { return value; } /// find - Finds the subtree associated with the specified key value. /// This method returns NULL if no matching subtree is found. ImutAVLTree* find(key_type_ref K) { ImutAVLTree *T = this; - while (T) { key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue()); - if (ImutInfo::isEqual(K,CurrentKey)) return T; else if (ImutInfo::isLess(K,CurrentKey)) @@ -81,7 +81,6 @@ public: else T = T->getRight(); } - return NULL; } @@ -90,7 +89,7 @@ public: ImutAVLTree* getMaxElement() { ImutAVLTree *T = this; ImutAVLTree *Right = T->getRight(); - while (Right) { T = Right; Right = T->getRight(); } + while (Right) { T = right; right = T->getRight(); } return T; } @@ -98,10 +97,10 @@ public: /// both leaves and non-leaf nodes. unsigned size() const { unsigned n = 1; - - if (const ImutAVLTree* L = getLeft()) n += L->size(); - if (const ImutAVLTree* R = getRight()) n += R->size(); - + if (const ImutAVLTree* L = getLeft()) + n += L->size(); + if (const ImutAVLTree* R = getRight()) + n += R->size(); return n; } @@ -114,7 +113,7 @@ public: /// inorder traversal. iterator end() const { return iterator(); } - bool ElementEqual(value_type_ref V) const { + bool isElementEqual(value_type_ref V) const { // Compare the keys. if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()), ImutInfo::KeyOfValue(V))) @@ -128,8 +127,8 @@ public: return true; } - bool ElementEqual(const ImutAVLTree* RHS) const { - return ElementEqual(RHS->getValue()); + bool isElementEqual(const ImutAVLTree* RHS) const { + return isElementEqual(RHS->getValue()); } /// isEqual - Compares two trees for structural equality and returns true @@ -144,12 +143,12 @@ public: while (LItr != LEnd && RItr != REnd) { if (*LItr == *RItr) { - LItr.SkipSubTree(); - RItr.SkipSubTree(); + LItr.skipSubTree(); + RItr.skipSubTree(); continue; } - if (!LItr->ElementEqual(*RItr)) + if (!LItr->isElementEqual(*RItr)) return false; ++LItr; @@ -173,22 +172,24 @@ public: /// Nodes are visited using an inorder traversal. template <typename Callback> void foreach(Callback& C) { - if (ImutAVLTree* L = getLeft()) L->foreach(C); + if (ImutAVLTree* L = getLeft()) + L->foreach(C); - C(Value); + C(value); - if (ImutAVLTree* R = getRight()) R->foreach(C); + if (ImutAVLTree* R = getRight()) + R->foreach(C); } - /// verify - A utility method that checks that the balancing and + /// validateTree - A utility method that checks that the balancing and /// ordering invariants of the tree are satisifed. It is a recursive /// method that returns the height of the tree, which is then consumed - /// by the enclosing verify call. External callers should ignore the + /// by the enclosing validateTree call. External callers should ignore the /// return value. An invalid tree will cause an assertion to fire in /// a debug build. - unsigned verify() const { - unsigned HL = getLeft() ? getLeft()->verify() : 0; - unsigned HR = getRight() ? getRight()->verify() : 0; + unsigned validateTree() const { + unsigned HL = getLeft() ? getLeft()->validateTree() : 0; + unsigned HR = getRight() ? getRight()->validateTree() : 0; (void) HL; (void) HR; @@ -198,37 +199,39 @@ public: assert((HL > HR ? HL-HR : HR-HL) <= 2 && "Balancing invariant violated"); - assert(!getLeft() - || ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()), - ImutInfo::KeyOfValue(getValue())) - && "Value in left child is not less that current value"); + assert((!getLeft() || + ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()), + ImutInfo::KeyOfValue(getValue()))) && + "Value in left child is not less that current value"); - assert(!getRight() - || ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()), - ImutInfo::KeyOfValue(getRight()->getValue())) - && "Current value is not less that value of right child"); + assert(!(getRight() || + ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()), + ImutInfo::KeyOfValue(getRight()->getValue()))) && + "Current value is not less that value of right child"); return getHeight(); } - /// Profile - Profiling for ImutAVLTree. - void Profile(llvm::FoldingSetNodeID& ID) { - ID.AddInteger(ComputeDigest()); - } - //===----------------------------------------------------===// - // Internal Values. + // Internal values. //===----------------------------------------------------===// private: - ImutAVLTree* Left; - ImutAVLTree* Right; - unsigned Height : 28; - unsigned Mutable : 1; - unsigned CachedDigest : 1; - value_type Value; - uint32_t Digest; + Factory *factory; + ImutAVLTree *left; + ImutAVLTree *right; + ImutAVLTree *prev; + ImutAVLTree *next; + + unsigned height : 28; + unsigned IsMutable : 1; + unsigned IsDigestCached : 1; + unsigned IsCanonicalized : 1; + + value_type value; + uint32_t digest; + uint32_t refCount; //===----------------------------------------------------===// // Internal methods (node manipulation; used by Factory). @@ -237,10 +240,15 @@ private: private: /// ImutAVLTree - Internal constructor that is only called by /// ImutAVLFactory. - ImutAVLTree(ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, + ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, unsigned height) - : Left(l), Right(r), Height(height), Mutable(true), CachedDigest(false), - Value(v), Digest(0) {} + : factory(f), left(l), right(r), prev(0), next(0), height(height), + IsMutable(true), IsDigestCached(false), IsCanonicalized(0), + value(v), digest(0), refCount(0) + { + if (left) left->retain(); + if (right) right->retain(); + } /// isMutable - Returns true if the left and right subtree references /// (as well as height) can be changed. If this method returns false, @@ -248,11 +256,11 @@ private: /// object should always have this method return true. Further, if this /// method returns false for an instance of ImutAVLTree, all subtrees /// will also have this method return false. The converse is not true. - bool isMutable() const { return Mutable; } + bool isMutable() const { return IsMutable; } /// hasCachedDigest - Returns true if the digest for this tree is cached. /// This can only be true if the tree is immutable. - bool hasCachedDigest() const { return CachedDigest; } + bool hasCachedDigest() const { return IsDigestCached; } //===----------------------------------------------------===// // Mutating operations. A tree root can be manipulated as @@ -265,51 +273,32 @@ private: // immutable. //===----------------------------------------------------===// - /// MarkImmutable - Clears the mutable flag for a tree. After this happens, + /// markImmutable - Clears the mutable flag for a tree. After this happens, /// it is an error to call setLeft(), setRight(), and setHeight(). - void MarkImmutable() { + void markImmutable() { assert(isMutable() && "Mutable flag already removed."); - Mutable = false; + IsMutable = false; } - /// MarkedCachedDigest - Clears the NoCachedDigest flag for a tree. - void MarkedCachedDigest() { + /// markedCachedDigest - Clears the NoCachedDigest flag for a tree. + void markedCachedDigest() { assert(!hasCachedDigest() && "NoCachedDigest flag already removed."); - CachedDigest = true; - } - - /// setLeft - Changes the reference of the left subtree. Used internally - /// by ImutAVLFactory. - void setLeft(ImutAVLTree* NewLeft) { - assert(isMutable() && - "Only a mutable tree can have its left subtree changed."); - Left = NewLeft; - CachedDigest = false; - } - - /// setRight - Changes the reference of the right subtree. Used internally - /// by ImutAVLFactory. - void setRight(ImutAVLTree* NewRight) { - assert(isMutable() && - "Only a mutable tree can have its right subtree changed."); - - Right = NewRight; - CachedDigest = false; + IsDigestCached = true; } /// setHeight - Changes the height of the tree. Used internally by /// ImutAVLFactory. void setHeight(unsigned h) { assert(isMutable() && "Only a mutable tree can have its height changed."); - Height = h; + height = h; } static inline - uint32_t ComputeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) { + uint32_t computeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) { uint32_t digest = 0; if (L) - digest += L->ComputeDigest(); + digest += L->computeDigest(); // Compute digest of stored data. FoldingSetNodeID ID; @@ -317,22 +306,54 @@ private: digest += ID.ComputeHash(); if (R) - digest += R->ComputeDigest(); + digest += R->computeDigest(); return digest; } - inline uint32_t ComputeDigest() { + inline uint32_t computeDigest() { // Check the lowest bit to determine if digest has actually been // pre-computed. if (hasCachedDigest()) - return Digest; + return digest; - uint32_t X = ComputeDigest(getLeft(), getRight(), getValue()); - Digest = X; - MarkedCachedDigest(); + uint32_t X = computeDigest(getLeft(), getRight(), getValue()); + digest = X; + markedCachedDigest(); return X; } + + //===----------------------------------------------------===// + // Reference count operations. + //===----------------------------------------------------===// + +public: + void retain() { ++refCount; } + void release() { + assert(refCount > 0); + if (--refCount == 0) + destroy(); + } + void destroy() { + if (left) + left->release(); + if (right) + right->release(); + if (IsCanonicalized) { + if (next) + next->prev = prev; + + if (prev) + prev->next = next; + else + factory->Cache[computeDigest()] = next; + } + + // We need to clear the mutability bit in case we are + // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes(). + IsMutable = false; + factory->freeNodes.push_back(this); + } }; //===----------------------------------------------------------------------===// @@ -341,14 +362,17 @@ private: template <typename ImutInfo > class ImutAVLFactory { + friend class ImutAVLTree<ImutInfo>; typedef ImutAVLTree<ImutInfo> TreeTy; typedef typename TreeTy::value_type_ref value_type_ref; typedef typename TreeTy::key_type_ref key_type_ref; - typedef FoldingSet<TreeTy> CacheTy; + typedef DenseMap<unsigned, TreeTy*> CacheTy; CacheTy Cache; uintptr_t Allocator; + std::vector<TreeTy*> createdNodes; + std::vector<TreeTy*> freeNodes; bool ownsAllocator() const { return Allocator & 0x1 ? false : true; @@ -373,55 +397,56 @@ public: if (ownsAllocator()) delete &getAllocator(); } - TreeTy* Add(TreeTy* T, value_type_ref V) { - T = Add_internal(V,T); - MarkImmutable(T); + TreeTy* add(TreeTy* T, value_type_ref V) { + T = add_internal(V,T); + markImmutable(T); + recoverNodes(); return T; } - TreeTy* Remove(TreeTy* T, key_type_ref V) { - T = Remove_internal(V,T); - MarkImmutable(T); + TreeTy* remove(TreeTy* T, key_type_ref V) { + T = remove_internal(V,T); + markImmutable(T); + recoverNodes(); return T; } - TreeTy* GetEmptyTree() const { return NULL; } + TreeTy* getEmptyTree() const { return NULL; } +protected: + //===--------------------------------------------------===// // A bunch of quick helper functions used for reasoning // about the properties of trees and their children. // These have succinct names so that the balancing code // is as terse (and readable) as possible. //===--------------------------------------------------===// -protected: - bool isEmpty(TreeTy* T) const { return !T; } - unsigned Height(TreeTy* T) const { return T ? T->getHeight() : 0; } - TreeTy* Left(TreeTy* T) const { return T->getLeft(); } - TreeTy* Right(TreeTy* T) const { return T->getRight(); } - value_type_ref Value(TreeTy* T) const { return T->Value; } + bool isEmpty(TreeTy* T) const { return !T; } + unsigned getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; } + TreeTy* getLeft(TreeTy* T) const { return T->getLeft(); } + TreeTy* getRight(TreeTy* T) const { return T->getRight(); } + value_type_ref getValue(TreeTy* T) const { return T->value; } - unsigned IncrementHeight(TreeTy* L, TreeTy* R) const { - unsigned hl = Height(L); - unsigned hr = Height(R); + unsigned incrementHeight(TreeTy* L, TreeTy* R) const { + unsigned hl = getHeight(L); + unsigned hr = getHeight(R); return (hl > hr ? hl : hr) + 1; } - static bool CompareTreeWithSection(TreeTy* T, + static bool compareTreeWithSection(TreeTy* T, typename TreeTy::iterator& TI, typename TreeTy::iterator& TE) { - typename TreeTy::iterator I = T->begin(), E = T->end(); - - for ( ; I!=E ; ++I, ++TI) - if (TI == TE || !I->ElementEqual(*TI)) + for ( ; I!=E ; ++I, ++TI) { + if (TI == TE || !I->isElementEqual(*TI)) return false; - + } return true; } //===--------------------------------------------------===// - // "CreateNode" is used to generate new tree roots that link + // "createNode" is used to generate new tree roots that link // to other trees. The functon may also simply move links // in an existing root if that root is still marked mutable. // This is necessary because otherwise our balancing code @@ -430,181 +455,188 @@ protected: // returned to the caller. //===--------------------------------------------------===// - TreeTy* CreateNode(TreeTy* L, value_type_ref V, TreeTy* R) { + TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) { BumpPtrAllocator& A = getAllocator(); - TreeTy* T = (TreeTy*) A.Allocate<TreeTy>(); - new (T) TreeTy(L, R, V, IncrementHeight(L,R)); + TreeTy* T; + if (!freeNodes.empty()) { + T = freeNodes.back(); + freeNodes.pop_back(); + assert(T != L); + assert(T != R); + } + else { + T = (TreeTy*) A.Allocate<TreeTy>(); + } + new (T) TreeTy(this, L, R, V, incrementHeight(L,R)); + createdNodes.push_back(T); return T; } - TreeTy* CreateNode(TreeTy* L, TreeTy* OldTree, TreeTy* R) { - assert(!isEmpty(OldTree)); + TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) { + return createNode(newLeft, getValue(oldTree), newRight); + } - if (OldTree->isMutable()) { - OldTree->setLeft(L); - OldTree->setRight(R); - OldTree->setHeight(IncrementHeight(L, R)); - return OldTree; + void recoverNodes() { + for (unsigned i = 0, n = createdNodes.size(); i < n; ++i) { + TreeTy *N = createdNodes[i]; + if (N->isMutable() && N->refCount == 0) + N->destroy(); } - else - return CreateNode(L, Value(OldTree), R); + createdNodes.clear(); } - /// Balance - Used by Add_internal and Remove_internal to + /// balanceTree - Used by add_internal and remove_internal to /// balance a newly created tree. - TreeTy* Balance(TreeTy* L, value_type_ref V, TreeTy* R) { - - unsigned hl = Height(L); - unsigned hr = Height(R); + TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) { + unsigned hl = getHeight(L); + unsigned hr = getHeight(R); if (hl > hr + 2) { assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2"); - TreeTy* LL = Left(L); - TreeTy* LR = Right(L); + TreeTy *LL = getLeft(L); + TreeTy *LR = getRight(L); - if (Height(LL) >= Height(LR)) - return CreateNode(LL, L, CreateNode(LR,V,R)); + if (getHeight(LL) >= getHeight(LR)) + return createNode(LL, L, createNode(LR,V,R)); assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1"); - TreeTy* LRL = Left(LR); - TreeTy* LRR = Right(LR); + TreeTy *LRL = getLeft(LR); + TreeTy *LRR = getRight(LR); - return CreateNode(CreateNode(LL,L,LRL), LR, CreateNode(LRR,V,R)); + return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R)); } else if (hr > hl + 2) { assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2"); - TreeTy* RL = Left(R); - TreeTy* RR = Right(R); + TreeTy *RL = getLeft(R); + TreeTy *RR = getRight(R); - if (Height(RR) >= Height(RL)) - return CreateNode(CreateNode(L,V,RL), R, RR); + if (getHeight(RR) >= getHeight(RL)) + return createNode(createNode(L,V,RL), R, RR); assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1"); - TreeTy* RLL = Left(RL); - TreeTy* RLR = Right(RL); + TreeTy *RLL = getLeft(RL); + TreeTy *RLR = getRight(RL); - return CreateNode(CreateNode(L,V,RLL), RL, CreateNode(RLR,R,RR)); + return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR)); } else - return CreateNode(L,V,R); + return createNode(L,V,R); } - /// Add_internal - Creates a new tree that includes the specified + /// add_internal - Creates a new tree that includes the specified /// data and the data from the original tree. If the original tree /// already contained the data item, the original tree is returned. - TreeTy* Add_internal(value_type_ref V, TreeTy* T) { + TreeTy* add_internal(value_type_ref V, TreeTy* T) { if (isEmpty(T)) - return CreateNode(T, V, T); - + return createNode(T, V, T); assert(!T->isMutable()); key_type_ref K = ImutInfo::KeyOfValue(V); - key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T)); + key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T)); if (ImutInfo::isEqual(K,KCurrent)) - return CreateNode(Left(T), V, Right(T)); + return createNode(getLeft(T), V, getRight(T)); else if (ImutInfo::isLess(K,KCurrent)) - return Balance(Add_internal(V,Left(T)), Value(T), Right(T)); + return balanceTree(add_internal(V, getLeft(T)), getValue(T), getRight(T)); else - return Balance(Left(T), Value(T), Add_internal(V,Right(T))); + return balanceTree(getLeft(T), getValue(T), add_internal(V, getRight(T))); } - /// Remove_internal - Creates a new tree that includes all the data + /// remove_internal - Creates a new tree that includes all the data /// from the original tree except the specified data. If the /// specified data did not exist in the original tree, the original /// tree is returned. - TreeTy* Remove_internal(key_type_ref K, TreeTy* T) { + TreeTy* remove_internal(key_type_ref K, TreeTy* T) { if (isEmpty(T)) return T; assert(!T->isMutable()); - key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T)); + key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T)); - if (ImutInfo::isEqual(K,KCurrent)) - return CombineLeftRightTrees(Left(T),Right(T)); - else if (ImutInfo::isLess(K,KCurrent)) - return Balance(Remove_internal(K,Left(T)), Value(T), Right(T)); - else - return Balance(Left(T), Value(T), Remove_internal(K,Right(T))); + if (ImutInfo::isEqual(K,KCurrent)) { + return combineTrees(getLeft(T), getRight(T)); + } else if (ImutInfo::isLess(K,KCurrent)) { + return balanceTree(remove_internal(K, getLeft(T)), + getValue(T), getRight(T)); + } else { + return balanceTree(getLeft(T), getValue(T), + remove_internal(K, getRight(T))); + } } - TreeTy* CombineLeftRightTrees(TreeTy* L, TreeTy* R) { - if (isEmpty(L)) return R; - if (isEmpty(R)) return L; - + TreeTy* combineTrees(TreeTy* L, TreeTy* R) { + if (isEmpty(L)) + return R; + if (isEmpty(R)) + return L; TreeTy* OldNode; - TreeTy* NewRight = RemoveMinBinding(R,OldNode); - return Balance(L,Value(OldNode),NewRight); + TreeTy* newRight = removeMinBinding(R,OldNode); + return balanceTree(L, getValue(OldNode), newRight); } - TreeTy* RemoveMinBinding(TreeTy* T, TreeTy*& NodeRemoved) { + TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) { assert(!isEmpty(T)); - - if (isEmpty(Left(T))) { - NodeRemoved = T; - return Right(T); + if (isEmpty(getLeft(T))) { + Noderemoved = T; + return getRight(T); } - - return Balance(RemoveMinBinding(Left(T),NodeRemoved),Value(T),Right(T)); + return balanceTree(removeMinBinding(getLeft(T), Noderemoved), + getValue(T), getRight(T)); } - /// MarkImmutable - Clears the mutable bits of a root and all of its + /// markImmutable - Clears the mutable bits of a root and all of its /// descendants. - void MarkImmutable(TreeTy* T) { + void markImmutable(TreeTy* T) { if (!T || !T->isMutable()) return; - - T->MarkImmutable(); - MarkImmutable(Left(T)); - MarkImmutable(Right(T)); + T->markImmutable(); + markImmutable(getLeft(T)); + markImmutable(getRight(T)); } public: - TreeTy *GetCanonicalTree(TreeTy *TNew) { + TreeTy *getCanonicalTree(TreeTy *TNew) { if (!TNew) - return NULL; - - // Search the FoldingSet bucket for a Tree with the same digest. - FoldingSetNodeID ID; - unsigned digest = TNew->ComputeDigest(); - ID.AddInteger(digest); - unsigned hash = ID.ComputeHash(); - - typename CacheTy::bucket_iterator I = Cache.bucket_begin(hash); - typename CacheTy::bucket_iterator E = Cache.bucket_end(hash); - - for (; I != E; ++I) { - TreeTy *T = &*I; - - if (T->ComputeDigest() != digest) - continue; - - // We found a collision. Perform a comparison of Contents('T') - // with Contents('TNew') - typename TreeTy::iterator TI = T->begin(), TE = T->end(); - - if (!CompareTreeWithSection(TNew, TI, TE)) - continue; - - if (TI != TE) - continue; // T has more contents than TNew. - - // Trees did match! Return 'T'. - return T; + return 0; + + if (TNew->IsCanonicalized) + return TNew; + + // Search the hashtable for another tree with the same digest, and + // if find a collision compare those trees by their contents. + unsigned digest = TNew->computeDigest(); + TreeTy *&entry = Cache[digest]; + do { + if (!entry) + break; + for (TreeTy *T = entry ; T != 0; T = T->next) { + // Compare the Contents('T') with Contents('TNew') + typename TreeTy::iterator TI = T->begin(), TE = T->end(); + if (!compareTreeWithSection(TNew, TI, TE)) + continue; + if (TI != TE) + continue; // T has more contents than TNew. + // Trees did match! Return 'T'. + if (TNew->refCount == 0) + TNew->destroy(); + return T; + } + entry->prev = TNew; + TNew->next = entry; } + while (false); - // 'TNew' is the only tree of its kind. Return it. - Cache.InsertNode(TNew, (void*) &*Cache.bucket_end(hash)); + entry = TNew; + TNew->IsCanonicalized = true; return TNew; } }; - //===----------------------------------------------------------------------===// // Immutable AVL-Tree Iterators. //===----------------------------------------------------------------------===// @@ -635,19 +667,17 @@ public: } - bool AtEnd() const { return stack.empty(); } + bool atEnd() const { return stack.empty(); } - bool AtBeginning() const { + bool atBeginning() const { return stack.size() == 1 && getVisitState() == VisitedNone; } - void SkipToParent() { + void skipToParent() { assert(!stack.empty()); stack.pop_back(); - if (stack.empty()) return; - switch (getVisitState()) { case VisitedNone: stack.back() |= VisitedLeft; @@ -663,11 +693,9 @@ public: inline bool operator==(const _Self& x) const { if (stack.size() != x.stack.size()) return false; - for (unsigned i = 0 ; i < stack.size(); i++) if (stack[i] != x.stack[i]) return false; - return true; } @@ -675,70 +703,52 @@ public: _Self& operator++() { assert(!stack.empty()); - TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); assert(Current); - switch (getVisitState()) { case VisitedNone: if (TreeTy* L = Current->getLeft()) stack.push_back(reinterpret_cast<uintptr_t>(L)); else stack.back() |= VisitedLeft; - break; - case VisitedLeft: if (TreeTy* R = Current->getRight()) stack.push_back(reinterpret_cast<uintptr_t>(R)); else stack.back() |= VisitedRight; - break; - case VisitedRight: - SkipToParent(); + skipToParent(); break; - default: assert(false && "Unreachable."); } - return *this; } _Self& operator--() { assert(!stack.empty()); - TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); assert(Current); - switch (getVisitState()) { case VisitedNone: stack.pop_back(); break; - case VisitedLeft: stack.back() &= ~Flags; // Set state to "VisitedNone." - if (TreeTy* L = Current->getLeft()) stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight); - break; - case VisitedRight: stack.back() &= ~Flags; stack.back() |= VisitedLeft; - if (TreeTy* R = Current->getRight()) stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight); - break; - default: assert(false && "Unreachable."); } - return *this; } }; @@ -769,7 +779,7 @@ public: inline _Self& operator++() { do ++InternalItr; - while (!InternalItr.AtEnd() && + while (!InternalItr.atEnd() && InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); return *this; @@ -777,16 +787,16 @@ public: inline _Self& operator--() { do --InternalItr; - while (!InternalItr.AtBeginning() && + while (!InternalItr.atBeginning() && InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); return *this; } - inline void SkipSubTree() { - InternalItr.SkipToParent(); + inline void skipSubTree() { + InternalItr.skipToParent(); - while (!InternalItr.AtEnd() && + while (!InternalItr.atEnd() && InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft) ++InternalItr; } @@ -927,7 +937,23 @@ public: /// should use a Factory object to create sets instead of directly /// invoking the constructor, but there are cases where make this /// constructor public is useful. - explicit ImmutableSet(TreeTy* R) : Root(R) {} + explicit ImmutableSet(TreeTy* R) : Root(R) { + if (Root) { Root->retain(); } + } + ImmutableSet(const ImmutableSet &X) : Root(X.Root) { + if (Root) { Root->retain(); } + } + ImmutableSet &operator=(const ImmutableSet &X) { + if (Root != X.Root) { + if (X.Root) { X.Root->retain(); } + if (Root) { Root->release(); } + Root = X.Root; + } + return *this; + } + ~ImmutableSet() { + if (Root) { Root->release(); } + } class Factory { typename TreeTy::Factory F; @@ -940,33 +966,33 @@ public: Factory(BumpPtrAllocator& Alloc, bool canonicalize = true) : F(Alloc), Canonicalize(canonicalize) {} - /// GetEmptySet - Returns an immutable set that contains no elements. - ImmutableSet GetEmptySet() { - return ImmutableSet(F.GetEmptyTree()); + /// getEmptySet - Returns an immutable set that contains no elements. + ImmutableSet getEmptySet() { + return ImmutableSet(F.getEmptyTree()); } - /// Add - Creates a new immutable set that contains all of the values + /// add - Creates a new immutable set that contains all of the values /// of the original set with the addition of the specified value. If /// the original set already included the value, then the original set is /// returned and no memory is allocated. The time and space complexity /// of this operation is logarithmic in the size of the original set. /// The memory allocated to represent the set is released when the /// factory object that created the set is destroyed. - ImmutableSet Add(ImmutableSet Old, value_type_ref V) { - TreeTy *NewT = F.Add(Old.Root, V); - return ImmutableSet(Canonicalize ? F.GetCanonicalTree(NewT) : NewT); + ImmutableSet add(ImmutableSet Old, value_type_ref V) { + TreeTy *NewT = F.add(Old.Root, V); + return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT); } - /// Remove - Creates a new immutable set that contains all of the values + /// remove - Creates a new immutable set that contains all of the values /// of the original set with the exception of the specified value. If /// the original set did not contain the value, the original set is /// returned and no memory is allocated. The time and space complexity /// of this operation is logarithmic in the size of the original set. /// The memory allocated to represent the set is released when the /// factory object that created the set is destroyed. - ImmutableSet Remove(ImmutableSet Old, value_type_ref V) { - TreeTy *NewT = F.Remove(Old.Root, V); - return ImmutableSet(Canonicalize ? F.GetCanonicalTree(NewT) : NewT); + ImmutableSet remove(ImmutableSet Old, value_type_ref V) { + TreeTy *NewT = F.remove(Old.Root, V); + return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT); } BumpPtrAllocator& getAllocator() { return F.getAllocator(); } @@ -978,20 +1004,21 @@ public: friend class Factory; - /// contains - Returns true if the set contains the specified value. + /// Returns true if the set contains the specified value. bool contains(value_type_ref V) const { return Root ? Root->contains(V) : false; } - bool operator==(ImmutableSet RHS) const { + bool operator==(const ImmutableSet &RHS) const { return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; } - bool operator!=(ImmutableSet RHS) const { + bool operator!=(const ImmutableSet &RHS) const { return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; } TreeTy *getRoot() { + if (Root) { Root->retain(); } return Root; } @@ -1049,7 +1076,7 @@ public: // For testing. //===--------------------------------------------------===// - void verify() const { if (Root) Root->verify(); } + void validateTree() const { if (Root) Root->validateTree(); } }; } // end namespace llvm diff --git a/include/llvm/ADT/InMemoryStruct.h b/include/llvm/ADT/InMemoryStruct.h new file mode 100644 index 0000000000..a56084501a --- /dev/null +++ b/include/llvm/ADT/InMemoryStruct.h @@ -0,0 +1,77 @@ +//===- InMemoryStruct.h - Indirect Struct Access Smart Pointer --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INMEMORYSTRUCT_H +#define LLVM_ADT_INMEMORYSTRUCT_H + +#include <cassert> + +namespace llvm { + +/// \brief Helper object for abstracting access to an in-memory structure which +/// may require some kind of temporary storage. +/// +/// This class is designed to be used for accessing file data structures which +/// in the common case can be accessed from a direct pointer to a memory mapped +/// object, but which in some cases may require indirect access to a temporary +/// structure (which, for example, may have undergone endianness translation). +template<typename T> +class InMemoryStruct { + typedef T value_type; + typedef value_type &reference; + typedef value_type *pointer; + typedef const value_type &const_reference; + typedef const value_type *const_pointer; + + /// \brief The smart pointer target. + value_type *Target; + + /// \brief A temporary object which can be used as a target of the smart + /// pointer. + value_type Contents; + +private: + +public: + InMemoryStruct() : Target(0) {} + InMemoryStruct(reference Value) : Target(&Contents), Contents(Value) {} + InMemoryStruct(pointer Value) : Target(Value) {} + InMemoryStruct(const InMemoryStruct<T> &Value) { *this = Value; } + + void operator=(const InMemoryStruct<T> &Value) { + if (Value.Target != &Value.Contents) { + Target = Value.Target; + } else { + Target = &Contents; + Contents = Value.Contents; + } + } + + const_reference operator*() const { + assert(Target && "Cannot dereference null pointer"); + return *Target; + } + reference operator*() { + assert(Target && "Cannot dereference null pointer"); + return *Target; + } + + const_pointer operator->() const { + return Target; + } + pointer operator->() { + return Target; + } + + operator bool() const { return Target != 0; } +}; + +} + +#endif diff --git a/include/llvm/ADT/IndexedMap.h b/include/llvm/ADT/IndexedMap.h index 89f0dfa64e..87126ea491 100644 --- a/include/llvm/ADT/IndexedMap.h +++ b/include/llvm/ADT/IndexedMap.h @@ -55,6 +55,14 @@ namespace llvm { return storage_[toIndex_(n)]; } + void reserve(typename StorageT::size_type s) { + storage_.reserve(s); + } + + void resize(typename StorageT::size_type s) { + storage_.resize(s, nullVal_); + } + void clear() { storage_.clear(); } @@ -62,7 +70,11 @@ namespace llvm { void grow(IndexT n) { unsigned NewSize = toIndex_(n) + 1; if (NewSize > storage_.size()) - storage_.resize(NewSize, nullVal_); + resize(NewSize); + } + + bool inBounds(IndexT n) const { + return toIndex_(n) < storage_.size(); } typename StorageT::size_type size() const { diff --git a/include/llvm/ADT/IntEqClasses.h b/include/llvm/ADT/IntEqClasses.h new file mode 100644 index 0000000000..8e75c48e37 --- /dev/null +++ b/include/llvm/ADT/IntEqClasses.h @@ -0,0 +1,88 @@ +//===-- llvm/ADT/IntEqClasses.h - Equiv. Classes of Integers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Equivalence classes for small integers. This is a mapping of the integers +// 0 .. N-1 into M equivalence classes numbered 0 .. M-1. +// +// Initially each integer has its own equivalence class. Classes are joined by +// passing a representative member of each class to join(). +// +// Once the classes are built, compress() will number them 0 .. M-1 and prevent +// further changes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTEQCLASSES_H +#define LLVM_ADT_INTEQCLASSES_H + +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class IntEqClasses { + /// EC - When uncompressed, map each integer to a smaller member of its + /// equivalence class. The class leader is the smallest member and maps to + /// itself. + /// + /// When compressed, EC[i] is the equivalence class of i. + SmallVector<unsigned, 8> EC; + + /// NumClasses - The number of equivalence classes when compressed, or 0 when + /// uncompressed. + unsigned NumClasses; + +public: + /// IntEqClasses - Create an equivalence class mapping for 0 .. N-1. + IntEqClasses(unsigned N = 0) : NumClasses(0) { grow(N); } + + /// grow - Increase capacity to hold 0 .. N-1, putting new integers in unique + /// equivalence classes. + /// This requires an uncompressed map. + void grow(unsigned N); + + /// clear - Clear all classes so that grow() will assign a unique class to + /// every integer. + void clear() { + EC.clear(); + NumClasses = 0; + } + + /// join - Join the equivalence classes of a and b. After joining classes, + /// findLeader(a) == findLeader(b). + /// This requires an uncompressed map. + void join(unsigned a, unsigned b); + + /// findLeader - Compute the leader of a's equivalence class. This is the + /// smallest member of the class. + /// This requires an uncompressed map. + unsigned findLeader(unsigned a) const; + + /// compress - Compress equivalence classes by numbering them 0 .. M. + /// This makes the equivalence class map immutable. + void compress(); + + /// getNumClasses - Return the number of equivalence classes after compress() + /// was called. + unsigned getNumClasses() const { return NumClasses; } + + /// operator[] - Return a's equivalence class number, 0 .. getNumClasses()-1. + /// This requires a compressed map. + unsigned operator[](unsigned a) const { + assert(NumClasses && "operator[] called before compress()"); + return EC[a]; + } + + /// uncompress - Change back to the uncompressed representation that allows + /// editing. + void uncompress(); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h new file mode 100644 index 0000000000..79f24d31c0 --- /dev/null +++ b/include/llvm/ADT/IntervalMap.h @@ -0,0 +1,2139 @@ +//===- llvm/ADT/IntervalMap.h - A sorted interval map -----------*- 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 a coalescing interval map for small objects. +// +// KeyT objects are mapped to ValT objects. Intervals of keys that map to the +// same value are represented in a compressed form. +// +// Iterators provide ordered access to the compressed intervals rather than the +// individual keys, and insert and erase operations use key intervals as well. +// +// Like SmallVector, IntervalMap will store the first N intervals in the map +// object itself without any allocations. When space is exhausted it switches to +// a B+-tree representation with very small overhead for small key and value +// objects. +// +// A Traits class specifies how keys are compared. It also allows IntervalMap to +// work with both closed and half-open intervals. +// +// Keys and values are not stored next to each other in a std::pair, so we don't +// provide such a value_type. Dereferencing iterators only returns the mapped +// value. The interval bounds are accessible through the start() and stop() +// iterator methods. +// +// IntervalMap is optimized for small key and value objects, 4 or 8 bytes each +// is the optimal size. For large objects use std::map instead. +// +//===----------------------------------------------------------------------===// +// +// Synopsis: +// +// template <typename KeyT, typename ValT, unsigned N, typename Traits> +// class IntervalMap { +// public: +// typedef KeyT key_type; +// typedef ValT mapped_type; +// typedef RecyclingAllocator<...> Allocator; +// class iterator; +// class const_iterator; +// +// explicit IntervalMap(Allocator&); +// ~IntervalMap(): +// +// bool empty() const; +// KeyT start() const; +// KeyT stop() const; +// ValT lookup(KeyT x, Value NotFound = Value()) const; +// +// const_iterator begin() const; +// const_iterator end() const; +// iterator begin(); +// iterator end(); +// const_iterator find(KeyT x) const; +// iterator find(KeyT x); +// +// void insert(KeyT a, KeyT b, ValT y); +// void clear(); +// }; +// +// template <typename KeyT, typename ValT, unsigned N, typename Traits> +// class IntervalMap::const_iterator : +// public std::iterator<std::bidirectional_iterator_tag, ValT> { +// public: +// bool operator==(const const_iterator &) const; +// bool operator!=(const const_iterator &) const; +// bool valid() const; +// +// const KeyT &start() const; +// const KeyT &stop() const; +// const ValT &value() const; +// const ValT &operator*() const; +// const ValT *operator->() const; +// +// const_iterator &operator++(); +// const_iterator &operator++(int); +// const_iterator &operator--(); +// const_iterator &operator--(int); +// void goToBegin(); +// void goToEnd(); +// void find(KeyT x); +// void advanceTo(KeyT x); +// }; +// +// template <typename KeyT, typename ValT, unsigned N, typename Traits> +// class IntervalMap::iterator : public const_iterator { +// public: +// void insert(KeyT a, KeyT b, Value y); +// void erase(); +// }; +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTERVALMAP_H +#define LLVM_ADT_INTERVALMAP_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/RecyclingAllocator.h" +#include <iterator> + +namespace llvm { + + +//===----------------------------------------------------------------------===// +//--- Key traits ---// +//===----------------------------------------------------------------------===// +// +// The IntervalMap works with closed or half-open intervals. +// Adjacent intervals that map to the same value are coalesced. +// +// The IntervalMapInfo traits class is used to determine if a key is contained +// in an interval, and if two intervals are adjacent so they can be coalesced. +// The provided implementation works for closed integer intervals, other keys +// probably need a specialized version. +// +// The point x is contained in [a;b] when !startLess(x, a) && !stopLess(b, x). +// +// It is assumed that (a;b] half-open intervals are not used, only [a;b) is +// allowed. This is so that stopLess(a, b) can be used to determine if two +// intervals overlap. +// +//===----------------------------------------------------------------------===// + +template <typename T> +struct IntervalMapInfo { + + /// startLess - Return true if x is not in [a;b]. + /// This is x < a both for closed intervals and for [a;b) half-open intervals. + static inline bool startLess(const T &x, const T &a) { + return x < a; + } + + /// stopLess - Return true if x is not in [a;b]. + /// This is b < x for a closed interval, b <= x for [a;b) half-open intervals. + static inline bool stopLess(const T &b, const T &x) { + return b < x; + } + + /// adjacent - Return true when the intervals [x;a] and [b;y] can coalesce. + /// This is a+1 == b for closed intervals, a == b for half-open intervals. + static inline bool adjacent(const T &a, const T &b) { + return a+1 == b; + } + +}; + +/// IntervalMapImpl - Namespace used for IntervalMap implementation details. +/// It should be considered private to the implementation. +namespace IntervalMapImpl { + +// Forward declarations. +template <typename, typename, unsigned, typename> class LeafNode; +template <typename, typename, unsigned, typename> class BranchNode; + +typedef std::pair<unsigned,unsigned> IdxPair; + + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::NodeBase ---// +//===----------------------------------------------------------------------===// +// +// Both leaf and branch nodes store vectors of pairs. +// Leaves store ((KeyT, KeyT), ValT) pairs, branches use (NodeRef, KeyT). +// +// Keys and values are stored in separate arrays to avoid padding caused by +// different object alignments. This also helps improve locality of reference +// when searching the keys. +// +// The nodes don't know how many elements they contain - that information is +// stored elsewhere. Omitting the size field prevents padding and allows a node +// to fill the allocated cache lines completely. +// +// These are typical key and value sizes, the node branching factor (N), and +// wasted space when nodes are sized to fit in three cache lines (192 bytes): +// +// T1 T2 N Waste Used by +// 4 4 24 0 Branch<4> (32-bit pointers) +// 8 4 16 0 Leaf<4,4>, Branch<4> +// 8 8 12 0 Leaf<4,8>, Branch<8> +// 16 4 9 12 Leaf<8,4> +// 16 8 8 0 Leaf<8,8> +// +//===----------------------------------------------------------------------===// + +template <typename T1, typename T2, unsigned N> +class NodeBase { +public: + enum { Capacity = N }; + + T1 first[N]; + T2 second[N]; + + /// copy - Copy elements from another node. + /// @param Other Node elements are copied from. + /// @param i Beginning of the source range in other. + /// @param j Beginning of the destination range in this. + /// @param Count Number of elements to copy. + template <unsigned M> + void copy(const NodeBase<T1, T2, M> &Other, unsigned i, + unsigned j, unsigned Count) { + assert(i + Count <= M && "Invalid source range"); + assert(j + Count <= N && "Invalid dest range"); + for (unsigned e = i + Count; i != e; ++i, ++j) { + first[j] = Other.first[i]; + second[j] = Other.second[i]; + } + } + + /// moveLeft - Move elements to the left. + /// @param i Beginning of the source range. + /// @param j Beginning of the destination range. + /// @param Count Number of elements to copy. + void moveLeft(unsigned i, unsigned j, unsigned Count) { + assert(j <= i && "Use moveRight shift elements right"); + copy(*this, i, j, Count); + } + + /// moveRight - Move elements to the right. + /// @param i Beginning of the source range. + /// @param j Beginning of the destination range. + /// @param Count Number of elements to copy. + void moveRight(unsigned i, unsigned j, unsigned Count) { + assert(i <= j && "Use moveLeft shift elements left"); + assert(j + Count <= N && "Invalid range"); + while (Count--) { + first[j + Count] = first[i + Count]; + second[j + Count] = second[i + Count]; + } + } + + /// erase - Erase elements [i;j). + /// @param i Beginning of the range to erase. + /// @param j End of the range. (Exclusive). + /// @param Size Number of elements in node. + void erase(unsigned i, unsigned j, unsigned Size) { + moveLeft(j, i, Size - j); + } + + /// erase - Erase element at i. + /// @param i Index of element to erase. + /// @param Size Number of elements in node. + void erase(unsigned i, unsigned Size) { + erase(i, i+1, Size); + } + + /// shift - Shift elements [i;size) 1 position to the right. + /// @param i Beginning of the range to move. + /// @param Size Number of elements in node. + void shift(unsigned i, unsigned Size) { + moveRight(i, i + 1, Size - i); + } + + /// transferToLeftSib - Transfer elements to a left sibling node. + /// @param Size Number of elements in this. + /// @param Sib Left sibling node. + /// @param SSize Number of elements in sib. + /// @param Count Number of elements to transfer. + void transferToLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize, + unsigned Count) { + Sib.copy(*this, 0, SSize, Count); + erase(0, Count, Size); + } + + /// transferToRightSib - Transfer elements to a right sibling node. + /// @param Size Number of elements in this. + /// @param Sib Right sibling node. + /// @param SSize Number of elements in sib. + /// @param Count Number of elements to transfer. + void transferToRightSib(unsigned Size, NodeBase &Sib, unsigned SSize, + unsigned Count) { + Sib.moveRight(0, Count, SSize); + Sib.copy(*this, Size-Count, 0, Count); + } + + /// adjustFromLeftSib - Adjust the number if elements in this node by moving + /// elements to or from a left sibling node. + /// @param Size Number of elements in this. + /// @param Sib Right sibling node. + /// @param SSize Number of elements in sib. + /// @param Add The number of elements to add to this node, possibly < 0. + /// @return Number of elements added to this node, possibly negative. + int adjustFromLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize, int Add) { + if (Add > 0) { + // We want to grow, copy from sib. + unsigned Count = std::min(std::min(unsigned(Add), SSize), N - Size); + Sib.transferToRightSib(SSize, *this, Size, Count); + return Count; + } else { + // We want to shrink, copy to sib. + unsigned Count = std::min(std::min(unsigned(-Add), Size), N - SSize); + transferToLeftSib(Size, Sib, SSize, Count); + return -Count; + } + } +}; + +/// IntervalMapImpl::adjustSiblingSizes - Move elements between sibling nodes. +/// @param Node Array of pointers to sibling nodes. +/// @param Nodes Number of nodes. +/// @param CurSize Array of current node sizes, will be overwritten. +/// @param NewSize Array of desired node sizes. +template <typename NodeT> +void adjustSiblingSizes(NodeT *Node[], unsigned Nodes, + unsigned CurSize[], const unsigned NewSize[]) { + // Move elements right. + for (int n = Nodes - 1; n; --n) { + if (CurSize[n] == NewSize[n]) + continue; + for (int m = n - 1; m != -1; --m) { + int d = Node[n]->adjustFromLeftSib(CurSize[n], *Node[m], CurSize[m], + NewSize[n] - CurSize[n]); + CurSize[m] -= d; + CurSize[n] += d; + // Keep going if the current node was exhausted. + if (CurSize[n] >= NewSize[n]) + break; + } + } + + if (Nodes == 0) + return; + + // Move elements left. + for (unsigned n = 0; n != Nodes - 1; ++n) { + if (CurSize[n] == NewSize[n]) + continue; + for (unsigned m = n + 1; m != Nodes; ++m) { + int d = Node[m]->adjustFromLeftSib(CurSize[m], *Node[n], CurSize[n], + CurSize[n] - NewSize[n]); + CurSize[m] += d; + CurSize[n] -= d; + // Keep going if the current node was exhausted. + if (CurSize[n] >= NewSize[n]) + break; + } + } + +#ifndef NDEBUG + for (unsigned n = 0; n != Nodes; n++) + assert(CurSize[n] == NewSize[n] && "Insufficient element shuffle"); +#endif +} + +/// IntervalMapImpl::distribute - Compute a new distribution of node elements +/// after an overflow or underflow. Reserve space for a new element at Position, +/// and compute the node that will hold Position after redistributing node +/// elements. +/// +/// It is required that +/// +/// Elements == sum(CurSize), and +/// Elements + Grow <= Nodes * Capacity. +/// +/// NewSize[] will be filled in such that: +/// +/// sum(NewSize) == Elements, and +/// NewSize[i] <= Capacity. +/// +/// The returned index is the node where Position will go, so: +/// +/// sum(NewSize[0..idx-1]) <= Position +/// sum(NewSize[0..idx]) >= Position +/// +/// The last equality, sum(NewSize[0..idx]) == Position, can only happen when +/// Grow is set and NewSize[idx] == Capacity-1. The index points to the node +/// before the one holding the Position'th element where there is room for an +/// insertion. +/// +/// @param Nodes The number of nodes. +/// @param Elements Total elements in all nodes. +/// @param Capacity The capacity of each node. +/// @param CurSize Array[Nodes] of current node sizes, or NULL. +/// @param NewSize Array[Nodes] to receive the new node sizes. +/// @param Position Insert position. +/// @param Grow Reserve space for a new element at Position. +/// @return (node, offset) for Position. +IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity, + const unsigned *CurSize, unsigned NewSize[], + unsigned Position, bool Grow); + + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::NodeSizer ---// +//===----------------------------------------------------------------------===// +// +// Compute node sizes from key and value types. +// +// The branching factors are chosen to make nodes fit in three cache lines. +// This may not be possible if keys or values are very large. Such large objects +// are handled correctly, but a std::map would probably give better performance. +// +//===----------------------------------------------------------------------===// + +enum { + // Cache line size. Most architectures have 32 or 64 byte cache lines. + // We use 64 bytes here because it provides good branching factors. + Log2CacheLine = 6, + CacheLineBytes = 1 << Log2CacheLine, + DesiredNodeBytes = 3 * CacheLineBytes +}; + +template <typename KeyT, typename ValT> +struct NodeSizer { + enum { + // Compute the leaf node branching factor that makes a node fit in three + // cache lines. The branching factor must be at least 3, or some B+-tree + // balancing algorithms won't work. + // LeafSize can't be larger than CacheLineBytes. This is required by the + // PointerIntPair used by NodeRef. + DesiredLeafSize = DesiredNodeBytes / + static_cast<unsigned>(2*sizeof(KeyT)+sizeof(ValT)), + MinLeafSize = 3, + LeafSize = DesiredLeafSize > MinLeafSize ? DesiredLeafSize : MinLeafSize + }; + + typedef NodeBase<std::pair<KeyT, KeyT>, ValT, LeafSize> LeafBase; + + enum { + // Now that we have the leaf branching factor, compute the actual allocation + // unit size by rounding up to a whole number of cache lines. + AllocBytes = (sizeof(LeafBase) + CacheLineBytes-1) & ~(CacheLineBytes-1), + + // Determine the branching factor for branch nodes. + BranchSize = AllocBytes / + static_cast<unsigned>(sizeof(KeyT) + sizeof(void*)) + }; + + /// Allocator - The recycling allocator used for both branch and leaf nodes. + /// This typedef is very likely to be identical for all IntervalMaps with + /// reasonably sized entries, so the same allocator can be shared among + /// different kinds of maps. + typedef RecyclingAllocator<BumpPtrAllocator, char, + AllocBytes, CacheLineBytes> Allocator; + +}; + + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::NodeRef ---// +//===----------------------------------------------------------------------===// +// +// B+-tree nodes can be leaves or branches, so we need a polymorphic node +// pointer that can point to both kinds. +// +// All nodes are cache line aligned and the low 6 bits of a node pointer are +// always 0. These bits are used to store the number of elements in the +// referenced node. Besides saving space, placing node sizes in the parents +// allow tree balancing algorithms to run without faulting cache lines for nodes +// that may not need to be modified. +// +// A NodeRef doesn't know whether it references a leaf node or a branch node. +// It is the responsibility of the caller to use the correct types. +// +// Nodes are never supposed to be empty, and it is invalid to store a node size +// of 0 in a NodeRef. The valid range of sizes is 1-64. +// +//===----------------------------------------------------------------------===// + +class NodeRef { + struct CacheAlignedPointerTraits { + static inline void *getAsVoidPointer(void *P) { return P; } + static inline void *getFromVoidPointer(void *P) { return P; } + enum { NumLowBitsAvailable = Log2CacheLine }; + }; + PointerIntPair<void*, Log2CacheLine, unsigned, CacheAlignedPointerTraits> pip; + +public: + /// NodeRef - Create a null ref. + NodeRef() {} + + /// operator bool - Detect a null ref. + operator bool() const { return pip.getOpaqueValue(); } + + /// NodeRef - Create a reference to the node p with n elements. + template <typename NodeT> + NodeRef(NodeT *p, unsigned n) : pip(p, n - 1) { + assert(n <= NodeT::Capacity && "Size too big for node"); + } + + /// size - Return the number of elements in the referenced node. + unsigned size() const { return pip.getInt() + 1; } + + /// setSize - Update the node size. + void setSize(unsigned n) { pip.setInt(n - 1); } + + /// subtree - Access the i'th subtree reference in a branch node. + /// This depends on branch nodes storing the NodeRef array as their first + /// member. + NodeRef &subtree(unsigned i) const { + return reinterpret_cast<NodeRef*>(pip.getPointer())[i]; + } + + /// get - Dereference as a NodeT reference. + template <typename NodeT> + NodeT &get() const { + return *reinterpret_cast<NodeT*>(pip.getPointer()); + } + + bool operator==(const NodeRef &RHS) const { + if (pip == RHS.pip) + return true; + assert(pip.getPointer() != RHS.pip.getPointer() && "Inconsistent NodeRefs"); + return false; + } + + bool operator!=(const NodeRef &RHS) const { + return !operator==(RHS); + } +}; + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::LeafNode ---// +//===----------------------------------------------------------------------===// +// +// Leaf nodes store up to N disjoint intervals with corresponding values. +// +// The intervals are kept sorted and fully coalesced so there are no adjacent +// intervals mapping to the same value. +// +// These constraints are always satisfied: +// +// - Traits::stopLess(start(i), stop(i)) - Non-empty, sane intervals. +// +// - Traits::stopLess(stop(i), start(i + 1) - Sorted. +// +// - value(i) != value(i + 1) || !Traits::adjacent(stop(i), start(i + 1)) +// - Fully coalesced. +// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +class LeafNode : public NodeBase<std::pair<KeyT, KeyT>, ValT, N> { +public: + const KeyT &start(unsigned i) const { return this->first[i].first; } + const KeyT &stop(unsigned i) const { return this->first[i].second; } + const ValT &value(unsigned i) const { return this->second[i]; } + + KeyT &start(unsigned i) { return this->first[i].first; } + KeyT &stop(unsigned i) { return this->first[i].second; } + ValT &value(unsigned i) { return this->second[i]; } + + /// findFrom - Find the first interval after i that may contain x. + /// @param i Starting index for the search. + /// @param Size Number of elements in node. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i].stop, x), or size. + /// This is the first interval that can possibly contain x. + unsigned findFrom(unsigned i, unsigned Size, KeyT x) const { + assert(i <= Size && Size <= N && "Bad indices"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index is past the needed point"); + while (i != Size && Traits::stopLess(stop(i), x)) ++i; + return i; + } + + /// safeFind - Find an interval that is known to exist. This is the same as + /// findFrom except is it assumed that x is at least within range of the last + /// interval. + /// @param i Starting index for the search. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i].stop, x), never size. + /// This is the first interval that can possibly contain x. + unsigned safeFind(unsigned i, KeyT x) const { + assert(i < N && "Bad index"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index is past the needed point"); + while (Traits::stopLess(stop(i), x)) ++i; + assert(i < N && "Unsafe intervals"); + return i; + } + + /// safeLookup - Lookup mapped value for a safe key. + /// It is assumed that x is within range of the last entry. + /// @param x Key to search for. + /// @param NotFound Value to return if x is not in any interval. + /// @return The mapped value at x or NotFound. + ValT safeLookup(KeyT x, ValT NotFound) const { + unsigned i = safeFind(0, x); + return Traits::startLess(x, start(i)) ? NotFound : value(i); + } + + unsigned insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y); +}; + +/// insertFrom - Add mapping of [a;b] to y if possible, coalescing as much as +/// possible. This may cause the node to grow by 1, or it may cause the node +/// to shrink because of coalescing. +/// @param i Starting index = insertFrom(0, size, a) +/// @param Size Number of elements in node. +/// @param a Interval start. +/// @param b Interval stop. +/// @param y Value be mapped. +/// @return (insert position, new size), or (i, Capacity+1) on overflow. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +unsigned LeafNode<KeyT, ValT, N, Traits>:: +insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y) { + unsigned i = Pos; + assert(i <= Size && Size <= N && "Invalid index"); + assert(!Traits::stopLess(b, a) && "Invalid interval"); + + // Verify the findFrom invariant. + assert((i == 0 || Traits::stopLess(stop(i - 1), a))); + assert((i == Size || !Traits::stopLess(stop(i), a))); + assert((i == Size || Traits::stopLess(b, start(i))) && "Overlapping insert"); + + // Coalesce with previous interval. + if (i && value(i - 1) == y && Traits::adjacent(stop(i - 1), a)) { + Pos = i - 1; + // Also coalesce with next interval? + if (i != Size && value(i) == y && Traits::adjacent(b, start(i))) { + stop(i - 1) = stop(i); + this->erase(i, Size); + return Size - 1; + } + stop(i - 1) = b; + return Size; + } + + // Detect overflow. + if (i == N) + return N + 1; + + // Add new interval at end. + if (i == Size) { + start(i) = a; + stop(i) = b; + value(i) = y; + return Size + 1; + } + + // Try to coalesce with following interval. + if (value(i) == y && Traits::adjacent(b, start(i))) { + start(i) = a; + return Size; + } + + // We must insert before i. Detect overflow. + if (Size == N) + return N + 1; + + // Insert before i. + this->shift(i, Size); + start(i) = a; + stop(i) = b; + value(i) = y; + return Size + 1; +} + + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::BranchNode ---// +//===----------------------------------------------------------------------===// +// +// A branch node stores references to 1--N subtrees all of the same height. +// +// The key array in a branch node holds the rightmost stop key of each subtree. +// It is redundant to store the last stop key since it can be found in the +// parent node, but doing so makes tree balancing a lot simpler. +// +// It is unusual for a branch node to only have one subtree, but it can happen +// in the root node if it is smaller than the normal nodes. +// +// When all of the leaf nodes from all the subtrees are concatenated, they must +// satisfy the same constraints as a single leaf node. They must be sorted, +// sane, and fully coalesced. +// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +class BranchNode : public NodeBase<NodeRef, KeyT, N> { +public: + const KeyT &stop(unsigned i) const { return this->second[i]; } + const NodeRef &subtree(unsigned i) const { return this->first[i]; } + + KeyT &stop(unsigned i) { return this->second[i]; } + NodeRef &subtree(unsigned i) { return this->first[i]; } + + /// findFrom - Find the first subtree after i that may contain x. + /// @param i Starting index for the search. + /// @param Size Number of elements in node. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i], x), or size. + /// This is the first subtree that can possibly contain x. + unsigned findFrom(unsigned i, unsigned Size, KeyT x) const { + assert(i <= Size && Size <= N && "Bad indices"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index to findFrom is past the needed point"); + while (i != Size && Traits::stopLess(stop(i), x)) ++i; + return i; + } + + /// safeFind - Find a subtree that is known to exist. This is the same as + /// findFrom except is it assumed that x is in range. + /// @param i Starting index for the search. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i], x), never size. + /// This is the first subtree that can possibly contain x. + unsigned safeFind(unsigned i, KeyT x) const { + assert(i < N && "Bad index"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index is past the needed point"); + while (Traits::stopLess(stop(i), x)) ++i; + assert(i < N && "Unsafe intervals"); + return i; + } + + /// safeLookup - Get the subtree containing x, Assuming that x is in range. + /// @param x Key to search for. + /// @return Subtree containing x + NodeRef safeLookup(KeyT x) const { + return subtree(safeFind(0, x)); + } + + /// insert - Insert a new (subtree, stop) pair. + /// @param i Insert position, following entries will be shifted. + /// @param Size Number of elements in node. + /// @param Node Subtree to insert. + /// @param Stop Last key in subtree. + void insert(unsigned i, unsigned Size, NodeRef Node, KeyT Stop) { + assert(Size < N && "branch node overflow"); + assert(i <= Size && "Bad insert position"); + this->shift(i, Size); + subtree(i) = Node; + stop(i) = Stop; + } +}; + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::Path ---// +//===----------------------------------------------------------------------===// +// +// A Path is used by iterators to represent a position in a B+-tree, and the +// path to get there from the root. +// +// The Path class also constains the tree navigation code that doesn't have to +// be templatized. +// +//===----------------------------------------------------------------------===// + +class Path { + /// Entry - Each step in the path is a node pointer and an offset into that + /// node. + struct Entry { + void *node; + unsigned size; + unsigned offset; + + Entry(void *Node, unsigned Size, unsigned Offset) + : node(Node), size(Size), offset(Offset) {} + + Entry(NodeRef Node, unsigned Offset) + : node(&Node.subtree(0)), size(Node.size()), offset(Offset) {} + + NodeRef &subtree(unsigned i) const { + return reinterpret_cast<NodeRef*>(node)[i]; + } + }; + + /// path - The path entries, path[0] is the root node, path.back() is a leaf. + SmallVector<Entry, 4> path; + +public: + // Node accessors. + template <typename NodeT> NodeT &node(unsigned Level) const { + return *reinterpret_cast<NodeT*>(path[Level].node); + } + unsigned size(unsigned Level) const { return path[Level].size; } + unsigned offset(unsigned Level) const { return path[Level].offset; } + unsigned &offset(unsigned Level) { return path[Level].offset; } + + // Leaf accessors. + template <typename NodeT> NodeT &leaf() const { + return *reinterpret_cast<NodeT*>(path.back().node); + } + unsigned leafSize() const { return path.back().size; } + unsigned leafOffset() const { return path.back().offset; } + unsigned &leafOffset() { return path.back().offset; } + + /// valid - Return true if path is at a valid node, not at end(). + bool valid() const { + return !path.empty() && path.front().offset < path.front().size; + } + + /// height - Return the height of the tree corresponding to this path. + /// This matches map->height in a full path. + unsigned height() const { return path.size() - 1; } + + /// subtree - Get the subtree referenced from Level. When the path is + /// consistent, node(Level + 1) == subtree(Level). + /// @param Level 0..height-1. The leaves have no subtrees. + NodeRef &subtree(unsigned Level) const { + return path[Level].subtree(path[Level].offset); + } + + /// reset - Reset cached information about node(Level) from subtree(Level -1). + /// @param Level 1..height. THe node to update after parent node changed. + void reset(unsigned Level) { + path[Level] = Entry(subtree(Level - 1), offset(Level)); + } + + /// push - Add entry to path. + /// @param Node Node to add, should be subtree(path.size()-1). + /// @param Offset Offset into Node. + void push(NodeRef Node, unsigned Offset) { + path.push_back(Entry(Node, Offset)); + } + + /// pop - Remove the last path entry. + void pop() { + path.pop_back(); + } + + /// setSize - Set the size of a node both in the path and in the tree. + /// @param Level 0..height. Note that setting the root size won't change + /// map->rootSize. + /// @param Size New node size. + void setSize(unsigned Level, unsigned Size) { + path[Level].size = Size; + if (Level) + subtree(Level - 1).setSize(Size); + } + + /// setRoot - Clear the path and set a new root node. + /// @param Node New root node. + /// @param Size New root size. + /// @param Offset Offset into root node. + void setRoot(void *Node, unsigned Size, unsigned Offset) { + path.clear(); + path.push_back(Entry(Node, Size, Offset)); + } + + /// replaceRoot - Replace the current root node with two new entries after the + /// tree height has increased. + /// @param Root The new root node. + /// @param Size Number of entries in the new root. + /// @param Offsets Offsets into the root and first branch nodes. + void replaceRoot(void *Root, unsigned Size, IdxPair Offsets); + + /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef. + /// @param Level Get the sibling to node(Level). + /// @return Left sibling, or NodeRef(). + NodeRef getLeftSibling(unsigned Level) const; + + /// moveLeft - Move path to the left sibling at Level. Leave nodes below Level + /// unaltered. + /// @param Level Move node(Level). + void moveLeft(unsigned Level); + + /// fillLeft - Grow path to Height by taking leftmost branches. + /// @param Height The target height. + void fillLeft(unsigned Height) { + while (height() < Height) + push(subtree(height()), 0); + } + + /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef. + /// @param Level Get the sinbling to node(Level). + /// @return Left sibling, or NodeRef(). + NodeRef getRightSibling(unsigned Level) const; + + /// moveRight - Move path to the left sibling at Level. Leave nodes below + /// Level unaltered. + /// @param Level Move node(Level). + void moveRight(unsigned Level); + + /// atBegin - Return true if path is at begin(). + bool atBegin() const { + for (unsigned i = 0, e = path.size(); i != e; ++i) + if (path[i].offset != 0) + return false; + return true; + } + + /// atLastEntry - Return true if the path is at the last entry of the node at + /// Level. + /// @param Level Node to examine. + bool atLastEntry(unsigned Level) const { + return path[Level].offset == path[Level].size - 1; + } + + /// legalizeForInsert - Prepare the path for an insertion at Level. When the + /// path is at end(), node(Level) may not be a legal node. legalizeForInsert + /// ensures that node(Level) is real by moving back to the last node at Level, + /// and setting offset(Level) to size(Level) if required. + /// @param Level The level where an insertion is about to take place. + void legalizeForInsert(unsigned Level) { + if (valid()) + return; + moveLeft(Level); + ++path[Level].offset; + } +}; + +} // namespace IntervalMapImpl + + +//===----------------------------------------------------------------------===// +//--- IntervalMap ----// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, + unsigned N = IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize, + typename Traits = IntervalMapInfo<KeyT> > +class IntervalMap { + typedef IntervalMapImpl::NodeSizer<KeyT, ValT> Sizer; + typedef IntervalMapImpl::LeafNode<KeyT, ValT, Sizer::LeafSize, Traits> Leaf; + typedef IntervalMapImpl::BranchNode<KeyT, ValT, Sizer::BranchSize, Traits> + Branch; + typedef IntervalMapImpl::LeafNode<KeyT, ValT, N, Traits> RootLeaf; + typedef IntervalMapImpl::IdxPair IdxPair; + + // The RootLeaf capacity is given as a template parameter. We must compute the + // corresponding RootBranch capacity. + enum { + DesiredRootBranchCap = (sizeof(RootLeaf) - sizeof(KeyT)) / + (sizeof(KeyT) + sizeof(IntervalMapImpl::NodeRef)), + RootBranchCap = DesiredRootBranchCap ? DesiredRootBranchCap : 1 + }; + + typedef IntervalMapImpl::BranchNode<KeyT, ValT, RootBranchCap, Traits> + RootBranch; + + // When branched, we store a global start key as well as the branch node. + struct RootBranchData { + KeyT start; + RootBranch node; + }; + + enum { + RootDataSize = sizeof(RootBranchData) > sizeof(RootLeaf) ? + sizeof(RootBranchData) : sizeof(RootLeaf) + }; + +public: + typedef typename Sizer::Allocator Allocator; + typedef KeyT KeyType; + typedef ValT ValueType; + typedef Traits KeyTraits; + +private: + // The root data is either a RootLeaf or a RootBranchData instance. + // We can't put them in a union since C++03 doesn't allow non-trivial + // constructors in unions. + // Instead, we use a char array with pointer alignment. The alignment is + // ensured by the allocator member in the class, but still verified in the + // constructor. We don't support keys or values that are more aligned than a + // pointer. + char data[RootDataSize]; + + // Tree height. + // 0: Leaves in root. + // 1: Root points to leaf. + // 2: root->branch->leaf ... + unsigned height; + + // Number of entries in the root node. + unsigned rootSize; + + // Allocator used for creating external nodes. + Allocator &allocator; + + /// dataAs - 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; + return *u.t; + } + + const RootLeaf &rootLeaf() const { + assert(!branched() && "Cannot acces leaf data in branched root"); + return dataAs<RootLeaf>(); + } + RootLeaf &rootLeaf() { + assert(!branched() && "Cannot acces leaf data in branched root"); + return dataAs<RootLeaf>(); + } + RootBranchData &rootBranchData() const { + assert(branched() && "Cannot access branch data in non-branched root"); + return dataAs<RootBranchData>(); + } + RootBranchData &rootBranchData() { + assert(branched() && "Cannot access branch data in non-branched root"); + return dataAs<RootBranchData>(); + } + const RootBranch &rootBranch() const { return rootBranchData().node; } + RootBranch &rootBranch() { return rootBranchData().node; } + KeyT rootBranchStart() const { return rootBranchData().start; } + KeyT &rootBranchStart() { return rootBranchData().start; } + + template <typename NodeT> NodeT *newNode() { + return new(allocator.template Allocate<NodeT>()) NodeT(); + } + + template <typename NodeT> void deleteNode(NodeT *P) { + P->~NodeT(); + allocator.Deallocate(P); + } + + IdxPair branchRoot(unsigned Position); + IdxPair splitRoot(unsigned Position); + + void switchRootToBranch() { + rootLeaf().~RootLeaf(); + height = 1; + new (&rootBranchData()) RootBranchData(); + } + + void switchRootToLeaf() { + rootBranchData().~RootBranchData(); + height = 0; + new(&rootLeaf()) RootLeaf(); + } + + bool branched() const { return height > 0; } + + ValT treeSafeLookup(KeyT x, ValT NotFound) const; + void visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef, + unsigned Level)); + void deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level); + +public: + explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) { + assert((uintptr_t(data) & (alignOf<RootLeaf>() - 1)) == 0 && + "Insufficient alignment"); + new(&rootLeaf()) RootLeaf(); + } + + ~IntervalMap() { + clear(); + rootLeaf().~RootLeaf(); + } + + /// empty - Return true when no intervals are mapped. + bool empty() const { + return rootSize == 0; + } + + /// start - Return the smallest mapped key in a non-empty map. + KeyT start() const { + assert(!empty() && "Empty IntervalMap has no start"); + return !branched() ? rootLeaf().start(0) : rootBranchStart(); + } + + /// stop - Return the largest mapped key in a non-empty map. + KeyT stop() const { + assert(!empty() && "Empty IntervalMap has no stop"); + return !branched() ? rootLeaf().stop(rootSize - 1) : + rootBranch().stop(rootSize - 1); + } + + /// lookup - Return the mapped value at x or NotFound. + ValT lookup(KeyT x, ValT NotFound = ValT()) const { + if (empty() || Traits::startLess(x, start()) || Traits::stopLess(stop(), x)) + return NotFound; + return branched() ? treeSafeLookup(x, NotFound) : + rootLeaf().safeLookup(x, NotFound); + } + + /// insert - Add a mapping of [a;b] to y, coalesce with adjacent intervals. + /// It is assumed that no key in the interval is mapped to another value, but + /// overlapping intervals already mapped to y will be coalesced. + void insert(KeyT a, KeyT b, ValT y) { + if (branched() || rootSize == RootLeaf::Capacity) + return find(a).insert(a, b, y); + + // Easy insert into root leaf. + unsigned p = rootLeaf().findFrom(0, rootSize, a); + rootSize = rootLeaf().insertFrom(p, rootSize, a, b, y); + } + + /// clear - Remove all entries. + void clear(); + + class const_iterator; + class iterator; + friend class const_iterator; + friend class iterator; + + const_iterator begin() const { + const_iterator I(*this); + I.goToBegin(); + return I; + } + + iterator begin() { + iterator I(*this); + I.goToBegin(); + return I; + } + + const_iterator end() const { + const_iterator I(*this); + I.goToEnd(); + return I; + } + + iterator end() { + iterator I(*this); + I.goToEnd(); + return I; + } + + /// find - Return an iterator pointing to the first interval ending at or + /// after x, or end(). + const_iterator find(KeyT x) const { + const_iterator I(*this); + I.find(x); + return I; + } + + iterator find(KeyT x) { + iterator I(*this); + I.find(x); + return I; + } +}; + +/// treeSafeLookup - Return the mapped value at x or NotFound, assuming a +/// branched root. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +ValT IntervalMap<KeyT, ValT, N, Traits>:: +treeSafeLookup(KeyT x, ValT NotFound) const { + assert(branched() && "treeLookup assumes a branched root"); + + IntervalMapImpl::NodeRef NR = rootBranch().safeLookup(x); + for (unsigned h = height-1; h; --h) + NR = NR.get<Branch>().safeLookup(x); + return NR.get<Leaf>().safeLookup(x, NotFound); +} + + +// branchRoot - Switch from a leaf root to a branched root. +// Return the new (root offset, node offset) corresponding to Position. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>:: +branchRoot(unsigned Position) { + using namespace IntervalMapImpl; + // How many external leaf nodes to hold RootLeaf+1? + const unsigned Nodes = RootLeaf::Capacity / Leaf::Capacity + 1; + + // Compute element distribution among new nodes. + unsigned size[Nodes]; + IdxPair NewOffset(0, Position); + + // Is is very common for the root node to be smaller than external nodes. + if (Nodes == 1) + size[0] = rootSize; + else + NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, NULL, size, + Position, true); + + // Allocate new nodes. + unsigned pos = 0; + NodeRef node[Nodes]; + for (unsigned n = 0; n != Nodes; ++n) { + Leaf *L = newNode<Leaf>(); + L->copy(rootLeaf(), pos, 0, size[n]); + node[n] = NodeRef(L, size[n]); + pos += size[n]; + } + + // Destroy the old leaf node, construct branch node instead. + switchRootToBranch(); + for (unsigned n = 0; n != Nodes; ++n) { + rootBranch().stop(n) = node[n].template get<Leaf>().stop(size[n]-1); + rootBranch().subtree(n) = node[n]; + } + rootBranchStart() = node[0].template get<Leaf>().start(0); + rootSize = Nodes; + return NewOffset; +} + +// splitRoot - Split the current BranchRoot into multiple Branch nodes. +// Return the new (root offset, node offset) corresponding to Position. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>:: +splitRoot(unsigned Position) { + using namespace IntervalMapImpl; + // How many external leaf nodes to hold RootBranch+1? + const unsigned Nodes = RootBranch::Capacity / Branch::Capacity + 1; + + // Compute element distribution among new nodes. + unsigned Size[Nodes]; + IdxPair NewOffset(0, Position); + + // Is is very common for the root node to be smaller than external nodes. + if (Nodes == 1) + Size[0] = rootSize; + else + NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, NULL, Size, + Position, true); + + // Allocate new nodes. + unsigned Pos = 0; + NodeRef Node[Nodes]; + for (unsigned n = 0; n != Nodes; ++n) { + Branch *B = newNode<Branch>(); + B->copy(rootBranch(), Pos, 0, Size[n]); + Node[n] = NodeRef(B, Size[n]); + Pos += Size[n]; + } + + for (unsigned n = 0; n != Nodes; ++n) { + rootBranch().stop(n) = Node[n].template get<Branch>().stop(Size[n]-1); + rootBranch().subtree(n) = Node[n]; + } + rootSize = Nodes; + ++height; + return NewOffset; +} + +/// visitNodes - Visit each external node. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef, unsigned Height)) { + if (!branched()) + return; + SmallVector<IntervalMapImpl::NodeRef, 4> Refs, NextRefs; + + // Collect level 0 nodes from the root. + for (unsigned i = 0; i != rootSize; ++i) + Refs.push_back(rootBranch().subtree(i)); + + // Visit all branch nodes. + for (unsigned h = height - 1; h; --h) { + for (unsigned i = 0, e = Refs.size(); i != e; ++i) { + for (unsigned j = 0, s = Refs[i].size(); j != s; ++j) + NextRefs.push_back(Refs[i].subtree(j)); + (this->*f)(Refs[i], h); + } + Refs.clear(); + Refs.swap(NextRefs); + } + + // Visit all leaf nodes. + for (unsigned i = 0, e = Refs.size(); i != e; ++i) + (this->*f)(Refs[i], 0); +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level) { + if (Level) + deleteNode(&Node.get<Branch>()); + else + deleteNode(&Node.get<Leaf>()); +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +clear() { + if (branched()) { + visitNodes(&IntervalMap::deleteNode); + switchRootToLeaf(); + } + rootSize = 0; +} + +//===----------------------------------------------------------------------===// +//--- IntervalMap::const_iterator ----// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +class IntervalMap<KeyT, ValT, N, Traits>::const_iterator : + public std::iterator<std::bidirectional_iterator_tag, ValT> { +protected: + friend class IntervalMap; + + // The map referred to. + IntervalMap *map; + + // We store a full path from the root to the current position. + // The path may be partially filled, but never between iterator calls. + IntervalMapImpl::Path path; + + explicit const_iterator(const IntervalMap &map) : + map(const_cast<IntervalMap*>(&map)) {} + + bool branched() const { + assert(map && "Invalid iterator"); + return map->branched(); + } + + void setRoot(unsigned Offset) { + if (branched()) + path.setRoot(&map->rootBranch(), map->rootSize, Offset); + else + path.setRoot(&map->rootLeaf(), map->rootSize, Offset); + } + + void pathFillFind(KeyT x); + void treeFind(KeyT x); + void treeAdvanceTo(KeyT x); + + /// unsafeStart - Writable access to start() for iterator. + KeyT &unsafeStart() const { + assert(valid() && "Cannot access invalid iterator"); + return branched() ? path.leaf<Leaf>().start(path.leafOffset()) : + path.leaf<RootLeaf>().start(path.leafOffset()); + } + + /// unsafeStop - Writable access to stop() for iterator. + KeyT &unsafeStop() const { + assert(valid() && "Cannot access invalid iterator"); + return branched() ? path.leaf<Leaf>().stop(path.leafOffset()) : + path.leaf<RootLeaf>().stop(path.leafOffset()); + } + + /// unsafeValue - Writable access to value() for iterator. + ValT &unsafeValue() const { + assert(valid() && "Cannot access invalid iterator"); + return branched() ? path.leaf<Leaf>().value(path.leafOffset()) : + path.leaf<RootLeaf>().value(path.leafOffset()); + } + +public: + /// const_iterator - Create an iterator that isn't pointing anywhere. + const_iterator() : map(0) {} + + /// valid - Return true if the current position is valid, false for end(). + bool valid() const { return path.valid(); } + + /// start - Return the beginning of the current interval. + const KeyT &start() const { return unsafeStart(); } + + /// stop - Return the end of the current interval. + const KeyT &stop() const { return unsafeStop(); } + + /// value - Return the mapped value at the current interval. + const ValT &value() const { return unsafeValue(); } + + const ValT &operator*() const { return value(); } + + bool operator==(const const_iterator &RHS) const { + assert(map == RHS.map && "Cannot compare iterators from different maps"); + if (!valid()) + return !RHS.valid(); + if (path.leafOffset() != RHS.path.leafOffset()) + return false; + return &path.template leaf<Leaf>() == &RHS.path.template leaf<Leaf>(); + } + + bool operator!=(const const_iterator &RHS) const { + return !operator==(RHS); + } + + /// goToBegin - Move to the first interval in map. + void goToBegin() { + setRoot(0); + if (branched()) + path.fillLeft(map->height); + } + + /// goToEnd - Move beyond the last interval in map. + void goToEnd() { + setRoot(map->rootSize); + } + + /// preincrement - move to the next interval. + const_iterator &operator++() { + assert(valid() && "Cannot increment end()"); + if (++path.leafOffset() == path.leafSize() && branched()) + path.moveRight(map->height); + return *this; + } + + /// postincrement - Dont do that! + const_iterator operator++(int) { + const_iterator tmp = *this; + operator++(); + return tmp; + } + + /// predecrement - move to the previous interval. + const_iterator &operator--() { + if (path.leafOffset() && (valid() || !branched())) + --path.leafOffset(); + else + path.moveLeft(map->height); + return *this; + } + + /// postdecrement - Dont do that! + const_iterator operator--(int) { + const_iterator tmp = *this; + operator--(); + return tmp; + } + + /// find - Move to the first interval with stop >= x, or end(). + /// This is a full search from the root, the current position is ignored. + void find(KeyT x) { + if (branched()) + treeFind(x); + else + setRoot(map->rootLeaf().findFrom(0, map->rootSize, x)); + } + + /// advanceTo - Move to the first interval with stop >= x, or end(). + /// The search is started from the current position, and no earlier positions + /// can be found. This is much faster than find() for small moves. + void advanceTo(KeyT x) { + if (!valid()) + return; + if (branched()) + treeAdvanceTo(x); + else + path.leafOffset() = + map->rootLeaf().findFrom(path.leafOffset(), map->rootSize, x); + } + +}; + +/// pathFillFind - Complete path by searching for x. +/// @param x Key to search for. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +const_iterator::pathFillFind(KeyT x) { + IntervalMapImpl::NodeRef NR = path.subtree(path.height()); + for (unsigned i = map->height - path.height() - 1; i; --i) { + unsigned p = NR.get<Branch>().safeFind(0, x); + path.push(NR, p); + NR = NR.subtree(p); + } + path.push(NR, NR.get<Leaf>().safeFind(0, x)); +} + +/// treeFind - Find in a branched tree. +/// @param x Key to search for. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +const_iterator::treeFind(KeyT x) { + setRoot(map->rootBranch().findFrom(0, map->rootSize, x)); + if (valid()) + pathFillFind(x); +} + +/// treeAdvanceTo - Find position after the current one. +/// @param x Key to search for. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +const_iterator::treeAdvanceTo(KeyT x) { + // Can we stay on the same leaf node? + if (!Traits::stopLess(path.leaf<Leaf>().stop(path.leafSize() - 1), x)) { + path.leafOffset() = path.leaf<Leaf>().safeFind(path.leafOffset(), x); + return; + } + + // Drop the current leaf. + path.pop(); + + // Search towards the root for a usable subtree. + if (path.height()) { + for (unsigned l = path.height() - 1; l; --l) { + if (!Traits::stopLess(path.node<Branch>(l).stop(path.offset(l)), x)) { + // The branch node at l+1 is usable + path.offset(l + 1) = + path.node<Branch>(l + 1).safeFind(path.offset(l + 1), x); + return pathFillFind(x); + } + path.pop(); + } + // Is the level-1 Branch usable? + if (!Traits::stopLess(map->rootBranch().stop(path.offset(0)), x)) { + path.offset(1) = path.node<Branch>(1).safeFind(path.offset(1), x); + return pathFillFind(x); + } + } + + // We reached the root. + setRoot(map->rootBranch().findFrom(path.offset(0), map->rootSize, x)); + if (valid()) + pathFillFind(x); +} + +//===----------------------------------------------------------------------===// +//--- IntervalMap::iterator ----// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +class IntervalMap<KeyT, ValT, N, Traits>::iterator : public const_iterator { + friend class IntervalMap; + typedef IntervalMapImpl::IdxPair IdxPair; + + explicit iterator(IntervalMap &map) : const_iterator(map) {} + + void setNodeStop(unsigned Level, KeyT Stop); + bool insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop); + template <typename NodeT> bool overflow(unsigned Level); + void treeInsert(KeyT a, KeyT b, ValT y); + void eraseNode(unsigned Level); + void treeErase(bool UpdateRoot = true); + bool canCoalesceLeft(KeyT Start, ValT x); + bool canCoalesceRight(KeyT Stop, ValT x); + +public: + /// iterator - Create null iterator. + iterator() {} + + /// setStart - Move the start of the current interval. + /// This may cause coalescing with the previous interval. + /// @param a New start key, must not overlap the previous interval. + void setStart(KeyT a); + + /// setStop - Move the end of the current interval. + /// This may cause coalescing with the following interval. + /// @param b New stop key, must not overlap the following interval. + void setStop(KeyT b); + + /// setValue - Change the mapped value of the current interval. + /// This may cause coalescing with the previous and following intervals. + /// @param x New value. + void setValue(ValT x); + + /// setStartUnchecked - Move the start of the current interval without + /// checking for coalescing or overlaps. + /// This should only be used when it is known that coalescing is not required. + /// @param a New start key. + void setStartUnchecked(KeyT a) { this->unsafeStart() = a; } + + /// setStopUnchecked - Move the end of the current interval without checking + /// for coalescing or overlaps. + /// This should only be used when it is known that coalescing is not required. + /// @param b New stop key. + void setStopUnchecked(KeyT b) { + this->unsafeStop() = b; + // Update keys in branch nodes as well. + if (this->path.atLastEntry(this->path.height())) + setNodeStop(this->path.height(), b); + } + + /// setValueUnchecked - Change the mapped value of the current interval + /// without checking for coalescing. + /// @param x New value. + void setValueUnchecked(ValT x) { this->unsafeValue() = x; } + + /// insert - Insert mapping [a;b] -> y before the current position. + void insert(KeyT a, KeyT b, ValT y); + + /// erase - Erase the current interval. + void erase(); + + iterator &operator++() { + const_iterator::operator++(); + return *this; + } + + iterator operator++(int) { + iterator tmp = *this; + operator++(); + return tmp; + } + + iterator &operator--() { + const_iterator::operator--(); + return *this; + } + + iterator operator--(int) { + iterator tmp = *this; + operator--(); + return tmp; + } + +}; + +/// canCoalesceLeft - Can the current interval coalesce to the left after +/// changing start or value? +/// @param Start New start of current interval. +/// @param Value New value for current interval. +/// @return True when updating the current interval would enable coalescing. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +bool IntervalMap<KeyT, ValT, N, Traits>:: +iterator::canCoalesceLeft(KeyT Start, ValT Value) { + using namespace IntervalMapImpl; + Path &P = this->path; + if (!this->branched()) { + unsigned i = P.leafOffset(); + RootLeaf &Node = P.leaf<RootLeaf>(); + return i && Node.value(i-1) == Value && + Traits::adjacent(Node.stop(i-1), Start); + } + // Branched. + if (unsigned i = P.leafOffset()) { + Leaf &Node = P.leaf<Leaf>(); + return Node.value(i-1) == Value && Traits::adjacent(Node.stop(i-1), Start); + } else if (NodeRef NR = P.getLeftSibling(P.height())) { + unsigned i = NR.size() - 1; + Leaf &Node = NR.get<Leaf>(); + return Node.value(i) == Value && Traits::adjacent(Node.stop(i), Start); + } + return false; +} + +/// canCoalesceRight - Can the current interval coalesce to the right after +/// changing stop or value? +/// @param Stop New stop of current interval. +/// @param Value New value for current interval. +/// @return True when updating the current interval would enable coalescing. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +bool IntervalMap<KeyT, ValT, N, Traits>:: +iterator::canCoalesceRight(KeyT Stop, ValT Value) { + using namespace IntervalMapImpl; + Path &P = this->path; + unsigned i = P.leafOffset() + 1; + if (!this->branched()) { + if (i >= P.leafSize()) + return false; + RootLeaf &Node = P.leaf<RootLeaf>(); + return Node.value(i) == Value && Traits::adjacent(Stop, Node.start(i)); + } + // Branched. + if (i < P.leafSize()) { + Leaf &Node = P.leaf<Leaf>(); + return Node.value(i) == Value && Traits::adjacent(Stop, Node.start(i)); + } else if (NodeRef NR = P.getRightSibling(P.height())) { + Leaf &Node = NR.get<Leaf>(); + return Node.value(0) == Value && Traits::adjacent(Stop, Node.start(0)); + } + return false; +} + +/// setNodeStop - Update the stop key of the current node at level and above. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::setNodeStop(unsigned Level, KeyT Stop) { + // There are no references to the root node, so nothing to update. + if (!Level) + return; + IntervalMapImpl::Path &P = this->path; + // Update nodes pointing to the current node. + while (--Level) { + P.node<Branch>(Level).stop(P.offset(Level)) = Stop; + if (!P.atLastEntry(Level)) + return; + } + // Update root separately since it has a different layout. + P.node<RootBranch>(Level).stop(P.offset(Level)) = Stop; +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::setStart(KeyT a) { + assert(Traits::stopLess(a, this->stop()) && "Cannot move start beyond stop"); + KeyT &CurStart = this->unsafeStart(); + if (!Traits::startLess(a, CurStart) || !canCoalesceLeft(a, this->value())) { + CurStart = a; + return; + } + // Coalesce with the interval to the left. + --*this; + a = this->start(); + erase(); + setStartUnchecked(a); +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::setStop(KeyT b) { + assert(Traits::stopLess(this->start(), b) && "Cannot move stop beyond start"); + if (Traits::startLess(b, this->stop()) || + !canCoalesceRight(b, this->value())) { + setStopUnchecked(b); + return; + } + // Coalesce with interval to the right. + KeyT a = this->start(); + erase(); + setStartUnchecked(a); +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::setValue(ValT x) { + setValueUnchecked(x); + if (canCoalesceRight(this->stop(), x)) { + KeyT a = this->start(); + erase(); + setStartUnchecked(a); + } + if (canCoalesceLeft(this->start(), x)) { + --*this; + KeyT a = this->start(); + erase(); + setStartUnchecked(a); + } +} + +/// insertNode - insert a node before the current path at level. +/// Leave the current path pointing at the new node. +/// @param Level path index of the node to be inserted. +/// @param Node The node to be inserted. +/// @param Stop The last index in the new node. +/// @return True if the tree height was increased. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +bool IntervalMap<KeyT, ValT, N, Traits>:: +iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) { + assert(Level && "Cannot insert next to the root"); + bool SplitRoot = false; + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + + if (Level == 1) { + // Insert into the root branch node. + if (IM.rootSize < RootBranch::Capacity) { + IM.rootBranch().insert(P.offset(0), IM.rootSize, Node, Stop); + P.setSize(0, ++IM.rootSize); + P.reset(Level); + return SplitRoot; + } + + // We need to split the root while keeping our position. + SplitRoot = true; + IdxPair Offset = IM.splitRoot(P.offset(0)); + P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset); + + // Fall through to insert at the new higher level. + ++Level; + } + + // When inserting before end(), make sure we have a valid path. + P.legalizeForInsert(--Level); + + // Insert into the branch node at Level-1. + if (P.size(Level) == Branch::Capacity) { + // Branch node is full, handle handle the overflow. + assert(!SplitRoot && "Cannot overflow after splitting the root"); + SplitRoot = overflow<Branch>(Level); + Level += SplitRoot; + } + P.node<Branch>(Level).insert(P.offset(Level), P.size(Level), Node, Stop); + P.setSize(Level, P.size(Level) + 1); + if (P.atLastEntry(Level)) + setNodeStop(Level, Stop); + P.reset(Level + 1); + return SplitRoot; +} + +// insert +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::insert(KeyT a, KeyT b, ValT y) { + if (this->branched()) + return treeInsert(a, b, y); + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + + // Try simple root leaf insert. + unsigned Size = IM.rootLeaf().insertFrom(P.leafOffset(), IM.rootSize, a, b, y); + + // Was the root node insert successful? + if (Size <= RootLeaf::Capacity) { + P.setSize(0, IM.rootSize = Size); + return; + } + + // Root leaf node is full, we must branch. + IdxPair Offset = IM.branchRoot(P.leafOffset()); + P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset); + + // Now it fits in the new leaf. + treeInsert(a, b, y); +} + + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::treeInsert(KeyT a, KeyT b, ValT y) { + using namespace IntervalMapImpl; + Path &P = this->path; + + if (!P.valid()) + P.legalizeForInsert(this->map->height); + + // Check if this insertion will extend the node to the left. + if (P.leafOffset() == 0 && Traits::startLess(a, P.leaf<Leaf>().start(0))) { + // Node is growing to the left, will it affect a left sibling node? + if (NodeRef Sib = P.getLeftSibling(P.height())) { + Leaf &SibLeaf = Sib.get<Leaf>(); + unsigned SibOfs = Sib.size() - 1; + if (SibLeaf.value(SibOfs) == y && + Traits::adjacent(SibLeaf.stop(SibOfs), a)) { + // This insertion will coalesce with the last entry in SibLeaf. We can + // handle it in two ways: + // 1. Extend SibLeaf.stop to b and be done, or + // 2. Extend a to SibLeaf, erase the SibLeaf entry and continue. + // We prefer 1., but need 2 when coalescing to the right as well. + Leaf &CurLeaf = P.leaf<Leaf>(); + P.moveLeft(P.height()); + if (Traits::stopLess(b, CurLeaf.start(0)) && + (y != CurLeaf.value(0) || !Traits::adjacent(b, CurLeaf.start(0)))) { + // Easy, just extend SibLeaf and we're done. + setNodeStop(P.height(), SibLeaf.stop(SibOfs) = b); + return; + } else { + // We have both left and right coalescing. Erase the old SibLeaf entry + // and continue inserting the larger interval. + a = SibLeaf.start(SibOfs); + treeErase(/* UpdateRoot= */false); + } + } + } else { + // No left sibling means we are at begin(). Update cached bound. + this->map->rootBranchStart() = a; + } + } + + // When we are inserting at the end of a leaf node, we must update stops. + unsigned Size = P.leafSize(); + bool Grow = P.leafOffset() == Size; + Size = P.leaf<Leaf>().insertFrom(P.leafOffset(), Size, a, b, y); + + // Leaf insertion unsuccessful? Overflow and try again. + if (Size > Leaf::Capacity) { + overflow<Leaf>(P.height()); + Grow = P.leafOffset() == P.leafSize(); + Size = P.leaf<Leaf>().insertFrom(P.leafOffset(), P.leafSize(), a, b, y); + assert(Size <= Leaf::Capacity && "overflow() didn't make room"); + } + + // Inserted, update offset and leaf size. + P.setSize(P.height(), Size); + + // Insert was the last node entry, update stops. + if (Grow) + setNodeStop(P.height(), b); +} + +/// erase - erase the current interval and move to the next position. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::erase() { + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + assert(P.valid() && "Cannot erase end()"); + if (this->branched()) + return treeErase(); + IM.rootLeaf().erase(P.leafOffset(), IM.rootSize); + P.setSize(0, --IM.rootSize); +} + +/// treeErase - erase() for a branched tree. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::treeErase(bool UpdateRoot) { + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + Leaf &Node = P.leaf<Leaf>(); + + // Nodes are not allowed to become empty. + if (P.leafSize() == 1) { + IM.deleteNode(&Node); + eraseNode(IM.height); + // Update rootBranchStart if we erased begin(). + if (UpdateRoot && IM.branched() && P.valid() && P.atBegin()) + IM.rootBranchStart() = P.leaf<Leaf>().start(0); + return; + } + + // Erase current entry. + Node.erase(P.leafOffset(), P.leafSize()); + unsigned NewSize = P.leafSize() - 1; + P.setSize(IM.height, NewSize); + // When we erase the last entry, update stop and move to a legal position. + if (P.leafOffset() == NewSize) { + setNodeStop(IM.height, Node.stop(NewSize - 1)); + P.moveRight(IM.height); + } else if (UpdateRoot && P.atBegin()) + IM.rootBranchStart() = P.leaf<Leaf>().start(0); +} + +/// eraseNode - Erase the current node at Level from its parent and move path to +/// the first entry of the next sibling node. +/// The node must be deallocated by the caller. +/// @param Level 1..height, the root node cannot be erased. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::eraseNode(unsigned Level) { + assert(Level && "Cannot erase root node"); + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + + if (--Level == 0) { + IM.rootBranch().erase(P.offset(0), IM.rootSize); + P.setSize(0, --IM.rootSize); + // If this cleared the root, switch to height=0. + if (IM.empty()) { + IM.switchRootToLeaf(); + this->setRoot(0); + return; + } + } else { + // Remove node ref from branch node at Level. + Branch &Parent = P.node<Branch>(Level); + if (P.size(Level) == 1) { + // Branch node became empty, remove it recursively. + IM.deleteNode(&Parent); + eraseNode(Level); + } else { + // Branch node won't become empty. + Parent.erase(P.offset(Level), P.size(Level)); + unsigned NewSize = P.size(Level) - 1; + P.setSize(Level, NewSize); + // If we removed the last branch, update stop and move to a legal pos. + if (P.offset(Level) == NewSize) { + setNodeStop(Level, Parent.stop(NewSize - 1)); + P.moveRight(Level); + } + } + } + // Update path cache for the new right sibling position. + if (P.valid()) { + P.reset(Level + 1); + P.offset(Level + 1) = 0; + } +} + +/// overflow - Distribute entries of the current node evenly among +/// its siblings and ensure that the current node is not full. +/// This may require allocating a new node. +/// @param NodeT The type of node at Level (Leaf or Branch). +/// @param Level path index of the overflowing node. +/// @return True when the tree height was changed. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +template <typename NodeT> +bool IntervalMap<KeyT, ValT, N, Traits>:: +iterator::overflow(unsigned Level) { + using namespace IntervalMapImpl; + Path &P = this->path; + unsigned CurSize[4]; + NodeT *Node[4]; + unsigned Nodes = 0; + unsigned Elements = 0; + unsigned Offset = P.offset(Level); + + // Do we have a left sibling? + NodeRef LeftSib = P.getLeftSibling(Level); + if (LeftSib) { + Offset += Elements = CurSize[Nodes] = LeftSib.size(); + Node[Nodes++] = &LeftSib.get<NodeT>(); + } + + // Current node. + Elements += CurSize[Nodes] = P.size(Level); + Node[Nodes++] = &P.node<NodeT>(Level); + + // Do we have a right sibling? + NodeRef RightSib = P.getRightSibling(Level); + if (RightSib) { + Elements += CurSize[Nodes] = RightSib.size(); + Node[Nodes++] = &RightSib.get<NodeT>(); + } + + // Do we need to allocate a new node? + unsigned NewNode = 0; + if (Elements + 1 > Nodes * NodeT::Capacity) { + // Insert NewNode at the penultimate position, or after a single node. + NewNode = Nodes == 1 ? 1 : Nodes - 1; + CurSize[Nodes] = CurSize[NewNode]; + Node[Nodes] = Node[NewNode]; + CurSize[NewNode] = 0; + Node[NewNode] = this->map->newNode<NodeT>(); + ++Nodes; + } + + // Compute the new element distribution. + unsigned NewSize[4]; + IdxPair NewOffset = distribute(Nodes, Elements, NodeT::Capacity, + CurSize, NewSize, Offset, true); + adjustSiblingSizes(Node, Nodes, CurSize, NewSize); + + // Move current location to the leftmost node. + if (LeftSib) + P.moveLeft(Level); + + // Elements have been rearranged, now update node sizes and stops. + bool SplitRoot = false; + unsigned Pos = 0; + for (;;) { + KeyT Stop = Node[Pos]->stop(NewSize[Pos]-1); + if (NewNode && Pos == NewNode) { + SplitRoot = insertNode(Level, NodeRef(Node[Pos], NewSize[Pos]), Stop); + Level += SplitRoot; + } else { + P.setSize(Level, NewSize[Pos]); + setNodeStop(Level, Stop); + } + if (Pos + 1 == Nodes) + break; + P.moveRight(Level); + ++Pos; + } + + // Where was I? Find NewOffset. + while(Pos != NewOffset.first) { + P.moveLeft(Level); + --Pos; + } + P.offset(Level) = NewOffset.second; + return SplitRoot; +} + +//===----------------------------------------------------------------------===// +//--- IntervalMapOverlaps ----// +//===----------------------------------------------------------------------===// + +/// IntervalMapOverlaps - Iterate over the overlaps of mapped intervals in two +/// IntervalMaps. The maps may be different, but the KeyT and Traits types +/// should be the same. +/// +/// Typical uses: +/// +/// 1. Test for overlap: +/// bool overlap = IntervalMapOverlaps(a, b).valid(); +/// +/// 2. Enumerate overlaps: +/// for (IntervalMapOverlaps I(a, b); I.valid() ; ++I) { ... } +/// +template <typename MapA, typename MapB> +class IntervalMapOverlaps { + typedef typename MapA::KeyType KeyType; + typedef typename MapA::KeyTraits Traits; + typename MapA::const_iterator posA; + typename MapB::const_iterator posB; + + /// advance - Move posA and posB forward until reaching an overlap, or until + /// either meets end. + /// Don't move the iterators if they are already overlapping. + void advance() { + if (!valid()) + return; + + if (Traits::stopLess(posA.stop(), posB.start())) { + // A ends before B begins. Catch up. + posA.advanceTo(posB.start()); + if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start())) + return; + } else if (Traits::stopLess(posB.stop(), posA.start())) { + // B ends before A begins. Catch up. + posB.advanceTo(posA.start()); + if (!posB.valid() || !Traits::stopLess(posA.stop(), posB.start())) + return; + } else + // Already overlapping. + return; + + for (;;) { + // Make a.end > b.start. + posA.advanceTo(posB.start()); + if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start())) + return; + // Make b.end > a.start. + posB.advanceTo(posA.start()); + if (!posB.valid() || !Traits::stopLess(posA.stop(), posB.start())) + return; + } + } + +public: + /// IntervalMapOverlaps - Create an iterator for the overlaps of a and b. + IntervalMapOverlaps(const MapA &a, const MapB &b) + : posA(b.empty() ? a.end() : a.find(b.start())), + posB(posA.valid() ? b.find(posA.start()) : b.end()) { advance(); } + + /// valid - Return true if iterator is at an overlap. + bool valid() const { + return posA.valid() && posB.valid(); + } + + /// a - access the left hand side in the overlap. + const typename MapA::const_iterator &a() const { return posA; } + + /// b - access the right hand side in the overlap. + const typename MapB::const_iterator &b() const { return posB; } + + /// start - Beginning of the overlapping interval. + KeyType start() const { + KeyType ak = a().start(); + KeyType bk = b().start(); + return Traits::startLess(ak, bk) ? bk : ak; + } + + /// stop - End of the overlapping interval. + KeyType stop() const { + KeyType ak = a().stop(); + KeyType bk = b().stop(); + return Traits::startLess(ak, bk) ? ak : bk; + } + + /// skipA - Move to the next overlap that doesn't involve a(). + void skipA() { + ++posA; + advance(); + } + + /// skipB - Move to the next overlap that doesn't involve b(). + void skipB() { + ++posB; + advance(); + } + + /// Preincrement - Move to the next overlap. + IntervalMapOverlaps &operator++() { + // Bump the iterator that ends first. The other one may have more overlaps. + if (Traits::startLess(posB.stop(), posA.stop())) + skipB(); + else + skipA(); + return *this; + } + + /// advanceTo - Move to the first overlapping interval with + /// stopLess(x, stop()). + void advanceTo(KeyType x) { + if (!valid()) + return; + // Make sure advanceTo sees monotonic keys. + if (Traits::stopLess(posA.stop(), x)) + posA.advanceTo(x); + if (Traits::stopLess(posB.stop(), x)) + posB.advanceTo(x); + advance(); + } +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 34e54a07a0..ee8b69f3d1 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -61,6 +61,60 @@ template <typename T> struct simplify_type<Optional<T> > : public simplify_type<const Optional<T> > {}; +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template<typename T, typename U> +void operator==(const Optional<T> &X, const Optional<U> &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template<typename T, typename U> +void operator!=(const Optional<T> &X, const Optional<U> &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template<typename T, typename U> +void operator<(const Optional<T> &X, const Optional<U> &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template<typename T, typename U> +void operator<=(const Optional<T> &X, const Optional<U> &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template<typename T, typename U> +void operator>=(const Optional<T> &X, const Optional<U> &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template<typename T, typename U> +void operator>(const Optional<T> &X, const Optional<U> &Y); + } // end llvm namespace #endif diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index 64f4a7cee4..85dbba2b4a 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -91,6 +91,13 @@ public: Value |= IntVal << IntShift; // Set new integer. } + PointerTy const *getAddrOfPointer() const { + assert(Value == reinterpret_cast<intptr_t>(getPointer()) && + "Can only return the address if IntBits is cleared and " + "PtrTraits doesn't change the pointer"); + return reinterpret_cast<PointerTy const *>(&Value); + } + void *getOpaqueValue() const { return reinterpret_cast<void*>(Value); } void setFromOpaqueValue(void *Val) { Value = reinterpret_cast<intptr_t>(Val);} diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h index 3a514b5626..61de042b0f 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -107,6 +107,18 @@ namespace llvm { if (is<T>()) return get<T>(); return T(); } + + /// \brief If the union is set to the first pointer type we can get an + /// address pointing to it. + template <typename T> + PT1 const *getAddrOf() const { + assert(is<PT1>() && "Val is not the first pointer"); + assert(get<PT1>() == Val.getPointer() && + "Can't get the address because PointerLikeTypeTraits changes the ptr"); + T const *can_only_get_address_of_first_pointer_type + = reinterpret_cast<PT1 const *>(Val.getAddrOfPointer()); + return can_only_get_address_of_first_pointer_type; + } /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h index 47e5b2bd4a..e3b499488d 100644 --- a/include/llvm/ADT/PostOrderIterator.h +++ b/include/llvm/ADT/PostOrderIterator.h @@ -56,8 +56,7 @@ class po_iterator : public std::iterator<std::forward_iterator_tag, void traverseChild() { while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) { NodeType *BB = *VisitStack.back().second++; - if (!this->Visited.count(BB)) { // If the block is not visited... - this->Visited.insert(BB); + if (this->Visited.insert(BB)) { // If the block is not visited... VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); } } @@ -72,8 +71,7 @@ class po_iterator : public std::iterator<std::forward_iterator_tag, inline po_iterator(NodeType *BB, SetType &S) : po_iterator_storage<SetType, ExtStorage>(S) { - if(!S.count(BB)) { - this->Visited.insert(BB); + if (this->Visited.insert(BB)) { VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); traverseChild(); } diff --git a/include/llvm/ADT/SCCIterator.h b/include/llvm/ADT/SCCIterator.h index c49d599cf3..3e93cfe914 100644 --- a/include/llvm/ADT/SCCIterator.h +++ b/include/llvm/ADT/SCCIterator.h @@ -60,7 +60,7 @@ class scc_iterator // First element is basic block pointer, second is the 'next child' to visit std::vector<std::pair<NodeType *, ChildItTy> > VisitStack; - // MinVistNumStack - Stack holding the "min" values for each node in the DFS. + // MinVisitNumStack - Stack holding the "min" values for each node in the DFS. // This is used to track the minimum uplink values for all children of // the corresponding node on the VisitStack. std::vector<unsigned> MinVisitNumStack; diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h index c96ad19707..a6803ee0ed 100644 --- a/include/llvm/ADT/ScopedHashTable.h +++ b/include/llvm/ADT/ScopedHashTable.h @@ -31,25 +31,23 @@ #ifndef LLVM_ADT_SCOPEDHASHTABLE_H #define LLVM_ADT_SCOPEDHASHTABLE_H -#include <cassert> #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Allocator.h" namespace llvm { -template <typename K, typename V, typename KInfo = DenseMapInfo<K> > +template <typename K, typename V, typename KInfo = DenseMapInfo<K>, + typename AllocatorTy = MallocAllocator> class ScopedHashTable; -template <typename K, typename V, typename KInfo = DenseMapInfo<K> > +template <typename K, typename V> class ScopedHashTableVal { ScopedHashTableVal *NextInScope; ScopedHashTableVal *NextForKey; K Key; V Val; + ScopedHashTableVal(const K &key, const V &val) : Key(key), Val(val) {} public: - ScopedHashTableVal(ScopedHashTableVal *nextInScope, - ScopedHashTableVal *nextForKey, const K &key, const V &val) - : NextInScope(nextInScope), NextForKey(nextForKey), Key(key), Val(val) { - } const K &getKey() const { return Key; } const V &getValue() const { return Val; } @@ -57,33 +55,56 @@ public: ScopedHashTableVal *getNextForKey() { return NextForKey; } const ScopedHashTableVal *getNextForKey() const { return NextForKey; } -public: ScopedHashTableVal *getNextInScope() { return NextInScope; } + + template <typename AllocatorTy> + static ScopedHashTableVal *Create(ScopedHashTableVal *nextInScope, + ScopedHashTableVal *nextForKey, + const K &key, const V &val, + AllocatorTy &Allocator) { + ScopedHashTableVal *New = Allocator.template Allocate<ScopedHashTableVal>(); + // Set up the value. + new (New) ScopedHashTableVal(key, val); + New->NextInScope = nextInScope; + New->NextForKey = nextForKey; + return New; + } + + template <typename AllocatorTy> + void Destroy(AllocatorTy &Allocator) { + // Free memory referenced by the item. + this->~ScopedHashTableVal(); + Allocator.Deallocate(this); + } }; -template <typename K, typename V, typename KInfo = DenseMapInfo<K> > +template <typename K, typename V, typename KInfo = DenseMapInfo<K>, + typename AllocatorTy = MallocAllocator> class ScopedHashTableScope { /// HT - The hashtable that we are active for. - ScopedHashTable<K, V, KInfo> &HT; + ScopedHashTable<K, V, KInfo, AllocatorTy> &HT; /// PrevScope - This is the scope that we are shadowing in HT. ScopedHashTableScope *PrevScope; /// LastValInScope - This is the last value that was inserted for this scope /// or null if none have been inserted yet. - ScopedHashTableVal<K, V, KInfo> *LastValInScope; + ScopedHashTableVal<K, V> *LastValInScope; void operator=(ScopedHashTableScope&); // DO NOT IMPLEMENT ScopedHashTableScope(ScopedHashTableScope&); // DO NOT IMPLEMENT public: - ScopedHashTableScope(ScopedHashTable<K, V, KInfo> &HT); + ScopedHashTableScope(ScopedHashTable<K, V, KInfo, AllocatorTy> &HT); ~ScopedHashTableScope(); + ScopedHashTableScope *getParentScope() { return PrevScope; } + const ScopedHashTableScope *getParentScope() const { return PrevScope; } + private: - friend class ScopedHashTable<K, V, KInfo>; - ScopedHashTableVal<K, V, KInfo> *getLastValInScope() { + friend class ScopedHashTable<K, V, KInfo, AllocatorTy>; + ScopedHashTableVal<K, V> *getLastValInScope() { return LastValInScope; } - void setLastValInScope(ScopedHashTableVal<K, V, KInfo> *Val) { + void setLastValInScope(ScopedHashTableVal<K, V> *Val) { LastValInScope = Val; } }; @@ -91,9 +112,9 @@ private: template <typename K, typename V, typename KInfo = DenseMapInfo<K> > class ScopedHashTableIterator { - ScopedHashTableVal<K, V, KInfo> *Node; + ScopedHashTableVal<K, V> *Node; public: - ScopedHashTableIterator(ScopedHashTableVal<K, V, KInfo> *node) : Node(node) {} + ScopedHashTableIterator(ScopedHashTableVal<K, V> *node) : Node(node) {} V &operator*() const { assert(Node && "Dereference end()"); @@ -121,26 +142,42 @@ public: }; -template <typename K, typename V, typename KInfo> +template <typename K, typename V, typename KInfo, typename AllocatorTy> class ScopedHashTable { - DenseMap<K, ScopedHashTableVal<K, V, KInfo>*, KInfo> TopLevelMap; - ScopedHashTableScope<K, V, KInfo> *CurScope; +public: + /// ScopeTy - This is a helpful typedef that allows clients to get easy access + /// to the name of the scope for this hash table. + typedef ScopedHashTableScope<K, V, KInfo, AllocatorTy> ScopeTy; +private: + typedef ScopedHashTableVal<K, V> ValTy; + DenseMap<K, ValTy*, KInfo> TopLevelMap; + ScopeTy *CurScope; + + AllocatorTy Allocator; + ScopedHashTable(const ScopedHashTable&); // NOT YET IMPLEMENTED void operator=(const ScopedHashTable&); // NOT YET IMPLEMENTED - friend class ScopedHashTableScope<K, V, KInfo>; + friend class ScopedHashTableScope<K, V, KInfo, AllocatorTy>; public: ScopedHashTable() : CurScope(0) {} + ScopedHashTable(AllocatorTy A) : CurScope(0), Allocator(A) {} ~ScopedHashTable() { assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!"); } + + + /// Access to the allocator. + typedef typename ReferenceAdder<AllocatorTy>::result AllocatorRefTy; + typedef typename ReferenceAdder<const AllocatorTy>::result AllocatorCRefTy; + AllocatorRefTy getAllocator() { return Allocator; } + AllocatorCRefTy getAllocator() const { return Allocator; } bool count(const K &Key) const { return TopLevelMap.count(Key); } V lookup(const K &Key) { - typename DenseMap<K, ScopedHashTableVal<K, V, KInfo>*, KInfo>::iterator - I = TopLevelMap.find(Key); + typename DenseMap<K, ValTy*, KInfo>::iterator I = TopLevelMap.find(Key); if (I != TopLevelMap.end()) return I->second->getValue(); @@ -148,13 +185,7 @@ public: } void insert(const K &Key, const V &Val) { - assert(CurScope && "No scope active!"); - - ScopedHashTableVal<K, V, KInfo> *&KeyEntry = TopLevelMap[Key]; - - KeyEntry= new ScopedHashTableVal<K, V, KInfo>(CurScope->getLastValInScope(), - KeyEntry, Key, Val); - CurScope->setLastValInScope(KeyEntry); + insertIntoScope(CurScope, Key, Val); } typedef ScopedHashTableIterator<K, V, KInfo> iterator; @@ -162,38 +193,52 @@ public: iterator end() { return iterator(0); } iterator begin(const K &Key) { - typename DenseMap<K, ScopedHashTableVal<K, V, KInfo>*, KInfo>::iterator I = + typename DenseMap<K, ValTy*, KInfo>::iterator I = TopLevelMap.find(Key); if (I == TopLevelMap.end()) return end(); return iterator(I->second); } + + ScopeTy *getCurScope() { return CurScope; } + const ScopeTy *getCurScope() const { return CurScope; } + + /// insertIntoScope - This inserts the specified key/value at the specified + /// (possibly not the current) scope. While it is ok to insert into a scope + /// that isn't the current one, it isn't ok to insert *underneath* an existing + /// value of the specified key. + void insertIntoScope(ScopeTy *S, const K &Key, const V &Val) { + assert(S && "No scope active!"); + ScopedHashTableVal<K, V> *&KeyEntry = TopLevelMap[Key]; + KeyEntry = ValTy::Create(S->getLastValInScope(), KeyEntry, Key, Val, + Allocator); + S->setLastValInScope(KeyEntry); + } }; /// ScopedHashTableScope ctor - Install this as the current scope for the hash /// table. -template <typename K, typename V, typename KInfo> -ScopedHashTableScope<K, V, KInfo>:: - ScopedHashTableScope(ScopedHashTable<K, V, KInfo> &ht) : HT(ht) { +template <typename K, typename V, typename KInfo, typename Allocator> +ScopedHashTableScope<K, V, KInfo, Allocator>:: + ScopedHashTableScope(ScopedHashTable<K, V, KInfo, Allocator> &ht) : HT(ht) { PrevScope = HT.CurScope; HT.CurScope = this; LastValInScope = 0; } -template <typename K, typename V, typename KInfo> -ScopedHashTableScope<K, V, KInfo>::~ScopedHashTableScope() { +template <typename K, typename V, typename KInfo, typename Allocator> +ScopedHashTableScope<K, V, KInfo, Allocator>::~ScopedHashTableScope() { assert(HT.CurScope == this && "Scope imbalance!"); HT.CurScope = PrevScope; // Pop and delete all values corresponding to this scope. - while (ScopedHashTableVal<K, V, KInfo> *ThisEntry = LastValInScope) { + while (ScopedHashTableVal<K, V> *ThisEntry = LastValInScope) { // Pop this value out of the TopLevelMap. if (ThisEntry->getNextForKey() == 0) { assert(HT.TopLevelMap[ThisEntry->getKey()] == ThisEntry && "Scope imbalance!"); HT.TopLevelMap.erase(ThisEntry->getKey()); } else { - ScopedHashTableVal<K, V, KInfo> *&KeyEntry = - HT.TopLevelMap[ThisEntry->getKey()]; + ScopedHashTableVal<K, V> *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()]; assert(KeyEntry == ThisEntry && "Scope imbalance!"); KeyEntry = ThisEntry->getNextForKey(); } @@ -202,7 +247,7 @@ ScopedHashTableScope<K, V, KInfo>::~ScopedHashTableScope() { LastValInScope = ThisEntry->getNextInScope(); // Delete this entry. - delete ThisEntry; + ThisEntry->Destroy(HT.getAllocator()); } } diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index 424bdba5a2..ff32ba87a2 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -16,9 +16,10 @@ #define LLVM_ADT_SMALLPTRSET_H #include <cassert> +#include <cstddef> #include <cstring> #include <iterator> -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/PointerLikeTypeTraits.h" namespace llvm { @@ -56,7 +57,7 @@ protected: /// it, so that the end iterator actually points to valid memory. unsigned CurArraySize; - // If small, this is # elts allocated consequtively + // If small, this is # elts allocated consecutively unsigned NumElements; unsigned NumTombstones; diff --git a/include/llvm/ADT/SmallString.h b/include/llvm/ADT/SmallString.h index 05bd8a42c6..da26416482 100644 --- a/include/llvm/ADT/SmallString.h +++ b/include/llvm/ADT/SmallString.h @@ -27,6 +27,9 @@ public: // Default ctor - Initialize to empty. SmallString() {} + // Initialize from a StringRef. + SmallString(StringRef S) : SmallVector<char, InternalLen>(S.begin(), S.end()) {} + // Initialize with a range. template<typename ItTy> SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {} @@ -38,15 +41,16 @@ public: // Extra methods. StringRef str() const { return StringRef(this->begin(), this->size()); } - // Implicit conversion to StringRef. - operator StringRef() const { return str(); } - - const char *c_str() { + // TODO: Make this const, if it's safe... + const char* c_str() { this->push_back(0); this->pop_back(); return this->data(); } + // Implicit conversion to StringRef. + operator StringRef() const { return str(); } + // Extra operators. const SmallString &operator=(StringRef RHS) { this->clear(); diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 10ae049ff9..8b0a13d6ed 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -20,6 +20,7 @@ #include <cstddef> #include <cstdlib> #include <cstring> +#include <iterator> #include <memory> #ifdef _MSC_VER @@ -88,7 +89,7 @@ protected: } /// grow_pod - This is an implementation of the grow() method which only works - /// on POD-like datatypes and is out of line to reduce code duplication. + /// on POD-like data types and is out of line to reduce code duplication. void grow_pod(size_t MinSizeInBytes, size_t TSize); public: @@ -263,7 +264,7 @@ public: template <typename T> class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> { typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass; - + SmallVectorImpl(const SmallVectorImpl&); // DISABLED. public: typedef typename SuperClass::iterator iterator; @@ -340,7 +341,6 @@ public: return Result; } - void swap(SmallVectorImpl &RHS); /// append - Add the specified range to the end of the SmallVector. diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index 0862981887..d977136b2f 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -17,7 +17,7 @@ #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include <cassert> diff --git a/include/llvm/ADT/Statistic.h b/include/llvm/ADT/Statistic.h index 3a1319f109..fda99c6edb 100644 --- a/include/llvm/ADT/Statistic.h +++ b/include/llvm/ADT/Statistic.h @@ -26,7 +26,7 @@ #ifndef LLVM_ADT_STATISTIC_H #define LLVM_ADT_STATISTIC_H -#include "llvm/System/Atomic.h" +#include "llvm/Support/Atomic.h" namespace llvm { class raw_ostream; @@ -121,6 +121,9 @@ protected: /// \brief Enable the collection and printing of statistics. void EnableStatistics(); +/// \brief Check if statistics are enabled. +bool AreStatisticsEnabled(); + /// \brief Print statistics to the file returned by CreateInfoOutputFile(). void PrintStatistics(); diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h index 3c53adee63..acbed66ef4 100644 --- a/include/llvm/ADT/StringExtras.h +++ b/include/llvm/ADT/StringExtras.h @@ -14,7 +14,7 @@ #ifndef LLVM_ADT_STRINGEXTRAS_H #define LLVM_ADT_STRINGEXTRAS_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/StringRef.h" #include <cctype> @@ -25,10 +25,11 @@ namespace llvm { template<typename T> class SmallVectorImpl; -/// hexdigit - Return the (uppercase) hexadecimal character for the +/// hexdigit - Return the hexadecimal character for the /// given number \arg X (which should be less than 16). -static inline char hexdigit(unsigned X) { - return X < 10 ? '0' + X : 'A' + X - 10; +static inline char hexdigit(unsigned X, bool LowerCase = false) { + const char HexChar = LowerCase ? 'a' : 'A'; + return X < 10 ? '0' + X : HexChar + X - 10; } /// utohex_buffer - Emit the specified number into the buffer specified by diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index d047a42079..bad0e6f513 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -242,9 +242,6 @@ public: }; -template <typename T> struct ReferenceAdder { typedef T& result; }; -template <typename T> struct ReferenceAdder<T&> { typedef T result; }; - /// StringMap - This is an unconventional map that is specialized for handling /// keys that are "strings", which are basically ranges of bytes. This does some /// funky memory allocation and hashing things to make it extremely efficient, @@ -265,10 +262,12 @@ public: : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) { assert(RHS.empty() && "Copy ctor from non-empty stringmap not implemented yet!"); + (void)RHS; } void operator=(const StringMap &RHS) { assert(RHS.empty() && "assignment from non-empty stringmap not implemented yet!"); + (void)RHS; clear(); } diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index ccf8ca9a66..1766d2b9f2 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -132,7 +132,7 @@ namespace llvm { /// numbers. int compare_numeric(StringRef RHS) const; - /// \brief Determine the edit distance between this string and another + /// \brief Determine the edit distance between this string and another /// string. /// /// \param Other the string to compare this string against. @@ -256,6 +256,18 @@ namespace llvm { /// Note: O(size() + Chars.size()) size_type find_first_not_of(StringRef Chars, size_t From = 0) const; + /// find_last_of - Find the last character in the string that is \arg C, or + /// npos if not found. + size_type find_last_of(char C, size_t From = npos) const { + return rfind(C, From); + } + + /// find_last_of - Find the last character in the string that is in \arg C, + /// or npos if not found. + /// + /// Note: O(size() + Chars.size()) + size_type find_last_of(StringRef Chars, size_t From = npos) const; + /// @} /// @name Helpful Algorithms /// @{ @@ -437,6 +449,10 @@ namespace llvm { /// @} + // StringRefs can be treated like a POD type. + template <typename T> struct isPodLike; + template <> struct isPodLike<StringRef> { static const bool value = true; }; + } #endif diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 467652773b..e6dcc23258 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -53,7 +53,6 @@ public: mips, // MIPS: mips, mipsallegrex mipsel, // MIPSEL: mipsel, mipsallegrexel, psp msp430, // MSP430: msp430 - pic16, // PIC16: pic16 ppc, // PPC: powerpc ppc64, // PPC64: powerpc64, ppu sparc, // Sparc: sparc @@ -85,8 +84,7 @@ public: FreeBSD, Linux, Lv2, // PS3 - MinGW32, - MinGW64, + MinGW32, // i*86-pc-mingw32, *-w64-mingw32 NetBSD, OpenBSD, Psp, @@ -96,7 +94,12 @@ public: Minix }; enum EnvironmentType { - UnknownEnvironment + UnknownEnvironment, + + GNU, + GNUEABI, + EABI, + MachO }; private: diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index b519a3e2ed..ab8d3653e3 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -11,7 +11,7 @@ #define LLVM_ADT_TWINE_H #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> #include <string> @@ -42,7 +42,7 @@ namespace llvm { /// Twines support a special 'null' value, which always concatenates to form /// itself, and renders as an empty string. This can be returned from APIs to /// effectively nullify any concatenations performed on the result. - /// + /// /// \b Implementation \n /// /// Given the nature of a Twine, it is not possible for the Twine's @@ -99,7 +99,7 @@ namespace llvm { /// A pointer to a StringRef instance. StringRefKind, - /// An unsigned int value reinterpreted as a pointer, to render as an + /// An unsigned int value reinterpreted as a pointer, to render as an /// unsigned decimal integer. DecUIKind, @@ -260,32 +260,32 @@ namespace llvm { } /// Construct a twine to print \arg Val as an unsigned decimal integer. - explicit Twine(unsigned Val) + explicit Twine(unsigned Val) : LHS((void*)(intptr_t)Val), LHSKind(DecUIKind), RHSKind(EmptyKind) { } /// Construct a twine to print \arg Val as a signed decimal integer. - explicit Twine(int Val) + explicit Twine(int Val) : LHS((void*)(intptr_t)Val), LHSKind(DecIKind), RHSKind(EmptyKind) { } /// Construct a twine to print \arg Val as an unsigned decimal integer. - explicit Twine(const unsigned long &Val) + explicit Twine(const unsigned long &Val) : LHS(&Val), LHSKind(DecULKind), RHSKind(EmptyKind) { } /// Construct a twine to print \arg Val as a signed decimal integer. - explicit Twine(const long &Val) + explicit Twine(const long &Val) : LHS(&Val), LHSKind(DecLKind), RHSKind(EmptyKind) { } /// Construct a twine to print \arg Val as an unsigned decimal integer. - explicit Twine(const unsigned long long &Val) + explicit Twine(const unsigned long long &Val) : LHS(&Val), LHSKind(DecULLKind), RHSKind(EmptyKind) { } /// Construct a twine to print \arg Val as a signed decimal integer. - explicit Twine(const long long &Val) + explicit Twine(const long long &Val) : LHS(&Val), LHSKind(DecLLKind), RHSKind(EmptyKind) { } @@ -330,12 +330,12 @@ 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: @@ -382,6 +382,14 @@ namespace llvm { /// SmallVector and a StringRef to the SmallVector's data is returned. StringRef toStringRef(SmallVectorImpl<char> &Out) const; + /// toNullTerminatedStringRef - This returns the twine as a single null + /// terminated 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. + /// + /// The returned StringRef's size does not include the null terminator. + StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const; + /// print - Write the concatenated string represented by this twine to the /// stream \arg OS. void print(raw_ostream &OS) const; diff --git a/include/llvm/ADT/ValueMap.h b/include/llvm/ADT/ValueMap.h index ded17fc322..d1f4e5a0da 100644 --- a/include/llvm/ADT/ValueMap.h +++ b/include/llvm/ADT/ValueMap.h @@ -29,7 +29,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/Support/ValueHandle.h" #include "llvm/Support/type_traits.h" -#include "llvm/System/Mutex.h" +#include "llvm/Support/Mutex.h" #include <iterator> diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index 4e3afe1711..865fcb3d8a 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -38,6 +38,7 @@ #ifndef LLVM_ADT_ILIST_H #define LLVM_ADT_ILIST_H +#include <algorithm> #include <cassert> #include <cstddef> #include <iterator> diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 53f0eea2be..71a5982c7d 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -48,6 +48,8 @@ class VAArgInst; class TargetData; class Pass; class AnalysisUsage; +class MemTransferInst; +class MemIntrinsic; class AliasAnalysis { protected: @@ -96,18 +98,17 @@ public: struct Location { /// Ptr - The address of the start of the location. const Value *Ptr; - /// Size - The maximum size of the location, or UnknownSize if the size is - /// not known. Note that an unknown size does not mean the pointer aliases - /// the entire virtual address space, because there are restrictions on - /// stepping out of one object and into another. + /// Size - The maximum size of the location, in address-units, or + /// UnknownSize if the size is not known. Note that an unknown size does + /// not mean the pointer aliases the entire virtual address space, because + /// there are restrictions on stepping out of one object and into another. /// See http://llvm.org/docs/LangRef.html#pointeraliasing uint64_t Size; /// TBAATag - The metadata node which describes the TBAA type of /// the location, or null if there is no known unique tag. const MDNode *TBAATag; - explicit Location(const Value *P = 0, - uint64_t S = UnknownSize, + explicit Location(const Value *P = 0, uint64_t S = UnknownSize, const MDNode *N = 0) : Ptr(P), Size(S), TBAATag(N) {} @@ -135,6 +136,8 @@ public: Location getLocation(const LoadInst *LI); Location getLocation(const StoreInst *SI); Location getLocation(const VAArgInst *VI); + static Location getLocationForSource(const MemTransferInst *MTI); + static Location getLocationForDest(const MemIntrinsic *MI); /// Alias analysis result - Either we know for sure that it does not alias, we /// know for sure it must alias, or we don't know anything: The two pointers @@ -147,8 +150,9 @@ public: /// enum AliasResult { NoAlias = 0, ///< No dependencies. - MayAlias = 1, ///< Anything goes. - MustAlias = 2 ///< Pointers are equal. + MayAlias, ///< Anything goes. + PartialAlias, ///< Pointers differ, but pointees overlap. + MustAlias ///< Pointers are equal. }; /// alias - The main low level interface to the alias analysis implementation. @@ -179,7 +183,17 @@ public: const Value *V2, uint64_t V2Size) { return isNoAlias(Location(V1, V1Size), Location(V2, V2Size)); } + + /// isMustAlias - A convenience wrapper. + bool isMustAlias(const Location &LocA, const Location &LocB) { + return alias(LocA, LocB) == MustAlias; + } + /// isMustAlias - A convenience wrapper. + bool isMustAlias(const Value *V1, const Value *V2) { + return alias(V1, 1, V2, 1) == MustAlias; + } + /// pointsToConstantMemory - If the specified memory location is /// known to be constant, return true. If OrLocal is true and the /// specified memory location is known to be "local" (derived from @@ -388,7 +402,7 @@ public: ModRefResult getModRefInfo(const StoreInst *S, const Location &Loc); /// getModRefInfo (for stores) - A convenience wrapper. - ModRefResult getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size) { + ModRefResult getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size){ return getModRefInfo(S, Location(P, Size)); } @@ -397,7 +411,7 @@ public: ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc); /// getModRefInfo (for va_args) - A convenience wrapper. - ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size) { + ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){ return getModRefInfo(I, Location(P, Size)); } @@ -455,6 +469,17 @@ public: /// virtual void copyValue(Value *From, Value *To); + /// addEscapingUse - This method should be used whenever an escaping use is + /// added to a pointer value. Analysis implementations may either return + /// conservative responses for that value in the future, or may recompute + /// some or all internal state to continue providing precise responses. + /// + /// Escaping uses are considered by anything _except_ the following: + /// - GEPs or bitcasts of the pointer + /// - Loads through the pointer + /// - Stores through (but not of) the pointer + virtual void addEscapingUse(Use &U); + /// replaceWithNewValue - This method is the obvious combination of the two /// above, and it provided as a helper to simplify client code. /// diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index a4884edd5b..089f322e4a 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -57,7 +57,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/ValueHandle.h" -#include "llvm/System/IncludeFile.h" +#include "llvm/Support/IncludeFile.h" #include <map> namespace llvm { @@ -138,6 +138,13 @@ public: /// not already exist. CallGraphNode *getOrInsertFunction(const Function *F); + /// spliceFunction - Replace the function represented by this node by another. + /// This does not rescan the body of the function, so it is suitable when + /// splicing the body of one function to another while also updating all + /// callers from the old function to the new. + /// + void spliceFunction(const Function *From, const Function *To); + //===--------------------------------------------------------------------- // Pass infrastructure interface glue code. // @@ -163,8 +170,10 @@ protected: // CallGraphNode class definition. // class CallGraphNode { - AssertingVH<Function> F; + friend class CallGraph; + AssertingVH<Function> F; + // CallRecord - This is a pair of the calling instruction (a call or invoke) // and the callgraph node being called. public: diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h index e89ad9026d..75edfbbed2 100644 --- a/include/llvm/Analysis/CodeMetrics.h +++ b/include/llvm/Analysis/CodeMetrics.h @@ -7,15 +7,16 @@ // //===----------------------------------------------------------------------===// // -// This file implements various weight measurements for a function, helping -// the Inliner and PartialSpecialization decide whether to duplicate its -// contents. +// This file implements various weight measurements for code, helping +// the Inliner and other passes decide whether to duplicate its contents. // //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_CODEMETRICS_H #define LLVM_ANALYSIS_CODEMETRICS_H +#include "llvm/ADT/DenseMap.h" + namespace llvm { // CodeMetrics - Calculate size and a few similar metrics for a set of // basic blocks. diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h index e2675eb2d4..f6b1f5ab99 100644 --- a/include/llvm/Analysis/ConstantFolding.h +++ b/include/llvm/Analysis/ConstantFolding.h @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file declares routines for folding instructions into constants. +// This file declares routines for folding instructions into constants when all +// operands are constants, for example "sub i32 1, 0" -> "1". // // Also, to supplement the basic VMCore ConstantExpr simplifications, // this file declares some additional folding routines that can make use of @@ -27,11 +28,11 @@ namespace llvm { class Function; class Type; -/// ConstantFoldInstruction - Attempt to constant fold the specified -/// instruction. If successful, the constant result is returned, if not, null -/// is returned. Note that this function can only fail when attempting to fold -/// instructions like loads and stores, which have no constant expression form. -/// +/// ConstantFoldInstruction - Try to constant fold the specified instruction. +/// If successful, the constant result is returned, if not, null is returned. +/// Note that this fails if not all of the operands are constant. Otherwise, +/// this function can only fail when attempting to fold instructions like loads +/// and stores, which have no constant expression form. Constant *ConstantFoldInstruction(Instruction *I, const TargetData *TD = 0); /// ConstantFoldConstantExpression - Attempt to fold the constant expression diff --git a/include/llvm/Analysis/DIBuilder.h b/include/llvm/Analysis/DIBuilder.h index 4b8eba949b..32a17e4f09 100644 --- a/include/llvm/Analysis/DIBuilder.h +++ b/include/llvm/Analysis/DIBuilder.h @@ -15,11 +15,15 @@ #ifndef LLVM_ANALYSIS_DIBUILDER_H #define LLVM_ANALYSIS_DIBUILDER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/ADT/StringRef.h" namespace llvm { + class BasicBlock; + class Instruction; + class Function; class Module; + class Value; class LLVMContext; class MDNode; class StringRef; @@ -27,6 +31,15 @@ namespace llvm { class DIFile; class DIEnumerator; class DIType; + class DIArray; + class DIGlobalVariable; + class DINameSpace; + class DIVariable; + class DISubrange; + class DILexicalBlock; + class DISubprogram; + class DITemplateTypeParameter; + class DITemplateValueParameter; class DIBuilder { private: @@ -34,14 +47,18 @@ namespace llvm { LLVMContext & VMContext; MDNode *TheCU; + Function *DeclareFn; // llvm.dbg.declare + Function *ValueFn; // llvm.dbg.value + DIBuilder(const DIBuilder &); // DO NOT IMPLEMENT void operator=(const DIBuilder &); // DO NOT IMPLEMENT public: explicit DIBuilder(Module &M); const MDNode *getCU() { return TheCU; } + enum ComplexAddrKind { OpPlus=1, OpDeref }; - /// CreateCompileUnit - A CompileUnit provides an anchor for all debugging + /// createCompileUnit - A CompileUnit provides an anchor for all debugging /// information generated during this instance of compilation. /// @param Lang Source programming language, eg. dwarf::DW_LANG_C99 /// @param File File name @@ -55,58 +72,392 @@ namespace llvm { /// by a tool analyzing generated debugging information. /// @param RV This indicates runtime version for languages like /// Objective-C. - void CreateCompileUnit(unsigned Lang, StringRef File, StringRef Dir, + void createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV); - /// CreateFile - Create a file descriptor to hold debugging information + /// createFile - Create a file descriptor to hold debugging information /// for a file. - DIFile CreateFile(StringRef Filename, StringRef Directory); + DIFile createFile(StringRef Filename, StringRef Directory); - /// CreateEnumerator - Create a single enumerator value. - DIEnumerator CreateEnumerator(StringRef Name, uint64_t Val); + /// createEnumerator - Create a single enumerator value. + DIEnumerator createEnumerator(StringRef Name, uint64_t Val); - /// CreateBasicType - Create debugging information entry for a basic + /// createBasicType - Create debugging information entry for a basic /// type. /// @param Name Type name. /// @param SizeInBits Size of the type. /// @param AlignInBits Type alignment. /// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. - DIType CreateBasicType(StringRef Name, uint64_t SizeInBits, + DIType createBasicType(StringRef Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding); - /// CreateQualifiedType - Create debugging information entry for a qualified + /// createQualifiedType - Create debugging information entry for a qualified /// type, e.g. 'const int'. /// @param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type /// @param FromTy Base Type. - DIType CreateQualifiedType(unsigned Tag, DIType FromTy); + DIType createQualifiedType(unsigned Tag, DIType FromTy); - /// CreatePointerType - Create debugging information entry for a pointer. - DIType CreatePointerType(DIType PointeeTy, uint64_t SizeInBits, - uint64_t AlignInBits = 0, StringRef Name = StringRef()); + /// createPointerType - Create debugging information entry for a pointer. + /// @param PointeeTy Type pointed by this pointer. + /// @param SizeInBits Size. + /// @param AlignInBits Alignment. (optional) + /// @param Name Pointer type name. (optional) + DIType createPointerType(DIType PointeeTy, uint64_t SizeInBits, + uint64_t AlignInBits = 0, + StringRef Name = StringRef()); - /// CreateReferenceType - Create debugging information entry for a reference. - DIType CreateReferenceType(DIType RTy); + /// createReferenceType - Create debugging information entry for a c++ + /// style reference. + DIType createReferenceType(DIType RTy); - /// CreateTypedef - Create debugging information entry for a typedef. - DIType CreateTypedef(DIType Ty, StringRef Name, DIFile F, unsigned LineNo); + /// createTypedef - Create debugging information entry for a typedef. + /// @param Ty Original type. + /// @param Name Typedef name. + /// @param File File where this type is defined. + /// @param LineNo Line number. + DIType createTypedef(DIType Ty, StringRef Name, DIFile File, + unsigned LineNo); - /// CreateFriend - Create debugging information entry for a 'friend'. - DIType CreateFriend(DIType Ty, DIType FriendTy); + /// createFriend - Create debugging information entry for a 'friend'. + DIType createFriend(DIType Ty, DIType FriendTy); - /// CreateInheritance - Create debugging information entry to establish + /// createInheritance - Create debugging information entry to establish /// inheritance relationship between two types. - DIType CreateInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset, + /// @param Ty Original type. + /// @param BaseTy Base type. Ty is inherits from base. + /// @param BaseOffset Base offset. + /// @param Flags Flags to describe inheritance attribute, + /// e.g. private + DIType createInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset, unsigned Flags); - /// CreateMemberType - Create debugging information entry for a member. - DIType CreateMemberType(DIDescriptor Context, StringRef Name, DIFile F, - unsigned LineNumber, uint64_t SizeInBits, + /// createMemberType - Create debugging information entry for a member. + /// @param Name Member name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param OffsetInBits Member offset. + /// @param Flags Flags to encode member attribute, e.g. private + /// @param Ty Parent type. + DIType createMemberType(StringRef Name, DIFile File, + unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType Ty); - /// CreateArtificialType - Create a new DIType with "artificial" flag set. - DIType CreateArtificialType(DIType Ty); + /// createClassType - Create debugging information entry for a class. + /// @param Scope Scope in which this class is defined. + /// @param Name class name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param OffsetInBits Member offset. + /// @param Flags Flags to encode member attribute, e.g. private + /// @param Elements class members. + /// @param VTableHolder Debug info of the base class that contains vtable + /// for this type. This is used in + /// DW_AT_containing_type. See DWARF documentation + /// for more info. + /// @param TemplateParms Template type parameters. + DIType createClassType(DIDescriptor Scope, StringRef Name, DIFile File, + unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DIType DerivedFrom, + DIArray Elements, MDNode *VTableHolder = 0, + MDNode *TemplateParms = 0); + + /// createStructType - Create debugging information entry for a struct. + /// @param Scope Scope in which this struct is defined. + /// @param Name Struct name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param Flags Flags to encode member attribute, e.g. private + /// @param Elements Struct elements. + /// @param RunTimeLang Optional parameter, Objective-C runtime version. + DIType createStructType(DIDescriptor Scope, StringRef Name, DIFile File, + unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Flags, + DIArray Elements, unsigned RunTimeLang = 0); + + /// createUnionType - Create debugging information entry for an union. + /// @param Scope Scope in which this union is defined. + /// @param Name Union name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param Flags Flags to encode member attribute, e.g. private + /// @param Elements Union elements. + /// @param RunTimeLang Optional parameter, Objective-C runtime version. + DIType createUnionType(DIDescriptor Scope, StringRef Name, DIFile File, + unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Flags, + DIArray Elements, unsigned RunTimeLang = 0); + + /// createTemplateTypeParameter - Create debugging information for template + /// type parameter. + /// @param Scope Scope in which this type is defined. + /// @param Name Type parameter name. + /// @param Ty Parameter type. + /// @param File File where this type parameter is defined. + /// @param LineNo Line number. + /// @param ColumnNo Column Number. + DITemplateTypeParameter + createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty, + MDNode *File = 0, unsigned LineNo = 0, + unsigned ColumnNo = 0); + + /// createTemplateValueParameter - Create debugging information for template + /// value parameter. + /// @param Scope Scope in which this type is defined. + /// @param Name Value parameter name. + /// @param Ty Parameter type. + /// @param Value Constant parameter value. + /// @param File File where this type parameter is defined. + /// @param LineNo Line number. + /// @param ColumnNo Column Number. + DITemplateValueParameter + createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty, + uint64_t Value, + MDNode *File = 0, unsigned LineNo = 0, + unsigned ColumnNo = 0); + + /// createArrayType - Create debugging information entry for an array. + /// @param Size Array size. + /// @param AlignInBits Alignment. + /// @param Ty Element type. + /// @param Subscripts Subscripts. + DIType createArrayType(uint64_t Size, uint64_t AlignInBits, + DIType Ty, DIArray Subscripts); + + /// createVectorType - Create debugging information entry for a vector type. + /// @param Size Array size. + /// @param AlignInBits Alignment. + /// @param Ty Element type. + /// @param Subscripts Subscripts. + DIType createVectorType(uint64_t Size, uint64_t AlignInBits, + DIType Ty, DIArray Subscripts); + + /// createEnumerationType - Create debugging information entry for an + /// enumeration. + /// @param Scope Scope in which this enumeration is defined. + /// @param Name Union name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param Elements Enumeration elements. + DIType createEnumerationType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, DIArray Elements); + + /// createSubroutineType - Create subroutine type. + /// @param File File in which this subroutine is defined. + /// @param ParamterTypes An array of subroutine parameter types. This + /// includes return type at 0th index. + DIType createSubroutineType(DIFile File, DIArray ParameterTypes); + + /// createArtificialType - Create a new DIType with "artificial" flag set. + DIType createArtificialType(DIType Ty); + + /// createTemporaryType - Create a temporary forward-declared type. + DIType createTemporaryType(); + DIType createTemporaryType(DIFile F); + + /// retainType - Retain DIType in a module even if it is not referenced + /// through debug info anchors. + void retainType(DIType T); + + /// createUnspecifiedParameter - Create unspeicified type descriptor + /// for a subroutine type. + DIDescriptor createUnspecifiedParameter(); + + /// getOrCreateArray - Get a DIArray, create one if required. + DIArray getOrCreateArray(Value *const *Elements, unsigned NumElements); + + /// getOrCreateSubrange - Create a descriptor for a value range. This + /// implicitly uniques the values returned. + DISubrange getOrCreateSubrange(int64_t Lo, int64_t Hi); + + /// createGlobalVariable - Create a new descriptor for the specified global. + /// @param Name Name of the variable. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Variable Type. + /// @param isLocalToUnit Boolean flag indicate whether this variable is + /// externally visible or not. + /// @param Val llvm::Value of the variable. + DIGlobalVariable + createGlobalVariable(StringRef Name, DIFile File, unsigned LineNo, + DIType Ty, bool isLocalToUnit, llvm::Value *Val); + + + /// createStaticVariable - Create a new descriptor for the specified + /// variable. + /// @param Conext Variable scope. + /// @param Name Name of the variable. + /// @param LinakgeName Mangled name of the variable. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Variable Type. + /// @param isLocalToUnit Boolean flag indicate whether this variable is + /// externally visible or not. + /// @param Val llvm::Value of the variable. + DIGlobalVariable + createStaticVariable(DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile File, unsigned LineNo, + DIType Ty, bool isLocalToUnit, llvm::Value *Val); + + + /// createLocalVariable - Create a new descriptor for the specified + /// local variable. + /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or + /// DW_TAG_arg_variable. + /// @param Scope Variable scope. + /// @param Name Variable name. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Variable Type + /// @param AlwaysPreserve Boolean. Set to true if debug info for this + /// variable should be preserved in optimized build. + /// @param Flags Flags, e.g. artificial variable. + /// @param ArgNo If this variable is an arugment then this argument's + /// number. 1 indicates 1st argument. + DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope, + StringRef Name, + DIFile File, unsigned LineNo, + DIType Ty, bool AlwaysPreserve = false, + unsigned Flags = 0, + unsigned ArgNo = 0); + + + /// createComplexVariable - Create a new descriptor for the specified + /// variable which has a complex address expression for its address. + /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or + /// DW_TAG_arg_variable. + /// @param Scope Variable scope. + /// @param Name Variable name. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Variable Type + /// @param Addr A pointer to a vector of complex address operations. + /// @param NumAddr Num of address operations in the vector. + /// @param ArgNo If this variable is an arugment then this argument's + /// number. 1 indicates 1st argument. + DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope, + StringRef Name, DIFile F, unsigned LineNo, + DIType Ty, Value *const *Addr, + unsigned NumAddr, unsigned ArgNo = 0); + + /// createFunction - Create a new descriptor for the specified subprogram. + /// See comments in DISubprogram for descriptions of these fields. + /// @param Scope Function scope. + /// @param Name Function name. + /// @param LinkageName Mangled function name. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Function type. + /// @param isLocalToUnit True if this function is not externally visible.. + /// @param isDefinition True if this is a function definition. + /// @param Flags e.g. is this function prototyped or not. + /// This flags are used to emit dwarf attributes. + /// @param isOptimized True if optimization is ON. + /// @param Fn llvm::Function pointer. + DISubprogram createFunction(DIDescriptor Scope, StringRef Name, + StringRef LinkageName, + DIFile File, unsigned LineNo, + DIType Ty, bool isLocalToUnit, + bool isDefinition, + unsigned Flags = 0, + bool isOptimized = false, + Function *Fn = 0); + + /// createMethod - Create a new descriptor for the specified C++ method. + /// See comments in DISubprogram for descriptions of these fields. + /// @param Scope Function scope. + /// @param Name Function name. + /// @param LinkageName Mangled function name. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Function type. + /// @param isLocalToUnit True if this function is not externally visible.. + /// @param isDefinition True if this is a function definition. + /// @param Virtuality Attributes describing virutallness. e.g. pure + /// virtual function. + /// @param VTableIndex Index no of this method in virtual table. + /// @param VTableHolder Type that holds vtable. + /// @param Flags e.g. is this function prototyped or not. + /// This flags are used to emit dwarf attributes. + /// @param isOptimized True if optimization is ON. + /// @param Fn llvm::Function pointer. + DISubprogram createMethod(DIDescriptor Scope, StringRef Name, + StringRef LinkageName, + DIFile File, unsigned LineNo, + DIType Ty, bool isLocalToUnit, + bool isDefinition, + unsigned Virtuality = 0, unsigned VTableIndex = 0, + MDNode *VTableHolder = 0, + unsigned Flags = 0, + bool isOptimized = false, + Function *Fn = 0); + + /// createNameSpace - This creates new descriptor for a namespace + /// with the specified parent scope. + /// @param Scope Namespace scope + /// @param Name Name of this namespace + /// @param File Source file + /// @param LineNo Line number + DINameSpace createNameSpace(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNo); + + + /// createLexicalBlock - This creates a descriptor for a lexical block + /// with the specified parent context. + /// @param Scope Parent lexical scope. + /// @param File Source file + /// @param Line Line number + /// @param Col Column number + DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File, + unsigned Line, unsigned Col); + + /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. + /// @param Storage llvm::Value of the variable + /// @param VarInfo Variable's debug info descriptor. + /// @param InsertAtEnd Location for the new intrinsic. + Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, + BasicBlock *InsertAtEnd); + + /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. + /// @param Storage llvm::Value of the variable + /// @param VarInfo Variable's debug info descriptor. + /// @param InsertBefore Location for the new intrinsic. + Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, + Instruction *InsertBefore); + + + /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. + /// @param Val llvm::Value of the variable + /// @param Offset Offset + /// @param VarInfo Variable's debug info descriptor. + /// @param InsertAtEnd Location for the new intrinsic. + Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, + DIVariable VarInfo, + BasicBlock *InsertAtEnd); + + /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. + /// @param Val llvm::Value of the variable + /// @param Offset Offset + /// @param VarInfo Variable's debug info descriptor. + /// @param InsertBefore Location for the new intrinsic. + Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, + DIVariable VarInfo, + Instruction *InsertBefore); + }; } // end namespace llvm diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h index af683af0c9..951fd3cf1f 100644 --- a/include/llvm/Analysis/DebugInfo.h +++ b/include/llvm/Analysis/DebugInfo.h @@ -122,6 +122,8 @@ namespace llvm { bool isType() const; bool isGlobal() const; bool isUnspecifiedParameter() const; + bool isTemplateTypeParameter() const; + bool isTemplateValueParameter() const; }; /// DISubrange - This is used to represent ranges, for array bounds. @@ -288,6 +290,7 @@ namespace llvm { /// replaceAllUsesWith - Replace all uses of debug info referenced by /// this descriptor. void replaceAllUsesWith(DIDescriptor &D); + void replaceAllUsesWith(MDNode *D); /// print - print type. void print(raw_ostream &OS) const; @@ -355,6 +358,7 @@ namespace llvm { DICompositeType getContainingType() const { return getFieldAs<DICompositeType>(12); } + DIArray getTemplateParams() const { return getFieldAs<DIArray>(13); } /// Verify - Verify that a composite type descriptor is well formed. bool Verify() const; @@ -366,6 +370,43 @@ namespace llvm { void dump() const; }; + /// DITemplateTypeParameter - This is a wrapper for template type parameter. + class DITemplateTypeParameter : public DIDescriptor { + public: + explicit DITemplateTypeParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs<DIScope>(1); } + StringRef getName() const { return getStringField(2); } + DIType getType() const { return getFieldAs<DIType>(3); } + StringRef getFilename() const { + return getFieldAs<DIFile>(4).getFilename(); + } + StringRef getDirectory() const { + return getFieldAs<DIFile>(4).getDirectory(); + } + unsigned getLineNumber() const { return getUnsignedField(5); } + unsigned getColumnNumber() const { return getUnsignedField(6); } + }; + + /// DITemplateValueParameter - This is a wrapper for template value parameter. + class DITemplateValueParameter : public DIDescriptor { + public: + explicit DITemplateValueParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs<DIScope>(1); } + StringRef getName() const { return getStringField(2); } + DIType getType() const { return getFieldAs<DIType>(3); } + uint64_t getValue() const { return getUInt64Field(4); } + StringRef getFilename() const { + return getFieldAs<DIFile>(5).getFilename(); + } + StringRef getDirectory() const { + return getFieldAs<DIFile>(5).getDirectory(); + } + unsigned getLineNumber() const { return getUnsignedField(6); } + unsigned getColumnNumber() const { return getUnsignedField(7); } + }; + /// DISubprogram - This is a wrapper for a subprogram (e.g. a function). class DISubprogram : public DIScope { public: @@ -523,7 +564,13 @@ namespace llvm { DIFile F = getFieldAs<DIFile>(3); return F.getCompileUnit(); } - unsigned getLineNumber() const { return getUnsignedField(4); } + unsigned getLineNumber() const { + return (getUnsignedField(4) << 8) >> 8; + } + unsigned getArgNumber() const { + unsigned L = getUnsignedField(4); + return L >> 24; + } DIType getType() const { return getFieldAs<DIType>(5); } /// isArtificial - Return true if this variable is marked as "artificial". @@ -619,217 +666,6 @@ namespace llvm { bool Verify() const; }; - /// DIFactory - This object assists with the construction of the various - /// descriptors. - class DIFactory { - Module &M; - LLVMContext& VMContext; - - Function *DeclareFn; // llvm.dbg.declare - Function *ValueFn; // llvm.dbg.value - - DIFactory(const DIFactory &); // DO NOT IMPLEMENT - void operator=(const DIFactory&); // DO NOT IMPLEMENT - public: - enum ComplexAddrKind { OpPlus=1, OpDeref }; - - explicit DIFactory(Module &m); - - /// GetOrCreateArray - Create an descriptor for an array of descriptors. - /// This implicitly uniques the arrays created. - DIArray GetOrCreateArray(DIDescriptor *Tys, unsigned NumTys); - - /// GetOrCreateSubrange - Create a descriptor for a value range. This - /// implicitly uniques the values returned. - DISubrange GetOrCreateSubrange(int64_t Lo, int64_t Hi); - - /// CreateUnspecifiedParameter - Create unspeicified type descriptor - /// for a subroutine type. - DIDescriptor CreateUnspecifiedParameter(); - - /// CreateCompileUnit - Create a new descriptor for the specified compile - /// unit. - DICompileUnit CreateCompileUnit(unsigned LangID, - StringRef Filename, - StringRef Directory, - StringRef Producer, - bool isMain = false, - bool isOptimized = false, - StringRef Flags = "", - unsigned RunTimeVer = 0); - - /// CreateFile - Create a new descriptor for the specified file. - DIFile CreateFile(StringRef Filename, StringRef Directory, - DICompileUnit CU); - - /// CreateEnumerator - Create a single enumerator value. - DIEnumerator CreateEnumerator(StringRef Name, uint64_t Val); - - /// CreateBasicType - Create a basic type like int, float, etc. - DIBasicType CreateBasicType(DIDescriptor Context, StringRef Name, - DIFile F, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - unsigned Encoding); - - /// CreateBasicType - Create a basic type like int, float, etc. - DIBasicType CreateBasicTypeEx(DIDescriptor Context, StringRef Name, - DIFile F, unsigned LineNumber, - Constant *SizeInBits, Constant *AlignInBits, - Constant *OffsetInBits, unsigned Flags, - unsigned Encoding); - - /// CreateDerivedType - Create a derived type like const qualified type, - /// pointer, typedef, etc. - DIDerivedType CreateDerivedType(unsigned Tag, DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - DIType DerivedFrom); - - /// CreateDerivedType - Create a derived type like const qualified type, - /// pointer, typedef, etc. - DIDerivedType CreateDerivedTypeEx(unsigned Tag, DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - Constant *SizeInBits, - Constant *AlignInBits, - Constant *OffsetInBits, unsigned Flags, - DIType DerivedFrom); - - /// CreateCompositeType - Create a composite type like array, struct, etc. - DICompositeType CreateCompositeType(unsigned Tag, DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - DIType DerivedFrom, - DIArray Elements, - unsigned RunTimeLang = 0, - MDNode *ContainingType = 0); - - /// CreateTemporaryType - Create a temporary forward-declared type. - DIType CreateTemporaryType(); - - /// CreateArtificialType - Create a new DIType with "artificial" flag set. - DIType CreateArtificialType(DIType Ty); - - /// CreateCompositeType - Create a composite type like array, struct, etc. - DICompositeType CreateCompositeTypeEx(unsigned Tag, DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - Constant *SizeInBits, - Constant *AlignInBits, - Constant *OffsetInBits, - unsigned Flags, - DIType DerivedFrom, - DIArray Elements, - unsigned RunTimeLang = 0, - MDNode *ContainingType = 0); - - /// CreateSubprogram - Create a new descriptor for the specified subprogram. - /// See comments in DISubprogram for descriptions of these fields. - DISubprogram CreateSubprogram(DIDescriptor Context, StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DIFile F, unsigned LineNo, - DIType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned VK = 0, - unsigned VIndex = 0, - DIType ContainingType = DIType(), - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = 0); - - /// CreateSubprogramDefinition - Create new subprogram descriptor for the - /// given declaration. - DISubprogram CreateSubprogramDefinition(DISubprogram &SPDeclaration); - - /// CreateGlobalVariable - Create a new descriptor for the specified global. - DIGlobalVariable - CreateGlobalVariable(DIDescriptor Context, StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DIFile F, - unsigned LineNo, DIType Ty, bool isLocalToUnit, - bool isDefinition, llvm::GlobalVariable *GV); - - /// CreateGlobalVariable - Create a new descriptor for the specified constant. - DIGlobalVariable - CreateGlobalVariable(DIDescriptor Context, StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DIFile F, - unsigned LineNo, DIType Ty, bool isLocalToUnit, - bool isDefinition, llvm::Constant *C); - - /// CreateVariable - Create a new descriptor for the specified variable. - DIVariable CreateVariable(unsigned Tag, DIDescriptor Context, - StringRef Name, - DIFile F, unsigned LineNo, - DIType Ty, bool AlwaysPreserve = false, - unsigned Flags = 0); - - /// CreateComplexVariable - Create a new descriptor for the specified - /// variable which has a complex address expression for its address. - DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Context, - StringRef Name, DIFile F, unsigned LineNo, - DIType Ty, Value *const *Addr, - unsigned NumAddr); - - /// CreateLexicalBlock - This creates a descriptor for a lexical block - /// with the specified parent context. - DILexicalBlock CreateLexicalBlock(DIDescriptor Context, DIFile F, - unsigned Line = 0, unsigned Col = 0); - - /// CreateNameSpace - This creates new descriptor for a namespace - /// with the specified parent context. - DINameSpace CreateNameSpace(DIDescriptor Context, StringRef Name, - DIFile F, unsigned LineNo); - - /// CreateLocation - Creates a debug info location. - DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo, - DIScope S, DILocation OrigLoc); - - /// CreateLocation - Creates a debug info location. - DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo, - DIScope S, MDNode *OrigLoc = 0); - - /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. - Instruction *InsertDeclare(llvm::Value *Storage, DIVariable D, - BasicBlock *InsertAtEnd); - - /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. - Instruction *InsertDeclare(llvm::Value *Storage, DIVariable D, - Instruction *InsertBefore); - - /// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. - Instruction *InsertDbgValueIntrinsic(llvm::Value *V, uint64_t Offset, - DIVariable D, BasicBlock *InsertAtEnd); - - /// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. - Instruction *InsertDbgValueIntrinsic(llvm::Value *V, uint64_t Offset, - DIVariable D, Instruction *InsertBefore); - - // RecordType - Record DIType in a module such that it is not lost even if - // it is not referenced through debug info anchors. - void RecordType(DIType T); - - private: - Constant *GetTagConstant(unsigned TAG); - }; - - bool getLocationInfo(const Value *V, std::string &DisplayName, - std::string &Type, unsigned &LineNo, std::string &File, - std::string &Dir); - /// getDISubprogram - Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); diff --git a/include/llvm/Analysis/DominanceFrontier.h b/include/llvm/Analysis/DominanceFrontier.h new file mode 100644 index 0000000000..d7f74af1c6 --- /dev/null +++ b/include/llvm/Analysis/DominanceFrontier.h @@ -0,0 +1,189 @@ +//===- llvm/Analysis/DominanceFrontier.h - Dominator Frontiers --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DominanceFrontier class, which calculate and holds the +// dominance frontier for a function. +// +// This should be considered deprecated, don't add any more uses of this data +// structure. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_H +#define LLVM_ANALYSIS_DOMINANCEFRONTIER_H + +#include "llvm/Analysis/Dominators.h" +#include <map> +#include <set> + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// DominanceFrontierBase - Common base class for computing forward and inverse +/// dominance frontiers for a function. +/// +class DominanceFrontierBase : public FunctionPass { +public: + typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb + typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map +protected: + DomSetMapType Frontiers; + std::vector<BasicBlock*> Roots; + const bool IsPostDominators; + +public: + DominanceFrontierBase(char &ID, bool isPostDom) + : FunctionPass(ID), IsPostDominators(isPostDom) {} + + /// getRoots - Return the root blocks of the current CFG. This may include + /// multiple blocks if we are computing post dominators. For forward + /// dominators, this will always be a single block (the entry node). + /// + inline const std::vector<BasicBlock*> &getRoots() const { return Roots; } + + /// isPostDominator - Returns true if analysis based of postdoms + /// + bool isPostDominator() const { return IsPostDominators; } + + virtual void releaseMemory() { Frontiers.clear(); } + + // Accessor interface: + typedef DomSetMapType::iterator iterator; + typedef DomSetMapType::const_iterator const_iterator; + iterator begin() { return Frontiers.begin(); } + const_iterator begin() const { return Frontiers.begin(); } + iterator end() { return Frontiers.end(); } + const_iterator end() const { return Frontiers.end(); } + iterator find(BasicBlock *B) { return Frontiers.find(B); } + const_iterator find(BasicBlock *B) const { return Frontiers.find(B); } + + iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) { + assert(find(BB) == end() && "Block already in DominanceFrontier!"); + return Frontiers.insert(std::make_pair(BB, frontier)).first; + } + + /// removeBlock - Remove basic block BB's frontier. + void removeBlock(BasicBlock *BB) { + assert(find(BB) != end() && "Block is not in DominanceFrontier!"); + for (iterator I = begin(), E = end(); I != E; ++I) + I->second.erase(BB); + Frontiers.erase(BB); + } + + void addToFrontier(iterator I, BasicBlock *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + I->second.insert(Node); + } + + void removeFromFrontier(iterator I, BasicBlock *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); + I->second.erase(Node); + } + + /// compareDomSet - Return false if two domsets match. Otherwise + /// return true; + bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const { + std::set<BasicBlock *> tmpSet; + for (DomSetType::const_iterator I = DS2.begin(), + E = DS2.end(); I != E; ++I) + tmpSet.insert(*I); + + for (DomSetType::const_iterator I = DS1.begin(), + E = DS1.end(); I != E; ) { + BasicBlock *Node = *I++; + + if (tmpSet.erase(Node) == 0) + // Node is in DS1 but not in DS2. + return true; + } + + if (!tmpSet.empty()) + // There are nodes that are in DS2 but not in DS1. + return true; + + // DS1 and DS2 matches. + return false; + } + + /// compare - Return true if the other dominance frontier base matches + /// this dominance frontier base. Otherwise return false. + bool compare(DominanceFrontierBase &Other) const { + DomSetMapType tmpFrontiers; + for (DomSetMapType::const_iterator I = Other.begin(), + E = Other.end(); I != E; ++I) + tmpFrontiers.insert(std::make_pair(I->first, I->second)); + + for (DomSetMapType::iterator I = tmpFrontiers.begin(), + E = tmpFrontiers.end(); I != E; ) { + BasicBlock *Node = I->first; + const_iterator DFI = find(Node); + if (DFI == end()) + return true; + + if (compareDomSet(I->second, DFI->second)) + return true; + + ++I; + tmpFrontiers.erase(Node); + } + + if (!tmpFrontiers.empty()) + return true; + + return false; + } + + /// print - Convert to human readable form + /// + virtual void print(raw_ostream &OS, const Module* = 0) const; + + /// dump - Dump the dominance frontier to dbgs(). + void dump() const; +}; + + +//===------------------------------------- +/// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is +/// used to compute a forward dominator frontiers. +/// +class DominanceFrontier : public DominanceFrontierBase { +public: + static char ID; // Pass ID, replacement for typeid + DominanceFrontier() : + DominanceFrontierBase(ID, false) { + initializeDominanceFrontierPass(*PassRegistry::getPassRegistry()); + } + + BasicBlock *getRoot() const { + assert(Roots.size() == 1 && "Should always have entry node!"); + return Roots[0]; + } + + virtual bool runOnFunction(Function &) { + Frontiers.clear(); + DominatorTree &DT = getAnalysis<DominatorTree>(); + Roots = DT.getRoots(); + assert(Roots.size() == 1 && "Only one entry block for forward domfronts!"); + calculate(DT, DT[Roots[0]]); + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired<DominatorTree>(); + } + + const DomSetType &calculate(const DominatorTree &DT, + const DomTreeNode *Node); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/DominatorInternals.h b/include/llvm/Analysis/DominatorInternals.h index 654289e630..ae552b05ab 100644 --- a/include/llvm/Analysis/DominatorInternals.h +++ b/include/llvm/Analysis/DominatorInternals.h @@ -22,13 +22,9 @@ // A Fast Algorithm for Finding Dominators in a Flowgraph // T. Lengauer & R. Tarjan, ACM TOPLAS July 1979, pgs 121-141. // -// This implements both the O(n*ack(n)) and the O(n*log(n)) versions of EVAL and -// LINK, but it turns out that the theoretically slower O(n*log(n)) -// implementation is actually faster than the "efficient" algorithm (even for -// large CFGs) because the constant overheads are substantially smaller. The -// lower-complexity version can be enabled with the following #define: -// -#define BALANCE_IDOM_TREE 0 +// This implements the O(n*log(n)) versions of EVAL and LINK, because it turns +// out that the theoretically slower O(n*log(n)) implementation is actually +// faster than the almost-linear O(n*alpha(n)) version, even for large CFGs. // //===----------------------------------------------------------------------===// @@ -46,9 +42,6 @@ unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT, VInfo.Label = V; Vertex.push_back(V); // Vertex[n] = V; - //Info[V].Ancestor = 0; // Ancestor[n] = 0 - //Info[V].Child = 0; // Child[v] = 0 - VInfo.Size = 1; // Size[v] = 1 for (succ_iterator SI = succ_begin(V), E = succ_end(V); SI != E; ++SI) { InfoRec &SuccVInfo = DT.Info[*SI]; @@ -58,10 +51,10 @@ unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT, } } #else - bool IsChilOfArtificialExit = (N != 0); + bool IsChildOfArtificialExit = (N != 0); - std::vector<std::pair<typename GraphT::NodeType*, - typename GraphT::ChildIteratorType> > Worklist; + SmallVector<std::pair<typename GraphT::NodeType*, + typename GraphT::ChildIteratorType>, 32> Worklist; Worklist.push_back(std::make_pair(V, GraphT::child_begin(V))); while (!Worklist.empty()) { typename GraphT::NodeType* BB = Worklist.back().first; @@ -76,14 +69,11 @@ unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT, BBInfo.Label = BB; DT.Vertex.push_back(BB); // Vertex[n] = V; - //BBInfo[V].Ancestor = 0; // Ancestor[n] = 0 - //BBInfo[V].Child = 0; // Child[v] = 0 - BBInfo.Size = 1; // Size[v] = 1 - if (IsChilOfArtificialExit) + if (IsChildOfArtificialExit) BBInfo.Parent = 1; - IsChilOfArtificialExit = false; + IsChildOfArtificialExit = false; } // store the DFS number of the current BB - the reference to BBInfo might @@ -114,118 +104,47 @@ unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT, } template<class GraphT> -void Compress(DominatorTreeBase<typename GraphT::NodeType>& DT, - typename GraphT::NodeType *VIn) { +typename GraphT::NodeType* +Eval(DominatorTreeBase<typename GraphT::NodeType>& DT, + typename GraphT::NodeType *VIn, unsigned LastLinked) { + typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInInfo = + DT.Info[VIn]; + if (VInInfo.DFSNum < LastLinked) + return VIn; + SmallVector<typename GraphT::NodeType*, 32> Work; SmallPtrSet<typename GraphT::NodeType*, 32> Visited; - typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInVAInfo = - DT.Info[DT.Vertex[DT.Info[VIn].Ancestor]]; - if (VInVAInfo.Ancestor != 0) + if (VInInfo.Parent >= LastLinked) Work.push_back(VIn); while (!Work.empty()) { typename GraphT::NodeType* V = Work.back(); typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInfo = DT.Info[V]; - typename GraphT::NodeType* VAncestor = DT.Vertex[VInfo.Ancestor]; - typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VAInfo = - DT.Info[VAncestor]; + typename GraphT::NodeType* VAncestor = DT.Vertex[VInfo.Parent]; // Process Ancestor first - if (Visited.insert(VAncestor) && - VAInfo.Ancestor != 0) { + if (Visited.insert(VAncestor) && VInfo.Parent >= LastLinked) { Work.push_back(VAncestor); continue; } Work.pop_back(); // Update VInfo based on Ancestor info - if (VAInfo.Ancestor == 0) + if (VInfo.Parent < LastLinked) continue; + + typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VAInfo = + DT.Info[VAncestor]; typename GraphT::NodeType* VAncestorLabel = VAInfo.Label; typename GraphT::NodeType* VLabel = VInfo.Label; if (DT.Info[VAncestorLabel].Semi < DT.Info[VLabel].Semi) VInfo.Label = VAncestorLabel; - VInfo.Ancestor = VAInfo.Ancestor; - } -} - -template<class GraphT> -typename GraphT::NodeType* -Eval(DominatorTreeBase<typename GraphT::NodeType>& DT, - typename GraphT::NodeType *V) { - typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInfo = - DT.Info[V]; -#if !BALANCE_IDOM_TREE - // Higher-complexity but faster implementation - if (VInfo.Ancestor == 0) - return V; - Compress<GraphT>(DT, V); - return VInfo.Label; -#else - // Lower-complexity but slower implementation - if (VInfo.Ancestor == 0) - return VInfo.Label; - Compress<GraphT>(DT, V); - GraphT::NodeType* VLabel = VInfo.Label; - - GraphT::NodeType* VAncestorLabel = DT.Info[VInfo.Ancestor].Label; - if (DT.Info[VAncestorLabel].Semi >= DT.Info[VLabel].Semi) - return VLabel; - else - return VAncestorLabel; -#endif -} - -template<class GraphT> -void Link(DominatorTreeBase<typename GraphT::NodeType>& DT, - unsigned DFSNumV, typename GraphT::NodeType* W, - typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo) { -#if !BALANCE_IDOM_TREE - // Higher-complexity but faster implementation - WInfo.Ancestor = DFSNumV; -#else - // Lower-complexity but slower implementation - GraphT::NodeType* WLabel = WInfo.Label; - unsigned WLabelSemi = DT.Info[WLabel].Semi; - GraphT::NodeType* S = W; - InfoRec *SInfo = &DT.Info[S]; - - GraphT::NodeType* SChild = SInfo->Child; - InfoRec *SChildInfo = &DT.Info[SChild]; - - while (WLabelSemi < DT.Info[SChildInfo->Label].Semi) { - GraphT::NodeType* SChildChild = SChildInfo->Child; - if (SInfo->Size+DT.Info[SChildChild].Size >= 2*SChildInfo->Size) { - SChildInfo->Ancestor = S; - SInfo->Child = SChild = SChildChild; - SChildInfo = &DT.Info[SChild]; - } else { - SChildInfo->Size = SInfo->Size; - S = SInfo->Ancestor = SChild; - SInfo = SChildInfo; - SChild = SChildChild; - SChildInfo = &DT.Info[SChild]; - } + VInfo.Parent = VAInfo.Parent; } - DominatorTreeBase::InfoRec &VInfo = DT.Info[V]; - SInfo->Label = WLabel; - - assert(V != W && "The optimization here will not work in this case!"); - unsigned WSize = WInfo.Size; - unsigned VSize = (VInfo.Size += WSize); - - if (VSize < 2*WSize) - std::swap(S, VInfo.Child); - - while (S) { - SInfo = &DT.Info[S]; - SInfo->Ancestor = V; - S = SInfo->Child; - } -#endif + return VInInfo.Label; } template<class FuncT, class NodeT> @@ -242,9 +161,6 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, BBInfo.Label = NULL; DT.Vertex.push_back(NULL); // Vertex[n] = V; - //BBInfo[V].Ancestor = 0; // Ancestor[n] = 0 - //BBInfo[V].Child = 0; // Child[v] = 0 - BBInfo.Size = 1; // Size[v] = 1 } // Step #1: Number blocks in depth-first order and initialize variables used @@ -257,12 +173,34 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, // infinite loops). In these cases an artificial exit node is required. MultipleRoots |= (DT.isPostDominator() && N != F.size()); + // When naively implemented, the Lengauer-Tarjan algorithm requires a separate + // bucket for each vertex. However, this is unnecessary, because each vertex + // is only placed into a single bucket (that of its semidominator), and each + // vertex's bucket is processed before it is added to any bucket itself. + // + // Instead of using a bucket per vertex, we use a single array Buckets that + // has two purposes. Before the vertex V with preorder number i is processed, + // Buckets[i] stores the index of the first element in V's bucket. After V's + // bucket is processed, Buckets[i] stores the index of the next element in the + // bucket containing V, if any. + SmallVector<unsigned, 32> Buckets; + Buckets.resize(N + 1); + for (unsigned i = 1; i <= N; ++i) + Buckets[i] = i; + for (unsigned i = N; i >= 2; --i) { typename GraphT::NodeType* W = DT.Vertex[i]; typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo = DT.Info[W]; - // Step #2: Calculate the semidominators of all vertices + // Step #2: Implicitly define the immediate dominator of vertices + for (unsigned j = i; Buckets[j] != i; j = Buckets[j]) { + typename GraphT::NodeType* V = DT.Vertex[Buckets[j]]; + typename GraphT::NodeType* U = Eval<GraphT>(DT, V, i + 1); + DT.IDoms[V] = DT.Info[U].Semi < i ? U : W; + } + + // Step #3: Calculate the semidominators of all vertices // initialize the semi dominator to point to the parent node WInfo.Semi = WInfo.Parent; @@ -272,25 +210,28 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, E = InvTraits::child_end(W); CI != E; ++CI) { typename InvTraits::NodeType *N = *CI; if (DT.Info.count(N)) { // Only if this predecessor is reachable! - unsigned SemiU = DT.Info[Eval<GraphT>(DT, N)].Semi; + unsigned SemiU = DT.Info[Eval<GraphT>(DT, N, i + 1)].Semi; if (SemiU < WInfo.Semi) WInfo.Semi = SemiU; } } - DT.Info[DT.Vertex[WInfo.Semi]].Bucket.push_back(W); - - typename GraphT::NodeType* WParent = DT.Vertex[WInfo.Parent]; - Link<GraphT>(DT, WInfo.Parent, W, WInfo); + // If V is a non-root vertex and sdom(V) = parent(V), then idom(V) is + // necessarily parent(V). In this case, set idom(V) here and avoid placing + // V into a bucket. + if (WInfo.Semi == WInfo.Parent) { + DT.IDoms[W] = DT.Vertex[WInfo.Parent]; + } else { + Buckets[i] = Buckets[WInfo.Semi]; + Buckets[WInfo.Semi] = i; + } + } - // Step #3: Implicitly define the immediate dominator of vertices - std::vector<typename GraphT::NodeType*> &WParentBucket = - DT.Info[WParent].Bucket; - while (!WParentBucket.empty()) { - typename GraphT::NodeType* V = WParentBucket.back(); - WParentBucket.pop_back(); - typename GraphT::NodeType* U = Eval<GraphT>(DT, V); - DT.IDoms[V] = DT.Info[U].Semi < DT.Info[V].Semi ? U : WParent; + if (N >= 1) { + typename GraphT::NodeType* Root = DT.Vertex[1]; + for (unsigned j = 1; Buckets[j] != 1; j = Buckets[j]) { + typename GraphT::NodeType* V = DT.Vertex[Buckets[j]]; + DT.IDoms[V] = Root; } } diff --git a/include/llvm/Analysis/Dominators.h b/include/llvm/Analysis/Dominators.h index 2620d2aaae..230e83d301 100644 --- a/include/llvm/Analysis/Dominators.h +++ b/include/llvm/Analysis/Dominators.h @@ -7,14 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file defines the following classes: -// 1. DominatorTree: Represent dominators as an explicit tree structure. -// 2. DominanceFrontier: Calculate and hold the dominance frontier for a -// function. -// -// These data structures are listed in increasing order of complexity. It -// takes longer to calculate the dominator frontier, for example, than the -// DominatorTree mapping. +// This file defines the DominatorTree class, which provides fast and efficient +// dominance queries. // //===----------------------------------------------------------------------===// @@ -23,19 +17,15 @@ #include "llvm/Pass.h" #include "llvm/Function.h" -#include "llvm/Instructions.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Assembly/Writer.h" #include "llvm/Support/CFG.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> -#include <map> -#include <set> namespace llvm { @@ -205,15 +195,11 @@ protected: // Information record used during immediate dominators computation. struct InfoRec { unsigned DFSNum; + unsigned Parent; unsigned Semi; - unsigned Size; - NodeT *Label, *Child; - unsigned Parent, Ancestor; - - std::vector<NodeT*> Bucket; + NodeT *Label; - InfoRec() : DFSNum(0), Semi(0), Size(0), Label(0), Child(0), Parent(0), - Ancestor(0) {} + InfoRec() : DFSNum(0), Parent(0), Semi(0), Label(0) {} }; DenseMap<NodeT*, NodeT*> IDoms; @@ -303,9 +289,6 @@ public: : DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {} virtual ~DominatorTreeBase() { reset(); } - // FIXME: Should remove this - virtual bool runOnFunction(Function &F) { return false; } - /// compare - Return false if the other dominator tree base matches this /// dominator tree base. Otherwise return true. bool compare(DominatorTreeBase &Other) const { @@ -570,7 +553,7 @@ public: o << "Inorder PostDominator Tree: "; else o << "Inorder Dominator Tree: "; - if (this->DFSInfoValid) + if (!this->DFSInfoValid) o << "DFSNumbers invalid: " << SlowQueries << " slow queries."; o << "\n"; @@ -581,18 +564,10 @@ public: protected: template<class GraphT> - friend void Compress(DominatorTreeBase<typename GraphT::NodeType>& DT, - typename GraphT::NodeType* VIn); - - template<class GraphT> friend typename GraphT::NodeType* Eval( DominatorTreeBase<typename GraphT::NodeType>& DT, - typename GraphT::NodeType* V); - - template<class GraphT> - friend void Link(DominatorTreeBase<typename GraphT::NodeType>& DT, - unsigned DFSNumV, typename GraphT::NodeType* W, - typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo); + typename GraphT::NodeType* V, + unsigned LastLinked); template<class GraphT> friend unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT, @@ -766,7 +741,7 @@ public: AU.setPreservesAll(); } - inline bool dominates(DomTreeNode* A, DomTreeNode* B) const { + inline bool dominates(const DomTreeNode* A, const DomTreeNode* B) const { return DT->dominates(A, B); } @@ -896,196 +871,6 @@ template <> struct GraphTraits<DominatorTree*> }; -//===----------------------------------------------------------------------===// -/// DominanceFrontierBase - Common base class for computing forward and inverse -/// dominance frontiers for a function. -/// -class DominanceFrontierBase : public FunctionPass { -public: - typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb - typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map -protected: - DomSetMapType Frontiers; - std::vector<BasicBlock*> Roots; - const bool IsPostDominators; - -public: - DominanceFrontierBase(char &ID, bool isPostDom) - : FunctionPass(ID), IsPostDominators(isPostDom) {} - - /// getRoots - Return the root blocks of the current CFG. This may include - /// multiple blocks if we are computing post dominators. For forward - /// dominators, this will always be a single block (the entry node). - /// - inline const std::vector<BasicBlock*> &getRoots() const { return Roots; } - - /// isPostDominator - Returns true if analysis based of postdoms - /// - bool isPostDominator() const { return IsPostDominators; } - - virtual void releaseMemory() { Frontiers.clear(); } - - // Accessor interface: - typedef DomSetMapType::iterator iterator; - typedef DomSetMapType::const_iterator const_iterator; - iterator begin() { return Frontiers.begin(); } - const_iterator begin() const { return Frontiers.begin(); } - iterator end() { return Frontiers.end(); } - const_iterator end() const { return Frontiers.end(); } - iterator find(BasicBlock *B) { return Frontiers.find(B); } - const_iterator find(BasicBlock *B) const { return Frontiers.find(B); } - - iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) { - assert(find(BB) == end() && "Block already in DominanceFrontier!"); - return Frontiers.insert(std::make_pair(BB, frontier)).first; - } - - /// removeBlock - Remove basic block BB's frontier. - void removeBlock(BasicBlock *BB) { - assert(find(BB) != end() && "Block is not in DominanceFrontier!"); - for (iterator I = begin(), E = end(); I != E; ++I) - I->second.erase(BB); - Frontiers.erase(BB); - } - - void addToFrontier(iterator I, BasicBlock *Node) { - assert(I != end() && "BB is not in DominanceFrontier!"); - I->second.insert(Node); - } - - void removeFromFrontier(iterator I, BasicBlock *Node) { - assert(I != end() && "BB is not in DominanceFrontier!"); - assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); - I->second.erase(Node); - } - - /// compareDomSet - Return false if two domsets match. Otherwise - /// return true; - bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const { - std::set<BasicBlock *> tmpSet; - for (DomSetType::const_iterator I = DS2.begin(), - E = DS2.end(); I != E; ++I) - tmpSet.insert(*I); - - for (DomSetType::const_iterator I = DS1.begin(), - E = DS1.end(); I != E; ) { - BasicBlock *Node = *I++; - - if (tmpSet.erase(Node) == 0) - // Node is in DS1 but not in DS2. - return true; - } - - if (!tmpSet.empty()) - // There are nodes that are in DS2 but not in DS1. - return true; - - // DS1 and DS2 matches. - return false; - } - - /// compare - Return true if the other dominance frontier base matches - /// this dominance frontier base. Otherwise return false. - bool compare(DominanceFrontierBase &Other) const { - DomSetMapType tmpFrontiers; - for (DomSetMapType::const_iterator I = Other.begin(), - E = Other.end(); I != E; ++I) - tmpFrontiers.insert(std::make_pair(I->first, I->second)); - - for (DomSetMapType::iterator I = tmpFrontiers.begin(), - E = tmpFrontiers.end(); I != E; ) { - BasicBlock *Node = I->first; - const_iterator DFI = find(Node); - if (DFI == end()) - return true; - - if (compareDomSet(I->second, DFI->second)) - return true; - - ++I; - tmpFrontiers.erase(Node); - } - - if (!tmpFrontiers.empty()) - return true; - - return false; - } - - /// print - Convert to human readable form - /// - virtual void print(raw_ostream &OS, const Module* = 0) const; - - /// dump - Dump the dominance frontier to dbgs(). - void dump() const; -}; - - -//===------------------------------------- -/// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is -/// used to compute a forward dominator frontiers. -/// -class DominanceFrontier : public DominanceFrontierBase { -public: - static char ID; // Pass ID, replacement for typeid - DominanceFrontier() : - DominanceFrontierBase(ID, false) { - initializeDominanceFrontierPass(*PassRegistry::getPassRegistry()); - } - - BasicBlock *getRoot() const { - assert(Roots.size() == 1 && "Should always have entry node!"); - return Roots[0]; - } - - virtual bool runOnFunction(Function &) { - Frontiers.clear(); - DominatorTree &DT = getAnalysis<DominatorTree>(); - Roots = DT.getRoots(); - assert(Roots.size() == 1 && "Only one entry block for forward domfronts!"); - calculate(DT, DT[Roots[0]]); - return false; - } - - virtual void verifyAnalysis() const; - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired<DominatorTree>(); - } - - /// splitBlock - BB is split and now it has one successor. Update dominance - /// frontier to reflect this change. - void splitBlock(BasicBlock *BB); - - /// BasicBlock BB's new dominator is NewBB. Update BB's dominance frontier - /// to reflect this change. - void changeImmediateDominator(BasicBlock *BB, BasicBlock *NewBB, - DominatorTree *DT) { - // NewBB is now dominating BB. Which means BB's dominance - // frontier is now part of NewBB's dominance frontier. However, BB - // itself is not member of NewBB's dominance frontier. - DominanceFrontier::iterator NewDFI = find(NewBB); - DominanceFrontier::iterator DFI = find(BB); - // If BB was an entry block then its frontier is empty. - if (DFI == end()) - return; - DominanceFrontier::DomSetType BBSet = DFI->second; - for (DominanceFrontier::DomSetType::iterator BBSetI = BBSet.begin(), - BBSetE = BBSet.end(); BBSetI != BBSetE; ++BBSetI) { - BasicBlock *DFMember = *BBSetI; - // Insert only if NewBB dominates DFMember. - if (!DT->dominates(NewBB, DFMember)) - NewDFI->second.insert(DFMember); - } - NewDFI->second.erase(BB); - } - - const DomSetType &calculate(const DominatorTree &DT, - const DomTreeNode *Node); -}; - - } // End llvm namespace #endif diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index ccec4c5247..b08bf57ace 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -33,7 +33,7 @@ namespace llvm { namespace InlineConstants { // Various magic constants used to adjust heuristics. const int InstrCost = 5; - const int IndirectCallBonus = 500; + const int IndirectCallBonus = -100; const int CallPenalty = 25; const int LastCallToStaticBonus = -15000; const int ColdccPenalty = 2000; @@ -96,10 +96,9 @@ namespace llvm { public: unsigned ConstantWeight; unsigned AllocaWeight; - unsigned ConstantBonus; - ArgInfo(unsigned CWeight, unsigned AWeight, unsigned CBonus) - : ConstantWeight(CWeight), AllocaWeight(AWeight), ConstantBonus(CBonus) + ArgInfo(unsigned CWeight, unsigned AWeight) + : ConstantWeight(CWeight), AllocaWeight(AWeight) {} }; @@ -112,8 +111,6 @@ namespace llvm { /// entry here. std::vector<ArgInfo> ArgumentWeights; - - /// analyzeFunction - Add information about the specified function /// to the current structure. void analyzeFunction(Function *F); @@ -127,6 +124,10 @@ namespace llvm { // the ValueMap will update itself when this happens. ValueMap<const Function *, FunctionInfo> CachedFunctionInfo; + int CountBonusForConstant(Value *V, Constant *C = NULL); + int ConstantFunctionBonus(CallSite CS, Constant *C); + int getInlineSize(CallSite CS, Function *Callee); + int getInlineBonuses(CallSite CS, Function *Callee); public: /// getInlineCost - The heuristic used to determine if we should inline the diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index d1ad061d5c..dff1ba2f7b 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -7,9 +7,12 @@ // //===----------------------------------------------------------------------===// // -// This file declares routines for folding instructions into simpler forms that -// do not require creating new instructions. For example, this does constant -// folding, and can handle identities like (X&0)->0. +// This file declares routines for folding instructions into simpler forms +// that do not require creating new instructions. This does constant folding +// ("add i32 1, 1" -> "2") but can also handle non-constant operands, either +// returning a constant ("and i32 %x, 0" -> "0") or an already existing value +// ("and i32 %x, %x" -> "%x"). If the simplification is also an instruction +// then it dominates the original instruction. // //===----------------------------------------------------------------------===// @@ -25,37 +28,86 @@ namespace llvm { /// SimplifyAddInst - Given operands for an Add, see if we can /// fold the result. If not, this returns null. Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, - const TargetData *TD = 0); + const TargetData *TD = 0, const DominatorTree *DT = 0); + + /// SimplifySubInst - Given operands for a Sub, see if we can + /// fold the result. If not, this returns null. + Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, + const TargetData *TD = 0, const DominatorTree *DT = 0); + + /// SimplifyMulInst - Given operands for a Mul, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyMulInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifySDivInst - Given operands for an SDiv, see if we can + /// fold the result. If not, this returns null. + Value *SimplifySDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyUDivInst - Given operands for a UDiv, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyUDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyFDivInst - Given operands for an FDiv, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyFDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyShlInst - Given operands for a Shl, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, + const TargetData *TD = 0, const DominatorTree *DT = 0); + + /// SimplifyLShrInst - Given operands for a LShr, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, + const TargetData *TD = 0, const DominatorTree *DT=0); + + /// SimplifyAShrInst - Given operands for a AShr, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, + const TargetData *TD = 0, + const DominatorTree *DT = 0); /// SimplifyAndInst - Given operands for an And, see if we can /// fold the result. If not, this returns null. - Value *SimplifyAndInst(Value *LHS, Value *RHS, - const TargetData *TD = 0); + Value *SimplifyAndInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); /// SimplifyOrInst - Given operands for an Or, see if we can /// fold the result. If not, this returns null. - Value *SimplifyOrInst(Value *LHS, Value *RHS, - const TargetData *TD = 0); + Value *SimplifyOrInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyXorInst - Given operands for a Xor, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyXorInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const TargetData *TD = 0); + const TargetData *TD = 0, + const DominatorTree *DT = 0); /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const TargetData *TD = 0); + const TargetData *TD = 0, + const DominatorTree *DT = 0); /// SimplifySelectInst - Given operands for a SelectInst, see if we can fold /// the result. If not, this returns null. Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, - const TargetData *TD = 0); + const TargetData *TD = 0, + const DominatorTree *DT = 0); /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyGEPInst(Value * const *Ops, unsigned NumOps, - const TargetData *TD = 0); + const TargetData *TD = 0, const DominatorTree *DT = 0); //=== Helper functions for higher up the class hierarchy. @@ -63,17 +115,15 @@ namespace llvm { /// SimplifyCmpInst - Given operands for a CmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const TargetData *TD = 0); + const TargetData *TD = 0, const DominatorTree *DT = 0); /// SimplifyBinOp - Given operands for a BinaryOperator, see if we can /// fold the result. If not, this returns null. Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, - const TargetData *TD = 0); + const TargetData *TD = 0, const DominatorTree *DT = 0); /// SimplifyInstruction - See if we can compute a simplified version of this /// instruction. If not, this returns null. - /// WARNING: If called on unreachable code, an instruction may be reported - /// to simplify to itself. Value *SimplifyInstruction(Instruction *I, const TargetData *TD = 0, const DominatorTree *DT = 0); diff --git a/include/llvm/Analysis/LiveValues.h b/include/llvm/Analysis/LiveValues.h deleted file mode 100644 index b92cb7833a..0000000000 --- a/include/llvm/Analysis/LiveValues.h +++ /dev/null @@ -1,99 +0,0 @@ -//===- LiveValues.h - Liveness information for LLVM IR Values. ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the interface for the LLVM IR Value liveness -// analysis pass. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_LIVEVALUES_H -#define LLVM_ANALYSIS_LIVEVALUES_H - -#include "llvm/Pass.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallPtrSet.h" - -namespace llvm { - -class DominatorTree; -class LoopInfo; -class Value; - -/// LiveValues - Analysis that provides liveness information for -/// LLVM IR Values. -/// -class LiveValues : public FunctionPass { - DominatorTree *DT; - LoopInfo *LI; - - /// Memo - A bunch of state to be associated with a value. - /// - struct Memo { - /// Used - The set of blocks which contain a use of the value. - /// - SmallPtrSet<const BasicBlock *, 4> Used; - - /// LiveThrough - A conservative approximation of the set of blocks in - /// which the value is live-through, meaning blocks properly dominated - /// by the definition, and from which blocks containing uses of the - /// value are reachable. - /// - SmallPtrSet<const BasicBlock *, 4> LiveThrough; - - /// Killed - A conservative approximation of the set of blocks in which - /// the value is used and not live-out. - /// - SmallPtrSet<const BasicBlock *, 4> Killed; - }; - - /// Memos - Remembers the Memo for each Value. This is populated on - /// demand. - /// - DenseMap<const Value *, Memo> Memos; - - /// getMemo - Retrieve an existing Memo for the given value if one - /// is available, otherwise compute a new one. - /// - Memo &getMemo(const Value *V); - - /// compute - Compute a new Memo for the given value. - /// - Memo &compute(const Value *V); - -public: - static char ID; - LiveValues(); - - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual bool runOnFunction(Function &F); - virtual void releaseMemory(); - - /// isUsedInBlock - Test if the given value is used in the given block. - /// - bool isUsedInBlock(const Value *V, const BasicBlock *BB); - - /// isLiveThroughBlock - Test if the given value is known to be - /// live-through the given block, meaning that the block is properly - /// dominated by the value's definition, and there exists a block - /// reachable from it that contains a use. This uses a conservative - /// approximation that errs on the side of returning false. - /// - bool isLiveThroughBlock(const Value *V, const BasicBlock *BB); - - /// isKilledInBlock - Test if the given value is known to be killed in - /// the given block, meaning that the block contains a use of the value, - /// and no blocks reachable from the block contain a use. This uses a - /// conservative approximation that errs on the side of returning false. - /// - bool isKilledInBlock(const Value *V, const BasicBlock *BB); -}; - -} // end namespace llvm - -#endif diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index 326b9d2891..392bdad5ab 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -32,6 +32,7 @@ #define LLVM_ANALYSIS_LOOP_INFO_H #include "llvm/Pass.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SmallVector.h" @@ -40,6 +41,7 @@ #include "llvm/Support/CFG.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <map> namespace llvm { @@ -53,6 +55,7 @@ static void RemoveFromVector(std::vector<T*> &V, T *N) { class DominatorTree; class LoopInfo; class Loop; +class PHINode; template<class N, class M> class LoopInfoBase; template<class N, class M> class LoopBase; @@ -629,7 +632,7 @@ private: template<class BlockT, class LoopT> class LoopInfoBase { // BBMap - Mapping of basic blocks to the inner most loop they occur in - std::map<BlockT *, LoopT *> BBMap; + DenseMap<BlockT *, LoopT *> BBMap; std::vector<LoopT *> TopLevelLoops; friend class LoopBase<BlockT, LoopT>; @@ -660,7 +663,7 @@ public: /// block is in no loop (for example the entry node), null is returned. /// LoopT *getLoopFor(const BlockT *BB) const { - typename std::map<BlockT *, LoopT *>::const_iterator I= + typename DenseMap<BlockT *, LoopT *>::const_iterator I= BBMap.find(const_cast<BlockT*>(BB)); return I != BBMap.end() ? I->second : 0; } @@ -728,7 +731,7 @@ public: /// including all of the Loop objects it is nested in and our mapping from /// BasicBlocks to loops. void removeBlock(BlockT *BB) { - typename std::map<BlockT *, LoopT *>::iterator I = BBMap.find(BB); + typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB); if (I != BBMap.end()) { for (LoopT *L = I->second; L; L = L->getParentLoop()) L->removeBlockFromLoop(BB); @@ -922,7 +925,7 @@ public: for (unsigned i = 0; i < TopLevelLoops.size(); ++i) TopLevelLoops[i]->print(OS); #if 0 - for (std::map<BasicBlock*, LoopT*>::const_iterator I = BBMap.begin(), + for (DenseMap<BasicBlock*, LoopT*>::const_iterator I = BBMap.begin(), E = BBMap.end(); I != E; ++I) OS << "BB '" << I->first->getName() << "' level = " << I->second->getLoopDepth() << "\n"; @@ -1020,6 +1023,27 @@ public: void removeBlock(BasicBlock *BB) { LI.removeBlock(BB); } + + /// replacementPreservesLCSSAForm - Returns true if replacing From with To + /// everywhere is guaranteed to preserve LCSSA form. + bool replacementPreservesLCSSAForm(Instruction *From, Value *To) { + // Preserving LCSSA form is only problematic if the replacing value is an + // instruction. + Instruction *I = dyn_cast<Instruction>(To); + if (!I) return true; + // If both instructions are defined in the same basic block then replacement + // cannot break LCSSA form. + if (I->getParent() == From->getParent()) + return true; + // If the instruction is not defined in a loop then it can safely replace + // anything. + Loop *ToLoop = getLoopFor(I->getParent()); + if (!ToLoop) return true; + // If the replacing instruction is defined in the same loop as the original + // instruction, or in a loop that contains it as an inner loop, then using + // it as a replacement will not break LCSSA form. + return ToLoop->contains(getLoopFor(From->getParent())); + } }; diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index a4f916227b..22493f6f8b 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -74,6 +74,10 @@ Value *getMallocArraySize(CallInst *CI, const TargetData *TD, /// isFreeCall - Returns non-null if the value is a call to the builtin free() const CallInst *isFreeCall(const Value *I); + +static inline CallInst *isFreeCall(Value *I) { + return const_cast<CallInst*>(isFreeCall((const Value*)I)); +} } // End llvm namespace diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index cc34992b45..4d5dd1987f 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -47,6 +47,9 @@ namespace llvm { /// pair holds the instruction that clobbers the memory. For example, /// this occurs when we see a may-aliased store to the memory location we /// care about. + /// + /// A dependence query on the first instruction of the entry block will + /// return a clobber(self) result. Clobber, /// Def - This is a dependence on the specified instruction which @@ -335,11 +338,19 @@ namespace llvm { /// critical edges. void invalidateCachedPredecessors(); - private: + /// getPointerDependencyFrom - Return the instruction on which a memory + /// location depends. If isLoad is true, this routine ignores may-aliases + /// with read-only operations. If isLoad is false, this routine ignores + /// may-aliases with reads from read-only locations. + /// + /// Note that this is an uncached query, and thus may be inefficient. + /// MemDepResult getPointerDependencyFrom(const AliasAnalysis::Location &Loc, bool isLoad, BasicBlock::iterator ScanIt, BasicBlock *BB); + + private: MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, BasicBlock::iterator ScanIt, BasicBlock *BB); diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index 64bd290dd6..0eff75fe2f 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -116,6 +116,28 @@ namespace llvm { //===--------------------------------------------------------------------===// // + // createPathProfileLoaderPass - This pass loads information from a path + // profile dump file. + // + ModulePass *createPathProfileLoaderPass(); + extern char &PathProfileLoaderPassID; + + //===--------------------------------------------------------------------===// + // + // createNoPathProfileInfoPass - This pass implements the default + // "no path profile". + // + ImmutablePass *createNoPathProfileInfoPass(); + + //===--------------------------------------------------------------------===// + // + // createPathProfileVerifierPass - This pass verifies path profiling + // information. + // + ModulePass *createPathProfileVerifierPass(); + + //===--------------------------------------------------------------------===// + // // createDSAAPass - This pass implements simple context sensitive alias // analysis. // @@ -137,12 +159,6 @@ namespace llvm { //===--------------------------------------------------------------------===// // - // createLiveValuesPass - This creates an instance of the LiveValues pass. - // - FunctionPass *createLiveValuesPass(); - - //===--------------------------------------------------------------------===// - // /// createLazyValueInfoPass - This creates an instance of the LazyValueInfo /// pass. FunctionPass *createLazyValueInfoPass(); @@ -153,7 +169,7 @@ namespace llvm { // LoopDependenceAnalysis pass. // LoopPass *createLoopDependenceAnalysisPass(); - + // Minor pass prototypes, allowing us to expose them through bugpoint and // analyze. FunctionPass *createInstCountPass(); diff --git a/include/llvm/Analysis/PathNumbering.h b/include/llvm/Analysis/PathNumbering.h new file mode 100644 index 0000000000..7025e28484 --- /dev/null +++ b/include/llvm/Analysis/PathNumbering.h @@ -0,0 +1,304 @@ +//===- PathNumbering.h ----------------------------------------*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Ball-Larus path numbers uniquely identify paths through a directed acyclic +// graph (DAG) [Ball96]. For a CFG backedges are removed and replaced by phony +// edges to obtain a DAG, and thus the unique path numbers [Ball96]. +// +// The purpose of this analysis is to enumerate the edges in a CFG in order +// to obtain paths from path numbers in a convenient manner. As described in +// [Ball96] edges can be enumerated such that given a path number by following +// the CFG and updating the path number, the path is obtained. +// +// [Ball96] +// T. Ball and J. R. Larus. "Efficient Path Profiling." +// International Symposium on Microarchitecture, pages 46-57, 1996. +// http://portal.acm.org/citation.cfm?id=243857 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PATH_NUMBERING_H +#define LLVM_PATH_NUMBERING_H + +#include "llvm/BasicBlock.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Support/CFG.h" +#include "llvm/Analysis/ProfileInfoTypes.h" +#include <map> +#include <stack> +#include <vector> + +namespace llvm { +class BallLarusNode; +class BallLarusEdge; +class BallLarusDag; + +// typedefs for storage/ interators of various DAG components +typedef std::vector<BallLarusNode*> BLNodeVector; +typedef std::vector<BallLarusNode*>::iterator BLNodeIterator; +typedef std::vector<BallLarusEdge*> BLEdgeVector; +typedef std::vector<BallLarusEdge*>::iterator BLEdgeIterator; +typedef std::map<BasicBlock*, BallLarusNode*> BLBlockNodeMap; +typedef std::stack<BallLarusNode*> BLNodeStack; + +// Represents a basic block with information necessary for the BallLarus +// algorithms. +class BallLarusNode { +public: + enum NodeColor { WHITE, GRAY, BLACK }; + + // Constructor: Initializes a new Node for the given BasicBlock + BallLarusNode(BasicBlock* BB) : + _basicBlock(BB), _numberPaths(0), _color(WHITE) { + static unsigned nextUID = 0; + _uid = nextUID++; + } + + // Returns the basic block for the BallLarusNode + BasicBlock* getBlock(); + + // Get/set the number of paths to the exit starting at the node. + unsigned getNumberPaths(); + void setNumberPaths(unsigned numberPaths); + + // Get/set the NodeColor used in graph algorithms. + NodeColor getColor(); + void setColor(NodeColor color); + + // Iterator information for predecessor edges. Includes phony and + // backedges. + BLEdgeIterator predBegin(); + BLEdgeIterator predEnd(); + unsigned getNumberPredEdges(); + + // Iterator information for successor edges. Includes phony and + // backedges. + BLEdgeIterator succBegin(); + BLEdgeIterator succEnd(); + unsigned getNumberSuccEdges(); + + // Add an edge to the predecessor list. + void addPredEdge(BallLarusEdge* edge); + + // Remove an edge from the predecessor list. + void removePredEdge(BallLarusEdge* edge); + + // Add an edge to the successor list. + void addSuccEdge(BallLarusEdge* edge); + + // Remove an edge from the successor list. + void removeSuccEdge(BallLarusEdge* edge); + + // Returns the name of the BasicBlock being represented. If BasicBlock + // is null then returns "<null>". If BasicBlock has no name, then + // "<unnamed>" is returned. Intended for use with debug output. + std::string getName(); + +private: + // The corresponding underlying BB. + BasicBlock* _basicBlock; + + // Holds the predecessor edges of this node. + BLEdgeVector _predEdges; + + // Holds the successor edges of this node. + BLEdgeVector _succEdges; + + // The number of paths from the node to the exit. + unsigned _numberPaths; + + // 'Color' used by graph algorithms to mark the node. + NodeColor _color; + + // Unique ID to ensure naming difference with dotgraphs + unsigned _uid; + + // Removes an edge from an edgeVector. Used by removePredEdge and + // removeSuccEdge. + void removeEdge(BLEdgeVector& v, BallLarusEdge* e); +}; + +// Represents an edge in the Dag. For an edge, v -> w, v is the source, and +// w is the target. +class BallLarusEdge { +public: + enum EdgeType { NORMAL, BACKEDGE, SPLITEDGE, + BACKEDGE_PHONY, SPLITEDGE_PHONY, CALLEDGE_PHONY }; + + // Constructor: Initializes an BallLarusEdge with a source and target. + BallLarusEdge(BallLarusNode* source, BallLarusNode* target, + unsigned duplicateNumber) + : _source(source), _target(target), _weight(0), _edgeType(NORMAL), + _realEdge(NULL), _duplicateNumber(duplicateNumber) {} + + // Returns the source/ target node of this edge. + BallLarusNode* getSource() const; + BallLarusNode* getTarget() const; + + // Sets the type of the edge. + EdgeType getType() const; + + // Gets the type of the edge. + void setType(EdgeType type); + + // Returns the weight of this edge. Used to decode path numbers to + // sequences of basic blocks. + unsigned getWeight(); + + // Sets the weight of the edge. Used during path numbering. + void setWeight(unsigned weight); + + // Gets/sets the phony edge originating at the root. + BallLarusEdge* getPhonyRoot(); + void setPhonyRoot(BallLarusEdge* phonyRoot); + + // Gets/sets the phony edge terminating at the exit. + BallLarusEdge* getPhonyExit(); + void setPhonyExit(BallLarusEdge* phonyExit); + + // Gets/sets the associated real edge if this is a phony edge. + BallLarusEdge* getRealEdge(); + void setRealEdge(BallLarusEdge* realEdge); + + // Returns the duplicate number of the edge. + unsigned getDuplicateNumber(); + +protected: + // Source node for this edge. + BallLarusNode* _source; + + // Target node for this edge. + BallLarusNode* _target; + +private: + // Edge weight cooresponding to path number increments before removing + // increments along a spanning tree. The sum over the edge weights gives + // the path number. + unsigned _weight; + + // Type to represent for what this edge is intended + EdgeType _edgeType; + + // For backedges and split-edges, the phony edge which is linked to the + // root node of the DAG. This contains a path number initialization. + BallLarusEdge* _phonyRoot; + + // For backedges and split-edges, the phony edge which is linked to the + // exit node of the DAG. This contains a path counter increment, and + // potentially a path number increment. + BallLarusEdge* _phonyExit; + + // If this is a phony edge, _realEdge is a link to the back or split + // edge. Otherwise, this is null. + BallLarusEdge* _realEdge; + + // An ID to differentiate between those edges which have the same source + // and destination blocks. + unsigned _duplicateNumber; +}; + +// Represents the Ball Larus DAG for a given Function. Can calculate +// various properties required for instrumentation or analysis. E.g. the +// edge weights that determine the path number. +class BallLarusDag { +public: + // Initializes a BallLarusDag from the CFG of a given function. Must + // call init() after creation, since some initialization requires + // virtual functions. + BallLarusDag(Function &F) + : _root(NULL), _exit(NULL), _function(F) {} + + // Initialization that requires virtual functions which are not fully + // functional in the constructor. + void init(); + + // Frees all memory associated with the DAG. + virtual ~BallLarusDag(); + + // Calculate the path numbers by assigning edge increments as prescribed + // in Ball-Larus path profiling. + void calculatePathNumbers(); + + // Returns the number of paths for the DAG. + unsigned getNumberOfPaths(); + + // Returns the root (i.e. entry) node for the DAG. + BallLarusNode* getRoot(); + + // Returns the exit node for the DAG. + BallLarusNode* getExit(); + + // Returns the function for the DAG. + Function& getFunction(); + + // Clears the node colors. + void clearColors(BallLarusNode::NodeColor color); + +protected: + // All nodes in the DAG. + BLNodeVector _nodes; + + // All edges in the DAG. + BLEdgeVector _edges; + + // All backedges in the DAG. + BLEdgeVector _backEdges; + + // Allows subclasses to determine which type of Node is created. + // Override this method to produce subclasses of BallLarusNode if + // necessary. The destructor of BallLarusDag will call free on each pointer + // created. + virtual BallLarusNode* createNode(BasicBlock* BB); + + // Allows subclasses to determine which type of Edge is created. + // Override this method to produce subclasses of BallLarusEdge if + // necessary. Parameters source and target will have been created by + // createNode and can be cast to the subclass of BallLarusNode* + // returned by createNode. The destructor of BallLarusDag will call free + // on each pointer created. + virtual BallLarusEdge* createEdge(BallLarusNode* source, BallLarusNode* + target, unsigned duplicateNumber); + + // Proxy to node's constructor. Updates the DAG state. + BallLarusNode* addNode(BasicBlock* BB); + + // Proxy to edge's constructor. Updates the DAG state. + BallLarusEdge* addEdge(BallLarusNode* source, BallLarusNode* target, + unsigned duplicateNumber); + +private: + // The root (i.e. entry) node for this DAG. + BallLarusNode* _root; + + // The exit node for this DAG. + BallLarusNode* _exit; + + // The function represented by this DAG. + Function& _function; + + // Processes one node and its imediate edges for building the DAG. + void buildNode(BLBlockNodeMap& inDag, std::stack<BallLarusNode*>& dfsStack); + + // Process an edge in the CFG for DAG building. + void buildEdge(BLBlockNodeMap& inDag, std::stack<BallLarusNode*>& dfsStack, + BallLarusNode* currentNode, BasicBlock* succBB, + unsigned duplicateNumber); + + // The weight on each edge is the increment required along any path that + // contains that edge. + void calculatePathNumbersFrom(BallLarusNode* node); + + // Adds a backedge with its phony edges. Updates the DAG state. + void addBackedge(BallLarusNode* source, BallLarusNode* target, + unsigned duplicateCount); +}; +} // end namespace llvm + +#endif diff --git a/include/llvm/Analysis/PathProfileInfo.h b/include/llvm/Analysis/PathProfileInfo.h new file mode 100644 index 0000000000..263763f7a8 --- /dev/null +++ b/include/llvm/Analysis/PathProfileInfo.h @@ -0,0 +1,113 @@ +//===- PathProfileInfo.h --------------------------------------*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file outlines the interface used by optimizers to load path profiles. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PATHPROFILEINFO_H +#define LLVM_PATHPROFILEINFO_H + +#include "llvm/BasicBlock.h" +#include "llvm/Analysis/PathNumbering.h" +#include <stack> + +namespace llvm { + +class ProfilePath; +class ProfilePathEdge; +class PathProfileInfo; + +typedef std::vector<ProfilePathEdge> ProfilePathEdgeVector; +typedef std::vector<ProfilePathEdge>::iterator ProfilePathEdgeIterator; + +typedef std::vector<BasicBlock*> ProfilePathBlockVector; +typedef std::vector<BasicBlock*>::iterator ProfilePathBlockIterator; + +typedef std::map<unsigned int,ProfilePath*> ProfilePathMap; +typedef std::map<unsigned int,ProfilePath*>::iterator ProfilePathIterator; + +typedef std::map<Function*,unsigned int> FunctionPathCountMap; +typedef std::map<Function*,ProfilePathMap> FunctionPathMap; +typedef std::map<Function*,ProfilePathMap>::iterator FunctionPathIterator; + +class ProfilePathEdge { +public: + ProfilePathEdge(BasicBlock* source, BasicBlock* target, + unsigned duplicateNumber); + + inline unsigned getDuplicateNumber() { return _duplicateNumber; } + inline BasicBlock* getSource() { return _source; } + inline BasicBlock* getTarget() { return _target; } + +protected: + BasicBlock* _source; + BasicBlock* _target; + unsigned _duplicateNumber; +}; + +class ProfilePath { +public: + ProfilePath(unsigned int number, unsigned int count, + double countStdDev, PathProfileInfo* ppi); + + double getFrequency() const; + + inline unsigned int getNumber() const { return _number; } + inline unsigned int getCount() const { return _count; } + inline double getCountStdDev() const { return _countStdDev; } + + ProfilePathEdgeVector* getPathEdges() const; + ProfilePathBlockVector* getPathBlocks() const; + + BasicBlock* getFirstBlockInPath() const; + +private: + unsigned int _number; + unsigned int _count; + double _countStdDev; + + // double pointer back to the profiling info + PathProfileInfo* _ppi; +}; + +// TODO: overload [] operator for getting path +// Add: getFunctionCallCount() +class PathProfileInfo { + public: + PathProfileInfo(); + ~PathProfileInfo(); + + void setCurrentFunction(Function* F); + Function* getCurrentFunction() const; + BasicBlock* getCurrentFunctionEntry(); + + ProfilePath* getPath(unsigned int number); + unsigned int getPotentialPathCount(); + + ProfilePathIterator pathBegin(); + ProfilePathIterator pathEnd(); + unsigned int pathsRun(); + + static char ID; // Pass identification + std::string argList; + +protected: + FunctionPathMap _functionPaths; + FunctionPathCountMap _functionPathCounts; + +private: + BallLarusDag* _currentDag; + Function* _currentFunction; + + friend class ProfilePath; +}; +} // end namespace llvm + +#endif diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h index b75dd909a9..2cd6ae346e 100644 --- a/include/llvm/Analysis/PostDominators.h +++ b/include/llvm/Analysis/PostDominators.h @@ -14,7 +14,7 @@ #ifndef LLVM_ANALYSIS_POST_DOMINATORS_H #define LLVM_ANALYSIS_POST_DOMINATORS_H -#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/DominanceFrontier.h" namespace llvm { diff --git a/include/llvm/Analysis/ProfileInfoTypes.h b/include/llvm/Analysis/ProfileInfoTypes.h index 0d531d5c5f..6b4ac85082 100644 --- a/include/llvm/Analysis/ProfileInfoTypes.h +++ b/include/llvm/Analysis/ProfileInfoTypes.h @@ -1,4 +1,4 @@ -/*===-- ProfileInfoTypes.h - Profiling info shared constants ------*- C -*-===*\ +/*===-- ProfileInfoTypes.h - Profiling info shared constants --------------===*\ |* |* The LLVM Compiler Infrastructure |* @@ -16,6 +16,17 @@ #ifndef LLVM_ANALYSIS_PROFILEINFOTYPES_H #define LLVM_ANALYSIS_PROFILEINFOTYPES_H +/* Included by libprofile. */ +#if defined(__cplusplus) +extern "C" { +#endif + +/* IDs to distinguish between those path counters stored in hashses vs arrays */ +enum ProfilingStorageType { + ProfilingArray = 1, + ProfilingHash = 2 +}; + enum ProfilingType { ArgumentInfo = 1, /* The command line argument block */ FunctionInfo = 2, /* Function profiling information */ @@ -26,4 +37,24 @@ enum ProfilingType { OptEdgeInfo = 7 /* Edge profiling information, optimal version */ }; +/* + * The header for tables that map path numbers to path counters. + */ +typedef struct { + unsigned fnNumber; /* function number for these counters */ + unsigned numEntries; /* number of entries stored */ +} PathProfileHeader; + +/* + * Describes an entry in a tagged table for path counters. + */ +typedef struct { + unsigned pathNumber; + unsigned pathCounter; +} PathProfileTableEntry; + +#if defined(__cplusplus) +} +#endif + #endif /* LLVM_ANALYSIS_PROFILEINFOTYPES_H */ diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 737d46cac6..a36ca110d8 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -305,6 +305,20 @@ public: /// NULL if such a basic block does not exist. Region *getExpandedRegion() const; + /// @brief Return the first block of this region's single entry edge, + /// if existing. + /// + /// @return The BasicBlock starting this region's single entry edge, + /// else NULL. + BasicBlock *getEnteringBlock() const; + + /// @brief Return the first block of this region's single exit edge, + /// if existing. + /// + /// @return The BasicBlock starting this region's single exit edge, + /// else NULL. + BasicBlock *getExitingBlock() const; + /// @brief Is this a simple region? /// /// A region is simple if it has exactly one exit and one entry edge. diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 1fa94e9c31..d1938061be 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -24,7 +24,7 @@ #include "llvm/Pass.h" #include "llvm/Instructions.h" #include "llvm/Function.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/ValueHandle.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ConstantRange.h" @@ -70,27 +70,16 @@ namespace llvm { private: SCEV(const SCEV &); // DO NOT IMPLEMENT void operator=(const SCEV &); // DO NOT IMPLEMENT - protected: - virtual ~SCEV(); + public: explicit SCEV(const FoldingSetNodeIDRef ID, unsigned SCEVTy) : FastID(ID), SCEVType(SCEVTy), SubclassData(0) {} unsigned getSCEVType() const { return SCEVType; } - /// isLoopInvariant - Return true if the value of this SCEV is unchanging in - /// the specified loop. - virtual bool isLoopInvariant(const Loop *L) const = 0; - - /// hasComputableLoopEvolution - Return true if this SCEV changes value in a - /// known way in the specified loop. This property being true implies that - /// the value is variant in the loop AND that we can emit an expression to - /// compute the value of the expression at any particular loop iteration. - virtual bool hasComputableLoopEvolution(const Loop *L) const = 0; - /// getType - Return the LLVM type of this SCEV expression. /// - virtual const Type *getType() const = 0; + const Type *getType() const; /// isZero - Return true if the expression is a constant zero. /// @@ -105,22 +94,10 @@ namespace llvm { /// bool isAllOnesValue() const; - /// hasOperand - Test whether this SCEV has Op as a direct or - /// indirect operand. - virtual bool hasOperand(const SCEV *Op) const = 0; - - /// dominates - Return true if elements that makes up this SCEV dominates - /// the specified basic block. - virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const = 0; - - /// properlyDominates - Return true if elements that makes up this SCEV - /// properly dominate the specified basic block. - virtual bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const = 0; - /// print - Print out the internal representation of this scalar to the /// specified stream. This should really only be used for debugging /// purposes. - virtual void print(raw_ostream &OS) const = 0; + void print(raw_ostream &OS) const; /// dump - This method is used for debugging. /// @@ -155,21 +132,6 @@ namespace llvm { struct SCEVCouldNotCompute : public SCEV { SCEVCouldNotCompute(); - // None of these methods are valid for this object. - virtual bool isLoopInvariant(const Loop *L) const; - virtual const Type *getType() const; - virtual bool hasComputableLoopEvolution(const Loop *L) const; - virtual void print(raw_ostream &OS) const; - virtual bool hasOperand(const SCEV *Op) const; - - virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const { - return true; - } - - virtual bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const { - return true; - } - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVCouldNotCompute *S) { return true; } static bool classof(const SCEV *S); @@ -180,6 +142,24 @@ namespace llvm { /// they must ask this class for services. /// class ScalarEvolution : public FunctionPass { + public: + /// LoopDisposition - An enum describing the relationship between a + /// SCEV and a loop. + enum LoopDisposition { + LoopVariant, ///< The SCEV is loop-variant (unknown). + LoopInvariant, ///< The SCEV is loop-invariant. + LoopComputable ///< The SCEV varies predictably with the loop. + }; + + /// BlockDisposition - An enum describing the relationship between a + /// SCEV and a basic block. + enum BlockDisposition { + DoesNotDominateBlock, ///< The SCEV does not dominate the block. + DominatesBlock, ///< The SCEV dominates the block. + ProperlyDominatesBlock ///< The SCEV properly dominates the block. + }; + + private: /// SCEVCallbackVH - A CallbackVH to arrange for ScalarEvolution to be /// notified whenever a Value is deleted. class SCEVCallbackVH : public CallbackVH { @@ -267,6 +247,46 @@ namespace llvm { std::map<const SCEV *, std::map<const Loop *, const SCEV *> > ValuesAtScopes; + /// LoopDispositions - Memoized computeLoopDisposition results. + std::map<const SCEV *, + std::map<const Loop *, LoopDisposition> > LoopDispositions; + + /// computeLoopDisposition - Compute a LoopDisposition value. + LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L); + + /// BlockDispositions - Memoized computeBlockDisposition results. + std::map<const SCEV *, + std::map<const BasicBlock *, BlockDisposition> > BlockDispositions; + + /// computeBlockDisposition - Compute a BlockDisposition value. + BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB); + + /// UnsignedRanges - Memoized results from getUnsignedRange + DenseMap<const SCEV *, ConstantRange> UnsignedRanges; + + /// SignedRanges - Memoized results from getSignedRange + DenseMap<const SCEV *, ConstantRange> SignedRanges; + + /// setUnsignedRange - Set the memoized unsigned range for the given SCEV. + const ConstantRange &setUnsignedRange(const SCEV *S, + const ConstantRange &CR) { + std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair = + UnsignedRanges.insert(std::make_pair(S, CR)); + if (!Pair.second) + Pair.first->second = CR; + return Pair.first->second; + } + + /// setUnsignedRange - Set the memoized signed range for the given SCEV. + const ConstantRange &setSignedRange(const SCEV *S, + const ConstantRange &CR) { + std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair = + SignedRanges.insert(std::make_pair(S, CR)); + if (!Pair.second) + Pair.first->second = CR; + return Pair.first->second; + } + /// createSCEV - We know that there is no SCEV for the specified value. /// Analyze the expression. const SCEV *createSCEV(Value *V); @@ -408,6 +428,9 @@ namespace llvm { bool isKnownPredicateWithRanges(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS); + /// forgetMemoizedResults - Drop memoized information computed for S. + void forgetMemoizedResults(const SCEV *S); + public: static char ID; // Pass identification, replacement for typeid ScalarEvolution(); @@ -514,10 +537,11 @@ namespace llvm { /// const SCEV *getNotSCEV(const SCEV *V); - /// getMinusSCEV - Return LHS-RHS. - /// - const SCEV *getMinusSCEV(const SCEV *LHS, - const SCEV *RHS); + /// getMinusSCEV - Return LHS-RHS. Minus is represented in SCEV as A+B*-1, + /// and thus the HasNUW and HasNSW bits apply to the resultant add, not + /// whether the sub would have overflowed. + const SCEV *getMinusSCEV(const SCEV *LHS, const SCEV *RHS, + bool HasNUW = false, bool HasNSW = false); /// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion /// of the input value to the specified type. If the type must be @@ -675,6 +699,36 @@ namespace llvm { const SCEV *&LHS, const SCEV *&RHS); + /// getLoopDisposition - Return the "disposition" of the given SCEV with + /// respect to the given loop. + LoopDisposition getLoopDisposition(const SCEV *S, const Loop *L); + + /// isLoopInvariant - Return true if the value of the given SCEV is + /// unchanging in the specified loop. + bool isLoopInvariant(const SCEV *S, const Loop *L); + + /// hasComputableLoopEvolution - Return true if the given SCEV changes value + /// in a known way in the specified loop. This property being true implies + /// that the value is variant in the loop AND that we can emit an expression + /// to compute the value of the expression at any particular loop iteration. + bool hasComputableLoopEvolution(const SCEV *S, const Loop *L); + + /// getLoopDisposition - Return the "disposition" of the given SCEV with + /// respect to the given block. + BlockDisposition getBlockDisposition(const SCEV *S, const BasicBlock *BB); + + /// dominates - Return true if elements that makes up the given SCEV + /// dominate the specified basic block. + bool dominates(const SCEV *S, const BasicBlock *BB); + + /// properlyDominates - Return true if elements that makes up the given SCEV + /// properly dominate the specified basic block. + bool properlyDominates(const SCEV *S, const BasicBlock *BB); + + /// hasOperand - Test whether the given SCEV has Op as a direct or + /// indirect operand. + bool hasOperand(const SCEV *S, const SCEV *Op) const; + virtual bool runOnFunction(Function &F); virtual void releaseMemory(); virtual void getAnalysisUsage(AnalysisUsage &AU) const; diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 4b02f82035..39d378ed9b 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -35,6 +35,9 @@ namespace llvm { std::set<AssertingVH<Value> > InsertedValues; std::set<AssertingVH<Value> > InsertedPostIncValues; + /// RelevantLoops - A memoization of the "relevant" loop for a given SCEV. + DenseMap<const SCEV *, const Loop *> RelevantLoops; + /// PostIncLoops - Addrecs referring to any of the given loops are expanded /// in post-inc mode. For example, expanding {1,+,1}<L> in post-inc mode /// returns the add instruction that adds one to the phi for {0,+,1}<L>, @@ -168,6 +171,9 @@ namespace llvm { return InsertedValues.count(I) || InsertedPostIncValues.count(I); } + /// getRelevantLoop - Determine the most "relevant" loop for the given SCEV. + const Loop *getRelevantLoop(const SCEV *); + Value *visitConstant(const SCEVConstant *S) { return S->getValue(); } diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index 4213a28701..db432c8173 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -42,29 +42,7 @@ namespace llvm { public: ConstantInt *getValue() const { return V; } - virtual bool isLoopInvariant(const Loop *L) const { - return true; - } - - virtual bool hasComputableLoopEvolution(const Loop *L) const { - return false; // Not loop variant - } - - virtual const Type *getType() const; - - virtual bool hasOperand(const SCEV *) const { - return false; - } - - bool dominates(BasicBlock *BB, DominatorTree *DT) const { - return true; - } - - bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const { - return true; - } - - virtual void print(raw_ostream &OS) const; + const Type *getType() const { return V->getType(); } /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVConstant *S) { return true; } @@ -86,23 +64,7 @@ namespace llvm { public: const SCEV *getOperand() const { return Op; } - virtual const Type *getType() const { return Ty; } - - virtual bool isLoopInvariant(const Loop *L) const { - return Op->isLoopInvariant(L); - } - - virtual bool hasComputableLoopEvolution(const Loop *L) const { - return Op->hasComputableLoopEvolution(L); - } - - virtual bool hasOperand(const SCEV *O) const { - return Op == O || Op->hasOperand(O); - } - - virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const; - - virtual bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; + const Type *getType() const { return Ty; } /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVCastExpr *S) { return true; } @@ -124,8 +86,6 @@ namespace llvm { const SCEV *op, const Type *ty); public: - virtual void print(raw_ostream &OS) const; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVTruncateExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -144,8 +104,6 @@ namespace llvm { const SCEV *op, const Type *ty); public: - virtual void print(raw_ostream &OS) const; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVZeroExtendExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -164,8 +122,6 @@ namespace llvm { const SCEV *op, const Type *ty); public: - virtual void print(raw_ostream &OS) const; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVSignExtendExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -202,20 +158,7 @@ namespace llvm { op_iterator op_begin() const { return Operands; } op_iterator op_end() const { return Operands + NumOperands; } - virtual bool isLoopInvariant(const Loop *L) const; - - // hasComputableLoopEvolution - N-ary expressions have computable loop - // evolutions iff they have at least one operand that varies with the loop, - // but that all varying operands are computable. - virtual bool hasComputableLoopEvolution(const Loop *L) const; - - virtual bool hasOperand(const SCEV *O) const; - - bool dominates(BasicBlock *BB, DominatorTree *DT) const; - - bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; - - virtual const Type *getType() const { return getOperand(0)->getType(); } + const Type *getType() const { return getOperand(0)->getType(); } bool hasNoUnsignedWrap() const { return SubclassData & (1 << 0); } void setHasNoUnsignedWrap(bool B) { @@ -248,10 +191,6 @@ namespace llvm { : SCEVNAryExpr(ID, T, O, N) {} public: - virtual const char *getOperationStr() const = 0; - - virtual void print(raw_ostream &OS) const; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVCommutativeExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -275,9 +214,7 @@ namespace llvm { } public: - virtual const char *getOperationStr() const { return " + "; } - - virtual const Type *getType() const { + const Type *getType() const { // Use the type of the last operand, which is likely to be a pointer // type, if there is one. This doesn't usually matter, but it can help // reduce casts when the expressions are expanded. @@ -303,8 +240,6 @@ namespace llvm { } public: - virtual const char *getOperationStr() const { return " * "; } - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVMulExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -328,27 +263,15 @@ namespace llvm { const SCEV *getLHS() const { return LHS; } const SCEV *getRHS() const { return RHS; } - virtual bool isLoopInvariant(const Loop *L) const { - return LHS->isLoopInvariant(L) && RHS->isLoopInvariant(L); - } - - virtual bool hasComputableLoopEvolution(const Loop *L) const { - return LHS->hasComputableLoopEvolution(L) && - RHS->hasComputableLoopEvolution(L); - } - - virtual bool hasOperand(const SCEV *O) const { - return O == LHS || O == RHS || LHS->hasOperand(O) || RHS->hasOperand(O); + const Type *getType() const { + // In most cases the types of LHS and RHS will be the same, but in some + // crazy cases one or the other may be a pointer. ScalarEvolution doesn't + // depend on the type for correctness, but handling types carefully can + // avoid extra casts in the SCEVExpander. The LHS is more likely to be + // a pointer type than the RHS, so use the RHS' type here. + return getRHS()->getType(); } - bool dominates(BasicBlock *BB, DominatorTree *DT) const; - - bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; - - virtual const Type *getType() const; - - void print(raw_ostream &OS) const; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVUDivExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -373,11 +296,7 @@ namespace llvm { SCEVAddRecExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N, const Loop *l) - : SCEVNAryExpr(ID, scAddRecExpr, O, N), L(l) { - for (size_t i = 0, e = NumOperands; i != e; ++i) - assert(Operands[i]->isLoopInvariant(l) && - "Operands of AddRec must be loop-invariant!"); - } + : SCEVNAryExpr(ID, scAddRecExpr, O, N), L(l) {} public: const SCEV *getStart() const { return Operands[0]; } @@ -393,16 +312,6 @@ namespace llvm { getLoop()); } - virtual bool hasComputableLoopEvolution(const Loop *QL) const { - return L == QL; - } - - virtual bool isLoopInvariant(const Loop *QueryLoop) const; - - bool dominates(BasicBlock *BB, DominatorTree *DT) const; - - bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; - /// isAffine - Return true if this is an affine AddRec (i.e., it represents /// an expressions A+B*x where A and B are loop invariant values. bool isAffine() const { @@ -437,8 +346,6 @@ namespace llvm { return cast<SCEVAddRecExpr>(SE.getAddExpr(this, getStepRecurrence(SE))); } - virtual void print(raw_ostream &OS) const; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVAddRecExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -462,8 +369,6 @@ namespace llvm { } public: - virtual const char *getOperationStr() const { return " smax "; } - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVSMaxExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -487,8 +392,6 @@ namespace llvm { } public: - virtual const char *getOperationStr() const { return " umax "; } - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVUMaxExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -534,22 +437,7 @@ namespace llvm { bool isAlignOf(const Type *&AllocTy) const; bool isOffsetOf(const Type *&STy, Constant *&FieldNo) const; - virtual bool isLoopInvariant(const Loop *L) const; - virtual bool hasComputableLoopEvolution(const Loop *QL) const { - return false; // not computable - } - - virtual bool hasOperand(const SCEV *) const { - return false; - } - - bool dominates(BasicBlock *BB, DominatorTree *DT) const; - - bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; - - virtual const Type *getType() const; - - virtual void print(raw_ostream &OS) const; + const Type *getType() const { return getValPtr()->getType(); } /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVUnknown *S) { return true; } diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 7b6026fea0..6df1693c78 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -15,7 +15,7 @@ #ifndef LLVM_ANALYSIS_VALUETRACKING_H #define LLVM_ANALYSIS_VALUETRACKING_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> namespace llvm { @@ -39,6 +39,23 @@ namespace llvm { APInt &KnownOne, const TargetData *TD = 0, unsigned Depth = 0); + /// ComputeSignBit - Determine whether the sign bit is known to be zero or + /// one. Convenience wrapper around ComputeMaskedBits. + void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne, + const TargetData *TD = 0, unsigned Depth = 0); + + /// isPowerOfTwo - Return true if the given value is known to have exactly one + /// bit set when defined. For vectors return true if every element is known to + /// be a power of two when defined. Supports values with integer or pointer + /// type and vectors of integers. + bool isPowerOfTwo(Value *V, const TargetData *TD = 0, unsigned Depth = 0); + + /// isKnownNonZero - Return true if the given value is known to be non-zero + /// when defined. For vectors return true if every element is known to be + /// non-zero when defined. Supports values with integer or pointer type and + /// vectors of integers. + bool isKnownNonZero(Value *V, const TargetData *TD = 0, unsigned Depth = 0); + /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use /// this predicate to simplify operations downstream. Mask is known to be /// zero for bits that V cannot have. @@ -77,7 +94,13 @@ namespace llvm { /// bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0); - + /// isBytewiseValue - If the specified value can be set by repeating the same + /// byte in memory, return the i8 value that it is represented with. This is + /// true for all i8 values obviously, but is also true for i32 0, i32 -1, + /// i16 0xF0F0, double 0.0 etc. If the value can't be handled with a repeated + /// byte store (e.g. i16 0x1234), return null. + Value *isBytewiseValue(Value *V); + /// FindInsertedValue - Given an aggregrate and an sequence of indices, see if /// the scalar value indexed is already around as a register, for example if /// it were inserted directly into the aggregrate. @@ -97,6 +120,17 @@ namespace llvm { return FindInsertedValue(V, &Idxs[0], &Idxs[1], InsertBefore); } + /// GetPointerBaseWithConstantOffset - Analyze the specified pointer to see if + /// it can be expressed as a base pointer plus a constant offset. Return the + /// base and offset to the caller. + Value *GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, + const TargetData &TD); + static inline const Value * + GetPointerBaseWithConstantOffset(const Value *Ptr, int64_t &Offset, + const TargetData &TD) { + return GetPointerBaseWithConstantOffset(const_cast<Value*>(Ptr), Offset,TD); + } + /// GetConstantStringInfo - This function computes the length of a /// null-terminated C string pointed to by V. If successful, it returns true /// and returns the string in Str. If unsuccessful, it returns false. If @@ -110,6 +144,20 @@ namespace llvm { /// GetStringLength - If we can compute the length of the string pointed to by /// the specified pointer, return 'len+1'. If we can't, return 0. uint64_t GetStringLength(Value *V); + + /// GetUnderlyingObject - This method strips off any GEP address adjustments + /// and pointer casts from the specified value, returning the original object + /// being addressed. Note that the returned value has pointer type if the + /// specified value does. If the MaxLookup value is non-zero, it limits the + /// number of instructions to be stripped off. + Value *GetUnderlyingObject(Value *V, const TargetData *TD = 0, + unsigned MaxLookup = 6); + static inline const Value * + GetUnderlyingObject(const Value *V, const TargetData *TD = 0, + unsigned MaxLookup = 6) { + return GetUnderlyingObject(const_cast<Value *>(V), TD, MaxLookup); + } + } // end namespace llvm #endif diff --git a/include/llvm/BasicBlock.h b/include/llvm/BasicBlock.h index bf5874f682..7e7c9e7694 100644 --- a/include/llvm/BasicBlock.h +++ b/include/llvm/BasicBlock.h @@ -18,7 +18,7 @@ #include "llvm/SymbolTableListTraits.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/Twine.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { @@ -58,9 +58,9 @@ private: /// tables. The type of a BasicBlock is "Type::LabelTy" because the basic block /// represents a label to which a branch can jump. /// -/// A well formed basic block is formed of a list of non-terminating -/// instructions followed by a single TerminatorInst instruction. -/// TerminatorInst's may not occur in the middle of basic blocks, and must +/// A well formed basic block is formed of a list of non-terminating +/// instructions followed by a single TerminatorInst instruction. +/// TerminatorInst's may not occur in the middle of basic blocks, and must /// terminate the blocks. The BasicBlock class allows malformed basic blocks to /// occur because it may be useful in the intermediate stage of constructing or /// modifying a program. However, the verifier will ensure that basic blocks @@ -90,7 +90,7 @@ private: public: /// getContext - Get the context in which this basic block lives. LLVMContext &getContext() const; - + /// Instruction iterators... typedef InstListType::iterator iterator; typedef InstListType::const_iterator const_iterator; @@ -98,7 +98,7 @@ public: /// Create - Creates a new BasicBlock. If the Parent parameter is specified, /// the basic block is automatically inserted at either the end of the /// function (if InsertBefore is 0), or before the specified basic block. - static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "", + static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "", Function *Parent = 0,BasicBlock *InsertBefore = 0) { return new BasicBlock(Context, Name, Parent, InsertBefore); } @@ -114,15 +114,15 @@ public: /// and BlockAddress's). User *use_back() { return cast<User>(*use_begin());} const User *use_back() const { return cast<User>(*use_begin());} - + /// getTerminator() - If this is a well formed basic block, then this returns /// a pointer to the terminator instruction. If it is not, then you get a /// null pointer back. /// TerminatorInst *getTerminator(); const TerminatorInst *getTerminator() const; - - /// Returns a pointer to the first instructon in this block that is not a + + /// Returns a pointer to the first instructon in this block that is not a /// PHINode instruction. When adding instruction to the beginning of the /// basic block, they should be added before the returned value, not before /// the first instruction, which might be PHI. @@ -137,7 +137,7 @@ public: const Instruction* getFirstNonPHIOrDbg() const { return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbg(); } - + /// removeFromParent - This method unlinks 'this' from the containing /// function, but does not delete it. /// @@ -147,15 +147,15 @@ public: /// and deletes it. /// void eraseFromParent(); - + /// moveBefore - Unlink this basic block from its current function and /// insert it into the function that MovePos lives in, right before MovePos. void moveBefore(BasicBlock *MovePos); - + /// moveAfter - Unlink this basic block from its current function and /// insert it into the function that MovePos lives in, right after MovePos. void moveAfter(BasicBlock *MovePos); - + /// getSinglePredecessor - If this basic block has a single predecessor block, /// return the block, otherwise return a null pointer. @@ -166,8 +166,8 @@ public: /// getUniquePredecessor - If this basic block has a unique predecessor block, /// return the block, otherwise return a null pointer. - /// Note that unique predecessor doesn't mean single edge, there can be - /// multiple edges from the unique predecessor to this block (for example + /// Note that unique predecessor doesn't mean single edge, there can be + /// multiple edges from the unique predecessor to this block (for example /// a switch statement with multiple cases having the same destination). BasicBlock *getUniquePredecessor(); const BasicBlock *getUniquePredecessor() const { @@ -247,7 +247,7 @@ public: /// hasAddressTaken - returns true if there are any uses of this basic block /// other than direct branches, switches, etc. to it. bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; } - + private: /// AdjustBlockAddressRefCount - BasicBlock stores the number of BlockAddress /// objects using it. This is almost always 0, sometimes one, possibly but diff --git a/include/llvm/Bitcode/Archive.h b/include/llvm/Bitcode/Archive.h index 934e764b65..4abfa6e844 100644 --- a/include/llvm/Bitcode/Archive.h +++ b/include/llvm/Bitcode/Archive.h @@ -19,7 +19,7 @@ #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" #include <map> #include <set> @@ -82,7 +82,7 @@ class ArchiveMember : public ilist_node<ArchiveMember> { unsigned getGroup() const { return info.getGroup(); } /// The "mode" specifies the access permissions for the file per Unix - /// security. This may not have any applicabiity on non-Unix systems but is + /// security. This may not have any applicability on non-Unix systems but is /// a required component of the "ar" file format. /// @brief Get the permission mode associated with this archive member. unsigned getMode() const { return info.getMode(); } @@ -144,7 +144,7 @@ class ArchiveMember : public ilist_node<ArchiveMember> { /// allowed that doesn't have this restriction. This method determines if /// that "long format" is used for this member. /// @returns true iff the file name uses the long form - /// @brief Determin if the member has a long file name + /// @brief Determine if the member has a long file name bool hasLongFilename() const { return flags&HasLongFilenameFlag; } /// This method returns the status info (like Unix stat(2)) for the archive @@ -402,7 +402,7 @@ class Archive { /// bitcode archive. It first makes sure the symbol table has been loaded /// and has a non-zero size. If it does, then it is an archive. If not, /// then it tries to load all the bitcode modules of the archive. Finally, - /// it returns whether it was successfull. + /// it returns whether it was successful. /// @returns true if the archive is a proper llvm bitcode archive /// @brief Determine whether the archive is a proper llvm bitcode archive. bool isBitcodeArchive(); diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h index ada2e65ee6..449dc35d7d 100644 --- a/include/llvm/Bitcode/BitCodes.h +++ b/include/llvm/Bitcode/BitCodes.h @@ -19,7 +19,7 @@ #define LLVM_BITCODE_BITCODES_H #include "llvm/ADT/SmallVector.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index d15c3ce93e..7692bd2872 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -199,10 +199,10 @@ namespace bitc { OBO_NO_SIGNED_WRAP = 1 }; - /// SDivOperatorOptionalFlags - Flags for serializing SDivOperator's - /// SubclassOptionalData contents. - enum SDivOperatorOptionalFlags { - SDIV_EXACT = 0 + /// PossiblyExactOperatorOptionalFlags - Flags for serializing + /// PossiblyExactOperator's SubclassOptionalData contents. + enum PossiblyExactOperatorOptionalFlags { + PEO_EXACT = 0 }; // The function body block (FUNCTION_BLOCK_ID) describes function bodies. It diff --git a/include/llvm/CMakeLists.txt b/include/llvm/CMakeLists.txt index 5e4f40881d..0c3ca1cd0c 100644 --- a/include/llvm/CMakeLists.txt +++ b/include/llvm/CMakeLists.txt @@ -4,6 +4,7 @@ tablegen(Intrinsics.gen -gen-intrinsic) add_custom_target(intrinsics_gen ALL DEPENDS ${llvm_builded_incs_dir}/Intrinsics.gen) +set_target_properties(intrinsics_gen PROPERTIES FOLDER "Tablegenning") set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} intrinsics_gen PARENT_SCOPE) @@ -16,4 +17,5 @@ if( MSVC_IDE OR XCODE ) # We need at least one source file: ${LLVM_MAIN_SRC_DIR}/lib/Transforms/Hello/Hello.cpp ${headers}) + set_target_properties(llvm_headers_do_not_build PROPERTIES FOLDER "Misc") endif() diff --git a/include/llvm/CallingConv.h b/include/llvm/CallingConv.h index 2679cb7139..4c5ee62670 100644 --- a/include/llvm/CallingConv.h +++ b/include/llvm/CallingConv.h @@ -87,7 +87,14 @@ namespace CallingConv { /// PTX_Device - Call to a PTX device function. /// Passes all arguments in register or parameter space. - PTX_Device = 72 + PTX_Device = 72, + + /// MBLAZE_INTR - Calling convention used for MBlaze interrupt routines. + MBLAZE_INTR = 73, + + /// MBLAZE_INTR - Calling convention used for MBlaze interrupt support + /// routines (i.e. GCC's save_volatiles attribute). + MBLAZE_SVOL = 74 }; } // End CallingConv namespace diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index a8292ea649..78bf9fc11a 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -23,8 +23,10 @@ namespace llvm { -class TargetLowering; class GlobalVariable; +class TargetLowering; +class SDNode; +class SelectionDAG; /// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence /// of insertvalue or extractvalue indices that identify a member, return @@ -75,6 +77,9 @@ ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred); bool isInTailCallPosition(ImmutableCallSite CS, Attributes CalleeRetAttr, const TargetLowering &TLI); +bool isInTailCallPosition(SelectionDAG &DAG, SDNode *Node, + const TargetLowering &TLI); + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 7eef9567a0..a071febb10 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -17,7 +17,7 @@ #define LLVM_CODEGEN_ASMPRINTER_H #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class BlockAddress; @@ -49,6 +49,7 @@ namespace llvm { class MCSection; class MCStreamer; class MCSymbol; + class MDNode; class DwarfDebug; class DwarfException; class Mangler; @@ -388,7 +389,7 @@ namespace llvm { /// frame. void EmitFrameMoves(const std::vector<MachineMove> &Moves, MCSymbol *BaseLabel, bool isEH) const; - + void EmitCFIFrameMoves(const std::vector<MachineMove> &Moves) const; //===------------------------------------------------------------------===// // Inline Asm Support @@ -432,7 +433,7 @@ namespace llvm { mutable unsigned SetCounter; /// EmitInlineAsm - Emit a blob of inline asm to the output streamer. - void EmitInlineAsm(StringRef Str, unsigned LocCookie) const; + void EmitInlineAsm(StringRef Str, const MDNode *LocMDNode = 0) const; /// EmitInlineAsm - This method formats and emits the specified machine /// instruction that is an inline asm. @@ -444,7 +445,8 @@ namespace llvm { /// EmitVisibility - This emits visibility information about symbol, if /// this is suported by the target. - void EmitVisibility(MCSymbol *Sym, unsigned Visibility) const; + void EmitVisibility(MCSymbol *Sym, unsigned Visibility, + bool IsDefinition = true) const; void EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const; diff --git a/include/llvm/CodeGen/BinaryObject.h b/include/llvm/CodeGen/BinaryObject.h index 3ade7c9e47..8c1431ffbe 100644 --- a/include/llvm/CodeGen/BinaryObject.h +++ b/include/llvm/CodeGen/BinaryObject.h @@ -16,7 +16,7 @@ #define LLVM_CODEGEN_BINARYOBJECT_H #include "llvm/CodeGen/MachineRelocation.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> #include <vector> diff --git a/include/llvm/CodeGen/CalcSpillWeights.h b/include/llvm/CodeGen/CalcSpillWeights.h index 24264d7f97..1f5f088be7 100644 --- a/include/llvm/CodeGen/CalcSpillWeights.h +++ b/include/llvm/CodeGen/CalcSpillWeights.h @@ -11,7 +11,7 @@ #ifndef LLVM_CODEGEN_CALCSPILLWEIGHTS_H #define LLVM_CODEGEN_CALCSPILLWEIGHTS_H -#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/SlotIndexes.h" #include "llvm/ADT/DenseMap.h" namespace llvm { @@ -20,6 +20,23 @@ namespace llvm { class LiveIntervals; class MachineLoopInfo; + /// normalizeSpillWeight - The spill weight of a live interval is computed as: + /// + /// (sum(use freq) + sum(def freq)) / (K + size) + /// + /// @param UseDefFreq Expected number of executed use and def instructions + /// per function call. Derived from block frequencies. + /// @param Size Size of live interval as returnexd by getSize() + /// + static inline float normalizeSpillWeight(float UseDefFreq, unsigned Size) { + // The constant 25 instructions is added to avoid depending too much on + // accidental SlotIndex gaps for small intervals. The effect is that small + // intervals have a spill weight that is mostly proportional to the number + // of uses, while large intervals get a spill weight that is closer to a use + // density. + return UseDefFreq / (Size + 25*SlotIndex::InstrDist); + } + /// VirtRegAuxInfo - Calculate auxiliary information for a virtual /// register such as its spill weight and allocation hint. class VirtRegAuxInfo { diff --git a/include/llvm/CodeGen/EdgeBundles.h b/include/llvm/CodeGen/EdgeBundles.h new file mode 100644 index 0000000000..2c5215a792 --- /dev/null +++ b/include/llvm/CodeGen/EdgeBundles.h @@ -0,0 +1,61 @@ +//===-------- EdgeBundles.h - Bundles of CFG edges --------------*- c++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The EdgeBundles analysis forms equivalence classes of CFG edges such that all +// edges leaving a machine basic block are in the same bundle, and all edges +// leaving a basic block are in the same bundle. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_EDGEBUNDLES_H +#define LLVM_CODEGEN_EDGEBUNDLES_H + +#include "llvm/ADT/IntEqClasses.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { + +class EdgeBundles : public MachineFunctionPass { + const MachineFunction *MF; + + /// EC - Each edge bundle is an equivalence class. The keys are: + /// 2*BB->getNumber() -> Ingoing bundle. + /// 2*BB->getNumber()+1 -> Outgoing bundle. + IntEqClasses EC; + +public: + static char ID; + EdgeBundles() : MachineFunctionPass(ID) {} + + /// getBundle - Return the ingoing (Out = false) or outgoing (Out = true) + /// bundle number for basic block #N + unsigned getBundle(unsigned N, bool Out) const { return EC[2 * N + Out]; } + + /// getNumBundles - Return the total number of bundles in the CFG. + unsigned getNumBundles() const { return EC.getNumClasses(); } + + /// getMachineFunction - Return the last machine function computed. + const MachineFunction *getMachineFunction() const { return MF; } + + /// view - Visualize the annotated bipartite CFG with Graphviz. + void view() const; + +private: + virtual bool runOnMachineFunction(MachineFunction&); + virtual void getAnalysisUsage(AnalysisUsage&) const; +}; + +/// Specialize WriteGraph, the standard implementation won't work. +raw_ostream &WriteGraph(raw_ostream &O, const EdgeBundles &G, + bool ShortNames = false, + const std::string &Title = ""); + +} // end namespace llvm + +#endif diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index f17fe5a146..4421cc02d1 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -19,6 +19,7 @@ #include "llvm/Instructions.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallVector.h" #ifndef NDEBUG #include "llvm/ADT/SmallSet.h" @@ -27,6 +28,7 @@ #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/Support/CallSite.h" +#include "llvm/Target/TargetRegisterInfo.h" #include <vector> namespace llvm { @@ -99,14 +101,16 @@ public: #endif struct LiveOutInfo { - unsigned NumSignBits; + unsigned NumSignBits : 31; + bool IsValid : 1; APInt KnownOne, KnownZero; - LiveOutInfo() : NumSignBits(0), KnownOne(1, 0), KnownZero(1, 0) {} + LiveOutInfo() : NumSignBits(0), IsValid(true), KnownOne(1, 0), + KnownZero(1, 0) {} }; - - /// LiveOutRegInfo - Information about live out vregs, indexed by their - /// register number offset by 'FirstVirtualRegister'. - std::vector<LiveOutInfo> LiveOutRegInfo; + + /// VisitedBBs - The set of basic blocks visited thus far by instruction + /// selection. + DenseSet<const BasicBlock*> VisitedBBs; /// PHINodesToUpdate - A list of phi instructions whose operand list will /// be updated after processing the current basic block. @@ -142,12 +146,67 @@ public: return R = CreateRegs(V->getType()); } + /// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the + /// register is a PHI destination and the PHI's LiveOutInfo is not valid. + const LiveOutInfo *GetLiveOutRegInfo(unsigned Reg) { + if (!LiveOutRegInfo.inBounds(Reg)) + return NULL; + + const LiveOutInfo *LOI = &LiveOutRegInfo[Reg]; + if (!LOI->IsValid) + return NULL; + + return LOI; + } + + /// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the + /// register is a PHI destination and the PHI's LiveOutInfo is not valid. If + /// the register's LiveOutInfo is for a smaller bit width, it is extended to + /// the larger bit width by zero extension. The bit width must be no smaller + /// than the LiveOutInfo's existing bit width. + const LiveOutInfo *GetLiveOutRegInfo(unsigned Reg, unsigned BitWidth); + + /// AddLiveOutRegInfo - Adds LiveOutInfo for a register. + void AddLiveOutRegInfo(unsigned Reg, unsigned NumSignBits, + const APInt &KnownZero, const APInt &KnownOne) { + // Only install this information if it tells us something. + if (NumSignBits == 1 && KnownZero == 0 && KnownOne == 0) + return; + + LiveOutRegInfo.grow(Reg); + LiveOutInfo &LOI = LiveOutRegInfo[Reg]; + LOI.NumSignBits = NumSignBits; + LOI.KnownOne = KnownOne; + LOI.KnownZero = KnownZero; + } + + /// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination + /// register based on the LiveOutInfo of its operands. + void ComputePHILiveOutRegInfo(const PHINode*); + + /// InvalidatePHILiveOutRegInfo - Invalidates a PHI's LiveOutInfo, to be + /// called when a block is visited before all of its predecessors. + void InvalidatePHILiveOutRegInfo(const PHINode *PN) { + // PHIs with no uses have no ValueMap entry. + DenseMap<const Value*, unsigned>::const_iterator It = ValueMap.find(PN); + if (It == ValueMap.end()) + return; + + unsigned Reg = It->second; + LiveOutRegInfo.grow(Reg); + LiveOutRegInfo[Reg].IsValid = false; + } + /// setByValArgumentFrameIndex - Record frame index for the byval /// argument. void setByValArgumentFrameIndex(const Argument *A, int FI); /// getByValArgumentFrameIndex - Get frame index for the byval argument. int getByValArgumentFrameIndex(const Argument *A); + +private: + /// LiveOutRegInfo - Information about live out vregs. + IndexedMap<LiveOutInfo, VirtReg2IndexFunctor> LiveOutRegInfo; }; /// AddCatchInfo - Extract the personality and type infos from an eh.selector @@ -155,8 +214,9 @@ public: void AddCatchInfo(const CallInst &I, MachineModuleInfo *MMI, MachineBasicBlock *MBB); -/// CopyCatchInfo - Copy catch information from DestBB to SrcBB. -void CopyCatchInfo(const BasicBlock *SrcBB, const BasicBlock *DestBB, +/// CopyCatchInfo - Copy catch information from SuccBB (or one of its +/// successors) to LPad. +void CopyCatchInfo(const BasicBlock *SuccBB, const BasicBlock *LPad, MachineModuleInfo *MMI, FunctionLoweringInfo &FLI); } // end namespace llvm diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 31da0211eb..3da11c4a0e 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -269,16 +269,24 @@ namespace ISD { /// lengths of the input vectors. CONCAT_VECTORS, + /// INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector + /// with VECTOR2 inserted into VECTOR1 at the (potentially + /// variable) element number IDX, which must be a multiple of the + /// VECTOR2 vector length. The elements of VECTOR1 starting at + /// IDX are overwritten with VECTOR2. Elements IDX through + /// vector_length(VECTOR2) must be valid VECTOR1 indices. + INSERT_SUBVECTOR, + /// EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR (an - /// vector value) starting with the (potentially variable) element number - /// IDX, which must be a multiple of the result vector length. + /// vector value) starting with the element number IDX, which must be a + /// constant multiple of the result vector length. EXTRACT_SUBVECTOR, - /// VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as + /// VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as /// VEC1/VEC2. A VECTOR_SHUFFLE node also contains an array of constant int /// values that indicate which value (or undef) each result element will - /// get. These constant ints are accessible through the - /// ShuffleVectorSDNode class. This is quite similar to the Altivec + /// get. These constant ints are accessible through the + /// ShuffleVectorSDNode class. This is quite similar to the Altivec /// 'vperm' instruction, except that the indices must be constants and are /// in terms of the element size of VEC1/VEC2, not in terms of bytes. VECTOR_SHUFFLE, @@ -295,13 +303,21 @@ namespace ISD { // an unsigned/signed value of type i[2*N], then return the top part. MULHU, MULHS, - // Bitwise operators - logical and, logical or, logical xor, shift left, - // shift right algebraic (shift in sign bits), shift right logical (shift in - // zeroes), rotate left, rotate right, and byteswap. - AND, OR, XOR, SHL, SRA, SRL, ROTL, ROTR, BSWAP, + /// Bitwise operators - logical and, logical or, logical xor. + AND, OR, XOR, + + /// Shift and rotation operations. After legalization, the type of the + /// shift amount is known to be TLI.getShiftAmountTy(). Before legalization + /// the shift amount can be any type, but care must be taken to ensure it is + /// large enough. TLI.getShiftAmountTy() is i8 on some targets, but before + /// legalization, types like i1024 can occur and i8 doesn't have enough bits + /// to represent the shift amount. By convention, DAGCombine and + /// SelectionDAGBuilder forces these shift amounts to i32 for simplicity. + /// + SHL, SRA, SRL, ROTL, ROTR, - // Counting operators - CTTZ, CTLZ, CTPOP, + /// Byte Swap and Counting operators. + BSWAP, CTTZ, CTLZ, CTPOP, // Select(COND, TRUEVAL, FALSEVAL). If the type of the boolean COND is not // i1 then the high bits must conform to getBooleanContents. @@ -399,14 +415,14 @@ namespace ISD { /// X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type. FP_EXTEND, - // BIT_CONVERT - This operator converts between integer, vector and FP + // BITCAST - This operator converts between integer, vector and FP // values, as if the value was stored to memory with one type and loaded // from the same address with the other type (or equivalently for vector // format conversions, etc). The source and result are required to have // the same bit size (e.g. f32 <-> i32). This can also be used for // int-to-int or fp-to-fp conversions, but that is a noop, deleted by // getNode(). - BIT_CONVERT, + BITCAST, // CONVERT_RNDSAT - This operator is used to support various conversions // between various types (float, signed, unsigned and vectors of those @@ -482,6 +498,7 @@ namespace ISD { // Operand #0 : Input chain. // Operand #1 : a ExternalSymbolSDNode with a pointer to the asm string. // Operand #2 : a MDNodeSDNode with the !srcloc metadata. + // Operand #3 : HasSideEffect, IsAlignStack bits. // After this, it is followed by a list of operands with this format: // ConstantSDNode: Flags that encode whether it is a mem or not, the // of operands that follow, etc. See InlineAsm.h. @@ -532,7 +549,7 @@ namespace ISD { // SRCVALUE - This is a node type that holds a Value* that is used to // make reference to a value in the LLVM IR. SRCVALUE, - + // MDNODE_SDNODE - This is a node that holdes an MDNode*, which is used to // reference metadata in the IR. MDNODE_SDNODE, diff --git a/include/llvm/CodeGen/IntrinsicLowering.h b/include/llvm/CodeGen/IntrinsicLowering.h index eefbc45cb2..767b666225 100644 --- a/include/llvm/CodeGen/IntrinsicLowering.h +++ b/include/llvm/CodeGen/IntrinsicLowering.h @@ -48,6 +48,11 @@ namespace llvm { /// be capable of handling this kind of change. /// void LowerIntrinsicCall(CallInst *CI); + + /// LowerToByteSwap - Replace a call instruction into a call to bswap + /// intrinsic. Return false if it has determined the call is not a + /// simple integer bswap. + static bool LowerToByteSwap(CallInst *CI); }; } diff --git a/include/llvm/CodeGen/JITCodeEmitter.h b/include/llvm/CodeGen/JITCodeEmitter.h index eb373fb145..fea8523051 100644 --- a/include/llvm/CodeGen/JITCodeEmitter.h +++ b/include/llvm/CodeGen/JITCodeEmitter.h @@ -18,7 +18,7 @@ #define LLVM_CODEGEN_JITCODEEMITTER_H #include <string> -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/ADT/DenseMap.h" diff --git a/include/llvm/CodeGen/LatencyPriorityQueue.h b/include/llvm/CodeGen/LatencyPriorityQueue.h index 13cebeaf42..1ed2547ca6 100644 --- a/include/llvm/CodeGen/LatencyPriorityQueue.h +++ b/include/llvm/CodeGen/LatencyPriorityQueue.h @@ -20,25 +20,25 @@ namespace llvm { class LatencyPriorityQueue; - + /// Sorting functions for the Available queue. struct latency_sort : public std::binary_function<SUnit*, SUnit*, bool> { LatencyPriorityQueue *PQ; explicit latency_sort(LatencyPriorityQueue *pq) : PQ(pq) {} - + bool operator()(const SUnit* left, const SUnit* right) const; }; class LatencyPriorityQueue : public SchedulingPriorityQueue { // SUnits - The SUnits for the current graph. std::vector<SUnit> *SUnits; - + /// NumNodesSolelyBlocking - This vector contains, for every node in the /// Queue, the number of nodes that the node is the sole unscheduled /// predecessor for. This is used as a tie-breaker heuristic for better /// mobility. std::vector<unsigned> NumNodesSolelyBlocking; - + /// Queue - The queue. std::vector<SUnit*> Queue; latency_sort Picker; @@ -47,6 +47,8 @@ namespace llvm { LatencyPriorityQueue() : Picker(this) { } + bool isBottomUp() const { return false; } + void initNodes(std::vector<SUnit> &sunits) { SUnits = &sunits; NumNodesSolelyBlocking.resize(SUnits->size(), 0); @@ -62,25 +64,27 @@ namespace llvm { void releaseState() { SUnits = 0; } - + unsigned getLatency(unsigned NodeNum) const { assert(NodeNum < (*SUnits).size()); return (*SUnits)[NodeNum].getHeight(); } - + unsigned getNumSolelyBlockNodes(unsigned NodeNum) const { assert(NodeNum < NumNodesSolelyBlocking.size()); return NumNodesSolelyBlocking[NodeNum]; } - + bool empty() const { return Queue.empty(); } - + virtual void push(SUnit *U); - + virtual SUnit *pop(); virtual void remove(SUnit *SU); + virtual void dump(ScheduleDAG* DAG) const; + // ScheduledNode - As nodes are scheduled, we look to see if there are any // successor nodes that have a single unscheduled predecessor. If so, that // single predecessor has a higher priority, since scheduling it will make diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index bc06d43b8f..c931261f63 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -36,6 +36,7 @@ namespace { (void) llvm::createFastRegisterAllocator(); (void) llvm::createBasicRegisterAllocator(); (void) llvm::createLinearScanRegisterAllocator(); + (void) llvm::createGreedyRegisterAllocator(); (void) llvm::createDefaultPBQPRegisterAllocator(); (void) llvm::createSimpleRegisterCoalescer(); diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index c21df28cdd..427af87960 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -21,7 +21,7 @@ #ifndef LLVM_CODEGEN_LIVEINTERVAL_H #define LLVM_CODEGEN_LIVEINTERVAL_H -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/IntEqClasses.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/AlignOf.h" #include "llvm/CodeGen/SlotIndexes.h" @@ -205,8 +205,7 @@ namespace llvm { typedef SmallVector<LiveRange,4> Ranges; typedef SmallVector<VNInfo*,4> VNInfoList; - unsigned reg; // the register or stack slot of this interval - // if the top bits is set, it represents a stack slot. + const unsigned reg; // the register or stack slot of this interval. float weight; // weight of this interval Ranges ranges; // the ranges in which this register is live VNInfoList valnos; // value#'s @@ -222,11 +221,8 @@ namespace llvm { }; - LiveInterval(unsigned Reg, float Weight, bool IsSS = false) - : reg(Reg), weight(Weight) { - if (IsSS) - reg = reg | (1U << (sizeof(unsigned)*CHAR_BIT-1)); - } + LiveInterval(unsigned Reg, float Weight) + : reg(Reg), weight(Weight) {} typedef Ranges::iterator iterator; iterator begin() { return ranges.begin(); } @@ -250,6 +246,7 @@ namespace llvm { /// position is in a hole, this method returns an iterator pointing to the /// LiveRange immediately after the hole. iterator advanceTo(iterator I, SlotIndex Pos) { + assert(I != end()); if (Pos >= endIndex()) return end(); while (I->end <= Pos) ++I; @@ -274,19 +271,6 @@ namespace llvm { ranges.clear(); } - /// isStackSlot - Return true if this is a stack slot interval. - /// - bool isStackSlot() const { - return reg & (1U << (sizeof(unsigned)*CHAR_BIT-1)); - } - - /// getStackSlotIndex - Return stack slot index if this is a stack slot - /// interval. - int getStackSlotIndex() const { - assert(isStackSlot() && "Interval is not a stack slot interval!"); - return reg & ~(1U << (sizeof(unsigned)*CHAR_BIT-1)); - } - bool hasAtLeastOneValue() const { return !valnos.empty(); } bool containsOneValue() const { return valnos.size() == 1; } @@ -463,6 +447,11 @@ namespace llvm { addRangeFrom(LR, ranges.begin()); } + /// extendInBlock - If this interval is live before UseIdx in the basic + /// block that starts at StartIdx, extend it to be live at UseIdx and return + /// the value. If there is no live range before UseIdx, return NULL. + VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex UseIdx); + /// join - Join two live intervals (this, and other) together. This applies /// mappings to the value numbers in the LHS/RHS intervals as specified. If /// the intervals are not joinable, this aborts. @@ -560,11 +549,7 @@ namespace llvm { class ConnectedVNInfoEqClasses { LiveIntervals &lis_; - - // Map each value number to its equivalence class. - // The invariant is that EqClass[x] <= x. - // Two values are connected iff EqClass[x] == EqClass[b]. - SmallVector<unsigned, 8> eqClass_; + IntEqClasses eqClass_; // Note that values a and b are connected. void Connect(unsigned a, unsigned b); @@ -580,7 +565,7 @@ namespace llvm { /// getEqClass - Classify creates equivalence classes numbered 0..N. Return /// the equivalence class assigned the VNI. - unsigned getEqClass(const VNInfo *VNI) { return eqClass_[VNI->id]; } + unsigned getEqClass(const VNInfo *VNI) const { return eqClass_[VNI->id]; } /// Distribute - Distribute values in LIV[0] into a separate LiveInterval /// for each connected component. LIV must have a LiveInterval for each diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 143a1a6836..b09f8d1110 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -75,14 +75,6 @@ namespace llvm { // Calculate the spill weight to assign to a single instruction. static float getSpillWeight(bool isDef, bool isUse, unsigned loopDepth); - // After summing the spill weights of all defs and uses, the final weight - // should be normalized, dividing the weight of the interval by its size. - // This encourages spilling of intervals that are large and have few uses, - // and discourages spilling of small intervals with many uses. - void normalizeSpillWeight(LiveInterval &li) { - li.weight /= getApproximateInstructionCount(li) + 25; - } - typedef Reg2IntervalMap::iterator iterator; typedef Reg2IntervalMap::const_iterator const_iterator; const_iterator begin() const { return r2iMap_.begin(); } @@ -163,6 +155,12 @@ namespace llvm { LiveRange addLiveRangeToEndOfBlock(unsigned reg, MachineInstr* startInst); + /// shrinkToUses - After removing some uses of a register, shrink its live + /// range to just the remaining uses. This method does not compute reaching + /// defs for new uses, and it doesn't remove dead defs. + /// Dead PHIDef values are marked as unused. + void shrinkToUses(LiveInterval *li); + // Interval removal void removeInterval(unsigned Reg) { @@ -171,6 +169,10 @@ namespace llvm { r2iMap_.erase(I); } + SlotIndexes *getSlotIndexes() const { + return indexes_; + } + SlotIndex getZeroIndex() const { return indexes_->getZeroIndex(); } @@ -304,6 +306,16 @@ namespace llvm { /// within a single basic block. bool intervalIsInOneMBB(const LiveInterval &li) const; + /// getLastSplitPoint - Return the last possible insertion point in mbb for + /// spilling and splitting code. This is the first terminator, or the call + /// instruction if li is live into a landing pad successor. + MachineBasicBlock::iterator getLastSplitPoint(const LiveInterval &li, + MachineBasicBlock *mbb) const; + + /// addKillFlags - Add kill flags to any instruction that kills a virtual + /// register. + void addKillFlags(); + private: /// computeIntervals - Compute live intervals. void computeIntervals(); @@ -441,9 +453,6 @@ namespace llvm { DenseMap<unsigned,unsigned> &MBBVRegsMap, std::vector<LiveInterval*> &NewLIs); - // Normalize the spill weight of all the intervals in NewLIs. - void normalizeSpillWeights(std::vector<LiveInterval*> &NewLIs); - static LiveInterval* createInterval(unsigned Reg); void printInstrs(raw_ostream &O) const; diff --git a/include/llvm/CodeGen/LiveStackAnalysis.h b/include/llvm/CodeGen/LiveStackAnalysis.h index 9310a30a4d..8a8dcaf572 100644 --- a/include/llvm/CodeGen/LiveStackAnalysis.h +++ b/include/llvm/CodeGen/LiveStackAnalysis.h @@ -52,19 +52,7 @@ namespace llvm { unsigned getNumIntervals() const { return (unsigned)S2IMap.size(); } - LiveInterval &getOrCreateInterval(int Slot, const TargetRegisterClass *RC) { - assert(Slot >= 0 && "Spill slot indice must be >= 0"); - SS2IntervalMap::iterator I = S2IMap.find(Slot); - if (I == S2IMap.end()) { - I = S2IMap.insert(I,std::make_pair(Slot, LiveInterval(Slot,0.0F,true))); - S2RCMap.insert(std::make_pair(Slot, RC)); - } else { - // Use the largest common subclass register class. - const TargetRegisterClass *OldRC = S2RCMap[Slot]; - S2RCMap[Slot] = getCommonSubClass(OldRC, RC); - } - return I->second; - } + LiveInterval &getOrCreateInterval(int Slot, const TargetRegisterClass *RC); LiveInterval &getInterval(int Slot) { assert(Slot >= 0 && "Spill slot indice must be >= 0"); diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index ea32efaf0c..f9b81b1ea7 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -32,8 +32,10 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SparseBitVector.h" @@ -121,10 +123,9 @@ public: private: /// VirtRegInfo - This list is a mapping from virtual register number to - /// variable information. FirstVirtualRegister is subtracted from the virtual - /// register number before indexing into this list. + /// variable information. /// - std::vector<VarInfo> VirtRegInfo; + IndexedMap<VarInfo, VirtReg2IndexFunctor> VirtRegInfo; /// PHIJoins - list of virtual registers that are PHI joins. These registers /// may have multiple definitions, and they require special handling when diff --git a/include/llvm/CodeGen/MachORelocation.h b/include/llvm/CodeGen/MachORelocation.h index 27306c62d8..21fe74f8e1 100644 --- a/include/llvm/CodeGen/MachORelocation.h +++ b/include/llvm/CodeGen/MachORelocation.h @@ -15,7 +15,7 @@ #ifndef LLVM_CODEGEN_MACHO_RELOCATION_H #define LLVM_CODEGEN_MACHO_RELOCATION_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 49daf5f4d3..1906093388 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -16,6 +16,7 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/ADT/GraphTraits.h" +#include <functional> namespace llvm { @@ -224,6 +225,10 @@ public: /// this basic block is entered via an exception handler. void setIsLandingPad() { IsLandingPad = true; } + /// getLandingPadSuccessor - If this block has a successor that is a landing + /// pad, return it. Otherwise return NULL. + const MachineBasicBlock *getLandingPadSuccessor() const; + // Code Layout methods. /// moveBefore/moveAfter - move 'this' block before or after the specified @@ -300,6 +305,10 @@ public: /// it returns end() iterator getFirstTerminator(); + /// getLastNonDebugInstr - returns an iterator to the last non-debug + /// instruction in the basic block, or end() + iterator getLastNonDebugInstr(); + /// SplitCriticalEdge - Split the critical edge from this block to the /// given successor block, and return the newly created block, or null /// if splitting is not possible. @@ -403,6 +412,14 @@ raw_ostream& operator<<(raw_ostream &OS, const MachineBasicBlock &MBB); void WriteAsOperand(raw_ostream &, const MachineBasicBlock*, bool t); +// This is useful when building IndexedMaps keyed on basic block pointers. +struct MBB2NumberFunctor : + public std::unary_function<const MachineBasicBlock*, unsigned> { + unsigned operator()(const MachineBasicBlock *MBB) const { + return MBB->getNumber(); + } +}; + //===--------------------------------------------------------------------===// // GraphTraits specializations for machine basic block graphs (machine-CFGs) //===--------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineCodeEmitter.h b/include/llvm/CodeGen/MachineCodeEmitter.h index 7abb49a219..8fc80adf7f 100644 --- a/include/llvm/CodeGen/MachineCodeEmitter.h +++ b/include/llvm/CodeGen/MachineCodeEmitter.h @@ -17,7 +17,7 @@ #ifndef LLVM_CODEGEN_MACHINECODEEMITTER_H #define LLVM_CODEGEN_MACHINECODEEMITTER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/DebugLoc.h" namespace llvm { diff --git a/include/llvm/CodeGen/MachineCodeInfo.h b/include/llvm/CodeGen/MachineCodeInfo.h index a75c02a052..c5c0c44504 100644 --- a/include/llvm/CodeGen/MachineCodeInfo.h +++ b/include/llvm/CodeGen/MachineCodeInfo.h @@ -17,7 +17,7 @@ #ifndef EE_MACHINE_CODE_INFO_H #define EE_MACHINE_CODE_INFO_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h index 498f815b9b..5727321a0d 100644 --- a/include/llvm/CodeGen/MachineConstantPool.h +++ b/include/llvm/CodeGen/MachineConstantPool.h @@ -16,6 +16,7 @@ #ifndef LLVM_CODEGEN_MACHINECONSTANTPOOL_H #define LLVM_CODEGEN_MACHINECONSTANTPOOL_H +#include "llvm/ADT/DenseSet.h" #include <cassert> #include <climits> #include <vector> @@ -130,6 +131,8 @@ class MachineConstantPool { const TargetData *TD; ///< The machine's TargetData. unsigned PoolAlignment; ///< The alignment for the pool. std::vector<MachineConstantPoolEntry> Constants; ///< The pool of constants. + /// MachineConstantPoolValues that use an existing MachineConstantPoolEntry. + DenseSet<MachineConstantPoolValue*> MachineCPVsSharingEntries; public: /// @brief The only constructor. explicit MachineConstantPool(const TargetData *td) diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index dca65ef6d4..22a82a9d6e 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -16,7 +16,7 @@ #include "llvm/ADT/SmallVector.h" //#include "llvm/ADT/IndexedMap.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> #include <vector> @@ -27,7 +27,7 @@ class TargetRegisterClass; class Type; class MachineFunction; class MachineBasicBlock; -class TargetFrameInfo; +class TargetFrameLowering; class BitVector; /// The CalleeSavedInfo class tracks the information need to locate where a @@ -192,13 +192,9 @@ class MachineFrameInfo { /// CSIValid - Has CSInfo been set yet? bool CSIValid; - /// SpillObjects - A vector indicating which frame indices refer to - /// spill slots. - SmallVector<bool, 8> SpillObjects; - - /// TargetFrameInfo - Target information about frame layout. + /// TargetFrameLowering - Target information about frame layout. /// - const TargetFrameInfo &TFI; + const TargetFrameLowering &TFI; /// LocalFrameObjects - References to frame indices which are mapped /// into the local frame allocation block. <FrameIdx, LocalOffset> @@ -217,7 +213,7 @@ class MachineFrameInfo { bool UseLocalStackAllocationBlock; public: - explicit MachineFrameInfo(const TargetFrameInfo &tfi) : TFI(tfi) { + explicit MachineFrameInfo(const TargetFrameLowering &tfi) : TFI(tfi) { StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0; HasVarSizedObjects = false; FrameAddressTaken = false; diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index eeba1bbddf..f56c053e47 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -271,7 +271,7 @@ public: /// verify - Run the current MachineFunction through the machine code /// verifier, useful for debugger use. - void verify(Pass *p=NULL) const; + void verify(Pass *p = NULL, const char *Banner = NULL) const; // Provide accessors for the MachineBasicBlock list... typedef BasicBlockListType::iterator iterator; diff --git a/include/llvm/CodeGen/MachineFunctionAnalysis.h b/include/llvm/CodeGen/MachineFunctionAnalysis.h index 75dbaab973..50676ad4ad 100644 --- a/include/llvm/CodeGen/MachineFunctionAnalysis.h +++ b/include/llvm/CodeGen/MachineFunctionAnalysis.h @@ -37,6 +37,10 @@ public: MachineFunction &getMF() const { return *MF; } CodeGenOpt::Level getOptLevel() const { return OptLevel; } + + virtual const char* getPassName() const { + return "Machine Function Analysis"; + } private: virtual bool doInitialization(Module &M); diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index d1f17d39db..0f69a7789c 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -50,13 +50,22 @@ public: enum CommentFlag { ReloadReuse = 0x1 }; - + + enum MIFlag { + NoFlags = 0, + FrameSetup = 1 << 0 // Instruction is used as a part of + // function frame setup code. + }; private: const TargetInstrDesc *TID; // Instruction descriptor. - unsigned short NumImplicitOps; // Number of implicit operands (which + uint16_t NumImplicitOps; // Number of implicit operands (which // are determined at construction time). - unsigned short AsmPrinterFlags; // Various bits of information used by + uint8_t Flags; // Various bits of additional + // information about machine + // instruction. + + uint8_t AsmPrinterFlags; // Various bits of information used by // the AsmPrinter to emit helpful // comments. This is *not* semantic // information. Do not use this for @@ -125,8 +134,12 @@ public: /// getAsmPrinterFlags - Return the asm printer flags bitvector. /// - unsigned short getAsmPrinterFlags() const { return AsmPrinterFlags; } + uint8_t getAsmPrinterFlags() const { return AsmPrinterFlags; } + /// clearAsmPrinterFlags - clear the AsmPrinter bitvector + /// + void clearAsmPrinterFlags() { AsmPrinterFlags = 0; } + /// getAsmPrinterFlag - Return whether an AsmPrinter flag is set. /// bool getAsmPrinterFlag(CommentFlag Flag) const { @@ -136,13 +149,38 @@ public: /// setAsmPrinterFlag - Set a flag for the AsmPrinter. /// void setAsmPrinterFlag(CommentFlag Flag) { - AsmPrinterFlags |= (unsigned short)Flag; + AsmPrinterFlags |= (uint8_t)Flag; + } + + /// getFlags - Return the MI flags bitvector. + uint8_t getFlags() const { + return Flags; + } + + /// getFlag - Return whether an MI flag is set. + bool getFlag(MIFlag Flag) const { + return Flags & Flag; + } + + /// setFlag - Set a MI flag. + void setFlag(MIFlag Flag) { + Flags |= (uint8_t)Flag; + } + + void setFlags(unsigned flags) { + Flags = flags; + } + + /// clearAsmPrinterFlag - clear specific AsmPrinter flags + /// + void clearAsmPrinterFlag(CommentFlag Flag) { + AsmPrinterFlags &= ~Flag; } /// getDebugLoc - Returns the debug location id of this MachineInstr. /// DebugLoc getDebugLoc() const { return debugLoc; } - + /// getDesc - Returns the target instruction descriptor of this /// MachineInstr. const TargetInstrDesc &getDesc() const { return *TID; } @@ -227,6 +265,7 @@ public: bool isKill() const { return getOpcode() == TargetOpcode::KILL; } bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; } bool isInlineAsm() const { return getOpcode() == TargetOpcode::INLINEASM; } + bool isStackAligningInlineAsm() const; bool isInsertSubreg() const { return getOpcode() == TargetOpcode::INSERT_SUBREG; } @@ -422,6 +461,15 @@ public: /// return 0. unsigned isConstantValuePHI() const; + /// hasUnmodeledSideEffects - Return true if this instruction has side + /// effects that are not modeled by mayLoad / mayStore, etc. + /// For all instructions, the property is encoded in TargetInstrDesc::Flags + /// (see TargetInstrDesc::hasUnmodeledSideEffects(). The only exception is + /// INLINEASM instruction, in which case the side effect property is encoded + /// in one of its operands (see InlineAsm::Extra_HasSideEffect). + /// + bool hasUnmodeledSideEffects() const; + /// allDefsAreDead - Return true if all the defs of this instruction are dead. /// bool allDefsAreDead() const; diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 1eb9735308..f04dee2b4b 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -145,6 +145,16 @@ public: return *this; } + const MachineInstrBuilder &setMIFlags(unsigned Flags) const { + MI->setFlags(Flags); + return *this; + } + + const MachineInstrBuilder &setMIFlag(MachineInstr::MIFlag Flag) const { + MI->setFlag(Flag); + return *this; + } + // Add a displacement from an existing MachineOperand with an added offset. const MachineInstrBuilder &addDisp(const MachineOperand &Disp, int64_t off) const { diff --git a/include/llvm/CodeGen/MachineLocation.h b/include/llvm/CodeGen/MachineLocation.h index a1fcb9fe75..21951b6680 100644 --- a/include/llvm/CodeGen/MachineLocation.h +++ b/include/llvm/CodeGen/MachineLocation.h @@ -32,7 +32,7 @@ private: public: enum { // The target register number for an abstract frame pointer. The value is - // an arbitrary value greater than TargetRegisterInfo::FirstVirtualRegister. + // an arbitrary value that doesn't collide with any real target register. VirtualFP = ~0U }; MachineLocation() @@ -41,6 +41,11 @@ public: : IsRegister(true), Register(R), Offset(0) {} MachineLocation(unsigned R, int O) : IsRegister(false), Register(R), Offset(O) {} + + bool operator==(const MachineLocation &Other) const { + return IsRegister == Other.IsRegister && Register == Other.Register && + Offset == Other.Offset; + } // Accessors bool isReg() const { return IsRegister; } diff --git a/include/llvm/CodeGen/MachineLoopRanges.h b/include/llvm/CodeGen/MachineLoopRanges.h new file mode 100644 index 0000000000..6a30e8b53c --- /dev/null +++ b/include/llvm/CodeGen/MachineLoopRanges.h @@ -0,0 +1,112 @@ +//===- MachineLoopRanges.h - Ranges of machine loops -----------*- c++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the interface to the MachineLoopRanges analysis. +// +// Provide on-demand information about the ranges of machine instructions +// covered by a loop. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINELOOPRANGES_H +#define LLVM_CODEGEN_MACHINELOOPRANGES_H + +#include "llvm/ADT/IntervalMap.h" +#include "llvm/CodeGen/SlotIndexes.h" + +namespace llvm { + +class MachineLoop; +class MachineLoopInfo; +class raw_ostream; + +/// MachineLoopRange - Range information for a single loop. +class MachineLoopRange { + friend class MachineLoopRanges; + +public: + typedef IntervalMap<SlotIndex, unsigned, 4> Map; + typedef Map::Allocator Allocator; + +private: + /// The mapped loop. + const MachineLoop *const Loop; + + /// Map intervals to a bit mask. + /// Bit 0 = inside loop block. + Map Intervals; + + /// Loop area as measured by SlotIndex::distance. + unsigned Area; + + /// Create a MachineLoopRange, only accessible to MachineLoopRanges. + MachineLoopRange(const MachineLoop*, Allocator&, SlotIndexes&); + +public: + /// getLoop - Return the mapped machine loop. + const MachineLoop *getLoop() const { return Loop; } + + /// overlaps - Return true if this loop overlaps the given range of machine + /// inteructions. + bool overlaps(SlotIndex Start, SlotIndex Stop); + + /// getNumber - Return the loop number. This is the same as the number of the + /// header block. + unsigned getNumber() const; + + /// getArea - Return the loop area. This number is approximately proportional + /// to the number of instructions in the loop. + unsigned getArea() const { return Area; } + + /// getMap - Allow public read-only access for IntervalMapOverlaps. + const Map &getMap() { return Intervals; } + + /// print - Print loop ranges on OS. + void print(raw_ostream&) const; + + /// byNumber - Comparator for array_pod_sort that sorts a list of + /// MachineLoopRange pointers by number. + static int byNumber(const void*, const void*); + + /// byAreaDesc - Comparator for array_pod_sort that sorts a list of + /// MachineLoopRange pointers by descending area, then by number. + static int byAreaDesc(const void*, const void*); +}; + +raw_ostream &operator<<(raw_ostream&, const MachineLoopRange&); + +/// MachineLoopRanges - Analysis pass that provides on-demand per-loop range +/// information. +class MachineLoopRanges : public MachineFunctionPass { + typedef DenseMap<const MachineLoop*, MachineLoopRange*> CacheMap; + typedef MachineLoopRange::Allocator MapAllocator; + + MapAllocator Allocator; + SlotIndexes *Indexes; + CacheMap Cache; + +public: + static char ID; // Pass identification, replacement for typeid + + MachineLoopRanges() : MachineFunctionPass(ID), Indexes(0) {} + ~MachineLoopRanges() { releaseMemory(); } + + /// getLoopRange - Return the range of loop. + MachineLoopRange *getLoopRange(const MachineLoop *Loop); + +private: + virtual bool runOnMachineFunction(MachineFunction&); + virtual void releaseMemory(); + virtual void getAnalysisUsage(AnalysisUsage&) const; +}; + + +} // end namespace llvm + +#endif // LLVM_CODEGEN_MACHINELOOPRANGES_H diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h index cabd129353..768ce47f8b 100644 --- a/include/llvm/CodeGen/MachineMemOperand.h +++ b/include/llvm/CodeGen/MachineMemOperand.h @@ -16,7 +16,7 @@ #ifndef LLVM_CODEGEN_MACHINEMEMOPERAND_H #define LLVM_CODEGEN_MACHINEMEMOPERAND_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 43405c0937..6bc80b099f 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -39,7 +39,7 @@ #include "llvm/Support/Dwarf.h" #include "llvm/Support/DebugLoc.h" #include "llvm/Support/ValueHandle.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" @@ -170,7 +170,8 @@ public: VariableDbgInfoMapTy VariableDbgInfo; MachineModuleInfo(); // DUMMY CONSTRUCTOR, DO NOT CALL. - MachineModuleInfo(const MCAsmInfo &MAI); // Real constructor. + // Real constructor. + MachineModuleInfo(const MCAsmInfo &MAI, const TargetAsmInfo *TAI); ~MachineModuleInfo(); bool doInitialization(); @@ -208,7 +209,7 @@ public: /// hasDebugInfo - Returns true if valid debug info is present. /// bool hasDebugInfo() const { return DbgInfoAvailable; } - void setDebugInfoAvailability(bool avail) { DbgInfoAvailable = true; } + void setDebugInfoAvailability(bool avail) { DbgInfoAvailable = avail; } bool callsEHReturn() const { return CallsEHReturn; } void setCallsEHReturn(bool b) { CallsEHReturn = b; } diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index aaf6a2fe4f..8acc9490d8 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -14,7 +14,7 @@ #ifndef LLVM_CODEGEN_MACHINEOPERAND_H #define LLVM_CODEGEN_MACHINEOPERAND_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { @@ -153,6 +153,16 @@ public: MachineInstr *getParent() { return ParentMI; } const MachineInstr *getParent() const { return ParentMI; } + /// clearParent - Reset the parent pointer. + /// + /// The MachineOperand copy constructor also copies ParentMI, expecting the + /// original to be deleted. If a MachineOperand is ever stored outside a + /// MachineInstr, the parent pointer must be cleared. + /// + /// Never call clearParent() on an operand in a MachineInstr. + /// + void clearParent() { ParentMI = 0; } + void print(raw_ostream &os, const TargetMachine *TM = 0) const; //===--------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index ddba61bf18..74df8da20e 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -16,6 +16,7 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/IndexedMap.h" #include <vector> namespace llvm { @@ -24,13 +25,12 @@ namespace llvm { /// registers, including vreg register classes, use/def chains for registers, /// etc. class MachineRegisterInfo { - /// VRegInfo - Information we keep for each virtual register. The entries in - /// this vector are actually converted to vreg numbers by adding the - /// TargetRegisterInfo::FirstVirtualRegister delta to their index. + /// VRegInfo - Information we keep for each virtual register. /// /// Each element in this list contains the register class of the vreg and the /// start of the use/def list for the register. - std::vector<std::pair<const TargetRegisterClass*, MachineOperand*> > VRegInfo; + IndexedMap<std::pair<const TargetRegisterClass*, MachineOperand*>, + VirtReg2IndexFunctor> VRegInfo; /// RegClassVRegMap - This vector acts as a map from TargetRegisterClass to /// virtual registers. For each target register class, it keeps a list of @@ -44,7 +44,7 @@ class MachineRegisterInfo { /// register for allocation. For example, if the hint is <0, 1024>, it means /// the allocator should prefer the physical register allocated to the virtual /// register of the hint. - std::vector<std::pair<unsigned, unsigned> > RegAllocHints; + IndexedMap<std::pair<unsigned, unsigned>, VirtReg2IndexFunctor> RegAllocHints; /// PhysRegUseDefLists - This is an array of the head of the use/def list for /// physical registers. @@ -159,17 +159,15 @@ public: /// getRegUseDefListHead - Return the head pointer for the register use/def /// list for the specified virtual or physical register. MachineOperand *&getRegUseDefListHead(unsigned RegNo) { - if (RegNo < TargetRegisterInfo::FirstVirtualRegister) - return PhysRegUseDefLists[RegNo]; - RegNo -= TargetRegisterInfo::FirstVirtualRegister; - return VRegInfo[RegNo].second; + if (TargetRegisterInfo::isVirtualRegister(RegNo)) + return VRegInfo[RegNo].second; + return PhysRegUseDefLists[RegNo]; } MachineOperand *getRegUseDefListHead(unsigned RegNo) const { - if (RegNo < TargetRegisterInfo::FirstVirtualRegister) - return PhysRegUseDefLists[RegNo]; - RegNo -= TargetRegisterInfo::FirstVirtualRegister; - return VRegInfo[RegNo].second; + if (TargetRegisterInfo::isVirtualRegister(RegNo)) + return VRegInfo[RegNo].second; + return PhysRegUseDefLists[RegNo]; } /// getVRegDef - Return the machine instr that defines the specified virtual @@ -194,8 +192,6 @@ public: /// getRegClass - Return the register class of the specified virtual register. /// const TargetRegisterClass *getRegClass(unsigned Reg) const { - Reg -= TargetRegisterInfo::FirstVirtualRegister; - assert(Reg < VRegInfo.size() && "Invalid vreg!"); return VRegInfo[Reg].first; } @@ -216,11 +212,9 @@ public: /// unsigned createVirtualRegister(const TargetRegisterClass *RegClass); - /// getLastVirtReg - Return the highest currently assigned virtual register. + /// getNumVirtRegs - Return the number of virtual registers created. /// - unsigned getLastVirtReg() const { - return (unsigned)VRegInfo.size()+TargetRegisterInfo::FirstVirtualRegister-1; - } + unsigned getNumVirtRegs() const { return VRegInfo.size(); } /// getRegClassVirtRegs - Return the list of virtual registers of the given /// target register class. @@ -232,8 +226,6 @@ public: /// setRegAllocationHint - Specify a register allocation hint for the /// specified virtual register. void setRegAllocationHint(unsigned Reg, unsigned Type, unsigned PrefReg) { - Reg -= TargetRegisterInfo::FirstVirtualRegister; - assert(Reg < VRegInfo.size() && "Invalid vreg!"); RegAllocHints[Reg].first = Type; RegAllocHints[Reg].second = PrefReg; } @@ -242,8 +234,6 @@ public: /// specified virtual register. std::pair<unsigned, unsigned> getRegAllocationHint(unsigned Reg) const { - Reg -= TargetRegisterInfo::FirstVirtualRegister; - assert(Reg < VRegInfo.size() && "Invalid vreg!"); return RegAllocHints[Reg]; } diff --git a/include/llvm/CodeGen/MachineRelocation.h b/include/llvm/CodeGen/MachineRelocation.h index c316785dd1..244b466e17 100644 --- a/include/llvm/CodeGen/MachineRelocation.h +++ b/include/llvm/CodeGen/MachineRelocation.h @@ -14,7 +14,7 @@ #ifndef LLVM_CODEGEN_MACHINERELOCATION_H #define LLVM_CODEGEN_MACHINERELOCATION_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index bbedabd407..53aee7a9c9 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -45,10 +45,19 @@ namespace llvm { /// extern char &MachineLoopInfoID; + /// MachineLoopRanges pass - This pass is an on-demand loop coverage + /// analysis pass. + /// + extern char &MachineLoopRangesID; + /// MachineDominators pass - This pass is a machine dominators analysis pass. /// extern char &MachineDominatorsID; + /// EdgeBundles analysis - Bundle machine CFG edges. + /// + extern char &EdgeBundlesID; + /// PHIElimination pass - This pass eliminates machine instruction PHI nodes /// by inserting copy instructions. This destroys SSA information, but is the /// desired input for some register allocators. This pass is "required" by @@ -79,6 +88,11 @@ namespace llvm { /// register allocators. extern char &TwoAddressInstructionPassID; + /// SpillPlacement analysis. Suggest optimal placement of spill code between + /// basic blocks. + /// + extern char &SpillPlacementID; + /// UnreachableMachineBlockElimination pass - This pass removes unreachable /// machine basic blocks. extern char &UnreachableMachineBlockElimID; @@ -103,6 +117,11 @@ namespace llvm { /// FunctionPass *createBasicRegisterAllocator(); + /// Greedy register allocation pass - This pass implements a global register + /// allocator for optimized builds. + /// + FunctionPass *createGreedyRegisterAllocator(); + /// LinearScanRegisterAllocation Pass - This pass implements the linear scan /// register allocation algorithm, a global register allocator. /// @@ -196,7 +215,7 @@ namespace llvm { /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. - FunctionPass *createMachineVerifierPass(); + FunctionPass *createMachineVerifierPass(const char *Banner = 0); /// createDwarfEHPass - This pass mulches exception handling code into a form /// adapted to code generation. Required if using dwarf exception handling. @@ -213,6 +232,10 @@ namespace llvm { /// addressing. FunctionPass *createLocalStackSlotAllocationPass(); + /// createExpandISelPseudosPass - This pass expands pseudo-instructions. + /// + FunctionPass *createExpandISelPseudosPass(); + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/PostRAHazardRecognizer.h b/include/llvm/CodeGen/PostRAHazardRecognizer.h deleted file mode 100644 index 4160384f89..0000000000 --- a/include/llvm/CodeGen/PostRAHazardRecognizer.h +++ /dev/null @@ -1,94 +0,0 @@ -//=- llvm/CodeGen/PostRAHazardRecognizer.h - Scheduling Support -*- 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 PostRAHazardRecognizer class, which -// implements hazard-avoidance heuristics for scheduling, based on the -// scheduling itineraries specified for the target. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H -#define LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H - -#include "llvm/CodeGen/ScheduleHazardRecognizer.h" -#include "llvm/System/DataTypes.h" - -#include <cassert> -#include <cstring> -#include <string> - -namespace llvm { - -class InstrItineraryData; -class SUnit; - -class PostRAHazardRecognizer : public ScheduleHazardRecognizer { - // ScoreBoard to track function unit usage. ScoreBoard[0] is a - // mask of the FUs in use in the cycle currently being - // schedule. ScoreBoard[1] is a mask for the next cycle. The - // ScoreBoard is used as a circular buffer with the current cycle - // indicated by Head. - class ScoreBoard { - unsigned *Data; - - // The maximum number of cycles monitored by the Scoreboard. This - // value is determined based on the target itineraries to ensure - // that all hazards can be tracked. - size_t Depth; - // Indices into the Scoreboard that represent the current cycle. - size_t Head; - public: - ScoreBoard():Data(NULL), Depth(0), Head(0) { } - ~ScoreBoard() { - delete[] Data; - } - - size_t getDepth() const { return Depth; } - unsigned& operator[](size_t idx) const { - assert(Depth && "ScoreBoard was not initialized properly!"); - - return Data[(Head + idx) % Depth]; - } - - void reset(size_t d = 1) { - if (Data == NULL) { - Depth = d; - Data = new unsigned[Depth]; - } - - memset(Data, 0, Depth * sizeof(Data[0])); - Head = 0; - } - - void advance() { - Head = (Head + 1) % Depth; - } - - // Print the scoreboard. - void dump() const; - }; - - // Itinerary data for the target. - const InstrItineraryData *ItinData; - - ScoreBoard ReservedScoreboard; - ScoreBoard RequiredScoreboard; - -public: - PostRAHazardRecognizer(const InstrItineraryData *ItinData); - - virtual HazardType getHazardType(SUnit *SU); - virtual void Reset(); - virtual void EmitInstruction(SUnit *SU); - virtual void AdvanceCycle(); -}; - -} - -#endif diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index 008a7b3bf3..7e8745edde 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -22,10 +22,11 @@ #include "llvm/CodeGen/PBQP/Solution.h" #include <map> +#include <set> namespace llvm { - class LiveInterval; + class LiveIntervals; class MachineFunction; class MachineLoopInfo; diff --git a/include/llvm/CodeGen/RegisterCoalescer.h b/include/llvm/CodeGen/RegisterCoalescer.h index 7644433a33..af0b394691 100644 --- a/include/llvm/CodeGen/RegisterCoalescer.h +++ b/include/llvm/CodeGen/RegisterCoalescer.h @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/System/IncludeFile.h" +#include "llvm/Support/IncludeFile.h" #include "llvm/CodeGen/LiveInterval.h" #include "llvm/ADT/SmallPtrSet.h" diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 246831c034..26b6773c05 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -100,7 +100,7 @@ public: /// getRegsAvailable - Return all available registers in the register class /// in Mask. - void getRegsAvailable(const TargetRegisterClass *RC, BitVector &Mask); + BitVector getRegsAvailable(const TargetRegisterClass *RC); /// FindUnusedReg - Find a unused register of the specified register class. /// Return 0 if none is found. diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index a86ba83185..3864ffd50a 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -221,6 +221,9 @@ namespace llvm { } }; + template <> + struct isPodLike<SDep> { static const bool value = true; }; + /// SUnit - Scheduling unit. This is a node in the scheduling DAG. class SUnit { private: @@ -229,9 +232,8 @@ namespace llvm { public: SUnit *OrigNode; // If not this, the node from which // this node was cloned. - - // Preds/Succs - The SUnits before/after us in the graph. The boolean value - // is true if the edge is a token chain edge, false if it is a value edge. + + // Preds/Succs - The SUnits before/after us in the graph. SmallVector<SDep, 4> Preds; // All sunit predecessors. SmallVector<SDep, 4> Succs; // All sunit successors. @@ -242,11 +244,12 @@ namespace llvm { unsigned NodeNum; // Entry # of node in the node vector. unsigned NodeQueueId; // Queue id of node. - unsigned short Latency; // Node latency. unsigned NumPreds; // # of SDep::Data preds. unsigned NumSuccs; // # of SDep::Data sucss. unsigned NumPredsLeft; // # of preds not scheduled. unsigned NumSuccsLeft; // # of succs not scheduled. + unsigned short NumRegDefsLeft; // # of reg defs with no scheduled use. + unsigned short Latency; // Node latency. bool isCall : 1; // Is a function call. bool isTwoAddress : 1; // Is a two-address instruction. bool isCommutable : 1; // Is a commutable instruction. @@ -268,13 +271,13 @@ namespace llvm { public: const TargetRegisterClass *CopyDstRC; // Is a special copy node if not null. const TargetRegisterClass *CopySrcRC; - + /// SUnit - Construct an SUnit for pre-regalloc scheduling to represent /// an SDNode and any nodes flagged to it. SUnit(SDNode *node, unsigned nodenum) : Node(node), Instr(0), OrigNode(0), NodeNum(nodenum), - NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), - NumSuccsLeft(0), + NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), + NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), isCall(false), isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), @@ -287,8 +290,8 @@ namespace llvm { /// a MachineInstr. SUnit(MachineInstr *instr, unsigned nodenum) : Node(0), Instr(instr), OrigNode(0), NodeNum(nodenum), - NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), - NumSuccsLeft(0), + NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), + NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), isCall(false), isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), @@ -300,8 +303,8 @@ namespace llvm { /// SUnit - Construct a placeholder SUnit. SUnit() : Node(0), Instr(0), OrigNode(0), NodeNum(~0u), - NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), - NumSuccsLeft(0), + NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), + NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), isCall(false), isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), @@ -324,6 +327,10 @@ namespace llvm { return Node; } + /// isInstr - Return true if this SUnit refers to a machine instruction as + /// opposed to an SDNode. + bool isInstr() const { return Instr; } + /// setInstr - Assign the instruction for the SUnit. /// This may be used during post-regalloc scheduling. void setInstr(MachineInstr *MI) { @@ -341,7 +348,7 @@ namespace llvm { /// addPred - This adds the specified edge as a pred of the current node if /// not already. It also adds the current node as a successor of the /// specified node. - void addPred(const SDep &D); + bool addPred(const SDep &D); /// removePred - This removes the specified edge as a pred of the current /// node if it exists. It also removes the current node as a successor of @@ -351,7 +358,7 @@ namespace llvm { /// getDepth - Return the depth of this node, which is the length of the /// maximum path up to any node with has no predecessors. unsigned getDepth() const { - if (!isDepthCurrent) + if (!isDepthCurrent) const_cast<SUnit *>(this)->ComputeDepth(); return Depth; } @@ -359,7 +366,7 @@ namespace llvm { /// getHeight - Return the height of this node, which is the length of the /// maximum path down to any node with has no successors. unsigned getHeight() const { - if (!isHeightCurrent) + if (!isHeightCurrent) const_cast<SUnit *>(this)->ComputeHeight(); return Height; } @@ -391,7 +398,7 @@ namespace llvm { return true; return false; } - + /// isSucc - Test if node N is a successor of this node. bool isSucc(SUnit *N) { for (unsigned i = 0, e = (unsigned)Succs.size(); i != e; ++i) @@ -412,25 +419,38 @@ namespace llvm { //===--------------------------------------------------------------------===// /// SchedulingPriorityQueue - This interface is used to plug different /// priorities computation algorithms into the list scheduler. It implements - /// the interface of a standard priority queue, where nodes are inserted in + /// the interface of a standard priority queue, where nodes are inserted in /// arbitrary order and returned in priority order. The computation of the /// priority and the representation of the queue are totally up to the /// implementation to decide. - /// + /// class SchedulingPriorityQueue { unsigned CurCycle; + bool HasReadyFilter; public: - SchedulingPriorityQueue() : CurCycle(0) {} + SchedulingPriorityQueue(bool rf = false): + CurCycle(0), HasReadyFilter(rf) {} virtual ~SchedulingPriorityQueue() {} - + + virtual bool isBottomUp() const = 0; + virtual void initNodes(std::vector<SUnit> &SUnits) = 0; virtual void addNode(const SUnit *SU) = 0; virtual void updateNode(const SUnit *SU) = 0; virtual void releaseState() = 0; virtual bool empty() const = 0; + + bool hasReadyFilter() const { return HasReadyFilter; } + + virtual bool tracksRegPressure() const { return false; } + + virtual bool isReady(SUnit *) const { + assert(!HasReadyFilter && "The ready filter must override isReady()"); + return true; + } virtual void push(SUnit *U) = 0; - + void push_all(const std::vector<SUnit *> &Nodes) { for (std::vector<SUnit *>::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) @@ -441,6 +461,8 @@ namespace llvm { virtual void remove(SUnit *SU) = 0; + virtual void dump(ScheduleDAG *) const {} + /// ScheduledNode - As each node is scheduled, this method is invoked. This /// allows the priority function to adjust the priority of related /// unscheduled nodes, for example. @@ -455,7 +477,7 @@ namespace llvm { unsigned getCurCycle() const { return CurCycle; - } + } }; class ScheduleDAG { @@ -477,11 +499,18 @@ namespace llvm { virtual ~ScheduleDAG(); + /// getInstrDesc - Return the TargetInstrDesc of this SUnit. + /// Return NULL for SDNodes without a machine opcode. + const TargetInstrDesc *getInstrDesc(const SUnit *SU) const { + if (SU->isInstr()) return &SU->getInstr()->getDesc(); + return getNodeDesc(SU->getNode()); + } + /// viewGraph - Pop up a GraphViz/gv window with the ScheduleDAG rendered /// using 'dot'. /// void viewGraph(); - + /// EmitSchedule - Insert MachineInstrs into the MachineBasicBlock /// according to the order specified in Sequence. /// @@ -540,6 +569,10 @@ namespace llvm { void EmitNoop(); void EmitPhysRegCopy(SUnit *SU, DenseMap<SUnit*, unsigned> &VRBaseMap); + + private: + // Return the TargetInstrDesc of this SDNode or NULL. + const TargetInstrDesc *getNodeDesc(const SDNode *Node) const; }; class SUnitIterator : public std::iterator<std::forward_iterator_tag, @@ -631,7 +664,7 @@ namespace llvm { /// Visited - a set of nodes visited during a DFS traversal. BitVector Visited; - /// DFS - make a DFS traversal and mark all nodes affected by the + /// DFS - make a DFS traversal and mark all nodes affected by the /// edge insertion. These nodes will later get new topological indexes /// by means of the Shift method. void DFS(const SUnit *SU, int UpperBound, bool& HasLoop); @@ -646,7 +679,7 @@ namespace llvm { public: explicit ScheduleDAGTopologicalSort(std::vector<SUnit> &SUnits); - /// InitDAGTopologicalSorting - create the initial topological + /// InitDAGTopologicalSorting - create the initial topological /// ordering from the DAG to be scheduled. void InitDAGTopologicalSorting(); diff --git a/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/include/llvm/CodeGen/ScheduleHazardRecognizer.h index 09e3e88613..2f53baa1c7 100644 --- a/include/llvm/CodeGen/ScheduleHazardRecognizer.h +++ b/include/llvm/CodeGen/ScheduleHazardRecognizer.h @@ -23,7 +23,15 @@ class SUnit; /// issued this cycle, and whether or not a noop needs to be inserted to handle /// the hazard. class ScheduleHazardRecognizer { +protected: + /// MaxLookAhead - Indicate the number of cycles in the scoreboard + /// state. Important to restore the state after backtracking. Additionally, + /// MaxLookAhead=0 identifies a fake recognizer, allowing the client to + /// bypass virtual calls. Currently the PostRA scheduler ignores it. + unsigned MaxLookAhead; + public: + ScheduleHazardRecognizer(): MaxLookAhead(0) {} virtual ~ScheduleHazardRecognizer(); enum HazardType { @@ -32,6 +40,14 @@ public: NoopHazard // This instruction can't be emitted, and needs noops. }; + unsigned getMaxLookAhead() const { return MaxLookAhead; } + + bool isEnabled() const { return MaxLookAhead != 0; } + + /// atIssueLimit - Return true if no more instructions may be issued in this + /// cycle. + virtual bool atIssueLimit() const { return false; } + /// getHazardType - Return the hazard type of emitting this node. There are /// three possible results. Either: /// * NoHazard: it is legal to issue this instruction on this cycle. @@ -39,7 +55,7 @@ public: /// other instruction is available, issue it first. /// * NoopHazard: issuing this instruction would break the program. If /// some other instruction can be issued, do so, otherwise issue a noop. - virtual HazardType getHazardType(SUnit *) { + virtual HazardType getHazardType(SUnit *m, int Stalls) { return NoHazard; } @@ -52,12 +68,18 @@ public: /// emitted, to advance the hazard state. virtual void EmitInstruction(SUnit *) {} - /// AdvanceCycle - This callback is invoked when no instructions can be - /// issued on this cycle without a hazard. This should increment the + /// AdvanceCycle - This callback is invoked whenever the next top-down + /// instruction to be scheduled cannot issue in the current cycle, either + /// because of latency or resource conflicts. This should increment the /// internal state of the hazard recognizer so that previously "Hazard" /// instructions will now not be hazards. virtual void AdvanceCycle() {} + /// RecedeCycle - This callback is invoked whenever the next bottom-up + /// instruction to be scheduled cannot issue in the current cycle, either + /// because of latency or resource conflicts. + virtual void RecedeCycle() {} + /// EmitNoop - This callback is invoked when a noop was added to the /// instruction stream. virtual void EmitNoop() { diff --git a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h new file mode 100644 index 0000000000..8850006df8 --- /dev/null +++ b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h @@ -0,0 +1,129 @@ +//=- llvm/CodeGen/ScoreboardHazardRecognizer.h - Schedule Support -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ScoreboardHazardRecognizer class, which +// encapsulates hazard-avoidance heuristics for scheduling, based on the +// scheduling itineraries specified for the target. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H +#define LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H + +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/Support/DataTypes.h" + +#include <cassert> +#include <cstring> +#include <string> + +namespace llvm { + +class InstrItineraryData; +class TargetInstrDesc; +class ScheduleDAG; +class SUnit; + +class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer { + // Scoreboard to track function unit usage. Scoreboard[0] is a + // mask of the FUs in use in the cycle currently being + // schedule. Scoreboard[1] is a mask for the next cycle. The + // Scoreboard is used as a circular buffer with the current cycle + // indicated by Head. + // + // Scoreboard always counts cycles in forward execution order. If used by a + // bottom-up scheduler, then the scoreboard cycles are the inverse of the + // scheduler's cycles. + class Scoreboard { + unsigned *Data; + + // The maximum number of cycles monitored by the Scoreboard. This + // value is determined based on the target itineraries to ensure + // that all hazards can be tracked. + size_t Depth; + // Indices into the Scoreboard that represent the current cycle. + size_t Head; + public: + Scoreboard():Data(NULL), Depth(0), Head(0) { } + ~Scoreboard() { + delete[] Data; + } + + size_t getDepth() const { return Depth; } + unsigned& operator[](size_t idx) const { + // Depth is expected to be a power-of-2. + assert(Depth && !(Depth & (Depth - 1)) && + "Scoreboard was not initialized properly!"); + + return Data[(Head + idx) & (Depth-1)]; + } + + void reset(size_t d = 1) { + if (Data == NULL) { + Depth = d; + Data = new unsigned[Depth]; + } + + memset(Data, 0, Depth * sizeof(Data[0])); + Head = 0; + } + + void advance() { + Head = (Head + 1) & (Depth-1); + } + + void recede() { + Head = (Head - 1) & (Depth-1); + } + + // Print the scoreboard. + void dump() const; + }; + +#ifndef NDEBUG + // Support for tracing ScoreboardHazardRecognizer as a component within + // another module. Follows the current thread-unsafe model of tracing. + static const char *DebugType; +#endif + + // Itinerary data for the target. + const InstrItineraryData *ItinData; + + const ScheduleDAG *DAG; + + /// IssueWidth - Max issue per cycle. 0=Unknown. + unsigned IssueWidth; + + /// IssueCount - Count instructions issued in this cycle. + unsigned IssueCount; + + Scoreboard ReservedScoreboard; + Scoreboard RequiredScoreboard; + +public: + ScoreboardHazardRecognizer(const InstrItineraryData *ItinData, + const ScheduleDAG *DAG, + const char *ParentDebugType = ""); + + /// atIssueLimit - Return true if no more instructions may be issued in this + /// cycle. + virtual bool atIssueLimit() const; + + // Stalls provides an cycle offset at which SU will be scheduled. It will be + // negative for bottom-up scheduling. + virtual HazardType getHazardType(SUnit *SU, int Stalls); + virtual void Reset(); + virtual void EmitInstruction(SUnit *SU); + virtual void AdvanceCycle(); + virtual void RecedeCycle(); +}; + +} + +#endif //!LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 4dfc3c6728..c9de95bebd 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -171,9 +171,6 @@ class SelectionDAG { /// DbgInfo - Tracks dbg_value information through SDISel. SDDbgInfo *DbgInfo; - /// VerifyNode - Sanity check the given node. Aborts if it is invalid. - void VerifyNode(SDNode *N); - /// setGraphColorHelper - Implementation of setSubgraphColor. /// Return whether we had to truncate the search. /// @@ -401,21 +398,21 @@ public: } // This version of the getCopyToReg method takes an extra operand, which - // indicates that there is potentially an incoming flag value (if Flag is not - // null) and that there should be a flag result. + // indicates that there is potentially an incoming glue value (if Glue is not + // null) and that there should be a glue result. SDValue getCopyToReg(SDValue Chain, DebugLoc dl, unsigned Reg, SDValue N, - SDValue Flag) { - SDVTList VTs = getVTList(MVT::Other, MVT::Flag); - SDValue Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Flag }; - return getNode(ISD::CopyToReg, dl, VTs, Ops, Flag.getNode() ? 4 : 3); + SDValue Glue) { + SDVTList VTs = getVTList(MVT::Other, MVT::Glue); + SDValue Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Glue }; + return getNode(ISD::CopyToReg, dl, VTs, Ops, Glue.getNode() ? 4 : 3); } // Similar to last getCopyToReg() except parameter Reg is a SDValue SDValue getCopyToReg(SDValue Chain, DebugLoc dl, SDValue Reg, SDValue N, - SDValue Flag) { - SDVTList VTs = getVTList(MVT::Other, MVT::Flag); - SDValue Ops[] = { Chain, Reg, N, Flag }; - return getNode(ISD::CopyToReg, dl, VTs, Ops, Flag.getNode() ? 4 : 3); + SDValue Glue) { + SDVTList VTs = getVTList(MVT::Other, MVT::Glue); + SDValue Ops[] = { Chain, Reg, N, Glue }; + return getNode(ISD::CopyToReg, dl, VTs, Ops, Glue.getNode() ? 4 : 3); } SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, EVT VT) { @@ -425,13 +422,13 @@ public: } // This version of the getCopyFromReg method takes an extra operand, which - // indicates that there is potentially an incoming flag value (if Flag is not - // null) and that there should be a flag result. + // indicates that there is potentially an incoming glue value (if Glue is not + // null) and that there should be a glue result. SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, EVT VT, - SDValue Flag) { - SDVTList VTs = getVTList(VT, MVT::Other, MVT::Flag); - SDValue Ops[] = { Chain, getRegister(Reg, VT), Flag }; - return getNode(ISD::CopyFromReg, dl, VTs, Ops, Flag.getNode() ? 3 : 2); + SDValue Glue) { + SDVTList VTs = getVTList(VT, MVT::Other, MVT::Glue); + SDValue Ops[] = { Chain, getRegister(Reg, VT), Glue }; + return getNode(ISD::CopyFromReg, dl, VTs, Ops, Glue.getNode() ? 3 : 2); } SDValue getCondCode(ISD::CondCode Cond); @@ -465,27 +462,27 @@ public: SDValue getNOT(DebugLoc DL, SDValue Val, EVT VT); /// getCALLSEQ_START - Return a new CALLSEQ_START node, which always must have - /// a flag result (to ensure it's not CSE'd). CALLSEQ_START does not have a + /// a glue result (to ensure it's not CSE'd). CALLSEQ_START does not have a /// useful DebugLoc. SDValue getCALLSEQ_START(SDValue Chain, SDValue Op) { - SDVTList VTs = getVTList(MVT::Other, MVT::Flag); + SDVTList VTs = getVTList(MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, Op }; return getNode(ISD::CALLSEQ_START, DebugLoc(), VTs, Ops, 2); } /// getCALLSEQ_END - Return a new CALLSEQ_END node, which always must have a - /// flag result (to ensure it's not CSE'd). CALLSEQ_END does not have + /// glue result (to ensure it's not CSE'd). CALLSEQ_END does not have /// a useful DebugLoc. SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, - SDValue InFlag) { - SDVTList NodeTys = getVTList(MVT::Other, MVT::Flag); + SDValue InGlue) { + SDVTList NodeTys = getVTList(MVT::Other, MVT::Glue); SmallVector<SDValue, 4> Ops; Ops.push_back(Chain); Ops.push_back(Op1); Ops.push_back(Op2); - Ops.push_back(InFlag); + Ops.push_back(InGlue); return getNode(ISD::CALLSEQ_END, DebugLoc(), NodeTys, &Ops[0], - (unsigned)Ops.size() - (InFlag.getNode() == 0 ? 1 : 0)); + (unsigned)Ops.size() - (InGlue.getNode() == 0 ? 1 : 0)); } /// getUNDEF - Return an UNDEF node. UNDEF does not have a useful DebugLoc. @@ -633,7 +630,7 @@ public: MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, unsigned Alignment, const MDNode *TBAAInfo = 0); - SDValue getExtLoad(ISD::LoadExtType ExtType, EVT VT, DebugLoc dl, + SDValue getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, bool isNonTemporal, unsigned Alignment, @@ -904,6 +901,9 @@ public: SmallVector<SDDbgValue*,2> &GetDbgValues(const SDNode* SD) { return DbgInfo->getSDDbgValues(SD); } + + /// TransferDbgValues - Transfer SDDbgValues. + void TransferDbgValues(SDValue From, SDValue To); /// hasDebugValues - Return true if there are any SDDbgValue nodes associated /// with this SelectionDAG. @@ -966,6 +966,13 @@ public: /// class to allow target nodes to be understood. unsigned ComputeNumSignBits(SDValue Op, unsigned Depth = 0) const; + /// isBaseWithConstantOffset - Return true if the specified operand is an + /// ISD::ADD with a ConstantSDNode on the right-hand side, or if it is an + /// ISD::OR with a ConstantSDNode that is guaranteed to have the same + /// semantics as an ADD. This handles the equivalence: + /// X|Cst == X+Cst iff X&Cst = 0. + bool isBaseWithConstantOffset(SDValue Op) const; + /// isKnownNeverNan - Test whether the given SDValue is known to never be NaN. bool isKnownNeverNaN(SDValue Op) const; diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 9601bbc2f9..54576794de 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -35,7 +35,7 @@ namespace llvm { class GCFunctionInfo; class ScheduleDAGSDNodes; class LoadInst; - + /// SelectionDAGISel - This is the common base class used for SelectionDAG-based /// pattern-matching instruction selectors. class SelectionDAGISel : public MachineFunctionPass { @@ -55,7 +55,7 @@ public: explicit SelectionDAGISel(const TargetMachine &tm, CodeGenOpt::Level OL = CodeGenOpt::Default); virtual ~SelectionDAGISel(); - + const TargetLowering &getTargetLowering() { return TLI; } virtual void getAnalysisUsage(AnalysisUsage &AU) const; @@ -63,18 +63,18 @@ public: virtual bool runOnMachineFunction(MachineFunction &MF); virtual void EmitFunctionEntryCode() {} - + /// PreprocessISelDAG - This hook allows targets to hack on the graph before /// instruction selection starts. virtual void PreprocessISelDAG() {} - + /// PostprocessISelDAG() - This hook allows the target to hack on the graph /// right after selection. virtual void PostprocessISelDAG() {} - + /// Select - Main hook targets implement to select a node. virtual SDNode *Select(SDNode *N) = 0; - + /// SelectInlineAsmMemoryOperand - Select the specified address as a target /// addressing mode, according to the specified constraint code. If this does /// not match or is not implemented, return true. The resultant operands @@ -98,19 +98,14 @@ public: CodeGenOpt::Level OptLevel, bool IgnoreChains = false); - /// CreateTargetHazardRecognizer - Return a newly allocated hazard recognizer - /// to use for this target when scheduling the DAG. - virtual ScheduleHazardRecognizer *CreateTargetHazardRecognizer(); - - // Opcodes used by the DAG state machine: enum BuiltinOpcodes { OPC_Scope, OPC_RecordNode, - OPC_RecordChild0, OPC_RecordChild1, OPC_RecordChild2, OPC_RecordChild3, + OPC_RecordChild0, OPC_RecordChild1, OPC_RecordChild2, OPC_RecordChild3, OPC_RecordChild4, OPC_RecordChild5, OPC_RecordChild6, OPC_RecordChild7, OPC_RecordMemRef, - OPC_CaptureFlagInput, + OPC_CaptureGlueInput, OPC_MoveChild, OPC_MoveParent, OPC_CheckSame, @@ -129,9 +124,10 @@ public: OPC_CheckComplexPat, OPC_CheckAndImm, OPC_CheckOrImm, OPC_CheckFoldableChainNode, - + OPC_EmitInteger, OPC_EmitRegister, + OPC_EmitRegister2, OPC_EmitConvertToTarget, OPC_EmitMergeInputChains, OPC_EmitMergeInputChains1_0, @@ -140,15 +136,15 @@ public: OPC_EmitNodeXForm, OPC_EmitNode, OPC_MorphNodeTo, - OPC_MarkFlagResults, + OPC_MarkGlueResults, OPC_CompleteMatch }; - + enum { - OPFL_None = 0, // Node has no chain or flag input and isn't variadic. + OPFL_None = 0, // Node has no chain or glue input and isn't variadic. OPFL_Chain = 1, // Node has a chain input. - OPFL_FlagInput = 2, // Node has a flag input. - OPFL_FlagOutput = 4, // Node has a flag output. + OPFL_GlueInput = 2, // Node has a glue input. + OPFL_GlueOutput = 4, // Node has a glue output. OPFL_MemRefs = 8, // Node gets accumulated MemRefs. OPFL_Variadic0 = 1<<4, // Node is variadic, root has 0 fixed inputs. OPFL_Variadic1 = 2<<4, // Node is variadic, root has 1 fixed inputs. @@ -157,37 +153,37 @@ public: OPFL_Variadic4 = 5<<4, // Node is variadic, root has 4 fixed inputs. OPFL_Variadic5 = 6<<4, // Node is variadic, root has 5 fixed inputs. OPFL_Variadic6 = 7<<4, // Node is variadic, root has 6 fixed inputs. - + OPFL_VariadicInfo = OPFL_Variadic6 }; - + /// getNumFixedFromVariadicInfo - Transform an EmitNode flags word into the /// number of fixed arity values that should be skipped when copying from the /// root. static inline int getNumFixedFromVariadicInfo(unsigned Flags) { return ((Flags&OPFL_VariadicInfo) >> 4)-1; } - - + + protected: /// DAGSize - Size of DAG being instruction selected. /// unsigned DAGSize; - + /// ISelPosition - Node iterator marking the current position of /// instruction selection as it procedes through the topologically-sorted /// node list. SelectionDAG::allnodes_iterator ISelPosition; - - /// ISelUpdater - helper class to handle updates of the + + /// ISelUpdater - helper class to handle updates of the /// instruction selection graph. class ISelUpdater : public SelectionDAG::DAGUpdateListener { SelectionDAG::allnodes_iterator &ISelPosition; public: explicit ISelUpdater(SelectionDAG::allnodes_iterator &isp) : ISelPosition(isp) {} - + /// NodeDeleted - Handle nodes deleted from the graph. If the /// node being deleted is the current ISelPosition node, update /// ISelPosition. @@ -196,46 +192,46 @@ protected: if (ISelPosition == SelectionDAG::allnodes_iterator(N)) ++ISelPosition; } - + /// NodeUpdated - Ignore updates for now. virtual void NodeUpdated(SDNode *N) {} }; - + /// ReplaceUses - replace all uses of the old node F with the use /// of the new node T. void ReplaceUses(SDValue F, SDValue T) { ISelUpdater ISU(ISelPosition); CurDAG->ReplaceAllUsesOfValueWith(F, T, &ISU); } - + /// ReplaceUses - replace all uses of the old nodes F with the use /// of the new nodes T. void ReplaceUses(const SDValue *F, const SDValue *T, unsigned Num) { ISelUpdater ISU(ISelPosition); CurDAG->ReplaceAllUsesOfValuesWith(F, T, Num, &ISU); } - + /// ReplaceUses - replace all uses of the old node F with the use /// of the new node T. void ReplaceUses(SDNode *F, SDNode *T) { ISelUpdater ISU(ISelPosition); CurDAG->ReplaceAllUsesWith(F, T, &ISU); } - + /// SelectInlineAsmMemoryOperands - Calls to this are automatically generated /// by tblgen. Others should not call it. void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops); - + public: // Calls to these predicates are generated by tblgen. bool CheckAndMask(SDValue LHS, ConstantSDNode *RHS, int64_t DesiredMaskS) const; bool CheckOrMask(SDValue LHS, ConstantSDNode *RHS, int64_t DesiredMaskS) const; - - + + /// CheckPatternPredicate - This function is generated by tblgen in the /// target. It runs the specified pattern predicate and returns true if it /// succeeds or false if it fails. The number is a private implementation @@ -253,14 +249,14 @@ public: assert(0 && "Tblgen should generate the implementation of this!"); return 0; } - + virtual bool CheckComplexPattern(SDNode *Root, SDNode *Parent, SDValue N, unsigned PatternNo, SmallVectorImpl<std::pair<SDValue, SDNode*> > &Result) { assert(0 && "Tblgen should generate the implementation of this!"); return false; } - + virtual SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) { assert(0 && "Tblgen shoudl generate this!"); return SDValue(); @@ -269,9 +265,9 @@ public: SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, unsigned TableSize); - + private: - + // Calls to these functions are generated by tblgen. SDNode *Select_INLINEASM(SDNode *N); SDNode *Select_UNDEF(SDNode *N); @@ -281,7 +277,7 @@ private: void DoInstructionSelection(); SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTs, const SDValue *Ops, unsigned NumOps, unsigned EmitNodeInfo); - + void PrepareEHLandingPad(); void SelectAllBasicBlocks(const Function &Fn); bool TryToFoldFastISelLoad(const LoadInst *LI, FastISel *FastIS); @@ -292,7 +288,7 @@ private: bool &HadTailCall); void CodeGenAndEmitDAG(); void LowerArguments(const BasicBlock *BB); - + void ComputeLiveOutVRegInfo(); /// Create the scheduler. If a specific scheduler was specified @@ -300,16 +296,16 @@ private: /// one preferred by the target. /// ScheduleDAGSDNodes *CreateScheduler(); - + /// OpcodeOffset - This is a cache used to dispatch efficiently into isel /// state machines that start with a OPC_SwitchOpcode node. std::vector<unsigned> OpcodeOffset; - - void UpdateChainsAndFlags(SDNode *NodeToMatch, SDValue InputChain, - const SmallVectorImpl<SDNode*> &ChainNodesMatched, - SDValue InputFlag,const SmallVectorImpl<SDNode*> &F, - bool isMorphNodeTo); - + + void UpdateChainsAndGlue(SDNode *NodeToMatch, SDValue InputChain, + const SmallVectorImpl<SDNode*> &ChainNodesMatched, + SDValue InputGlue, const SmallVectorImpl<SDNode*> &F, + bool isMorphNodeTo); + }; } diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 8fa099ae39..64546394ce 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -29,7 +29,7 @@ #include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/Support/MathExtras.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/DebugLoc.h" #include <cassert> @@ -524,24 +524,24 @@ public: return X; } - /// getFlaggedNode - If this node has a flag operand, return the node - /// to which the flag operand points. Otherwise return NULL. - SDNode *getFlaggedNode() const { + /// getGluedNode - If this node has a glue operand, return the node + /// to which the glue operand points. Otherwise return NULL. + SDNode *getGluedNode() const { if (getNumOperands() != 0 && - getOperand(getNumOperands()-1).getValueType() == MVT::Flag) + getOperand(getNumOperands()-1).getValueType() == MVT::Glue) return getOperand(getNumOperands()-1).getNode(); return 0; } // If this is a pseudo op, like copyfromreg, look to see if there is a - // real target node flagged to it. If so, return the target node. - const SDNode *getFlaggedMachineNode() const { + // real target node glued to it. If so, return the target node. + const SDNode *getGluedMachineNode() const { const SDNode *FoundNode = this; - // Climb up flag edges until a machine-opcode node is found, or the + // Climb up glue edges until a machine-opcode node is found, or the // end of the chain is reached. while (!FoundNode->isMachineOpcode()) { - const SDNode *N = FoundNode->getFlaggedNode(); + const SDNode *N = FoundNode->getGluedNode(); if (!N) break; FoundNode = N; } @@ -549,11 +549,11 @@ public: return FoundNode; } - /// getFlaggedUser - If this node has a flag value with a user, return + /// getGluedUser - If this node has a glue value with a user, return /// the user (there is at most one). Otherwise return NULL. - SDNode *getFlaggedUser() const { + SDNode *getGluedUser() const { for (use_iterator UI = use_begin(), UE = use_end(); UI != UE; ++UI) - if (UI.getUse().get().getValueType() == MVT::Flag) + if (UI.getUse().get().getValueType() == MVT::Glue) return *UI; return 0; } diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index c8f26544f0..0e2adb5897 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -34,77 +34,35 @@ namespace llvm { /// SlotIndex & SlotIndexes classes for the public interface to this /// information. class IndexListEntry { - static const unsigned EMPTY_KEY_INDEX = ~0U & ~3U, - TOMBSTONE_KEY_INDEX = ~0U & ~7U; - IndexListEntry *next, *prev; MachineInstr *mi; unsigned index; - protected: - - typedef enum { EMPTY_KEY, TOMBSTONE_KEY } ReservedEntryType; - - // This constructor is only to be used by getEmptyKeyEntry - // & getTombstoneKeyEntry. It sets index to the given - // value and mi to zero. - IndexListEntry(ReservedEntryType r) : mi(0) { - switch(r) { - case EMPTY_KEY: index = EMPTY_KEY_INDEX; break; - case TOMBSTONE_KEY: index = TOMBSTONE_KEY_INDEX; break; - default: assert(false && "Invalid value for constructor."); - } - next = this; - prev = this; - } - public: - IndexListEntry(MachineInstr *mi, unsigned index) : mi(mi), index(index) { - assert(index != EMPTY_KEY_INDEX && index != TOMBSTONE_KEY_INDEX && - "Attempt to create invalid index. " - "Available indexes may have been exhausted?."); - } - - bool isValid() const { - return (index != EMPTY_KEY_INDEX && index != TOMBSTONE_KEY_INDEX); - } + IndexListEntry(MachineInstr *mi, unsigned index) : mi(mi), index(index) {} MachineInstr* getInstr() const { return mi; } void setInstr(MachineInstr *mi) { - assert(isValid() && "Attempt to modify reserved index."); this->mi = mi; } unsigned getIndex() const { return index; } void setIndex(unsigned index) { - assert(index != EMPTY_KEY_INDEX && index != TOMBSTONE_KEY_INDEX && - "Attempt to set index to invalid value."); - assert(isValid() && "Attempt to reset reserved index value."); this->index = index; } IndexListEntry* getNext() { return next; } const IndexListEntry* getNext() const { return next; } void setNext(IndexListEntry *next) { - assert(isValid() && "Attempt to modify reserved index."); this->next = next; } IndexListEntry* getPrev() { return prev; } const IndexListEntry* getPrev() const { return prev; } void setPrev(IndexListEntry *prev) { - assert(isValid() && "Attempt to modify reserved index."); this->prev = prev; } - - // This function returns the index list entry that is to be used for empty - // SlotIndex keys. - static IndexListEntry* getEmptyKeyEntry(); - - // This function returns the index list entry that is to be used for - // tombstone SlotIndex keys. - static IndexListEntry* getTombstoneKeyEntry(); }; // Specialize PointerLikeTypeTraits for IndexListEntry. @@ -130,11 +88,10 @@ namespace llvm { PointerIntPair<IndexListEntry*, 2, unsigned> lie; SlotIndex(IndexListEntry *entry, unsigned slot) - : lie(entry, slot) { - assert(entry != 0 && "Attempt to construct index with 0 pointer."); - } + : lie(entry, slot) {} IndexListEntry& entry() const { + assert(isValid() && "Attempt to compare reserved index."); return *lie.getPointer(); } @@ -148,22 +105,27 @@ namespace llvm { } static inline unsigned getHashValue(const SlotIndex &v) { - IndexListEntry *ptrVal = &v.entry(); - return (unsigned((intptr_t)ptrVal) >> 4) ^ - (unsigned((intptr_t)ptrVal) >> 9); + void *ptrVal = v.lie.getOpaqueValue(); + return (unsigned((intptr_t)ptrVal)) ^ (unsigned((intptr_t)ptrVal) >> 9); } public: + enum { + /// The default distance between instructions as returned by distance(). + /// This may vary as instructions are inserted and removed. + InstrDist = 4*NUM + }; + static inline SlotIndex getEmptyKey() { - return SlotIndex(IndexListEntry::getEmptyKeyEntry(), 0); + return SlotIndex(0, 1); } static inline SlotIndex getTombstoneKey() { - return SlotIndex(IndexListEntry::getTombstoneKeyEntry(), 0); + return SlotIndex(0, 2); } /// Construct an invalid index. - SlotIndex() : lie(IndexListEntry::getEmptyKeyEntry(), 0) {} + SlotIndex() : lie(0, 0) {} // Construct a new slot index from the given one, and set the slot. SlotIndex(const SlotIndex &li, Slot s) @@ -175,8 +137,7 @@ namespace llvm { /// Returns true if this is a valid index. Invalid indicies do /// not point into an index table, and cannot be compared. bool isValid() const { - IndexListEntry *entry = lie.getPointer(); - return ((entry!= 0) && (entry->isValid())); + return lie.getPointer(); } /// Print this index to the given raw_ostream. @@ -187,11 +148,11 @@ namespace llvm { /// Compare two SlotIndex objects for equality. bool operator==(SlotIndex other) const { - return getIndex() == other.getIndex(); + return lie == other.lie; } /// Compare two SlotIndex objects for inequality. bool operator!=(SlotIndex other) const { - return getIndex() != other.getIndex(); + return lie != other.lie; } /// Compare two SlotIndex objects. Return true if the first index @@ -466,6 +427,9 @@ namespace llvm { insert(getTail(), val); } + /// Renumber locally after inserting newEntry. + void renumberIndexes(IndexListEntry *newEntry); + public: static char ID; @@ -530,7 +494,7 @@ namespace llvm { /// Returns the instruction for the given index, or null if the given /// index has no instruction associated with it. MachineInstr* getInstructionFromIndex(SlotIndex index) const { - return index.entry().getInstr(); + return index.isValid() ? index.entry().getInstr() : 0; } /// Returns the next non-null index. @@ -545,18 +509,22 @@ namespace llvm { return nextNonNull; } - /// Returns the first index in the given basic block. - SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const { + /// Return the (start,end) range of the given basic block. + const std::pair<SlotIndex, SlotIndex> & + getMBBRange(const MachineBasicBlock *mbb) const { MBB2IdxMap::const_iterator itr = mbb2IdxMap.find(mbb); assert(itr != mbb2IdxMap.end() && "MBB not found in maps."); - return itr->second.first; + return itr->second; + } + + /// Returns the first index in the given basic block. + SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const { + return getMBBRange(mbb).first; } /// Returns the last index in the given basic block. SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const { - MBB2IdxMap::const_iterator itr = mbb2IdxMap.find(mbb); - assert(itr != mbb2IdxMap.end() && "MBB not found in maps."); - return itr->second.second; + return getMBBRange(mbb).second; } /// Returns the basic block which the given index falls in. @@ -618,9 +586,11 @@ namespace llvm { /// Insert the given machine instruction into the mapping. Returns the /// assigned index. - SlotIndex insertMachineInstrInMaps(MachineInstr *mi, - bool *deferredRenumber = 0) { + SlotIndex insertMachineInstrInMaps(MachineInstr *mi) { assert(mi2iMap.find(mi) == mi2iMap.end() && "Instr already indexed."); + // Numbering DBG_VALUE instructions could cause code generation to be + // affected by debug information. + assert(!mi->isDebugValue() && "Cannot number DBG_VALUE instructions."); MachineBasicBlock *mbb = mi->getParent(); @@ -632,7 +602,6 @@ namespace llvm { "Instruction's parent MBB has not been added to SlotIndexes."); MachineBasicBlock::iterator miItr(mi); - bool needRenumber = false; IndexListEntry *newEntry; // Get previous index, considering that not all instructions are indexed. IndexListEntry *prevEntry; @@ -655,55 +624,22 @@ namespace llvm { // Get a number for the new instr, or 0 if there's no room currently. // In the latter case we'll force a renumber later. - unsigned dist = nextEntry->getIndex() - prevEntry->getIndex(); - unsigned newNumber = dist > SlotIndex::NUM ? - prevEntry->getIndex() + ((dist >> 1) & ~3U) : 0; - - if (newNumber == 0) { - needRenumber = true; - } + unsigned dist = ((nextEntry->getIndex() - prevEntry->getIndex())/2) & ~3u; + unsigned newNumber = prevEntry->getIndex() + dist; // Insert a new list entry for mi. newEntry = createEntry(mi, newNumber); insert(nextEntry, newEntry); - - SlotIndex newIndex(newEntry, SlotIndex::LOAD); - mi2iMap.insert(std::make_pair(mi, newIndex)); - if (miItr == mbb->end()) { - // If this is the last instr in the MBB then we need to fix up the bb - // range: - mbbRangeItr->second.second = SlotIndex(newEntry, SlotIndex::STORE); - } - - // Renumber if we need to. - if (needRenumber) { - if (deferredRenumber == 0) - renumberIndexes(); - else - *deferredRenumber = true; - } + // Renumber locally if we need to. + if (dist == 0) + renumberIndexes(newEntry); + SlotIndex newIndex(newEntry, SlotIndex::LOAD); + mi2iMap.insert(std::make_pair(mi, newIndex)); return newIndex; } - /// Add all instructions in the vector to the index list. This method will - /// defer renumbering until all instrs have been added, and should be - /// preferred when adding multiple instrs. - void insertMachineInstrsInMaps(SmallVectorImpl<MachineInstr*> &mis) { - bool renumber = false; - - for (SmallVectorImpl<MachineInstr*>::iterator - miItr = mis.begin(), miEnd = mis.end(); - miItr != miEnd; ++miItr) { - insertMachineInstrInMaps(*miItr, &renumber); - } - - if (renumber) - renumberIndexes(); - } - - /// Remove the given machine instruction from the mapping. void removeMachineInstrFromMaps(MachineInstr *mi) { // remove index -> MachineInstr and @@ -773,6 +709,20 @@ namespace llvm { }; + // Specialize IntervalMapInfo for half-open slot index intervals. + template <typename> struct IntervalMapInfo; + template <> struct IntervalMapInfo<SlotIndex> { + static inline bool startLess(const SlotIndex &x, const SlotIndex &a) { + return x < a; + } + static inline bool stopLess(const SlotIndex &b, const SlotIndex &x) { + return b <= x; + } + static inline bool adjacent(const SlotIndex &a, const SlotIndex &b) { + return a == b; + } + }; + } #endif // LLVM_CODEGEN_LIVEINDEX_H diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index d8f0373859..fba3e48c47 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -57,6 +57,8 @@ public: virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + virtual const MCSection *getEHFrameSection() const; + const MCSection *getDataRelSection() const { return DataRelSection; } /// getSectionForConstant - Given a constant with the SectionKind, return a @@ -121,6 +123,8 @@ public: virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + virtual const MCSection *getEHFrameSection() const; + virtual const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const; @@ -184,6 +188,8 @@ public: virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + virtual const MCSection *getEHFrameSection() const; + virtual const MCSection *getDrectveSection() const { return DrectveSection; } virtual const MCSection * diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index ae6729a205..22d1622207 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -18,7 +18,7 @@ #include <cassert> #include <string> -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" namespace llvm { @@ -79,7 +79,7 @@ namespace llvm { x86mmx = 33, // This is an X86 MMX value - Flag = 34, // This glues nodes together during pre-RA sched + Glue = 34, // This glues nodes together during pre-RA sched isVoid = 35, // This has no value diff --git a/include/llvm/CompilerDriver/CompilationGraph.h b/include/llvm/CompilerDriver/CompilationGraph.h index 619c904f15..e1eea325e3 100644 --- a/include/llvm/CompilerDriver/CompilationGraph.h +++ b/include/llvm/CompilerDriver/CompilationGraph.h @@ -21,7 +21,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" #include <cassert> #include <string> diff --git a/include/llvm/CompilerDriver/Tool.h b/include/llvm/CompilerDriver/Tool.h index 7316dfdcab..d0926ba983 100644 --- a/include/llvm/CompilerDriver/Tool.h +++ b/include/llvm/CompilerDriver/Tool.h @@ -18,7 +18,7 @@ #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringSet.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" #include <string> #include <vector> diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 26a39b224e..b2deb1dccf 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -1,4 +1,3 @@ - /************************************** ** Created by Kevin from config.h.in ** ***************************************/ @@ -6,53 +5,35 @@ #ifndef CONFIG_H #define CONFIG_H -/* Define if dlopen(0) will open the symbols of the program */ -#undef CAN_DLOPEN_SELF - /* Define if CBE is enabled for printf %a output */ -#undef ENABLE_CBE_PRINTF_A - -/* Relative directory for resource files */ -#define CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}" - -/* Directories clang will search for headers */ -#define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}" - -/* Directory clang will search for libstdc++ headers */ -#define CXX_INCLUDE_ROOT "${CXX_INCLUDE_ROOT}" - -/* Architecture of libstdc++ headers */ -#define CXX_INCLUDE_ARCH "${CXX_INCLUDE_ARCH}" - -/* 32 bit multilib directory */ -#define CXX_INCLUDE_32BIT_DIR "${CXX_INCLUDE_32BIT_DIR}" - -/* 64 bit multilib directory */ -#define CXX_INCLUDE_64BIT_DIR "${CXX_INCLUDE_64BIT_DIR}" +#cmakedefine ENABLE_CBE_PRINTF_A ${ENABLE_CBE_PRINTF_A} /* Define if position independent code is enabled */ -#cmakedefine ENABLE_PIC ${ENABLE_PIC} +#cmakedefine ENABLE_PIC /* Define if threads enabled */ #cmakedefine ENABLE_THREADS ${ENABLE_THREADS} +/* Define if timestamp information (e.g., __DATE___) is allowed */ +#cmakedefine ENABLE_TIMESTAMPS ${ENABLE_TIMESTAMPS} + /* Define to 1 if you have the `argz_append' function. */ -#undef HAVE_ARGZ_APPEND +#cmakedefine HAVE_ARGZ_APPEND ${HAVE_ARGZ_APPEND} /* Define to 1 if you have the `argz_create_sep' function. */ -#undef HAVE_ARGZ_CREATE_SEP +#cmakedefine HAVE_ARGZ_CREATE_SEP ${HAVE_ARGZ_CREATE_SEP} /* Define to 1 if you have the <argz.h> header file. */ #cmakedefine HAVE_ARGZ_H ${HAVE_ARGZ_H} /* Define to 1 if you have the `argz_insert' function. */ -#undef HAVE_ARGZ_INSERT +#cmakedefine HAVE_ARGZ_INSERT ${HAVE_ARGZ_INSERT} /* Define to 1 if you have the `argz_next' function. */ -#undef HAVE_ARGZ_NEXT +#cmakedefine HAVE_ARGZ_NEXT ${HAVE_ARGZ_NEXT} /* Define to 1 if you have the `argz_stringify' function. */ -#undef HAVE_ARGZ_STRINGIFY +#cmakedefine HAVE_ARGZ_STRINGIFY ${HAVE_ARGZ_STRINGIFY} /* Define to 1 if you have the <assert.h> header file. */ #cmakedefine HAVE_ASSERT_H ${HAVE_ASSERT_H} @@ -63,9 +44,6 @@ /* Define to 1 if you have the `bcopy' function. */ #undef HAVE_BCOPY -/* Does not have bi-directional iterator */ -#undef HAVE_BI_ITERATOR - /* Define to 1 if you have the `ceilf' function. */ #cmakedefine HAVE_CEILF ${HAVE_CEILF} @@ -73,10 +51,20 @@ #cmakedefine HAVE_CIRCO ${HAVE_CIRCO} /* Define to 1 if you have the `closedir' function. */ -#undef HAVE_CLOSEDIR +#cmakedefine HAVE_CLOSEDIR ${HAVE_CLOSEDIR} + +/* Define to 1 if you have the <CrashReporterClient.h> header file. */ +#undef HAVE_CRASHREPORTERCLIENT_H + +/* Define if __crashreporter_info__ exists. */ +#undef HAVE_CRASHREPORTER_INFO /* Define to 1 if you have the <ctype.h> header file. */ -#undef HAVE_CTYPE_H +#cmakedefine HAVE_CTYPE_H ${HAVE_CTYPE_H} + +/* Define to 1 if you have the declaration of `strerror_s', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_STRERROR_S /* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. */ @@ -89,13 +77,13 @@ #cmakedefine HAVE_DLD_H ${HAVE_DLD_H} /* Define to 1 if you have the `dlerror' function. */ -#undef HAVE_DLERROR +#cmakedefine HAVE_DLERROR ${HAVE_DLERROR} /* Define to 1 if you have the <dlfcn.h> header file. */ #cmakedefine HAVE_DLFCN_H ${HAVE_DLFCN_H} /* Define if dlopen() is available on this platform. */ -#undef HAVE_DLOPEN +#cmakedefine HAVE_DLOPEN ${HAVE_DLOPEN} /* Define to 1 if you have the <dl.h> header file. */ #cmakedefine HAVE_DL_H ${HAVE_DL_H} @@ -113,7 +101,7 @@ #cmakedefine HAVE_ERRNO_H ${HAVE_ERRNO_H} /* Define to 1 if the system has the type `error_t'. */ -#undef HAVE_ERROR_T +#cmakedefine HAVE_ERROR_T ${HAVE_ERROR_T} /* Define to 1 if you have the <execinfo.h> header file. */ #cmakedefine HAVE_EXECINFO_H ${HAVE_EXECINFO_H} @@ -124,41 +112,41 @@ /* Define if the neat program is available */ #cmakedefine HAVE_FDP ${HAVE_FDP} +/* Define to 1 if you have the <fenv.h> header file. */ +#cmakedefine HAVE_FENV_H ${HAVE_FENV_H} + +/* Define if libffi is available on this platform. */ +#cmakedefine HAVE_FFI_CALL ${HAVE_FFI_CALL} + +/* Define to 1 if you have the <ffi/ffi.h> header file. */ +#cmakedefine HAVE_FFI_FFI_H ${HAVE_FFI_FFI_H} + +/* Define to 1 if you have the <ffi.h> header file. */ +#cmakedefine HAVE_FFI_H ${HAVE_FFI_H} + /* Set to 1 if the finite function is found in <ieeefp.h> */ #cmakedefine HAVE_FINITE_IN_IEEEFP_H ${HAVE_FINITE_IN_IEEEFP_H} /* Define to 1 if you have the `floorf' function. */ #cmakedefine HAVE_FLOORF ${HAVE_FLOORF} -/* Does not have forward iterator */ -#undef HAVE_FWD_ITERATOR +/* Define to 1 if you have the `fmodf' function. */ +#cmakedefine HAVE_FMODF ${HAVE_FMODF} /* Define to 1 if you have the `getcwd' function. */ -#undef HAVE_GETCWD +#cmakedefine HAVE_GETCWD ${HAVE_GETCWD} /* Define to 1 if you have the `getpagesize' function. */ #cmakedefine HAVE_GETPAGESIZE ${HAVE_GETPAGESIZE} /* Define to 1 if you have the `getrlimit' function. */ -#undef HAVE_GETRLIMIT +#cmakedefine HAVE_GETRLIMIT ${HAVE_GETRLIMIT} /* Define to 1 if you have the `getrusage' function. */ #cmakedefine HAVE_GETRUSAGE ${HAVE_GETRUSAGE} /* Define to 1 if you have the `gettimeofday' function. */ -#undef HAVE_GETTIMEOFDAY - -/* Does not have <hash_map> */ -#undef HAVE_GLOBAL_HASH_MAP - -/* Does not have hash_set in global namespace */ -#undef HAVE_GLOBAL_HASH_SET - -/* Does not have ext/hash_map */ -#undef HAVE_GNU_EXT_HASH_MAP - -/* Does not have hash_set in gnu namespace */ -#undef HAVE_GNU_EXT_HASH_SET +#cmakedefine HAVE_GETTIMEOFDAY ${HAVE_GETTIMEOFDAY} /* Define if the Graphviz program is available */ #undef HAVE_GRAPHVIZ @@ -167,10 +155,10 @@ #cmakedefine HAVE_GV ${HAVE_GV} /* Define to 1 if you have the `index' function. */ -#undef HAVE_INDEX +#cmakedefine HAVE_INDEX ${HAVE_INDEX} /* Define to 1 if the system has the type `int64_t'. */ -#undef HAVE_INT64_T +#cmakedefine HAVE_INT64_T ${HAVE_INT64_T} /* Define to 1 if you have the <inttypes.h> header file. */ #cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H} @@ -191,7 +179,7 @@ #cmakedefine HAVE_ISNAN_IN_MATH_H ${HAVE_ISNAN_IN_MATH_H} /* Define if you have the libdl library or equivalent. */ -#undef HAVE_LIBDL +#cmakedefine HAVE_LIBDL ${HAVE_LIBDL} /* Define to 1 if you have the `imagehlp' library (-limagehlp). */ #cmakedefine HAVE_LIBIMAGEHLP ${HAVE_LIBIMAGEHLP} @@ -211,6 +199,9 @@ /* Define to 1 if you have the <limits.h> header file. */ #cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H} +/* Define if you can use -Wl,-export-dynamic. */ +#define HAVE_LINK_EXPORT_DYNAMIC 1 + /* Define to 1 if you have the <link.h> header file. */ #cmakedefine HAVE_LINK_H ${HAVE_LINK_H} @@ -219,13 +210,13 @@ #undef HAVE_LINK_R /* Define to 1 if you have the `longjmp' function. */ -#undef HAVE_LONGJMP +#cmakedefine HAVE_LONGJMP ${HAVE_LONGJMP} /* Define to 1 if you have the <mach/mach.h> header file. */ -#undef HAVE_MACH_MACH_H +#cmakedefine HAVE_MACH_MACH_H ${HAVE_MACH_MACH_H} /* Define to 1 if you have the <mach-o/dyld.h> header file. */ -#undef HAVE_MACH_O_DYLD_H +#cmakedefine HAVE_MACH_O_DYLD_H ${HAVE_MACH_O_DYLD_H} /* Define if mallinfo() is available on this platform. */ #cmakedefine HAVE_MALLINFO ${HAVE_MALLINFO} @@ -240,10 +231,10 @@ #cmakedefine HAVE_MALLOC_ZONE_STATISTICS ${HAVE_MALLOC_ZONE_STATISTICS} /* Define to 1 if you have the `memcpy' function. */ -#undef HAVE_MEMCPY +#cmakedefine HAVE_MEMCPY ${HAVE_MEMCPY} /* Define to 1 if you have the `memmove' function. */ -#undef HAVE_MEMMOVE +#cmakedefine HAVE_MEMMOVE ${HAVE_MEMMOVE} /* Define to 1 if you have the <memory.h> header file. */ #cmakedefine HAVE_MEMORY_H ${HAVE_MEMORY_H} @@ -267,9 +258,6 @@ /* Define if mmap() can map files into memory */ #undef HAVE_MMAP_FILE -/* define if the compiler implements namespaces */ -#undef HAVE_NAMESPACES - /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ #cmakedefine HAVE_NDIR_H ${HAVE_NDIR_H} @@ -280,7 +268,13 @@ #cmakedefine HAVE_NEATO ${HAVE_NEATO} /* Define to 1 if you have the `opendir' function. */ -#undef HAVE_OPENDIR +#cmakedefine HAVE_OPENDIR ${HAVE_OPENDIR} + +/* Define to 1 if you have the `posix_spawn' function. */ +#cmakedefine HAVE_POSIX_SPAWN ${HAVE_POSIX_SPAWN} + +/* Define to 1 if you have the `powf' function. */ +#cmakedefine HAVE_POWF ${HAVE_POWF} /* Define if libtool can extract symbol lists from object files. */ #undef HAVE_PRELOADED_SYMBOLS @@ -288,7 +282,10 @@ /* Define to have the %a format string */ #undef HAVE_PRINTF_A -/* Have pthread.h */ +/* Have pthread_getspecific */ +#cmakedefine HAVE_PTHREAD_GETSPECIFIC ${HAVE_PTHREAD_GETSPECIFIC} + +/* Define to 1 if you have the <pthread.h> header file. */ #cmakedefine HAVE_PTHREAD_H ${HAVE_PTHREAD_H} /* Have pthread_mutex_lock */ @@ -297,30 +294,27 @@ /* Have pthread_rwlock_init */ #cmakedefine HAVE_PTHREAD_RWLOCK_INIT ${HAVE_PTHREAD_RWLOCK_INIT} -/* Have pthread_getspecific */ -#cmakedefine HAVE_PTHREAD_GETSPECIFIC ${HAVE_PTHREAD_GETSPECIFIC} - /* Define to 1 if srand48/lrand48/drand48 exist in <stdlib.h> */ -#undef HAVE_RAND48 +#cmakedefine HAVE_RAND48 ${HAVE_RAND48} /* Define to 1 if you have the `readdir' function. */ -#undef HAVE_READDIR +#cmakedefine HAVE_READDIR ${HAVE_READDIR} /* Define to 1 if you have the `realpath' function. */ #undef HAVE_REALPATH /* Define to 1 if you have the `rindex' function. */ -#undef HAVE_RINDEX +#cmakedefine HAVE_RINDEX ${HAVE_RINDEX} /* Define to 1 if you have the `rintf' function. */ #undef HAVE_RINTF -/* Define to 1 if you have the `roundf' function. */ -#undef HAVE_ROUNDF - /* Define to 1 if you have the `round' function. */ #cmakedefine HAVE_ROUND ${HAVE_ROUND} +/* Define to 1 if you have the `roundf' function. */ +#undef HAVE_ROUNDF + /* Define to 1 if you have the `sbrk' function. */ #cmakedefine HAVE_SBRK ${HAVE_SBRK} @@ -328,7 +322,7 @@ #cmakedefine HAVE_SETENV ${HAVE_SETENV} /* Define to 1 if you have the `setjmp' function. */ -#undef HAVE_SETJMP +#cmakedefine HAVE_SETJMP ${HAVE_SETJMP} /* Define to 1 if you have the <setjmp.h> header file. */ #cmakedefine HAVE_SETJMP_H ${HAVE_SETJMP_H} @@ -340,13 +334,13 @@ #undef HAVE_SHL_LOAD /* Define to 1 if you have the `siglongjmp' function. */ -#undef HAVE_SIGLONGJMP +#cmakedefine HAVE_SIGLONGJMP ${HAVE_SIGLONGJMP} /* Define to 1 if you have the <signal.h> header file. */ #cmakedefine HAVE_SIGNAL_H ${HAVE_SIGNAL_H} /* Define to 1 if you have the `sigsetjmp' function. */ -#undef HAVE_SIGSETJMP +#cmakedefine HAVE_SIGSETJMP ${HAVE_SIGSETJMP} /* Define to 1 if you have the <stdint.h> header file. */ #cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H} @@ -357,29 +351,20 @@ /* Define to 1 if you have the <stdlib.h> header file. */ #cmakedefine HAVE_STDLIB_H ${HAVE_STDLIB_H} -/* Does not have ext/hash_map> */ -#undef HAVE_STD_EXT_HASH_MAP - -/* Does not have hash_set in std namespace */ -#undef HAVE_STD_EXT_HASH_SET - /* Set to 1 if the std::isinf function is found in <cmath> */ #undef HAVE_STD_ISINF_IN_CMATH /* Set to 1 if the std::isnan function is found in <cmath> */ #undef HAVE_STD_ISNAN_IN_CMATH -/* Does not have std namespace iterator */ -#undef HAVE_STD_ITERATOR - /* Define to 1 if you have the `strchr' function. */ -#undef HAVE_STRCHR +#cmakedefine HAVE_STRCHR ${HAVE_STRCHR} /* Define to 1 if you have the `strcmp' function. */ -#undef HAVE_STRCMP +#cmakedefine HAVE_STRCMP ${HAVE_STRCMP} /* Define to 1 if you have the `strdup' function. */ -#undef HAVE_STRDUP +#cmakedefine HAVE_STRDUP ${HAVE_STRDUP} /* Define to 1 if you have the `strerror' function. */ #cmakedefine HAVE_STRERROR ${HAVE_STRERROR} @@ -387,23 +372,23 @@ /* Define to 1 if you have the `strerror_r' function. */ #cmakedefine HAVE_STRERROR_R ${HAVE_STRERROR_R} -/* Define to 1 if you have the `strerror_s' function. */ -#cmakedefine HAVE_STRERROR_S ${HAVE_STRERROR_S} - /* Define to 1 if you have the <strings.h> header file. */ -#undef HAVE_STRINGS_H +#cmakedefine HAVE_STRINGS_H ${HAVE_STRINGS_H} /* Define to 1 if you have the <string.h> header file. */ #cmakedefine HAVE_STRING_H ${HAVE_STRING_H} /* Define to 1 if you have the `strrchr' function. */ -#undef HAVE_STRRCHR +#cmakedefine HAVE_STRRCHR ${HAVE_STRRCHR} + +/* Define to 1 if you have the `strtof' function. */ +#cmakedefine HAVE_STRTOF ${HAVE_STRTOF} /* Define to 1 if you have the `strtoll' function. */ #cmakedefine HAVE_STRTOLL ${HAVE_STRTOLL} /* Define to 1 if you have the `strtoq' function. */ -#undef HAVE_STRTOQ +#cmakedefine HAVE_STRTOQ ${HAVE_STRTOQ} /* Define to 1 if you have the `sysconf' function. */ #undef HAVE_SYSCONF @@ -440,15 +425,12 @@ /* Define to 1 if you have the <sys/types.h> header file. */ #cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H} +/* Define to 1 if you have the <sys/uio.h> header file. */ +#cmakedefine HAVE_SYS_UIO_H ${HAVE_SYS_UIO_H} + /* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ #cmakedefine HAVE_SYS_WAIT_H ${HAVE_SYS_WAIT_H} -/* Define if the neat program is available */ -#cmakedefine HAVE_TWOPI ${HAVE_TWOPI} - -/* Define to 1 if the system has the type `uint64_t'. */ -#undef HAVE_UINT64_T - /* Define to 1 if you have the <termios.h> header file. */ #cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} @@ -459,17 +441,74 @@ #cmakedefine HAVE_UTIME_H ${HAVE_UTIME_H} /* Define to 1 if the system has the type `u_int64_t'. */ -#undef HAVE_U_INT64_T +#cmakedefine HAVE_U_INT64_T ${HAVE_U_INT64_T} /* Define to 1 if you have the <valgrind/valgrind.h> header file. */ #cmakedefine HAVE_VALGRIND_VALGRIND_H ${HAVE_VALGRIND_VALGRIND_H} -/* Define to 1 if you have the <fenv.h> header file. */ -#cmakedefine HAVE_FENV_H ${HAVE_FENV_H} - /* Define to 1 if you have the <windows.h> header file. */ #cmakedefine HAVE_WINDOWS_H ${HAVE_WINDOWS_H} +/* Define to 1 if you have the `writev' function. */ +#cmakedefine HAVE_WRITEV ${HAVE_WRITEV} + +/* Define if the xdot.py program is available */ +#cmakedefine HAVE_XDOT_PY ${HAVE_XDOT_PY} + +/* Have host's _alloca */ +#cmakedefine HAVE__ALLOCA ${HAVE__ALLOCA} + +/* Have host's __alloca */ +#cmakedefine HAVE___ALLOCA ${HAVE___ALLOCA} + +/* Have host's __ashldi3 */ +#cmakedefine HAVE___ASHLDI3 ${HAVE___ASHLDI3} + +/* Have host's __ashrdi3 */ +#cmakedefine HAVE___ASHRDI3 ${HAVE___ASHRDI3} + +/* Have host's __chkstk */ +#cmakedefine HAVE___CHKSTK ${HAVE___CHKSTK} + +/* Have host's __cmpdi2 */ +#cmakedefine HAVE___CMPDI2 ${HAVE___CMPDI2} + +/* Have host's __divdi3 */ +#cmakedefine HAVE___DIVDI3 ${HAVE___DIVDI3} + +/* Define to 1 if you have the `__dso_handle' function. */ +#undef HAVE___DSO_HANDLE + +/* Have host's __fixdfdi */ +#cmakedefine HAVE___FIXDFDI ${HAVE___FIXDFDI} + +/* Have host's __fixsfdi */ +#cmakedefine HAVE___FIXSFDI ${HAVE___FIXSFDI} + +/* Have host's __floatdidf */ +#cmakedefine HAVE___FLOATDIDF ${HAVE___FLOATDIDF} + +/* Have host's __lshrdi3 */ +#cmakedefine HAVE___LSHRDI3 ${HAVE___LSHRDI3} + +/* Have host's __main */ +#cmakedefine HAVE___MAIN ${HAVE___MAIN} + +/* Have host's __moddi3 */ +#cmakedefine HAVE___MODDI3 ${HAVE___MODDI3} + +/* Have host's __udivdi3 */ +#cmakedefine HAVE___UDIVDI3 ${HAVE___UDIVDI3} + +/* Have host's __umoddi3 */ +#cmakedefine HAVE___UMODDI3 ${HAVE___UMODDI3} + +/* Have host's ___chkstk */ +#cmakedefine HAVE____CHKSTK ${HAVE____CHKSTK} + +/* Linker version detected at compile time. */ +#undef HOST_LINK_VERSION + /* Installation directory for binary executables */ #undef LLVM_BINDIR @@ -479,6 +518,9 @@ /* Installation directory for documentation */ #undef LLVM_DATADIR +/* Installation directory for documentation */ +#undef LLVM_DOCSDIR + /* Installation directory for config files */ #undef LLVM_ETCDIR @@ -500,15 +542,24 @@ /* Build multithreading support into LLVM */ #cmakedefine LLVM_MULTITHREADED ${LLVM_MULTITHREADED} +/* LLVM architecture name for the native architecture, if available */ +#cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH} + +/* LLVM name for the native AsmPrinter init function, if available */ +#cmakedefine LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter + +/* LLVM name for the native Target init function, if available */ +#cmakedefine LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target + +/* LLVM name for the native TargetInfo init function, if available */ +#cmakedefine LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo + /* Define if this is Unixish platform */ #cmakedefine LLVM_ON_UNIX ${LLVM_ON_UNIX} /* Define if this is Win32ish platform */ #cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32} -/* Added by Kevin -- Maximum path length */ -#cmakedefine MAXPATHLEN ${MAXPATHLEN} - /* Define to path to circo program if found or 'echo circo' otherwise */ #cmakedefine LLVM_PATH_CIRCO "${LLVM_PATH_CIRCO}" @@ -533,6 +584,9 @@ /* Define to path to twopi program if found or 'echo twopi' otherwise */ #cmakedefine LLVM_PATH_TWOPI "${LLVM_PATH_TWOPI}" +/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */ +#cmakedefine LLVM_PATH_XDOT_PY "${LLVM_PATH_XDOT_PY}" + /* Installation prefix directory */ #cmakedefine LLVM_PREFIX "${LLVM_PREFIX}" @@ -578,6 +632,9 @@ /* Define as the return type of signal handlers (`int' or `void'). */ #cmakedefine RETSIGTYPE ${RETSIGTYPE} +/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */ +#undef STAT_MACROS_BROKEN + /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. @@ -598,28 +655,37 @@ /* Define to 1 if your <sys/time.h> declares `struct tm'. */ #undef TM_IN_SYS_TIME +/* Define if we have the oprofile JIT-support library */ +#undef USE_OPROFILE + /* Define if use udis86 library */ #undef USE_UDIS86 -/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a - `char[]'. */ -#undef YYTEXT_POINTER - /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to a type to use for `error_t' if it is not otherwise available. */ #cmakedefine error_t ${error_t} -/* Define to a type to use for `mode_t' if it is not otherwise available. */ -#cmakedefine mode_t ${mode_t} - /* Define to `int' if <sys/types.h> does not define. */ #undef pid_t /* Define to `unsigned int' if <sys/types.h> does not define. */ #undef size_t +/* Define if the neat program is available */ +#cmakedefine HAVE_TWOPI ${HAVE_TWOPI} + +/* Define to 1 if the system has the type `uint64_t'. */ +#cmakedefine HAVE_UINT64_T ${HAVE_UINT64_T} + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#undef YYTEXT_POINTER + +/* Define to a type to use for `mode_t' if it is not otherwise available. */ +#cmakedefine mode_t ${mode_t} + /* Define to a function replacing strtoll */ #cmakedefine strtoll ${strtoll} @@ -632,16 +698,40 @@ /* Define to a function implementing strdup */ #cmakedefine strdup ${strdup} -/* LLVM architecture name for the native architecture, if available */ -#cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH} - -/* LLVM name for the native Target init function, if available */ -#cmakedefine LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target - -/* LLVM name for the native TargetInfo init function, if available */ -#cmakedefine LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo - -/* LLVM name for the native AsmPrinter init function, if available */ -#cmakedefine LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter +/* Define to 1 if you have the `_chsize_s' function. */ +#cmakedefine HAVE__CHSIZE_S ${HAVE__CHSIZE_S} + +/* define if the compiler implements namespaces */ +#undef HAVE_NAMESPACES + +/* Does not have std namespace iterator */ +#undef HAVE_STD_ITERATOR + +/* Does not have forward iterator */ +#undef HAVE_FWD_ITERATOR + +/* Does not have bi-directional iterator */ +#undef HAVE_BI_ITERATOR + +/* Does not have <hash_map> */ +#undef HAVE_GLOBAL_HASH_MAP + +/* Does not have hash_set in global namespace */ +#undef HAVE_GLOBAL_HASH_SET + +/* Does not have ext/hash_map */ +#undef HAVE_GNU_EXT_HASH_MAP + +/* Does not have hash_set in gnu namespace */ +#undef HAVE_GNU_EXT_HASH_SET + +/* Does not have ext/hash_map> */ +#undef HAVE_STD_EXT_HASH_MAP + +/* Does not have hash_set in std namespace */ +#undef HAVE_STD_EXT_HASH_SET + +/* Added by Kevin -- Maximum path length */ +#cmakedefine MAXPATHLEN ${MAXPATHLEN} #endif diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 1cc0c7bc76..14c44b4b1e 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -72,9 +72,16 @@ /* Define to 1 if you have the <CrashReporterClient.h> header file. */ #undef HAVE_CRASHREPORTERCLIENT_H +/* Define if __crashreporter_info__ exists. */ +#undef HAVE_CRASHREPORTER_INFO + /* Define to 1 if you have the <ctype.h> header file. */ #undef HAVE_CTYPE_H +/* Define to 1 if you have the declaration of `strerror_s', and to 0 if you + don't. */ +#undef HAVE_DECL_STRERROR_S + /* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H @@ -381,9 +388,6 @@ /* Define to 1 if you have the `strerror_r' function. */ #undef HAVE_STRERROR_R -/* Define to 1 if you have the `strerror_s' function. */ -#undef HAVE_STRERROR_S - /* Define to 1 if you have the <strings.h> header file. */ #undef HAVE_STRINGS_H @@ -437,6 +441,9 @@ /* Define to 1 if you have the <sys/types.h> header file. */ #undef HAVE_SYS_TYPES_H +/* Define to 1 if you have the <sys/uio.h> header file. */ +#undef HAVE_SYS_UIO_H + /* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H @@ -464,12 +471,63 @@ /* Define to 1 if you have the <windows.h> header file. */ #undef HAVE_WINDOWS_H +/* Define to 1 if you have the `writev' function. */ +#undef HAVE_WRITEV + /* Define if the xdot.py program is available */ #undef HAVE_XDOT_PY +/* Have host's _alloca */ +#undef HAVE__ALLOCA + +/* Have host's __alloca */ +#undef HAVE___ALLOCA + +/* Have host's __ashldi3 */ +#undef HAVE___ASHLDI3 + +/* Have host's __ashrdi3 */ +#undef HAVE___ASHRDI3 + +/* Have host's __chkstk */ +#undef HAVE___CHKSTK + +/* Have host's __cmpdi2 */ +#undef HAVE___CMPDI2 + +/* Have host's __divdi3 */ +#undef HAVE___DIVDI3 + /* Define to 1 if you have the `__dso_handle' function. */ #undef HAVE___DSO_HANDLE +/* Have host's __fixdfdi */ +#undef HAVE___FIXDFDI + +/* Have host's __fixsfdi */ +#undef HAVE___FIXSFDI + +/* Have host's __floatdidf */ +#undef HAVE___FLOATDIDF + +/* Have host's __lshrdi3 */ +#undef HAVE___LSHRDI3 + +/* Have host's __main */ +#undef HAVE___MAIN + +/* Have host's __moddi3 */ +#undef HAVE___MODDI3 + +/* Have host's __udivdi3 */ +#undef HAVE___UDIVDI3 + +/* Have host's __umoddi3 */ +#undef HAVE___UMODDI3 + +/* Have host's ___chkstk */ +#undef HAVE____CHKSTK + /* Linker version detected at compile time. */ #undef HOST_LINK_VERSION diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index 8469bcc606..33a40350d5 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -47,7 +47,7 @@ #cmakedefine LLVM_MANDIR "${LLVM_MANDIR}" /* Build multithreading support into LLVM */ -#cmakedefine LLVM_MULTITHREADED +#cmakedefine LLVM_MULTITHREADED ${LLVM_MULTITHREADED} /* LLVM architecture name for the native architecture, if available */ #cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH} @@ -62,10 +62,10 @@ #cmakedefine LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter /* Define if this is Unixish platform */ -#cmakedefine LLVM_ON_UNIX +#cmakedefine LLVM_ON_UNIX ${LLVM_ON_UNIX} /* Define if this is Win32ish platform */ -#cmakedefine LLVM_ON_WIN32 +#cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32} /* Define to path to circo program if found or 'echo circo' otherwise */ #cmakedefine LLVM_PATH_CIRCO "${LLVM_PATH_CIRCO}" @@ -91,6 +91,9 @@ /* Define to path to twopi program if found or 'echo twopi' otherwise */ #cmakedefine LLVM_PATH_TWOPI "${LLVM_PATH_TWOPI}" +/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */ +#cmakedefine LLVM_PATH_XDOT_PY "${LLVM_PATH_XDOT.PY}" + /* Installation prefix directory */ #cmakedefine LLVM_PREFIX "${LLVM_PREFIX}" diff --git a/include/llvm/Constant.h b/include/llvm/Constant.h index defe474fb5..38045fc0c1 100644 --- a/include/llvm/Constant.h +++ b/include/llvm/Constant.h @@ -141,16 +141,22 @@ public: assert(0 && "Constants that do not have operands cannot be using 'From'!"); } - static Constant* getNullValue(const Type* Ty); + static Constant *getNullValue(const Type* Ty); /// @returns the value for an integer constant of the given type that has all /// its bits set to true. /// @brief Get the all ones value - static Constant* getAllOnesValue(const Type* Ty); + static Constant *getAllOnesValue(const Type* Ty); /// getIntegerValue - Return the value for an integer or pointer constant, /// or a vector thereof, with the given scalar value. - static Constant* getIntegerValue(const Type* Ty, const APInt &V); + static Constant *getIntegerValue(const Type* Ty, const APInt &V); + + /// removeDeadConstantUsers - If there are any dead constant users dangling + /// off of this constant, remove them. This method is useful for clients + /// that want to check to see if a global is unused, but don't want to deal + /// with potentially dead constants hanging off of the globals. + void removeDeadConstantUsers() const; }; } // End llvm namespace diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index a75aaf72a3..c12b33fae7 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -25,7 +25,7 @@ #include "llvm/OperandTraits.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APFloat.h" -#include <vector> +#include "llvm/ADT/ArrayRef.h" namespace llvm { @@ -39,8 +39,6 @@ template<class ConstantClass, class TypeClass, class ValType> struct ConstantCreator; template<class ConstantClass, class TypeClass> struct ConvertConstantType; -template<typename T, unsigned N> -class SmallVector; //===----------------------------------------------------------------------===// /// This is the shared class of boolean and integer constants. This class @@ -59,6 +57,8 @@ protected: public: static ConstantInt *getTrue(LLVMContext &Context); static ConstantInt *getFalse(LLVMContext &Context); + static Constant *getTrue(const Type *Ty); + static Constant *getFalse(const Type *Ty); /// If Ty is a vector type, return a Constant with a splat of the given /// value. Otherwise return a ConstantInt for the given value. @@ -266,8 +266,8 @@ public: inline const APFloat& getValueAPF() const { return Val; } /// isNullValue - Return true if this is the value that would be returned by - /// getNullValue. Don't depend on == for doubles to tell us it's zero, it - /// considers -0.0 to be null as well as 0.0. :( + /// getNullValue. For ConstantFP, this is +0.0, but not -0.0. To handle the + /// two the same, use isZero(). virtual bool isNullValue() const; /// isNegativeZeroValue - Return true if the value is what would be returned @@ -405,7 +405,8 @@ public: }; template <> -struct OperandTraits<ConstantArray> : public VariadicOperandTraits<> { +struct OperandTraits<ConstantArray> : + public VariadicOperandTraits<ConstantArray> { }; DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantArray, Constant) @@ -426,6 +427,8 @@ public: const std::vector<Constant*> &V, bool Packed); static Constant *get(LLVMContext &Context, Constant *const *Vals, unsigned NumVals, bool Packed); + static Constant *get(LLVMContext &Context, bool Packed, + Constant * Val, ...) END_WITH_NULL; /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -454,7 +457,8 @@ public: }; template <> -struct OperandTraits<ConstantStruct> : public VariadicOperandTraits<> { +struct OperandTraits<ConstantStruct> : + public VariadicOperandTraits<ConstantStruct> { }; DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantStruct, Constant) @@ -471,9 +475,9 @@ protected: ConstantVector(const VectorType *T, const std::vector<Constant*> &Val); public: // ConstantVector accessors + static Constant *get(ArrayRef<Constant*> V); + // FIXME: Eliminate this constructor form. static Constant *get(const VectorType *T, const std::vector<Constant*> &V); - static Constant *get(const std::vector<Constant*> &V); - static Constant *get(Constant *const *Vals, unsigned NumVals); /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -498,7 +502,7 @@ public: /// getSplatValue - If this is a splat constant, meaning that all of the /// elements have the same value, return that value. Otherwise return NULL. - Constant *getSplatValue(); + Constant *getSplatValue() const; virtual void destroyConstant(); virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); @@ -511,7 +515,8 @@ public: }; template <> -struct OperandTraits<ConstantVector> : public VariadicOperandTraits<> { +struct OperandTraits<ConstantVector> : + public VariadicOperandTraits<ConstantVector> { }; DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantVector, Constant) @@ -592,11 +597,13 @@ public: }; template <> -struct OperandTraits<BlockAddress> : public FixedNumOperandTraits<2> { +struct OperandTraits<BlockAddress> : + public FixedNumOperandTraits<BlockAddress, 2> { }; DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(BlockAddress, Value) + //===----------------------------------------------------------------------===// /// ConstantExpr - a constant value that is initialized with an expression using /// other constant values. @@ -625,11 +632,10 @@ protected: Constant *C2); static Constant *getSelectTy(const Type *Ty, Constant *C1, Constant *C2, Constant *C3); + template<typename IndexTy> static Constant *getGetElementPtrTy(const Type *Ty, Constant *C, - Value* const *Idxs, unsigned NumIdxs); - static Constant *getInBoundsGetElementPtrTy(const Type *Ty, Constant *C, - Value* const *Idxs, - unsigned NumIdxs); + IndexTy const *Idxs, unsigned NumIdxs, + bool InBounds); static Constant *getExtractElementTy(const Type *Ty, Constant *Val, Constant *Idx); static Constant *getInsertElementTy(const Type *Ty, Constant *Val, @@ -641,6 +647,10 @@ protected: static Constant *getInsertValueTy(const Type *Ty, Constant *Agg, Constant *Val, const unsigned *Idxs, unsigned NumIdxs); + template<typename IndexTy> + static Constant *getGetElementPtrImpl(Constant *C, + IndexTy const *IdxList, + unsigned NumIdx, bool InBounds); public: // Static methods to construct a ConstantExpr of different kinds. Note that @@ -650,35 +660,38 @@ public: /// getAlignOf constant expr - computes the alignment of a type in a target /// independent way (Note: the return type is an i64). - static Constant *getAlignOf(const Type* Ty); + static Constant *getAlignOf(const Type *Ty); /// getSizeOf constant expr - computes the (alloc) size of a type (in /// address-units, not bits) in a target independent way (Note: the return /// type is an i64). /// - static Constant *getSizeOf(const Type* Ty); + static Constant *getSizeOf(const Type *Ty); /// getOffsetOf constant expr - computes the offset of a struct field in a /// target independent way (Note: the return type is an i64). /// - static Constant *getOffsetOf(const StructType* STy, unsigned FieldNo); + static Constant *getOffsetOf(const StructType *STy, unsigned FieldNo); /// getOffsetOf constant expr - This is a generalized form of getOffsetOf, /// which supports any aggregate type, and any Constant index. /// - static Constant *getOffsetOf(const Type* Ty, Constant *FieldNo); + static Constant *getOffsetOf(const Type *Ty, Constant *FieldNo); - static Constant *getNeg(Constant *C); + static Constant *getNeg(Constant *C, bool HasNUW = false, bool HasNSW =false); static Constant *getFNeg(Constant *C); static Constant *getNot(Constant *C); - static Constant *getAdd(Constant *C1, Constant *C2); + static Constant *getAdd(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); static Constant *getFAdd(Constant *C1, Constant *C2); - static Constant *getSub(Constant *C1, Constant *C2); + static Constant *getSub(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); static Constant *getFSub(Constant *C1, Constant *C2); - static Constant *getMul(Constant *C1, Constant *C2); + static Constant *getMul(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); static Constant *getFMul(Constant *C1, Constant *C2); - static Constant *getUDiv(Constant *C1, Constant *C2); - static Constant *getSDiv(Constant *C1, Constant *C2); + static Constant *getUDiv(Constant *C1, Constant *C2, bool isExact = false); + static Constant *getSDiv(Constant *C1, Constant *C2, bool isExact = false); static Constant *getFDiv(Constant *C1, Constant *C2); static Constant *getURem(Constant *C1, Constant *C2); static Constant *getSRem(Constant *C1, Constant *C2); @@ -686,9 +699,10 @@ public: static Constant *getAnd(Constant *C1, Constant *C2); static Constant *getOr(Constant *C1, Constant *C2); static Constant *getXor(Constant *C1, Constant *C2); - static Constant *getShl(Constant *C1, Constant *C2); - static Constant *getLShr(Constant *C1, Constant *C2); - static Constant *getAShr(Constant *C1, Constant *C2); + static Constant *getShl(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); + static Constant *getLShr(Constant *C1, Constant *C2, bool isExact = false); + static Constant *getAShr(Constant *C1, Constant *C2, bool isExact = false); static Constant *getTrunc (Constant *C, const Type *Ty); static Constant *getSExt (Constant *C, const Type *Ty); static Constant *getZExt (Constant *C, const Type *Ty); @@ -702,15 +716,44 @@ public: static Constant *getIntToPtr(Constant *C, const Type *Ty); static Constant *getBitCast (Constant *C, const Type *Ty); - static Constant *getNSWNeg(Constant *C); - static Constant *getNUWNeg(Constant *C); - static Constant *getNSWAdd(Constant *C1, Constant *C2); - static Constant *getNUWAdd(Constant *C1, Constant *C2); - static Constant *getNSWSub(Constant *C1, Constant *C2); - static Constant *getNUWSub(Constant *C1, Constant *C2); - static Constant *getNSWMul(Constant *C1, Constant *C2); - static Constant *getNUWMul(Constant *C1, Constant *C2); - static Constant *getExactSDiv(Constant *C1, Constant *C2); + static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); } + static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); } + static Constant *getNSWAdd(Constant *C1, Constant *C2) { + return getAdd(C1, C2, false, true); + } + static Constant *getNUWAdd(Constant *C1, Constant *C2) { + return getAdd(C1, C2, true, false); + } + static Constant *getNSWSub(Constant *C1, Constant *C2) { + return getSub(C1, C2, false, true); + } + static Constant *getNUWSub(Constant *C1, Constant *C2) { + return getSub(C1, C2, true, false); + } + static Constant *getNSWMul(Constant *C1, Constant *C2) { + return getMul(C1, C2, false, true); + } + static Constant *getNUWMul(Constant *C1, Constant *C2) { + return getMul(C1, C2, true, false); + } + static Constant *getNSWShl(Constant *C1, Constant *C2) { + return getShl(C1, C2, false, true); + } + static Constant *getNUWShl(Constant *C1, Constant *C2) { + return getShl(C1, C2, true, false); + } + static Constant *getExactSDiv(Constant *C1, Constant *C2) { + return getSDiv(C1, C2, true); + } + static Constant *getExactUDiv(Constant *C1, Constant *C2) { + return getUDiv(C1, C2, true); + } + static Constant *getExactAShr(Constant *C1, Constant *C2) { + return getAShr(C1, C2, true); + } + static Constant *getExactLShr(Constant *C1, Constant *C2) { + return getLShr(C1, C2, true); + } /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -802,18 +845,24 @@ public: /// all elements must be Constant's. /// static Constant *getGetElementPtr(Constant *C, - Constant *const *IdxList, unsigned NumIdx); + Constant *const *IdxList, unsigned NumIdx, + bool InBounds = false); static Constant *getGetElementPtr(Constant *C, - Value* const *IdxList, unsigned NumIdx); + Value *const *IdxList, unsigned NumIdx, + bool InBounds = false); /// Create an "inbounds" getelementptr. See the documentation for the /// "inbounds" flag in LangRef.html for details. static Constant *getInBoundsGetElementPtr(Constant *C, Constant *const *IdxList, - unsigned NumIdx); + unsigned NumIdx) { + return getGetElementPtr(C, IdxList, NumIdx, true); + } static Constant *getInBoundsGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx); + unsigned NumIdx) { + return getGetElementPtr(C, IdxList, NumIdx, true); + } static Constant *getExtractElement(Constant *Vec, Constant *Idx); static Constant *getInsertElement(Constant *Vec, Constant *Elt,Constant *Idx); @@ -871,7 +920,8 @@ private: }; template <> -struct OperandTraits<ConstantExpr> : public VariadicOperandTraits<1> { +struct OperandTraits<ConstantExpr> : + public VariadicOperandTraits<ConstantExpr, 1> { }; DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantExpr, Constant) diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h index 721c603314..56d1e3e237 100644 --- a/include/llvm/DerivedTypes.h +++ b/include/llvm/DerivedTypes.h @@ -19,7 +19,7 @@ #define LLVM_DERIVED_TYPES_H #include "llvm/Type.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 0e51271c6f..dcc9743d69 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -21,8 +21,9 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/ValueMap.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/Support/ValueHandle.h" -#include "llvm/System/Mutex.h" +#include "llvm/Support/Mutex.h" #include "llvm/Target/TargetMachine.h" namespace llvm { @@ -126,8 +127,8 @@ protected: virtual char *getMemoryForGV(const GlobalVariable *GV); // To avoid having libexecutionengine depend on the JIT and interpreter - // libraries, the JIT and Interpreter set these functions to ctor pointers at - // startup time if they are linked in. + // libraries, the execution engine implementations set these functions to ctor + // pointers at startup time if they are linked in. static ExecutionEngine *(*JITCtor)( Module *M, std::string *ErrorStr, @@ -138,6 +139,16 @@ protected: StringRef MArch, StringRef MCPU, const SmallVectorImpl<std::string>& MAttrs); + static ExecutionEngine *(*MCJITCtor)( + Module *M, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl<std::string>& MAttrs); static ExecutionEngine *(*InterpCtor)(Module *M, std::string *ErrorStr); @@ -151,7 +162,9 @@ protected: typedef void (*EERegisterFn)(void*); EERegisterFn ExceptionTableRegister; EERegisterFn ExceptionTableDeregister; - std::vector<void*> AllExceptionTables; + /// This maps functions to their exception tables frames. + DenseMap<const Function*, void*> AllExceptionTables; + public: /// lock - This lock protects the ExecutionEngine, JIT, JITResolver and @@ -400,10 +413,21 @@ public: /// RegisterTable - Registers the given pointer as an exception table. It /// uses the ExceptionTableRegister function. - void RegisterTable(void* res) { + void RegisterTable(const Function *fn, void* res) { if (ExceptionTableRegister) { ExceptionTableRegister(res); - AllExceptionTables.push_back(res); + AllExceptionTables[fn] = res; + } + } + + /// DeregisterTable - Deregisters the exception frame previously registered for the given function. + void DeregisterTable(const Function *Fn) { + if (ExceptionTableDeregister) { + DenseMap<const Function*, void*>::iterator frame = AllExceptionTables.find(Fn); + if(frame != AllExceptionTables.end()) { + ExceptionTableDeregister(frame->second); + AllExceptionTables.erase(frame); + } } } @@ -447,6 +471,7 @@ private: std::string MArch; std::string MCPU; SmallVector<std::string, 4> MAttrs; + bool UseMCJIT; /// InitEngine - Does the common initialization of default options. void InitEngine() { @@ -456,6 +481,7 @@ private: JMM = NULL; AllocateGVsWithCode = false; CMModel = CodeModel::Default; + UseMCJIT = false; } public: @@ -526,6 +552,12 @@ public: return *this; } + /// setUseMCJIT - Set whether the MC-JIT implementation should be used + /// (experimental). + void setUseMCJIT(bool Value) { + UseMCJIT = Value; + } + /// setMAttrs - Set cpu-specific attributes. template<typename StringSequence> EngineBuilder &setMAttrs(const StringSequence &mattrs) { diff --git a/include/llvm/ExecutionEngine/GenericValue.h b/include/llvm/ExecutionEngine/GenericValue.h index 1301320c14..a2fed98c15 100644 --- a/include/llvm/ExecutionEngine/GenericValue.h +++ b/include/llvm/ExecutionEngine/GenericValue.h @@ -16,7 +16,7 @@ #define GENERIC_VALUE_H #include "llvm/ADT/APInt.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h index 1c060793d6..abc063b070 100644 --- a/include/llvm/ExecutionEngine/JITEventListener.h +++ b/include/llvm/ExecutionEngine/JITEventListener.h @@ -15,7 +15,7 @@ #ifndef LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H #define LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/DebugLoc.h" #include <vector> diff --git a/include/llvm/ExecutionEngine/JITMemoryManager.h b/include/llvm/ExecutionEngine/JITMemoryManager.h index 78a77ecd32..3841418016 100644 --- a/include/llvm/ExecutionEngine/JITMemoryManager.h +++ b/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -10,7 +10,7 @@ #ifndef LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H #define LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> namespace llvm { diff --git a/include/llvm/ExecutionEngine/MCJIT.h b/include/llvm/ExecutionEngine/MCJIT.h new file mode 100644 index 0000000000..f956a5029b --- /dev/null +++ b/include/llvm/ExecutionEngine/MCJIT.h @@ -0,0 +1,38 @@ +//===-- MCJIT.h - MC-Based Just-In-Time Execution Engine --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file forces the MCJIT to link in on certain operating systems. +// (Windows). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_MCJIT_H +#define LLVM_EXECUTION_ENGINE_MCJIT_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include <cstdlib> + +extern "C" void LLVMLinkInMCJIT(); + +namespace { + struct ForceMCJITLinking { + ForceMCJITLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + LLVMLinkInMCJIT(); + } + } ForceMCJITLinking; +} + +#endif diff --git a/include/llvm/GlobalAlias.h b/include/llvm/GlobalAlias.h index 9867c518c8..f4af5b1202 100644 --- a/include/llvm/GlobalAlias.h +++ b/include/llvm/GlobalAlias.h @@ -89,7 +89,8 @@ public: }; template <> -struct OperandTraits<GlobalAlias> : public FixedNumOperandTraits<1> { +struct OperandTraits<GlobalAlias> : + public FixedNumOperandTraits<GlobalAlias, 1> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Value) diff --git a/include/llvm/GlobalValue.h b/include/llvm/GlobalValue.h index 62e84f8335..b184b8e449 100644 --- a/include/llvm/GlobalValue.h +++ b/include/llvm/GlobalValue.h @@ -60,7 +60,8 @@ protected: GlobalValue(const Type *ty, ValueTy vty, Use *Ops, unsigned NumOps, LinkageTypes linkage, const Twine &Name) : Constant(ty, vty, Ops, NumOps), Parent(0), - Linkage(linkage), Visibility(DefaultVisibility), Alignment(0) { + Linkage(linkage), Visibility(DefaultVisibility), Alignment(0), + UnnamedAddr(0) { setName(Name); } @@ -70,6 +71,7 @@ protected: LinkageTypes Linkage : 5; // The linkage of this global unsigned Visibility : 2; // The visibility style of this global unsigned Alignment : 16; // Alignment of this symbol, must be power of two + unsigned UnnamedAddr : 1; // This value's address is not significant std::string Section; // Section to emit this into, empty mean default public: ~GlobalValue() { @@ -81,6 +83,9 @@ public: } void setAlignment(unsigned Align); + bool hasUnnamedAddr() const { return UnnamedAddr; } + void setUnnamedAddr(bool Val) { UnnamedAddr = Val; } + VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); } bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; } bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; } @@ -173,7 +178,9 @@ public: } /// isWeakForLinker - Whether the definition of this global may be replaced at - /// link time. + /// link time. NB: Using this method outside of the code generators is almost + /// always a mistake: when working at the IR level use mayBeOverridden instead + /// as it knows about ODR semantics. static bool isWeakForLinker(LinkageTypes Linkage) { return Linkage == AvailableExternallyLinkage || Linkage == WeakAnyLinkage || @@ -275,12 +282,6 @@ public: inline Module *getParent() { return Parent; } inline const Module *getParent() const { return Parent; } - /// removeDeadConstantUsers - If there are any dead constant users dangling - /// off of this global value, remove them. This method is useful for clients - /// that want to check to see if a global is unused, but don't want to deal - /// with potentially dead constants hanging off of the globals. - void removeDeadConstantUsers() const; - // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const GlobalValue *) { return true; } static inline bool classof(const Value *V) { diff --git a/include/llvm/GlobalVariable.h b/include/llvm/GlobalVariable.h index 597583b2ce..1769c665d0 100644 --- a/include/llvm/GlobalVariable.h +++ b/include/llvm/GlobalVariable.h @@ -169,7 +169,8 @@ public: }; template <> -struct OperandTraits<GlobalVariable> : public OptionalOperandTraits<> { +struct OperandTraits<GlobalVariable> : + public OptionalOperandTraits<GlobalVariable> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalVariable, Value) diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 50443e2f3f..2758b299ec 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -19,19 +19,19 @@ namespace llvm { class PassRegistry; -/// initializeCore - Initialize all passes linked into the +/// initializeCore - Initialize all passes linked into the /// TransformUtils library. void initializeCore(PassRegistry&); -/// initializeTransformUtils - Initialize all passes linked into the +/// initializeTransformUtils - Initialize all passes linked into the /// TransformUtils library. void initializeTransformUtils(PassRegistry&); -/// initializeScalarOpts - Initialize all passes linked into the +/// initializeScalarOpts - Initialize all passes linked into the /// ScalarOpts library. void initializeScalarOpts(PassRegistry&); -/// initializeInstCombine - Initialize all passes linked into the +/// initializeInstCombine - Initialize all passes linked into the /// ScalarOpts library. void initializeInstCombine(PassRegistry&); @@ -91,11 +91,14 @@ void initializeDomPrinterPass(PassRegistry&); void initializeDomViewerPass(PassRegistry&); void initializeDominanceFrontierPass(PassRegistry&); void initializeDominatorTreePass(PassRegistry&); +void initializeEdgeBundlesPass(PassRegistry&); void initializeEdgeProfilerPass(PassRegistry&); +void initializePathProfilerPass(PassRegistry&); +void initializeEarlyCSEPass(PassRegistry&); +void initializeExpandISelPseudosPass(PassRegistry&); void initializeFindUsedTypesPass(PassRegistry&); void initializeFunctionAttrsPass(PassRegistry&); void initializeGCModuleInfoPass(PassRegistry&); -void initializeGEPSplitterPass(PassRegistry&); void initializeGVNPass(PassRegistry&); void initializeGlobalDCEPass(PassRegistry&); void initializeGlobalOptPass(PassRegistry&); @@ -116,21 +119,24 @@ void initializeLICMPass(PassRegistry&); void initializeLazyValueInfoPass(PassRegistry&); void initializeLibCallAliasAnalysisPass(PassRegistry&); void initializeLintPass(PassRegistry&); +void initializeLiveDebugVariablesPass(PassRegistry&); void initializeLiveIntervalsPass(PassRegistry&); void initializeLiveStacksPass(PassRegistry&); -void initializeLiveValuesPass(PassRegistry&); void initializeLiveVariablesPass(PassRegistry&); void initializeLoaderPassPass(PassRegistry&); +void initializePathProfileLoaderPassPass(PassRegistry&); void initializeLoopDeletionPass(PassRegistry&); void initializeLoopDependenceAnalysisPass(PassRegistry&); void initializeLoopExtractorPass(PassRegistry&); void initializeLoopInfoPass(PassRegistry&); +void initializeLoopInstSimplifyPass(PassRegistry&); void initializeLoopRotatePass(PassRegistry&); void initializeLoopSimplifyPass(PassRegistry&); void initializeLoopSplitterPass(PassRegistry&); void initializeLoopStrengthReducePass(PassRegistry&); void initializeLoopUnrollPass(PassRegistry&); void initializeLoopUnswitchPass(PassRegistry&); +void initializeLoopIdiomRecognizePass(PassRegistry&); void initializeLowerAtomicPass(PassRegistry&); void initializeLowerIntrinsicsPass(PassRegistry&); void initializeLowerInvokePass(PassRegistry&); @@ -140,6 +146,7 @@ void initializeMachineCSEPass(PassRegistry&); void initializeMachineDominatorTreePass(PassRegistry&); void initializeMachineLICMPass(PassRegistry&); void initializeMachineLoopInfoPass(PassRegistry&); +void initializeMachineLoopRangesPass(PassRegistry&); void initializeMachineModuleInfoPass(PassRegistry&); void initializeMachineSinkingPass(PassRegistry&); void initializeMachineVerifierPassPass(PassRegistry&); @@ -150,11 +157,11 @@ void initializeMergeFunctionsPass(PassRegistry&); void initializeModuleDebugInfoPrinterPass(PassRegistry&); void initializeNoAAPass(PassRegistry&); void initializeNoProfileInfoPass(PassRegistry&); +void initializeNoPathProfileInfoPass(PassRegistry&); void initializeOptimalEdgeProfilerPass(PassRegistry&); void initializeOptimizePHIsPass(PassRegistry&); void initializePEIPass(PassRegistry&); void initializePHIEliminationPass(PassRegistry&); -void initializePartSpecPass(PassRegistry&); void initializePartialInlinerPass(PassRegistry&); void initializePeepholeOptimizerPass(PassRegistry&); void initializePostDomOnlyPrinterPass(PassRegistry&); @@ -171,6 +178,8 @@ void initializePrintModulePassPass(PassRegistry&); void initializeProcessImplicitDefsPass(PassRegistry&); void initializeProfileEstimatorPassPass(PassRegistry&); void initializeProfileInfoAnalysisGroup(PassRegistry&); +void initializePathProfileInfoAnalysisGroup(PassRegistry&); +void initializePathProfileVerifierPass(PassRegistry&); void initializeProfileVerifierPassPass(PassRegistry&); void initializePromotePassPass(PassRegistry&); void initializePruneEHPass(PassRegistry&); @@ -186,16 +195,17 @@ void initializeRegisterCoalescerAnalysisGroup(PassRegistry&); void initializeRenderMachineFunctionPass(PassRegistry&); void initializeSCCPPass(PassRegistry&); void initializeSRETPromotionPass(PassRegistry&); -void initializeSROAPass(PassRegistry&); +void initializeSROA_DTPass(PassRegistry&); +void initializeSROA_SSAUpPass(PassRegistry&); void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); void initializeScalarEvolutionPass(PassRegistry&); void initializeSimpleInlinerPass(PassRegistry&); void initializeSimpleRegisterCoalescingPass(PassRegistry&); -void initializeSimplifyHalfPowrLibCallsPass(PassRegistry&); void initializeSimplifyLibCallsPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); void initializeSinkingPass(PassRegistry&); void initializeSlotIndexesPass(PassRegistry&); +void initializeSpillPlacementPass(PassRegistry&); void initializeStackProtectorPass(PassRegistry&); void initializeStackSlotColoringPass(PassRegistry&); void initializeStripDeadDebugInfoPass(PassRegistry&); @@ -207,6 +217,7 @@ void initializeStrongPHIEliminationPass(PassRegistry&); void initializeTailCallElimPass(PassRegistry&); void initializeTailDupPass(PassRegistry&); void initializeTargetDataPass(PassRegistry&); +void initializeTargetLibraryInfoPass(PassRegistry&); void initializeTwoAddressInstructionPassPass(PassRegistry&); void initializeTypeBasedAliasAnalysisPass(PassRegistry&); void initializeUnifyFunctionExitNodesPass(PassRegistry&); @@ -214,6 +225,7 @@ void initializeUnreachableBlockElimPass(PassRegistry&); void initializeUnreachableMachineBlockElimPass(PassRegistry&); void initializeVerifierPass(PassRegistry&); void initializeVirtRegMapPass(PassRegistry&); +void initializeInstSimplifierPass(PassRegistry&); } diff --git a/include/llvm/InlineAsm.h b/include/llvm/InlineAsm.h index 4ca012e974..ed8f0f7f61 100644 --- a/include/llvm/InlineAsm.h +++ b/include/llvm/InlineAsm.h @@ -190,8 +190,15 @@ public: Op_InputChain = 0, Op_AsmString = 1, Op_MDNode = 2, - Op_IsAlignStack = 3, + Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack Op_FirstOperand = 4, + + MIOp_AsmString = 0, + MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack + MIOp_FirstOperand = 2, + + Extra_HasSideEffects = 1, + Extra_IsAlignStack = 2, Kind_RegUse = 1, Kind_RegDef = 2, diff --git a/include/llvm/InstrTypes.h b/include/llvm/InstrTypes.h index 6715416afa..a166956e1a 100644 --- a/include/llvm/InstrTypes.h +++ b/include/llvm/InstrTypes.h @@ -128,7 +128,8 @@ public: }; template <> -struct OperandTraits<UnaryInstruction> : public FixedNumOperandTraits<1> { +struct OperandTraits<UnaryInstruction> : + public FixedNumOperandTraits<UnaryInstruction, 1> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value) @@ -193,154 +194,93 @@ public: } #include "llvm/Instruction.def" - - /// CreateNSWAdd - Create an Add operator with the NSW flag set. - /// - static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateAdd(V1, V2, Name); + static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = Create(Opc, V1, V2, Name); BO->setHasNoSignedWrap(true); return BO; } - static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateAdd(V1, V2, Name, BB); + static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); BO->setHasNoSignedWrap(true); return BO; } - static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateAdd(V1, V2, Name, I); + static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, I); BO->setHasNoSignedWrap(true); return BO; } - - /// CreateNUWAdd - Create an Add operator with the NUW flag set. - /// - static BinaryOperator *CreateNUWAdd(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateAdd(V1, V2, Name); - BO->setHasNoUnsignedWrap(true); - return BO; - } - static BinaryOperator *CreateNUWAdd(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateAdd(V1, V2, Name, BB); - BO->setHasNoUnsignedWrap(true); - return BO; - } - static BinaryOperator *CreateNUWAdd(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateAdd(V1, V2, Name, I); - BO->setHasNoUnsignedWrap(true); - return BO; - } - - /// CreateNSWSub - Create an Sub operator with the NSW flag set. - /// - static BinaryOperator *CreateNSWSub(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateSub(V1, V2, Name); - BO->setHasNoSignedWrap(true); - return BO; - } - static BinaryOperator *CreateNSWSub(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateSub(V1, V2, Name, BB); - BO->setHasNoSignedWrap(true); - return BO; - } - static BinaryOperator *CreateNSWSub(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateSub(V1, V2, Name, I); - BO->setHasNoSignedWrap(true); - return BO; - } - - /// CreateNUWSub - Create an Sub operator with the NUW flag set. - /// - static BinaryOperator *CreateNUWSub(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateSub(V1, V2, Name); - BO->setHasNoUnsignedWrap(true); - return BO; - } - static BinaryOperator *CreateNUWSub(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateSub(V1, V2, Name, BB); - BO->setHasNoUnsignedWrap(true); - return BO; - } - static BinaryOperator *CreateNUWSub(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateSub(V1, V2, Name, I); - BO->setHasNoUnsignedWrap(true); - return BO; - } - - /// CreateNSWMul - Create a Mul operator with the NSW flag set. - /// - static BinaryOperator *CreateNSWMul(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateMul(V1, V2, Name); - BO->setHasNoSignedWrap(true); - return BO; - } - static BinaryOperator *CreateNSWMul(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateMul(V1, V2, Name, BB); - BO->setHasNoSignedWrap(true); - return BO; - } - static BinaryOperator *CreateNSWMul(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateMul(V1, V2, Name, I); - BO->setHasNoSignedWrap(true); - return BO; - } - - /// CreateNUWMul - Create a Mul operator with the NUW flag set. - /// - static BinaryOperator *CreateNUWMul(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateMul(V1, V2, Name); + + static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = Create(Opc, V1, V2, Name); BO->setHasNoUnsignedWrap(true); return BO; } - static BinaryOperator *CreateNUWMul(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateMul(V1, V2, Name, BB); + static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); BO->setHasNoUnsignedWrap(true); return BO; } - static BinaryOperator *CreateNUWMul(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateMul(V1, V2, Name, I); + static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, I); BO->setHasNoUnsignedWrap(true); return BO; } - - /// CreateExactSDiv - Create an SDiv operator with the exact flag set. - /// - static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateSDiv(V1, V2, Name); + + static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = Create(Opc, V1, V2, Name); BO->setIsExact(true); return BO; } - static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateSDiv(V1, V2, Name, BB); + static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); BO->setIsExact(true); return BO; } - static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateSDiv(V1, V2, Name, I); + static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, I); BO->setIsExact(true); return BO; } - + +#define DEFINE_HELPERS(OPC, NUWNSWEXACT) \ + static BinaryOperator *Create ## NUWNSWEXACT ## OPC \ + (Value *V1, Value *V2, const Twine &Name = "") { \ + return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name); \ + } \ + static BinaryOperator *Create ## NUWNSWEXACT ## OPC \ + (Value *V1, Value *V2, const Twine &Name, BasicBlock *BB) { \ + return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name, BB); \ + } \ + static BinaryOperator *Create ## NUWNSWEXACT ## OPC \ + (Value *V1, Value *V2, const Twine &Name, Instruction *I) { \ + return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name, I); \ + } + + DEFINE_HELPERS(Add, NSW) // CreateNSWAdd + DEFINE_HELPERS(Add, NUW) // CreateNUWAdd + DEFINE_HELPERS(Sub, NSW) // CreateNSWSub + DEFINE_HELPERS(Sub, NUW) // CreateNUWSub + DEFINE_HELPERS(Mul, NSW) // CreateNSWMul + DEFINE_HELPERS(Mul, NUW) // CreateNUWMul + DEFINE_HELPERS(Shl, NSW) // CreateNSWShl + DEFINE_HELPERS(Shl, NUW) // CreateNUWShl + + DEFINE_HELPERS(SDiv, Exact) // CreateExactSDiv + DEFINE_HELPERS(UDiv, Exact) // CreateExactUDiv + DEFINE_HELPERS(AShr, Exact) // CreateExactAShr + DEFINE_HELPERS(LShr, Exact) // CreateExactLShr + +#undef DEFINE_HELPERS + /// Helper functions to construct and inspect unary operations (NEG and NOT) /// via binary operators SUB and XOR: /// @@ -432,7 +372,8 @@ public: }; template <> -struct OperandTraits<BinaryOperator> : public FixedNumOperandTraits<2> { +struct OperandTraits<BinaryOperator> : + public FixedNumOperandTraits<BinaryOperator, 2> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value) @@ -824,11 +765,11 @@ public: /// This is just a convenience that dispatches to the subclasses. /// @brief Determine if this CmpInst is commutative. - bool isCommutative(); + bool isCommutative() const; /// This is just a convenience that dispatches to the subclasses. /// @brief Determine if this is an equals/not equals predicate. - bool isEquality(); + bool isEquality() const; /// @returns true if the comparison is signed, false otherwise. /// @brief Determine if this instruction is using a signed comparison. @@ -903,7 +844,7 @@ private: // FIXME: these are redundant if CmpInst < BinaryOperator template <> -struct OperandTraits<CmpInst> : public FixedNumOperandTraits<2> { +struct OperandTraits<CmpInst> : public FixedNumOperandTraits<CmpInst, 2> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CmpInst, Value) diff --git a/include/llvm/Instruction.h b/include/llvm/Instruction.h index 88f5ce1b26..89bb9fdf42 100644 --- a/include/llvm/Instruction.h +++ b/include/llvm/Instruction.h @@ -200,11 +200,10 @@ public: /// /// Associative operators satisfy: x op (y op z) === (x op y) op z /// - /// In LLVM, the Add, Mul, And, Or, and Xor operators are associative, when - /// not applied to floating point types. + /// In LLVM, the Add, Mul, And, Or, and Xor operators are associative. /// - bool isAssociative() const { return isAssociative(getOpcode(), getType()); } - static bool isAssociative(unsigned op, const Type *Ty); + bool isAssociative() const { return isAssociative(getOpcode()); } + static bool isAssociative(unsigned op); /// isCommutative - Return true if the instruction is commutative: /// diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index 91f7729a11..17ff763c52 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -29,7 +29,6 @@ class ConstantInt; class ConstantRange; class APInt; class LLVMContext; -class DominatorTree; //===----------------------------------------------------------------------===// // AllocaInst Class @@ -263,7 +262,7 @@ private: }; template <> -struct OperandTraits<StoreInst> : public FixedNumOperandTraits<2> { +struct OperandTraits<StoreInst> : public FixedNumOperandTraits<StoreInst, 2> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) @@ -459,6 +458,9 @@ public: Value* const *Idx, unsigned NumIdx); static const Type *getIndexedType(const Type *Ptr, + Constant* const *Idx, unsigned NumIdx); + + static const Type *getIndexedType(const Type *Ptr, uint64_t const *Idx, unsigned NumIdx); static const Type *getIndexedType(const Type *Ptr, Value *Idx); @@ -525,7 +527,8 @@ public: }; template <> -struct OperandTraits<GetElementPtrInst> : public VariadicOperandTraits<1> { +struct OperandTraits<GetElementPtrInst> : + public VariadicOperandTraits<GetElementPtrInst, 1> { }; template<typename RandomAccessIterator> @@ -1088,7 +1091,7 @@ private: }; template <> -struct OperandTraits<CallInst> : public VariadicOperandTraits<1> { +struct OperandTraits<CallInst> : public VariadicOperandTraits<CallInst, 1> { }; template<typename RandomAccessIterator> @@ -1196,7 +1199,7 @@ public: }; template <> -struct OperandTraits<SelectInst> : public FixedNumOperandTraits<3> { +struct OperandTraits<SelectInst> : public FixedNumOperandTraits<SelectInst, 3> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectInst, Value) @@ -1293,7 +1296,8 @@ public: }; template <> -struct OperandTraits<ExtractElementInst> : public FixedNumOperandTraits<2> { +struct OperandTraits<ExtractElementInst> : + public FixedNumOperandTraits<ExtractElementInst, 2> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementInst, Value) @@ -1351,7 +1355,8 @@ public: }; template <> -struct OperandTraits<InsertElementInst> : public FixedNumOperandTraits<3> { +struct OperandTraits<InsertElementInst> : + public FixedNumOperandTraits<InsertElementInst, 3> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementInst, Value) @@ -1408,7 +1413,8 @@ public: }; template <> -struct OperandTraits<ShuffleVectorInst> : public FixedNumOperandTraits<3> { +struct OperandTraits<ShuffleVectorInst> : + public FixedNumOperandTraits<ShuffleVectorInst, 3> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorInst, Value) @@ -1451,8 +1457,7 @@ class ExtractValueInst : public UnaryInstruction { /// getIndexedType - Returns the type of the element that would be extracted /// with an extractvalue instruction with the specified parameters. /// - /// Null is returned if the indices are invalid for the specified - /// pointer type. + /// Null is returned if the indices are invalid for the specified type. /// static const Type *getIndexedType(const Type *Agg, const unsigned *Idx, unsigned NumIdx); @@ -1535,8 +1540,7 @@ public: /// getIndexedType - Returns the type of the element that would be extracted /// with an extractvalue instruction with the specified parameters. /// - /// Null is returned if the indices are invalid for the specified - /// pointer type. + /// Null is returned if the indices are invalid for the specified type. /// template<typename RandomAccessIterator> static const Type *getIndexedType(const Type *Ptr, @@ -1754,7 +1758,8 @@ public: }; template <> -struct OperandTraits<InsertValueInst> : public FixedNumOperandTraits<2> { +struct OperandTraits<InsertValueInst> : + public FixedNumOperandTraits<InsertValueInst, 2> { }; template<typename RandomAccessIterator> @@ -1946,13 +1951,7 @@ public: /// hasConstantValue - If the specified PHI node always merges together the /// same value, return the value, otherwise return null. - /// - /// If the PHI has undef operands, but all the rest of the operands are - /// some unique value, return that value if it can be proved that the - /// value dominates the PHI. If DT is null, use a conservative check, - /// otherwise use DT to test for dominance. - /// - Value *hasConstantValue(const DominatorTree *DT = 0) const; + Value *hasConstantValue() const; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const PHINode *) { return true; } @@ -2041,7 +2040,7 @@ public: }; template <> -struct OperandTraits<ReturnInst> : public VariadicOperandTraits<> { +struct OperandTraits<ReturnInst> : public VariadicOperandTraits<ReturnInst> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ReturnInst, Value) @@ -2077,22 +2076,20 @@ protected: virtual BranchInst *clone_impl() const; public: static BranchInst *Create(BasicBlock *IfTrue, Instruction *InsertBefore = 0) { - return new(1, true) BranchInst(IfTrue, InsertBefore); + return new(1) BranchInst(IfTrue, InsertBefore); } static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, Instruction *InsertBefore = 0) { return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertBefore); } static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *InsertAtEnd) { - return new(1, true) BranchInst(IfTrue, InsertAtEnd); + return new(1) BranchInst(IfTrue, InsertAtEnd); } static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, BasicBlock *InsertAtEnd) { return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertAtEnd); } - ~BranchInst(); - /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2109,19 +2106,6 @@ public: Op<-3>() = V; } - // setUnconditionalDest - Change the current branch to an unconditional branch - // targeting the specified block. - // FIXME: Eliminate this ugly method. - void setUnconditionalDest(BasicBlock *Dest) { - Op<-1>() = (Value*)Dest; - if (isConditional()) { // Convert this to an uncond branch. - Op<-2>() = 0; - Op<-3>() = 0; - NumOperands = 1; - OperandList = op_begin(); - } - } - unsigned getNumSuccessors() const { return 1+isConditional(); } BasicBlock *getSuccessor(unsigned i) const { @@ -2149,7 +2133,8 @@ private: }; template <> -struct OperandTraits<BranchInst> : public VariadicOperandTraits<1> {}; +struct OperandTraits<BranchInst> : public VariadicOperandTraits<BranchInst, 1> { +}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) @@ -2168,7 +2153,7 @@ class SwitchInst : public TerminatorInst { // Operand[2n ] = Value to match // Operand[2n+1] = BasicBlock to go to on match SwitchInst(const SwitchInst &SI); - void init(Value *Value, BasicBlock *Default, unsigned NumCases); + void init(Value *Value, BasicBlock *Default, unsigned NumReserved); void resizeOperands(unsigned No); // allocate space for exactly zero operands void *operator new(size_t s) { @@ -2262,7 +2247,8 @@ public: /// removeCase - This method removes the specified successor from the switch /// instruction. Note that this cannot be used to remove the default - /// destination (successor #0). + /// destination (successor #0). Also note that this operation may reorder the + /// remaining cases at index idx and above. /// void removeCase(unsigned idx); @@ -2640,7 +2626,7 @@ private: }; template <> -struct OperandTraits<InvokeInst> : public VariadicOperandTraits<3> { +struct OperandTraits<InvokeInst> : public VariadicOperandTraits<InvokeInst, 3> { }; template<typename RandomAccessIterator> diff --git a/include/llvm/IntrinsicInst.h b/include/llvm/IntrinsicInst.h index a17fa9cc5b..74c30fbddd 100644 --- a/include/llvm/IntrinsicInst.h +++ b/include/llvm/IntrinsicInst.h @@ -55,7 +55,7 @@ namespace llvm { return isa<CallInst>(V) && classof(cast<CallInst>(V)); } }; - + /// DbgInfoIntrinsic - This is the common base class for debug info intrinsics /// class DbgInfoIntrinsic : public IntrinsicInst { @@ -139,6 +139,10 @@ namespace llvm { return !getVolatileCst()->isZero(); } + unsigned getAddressSpace() const { + return cast<PointerType>(getRawDest()->getType())->getAddressSpace(); + } + /// getDest - This is just like getRawDest, but it strips off any cast /// instructions that feed it, giving the original input. The returned /// value is guaranteed to be a pointer. @@ -297,29 +301,6 @@ namespace llvm { } }; - /// MemoryUseIntrinsic - This is the common base class for the memory use - /// marker intrinsics. - /// - class MemoryUseIntrinsic : public IntrinsicInst { - public: - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const MemoryUseIntrinsic *) { return true; } - static inline bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::lifetime_start: - case Intrinsic::lifetime_end: - case Intrinsic::invariant_start: - case Intrinsic::invariant_end: - return true; - default: return false; - } - } - static inline bool classof(const Value *V) { - return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); - } - }; - } #endif diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index 347541f71f..ba66555c4e 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -259,7 +259,7 @@ def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty]>; // Internal interface for object size checking def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_ptr_ty, llvm_i1_ty], - [IntrReadArgMem]>, + [IntrNoMem]>, GCCBuiltin<"__builtin_object_size">; //===-------------------- Bit Manipulation Intrinsics ---------------------===// @@ -436,7 +436,7 @@ def int_lifetime_end : Intrinsic<[], [IntrReadWriteArgMem, NoCapture<1>]>; def int_invariant_start : Intrinsic<[llvm_descriptor_ty], [llvm_i64_ty, llvm_ptr_ty], - [IntrReadArgMem, NoCapture<1>]>; + [IntrReadWriteArgMem, NoCapture<1>]>; def int_invariant_end : Intrinsic<[], [llvm_descriptor_ty, llvm_i64_ty, llvm_ptr_ty], @@ -490,3 +490,4 @@ include "llvm/IntrinsicsARM.td" include "llvm/IntrinsicsCellSPU.td" include "llvm/IntrinsicsAlpha.td" include "llvm/IntrinsicsXCore.td" +include "llvm/IntrinsicsPTX.td" diff --git a/include/llvm/IntrinsicsARM.td b/include/llvm/IntrinsicsARM.td index 6c047718e6..823f095dbd 100644 --- a/include/llvm/IntrinsicsARM.td +++ b/include/llvm/IntrinsicsARM.td @@ -1,10 +1,10 @@ //===- IntrinsicsARM.td - Defines ARM intrinsics -----------*- tablegen -*-===// -// +// // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // // This file defines all of the ARM-specific intrinsics. @@ -286,6 +286,12 @@ def int_arm_neon_vcvtfp2fxu : Neon_CvtFPToFx_Intrinsic; def int_arm_neon_vcvtfxs2fp : Neon_CvtFxToFP_Intrinsic; def int_arm_neon_vcvtfxu2fp : Neon_CvtFxToFP_Intrinsic; +// Vector Conversions Between Half-Precision and Single-Precision. +def int_arm_neon_vcvtfp2hf + : Intrinsic<[llvm_v4i16_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_arm_neon_vcvthf2fp + : Intrinsic<[llvm_v4f32_ty], [llvm_v4i16_ty], [IntrNoMem]>; + // Narrowing Saturating Vector Moves. def int_arm_neon_vqmovns : Neon_1Arg_Narrow_Intrinsic; def int_arm_neon_vqmovnu : Neon_1Arg_Narrow_Intrinsic; diff --git a/include/llvm/IntrinsicsPTX.td b/include/llvm/IntrinsicsPTX.td new file mode 100644 index 0000000000..ec291e467e --- /dev/null +++ b/include/llvm/IntrinsicsPTX.td @@ -0,0 +1,32 @@ +//===- IntrinsicsPTX.td - Defines PTX intrinsics -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the PTX-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "ptx" in { + multiclass PTXReadSpecialRegisterIntrinsic { + def _r64 : Intrinsic<[llvm_i64_ty], [], [IntrNoMem]>; + def _v4i16 : Intrinsic<[llvm_v4i16_ty], [], [IntrNoMem]>; + } + + multiclass PTXReadSpecialSubRegisterIntrinsic { + def _x : Intrinsic<[llvm_i16_ty], [], [IntrNoMem]>; + def _y : Intrinsic<[llvm_i16_ty], [], [IntrNoMem]>; + def _z : Intrinsic<[llvm_i16_ty], [], [IntrNoMem]>; + def _w : Intrinsic<[llvm_i16_ty], [], [IntrNoMem]>; + } +} + +defm int_ptx_read_tid : PTXReadSpecialRegisterIntrinsic; +defm int_ptx_read_tid : PTXReadSpecialSubRegisterIntrinsic; + +let TargetPrefix = "ptx" in + def int_ptx_bar_sync : Intrinsic<[], [llvm_i32_ty], []>; diff --git a/include/llvm/IntrinsicsXCore.td b/include/llvm/IntrinsicsXCore.td index a86cda28a5..944120fc8c 100644 --- a/include/llvm/IntrinsicsXCore.td +++ b/include/llvm/IntrinsicsXCore.td @@ -11,4 +11,45 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". def int_xcore_bitrev : Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem]>; def int_xcore_getid : Intrinsic<[llvm_i32_ty],[],[IntrNoMem]>; + + // Resource instructions. + def int_xcore_getr : Intrinsic<[llvm_anyptr_ty],[llvm_i32_ty]>; + def int_xcore_freer : Intrinsic<[],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_in : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty],[NoCapture<0>]>; + def int_xcore_int : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_inct : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_out : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_outt : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_outct : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_chkct : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setd : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setc : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_inshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_outshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setpt : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_getts : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_syncr : Intrinsic<[],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_settw : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setv : Intrinsic<[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; + def int_xcore_eeu : Intrinsic<[],[llvm_anyptr_ty], [NoCapture<0>]>; + + // Intrinsics for events. + def int_xcore_waitevent : Intrinsic<[llvm_ptr_ty],[], [IntrReadMem]>; + def int_xcore_clre : Intrinsic<[],[],[]>; } diff --git a/include/llvm/LLVMContext.h b/include/llvm/LLVMContext.h index e5b77777d9..3502ff73c1 100644 --- a/include/llvm/LLVMContext.h +++ b/include/llvm/LLVMContext.h @@ -21,6 +21,7 @@ class LLVMContextImpl; class StringRef; class Instruction; class Module; +class SMDiagnostic; template <typename T> class SmallVectorImpl; /// This is an important class for using LLVM in a threaded context. It @@ -49,18 +50,23 @@ public: /// custom metadata IDs registered in this LLVMContext. void getMDKindNames(SmallVectorImpl<StringRef> &Result) const; + + typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context, + unsigned LocCookie); + /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked /// when problems with inline asm are detected by the backend. The first - /// argument is a function pointer (of type SourceMgr::DiagHandlerTy) and the - /// second is a context pointer that gets passed into the DiagHandler. + /// argument is a function pointer and the second is a context pointer that + /// gets passed into the DiagHandler. /// - /// LLVMContext doesn't take ownership or interpreter either of these + /// LLVMContext doesn't take ownership or interpret either of these /// pointers. - void setInlineAsmDiagnosticHandler(void *DiagHandler, void *DiagContext = 0); + void setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, + void *DiagContext = 0); /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by /// setInlineAsmDiagnosticHandler. - void *getInlineAsmDiagnosticHandler() const; + InlineAsmDiagHandlerTy getInlineAsmDiagnosticHandler() const; /// getInlineAsmDiagnosticContext - Return the diagnostic context set by /// setInlineAsmDiagnosticHandler. diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index c260425713..1769ba1ef4 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This header file pulls in all transformation and analysis passes for tools +// This header file pulls in all transformation and analysis passes for tools // like opt and bugpoint that need this functionality. // //===----------------------------------------------------------------------===// @@ -70,6 +70,7 @@ namespace { (void) llvm::createDomViewerPass(); (void) llvm::createEdgeProfilerPass(); (void) llvm::createOptimalEdgeProfilerPass(); + (void) llvm::createPathProfilerPass(); (void) llvm::createFunctionInliningPass(); (void) llvm::createAlwaysInlinerPass(); (void) llvm::createGlobalDCEPass(); @@ -83,13 +84,13 @@ namespace { (void) llvm::createLCSSAPass(); (void) llvm::createLICMPass(); (void) llvm::createLazyValueInfoPass(); - (void) llvm::createLiveValuesPass(); (void) llvm::createLoopDependenceAnalysisPass(); (void) llvm::createLoopExtractorPass(); (void) llvm::createLoopSimplifyPass(); (void) llvm::createLoopStrengthReducePass(); (void) llvm::createLoopUnrollPass(); (void) llvm::createLoopUnswitchPass(); + (void) llvm::createLoopIdiomPass(); (void) llvm::createLoopRotatePass(); (void) llvm::createLowerInvokePass(); (void) llvm::createLowerSetJmpPass(); @@ -98,7 +99,9 @@ namespace { (void) llvm::createNoProfileInfoPass(); (void) llvm::createProfileEstimatorPass(); (void) llvm::createProfileVerifierPass(); + (void) llvm::createPathProfileVerifierPass(); (void) llvm::createProfileLoaderPass(); + (void) llvm::createPathProfileLoaderPass(); (void) llvm::createPromoteMemoryToRegisterPass(); (void) llvm::createDemoteRegisterToMemoryPass(); (void) llvm::createPruneEHPass(); @@ -115,7 +118,6 @@ namespace { (void) llvm::createSCCPPass(); (void) llvm::createScalarReplAggregatesPass(); (void) llvm::createSimplifyLibCallsPass(); - (void) llvm::createSimplifyHalfPowrLibCallsPass(); (void) llvm::createSingleLoopExtractorPass(); (void) llvm::createStripSymbolsPass(); (void) llvm::createStripNonDebugSymbolsPass(); @@ -127,13 +129,13 @@ namespace { (void) llvm::createUnifyFunctionExitNodesPass(); (void) llvm::createInstCountPass(); (void) llvm::createCodeGenPreparePass(); + (void) llvm::createEarlyCSEPass(); (void) llvm::createGVNPass(); (void) llvm::createMemCpyOptPass(); (void) llvm::createLoopDeletionPass(); (void) llvm::createPostDomTree(); (void) llvm::createPostDomFrontier(); (void) llvm::createInstructionNamerPass(); - (void) llvm::createPartialSpecializationPass(); (void) llvm::createFunctionAttrsPass(); (void) llvm::createMergeFunctionsPass(); (void) llvm::createPrintModulePass(0); @@ -141,12 +143,12 @@ namespace { (void) llvm::createDbgInfoPrinterPass(); (void) llvm::createModuleDebugInfoPrinterPass(); (void) llvm::createPartialInliningPass(); - (void) llvm::createGEPSplitterPass(); (void) llvm::createLintPass(); (void) llvm::createSinkingPass(); (void) llvm::createLowerAtomicPass(); (void) llvm::createCorrelatedValuePropagationPass(); (void) llvm::createMemDepPrinter(); + (void) llvm::createInstructionSimplifierPass(); (void)new llvm::IntervalPartition(); (void)new llvm::FindUsedTypes(); diff --git a/include/llvm/LinkAllVMCore.h b/include/llvm/LinkAllVMCore.h index 6959cb6d1e..83684c0fb6 100644 --- a/include/llvm/LinkAllVMCore.h +++ b/include/llvm/LinkAllVMCore.h @@ -22,15 +22,14 @@ #include "llvm/IntrinsicInst.h" #include "llvm/InlineAsm.h" #include "llvm/Analysis/Verifier.h" -#include "llvm/System/Alarm.h" -#include "llvm/System/DynamicLibrary.h" -#include "llvm/System/Memory.h" -#include "llvm/System/Mutex.h" -#include "llvm/System/Path.h" -#include "llvm/System/Process.h" -#include "llvm/System/Program.h" -#include "llvm/System/Signals.h" -#include "llvm/System/TimeValue.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Memory.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/TimeValue.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/MathExtras.h" #include <cstdlib> diff --git a/include/llvm/MC/EDInstInfo.h b/include/llvm/MC/EDInstInfo.h index dded25521a..83d9e780fe 100644 --- a/include/llvm/MC/EDInstInfo.h +++ b/include/llvm/MC/EDInstInfo.h @@ -9,7 +9,7 @@ #ifndef EDINSTINFO_H #define EDINSTINFO_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 0c0a942e1b..7e24a3d1d3 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -25,7 +25,9 @@ namespace llvm { /// MCAsmInfo - This class is intended to be used as a base class for asm /// properties and features specific to the target. - namespace ExceptionHandling { enum ExceptionsType { None, Dwarf, SjLj }; } + namespace ExceptionHandling { + enum ExceptionsType { None, DwarfTable, DwarfCFI, SjLj, ARM }; + } class MCAsmInfo { protected: @@ -51,6 +53,11 @@ namespace llvm { /// emitted in Static relocation model. bool HasStaticCtorDtorReferenceInStaticMode; // Default is false. + /// LinkerRequiresNonEmptyDwarfLines - True if the linker has a bug and + /// requires that the debug_line section be of a minimum size. In practice + /// such a linker requires a non empty line sequence if a file is present. + bool LinkerRequiresNonEmptyDwarfLines; // Default to false. + /// MaxInstLength - This is the maximum possible length of an instruction, /// which is needed to compute the size of an inline asm. unsigned MaxInstLength; // Defaults to 4. @@ -192,6 +199,13 @@ namespace llvm { /// HasSetDirective - True if the assembler supports the .set directive. bool HasSetDirective; // Defaults to true. + /// HasAggressiveSymbolFolding - False if the assembler requires that we use + /// Lc = a - b + /// .long Lc + /// instead of + /// .long a - b + bool HasAggressiveSymbolFolding; // Defaults to true. + /// HasLCOMMDirective - This is true if the target supports the .lcomm /// directive. bool HasLCOMMDirective; // Defaults to false. @@ -212,6 +226,10 @@ namespace llvm { /// directive. bool HasNoDeadStrip; // Defaults to false. + /// HasSymbolResolver - True if this target supports the MachO + /// .symbol_resolver directive. + bool HasSymbolResolver; // Defaults to false. + /// WeakRefDirective - This directive, if non-null, is used to declare a /// global as being a weak undefined symbol. const char *WeakRefDirective; // Defaults to NULL. @@ -228,6 +246,11 @@ namespace llvm { /// declare a symbol as having hidden visibility. MCSymbolAttr HiddenVisibilityAttr; // Defaults to MCSA_Hidden. + /// HiddenDeclarationVisibilityAttr - This attribute, if not MCSA_Invalid, + /// is used to declare an undefined symbol as having hidden visibility. + MCSymbolAttr HiddenDeclarationVisibilityAttr; // Defaults to MCSA_Hidden. + + /// ProtectedVisibilityAttr - This attribute, if not MCSA_Invalid, is used /// to declare a symbol as having protected visibility. MCSymbolAttr ProtectedVisibilityAttr; // Defaults to MCSA_Protected @@ -237,10 +260,6 @@ namespace llvm { /// HasLEB128 - True if target asm supports leb128 directives. bool HasLEB128; // Defaults to false. - /// hasDotLocAndDotFile - True if target asm supports .loc and .file - /// directives for emitting debugging information. - bool HasDotLocAndDotFile; // Defaults to false. - /// SupportsDebugInformation - True if target supports emission of debugging /// information. bool SupportsDebugInformation; // Defaults to false. @@ -322,6 +341,9 @@ namespace llvm { bool hasStaticCtorDtorReferenceInStaticMode() const { return HasStaticCtorDtorReferenceInStaticMode; } + bool getLinkerRequiresNonEmptyDwarfLines() const { + return LinkerRequiresNonEmptyDwarfLines; + } unsigned getMaxInstLength() const { return MaxInstLength; } @@ -392,6 +414,9 @@ namespace llvm { return ExternDirective; } bool hasSetDirective() const { return HasSetDirective; } + bool hasAggressiveSymbolFolding() const { + return HasAggressiveSymbolFolding; + } bool hasLCOMMDirective() const { return HasLCOMMDirective; } bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} bool getCOMMDirectiveAlignmentIsInBytes() const { @@ -399,20 +424,21 @@ namespace llvm { } bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } bool hasNoDeadStrip() const { return HasNoDeadStrip; } + bool hasSymbolResolver() const { return HasSymbolResolver; } const char *getWeakRefDirective() const { return WeakRefDirective; } const char *getWeakDefDirective() const { return WeakDefDirective; } const char *getLinkOnceDirective() const { return LinkOnceDirective; } MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr;} + MCSymbolAttr getHiddenDeclarationVisibilityAttr() const { + return HiddenDeclarationVisibilityAttr; + } MCSymbolAttr getProtectedVisibilityAttr() const { return ProtectedVisibilityAttr; } bool hasLEB128() const { return HasLEB128; } - bool hasDotLocAndDotFile() const { - return HasDotLocAndDotFile; - } bool doesSupportDebugInformation() const { return SupportsDebugInformation; } @@ -422,6 +448,13 @@ namespace llvm { ExceptionHandling::ExceptionsType getExceptionHandlingType() const { return ExceptionsType; } + bool isExceptionHandlingDwarf() const { + return + (ExceptionsType == ExceptionHandling::DwarfTable || + ExceptionsType == ExceptionHandling::DwarfCFI || + ExceptionsType == ExceptionHandling::ARM); + } + bool doesDwarfRequireFrameSection() const { return DwarfRequiresFrameSection; } diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index b9565ba061..01cb0006b3 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -39,13 +39,12 @@ private: /// The last fragment which was layed out, or 0 if nothing has been layed /// out. Fragments are always layed out in order, so all fragments with a /// lower ordinal will be up to date. - mutable MCFragment *LastValidFragment; + mutable DenseMap<const MCSectionData*, MCFragment *> LastValidFragment; /// \brief Make sure that the layout for the given fragment is valid, lazily /// computing it if necessary. void EnsureValid(const MCFragment *F) const; - bool isSectionUpToDate(const MCSectionData *SD) const; bool isFragmentUpToDate(const MCFragment *F) const; public: @@ -54,27 +53,15 @@ public: /// Get the assembler object this is a layout for. MCAssembler &getAssembler() const { return Assembler; } - /// \brief Update the layout because a fragment has been resized. The - /// fragments size should have already been updated, the \arg SlideAmount is - /// the delta from the old size. - void UpdateForSlide(MCFragment *F, int SlideAmount); - - /// \brief Update the layout because a fragment has been replaced. - void FragmentReplaced(MCFragment *Src, MCFragment *Dst); - - /// \brief Perform a full layout. - void LayoutFile(); + /// \brief Invalidate all following fragments because a fragment has been + /// resized. The fragments size should have already been updated. + void Invalidate(MCFragment *F); /// \brief Perform layout for a single fragment, assuming that the previous /// fragment has already been layed out correctly, and the parent section has /// been initialized. void LayoutFragment(MCFragment *Fragment); - /// \brief Performs initial layout for a single section, assuming that the - /// previous section (including its fragments) has already been layed out - /// correctly. - void LayoutSection(MCSectionData *SD); - /// @name Section Access (in layout order) /// @{ @@ -89,28 +76,13 @@ public: /// @name Fragment Layout Data /// @{ - /// \brief Get the effective size of the given fragment, as computed in the - /// current layout. - uint64_t getFragmentEffectiveSize(const MCFragment *F) const; - /// \brief Get the offset of the given fragment inside its containing section. uint64_t getFragmentOffset(const MCFragment *F) const; /// @} - /// @name Section Layout Data - /// @{ - - /// \brief Get the computed address of the given section. - uint64_t getSectionAddress(const MCSectionData *SD) const; - - /// @} /// @name Utility Functions /// @{ - /// \brief Get the address of the given fragment, as computed in the current - /// layout. - uint64_t getFragmentAddress(const MCFragment *F) const; - /// \brief Get the address space size of the given section, as it effects /// layout. This may differ from the size reported by \see getSectionSize() by /// not including section tail padding. @@ -120,12 +92,9 @@ public: /// file. This may include additional padding, or be 0 for virtual sections. uint64_t getSectionFileSize(const MCSectionData *SD) const; - /// \brief Get the logical data size of the given section. - uint64_t getSectionSize(const MCSectionData *SD) const; - - /// \brief Get the address of the given symbol, as computed in the current + /// \brief Get the offset of the given symbol, as computed in the current /// layout. - uint64_t getSymbolAddress(const MCSymbolData *SD) const; + uint64_t getSymbolOffset(const MCSymbolData *SD) const; /// @} }; diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index a757a92208..30971c62a9 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -11,13 +11,14 @@ #define LLVM_MC_MCASSEMBLER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" #include "llvm/Support/Casting.h" #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCInst.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <vector> // FIXME: Shouldn't be needed. namespace llvm { @@ -51,6 +52,7 @@ public: FT_Inst, FT_Org, FT_Dwarf, + FT_DwarfFrame, FT_LEB }; @@ -74,12 +76,7 @@ private: /// initialized. uint64_t Offset; - /// EffectiveSize - The compute size of this section. This is ~0 until - /// initialized. - uint64_t EffectiveSize; - - /// LayoutOrder - The global layout order of this fragment. This is the index - /// across all fragments in the file, not just within the section. + /// LayoutOrder - The layout order of this fragment. unsigned LayoutOrder; /// @} @@ -236,19 +233,12 @@ class MCAlignFragment : public MCFragment { /// target dependent. bool EmitNops : 1; - /// OnlyAlignAddress - Flag to indicate that this align is only used to adjust - /// the address space size of a section and that it should not be included as - /// part of the section size. This flag can only be used on the last fragment - /// in a section. - bool OnlyAlignAddress : 1; - public: MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, unsigned _MaxBytesToEmit, MCSectionData *SD = 0) : MCFragment(FT_Align, SD), Alignment(_Alignment), Value(_Value),ValueSize(_ValueSize), - MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false), - OnlyAlignAddress(false) {} + MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {} /// @name Accessors /// @{ @@ -264,9 +254,6 @@ public: bool hasEmitNops() const { return EmitNops; } void setEmitNops(bool Value) { EmitNops = Value; } - bool hasOnlyAlignAddress() const { return OnlyAlignAddress; } - void setOnlyAlignAddress(bool Value) { OnlyAlignAddress = Value; } - /// @} static bool classof(const MCFragment *F) { @@ -319,13 +306,10 @@ class MCOrgFragment : public MCFragment { /// Value - Value to use for filling bytes. int8_t Value; - /// Size - The current estimate of the size. - unsigned Size; - public: MCOrgFragment(const MCExpr &_Offset, int8_t _Value, MCSectionData *SD = 0) : MCFragment(FT_Org, SD), - Offset(&_Offset), Value(_Value), Size(0) {} + Offset(&_Offset), Value(_Value) {} /// @name Accessors /// @{ @@ -334,9 +318,6 @@ public: uint8_t getValue() const { return Value; } - unsigned getSize() const { return Size; } - - void setSize(unsigned Size_) { Size = Size_; } /// @} static bool classof(const MCFragment *F) { @@ -352,13 +333,11 @@ class MCLEBFragment : public MCFragment { /// IsSigned - True if this is a sleb128, false if uleb128. bool IsSigned; - /// Size - The current size estimate. - uint64_t Size; - + SmallString<8> Contents; public: MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSectionData *SD) : MCFragment(FT_LEB, SD), - Value(&Value_), IsSigned(IsSigned_), Size(1) {} + Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); } /// @name Accessors /// @{ @@ -367,9 +346,8 @@ public: bool isSigned() const { return IsSigned; } - uint64_t getSize() const { return Size; } - - void setSize(uint64_t Size_) { Size = Size_; } + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } /// @} @@ -388,14 +366,13 @@ class MCDwarfLineAddrFragment : public MCFragment { /// make up the address delta between two .loc dwarf directives. const MCExpr *AddrDelta; - /// Size - The current size estimate. - uint64_t Size; + SmallString<8> Contents; public: MCDwarfLineAddrFragment(int64_t _LineDelta, const MCExpr &_AddrDelta, - MCSectionData *SD = 0) + MCSectionData *SD) : MCFragment(FT_Dwarf, SD), - LineDelta(_LineDelta), AddrDelta(&_AddrDelta), Size(1) {} + LineDelta(_LineDelta), AddrDelta(&_AddrDelta) { Contents.push_back(0); } /// @name Accessors /// @{ @@ -404,9 +381,8 @@ public: const MCExpr &getAddrDelta() const { return *AddrDelta; } - uint64_t getSize() const { return Size; } - - void setSize(uint64_t Size_) { Size = Size_; } + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } /// @} @@ -416,6 +392,34 @@ public: static bool classof(const MCDwarfLineAddrFragment *) { return true; } }; +class MCDwarfCallFrameFragment : public MCFragment { + /// AddrDelta - The expression for the difference of the two symbols that + /// make up the address delta between two .cfi_* dwarf directives. + const MCExpr *AddrDelta; + + SmallString<8> Contents; + +public: + MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, MCSectionData *SD) + : MCFragment(FT_DwarfFrame, SD), + AddrDelta(&_AddrDelta) { Contents.push_back(0); } + + /// @name Accessors + /// @{ + + const MCExpr &getAddrDelta() const { return *AddrDelta; } + + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_DwarfFrame; + } + static bool classof(const MCDwarfCallFrameFragment *) { return true; } +}; + // FIXME: Should this be a separate class, or just merged into MCSection? Since // we anticipate the fast path being through an MCAssembler, the only reason to // keep it out is for API abstraction. @@ -452,10 +456,6 @@ private: // // FIXME: This could all be kept private to the assembler implementation. - /// Address - The computed address of this section. This is ~0 until - /// initialized. - uint64_t Address; - /// HasInstructions - Whether this section has had instructions emitted into /// it. unsigned HasInstructions : 1; @@ -664,6 +664,8 @@ private: MCCodeEmitter &Emitter; + MCObjectWriter &Writer; + raw_ostream &OS; iplist<MCSectionData> Sections; @@ -682,9 +684,18 @@ private: std::vector<IndirectSymbolData> IndirectSymbols; + /// The set of function symbols for which a .thumb_func directive has + /// been seen. + // + // FIXME: We really would like this in target specific code rather than + // here. Maybe when the relocation stuff moves to target specific, + // this can go with it? The streamer would need some target specific + // refactoring too. + SmallPtrSet<const MCSymbol*, 64> ThumbFuncs; + unsigned RelaxAll : 1; + unsigned NoExecStack : 1; unsigned SubsectionsViaSymbols : 1; - unsigned PadSectionToAlignment : 1; private: /// Evaluate a fixup to a relocatable expression and the value which should be @@ -700,47 +711,44 @@ private: /// \return Whether the fixup value was fully resolved. This is true if the /// \arg Value result is fixed, otherwise the value may change due to /// relocation. - bool EvaluateFixup(const MCObjectWriter &Writer, const MCAsmLayout &Layout, + bool EvaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value) const; /// Check whether a fixup can be satisfied, or whether it needs to be relaxed /// (increased in size, in order to hold its value correctly). - bool FixupNeedsRelaxation(const MCObjectWriter &Writer, - const MCFixup &Fixup, const MCFragment *DF, + bool FixupNeedsRelaxation(const MCFixup &Fixup, const MCFragment *DF, const MCAsmLayout &Layout) const; /// Check whether the given fragment needs relaxation. - bool FragmentNeedsRelaxation(const MCObjectWriter &Writer, - const MCInstFragment *IF, + bool FragmentNeedsRelaxation(const MCInstFragment *IF, const MCAsmLayout &Layout) const; - /// Compute the effective fragment size assuming it is layed out at the given - /// \arg SectionAddress and \arg FragmentOffset. - uint64_t ComputeFragmentSize(MCAsmLayout &Layout, const MCFragment &F, - uint64_t SectionAddress, - uint64_t FragmentOffset) const; - /// LayoutOnce - Perform one layout iteration and return true if any offsets /// were adjusted. - bool LayoutOnce(const MCObjectWriter &Writer, MCAsmLayout &Layout); + bool LayoutOnce(MCAsmLayout &Layout); - bool RelaxInstruction(const MCObjectWriter &Writer, MCAsmLayout &Layout, - MCInstFragment &IF); + bool LayoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD); - bool RelaxOrg(const MCObjectWriter &Writer, MCAsmLayout &Layout, - MCOrgFragment &OF); + bool RelaxInstruction(MCAsmLayout &Layout, MCInstFragment &IF); - bool RelaxLEB(const MCObjectWriter &Writer, MCAsmLayout &Layout, - MCLEBFragment &IF); + bool RelaxLEB(MCAsmLayout &Layout, MCLEBFragment &IF); - bool RelaxDwarfLineAddr(const MCObjectWriter &Writer, MCAsmLayout &Layout, - MCDwarfLineAddrFragment &DF); + bool RelaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF); + bool RelaxDwarfCallFrameFragment(MCAsmLayout &Layout, + MCDwarfCallFrameFragment &DF); /// FinishLayout - Finalize a layout, including fragment lowering. void FinishLayout(MCAsmLayout &Layout); + uint64_t HandleFixup(const MCAsmLayout &Layout, + MCFragment &F, const MCFixup &Fixup); + public: + /// Compute the effective fragment size assuming it is layed out at the given + /// \arg SectionAddress and \arg FragmentOffset. + uint64_t ComputeFragmentSize(const MCAsmLayout &Layout, const MCFragment &F) const; + /// Find the symbol which defines the atom containing the given symbol, or /// null if there is no such symbol. const MCSymbolData *getAtom(const MCSymbolData *Symbol) const; @@ -752,13 +760,16 @@ public: bool isSymbolLinkerVisible(const MCSymbol &SD) const; /// Emit the section contents using the given object writer. - // - // FIXME: Should MCAssembler always have a reference to the object writer? - void WriteSectionData(const MCSectionData *Section, const MCAsmLayout &Layout, - MCObjectWriter *OW) const; + void WriteSectionData(const MCSectionData *Section, + const MCAsmLayout &Layout) const; + + /// Check whether a given symbol has been flagged with .thumb_func. + bool isThumbFunc(const MCSymbol *Func) const { + return ThumbFuncs.count(Func); + } - void AddSectionToTheEnd(const MCObjectWriter &Writer, MCSectionData &SD, - MCAsmLayout &Layout); + /// Flag a function symbol as the target of a .thumb_func directive. + void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); } public: /// Construct a new assembler instance. @@ -769,8 +780,8 @@ public: // concrete and require clients to pass in a target like object. The other // option is to make this abstract, and have targets provide concrete // implementations as we do with AsmParser. - MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, - MCCodeEmitter &_Emitter, bool _PadSectionToAlignment, + MCAssembler(MCContext &Context_, TargetAsmBackend &Backend_, + MCCodeEmitter &Emitter_, MCObjectWriter &Writer_, raw_ostream &OS); ~MCAssembler(); @@ -780,10 +791,12 @@ public: MCCodeEmitter &getEmitter() const { return Emitter; } + MCObjectWriter &getWriter() const { return Writer; } + /// Finish - Do final processing and write the object to the output stream. /// \arg Writer is used for custom object writer (as the MCJIT does), /// if not specified it is automatically created from backend. - void Finish(MCObjectWriter *Writer = 0); + void Finish(); // FIXME: This does not belong here. bool getSubsectionsViaSymbols() const { @@ -796,6 +809,9 @@ public: bool getRelaxAll() const { return RelaxAll; } void setRelaxAll(bool Value) { RelaxAll = Value; } + bool getNoExecStack() const { return NoExecStack; } + void setNoExecStack(bool Value) { NoExecStack = Value; } + /// @name Section List Access /// @{ diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h index eac06ede2a..bc63241bec 100644 --- a/include/llvm/MC/MCCodeEmitter.h +++ b/include/llvm/MC/MCCodeEmitter.h @@ -20,33 +20,6 @@ class MCInst; class raw_ostream; template<typename T> class SmallVectorImpl; -/// MCFixupKindInfo - Target independent information on a fixup kind. -struct MCFixupKindInfo { - enum FixupKindFlags { - /// Is this fixup kind PCrelative? This is used by the assembler backend to - /// evaluate fixup values in a target independent manner when possible. - FKF_IsPCRel = (1 << 0) - }; - - /// A target specific name for the fixup kind. The names will be unique for - /// distinct kinds on any given target. - const char *Name; - - /// The bit offset to write the relocation into. - // - // FIXME: These two fields are under-specified and not general enough, but it - // covers many things. It's enough to let the AsmStreamer pretty-print - // the encoding. - unsigned TargetOffset; - - /// The number of bits written by this fixup. The bits are assumed to be - /// contiguous. - unsigned TargetSize; - - /// Flags describing additional information on this fixup kind. - unsigned Flags; -}; - /// MCCodeEmitter - Generic instruction encoding interface. class MCCodeEmitter { private: @@ -58,17 +31,6 @@ protected: // Can only create subclasses. public: virtual ~MCCodeEmitter(); - /// @name Target Independent Fixup Information - /// @{ - - /// getNumFixupKinds - Get the number of target specific fixup kinds. - virtual unsigned getNumFixupKinds() const = 0; - - /// getFixupKindInfo - Get information on a fixup kind. - virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const; - - /// @} - /// EncodeInstruction - Encode the given \arg Inst to bytes on the output /// stream \arg OS. virtual void EncodeInstruction(const MCInst &Inst, raw_ostream &OS, diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index cec29fad63..7b26d54937 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -29,6 +29,7 @@ namespace llvm { class MCLineSection; class StringRef; class Twine; + class TargetAsmInfo; class MCSectionMachO; class MCSectionELF; @@ -42,9 +43,15 @@ namespace llvm { /// The MCAsmInfo for this target. const MCAsmInfo &MAI; + const TargetAsmInfo *TAI; + /// Symbols - Bindings of names to symbols. StringMap<MCSymbol*> Symbols; + /// UsedNames - Keeps tracks of names that were used both for used declared + /// and artificial symbols. + StringMap<bool> UsedNames; + /// NextUniqueID - The next ID to dole out to an unnamed assembler temporary /// symbol. unsigned NextUniqueID; @@ -57,8 +64,8 @@ namespace llvm { /// GetInstance() gets the current instance of the directional local label /// for the LocalLabelVal and adds it to the map if needed. unsigned GetInstance(int64_t LocalLabelVal); - - /// The file name of the log file from the enviromment variable + + /// The file name of the log file from the environment variable /// AS_SECURE_LOG_FILE. Which must be set before the .secure_log_unique /// directive is used or it is an error. char *SecureLogFile; @@ -80,29 +87,37 @@ namespace llvm { /// The dwarf line information from the .loc directives for the sections /// with assembled machine instructions have after seeing .loc directives. DenseMap<const MCSection *, MCLineSection *> MCLineSections; + /// We need a deterministic iteration order, so we remember the order + /// the elements were added. + std::vector<const MCSection *> MCLineSectionOrder; /// Allocator - Allocator object used for creating machine code objects. /// /// We use a bump pointer allocator to avoid the need to track all allocated /// objects. BumpPtrAllocator Allocator; - + void *MachOUniquingMap, *ELFUniquingMap, *COFFUniquingMap; + + MCSymbol *CreateSymbol(StringRef Name); + public: - explicit MCContext(const MCAsmInfo &MAI); + explicit MCContext(const MCAsmInfo &MAI, const TargetAsmInfo *TAI); ~MCContext(); - + const MCAsmInfo &getAsmInfo() const { return MAI; } - /// @name Symbol Managment + const TargetAsmInfo &getTargetAsmInfo() const { return *TAI; } + + /// @name Symbol Management /// @{ - + /// CreateTempSymbol - Create and return a new assembler temporary symbol /// with a unique but unspecified name. MCSymbol *CreateTempSymbol(); - /// CreateDirectionalLocalSymbol - Create the defintion of a directional - /// local symbol for numbered label (used for "1:" defintions). + /// CreateDirectionalLocalSymbol - Create the definition of a directional + /// local symbol for numbered label (used for "1:" definitions). MCSymbol *CreateDirectionalLocalSymbol(int64_t LocalLabelVal); /// GetDirectionalLocalSymbol - Create and return a directional local @@ -121,8 +136,8 @@ namespace llvm { MCSymbol *LookupSymbol(StringRef Name) const; /// @} - - /// @name Section Managment + + /// @name Section Management /// @{ /// getMachOSection - Return the MCSection for the specified mach-o section. @@ -156,10 +171,10 @@ namespace llvm { return getCOFFSection (Section, Characteristics, 0, Kind); } - + /// @} - /// @name Dwarf Managment + /// @name Dwarf Management /// @{ /// GetDwarfFile - creates an entry in the dwarf file and directory tables. @@ -167,8 +182,8 @@ namespace llvm { bool isValidDwarfFileNumber(unsigned FileNumber); - bool hasDwarfFiles(void) { - return MCDwarfFiles.size() != 0; + bool hasDwarfFiles() const { + return !MCDwarfFiles.empty(); } const std::vector<MCDwarfFile *> &getMCDwarfFiles() { @@ -177,9 +192,18 @@ namespace llvm { const std::vector<StringRef> &getMCDwarfDirs() { return MCDwarfDirs; } - DenseMap<const MCSection *, MCLineSection *> &getMCLineSections() { + + const DenseMap<const MCSection *, MCLineSection *> + &getMCLineSections() const { return MCLineSections; } + const std::vector<const MCSection *> &getMCLineSectionOrder() const { + return MCLineSectionOrder; + } + void addMCLineSection(const MCSection *Sec, MCLineSection *Line) { + MCLineSections[Sec] = Line; + MCLineSectionOrder.push_back(Sec); + } /// setCurrentDwarfLoc - saves the information from the currently parsed /// dwarf .loc directive and sets DwarfLocSeen. When the next instruction diff --git a/include/llvm/MC/MCDirectives.h b/include/llvm/MC/MCDirectives.h index 03337a9f52..1df55dc252 100644 --- a/include/llvm/MC/MCDirectives.h +++ b/include/llvm/MC/MCDirectives.h @@ -34,6 +34,7 @@ enum MCSymbolAttr { MCSA_LazyReference, ///< .lazy_reference (MachO) MCSA_Local, ///< .local (ELF) MCSA_NoDeadStrip, ///< .no_dead_strip (MachO) + MCSA_SymbolResolver, ///< .symbol_resolver (MachO) MCSA_PrivateExtern, ///< .private_extern (MachO) MCSA_Protected, ///< .protected (ELF) MCSA_Reference, ///< .reference (MachO) diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h index dfb8ed5e8a..c9e42eb6c7 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -9,7 +9,7 @@ #ifndef MCDISASSEMBLER_H #define MCDISASSEMBLER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 609d819626..07a7bad15b 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -16,16 +16,19 @@ #define LLVM_MC_MCDWARF_H #include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/CodeGen/MachineLocation.h" // FIXME #include "llvm/MC/MCObjectWriter.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Dwarf.h" #include <vector> namespace llvm { + class MachineMove; class MCContext; + class MCExpr; class MCSection; + class MCSectionData; + class MCStreamer; class MCSymbol; class MCObjectStreamer; class raw_ostream; @@ -107,22 +110,22 @@ namespace llvm { public: /// getFileNum - Get the FileNum of this MCDwarfLoc. - unsigned getFileNum() { return FileNum; } + unsigned getFileNum() const { return FileNum; } /// getLine - Get the Line of this MCDwarfLoc. - unsigned getLine() { return Line; } + unsigned getLine() const { return Line; } /// getColumn - Get the Column of this MCDwarfLoc. - unsigned getColumn() { return Column; } + unsigned getColumn() const { return Column; } /// getFlags - Get the Flags of this MCDwarfLoc. - unsigned getFlags() { return Flags; } + unsigned getFlags() const { return Flags; } /// getIsa - Get the Isa of this MCDwarfLoc. - unsigned getIsa() { return Isa; } + unsigned getIsa() const { return Isa; } /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. - unsigned getDiscriminator() { return Discriminator; } + unsigned getDiscriminator() const { return Discriminator; } /// setFileNum - Set the FileNum of this MCDwarfLoc. void setFileNum(unsigned fileNum) { FileNum = fileNum; } @@ -162,12 +165,12 @@ namespace llvm { MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) : MCDwarfLoc(loc), Label(label) {} - MCSymbol *getLabel() { return Label; } + MCSymbol *getLabel() const { return Label; } // This is called when an instruction is assembled into the specified // section and if there is information from the last .loc directive that // has yet to have a line entry made for it is made. - static void Make(MCObjectStreamer *MCOS, const MCSection *Section); + static void Make(MCStreamer *MCOS, const MCSection *Section); }; /// MCLineSection - Instances of this class represent the line information @@ -192,12 +195,15 @@ namespace llvm { typedef std::vector<MCLineEntry> MCLineEntryCollection; typedef MCLineEntryCollection::iterator iterator; + typedef MCLineEntryCollection::const_iterator const_iterator; private: MCLineEntryCollection MCLineEntries; public: - MCLineEntryCollection *getMCLineEntries() { return &MCLineEntries; } + const MCLineEntryCollection *getMCLineEntries() const { + return &MCLineEntries; + } }; class MCDwarfFileTable { @@ -205,7 +211,7 @@ namespace llvm { // // This emits the Dwarf file and the line tables. // - static void Emit(MCObjectStreamer *MCOS, const MCSection *DwarfLineSection); + static void Emit(MCStreamer *MCOS); }; class MCDwarfLineAddr { @@ -214,16 +220,60 @@ namespace llvm { static void Encode(int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS); /// Utility function to emit the encoding to a streamer. - static void Emit(MCObjectStreamer *MCOS, + static void Emit(MCStreamer *MCOS, int64_t LineDelta,uint64_t AddrDelta); - /// Utility function to compute the size of the encoding. - static uint64_t ComputeSize(int64_t LineDelta, uint64_t AddrDelta); - /// Utility function to write the encoding to an object writer. static void Write(MCObjectWriter *OW, int64_t LineDelta, uint64_t AddrDelta); }; + + class MCCFIInstruction { + public: + enum OpType { Remember, Restore, Move }; + private: + OpType Operation; + MCSymbol *Label; + // Move to & from location. + MachineLocation Destination; + MachineLocation Source; + public: + MCCFIInstruction(OpType Op, MCSymbol *L) + : Operation(Op), Label(L) { + assert(Op == Remember || Op == Restore); + } + MCCFIInstruction(MCSymbol *L, const MachineLocation &D, + const MachineLocation &S) + : Operation(Move), Label(L), Destination(D), Source(S) { + } + OpType getOperation() const { return Operation; } + MCSymbol *getLabel() const { return Label; } + const MachineLocation &getDestination() const { return Destination; } + const MachineLocation &getSource() const { return Source; } + }; + + struct MCDwarfFrameInfo { + MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), + Instructions(), PersonalityEncoding(0), + LsdaEncoding(0) {} + MCSymbol *Begin; + MCSymbol *End; + const MCSymbol *Personality; + const MCSymbol *Lsda; + std::vector<MCCFIInstruction> Instructions; + unsigned PersonalityEncoding; + unsigned LsdaEncoding; + }; + + class MCDwarfFrameEmitter { + public: + // + // This emits the frame info section. + // + static void Emit(MCStreamer &streamer); + static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); + static void EncodeAdvanceLoc(uint64_t AddrDelta, raw_ostream &OS); + }; } // end namespace llvm #endif diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h new file mode 100644 index 0000000000..3c150dca9e --- /dev/null +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -0,0 +1,47 @@ +//===-- llvm/MC/MCELFObjectWriter.h - ELF Object Writer ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCELFOBJECTWRITER_H +#define LLVM_MC_MCELFOBJECTWRITER_H + +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { +class MCELFObjectTargetWriter { + const Triple::OSType OSType; + const uint16_t EMachine; + const unsigned HasRelocationAddend : 1; + const unsigned Is64Bit : 1; +protected: + MCELFObjectTargetWriter(bool Is64Bit_, Triple::OSType OSType_, + uint16_t EMachine_, bool HasRelocationAddend_); + +public: + virtual ~MCELFObjectTargetWriter(); + + /// @name Accessors + /// @{ + Triple::OSType getOSType() { return OSType; } + uint16_t getEMachine() { return EMachine; } + bool hasRelocationAddend() { return HasRelocationAddend; } + bool is64Bit() { return Is64Bit; } + /// @} +}; + +/// \brief Construct a new ELF writer instance. +/// +/// \param MOTW - The target specific ELF writer subclass. +/// \param OS - The stream to write to. +/// \returns The constructed object writer. +MCObjectWriter *createELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &OS, bool IsLittleEndian); +} // End llvm namespace + +#endif diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index e8b15284f2..fea5249eab 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -10,17 +10,21 @@ #ifndef LLVM_MC_MCEXPR_H #define LLVM_MC_MCEXPR_H +#include "llvm/ADT/DenseMap.h" #include "llvm/Support/Casting.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class MCAsmInfo; class MCAsmLayout; +class MCAssembler; class MCContext; +class MCSectionData; class MCSymbol; class MCValue; class raw_ostream; class StringRef; +typedef DenseMap<const MCSectionData*, uint64_t> SectionAddrMap; /// MCExpr - Base class for the full range of assembler expressions which are /// needed for parsing. @@ -40,10 +44,15 @@ private: MCExpr(const MCExpr&); // DO NOT IMPLEMENT void operator=(const MCExpr&); // DO NOT IMPLEMENT + bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs) const; protected: explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {} - bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, + bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, bool InSet) const; public: /// @name Accessors @@ -69,7 +78,11 @@ public: /// values. If not given, then only non-symbolic expressions will be /// evaluated. /// @result - True on success. - bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout = 0) const; + bool EvaluateAsAbsolute(int64_t &Res) const; + bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; + bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; + bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout, + const SectionAddrMap &Addrs) const; /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable /// value, i.e. an expression of the fixed form (a - b + constant). @@ -77,7 +90,7 @@ public: /// @param Res - The relocatable value, if evaluation succeeds. /// @param Layout - The assembler layout object to use for evaluating values. /// @result - True on success. - bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout = 0) const; + bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout &Layout) const; /// @} @@ -142,8 +155,6 @@ public: VK_TPOFF, VK_DTPOFF, VK_TLVP, // Mach-O thread local variable relocation - VK_ARM_HI16, // The R_ARM_MOVT_ABS relocation (:upper16: in the .s file) - VK_ARM_LO16, // The R_ARM_MOVW_ABS_NC relocation (:lower16: in the .w file) // FIXME: We'd really like to use the generic Kinds listed above for these. VK_ARM_PLT, // ARM-style PLT references. i.e., (PLT) instead of @PLT VK_ARM_TLSGD, // ditto for TLSGD, GOT, GOTOFF, TPOFF and GOTTPOFF @@ -151,7 +162,7 @@ public: VK_ARM_GOTOFF, VK_ARM_TPOFF, VK_ARM_GOTTPOFF, - + VK_PPC_TOC, VK_PPC_HA16, // ha16(symbol) VK_PPC_LO16 // lo16(symbol) @@ -179,7 +190,7 @@ public: MCContext &Ctx); static const MCSymbolRefExpr *Create(StringRef Name, VariantKind Kind, MCContext &Ctx); - + /// @} /// @name Accessors /// @{ @@ -408,7 +419,7 @@ public: virtual void PrintImpl(raw_ostream &OS) const = 0; virtual bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout) const = 0; - + virtual void AddValueSymbols(MCAssembler *) const = 0; static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Target; diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h index eed4c349e8..6fde797e40 100644 --- a/include/llvm/MC/MCFixup.h +++ b/include/llvm/MC/MCFixup.h @@ -10,7 +10,7 @@ #ifndef LLVM_MC_MCFIXUP_H #define LLVM_MC_MCFIXUP_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { @@ -22,6 +22,10 @@ enum MCFixupKind { FK_Data_2, ///< A two-byte fixup. FK_Data_4, ///< A four-byte fixup. FK_Data_8, ///< A eight-byte fixup. + FK_PCRel_1, ///< A one-byte pc relative fixup. + FK_PCRel_2, ///< A two-byte pc relative fixup. + FK_PCRel_4, ///< A four-byte pc relative fixup. + FK_PCRel_8, ///< A eight-byte pc relative fixup. FirstTargetFixupKind = 128, @@ -77,13 +81,13 @@ public: /// getKindForSize - Return the generic fixup kind for a value with the given /// size. It is an error to pass an unsupported size. - static MCFixupKind getKindForSize(unsigned Size) { + static MCFixupKind getKindForSize(unsigned Size, bool isPCRel) { switch (Size) { default: assert(0 && "Invalid generic fixup size!"); - case 1: return FK_Data_1; - case 2: return FK_Data_2; - case 4: return FK_Data_4; - case 8: return FK_Data_8; + case 1: return isPCRel ? FK_PCRel_1 : FK_Data_1; + case 2: return isPCRel ? FK_PCRel_2 : FK_Data_2; + case 4: return isPCRel ? FK_PCRel_4 : FK_Data_4; + case 8: return isPCRel ? FK_PCRel_8 : FK_Data_8; } } }; diff --git a/include/llvm/MC/MCFixupKindInfo.h b/include/llvm/MC/MCFixupKindInfo.h new file mode 100644 index 0000000000..1961687146 --- /dev/null +++ b/include/llvm/MC/MCFixupKindInfo.h @@ -0,0 +1,43 @@ +//===-- llvm/MC/MCFixupKindInfo.h - Fixup Descriptors -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCFIXUPKINDINFO_H +#define LLVM_MC_MCFIXUPKINDINFO_H + +namespace llvm { + +/// MCFixupKindInfo - Target independent information on a fixup kind. +struct MCFixupKindInfo { + enum FixupKindFlags { + /// Is this fixup kind PCrelative? This is used by the assembler backend to + /// evaluate fixup values in a target independent manner when possible. + FKF_IsPCRel = (1 << 0), + + /// Should this fixup kind force a 4-byte aligned effective PC value? + FKF_IsAlignedDownTo32Bits = (1 << 1) + }; + + /// A target specific name for the fixup kind. The names will be unique for + /// distinct kinds on any given target. + const char *Name; + + /// The bit offset to write the relocation into. + unsigned TargetOffset; + + /// The number of bits written by this fixup. The bits are assumed to be + /// contiguous. + unsigned TargetSize; + + /// Flags describing additional information on this fixup kind. + unsigned Flags; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index 2b337e3624..d6ef7b4c33 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -18,7 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class raw_ostream; diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index 96716c775f..92f06ed09c 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -41,6 +41,9 @@ public: /// getOpcodeName - Return the name of the specified opcode enum (e.g. /// "MOV32ri") or empty if we can't resolve it. virtual StringRef getOpcodeName(unsigned Opcode) const; + + /// getRegName - Return the assembler register name. + virtual StringRef getRegName(unsigned RegNo) const; }; } // namespace llvm diff --git a/include/llvm/MC/MCMachOSymbolFlags.h b/include/llvm/MC/MCMachOSymbolFlags.h index c938c81f69..696436dffa 100644 --- a/include/llvm/MC/MCMachOSymbolFlags.h +++ b/include/llvm/MC/MCMachOSymbolFlags.h @@ -34,9 +34,11 @@ namespace llvm { SF_ReferenceTypePrivateUndefinedLazy = 0x0005, // Other 'desc' flags. + SF_ThumbFunc = 0x0008, SF_NoDeadStrip = 0x0020, SF_WeakReference = 0x0040, - SF_WeakDefinition = 0x0080 + SF_WeakDefinition = 0x0080, + SF_SymbolResolver = 0x0100 }; } // end namespace llvm diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h new file mode 100644 index 0000000000..ec51031d0b --- /dev/null +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -0,0 +1,65 @@ +//===-- llvm/MC/MCMachObjectWriter.h - Mach Object Writer -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCMACHOBJECTWRITER_H +#define LLVM_MC_MCMACHOBJECTWRITER_H + +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class MCMachObjectTargetWriter { + const unsigned Is64Bit : 1; + const uint32_t CPUType; + const uint32_t CPUSubtype; + // FIXME: Remove this, we should just always use it once we no longer care + // about Darwin 'as' compatibility. + const unsigned UseAggressiveSymbolFolding : 1; + unsigned LocalDifference_RIT; + +protected: + MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_, + uint32_t CPUSubtype_, + bool UseAggressiveSymbolFolding_ = false); + + void setLocalDifferenceRelocationType(unsigned Type) { + LocalDifference_RIT = Type; + } + +public: + virtual ~MCMachObjectTargetWriter(); + + /// @name Accessors + /// @{ + + bool is64Bit() const { return Is64Bit; } + bool useAggressiveSymbolFolding() const { return UseAggressiveSymbolFolding; } + uint32_t getCPUType() const { return CPUType; } + uint32_t getCPUSubtype() const { return CPUSubtype; } + unsigned getLocalDifferenceRelocationType() const { + return LocalDifference_RIT; + } + + /// @} +}; + +/// \brief Construct a new Mach-O writer instance. +/// +/// This routine takes ownership of the target writer subclass. +/// +/// \param MOTW - The target specific Mach-O writer subclass. +/// \param OS - The stream to write to. +/// \returns The constructed object writer. +MCObjectWriter *createMachObjectWriter(MCMachObjectTargetWriter *MOTW, + raw_ostream &OS, bool IsLittleEndian); + +} // End llvm namespace + +#endif diff --git a/include/llvm/MC/MCObjectFormat.h b/include/llvm/MC/MCObjectFormat.h deleted file mode 100644 index 5c3f003696..0000000000 --- a/include/llvm/MC/MCObjectFormat.h +++ /dev/null @@ -1,54 +0,0 @@ -//===-- llvm/MC/MCObjectFormat.h - Object Format Info -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCOBJECTFORMAT_H -#define LLVM_MC_MCOBJECTFORMAT_H - -namespace llvm { -class MCSymbol; - -class MCObjectFormat { -public: - virtual ~MCObjectFormat(); - - /// isAbsolute - Check if A - B is an absolute value - /// - /// \param InSet - True if this expression is in a set. For example: - /// a: - /// ... - /// b: - /// tmp = a - b - /// .long tmp - /// \param A - LHS - /// \param B - RHS - virtual bool isAbsolute(bool InSet, const MCSymbol &A, - const MCSymbol &B) const = 0; -}; - -class MCELFObjectFormat : public MCObjectFormat { -public: - virtual bool isAbsolute(bool InSet, const MCSymbol &A, - const MCSymbol &B) const; -}; - -class MCMachOObjectFormat : public MCObjectFormat { -public: - virtual bool isAbsolute(bool InSet, const MCSymbol &A, - const MCSymbol &B) const; -}; - -class MCCOFFObjectFormat : public MCObjectFormat { -public: - virtual bool isAbsolute(bool InSet, const MCSymbol &A, - const MCSymbol &B) const; -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 8c21c10522..833341eb97 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -33,13 +33,11 @@ class MCObjectStreamer : public MCStreamer { MCAssembler *Assembler; MCSectionData *CurSectionData; - virtual void EmitInstToFragment(const MCInst &Inst) = 0; virtual void EmitInstToData(const MCInst &Inst) = 0; protected: MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, - raw_ostream &_OS, MCCodeEmitter *_Emitter, - bool _PadSectionToAlignment); + raw_ostream &_OS, MCCodeEmitter *_Emitter); ~MCObjectStreamer(); MCSectionData *getCurrentSectionData() const { @@ -60,11 +58,21 @@ public: /// @name MCStreamer Interface /// @{ + virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace); virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - virtual void SwitchSection(const MCSection *Section); + virtual void ChangeSection(const MCSection *Section); virtual void EmitInstruction(const MCInst &Inst); + virtual void EmitInstToFragment(const MCInst &Inst); + virtual void EmitValueToOffset(const MCExpr *Offset, unsigned char Value); + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label); + virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label); virtual void Finish(); /// @} diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 77ab6abed2..782d844598 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -12,7 +12,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { @@ -20,6 +20,9 @@ class MCAsmLayout; class MCAssembler; class MCFixup; class MCFragment; +class MCSymbol; +class MCSymbolData; +class MCSymbolRefExpr; class MCValue; class raw_ostream; @@ -62,7 +65,8 @@ public: /// /// This routine is called by the assembler after layout and relaxation is /// complete. - virtual void ExecutePostLayoutBinding(MCAssembler &Asm) = 0; + virtual void ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) = 0; /// Record a relocation entry. /// @@ -76,15 +80,24 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) = 0; - /// Check if a fixup is fully resolved. + /// \brief Check whether the difference (A - B) between two symbol + /// references is fully resolved. /// - /// This routine is used by the assembler to let the file format decide - /// if a fixup is not fully resolved. For example, one that crosses - /// two sections on ELF. - virtual bool IsFixupFullyResolved(const MCAssembler &Asm, - const MCValue Target, - bool IsPCRel, - const MCFragment *DF) const = 0; + /// Clients are not required to answer precisely and may conservatively return + /// false, even when a difference is fully resolved. + bool + IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, + const MCSymbolRefExpr *A, + const MCSymbolRefExpr *B, + bool InSet) const; + + virtual bool + IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const; + /// Write the object file. /// @@ -178,13 +191,6 @@ public: static void EncodeULEB128(uint64_t Value, raw_ostream &OS); }; -MCObjectWriter *createMachObjectWriter(raw_ostream &OS, bool is64Bit, - uint32_t CPUType, uint32_t CPUSubtype, - bool IsLittleEndian); -MCObjectWriter *createELFObjectWriter(raw_ostream &OS, bool is64Bit, - Triple::OSType OSType, uint16_t EMachine, - bool IsLittleEndian, - bool HasRelocationAddend); MCObjectWriter *createWinCOFFObjectWriter(raw_ostream &OS, bool is64Bit); } // End llvm namespace diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index 439ecb91e5..252696bec3 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -17,7 +17,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> #include <cassert> @@ -29,10 +29,10 @@ class MCAsmInfo; /// AsmLexer - Lexer class for assembly files. class AsmLexer : public MCAsmLexer { const MCAsmInfo &MAI; - + const char *CurPtr; const MemoryBuffer *CurBuf; - + void operator=(const AsmLexer&); // DO NOT IMPLEMENT AsmLexer(const AsmLexer&); // DO NOT IMPLEMENT @@ -43,13 +43,13 @@ protected: public: AsmLexer(const MCAsmInfo &MAI); ~AsmLexer(); - + void setBuffer(const MemoryBuffer *buf, const char *ptr = NULL); - + virtual StringRef LexUntilEndOfStatement(); bool isAtStartOfComment(char Char); - + const MCAsmInfo &getMAI() const { return MAI; } private: @@ -60,10 +60,11 @@ private: AsmToken LexSlash(); AsmToken LexLineComment(); AsmToken LexDigit(); + AsmToken LexSingleQuote(); AsmToken LexQuote(); AsmToken LexFloatLiteral(); }; - + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index b0039fe2ba..606725a985 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -11,7 +11,7 @@ #define LLVM_MC_MCASMLEXER_H #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/SMLoc.h" namespace llvm { @@ -29,16 +29,16 @@ public: // String values. Identifier, String, - + // Integer values. Integer, - + // Real values. Real, - + // Register values (stored in IntVal). Only used by TargetAsmLexer. Register, - + // No-value. EndOfStatement, Colon, @@ -46,8 +46,8 @@ public: Slash, // '/' LParen, RParen, LBrac, RBrac, LCurly, RCurly, Star, Dot, Comma, Dollar, Equal, EqualEqual, - - Pipe, PipePipe, Caret, + + Pipe, PipePipe, Caret, Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash, Less, LessEqual, LessLess, LessGreater, Greater, GreaterEqual, GreaterGreater, At @@ -73,7 +73,7 @@ public: SMLoc getLoc() const; /// getStringContents - Get the contents of a string token (without quotes). - StringRef getStringContents() const { + StringRef getStringContents() const { assert(Kind == String && "This token isn't a string!"); return Str.slice(1, Str.size() - 1); } @@ -98,11 +98,11 @@ public: // FIXME: Don't compute this in advance, it makes every token larger, and is // also not generally what we want (it is nicer for recovery etc. to lex 123br // as a single token, then diagnose as an invalid number). - int64_t getIntVal() const { + int64_t getIntVal() const { assert(Kind == Integer && "This token isn't an integer!"); - return IntVal; + return IntVal; } - + /// getRegVal - Get the register number for the current token, which should /// be a register. unsigned getRegVal() const { @@ -116,7 +116,7 @@ public: class MCAsmLexer { /// The current token, stored in the base class for faster access. AsmToken CurTok; - + /// The location and description of the current error SMLoc ErrLoc; std::string Err; @@ -129,12 +129,12 @@ protected: // Can only create subclasses. MCAsmLexer(); virtual AsmToken LexToken() = 0; - + void SetError(const SMLoc &errLoc, const std::string &err) { ErrLoc = errLoc; Err = err; } - + public: virtual ~MCAsmLexer(); @@ -155,12 +155,12 @@ public: const AsmToken &getTok() { return CurTok; } - + /// getErrLoc - Get the current error location const SMLoc &getErrLoc() { return ErrLoc; } - + /// getErr - Get the current error string const std::string &getErr() { return Err; diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index 6e1e2e3ece..54979d977d 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -10,7 +10,7 @@ #ifndef LLVM_MC_MCASMPARSER_H #define LLVM_MC_MCASMPARSER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class AsmToken; @@ -102,7 +102,7 @@ public: /// EatToEndOfStatement - Skip to the end of the current statement, for error /// recovery. virtual void EatToEndOfStatement() = 0; - + /// ParseExpression - Parse an arbitrary expression. /// /// @param Res - The value of the expression. The result is undefined diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h index 95184cdfcf..ceb57f57e9 100644 --- a/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -38,6 +38,8 @@ protected: return (Obj->*Handler)(Directive, DirectiveLoc); } + bool BracketExpressionsSupported; + public: virtual ~MCAsmParserExtension(); @@ -68,6 +70,8 @@ public: const AsmToken &getTok() { return getParser().getTok(); } + bool HasBracketExpressions() const { return BracketExpressionsSupported; } + /// @} }; diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h index 99fa5adae9..91f5773b8d 100644 --- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -19,10 +19,10 @@ class raw_ostream; /// base class is used by target-independent clients and is the interface /// between parsing an asm instruction and recognizing it. class MCParsedAsmOperand { -public: +public: MCParsedAsmOperand() {} virtual ~MCParsedAsmOperand() {} - + /// getStartLoc - Get the location of the first token of this operand. virtual SMLoc getStartLoc() const = 0; /// getEndLoc - Get the location of the last token of this operand. diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index b741216f94..1c01b2f8f3 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -64,6 +64,10 @@ namespace llvm { // "optimized nops" to fill instead of 0s. virtual bool UseCodeAlign() const = 0; + /// isVirtualSection - Check whether this section is "virtual", that is + /// has no actual object file contents. + virtual bool isVirtualSection() const = 0; + static bool classof(const MCSection *) { return true; } }; diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index 8bf7f448ec..b154cf59d1 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -56,6 +56,7 @@ namespace llvm { virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS) const; virtual bool UseCodeAlign() const; + virtual bool isVirtualSection() const; static bool classof(const MCSection *S) { return S->getVariant() == SV_COFF; diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 5af538557e..c82de71282 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -15,6 +15,7 @@ #define LLVM_MC_MCSECTIONELF_H #include "llvm/MC/MCSection.h" +#include "llvm/Support/ELF.h" namespace llvm { @@ -54,131 +55,6 @@ public: /// should be printed before the section name bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; - /// HasCommonSymbols - True if this section holds common symbols, this is - /// indicated on the ELF object file by a symbol with SHN_COMMON section - /// header index. - bool HasCommonSymbols() const; - - /// These are the section type and flags fields. An ELF section can have - /// only one Type, but can have more than one of the flags specified. - /// - /// Valid section types. - enum { - // This value marks the section header as inactive. - SHT_NULL = 0x00U, - - // Holds information defined by the program, with custom format and meaning. - SHT_PROGBITS = 0x01U, - - // This section holds a symbol table. - SHT_SYMTAB = 0x02U, - - // The section holds a string table. - SHT_STRTAB = 0x03U, - - // The section holds relocation entries with explicit addends. - SHT_RELA = 0x04U, - - // The section holds a symbol hash table. - SHT_HASH = 0x05U, - - // Information for dynamic linking. - SHT_DYNAMIC = 0x06U, - - // The section holds information that marks the file in some way. - SHT_NOTE = 0x07U, - - // A section of this type occupies no space in the file. - SHT_NOBITS = 0x08U, - - // The section holds relocation entries without explicit addends. - SHT_REL = 0x09U, - - // This section type is reserved but has unspecified semantics. - SHT_SHLIB = 0x0AU, - - // This section holds a symbol table. - SHT_DYNSYM = 0x0BU, - - // This section contains an array of pointers to initialization functions. - SHT_INIT_ARRAY = 0x0EU, - - // This section contains an array of pointers to termination functions. - SHT_FINI_ARRAY = 0x0FU, - - // This section contains an array of pointers to functions that are invoked - // before all other initialization functions. - SHT_PREINIT_ARRAY = 0x10U, - - // A section group is a set of sections that are related and that must be - // treated specially by the linker. - SHT_GROUP = 0x11U, - - // This section is associated with a section of type SHT_SYMTAB, when the - // referenced symbol table contain the escape value SHN_XINDEX - SHT_SYMTAB_SHNDX = 0x12U, - - // Start of target-specific flags. - - // Exception Index table - SHT_ARM_EXIDX = 0x70000001U, - // BPABI DLL dynamic linking pre-emption map - SHT_ARM_PREEMPTMAP = 0x70000002U, - // Object file compatibility attributes - SHT_ARM_ATTRIBUTES = 0x70000003U, - SHT_ARM_DEBUGOVERLAY = 0x70000004U, - SHT_ARM_OVERLAYSECTION = 0x70000005U, - - LAST_KNOWN_SECTION_TYPE = SHT_ARM_OVERLAYSECTION - }; - - /// Valid section flags. - enum { - // The section contains data that should be writable. - SHF_WRITE = 0x1U, - - // The section occupies memory during execution. - SHF_ALLOC = 0x2U, - - // The section contains executable machine instructions. - SHF_EXECINSTR = 0x4U, - - // The data in the section may be merged to eliminate duplication. - SHF_MERGE = 0x10U, - - // Elements in the section consist of null-terminated character strings. - SHF_STRINGS = 0x20U, - - // A field in this section holds a section header table index. - SHF_INFO_LINK = 0x40U, - - // Adds special ordering requirements for link editors. - SHF_LINK_ORDER = 0x80U, - - // This section requires special OS-specific processing to avoid incorrect - // behavior. - SHF_OS_NONCONFORMING = 0x100U, - - // This section is a member of a section group. - SHF_GROUP = 0x200U, - - // This section holds Thread-Local Storage. - SHF_TLS = 0x400U, - - - // Start of target-specific flags. - - /// XCORE_SHF_CP_SECTION - All sections with the "c" flag are grouped - /// together by the linker to form the constant pool and the cp register is - /// set to the start of the constant pool by the boot code. - XCORE_SHF_CP_SECTION = 0x800U, - - /// XCORE_SHF_DP_SECTION - All sections with the "d" flag are grouped - /// together by the linker to form the data section and the dp register is - /// set to the start of the section by the boot code. - XCORE_SHF_DP_SECTION = 0x1000U - }; - StringRef getSectionName() const { return SectionName; } unsigned getType() const { return Type; } unsigned getFlags() const { return Flags; } @@ -188,11 +64,12 @@ public: void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS) const; virtual bool UseCodeAlign() const; + virtual bool isVirtualSection() const; /// isBaseAddressKnownZero - We know that non-allocatable sections (like /// debug info) have a base of zero. virtual bool isBaseAddressKnownZero() const { - return (getFlags() & SHF_ALLOC) == 0; + return (getFlags() & ELF::SHF_ALLOC) == 0; } static bool classof(const MCSection *S) { diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h index f409f3253b..7633515f27 100644 --- a/include/llvm/MC/MCSectionMachO.h +++ b/include/llvm/MC/MCSectionMachO.h @@ -166,6 +166,7 @@ public: virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS) const; virtual bool UseCodeAlign() const; + virtual bool isVirtualSection() const; static bool classof(const MCSection *S) { return S->getVariant() == SV_MachO; diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 089650cb88..4fdbc44b25 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -14,8 +14,10 @@ #ifndef LLVM_MC_MCSTREAMER_H #define LLVM_MC_MCSTREAMER_H -#include "llvm/System/DataTypes.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" #include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" namespace llvm { class MCAsmInfo; @@ -28,6 +30,7 @@ namespace llvm { class MCSymbol; class StringRef; class TargetAsmBackend; + class TargetLoweringObjectFile; class Twine; class raw_ostream; class formatted_raw_ostream; @@ -47,22 +50,34 @@ namespace llvm { MCStreamer(const MCStreamer&); // DO NOT IMPLEMENT MCStreamer &operator=(const MCStreamer&); // DO NOT IMPLEMENT - protected: - MCStreamer(MCContext &Ctx); + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + bool isPCRel, unsigned AddrSpace); - /// CurSection - This is the current section code is being emitted to, it is - /// kept up to date by SwitchSection. - const MCSection *CurSection; + std::vector<MCDwarfFrameInfo> FrameInfos; + MCDwarfFrameInfo *getCurrentFrameInfo(); + void EnsureValidFrame(); - /// PrevSection - This is the previous section code is being emitted to, it - /// is kept up to date by SwitchSection. - const MCSection *PrevSection; + /// SectionStack - This is stack of current and previous section + /// values saved by PushSection. + SmallVector<std::pair<const MCSection *, + const MCSection *>, 4> SectionStack; + + protected: + MCStreamer(MCContext &Ctx); public: virtual ~MCStreamer(); MCContext &getContext() const { return Context; } + unsigned getNumFrameInfos() { + return FrameInfos.size(); + } + + const MCDwarfFrameInfo &getFrameInfo(unsigned i) { + return FrameInfos[i]; + } + /// @name Assembly File Formatting. /// @{ @@ -98,17 +113,61 @@ namespace llvm { /// getCurrentSection - Return the current section that the streamer is /// emitting code to. - const MCSection *getCurrentSection() const { return CurSection; } + const MCSection *getCurrentSection() const { + if (!SectionStack.empty()) + return SectionStack.back().first; + return NULL; + } /// getPreviousSection - Return the previous section that the streamer is /// emitting code to. - const MCSection *getPreviousSection() const { return PrevSection; } + const MCSection *getPreviousSection() const { + if (!SectionStack.empty()) + return SectionStack.back().second; + return NULL; + } + + /// ChangeSection - Update streamer for a new active section. + /// + /// This is called by PopSection and SwitchSection, if the current + /// section changes. + virtual void ChangeSection(const MCSection *) = 0; + + /// pushSection - Save the current and previous section on the + /// section stack. + void PushSection() { + SectionStack.push_back(std::make_pair(getCurrentSection(), + getPreviousSection())); + } + + /// popSection - Restore the current and previous section from + /// the section stack. Calls ChangeSection as needed. + /// + /// Returns false if the stack was empty. + bool PopSection() { + if (SectionStack.size() <= 1) + return false; + const MCSection *oldSection = SectionStack.pop_back_val().first; + const MCSection *curSection = SectionStack.back().first; + + if (oldSection != curSection) + ChangeSection(curSection); + return true; + } /// SwitchSection - Set the current section where code is being emitted to /// @p Section. This is required to update CurSection. /// /// This corresponds to assembler directives like .section, .text, etc. - virtual void SwitchSection(const MCSection *Section) = 0; + void SwitchSection(const MCSection *Section) { + assert(Section && "Cannot switch to a null section!"); + const MCSection *curSection = SectionStack.back().first; + SectionStack.back().second = curSection; + if (Section != curSection) { + SectionStack.back().first = Section; + ChangeSection(Section); + } + } /// InitSections - Create the default sections and set the initial one. virtual void InitSections() = 0; @@ -240,14 +299,25 @@ namespace llvm { /// @param Value - The value to emit. /// @param Size - The size of the integer (in bytes) to emit. This must /// match a native machine width. - virtual void EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace = 0) = 0; + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace) = 0; + + void EmitValue(const MCExpr *Value, unsigned Size, unsigned AddrSpace = 0); + + void EmitPCRelValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace = 0); /// EmitIntValue - Special case of EmitValue that avoids the client having /// to pass in a MCExpr for constant integers. virtual void EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace = 0); + /// EmitAbsValue - Emit the Value, but try to avoid relocations. On MachO + /// this is done by producing + /// foo = value + /// .long foo + void EmitAbsValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace = 0); virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0) = 0; @@ -257,23 +327,26 @@ namespace llvm { /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. - virtual void EmitULEB128IntValue(uint64_t Value, unsigned AddrSpace = 0); + void EmitULEB128IntValue(uint64_t Value, unsigned AddrSpace = 0); /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. - virtual void EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace = 0); + void EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace = 0); /// EmitSymbolValue - Special case of EmitValue that avoids the client /// having to pass in a MCExpr for MCSymbols. - virtual void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, - unsigned AddrSpace = 0); + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + unsigned AddrSpace = 0); + + void EmitPCRelSymbolValue(const MCSymbol *Sym, unsigned Size, + unsigned AddrSpace = 0); /// EmitGPRel32Value - Emit the expression @p Value into the output as a /// gprel32 (32-bit GP relative) value. /// /// This is used to implement assembler directives such as .gprel32 on /// targets that support them. - virtual void EmitGPRel32Value(const MCExpr *Value) = 0; + virtual void EmitGPRel32Value(const MCExpr *Value); /// EmitFill - Emit NumBytes bytes worth of the value specified by /// FillValue. This implements directives such as '.space'. @@ -342,7 +415,37 @@ namespace llvm { /// EmitDwarfFileDirective - Associate a filename with a specified logical /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler /// directive. - virtual void EmitDwarfFileDirective(unsigned FileNo,StringRef Filename) = 0; + virtual bool EmitDwarfFileDirective(unsigned FileNo,StringRef Filename); + + /// EmitDwarfLocDirective - This implements the DWARF2 + // '.loc fileno lineno ...' assembler directive. + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, + unsigned Discriminator); + + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label) = 0; + + virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label) { + } + + void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, + int PointerSize); + + virtual bool EmitCFIStartProc(); + virtual bool EmitCFIEndProc(); + virtual bool EmitCFIDefCfa(int64_t Register, int64_t Offset); + virtual bool EmitCFIDefCfaOffset(int64_t Offset); + virtual bool EmitCFIDefCfaRegister(int64_t Register); + virtual bool EmitCFIOffset(int64_t Register, int64_t Offset); + virtual bool EmitCFIPersonality(const MCSymbol *Sym, + unsigned Encoding); + virtual bool EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + virtual bool EmitCFIRememberState(); + virtual bool EmitCFIRestoreState(); /// EmitInstruction - Emit the given @p Instruction into the current /// section. @@ -354,6 +457,19 @@ namespace llvm { virtual void EmitRawText(StringRef String); void EmitRawText(const Twine &String); + /// ARM-related methods. + /// FIXME: Eventually we should have some "target MC streamer" and move + /// these methods there. + virtual void EmitFnStart(); + virtual void EmitFnEnd(); + virtual void EmitCantUnwind(); + virtual void EmitPersonality(const MCSymbol *Personality); + virtual void EmitHandlerData(); + virtual void EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0); + virtual void EmitPad(int64_t Offset); + virtual void EmitRegSave(const SmallVectorImpl<unsigned> &RegList, + bool isVector); + /// Finish - Finish emission of machine code. virtual void Finish() = 0; }; @@ -373,12 +489,18 @@ namespace llvm { /// \param CE - If given, a code emitter to use to show the instruction /// encoding inline with the assembly. This method takes ownership of \arg CE. /// + /// \param TAB - If given, a target asm backend to use to show the fixup + /// information in conjunction with encoding information. This method takes + /// ownership of \arg TAB. + /// /// \param ShowInst - Whether to show the MCInst representation inline with /// the assembly. MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isLittleEndian, bool isVerboseAsm, + bool isVerboseAsm, + bool useLoc, MCInstPrinter *InstPrint = 0, MCCodeEmitter *CE = 0, + TargetAsmBackend *TAB = 0, bool ShowInst = false); /// createMachOStreamer - Create a machine code streamer which will generate @@ -402,7 +524,7 @@ namespace llvm { /// ELF format object files. MCStreamer *createELFStreamer(MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll = false); + bool RelaxAll, bool NoExecStack); /// createLoggingStreamer - Create a machine code streamer which just logs the /// API calls and then dispatches to another streamer. @@ -410,6 +532,13 @@ namespace llvm { /// The new streamer takes ownership of the \arg Child. MCStreamer *createLoggingStreamer(MCStreamer *Child, raw_ostream &OS); + /// createPureStreamer - Create a machine code streamer which will generate + /// "pure" MC object files, for use with MC-JIT and testing tools. + /// + /// Takes ownership of \arg TAB and \arg CE. + MCStreamer *createPureStreamer(MCContext &Ctx, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE); + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCValue.h b/include/llvm/MC/MCValue.h index 11b6c2a17b..df8dbd930b 100644 --- a/include/llvm/MC/MCValue.h +++ b/include/llvm/MC/MCValue.h @@ -14,7 +14,7 @@ #ifndef LLVM_MC_MCVALUE_H #define LLVM_MC_MCVALUE_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/MC/MCSymbol.h" #include <cassert> diff --git a/include/llvm/Metadata.h b/include/llvm/Metadata.h index a6c3f039a1..6a61996ff7 100644 --- a/include/llvm/Metadata.h +++ b/include/llvm/Metadata.h @@ -17,6 +17,7 @@ #define LLVM_METADATA_H #include "llvm/Value.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ilist_node.h" @@ -117,6 +118,8 @@ class MDNode : public Value, public FoldingSetNode { FunctionLocalness FL, bool Insert = true); public: // Constructors and destructors. + static MDNode *get(LLVMContext &Context, ArrayRef<Value*> V); + // FIXME: Eliminate this constructor form. static MDNode *get(LLVMContext &Context, Value *const *Vals, unsigned NumVals); // getWhenValsUnresolved - Construct MDNode determining function-localness diff --git a/include/llvm/Module.h b/include/llvm/Module.h index b7880ca2cb..c7063f5e1c 100644 --- a/include/llvm/Module.h +++ b/include/llvm/Module.h @@ -20,7 +20,7 @@ #include "llvm/GlobalAlias.h" #include "llvm/Metadata.h" #include "llvm/ADT/OwningPtr.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <vector> namespace llvm { @@ -211,15 +211,20 @@ public: void setTargetTriple(StringRef T) { TargetTriple = T; } /// Set the module-scope inline assembly blocks. - void setModuleInlineAsm(StringRef Asm) { GlobalScopeAsm = Asm; } + void setModuleInlineAsm(StringRef Asm) { + GlobalScopeAsm = Asm; + if (!GlobalScopeAsm.empty() && + GlobalScopeAsm[GlobalScopeAsm.size()-1] != '\n') + GlobalScopeAsm += '\n'; + } /// Append to the module-scope inline assembly blocks, automatically inserting /// a separating newline if necessary. void appendModuleInlineAsm(StringRef Asm) { + GlobalScopeAsm += Asm; if (!GlobalScopeAsm.empty() && GlobalScopeAsm[GlobalScopeAsm.size()-1] != '\n') GlobalScopeAsm += '\n'; - GlobalScopeAsm += Asm; } /// @} diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h new file mode 100644 index 0000000000..31cd523ea2 --- /dev/null +++ b/include/llvm/Object/MachOFormat.h @@ -0,0 +1,367 @@ +//===- MachOFormat.h - Mach-O Format Structures And Constants ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares various structures and constants which are platform +// independent and can be shared by any client which wishes to interact with +// Mach object files. +// +// The definitions here are purposely chosen to match the LLVM style as opposed +// to following the platform specific definition of the format. +// +// On a Mach system, see the <mach-o/...> includes for more information, in +// particular <mach-o/loader.h>. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MACHOFORMAT_H +#define LLVM_OBJECT_MACHOFORMAT_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { +namespace object { + +/// General Mach platform information. +namespace mach { + /// @name CPU Type and Subtype Information + /// { + + /// \brief Capability bits used in CPU type encoding. + enum CPUTypeFlagsMask { + CTFM_ArchMask = 0xFF000000, + CTFM_ArchABI64 = 0x01000000 + }; + + /// \brief Machine type IDs used in CPU type encoding. + enum CPUTypeMachine { + CTM_i386 = 7, + CTM_x86_64 = CTM_i386 | CTFM_ArchABI64, + CTM_ARM = 12, + CTM_SPARC = 14, + CTM_PowerPC = 18, + CTM_PowerPC64 = CTM_PowerPC | CTFM_ArchABI64 + }; + + /// \brief Capability bits used in CPU subtype encoding. + enum CPUSubtypeFlagsMask { + CSFM_SubtypeMask = 0xFF000000, + CSFM_SubtypeLib64 = 0x80000000 + }; + + /// \brief ARM Machine Subtypes. + enum CPUSubtypeARM { + CSARM_ALL = 0, + CSARM_V4T = 5, + CSARM_V6 = 6, + CSARM_V5TEJ = 7, + CSARM_XSCALE = 8, + CSARM_V7 = 9 + }; + + /// \brief PowerPC Machine Subtypes. + enum CPUSubtypePowerPC { + CSPPC_ALL = 0 + }; + + /// \brief SPARC Machine Subtypes. + enum CPUSubtypeSPARC { + CSSPARC_ALL = 0 + }; + + /// \brief x86 Machine Subtypes. + enum CPUSubtypeX86 { + CSX86_ALL = 3 + }; + + /// @} + +} // end namespace mach + +/// Format information for Mach object files. +namespace macho { + /// \brief Constants for structure sizes. + enum StructureSizes { + Header32Size = 28, + Header64Size = 32, + SegmentLoadCommand32Size = 56, + SegmentLoadCommand64Size = 72, + Section32Size = 68, + Section64Size = 80, + SymtabLoadCommandSize = 24, + DysymtabLoadCommandSize = 80, + Nlist32Size = 12, + Nlist64Size = 16, + RelocationInfoSize = 8 + }; + + /// \brief Constants for header magic field. + enum HeaderMagic { + HM_Object32 = 0xFEEDFACE, ///< 32-bit mach object file + HM_Object64 = 0xFEEDFACF, ///< 64-bit mach object file + HM_Universal = 0xCAFEBABE ///< Universal object file + }; + + /// \brief Header common to all Mach object files. + struct Header { + uint32_t Magic; + uint32_t CPUType; + uint32_t CPUSubtype; + uint32_t FileType; + uint32_t NumLoadCommands; + uint32_t SizeOfLoadCommands; + uint32_t Flags; + }; + + /// \brief Extended header for 64-bit object files. + struct Header64Ext { + uint32_t Reserved; + }; + + // See <mach-o/loader.h>. + enum HeaderFileType { + HFT_Object = 0x1 + }; + + enum HeaderFlags { + HF_SubsectionsViaSymbols = 0x2000 + }; + + enum LoadCommandType { + LCT_Segment = 0x1, + LCT_Symtab = 0x2, + LCT_Dysymtab = 0xb, + LCT_Segment64 = 0x19, + LCT_UUID = 0x1b + }; + + /// \brief Load command structure. + struct LoadCommand { + uint32_t Type; + uint32_t Size; + }; + + /// @name Load Command Structures + /// @{ + + struct SegmentLoadCommand { + uint32_t Type; + uint32_t Size; + char Name[16]; + uint32_t VMAddress; + uint32_t VMSize; + uint32_t FileOffset; + uint32_t FileSize; + uint32_t MaxVMProtection; + uint32_t InitialVMProtection; + uint32_t NumSections; + uint32_t Flags; + }; + + struct Segment64LoadCommand { + uint32_t Type; + uint32_t Size; + char Name[16]; + uint64_t VMAddress; + uint64_t VMSize; + uint64_t FileOffset; + uint64_t FileSize; + uint32_t MaxVMProtection; + uint32_t InitialVMProtection; + uint32_t NumSections; + uint32_t Flags; + }; + + struct SymtabLoadCommand { + uint32_t Type; + uint32_t Size; + uint32_t SymbolTableOffset; + uint32_t NumSymbolTableEntries; + uint32_t StringTableOffset; + uint32_t StringTableSize; + }; + + struct DysymtabLoadCommand { + uint32_t Type; + uint32_t Size; + + uint32_t LocalSymbolsIndex; + uint32_t NumLocalSymbols; + + uint32_t ExternalSymbolsIndex; + uint32_t NumExternalSymbols; + + uint32_t UndefinedSymbolsIndex; + uint32_t NumUndefinedSymbols; + + uint32_t TOCOffset; + uint32_t NumTOCEntries; + + uint32_t ModuleTableOffset; + uint32_t NumModuleTableEntries; + + uint32_t ReferenceSymbolTableOffset; + uint32_t NumReferencedSymbolTableEntries; + + uint32_t IndirectSymbolTableOffset; + uint32_t NumIndirectSymbolTableEntries; + + uint32_t ExternalRelocationTableOffset; + uint32_t NumExternalRelocationTableEntries; + + uint32_t LocalRelocationTableOffset; + uint32_t NumLocalRelocationTableEntries; + }; + + /// @} + /// @name Section Data + /// @{ + + struct Section { + char Name[16]; + char SegmentName[16]; + uint32_t Address; + uint32_t Size; + uint32_t Offset; + uint32_t Align; + uint32_t RelocationTableOffset; + uint32_t NumRelocationTableEntries; + uint32_t Flags; + uint32_t Reserved1; + uint32_t Reserved2; + }; + struct Section64 { + char Name[16]; + char SegmentName[16]; + uint64_t Address; + uint64_t Size; + uint32_t Offset; + uint32_t Align; + uint32_t RelocationTableOffset; + uint32_t NumRelocationTableEntries; + uint32_t Flags; + uint32_t Reserved1; + uint32_t Reserved2; + uint32_t Reserved3; + }; + + /// @} + /// @name Symbol Table Entries + /// @{ + + struct SymbolTableEntry { + uint32_t StringIndex; + uint8_t Type; + uint8_t SectionIndex; + uint16_t Flags; + uint32_t Value; + }; + struct Symbol64TableEntry { + uint32_t StringIndex; + uint8_t Type; + uint8_t SectionIndex; + uint16_t Flags; + uint64_t Value; + }; + + /// @} + /// @name Indirect Symbol Table + /// @{ + + struct IndirectSymbolTableEntry { + uint32_t Index; + }; + + /// @} + /// @name Relocation Data + /// @{ + + struct RelocationEntry { + uint32_t Word0; + uint32_t Word1; + }; + + /// @} + + // See <mach-o/nlist.h>. + enum SymbolTypeType { + STT_Undefined = 0x00, + STT_Absolute = 0x02, + STT_Section = 0x0e + }; + + enum SymbolTypeFlags { + // If any of these bits are set, then the entry is a stab entry number (see + // <mach-o/stab.h>. Otherwise the other masks apply. + STF_StabsEntryMask = 0xe0, + + STF_TypeMask = 0x0e, + STF_External = 0x01, + STF_PrivateExtern = 0x10 + }; + + /// IndirectSymbolFlags - Flags for encoding special values in the indirect + /// symbol entry. + enum IndirectSymbolFlags { + ISF_Local = 0x80000000, + ISF_Absolute = 0x40000000 + }; + + /// RelocationFlags - Special flags for addresses. + enum RelocationFlags { + RF_Scattered = 0x80000000 + }; + + /// Common relocation info types. + enum RelocationInfoType { + RIT_Vanilla = 0, + RIT_Pair = 1, + RIT_Difference = 2 + }; + + /// Generic relocation info types, which are shared by some (but not all) + /// platforms. + enum RelocationInfoType_Generic { + RIT_Generic_PreboundLazyPointer = 3, + RIT_Generic_LocalDifference = 4, + RIT_Generic_TLV = 5 + }; + + /// X86_64 uses its own relocation types. + enum RelocationInfoTypeX86_64 { + // Note that x86_64 doesn't even share the common relocation types. + RIT_X86_64_Unsigned = 0, + RIT_X86_64_Signed = 1, + RIT_X86_64_Branch = 2, + RIT_X86_64_GOTLoad = 3, + RIT_X86_64_GOT = 4, + RIT_X86_64_Subtractor = 5, + RIT_X86_64_Signed1 = 6, + RIT_X86_64_Signed2 = 7, + RIT_X86_64_Signed4 = 8, + RIT_X86_64_TLV = 9 + }; + + /// ARM uses its own relocation types. + enum RelocationInfoTypeARM { + RIT_ARM_LocalDifference = 3, + RIT_ARM_PreboundLazyPointer = 4, + RIT_ARM_Branch24Bit = 5, + RIT_ARM_ThumbBranch22Bit = 6, + RIT_ARM_ThumbBranch32Bit = 7, + RIT_ARM_Half = 8, + RIT_ARM_HalfDifference = 9 + + }; + +} // end namespace macho + +} // end namespace object +} // end namespace llvm + +#endif diff --git a/include/llvm/Object/MachOObject.h b/include/llvm/Object/MachOObject.h new file mode 100644 index 0000000000..03d9c147b4 --- /dev/null +++ b/include/llvm/Object/MachOObject.h @@ -0,0 +1,180 @@ +//===- MachOObject.h - Mach-O Object File Wrapper ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MACHOOBJECT_H +#define LLVM_OBJECT_MACHOOBJECT_H + +#include <string> +#include "llvm/ADT/InMemoryStruct.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Object/MachOFormat.h" + +namespace llvm { + +class MemoryBuffer; + +namespace object { + +/// \brief Wrapper object for manipulating Mach-O object files. +/// +/// This class is designed to implement a full-featured, efficient, portable, +/// and robust Mach-O interface to Mach-O object files. It does not attempt to +/// smooth over rough edges in the Mach-O format or generalize access to object +/// independent features. +/// +/// The class is designed around accessing the Mach-O object which is expected +/// to be fully loaded into memory. +/// +/// This class is *not* suitable for concurrent use. For efficient operation, +/// the class uses APIs which rely on the ability to cache the results of +/// certain calls in internal objects which are not safe for concurrent +/// access. This allows the API to be zero-copy on the common paths. +// +// FIXME: It would be cool if we supported a "paged" MemoryBuffer +// implementation. This would allow us to implement a more sensible version of +// MemoryObject which can work like a MemoryBuffer, but be more efficient for +// objects which are in the current address space. +class MachOObject { +public: + struct LoadCommandInfo { + /// The load command information. + macho::LoadCommand Command; + + /// The offset to the start of the load command in memory. + uint64_t Offset; + }; + +private: + OwningPtr<MemoryBuffer> Buffer; + + /// Whether the object is little endian. + bool IsLittleEndian; + /// Whether the object is 64-bit. + bool Is64Bit; + /// Whether the object is swapped endianness from the host. + bool IsSwappedEndian; + /// Whether the string table has been registered. + bool HasStringTable; + + /// The cached information on the load commands. + LoadCommandInfo *LoadCommands; + mutable unsigned NumLoadedCommands; + + /// The cached copy of the header. + macho::Header Header; + macho::Header64Ext Header64Ext; + + /// Cache string table information. + StringRef StringTable; + +private: + MachOObject(MemoryBuffer *Buffer, bool IsLittleEndian, bool Is64Bit); + +public: + ~MachOObject(); + + /// \brief Load a Mach-O object from a MemoryBuffer object. + /// + /// \param Buffer - The buffer to load the object from. This routine takes + /// exclusive ownership of the buffer (which is passed to the returned object + /// on success). + /// \param ErrorStr [out] - If given, will be set to a user readable error + /// message on failure. + /// \returns The loaded object, or null on error. + static MachOObject *LoadFromBuffer(MemoryBuffer *Buffer, + std::string *ErrorStr = 0); + + /// @name File Information + /// @{ + + bool isLittleEndian() const { return IsLittleEndian; } + bool isSwappedEndian() const { return IsSwappedEndian; } + bool is64Bit() const { return Is64Bit; } + + unsigned getHeaderSize() const { + return Is64Bit ? macho::Header64Size : macho::Header32Size; + } + + StringRef getData(size_t Offset, size_t Size) const; + + /// @} + /// @name String Table Data + /// @{ + + StringRef getStringTableData() const { + assert(HasStringTable && "String table has not been registered!"); + return StringTable; + } + + StringRef getStringAtIndex(unsigned Index) const { + size_t End = getStringTableData().find('\0', Index); + return getStringTableData().slice(Index, End); + } + + void RegisterStringTable(macho::SymtabLoadCommand &SLC); + + /// @} + /// @name Object Header Access + /// @{ + + const macho::Header &getHeader() const { return Header; } + const macho::Header64Ext &getHeader64Ext() const { + assert(is64Bit() && "Invalid access!"); + return Header64Ext; + } + + /// @} + /// @name Object Structure Access + /// @{ + + /// \brief Retrieve the information for the given load command. + const LoadCommandInfo &getLoadCommandInfo(unsigned Index) const; + + void ReadSegmentLoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct<macho::SegmentLoadCommand> &Res) const; + void ReadSegment64LoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct<macho::Segment64LoadCommand> &Res) const; + void ReadSymtabLoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct<macho::SymtabLoadCommand> &Res) const; + void ReadDysymtabLoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct<macho::DysymtabLoadCommand> &Res) const; + void ReadIndirectSymbolTableEntry( + const macho::DysymtabLoadCommand &DLC, + unsigned Index, + InMemoryStruct<macho::IndirectSymbolTableEntry> &Res) const; + void ReadSection( + const LoadCommandInfo &LCI, + unsigned Index, + InMemoryStruct<macho::Section> &Res) const; + void ReadSection64( + const LoadCommandInfo &LCI, + unsigned Index, + InMemoryStruct<macho::Section64> &Res) const; + void ReadRelocationEntry( + uint64_t RelocationTableOffset, unsigned Index, + InMemoryStruct<macho::RelocationEntry> &Res) const; + void ReadSymbolTableEntry( + uint64_t SymbolTableOffset, unsigned Index, + InMemoryStruct<macho::SymbolTableEntry> &Res) const; + void ReadSymbol64TableEntry( + uint64_t SymbolTableOffset, unsigned Index, + InMemoryStruct<macho::Symbol64TableEntry> &Res) const; + + /// @} +}; + +} // end namespace object +} // end namespace llvm + +#endif diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index ca51581434..eee9d447cd 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -15,7 +15,8 @@ #define LLVM_OBJECT_OBJECT_FILE_H #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" +#include <cstring> namespace llvm { @@ -25,7 +26,19 @@ class StringRef; namespace object { class ObjectFile; -typedef uint64_t DataRefImpl; + +union DataRefImpl { + struct { + uint32_t a, b; + } d; + intptr_t p; +}; + +static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; +} /// SymbolRef - This is a value type class that represents a single symbol in /// the list of symbols in the object file. diff --git a/include/llvm/OperandTraits.h b/include/llvm/OperandTraits.h index b614ccbc37..f0df5fa9bd 100644 --- a/include/llvm/OperandTraits.h +++ b/include/llvm/OperandTraits.h @@ -27,27 +27,17 @@ namespace llvm { /// when it is a prefix to the User object, and the number of Use objects is /// known at compile time. -template <unsigned ARITY> +template <typename SubClass, unsigned ARITY> struct FixedNumOperandTraits { - static Use *op_begin(User* U) { + static Use *op_begin(SubClass* U) { return reinterpret_cast<Use*>(U) - ARITY; } - static Use *op_end(User* U) { + static Use *op_end(SubClass* U) { return reinterpret_cast<Use*>(U); } static unsigned operands(const User*) { return ARITY; } - struct prefix { - Use Ops[ARITY]; - prefix(); // DO NOT IMPLEMENT - }; - template <class U> - struct Layout { - struct overlay : public prefix, public U { - overlay(); // DO NOT IMPLEMENT - }; - }; }; //===----------------------------------------------------------------------===// @@ -57,8 +47,8 @@ struct FixedNumOperandTraits { /// OptionalOperandTraits - when the number of operands may change at runtime. /// Naturally it may only decrease, because the allocations may not change. -template <unsigned ARITY = 1> -struct OptionalOperandTraits : public FixedNumOperandTraits<ARITY> { +template <typename SubClass, unsigned ARITY = 1> +struct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> { static unsigned operands(const User *U) { return U->getNumOperands(); } @@ -72,12 +62,12 @@ struct OptionalOperandTraits : public FixedNumOperandTraits<ARITY> { /// when it is a prefix to the User object, and the number of Use objects is /// only known at allocation time. -template <unsigned MINARITY = 0> +template <typename SubClass, unsigned MINARITY = 0> struct VariadicOperandTraits { - static Use *op_begin(User* U) { - return reinterpret_cast<Use*>(U) - U->getNumOperands(); + static Use *op_begin(SubClass* U) { + return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands(); } - static Use *op_end(User* U) { + static Use *op_end(SubClass* U) { return reinterpret_cast<Use*>(U); } static unsigned operands(const User *U) { diff --git a/include/llvm/Operator.h b/include/llvm/Operator.h index 3aae586f14..ff2a0ad5e4 100644 --- a/include/llvm/Operator.h +++ b/include/llvm/Operator.h @@ -106,12 +106,14 @@ public: static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Add || I->getOpcode() == Instruction::Sub || - I->getOpcode() == Instruction::Mul; + I->getOpcode() == Instruction::Mul || + I->getOpcode() == Instruction::Shl; } static inline bool classof(const ConstantExpr *CE) { return CE->getOpcode() == Instruction::Add || CE->getOpcode() == Instruction::Sub || - CE->getOpcode() == Instruction::Mul; + CE->getOpcode() == Instruction::Mul || + CE->getOpcode() == Instruction::Shl; } static inline bool classof(const Value *V) { return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || @@ -119,105 +121,97 @@ public: } }; -/// AddOperator - Utility class for integer addition operators. -/// -class AddOperator : public OverflowingBinaryOperator { - ~AddOperator(); // do not implement -public: - static inline bool classof(const AddOperator *) { return true; } - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Add; - } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::Add; - } - static inline bool classof(const Value *V) { - return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || - (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); - } -}; - -/// SubOperator - Utility class for integer subtraction operators. -/// -class SubOperator : public OverflowingBinaryOperator { - ~SubOperator(); // do not implement -public: - static inline bool classof(const SubOperator *) { return true; } - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Sub; - } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::Sub; - } - static inline bool classof(const Value *V) { - return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || - (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); - } -}; - -/// MulOperator - Utility class for integer multiplication operators. -/// -class MulOperator : public OverflowingBinaryOperator { - ~MulOperator(); // do not implement -public: - static inline bool classof(const MulOperator *) { return true; } - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Mul; - } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::Mul; - } - static inline bool classof(const Value *V) { - return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || - (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); - } -}; - -/// SDivOperator - An Operator with opcode Instruction::SDiv. -/// -class SDivOperator : public Operator { +/// PossiblyExactOperator - A udiv or sdiv instruction, which can be marked as +/// "exact", indicating that no bits are destroyed. +class PossiblyExactOperator : public Operator { public: enum { IsExact = (1 << 0) }; - -private: - ~SDivOperator(); // do not implement - + friend class BinaryOperator; friend class ConstantExpr; void setIsExact(bool B) { SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); } - + +private: + ~PossiblyExactOperator(); // do not implement public: /// isExact - Test whether this division is known to be exact, with /// zero remainder. bool isExact() const { return SubclassOptionalData & IsExact; } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SDivOperator *) { return true; } + + static bool isPossiblyExactOpcode(unsigned OpC) { + return OpC == Instruction::SDiv || + OpC == Instruction::UDiv || + OpC == Instruction::AShr || + OpC == Instruction::LShr; + } static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::SDiv; + return isPossiblyExactOpcode(CE->getOpcode()); } static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::SDiv; + return isPossiblyExactOpcode(I->getOpcode()); } static inline bool classof(const Value *V) { return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); } }; + -class GEPOperator : public Operator { + +/// ConcreteOperator - A helper template for defining operators for individual +/// opcodes. +template<typename SuperClass, unsigned Opc> +class ConcreteOperator : public SuperClass { + ~ConcreteOperator(); // DO NOT IMPLEMENT +public: + static inline bool classof(const ConcreteOperator<SuperClass, Opc> *) { + return true; + } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Opc; + } + static inline bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Opc; + } + static inline bool classof(const Value *V) { + return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || + (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); + } +}; + +class AddOperator + : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> {}; +class SubOperator + : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> {}; +class MulOperator + : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> {}; +class ShlOperator + : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> {}; + + +class SDivOperator + : public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> {}; +class UDivOperator + : public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> {}; +class AShrOperator + : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> {}; +class LShrOperator + : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> {}; + + + +class GEPOperator + : public ConcreteOperator<Operator, Instruction::GetElementPtr> { enum { IsInBounds = (1 << 0) }; - ~GEPOperator(); // do not implement - friend class GetElementPtrInst; friend class ConstantExpr; void setIsInBounds(bool B) { @@ -266,8 +260,8 @@ public: /// value, just potentially different types. bool hasAllZeroIndices() const { for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { - if (Constant *C = dyn_cast<Constant>(I)) - if (C->isNullValue()) + if (ConstantInt *C = dyn_cast<ConstantInt>(I)) + if (C->isZero()) continue; return false; } @@ -284,21 +278,6 @@ public: } return true; } - - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const GEPOperator *) { return true; } - static inline bool classof(const GetElementPtrInst *) { return true; } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::GetElementPtr; - } - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::GetElementPtr; - } - static inline bool classof(const Value *V) { - return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || - (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); - } }; } // End llvm namespace diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h index d00d0c0d6d..082790956c 100644 --- a/include/llvm/PassSupport.h +++ b/include/llvm/PassSupport.h @@ -24,7 +24,7 @@ #include "Pass.h" #include "llvm/PassRegistry.h" #include "llvm/InitializePasses.h" -#include "llvm/System/Atomic.h" +#include "llvm/Support/Atomic.h" #include <vector> namespace llvm { diff --git a/include/llvm/System/AIXDataTypesFix.h b/include/llvm/Support/AIXDataTypesFix.h index 8dbf02f282..a9a9147de2 100644 --- a/include/llvm/System/AIXDataTypesFix.h +++ b/include/llvm/Support/AIXDataTypesFix.h @@ -1,4 +1,4 @@ -//===-- llvm/System/AIXDataTypesFix.h - Fix datatype defs ------*- C++ -*-===// +//===-- llvm/Support/AIXDataTypesFix.h - Fix datatype defs ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index 979e5975aa..cebfa7982d 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -49,7 +49,7 @@ struct AlignOf { }; -/// alignOf - A templated function that returns the mininum alignment of +/// alignOf - A templated function that returns the minimum alignment of /// of a type. This provides no extra functionality beyond the AlignOf /// class besides some cosmetic cleanliness. Example usage: /// alignOf<int>() returns the alignment of an int. diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index f3c53d14e5..c6807099f8 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -16,13 +16,15 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/MathExtras.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <algorithm> #include <cassert> #include <cstdlib> #include <cstddef> namespace llvm { +template <typename T> struct ReferenceAdder { typedef T& result; }; +template <typename T> struct ReferenceAdder<T&> { typedef T result; }; class MallocAllocator { public: diff --git a/include/llvm/System/Atomic.h b/include/llvm/Support/Atomic.h index fc19369d11..1a6c606aa5 100644 --- a/include/llvm/System/Atomic.h +++ b/include/llvm/Support/Atomic.h @@ -1,4 +1,4 @@ -//===- llvm/System/Atomic.h - Atomic Operations -----------------*- C++ -*-===// +//===- llvm/Support/Atomic.h - Atomic Operations -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_ATOMIC_H #define LLVM_SYSTEM_ATOMIC_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { namespace sys { diff --git a/include/llvm/Support/CFG.h b/include/llvm/Support/CFG.h index 9ba71fcca8..d2ea12364e 100644 --- a/include/llvm/Support/CFG.h +++ b/include/llvm/Support/CFG.h @@ -41,6 +41,7 @@ class PredIterator : public std::iterator<std::forward_iterator_tag, public: typedef typename super::pointer pointer; + PredIterator() {} explicit inline PredIterator(Ptr *bb) : It(bb->use_begin()) { advancePastNonTerminators(); } @@ -64,6 +65,12 @@ public: inline Self operator++(int) { // Postincrement Self tmp = *this; ++*this; return tmp; } + + /// getOperandNo - Return the operand number in the predecessor's + /// terminator of the successor. + unsigned getOperandNo() const { + return It.getOperandNo(); + } }; typedef PredIterator<BasicBlock, Value::use_iterator> pred_iterator; diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 46fe269a23..673925593e 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -23,7 +23,7 @@ #ifndef LLVM_SUPPORT_WIN_COFF_H #define LLVM_SUPPORT_WIN_COFF_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cstring> namespace llvm { diff --git a/include/llvm/Support/CallSite.h b/include/llvm/Support/CallSite.h index 571a04924d..8a998a8cd0 100644 --- a/include/llvm/Support/CallSite.h +++ b/include/llvm/Support/CallSite.h @@ -52,11 +52,6 @@ public: CallSiteBase(CallTy *CI) : I(CI, true) { assert(CI); } CallSiteBase(InvokeTy *II) : I(II, false) { assert(II); } CallSiteBase(ValTy *II) { *this = get(II); } - CallSiteBase(InstrTy *II) { - assert(II && "Null instruction given?"); - *this = get(II); - assert(I.getPointer() && "Not a call?"); - } protected: /// CallSiteBase::get - This static method is sort of like a constructor. It /// will create an appropriate call site for a Call or Invoke instruction, but diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 6ac7f9c0b0..67f0fd7e0d 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -15,6 +15,10 @@ #ifndef LLVM_SUPPORT_COMPILER_H #define LLVM_SUPPORT_COMPILER_H +#ifndef __has_feature +# define __has_feature(x) 0 +#endif + /// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked /// into a shared library, then the class should be private to the library and /// not accessible from outside it. Can also be used to mark variables and @@ -107,4 +111,19 @@ #define LLVM_ATTRIBUTE_NORETURN #endif +// LLVM_ATTRIBUTE_DEPRECATED(decl, "message") +#if __has_feature(attribute_deprecated_with_message) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl __attribute__((deprecated(message))) +#elif defined(__GNUC__) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + __declspec(deprecated(message)) decl +#else +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl +#endif + #endif diff --git a/include/llvm/Support/ConstantFolder.h b/include/llvm/Support/ConstantFolder.h index ea6c5fd82a..bd3765d592 100644 --- a/include/llvm/Support/ConstantFolder.h +++ b/include/llvm/Support/ConstantFolder.h @@ -33,50 +33,34 @@ public: // Binary Operators //===--------------------------------------------------------------------===// - Constant *CreateAdd(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getAdd(LHS, RHS); - } - Constant *CreateNSWAdd(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNSWAdd(LHS, RHS); - } - Constant *CreateNUWAdd(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNUWAdd(LHS, RHS); + Constant *CreateAdd(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW); } Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFAdd(LHS, RHS); } - Constant *CreateSub(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getSub(LHS, RHS); - } - Constant *CreateNSWSub(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNSWSub(LHS, RHS); - } - Constant *CreateNUWSub(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNUWSub(LHS, RHS); + Constant *CreateSub(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW); } Constant *CreateFSub(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFSub(LHS, RHS); } - Constant *CreateMul(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getMul(LHS, RHS); - } - Constant *CreateNSWMul(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNSWMul(LHS, RHS); - } - Constant *CreateNUWMul(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNUWMul(LHS, RHS); + Constant *CreateMul(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW); } Constant *CreateFMul(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFMul(LHS, RHS); } - Constant *CreateUDiv(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getUDiv(LHS, RHS); - } - Constant *CreateSDiv(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getSDiv(LHS, RHS); + Constant *CreateUDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getUDiv(LHS, RHS, isExact); } - Constant *CreateExactSDiv(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getExactSDiv(LHS, RHS); + Constant *CreateSDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getSDiv(LHS, RHS, isExact); } Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFDiv(LHS, RHS); @@ -90,14 +74,17 @@ public: Constant *CreateFRem(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFRem(LHS, RHS); } - Constant *CreateShl(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getShl(LHS, RHS); + Constant *CreateShl(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW); } - Constant *CreateLShr(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getLShr(LHS, RHS); + Constant *CreateLShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getLShr(LHS, RHS, isExact); } - Constant *CreateAShr(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getAShr(LHS, RHS); + Constant *CreateAShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getAShr(LHS, RHS, isExact); } Constant *CreateAnd(Constant *LHS, Constant *RHS) const { return ConstantExpr::getAnd(LHS, RHS); @@ -118,14 +105,9 @@ public: // Unary Operators //===--------------------------------------------------------------------===// - Constant *CreateNeg(Constant *C) const { - return ConstantExpr::getNeg(C); - } - Constant *CreateNSWNeg(Constant *C) const { - return ConstantExpr::getNSWNeg(C); - } - Constant *CreateNUWNeg(Constant *C) const { - return ConstantExpr::getNUWNeg(C); + Constant *CreateNeg(Constant *C, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getNeg(C, HasNUW, HasNSW); } Constant *CreateFNeg(Constant *C) const { return ConstantExpr::getFNeg(C); diff --git a/include/llvm/Support/ConstantRange.h b/include/llvm/Support/ConstantRange.h index 792b4107b1..ced3a2cf2d 100644 --- a/include/llvm/Support/ConstantRange.h +++ b/include/llvm/Support/ConstantRange.h @@ -33,7 +33,7 @@ #define LLVM_SUPPORT_CONSTANT_RANGE_H #include "llvm/ADT/APInt.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { @@ -54,7 +54,7 @@ public: /// @brief Initialize a range of values explicitly. This will assert out if /// Lower==Upper and Lower != Min or Max value for its type. It will also /// assert out if the two APInt's are not the same bit width. - ConstantRange(const APInt& Lower, const APInt& Upper); + ConstantRange(const APInt &Lower, const APInt &Upper); /// makeICmpRegion - Produce the smallest range that contains all values that /// might satisfy the comparison specified by Pred when compared to any value diff --git a/include/llvm/Support/DOTGraphTraits.h b/include/llvm/Support/DOTGraphTraits.h index 796c74a21c..3cb8164c3c 100644 --- a/include/llvm/Support/DOTGraphTraits.h +++ b/include/llvm/Support/DOTGraphTraits.h @@ -89,8 +89,9 @@ public: /// If you want to override the dot attributes printed for a particular edge, /// override this method. - template<typename EdgeIter> - static std::string getEdgeAttributes(const void *Node, EdgeIter EI) { + template<typename EdgeIter, typename GraphType> + static std::string getEdgeAttributes(const void *Node, EdgeIter EI, + const GraphType& Graph) { return ""; } diff --git a/include/llvm/System/DataTypes.h.cmake b/include/llvm/Support/DataTypes.h.cmake index 9efe75a56e..72c451873c 100644 --- a/include/llvm/System/DataTypes.h.cmake +++ b/include/llvm/Support/DataTypes.h.cmake @@ -1,4 +1,4 @@ -/*===-- include/System/DataTypes.h - Define fixed size types -----*- C -*-===*\ +/*===-- include/Support/DataTypes.h - Define fixed size types -----*- C -*-===*\ |* *| |* The LLVM Compiler Infrastructure *| |* *| @@ -43,12 +43,12 @@ happening when system headers or C++ STL headers include stdint.h before we define it here, we define it on the g++ command line (in Makefile.rules). */ #if !defined(__STDC_LIMIT_MACROS) -# error "Must #define __STDC_LIMIT_MACROS before #including System/DataTypes.h" +# error "Must #define __STDC_LIMIT_MACROS before #including Support/DataTypes.h" #endif #if !defined(__STDC_CONSTANT_MACROS) # error "Must #define __STDC_CONSTANT_MACROS before " \ - "#including System/DataTypes.h" + "#including Support/DataTypes.h" #endif /* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ @@ -65,7 +65,7 @@ #endif #ifdef _AIX -#include "llvm/System/AIXDataTypesFix.h" +#include "llvm/Support/AIXDataTypesFix.h" #endif /* Handle incorrect definition of uint64_t as u_int64_t */ diff --git a/include/llvm/System/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in index 6537f3010f..5965e8c0b2 100644 --- a/include/llvm/System/DataTypes.h.in +++ b/include/llvm/Support/DataTypes.h.in @@ -63,7 +63,7 @@ #endif #ifdef _AIX -#include "llvm/System/AIXDataTypesFix.h" +#include "llvm/Support/AIXDataTypesFix.h" #endif /* Handle incorrect definition of uint64_t as u_int64_t */ diff --git a/include/llvm/System/Disassembler.h b/include/llvm/Support/Disassembler.h index e11e792de8..6d1cc0fdcb 100644 --- a/include/llvm/System/Disassembler.h +++ b/include/llvm/Support/Disassembler.h @@ -15,7 +15,7 @@ #ifndef LLVM_SYSTEM_DISASSEMBLER_H #define LLVM_SYSTEM_DISASSEMBLER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> namespace llvm { diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index 1b5d2a4538..5d0b5a943d 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -45,11 +45,9 @@ enum llvm_dwarf_constants { // llvm mock tags DW_TAG_invalid = ~0U, // Tag for invalid results. - DW_TAG_anchor = 0, // Tag for descriptor anchors. DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables. DW_TAG_arg_variable = 0x101, // Tag for argument variables. DW_TAG_return_variable = 0x102, // Tag for return variables. - DW_TAG_vector_type = 0x103, // Tag for vector types. DW_TAG_user_base = 0x1000, // Recommended base for user tags. @@ -119,6 +117,7 @@ enum dwarf_constants { DW_TAG_imported_unit = 0x3d, DW_TAG_condition = 0x3f, DW_TAG_shared_type = 0x40, + DW_TAG_rvalue_reference_type = 0x41, DW_TAG_lo_user = 0x4080, DW_TAG_hi_user = 0xffff, diff --git a/include/llvm/System/DynamicLibrary.h b/include/llvm/Support/DynamicLibrary.h index 745b8f8b5b..e6d9ff57ae 100644 --- a/include/llvm/System/DynamicLibrary.h +++ b/include/llvm/Support/DynamicLibrary.h @@ -1,4 +1,4 @@ -//===-- llvm/System/DynamicLibrary.h - Portable Dynamic Library -*- C++ -*-===// +//===-- llvm/Support/DynamicLibrary.h - Portable Dynamic Library -*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/Support/DynamicLinker.h b/include/llvm/Support/DynamicLinker.h deleted file mode 100644 index b60ffa875c..0000000000 --- a/include/llvm/Support/DynamicLinker.h +++ /dev/null @@ -1,40 +0,0 @@ -//===-- llvm/Support/DynamicLinker.h - Portable Dynamic Linker --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Lightweight interface to dynamic library linking and loading, and dynamic -// symbol lookup functionality, in whatever form the operating system -// provides it. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_DYNAMICLINKER_H -#define LLVM_SUPPORT_DYNAMICLINKER_H - -#include <string> - -namespace llvm { - -/// LinkDynamicObject - Load the named file as a dynamic library -/// and link it with the currently running process. Returns false -/// on success, true if there is an error (and sets ErrorMessage -/// if it is not NULL). Analogous to dlopen(). -/// -bool LinkDynamicObject (const char *filename, std::string *ErrorMessage); - -/// GetAddressOfSymbol - Returns the address of the named symbol in -/// the currently running process, as reported by the dynamic linker, -/// or NULL if the symbol does not exist or some other error has -/// occurred. -/// -void *GetAddressOfSymbol (const char *symbolName); -void *GetAddressOfSymbol (const std::string &symbolName); - -} // End llvm namespace - -#endif // SUPPORT_DYNAMICLINKER_H diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index c6304aa34b..cc72bd59cb 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -20,7 +20,7 @@ #ifndef LLVM_SUPPORT_ELF_H #define LLVM_SUPPORT_ELF_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cstring> namespace llvm { @@ -146,6 +146,7 @@ enum { // Object file classes. enum { + ELFCLASSNONE = 0, ELFCLASS32 = 1, // 32-bit object file ELFCLASS64 = 2 // 64-bit object file }; @@ -263,6 +264,175 @@ enum { R_386_NUM = 43 }; +// MBlaze relocations. +enum { + R_MICROBLAZE_NONE = 0, + R_MICROBLAZE_32 = 1, + R_MICROBLAZE_32_PCREL = 2, + R_MICROBLAZE_64_PCREL = 3, + R_MICROBLAZE_32_PCREL_LO = 4, + R_MICROBLAZE_64 = 5, + R_MICROBLAZE_32_LO = 6, + R_MICROBLAZE_SRO32 = 7, + R_MICROBLAZE_SRW32 = 8, + R_MICROBLAZE_64_NONE = 9, + R_MICROBLAZE_32_SYM_OP_SYM = 10, + R_MICROBLAZE_GNU_VTINHERIT = 11, + R_MICROBLAZE_GNU_VTENTRY = 12, + R_MICROBLAZE_GOTPC_64 = 13, + R_MICROBLAZE_GOT_64 = 14, + R_MICROBLAZE_PLT_64 = 15, + R_MICROBLAZE_REL = 16, + R_MICROBLAZE_JUMP_SLOT = 17, + R_MICROBLAZE_GLOB_DAT = 18, + R_MICROBLAZE_GOTOFF_64 = 19, + R_MICROBLAZE_GOTOFF_32 = 20, + R_MICROBLAZE_COPY = 21 +}; + + +// ARM Specific e_flags +enum { EF_ARM_EABIMASK = 0xFF000000U }; + +// ELF Relocation types for ARM +// Meets 2.08 ABI Specs. + +enum { + R_ARM_NONE = 0x00, + R_ARM_PC24 = 0x01, + R_ARM_ABS32 = 0x02, + R_ARM_REL32 = 0x03, + R_ARM_LDR_PC_G0 = 0x04, + R_ARM_ABS16 = 0x05, + R_ARM_ABS12 = 0x06, + R_ARM_THM_ABS5 = 0x07, + R_ARM_ABS8 = 0x08, + R_ARM_SBREL32 = 0x09, + R_ARM_THM_CALL = 0x0a, + R_ARM_THM_PC8 = 0x0b, + R_ARM_BREL_ADJ = 0x0c, + R_ARM_TLS_DESC = 0x0d, + R_ARM_THM_SWI8 = 0x0e, + R_ARM_XPC25 = 0x0f, + R_ARM_THM_XPC22 = 0x10, + R_ARM_TLS_DTPMOD32 = 0x11, + R_ARM_TLS_DTPOFF32 = 0x12, + R_ARM_TLS_TPOFF32 = 0x13, + R_ARM_COPY = 0x14, + R_ARM_GLOB_DAT = 0x15, + R_ARM_JUMP_SLOT = 0x16, + R_ARM_RELATIVE = 0x17, + R_ARM_GOTOFF32 = 0x18, + R_ARM_BASE_PREL = 0x19, + R_ARM_GOT_BREL = 0x1a, + R_ARM_PLT32 = 0x1b, + R_ARM_CALL = 0x1c, + R_ARM_JUMP24 = 0x1d, + R_ARM_THM_JUMP24 = 0x1e, + R_ARM_BASE_ABS = 0x1f, + R_ARM_ALU_PCREL_7_0 = 0x20, + R_ARM_ALU_PCREL_15_8 = 0x21, + R_ARM_ALU_PCREL_23_15 = 0x22, + R_ARM_LDR_SBREL_11_0_NC = 0x23, + R_ARM_ALU_SBREL_19_12_NC = 0x24, + R_ARM_ALU_SBREL_27_20_CK = 0x25, + R_ARM_TARGET1 = 0x26, + R_ARM_SBREL31 = 0x27, + R_ARM_V4BX = 0x28, + R_ARM_TARGET2 = 0x29, + R_ARM_PREL31 = 0x2a, + R_ARM_MOVW_ABS_NC = 0x2b, + R_ARM_MOVT_ABS = 0x2c, + R_ARM_MOVW_PREL_NC = 0x2d, + R_ARM_MOVT_PREL = 0x2e, + R_ARM_THM_MOVW_ABS_NC = 0x2f, + R_ARM_THM_MOVT_ABS = 0x30, + R_ARM_THM_MOVW_PREL_NC = 0x31, + R_ARM_THM_MOVT_PREL = 0x32, + R_ARM_THM_JUMP19 = 0x33, + R_ARM_THM_JUMP6 = 0x34, + R_ARM_THM_ALU_PREL_11_0 = 0x35, + R_ARM_THM_PC12 = 0x36, + R_ARM_ABS32_NOI = 0x37, + R_ARM_REL32_NOI = 0x38, + R_ARM_ALU_PC_G0_NC = 0x39, + R_ARM_ALU_PC_G0 = 0x3a, + R_ARM_ALU_PC_G1_NC = 0x3b, + R_ARM_ALU_PC_G1 = 0x3c, + R_ARM_ALU_PC_G2 = 0x3d, + R_ARM_LDR_PC_G1 = 0x3e, + R_ARM_LDR_PC_G2 = 0x3f, + R_ARM_LDRS_PC_G0 = 0x40, + R_ARM_LDRS_PC_G1 = 0x41, + R_ARM_LDRS_PC_G2 = 0x42, + R_ARM_LDC_PC_G0 = 0x43, + R_ARM_LDC_PC_G1 = 0x44, + R_ARM_LDC_PC_G2 = 0x45, + R_ARM_ALU_SB_G0_NC = 0x46, + R_ARM_ALU_SB_G0 = 0x47, + R_ARM_ALU_SB_G1_NC = 0x48, + R_ARM_ALU_SB_G1 = 0x49, + R_ARM_ALU_SB_G2 = 0x4a, + R_ARM_LDR_SB_G0 = 0x4b, + R_ARM_LDR_SB_G1 = 0x4c, + R_ARM_LDR_SB_G2 = 0x4d, + R_ARM_LDRS_SB_G0 = 0x4e, + R_ARM_LDRS_SB_G1 = 0x4f, + R_ARM_LDRS_SB_G2 = 0x50, + R_ARM_LDC_SB_G0 = 0x51, + R_ARM_LDC_SB_G1 = 0x52, + R_ARM_LDC_SB_G2 = 0x53, + R_ARM_MOVW_BREL_NC = 0x54, + R_ARM_MOVT_BREL = 0x55, + R_ARM_MOVW_BREL = 0x56, + R_ARM_THM_MOVW_BREL_NC = 0x57, + R_ARM_THM_MOVT_BREL = 0x58, + R_ARM_THM_MOVW_BREL = 0x59, + R_ARM_TLS_GOTDESC = 0x5a, + R_ARM_TLS_CALL = 0x5b, + R_ARM_TLS_DESCSEQ = 0x5c, + R_ARM_THM_TLS_CALL = 0x5d, + R_ARM_PLT32_ABS = 0x5e, + R_ARM_GOT_ABS = 0x5f, + R_ARM_GOT_PREL = 0x60, + R_ARM_GOT_BREL12 = 0x61, + R_ARM_GOTOFF12 = 0x62, + R_ARM_GOTRELAX = 0x63, + R_ARM_GNU_VTENTRY = 0x64, + R_ARM_GNU_VTINHERIT = 0x65, + R_ARM_THM_JUMP11 = 0x66, + R_ARM_THM_JUMP8 = 0x67, + R_ARM_TLS_GD32 = 0x68, + R_ARM_TLS_LDM32 = 0x69, + R_ARM_TLS_LDO32 = 0x6a, + R_ARM_TLS_IE32 = 0x6b, + R_ARM_TLS_LE32 = 0x6c, + R_ARM_TLS_LDO12 = 0x6d, + R_ARM_TLS_LE12 = 0x6e, + R_ARM_TLS_IE12GP = 0x6f, + R_ARM_PRIVATE_0 = 0x70, + R_ARM_PRIVATE_1 = 0x71, + R_ARM_PRIVATE_2 = 0x72, + R_ARM_PRIVATE_3 = 0x73, + R_ARM_PRIVATE_4 = 0x74, + R_ARM_PRIVATE_5 = 0x75, + R_ARM_PRIVATE_6 = 0x76, + R_ARM_PRIVATE_7 = 0x77, + R_ARM_PRIVATE_8 = 0x78, + R_ARM_PRIVATE_9 = 0x79, + R_ARM_PRIVATE_10 = 0x7a, + R_ARM_PRIVATE_11 = 0x7b, + R_ARM_PRIVATE_12 = 0x7c, + R_ARM_PRIVATE_13 = 0x7d, + R_ARM_PRIVATE_14 = 0x7e, + R_ARM_PRIVATE_15 = 0x7f, + R_ARM_ME_TOO = 0x80, + R_ARM_THM_TLS_DESCSEQ16 = 0x81, + R_ARM_THM_TLS_DESCSEQ32 = 0x82 +}; + + + // Section header. struct Elf32_Shdr { Elf32_Word sh_name; // Section name (index into string table) @@ -335,6 +505,8 @@ enum { SHT_ARM_DEBUGOVERLAY = 0x70000004U, SHT_ARM_OVERLAYSECTION = 0x70000005U, + SHT_X86_64_UNWIND = 0x70000001, // Unwind information + SHT_HIPROC = 0x7fffffff, // Highest processor architecture-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. SHT_HIUSER = 0xffffffff // Highest type reserved for applications. @@ -342,10 +514,51 @@ enum { // Section flags. enum { - SHF_WRITE = 0x1, // Section data should be writable during execution. - SHF_ALLOC = 0x2, // Section occupies memory during program execution. - SHF_EXECINSTR = 0x4, // Section contains executable machine instructions. - SHF_MASKPROC = 0xf0000000 // Bits indicating processor-specific flags. + // Section data should be writable during execution. + SHF_WRITE = 0x1, + + // Section occupies memory during program execution. + SHF_ALLOC = 0x2, + + // Section contains executable machine instructions. + SHF_EXECINSTR = 0x4, + + // The data in this section may be merged. + SHF_MERGE = 0x10, + + // The data in this section is null-terminated strings. + SHF_STRINGS = 0x20, + + // A field in this section holds a section header table index. + SHF_INFO_LINK = 0x40U, + + // Adds special ordering requirements for link editors. + SHF_LINK_ORDER = 0x80U, + + // This section requires special OS-specific processing to avoid incorrect + // behavior. + SHF_OS_NONCONFORMING = 0x100U, + + // This section is a member of a section group. + SHF_GROUP = 0x200U, + + // This section holds Thread-Local Storage. + SHF_TLS = 0x400U, + + // Start of target-specific flags. + + /// XCORE_SHF_CP_SECTION - All sections with the "c" flag are grouped + /// together by the linker to form the constant pool and the cp register is + /// set to the start of the constant pool by the boot code. + XCORE_SHF_CP_SECTION = 0x800U, + + /// XCORE_SHF_DP_SECTION - All sections with the "d" flag are grouped + /// together by the linker to form the data section and the dp register is + /// set to the start of the section by the boot code. + XCORE_SHF_DP_SECTION = 0x1000U, + + // Bits indicating processor-specific flags. + SHF_MASKPROC = 0xf0000000 }; // Section Group Flags diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index dc88a129e1..f62eab0702 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -15,8 +15,8 @@ #define LLVM_SUPPORT_ENDIAN_H #include "llvm/Config/config.h" -#include "llvm/System/Host.h" -#include "llvm/System/SwapByteOrder.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/SwapByteOrder.h" #include "llvm/Support/type_traits.h" namespace llvm { diff --git a/include/llvm/System/Errno.h b/include/llvm/Support/Errno.h index 6e292ba626..150bdb7016 100644 --- a/include/llvm/System/Errno.h +++ b/include/llvm/Support/Errno.h @@ -1,4 +1,4 @@ -//===- llvm/System/Errno.h - Portable+convenient errno handling -*- C++ -*-===// +//===- llvm/Support/Errno.h - Portable+convenient errno handling -*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/System/FEnv.h b/include/llvm/Support/FEnv.h index 042e43928b..f6f43337bd 100644 --- a/include/llvm/System/FEnv.h +++ b/include/llvm/Support/FEnv.h @@ -1,4 +1,4 @@ -//===- llvm/System/FEnv.h - Host floating-point exceptions ------*- C++ -*-===// +//===- llvm/Support/FEnv.h - Host floating-point exceptions ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h new file mode 100644 index 0000000000..4f013f89e8 --- /dev/null +++ b/include/llvm/Support/FileSystem.h @@ -0,0 +1,690 @@ +//===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::fs namespace. It is designed after +// TR2/boost filesystem (v3), but modified to remove exception handling and the +// path class. +// +// All functions return an error_code and their actual work via the last out +// argument. The out argument is defined if and only if errc::success is +// returned. A function may return any error code in the generic or system +// category. However, they shall be equivalent to any error conditions listed +// in each functions respective documentation if the condition applies. [ note: +// this does not guarantee that error_code will be in the set of explicitly +// listed codes, but it does guarantee that if any of the explicitly listed +// errors occur, the correct error_code will be used ]. All functions may +// return errc::not_enough_memory if there is not enough memory to complete the +// operation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FILE_SYSTEM_H +#define LLVM_SUPPORT_FILE_SYSTEM_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/PathV1.h" +#include "llvm/Support/system_error.h" +#include <ctime> +#include <iterator> +#include <string> + +namespace llvm { +namespace sys { +namespace fs { + +/// file_type - An "enum class" enumeration for the file system's view of the +/// type. +struct file_type { + enum _ { + status_error, + file_not_found, + regular_file, + directory_file, + symlink_file, + block_file, + character_file, + fifo_file, + socket_file, + type_unknown + }; + + file_type(_ v) : v_(v) {} + explicit file_type(int v) : v_(_(v)) {} + operator int() const {return v_;} + +private: + int v_; +}; + +/// copy_option - An "enum class" enumeration of copy semantics for copy +/// operations. +struct copy_option { + enum _ { + fail_if_exists, + overwrite_if_exists + }; + + copy_option(_ v) : v_(v) {} + explicit copy_option(int v) : v_(_(v)) {} + operator int() const {return v_;} + +private: + int v_; +}; + +/// space_info - Self explanatory. +struct space_info { + uint64_t capacity; + uint64_t free; + uint64_t available; +}; + +/// file_status - Represents the result of a call to stat and friends. It has +/// a platform specific member to store the result. +class file_status +{ + // implementation defined status field. + file_type Type; +public: + explicit file_status(file_type v=file_type::status_error) + : Type(v) {} + + file_type type() const { return Type; } + void type(file_type v) { Type = v; } +}; + +/// @} +/// @name Physical Operators +/// @{ + +/// @brief Make \a path an absolute path. +/// +/// Makes \a path absolute using the current directory if it is not already. An +/// empty \a path will result in the current directory. +/// +/// /absolute/path => /absolute/path +/// relative/../path => <current-directory>/relative/../path +/// +/// @param path A path that is modified to be an absolute path. +/// @returns errc::success if \a path has been made absolute, otherwise a +/// platform specific error_code. +error_code make_absolute(SmallVectorImpl<char> &path); + +/// @brief Copy the file at \a from to the path \a to. +/// +/// @param from The path to copy the file from. +/// @param to The path to copy the file to. +/// @param copt Behavior if \a to already exists. +/// @returns errc::success if the file has been successfully copied. +/// errc::file_exists if \a to already exists and \a copt == +/// copy_option::fail_if_exists. Otherwise a platform specific +/// error_code. +error_code copy_file(const Twine &from, const Twine &to, + copy_option copt = copy_option::fail_if_exists); + +/// @brief Create all the non-existent directories in path. +/// +/// @param path Directories to create. +/// @param existed Set to true if \a path already existed, false otherwise. +/// @returns errc::success if is_directory(path) and existed have been set, +/// otherwise a platform specific error_code. +error_code create_directories(const Twine &path, bool &existed); + +/// @brief Create the directory in path. +/// +/// @param path Directory to create. +/// @param existed Set to true if \a path already existed, false otherwise. +/// @returns errc::success if is_directory(path) and existed have been set, +/// otherwise a platform specific error_code. +error_code create_directory(const Twine &path, bool &existed); + +/// @brief Create a hard link from \a from to \a to. +/// +/// @param to The path to hard link to. +/// @param from The path to hard link from. This is created. +/// @returns errc::success if exists(to) && exists(from) && equivalent(to, from) +/// , otherwise a platform specific error_code. +error_code create_hard_link(const Twine &to, const Twine &from); + +/// @brief Create a symbolic link from \a from to \a to. +/// +/// @param to The path to symbolically link to. +/// @param from The path to symbolically link from. This is created. +/// @returns errc::success if exists(to) && exists(from) && is_symlink(from), +/// otherwise a platform specific error_code. +error_code create_symlink(const Twine &to, const Twine &from); + +/// @brief Get the current path. +/// +/// @param result Holds the current path on return. +/// @results errc::success if the current path has been stored in result, +/// otherwise a platform specific error_code. +error_code current_path(SmallVectorImpl<char> &result); + +/// @brief Remove path. Equivalent to POSIX remove(). +/// +/// @param path Input path. +/// @param existed Set to true if \a path existed, false if it did not. +/// undefined otherwise. +/// @results errc::success if path has been removed and existed has been +/// successfully set, otherwise a platform specific error_code. +error_code remove(const Twine &path, bool &existed); + +/// @brief Recursively remove all files below \a path, then \a path. Files are +/// removed as if by POSIX remove(). +/// +/// @param path Input path. +/// @param num_removed Number of files removed. +/// @results errc::success if path has been removed and num_removed has been +/// successfully set, otherwise a platform specific error_code. +error_code remove_all(const Twine &path, uint32_t &num_removed); + +/// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). +/// +/// @param from The path to rename from. +/// @param to The path to rename to. This is created. +error_code rename(const Twine &from, const Twine &to); + +/// @brief Resize path to size. File is resized as if by POSIX truncate(). +/// +/// @param path Input path. +/// @param size Size to resize to. +/// @returns errc::success if \a path has been resized to \a size, otherwise a +/// platform specific error_code. +error_code resize_file(const Twine &path, uint64_t size); + +/// @brief Make file readable. +/// +/// @param path Input path. +/// @param value If true, make readable, else, make unreadable. +/// @results errc::success if readability has been successfully set, otherwise a +/// platform specific error_code. +error_code set_read(const Twine &path, bool value); + +/// @brief Make file writeable. +/// +/// @param path Input path. +/// @param value If true, make writeable, else, make unwriteable. +/// @results errc::success if writeability has been successfully set, otherwise +/// a platform specific error_code. +error_code set_write(const Twine &path, bool value); + +/// @brief Make file executable. +/// +/// @param path Input path. +/// @param value If true, make executable, else, make unexecutable. +/// @results errc::success if executability has been successfully set, otherwise +/// a platform specific error_code. +error_code set_execute(const Twine &path, bool value); + +/// @} +/// @name Physical Observers +/// @{ + +/// @brief Does file exist? +/// +/// @param status A file_status previously returned from stat. +/// @results True if the file represented by status exists, false if it does +/// not. +bool exists(file_status status); + +/// @brief Does file exist? +/// +/// @param path Input path. +/// @param result Set to true if the file represented by status exists, false if +/// it does not. Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code exists(const Twine &path, bool &result); + +/// @brief Do file_status's represent the same thing? +/// +/// @param A Input file_status. +/// @param B Input file_status. +/// +/// assert(status_known(A) || status_known(B)); +/// +/// @results True if A and B both represent the same file system entity, false +/// otherwise. +bool equivalent(file_status A, file_status B); + +/// @brief Do paths represent the same thing? +/// +/// @param A Input path A. +/// @param B Input path B. +/// @param result Set to true if stat(A) and stat(B) have the same device and +/// inode (or equivalent). +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code equivalent(const Twine &A, const Twine &B, bool &result); + +/// @brief Get file size. +/// +/// @param path Input path. +/// @param result Set to the size of the file in \a path. +/// @returns errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code file_size(const Twine &path, uint64_t &result); + +/// @brief Does status represent a directory? +/// +/// @param status A file_status previously returned from status. +/// @results status.type() == file_type::directory_file. +bool is_directory(file_status status); + +/// @brief Is path a directory? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a directory, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_directory(const Twine &path, bool &result); + +/// @brief Is path an empty file? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a an empty file, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_empty(const Twine &path, bool &result); + +/// @brief Does status represent a regular file? +/// +/// @param status A file_status previously returned from status. +/// @results status_known(status) && status.type() == file_type::regular_file. +bool is_regular_file(file_status status); + +/// @brief Is path a regular file? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a regular file, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_regular_file(const Twine &path, bool &result); + +/// @brief Does this status represent something that exists but is not a +/// directory, regular file, or symlink? +/// +/// @param status A file_status previously returned from status. +/// @results exists(s) && !is_regular_file(s) && !is_directory(s) && +/// !is_symlink(s) +bool is_other(file_status status); + +/// @brief Is path something that exists but is not a directory, +/// regular file, or symlink? +/// +/// @param path Input path. +/// @param result Set to true if \a path exists, but is not a directory, regular +/// file, or a symlink, false if it does not. Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_other(const Twine &path, bool &result); + +/// @brief Does status represent a symlink? +/// +/// @param status A file_status previously returned from stat. +/// @param result status.type() == symlink_file. +bool is_symlink(file_status status); + +/// @brief Is path a symlink? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a symlink, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_symlink(const Twine &path, bool &result); + +/// @brief Get last write time without changing it. +/// +/// @param path Input path. +/// @param result Set to the last write time (UNIX time) of \a path if it +/// exists. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code last_write_time(const Twine &path, std::time_t &result); + +/// @brief Set last write time. +/// +/// @param path Input path. +/// @param value Time to set (UNIX time) \a path's last write time to. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code set_last_write_time(const Twine &path, std::time_t value); + +/// @brief Read a symlink's value. +/// +/// @param path Input path. +/// @param result Set to the value of the symbolic link \a path. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code read_symlink(const Twine &path, SmallVectorImpl<char> &result); + +/// @brief Get disk space usage information. +/// +/// @param path Input path. +/// @param result Set to the capacity, free, and available space on the device +/// \a path is on. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code disk_space(const Twine &path, space_info &result); + +/// @brief Get file status as if by POSIX stat(). +/// +/// @param path Input path. +/// @param result Set to the file status. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code status(const Twine &path, file_status &result); + +/// @brief Is status available? +/// +/// @param path Input path. +/// @results True if status() != status_error. +bool status_known(file_status s); + +/// @brief Is status available? +/// +/// @param path Input path. +/// @param result Set to true if status() != status_error. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code status_known(const Twine &path, bool &result); + +/// @brief Get file status as if by POSIX lstat(). +/// +/// Does not resolve symlinks. +/// +/// @param path Input path. +/// @param result Set to the file status. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code symlink_status(const Twine &path, file_status &result); + +/// @brief Generate a unique path and open it as a file. +/// +/// Generates a unique path suitable for a temporary file and then opens it as a +/// file. The name is based on \a model with '%' replaced by a random char in +/// [0-9a-f]. If \a model is not an absolute path, a suitable temporary +/// directory will be prepended. +/// +/// This is an atomic operation. Either the file is created and opened, or the +/// file system is left untouched. +/// +/// clang-%%-%%-%%-%%-%%.s => /tmp/clang-a0-b1-c2-d3-e4.s +/// +/// @param model Name to base unique path off of. +/// @param result_fs Set to the opened file's file descriptor. +/// @param result_path Set to the opened file's absolute path. +/// @results errc::success if result_{fd,path} have been successfully set, +/// otherwise a platform specific error_code. +error_code unique_file(const Twine &model, int &result_fd, + SmallVectorImpl<char> &result_path); + +/// @brief Canonicalize path. +/// +/// Sets result to the file system's idea of what path is. The result is always +/// absolute and has the same capitalization as the file system. +/// +/// @param path Input path. +/// @param result Set to the canonicalized version of \a path. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code canonicalize(const Twine &path, SmallVectorImpl<char> &result); + +/// @brief Are \a path's first bytes \a magic? +/// +/// @param path Input path. +/// @param magic Byte sequence to compare \a path's first len(magic) bytes to. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code has_magic(const Twine &path, const Twine &magic, bool &result); + +/// @brief Get \a path's first \a len bytes. +/// +/// @param path Input path. +/// @param len Number of magic bytes to get. +/// @param result Set to the first \a len bytes in the file pointed to by +/// \a path. Or the entire file if file_size(path) < len, in which +/// case result.size() returns the size of the file. +/// @results errc::success if result has been successfully set, +/// errc::value_too_large if len is larger then the file pointed to by +/// \a path, otherwise a platform specific error_code. +error_code get_magic(const Twine &path, uint32_t len, + SmallVectorImpl<char> &result); + +/// @brief Get and identify \a path's type based on its content. +/// +/// @param path Input path. +/// @param result Set to the type of file, or LLVMFileType::Unknown_FileType. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code identify_magic(const Twine &path, LLVMFileType &result); + +/// @brief Is file bitcode? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a bitcode file, false if it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_bitcode(const Twine &path, bool &result); + +/// @brief Is file a dynamic library? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a dynamic library, false if it is +/// not, undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_dynamic_library(const Twine &path, bool &result); + +/// @brief Is an object file? +/// +/// @param path Input path. +/// @param result Set to true if \a path is an object file, false if it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_object_file(const Twine &path, bool &result); + +/// @brief Can file be read? +/// +/// @param path Input path. +/// @param result Set to true if \a path is readable, false it it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code can_read(const Twine &path, bool &result); + +/// @brief Can file be written? +/// +/// @param path Input path. +/// @param result Set to true if \a path is writeable, false it it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code can_write(const Twine &path, bool &result); + +/// @brief Can file be executed? +/// +/// @param path Input path. +/// @param result Set to true if \a path is executable, false it it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code can_execute(const Twine &path, bool &result); + +/// @brief Get library paths the system linker uses. +/// +/// @param result Set to the list of system library paths. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code GetSystemLibraryPaths(SmallVectorImpl<std::string> &result); + +/// @brief Get bitcode library paths the system linker uses +/// + LLVM_LIB_SEARCH_PATH + LLVM_LIBDIR. +/// +/// @param result Set to the list of bitcode library paths. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code GetBitcodeLibraryPaths(SmallVectorImpl<std::string> &result); + +/// @brief Find a library. +/// +/// Find the path to a library using its short name. Use the system +/// dependent library paths to locate the library. +/// +/// c => /usr/lib/libc.so +/// +/// @param short_name Library name one would give to the system linker. +/// @param result Set to the absolute path \a short_name represents. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code FindLibrary(const Twine &short_name, SmallVectorImpl<char> &result); + +/// @brief Get absolute path of main executable. +/// +/// @param argv0 The program name as it was spelled on the command line. +/// @param MainAddr Address of some symbol in the executable (not in a library). +/// @param result Set to the absolute path of the current executable. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code GetMainExecutable(const char *argv0, void *MainAddr, + SmallVectorImpl<char> &result); + +/// @} +/// @name Iterators +/// @{ + +/// directory_entry - A single entry in a directory. Caches the status either +/// from the result of the iteration syscall, or the first time status or +/// symlink_status is called. +class directory_entry { + std::string Path; + mutable file_status Status; + mutable file_status SymlinkStatus; + +public: + explicit directory_entry(const Twine &path, file_status st = file_status(), + file_status symlink_st = file_status()) + : Path(path.str()) + , Status(st) + , SymlinkStatus(symlink_st) {} + + directory_entry() {} + + void assign(const Twine &path, file_status st = file_status(), + file_status symlink_st = file_status()) { + Path = path.str(); + Status = st; + SymlinkStatus = symlink_st; + } + + void replace_filename(const Twine &filename, file_status st = file_status(), + file_status symlink_st = file_status()); + + const std::string &path() const { return Path; } + error_code status(file_status &result) const; + error_code symlink_status(file_status &result) const; + + bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } + bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } + bool operator< (const directory_entry& rhs) const; + bool operator<=(const directory_entry& rhs) const; + bool operator> (const directory_entry& rhs) const; + bool operator>=(const directory_entry& rhs) const; +}; + +/// directory_iterator - Iterates through the entries in path. There is no +/// operator++ because we need an error_code. If it's really needed we can make +/// it call report_fatal_error on error. +class directory_iterator { + intptr_t IterationHandle; + directory_entry CurrentEntry; + + // Platform implementations implement these functions to handle iteration. + friend error_code directory_iterator_construct(directory_iterator &it, + StringRef path); + friend error_code directory_iterator_increment(directory_iterator &it); + friend error_code directory_iterator_destruct(directory_iterator &it); + +public: + explicit directory_iterator(const Twine &path, error_code &ec) + : IterationHandle(0) { + SmallString<128> path_storage; + ec = directory_iterator_construct(*this, path.toStringRef(path_storage)); + } + + /// Construct end iterator. + directory_iterator() : IterationHandle(0) {} + + ~directory_iterator() { + directory_iterator_destruct(*this); + } + + // No operator++ because we need error_code. + directory_iterator &increment(error_code &ec) { + ec = directory_iterator_increment(*this); + return *this; + } + + const directory_entry &operator*() const { return CurrentEntry; } + const directory_entry *operator->() const { return &CurrentEntry; } + + bool operator!=(const directory_iterator &RHS) const { + return CurrentEntry != RHS.CurrentEntry; + } + // Other members as required by + // C++ Std, 24.1.1 Input iterators [input.iterators] +}; + +/// recursive_directory_iterator - Same as directory_iterator except for it +/// recurses down into child directories. +class recursive_directory_iterator { + uint16_t Level; + bool HasNoPushRequest; + // implementation directory iterator status + +public: + explicit recursive_directory_iterator(const Twine &path, error_code &ec); + // No operator++ because we need error_code. + directory_iterator &increment(error_code &ec); + + const directory_entry &operator*() const; + const directory_entry *operator->() const; + + // observers + /// Gets the current level. path is at level 0. + int level() const; + /// Returns true if no_push has been called for this directory_entry. + bool no_push_request() const; + + // modifiers + /// Goes up one level if Level > 0. + void pop(); + /// Does not go down into the current directory_entry. + void no_push(); + + // Other members as required by + // C++ Std, 24.1.1 Input iterators [input.iterators] +}; + +/// @} + +} // end namespace fs +} // end namespace sys +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/FileUtilities.h b/include/llvm/Support/FileUtilities.h index d0dd4a7598..748ce7cea7 100644 --- a/include/llvm/Support/FileUtilities.h +++ b/include/llvm/Support/FileUtilities.h @@ -15,7 +15,7 @@ #ifndef LLVM_SUPPORT_FILEUTILITIES_H #define LLVM_SUPPORT_FILEUTILITIES_H -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" namespace llvm { diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index 2d29e525fb..a5165f44d5 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -26,7 +26,7 @@ #include "llvm/Support/DOTGraphTraits.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" #include <vector> #include <cassert> @@ -70,7 +70,7 @@ class GraphWriter { for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) { std::string label = DTraits.getEdgeSourceLabel(Node, EI); - if (label == "") + if (label.empty()) continue; hasEdgeSourceLabels = true; @@ -78,7 +78,7 @@ class GraphWriter { if (i) O << "|"; - O << "<s" << i << ">" << DTraits.getEdgeSourceLabel(Node, EI); + O << "<s" << i << ">" << DOT::EscapeString(label); } if (EI != EE && hasEdgeSourceLabels) @@ -235,12 +235,12 @@ public: DestPort = static_cast<int>(Offset); } - if (DTraits.getEdgeSourceLabel(Node, EI) == "") + if (DTraits.getEdgeSourceLabel(Node, EI).empty()) edgeidx = -1; emitEdge(static_cast<const void*>(Node), edgeidx, static_cast<const void*>(TargetNode), DestPort, - DTraits.getEdgeAttributes(Node, EI)); + DTraits.getEdgeAttributes(Node, EI, G)); } } diff --git a/include/llvm/System/Host.h b/include/llvm/Support/Host.h index 4fbf5c177c..f77d4c1182 100644 --- a/include/llvm/System/Host.h +++ b/include/llvm/Support/Host.h @@ -1,4 +1,4 @@ -//===- llvm/System/Host.h - Host machine characteristics --------*- C++ -*-===// +//===- llvm/Support/Host.h - Host machine characteristics --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h index b3934224f5..2394a59c09 100644 --- a/include/llvm/Support/IRBuilder.h +++ b/include/llvm/Support/IRBuilder.h @@ -74,6 +74,13 @@ public: } /// SetInsertPoint - This specifies that created instructions should be + /// inserted before the specified instruction. + void SetInsertPoint(Instruction *I) { + BB = I->getParent(); + InsertPt = I; + } + + /// SetInsertPoint - This specifies that created instructions should be /// inserted at the specified point. void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { BB = TheBB; @@ -228,13 +235,48 @@ public: return Type::getVoidTy(Context); } - const PointerType *getInt8PtrTy() { - return Type::getInt8PtrTy(Context); + const PointerType *getInt8PtrTy(unsigned AddrSpace = 0) { + return Type::getInt8PtrTy(Context, AddrSpace); } /// getCurrentFunctionReturnType - Get the return type of the current function /// that we're emitting into. const Type *getCurrentFunctionReturnType() const; + + /// CreateMemSet - Create and insert a memset to the specified pointer and the + /// specified value. If the pointer isn't an i8*, it will be converted. If a + /// TBAA tag is specified, it will be added to the instruction. + CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); + + /// CreateMemCpy - Create and insert a memcpy between the specified pointers. + /// If the pointers aren't i8*, they will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. + CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); + + /// CreateMemMove - Create and insert a memmove between the specified + /// pointers. If the pointers aren't i8*, they will be converted. If a TBAA + /// tag is specified, it will be added to the instruction. + CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); +private: + Value *getCastedInt8PtrValue(Value *Ptr); }; /// IRBuilder - This provides a uniform API for creating instructions and @@ -272,6 +314,11 @@ public: SetInsertPoint(TheBB); } + explicit IRBuilder(Instruction *IP) + : IRBuilderBase(IP->getContext()), Folder(Context) { + SetInsertPoint(IP); + } + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F) : IRBuilderBase(TheBB->getContext()), Folder(F) { SetInsertPoint(TheBB, IP); @@ -298,6 +345,11 @@ public: return I; } + /// Insert - No-op overload to handle constants. + Constant *Insert(Constant *C, const Twine& = "") const { + return C; + } + //===--------------------------------------------------------------------===// // Instruction creation methods: Terminators //===--------------------------------------------------------------------===// @@ -396,177 +448,179 @@ public: //===--------------------------------------------------------------------===// // Instruction creation methods: Binary Operators //===--------------------------------------------------------------------===// - - Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "") { +private: + BinaryOperator *CreateInsertNUWNSWBinOp(BinaryOperator::BinaryOps Opc, + Value *LHS, Value *RHS, + const Twine &Name, + bool HasNUW, bool HasNSW) { + BinaryOperator *BO = Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } +public: + Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateAdd(LC, RC); - return Insert(BinaryOperator::CreateAdd(LHS, RHS), Name); + return Insert(Folder.CreateAdd(LC, RC, HasNUW, HasNSW), Name); + return CreateInsertNUWNSWBinOp(Instruction::Add, LHS, RHS, Name, + HasNUW, HasNSW); } Value *CreateNSWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNSWAdd(LC, RC); - return Insert(BinaryOperator::CreateNSWAdd(LHS, RHS), Name); + return CreateAdd(LHS, RHS, Name, false, true); } Value *CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNUWAdd(LC, RC); - return Insert(BinaryOperator::CreateNUWAdd(LHS, RHS), Name); + return CreateAdd(LHS, RHS, Name, true, false); } Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFAdd(LC, RC); + return Insert(Folder.CreateFAdd(LC, RC), Name); return Insert(BinaryOperator::CreateFAdd(LHS, RHS), Name); } - Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateSub(LC, RC); - return Insert(BinaryOperator::CreateSub(LHS, RHS), Name); + return Insert(Folder.CreateSub(LC, RC), Name); + return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name, + HasNUW, HasNSW); } Value *CreateNSWSub(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNSWSub(LC, RC); - return Insert(BinaryOperator::CreateNSWSub(LHS, RHS), Name); + return CreateSub(LHS, RHS, Name, false, true); } Value *CreateNUWSub(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNUWSub(LC, RC); - return Insert(BinaryOperator::CreateNUWSub(LHS, RHS), Name); + return CreateSub(LHS, RHS, Name, true, false); } Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFSub(LC, RC); + return Insert(Folder.CreateFSub(LC, RC), Name); return Insert(BinaryOperator::CreateFSub(LHS, RHS), Name); } - Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateMul(LC, RC); - return Insert(BinaryOperator::CreateMul(LHS, RHS), Name); + return Insert(Folder.CreateMul(LC, RC), Name); + return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name, + HasNUW, HasNSW); } Value *CreateNSWMul(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNSWMul(LC, RC); - return Insert(BinaryOperator::CreateNSWMul(LHS, RHS), Name); + return CreateMul(LHS, RHS, Name, false, true); } Value *CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNUWMul(LC, RC); - return Insert(BinaryOperator::CreateNUWMul(LHS, RHS), Name); + return CreateMul(LHS, RHS, Name, true, false); } Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFMul(LC, RC); + return Insert(Folder.CreateFMul(LC, RC), Name); return Insert(BinaryOperator::CreateFMul(LHS, RHS), Name); } - Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateUDiv(LC, RC); - return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name); + return Insert(Folder.CreateUDiv(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactUDiv(LHS, RHS), Name); } - Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateSDiv(LC, RC); - return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name); + Value *CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateUDiv(LHS, RHS, Name, true); } - Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateExactSDiv(LC, RC); + return Insert(Folder.CreateSDiv(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name); return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name); } + Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateSDiv(LHS, RHS, Name, true); + } Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFDiv(LC, RC); + return Insert(Folder.CreateFDiv(LC, RC), Name); return Insert(BinaryOperator::CreateFDiv(LHS, RHS), Name); } Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateURem(LC, RC); + return Insert(Folder.CreateURem(LC, RC), Name); return Insert(BinaryOperator::CreateURem(LHS, RHS), Name); } Value *CreateSRem(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateSRem(LC, RC); + return Insert(Folder.CreateSRem(LC, RC), Name); return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name); } Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFRem(LC, RC); + return Insert(Folder.CreateFRem(LC, RC), Name); return Insert(BinaryOperator::CreateFRem(LHS, RHS), Name); } - Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateShl(LC, RC); - return Insert(BinaryOperator::CreateShl(LHS, RHS), Name); + return Insert(Folder.CreateShl(LC, RC, HasNUW, HasNSW), Name); + return CreateInsertNUWNSWBinOp(Instruction::Shl, LHS, RHS, Name, + HasNUW, HasNSW); } - Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateShl(LC, RHSC); - return Insert(BinaryOperator::CreateShl(LHS, RHSC), Name); + Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, + HasNUW, HasNSW); } - Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateShl(LC, RHSC); - return Insert(BinaryOperator::CreateShl(LHS, RHSC), Name); + Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, + HasNUW, HasNSW); } - Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateLShr(LC, RC); - return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name); + return Insert(Folder.CreateLShr(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactLShr(LHS, RHS), Name); } - Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateLShr(LC, RHSC); - return Insert(BinaryOperator::CreateLShr(LHS, RHSC), Name); + Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool isExact = false) { + return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } - Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateLShr(LC, RHSC); - return Insert(BinaryOperator::CreateLShr(LHS, RHSC), Name); + Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool isExact = false) { + return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } - Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateAShr(LC, RC); - return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name); + return Insert(Folder.CreateAShr(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactAShr(LHS, RHS), Name); } - Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAShr(LC, RHSC); - return Insert(BinaryOperator::CreateAShr(LHS, RHSC), Name); + Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool isExact = false) { + return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } - Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAShr(LC, RHSC); - return Insert(BinaryOperator::CreateAShr(LHS, RHSC), Name); + Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool isExact = false) { + return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") { @@ -574,21 +628,15 @@ public: if (isa<ConstantInt>(RC) && cast<ConstantInt>(RC)->isAllOnesValue()) return LHS; // LHS & -1 -> LHS if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAnd(LC, RC); + return Insert(Folder.CreateAnd(LC, RC), Name); } return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name); } Value *CreateAnd(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAnd(LC, RHSC); - return Insert(BinaryOperator::CreateAnd(LHS, RHSC), Name); + return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateAnd(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAnd(LC, RHSC); - return Insert(BinaryOperator::CreateAnd(LHS, RHSC), Name); + return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") { @@ -596,73 +644,61 @@ public: if (RC->isNullValue()) return LHS; // LHS | 0 -> LHS if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateOr(LC, RC); + return Insert(Folder.CreateOr(LC, RC), Name); } return Insert(BinaryOperator::CreateOr(LHS, RHS), Name); } Value *CreateOr(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateOr(LC, RHSC); - return Insert(BinaryOperator::CreateOr(LHS, RHSC), Name); + return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateOr(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateOr(LC, RHSC); - return Insert(BinaryOperator::CreateOr(LHS, RHSC), Name); + return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateXor(LC, RC); + return Insert(Folder.CreateXor(LC, RC), Name); return Insert(BinaryOperator::CreateXor(LHS, RHS), Name); } Value *CreateXor(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateXor(LC, RHSC); - return Insert(BinaryOperator::CreateXor(LHS, RHSC), Name); + return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateXor(LC, RHSC); - return Insert(BinaryOperator::CreateXor(LHS, RHSC), Name); + return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateBinOp(Opc, LC, RC); + return Insert(Folder.CreateBinOp(Opc, LC, RC), Name); return Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); } - Value *CreateNeg(Value *V, const Twine &Name = "") { + Value *CreateNeg(Value *V, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateNeg(VC); - return Insert(BinaryOperator::CreateNeg(V), Name); + return Insert(Folder.CreateNeg(VC, HasNUW, HasNSW), Name); + BinaryOperator *BO = Insert(BinaryOperator::CreateNeg(V), Name); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; } Value *CreateNSWNeg(Value *V, const Twine &Name = "") { - if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateNSWNeg(VC); - return Insert(BinaryOperator::CreateNSWNeg(V), Name); + return CreateNeg(V, Name, false, true); } Value *CreateNUWNeg(Value *V, const Twine &Name = "") { - if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateNUWNeg(VC); - return Insert(BinaryOperator::CreateNUWNeg(V), Name); + return CreateNeg(V, Name, true, false); } Value *CreateFNeg(Value *V, const Twine &Name = "") { if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateFNeg(VC); + return Insert(Folder.CreateFNeg(VC), Name); return Insert(BinaryOperator::CreateFNeg(V), Name); } Value *CreateNot(Value *V, const Twine &Name = "") { if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateNot(VC); + return Insert(Folder.CreateNot(VC), Name); return Insert(BinaryOperator::CreateNot(V), Name); } @@ -700,7 +736,9 @@ public: if (!isa<Constant>(*i)) break; if (i == IdxEnd) - return Folder.CreateGetElementPtr(PC, &IdxBegin[0], IdxEnd - IdxBegin); + return Insert(Folder.CreateGetElementPtr(PC, &IdxBegin[0], + IdxEnd - IdxBegin), + Name); } return Insert(GetElementPtrInst::Create(Ptr, IdxBegin, IdxEnd), Name); } @@ -715,9 +753,10 @@ public: if (!isa<Constant>(*i)) break; if (i == IdxEnd) - return Folder.CreateInBoundsGetElementPtr(PC, - &IdxBegin[0], - IdxEnd - IdxBegin); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, + &IdxBegin[0], + IdxEnd - IdxBegin), + Name); } return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxBegin, IdxEnd), Name); @@ -725,20 +764,20 @@ public: Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Folder.CreateGetElementPtr(PC, &IC, 1); + return Insert(Folder.CreateGetElementPtr(PC, &IC, 1), Name); return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); } Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Folder.CreateInBoundsGetElementPtr(PC, &IC, 1); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, &IC, 1), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); } Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateGetElementPtr(PC, &Idx, 1); + return Insert(Folder.CreateGetElementPtr(PC, &Idx, 1), Name); return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); } @@ -747,7 +786,7 @@ public: Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); } @@ -759,7 +798,7 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateGetElementPtr(PC, Idxs, 2); + return Insert(Folder.CreateGetElementPtr(PC, Idxs, 2), Name); return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); } @@ -771,7 +810,7 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); } @@ -779,7 +818,7 @@ public: Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateGetElementPtr(PC, &Idx, 1); + return Insert(Folder.CreateGetElementPtr(PC, &Idx, 1), Name); return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); } @@ -788,7 +827,7 @@ public: Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); } @@ -800,7 +839,7 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateGetElementPtr(PC, Idxs, 2); + return Insert(Folder.CreateGetElementPtr(PC, Idxs, 2), Name); return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); } @@ -812,7 +851,7 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); } @@ -878,7 +917,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateZExtOrBitCast(VC, DestTy); + return Insert(Folder.CreateZExtOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateZExtOrBitCast(V, DestTy), Name); } Value *CreateSExtOrBitCast(Value *V, const Type *DestTy, @@ -886,7 +925,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateSExtOrBitCast(VC, DestTy); + return Insert(Folder.CreateSExtOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateSExtOrBitCast(V, DestTy), Name); } Value *CreateTruncOrBitCast(Value *V, const Type *DestTy, @@ -894,7 +933,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateTruncOrBitCast(VC, DestTy); + return Insert(Folder.CreateTruncOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateTruncOrBitCast(V, DestTy), Name); } Value *CreateCast(Instruction::CastOps Op, Value *V, const Type *DestTy, @@ -902,7 +941,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateCast(Op, VC, DestTy); + return Insert(Folder.CreateCast(Op, VC, DestTy), Name); return Insert(CastInst::Create(Op, V, DestTy), Name); } Value *CreatePointerCast(Value *V, const Type *DestTy, @@ -910,7 +949,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreatePointerCast(VC, DestTy); + return Insert(Folder.CreatePointerCast(VC, DestTy), Name); return Insert(CastInst::CreatePointerCast(V, DestTy), Name); } Value *CreateIntCast(Value *V, const Type *DestTy, bool isSigned, @@ -918,7 +957,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateIntCast(VC, DestTy, isSigned); + return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); } private: @@ -930,7 +969,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateFPCast(VC, DestTy); + return Insert(Folder.CreateFPCast(VC, DestTy), Name); return Insert(CastInst::CreateFPCast(V, DestTy), Name); } @@ -1016,14 +1055,14 @@ public: const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateICmp(P, LC, RC); + return Insert(Folder.CreateICmp(P, LC, RC), Name); return Insert(new ICmpInst(P, LHS, RHS), Name); } Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFCmp(P, LC, RC); + return Insert(Folder.CreateFCmp(P, LC, RC), Name); return Insert(new FCmpInst(P, LHS, RHS), Name); } @@ -1073,7 +1112,7 @@ public: if (Constant *CC = dyn_cast<Constant>(C)) if (Constant *TC = dyn_cast<Constant>(True)) if (Constant *FC = dyn_cast<Constant>(False)) - return Folder.CreateSelect(CC, TC, FC); + return Insert(Folder.CreateSelect(CC, TC, FC), Name); return Insert(SelectInst::Create(C, True, False), Name); } @@ -1085,7 +1124,7 @@ public: const Twine &Name = "") { if (Constant *VC = dyn_cast<Constant>(Vec)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Folder.CreateExtractElement(VC, IC); + return Insert(Folder.CreateExtractElement(VC, IC), Name); return Insert(ExtractElementInst::Create(Vec, Idx), Name); } @@ -1094,7 +1133,7 @@ public: if (Constant *VC = dyn_cast<Constant>(Vec)) if (Constant *NC = dyn_cast<Constant>(NewElt)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Folder.CreateInsertElement(VC, NC, IC); + return Insert(Folder.CreateInsertElement(VC, NC, IC), Name); return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name); } @@ -1103,14 +1142,14 @@ public: if (Constant *V1C = dyn_cast<Constant>(V1)) if (Constant *V2C = dyn_cast<Constant>(V2)) if (Constant *MC = dyn_cast<Constant>(Mask)) - return Folder.CreateShuffleVector(V1C, V2C, MC); + return Insert(Folder.CreateShuffleVector(V1C, V2C, MC), Name); return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); } Value *CreateExtractValue(Value *Agg, unsigned Idx, const Twine &Name = "") { if (Constant *AggC = dyn_cast<Constant>(Agg)) - return Folder.CreateExtractValue(AggC, &Idx, 1); + return Insert(Folder.CreateExtractValue(AggC, &Idx, 1), Name); return Insert(ExtractValueInst::Create(Agg, Idx), Name); } @@ -1120,7 +1159,8 @@ public: RandomAccessIterator IdxEnd, const Twine &Name = "") { if (Constant *AggC = dyn_cast<Constant>(Agg)) - return Folder.CreateExtractValue(AggC, IdxBegin, IdxEnd - IdxBegin); + return Insert(Folder.CreateExtractValue(AggC, IdxBegin, IdxEnd-IdxBegin), + Name); return Insert(ExtractValueInst::Create(Agg, IdxBegin, IdxEnd), Name); } @@ -1128,7 +1168,7 @@ public: const Twine &Name = "") { if (Constant *AggC = dyn_cast<Constant>(Agg)) if (Constant *ValC = dyn_cast<Constant>(Val)) - return Folder.CreateInsertValue(AggC, ValC, &Idx, 1); + return Insert(Folder.CreateInsertValue(AggC, ValC, &Idx, 1), Name); return Insert(InsertValueInst::Create(Agg, Val, Idx), Name); } @@ -1139,7 +1179,9 @@ public: const Twine &Name = "") { if (Constant *AggC = dyn_cast<Constant>(Agg)) if (Constant *ValC = dyn_cast<Constant>(Val)) - return Folder.CreateInsertValue(AggC, ValC, IdxBegin, IdxEnd-IdxBegin); + return Insert(Folder.CreateInsertValue(AggC, ValC, IdxBegin, + IdxEnd - IdxBegin), + Name); return Insert(InsertValueInst::Create(Agg, Val, IdxBegin, IdxEnd), Name); } diff --git a/include/llvm/Support/IRReader.h b/include/llvm/Support/IRReader.h index a44da528ac..292c001e09 100644 --- a/include/llvm/Support/IRReader.h +++ b/include/llvm/Support/IRReader.h @@ -19,10 +19,12 @@ #ifndef LLVM_SUPPORT_IRREADER_H #define LLVM_SUPPORT_IRREADER_H +#include "llvm/ADT/OwningPtr.h" #include "llvm/Assembly/Parser.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/system_error.h" namespace llvm { @@ -56,15 +58,14 @@ namespace llvm { inline Module *getLazyIRFileModule(const std::string &Filename, SMDiagnostic &Err, LLVMContext &Context) { - std::string ErrMsg; - MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrMsg); - if (F == 0) { - Err = SMDiagnostic(Filename, - "Could not open input file: " + ErrMsg); + OwningPtr<MemoryBuffer> File; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { + Err = SMDiagnostic(Filename, + "Could not open input file: " + ec.message()); return 0; } - return getLazyIRModule(F, Err, Context); + return getLazyIRModule(File.take(), Err, Context); } /// If the given MemoryBuffer holds a bitcode image, return a Module @@ -94,15 +95,14 @@ namespace llvm { inline Module *ParseIRFile(const std::string &Filename, SMDiagnostic &Err, LLVMContext &Context) { - std::string ErrMsg; - MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrMsg); - if (F == 0) { - Err = SMDiagnostic(Filename, - "Could not open input file: " + ErrMsg); + OwningPtr<MemoryBuffer> File; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { + Err = SMDiagnostic(Filename, + "Could not open input file: " + ec.message()); return 0; } - return ParseIR(F, Err, Context); + return ParseIR(File.take(), Err, Context); } } diff --git a/include/llvm/System/IncludeFile.h b/include/llvm/Support/IncludeFile.h index 3268ea225f..a9319725d4 100644 --- a/include/llvm/System/IncludeFile.h +++ b/include/llvm/Support/IncludeFile.h @@ -1,4 +1,4 @@ -//===- llvm/System/IncludeFile.h - Ensure Linking Of Library ---*- C++ -*-===// +//===- llvm/Support/IncludeFile.h - Ensure Linking Of Library ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,14 +16,14 @@ #define LLVM_SYSTEM_INCLUDEFILE_H /// This macro is the public interface that IncludeFile.h exports. This gives -/// us the option to implement the "link the definition" capability in any +/// us the option to implement the "link the definition" capability in any /// manner that we choose. All header files that depend on a specific .cpp /// file being linked at run time should use this macro instead of the -/// IncludeFile class directly. -/// +/// IncludeFile class directly. +/// /// For example, foo.h would use:<br/> /// <tt>FORCE_DEFINING_FILE_TO_BE_LINKED(foo)</tt><br/> -/// +/// /// And, foo.cp would use:<br/> /// <tt>DEFINING_FILE_FOR(foo)</tt><br/> #ifdef __GNUC__ @@ -34,14 +34,14 @@ extern const char name ## LinkVar; \ __attribute__((used)) static const char *const name ## LinkObj = \ &name ## LinkVar; \ - } + } #else // Otherwise use a constructor call. #define FORCE_DEFINING_FILE_TO_BE_LINKED(name) \ namespace llvm { \ extern const char name ## LinkVar; \ static const IncludeFile name ## LinkObj ( &name ## LinkVar ); \ - } + } #endif /// This macro is the counterpart to FORCE_DEFINING_FILE_TO_BE_LINKED. It should @@ -53,9 +53,9 @@ namespace llvm { /// This class is used in the implementation of FORCE_DEFINING_FILE_TO_BE_LINKED -/// macro to make sure that the implementation of a header file is included -/// into a tool that uses the header. This is solely -/// to overcome problems linking .a files and not getting the implementation +/// macro to make sure that the implementation of a header file is included +/// into a tool that uses the header. This is solely +/// to overcome problems linking .a files and not getting the implementation /// of compilation units we need. This is commonly an issue with the various /// Passes but also occurs elsewhere in LLVM. We like to use .a files because /// they link faster and provide the smallest executables. However, sometimes diff --git a/include/llvm/System/LICENSE.TXT b/include/llvm/Support/LICENSE.TXT index f569da2052..3479b3fd74 100644 --- a/include/llvm/System/LICENSE.TXT +++ b/include/llvm/Support/LICENSE.TXT @@ -1,6 +1,6 @@ LLVM System Interface Library ------------------------------------------------------------------------------- -The LLVM System Interface Library is licensed under the Illinois Open Source +The LLVM System Interface Library is licensed under the Illinois Open Source License and has the following additional copyright: Copyright (C) 2004 eXtensible Systems, Inc. diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h index 964ac6a845..6841a0f1fc 100644 --- a/include/llvm/Support/MachO.h +++ b/include/llvm/Support/MachO.h @@ -14,7 +14,7 @@ #ifndef LLVM_SUPPORT_MACHO_H #define LLVM_SUPPORT_MACHO_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" // NOTE: The enums in this file are intentially named to be different than those // in the headers in /usr/include/mach (on darwin systems) to avoid conflicts @@ -23,7 +23,7 @@ namespace llvm { namespace MachO { // Enums from <mach-o/loader.h> enum { - // Constants for the "magic" field in llvm::MachO::mach_header and + // Constants for the "magic" field in llvm::MachO::mach_header and // llvm::MachO::mach_header_64 HeaderMagic32 = 0xFEEDFACEu, // MH_MAGIC HeaderMagic32Swapped = 0xCEFAEDFEu, // MH_CIGAM @@ -71,7 +71,7 @@ namespace llvm { HeaderFlagBitNoReexportedDylibs = 0x00100000u, // MH_NO_REEXPORTED_DYLIBS HeaderFlagBitPIE = 0x00200000u, // MH_PIE HeaderFlagBitDeadStrippableDylib = 0x00400000u, // MH_DEAD_STRIPPABLE_DYLIB - + // Constants for the "cmd" field in llvm::MachO::load_command LoadCommandDynamicLinkerRequired = 0x80000000u, // LC_REQ_DYLD LoadCommandSegment32 = 0x00000001u, // LC_SEGMENT @@ -110,7 +110,7 @@ namespace llvm { LoadCommandDynamicLinkerInfo = 0x00000022u, // LC_DYLD_INFO LoadCommandDynamicLinkerInfoOnly = 0x80000022u, // LC_DYLD_INFO_ONLY LoadCommandDylibLoadUpward = 0x80000023u, // LC_LOAD_UPWARD_DYLIB - + // Constant bits for the "flags" field in llvm::MachO::segment_command SegmentCommandFlagBitHighVM = 0x1u, // SG_HIGHVM SegmentCommandFlagBitFixedVMLibrary = 0x2u, // SG_FVMLIB @@ -243,20 +243,20 @@ namespace llvm { StabFunction = 0x24u, // N_FUN StabStaticSymbol = 0x26u, // N_STSYM StabLocalCommon = 0x28u, // N_LCSYM - StabBeginSymbol = 0x2Eu, // N_BNSYM + StabBeginSymbol = 0x2Eu, // N_BNSYM StabSourceFileOptions = 0x3Cu, // N_OPT StabRegisterSymbol = 0x40u, // N_RSYM StabSourceLine = 0x44u, // N_SLINE - StabEndSymbol = 0x4Eu, // N_ENSYM + StabEndSymbol = 0x4Eu, // N_ENSYM StabStructureType = 0x60u, // N_SSYM StabSourceFileName = 0x64u, // N_SO StabObjectFileName = 0x66u, // N_OSO StabLocalSymbol = 0x80u, // N_LSYM StabBeginIncludeFileName = 0x82u, // N_BINCL StabIncludeFileName = 0x84u, // N_SOL - StabCompilerParameters = 0x86u, // N_PARAMS - StabCompilerVersion = 0x88u, // N_VERSION - StabCompilerOptLevel = 0x8Au, // N_OLEVEL + StabCompilerParameters = 0x86u, // N_PARAMS + StabCompilerVersion = 0x88u, // N_VERSION + StabCompilerOptLevel = 0x8Au, // N_OLEVEL StabParameter = 0xA0u, // N_PSYM StabEndIncludeFile = 0xA2u, // N_EINCL StabAlternateEntry = 0xA4u, // N_ENTRY @@ -269,9 +269,9 @@ namespace llvm { StabLength = 0xFEu // N_LENG }; - + // Structs from <mach-o/loader.h> - + struct mach_header { uint32_t magic; uint32_t cputype; @@ -636,12 +636,12 @@ namespace llvm { }; // Get/Set functions from <mach-o/nlist.h> - + static inline uint16_t GET_LIBRARY_ORDINAL(uint16_t n_desc) { return (((n_desc) >> 8u) & 0xffu); } - + static inline void SET_LIBRARY_ORDINAL(uint16_t &n_desc, uint8_t ordinal) { n_desc = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8)); @@ -651,7 +651,7 @@ namespace llvm { { return (n_desc >> 8u) & 0x0fu; } - + static inline void SET_COMM_ALIGN (uint16_t &n_desc, uint8_t align) { n_desc = ((n_desc & 0xf0ffu) | ((align & 0x0fu) << 8u)); @@ -662,7 +662,7 @@ namespace llvm { // Capability bits used in the definition of cpu_type. CPUArchMask = 0xff000000, // Mask for architecture bits CPUArchABI64 = 0x01000000, // 64 bit ABI - + // Constants for the cputype field. CPUTypeI386 = 7, CPUTypeX86_64 = CPUTypeI386 | CPUArchABI64, @@ -673,11 +673,11 @@ namespace llvm { // Constants for the cpusubtype field. - + // X86 CPUSubType_I386_ALL = 3, CPUSubType_X86_64_ALL = 3, - + // ARM CPUSubType_ARM_ALL = 0, CPUSubType_ARM_V4T = 5, @@ -687,7 +687,7 @@ namespace llvm { // PowerPC CPUSubType_POWERPC_ALL = 0, - + CPUSubType_SPARC_ALL = 0 }; } // end namespace MachO diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h index a6b3341c16..53e73ad35f 100644 --- a/include/llvm/Support/ManagedStatic.h +++ b/include/llvm/Support/ManagedStatic.h @@ -14,8 +14,8 @@ #ifndef LLVM_SUPPORT_MANAGED_STATIC_H #define LLVM_SUPPORT_MANAGED_STATIC_H -#include "llvm/System/Atomic.h" -#include "llvm/System/Threading.h" +#include "llvm/Support/Atomic.h" +#include "llvm/Support/Threading.h" namespace llvm { diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index dafb479a99..4627557f7f 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -14,8 +14,7 @@ #ifndef LLVM_SUPPORT_MATHEXTRAS_H #define LLVM_SUPPORT_MATHEXTRAS_H -#include "llvm/System/DataTypes.h" -#include "llvm/System/SwapByteOrder.h" +#include "llvm/Support/SwapByteOrder.h" namespace llvm { @@ -77,6 +76,12 @@ inline bool isUIntN(unsigned N, uint64_t x) { return x == (x & (~0ULL >> (64 - N))); } +/// isIntN - Checks if an signed integer fits into the given (dynamic) +/// bit width. +inline bool isIntN(unsigned N, int64_t x) { + return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); +} + /// isMask_32 - This function returns true if the argument is a sequence of ones /// starting at the least significant bit with the remainder zero (32 bit /// version). Ex. isMask_32(0x0000FFFFU) == true. @@ -119,19 +124,19 @@ inline bool isPowerOf2_64(uint64_t Value) { /// ByteSwap_16 - This function returns a byte-swapped representation of the /// 16-bit argument, Value. inline uint16_t ByteSwap_16(uint16_t Value) { - return sys::SwapByteOrder(Value); + return sys::SwapByteOrder_16(Value); } /// ByteSwap_32 - This function returns a byte-swapped representation of the /// 32-bit argument, Value. inline uint32_t ByteSwap_32(uint32_t Value) { - return sys::SwapByteOrder(Value); + return sys::SwapByteOrder_32(Value); } /// ByteSwap_64 - This function returns a byte-swapped representation of the /// 64-bit argument, Value. inline uint64_t ByteSwap_64(uint64_t Value) { - return sys::SwapByteOrder(Value); + return sys::SwapByteOrder_64(Value); } /// CountLeadingZeros_32 - this function performs the platform optimal form of diff --git a/include/llvm/System/Memory.h b/include/llvm/Support/Memory.h index 2dd36e8ab1..9c3f85b958 100644 --- a/include/llvm/System/Memory.h +++ b/include/llvm/Support/Memory.h @@ -1,4 +1,4 @@ -//===- llvm/System/Memory.h - Memory Support --------------------*- C++ -*-===// +//===- llvm/Support/Memory.h - Memory Support --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_MEMORY_H #define LLVM_SYSTEM_MEMORY_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> namespace llvm { @@ -51,7 +51,7 @@ namespace sys { /// /// On success, this returns a non-null memory block, otherwise it returns /// a null memory block and fills in *ErrMsg. - /// + /// /// @brief Allocate Read/Write/Execute memory. static MemoryBlock AllocateRWX(size_t NumBytes, const MemoryBlock *NearBlock, @@ -65,8 +65,8 @@ namespace sys { /// in *ErrMsg. /// @brief Release Read/Write/Execute memory. static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = 0); - - + + /// InvalidateInstructionCache - Before the JIT can run a block of code /// that has been emitted it must invalidate the instruction cache on some /// platforms. @@ -82,11 +82,11 @@ namespace sys { /// boundaries, and the JIT internal allocations are not page aligned. static bool setWritable (MemoryBlock &M, std::string *ErrMsg = 0); - /// setRangeExecutable - Mark the page containing a range of addresses + /// setRangeExecutable - Mark the page containing a range of addresses /// as executable. static bool setRangeExecutable(const void *Addr, size_t Size); - /// setRangeWritable - Mark the page containing a range of addresses + /// setRangeWritable - Mark the page containing a range of addresses /// as writable. static bool setRangeWritable(const void *Addr, size_t Size); }; diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index eb3e25d3db..b6243b7b10 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -15,12 +15,13 @@ #define LLVM_SUPPORT_MEMORYBUFFER_H #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" -#include <string> -#include <sys/stat.h> +#include "llvm/Support/DataTypes.h" namespace llvm { +class error_code; +template<class T> class OwningPtr; + /// MemoryBuffer - This interface provides simple read-only access to a block /// of memory, and provides simple methods for reading files and standard input /// into a memory buffer. In addition to basic access to the characters in the @@ -47,8 +48,8 @@ public: const char *getBufferEnd() const { return BufferEnd; } size_t getBufferSize() const { return BufferEnd-BufferStart; } - StringRef getBuffer() const { - return StringRef(BufferStart, getBufferSize()); + StringRef getBuffer() const { + return StringRef(BufferStart, getBufferSize()); } /// getBufferIdentifier - Return an identifier for this buffer, typically the @@ -61,14 +62,17 @@ public: /// MemoryBuffer if successful, otherwise returning null. If FileSize is /// specified, this means that the client knows that the file exists and that /// it has the specified size. - static MemoryBuffer *getFile(StringRef Filename, - std::string *ErrStr = 0, - int64_t FileSize = -1, - struct stat *FileInfo = 0); - static MemoryBuffer *getFile(const char *Filename, - std::string *ErrStr = 0, - int64_t FileSize = -1, - struct stat *FileInfo = 0); + static error_code getFile(StringRef Filename, OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); + static error_code getFile(const char *Filename, + OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); + + /// getOpenFile - Given an already-open file descriptor, read the file and + /// return a MemoryBuffer. + static error_code getOpenFile(int FD, const char *Filename, + OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note /// that InputData must be null terminated. @@ -95,21 +99,19 @@ public: StringRef BufferName = ""); /// getSTDIN - Read all of stdin into a file buffer, and return it. - /// If an error occurs, this returns null and fills in *ErrStr with a reason. - static MemoryBuffer *getSTDIN(std::string *ErrStr = 0); + /// If an error occurs, this returns null and sets ec. + static error_code getSTDIN(OwningPtr<MemoryBuffer> &result); /// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin - /// if the Filename is "-". If an error occurs, this returns null and fills - /// in *ErrStr with a reason. - static MemoryBuffer *getFileOrSTDIN(StringRef Filename, - std::string *ErrStr = 0, - int64_t FileSize = -1, - struct stat *FileInfo = 0); - static MemoryBuffer *getFileOrSTDIN(const char *Filename, - std::string *ErrStr = 0, - int64_t FileSize = -1, - struct stat *FileInfo = 0); + /// if the Filename is "-". If an error occurs, this returns null and sets + /// ec. + static error_code getFileOrSTDIN(StringRef Filename, + OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); + static error_code getFileOrSTDIN(const char *Filename, + OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); }; } // end namespace llvm diff --git a/include/llvm/Support/MemoryObject.h b/include/llvm/Support/MemoryObject.h index e193ca2f2b..dec0f134b3 100644 --- a/include/llvm/Support/MemoryObject.h +++ b/include/llvm/Support/MemoryObject.h @@ -10,7 +10,7 @@ #ifndef MEMORYOBJECT_H #define MEMORYOBJECT_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/System/Mutex.h b/include/llvm/Support/Mutex.h index 71d10067c3..42ea63060f 100644 --- a/include/llvm/System/Mutex.h +++ b/include/llvm/Support/Mutex.h @@ -1,4 +1,4 @@ -//===- llvm/System/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===// +//===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_MUTEX_H #define LLVM_SYSTEM_MUTEX_H -#include "llvm/System/Threading.h" +#include "llvm/Support/Threading.h" #include <cassert> namespace llvm @@ -79,9 +79,9 @@ namespace llvm void operator=(const MutexImpl &); /// @} }; - - - /// SmartMutex - A mutex with a compile time constant parameter that + + + /// SmartMutex - A mutex with a compile time constant parameter that /// indicates whether this mutex should become a no-op when we're not /// running in multithreaded mode. template<bool mt_only> @@ -91,7 +91,7 @@ namespace llvm public: explicit SmartMutex(bool rec = true) : MutexImpl(rec), acquired(0), recursive(rec) { } - + bool acquire() { if (!mt_only || llvm_is_multithreaded()) { return MutexImpl::acquire(); @@ -124,29 +124,29 @@ namespace llvm return MutexImpl::tryacquire(); else return true; } - + private: SmartMutex(const SmartMutex<mt_only> & original); void operator=(const SmartMutex<mt_only> &); }; - + /// Mutex - A standard, always enforced mutex. typedef SmartMutex<false> Mutex; - + template<bool mt_only> class SmartScopedLock { SmartMutex<mt_only>& mtx; - + public: SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { mtx.acquire(); } - + ~SmartScopedLock() { mtx.release(); } }; - + typedef SmartScopedLock<false> ScopedLock; } } diff --git a/include/llvm/Support/MutexGuard.h b/include/llvm/Support/MutexGuard.h index 9958b97a3e..cd13bfe6ee 100644 --- a/include/llvm/Support/MutexGuard.h +++ b/include/llvm/Support/MutexGuard.h @@ -15,7 +15,7 @@ #ifndef LLVM_SUPPORT_MUTEXGUARD_H #define LLVM_SUPPORT_MUTEXGUARD_H -#include "llvm/System/Mutex.h" +#include "llvm/Support/Mutex.h" namespace llvm { /// Instances of this class acquire a given Mutex Lock when constructed and diff --git a/include/llvm/Support/NoFolder.h b/include/llvm/Support/NoFolder.h index 01256e18a5..92a9fd695e 100644 --- a/include/llvm/Support/NoFolder.h +++ b/include/llvm/Support/NoFolder.h @@ -15,8 +15,7 @@ // llvm/Analysis/ConstantFolding.h. // // Note: since it is not actually possible to create unfolded constants, this -// class returns values rather than constants. The values do not have names, -// even if names were provided to IRBuilder, which may be confusing. +// class returns instructions rather than constants. // //===----------------------------------------------------------------------===// @@ -30,7 +29,7 @@ namespace llvm { class LLVMContext; -/// NoFolder - Create "constants" (actually, values) with no folding. +/// NoFolder - Create "constants" (actually, instructions) with no folding. class NoFolder { public: explicit NoFolder(LLVMContext &) {} @@ -39,84 +38,115 @@ public: // Binary Operators //===--------------------------------------------------------------------===// - Value *CreateAdd(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateAdd(LHS, RHS); - } - Value *CreateNSWAdd(Constant *LHS, Constant *RHS) const { + Instruction *CreateAdd(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateAdd(LHS, RHS); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } + Instruction *CreateNSWAdd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNSWAdd(LHS, RHS); } - Value *CreateNUWAdd(Constant *LHS, Constant *RHS) const { + Instruction *CreateNUWAdd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNUWAdd(LHS, RHS); } - Value *CreateFAdd(Constant *LHS, Constant *RHS) const { + Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFAdd(LHS, RHS); } - Value *CreateSub(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateSub(LHS, RHS); + Instruction *CreateSub(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateSub(LHS, RHS); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; } - Value *CreateNSWSub(Constant *LHS, Constant *RHS) const { + Instruction *CreateNSWSub(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNSWSub(LHS, RHS); } - Value *CreateNUWSub(Constant *LHS, Constant *RHS) const { + Instruction *CreateNUWSub(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNUWSub(LHS, RHS); } - Value *CreateFSub(Constant *LHS, Constant *RHS) const { + Instruction *CreateFSub(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFSub(LHS, RHS); } - Value *CreateMul(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateMul(LHS, RHS); + Instruction *CreateMul(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateMul(LHS, RHS); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; } - Value *CreateNSWMul(Constant *LHS, Constant *RHS) const { + Instruction *CreateNSWMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNSWMul(LHS, RHS); } - Value *CreateNUWMul(Constant *LHS, Constant *RHS) const { + Instruction *CreateNUWMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNUWMul(LHS, RHS); } - Value *CreateFMul(Constant *LHS, Constant *RHS) const { + Instruction *CreateFMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFMul(LHS, RHS); } - Value *CreateUDiv(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateUDiv(LHS, RHS); + Instruction *CreateUDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + if (!isExact) + return BinaryOperator::CreateUDiv(LHS, RHS); + return BinaryOperator::CreateExactUDiv(LHS, RHS); + } + Instruction *CreateExactUDiv(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateExactUDiv(LHS, RHS); } - Value *CreateSDiv(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateSDiv(LHS, RHS); + Instruction *CreateSDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + if (!isExact) + return BinaryOperator::CreateSDiv(LHS, RHS); + return BinaryOperator::CreateExactSDiv(LHS, RHS); } - Value *CreateExactSDiv(Constant *LHS, Constant *RHS) const { + Instruction *CreateExactSDiv(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateExactSDiv(LHS, RHS); } - Value *CreateFDiv(Constant *LHS, Constant *RHS) const { + Instruction *CreateFDiv(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFDiv(LHS, RHS); } - Value *CreateURem(Constant *LHS, Constant *RHS) const { + Instruction *CreateURem(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateURem(LHS, RHS); } - Value *CreateSRem(Constant *LHS, Constant *RHS) const { + Instruction *CreateSRem(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateSRem(LHS, RHS); } - Value *CreateFRem(Constant *LHS, Constant *RHS) const { + Instruction *CreateFRem(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFRem(LHS, RHS); } - Value *CreateShl(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateShl(LHS, RHS); - } - Value *CreateLShr(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateLShr(LHS, RHS); - } - Value *CreateAShr(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateAShr(LHS, RHS); - } - Value *CreateAnd(Constant *LHS, Constant *RHS) const { + Instruction *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false, + bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateShl(LHS, RHS); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } + Instruction *CreateLShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + if (!isExact) + return BinaryOperator::CreateLShr(LHS, RHS); + return BinaryOperator::CreateExactLShr(LHS, RHS); + } + Instruction *CreateAShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + if (!isExact) + return BinaryOperator::CreateAShr(LHS, RHS); + return BinaryOperator::CreateExactAShr(LHS, RHS); + } + Instruction *CreateAnd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateAnd(LHS, RHS); } - Value *CreateOr(Constant *LHS, Constant *RHS) const { + Instruction *CreateOr(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateOr(LHS, RHS); } - Value *CreateXor(Constant *LHS, Constant *RHS) const { + Instruction *CreateXor(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateXor(LHS, RHS); } - Value *CreateBinOp(Instruction::BinaryOps Opc, - Constant *LHS, Constant *RHS) const { + Instruction *CreateBinOp(Instruction::BinaryOps Opc, + Constant *LHS, Constant *RHS) const { return BinaryOperator::Create(Opc, LHS, RHS); } @@ -124,16 +154,23 @@ public: // Unary Operators //===--------------------------------------------------------------------===// - Value *CreateNeg(Constant *C) const { - return BinaryOperator::CreateNeg(C); - } - Value *CreateNSWNeg(Constant *C) const { + Instruction *CreateNeg(Constant *C, + bool HasNUW = false, bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateNeg(C); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } + Instruction *CreateNSWNeg(Constant *C) const { return BinaryOperator::CreateNSWNeg(C); } - Value *CreateNUWNeg(Constant *C) const { + Instruction *CreateNUWNeg(Constant *C) const { return BinaryOperator::CreateNUWNeg(C); } - Value *CreateNot(Constant *C) const { + Instruction *CreateFNeg(Constant *C) const { + return BinaryOperator::CreateFNeg(C); + } + Instruction *CreateNot(Constant *C) const { return BinaryOperator::CreateNot(C); } @@ -145,8 +182,8 @@ public: unsigned NumIdx) const { return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); } - Value *CreateGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx) const { + Instruction *CreateGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { return GetElementPtrInst::Create(C, IdxList, IdxList+NumIdx); } @@ -154,8 +191,8 @@ public: unsigned NumIdx) const { return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); } - Value *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx) const { + Instruction *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { return GetElementPtrInst::CreateInBounds(C, IdxList, IdxList+NumIdx); } @@ -163,23 +200,51 @@ public: // Cast/Conversion Operators //===--------------------------------------------------------------------===// - Value *CreateCast(Instruction::CastOps Op, Constant *C, + Instruction *CreateCast(Instruction::CastOps Op, Constant *C, const Type *DestTy) const { return CastInst::Create(Op, C, DestTy); } - Value *CreateIntCast(Constant *C, const Type *DestTy, + Instruction *CreatePointerCast(Constant *C, const Type *DestTy) const { + return CastInst::CreatePointerCast(C, DestTy); + } + Instruction *CreateIntCast(Constant *C, const Type *DestTy, bool isSigned) const { return CastInst::CreateIntegerCast(C, DestTy, isSigned); } + Instruction *CreateFPCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateFPCast(C, DestTy); + } + + Instruction *CreateBitCast(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::BitCast, C, DestTy); + } + Instruction *CreateIntToPtr(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::IntToPtr, C, DestTy); + } + Instruction *CreatePtrToInt(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::PtrToInt, C, DestTy); + } + Instruction *CreateZExtOrBitCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateZExtOrBitCast(C, DestTy); + } + Instruction *CreateSExtOrBitCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateSExtOrBitCast(C, DestTy); + } + + Instruction *CreateTruncOrBitCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateTruncOrBitCast(C, DestTy); + } //===--------------------------------------------------------------------===// // Compare Instructions //===--------------------------------------------------------------------===// - Value *CreateICmp(CmpInst::Predicate P, Constant *LHS, Constant *RHS) const { + Instruction *CreateICmp(CmpInst::Predicate P, + Constant *LHS, Constant *RHS) const { return new ICmpInst(P, LHS, RHS); } - Value *CreateFCmp(CmpInst::Predicate P, Constant *LHS, Constant *RHS) const { + Instruction *CreateFCmp(CmpInst::Predicate P, + Constant *LHS, Constant *RHS) const { return new FCmpInst(P, LHS, RHS); } @@ -187,30 +252,33 @@ public: // Other Instructions //===--------------------------------------------------------------------===// - Value *CreateSelect(Constant *C, Constant *True, Constant *False) const { + Instruction *CreateSelect(Constant *C, + Constant *True, Constant *False) const { return SelectInst::Create(C, True, False); } - Value *CreateExtractElement(Constant *Vec, Constant *Idx) const { + Instruction *CreateExtractElement(Constant *Vec, Constant *Idx) const { return ExtractElementInst::Create(Vec, Idx); } - Value *CreateInsertElement(Constant *Vec, Constant *NewElt, - Constant *Idx) const { + Instruction *CreateInsertElement(Constant *Vec, Constant *NewElt, + Constant *Idx) const { return InsertElementInst::Create(Vec, NewElt, Idx); } - Value *CreateShuffleVector(Constant *V1, Constant *V2, Constant *Mask) const { + Instruction *CreateShuffleVector(Constant *V1, Constant *V2, + Constant *Mask) const { return new ShuffleVectorInst(V1, V2, Mask); } - Value *CreateExtractValue(Constant *Agg, const unsigned *IdxList, - unsigned NumIdx) const { + Instruction *CreateExtractValue(Constant *Agg, const unsigned *IdxList, + unsigned NumIdx) const { return ExtractValueInst::Create(Agg, IdxList, IdxList+NumIdx); } - Value *CreateInsertValue(Constant *Agg, Constant *Val, - const unsigned *IdxList, unsigned NumIdx) const { + Instruction *CreateInsertValue(Constant *Agg, Constant *Val, + const unsigned *IdxList, + unsigned NumIdx) const { return InsertValueInst::Create(Agg, Val, IdxList, IdxList+NumIdx); } }; diff --git a/include/llvm/Support/Path.h b/include/llvm/Support/Path.h new file mode 100644 index 0000000000..196eecce81 --- /dev/null +++ b/include/llvm/Support/Path.h @@ -0,0 +1,16 @@ +//===- llvm/Support/Path.h - Path Operating System Concept ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file currently includes both PathV1 and PathV2 to facilitate moving +// clients over to the new interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/PathV1.h" +#include "llvm/Support/PathV2.h" diff --git a/include/llvm/System/Path.h b/include/llvm/Support/PathV1.h index eca9dd9f87..d7753a3e71 100644 --- a/include/llvm/System/Path.h +++ b/include/llvm/Support/PathV1.h @@ -1,4 +1,4 @@ -//===- llvm/System/Path.h - Path Operating System Concept -------*- C++ -*-===// +//===- llvm/Support/PathV1.h - Path Operating System Concept ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,11 +15,17 @@ #define LLVM_SYSTEM_PATH_H #include "llvm/ADT/StringRef.h" -#include "llvm/System/TimeValue.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/TimeValue.h" #include <set> #include <string> #include <vector> +#define LLVM_PATH_DEPRECATED_MSG(replacement) \ + "PathV1 has been deprecated and will be removed as soon as all LLVM and" \ + " Clang clients have been moved over to PathV2. Please use `" #replacement \ + "` from PathV2 instead." + namespace llvm { namespace sys { @@ -92,7 +98,8 @@ namespace sys { /// it is file:///. Other operating systems may have different notions of /// what the root directory is or none at all. In that case, a consistent /// default root directory will be used. - static Path GetRootDirectory(); + LLVM_ATTRIBUTE_DEPRECATED(static Path GetRootDirectory(), + LLVM_PATH_DEPRECATED_MSG(NOTHING)); /// Construct a path to a unique temporary directory that is created in /// a "standard" place for the operating system. The directory is @@ -100,7 +107,7 @@ namespace sys { /// cannot be created, the function will throw an exception. /// @returns an invalid path (empty) on error /// @param ErrMsg Optional place for an error message if an error occurs - /// @brief Constrct a path to an new, unique, existing temporary + /// @brief Construct a path to an new, unique, existing temporary /// directory. static Path GetTemporaryDirectory(std::string* ErrMsg = 0); @@ -254,23 +261,27 @@ namespace sys { bool isEmpty() const { return path.empty(); } /// This function returns the last component of the path name. The last - /// component is the file or directory name occuring after the last + /// component is the file or directory name occurring after the last /// directory separator. If no directory separator is present, the entire /// path name is returned (i.e. same as toString). /// @returns StringRef containing the last component of the path name. /// @brief Returns the last component of the path name. - StringRef getLast() const; + LLVM_ATTRIBUTE_DEPRECATED( + StringRef getLast() const, + LLVM_PATH_DEPRECATED_MSG(path::filename)); /// This function strips off the path and suffix of the file or directory /// name and returns just the basename. For example /a/foo.bar would cause /// this function to return "foo". /// @returns StringRef containing the basename of the path /// @brief Get the base name of the path - StringRef getBasename() const; + LLVM_ATTRIBUTE_DEPRECATED(StringRef getBasename() const, + LLVM_PATH_DEPRECATED_MSG(path::stem)); /// This function strips off the suffix of the path beginning with the /// path separator ('/' on Unix, '\' on Windows) and returns the result. - StringRef getDirname() const; + LLVM_ATTRIBUTE_DEPRECATED(StringRef getDirname() const, + LLVM_PATH_DEPRECATED_MSG(path::parent_path)); /// This function strips off the path and basename(up to and /// including the last dot) of the file or directory name and @@ -278,7 +289,8 @@ namespace sys { /// this function to return "bar". /// @returns StringRef containing the suffix of the path /// @brief Get the suffix of the path - StringRef getSuffix() const; + LLVM_ATTRIBUTE_DEPRECATED(StringRef getSuffix() const, + LLVM_PATH_DEPRECATED_MSG(path::extension)); /// Obtain a 'C' string for the path name. /// @returns a 'C' string containing the path name. @@ -300,12 +312,16 @@ namespace sys { /// This function determines if the path name is absolute, as opposed to /// relative. /// @brief Determine if the path is absolute. - bool isAbsolute() const; + LLVM_ATTRIBUTE_DEPRECATED( + bool isAbsolute() const, + LLVM_PATH_DEPRECATED_MSG(path::is_absolute)); /// This function determines if the path name is absolute, as opposed to /// relative. /// @brief Determine if the path is absolute. - static bool isAbsolute(const char *NameStart, unsigned NameLen); + LLVM_ATTRIBUTE_DEPRECATED( + static bool isAbsolute(const char *NameStart, unsigned NameLen), + LLVM_PATH_DEPRECATED_MSG(path::is_absolute)); /// This function opens the file associated with the path name provided by /// the Path object and reads its magic number. If the magic number at the @@ -313,7 +329,8 @@ namespace sys { /// cases (file not found, file not accessible, etc.) it returns false. /// @returns true if the magic number of the file matches \p magic. /// @brief Determine if file has a specific magic number - bool hasMagicNumber(StringRef magic) const; + LLVM_ATTRIBUTE_DEPRECATED(bool hasMagicNumber(StringRef magic) const, + LLVM_PATH_DEPRECATED_MSG(fs::has_magic)); /// This function retrieves the first \p len bytes of the file associated /// with \p this. These bytes are returned as the "magic number" in the @@ -363,19 +380,22 @@ namespace sys { /// directory. /// @brief Determines if the path is a file or directory in /// the file system. - bool exists() const; + LLVM_ATTRIBUTE_DEPRECATED(bool exists() const, + LLVM_PATH_DEPRECATED_MSG(fs::exists)); /// This function determines if the path name references an /// existing directory. /// @returns true if the pathname references an existing directory. /// @brief Determines if the path is a directory in the file system. - bool isDirectory() const; + LLVM_ATTRIBUTE_DEPRECATED(bool isDirectory() const, + LLVM_PATH_DEPRECATED_MSG(fs::is_directory)); /// This function determines if the path name references an /// existing symbolic link. /// @returns true if the pathname references an existing symlink. /// @brief Determines if the path is a symlink in the file system. - bool isSymLink() const; + LLVM_ATTRIBUTE_DEPRECATED(bool isSymLink() const, + LLVM_PATH_DEPRECATED_MSG(fs::is_symlink)); /// This function determines if the path name references a readable file /// or directory in the file system. This function checks for @@ -455,14 +475,9 @@ namespace sys { bool appendComponent(StringRef component); /// A period and the \p suffix are appended to the end of the pathname. - /// The precondition for this function is that the Path reference a file - /// name (i.e. isFile() returns true). If the Path is not a file, no - /// action is taken and the function returns false. If the path would - /// become invalid for the host operating system, false is returned. When - /// the \p suffix is empty, no action is performed. - /// @returns false if the suffix could not be added, true if it was. + /// When the \p suffix is empty, no action is performed. /// @brief Adds a period and the \p suffix to the end of the pathname. - bool appendSuffix(StringRef suffix); + void appendSuffix(StringRef suffix); /// The suffix of the filename is erased. The suffix begins with and /// includes the last . character in the filename after the last directory @@ -484,7 +499,9 @@ namespace sys { /// The current Path name is made absolute by prepending the /// current working directory if necessary. - void makeAbsolute(); + LLVM_ATTRIBUTE_DEPRECATED( + void makeAbsolute(), + LLVM_PATH_DEPRECATED_MSG(fs::make_absolute)); /// @} /// @name Disk Mutators @@ -616,7 +633,7 @@ namespace sys { /// efficiency. First, the file status requires additional space and the space /// is incorporated directly into PathWithStatus without an additional malloc. /// Second, obtaining status information is an expensive operation on most - /// operating systems so we want to be careful and explicity about where we + /// operating systems so we want to be careful and explicit about where we /// allow this operation in LLVM. /// @brief Path with file status class. class PathWithStatus : public Path { @@ -710,7 +727,7 @@ namespace sys { Mach_O_Executable_FileType, ///< Mach-O Executable Mach_O_FixedVirtualMemorySharedLib_FileType, ///< Mach-O Shared Lib, FVM Mach_O_Core_FileType, ///< Mach-O Core File - Mach_O_PreloadExectuable_FileType, ///< Mach-O Preloaded Executable + Mach_O_PreloadExecutable_FileType, ///< Mach-O Preloaded Executable Mach_O_DynamicallyLinkedSharedLib_FileType, ///< Mach-O dynlinked shared lib Mach_O_DynamicLinker_FileType, ///< The Mach-O dynamic linker Mach_O_Bundle_FileType, ///< Mach-O Bundle file diff --git a/include/llvm/Support/PathV2.h b/include/llvm/Support/PathV2.h new file mode 100644 index 0000000000..251563398f --- /dev/null +++ b/include/llvm/Support/PathV2.h @@ -0,0 +1,347 @@ +//===- llvm/Support/PathV2.h - Path Operating System Concept ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::path namespace. It is designed after +// TR2/boost filesystem (v3), but modified to remove exception handling and the +// path class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PATHV2_H +#define LLVM_SUPPORT_PATHV2_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/DataTypes.h" +#include <iterator> + +namespace llvm { +namespace sys { +namespace path { + +/// @name Lexical Component Iterator +/// @{ + +/// @brief Path iterator. +/// +/// This is a bidirectional iterator that iterates over the individual +/// components in \a path. The forward traversal order is as follows: +/// * The root-name element, if present. +/// * The root-directory element, if present. +/// * Each successive filename element, if present. +/// * Dot, if one or more trailing non-root slash characters are present. +/// The backwards traversal order is the reverse of forward traversal. +/// +/// Iteration examples. Each component is separated by ',': +/// / => / +/// /foo => /,foo +/// foo/ => foo,. +/// /foo/bar => /,foo,bar +/// ../ => ..,. +/// C:\foo\bar => C:,/,foo,bar +/// +class const_iterator { + StringRef Path; //< The entire path. + StringRef Component; //< The current component. Not necessarily in Path. + size_t Position; //< The iterators current position within Path. + + // An end iterator has Position = Path.size() + 1. + friend const_iterator begin(StringRef path); + friend const_iterator end(StringRef path); + +public: + typedef const StringRef value_type; + typedef ptrdiff_t difference_type; + typedef value_type &reference; + typedef value_type *pointer; + typedef std::bidirectional_iterator_tag iterator_category; + + reference operator*() const { return Component; } + pointer operator->() const { return &Component; } + const_iterator &operator++(); // preincrement + const_iterator &operator++(int); // postincrement + const_iterator &operator--(); // predecrement + const_iterator &operator--(int); // postdecrement + bool operator==(const const_iterator &RHS) const; + bool operator!=(const const_iterator &RHS) const; + + /// @brief Difference in bytes between this and RHS. + ptrdiff_t operator-(const const_iterator &RHS) const; +}; + +typedef std::reverse_iterator<const_iterator> reverse_iterator; + +/// @brief Get begin iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized with the first component of \a path. +const_iterator begin(StringRef path); + +/// @brief Get end iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized to the end of \a path. +const_iterator end(StringRef path); + +/// @brief Get reverse begin iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized with the first reverse component of \a path. +inline reverse_iterator rbegin(StringRef path) { + return reverse_iterator(end(path)); +} + +/// @brief Get reverse end iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized to the reverse end of \a path. +inline reverse_iterator rend(StringRef path) { + return reverse_iterator(begin(path)); +} + +/// @} +/// @name Lexical Modifiers +/// @{ + +/// @brief Remove the last component from \a path unless it is the root dir. +/// +/// directory/filename.cpp => directory/ +/// directory/ => directory +/// / => / +/// +/// @param path A path that is modified to not have a file component. +void remove_filename(SmallVectorImpl<char> &path); + +/// @brief Replace the file extension of \a path with \a extension. +/// +/// ./filename.cpp => ./filename.extension +/// ./filename => ./filename.extension +/// ./ => ./.extension +/// +/// @param path A path that has its extension replaced with \a extension. +/// @param extension The extension to be added. It may be empty. It may also +/// optionally start with a '.', if it does not, one will be +/// prepended. +void replace_extension(SmallVectorImpl<char> &path, const Twine &extension); + +/// @brief Append to path. +/// +/// /foo + bar/f => /foo/bar/f +/// /foo/ + bar/f => /foo/bar/f +/// foo + bar/f => foo/bar/f +/// +/// @param path Set to \a path + \a component. +/// @param component The component to be appended to \a path. +void append(SmallVectorImpl<char> &path, const Twine &a, + const Twine &b = "", + const Twine &c = "", + const Twine &d = ""); + +/// @brief Append to path. +/// +/// /foo + [bar,f] => /foo/bar/f +/// /foo/ + [bar,f] => /foo/bar/f +/// foo + [bar,f] => foo/bar/f +/// +/// @param path Set to \a path + [\a begin, \a end). +/// @param begin Start of components to append. +/// @param end One past the end of components to append. +void append(SmallVectorImpl<char> &path, + const_iterator begin, const_iterator end); + +/// @} +/// @name Transforms (or some other better name) +/// @{ + +/// Convert path to the native form. This is used to give paths to users and +/// operating system calls in the platform's normal way. For example, on Windows +/// all '/' are converted to '\'. +/// +/// @param path A path that is transformed to native format. +/// @param result Holds the result of the transformation. +void native(const Twine &path, SmallVectorImpl<char> &result); + +/// @} +/// @name Lexical Observers +/// @{ + +/// @brief Get root name. +/// +/// //net/hello => //net +/// c:/hello => c: (on Windows, on other platforms nothing) +/// /hello => <empty> +/// +/// @param path Input path. +/// @result The root name of \a path if it has one, otherwise "". +const StringRef root_name(StringRef path); + +/// @brief Get root directory. +/// +/// /goo/hello => / +/// c:/hello => / +/// d/file.txt => <empty> +/// +/// @param path Input path. +/// @result The root directory of \a path if it has one, otherwise +/// "". +const StringRef root_directory(StringRef path); + +/// @brief Get root path. +/// +/// Equivalent to root_name + root_directory. +/// +/// @param path Input path. +/// @result The root path of \a path if it has one, otherwise "". +const StringRef root_path(StringRef path); + +/// @brief Get relative path. +/// +/// C:\hello\world => hello\world +/// foo/bar => foo/bar +/// /foo/bar => foo/bar +/// +/// @param path Input path. +/// @result The path starting after root_path if one exists, otherwise "". +const StringRef relative_path(StringRef path); + +/// @brief Get parent path. +/// +/// / => <empty> +/// /foo => / +/// foo/../bar => foo/.. +/// +/// @param path Input path. +/// @result The parent path of \a path if one exists, otherwise "". +const StringRef parent_path(StringRef path); + +/// @brief Get filename. +/// +/// /foo.txt => foo.txt +/// . => . +/// .. => .. +/// / => / +/// +/// @param path Input path. +/// @result The filename part of \a path. This is defined as the last component +/// of \a path. +const StringRef filename(StringRef path); + +/// @brief Get stem. +/// +/// If filename contains a dot but not solely one or two dots, result is the +/// substring of filename ending at (but not including) the last dot. Otherwise +/// it is filename. +/// +/// /foo/bar.txt => bar +/// /foo/bar => bar +/// /foo/.txt => <empty> +/// /foo/. => . +/// /foo/.. => .. +/// +/// @param path Input path. +/// @result The stem of \a path. +const StringRef stem(StringRef path); + +/// @brief Get extension. +/// +/// If filename contains a dot but not solely one or two dots, result is the +/// substring of filename starting at (and including) the last dot, and ending +/// at the end of \a path. Otherwise "". +/// +/// /foo/bar.txt => .txt +/// /foo/bar => <empty> +/// /foo/.txt => .txt +/// +/// @param path Input path. +/// @result The extension of \a path. +const StringRef extension(StringRef path); + +/// @brief Check whether the given char is a path separator on the host OS. +/// +/// @param value a character +/// @result true if \a value is a path separator character on the host OS +bool is_separator(char value); + +/// @brief Has root name? +/// +/// root_name != "" +/// +/// @param path Input path. +/// @result True if the path has a root name, false otherwise. +bool has_root_name(const Twine &path); + +/// @brief Has root directory? +/// +/// root_directory != "" +/// +/// @param path Input path. +/// @result True if the path has a root directory, false otherwise. +bool has_root_directory(const Twine &path); + +/// @brief Has root path? +/// +/// root_path != "" +/// +/// @param path Input path. +/// @result True if the path has a root path, false otherwise. +bool has_root_path(const Twine &path); + +/// @brief Has relative path? +/// +/// relative_path != "" +/// +/// @param path Input path. +/// @result True if the path has a relative path, false otherwise. +bool has_relative_path(const Twine &path); + +/// @brief Has parent path? +/// +/// parent_path != "" +/// +/// @param path Input path. +/// @result True if the path has a parent path, false otherwise. +bool has_parent_path(const Twine &path); + +/// @brief Has filename? +/// +/// filename != "" +/// +/// @param path Input path. +/// @result True if the path has a filename, false otherwise. +bool has_filename(const Twine &path); + +/// @brief Has stem? +/// +/// stem != "" +/// +/// @param path Input path. +/// @result True if the path has a stem, false otherwise. +bool has_stem(const Twine &path); + +/// @brief Has extension? +/// +/// extension != "" +/// +/// @param path Input path. +/// @result True if the path has a extension, false otherwise. +bool has_extension(const Twine &path); + +/// @brief Is path absolute? +/// +/// @param path Input path. +/// @result True if the path is absolute, false if it is not. +bool is_absolute(const Twine &path); + +/// @brief Is path relative? +/// +/// @param path Input path. +/// @result True if the path is relative, false if it is not. +bool is_relative(const Twine &path); + +} // end namespace path +} // end namespace sys +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/PatternMatch.h b/include/llvm/Support/PatternMatch.h index bee6768637..948ae5176e 100644 --- a/include/llvm/Support/PatternMatch.h +++ b/include/llvm/Support/PatternMatch.h @@ -41,18 +41,62 @@ bool match(Val *V, const Pattern &P) { } template<typename Class> -struct leaf_ty { +struct class_match { template<typename ITy> bool match(ITy *V) { return isa<Class>(V); } }; /// m_Value() - Match an arbitrary value and ignore it. -inline leaf_ty<Value> m_Value() { return leaf_ty<Value>(); } +inline class_match<Value> m_Value() { return class_match<Value>(); } /// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it. -inline leaf_ty<ConstantInt> m_ConstantInt() { return leaf_ty<ConstantInt>(); } +inline class_match<ConstantInt> m_ConstantInt() { + return class_match<ConstantInt>(); +} +/// m_Undef() - Match an arbitrary undef constant. +inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); } +inline class_match<Constant> m_Constant() { return class_match<Constant>(); } + +struct match_zero { + template<typename ITy> + bool match(ITy *V) { + if (const Constant *C = dyn_cast<Constant>(V)) + return C->isNullValue(); + return false; + } +}; + +/// m_Zero() - Match an arbitrary zero/null constant. This includes +/// zero_initializer for vectors and ConstantPointerNull for pointers. +inline match_zero m_Zero() { return match_zero(); } + + +struct apint_match { + const APInt *&Res; + apint_match(const APInt *&R) : Res(R) {} + template<typename ITy> + bool match(ITy *V) { + if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) { + Res = &CI->getValue(); + return true; + } + if (ConstantVector *CV = dyn_cast<ConstantVector>(V)) + if (ConstantInt *CI = + dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) { + Res = &CI->getValue(); + return true; + } + return false; + } +}; + +/// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the +/// specified pointer to the contained APInt. +inline apint_match m_APInt(const APInt *&Res) { return Res; } + + template<int64_t Val> -struct constantint_ty { +struct constantint_match { template<typename ITy> bool match(ITy *V) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) { @@ -68,37 +112,82 @@ struct constantint_ty { } }; -/// m_ConstantInt(int64_t) - Match a ConstantInt with a specific value -/// and ignore it. +/// m_ConstantInt<int64_t> - Match a ConstantInt with a specific value. template<int64_t Val> -inline constantint_ty<Val> m_ConstantInt() { - return constantint_ty<Val>(); +inline constantint_match<Val> m_ConstantInt() { + return constantint_match<Val>(); } -struct zero_ty { +/// cst_pred_ty - This helper class is used to match scalar and vector constants +/// that satisfy a specified predicate. +template<typename Predicate> +struct cst_pred_ty : public Predicate { template<typename ITy> bool match(ITy *V) { - if (const Constant *C = dyn_cast<Constant>(V)) - return C->isNullValue(); + if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) + return this->isValue(CI->getValue()); + if (const ConstantVector *CV = dyn_cast<ConstantVector>(V)) + if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) + return this->isValue(CI->getValue()); return false; } }; - -/// m_Zero() - Match an arbitrary zero/null constant. -inline zero_ty m_Zero() { return zero_ty(); } - -struct one_ty { + +/// api_pred_ty - This helper class is used to match scalar and vector constants +/// that satisfy a specified predicate, and bind them to an APInt. +template<typename Predicate> +struct api_pred_ty : public Predicate { + const APInt *&Res; + api_pred_ty(const APInt *&R) : Res(R) {} template<typename ITy> bool match(ITy *V) { - if (const ConstantInt *C = dyn_cast<ConstantInt>(V)) - return C->isOne(); + if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) + if (this->isValue(CI->getValue())) { + Res = &CI->getValue(); + return true; + } + if (const ConstantVector *CV = dyn_cast<ConstantVector>(V)) + if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) + if (this->isValue(CI->getValue())) { + Res = &CI->getValue(); + return true; + } return false; } }; + + +struct is_one { + bool isValue(const APInt &C) { return C == 1; } +}; -/// m_One() - Match a an integer 1. -inline one_ty m_One() { return one_ty(); } +/// m_One() - Match an integer 1 or a vector with all elements equal to 1. +inline cst_pred_ty<is_one> m_One() { return cst_pred_ty<is_one>(); } +inline api_pred_ty<is_one> m_One(const APInt *&V) { return V; } + +struct is_all_ones { + bool isValue(const APInt &C) { return C.isAllOnesValue(); } +}; +/// m_AllOnes() - Match an integer or vector with all bits set to true. +inline cst_pred_ty<is_all_ones> m_AllOnes() {return cst_pred_ty<is_all_ones>();} +inline api_pred_ty<is_all_ones> m_AllOnes(const APInt *&V) { return V; } + +struct is_sign_bit { + bool isValue(const APInt &C) { return C.isSignBit(); } +}; + +/// m_SignBit() - Match an integer or vector with only the sign bit(s) set. +inline cst_pred_ty<is_sign_bit> m_SignBit() {return cst_pred_ty<is_sign_bit>();} +inline api_pred_ty<is_sign_bit> m_SignBit(const APInt *&V) { return V; } + +struct is_power2 { + bool isValue(const APInt &C) { return C.isPowerOf2(); } +}; + +/// m_Power2() - Match an integer or vector power of 2. +inline cst_pred_ty<is_power2> m_Power2() { return cst_pred_ty<is_power2>(); } +inline api_pred_ty<is_power2> m_Power2(const APInt *&V) { return V; } template<typename Class> struct bind_ty { @@ -121,6 +210,9 @@ inline bind_ty<Value> m_Value(Value *&V) { return V; } /// m_ConstantInt - Match a ConstantInt, capturing the value if we match. inline bind_ty<ConstantInt> m_ConstantInt(ConstantInt *&CI) { return CI; } +/// m_Constant - Match a Constant, capturing the value if we match. +inline bind_ty<Constant> m_Constant(Constant *&C) { return C; } + /// specificval_ty - Match a specified Value*. struct specificval_ty { const Value *Val; @@ -140,8 +232,7 @@ inline specificval_ty m_Specific(const Value *V) { return V; } // Matchers for specific binary operators. // -template<typename LHS_t, typename RHS_t, - unsigned Opcode, typename ConcreteTy = BinaryOperator> +template<typename LHS_t, typename RHS_t, unsigned Opcode> struct BinaryOp_match { LHS_t L; RHS_t R; @@ -151,9 +242,8 @@ struct BinaryOp_match { template<typename OpTy> bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opcode) { - ConcreteTy *I = cast<ConcreteTy>(V); - return I->getOpcode() == Opcode && L.match(I->getOperand(0)) && - R.match(I->getOperand(1)); + BinaryOperator *I = cast<BinaryOperator>(V); + return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && @@ -163,193 +253,156 @@ struct BinaryOp_match { }; template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Add> m_Add(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Add> +m_Add(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Add>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FAdd> m_FAdd(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FAdd> +m_FAdd(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FAdd>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Sub> m_Sub(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Sub> +m_Sub(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Sub>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FSub> m_FSub(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FSub> +m_FSub(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Mul> +m_Mul(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Mul>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FMul> m_FMul(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FMul> +m_FMul(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FMul>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::UDiv> m_UDiv(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::UDiv> +m_UDiv(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::UDiv>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::SDiv> m_SDiv(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::SDiv> +m_SDiv(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::SDiv>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FDiv> m_FDiv(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FDiv> +m_FDiv(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FDiv>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::URem> m_URem(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::URem> +m_URem(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::URem>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::SRem> m_SRem(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::SRem> +m_SRem(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::SRem>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FRem> m_FRem(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FRem> +m_FRem(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FRem>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::And> m_And(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::And> +m_And(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::And>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Or> m_Or(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Or> +m_Or(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Or>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Xor> m_Xor(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Xor> +m_Xor(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Xor>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Shl> m_Shl(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Shl> +m_Shl(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Shl>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::LShr> m_LShr(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::LShr> +m_LShr(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::LShr>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::AShr> m_AShr(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::AShr> +m_AShr(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, R); } //===----------------------------------------------------------------------===// -// Matchers for either AShr or LShr .. for convenience +// Class that matches two different binary ops. // -template<typename LHS_t, typename RHS_t, typename ConcreteTy = BinaryOperator> -struct Shr_match { +template<typename LHS_t, typename RHS_t, unsigned Opc1, unsigned Opc2> +struct BinOp2_match { LHS_t L; RHS_t R; - Shr_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} template<typename OpTy> bool match(OpTy *V) { - if (V->getValueID() == Value::InstructionVal + Instruction::LShr || - V->getValueID() == Value::InstructionVal + Instruction::AShr) { - ConcreteTy *I = cast<ConcreteTy>(V); - return (I->getOpcode() == Instruction::AShr || - I->getOpcode() == Instruction::LShr) && - L.match(I->getOperand(0)) && - R.match(I->getOperand(1)); + if (V->getValueID() == Value::InstructionVal + Opc1 || + V->getValueID() == Value::InstructionVal + Opc2) { + BinaryOperator *I = cast<BinaryOperator>(V); + return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) - return (CE->getOpcode() == Instruction::LShr || - CE->getOpcode() == Instruction::AShr) && - L.match(CE->getOperand(0)) && - R.match(CE->getOperand(1)); + return (CE->getOpcode() == Opc1 || CE->getOpcode() == Opc2) && + L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; +/// m_Shr - Matches LShr or AShr. template<typename LHS, typename RHS> -inline Shr_match<LHS, RHS> m_Shr(const LHS &L, const RHS &R) { - return Shr_match<LHS, RHS>(L, R); +inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr> +m_Shr(const LHS &L, const RHS &R) { + return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr>(L, R); } -//===----------------------------------------------------------------------===// -// Matchers for binary classes -// - -template<typename LHS_t, typename RHS_t, typename Class, typename OpcType> -struct BinaryOpClass_match { - OpcType *Opcode; - LHS_t L; - RHS_t R; - - BinaryOpClass_match(OpcType &Op, const LHS_t &LHS, - const RHS_t &RHS) - : Opcode(&Op), L(LHS), R(RHS) {} - BinaryOpClass_match(const LHS_t &LHS, const RHS_t &RHS) - : Opcode(0), L(LHS), R(RHS) {} - - template<typename OpTy> - bool match(OpTy *V) { - if (Class *I = dyn_cast<Class>(V)) - if (L.match(I->getOperand(0)) && - R.match(I->getOperand(1))) { - if (Opcode) - *Opcode = I->getOpcode(); - return true; - } -#if 0 // Doesn't handle constantexprs yet! - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) - return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && - R.match(CE->getOperand(1)); -#endif - return false; - } -}; - +/// m_LogicalShift - Matches LShr or Shl. template<typename LHS, typename RHS> -inline BinaryOpClass_match<LHS, RHS, BinaryOperator, Instruction::BinaryOps> -m_Shift(Instruction::BinaryOps &Op, const LHS &L, const RHS &R) { - return BinaryOpClass_match<LHS, RHS, - BinaryOperator, Instruction::BinaryOps>(Op, L, R); +inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl> +m_LogicalShift(const LHS &L, const RHS &R) { + return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl>(L, R); } +/// m_IDiv - Matches UDiv and SDiv. template<typename LHS, typename RHS> -inline BinaryOpClass_match<LHS, RHS, BinaryOperator, Instruction::BinaryOps> -m_Shift(const LHS &L, const RHS &R) { - return BinaryOpClass_match<LHS, RHS, - BinaryOperator, Instruction::BinaryOps>(L, R); +inline BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv> +m_IDiv(const LHS &L, const RHS &R) { + return BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv>(L, R); } //===----------------------------------------------------------------------===// @@ -362,15 +415,13 @@ struct CmpClass_match { LHS_t L; RHS_t R; - CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, - const RHS_t &RHS) + CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS) : Predicate(Pred), L(LHS), R(RHS) {} template<typename OpTy> bool match(OpTy *V) { if (Class *I = dyn_cast<Class>(V)) - if (L.match(I->getOperand(0)) && - R.match(I->getOperand(1))) { + if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { Predicate = I->getPredicate(); return true; } @@ -425,11 +476,9 @@ m_Select(const Cond &C, const LHS &L, const RHS &R) { /// m_SelectCst - This matches a select of two constants, e.g.: /// m_SelectCst<-1, 0>(m_Value(V)) template<int64_t L, int64_t R, typename Cond> -inline SelectClass_match<Cond, constantint_ty<L>, constantint_ty<R> > +inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R> > m_SelectCst(const Cond &C) { - return SelectClass_match<Cond, constantint_ty<L>, - constantint_ty<R> >(C, m_ConstantInt<L>(), - m_ConstantInt<R>()); + return m_Select(C, m_ConstantInt<L>(), m_ConstantInt<R>()); } @@ -507,20 +556,14 @@ struct not_match { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (CE->getOpcode() == Instruction::Xor) return matchIfNot(CE->getOperand(0), CE->getOperand(1)); - if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) - return L.match(ConstantExpr::getNot(CI)); return false; } private: bool matchIfNot(Value *LHS, Value *RHS) { if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) return CI->isAllOnesValue() && L.match(LHS); - if (ConstantInt *CI = dyn_cast<ConstantInt>(LHS)) - return CI->isAllOnesValue() && L.match(RHS); if (ConstantVector *CV = dyn_cast<ConstantVector>(RHS)) return CV->isAllOnesValue() && L.match(LHS); - if (ConstantVector *CV = dyn_cast<ConstantVector>(LHS)) - return CV->isAllOnesValue() && L.match(RHS); return false; } }; @@ -543,17 +586,17 @@ struct neg_match { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (CE->getOpcode() == Instruction::Sub) return matchIfNeg(CE->getOperand(0), CE->getOperand(1)); - if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) - return L.match(ConstantExpr::getNeg(CI)); return false; } private: bool matchIfNeg(Value *LHS, Value *RHS) { - return LHS == ConstantFP::getZeroValueForNegation(LHS->getType()) && - L.match(RHS); + if (ConstantInt *C = dyn_cast<ConstantInt>(LHS)) + return C->isZero() && L.match(RHS); + return false; } }; +/// m_Neg - Match an integer negate. template<typename LHS> inline neg_match<LHS> m_Neg(const LHS &L) { return L; } @@ -572,23 +615,23 @@ struct fneg_match { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (CE->getOpcode() == Instruction::FSub) return matchIfFNeg(CE->getOperand(0), CE->getOperand(1)); - if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) - return L.match(ConstantExpr::getFNeg(CF)); return false; } private: bool matchIfFNeg(Value *LHS, Value *RHS) { - return LHS == ConstantFP::getZeroValueForNegation(LHS->getType()) && - L.match(RHS); + if (ConstantFP *C = dyn_cast<ConstantFP>(LHS)) + return C->isNegativeZeroValue() && L.match(RHS); + return false; } }; +/// m_FNeg - Match a floating point negate. template<typename LHS> inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; } //===----------------------------------------------------------------------===// -// Matchers for control flow +// Matchers for control flow. // template<typename Cond_t> @@ -602,12 +645,10 @@ struct brc_match { template<typename OpTy> bool match(OpTy *V) { if (BranchInst *BI = dyn_cast<BranchInst>(V)) - if (BI->isConditional()) { - if (Cond.match(BI->getCondition())) { - T = BI->getSuccessor(0); - F = BI->getSuccessor(1); - return true; - } + if (BI->isConditional() && Cond.match(BI->getCondition())) { + T = BI->getSuccessor(0); + F = BI->getSuccessor(1); + return true; } return false; } diff --git a/include/llvm/Support/PointerLikeTypeTraits.h b/include/llvm/Support/PointerLikeTypeTraits.h index b851404800..8370821392 100644 --- a/include/llvm/Support/PointerLikeTypeTraits.h +++ b/include/llvm/Support/PointerLikeTypeTraits.h @@ -15,7 +15,7 @@ #ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H #define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/System/Process.h b/include/llvm/Support/Process.h index 41bcd69b6a..33799229ff 100644 --- a/include/llvm/System/Process.h +++ b/include/llvm/Support/Process.h @@ -1,4 +1,4 @@ -//===- llvm/System/Process.h ------------------------------------*- C++ -*-===// +//===- llvm/Support/Process.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_PROCESS_H #define LLVM_SYSTEM_PROCESS_H -#include "llvm/System/TimeValue.h" +#include "llvm/Support/TimeValue.h" namespace llvm { namespace sys { diff --git a/include/llvm/System/Program.h b/include/llvm/Support/Program.h index c595082e8b..78a495ef21 100644 --- a/include/llvm/System/Program.h +++ b/include/llvm/Support/Program.h @@ -1,4 +1,4 @@ -//===- llvm/System/Program.h ------------------------------------*- C++ -*-===// +//===- llvm/Support/Program.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_PROGRAM_H #define LLVM_SYSTEM_PROGRAM_H -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" namespace llvm { namespace sys { diff --git a/include/llvm/System/RWMutex.h b/include/llvm/Support/RWMutex.h index 3a288180bf..0d4cb81de3 100644 --- a/include/llvm/System/RWMutex.h +++ b/include/llvm/Support/RWMutex.h @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_RWMUTEX_H #define LLVM_SYSTEM_RWMUTEX_H -#include "llvm/System/Threading.h" +#include "llvm/Support/Threading.h" #include <cassert> namespace llvm @@ -43,7 +43,7 @@ namespace llvm /// Attempts to unconditionally acquire the lock in reader mode. If the /// lock is held by a writer, this method will wait until it can acquire - /// the lock. + /// the lock. /// @returns false if any kind of error occurs, true otherwise. /// @brief Unconditionally acquire the lock in reader mode. bool reader_acquire(); @@ -55,7 +55,7 @@ namespace llvm /// Attempts to unconditionally acquire the lock in reader mode. If the /// lock is held by any readers, this method will wait until it can - /// acquire the lock. + /// acquire the lock. /// @returns false if any kind of error occurs, true otherwise. /// @brief Unconditionally acquire the lock in writer mode. bool writer_acquire(); @@ -79,8 +79,8 @@ namespace llvm void operator=(const RWMutexImpl &); /// @} }; - - /// SmartMutex - An R/W mutex with a compile time constant parameter that + + /// SmartMutex - An R/W mutex with a compile time constant parameter that /// indicates whether this mutex should become a no-op when we're not /// running in multithreaded mode. template<bool mt_only> @@ -88,80 +88,80 @@ namespace llvm unsigned readers, writers; public: explicit SmartRWMutex() : RWMutexImpl(), readers(0), writers(0) { } - + bool reader_acquire() { if (!mt_only || llvm_is_multithreaded()) return RWMutexImpl::reader_acquire(); - + // Single-threaded debugging code. This would be racy in multithreaded // mode, but provides not sanity checks in single threaded mode. ++readers; return true; } - + bool reader_release() { if (!mt_only || llvm_is_multithreaded()) return RWMutexImpl::reader_release(); - + // Single-threaded debugging code. This would be racy in multithreaded // mode, but provides not sanity checks in single threaded mode. assert(readers > 0 && "Reader lock not acquired before release!"); --readers; return true; } - + bool writer_acquire() { if (!mt_only || llvm_is_multithreaded()) return RWMutexImpl::writer_acquire(); - + // Single-threaded debugging code. This would be racy in multithreaded // mode, but provides not sanity checks in single threaded mode. assert(writers == 0 && "Writer lock already acquired!"); ++writers; return true; } - + bool writer_release() { if (!mt_only || llvm_is_multithreaded()) return RWMutexImpl::writer_release(); - + // Single-threaded debugging code. This would be racy in multithreaded // mode, but provides not sanity checks in single threaded mode. assert(writers == 1 && "Writer lock not acquired before release!"); --writers; return true; } - + private: SmartRWMutex(const SmartRWMutex<mt_only> & original); void operator=(const SmartRWMutex<mt_only> &); }; typedef SmartRWMutex<false> RWMutex; - + /// ScopedReader - RAII acquisition of a reader lock template<bool mt_only> struct SmartScopedReader { SmartRWMutex<mt_only>& mutex; - + explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) { mutex.reader_acquire(); } - + ~SmartScopedReader() { mutex.reader_release(); } }; typedef SmartScopedReader<false> ScopedReader; - + /// ScopedWriter - RAII acquisition of a writer lock template<bool mt_only> struct SmartScopedWriter { SmartRWMutex<mt_only>& mutex; - + explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) { mutex.writer_acquire(); } - + ~SmartScopedWriter() { mutex.writer_release(); } diff --git a/include/llvm/System/Signals.h b/include/llvm/Support/Signals.h index 7f1c87c3d5..9a84df68dd 100644 --- a/include/llvm/System/Signals.h +++ b/include/llvm/Support/Signals.h @@ -1,4 +1,4 @@ -//===- llvm/System/Signals.h - Signal Handling support ----------*- C++ -*-===// +//===- llvm/Support/Signals.h - Signal Handling support ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,7 +15,7 @@ #ifndef LLVM_SYSTEM_SIGNALS_H #define LLVM_SYSTEM_SIGNALS_H -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" namespace llvm { namespace sys { diff --git a/include/llvm/System/Solaris.h b/include/llvm/Support/Solaris.h index 15adb7472c..57eee2cb49 100644 --- a/include/llvm/System/Solaris.h +++ b/include/llvm/Support/Solaris.h @@ -1,4 +1,4 @@ -/*===- llvm/System/Solaris.h ------------------------------------*- C++ -*-===* +/*===- llvm/Support/Solaris.h ------------------------------------*- C++ -*-===* * * The LLVM Compiler Infrastructure * diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index 816f894372..2a712e44bd 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -36,8 +36,7 @@ public: /// DiagHandlerTy - Clients that want to handle their own diagnostics in a /// custom way can register a function pointer+context as a diagnostic /// handler. It gets called each time PrintMessage is invoked. - typedef void (*DiagHandlerTy)(const SMDiagnostic&, void *Context, - unsigned LocCookie); + typedef void (*DiagHandlerTy)(const SMDiagnostic&, void *Context); private: struct SrcBuffer { /// Buffer - The memory buffer for the file. @@ -61,7 +60,6 @@ private: DiagHandlerTy DiagHandler; void *DiagContext; - unsigned DiagLocCookie; SourceMgr(const SourceMgr&); // DO NOT IMPLEMENT void operator=(const SourceMgr&); // DO NOT IMPLEMENT @@ -74,12 +72,10 @@ public: } /// setDiagHandler - Specify a diagnostic handler to be invoked every time - /// PrintMessage is called. Ctx and Cookie are passed into the handler when - /// it is invoked. - void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0, unsigned Cookie = 0) { + /// PrintMessage is called. Ctx is passed into the handler when it is invoked. + void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0) { DiagHandler = DH; DiagContext = Ctx; - DiagLocCookie = Cookie; } const SrcBuffer &getBufferInfo(unsigned i) const { @@ -160,10 +156,9 @@ public: // Null diagnostic. SMDiagnostic() : SM(0), LineNo(0), ColumnNo(0), ShowLine(0) {} // Diagnostic with no location (e.g. file not found, command line arg error). - SMDiagnostic(const std::string &filename, const std::string &Msg, - bool showline = true) + SMDiagnostic(const std::string &filename, const std::string &Msg) : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), - Message(Msg), ShowLine(showline) {} + Message(Msg), ShowLine(false) {} // Diagnostic with a location. SMDiagnostic(const SourceMgr &sm, SMLoc L, const std::string &FN, @@ -175,7 +170,7 @@ public: const SourceMgr *getSourceMgr() const { return SM; } SMLoc getLoc() const { return Loc; } - const std::string &getFilename() { return Filename; } + const std::string &getFilename() const { return Filename; } int getLineNo() const { return LineNo; } int getColumnNo() const { return ColumnNo; } const std::string &getMessage() const { return Message; } diff --git a/include/llvm/Support/StableBasicBlockNumbering.h b/include/llvm/Support/StableBasicBlockNumbering.h deleted file mode 100644 index 5e0f87e489..0000000000 --- a/include/llvm/Support/StableBasicBlockNumbering.h +++ /dev/null @@ -1,59 +0,0 @@ -//===- StableBasicBlockNumbering.h - Provide BB identifiers -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class provides a *stable* numbering of basic blocks that does not depend -// on their address in memory (which is nondeterministic). When requested, this -// class simply provides a unique ID for each basic block in the function -// specified and the inverse mapping. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_STABLEBASICBLOCKNUMBERING_H -#define LLVM_SUPPORT_STABLEBASICBLOCKNUMBERING_H - -#include "llvm/Function.h" -#include "llvm/ADT/UniqueVector.h" - -namespace llvm { - class StableBasicBlockNumbering { - // BBNumbering - Holds the numbering. - UniqueVector<BasicBlock*> BBNumbering; - public: - StableBasicBlockNumbering(Function *F = 0) { - if (F) compute(*F); - } - - /// compute - If we have not computed a numbering for the function yet, do - /// so. - void compute(Function &F) { - if (BBNumbering.empty()) { - for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) - BBNumbering.insert(I); - } - } - - /// getNumber - Return the ID number for the specified BasicBlock. - /// - unsigned getNumber(BasicBlock *BB) const { - unsigned Idx = BBNumbering.idFor(BB); - assert(Idx && "Invalid basic block or numbering not computed!"); - return Idx-1; - } - - /// getBlock - Return the BasicBlock corresponding to a particular ID. - /// - BasicBlock *getBlock(unsigned N) const { - assert(N < BBNumbering.size() && - "Block ID out of range or numbering not computed!"); - return BBNumbering[N+1]; - } - }; -} - -#endif diff --git a/include/llvm/Support/StandardPasses.h b/include/llvm/Support/StandardPasses.h index a608f2ceab..d774faf386 100644 --- a/include/llvm/Support/StandardPasses.h +++ b/include/llvm/Support/StandardPasses.h @@ -20,20 +20,35 @@ #define LLVM_SUPPORT_STANDARDPASSES_H #include "llvm/PassManager.h" -#include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/IPO.h" namespace llvm { + + static inline void createStandardAliasAnalysisPasses(PassManagerBase *PM) { + // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that + // BasicAliasAnalysis wins if they disagree. This is intended to help + // support "obvious" type-punning idioms. + PM->add(createTypeBasedAliasAnalysisPass()); + PM->add(createBasicAliasAnalysisPass()); + } + /// createStandardFunctionPasses - Add the standard list of function passes to /// the provided pass manager. /// /// \arg OptimizationLevel - The optimization level, corresponding to -O0, /// -O1, etc. static inline void createStandardFunctionPasses(PassManagerBase *PM, - unsigned OptimizationLevel); + unsigned OptimizationLevel) { + if (OptimizationLevel > 0) { + createStandardAliasAnalysisPasses(PM); + PM->add(createCFGSimplificationPass()); + PM->add(createScalarReplAggregatesPass()); + PM->add(createEarlyCSEPass()); + } + } /// createStandardModulePasses - Add the standard list of module passes to the /// provided pass manager. @@ -54,51 +69,6 @@ namespace llvm { bool UnrollLoops, bool SimplifyLibCalls, bool HaveExceptions, - Pass *InliningPass); - - /// createStandardLTOPasses - Add the standard list of module passes suitable - /// for link time optimization. - /// - /// Internalize - Run the internalize pass. - /// RunInliner - Use a function inlining pass. - /// VerifyEach - Run the verifier after each pass. - static inline void createStandardLTOPasses(PassManagerBase *PM, - bool Internalize, - bool RunInliner, - bool VerifyEach); - - // Implementations - - static inline void createStandardAliasAnalysisPasses(PassManagerBase *PM) { - // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that - // BasicAliasAnalysis wins if they disagree. This is intended to help - // support "obvious" type-punning idioms. - PM->add(createTypeBasedAliasAnalysisPass()); - PM->add(createBasicAliasAnalysisPass()); - } - - static inline void createStandardFunctionPasses(PassManagerBase *PM, - unsigned OptimizationLevel) { - if (OptimizationLevel > 0) { - createStandardAliasAnalysisPasses(PM); - PM->add(createCFGSimplificationPass()); - if (OptimizationLevel == 1) - PM->add(createPromoteMemoryToRegisterPass()); - else - PM->add(createScalarReplAggregatesPass()); - PM->add(createInstructionCombiningPass()); - } - } - - /// createStandardModulePasses - Add the standard module passes. This is - /// expected to be run after the standard function passes. - static inline void createStandardModulePasses(PassManagerBase *PM, - unsigned OptimizationLevel, - bool OptimizeSize, - bool UnitAtATime, - bool UnrollLoops, - bool SimplifyLibCalls, - bool HaveExceptions, Pass *InliningPass) { createStandardAliasAnalysisPasses(PM); @@ -119,7 +89,7 @@ namespace llvm { // Start of CallGraph SCC passes. if (UnitAtATime && HaveExceptions) - PM->add(createPruneEHPass()); // Remove dead EH info + PM->add(createPruneEHPass()); // Remove dead EH info if (InliningPass) PM->add(InliningPass); if (UnitAtATime) @@ -128,10 +98,11 @@ namespace llvm { PM->add(createArgumentPromotionPass()); // Scalarize uninlined fn args // Start of function pass. - PM->add(createScalarReplAggregatesPass()); // Break up aggregate allocas + // Break up aggregate allocas, using SSAUpdater. + PM->add(createScalarReplAggregatesPass(-1, false)); + PM->add(createEarlyCSEPass()); // Catch trivial redundancies if (SimplifyLibCalls) PM->add(createSimplifyLibCallsPass()); // Library Call Optimizations - PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. PM->add(createJumpThreadingPass()); // Thread jumps. PM->add(createCorrelatedValuePropagationPass()); // Propagate conditionals PM->add(createCFGSimplificationPass()); // Merge & remove BBs @@ -145,6 +116,7 @@ namespace llvm { PM->add(createLoopUnswitchPass(OptimizeSize || OptimizationLevel < 3)); PM->add(createInstructionCombiningPass()); PM->add(createIndVarSimplifyPass()); // Canonicalize indvars + PM->add(createLoopIdiomPass()); // Recognize idioms like memset. PM->add(createLoopDeletionPass()); // Delete dead loops if (UnrollLoops) PM->add(createLoopUnrollPass()); // Unroll small loops @@ -184,6 +156,12 @@ namespace llvm { PM->add(createVerifierPass()); } + /// createStandardLTOPasses - Add the standard list of module passes suitable + /// for link time optimization. + /// + /// Internalize - Run the internalize pass. + /// RunInliner - Use a function inlining pass. + /// VerifyEach - Run the verifier after each pass. static inline void createStandardLTOPasses(PassManagerBase *PM, bool Internalize, bool RunInliner, diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h new file mode 100644 index 0000000000..6c0592c05a --- /dev/null +++ b/include/llvm/Support/SwapByteOrder.h @@ -0,0 +1,101 @@ +//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares generic and optimized functions to swap the byte order of +// an integral type. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_SWAP_BYTE_ORDER_H +#define LLVM_SYSTEM_SWAP_BYTE_ORDER_H + +#include "llvm/Support/DataTypes.h" +#include <cstddef> +#include <limits> + +namespace llvm { +namespace sys { + +/// SwapByteOrder_16 - This function returns a byte-swapped representation of +/// the 16-bit argument. +inline uint16_t SwapByteOrder_16(uint16_t value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return _byteswap_ushort(value); +#else + uint16_t Hi = value << 8; + uint16_t Lo = value >> 8; + return Hi | Lo; +#endif +} + +/// SwapByteOrder_32 - This function returns a byte-swapped representation of +/// the 32-bit argument. +inline uint32_t SwapByteOrder_32(uint32_t value) { +#if defined(__llvm__) || \ +(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) + return __builtin_bswap32(value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_ulong(value); +#else + uint32_t Byte0 = value & 0x000000FF; + uint32_t Byte1 = value & 0x0000FF00; + uint32_t Byte2 = value & 0x00FF0000; + uint32_t Byte3 = value & 0xFF000000; + return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); +#endif +} + +/// SwapByteOrder_64 - This function returns a byte-swapped representation of +/// the 64-bit argument. +inline uint64_t SwapByteOrder_64(uint64_t value) { +#if defined(__llvm__) || \ +(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) + return __builtin_bswap64(value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_uint64(value); +#else + uint64_t Hi = SwapByteOrder_32(uint32_t(value)); + uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32)); + return (Hi << 32) | Lo; +#endif +} + +inline unsigned char SwapByteOrder(unsigned char C) { return C; } +inline signed char SwapByteOrder(signed char C) { return C; } +inline char SwapByteOrder(char C) { return C; } + +inline unsigned short SwapByteOrder(unsigned short C) { return SwapByteOrder_16(C); } +inline signed short SwapByteOrder( signed short C) { return SwapByteOrder_16(C); } + +inline unsigned int SwapByteOrder(unsigned int C) { return SwapByteOrder_32(C); } +inline signed int SwapByteOrder( signed int C) { return SwapByteOrder_32(C); } + +#if __LONG_MAX__ == __INT_MAX__ +inline unsigned long SwapByteOrder(unsigned long C) { return SwapByteOrder_32(C); } +inline signed long SwapByteOrder( signed long C) { return SwapByteOrder_32(C); } +#elif __LONG_MAX__ == __LONG_LONG_MAX__ +inline unsigned long SwapByteOrder(unsigned long C) { return SwapByteOrder_64(C); } +inline signed long SwapByteOrder( signed long C) { return SwapByteOrder_64(C); } +#else +#error "Unknown long size!" +#endif + +inline unsigned long long SwapByteOrder(unsigned long long C) { + return SwapByteOrder_64(C); +} +inline signed long long SwapByteOrder(signed long long C) { + return SwapByteOrder_64(C); +} + +} // end namespace sys +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/TargetFolder.h b/include/llvm/Support/TargetFolder.h index d34f35fe0d..20ca5571ff 100644 --- a/include/llvm/Support/TargetFolder.h +++ b/include/llvm/Support/TargetFolder.h @@ -46,50 +46,32 @@ public: // Binary Operators //===--------------------------------------------------------------------===// - Constant *CreateAdd(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getAdd(LHS, RHS)); - } - Constant *CreateNSWAdd(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNSWAdd(LHS, RHS)); - } - Constant *CreateNUWAdd(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNUWAdd(LHS, RHS)); + Constant *CreateAdd(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW)); } Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFAdd(LHS, RHS)); } - Constant *CreateSub(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getSub(LHS, RHS)); - } - Constant *CreateNSWSub(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNSWSub(LHS, RHS)); - } - Constant *CreateNUWSub(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNUWSub(LHS, RHS)); + Constant *CreateSub(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW)); } Constant *CreateFSub(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFSub(LHS, RHS)); } - Constant *CreateMul(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getMul(LHS, RHS)); - } - Constant *CreateNSWMul(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNSWMul(LHS, RHS)); - } - Constant *CreateNUWMul(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNUWMul(LHS, RHS)); + Constant *CreateMul(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW)); } Constant *CreateFMul(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFMul(LHS, RHS)); } - Constant *CreateUDiv(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getUDiv(LHS, RHS)); - } - Constant *CreateSDiv(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getSDiv(LHS, RHS)); + Constant *CreateUDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getUDiv(LHS, RHS, isExact)); } - Constant *CreateExactSDiv(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getExactSDiv(LHS, RHS)); + Constant *CreateSDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getSDiv(LHS, RHS, isExact)); } Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFDiv(LHS, RHS)); @@ -103,14 +85,15 @@ public: Constant *CreateFRem(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFRem(LHS, RHS)); } - Constant *CreateShl(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getShl(LHS, RHS)); + Constant *CreateShl(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW)); } - Constant *CreateLShr(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getLShr(LHS, RHS)); + Constant *CreateLShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getLShr(LHS, RHS, isExact)); } - Constant *CreateAShr(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getAShr(LHS, RHS)); + Constant *CreateAShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getAShr(LHS, RHS, isExact)); } Constant *CreateAnd(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getAnd(LHS, RHS)); @@ -131,14 +114,9 @@ public: // Unary Operators //===--------------------------------------------------------------------===// - Constant *CreateNeg(Constant *C) const { - return Fold(ConstantExpr::getNeg(C)); - } - Constant *CreateNSWNeg(Constant *C) const { - return Fold(ConstantExpr::getNSWNeg(C)); - } - Constant *CreateNUWNeg(Constant *C) const { - return Fold(ConstantExpr::getNUWNeg(C)); + Constant *CreateNeg(Constant *C, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getNeg(C, HasNUW, HasNSW)); } Constant *CreateFNeg(Constant *C) const { return Fold(ConstantExpr::getFNeg(C)); diff --git a/include/llvm/System/ThreadLocal.h b/include/llvm/Support/ThreadLocal.h index e6edd79d6f..15350a7aff 100644 --- a/include/llvm/System/ThreadLocal.h +++ b/include/llvm/Support/ThreadLocal.h @@ -1,4 +1,4 @@ -//===- llvm/System/ThreadLocal.h - Thread Local Data ------------*- C++ -*-===// +//===- llvm/Support/ThreadLocal.h - Thread Local Data ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_THREAD_LOCAL_H #define LLVM_SYSTEM_THREAD_LOCAL_H -#include "llvm/System/Threading.h" +#include "llvm/Support/Threading.h" #include <cassert> namespace llvm { @@ -30,21 +30,21 @@ namespace llvm { const void* getInstance(); void removeInstance(); }; - + /// ThreadLocal - A class used to abstract thread-local storage. It holds, /// for each thread, a pointer a single object of type T. template<class T> class ThreadLocal : public ThreadLocalImpl { public: ThreadLocal() : ThreadLocalImpl() { } - + /// get - Fetches a pointer to the object associated with the current /// thread. If no object has yet been associated, it returns NULL; T* get() { return static_cast<T*>(getInstance()); } - + // set - Associates a pointer to an object with the current thread. void set(T* d) { setInstance(d); } - + // erase - Removes the pointer associated with the current thread. void erase() { removeInstance(); } }; diff --git a/include/llvm/System/Threading.h b/include/llvm/Support/Threading.h index 1d0ed1e492..c0e842c2fe 100644 --- a/include/llvm/System/Threading.h +++ b/include/llvm/Support/Threading.h @@ -1,4 +1,4 @@ -//===-- llvm/System/Threading.h - Control multithreading mode --*- C++ -*-===// +//===-- llvm/Support/Threading.h - Control multithreading mode --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,25 +18,25 @@ namespace llvm { /// llvm_start_multithreaded - Allocate and initialize structures needed to /// make LLVM safe for multithreading. The return value indicates whether /// multithreaded initialization succeeded. LLVM will still be operational - /// on "failed" return, and will still be safe for hosting threading + /// on "failed" return, and will still be safe for hosting threading /// applications in the JIT, but will not be safe for concurrent calls to the /// LLVM APIs. /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. bool llvm_start_multithreaded(); - + /// llvm_stop_multithreaded - Deallocate structures necessary to make LLVM /// safe for multithreading. /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. void llvm_stop_multithreaded(); - + /// llvm_is_multithreaded - Check whether LLVM is executing in thread-safe /// mode or not. bool llvm_is_multithreaded(); - + /// acquire_global_lock - Acquire the global lock. This is a no-op if called /// before llvm_start_multithreaded(). void llvm_acquire_global_lock(); - + /// release_global_lock - Release the global lock. This is a no-op if called /// before llvm_start_multithreaded(). void llvm_release_global_lock(); diff --git a/include/llvm/System/TimeValue.h b/include/llvm/Support/TimeValue.h index b82647f74e..e1227118c2 100644 --- a/include/llvm/System/TimeValue.h +++ b/include/llvm/Support/TimeValue.h @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> #ifndef LLVM_SYSTEM_TIMEVALUE_H diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h index b1792b1671..faba94edf2 100644 --- a/include/llvm/Support/Timer.h +++ b/include/llvm/Support/Timer.h @@ -15,7 +15,7 @@ #ifndef LLVM_SUPPORT_TIMER_H #define LLVM_SUPPORT_TIMER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/ADT/StringRef.h" #include <cassert> #include <string> diff --git a/include/llvm/System/Valgrind.h b/include/llvm/Support/Valgrind.h index 5ec79c3c55..7662eaaff5 100644 --- a/include/llvm/System/Valgrind.h +++ b/include/llvm/Support/Valgrind.h @@ -1,4 +1,4 @@ -//===- llvm/System/Valgrind.h - Communication with Valgrind -----*- C++ -*-===// +//===- llvm/Support/Valgrind.h - Communication with Valgrind -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index 6bc8935b14..6bfae5e298 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -15,7 +15,7 @@ #define LLVM_SUPPORT_RAW_OSTREAM_H #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class format_object_base; @@ -165,7 +165,7 @@ public: } raw_ostream &operator<<(const char *Str) { - // Inline fast path, particulary for constant strings where a sufficiently + // Inline fast path, particularly for constant strings where a sufficiently // smart compiler will simplify strlen. return this->operator<<(StringRef(Str)); @@ -196,7 +196,7 @@ public: /// write_escaped - Output \arg Str, turning '\\', '\t', '\n', '"', and /// anything that doesn't satisfy std::isprint into an escape sequence. - raw_ostream &write_escaped(StringRef Str); + raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); raw_ostream &write(unsigned char C); raw_ostream &write(const char *Ptr, size_t Size); @@ -301,6 +301,10 @@ class raw_fd_ostream : public raw_ostream { /// bool Error; + /// Controls whether the stream should attempt to use atomic writes, when + /// possible. + bool UseAtomicWrites; + uint64_t pos; /// write_impl - See raw_ostream::write_impl. @@ -358,9 +362,19 @@ public: void close(); /// seek - Flushes the stream and repositions the underlying file descriptor - /// positition to the offset specified from the beginning of the file. + /// position to the offset specified from the beginning of the file. uint64_t seek(uint64_t off); + /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for + /// individual output routines where possible. + /// + /// Note that because raw_ostream's are typically buffered, this flag is only + /// sensible when used on unbuffered streams which will flush their output + /// immediately. + void SetUseAtomicWrites(bool Value) { + UseAtomicWrites = Value; + } + virtual raw_ostream &changeColor(enum Colors colors, bool bold=false, bool bg=false); virtual raw_ostream &resetColor(); diff --git a/include/llvm/Support/system_error.h b/include/llvm/Support/system_error.h new file mode 100644 index 0000000000..e5306ecfb3 --- /dev/null +++ b/include/llvm/Support/system_error.h @@ -0,0 +1,910 @@ +//===---------------------------- system_error ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This was lifted from libc++ and modified for C++03. This is called +// system_error even though it does not define that class because that's what +// it's called in C++0x. We don't define system_error because it is only used +// for exception handling, which we don't use in LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_SYSTEM_ERROR_H +#define LLVM_SYSTEM_SYSTEM_ERROR_H + +/* + system_error synopsis + +namespace std +{ + +class error_category +{ +public: + virtual ~error_category(); + + error_category(const error_category&) = delete; + error_category& operator=(const error_category&) = delete; + + virtual const char* name() const = 0; + virtual error_condition default_error_condition(int ev) const; + virtual bool equivalent(int code, const error_condition& condition) const; + virtual bool equivalent(const error_code& code, int condition) const; + virtual std::string message(int ev) const = 0; + + bool operator==(const error_category& rhs) const; + bool operator!=(const error_category& rhs) const; + bool operator<(const error_category& rhs) const; +}; + +const error_category& generic_category(); +const error_category& system_category(); + +template <class T> struct is_error_code_enum + : public false_type {}; + +template <class T> struct is_error_condition_enum + : public false_type {}; + +class error_code +{ +public: + // constructors: + error_code(); + error_code(int val, const error_category& cat); + template <class ErrorCodeEnum> + error_code(ErrorCodeEnum e); + + // modifiers: + void assign(int val, const error_category& cat); + template <class ErrorCodeEnum> + error_code& operator=(ErrorCodeEnum e); + void clear(); + + // observers: + int value() const; + const error_category& category() const; + error_condition default_error_condition() const; + std::string message() const; + explicit operator bool() const; +}; + +// non-member functions: +bool operator<(const error_code& lhs, const error_code& rhs); +template <class charT, class traits> + basic_ostream<charT,traits>& + operator<<(basic_ostream<charT,traits>& os, const error_code& ec); + +class error_condition +{ +public: + // constructors: + error_condition(); + error_condition(int val, const error_category& cat); + template <class ErrorConditionEnum> + error_condition(ErrorConditionEnum e); + + // modifiers: + void assign(int val, const error_category& cat); + template <class ErrorConditionEnum> + error_condition& operator=(ErrorConditionEnum e); + void clear(); + + // observers: + int value() const; + const error_category& category() const; + std::string message() const; + explicit operator bool() const; +}; + +bool operator<(const error_condition& lhs, const error_condition& rhs); + +class system_error + : public runtime_error +{ +public: + system_error(error_code ec, const std::string& what_arg); + system_error(error_code ec, const char* what_arg); + system_error(error_code ec); + system_error(int ev, const error_category& ecat, const std::string& what_arg); + system_error(int ev, const error_category& ecat, const char* what_arg); + system_error(int ev, const error_category& ecat); + + const error_code& code() const throw(); + const char* what() const throw(); +}; + +enum class errc +{ + address_family_not_supported, // EAFNOSUPPORT + address_in_use, // EADDRINUSE + address_not_available, // EADDRNOTAVAIL + already_connected, // EISCONN + argument_list_too_long, // E2BIG + argument_out_of_domain, // EDOM + bad_address, // EFAULT + bad_file_descriptor, // EBADF + bad_message, // EBADMSG + broken_pipe, // EPIPE + connection_aborted, // ECONNABORTED + connection_already_in_progress, // EALREADY + connection_refused, // ECONNREFUSED + connection_reset, // ECONNRESET + cross_device_link, // EXDEV + destination_address_required, // EDESTADDRREQ + device_or_resource_busy, // EBUSY + directory_not_empty, // ENOTEMPTY + executable_format_error, // ENOEXEC + file_exists, // EEXIST + file_too_large, // EFBIG + filename_too_long, // ENAMETOOLONG + function_not_supported, // ENOSYS + host_unreachable, // EHOSTUNREACH + identifier_removed, // EIDRM + illegal_byte_sequence, // EILSEQ + inappropriate_io_control_operation, // ENOTTY + interrupted, // EINTR + invalid_argument, // EINVAL + invalid_seek, // ESPIPE + io_error, // EIO + is_a_directory, // EISDIR + message_size, // EMSGSIZE + network_down, // ENETDOWN + network_reset, // ENETRESET + network_unreachable, // ENETUNREACH + no_buffer_space, // ENOBUFS + no_child_process, // ECHILD + no_link, // ENOLINK + no_lock_available, // ENOLCK + no_message_available, // ENODATA + no_message, // ENOMSG + no_protocol_option, // ENOPROTOOPT + no_space_on_device, // ENOSPC + no_stream_resources, // ENOSR + no_such_device_or_address, // ENXIO + no_such_device, // ENODEV + no_such_file_or_directory, // ENOENT + no_such_process, // ESRCH + not_a_directory, // ENOTDIR + not_a_socket, // ENOTSOCK + not_a_stream, // ENOSTR + not_connected, // ENOTCONN + not_enough_memory, // ENOMEM + not_supported, // ENOTSUP + operation_canceled, // ECANCELED + operation_in_progress, // EINPROGRESS + operation_not_permitted, // EPERM + operation_not_supported, // EOPNOTSUPP + operation_would_block, // EWOULDBLOCK + owner_dead, // EOWNERDEAD + permission_denied, // EACCES + protocol_error, // EPROTO + protocol_not_supported, // EPROTONOSUPPORT + read_only_file_system, // EROFS + resource_deadlock_would_occur, // EDEADLK + resource_unavailable_try_again, // EAGAIN + result_out_of_range, // ERANGE + state_not_recoverable, // ENOTRECOVERABLE + stream_timeout, // ETIME + text_file_busy, // ETXTBSY + timed_out, // ETIMEDOUT + too_many_files_open_in_system, // ENFILE + too_many_files_open, // EMFILE + too_many_links, // EMLINK + too_many_symbolic_link_levels, // ELOOP + value_too_large, // EOVERFLOW + wrong_protocol_type // EPROTOTYPE +}; + +template <> struct is_error_condition_enum<errc> : true_type { } + +error_code make_error_code(errc e); +error_condition make_error_condition(errc e); + +// Comparison operators: +bool operator==(const error_code& lhs, const error_code& rhs); +bool operator==(const error_code& lhs, const error_condition& rhs); +bool operator==(const error_condition& lhs, const error_code& rhs); +bool operator==(const error_condition& lhs, const error_condition& rhs); +bool operator!=(const error_code& lhs, const error_code& rhs); +bool operator!=(const error_code& lhs, const error_condition& rhs); +bool operator!=(const error_condition& lhs, const error_code& rhs); +bool operator!=(const error_condition& lhs, const error_condition& rhs); + +template <> struct hash<std::error_code>; + +} // std + +*/ + +#include "llvm/Config/config.h" +#include "llvm/Support/type_traits.h" +#include <cerrno> +#include <string> + +// This must be here instead of a .inc file because it is used in the definition +// of the enum values below. +#ifdef LLVM_ON_WIN32 + + // The following numbers were taken from VS2010. +# ifndef EAFNOSUPPORT +# define EAFNOSUPPORT 102 +# endif +# ifndef EADDRINUSE +# define EADDRINUSE 100 +# endif +# ifndef EADDRNOTAVAIL +# define EADDRNOTAVAIL 101 +# endif +# ifndef EISCONN +# define EISCONN 113 +# endif +# ifndef E2BIG +# define E2BIG 7 +# endif +# ifndef EDOM +# define EDOM 33 +# endif +# ifndef EFAULT +# define EFAULT 14 +# endif +# ifndef EBADF +# define EBADF 9 +# endif +# ifndef EBADMSG +# define EBADMSG 104 +# endif +# ifndef EPIPE +# define EPIPE 32 +# endif +# ifndef ECONNABORTED +# define ECONNABORTED 106 +# endif +# ifndef EALREADY +# define EALREADY 103 +# endif +# ifndef ECONNREFUSED +# define ECONNREFUSED 107 +# endif +# ifndef ECONNRESET +# define ECONNRESET 108 +# endif +# ifndef EXDEV +# define EXDEV 18 +# endif +# ifndef EDESTADDRREQ +# define EDESTADDRREQ 109 +# endif +# ifndef EBUSY +# define EBUSY 16 +# endif +# ifndef ENOTEMPTY +# define ENOTEMPTY 41 +# endif +# ifndef ENOEXEC +# define ENOEXEC 8 +# endif +# ifndef EEXIST +# define EEXIST 17 +# endif +# ifndef EFBIG +# define EFBIG 27 +# endif +# ifndef ENAMETOOLONG +# define ENAMETOOLONG 38 +# endif +# ifndef ENOSYS +# define ENOSYS 40 +# endif +# ifndef EHOSTUNREACH +# define EHOSTUNREACH 110 +# endif +# ifndef EIDRM +# define EIDRM 111 +# endif +# ifndef EILSEQ +# define EILSEQ 42 +# endif +# ifndef ENOTTY +# define ENOTTY 25 +# endif +# ifndef EINTR +# define EINTR 4 +# endif +# ifndef EINVAL +# define EINVAL 22 +# endif +# ifndef ESPIPE +# define ESPIPE 29 +# endif +# ifndef EIO +# define EIO 5 +# endif +# ifndef EISDIR +# define EISDIR 21 +# endif +# ifndef EMSGSIZE +# define EMSGSIZE 115 +# endif +# ifndef ENETDOWN +# define ENETDOWN 116 +# endif +# ifndef ENETRESET +# define ENETRESET 117 +# endif +# ifndef ENETUNREACH +# define ENETUNREACH 118 +# endif +# ifndef ENOBUFS +# define ENOBUFS 119 +# endif +# ifndef ECHILD +# define ECHILD 10 +# endif +# ifndef ENOLINK +# define ENOLINK 121 +# endif +# ifndef ENOLCK +# define ENOLCK 39 +# endif +# ifndef ENODATA +# define ENODATA 120 +# endif +# ifndef ENOMSG +# define ENOMSG 122 +# endif +# ifndef ENOPROTOOPT +# define ENOPROTOOPT 123 +# endif +# ifndef ENOSPC +# define ENOSPC 28 +# endif +# ifndef ENOSR +# define ENOSR 124 +# endif +# ifndef ENXIO +# define ENXIO 6 +# endif +# ifndef ENODEV +# define ENODEV 19 +# endif +# ifndef ENOENT +# define ENOENT 2 +# endif +# ifndef ESRCH +# define ESRCH 3 +# endif +# ifndef ENOTDIR +# define ENOTDIR 20 +# endif +# ifndef ENOTSOCK +# define ENOTSOCK 128 +# endif +# ifndef ENOSTR +# define ENOSTR 125 +# endif +# ifndef ENOTCONN +# define ENOTCONN 126 +# endif +# ifndef ENOMEM +# define ENOMEM 12 +# endif +# ifndef ENOTSUP +# define ENOTSUP 129 +# endif +# ifndef ECANCELED +# define ECANCELED 105 +# endif +# ifndef EINPROGRESS +# define EINPROGRESS 112 +# endif +# ifndef EPERM +# define EPERM 1 +# endif +# ifndef EOPNOTSUPP +# define EOPNOTSUPP 130 +# endif +# ifndef EWOULDBLOCK +# define EWOULDBLOCK 140 +# endif +# ifndef EOWNERDEAD +# define EOWNERDEAD 133 +# endif +# ifndef EACCES +# define EACCES 13 +# endif +# ifndef EPROTO +# define EPROTO 134 +# endif +# ifndef EPROTONOSUPPORT +# define EPROTONOSUPPORT 135 +# endif +# ifndef EROFS +# define EROFS 30 +# endif +# ifndef EDEADLK +# define EDEADLK 36 +# endif +# ifndef EAGAIN +# define EAGAIN 11 +# endif +# ifndef ERANGE +# define ERANGE 34 +# endif +# ifndef ENOTRECOVERABLE +# define ENOTRECOVERABLE 127 +# endif +# ifndef ETIME +# define ETIME 137 +# endif +# ifndef ETXTBSY +# define ETXTBSY 139 +# endif +# ifndef ETIMEDOUT +# define ETIMEDOUT 138 +# endif +# ifndef ENFILE +# define ENFILE 23 +# endif +# ifndef EMFILE +# define EMFILE 24 +# endif +# ifndef EMLINK +# define EMLINK 31 +# endif +# ifndef ELOOP +# define ELOOP 114 +# endif +# ifndef EOVERFLOW +# define EOVERFLOW 132 +# endif +# ifndef EPROTOTYPE +# define EPROTOTYPE 136 +# endif +#endif + +namespace llvm { + +template <class T, T v> +struct integral_constant { + typedef T value_type; + static const value_type value = v; + typedef integral_constant<T,v> type; + operator value_type() { return value; } +}; + +typedef integral_constant<bool, true> true_type; +typedef integral_constant<bool, false> false_type; + +// is_error_code_enum + +template <class Tp> struct is_error_code_enum : public false_type {}; + +// is_error_condition_enum + +template <class Tp> struct is_error_condition_enum : public false_type {}; + +// Some error codes are not present on all platforms, so we provide equivalents +// for them: + +//enum class errc +struct errc { +enum _ { + success = 0, + address_family_not_supported = EAFNOSUPPORT, + address_in_use = EADDRINUSE, + address_not_available = EADDRNOTAVAIL, + already_connected = EISCONN, + argument_list_too_long = E2BIG, + argument_out_of_domain = EDOM, + bad_address = EFAULT, + bad_file_descriptor = EBADF, +#ifdef EBADMSG + bad_message = EBADMSG, +#else + bad_message = EINVAL, +#endif + broken_pipe = EPIPE, + connection_aborted = ECONNABORTED, + connection_already_in_progress = EALREADY, + connection_refused = ECONNREFUSED, + connection_reset = ECONNRESET, + cross_device_link = EXDEV, + destination_address_required = EDESTADDRREQ, + device_or_resource_busy = EBUSY, + directory_not_empty = ENOTEMPTY, + executable_format_error = ENOEXEC, + file_exists = EEXIST, + file_too_large = EFBIG, + filename_too_long = ENAMETOOLONG, + function_not_supported = ENOSYS, + host_unreachable = EHOSTUNREACH, + identifier_removed = EIDRM, + illegal_byte_sequence = EILSEQ, + inappropriate_io_control_operation = ENOTTY, + interrupted = EINTR, + invalid_argument = EINVAL, + invalid_seek = ESPIPE, + io_error = EIO, + is_a_directory = EISDIR, + message_size = EMSGSIZE, + network_down = ENETDOWN, + network_reset = ENETRESET, + network_unreachable = ENETUNREACH, + no_buffer_space = ENOBUFS, + no_child_process = ECHILD, +#ifdef ENOLINK + no_link = ENOLINK, +#else + no_link = EINVAL, +#endif + no_lock_available = ENOLCK, +#ifdef ENODATA + no_message_available = ENODATA, +#else + no_message_available = ENOMSG, +#endif + no_message = ENOMSG, + no_protocol_option = ENOPROTOOPT, + no_space_on_device = ENOSPC, +#ifdef ENOSR + no_stream_resources = ENOSR, +#else + no_stream_resources = ENOMEM, +#endif + no_such_device_or_address = ENXIO, + no_such_device = ENODEV, + no_such_file_or_directory = ENOENT, + no_such_process = ESRCH, + not_a_directory = ENOTDIR, + not_a_socket = ENOTSOCK, +#ifdef ENOSTR + not_a_stream = ENOSTR, +#else + not_a_stream = EINVAL, +#endif + not_connected = ENOTCONN, + not_enough_memory = ENOMEM, + not_supported = ENOTSUP, +#ifdef ECANCELED + operation_canceled = ECANCELED, +#else + operation_canceled = EINVAL, +#endif + operation_in_progress = EINPROGRESS, + operation_not_permitted = EPERM, + operation_not_supported = EOPNOTSUPP, + operation_would_block = EWOULDBLOCK, +#ifdef EOWNERDEAD + owner_dead = EOWNERDEAD, +#else + owner_dead = EINVAL, +#endif + permission_denied = EACCES, +#ifdef EPROTO + protocol_error = EPROTO, +#else + protocol_error = EINVAL, +#endif + protocol_not_supported = EPROTONOSUPPORT, + read_only_file_system = EROFS, + resource_deadlock_would_occur = EDEADLK, + resource_unavailable_try_again = EAGAIN, + result_out_of_range = ERANGE, +#ifdef ENOTRECOVERABLE + state_not_recoverable = ENOTRECOVERABLE, +#else + state_not_recoverable = EINVAL, +#endif +#ifdef ETIME + stream_timeout = ETIME, +#else + stream_timeout = ETIMEDOUT, +#endif + text_file_busy = ETXTBSY, + timed_out = ETIMEDOUT, + too_many_files_open_in_system = ENFILE, + too_many_files_open = EMFILE, + too_many_links = EMLINK, + too_many_symbolic_link_levels = ELOOP, + value_too_large = EOVERFLOW, + wrong_protocol_type = EPROTOTYPE +}; + + _ v_; + + errc(_ v) : v_(v) {} + operator int() const {return v_;} +}; + +template <> struct is_error_condition_enum<errc> : true_type { }; + +template <> struct is_error_condition_enum<errc::_> : true_type { }; + +class error_condition; +class error_code; + +// class error_category + +class _do_message; + +class error_category +{ +public: + virtual ~error_category(); + +private: + error_category(); + error_category(const error_category&);// = delete; + error_category& operator=(const error_category&);// = delete; + +public: + virtual const char* name() const = 0; + virtual error_condition default_error_condition(int _ev) const; + virtual bool equivalent(int _code, const error_condition& _condition) const; + virtual bool equivalent(const error_code& _code, int _condition) const; + virtual std::string message(int _ev) const = 0; + + bool operator==(const error_category& _rhs) const {return this == &_rhs;} + + bool operator!=(const error_category& _rhs) const {return !(*this == _rhs);} + + bool operator< (const error_category& _rhs) const {return this < &_rhs;} + + friend class _do_message; +}; + +class _do_message : public error_category +{ +public: + virtual std::string message(int ev) const; +}; + +const error_category& generic_category(); +const error_category& system_category(); + +/// Get the error_category used for errno values from POSIX functions. This is +/// the same as the system_category on POISIX systems, but is the same as the +/// generic_category on Windows. +const error_category& posix_category(); + +class error_condition +{ + int _val_; + const error_category* _cat_; +public: + error_condition() : _val_(0), _cat_(&generic_category()) {} + + error_condition(int _val, const error_category& _cat) + : _val_(_val), _cat_(&_cat) {} + + template <class E> + error_condition(E _e, typename enable_if_c< + is_error_condition_enum<E>::value + >::type* = 0) + {*this = make_error_condition(_e);} + + void assign(int _val, const error_category& _cat) { + _val_ = _val; + _cat_ = &_cat; + } + + template <class E> + typename enable_if_c + < + is_error_condition_enum<E>::value, + error_condition& + >::type + operator=(E _e) + {*this = make_error_condition(_e); return *this;} + + void clear() { + _val_ = 0; + _cat_ = &generic_category(); + } + + int value() const {return _val_;} + + const error_category& category() const {return *_cat_;} + std::string message() const; + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + operator unspecified_bool_type() const { // true if error + return _val_ == 0 ? 0 : unspecified_bool_true; + } +}; + +inline error_condition make_error_condition(errc _e) { + return error_condition(static_cast<int>(_e), generic_category()); +} + +inline bool operator<(const error_condition& _x, const error_condition& _y) { + return _x.category() < _y.category() + || (_x.category() == _y.category() && _x.value() < _y.value()); +} + +// error_code + +class error_code { + int _val_; + const error_category* _cat_; +public: + error_code() : _val_(0), _cat_(&system_category()) {} + + error_code(int _val, const error_category& _cat) + : _val_(_val), _cat_(&_cat) {} + + template <class E> + error_code(E _e, typename enable_if_c< + is_error_code_enum<E>::value + >::type* = 0) { + *this = make_error_code(_e); + } + + void assign(int _val, const error_category& _cat) { + _val_ = _val; + _cat_ = &_cat; + } + + template <class E> + typename enable_if_c + < + is_error_code_enum<E>::value, + error_code& + >::type + operator=(E _e) + {*this = make_error_code(_e); return *this;} + + void clear() { + _val_ = 0; + _cat_ = &system_category(); + } + + int value() const {return _val_;} + + const error_category& category() const {return *_cat_;} + + error_condition default_error_condition() const + {return _cat_->default_error_condition(_val_);} + + std::string message() const; + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + operator unspecified_bool_type() const { // true if error + return _val_ == 0 ? 0 : unspecified_bool_true; + } +}; + +inline error_code make_error_code(errc _e) { + return error_code(static_cast<int>(_e), generic_category()); +} + +inline bool operator<(const error_code& _x, const error_code& _y) { + return _x.category() < _y.category() + || (_x.category() == _y.category() && _x.value() < _y.value()); +} + +inline bool operator==(const error_code& _x, const error_code& _y) { + return _x.category() == _y.category() && _x.value() == _y.value(); +} + +inline bool operator==(const error_code& _x, const error_condition& _y) { + return _x.category().equivalent(_x.value(), _y) + || _y.category().equivalent(_x, _y.value()); +} + +inline bool operator==(const error_condition& _x, const error_code& _y) { + return _y == _x; +} + +inline bool operator==(const error_condition& _x, const error_condition& _y) { + return _x.category() == _y.category() && _x.value() == _y.value(); +} + +inline bool operator!=(const error_code& _x, const error_code& _y) { + return !(_x == _y); +} + +inline bool operator!=(const error_code& _x, const error_condition& _y) { + return !(_x == _y); +} + +inline bool operator!=(const error_condition& _x, const error_code& _y) { + return !(_x == _y); +} + +inline bool operator!=(const error_condition& _x, const error_condition& _y) { + return !(_x == _y); +} + +// Windows errors. + +// To construct an error_code after an API error: +// +// error_code( ::GetLastError(), system_category() ) +struct windows_error { +enum _ { + success = 0, + // These names and values are based on Windows WinError.h + // This is not a complete list. Add to this list if you need to explicitly + // check for it. + invalid_function = 1, // ERROR_INVALID_FUNCTION, + file_not_found = 2, // ERROR_FILE_NOT_FOUND, + path_not_found = 3, // ERROR_PATH_NOT_FOUND, + too_many_open_files = 4, // ERROR_TOO_MANY_OPEN_FILES, + access_denied = 5, // ERROR_ACCESS_DENIED, + invalid_handle = 6, // ERROR_INVALID_HANDLE, + arena_trashed = 7, // ERROR_ARENA_TRASHED, + not_enough_memory = 8, // ERROR_NOT_ENOUGH_MEMORY, + invalid_block = 9, // ERROR_INVALID_BLOCK, + bad_environment = 10, // ERROR_BAD_ENVIRONMENT, + bad_format = 11, // ERROR_BAD_FORMAT, + invalid_access = 12, // ERROR_INVALID_ACCESS, + outofmemory = 14, // ERROR_OUTOFMEMORY, + invalid_drive = 15, // ERROR_INVALID_DRIVE, + current_directory = 16, // ERROR_CURRENT_DIRECTORY, + not_same_device = 17, // ERROR_NOT_SAME_DEVICE, + no_more_files = 18, // ERROR_NO_MORE_FILES, + write_protect = 19, // ERROR_WRITE_PROTECT, + bad_unit = 20, // ERROR_BAD_UNIT, + not_ready = 21, // ERROR_NOT_READY, + bad_command = 22, // ERROR_BAD_COMMAND, + crc = 23, // ERROR_CRC, + bad_length = 24, // ERROR_BAD_LENGTH, + seek = 25, // ERROR_SEEK, + not_dos_disk = 26, // ERROR_NOT_DOS_DISK, + sector_not_found = 27, // ERROR_SECTOR_NOT_FOUND, + out_of_paper = 28, // ERROR_OUT_OF_PAPER, + write_fault = 29, // ERROR_WRITE_FAULT, + read_fault = 30, // ERROR_READ_FAULT, + gen_failure = 31, // ERROR_GEN_FAILURE, + sharing_violation = 32, // ERROR_SHARING_VIOLATION, + lock_violation = 33, // ERROR_LOCK_VIOLATION, + wrong_disk = 34, // ERROR_WRONG_DISK, + sharing_buffer_exceeded = 36, // ERROR_SHARING_BUFFER_EXCEEDED, + handle_eof = 38, // ERROR_HANDLE_EOF, + handle_disk_full = 39, // ERROR_HANDLE_DISK_FULL, + rem_not_list = 51, // ERROR_REM_NOT_LIST, + dup_name = 52, // ERROR_DUP_NAME, + bad_net_path = 53, // ERROR_BAD_NETPATH, + network_busy = 54, // ERROR_NETWORK_BUSY, + file_exists = 80, // ERROR_FILE_EXISTS, + cannot_make = 82, // ERROR_CANNOT_MAKE, + broken_pipe = 109, // ERROR_BROKEN_PIPE, + open_failed = 110, // ERROR_OPEN_FAILED, + buffer_overflow = 111, // ERROR_BUFFER_OVERFLOW, + disk_full = 112, // ERROR_DISK_FULL, + insufficient_buffer = 122, // ERROR_INSUFFICIENT_BUFFER, + lock_failed = 167, // ERROR_LOCK_FAILED, + busy = 170, // ERROR_BUSY, + cancel_violation = 173, // ERROR_CANCEL_VIOLATION, + already_exists = 183 // ERROR_ALREADY_EXISTS +}; + _ v_; + + windows_error(_ v) : v_(v) {} + explicit windows_error(int v) : v_(_(v)) {} + operator int() const {return v_;} +}; + + +template <> struct is_error_code_enum<windows_error> : true_type { }; + +template <> struct is_error_code_enum<windows_error::_> : true_type { }; + +inline error_code make_error_code(windows_error e) { + return error_code(static_cast<int>(e), system_category()); +} + +} // end namespace llvm + +#endif diff --git a/include/llvm/System/Alarm.h b/include/llvm/System/Alarm.h deleted file mode 100644 index 7c284167c2..0000000000 --- a/include/llvm/System/Alarm.h +++ /dev/null @@ -1,51 +0,0 @@ -//===- llvm/System/Alarm.h - Alarm Generation support ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides an operating system independent interface to alarm(2) -// type functionality. The Alarm class allows a one-shot alarm to be set up -// at some number of seconds in the future. When the alarm triggers, a method -// is called to process the event -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SYSTEM_ALARM_H -#define LLVM_SYSTEM_ALARM_H - -namespace llvm { -namespace sys { - - /// This function registers an alarm to trigger some number of \p seconds in - /// the future. When that time arrives, the AlarmStatus function will begin - /// to return 1 instead of 0. The user must poll the status of the alarm by - /// making occasional calls to AlarmStatus. If the user sends an interrupt - /// signal, AlarmStatus will begin returning -1, even if the alarm event - /// occurred. - /// @returns nothing - void SetupAlarm( - unsigned seconds ///< Number of seconds in future when alarm arrives - ); - - /// This function terminates the alarm previously set up - /// @returns nothing - void TerminateAlarm(); - - /// This function acquires the status of the alarm. - /// @returns -1=cancelled, 0=untriggered, 1=triggered - int AlarmStatus(); - - /// Sleep for n seconds. Warning: mixing calls to Sleep() and other *Alarm - /// calls may be a bad idea on some platforms (source: Linux man page). - /// @returns nothing. - void Sleep(unsigned n); - - -} // End sys namespace -} // End llvm namespace - -#endif diff --git a/include/llvm/System/SwapByteOrder.h b/include/llvm/System/SwapByteOrder.h deleted file mode 100644 index 64a8acb019..0000000000 --- a/include/llvm/System/SwapByteOrder.h +++ /dev/null @@ -1,101 +0,0 @@ -//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares generic and optimized functions to swap the byte order of -// an integral type. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SYSTEM_SWAP_BYTE_ORDER_H -#define LLVM_SYSTEM_SWAP_BYTE_ORDER_H - -#include "llvm/Support/type_traits.h" -#include "llvm/System/DataTypes.h" -#include <cstddef> -#include <limits> - -namespace llvm { -namespace sys { - -template<typename value_type> -inline -typename enable_if_c<sizeof(value_type) == 1 - && std::numeric_limits<value_type>::is_integer, - value_type>::type -SwapByteOrder(value_type Value) { - // No swapping needed. - return Value; -} - -template<typename value_type> -inline -typename enable_if_c<sizeof(value_type) == 2 - && std::numeric_limits<value_type>::is_integer, - value_type>::type -SwapByteOrder(value_type Value) { - // Cast signed types to unsigned before swapping. - uint16_t value = static_cast<uint16_t>(Value); -#if defined(_MSC_VER) && !defined(_DEBUG) - // The DLL version of the runtime lacks these functions (bug!?), but in a - // release build they're replaced with BSWAP instructions anyway. - return _byteswap_ushort(value); -#else - uint16_t Hi = value << 8; - uint16_t Lo = value >> 8; - return value_type(Hi | Lo); -#endif -} - -template<typename value_type> -inline -typename enable_if_c<sizeof(value_type) == 4 - && std::numeric_limits<value_type>::is_integer, - value_type>::type -SwapByteOrder(value_type Value) { - // Cast signed types to unsigned before swapping. - uint32_t value = static_cast<uint32_t>(Value); -#if defined(__llvm__) || \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) - return __builtin_bswap32(value); -#elif defined(_MSC_VER) && !defined(_DEBUG) - return _byteswap_ulong(value); -#else - uint32_t Byte0 = value & 0x000000FF; - uint32_t Byte1 = value & 0x0000FF00; - uint32_t Byte2 = value & 0x00FF0000; - uint32_t Byte3 = value & 0xFF000000; - return value_type( - (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24)); -#endif -} - -template<typename value_type> -inline -typename enable_if_c<sizeof(value_type) == 8 - && std::numeric_limits<value_type>::is_integer, - value_type>::type -SwapByteOrder(value_type Value) { - // Cast signed types to unsigned before swapping. - uint64_t value = static_cast<uint64_t>(Value); -#if defined(__llvm__) || \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) - return __builtin_bswap64(value); -#elif defined(_MSC_VER) && !defined(_DEBUG) - return _byteswap_uint64(value); -#else - uint64_t Hi = SwapByteOrder<uint32_t>(uint32_t(value)); - uint32_t Lo = SwapByteOrder<uint32_t>(uint32_t(value >> 32)); - return value_type((Hi << 32) | Lo); -#endif -} - -} // end namespace sys -} // end namespace llvm - -#endif diff --git a/include/llvm/Target/Mangler.h b/include/llvm/Target/Mangler.h index a9f3576559..c1c118b08c 100644 --- a/include/llvm/Target/Mangler.h +++ b/include/llvm/Target/Mangler.h @@ -15,7 +15,6 @@ #define LLVM_SUPPORT_MANGLER_H #include "llvm/ADT/DenseMap.h" -#include <string> namespace llvm { class StringRef; @@ -69,12 +68,6 @@ public: /// empty. void getNameWithPrefix(SmallVectorImpl<char> &OutName, const Twine &GVName, ManglerPrefixTy PrefixTy = Mangler::Default); - - /// getNameWithPrefix - Return the name of the appropriate prefix - /// and the specified global variable's name. If the global variable doesn't - /// have a name, this fills in a unique name for the global. - std::string getNameWithPrefix(const GlobalValue *GV, - bool isImplicitlyPrivate = false); }; } // End llvm namespace diff --git a/include/llvm/Target/SubtargetFeature.h b/include/llvm/Target/SubtargetFeature.h index 45468714a3..6c21ae9583 100644 --- a/include/llvm/Target/SubtargetFeature.h +++ b/include/llvm/Target/SubtargetFeature.h @@ -22,7 +22,7 @@ #include <vector> #include <cstring> #include "llvm/ADT/Triple.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class raw_ostream; diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index bd629f16e2..0f7e6aaaf2 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -1,10 +1,10 @@ //===- Target.td - Target Independent TableGen interface ---*- tablegen -*-===// -// +// // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // // This file defines the target-independent interfaces which should be @@ -47,7 +47,7 @@ class Register<string n> { // modification of this register can potentially read or modify the aliased // registers. list<Register> Aliases = []; - + // SubRegs - A list of registers that are parts of this register. Note these // are "immediate" sub-registers and the registers within the list do not // themselves overlap. e.g. For X86, EAX's SubRegs list contains only [AX], @@ -84,7 +84,7 @@ class Register<string n> { // need to specify sub-registers. // List "subregs" specifies which registers are sub-registers to this one. This // is used to populate the SubRegs and AliasSet fields of TargetRegisterDesc. -// This allows the code generator to be careful not to put two values with +// This allows the code generator to be careful not to put two values with // overlapping live ranges into registers which alias. class RegisterWithSubRegs<string n, list<Register> subregs> : Register<n> { let SubRegs = subregs; @@ -101,7 +101,7 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, // RegType - Specify the list ValueType of the registers in this register // class. Note that all registers in a register class must have the same - // ValueTypes. This is a list because some targets permit storing different + // ValueTypes. This is a list because some targets permit storing different // types in same register, for example vector values with 128-bit total size, // but different count/size of items, like SSE on x86. // @@ -127,13 +127,13 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, // allocation used by the register allocator. // list<Register> MemberList = regList; - + // SubRegClasses - Specify the register class of subregisters as a list of // dags: (RegClass SubRegIndex, SubRegindex, ...) list<dag> SubRegClasses = []; // MethodProtos/MethodBodies - These members can be used to insert arbitrary - // code into a generated register class. The normal usage of this is to + // code into a generated register class. The normal usage of this is to // overload virtual methods. code MethodProtos = [{}]; code MethodBodies = [{}]; @@ -199,6 +199,7 @@ class Instruction { bit isBranch = 0; // Is this instruction a branch instruction? bit isIndirectBranch = 0; // Is this instruction an indirect branch? bit isCompare = 0; // Is this instruction a comparison instruction? + bit isMoveImm = 0; // Is this instruction a move immediate instruction? bit isBarrier = 0; // Can control flow fall through this instruction? bit isCall = 0; // Is this instruction a call instruction? bit canFoldAsLoad = 0; // Can this be folded as a simple memory operand? @@ -244,16 +245,24 @@ class Instruction { string DisableEncoding = ""; string PostEncoderMethod = ""; + string DecoderMethod = ""; /// Target-specific flags. This becomes the TSFlags field in TargetInstrDesc. bits<64> TSFlags = 0; + + ///@name Assembler Parser Support + ///@{ + + string AsmMatchConverter = ""; + + ///@} } /// Predicates - These are extra conditionals which are turned into instruction /// selector matching code. Currently each predicate is just a string. class Predicate<string cond> { string CondString = cond; - + /// AssemblerMatcherPredicate - If this feature can be used by the assembler /// matcher, this is true. Targets should set this by inheriting their /// feature from the AssemblerPredicate class in addition to Predicate. @@ -333,12 +342,18 @@ class AsmOperandClass { /// signature should be: /// void addFooOperands(MCInst &Inst, unsigned N) const; string RenderMethod = ?; + + /// The name of the method on the target specific operand to call to custom + /// handle the operand parsing. This is useful when the operands do not relate + /// to immediates or registers and are very instruction specific (as flags to + /// set in a processor register, coprocessor number, ...). + string ParserMethod = ?; } def ImmAsmOperand : AsmOperandClass { let Name = "Imm"; } - + /// Operand Types - These provide the built-in operand types that may be used /// by a target. Targets can optionally provide their own operand types as /// needed, though this should not be needed for RISC targets. @@ -346,6 +361,7 @@ class Operand<ValueType ty> { ValueType Type = ty; string PrintMethod = "printOperand"; string EncoderMethod = ""; + string DecoderMethod = ""; string AsmOperandLowerMethod = ?; dag MIOperandInfo = (ops); @@ -417,6 +433,7 @@ def INLINEASM : Instruction { let OutOperandList = (outs); let InOperandList = (ins variable_ops); let AsmString = ""; + let neverHasSideEffects = 1; // Note side effect is encoded in an operand. } def PROLOG_LABEL : Instruction { let OutOperandList = (outs); @@ -483,7 +500,7 @@ def DBG_VALUE : Instruction { let OutOperandList = (outs); let InOperandList = (ins variable_ops); let AsmString = "DBG_VALUE"; - let isAsCheapAsAMove = 1; + let neverHasSideEffects = 1; } def REG_SEQUENCE : Instruction { let OutOperandList = (outs unknown:$dst); @@ -565,7 +582,7 @@ class AssemblerPredicate { class MnemonicAlias<string From, string To> { string FromMnemonic = From; string ToMnemonic = To; - + // Predicates - Predicates that must be true for this remapping to happen. list<Predicate> Predicates = []; } @@ -576,7 +593,7 @@ class MnemonicAlias<string From, string To> { class InstAlias<string Asm, dag Result> { string AsmString = Asm; // The .s format to match the instruction with. dag ResultInst = Result; // The MCInst to generate. - + // Predicates - Predicates that must be true for this to match. list<Predicate> Predicates = []; } @@ -601,15 +618,15 @@ class AsmWriter { // will specify which alternative to use. For example "{x|y|z}" with Variant // == 1, will expand to "y". int Variant = 0; - - + + // FirstOperandColumn/OperandSpacing - If the assembler syntax uses a columnar // layout, the asmwriter can actually generate output in this columns (in // verbose-asm mode). These two values indicate the width of the first column // (the "opcode" area) and the width to reserve for subsequent operands. When // verbose asm mode is enabled, operands will be indented to respect this. int FirstOperandColumn = -1; - + // OperandSpacing - Space between operand columns. int OperandSpacing = -1; @@ -644,15 +661,15 @@ class SubtargetFeature<string n, string a, string v, string d, // appropriate target chip. // string Name = n; - + // Attribute - Attribute to be set by feature. // string Attribute = a; - + // Value - Value the attribute to be set to by feature. // string Value = v; - + // Desc - Feature description. Used by command line (-mattr=) to display help // information. // @@ -674,12 +691,12 @@ class Processor<string n, ProcessorItineraries pi, list<SubtargetFeature> f> { // appropriate target chip. // string Name = n; - + // ProcItin - The scheduling information for the target processor. // ProcessorItineraries ProcItin = pi; - - // Features - list of + + // Features - list of list<SubtargetFeature> Features = f; } diff --git a/include/llvm/Target/TargetAsmBackend.h b/include/llvm/Target/TargetAsmBackend.h index b424dea4a5..7527298efa 100644 --- a/include/llvm/Target/TargetAsmBackend.h +++ b/include/llvm/Target/TargetAsmBackend.h @@ -10,18 +10,18 @@ #ifndef LLVM_TARGET_TARGETASMBACKEND_H #define LLVM_TARGET_TARGETASMBACKEND_H -#include "llvm/System/DataTypes.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/Support/DataTypes.h" namespace llvm { -class MCDataFragment; class MCFixup; class MCInst; -class MCObjectFormat; class MCObjectWriter; class MCSection; template<typename T> class SmallVectorImpl; -class Target; class raw_ostream; /// TargetAsmBackend - Generic interface to target specific assembler backends. @@ -29,21 +29,13 @@ class TargetAsmBackend { TargetAsmBackend(const TargetAsmBackend &); // DO NOT IMPLEMENT void operator=(const TargetAsmBackend &); // DO NOT IMPLEMENT protected: // Can only create subclasses. - TargetAsmBackend(const Target &); - - /// TheTarget - The Target that this machine was created for. - const Target &TheTarget; + TargetAsmBackend(); unsigned HasReliableSymbolDifference : 1; - unsigned HasScatteredSymbols : 1; public: virtual ~TargetAsmBackend(); - const Target &getTarget() const { return TheTarget; } - - virtual const MCObjectFormat &getObjectFormat() const = 0; - /// createObjectWriter - Create a new MCObjectWriter instance for use by the /// assembler backend to emit the final object file. virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const = 0; @@ -62,16 +54,6 @@ public: return HasReliableSymbolDifference; } - /// hasScatteredSymbols - Check whether this target supports scattered - /// symbols. If so, the assembler should assume that atoms can be scattered by - /// the linker. In particular, this means that the offsets between symbols - /// which are in distinct atoms is not known at link time, and the assembler - /// must generate fixups and relocations appropriately. - /// - /// Note that the assembler currently does not reason about atoms, instead it - /// assumes all temporary symbols reside in the "current atom". - bool hasScatteredSymbols() const { return HasScatteredSymbols; } - /// doesSectionRequireSymbols - Check whether the given section requires that /// all symbols (even temporaries) have symbol table entries. virtual bool doesSectionRequireSymbols(const MCSection &Section) const { @@ -86,19 +68,28 @@ public: return true; } - /// isVirtualSection - Check whether the given section is "virtual", that is - /// has no actual object file contents. - virtual bool isVirtualSection(const MCSection &Section) const = 0; + /// @name Target Fixup Interfaces + /// @{ + + /// getNumFixupKinds - Get the number of target specific fixup kinds. + virtual unsigned getNumFixupKinds() const = 0; - /// getPointerSize - Get the pointer size in bytes. - virtual unsigned getPointerSize() const = 0; + /// getFixupKindInfo - Get information on a fixup kind. + virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const; + + /// @} /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided /// data fragment, at the offset specified by the fixup and following the /// fixup kind as appropriate. - virtual void ApplyFixup(const MCFixup &Fixup, MCDataFragment &Fragment, + virtual void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const = 0; + /// @} + + /// @name Target Relaxation Interfaces + /// @{ + /// MayNeedRelaxation - Check whether the given instruction may need /// relaxation. /// @@ -113,12 +104,18 @@ public: /// \parm Res [output] - On return, the relaxed instruction. virtual void RelaxInstruction(const MCInst &Inst, MCInst &Res) const = 0; + /// @} + /// WriteNopData - Write an (optimal) nop sequence of Count bytes to the given /// output. If the target cannot generate such a sequence, it should return an /// error. /// /// \return - True on success. virtual bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const = 0; + + /// HandleAssemblerFlag - Handle any target-specific assembler flags. + /// By default, do nothing. + virtual void HandleAssemblerFlag(MCAssemblerFlag Flag) {} }; } // End llvm namespace diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h new file mode 100644 index 0000000000..98aab142b8 --- /dev/null +++ b/include/llvm/Target/TargetAsmInfo.h @@ -0,0 +1,75 @@ +//===-- llvm/Target/TargetAsmInfo.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface to provide the information necessary for producing assembly files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETASMINFO_H +#define LLVM_TARGET_TARGETASMINFO_H + +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetRegisterInfo.h" + +namespace llvm { + class MCSection; + class MCContext; + class TargetMachine; + class TargetLoweringObjectFile; + +class TargetAsmInfo { + unsigned PointerSize; + bool IsLittleEndian; + TargetFrameLowering::StackDirection StackDir; + const TargetRegisterInfo *TRI; + std::vector<MachineMove> InitialFrameState; + const TargetLoweringObjectFile *TLOF; + +public: + explicit TargetAsmInfo(const TargetMachine &TM); + + /// getPointerSize - Get the pointer size in bytes. + unsigned getPointerSize() const { + return PointerSize; + } + + /// islittleendian - True if the target is little endian. + bool isLittleEndian() const { + return IsLittleEndian; + } + + TargetFrameLowering::StackDirection getStackGrowthDirection() const { + return StackDir; + } + + const MCSection *getDwarfLineSection() const { + return TLOF->getDwarfLineSection(); + } + + const MCSection *getEHFrameSection() const { + return TLOF->getEHFrameSection(); + } + + unsigned getDwarfRARegNum(bool isEH) const { + return TRI->getDwarfRegNum(TRI->getRARegister(), isEH); + } + + const std::vector<MachineMove> &getInitialFrameState() const { + return InitialFrameState; + } + + int getDwarfRegNum(unsigned RegNum, bool isEH) const { + return TRI->getDwarfRegNum(RegNum, isEH); + } +}; + +} +#endif diff --git a/include/llvm/Target/TargetAsmParser.h b/include/llvm/Target/TargetAsmParser.h index 6b38b8c7e1..9ff50cb275 100644 --- a/include/llvm/Target/TargetAsmParser.h +++ b/include/llvm/Target/TargetAsmParser.h @@ -42,6 +42,8 @@ public: unsigned getAvailableFeatures() const { return AvailableFeatures; } void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } + virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) = 0; + /// ParseInstruction - Parse one assembly instruction. /// /// The parser is positioned following the instruction name. The target diff --git a/include/llvm/Target/TargetData.h b/include/llvm/Target/TargetData.h index 5cdd114e8b..25065d30bb 100644 --- a/include/llvm/Target/TargetData.h +++ b/include/llvm/Target/TargetData.h @@ -22,7 +22,7 @@ #include "llvm/Pass.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { @@ -144,7 +144,7 @@ public: std::string getStringRepresentation() const; /// isLegalInteger - This function returns true if the specified type is - /// known tobe a native integer type supported by the CPU. For example, + /// known to be a native integer type supported by the CPU. For example, /// i64 is not native on most 32-bit CPUs and i37 is not native on any known /// one. This returns false if the integer width is not legal. /// diff --git a/include/llvm/Target/TargetFrameInfo.h b/include/llvm/Target/TargetFrameInfo.h deleted file mode 100644 index 6143f3c549..0000000000 --- a/include/llvm/Target/TargetFrameInfo.h +++ /dev/null @@ -1,112 +0,0 @@ -//===-- llvm/Target/TargetFrameInfo.h ---------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Interface to describe the layout of a stack frame on the target machine. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETFRAMEINFO_H -#define LLVM_TARGET_TARGETFRAMEINFO_H - -#include <utility> - -namespace llvm { - class MachineFunction; - class MachineBasicBlock; - -/// Information about stack frame layout on the target. It holds the direction -/// of stack growth, the known stack alignment on entry to each function, and -/// the offset to the locals area. -/// -/// The offset to the local area is the offset from the stack pointer on -/// function entry to the first location where function data (local variables, -/// spill locations) can be stored. -class TargetFrameInfo { -public: - enum StackDirection { - StackGrowsUp, // Adding to the stack increases the stack address - StackGrowsDown // Adding to the stack decreases the stack address - }; - - // Maps a callee saved register to a stack slot with a fixed offset. - struct SpillSlot { - unsigned Reg; - int Offset; // Offset relative to stack pointer on function entry. - }; -private: - StackDirection StackDir; - unsigned StackAlignment; - unsigned TransientStackAlignment; - int LocalAreaOffset; -public: - TargetFrameInfo(StackDirection D, unsigned StackAl, int LAO, - unsigned TransAl = 1) - : StackDir(D), StackAlignment(StackAl), TransientStackAlignment(TransAl), - LocalAreaOffset(LAO) {} - - virtual ~TargetFrameInfo(); - - // These methods return information that describes the abstract stack layout - // of the target machine. - - /// getStackGrowthDirection - Return the direction the stack grows - /// - StackDirection getStackGrowthDirection() const { return StackDir; } - - /// getStackAlignment - This method returns the number of bytes to which the - /// stack pointer must be aligned on entry to a function. Typically, this - /// is the largest alignment for any data object in the target. - /// - unsigned getStackAlignment() const { return StackAlignment; } - - /// getTransientStackAlignment - This method returns the number of bytes to - /// which the stack pointer must be aligned at all times, even between - /// calls. - /// - unsigned getTransientStackAlignment() const { - return TransientStackAlignment; - } - - /// getOffsetOfLocalArea - This method returns the offset of the local area - /// from the stack pointer on entrance to a function. - /// - int getOffsetOfLocalArea() const { return LocalAreaOffset; } - - /// getCalleeSavedSpillSlots - This method returns a pointer to an array of - /// pairs, that contains an entry for each callee saved register that must be - /// spilled to a particular stack location if it is spilled. - /// - /// Each entry in this array contains a <register,offset> pair, indicating the - /// fixed offset from the incoming stack pointer that each register should be - /// spilled at. If a register is not listed here, the code generator is - /// allowed to spill it anywhere it chooses. - /// - virtual const SpillSlot * - getCalleeSavedSpillSlots(unsigned &NumEntries) const { - NumEntries = 0; - return 0; - } - - /// targetHandlesStackFrameRounding - Returns true if the target is - /// responsible for rounding up the stack frame (probably at emitPrologue - /// time). - virtual bool targetHandlesStackFrameRounding() const { - return false; - } - - /// emitProlog/emitEpilog - These methods insert prolog and epilog code into - /// the function. - virtual void emitPrologue(MachineFunction &MF) const = 0; - virtual void emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const = 0; -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h new file mode 100644 index 0000000000..e104b1663f --- /dev/null +++ b/include/llvm/Target/TargetFrameLowering.h @@ -0,0 +1,196 @@ +//===-- llvm/Target/TargetFrameLowering.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface to describe the layout of a stack frame on the target machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETFRAMELOWERING_H +#define LLVM_TARGET_TARGETFRAMELOWERING_H + +#include "llvm/CodeGen/MachineBasicBlock.h" + +#include <utility> +#include <vector> + +namespace llvm { + class CalleeSavedInfo; + class MachineFunction; + class MachineBasicBlock; + class MachineMove; + class RegScavenger; + +/// Information about stack frame layout on the target. It holds the direction +/// of stack growth, the known stack alignment on entry to each function, and +/// the offset to the locals area. +/// +/// The offset to the local area is the offset from the stack pointer on +/// function entry to the first location where function data (local variables, +/// spill locations) can be stored. +class TargetFrameLowering { +public: + enum StackDirection { + StackGrowsUp, // Adding to the stack increases the stack address + StackGrowsDown // Adding to the stack decreases the stack address + }; + + // Maps a callee saved register to a stack slot with a fixed offset. + struct SpillSlot { + unsigned Reg; + int Offset; // Offset relative to stack pointer on function entry. + }; +private: + StackDirection StackDir; + unsigned StackAlignment; + unsigned TransientStackAlignment; + int LocalAreaOffset; +public: + TargetFrameLowering(StackDirection D, unsigned StackAl, int LAO, + unsigned TransAl = 1) + : StackDir(D), StackAlignment(StackAl), TransientStackAlignment(TransAl), + LocalAreaOffset(LAO) {} + + virtual ~TargetFrameLowering(); + + // These methods return information that describes the abstract stack layout + // of the target machine. + + /// getStackGrowthDirection - Return the direction the stack grows + /// + StackDirection getStackGrowthDirection() const { return StackDir; } + + /// getStackAlignment - This method returns the number of bytes to which the + /// stack pointer must be aligned on entry to a function. Typically, this + /// is the largest alignment for any data object in the target. + /// + unsigned getStackAlignment() const { return StackAlignment; } + + /// getTransientStackAlignment - This method returns the number of bytes to + /// which the stack pointer must be aligned at all times, even between + /// calls. + /// + unsigned getTransientStackAlignment() const { + return TransientStackAlignment; + } + + /// getOffsetOfLocalArea - This method returns the offset of the local area + /// from the stack pointer on entrance to a function. + /// + int getOffsetOfLocalArea() const { return LocalAreaOffset; } + + /// getCalleeSavedSpillSlots - This method returns a pointer to an array of + /// pairs, that contains an entry for each callee saved register that must be + /// spilled to a particular stack location if it is spilled. + /// + /// Each entry in this array contains a <register,offset> pair, indicating the + /// fixed offset from the incoming stack pointer that each register should be + /// spilled at. If a register is not listed here, the code generator is + /// allowed to spill it anywhere it chooses. + /// + virtual const SpillSlot * + getCalleeSavedSpillSlots(unsigned &NumEntries) const { + NumEntries = 0; + return 0; + } + + /// targetHandlesStackFrameRounding - Returns true if the target is + /// responsible for rounding up the stack frame (probably at emitPrologue + /// time). + virtual bool targetHandlesStackFrameRounding() const { + return false; + } + + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. + virtual void emitPrologue(MachineFunction &MF) const = 0; + virtual void emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const = 0; + + /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee + /// saved registers and returns true if it isn't possible / profitable to do + /// so by issuing a series of store instructions via + /// storeRegToStackSlot(). Returns false otherwise. + virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const { + return false; + } + + /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee + /// saved registers and returns true if it isn't possible / profitable to do + /// so by issuing a series of load instructions via loadRegToStackSlot(). + /// Returns false otherwise. + virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const { + return false; + } + + /// hasFP - Return true if the specified function should have a dedicated + /// frame pointer register. For most targets this is true only if the function + /// has variable sized allocas or if frame pointer elimination is disabled. + virtual bool hasFP(const MachineFunction &MF) const = 0; + + /// hasReservedCallFrame - Under normal circumstances, when a frame pointer is + /// not required, we reserve argument space for call sites in the function + /// immediately on entry to the current function. This eliminates the need for + /// add/sub sp brackets around call sites. Returns true if the call frame is + /// included as part of the stack frame. + virtual bool hasReservedCallFrame(const MachineFunction &MF) const { + return !hasFP(MF); + } + + /// canSimplifyCallFramePseudos - When possible, it's best to simplify the + /// call frame pseudo ops before doing frame index elimination. This is + /// possible only when frame index references between the pseudos won't + /// need adjusting for the call frame adjustments. Normally, that's true + /// if the function has a reserved call frame or a frame pointer. Some + /// targets (Thumb2, for example) may have more complicated criteria, + /// however, and can override this behavior. + virtual bool canSimplifyCallFramePseudos(const MachineFunction &MF) const { + return hasReservedCallFrame(MF) || hasFP(MF); + } + + /// getInitialFrameState - Returns a list of machine moves that are assumed + /// on entry to all functions. Note that LabelID is ignored (assumed to be + /// the beginning of the function.) + virtual void getInitialFrameState(std::vector<MachineMove> &Moves) const; + + /// getFrameIndexOffset - Returns the displacement from the frame register to + /// the stack frame of the specified index. + virtual int getFrameIndexOffset(const MachineFunction &MF, int FI) const; + + /// getFrameIndexReference - This method should return the base register + /// and offset used to reference a frame index location. The offset is + /// returned directly, and the base register is returned via FrameReg. + virtual int getFrameIndexReference(const MachineFunction &MF, int FI, + unsigned &FrameReg) const; + + /// processFunctionBeforeCalleeSavedScan - This method is called immediately + /// before PrologEpilogInserter scans the physical registers used to determine + /// what callee saved registers should be spilled. This method is optional. + virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS = NULL) const { + + } + + /// processFunctionBeforeFrameFinalized - This method is called immediately + /// before the specified function's frame layout (MF.getFrameInfo()) is + /// finalized. Once the frame is finalized, MO_FrameIndex operands are + /// replaced with direct constants. This method is optional. + /// + virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const { + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Target/TargetInstrDesc.h b/include/llvm/Target/TargetInstrDesc.h index a127aed8f6..8823d5a4d1 100644 --- a/include/llvm/Target/TargetInstrDesc.h +++ b/include/llvm/Target/TargetInstrDesc.h @@ -15,7 +15,7 @@ #ifndef LLVM_TARGET_TARGETINSTRDESC_H #define LLVM_TARGET_TARGETINSTRDESC_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { @@ -103,13 +103,14 @@ namespace TID { Terminator, Branch, IndirectBranch, - Predicable, - NotDuplicable, Compare, + MoveImm, DelaySlot, FoldableAsLoad, MayLoad, MayStore, + Predicable, + NotDuplicable, UnmodeledSideEffects, Commutable, ConvertibleTo3Addr, @@ -352,6 +353,12 @@ public: return Flags & (1 << TID::Compare); } + /// isMoveImmediate - Return true if this instruction is a move immediate + /// (including conditional moves) instruction. + bool isMoveImmediate() const { + return Flags & (1 << TID::MoveImm); + } + /// isNotDuplicable - Return true if this instruction cannot be safely /// duplicated. For example, if the instruction has a unique labels attached /// to it, duplicating it would cause multiple definition errors. diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 2bb01f483a..c903f3153e 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -19,7 +19,6 @@ namespace llvm { -class CalleeSavedInfo; class InstrItineraryData; class LiveVariables; class MCAsmInfo; @@ -30,6 +29,7 @@ class MCInst; class SDNode; class ScheduleHazardRecognizer; class SelectionDAG; +class ScheduleDAG; class TargetRegisterClass; class TargetRegisterInfo; @@ -135,7 +135,7 @@ public: int &FrameIndex) const { return 0; } - + /// isStoreToStackSlot - If the specified machine instruction is a direct /// store to a stack slot, return the virtual or physical register number of /// the source reg along with the FrameIndex of the loaded stack slot. If @@ -228,9 +228,12 @@ public: /// produceSameValue - Return true if two machine instructions would produce /// identical values. By default, this is only true when the two instructions - /// are deemed identical except for defs. + /// are deemed identical except for defs. If this function is called when the + /// IR is still in SSA form, the caller can pass the MachineRegisterInfo for + /// aggressive checks. virtual bool produceSameValue(const MachineInstr *MI0, - const MachineInstr *MI1) const = 0; + const MachineInstr *MI1, + const MachineRegisterInfo *MRI = 0) const = 0; /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning /// true if it cannot be understood (e.g. it's a switch dispatch or isn't @@ -268,7 +271,7 @@ public: /// This is only invoked in cases where AnalyzeBranch returns success. It /// returns the number of instructions that were removed. virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const { - assert(0 && "Target didn't implement TargetInstrInfo::RemoveBranch!"); + assert(0 && "Target didn't implement TargetInstrInfo::RemoveBranch!"); return 0; } @@ -286,7 +289,7 @@ public: MachineBasicBlock *FBB, const SmallVectorImpl<MachineOperand> &Cond, DebugLoc DL) const { - assert(0 && "Target didn't implement TargetInstrInfo::InsertBranch!"); + assert(0 && "Target didn't implement TargetInstrInfo::InsertBranch!"); return 0; } @@ -315,7 +318,7 @@ public: float Probability, float Confidence) const { return false; } - + /// isProfitableToIfCvt - Second variant of isProfitableToIfCvt, this one /// checks for the case where two basic blocks from true and false path /// of a if-then-else (diamond) are predicated on mutally exclusive @@ -342,7 +345,7 @@ public: float Probability, float Confidence) const { return false; } - + /// copyPhysReg - Emit instructions to copy a pair of physical registers. virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, DebugLoc DL, @@ -375,29 +378,7 @@ public: const TargetRegisterInfo *TRI) const { assert(0 && "Target didn't implement TargetInstrInfo::loadRegFromStackSlot!"); } - - /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee - /// saved registers and returns true if it isn't possible / profitable to do - /// so by issuing a series of store instructions via - /// storeRegToStackSlot(). Returns false otherwise. - virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const { - return false; - } - /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee - /// saved registers and returns true if it isn't possible / profitable to do - /// so by issuing a series of load instructions via loadRegToStackSlot(). - /// Returns false otherwise. - virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const { - return false; - } - /// emitFrameIndexDebugValue - Emit a target-dependent form of /// DBG_VALUE encoding the address of a frame index. Addresses would /// normally be lowered the same way as other addresses on the target, @@ -508,7 +489,7 @@ public: unsigned NumLoads) const { return false; } - + /// ReverseBranchCondition - Reverses the branch condition of the specified /// condition list, returning false on success and true if it cannot be /// reversed. @@ -516,19 +497,19 @@ public: bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { return true; } - + /// insertNoop - Insert a noop into the instruction stream at the specified /// point. - virtual void insertNoop(MachineBasicBlock &MBB, + virtual void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const; - - + + /// getNoopForMachoTarget - Return the noop instruction to use for a noop. virtual void getNoopForMachoTarget(MCInst &NopInst) const { // Default to just using 'nop' string. } - - + + /// isPredicated - Returns true if the instruction is already predicated. /// virtual bool isPredicated(const MachineInstr *MI) const { @@ -586,11 +567,19 @@ public: virtual unsigned getInlineAsmLength(const char *Str, const MCAsmInfo &MAI) const; - /// CreateTargetHazardRecognizer - Allocate and return a hazard recognizer - /// to use for this target when scheduling the machine instructions after + /// CreateTargetHazardRecognizer - Allocate and return a hazard recognizer to + /// use for this target when scheduling the machine instructions before /// register allocation. virtual ScheduleHazardRecognizer* - CreateTargetPostRAHazardRecognizer(const InstrItineraryData*) const = 0; + CreateTargetHazardRecognizer(const TargetMachine *TM, + const ScheduleDAG *DAG) const = 0; + + /// CreateTargetPostRAHazardRecognizer - Allocate and return a hazard + /// recognizer to use for this target when scheduling the machine instructions + /// after register allocation. + virtual ScheduleHazardRecognizer* + CreateTargetPostRAHazardRecognizer(const InstrItineraryData*, + const ScheduleDAG *DAG) const = 0; /// AnalyzeCompare - For a comparison instruction, return the source register /// in SrcReg and the value it compares against in CmpValue. Return true if @@ -609,11 +598,26 @@ public: return false; } + /// FoldImmediate - 'Reg' is known to be defined by a move immediate + /// instruction, try to fold the immediate into the use instruction. + virtual bool FoldImmediate(MachineInstr *UseMI, MachineInstr *DefMI, + unsigned Reg, MachineRegisterInfo *MRI) const { + return false; + } + /// getNumMicroOps - Return the number of u-operations the given machine /// instruction will be decoded to on the target cpu. virtual unsigned getNumMicroOps(const InstrItineraryData *ItinData, const MachineInstr *MI) const; + /// isZeroCost - Return true for pseudo instructions that don't consume any + /// machine resources in their current form. These are common cases that the + /// scheduler should consider free, rather than conservatively handling them + /// as instructions with no itinerary. + bool isZeroCost(unsigned Opcode) const { + return Opcode <= TargetOpcode::COPY; + } + /// getOperandLatency - Compute and return the use operand latency of a given /// pair of def and use. /// In most cases, the static scheduling itinerary was enough to determine the @@ -637,6 +641,10 @@ public: virtual int getInstrLatency(const InstrItineraryData *ItinData, SDNode *Node) const; + /// isHighLatencyDef - Return true if this opcode has high latency to its + /// result. + virtual bool isHighLatencyDef(int opc) const { return false; } + /// hasHighOperandLatency - Compute operand latency between a def of 'Reg' /// and an use in the current loop, return true if the target considered /// it 'high'. This is used by optimization passes such as machine LICM to @@ -684,13 +692,20 @@ public: virtual MachineInstr *duplicate(MachineInstr *Orig, MachineFunction &MF) const; virtual bool produceSameValue(const MachineInstr *MI0, - const MachineInstr *MI1) const; + const MachineInstr *MI1, + const MachineRegisterInfo *MRI) const; virtual bool isSchedulingBoundary(const MachineInstr *MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const; + bool usePreRAHazardRecognizer() const; + + virtual ScheduleHazardRecognizer * + CreateTargetHazardRecognizer(const TargetMachine*, const ScheduleDAG*) const; + virtual ScheduleHazardRecognizer * - CreateTargetPostRAHazardRecognizer(const InstrItineraryData*) const; + CreateTargetPostRAHazardRecognizer(const InstrItineraryData*, + const ScheduleDAG*) const; }; } // End llvm namespace diff --git a/include/llvm/Target/TargetInstrItineraries.h b/include/llvm/Target/TargetInstrItineraries.h index 380147c650..a95b70f6b9 100644 --- a/include/llvm/Target/TargetInstrItineraries.h +++ b/include/llvm/Target/TargetInstrItineraries.h @@ -113,15 +113,17 @@ public: const unsigned *OperandCycles; ///< Array of operand cycles selected const unsigned *Forwardings; ///< Array of pipeline forwarding pathes const InstrItinerary *Itineraries; ///< Array of itineraries selected + unsigned IssueWidth; ///< Max issue per cycle. 0=Unknown. /// Ctors. /// InstrItineraryData() : Stages(0), OperandCycles(0), Forwardings(0), - Itineraries(0) {} + Itineraries(0), IssueWidth(0) {} + InstrItineraryData(const InstrStage *S, const unsigned *OS, const unsigned *F, const InstrItinerary *I) : Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(I) {} - + /// isEmpty - Returns true if there are no itineraries. /// bool isEmpty() const { return Itineraries == 0; } @@ -135,14 +137,14 @@ public: } /// beginStage - Return the first stage of the itinerary. - /// + /// const InstrStage *beginStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; return Stages + StageIdx; } /// endStage - Return the last+1 stage of the itinerary. - /// + /// const InstrStage *endStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; return Stages + StageIdx; diff --git a/include/llvm/Target/TargetJITInfo.h b/include/llvm/Target/TargetJITInfo.h index 7208a8dc44..b198eb62f0 100644 --- a/include/llvm/Target/TargetJITInfo.h +++ b/include/llvm/Target/TargetJITInfo.h @@ -19,7 +19,7 @@ #include <cassert> #include "llvm/Support/ErrorHandling.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class Function; diff --git a/include/llvm/Target/TargetLibraryInfo.h b/include/llvm/Target/TargetLibraryInfo.h new file mode 100644 index 0000000000..1847a3725e --- /dev/null +++ b/include/llvm/Target/TargetLibraryInfo.h @@ -0,0 +1,75 @@ +//===-- llvm/Target/TargetLibraryInfo.h - Library information ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETLIBRARYINFO_H +#define LLVM_TARGET_TARGETLIBRARYINFO_H + +#include "llvm/Pass.h" + +namespace llvm { + class Triple; + + namespace LibFunc { + enum Func { + /// void *memset(void *b, int c, size_t len); + memset, + + // void *memcpy(void *s1, const void *s2, size_t n); + memcpy, + + /// void memset_pattern16(void *b, const void *pattern16, size_t len); + memset_pattern16, + + /// int iprintf(const char *format, ...); + iprintf, + + /// int siprintf(char *str, const char *format, ...); + siprintf, + + /// int fiprintf(FILE *stream, const char *format, ...); + fiprintf, + + NumLibFuncs + }; + } + +/// TargetLibraryInfo - This immutable pass captures information about what +/// library functions are available for the current target, and allows a +/// frontend to disable optimizations through -fno-builtin etc. +class TargetLibraryInfo : public ImmutablePass { + unsigned char AvailableArray[(LibFunc::NumLibFuncs+7)/8]; +public: + static char ID; + TargetLibraryInfo(); + TargetLibraryInfo(const Triple &T); + + /// has - This function is used by optimizations that want to match on or form + /// a given library function. + bool has(LibFunc::Func F) const { + return (AvailableArray[F/8] & (1 << (F&7))) != 0; + } + + /// setUnavailable - this can be used by whatever sets up TargetLibraryInfo to + /// ban use of specific library functions. + void setUnavailable(LibFunc::Func F) { + AvailableArray[F/8] &= ~(1 << (F&7)); + } + + void setAvailable(LibFunc::Func F) { + AvailableArray[F/8] |= 1 << (F&7); + } + + /// disableAllFunctions - This disables all builtins, which is used for + /// options like -fno-builtin. + void disableAllFunctions(); +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 75e5325524..42c330f4f2 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -39,6 +39,7 @@ namespace llvm { class AllocaInst; class APFloat; class CallInst; + class CCState; class Function; class FastISel; class FunctionLoweringInfo; @@ -111,7 +112,7 @@ public: bool isBigEndian() const { return !IsLittleEndian; } bool isLittleEndian() const { return IsLittleEndian; } MVT getPointerTy() const { return PointerTy; } - MVT getShiftAmountTy() const { return ShiftAmountTy; } + virtual MVT getShiftAmountTy(EVT LHSTy) const; /// isSelectExpensive - Return true if the select operation is expensive for /// this target. @@ -125,6 +126,10 @@ public: /// srl/add/sra. bool isPow2DivCheap() const { return Pow2DivIsCheap; } + /// isJumpExpensive() - Return true if Flow Control is an expensive operation + /// that should be avoided. + bool isJumpExpensive() const { return JumpIsExpensive; } + /// getSetCCResultType - Return the ValueType of the result of SETCC /// operations. Also used to obtain the target's preferred type for /// the condition operand of SELECT and BRCOND nodes. In the case of @@ -206,7 +211,7 @@ public: /// ValueTypeActions - For each value type, keep a LegalizeAction enum /// that indicates how instruction selection should deal with the type. uint8_t ValueTypeActions[MVT::LAST_VALUETYPE]; - + LegalizeAction getExtendedTypeAction(EVT VT) const { // Handle non-vector integers. if (!VT.isVector()) { @@ -217,42 +222,56 @@ public: return Promote; return Expand; } - - // If this is a type smaller than a legal vector type, promote to that - // type, e.g. <2 x float> -> <4 x float>. - if (VT.getVectorElementType().isSimple() && - VT.getVectorNumElements() != 1) { - MVT EltType = VT.getVectorElementType().getSimpleVT(); - unsigned NumElts = VT.getVectorNumElements(); - while (1) { - // Round up to the nearest power of 2. - NumElts = (unsigned)NextPowerOf2(NumElts); - - MVT LargerVector = MVT::getVectorVT(EltType, NumElts); - if (LargerVector == MVT()) break; - - // If this the larger type is legal, promote to it. - if (getTypeAction(LargerVector) == Legal) return Promote; - } + + // Vectors with only one element are always scalarized. + if (VT.getVectorNumElements() == 1) + return Expand; + + // Vectors with a number of elements that is not a power of two are always + // widened, for example <3 x float> -> <4 x float>. + if (!VT.isPow2VectorType()) + return Promote; + + // Vectors with a crazy element type are always expanded, for example + // <4 x i2> is expanded into two vectors of type <2 x i2>. + if (!VT.getVectorElementType().isSimple()) + return Expand; + + // If this type is smaller than a legal vector type then widen it, + // otherwise expand it. E.g. <2 x float> -> <4 x float>. + MVT EltType = VT.getVectorElementType().getSimpleVT(); + unsigned NumElts = VT.getVectorNumElements(); + while (1) { + // Round up to the next power of 2. + NumElts = (unsigned)NextPowerOf2(NumElts); + + // If there is no simple vector type with this many elements then there + // cannot be a larger legal vector type. Note that this assumes that + // there are no skipped intermediate vector types in the simple types. + MVT LargerVector = MVT::getVectorVT(EltType, NumElts); + if (LargerVector == MVT()) + return Expand; + + // If this type is legal then widen the vector. + if (getTypeAction(LargerVector) == Legal) + return Promote; } - - return VT.isPow2VectorType() ? Expand : Promote; - } + } public: ValueTypeActionImpl() { std::fill(ValueTypeActions, array_endof(ValueTypeActions), 0); } - + LegalizeAction getTypeAction(EVT VT) const { if (!VT.isExtended()) return getTypeAction(VT.getSimpleVT()); return getExtendedTypeAction(VT); } - + LegalizeAction getTypeAction(MVT VT) const { return (LegalizeAction)ValueTypeActions[VT.SimpleTy]; } - + void setTypeAction(EVT VT, LegalizeAction Action) { unsigned I = VT.getSimpleVT().SimpleTy; ValueTypeActions[I] = Action; @@ -273,7 +292,7 @@ public: LegalizeAction getTypeAction(MVT VT) const { return ValueTypeActions.getTypeAction(VT); } - + /// getTypeToTransformTo - For types supported by the target, this is an /// identity function. For types that must be promoted to larger types, this /// returns the larger type to promote to. For integer types that are larger @@ -306,7 +325,7 @@ public: EVT NVT = VT.getRoundIntegerType(Context); if (NVT == VT) // Size is a power of two - expand to half the size. return EVT::getIntegerVT(Context, VT.getSizeInBits() / 2); - + // Promote to a power of two size, avoiding multi-step promotion. return getTypeAction(NVT) == Promote ? getTypeToTransformTo(Context, NVT) : NVT; @@ -638,21 +657,30 @@ public: /// This function returns the maximum number of store operations permitted /// to replace a call to llvm.memset. The value is set by the target at the - /// performance threshold for such a replacement. + /// performance threshold for such a replacement. If OptSize is true, + /// return the limit for functions that have OptSize attribute. /// @brief Get maximum # of store operations permitted for llvm.memset - unsigned getMaxStoresPerMemset() const { return maxStoresPerMemset; } + unsigned getMaxStoresPerMemset(bool OptSize) const { + return OptSize ? maxStoresPerMemsetOptSize : maxStoresPerMemset; + } /// This function returns the maximum number of store operations permitted /// to replace a call to llvm.memcpy. The value is set by the target at the - /// performance threshold for such a replacement. + /// performance threshold for such a replacement. If OptSize is true, + /// return the limit for functions that have OptSize attribute. /// @brief Get maximum # of store operations permitted for llvm.memcpy - unsigned getMaxStoresPerMemcpy() const { return maxStoresPerMemcpy; } + unsigned getMaxStoresPerMemcpy(bool OptSize) const { + return OptSize ? maxStoresPerMemcpyOptSize : maxStoresPerMemcpy; + } /// This function returns the maximum number of store operations permitted /// to replace a call to llvm.memmove. The value is set by the target at the - /// performance threshold for such a replacement. + /// performance threshold for such a replacement. If OptSize is true, + /// return the limit for functions that have OptSize attribute. /// @brief Get maximum # of store operations permitted for llvm.memmove - unsigned getMaxStoresPerMemmove() const { return maxStoresPerMemmove; } + unsigned getMaxStoresPerMemmove(bool OptSize) const { + return OptSize ? maxStoresPerMemmoveOptSize : maxStoresPerMemmove; + } /// This function returns true if the target allows unaligned memory accesses. /// of the specified type. This is used, for example, in situations where an @@ -950,6 +978,13 @@ public: return isTypeLegal(VT); } + /// isDesirableToPromoteOp - Return true if it is profitable for dag combiner + /// to transform a floating point op of specified opcode to a equivalent op of + /// an integer type. e.g. f32 load -> i32 load can be profitable on ARM. + virtual bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const { + return false; + } + /// IsDesirableToPromoteOp - This method query the target whether it is /// beneficial for dag combiner to promote the specified node. If true, it /// should return the desired promotion type by reference. @@ -963,10 +998,6 @@ public: // protected: - /// setShiftAmountType - Describe the type that should be used for shift - /// amounts. This type defaults to the pointer type. - void setShiftAmountType(MVT VT) { ShiftAmountTy = VT; } - /// setBooleanContents - Specify how the target extends the result of a /// boolean value from i1 to a wider type. See getBooleanContents. void setBooleanContents(BooleanContent Ty) { BooleanContents = Ty; } @@ -1013,7 +1044,16 @@ protected: /// SelectIsExpensive - Tells the code generator not to expand operations /// into sequences that use the select operations if possible. - void setSelectIsExpensive() { SelectIsExpensive = true; } + void setSelectIsExpensive(bool isExpensive = true) { + SelectIsExpensive = isExpensive; + } + + /// JumpIsExpensive - Tells the code generator not to expand sequence of + /// operations into a seperate sequences that increases the amount of + /// flow control. + void setJumpIsExpensive(bool isExpensive = true) { + JumpIsExpensive = isExpensive; + } /// setIntDivIsCheap - Tells the code generator that integer divide is /// expensive, and if possible, should be replaced by an alternate sequence @@ -1219,6 +1259,9 @@ public: return SDValue(); // this is here to silence compiler errors } + /// HandleByVal - Target-specific cleanup for formal ByVal parameters. + virtual void HandleByVal(CCState *) const {} + /// CanLowerReturn - This hook should be implemented to check whether the /// return values described by the Outs array can fit into the return /// registers. If false is returned, an sret-demotion is performed. @@ -1245,6 +1288,13 @@ public: return SDValue(); // this is here to silence compiler errors } + /// isUsedByReturnOnly - Return true if result of the specified node is used + /// by a return node only. This is used to determine whether it is possible + /// to codegen a libcall as tail call at legalization time. + virtual bool isUsedByReturnOnly(SDNode *N) const { + return false; + } + /// LowerOperationWrapper - This callback is invoked by the type legalizer /// to legalize nodes with an illegal operand type but legal result types. /// It replaces the LowerOperation callback in the type Legalizer. @@ -1319,7 +1369,7 @@ public: CW_Good = 1, // Good weight. CW_Better = 2, // Better weight. CW_Best = 3, // Best weight. - + // Well-known weights. CW_SpecificReg = CW_Okay, // Specific register operands. CW_Register = CW_Good, // Register operands. @@ -1372,21 +1422,21 @@ public: CallOperandVal(0), ConstraintVT(MVT::Other) { } }; - + typedef std::vector<AsmOperandInfo> AsmOperandInfoVector; - + /// ParseConstraints - Split up the constraint string from the inline /// assembly value into the specific constraints and their prefixes, /// and also tie in the associated operand values. /// If this returns an empty vector, and if the constraint string itself /// isn't empty, there was an error parsing. virtual AsmOperandInfoVector ParseConstraints(ImmutableCallSite CS) const; - + /// Examine constraint type and operand type and determine a weight value. /// The operand object must already have been set up with the operand type. virtual ConstraintWeight getMultipleConstraintMatchWeight( AsmOperandInfo &info, int maIndex) const; - + /// Examine constraint string and operand type and determine a weight value. /// The operand object must already have been set up with the operand type. virtual ConstraintWeight getSingleConstraintMatchWeight( @@ -1396,7 +1446,7 @@ public: /// type to use for the specific AsmOperandInfo, setting /// OpInfo.ConstraintCode and OpInfo.ConstraintType. If the actual operand /// being passed in is available, it can be passed in as Op, otherwise an - /// empty SDValue can be passed. + /// empty SDValue can be passed. virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, SelectionDAG *DAG = 0) const; @@ -1597,6 +1647,11 @@ private: /// it. bool Pow2DivIsCheap; + /// JumpIsExpensive - Tells the code generator that it shouldn't generate + /// extra flow control instructions and should attempt to combine flow + /// control instructions via predication. + bool JumpIsExpensive; + /// UseUnderscoreSetJmp - This target prefers to use _setjmp to implement /// llvm.setjmp. Defaults to false. bool UseUnderscoreSetJmp; @@ -1605,10 +1660,6 @@ private: /// llvm.longjmp. Defaults to false. bool UseUnderscoreLongJmp; - /// ShiftAmountTy - The type to use for shift amounts, usually i8 or whatever - /// PointerTy is. - MVT ShiftAmountTy; - /// BooleanContents - Information about the contents of the high-bits in /// boolean values held in a type wider than i1. See getBooleanContents. BooleanContent BooleanContents; @@ -1751,6 +1802,10 @@ protected: /// @brief Specify maximum number of store instructions per memset call. unsigned maxStoresPerMemset; + /// Maximum number of stores operations that may be substituted for the call + /// to memset, used for functions with OptSize attribute. + unsigned maxStoresPerMemsetOptSize; + /// When lowering \@llvm.memcpy this field specifies the maximum number of /// store operations that may be substituted for a call to memcpy. Targets /// must set this value based on the cost threshold for that target. Targets @@ -1763,6 +1818,10 @@ protected: /// @brief Specify maximum bytes of store instructions per memcpy call. unsigned maxStoresPerMemcpy; + /// Maximum number of store operations that may be substituted for a call + /// to memcpy, used for functions with OptSize attribute. + unsigned maxStoresPerMemcpyOptSize; + /// When lowering \@llvm.memmove this field specifies the maximum number of /// store instructions that may be substituted for a call to memmove. Targets /// must set this value based on the cost threshold for that target. Targets @@ -1774,6 +1833,10 @@ protected: /// @brief Specify maximum bytes of store instructions per memmove call. unsigned maxStoresPerMemmove; + /// Maximum number of store instructions that may be substituted for a call + /// to memmove, used for functions with OpSize attribute. + unsigned maxStoresPerMemmoveOptSize; + /// This field specifies whether the target can benefit from code placement /// optimization. bool benefitFromCodePlacementOpt; diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 5456dd0700..34bf27132d 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -69,10 +69,6 @@ protected: /// the section the Language Specific Data Area information is emitted to. const MCSection *LSDASection; - /// EHFrameSection - If exception handling is supported by the target, this is - /// the section the EH Frame is emitted to. - const MCSection *EHFrameSection; - // Dwarf sections for debug info. If a target supports debug info, these must // be set. const MCSection *DwarfAbbrevSection; @@ -143,7 +139,7 @@ public: const MCSection *getStaticCtorSection() const { return StaticCtorSection; } const MCSection *getStaticDtorSection() const { return StaticDtorSection; } const MCSection *getLSDASection() const { return LSDASection; } - const MCSection *getEHFrameSection() const { return EHFrameSection; } + virtual const MCSection *getEHFrameSection() const = 0; const MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } const MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } const MCSection *getDwarfLineSection() const { return DwarfLineSection; } diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 01dc1b0c41..030bf5b89f 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -29,7 +29,7 @@ class TargetIntrinsicInfo; class TargetJITInfo; class TargetLowering; class TargetSelectionDAGInfo; -class TargetFrameInfo; +class TargetFrameLowering; class JITCodeEmitter; class MCContext; class TargetRegisterInfo; @@ -104,6 +104,8 @@ protected: // Can only create subclasses. const MCAsmInfo *AsmInfo; unsigned MCRelaxAll : 1; + unsigned MCNoExecStack : 1; + unsigned MCUseLoc : 1; public: virtual ~TargetMachine(); @@ -116,11 +118,11 @@ public: // -- Stack frame information // -- Selection DAG lowering information // - virtual const TargetInstrInfo *getInstrInfo() const { return 0; } - virtual const TargetFrameInfo *getFrameInfo() const { return 0; } + virtual const TargetInstrInfo *getInstrInfo() const { return 0; } + virtual const TargetFrameLowering *getFrameLowering() const { return 0; } virtual const TargetLowering *getTargetLowering() const { return 0; } virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const{ return 0; } - virtual const TargetData *getTargetData() const { return 0; } + virtual const TargetData *getTargetData() const { return 0; } /// getMCAsmInfo - Return target specific asm information. /// @@ -169,6 +171,18 @@ public: /// relaxed. void setMCRelaxAll(bool Value) { MCRelaxAll = Value; } + /// hasMCNoExecStack - Check whether an executable stack is not needed. + bool hasMCNoExecStack() const { return MCNoExecStack; } + + /// setMCNoExecStack - Set whether an executabel stack is not needed. + void setMCNoExecStack(bool Value) { MCNoExecStack = Value; } + + /// hasMCUseLoc - Check whether we should use dwarf's .loc directive. + bool hasMCUseLoc() const { return MCUseLoc; } + + /// setMCUseLoc - Set whether all we should use dwarf's .loc directive. + void setMCUseLoc(bool Value) { MCUseLoc = Value; } + /// getRelocationModel - Returns the code generation relocation model. The /// choices are static, PIC, and dynamic-no-pic, and target default. static Reloc::Model getRelocationModel(); diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 9be36238a1..af10748ef4 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -29,21 +29,21 @@ class MachineFunction; class MachineMove; class RegScavenger; template<class T> class SmallVectorImpl; +class raw_ostream; /// TargetRegisterDesc - This record contains all of the information known about -/// a particular register. The AliasSet field (if not null) contains a pointer -/// to a Zero terminated array of registers that this register aliases. This is -/// needed for architectures like X86 which have AL alias AX alias EAX. -/// Registers that this does not apply to simply should set this to null. -/// The SubRegs field is a zero terminated array of registers that are -/// sub-registers of the specific register, e.g. AL, AH are sub-registers of AX. -/// The SuperRegs field is a zero terminated array of registers that are +/// a particular register. The Overlaps field contains a pointer to a zero +/// terminated array of registers that this register aliases, starting with +/// itself. This is needed for architectures like X86 which have AL alias AX +/// alias EAX. The SubRegs field is a zero terminated array of registers that +/// are sub-registers of the specific register, e.g. AL, AH are sub-registers of +/// AX. The SuperRegs field is a zero terminated array of registers that are /// super-registers of the specific register, e.g. RAX, EAX, are super-registers /// of AX. /// struct TargetRegisterDesc { const char *Name; // Printable name for the reg (for debugging) - const unsigned *AliasSet; // Register Alias Set, described above + const unsigned *Overlaps; // Overlapping registers, described above const unsigned *SubRegs; // Sub-register set, described above const unsigned *SuperRegs; // Super-register set, described above }; @@ -295,30 +295,68 @@ protected: virtual ~TargetRegisterInfo(); public: - enum { // Define some target independent constants - /// NoRegister - This physical register is not a real target register. It - /// is useful as a sentinal. - NoRegister = 0, + // Register numbers can represent physical registers, virtual registers, and + // sometimes stack slots. The unsigned values are divided into these ranges: + // + // 0 Not a register, can be used as a sentinel. + // [1;2^30) Physical registers assigned by TableGen. + // [2^30;2^31) Stack slots. (Rarely used.) + // [2^31;2^32) Virtual registers assigned by MachineRegisterInfo. + // + // Further sentinels can be allocated from the small negative integers. + // DenseMapInfo<unsigned> uses -1u and -2u. + + /// isStackSlot - Sometimes it is useful the be able to store a non-negative + /// frame index in a variable that normally holds a register. isStackSlot() + /// returns true if Reg is in the range used for stack slots. + /// + /// Note that isVirtualRegister() and isPhysicalRegister() cannot handle stack + /// slots, so if a variable may contains a stack slot, always check + /// isStackSlot() first. + /// + static bool isStackSlot(unsigned Reg) { + return int(Reg) >= (1 << 30); + } - /// FirstVirtualRegister - This is the first register number that is - /// considered to be a 'virtual' register, which is part of the SSA - /// namespace. This must be the same for all targets, which means that each - /// target is limited to this fixed number of registers. - FirstVirtualRegister = 16384 - }; + /// stackSlot2Index - Compute the frame index from a register value + /// representing a stack slot. + static int stackSlot2Index(unsigned Reg) { + assert(isStackSlot(Reg) && "Not a stack slot"); + return int(Reg - (1u << 30)); + } + + /// index2StackSlot - Convert a non-negative frame index to a stack slot + /// register value. + static unsigned index2StackSlot(int FI) { + assert(FI >= 0 && "Cannot hold a negative frame index."); + return FI + (1u << 30); + } /// isPhysicalRegister - Return true if the specified register number is in /// the physical register namespace. static bool isPhysicalRegister(unsigned Reg) { - assert(Reg && "this is not a register!"); - return Reg < FirstVirtualRegister; + assert(!isStackSlot(Reg) && "Not a register! Check isStackSlot() first."); + return int(Reg) > 0; } /// isVirtualRegister - Return true if the specified register number is in /// the virtual register namespace. static bool isVirtualRegister(unsigned Reg) { - assert(Reg && "this is not a register!"); - return Reg >= FirstVirtualRegister; + assert(!isStackSlot(Reg) && "Not a register! Check isStackSlot() first."); + return int(Reg) < 0; + } + + /// virtReg2Index - Convert a virtual register number to a 0-based index. + /// The first virtual register in a function will get the index 0. + static unsigned virtReg2Index(unsigned Reg) { + assert(isVirtualRegister(Reg) && "Not a virtual register"); + return Reg - (1u << 31); + } + + /// index2VirtReg - Convert a 0-based index to a virtual register number. + /// This is the inverse operation of VirtReg2IndexFunctor below. + static unsigned index2VirtReg(unsigned Index) { + return Index + (1u << 31); } /// getMinimalPhysRegClass - Returns the Register Class of a physical @@ -351,7 +389,17 @@ public: /// terminated. /// const unsigned *getAliasSet(unsigned RegNo) const { - return get(RegNo).AliasSet; + // The Overlaps set always begins with Reg itself. + return get(RegNo).Overlaps + 1; + } + + /// getOverlaps - Return a list of registers that overlap Reg, including + /// itself. This is the same as the alias set except Reg is included in the + /// list. + /// These are exactly the registers in { x | regsOverlap(x, Reg) }. + /// + const unsigned *getOverlaps(unsigned RegNo) const { + return get(RegNo).Overlaps; } /// getSubRegisters - Return the list of registers that are sub-registers of @@ -583,6 +631,13 @@ public: return false; } + /// useFPForScavengingIndex - returns true if the target wants to use + /// frame pointer based accesses to spill to the scavenger emergency spill + /// slot. + virtual bool useFPForScavengingIndex(const MachineFunction &MF) const { + return true; + } + /// requiresFrameIndexScavenging - returns true if the target requires post /// PEI scavenging of registers for materializing frame index constants. virtual bool requiresFrameIndexScavenging(const MachineFunction &MF) const { @@ -596,31 +651,6 @@ public: return false; } - /// hasFP - Return true if the specified function should have a dedicated - /// frame pointer register. For most targets this is true only if the function - /// has variable sized allocas or if frame pointer elimination is disabled. - virtual bool hasFP(const MachineFunction &MF) const = 0; - - /// hasReservedCallFrame - Under normal circumstances, when a frame pointer is - /// not required, we reserve argument space for call sites in the function - /// immediately on entry to the current function. This eliminates the need for - /// add/sub sp brackets around call sites. Returns true if the call frame is - /// included as part of the stack frame. - virtual bool hasReservedCallFrame(const MachineFunction &MF) const { - return !hasFP(MF); - } - - /// canSimplifyCallFramePseudos - When possible, it's best to simplify the - /// call frame pseudo ops before doing frame index elimination. This is - /// possible only when frame index references between the pseudos won't - /// need adjusting for the call frame adjustments. Normally, that's true - /// if the function has a reserved call frame or a frame pointer. Some - /// targets (Thumb2, for example) may have more complicated criteria, - /// however, and can override this behavior. - virtual bool canSimplifyCallFramePseudos(const MachineFunction &MF) const { - return hasReservedCallFrame(MF) || hasFP(MF); - } - /// hasReservedSpillSlot - Return true if target has reserved a spill slot in /// the stack frame of the given function for the specified register. e.g. On /// x86, if the frame register is required, the first fixed stack object is @@ -640,7 +670,7 @@ public: } /// getFrameIndexInstrOffset - Get the offset from the referenced frame - /// index in the instruction, if the is one. + /// index in the instruction, if there is one. virtual int64_t getFrameIndexInstrOffset(const MachineInstr *MI, int Idx) const { return 0; @@ -656,7 +686,7 @@ public: /// materializeFrameBaseRegister - Insert defining instruction(s) for /// BaseReg to be a pointer to FrameIdx before insertion point I. - virtual void materializeFrameBaseRegister(MachineBasicBlock::iterator I, + virtual void materializeFrameBaseRegister(MachineBasicBlock *MBB, unsigned BaseReg, int FrameIdx, int64_t Offset) const { assert(0 && "materializeFrameBaseRegister does not exist on this target"); @@ -703,21 +733,6 @@ public: assert(0 && "Call Frame Pseudo Instructions do not exist on this target!"); } - /// processFunctionBeforeCalleeSavedScan - This method is called immediately - /// before PrologEpilogInserter scans the physical registers used to determine - /// what callee saved registers should be spilled. This method is optional. - virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, - RegScavenger *RS = NULL) const { - - } - - /// processFunctionBeforeFrameFinalized - This method is called immediately - /// before the specified function's frame layout (MF.getFrameInfo()) is - /// finalized. Once the frame is finalized, MO_FrameIndex operands are - /// replaced with direct constants. This method is optional. - /// - virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const { - } /// saveScavengerRegister - Spill the register so it can be used by the /// register scavenger. Return true if the register was spilled, false @@ -755,37 +770,16 @@ public: /// for values allocated in the current stack frame. virtual unsigned getFrameRegister(const MachineFunction &MF) const = 0; - /// getFrameIndexOffset - Returns the displacement from the frame register to - /// the stack frame of the specified index. - virtual int getFrameIndexOffset(const MachineFunction &MF, int FI) const; - - /// getFrameIndexReference - This method should return the base register - /// and offset used to reference a frame index location. The offset is - /// returned directly, and the base register is returned via FrameReg. - virtual int getFrameIndexReference(const MachineFunction &MF, int FI, - unsigned &FrameReg) const { - // By default, assume all frame indices are referenced via whatever - // getFrameRegister() says. The target can override this if it's doing - // something different. - FrameReg = getFrameRegister(MF); - return getFrameIndexOffset(MF, FI); - } - /// getRARegister - This method should return the register where the return /// address can be found. virtual unsigned getRARegister() const = 0; - - /// getInitialFrameState - Returns a list of machine moves that are assumed - /// on entry to all functions. Note that LabelID is ignored (assumed to be - /// the beginning of the function.) - virtual void getInitialFrameState(std::vector<MachineMove> &Moves) const; }; // This is useful when building IndexedMaps keyed on virtual registers struct VirtReg2IndexFunctor : public std::unary_function<unsigned, unsigned> { unsigned operator()(unsigned Reg) const { - return Reg - TargetRegisterInfo::FirstVirtualRegister; + return TargetRegisterInfo::virtReg2Index(Reg); } }; @@ -794,6 +788,33 @@ struct VirtReg2IndexFunctor : public std::unary_function<unsigned, unsigned> { const TargetRegisterClass *getCommonSubClass(const TargetRegisterClass *A, const TargetRegisterClass *B); +/// PrintReg - Helper class for printing registers on a raw_ostream. +/// Prints virtual and physical registers with or without a TRI instance. +/// +/// The format is: +/// %noreg - NoRegister +/// %vreg5 - a virtual register. +/// %vreg5:sub_8bit - a virtual register with sub-register index (with TRI). +/// %EAX - a physical register +/// %physreg17 - a physical register when no TRI instance given. +/// +/// Usage: OS << PrintReg(Reg, TRI) << '\n'; +/// +class PrintReg { + const TargetRegisterInfo *TRI; + unsigned Reg; + unsigned SubIdx; +public: + PrintReg(unsigned reg, const TargetRegisterInfo *tri = 0, unsigned subidx = 0) + : TRI(tri), Reg(reg), SubIdx(subidx) {} + void print(raw_ostream&) const; +}; + +static inline raw_ostream &operator<<(raw_ostream &OS, const PrintReg &PR) { + PR.print(OS); + return OS; +} + } // End llvm namespace #endif diff --git a/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h index abffb5852a..f851ad0a9b 100644 --- a/include/llvm/Target/TargetRegistry.h +++ b/include/llvm/Target/TargetRegistry.h @@ -42,9 +42,11 @@ namespace llvm { class formatted_raw_ostream; MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isLittleEndian, bool isVerboseAsm, + bool isVerboseAsm, + bool useLoc, MCInstPrinter *InstPrint, MCCodeEmitter *CE, + TargetAsmBackend *TAB, bool ShowInst); /// Target - Wrapper for Target specific information. @@ -87,13 +89,15 @@ namespace llvm { TargetAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, - bool RelaxAll); + bool RelaxAll, + bool NoExecStack); typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx, formatted_raw_ostream &OS, - bool isLittleEndian, bool isVerboseAsm, + bool useLoc, MCInstPrinter *InstPrint, MCCodeEmitter *CE, + TargetAsmBackend *TAB, bool ShowInst); private: @@ -305,27 +309,31 @@ namespace llvm { /// \arg _OS - The stream object. /// \arg _Emitter - The target independent assembler object.Takes ownership. /// \arg RelaxAll - Relax all fixups? + /// \arg NoExecStack - Mark file as not needing a executable stack. MCStreamer *createObjectStreamer(const std::string &TT, MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, - bool RelaxAll) const { + bool RelaxAll, + bool NoExecStack) const { if (!ObjectStreamerCtorFn) return 0; - return ObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, RelaxAll); + return ObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, RelaxAll, + NoExecStack); } /// createAsmStreamer - Create a target specific MCStreamer. MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isLittleEndian, bool isVerboseAsm, + bool useLoc, MCInstPrinter *InstPrint, MCCodeEmitter *CE, + TargetAsmBackend *TAB, bool ShowInst) const { // AsmStreamerCtorFn is default to llvm::createAsmStreamer - return AsmStreamerCtorFn(Ctx, OS, isLittleEndian, isVerboseAsm, - InstPrint, CE, ShowInst); + return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, + InstPrint, CE, TAB, ShowInst); } /// @} diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 7315e52ef0..c9be40d23f 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -1,10 +1,10 @@ //===- TargetSelectionDAG.td - Common code for DAG isels ---*- tablegen -*-===// -// +// // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // // This file defines the target-independent interfaces used by SelectionDAG @@ -61,6 +61,13 @@ class SDTCisEltOfVec<int ThisOp, int OtherOp> int OtherOpNum = OtherOp; } +/// SDTCisSubVecOfVec - This indicates that ThisOp is a vector type +/// with length less that of OtherOp, which is a vector type. +class SDTCisSubVecOfVec<int ThisOp, int OtherOp> + : SDTypeConstraint<ThisOp> { + int OtherOpNum = OtherOp; +} + //===----------------------------------------------------------------------===// // Selection DAG Type Profile definitions. // @@ -123,10 +130,10 @@ def SDTFPRoundOp : SDTypeProfile<1, 1, [ // fround def SDTFPExtendOp : SDTypeProfile<1, 1, [ // fextend SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<1, 0> ]>; -def SDTIntToFPOp : SDTypeProfile<1, 1, [ // [su]int_to_fp +def SDTIntToFPOp : SDTypeProfile<1, 1, [ // [su]int_to_fp SDTCisFP<0>, SDTCisInt<1> ]>; -def SDTFPToIntOp : SDTypeProfile<1, 1, [ // fp_to_[su]int +def SDTFPToIntOp : SDTypeProfile<1, 1, [ // fp_to_[su]int SDTCisInt<0>, SDTCisFP<1> ]>; def SDTExtInreg : SDTypeProfile<1, 2, [ // sext_inreg @@ -138,7 +145,7 @@ def SDTSetCC : SDTypeProfile<1, 3, [ // setcc SDTCisInt<0>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT> ]>; -def SDTSelect : SDTypeProfile<1, 3, [ // select +def SDTSelect : SDTypeProfile<1, 3, [ // select SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3> ]>; @@ -162,11 +169,11 @@ def SDTBrind : SDTypeProfile<0, 1, [ // brind def SDTNone : SDTypeProfile<0, 0, []>; // ret, trap def SDTLoad : SDTypeProfile<1, 1, [ // load - SDTCisPtrTy<1> + SDTCisPtrTy<1> ]>; def SDTStore : SDTypeProfile<0, 2, [ // store - SDTCisPtrTy<1> + SDTCisPtrTy<1> ]>; def SDTIStore : SDTypeProfile<1, 3, [ // indexed store @@ -183,6 +190,13 @@ def SDTVecInsert : SDTypeProfile<1, 3, [ // vector insert SDTCisEltOfVec<2, 1>, SDTCisSameAs<0, 1>, SDTCisPtrTy<3> ]>; +def SDTSubVecExtract : SDTypeProfile<1, 2, [// subvector extract + SDTCisSubVecOfVec<0,1>, SDTCisInt<2> +]>; +def SDTSubVecInsert : SDTypeProfile<1, 3, [ // subvector insert + SDTCisSubVecOfVec<2, 1>, SDTCisSameAs<0,1>, SDTCisInt<3> +]>; + def SDTPrefetch : SDTypeProfile<0, 3, [ // prefetch SDTCisPtrTy<0>, SDTCisSameAs<1, 2>, SDTCisInt<1> ]>; @@ -216,9 +230,9 @@ class SDNodeProperty; def SDNPCommutative : SDNodeProperty; // X op Y == Y op X def SDNPAssociative : SDNodeProperty; // (X op Y) op Z == X op (Y op Z) def SDNPHasChain : SDNodeProperty; // R/W chain operand and result -def SDNPOutFlag : SDNodeProperty; // Write a flag result -def SDNPInFlag : SDNodeProperty; // Read a flag operand -def SDNPOptInFlag : SDNodeProperty; // Optionally read a flag operand +def SDNPOutGlue : SDNodeProperty; // Write a flag result +def SDNPInGlue : SDNodeProperty; // Read a flag operand +def SDNPOptInGlue : SDNodeProperty; // Optionally read a flag operand def SDNPMayStore : SDNodeProperty; // May write to memory, sets 'mayStore'. def SDNPMayLoad : SDNodeProperty; // May read memory, sets 'mayLoad'. def SDNPSideEffect : SDNodeProperty; // Sets 'HasUnmodelledSideEffects'. @@ -235,7 +249,7 @@ class SDPatternOperator; // Selection DAG Node definitions. // class SDNode<string opcode, SDTypeProfile typeprof, - list<SDNodeProperty> props = [], string sdclass = "SDNode"> + list<SDNodeProperty> props = [], string sdclass = "SDNode"> : SDPatternOperator { string Opcode = opcode; string SDClass = sdclass; @@ -312,14 +326,14 @@ def or : SDNode<"ISD::OR" , SDTIntBinOp, def xor : SDNode<"ISD::XOR" , SDTIntBinOp, [SDNPCommutative, SDNPAssociative]>; def addc : SDNode<"ISD::ADDC" , SDTIntBinOp, - [SDNPCommutative, SDNPOutFlag]>; + [SDNPCommutative, SDNPOutGlue]>; def adde : SDNode<"ISD::ADDE" , SDTIntBinOp, - [SDNPCommutative, SDNPOutFlag, SDNPInFlag]>; + [SDNPCommutative, SDNPOutGlue, SDNPInGlue]>; def subc : SDNode<"ISD::SUBC" , SDTIntBinOp, - [SDNPOutFlag]>; + [SDNPOutGlue]>; def sube : SDNode<"ISD::SUBE" , SDTIntBinOp, - [SDNPOutFlag, SDNPInFlag]>; - + [SDNPOutGlue, SDNPInGlue]>; + def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>; def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>; def ctlz : SDNode<"ISD::CTLZ" , SDTIntUnaryOp>; @@ -329,11 +343,11 @@ def sext : SDNode<"ISD::SIGN_EXTEND", SDTIntExtendOp>; def zext : SDNode<"ISD::ZERO_EXTEND", SDTIntExtendOp>; def anyext : SDNode<"ISD::ANY_EXTEND" , SDTIntExtendOp>; def trunc : SDNode<"ISD::TRUNCATE" , SDTIntTruncOp>; -def bitconvert : SDNode<"ISD::BIT_CONVERT", SDTUnaryOp>; +def bitconvert : SDNode<"ISD::BITCAST" , SDTUnaryOp>; def extractelt : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTVecExtract>; def insertelt : SDNode<"ISD::INSERT_VECTOR_ELT", SDTVecInsert>; - + def fadd : SDNode<"ISD::FADD" , SDTFPBinOp, [SDNPCommutative]>; def fsub : SDNode<"ISD::FSUB" , SDTFPBinOp>; def fmul : SDNode<"ISD::FMUL" , SDTFPBinOp, [SDNPCommutative]>; @@ -375,7 +389,8 @@ def trap : SDNode<"ISD::TRAP" , SDTNone, [SDNPHasChain, SDNPSideEffect]>; def prefetch : SDNode<"ISD::PREFETCH" , SDTPrefetch, - [SDNPHasChain, SDNPMayLoad, SDNPMayStore]>; + [SDNPHasChain, SDNPMayLoad, SDNPMayStore, + SDNPMemOperand]>; def membarrier : SDNode<"ISD::MEMBARRIER" , SDTMemBarrier, [SDNPHasChain, SDNPSideEffect]>; @@ -422,16 +437,26 @@ def vector_extract : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTypeProfile<1, 2, [SDTCisPtrTy<2>]>, []>; def vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT", SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisPtrTy<3>]>, []>; - + +// This operator does not do subvector type checking. The ARM +// backend, at least, needs it. +def vector_extract_subvec : SDNode<"ISD::EXTRACT_SUBVECTOR", + SDTypeProfile<1, 2, [SDTCisInt<2>, SDTCisVec<1>, SDTCisVec<0>]>, + []>; + +// This operator does subvector type checking. +def extract_subvector : SDNode<"ISD::EXTRACT_SUBVECTOR", SDTSubVecExtract, []>; +def insert_subvector : SDNode<"ISD::INSERT_SUBVECTOR", SDTSubVecInsert, []>; + // Nodes for intrinsics, you should use the intrinsic itself and let tblgen use // these internally. Don't reference these directly. -def intrinsic_void : SDNode<"ISD::INTRINSIC_VOID", +def intrinsic_void : SDNode<"ISD::INTRINSIC_VOID", SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>, [SDNPHasChain]>; -def intrinsic_w_chain : SDNode<"ISD::INTRINSIC_W_CHAIN", +def intrinsic_w_chain : SDNode<"ISD::INTRINSIC_W_CHAIN", SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, [SDNPHasChain]>; -def intrinsic_wo_chain : SDNode<"ISD::INTRINSIC_WO_CHAIN", +def intrinsic_wo_chain : SDNode<"ISD::INTRINSIC_WO_CHAIN", SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, []>; // Do not use cvt directly. Use cvt forms below diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index 40ef9bbbd6..12398813cc 100644 --- a/include/llvm/Transforms/IPO.h +++ b/include/llvm/Transforms/IPO.h @@ -189,12 +189,6 @@ ModulePass *createBlockExtractorPass(); ModulePass *createStripDeadPrototypesPass(); //===----------------------------------------------------------------------===// -/// createPartialSpecializationPass - This pass specializes functions for -/// constant arguments. -/// -ModulePass *createPartialSpecializationPass(); - -//===----------------------------------------------------------------------===// /// createFunctionAttrsPass - This pass discovers functions that do not access /// memory, or only read memory, and gives them the readnone/readonly attribute. /// It also discovers function arguments that are not captured by the function diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index 9c579ac761..aa9873fb8a 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -25,6 +25,9 @@ ModulePass *createEdgeProfilerPass(); // Insert optimal edge profiling instrumentation ModulePass *createOptimalEdgeProfilerPass(); +// Insert path profiling instrumentation +ModulePass *createPathProfilerPass(); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/RSProfiling.h b/include/llvm/Transforms/RSProfiling.h deleted file mode 100644 index 02439e8e23..0000000000 --- a/include/llvm/Transforms/RSProfiling.h +++ /dev/null @@ -1,42 +0,0 @@ -//===- RSProfiling.cpp - Various profiling using random sampling ----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the abstract interface that a profiler must implement to -// support the random profiling transform. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_RSPROFILING_H -#define LLVM_TRANSFORMS_RSPROFILING_H - -#include "llvm/Pass.h" - -namespace llvm { - class Value; - - //===--------------------------------------------------------------------===// - /// RSProfilers - The basic Random Sampling Profiler Interface Any profiler - /// that implements this interface can be transformed by the random sampling - /// pass to be sample based rather than always on. - /// - /// The only exposed function can be queried to find out if an instruction - /// was original or if it was inserted by the profiler. Implementations of - /// this interface are expected to chain to other implementations, such that - /// multiple profilers can be support simultaniously. - struct RSProfilers : public ModulePass { - static char ID; // Pass identification, replacement for typeinfo - RSProfilers() : ModulePass(&ID) {} - - /// isProfiling - This method returns true if the value passed it was - /// inserted by the profiler. - virtual bool isProfiling(Value* v) = 0; - }; -} - -#endif diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index fa848459a7..8d5ed44cff 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -73,7 +73,8 @@ FunctionPass *createAggressiveDCEPass(); // ScalarReplAggregates - Break up alloca's of aggregates into multiple allocas // if possible. // -FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1); +FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1, + bool UseDomTree = true); //===----------------------------------------------------------------------===// // @@ -119,6 +120,12 @@ Pass *createLoopUnswitchPass(bool OptimizeForSize = false); //===----------------------------------------------------------------------===// // +// LoopInstSimplify - This pass simplifies instructions in a loop's body. +// +Pass *createLoopInstSimplifyPass(); + +//===----------------------------------------------------------------------===// +// // LoopUnroll - This pass is a simple loop unrolling pass. // Pass *createLoopUnrollPass(); @@ -131,6 +138,12 @@ Pass *createLoopRotatePass(); //===----------------------------------------------------------------------===// // +// LoopIdiom - This pass recognizes and replaces idioms in loops. +// +Pass *createLoopIdiomPass(); + +//===----------------------------------------------------------------------===// +// // PromoteMemoryToRegister - This pass is used to promote memory references to // be register references. A simple example of the transformation performed by // this pass is: @@ -254,6 +267,13 @@ extern char &LCSSAID; //===----------------------------------------------------------------------===// // +// EarlyCSE - This pass performs a simple and fast CSE pass over the dominator +// tree. +// +FunctionPass *createEarlyCSEPass(); + +//===----------------------------------------------------------------------===// +// // GVN - This pass performs global value numbering and redundant load // elimination cotemporaneously. // @@ -281,12 +301,6 @@ FunctionPass *createSimplifyLibCallsPass(); //===----------------------------------------------------------------------===// // -/// createSimplifyHalfPowrLibCallsPass - This is an experimental pass that -/// optimizes specific half_pow functions. -FunctionPass *createSimplifyHalfPowrLibCallsPass(); - -//===----------------------------------------------------------------------===// -// // CodeGenPrepare - This pass prepares a function for instruction selection. // FunctionPass *createCodeGenPreparePass(const TargetLowering *TLI = 0); @@ -322,6 +336,13 @@ Pass *createLowerAtomicPass(); // Pass *createCorrelatedValuePropagationPass(); +//===----------------------------------------------------------------------===// +// +// InstructionSimplifier - Remove redundant instructions. +// +FunctionPass *createInstructionSimplifierPass(); +extern char &InstructionSimplifierID; + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/AddrModeMatcher.h b/include/llvm/Transforms/Utils/AddrModeMatcher.h index be601e257b..0678eccb5d 100644 --- a/include/llvm/Transforms/Utils/AddrModeMatcher.h +++ b/include/llvm/Transforms/Utils/AddrModeMatcher.h @@ -39,6 +39,12 @@ struct ExtAddrMode : public TargetLowering::AddrMode { ExtAddrMode() : BaseReg(0), ScaledReg(0) {} void print(raw_ostream &OS) const; void dump() const; + + bool operator==(const ExtAddrMode& O) const { + return (BaseReg == O.BaseReg) && (ScaledReg == O.ScaledReg) && + (BaseGV == O.BaseGV) && (BaseOffs == O.BaseOffs) && + (HasBaseReg == O.HasBaseReg) && (Scale == O.Scale); + } }; static inline raw_ostream &operator<<(raw_ostream &OS, const ExtAddrMode &AM) { @@ -84,7 +90,7 @@ public: bool Success = AddressingModeMatcher(AddrModeInsts, TLI, AccessTy, MemoryInst, Result).MatchAddr(V, 0); - Success = Success; assert(Success && "Couldn't select *anything*?"); + (void)Success; assert(Success && "Couldn't select *anything*?"); return Result; } private: diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index 0f5445077b..5335860287 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -22,9 +22,10 @@ namespace llvm { +class AliasAnalysis; class Instruction; class Pass; -class AliasAnalysis; +class ReturnInst; /// DeleteDeadBlock - Delete the specified block, which must have no /// predecessors. @@ -35,7 +36,7 @@ void DeleteDeadBlock(BasicBlock *BB); /// any single-entry PHI nodes in it, fold them away. This handles the case /// when all entries to the PHI nodes in a block are guaranteed equal, such as /// when the block has exactly one predecessor. -void FoldSingleEntryPHINodes(BasicBlock *BB); +void FoldSingleEntryPHINodes(BasicBlock *BB, Pass *P = 0); /// DeleteDeadPHIs - Examine each PHI in the given block and delete it if it /// is dead. Also recursively delete any operands that become dead as @@ -46,7 +47,7 @@ bool DeleteDeadPHIs(BasicBlock *BB); /// MergeBlockIntoPredecessor - Attempts to merge a block into its predecessor, /// if possible. The return value indicates success or failure. -bool MergeBlockIntoPredecessor(BasicBlock* BB, Pass* P = 0); +bool MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P = 0); // ReplaceInstWithValue - Replace all uses of an instruction (specified by BI) // with a value, then remove and delete the original instruction. @@ -75,15 +76,6 @@ void FindFunctionBackedges(const Function &F, SmallVectorImpl<std::pair<const BasicBlock*,const BasicBlock*> > &Result); -// RemoveSuccessor - Change the specified terminator instruction such that its -// successor #SuccNum no longer exists. Because this reduces the outgoing -// degree of the current basic block, the actual terminator instruction itself -// may have to be changed. In the case where the last successor of the block is -// deleted, a return instruction is inserted in its place which can cause a -// suprising change in program behavior if it is not expected. -// -void RemoveSuccessor(TerminatorInst *TI, unsigned SuccNum); - /// GetSuccessorNumber - Search for the specified successor of basic block BB /// and return its position in the terminator instruction's list of /// successors. It is an error to call this with a block that is not a @@ -180,7 +172,15 @@ BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P); BasicBlock *SplitBlockPredecessors(BasicBlock *BB, BasicBlock *const *Preds, unsigned NumPreds, const char *Suffix, Pass *P = 0); - + +/// FoldReturnIntoUncondBranch - This method duplicates the specified return +/// instruction into a predecessor which ends in an unconditional branch. If +/// the return instruction returns a value defined by a PHI, propagate the +/// right value into the return. It returns the new return instruction in the +/// predecessor. +ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, + BasicBlock *Pred); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h index c75c14277f..e825938384 100644 --- a/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -47,11 +47,6 @@ namespace llvm { /// specified pointer arguments and length. Value *EmitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, const TargetData *TD, StringRef Name = "strncpy"); - - /// EmitMemCpy - Emit a call to the memcpy function to the builder. This - /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. - Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, unsigned Align, - bool isVolatile, IRBuilder<> &B, const TargetData *TD); /// EmitMemCpyChk - Emit a call to the __memcpy_chk function to the builder. /// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src @@ -59,11 +54,6 @@ namespace llvm { Value *EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, IRBuilder<> &B, const TargetData *TD); - /// EmitMemMove - Emit a call to the memmove function to the builder. This - /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. - Value *EmitMemMove(Value *Dst, Value *Src, Value *Len, unsigned Align, - bool isVolatile, IRBuilder<> &B, const TargetData *TD); - /// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is /// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B, @@ -73,10 +63,6 @@ namespace llvm { Value *EmitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, const TargetData *TD); - /// EmitMemSet - Emit a call to the memset function - Value *EmitMemSet(Value *Dst, Value *Val, Value *Len, bool isVolatile, - IRBuilder<> &B, const TargetData *TD); - /// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' /// (e.g. 'floor'). This function is known to take a single of type matching /// 'Op' and returns one value with the same type. If 'Op' is a long double, diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index dc18f3c4c7..2823fbb719 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -60,7 +60,7 @@ bool RecursivelyDeleteTriviallyDeadInstructions(Value *V); /// dead PHI node, due to being a def-use chain of single-use nodes that /// either forms a cycle or is terminated by a trivially dead instruction, /// delete it. If that makes any of its operands trivially dead, delete them -/// too, recursively. Return true if the PHI node is actually deleted. +/// too, recursively. Return true if a change was made. bool RecursivelyDeleteDeadPHINode(PHINode *PN); @@ -145,6 +145,18 @@ AllocaInst *DemoteRegToStack(Instruction &X, /// The phi node is deleted and it returns the pointer to the alloca inserted. AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = 0); +/// getOrEnforceKnownAlignment - If the specified pointer has an alignment that +/// we can determine, return it, otherwise return 0. If PrefAlign is specified, +/// and it is more than the alignment of the ultimate object, see if we can +/// increase the alignment of the ultimate object, making this check succeed. +unsigned getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign, + const TargetData *TD = 0); + +/// getKnownAlignment - Try to infer an alignment for the specified pointer. +static inline unsigned getKnownAlignment(Value *V, const TargetData *TD = 0) { + return getOrEnforceKnownAlignment(V, 0, TD); +} + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h index 35cfaddb73..98d51a29ad 100644 --- a/include/llvm/Transforms/Utils/PromoteMemToReg.h +++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -38,8 +38,7 @@ bool isAllocaPromotable(const AllocaInst *AI); /// made to the IR. /// void PromoteMemToReg(const std::vector<AllocaInst*> &Allocas, - DominatorTree &DT, DominanceFrontier &DF, - AliasSetTracker *AST = 0); + DominatorTree &DT, AliasSetTracker *AST = 0); } // End llvm namespace diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h index e50a6b15df..b4048b9b44 100644 --- a/include/llvm/Transforms/Utils/SSAUpdater.h +++ b/include/llvm/Transforms/Utils/SSAUpdater.h @@ -108,6 +108,55 @@ private: void operator=(const SSAUpdater&); // DO NOT IMPLEMENT SSAUpdater(const SSAUpdater&); // DO NOT IMPLEMENT }; + +/// LoadAndStorePromoter - This little helper class provides a convenient way to +/// promote a collection of loads and stores into SSA Form using the SSAUpdater. +/// This handles complexities that SSAUpdater doesn't, such as multiple loads +/// and stores in one block. +/// +/// Clients of this class are expected to subclass this and implement the +/// virtual methods. +/// +class LoadAndStorePromoter { +protected: + SSAUpdater &SSA; +public: + LoadAndStorePromoter(const SmallVectorImpl<Instruction*> &Insts, + SSAUpdater &S, StringRef Name = StringRef()); + virtual ~LoadAndStorePromoter() {} + + /// run - This does the promotion. Insts is a list of loads and stores to + /// promote, and Name is the basename for the PHIs to insert. After this is + /// complete, the loads and stores are removed from the code. + void run(const SmallVectorImpl<Instruction*> &Insts) const; + + + /// Return true if the specified instruction is in the Inst list (which was + /// passed into the run method). Clients should implement this with a more + /// efficient version if possible. + virtual bool isInstInList(Instruction *I, + const SmallVectorImpl<Instruction*> &Insts) const { + for (unsigned i = 0, e = Insts.size(); i != e; ++i) + if (Insts[i] == I) + return true; + return false; + } + + /// doExtraRewritesBeforeFinalDeletion - This hook is invoked after all the + /// stores are found and inserted as available values, but + virtual void doExtraRewritesBeforeFinalDeletion() const { + } + + /// replaceLoadWithValue - Clients can choose to implement this to get + /// notified right before a load is RAUW'd another value. + virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const { + } + + /// This is called before each instruction is deleted. + virtual void instructionDeleted(Instruction *I) const { + } + +}; } // End llvm namespace diff --git a/include/llvm/Transforms/Utils/ValueMapper.h b/include/llvm/Transforms/Utils/ValueMapper.h index dd320a3fb4..d612213a87 100644 --- a/include/llvm/Transforms/Utils/ValueMapper.h +++ b/include/llvm/Transforms/Utils/ValueMapper.h @@ -22,10 +22,29 @@ namespace llvm { class Instruction; typedef ValueMap<const Value *, TrackingVH<Value> > ValueToValueMapTy; + /// RemapFlags - These are flags that the value mapping APIs allow. + enum RemapFlags { + RF_None = 0, + + /// RF_NoModuleLevelChanges - If this flag is set, the remapper knows that + /// only local values within a function (such as an instruction or argument) + /// are mapped, not global values like functions and global metadata. + RF_NoModuleLevelChanges = 1, + + /// RF_IgnoreMissingEntries - If this flag is set, the remapper ignores + /// entries that are not in the value map. If it is unset, it aborts if an + /// operand is asked to be remapped which doesn't exist in the mapping. + RF_IgnoreMissingEntries = 2 + }; + + static inline RemapFlags operator|(RemapFlags LHS, RemapFlags RHS) { + return RemapFlags(unsigned(LHS)|unsigned(RHS)); + } + Value *MapValue(const Value *V, ValueToValueMapTy &VM, - bool ModuleLevelChanges); + RemapFlags Flags = RF_None); void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, - bool ModuleLevelChanges); + RemapFlags Flags = RF_None); } // End llvm namespace #endif diff --git a/include/llvm/TypeSymbolTable.h b/include/llvm/TypeSymbolTable.h index 55b8b7a3d9..9fdcb98323 100644 --- a/include/llvm/TypeSymbolTable.h +++ b/include/llvm/TypeSymbolTable.h @@ -16,7 +16,7 @@ #include "llvm/Type.h" #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <map> namespace llvm { diff --git a/include/llvm/Use.h b/include/llvm/Use.h index e1ebc6a51b..ccbdd7fcae 100644 --- a/include/llvm/Use.h +++ b/include/llvm/Use.h @@ -25,7 +25,6 @@ #ifndef LLVM_USE_H #define LLVM_USE_H -#include "llvm/Support/Casting.h" #include "llvm/ADT/PointerIntPair.h" #include <cstddef> #include <iterator> @@ -35,9 +34,8 @@ namespace llvm { class Value; class User; class Use; - -/// Tag - generic tag type for (at least 32 bit) pointers -enum Tag { noTag, tagOne, tagTwo, tagThree }; +template<typename> +struct simplify_type; // Use** is only 4-byte aligned. template<> @@ -67,17 +65,19 @@ private: Use(const Use &U); /// Destructor - Only for zap() - inline ~Use() { + ~Use() { if (Val) removeFromList(); } - /// Default ctor - This leaves the Use completely uninitialized. The only - /// thing that is valid to do with this use is to call the "init" method. - inline Use() {} - enum PrevPtrTag { zeroDigitTag = noTag - , oneDigitTag = tagOne - , stopTag = tagTwo - , fullStopTag = tagThree }; + enum PrevPtrTag { zeroDigitTag + , oneDigitTag + , stopTag + , fullStopTag }; + + /// Constructor + Use(PrevPtrTag tag) : Val(0) { + Prev.setInt(tag); + } public: /// Normally Use will just implicitly convert to a Value* that it holds. @@ -112,11 +112,9 @@ public: /// a User changes. static void zap(Use *Start, const Use *Stop, bool del = false); - /// getPrefix - Return deletable pointer if appropriate - Use *getPrefix(); private: const Use* getImpliedUser() const; - static Use *initTags(Use *Start, Use *Stop, ptrdiff_t Done = 0); + static Use *initTags(Use *Start, Use *Stop); Value *Val; Use *Next; @@ -210,6 +208,15 @@ public: unsigned getOperandNo() const; }; +//===----------------------------------------------------------------------===// +// AugmentedUse layout struct +//===----------------------------------------------------------------------===// + +struct AugmentedUse : public Use { + PointerIntPair<User*, 1, unsigned> ref; + AugmentedUse(); // not implemented +}; + } // End llvm namespace #endif diff --git a/include/llvm/User.h b/include/llvm/User.h index f8277952ee..1363495f7c 100644 --- a/include/llvm/User.h +++ b/include/llvm/User.h @@ -29,20 +29,6 @@ namespace llvm { template <class> struct OperandTraits; -class User; - -/// OperandTraits<User> - specialization to User -template <> -struct OperandTraits<User> { - static inline Use *op_begin(User*); - static inline Use *op_end(User*); - static inline unsigned operands(const User*); - template <class U> - struct Layout { - typedef U overlay; - }; -}; - class User : public Value { User(const User &); // Do not implement void *operator new(size_t); // Do not implement @@ -61,21 +47,18 @@ protected: unsigned NumOperands; void *operator new(size_t s, unsigned Us); - void *operator new(size_t s, unsigned Us, bool Prefix); User(const Type *ty, unsigned vty, Use *OpList, unsigned NumOps) : Value(ty, vty), OperandList(OpList), NumOperands(NumOps) {} Use *allocHungoffUses(unsigned) const; - void dropHungoffUses(Use *U) { - if (OperandList == U) { - OperandList = 0; - NumOperands = 0; - } - Use::zap(U, U->getImpliedUser(), true); + void dropHungoffUses() { + Use::zap(OperandList, OperandList + NumOperands, true); + OperandList = 0; + // Reset NumOperands so User::operator delete() does the right thing. + NumOperands = 0; } public: ~User() { - if ((intptr_t(OperandList) & 1) == 0) - Use::zap(OperandList, OperandList + NumOperands); + Use::zap(OperandList, OperandList + NumOperands); } /// operator delete - free memory allocated for User and Use objects void operator delete(void *Usr); @@ -158,18 +141,6 @@ public: } }; -inline Use *OperandTraits<User>::op_begin(User *U) { - return U->op_begin(); -} - -inline Use *OperandTraits<User>::op_end(User *U) { - return U->op_end(); -} - -inline unsigned OperandTraits<User>::operands(const User *U) { - return U->getNumOperands(); -} - template<> struct simplify_type<User::op_iterator> { typedef Value* SimpleType; diff --git a/include/llvm/Value.h b/include/llvm/Value.h index 8dc4105b9e..130e2735f5 100644 --- a/include/llvm/Value.h +++ b/include/llvm/Value.h @@ -252,6 +252,12 @@ public: return SubclassOptionalData; } + /// clearSubclassOptionalData - Clear the optional flags contained in + /// this value. + void clearSubclassOptionalData() { + SubclassOptionalData = 0; + } + /// hasSameSubclassOptionalData - Test whether the optional flags contained /// in this value are equal to the optional flags in the given value. bool hasSameSubclassOptionalData(const Value *V) const { @@ -285,16 +291,6 @@ public: return const_cast<Value*>(this)->stripPointerCasts(); } - /// getUnderlyingObject - This method strips off any GEP address adjustments - /// and pointer casts from the specified value, returning the original object - /// being addressed. Note that the returned value has pointer type if the - /// specified value does. If the MaxLookup value is non-zero, it limits the - /// number of instructions to be stripped off. - Value *getUnderlyingObject(unsigned MaxLookup = 6); - const Value *getUnderlyingObject(unsigned MaxLookup = 6) const { - return const_cast<Value*>(this)->getUnderlyingObject(MaxLookup); - } - /// isDereferenceablePointer - Test if this value is always a pointer to /// allocated and suitably aligned memory for a simple load or store. bool isDereferenceablePointer() const; diff --git a/include/llvm/ValueSymbolTable.h b/include/llvm/ValueSymbolTable.h index 35fc97b2d3..1738cc4a7a 100644 --- a/include/llvm/ValueSymbolTable.h +++ b/include/llvm/ValueSymbolTable.h @@ -16,7 +16,7 @@ #include "llvm/Value.h" #include "llvm/ADT/StringMap.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { template<typename ValueSubClass, typename ItemParentClass> |