diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-05-27 18:44:32 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-05-27 18:44:32 +0000 |
commit | 5a5ac124e1efaf208671f01c46edb15f29ed2a0b (patch) | |
tree | a6140557876943cdd800ee997c9317283394b22c /include/llvm | |
parent | f03b5bed27d0d2eafd68562ce14f8b5e3f1f0801 (diff) | |
download | src-5a5ac124e1efaf208671f01c46edb15f29ed2a0b.tar.gz src-5a5ac124e1efaf208671f01c46edb15f29ed2a0b.zip |
Vendor import of llvm trunk r238337:vendor/llvm/llvm-trunk-r238337
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=283625
svn path=/vendor/llvm/llvm-trunk-r238337/; revision=283626; tag=vendor/llvm/llvm-trunk-r238337
Diffstat (limited to 'include/llvm')
497 files changed, 27346 insertions, 13474 deletions
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 26aae773624c..958e3fdaea14 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -282,12 +282,6 @@ public: /// into FoldingSets. void Profile(FoldingSetNodeID &NID) 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. - static APFloat ReadVal(Deserializer &D); - /// \name Arithmetic /// @{ @@ -349,7 +343,7 @@ public: /// copied from some other APFloat. static APFloat copySign(APFloat Value, const APFloat &Sign) { Value.copySign(Sign); - return std::move(Value); + return Value; } /// @} @@ -376,7 +370,7 @@ public: /// The definition of equality is not straightforward for floating point, so /// we won't use operator==. Use one of the following, or write whatever it /// is you really mean. - bool operator==(const APFloat &) const LLVM_DELETED_FUNCTION; + bool operator==(const APFloat &) const = delete; /// IEEE comparison with another floating point number (NaNs compare /// unordered, 0==-0). diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 025397d9ce45..36d8159d21ba 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -25,9 +25,7 @@ #include <string> namespace llvm { -class Deserializer; class FoldingSetNodeID; -class Serializer; class StringRef; class hash_code; class raw_ostream; @@ -409,6 +407,13 @@ public: : getZExtValue(); } + /// \brief Check if the APInt consists of a repeated bit pattern. + /// + /// e.g. 0x01010101 satisfies isSplat(8). + /// \param SplatSizeInBits The size of the pattern in bits. Must divide bit + /// width without remainder. + bool isSplat(unsigned SplatSizeInBits) const; + /// @} /// \name Value Generators /// @{ @@ -1356,7 +1361,7 @@ public: /// \brief Count the number of leading one bits. /// - /// This function is an APInt version of the countLeadingOnes_{32,64} + /// This function is an APInt version of the countLeadingOnes /// functions in MathExtras.h. It counts the number of ones from the most /// significant bit to the first zero bit. /// @@ -1372,7 +1377,7 @@ public: /// \brief Count the number of trailing zero bits. /// - /// This function is an APInt version of the countTrailingZeros_{32,64} + /// This function is an APInt version of the countTrailingZeros /// functions in MathExtras.h. It counts the number of zeros from the least /// significant bit to the first set bit. /// @@ -1382,7 +1387,7 @@ public: /// \brief Count the number of trailing one bits. /// - /// This function is an APInt version of the countTrailingOnes_{32,64} + /// This function is an APInt version of the countTrailingOnes /// functions in MathExtras.h. It counts the number of ones from the least /// significant bit to the first zero bit. /// @@ -1390,19 +1395,19 @@ public: /// of ones from the least significant bit to the first zero bit. unsigned countTrailingOnes() const { if (isSingleWord()) - return CountTrailingOnes_64(VAL); + return llvm::countTrailingOnes(VAL); return countTrailingOnesSlowCase(); } /// \brief Count the number of bits set. /// - /// This function is an APInt version of the countPopulation_{32,64} functions + /// This function is an APInt version of the countPopulation functions /// in MathExtras.h. It counts the number of 1 bits in the APInt value. /// /// \returns 0 if the value is zero, otherwise returns the number of set bits. unsigned countPopulation() const { if (isSingleWord()) - return CountPopulation_64(VAL); + return llvm::countPopulation(VAL); return countPopulationSlowCase(); } diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index a6693f7992cd..91ccda22f2f0 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -62,6 +62,12 @@ public: } using APInt::toString; + /// \brief Get the correctly-extended \c int64_t value. + int64_t getExtValue() const { + assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); + return isSigned() ? getSExtValue() : getZExtValue(); + } + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const { return APSInt(APInt::trunc(width), IsUnsigned); } @@ -133,14 +139,27 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return eq(RHS); } - inline bool operator==(int64_t RHS) const { - return isSameValue(*this, APSInt(APInt(64, RHS), true)); - } inline bool operator!=(const APSInt& RHS) const { return !((*this) == RHS); } - inline bool operator!=(int64_t RHS) const { - return !((*this) == RHS); + + bool operator==(int64_t RHS) const { + return compareValues(*this, get(RHS)) == 0; + } + bool operator!=(int64_t RHS) const { + return compareValues(*this, get(RHS)) != 0; + } + bool operator<=(int64_t RHS) const { + return compareValues(*this, get(RHS)) <= 0; + } + bool operator>=(int64_t RHS) const { + return compareValues(*this, get(RHS)) >= 0; + } + bool operator<(int64_t RHS) const { + return compareValues(*this, get(RHS)) < 0; + } + bool operator>(int64_t RHS) const { + return compareValues(*this, get(RHS)) > 0; } // The remaining operators just wrap the logic of APInt, but retain the @@ -260,37 +279,49 @@ public: /// \brief Determine if two APSInts have the same value, zero- or /// sign-extending as needed. static bool isSameValue(const APSInt &I1, const APSInt &I2) { + return !compareValues(I1, I2); + } + + /// \brief Compare underlying values of two numbers. + static int compareValues(const APSInt &I1, const APSInt &I2) { if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) - return I1 == I2; + return I1 == I2 ? 0 : I1 > I2 ? 1 : -1; // Check for a bit-width mismatch. if (I1.getBitWidth() > I2.getBitWidth()) - return isSameValue(I1, I2.extend(I1.getBitWidth())); + return compareValues(I1, I2.extend(I1.getBitWidth())); else if (I2.getBitWidth() > I1.getBitWidth()) - return isSameValue(I1.extend(I2.getBitWidth()), I2); - - assert(I1.isSigned() != I2.isSigned()); + return compareValues(I1.extend(I2.getBitWidth()), I2); // We have a signedness mismatch. Check for negative values and do an - // unsigned compare if signs match. - if ((I1.isSigned() && I1.isNegative()) || - (!I1.isSigned() && I2.isNegative())) - return false; + // unsigned compare if both are positive. + if (I1.isSigned()) { + assert(!I2.isSigned() && "Expected signed mismatch"); + if (I1.isNegative()) + return -1; + } else { + assert(I2.isSigned() && "Expected signed mismatch"); + if (I2.isNegative()) + return 1; + } - return I1.eq(I2); + return I1.eq(I2) ? 0 : I1.ugt(I2) ? 1 : -1; } + static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); } + static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); } + /// Profile - Used to insert APSInt objects, or objects that contain APSInt /// objects, into FoldingSets. void Profile(FoldingSetNodeID& ID) const; }; -inline bool operator==(int64_t V1, const APSInt& V2) { - return V2 == V1; -} -inline bool operator!=(int64_t V1, const APSInt& V2) { - return V2 != V1; -} +inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; } +inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; } +inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; } +inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; } +inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; } +inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; } inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { I.print(OS, I.isSigned()); diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index 8c14a423c8f5..1b2bdffc8335 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -11,7 +11,6 @@ #define LLVM_ADT_ARRAYREF_H #include "llvm/ADT/None.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include <vector> @@ -44,19 +43,6 @@ namespace llvm { /// The number of elements. size_type Length; - /// \brief A dummy "optional" type that is only created by implicit - /// conversion from a reference to T. - /// - /// This type must *only* be used in a function argument or as a copy of - /// a function argument, as otherwise it will hold a pointer to a temporary - /// past that temporaries' lifetime. - struct TRefOrNothing { - const T *TPtr; - - TRefOrNothing() : TPtr(nullptr) {} - TRefOrNothing(const T &TRef) : TPtr(&TRef) {} - }; - public: /// @name Constructors /// @{ @@ -97,12 +83,10 @@ namespace llvm { /*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N]) : Data(Arr), Length(N) {} -#if LLVM_HAS_INITIALIZER_LISTS /// Construct an ArrayRef from a std::initializer_list. /*implicit*/ ArrayRef(const std::initializer_list<T> &Vec) : Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()), Length(Vec.size()) {} -#endif /// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to /// ensure that only ArrayRefs of pointers can be converted. @@ -112,6 +96,25 @@ namespace llvm { std::is_convertible<U *const *, T const *>::value>::type* = 0) : Data(A.data()), Length(A.size()) {} + /// Construct an ArrayRef<const T*> from a SmallVector<T*>. This is + /// templated in order to avoid instantiating SmallVectorTemplateCommon<T> + /// whenever we copy-construct an ArrayRef. + template<typename U, typename DummyT> + /*implicit*/ ArrayRef(const SmallVectorTemplateCommon<U*, DummyT> &Vec, + typename std::enable_if< + std::is_convertible<U *const *, + T const *>::value>::type* = 0) + : Data(Vec.data()), Length(Vec.size()) { + } + + /// Construct an ArrayRef<const T*> from std::vector<T*>. This uses SFINAE + /// to ensure that only vectors of pointers can be converted. + template<typename U, typename A> + ArrayRef(const std::vector<U *, A> &Vec, + typename std::enable_if< + std::is_convertible<U *const *, T const *>::value>::type* = 0) + : Data(Vec.data()), Length(Vec.size()) {} + /// @} /// @name Simple Operations /// @{ @@ -153,13 +156,9 @@ namespace llvm { bool equals(ArrayRef RHS) const { if (Length != RHS.Length) return false; - // Don't use std::equal(), since it asserts in MSVC on nullptr iterators. - for (auto L = begin(), LE = end(), R = RHS.begin(); L != LE; ++L, ++R) - // Match std::equal() in using == (instead of !=) to minimize API - // requirements of ArrayRef'ed types. - if (!(*L == *R)) - return false; - return true; + if (Length == 0) + return true; + return std::equal(begin(), end(), RHS.begin()); } /// slice(n) - Chop off the first N elements of the array. @@ -204,47 +203,6 @@ namespace llvm { } /// @} - /// @{ - /// @name Convenience methods - - /// @brief Predicate for testing that the array equals the exact sequence of - /// arguments. - /// - /// Will return false if the size is not equal to the exact number of - /// arguments given or if the array elements don't equal the argument - /// elements in order. Currently supports up to 16 arguments, but can - /// easily be extended. - bool equals(TRefOrNothing Arg0 = TRefOrNothing(), - TRefOrNothing Arg1 = TRefOrNothing(), - TRefOrNothing Arg2 = TRefOrNothing(), - TRefOrNothing Arg3 = TRefOrNothing(), - TRefOrNothing Arg4 = TRefOrNothing(), - TRefOrNothing Arg5 = TRefOrNothing(), - TRefOrNothing Arg6 = TRefOrNothing(), - TRefOrNothing Arg7 = TRefOrNothing(), - TRefOrNothing Arg8 = TRefOrNothing(), - TRefOrNothing Arg9 = TRefOrNothing(), - TRefOrNothing Arg10 = TRefOrNothing(), - TRefOrNothing Arg11 = TRefOrNothing(), - TRefOrNothing Arg12 = TRefOrNothing(), - TRefOrNothing Arg13 = TRefOrNothing(), - TRefOrNothing Arg14 = TRefOrNothing(), - TRefOrNothing Arg15 = TRefOrNothing()) { - TRefOrNothing Args[] = {Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, - Arg6, Arg7, Arg8, Arg9, Arg10, Arg11, - Arg12, Arg13, Arg14, Arg15}; - if (size() > array_lengthof(Args)) - return false; - - for (unsigned i = 0, e = size(); i != e; ++i) - if (Args[i].TPtr == nullptr || (*this)[i] != *Args[i].TPtr) - return false; - - // Either the size is exactly as many args, or the next arg must be null. - return size() == array_lengthof(Args) || Args[size()].TPtr == nullptr; - } - - /// @} }; /// MutableArrayRef - Represent a mutable reference to an array (0 or more diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index a40f694485bf..f58dd7356c7d 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -29,6 +29,9 @@ class BitVector { enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT }; + static_assert(BITWORD_SIZE == 64 || BITWORD_SIZE == 32, + "Unsupported word size"); + BitWord *Bits; // Actual bits. unsigned Size; // Size of bitvector in bits. unsigned Capacity; // Size of allocated memory in BitWord. @@ -50,7 +53,7 @@ public: BitPos = Idx % BITWORD_SIZE; } - ~reference() {} + reference(const reference&) = default; reference &operator=(reference t) { *this = bool(t); @@ -118,12 +121,7 @@ public: size_type count() const { unsigned NumBits = 0; for (unsigned i = 0; i < NumBitWords(size()); ++i) - if (sizeof(BitWord) == 4) - NumBits += CountPopulation_32((uint32_t)Bits[i]); - else if (sizeof(BitWord) == 8) - NumBits += CountPopulation_64(Bits[i]); - else - llvm_unreachable("Unsupported!"); + NumBits += countPopulation(Bits[i]); return NumBits; } @@ -157,13 +155,8 @@ public: /// of the bits are set. int find_first() const { for (unsigned i = 0; i < NumBitWords(size()); ++i) - if (Bits[i] != 0) { - if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]); - if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - llvm_unreachable("Unsupported!"); - } + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); return -1; } @@ -180,23 +173,13 @@ public: // Mask off previous bits. Copy &= ~0UL << BitPos; - if (Copy != 0) { - if (sizeof(BitWord) == 4) - return WordPos * BITWORD_SIZE + countTrailingZeros((uint32_t)Copy); - if (sizeof(BitWord) == 8) - return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); - llvm_unreachable("Unsupported!"); - } + if (Copy != 0) + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); // Check subsequent words. for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i) - if (Bits[i] != 0) { - if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]); - if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - llvm_unreachable("Unsupported!"); - } + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); return -1; } @@ -559,7 +542,7 @@ private: template<bool AddBits, bool InvertMask> void applyMask(const uint32_t *Mask, unsigned MaskWords) { - assert(BITWORD_SIZE % 32 == 0 && "Unsupported BitWord size."); + static_assert(BITWORD_SIZE % 32 == 0, "Unsupported BitWord size."); MaskWords = std::min(MaskWords, (size() + 31) / 32); const unsigned Scale = BITWORD_SIZE / 32; unsigned i; diff --git a/include/llvm/ADT/DeltaAlgorithm.h b/include/llvm/ADT/DeltaAlgorithm.h index 4d07e044781f..21bc1e80c9d8 100644 --- a/include/llvm/ADT/DeltaAlgorithm.h +++ b/include/llvm/ADT/DeltaAlgorithm.h @@ -77,6 +77,8 @@ protected: /// ExecuteOneTest - Execute a single test predicate on the change set \p S. virtual bool ExecuteOneTest(const changeset_ty &S) = 0; + DeltaAlgorithm& operator=(const DeltaAlgorithm&) = default; + public: virtual ~DeltaAlgorithm(); diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 050f8ac150dd..27f73157a29f 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -15,6 +15,7 @@ #define LLVM_ADT_DENSEMAP_H #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/EpochTracker.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MathExtras.h" @@ -50,7 +51,7 @@ class DenseMapIterator; template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, typename BucketT> -class DenseMapBase { +class DenseMapBase : public DebugEpochBase { public: typedef unsigned size_type; typedef KeyT key_type; @@ -62,16 +63,17 @@ public: const_iterator; inline iterator begin() { // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets(). - return empty() ? end() : iterator(getBuckets(), getBucketsEnd()); + return empty() ? end() : iterator(getBuckets(), getBucketsEnd(), *this); } inline iterator end() { - return iterator(getBucketsEnd(), getBucketsEnd(), true); + return iterator(getBucketsEnd(), getBucketsEnd(), *this, true); } inline const_iterator begin() const { - return empty() ? end() : const_iterator(getBuckets(), getBucketsEnd()); + return empty() ? end() + : const_iterator(getBuckets(), getBucketsEnd(), *this); } inline const_iterator end() const { - return const_iterator(getBucketsEnd(), getBucketsEnd(), true); + return const_iterator(getBucketsEnd(), getBucketsEnd(), *this, true); } bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { @@ -81,11 +83,13 @@ public: /// Grow the densemap so that it has at least Size buckets. Does not shrink void resize(size_type Size) { + incrementEpoch(); if (Size > getNumBuckets()) grow(Size); } void clear() { + incrementEpoch(); if (getNumEntries() == 0 && getNumTombstones() == 0) return; // If the capacity of the array is huge, and the # elements used is small, @@ -96,16 +100,18 @@ public: } const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + unsigned NumEntries = getNumEntries(); for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) { if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { P->getSecond().~ValueT(); - decrementNumEntries(); + --NumEntries; } P->getFirst() = EmptyKey; } } - assert(getNumEntries() == 0 && "Node count imbalance!"); + assert(NumEntries == 0 && "Node count imbalance!"); + setNumEntries(0); setNumTombstones(0); } @@ -118,13 +124,13 @@ public: iterator find(const KeyT &Val) { BucketT *TheBucket; if (LookupBucketFor(Val, TheBucket)) - return iterator(TheBucket, getBucketsEnd(), true); + return iterator(TheBucket, getBucketsEnd(), *this, true); return end(); } const_iterator find(const KeyT &Val) const { const BucketT *TheBucket; if (LookupBucketFor(Val, TheBucket)) - return const_iterator(TheBucket, getBucketsEnd(), true); + return const_iterator(TheBucket, getBucketsEnd(), *this, true); return end(); } @@ -137,14 +143,14 @@ public: iterator find_as(const LookupKeyT &Val) { BucketT *TheBucket; if (LookupBucketFor(Val, TheBucket)) - return iterator(TheBucket, getBucketsEnd(), true); + return iterator(TheBucket, getBucketsEnd(), *this, true); return end(); } template<class LookupKeyT> const_iterator find_as(const LookupKeyT &Val) const { const BucketT *TheBucket; if (LookupBucketFor(Val, TheBucket)) - return const_iterator(TheBucket, getBucketsEnd(), true); + return const_iterator(TheBucket, getBucketsEnd(), *this, true); return end(); } @@ -163,12 +169,13 @@ public: std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { BucketT *TheBucket; if (LookupBucketFor(KV.first, TheBucket)) - return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), + return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), false); // Already in map. // Otherwise, insert the new element. TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket); - return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true); + return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), + true); } // Inserts key,value pair into the map if the key isn't already in the map. @@ -177,14 +184,15 @@ public: std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) { BucketT *TheBucket; if (LookupBucketFor(KV.first, TheBucket)) - return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), + return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), false); // Already in map. - + // Otherwise, insert the new element. TheBucket = InsertIntoBucket(std::move(KV.first), std::move(KV.second), TheBucket); - return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true); + return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), + true); } /// insert - Range insertion of pairs. @@ -251,7 +259,7 @@ public: const void *getPointerIntoBucketsArray() const { return getBuckets(); } protected: - DenseMapBase() {} + DenseMapBase() = default; void destroyAll() { if (getNumBuckets() == 0) // Nothing to do. @@ -264,10 +272,6 @@ protected: P->getSecond().~ValueT(); P->getFirst().~KeyT(); } - -#ifndef NDEBUG - memset((void*)getBuckets(), 0x5a, sizeof(BucketT)*getNumBuckets()); -#endif } void initEmpty() { @@ -304,12 +308,6 @@ protected: } B->getFirst().~KeyT(); } - -#ifndef NDEBUG - if (OldBucketsBegin != OldBucketsEnd) - memset((void*)OldBucketsBegin, 0x5a, - sizeof(BucketT) * (OldBucketsEnd - OldBucketsBegin)); -#endif } template <typename OtherBaseT> @@ -335,11 +333,6 @@ protected: } } - void swap(DenseMapBase& RHS) { - std::swap(getNumEntries(), RHS.getNumEntries()); - std::swap(getNumTombstones(), RHS.getNumTombstones()); - } - static unsigned getHashValue(const KeyT &Val) { return KeyInfoT::getHashValue(Val); } @@ -431,6 +424,8 @@ private: } BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) { + incrementEpoch(); + // If the load of the hash table is more than 3/4, or if fewer than 1/8 of // the buckets are empty (meaning that many are filled with tombstones), // grow the table. @@ -442,11 +437,12 @@ private: // causing infinite loops in lookup. unsigned NewNumEntries = getNumEntries() + 1; unsigned NumBuckets = getNumBuckets(); - if (NewNumEntries*4 >= NumBuckets*3) { + if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) { this->grow(NumBuckets * 2); LookupBucketFor(Key, TheBucket); NumBuckets = getNumBuckets(); - } else if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) { + } else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <= + NumBuckets/8)) { this->grow(NumBuckets); LookupBucketFor(Key, TheBucket); } @@ -492,14 +488,14 @@ private: while (1) { const BucketT *ThisBucket = BucketsPtr + BucketNo; // Found Val's bucket? If so, return it. - if (KeyInfoT::isEqual(Val, ThisBucket->getFirst())) { + if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) { FoundBucket = ThisBucket; return true; } // If we found an empty bucket, the key doesn't exist in the set. // Insert it and return the default value. - if (KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey)) { + if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) { // If we've already seen a tombstone while probing, fill it in instead // of the empty bucket we eventually probed to. FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; @@ -580,6 +576,8 @@ public: } void swap(DenseMap& RHS) { + this->incrementEpoch(); + RHS.incrementEpoch(); std::swap(Buckets, RHS.Buckets); std::swap(NumEntries, RHS.NumEntries); std::swap(NumTombstones, RHS.NumTombstones); @@ -986,9 +984,10 @@ private: template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket, bool IsConst> -class DenseMapIterator { +class DenseMapIterator : DebugEpochBase::HandleBase { typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true> ConstIterator; friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>; + friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>; public: typedef ptrdiff_t difference_type; @@ -1002,38 +1001,54 @@ private: public: DenseMapIterator() : Ptr(nullptr), End(nullptr) {} - DenseMapIterator(pointer Pos, pointer E, bool NoAdvance = false) - : Ptr(Pos), End(E) { + DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch, + bool NoAdvance = false) + : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) { + assert(isHandleInSync() && "invalid construction!"); if (!NoAdvance) AdvancePastEmptyBuckets(); } - // If IsConst is true this is a converting constructor from iterator to - // const_iterator and the default copy constructor is used. - // Otherwise this is a copy constructor for iterator. + // Converting ctor from non-const iterators to const iterators. SFINAE'd out + // for const iterator destinations so it doesn't end up as a user defined copy + // constructor. + template <bool IsConstSrc, + typename = typename std::enable_if<!IsConstSrc && IsConst>::type> DenseMapIterator( - const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false> &I) - : Ptr(I.Ptr), End(I.End) {} + const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I) + : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End) {} reference operator*() const { + assert(isHandleInSync() && "invalid iterator access!"); return *Ptr; } pointer operator->() const { + assert(isHandleInSync() && "invalid iterator access!"); return Ptr; } bool operator==(const ConstIterator &RHS) const { - return Ptr == RHS.operator->(); + assert((!Ptr || isHandleInSync()) && "handle not in sync!"); + assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!"); + assert(getEpochAddress() == RHS.getEpochAddress() && + "comparing incomparable iterators!"); + return Ptr == RHS.Ptr; } bool operator!=(const ConstIterator &RHS) const { - return Ptr != RHS.operator->(); + assert((!Ptr || isHandleInSync()) && "handle not in sync!"); + assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!"); + assert(getEpochAddress() == RHS.getEpochAddress() && + "comparing incomparable iterators!"); + return Ptr != RHS.Ptr; } inline DenseMapIterator& operator++() { // Preincrement + assert(isHandleInSync() && "invalid iterator access!"); ++Ptr; AdvancePastEmptyBuckets(); return *this; } DenseMapIterator operator++(int) { // Postincrement + assert(isHandleInSync() && "invalid iterator access!"); DenseMapIterator tmp = *this; ++*this; return tmp; } diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index 6cd9e68aea56..d79b9acacfa9 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -113,9 +113,8 @@ private: while (It != GT::child_end(Node)) { NodeType *Next = *It++; // Has our next sibling been visited? - if (Next && !this->Visited.count(Next)) { + if (Next && this->Visited.insert(Next).second) { // No, do it now. - this->Visited.insert(Next); VisitStack.push_back(std::make_pair(PointerIntTy(Next, 0), GT::child_begin(Next))); return; @@ -129,58 +128,59 @@ private: public: typedef typename super::pointer pointer; - typedef df_iterator<GraphT, SetType, ExtStorage, GT> _Self; // Provide static begin and end methods as our public "constructors" - static inline _Self begin(const GraphT& G) { - return _Self(GT::getEntryNode(G)); + static df_iterator begin(const GraphT &G) { + return df_iterator(GT::getEntryNode(G)); } - static inline _Self end(const GraphT& G) { return _Self(); } + static df_iterator end(const GraphT &G) { return df_iterator(); } // Static begin and end methods as our public ctors for external iterators - static inline _Self begin(const GraphT& G, SetType &S) { - return _Self(GT::getEntryNode(G), S); + static df_iterator begin(const GraphT &G, SetType &S) { + return df_iterator(GT::getEntryNode(G), S); } - static inline _Self end(const GraphT& G, SetType &S) { return _Self(S); } + static df_iterator end(const GraphT &G, SetType &S) { return df_iterator(S); } - inline bool operator==(const _Self& x) const { + bool operator==(const df_iterator &x) const { return VisitStack == x.VisitStack; } - inline bool operator!=(const _Self& x) const { return !operator==(x); } + bool operator!=(const df_iterator &x) const { return !(*this == x); } - inline pointer operator*() const { - return VisitStack.back().first.getPointer(); - } + pointer operator*() const { return VisitStack.back().first.getPointer(); } // This is a nonstandard operator-> that dereferences the pointer an extra // time... so that you can actually call methods ON the Node, because // the contained type is a pointer. This allows BBIt->getTerminator() f.e. // - inline NodeType *operator->() const { return operator*(); } + NodeType *operator->() const { return **this; } - inline _Self& operator++() { // Preincrement + df_iterator &operator++() { // Preincrement toNext(); return *this; } - // skips all children of the current node and traverses to next node - // - inline _Self& skipChildren() { + /// \brief Skips all children of the current node and traverses to next node + /// + /// Note: This function takes care of incrementing the iterator. If you + /// always increment and call this function, you risk walking off the end. + df_iterator &skipChildren() { VisitStack.pop_back(); if (!VisitStack.empty()) toNext(); return *this; } - inline _Self operator++(int) { // Postincrement - _Self tmp = *this; ++*this; return tmp; + df_iterator operator++(int) { // Postincrement + df_iterator tmp = *this; + ++*this; + return tmp; } // nodeVisited - return true if this iterator has already visited the // specified node. This is public, and will probably be used to iterate over // nodes that a depth first iteration did not find: ie unreachable nodes. // - inline bool nodeVisited(NodeType *Node) const { + bool nodeVisited(NodeType *Node) const { return this->Visited.count(Node) != 0; } @@ -211,7 +211,7 @@ df_iterator<T> df_end(const T& G) { // Provide an accessor method to use them in range-based patterns. template <class T> iterator_range<df_iterator<T>> depth_first(const T& G) { - return iterator_range<df_iterator<T>>(df_begin(G), df_end(G)); + return make_range(df_begin(G), df_end(G)); } // Provide global definitions of external depth first iterators... @@ -234,8 +234,7 @@ df_ext_iterator<T, SetTy> df_ext_end(const T& G, SetTy &S) { template <class T, class SetTy> iterator_range<df_ext_iterator<T, SetTy>> depth_first_ext(const T& G, SetTy &S) { - return iterator_range<df_ext_iterator<T, SetTy>>(df_ext_begin(G, S), - df_ext_end(G, S)); + return make_range(df_ext_begin(G, S), df_ext_end(G, S)); } @@ -261,7 +260,7 @@ idf_iterator<T> idf_end(const T& G){ // Provide an accessor method to use them in range-based patterns. template <class T> iterator_range<idf_iterator<T>> inverse_depth_first(const T& G) { - return iterator_range<idf_iterator<T>>(idf_begin(G), idf_end(G)); + return make_range(idf_begin(G), idf_end(G)); } // Provide global definitions of external inverse depth first iterators... @@ -286,8 +285,7 @@ idf_ext_iterator<T, SetTy> idf_ext_end(const T& G, SetTy &S) { template <class T, class SetTy> iterator_range<idf_ext_iterator<T, SetTy>> inverse_depth_first_ext(const T& G, SetTy &S) { - return iterator_range<idf_ext_iterator<T, SetTy>>(idf_ext_begin(G, S), - idf_ext_end(G, S)); + return make_range(idf_ext_begin(G, S), idf_ext_end(G, S)); } } // End llvm namespace diff --git a/include/llvm/ADT/EpochTracker.h b/include/llvm/ADT/EpochTracker.h new file mode 100644 index 000000000000..582d58179d13 --- /dev/null +++ b/include/llvm/ADT/EpochTracker.h @@ -0,0 +1,99 @@ +//===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- 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 DebugEpochBase and DebugEpochBase::HandleBase classes. +// These can be used to write iterators that are fail-fast when LLVM is built +// with asserts enabled. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_EPOCH_TRACKER_H +#define LLVM_ADT_EPOCH_TRACKER_H + +#include "llvm/Config/llvm-config.h" + +#include <cstdint> + +namespace llvm { + +#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS + +class DebugEpochBase { +public: + void incrementEpoch() {} + + class HandleBase { + public: + HandleBase() = default; + explicit HandleBase(const DebugEpochBase *) {} + bool isHandleInSync() const { return true; } + const void *getEpochAddress() const { return nullptr; } + }; +}; + +#else + +/// \brief A base class for data structure classes wishing to make iterators +/// ("handles") pointing into themselves fail-fast. When building without +/// asserts, this class is empty and does nothing. +/// +/// DebugEpochBase does not by itself track handles pointing into itself. The +/// expectation is that routines touching the handles will poll on +/// isHandleInSync at appropriate points to assert that the handle they're using +/// is still valid. +/// +class DebugEpochBase { + uint64_t Epoch; + +public: + DebugEpochBase() : Epoch(0) {} + + /// \brief Calling incrementEpoch invalidates all handles pointing into the + /// calling instance. + void incrementEpoch() { ++Epoch; } + + /// \brief The destructor calls incrementEpoch to make use-after-free bugs + /// more likely to crash deterministically. + ~DebugEpochBase() { incrementEpoch(); } + + /// \brief A base class for iterator classes ("handles") that wish to poll for + /// iterator invalidating modifications in the underlying data structure. + /// When LLVM is built without asserts, this class is empty and does nothing. + /// + /// HandleBase does not track the parent data structure by itself. It expects + /// the routines modifying the data structure to call incrementEpoch when they + /// make an iterator-invalidating modification. + /// + class HandleBase { + const uint64_t *EpochAddress; + uint64_t EpochAtCreation; + + public: + HandleBase() : EpochAddress(nullptr), EpochAtCreation(UINT64_MAX) {} + + explicit HandleBase(const DebugEpochBase *Parent) + : EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {} + + /// \brief Returns true if the DebugEpochBase this Handle is linked to has + /// not called incrementEpoch on itself since the creation of this + /// HandleBase instance. + bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; } + + /// \brief Returns a pointer to the epoch word stored in the data structure + /// this handle points into. Can be used to check if two iterators point + /// into the same data structure. + const void *getEpochAddress() const { return EpochAddress; } + }; +}; + +#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS + +} // namespace llvm + +#endif diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h index e0396c7e7914..d6a26f88e67d 100644 --- a/include/llvm/ADT/EquivalenceClasses.h +++ b/include/llvm/ADT/EquivalenceClasses.h @@ -17,6 +17,7 @@ #include "llvm/Support/DataTypes.h" #include <cassert> +#include <cstddef> #include <set> namespace llvm { @@ -254,7 +255,7 @@ public: assert(Node != nullptr && "Dereferencing end()!"); return Node->getData(); } - reference operator->() const { return operator*(); } + pointer operator->() const { return &operator*(); } member_iterator &operator++() { assert(Node != nullptr && "++'d off the end of the list!"); diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index 14c5933d388a..52d10c1c1245 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -18,13 +18,11 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" namespace llvm { - class APFloat; - class APInt; - /// This folding set used for two purposes: /// 1. Given information about a node we want to create, look up the unique /// instance of the node in the set. If the node already exists, return @@ -109,6 +107,8 @@ class FoldingSetNodeID; /// back to the bucket to facilitate node removal. /// class FoldingSetImpl { + virtual void anchor(); // Out of line virtual method. + protected: /// Buckets - Array of bucket chains. /// @@ -122,10 +122,11 @@ protected: /// is greater than twice the number of buckets. unsigned NumNodes; -public: + ~FoldingSetImpl(); + explicit FoldingSetImpl(unsigned Log2InitSize = 6); - virtual ~FoldingSetImpl(); +public: //===--------------------------------------------------------------------===// /// Node - This class is used to maintain the singly linked bucket list in /// a folding set. @@ -392,7 +393,7 @@ DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(T &X, /// implementation of the folding set to the node class T. T must be a /// subclass of FoldingSetNode and implement a Profile function. /// -template<class T> class FoldingSet : public FoldingSetImpl { +template <class T> class FoldingSet final : public FoldingSetImpl { private: /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a /// way to convert nodes into a unique specifier. @@ -462,7 +463,7 @@ public: /// function with signature /// void Profile(llvm::FoldingSetNodeID &, Ctx); template <class T, class Ctx> -class ContextualFoldingSet : public FoldingSetImpl { +class ContextualFoldingSet final : public FoldingSetImpl { // Unfortunately, this can't derive from FoldingSet<T> because the // construction vtable for FoldingSet<T> requires // FoldingSet<T>::GetNodeProfile to be instantiated, which in turn @@ -532,46 +533,6 @@ public: }; //===----------------------------------------------------------------------===// -/// FoldingSetVectorIterator - This implements an iterator for -/// FoldingSetVector. It is only necessary because FoldingSetIterator provides -/// a value_type of T, while the vector in FoldingSetVector exposes -/// a value_type of T*. Fortunately, FoldingSetIterator doesn't expose very -/// much besides operator* and operator->, so we just wrap the inner vector -/// iterator and perform the extra dereference. -template <class T, class VectorIteratorT> -class FoldingSetVectorIterator { - // Provide a typedef to workaround the lack of correct injected class name - // support in older GCCs. - typedef FoldingSetVectorIterator<T, VectorIteratorT> SelfT; - - VectorIteratorT Iterator; - -public: - FoldingSetVectorIterator(VectorIteratorT I) : Iterator(I) {} - - bool operator==(const SelfT &RHS) const { - return Iterator == RHS.Iterator; - } - bool operator!=(const SelfT &RHS) const { - return Iterator != RHS.Iterator; - } - - T &operator*() const { return **Iterator; } - - T *operator->() const { return *Iterator; } - - inline SelfT &operator++() { - ++Iterator; - return *this; - } - SelfT operator++(int) { - SelfT tmp = *this; - ++*this; - return tmp; - } -}; - -//===----------------------------------------------------------------------===// /// FoldingSetVector - This template class combines a FoldingSet and a vector /// to provide the interface of FoldingSet but with deterministic iteration /// order based on the insertion order. T must be a subclass of FoldingSetNode @@ -586,12 +547,11 @@ public: : Set(Log2InitSize) { } - typedef FoldingSetVectorIterator<T, typename VectorT::iterator> iterator; + typedef pointee_iterator<typename VectorT::iterator> iterator; iterator begin() { return Vector.begin(); } iterator end() { return Vector.end(); } - typedef FoldingSetVectorIterator<const T, typename VectorT::const_iterator> - const_iterator; + typedef pointee_iterator<typename VectorT::const_iterator> const_iterator; const_iterator begin() const { return Vector.begin(); } const_iterator end() const { return Vector.end(); } @@ -735,31 +695,9 @@ template <typename T> class FoldingSetNodeWrapper : public FoldingSetNode { T data; public: - explicit FoldingSetNodeWrapper(const T &x) : data(x) {} - virtual ~FoldingSetNodeWrapper() {} - - template<typename A1> - explicit FoldingSetNodeWrapper(const A1 &a1) - : data(a1) {} - - template <typename A1, typename A2> - explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2) - : data(a1,a2) {} - - template <typename A1, typename A2, typename A3> - explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3) - : data(a1,a2,a3) {} - - template <typename A1, typename A2, typename A3, typename A4> - explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3, - const A4 &a4) - : data(a1,a2,a3,a4) {} - - template <typename A1, typename A2, typename A3, typename A4, typename A5> - explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3, - const A4 &a4, const A5 &a5) - : data(a1,a2,a3,a4,a5) {} - + template <typename... Ts> + explicit FoldingSetNodeWrapper(Ts &&... Args) + : data(std::forward<Ts>(Args)...) {} void Profile(FoldingSetNodeID &ID) { FoldingSetTrait<T>::Profile(data, ID); } diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index abf02b8cc9d5..77e6d77b1b8e 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -55,12 +55,6 @@ #include <iterator> #include <utility> -// Allow detecting C++11 feature availability when building with Clang without -// breaking other compilers. -#ifndef __has_feature -# define __has_feature(x) 0 -#endif - namespace llvm { /// \brief An opaque object representing a hash code. @@ -81,7 +75,7 @@ class hash_code { public: /// \brief Default construct a hash_code. /// Note that this leaves the value uninitialized. - hash_code() {} + hash_code() = default; /// \brief Form a hash code directly from a numerical value. hash_code(size_t value) : value(value) {} @@ -553,8 +547,6 @@ public: return buffer_ptr; } -#if defined(__has_feature) && __has_feature(__cxx_variadic_templates__) - /// \brief Recursive, variadic combining method. /// /// This function recurses through each argument, combining that argument @@ -568,53 +560,6 @@ public: return combine(length, buffer_ptr, buffer_end, args...); } -#else - // Manually expanded recursive combining methods. See variadic above for - // documentation. - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6> - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4, const T5 &arg5, const T6 &arg6) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5, arg6); - } - template <typename T1, typename T2, typename T3, typename T4, typename T5> - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4, const T5 &arg5) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5); - } - template <typename T1, typename T2, typename T3, typename T4> - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4); - } - template <typename T1, typename T2, typename T3> - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2, const T3 &arg3) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2, arg3); - } - template <typename T1, typename T2> - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2); - } - template <typename T1> - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end); - } - -#endif - /// \brief Base case for recursive, variadic combining. /// /// The base case when combining arguments recursively is reached when all @@ -643,9 +588,6 @@ public: } // namespace detail } // namespace hashing - -#if __has_feature(__cxx_variadic_templates__) - /// \brief Combine values into a single hash_code. /// /// This routine accepts a varying number of arguments of any type. It will @@ -663,52 +605,6 @@ template <typename ...Ts> hash_code hash_combine(const Ts &...args) { return helper.combine(0, helper.buffer, helper.buffer + 64, args...); } -#else - -// What follows are manually exploded overloads for each argument width. See -// the above variadic definition for documentation and specification. - -template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6> -hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4, const T5 &arg5, const T6 &arg6) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, - arg1, arg2, arg3, arg4, arg5, arg6); -} -template <typename T1, typename T2, typename T3, typename T4, typename T5> -hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4, const T5 &arg5) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, - arg1, arg2, arg3, arg4, arg5); -} -template <typename T1, typename T2, typename T3, typename T4> -hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, - arg1, arg2, arg3, arg4); -} -template <typename T1, typename T2, typename T3> -hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2, arg3); -} -template <typename T1, typename T2> -hash_code hash_combine(const T1 &arg1, const T2 &arg2) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2); -} -template <typename T1> -hash_code hash_combine(const T1 &arg1) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, arg1); -} - -#endif - - // Implementation details for implementations of hash_value overloads provided // here. namespace hashing { diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h index 7f0c239423bd..748d3e4bf9ff 100644 --- a/include/llvm/ADT/ImmutableList.h +++ b/include/llvm/ADT/ImmutableList.h @@ -33,8 +33,8 @@ class ImmutableListImpl : public FoldingSetNode { friend class ImmutableListFactory<T>; - void operator=(const ImmutableListImpl&) LLVM_DELETED_FUNCTION; - ImmutableListImpl(const ImmutableListImpl&) LLVM_DELETED_FUNCTION; + void operator=(const ImmutableListImpl&) = delete; + ImmutableListImpl(const ImmutableListImpl&) = delete; public: const T& getHead() const { return Head; } diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h index 11f281be3d23..438dec2333c5 100644 --- a/include/llvm/ADT/ImmutableMap.h +++ b/include/llvm/ADT/ImmutableMap.h @@ -122,8 +122,8 @@ public: } private: - Factory(const Factory& RHS) LLVM_DELETED_FUNCTION; - void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION; + Factory(const Factory& RHS) = delete; + void operator=(const Factory& RHS) = delete; }; bool contains(key_type_ref K) const { @@ -203,33 +203,14 @@ public: // Iterators. //===--------------------------------------------------===// - class iterator { - typename TreeTy::iterator itr; - - iterator() {} - iterator(TreeTy* t) : itr(t) {} + class iterator : public ImutAVLValueIterator<ImmutableMap> { + iterator() = default; + explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {} friend class ImmutableMap; public: - typedef ptrdiff_t difference_type; - typedef typename ImmutableMap<KeyT,ValT,ValInfo>::value_type value_type; - typedef typename ImmutableMap<KeyT,ValT,ValInfo>::value_type_ref reference; - typedef typename iterator::value_type *pointer; - typedef std::bidirectional_iterator_tag iterator_category; - - typename iterator::reference operator*() const { return itr->getValue(); } - typename iterator::pointer operator->() const { return &itr->getValue(); } - - key_type_ref getKey() const { return itr->getValue().first; } - data_type_ref getData() const { return itr->getValue().second; } - - iterator& operator++() { ++itr; return *this; } - iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } - iterator& operator--() { --itr; return *this; } - iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } - - bool operator==(const iterator& RHS) const { return RHS.itr == itr; } - bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } + key_type_ref getKey() const { return (*this)->first; } + data_type_ref getData() const { return (*this)->second; } }; iterator begin() const { return iterator(Root); } @@ -376,30 +357,17 @@ public: //===--------------------------------------------------===// // Iterators. //===--------------------------------------------------===// - - class iterator { - typename TreeTy::iterator itr; - - iterator() {} - iterator(TreeTy* t) : itr(t) {} + + class iterator : public ImutAVLValueIterator<ImmutableMapRef> { + iterator() = default; + explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {} friend class ImmutableMapRef; - + public: - value_type_ref operator*() const { return itr->getValue(); } - value_type* operator->() const { return &itr->getValue(); } - - key_type_ref getKey() const { return itr->getValue().first; } - data_type_ref getData() const { return itr->getValue().second; } - - - iterator& operator++() { ++itr; return *this; } - iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } - iterator& operator--() { --itr; return *this; } - iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } - bool operator==(const iterator& RHS) const { return RHS.itr == itr; } - bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } + key_type_ref getKey() const { return (*this)->first; } + data_type_ref getData() const { return (*this)->second; } }; - + iterator begin() const { return iterator(Root); } iterator end() const { return iterator(); } diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h index 5a3d8ad21f92..87026f019fec 100644 --- a/include/llvm/ADT/ImmutableSet.h +++ b/include/llvm/ADT/ImmutableSet.h @@ -142,13 +142,13 @@ public: iterator RItr = RHS.begin(), REnd = RHS.end(); while (LItr != LEnd && RItr != REnd) { - if (*LItr == *RItr) { + if (&*LItr == &*RItr) { LItr.skipSubTree(); RItr.skipSubTree(); continue; } - if (!LItr->isElementEqual(*RItr)) + if (!LItr->isElementEqual(&*RItr)) return false; ++LItr; @@ -293,8 +293,8 @@ private: height = h; } - static inline - uint32_t computeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) { + static uint32_t computeDigest(ImutAVLTree *L, ImutAVLTree *R, + value_type_ref V) { uint32_t digest = 0; if (L) @@ -311,7 +311,7 @@ private: return digest; } - inline uint32_t computeDigest() { + uint32_t computeDigest() { // Check the lowest bit to determine if digest has actually been // pre-computed. if (hasCachedDigest()) @@ -429,9 +429,7 @@ protected: value_type_ref getValue(TreeTy* T) const { return T->value; } // Make sure the index is not the Tombstone or Entry key of the DenseMap. - static inline unsigned maskCacheIndex(unsigned I) { - return (I & ~0x02); - } + static unsigned maskCacheIndex(unsigned I) { return (I & ~0x02); } unsigned incrementHeight(TreeTy* L, TreeTy* R) const { unsigned hl = getHeight(L); @@ -444,7 +442,7 @@ protected: typename TreeTy::iterator& TE) { typename TreeTy::iterator I = T->begin(), E = T->end(); for ( ; I!=E ; ++I, ++TI) { - if (TI == TE || !I->isElementEqual(*TI)) + if (TI == TE || !I->isElementEqual(&*TI)) return false; } return true; @@ -647,24 +645,26 @@ public: //===----------------------------------------------------------------------===// template <typename ImutInfo> -class ImutAVLTreeGenericIterator { +class ImutAVLTreeGenericIterator + : public std::iterator<std::bidirectional_iterator_tag, + ImutAVLTree<ImutInfo>> { SmallVector<uintptr_t,20> stack; public: enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3, Flags=0x3 }; typedef ImutAVLTree<ImutInfo> TreeTy; - typedef ImutAVLTreeGenericIterator<ImutInfo> _Self; - inline ImutAVLTreeGenericIterator() {} - inline ImutAVLTreeGenericIterator(const TreeTy* Root) { + ImutAVLTreeGenericIterator() {} + ImutAVLTreeGenericIterator(const TreeTy *Root) { if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root)); } - TreeTy* operator*() const { + TreeTy &operator*() const { assert(!stack.empty()); - return reinterpret_cast<TreeTy*>(stack.back() & ~Flags); + return *reinterpret_cast<TreeTy *>(stack.back() & ~Flags); } + TreeTy *operator->() const { return &*this; } uintptr_t getVisitState() const { assert(!stack.empty()); @@ -695,13 +695,15 @@ public: } } - inline bool operator==(const _Self& x) const { + bool operator==(const ImutAVLTreeGenericIterator &x) const { return stack == x.stack; } - inline bool operator!=(const _Self& x) const { return !operator==(x); } + bool operator!=(const ImutAVLTreeGenericIterator &x) const { + return !(*this == x); + } - _Self& operator++() { + ImutAVLTreeGenericIterator &operator++() { assert(!stack.empty()); TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); assert(Current); @@ -727,7 +729,7 @@ public: return *this; } - _Self& operator--() { + ImutAVLTreeGenericIterator &operator--() { assert(!stack.empty()); TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); assert(Current); @@ -754,30 +756,34 @@ public: }; template <typename ImutInfo> -class ImutAVLTreeInOrderIterator { +class ImutAVLTreeInOrderIterator + : public std::iterator<std::bidirectional_iterator_tag, + ImutAVLTree<ImutInfo>> { typedef ImutAVLTreeGenericIterator<ImutInfo> InternalIteratorTy; InternalIteratorTy InternalItr; public: typedef ImutAVLTree<ImutInfo> TreeTy; - typedef ImutAVLTreeInOrderIterator<ImutInfo> _Self; ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) { - if (Root) operator++(); // Advance to first element. + if (Root) + ++*this; // Advance to first element. } ImutAVLTreeInOrderIterator() : InternalItr() {} - inline bool operator==(const _Self& x) const { + bool operator==(const ImutAVLTreeInOrderIterator &x) const { return InternalItr == x.InternalItr; } - inline bool operator!=(const _Self& x) const { return !operator==(x); } + bool operator!=(const ImutAVLTreeInOrderIterator &x) const { + return !(*this == x); + } - inline TreeTy* operator*() const { return *InternalItr; } - inline TreeTy* operator->() const { return *InternalItr; } + TreeTy &operator*() const { return *InternalItr; } + TreeTy *operator->() const { return &*InternalItr; } - inline _Self& operator++() { + ImutAVLTreeInOrderIterator &operator++() { do ++InternalItr; while (!InternalItr.atEnd() && InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); @@ -785,7 +791,7 @@ public: return *this; } - inline _Self& operator--() { + ImutAVLTreeInOrderIterator &operator--() { do --InternalItr; while (!InternalItr.atBeginning() && InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); @@ -793,7 +799,7 @@ public: return *this; } - inline void skipSubTree() { + void skipSubTree() { InternalItr.skipToParent(); while (!InternalItr.atEnd() && @@ -802,6 +808,24 @@ public: } }; +/// Generic iterator that wraps a T::TreeTy::iterator and exposes +/// iterator::getValue() on dereference. +template <typename T> +struct ImutAVLValueIterator + : iterator_adaptor_base< + ImutAVLValueIterator<T>, typename T::TreeTy::iterator, + typename std::iterator_traits< + typename T::TreeTy::iterator>::iterator_category, + const typename T::value_type> { + ImutAVLValueIterator() = default; + explicit ImutAVLValueIterator(typename T::TreeTy *Tree) + : ImutAVLValueIterator::iterator_adaptor_base(Tree) {} + + typename ImutAVLValueIterator::reference operator*() const { + return this->I->getValue(); + } +}; + //===----------------------------------------------------------------------===// // Trait classes for Profile information. //===----------------------------------------------------------------------===// @@ -814,7 +838,7 @@ struct ImutProfileInfo { typedef const T value_type; typedef const T& value_type_ref; - static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { + static void Profile(FoldingSetNodeID &ID, value_type_ref X) { FoldingSetTrait<T>::Profile(X,ID); } }; @@ -825,7 +849,7 @@ struct ImutProfileInteger { typedef const T value_type; typedef const T& value_type_ref; - static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { + static void Profile(FoldingSetNodeID &ID, value_type_ref X) { ID.AddInteger(X); } }; @@ -852,7 +876,7 @@ struct ImutProfileInfo<bool> { typedef const bool value_type; typedef const bool& value_type_ref; - static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { + static void Profile(FoldingSetNodeID &ID, value_type_ref X) { ID.AddBoolean(X); } }; @@ -865,7 +889,7 @@ struct ImutProfileInfo<T*> { typedef const T* value_type; typedef value_type value_type_ref; - static inline void Profile(FoldingSetNodeID &ID, value_type_ref X) { + static void Profile(FoldingSetNodeID &ID, value_type_ref X) { ID.AddPointer(X); } }; @@ -890,18 +914,18 @@ struct ImutContainerInfo : public ImutProfileInfo<T> { typedef bool data_type; typedef bool data_type_ref; - static inline key_type_ref KeyOfValue(value_type_ref D) { return D; } - static inline data_type_ref DataOfValue(value_type_ref) { return true; } + static key_type_ref KeyOfValue(value_type_ref D) { return D; } + static data_type_ref DataOfValue(value_type_ref) { return true; } - static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) { + static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return std::equal_to<key_type>()(LHS,RHS); } - static inline bool isLess(key_type_ref LHS, key_type_ref RHS) { + static bool isLess(key_type_ref LHS, key_type_ref RHS) { return std::less<key_type>()(LHS,RHS); } - static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; } + static bool isDataEqual(data_type_ref, data_type_ref) { return true; } }; /// ImutContainerInfo - Specialization for pointer values to treat pointers @@ -916,18 +940,14 @@ struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> { typedef bool data_type; typedef bool data_type_ref; - static inline key_type_ref KeyOfValue(value_type_ref D) { return D; } - static inline data_type_ref DataOfValue(value_type_ref) { return true; } + static key_type_ref KeyOfValue(value_type_ref D) { return D; } + static data_type_ref DataOfValue(value_type_ref) { return true; } - static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) { - return LHS == RHS; - } + static bool isEqual(key_type_ref LHS, key_type_ref RHS) { return LHS == RHS; } - static inline bool isLess(key_type_ref LHS, key_type_ref RHS) { - return LHS < RHS; - } + static bool isLess(key_type_ref LHS, key_type_ref RHS) { return LHS < RHS; } - static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; } + static bool isDataEqual(data_type_ref, data_type_ref) { return true; } }; //===----------------------------------------------------------------------===// @@ -1014,8 +1034,8 @@ public: } private: - Factory(const Factory& RHS) LLVM_DELETED_FUNCTION; - void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION; + Factory(const Factory& RHS) = delete; + void operator=(const Factory& RHS) = delete; }; friend class Factory; @@ -1059,31 +1079,7 @@ public: // Iterators. //===--------------------------------------------------===// - class iterator { - typename TreeTy::iterator itr; - - iterator() {} - iterator(TreeTy* t) : itr(t) {} - friend class ImmutableSet<ValT,ValInfo>; - - public: - typedef ptrdiff_t difference_type; - typedef typename ImmutableSet<ValT,ValInfo>::value_type value_type; - typedef typename ImmutableSet<ValT,ValInfo>::value_type_ref reference; - typedef typename iterator::value_type *pointer; - typedef std::bidirectional_iterator_tag iterator_category; - - typename iterator::reference operator*() const { return itr->getValue(); } - typename iterator::pointer operator->() const { return &(operator*()); } - - iterator& operator++() { ++itr; return *this; } - iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } - iterator& operator--() { --itr; return *this; } - iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } - - bool operator==(const iterator& RHS) const { return RHS.itr == itr; } - bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } - }; + typedef ImutAVLValueIterator<ImmutableSet> iterator; iterator begin() const { return iterator(Root); } iterator end() const { return iterator(); } @@ -1094,13 +1090,11 @@ public: unsigned getHeight() const { return Root ? Root->getHeight() : 0; } - static inline void Profile(FoldingSetNodeID& ID, const ImmutableSet& S) { + static void Profile(FoldingSetNodeID &ID, const ImmutableSet &S) { ID.AddPointer(S.Root); } - inline void Profile(FoldingSetNodeID& ID) const { - return Profile(ID,*this); - } + void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); } //===--------------------------------------------------===// // For testing. @@ -1150,7 +1144,7 @@ public: if (Root) { Root->release(); } } - static inline ImmutableSetRef getEmptySet(FactoryTy *F) { + static ImmutableSetRef getEmptySet(FactoryTy *F) { return ImmutableSetRef(0, F); } @@ -1195,21 +1189,7 @@ public: // Iterators. //===--------------------------------------------------===// - class iterator { - typename TreeTy::iterator itr; - iterator(TreeTy* t) : itr(t) {} - friend class ImmutableSetRef<ValT,ValInfo>; - public: - iterator() {} - inline value_type_ref operator*() const { return itr->getValue(); } - inline iterator& operator++() { ++itr; return *this; } - inline iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } - inline iterator& operator--() { --itr; return *this; } - inline iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } - inline bool operator==(const iterator& RHS) const { return RHS.itr == itr; } - inline bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } - inline value_type *operator->() const { return &(operator*()); } - }; + typedef ImutAVLValueIterator<ImmutableSetRef> iterator; iterator begin() const { return iterator(Root); } iterator end() const { return iterator(); } @@ -1220,13 +1200,11 @@ public: unsigned getHeight() const { return Root ? Root->getHeight() : 0; } - static inline void Profile(FoldingSetNodeID& ID, const ImmutableSetRef& S) { + static void Profile(FoldingSetNodeID &ID, const ImmutableSetRef &S) { ID.AddPointer(S.Root); } - inline void Profile(FoldingSetNodeID& ID) const { - return Profile(ID,*this); - } + void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); } //===--------------------------------------------------===// // For testing. diff --git a/include/llvm/ADT/IndexedMap.h b/include/llvm/ADT/IndexedMap.h index 2ffb5058e5bb..5ba85c027920 100644 --- a/include/llvm/ADT/IndexedMap.h +++ b/include/llvm/ADT/IndexedMap.h @@ -21,16 +21,19 @@ #define LLVM_ADT_INDEXEDMAP_H #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include <cassert> #include <functional> -#include <vector> namespace llvm { template <typename T, typename ToIndexT = llvm::identity<unsigned> > class IndexedMap { typedef typename ToIndexT::argument_type IndexT; - typedef std::vector<T> StorageT; + // Prefer SmallVector with zero inline storage over std::vector. IndexedMaps + // can grow very large and SmallVector grows more efficiently as long as T + // is trivially copyable. + typedef SmallVector<T, 0> StorageT; StorageT storage_; T nullVal_; ToIndexT toIndex_; diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h index 46549eed9939..f8843b2a4e50 100644 --- a/include/llvm/ADT/IntervalMap.h +++ b/include/llvm/ADT/IntervalMap.h @@ -101,6 +101,7 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/AlignOf.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/RecyclingAllocator.h" #include <iterator> @@ -496,7 +497,7 @@ public: NodeRef() {} /// operator bool - Detect a null ref. - LLVM_EXPLICIT operator bool() const { return pip.getOpaqueValue(); } + explicit operator bool() const { return pip.getOpaqueValue(); } /// NodeRef - Create a reference to the node p with n elements. template <typename NodeT> @@ -953,11 +954,6 @@ class IntervalMap { RootBranch node; }; - enum { - RootDataSize = sizeof(RootBranchData) > sizeof(RootLeaf) ? - sizeof(RootBranchData) : sizeof(RootLeaf) - }; - public: typedef typename Sizer::Allocator Allocator; typedef KeyT KeyType; @@ -966,13 +962,7 @@ public: 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]; + AlignedCharArrayUnion<RootLeaf, RootBranchData> data; // Tree height. // 0: Leaves in root. @@ -993,7 +983,7 @@ private: const char *d; T *t; } u; - u.d = data; + u.d = data.buffer; return *u.t; } @@ -1051,7 +1041,7 @@ private: public: explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) { - assert((uintptr_t(data) & (alignOf<RootLeaf>() - 1)) == 0 && + assert((uintptr_t(data.buffer) & (alignOf<RootLeaf>() - 1)) == 0 && "Insufficient alignment"); new(&rootLeaf()) RootLeaf(); } diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index c859c98d06b2..65b2da793d7c 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -21,10 +21,9 @@ #ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H #define LLVM_ADT_INTRUSIVEREFCNTPTR_H -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" #include <atomic> -#include <memory> +#include <cassert> +#include <cstddef> namespace llvm { @@ -84,7 +83,7 @@ namespace llvm { friend struct IntrusiveRefCntPtrInfo; }; - + template <typename T> struct IntrusiveRefCntPtrInfo { static void retain(T *obj) { obj->Retain(); } static void release(T *obj) { obj->Release(); } @@ -114,7 +113,7 @@ public: delete static_cast<const Derived*>(this); } }; - + //===----------------------------------------------------------------------===// /// IntrusiveRefCntPtr - A template class that implements a "smart pointer" /// that assumes the wrapped object has a reference count associated @@ -177,7 +176,7 @@ public: T* get() const { return Obj; } - LLVM_EXPLICIT operator bool() const { return Obj; } + explicit operator bool() const { return Obj; } void swap(IntrusiveRefCntPtr& other) { T* tmp = other.Obj; @@ -268,6 +267,8 @@ public: // LLVM-style downcasting support for IntrusiveRefCntPtr objects //===----------------------------------------------------------------------===// + template <typename From> struct simplify_type; + template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > { typedef T* SimpleType; static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) { diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h index 1331b15b2d29..f19a50b7ba84 100644 --- a/include/llvm/ADT/MapVector.h +++ b/include/llvm/ADT/MapVector.h @@ -67,6 +67,11 @@ public: Vector.clear(); } + void swap(MapVector &RHS) { + std::swap(Map, RHS.Map); + std::swap(Vector, RHS.Vector); + } + ValueT &operator[](const KeyT &Key) { std::pair<KeyT, unsigned> Pair = std::make_pair(Key, 0); std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair); diff --git a/include/llvm/ADT/None.h b/include/llvm/ADT/None.h index 5793bd2faef4..d69ec17c15f9 100644 --- a/include/llvm/ADT/None.h +++ b/include/llvm/ADT/None.h @@ -19,9 +19,8 @@ namespace llvm { /// \brief A simple null object to allow implicit construction of Optional<T> /// and similar types without having to spell out the specialization's name. -enum NoneType { - None -}; +enum class NoneType { None }; +const NoneType None = None; } #endif diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 591872e6591a..855ab890392e 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -70,8 +70,6 @@ public: return *this; } -#if LLVM_HAS_VARIADIC_TEMPLATES - /// Create a new object by constructing it in place with the given arguments. template<typename ...ArgTypes> void emplace(ArgTypes &&...Args) { @@ -80,51 +78,6 @@ public: new (storage.buffer) T(std::forward<ArgTypes>(Args)...); } -#else - - /// Create a new object by default-constructing it in place. - void emplace() { - reset(); - hasVal = true; - new (storage.buffer) T(); - } - - /// Create a new object by constructing it in place with the given arguments. - template<typename T1> - void emplace(T1 &&A1) { - reset(); - hasVal = true; - new (storage.buffer) T(std::forward<T1>(A1)); - } - - /// Create a new object by constructing it in place with the given arguments. - template<typename T1, typename T2> - void emplace(T1 &&A1, T2 &&A2) { - reset(); - hasVal = true; - new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2)); - } - - /// Create a new object by constructing it in place with the given arguments. - template<typename T1, typename T2, typename T3> - void emplace(T1 &&A1, T2 &&A2, T3 &&A3) { - reset(); - hasVal = true; - new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2), - std::forward<T3>(A3)); - } - - /// Create a new object by constructing it in place with the given arguments. - template<typename T1, typename T2, typename T3, typename T4> - void emplace(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) { - reset(); - hasVal = true; - new (storage.buffer) T(std::forward<T1>(A1), std::forward<T2>(A2), - std::forward<T3>(A3), std::forward<T4>(A4)); - } - -#endif // LLVM_HAS_VARIADIC_TEMPLATES - static inline Optional create(const T* y) { return y ? Optional(*y) : Optional(); } @@ -168,7 +121,7 @@ public: const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } - LLVM_EXPLICIT operator bool() const { return hasVal; } + explicit operator bool() const { return hasVal; } bool hasValue() const { return hasVal; } const T* operator->() const { return getPointer(); } T* operator->() { return getPointer(); } diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h index a6dddd277621..f27b81113ec5 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -61,7 +61,7 @@ namespace llvm { NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv }; }; - + /// PointerUnion - This implements a discriminated union of two pointer types, /// and keeps the discriminator bit-mangled into the low bits of the pointer. /// This allows the implementation to be extremely efficient in space, but @@ -80,7 +80,7 @@ namespace llvm { template <typename PT1, typename PT2> class PointerUnion { public: - typedef PointerIntPair<void*, 1, bool, + typedef PointerIntPair<void*, 1, bool, PointerUnionUIntTraits<PT1,PT2> > ValTy; private: ValTy Val; @@ -96,14 +96,14 @@ namespace llvm { public: PointerUnion() {} - + PointerUnion(PT1 V) : Val( const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) { } PointerUnion(PT2 V) : Val( const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) { } - + /// isNull - Return true if the pointer held in the union is null, /// regardless of which type it is. bool isNull() const { @@ -111,7 +111,7 @@ namespace llvm { // we recursively strip off low bits if we have a nested PointerUnion. return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer()); } - LLVM_EXPLICIT operator bool() const { return !isNull(); } + explicit operator bool() const { return !isNull(); } /// is<T>() return true if the Union currently holds the type matching T. template<typename T> @@ -123,7 +123,7 @@ namespace llvm { int TyNo = Ty::Num; return static_cast<int>(Val.getInt()) == TyNo; } - + /// get<T>() - Return the value of the specified pointer type. If the /// specified pointer type is incorrect, assert. template<typename T> @@ -131,7 +131,7 @@ namespace llvm { assert(is<T>() && "Invalid accessor called"); return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer()); } - + /// dyn_cast<T>() - If the current value is of the specified pointer type, /// return it, otherwise return null. template<typename T> @@ -160,7 +160,7 @@ namespace llvm { Val.initWithPointer(nullptr); return *this; } - + /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. const PointerUnion &operator=(const PT1 &RHS) { @@ -174,7 +174,7 @@ namespace llvm { 1); return *this; } - + void *getOpaqueValue() const { return Val.getOpaqueValue(); } static inline PointerUnion getFromOpaqueValue(void *VP) { PointerUnion V; @@ -195,6 +195,12 @@ namespace llvm { return lhs.getOpaqueValue() != rhs.getOpaqueValue(); } + template<typename PT1, typename PT2> + static bool operator<(PointerUnion<PT1, PT2> lhs, + PointerUnion<PT1, PT2> rhs) { + return lhs.getOpaqueValue() < rhs.getOpaqueValue(); + } + // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has // # low bits available = min(PT1bits,PT2bits)-1. template<typename PT1, typename PT2> @@ -208,16 +214,16 @@ namespace llvm { getFromVoidPointer(void *P) { return PointerUnion<PT1, PT2>::getFromOpaqueValue(P); } - + // The number of bits available are the min of the two pointer types. enum { - NumLowBitsAvailable = + NumLowBitsAvailable = PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy> ::NumLowBitsAvailable }; }; - - + + /// PointerUnion3 - This is a pointer union of three pointer types. See /// documentation for PointerUnion for usage. template <typename PT1, typename PT2, typename PT3> @@ -233,7 +239,7 @@ namespace llvm { IsInnerUnion(ValTy val) : Val(val) { } template<typename T> int is() const { - return Val.template is<InnerUnion>() && + return Val.template is<InnerUnion>() && Val.template get<InnerUnion>().template is<T>(); } template<typename T> @@ -257,7 +263,7 @@ namespace llvm { public: PointerUnion3() {} - + PointerUnion3(PT1 V) { Val = InnerUnion(V); } @@ -267,12 +273,12 @@ namespace llvm { PointerUnion3(PT3 V) { Val = V; } - + /// isNull - Return true if the pointer held in the union is null, /// regardless of which type it is. bool isNull() const { return Val.isNull(); } - LLVM_EXPLICIT operator bool() const { return !isNull(); } - + explicit operator bool() const { return !isNull(); } + /// is<T>() return true if the Union currently holds the type matching T. template<typename T> int is() const { @@ -283,7 +289,7 @@ namespace llvm { >::Return Ty; return Ty(Val).template is<T>(); } - + /// get<T>() - Return the value of the specified pointer type. If the /// specified pointer type is incorrect, assert. template<typename T> @@ -296,7 +302,7 @@ namespace llvm { >::Return Ty; return Ty(Val).template get<T>(); } - + /// dyn_cast<T>() - If the current value is of the specified pointer type, /// return it, otherwise return null. template<typename T> @@ -310,7 +316,7 @@ namespace llvm { Val = nullptr; return *this; } - + /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. const PointerUnion3 &operator=(const PT1 &RHS) { @@ -325,7 +331,7 @@ namespace llvm { Val = RHS; return *this; } - + void *getOpaqueValue() const { return Val.getOpaqueValue(); } static inline PointerUnion3 getFromOpaqueValue(void *VP) { PointerUnion3 V; @@ -333,7 +339,7 @@ namespace llvm { return V; } }; - + // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. template<typename PT1, typename PT2, typename PT3> @@ -347,10 +353,10 @@ namespace llvm { getFromVoidPointer(void *P) { return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P); } - + // The number of bits available are the min of the two pointer types. enum { - NumLowBitsAvailable = + NumLowBitsAvailable = PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy> ::NumLowBitsAvailable }; @@ -368,7 +374,7 @@ namespace llvm { ValTy Val; public: PointerUnion4() {} - + PointerUnion4(PT1 V) { Val = InnerUnion1(V); } @@ -381,12 +387,12 @@ namespace llvm { PointerUnion4(PT4 V) { Val = InnerUnion2(V); } - + /// isNull - Return true if the pointer held in the union is null, /// regardless of which type it is. bool isNull() const { return Val.isNull(); } - LLVM_EXPLICIT operator bool() const { return !isNull(); } - + explicit operator bool() const { return !isNull(); } + /// is<T>() return true if the Union currently holds the type matching T. template<typename T> int is() const { @@ -395,10 +401,10 @@ namespace llvm { ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1, ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 > >::Return Ty; - return Val.template is<Ty>() && + return Val.template is<Ty>() && Val.template get<Ty>().template is<T>(); } - + /// get<T>() - Return the value of the specified pointer type. If the /// specified pointer type is incorrect, assert. template<typename T> @@ -411,7 +417,7 @@ namespace llvm { >::Return Ty; return Val.template get<Ty>().template get<T>(); } - + /// dyn_cast<T>() - If the current value is of the specified pointer type, /// return it, otherwise return null. template<typename T> @@ -425,7 +431,7 @@ namespace llvm { Val = nullptr; return *this; } - + /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. const PointerUnion4 &operator=(const PT1 &RHS) { @@ -444,7 +450,7 @@ namespace llvm { Val = InnerUnion2(RHS); return *this; } - + void *getOpaqueValue() const { return Val.getOpaqueValue(); } static inline PointerUnion4 getFromOpaqueValue(void *VP) { PointerUnion4 V; @@ -452,7 +458,7 @@ namespace llvm { return V; } }; - + // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. template<typename PT1, typename PT2, typename PT3, typename PT4> @@ -466,10 +472,10 @@ namespace llvm { getFromVoidPointer(void *P) { return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P); } - + // The number of bits available are the min of the two pointer types. enum { - NumLowBitsAvailable = + NumLowBitsAvailable = PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy> ::NumLowBitsAvailable }; diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h index dfadc3b85db6..759a2db24f2a 100644 --- a/include/llvm/ADT/PostOrderIterator.h +++ b/include/llvm/ADT/PostOrderIterator.h @@ -18,6 +18,7 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator_range.h" #include <set> #include <vector> @@ -111,53 +112,52 @@ class po_iterator : public std::iterator<std::forward_iterator_tag, } } - inline po_iterator(NodeType *BB) { + po_iterator(NodeType *BB) { this->insertEdge((NodeType*)nullptr, BB); VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); traverseChild(); } - inline po_iterator() {} // End is when stack is empty. + po_iterator() {} // End is when stack is empty. - inline po_iterator(NodeType *BB, SetType &S) : - po_iterator_storage<SetType, ExtStorage>(S) { + po_iterator(NodeType *BB, SetType &S) + : po_iterator_storage<SetType, ExtStorage>(S) { if (this->insertEdge((NodeType*)nullptr, BB)) { VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); traverseChild(); } } - inline po_iterator(SetType &S) : - po_iterator_storage<SetType, ExtStorage>(S) { + po_iterator(SetType &S) + : po_iterator_storage<SetType, ExtStorage>(S) { } // End is when stack is empty. public: typedef typename super::pointer pointer; - typedef po_iterator<GraphT, SetType, ExtStorage, GT> _Self; // Provide static "constructors"... - static inline _Self begin(GraphT G) { return _Self(GT::getEntryNode(G)); } - static inline _Self end (GraphT G) { return _Self(); } + static po_iterator begin(GraphT G) { + return po_iterator(GT::getEntryNode(G)); + } + static po_iterator end(GraphT G) { return po_iterator(); } - static inline _Self begin(GraphT G, SetType &S) { - return _Self(GT::getEntryNode(G), S); + static po_iterator begin(GraphT G, SetType &S) { + return po_iterator(GT::getEntryNode(G), S); } - static inline _Self end (GraphT G, SetType &S) { return _Self(S); } + static po_iterator end(GraphT G, SetType &S) { return po_iterator(S); } - inline bool operator==(const _Self& x) const { + bool operator==(const po_iterator &x) const { return VisitStack == x.VisitStack; } - inline bool operator!=(const _Self& x) const { return !operator==(x); } + bool operator!=(const po_iterator &x) const { return !(*this == x); } - inline pointer operator*() const { - return VisitStack.back().first; - } + pointer operator*() const { return VisitStack.back().first; } // This is a nonstandard operator-> that dereferences the pointer an extra // time... so that you can actually call methods ON the BasicBlock, because // the contained type is a pointer. This allows BBIt->getTerminator() f.e. // - inline NodeType *operator->() const { return operator*(); } + NodeType *operator->() const { return **this; } - inline _Self& operator++() { // Preincrement + po_iterator &operator++() { // Preincrement this->finishPostorder(VisitStack.back().first); VisitStack.pop_back(); if (!VisitStack.empty()) @@ -165,17 +165,23 @@ public: return *this; } - inline _Self operator++(int) { // Postincrement - _Self tmp = *this; ++*this; return tmp; + po_iterator operator++(int) { // Postincrement + po_iterator tmp = *this; + ++*this; + return tmp; } }; // Provide global constructors that automatically figure out correct types... // template <class T> -po_iterator<T> po_begin(T G) { return po_iterator<T>::begin(G); } +po_iterator<T> po_begin(const T &G) { return po_iterator<T>::begin(G); } template <class T> -po_iterator<T> po_end (T G) { return po_iterator<T>::end(G); } +po_iterator<T> po_end (const T &G) { return po_iterator<T>::end(G); } + +template <class T> iterator_range<po_iterator<T>> post_order(const T &G) { + return make_range(po_begin(G), po_end(G)); +} // Provide global definitions of external postorder iterators... template<class T, class SetType=std::set<typename GraphTraits<T>::NodeType*> > @@ -194,6 +200,11 @@ po_ext_iterator<T, SetType> po_ext_end(T G, SetType &S) { return po_ext_iterator<T, SetType>::end(G, S); } +template <class T, class SetType> +iterator_range<po_ext_iterator<T, SetType>> post_order_ext(const T &G, SetType &S) { + return make_range(po_ext_begin(G, S), po_ext_end(G, S)); +} + // Provide global definitions of inverse post order iterators... template <class T, class SetType = std::set<typename GraphTraits<T>::NodeType*>, @@ -204,15 +215,20 @@ struct ipo_iterator : public po_iterator<Inverse<T>, SetType, External > { }; template <class T> -ipo_iterator<T> ipo_begin(T G, bool Reverse = false) { +ipo_iterator<T> ipo_begin(const T &G, bool Reverse = false) { return ipo_iterator<T>::begin(G, Reverse); } template <class T> -ipo_iterator<T> ipo_end(T G){ +ipo_iterator<T> ipo_end(const T &G){ return ipo_iterator<T>::end(G); } +template <class T> +iterator_range<ipo_iterator<T>> inverse_post_order(const T &G, bool Reverse = false) { + return make_range(ipo_begin(G, Reverse), ipo_end(G)); +} + // Provide global definitions of external inverse postorder iterators... template <class T, class SetType = std::set<typename GraphTraits<T>::NodeType*> > @@ -224,15 +240,21 @@ struct ipo_ext_iterator : public ipo_iterator<T, SetType, true> { }; template <class T, class SetType> -ipo_ext_iterator<T, SetType> ipo_ext_begin(T G, SetType &S) { +ipo_ext_iterator<T, SetType> ipo_ext_begin(const T &G, SetType &S) { return ipo_ext_iterator<T, SetType>::begin(G, S); } template <class T, class SetType> -ipo_ext_iterator<T, SetType> ipo_ext_end(T G, SetType &S) { +ipo_ext_iterator<T, SetType> ipo_ext_end(const T &G, SetType &S) { return ipo_ext_iterator<T, SetType>::end(G, S); } +template <class T, class SetType> +iterator_range<ipo_ext_iterator<T, SetType>> +inverse_post_order_ext(const T &G, SetType &S) { + return make_range(ipo_ext_begin(G, S), ipo_ext_end(G, S)); +} + //===--------------------------------------------------------------------===// // Reverse Post Order CFG iterator code //===--------------------------------------------------------------------===// @@ -260,19 +282,17 @@ template<class GraphT, class GT = GraphTraits<GraphT> > class ReversePostOrderTraversal { typedef typename GT::NodeType NodeType; std::vector<NodeType*> Blocks; // Block list in normal PO order - inline void Initialize(NodeType *BB) { + void Initialize(NodeType *BB) { std::copy(po_begin(BB), po_end(BB), std::back_inserter(Blocks)); } public: typedef typename std::vector<NodeType*>::reverse_iterator rpo_iterator; - inline ReversePostOrderTraversal(GraphT G) { - Initialize(GT::getEntryNode(G)); - } + ReversePostOrderTraversal(GraphT G) { Initialize(GT::getEntryNode(G)); } // Because we want a reverse post order, use reverse iterators from the vector - inline rpo_iterator begin() { return Blocks.rbegin(); } - inline rpo_iterator end() { return Blocks.rend(); } + rpo_iterator begin() { return Blocks.rbegin(); } + rpo_iterator end() { return Blocks.rend(); } }; } // End llvm namespace diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index 4e56e4d74470..b68345a1dcf6 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -18,6 +18,8 @@ #define LLVM_ADT_STLEXTRAS_H #include "llvm/Support/Compiler.h" +#include <algorithm> // for std::all_of +#include <cassert> #include <cstddef> // for std::size_t #include <cstdlib> // for qsort #include <functional> @@ -63,8 +65,6 @@ struct greater_ptr : public std::binary_function<Ty, Ty, bool> { /// a function_ref. template<typename Fn> class function_ref; -#if LLVM_HAS_VARIADIC_TEMPLATES - template<typename Ret, typename ...Params> class function_ref<Ret(Params...)> { Ret (*callback)(intptr_t callable, Params ...params); @@ -89,112 +89,6 @@ public: } }; -#else - -template<typename Ret> -class function_ref<Ret()> { - Ret (*callback)(intptr_t callable); - intptr_t callable; - - template<typename Callable> - static Ret callback_fn(intptr_t callable) { - return (*reinterpret_cast<Callable*>(callable))(); - } - -public: - template<typename Callable> - function_ref(Callable &&callable, - typename std::enable_if< - !std::is_same<typename std::remove_reference<Callable>::type, - function_ref>::value>::type * = nullptr) - : callback(callback_fn<typename std::remove_reference<Callable>::type>), - callable(reinterpret_cast<intptr_t>(&callable)) {} - Ret operator()() const { return callback(callable); } -}; - -template<typename Ret, typename Param1> -class function_ref<Ret(Param1)> { - Ret (*callback)(intptr_t callable, Param1 param1); - intptr_t callable; - - template<typename Callable> - static Ret callback_fn(intptr_t callable, Param1 param1) { - return (*reinterpret_cast<Callable*>(callable))( - std::forward<Param1>(param1)); - } - -public: - template<typename Callable> - function_ref(Callable &&callable, - typename std::enable_if< - !std::is_same<typename std::remove_reference<Callable>::type, - function_ref>::value>::type * = nullptr) - : callback(callback_fn<typename std::remove_reference<Callable>::type>), - callable(reinterpret_cast<intptr_t>(&callable)) {} - Ret operator()(Param1 param1) { - return callback(callable, std::forward<Param1>(param1)); - } -}; - -template<typename Ret, typename Param1, typename Param2> -class function_ref<Ret(Param1, Param2)> { - Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2); - intptr_t callable; - - template<typename Callable> - static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2) { - return (*reinterpret_cast<Callable*>(callable))( - std::forward<Param1>(param1), - std::forward<Param2>(param2)); - } - -public: - template<typename Callable> - function_ref(Callable &&callable, - typename std::enable_if< - !std::is_same<typename std::remove_reference<Callable>::type, - function_ref>::value>::type * = nullptr) - : callback(callback_fn<typename std::remove_reference<Callable>::type>), - callable(reinterpret_cast<intptr_t>(&callable)) {} - Ret operator()(Param1 param1, Param2 param2) { - return callback(callable, - std::forward<Param1>(param1), - std::forward<Param2>(param2)); - } -}; - -template<typename Ret, typename Param1, typename Param2, typename Param3> -class function_ref<Ret(Param1, Param2, Param3)> { - Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2, Param3 param3); - intptr_t callable; - - template<typename Callable> - static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2, - Param3 param3) { - return (*reinterpret_cast<Callable*>(callable))( - std::forward<Param1>(param1), - std::forward<Param2>(param2), - std::forward<Param3>(param3)); - } - -public: - template<typename Callable> - function_ref(Callable &&callable, - typename std::enable_if< - !std::is_same<typename std::remove_reference<Callable>::type, - function_ref>::value>::type * = nullptr) - : callback(callback_fn<typename std::remove_reference<Callable>::type>), - callable(reinterpret_cast<intptr_t>(&callable)) {} - Ret operator()(Param1 param1, Param2 param2, Param3 param3) { - return callback(callable, - std::forward<Param1>(param1), - std::forward<Param2>(param2), - std::forward<Param3>(param3)); - } -}; - -#endif - // deleter - Very very very simple method that is used to invoke operator // delete on something. It is used like this: // @@ -230,7 +124,6 @@ public: typedef void reference; // Can't modify value returned by fn typedef RootIt iterator_type; - typedef mapped_iterator<RootIt, UnaryFunc> _Self; inline const RootIt &getCurrent() const { return current; } inline const UnaryFunc &getFunc() const { return Fn; } @@ -242,34 +135,56 @@ public: return Fn(*current); // little change } - _Self& operator++() { ++current; return *this; } - _Self& operator--() { --current; return *this; } - _Self operator++(int) { _Self __tmp = *this; ++current; return __tmp; } - _Self operator--(int) { _Self __tmp = *this; --current; return __tmp; } - _Self operator+ (difference_type n) const { - return _Self(current + n, Fn); + mapped_iterator &operator++() { + ++current; + return *this; } - _Self& operator+= (difference_type n) { current += n; return *this; } - _Self operator- (difference_type n) const { - return _Self(current - n, Fn); + mapped_iterator &operator--() { + --current; + return *this; + } + mapped_iterator operator++(int) { + mapped_iterator __tmp = *this; + ++current; + return __tmp; + } + mapped_iterator operator--(int) { + mapped_iterator __tmp = *this; + --current; + return __tmp; + } + mapped_iterator operator+(difference_type n) const { + return mapped_iterator(current + n, Fn); + } + mapped_iterator &operator+=(difference_type n) { + current += n; + return *this; + } + mapped_iterator operator-(difference_type n) const { + return mapped_iterator(current - n, Fn); + } + mapped_iterator &operator-=(difference_type n) { + current -= n; + return *this; } - _Self& operator-= (difference_type n) { current -= n; return *this; } reference operator[](difference_type n) const { return *(*this + n); } - inline bool operator!=(const _Self &X) const { return !operator==(X); } - inline bool operator==(const _Self &X) const { return current == X.current; } - inline bool operator< (const _Self &X) const { return current < X.current; } + bool operator!=(const mapped_iterator &X) const { return !operator==(X); } + bool operator==(const mapped_iterator &X) const { + return current == X.current; + } + bool operator<(const mapped_iterator &X) const { return current < X.current; } - inline difference_type operator-(const _Self &X) const { + difference_type operator-(const mapped_iterator &X) const { return current - X.current; } }; -template <class _Iterator, class Func> -inline mapped_iterator<_Iterator, Func> -operator+(typename mapped_iterator<_Iterator, Func>::difference_type N, - const mapped_iterator<_Iterator, Func>& X) { - return mapped_iterator<_Iterator, Func>(X.getCurrent() - N, X.getFunc()); +template <class Iterator, class Func> +inline mapped_iterator<Iterator, Func> +operator+(typename mapped_iterator<Iterator, Func>::difference_type N, + const mapped_iterator<Iterator, Func> &X) { + return mapped_iterator<Iterator, Func>(X.getCurrent() - N, X.getFunc()); } @@ -301,6 +216,28 @@ struct less_second { } }; +// A subset of N3658. More stuff can be added as-needed. + +/// \brief Represents a compile-time sequence of integers. +template <class T, T... I> struct integer_sequence { + typedef T value_type; + + static LLVM_CONSTEXPR size_t size() { return sizeof...(I); } +}; + +/// \brief Alias for the common case of a sequence of size_ts. +template <size_t... I> +struct index_sequence : integer_sequence<std::size_t, I...> {}; + +template <std::size_t N, std::size_t... I> +struct build_index_impl : build_index_impl<N - 1, N - 1, I...> {}; +template <std::size_t... I> +struct build_index_impl<0, I...> : index_sequence<I...> {}; + +/// \brief Creates a compile-time integer sequence for a parameter pack. +template <class... Ts> +struct index_sequence_for : build_index_impl<sizeof...(Ts)> {}; + //===----------------------------------------------------------------------===// // Extra additions for arrays //===----------------------------------------------------------------------===// @@ -348,10 +285,11 @@ inline int (*get_array_pod_sort_comparator(const T &)) /// default to std::less. template<class IteratorTy> inline void array_pod_sort(IteratorTy Start, IteratorTy End) { - // Don't dereference start iterator of empty sequence. - if (Start == End) return; - qsort(&*Start, End-Start, sizeof(*Start), - get_array_pod_sort_comparator(*Start)); + // Don't inefficiently call qsort with one element or trigger undefined + // behavior with an empty sequence. + auto NElts = End - Start; + if (NElts <= 1) return; + qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); } template <class IteratorTy> @@ -360,9 +298,11 @@ inline void array_pod_sort( int (*Compare)( const typename std::iterator_traits<IteratorTy>::value_type *, const typename std::iterator_traits<IteratorTy>::value_type *)) { - // Don't dereference start iterator of empty sequence. - if (Start == End) return; - qsort(&*Start, End - Start, sizeof(*Start), + // Don't inefficiently call qsort with one element or trigger undefined + // behavior with an empty sequence. + auto NElts = End - Start; + if (NElts <= 1) return; + qsort(&*Start, NElts, sizeof(*Start), reinterpret_cast<int (*)(const void *, const void *)>(Compare)); } @@ -388,12 +328,18 @@ void DeleteContainerSeconds(Container &C) { C.clear(); } +/// Provide wrappers to std::all_of which take ranges instead of having to pass +/// being/end explicitly. +template<typename R, class UnaryPredicate> +bool all_of(R &&Range, UnaryPredicate &&P) { + return std::all_of(Range.begin(), Range.end(), + std::forward<UnaryPredicate>(P)); +} + //===----------------------------------------------------------------------===// // Extra additions to <memory> //===----------------------------------------------------------------------===// -#if LLVM_HAS_VARIADIC_TEMPLATES - // Implement make_unique according to N3656. /// \brief Constructs a `new T()` with the given args and returns a @@ -427,123 +373,7 @@ make_unique(size_t n) { /// This function isn't used and is only here to provide better compile errors. template <class T, class... Args> typename std::enable_if<std::extent<T>::value != 0>::type -make_unique(Args &&...) LLVM_DELETED_FUNCTION; - -#else - -template <class T> -typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type -make_unique() { - return std::unique_ptr<T>(new T()); -} - -template <class T, class Arg1> -typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type -make_unique(Arg1 &&arg1) { - return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1))); -} - -template <class T, class Arg1, class Arg2> -typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2) { - return std::unique_ptr<T>( - new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2))); -} - -template <class T, class Arg1, class Arg2, class Arg3> -typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) { - return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1), - std::forward<Arg2>(arg2), - std::forward<Arg3>(arg3))); -} - -template <class T, class Arg1, class Arg2, class Arg3, class Arg4> -typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) { - return std::unique_ptr<T>( - new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), - std::forward<Arg3>(arg3), std::forward<Arg4>(arg4))); -} - -template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5> -typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5) { - return std::unique_ptr<T>( - new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), - std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), - std::forward<Arg5>(arg5))); -} - -template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, - class Arg6> -typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6) { - return std::unique_ptr<T>( - new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), - std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), - std::forward<Arg5>(arg5), std::forward<Arg6>(arg6))); -} - -template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, - class Arg6, class Arg7> -typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6, Arg7 &&arg7) { - return std::unique_ptr<T>( - new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), - std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), - std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), - std::forward<Arg7>(arg7))); -} - -template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, - class Arg6, class Arg7, class Arg8> -typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8) { - return std::unique_ptr<T>( - new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), - std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), - std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), - std::forward<Arg7>(arg7), std::forward<Arg8>(arg8))); -} - -template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, - class Arg6, class Arg7, class Arg8, class Arg9> -typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9) { - return std::unique_ptr<T>( - new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), - std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), - std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), - std::forward<Arg7>(arg7), std::forward<Arg8>(arg8), - std::forward<Arg9>(arg9))); -} - -template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, - class Arg6, class Arg7, class Arg8, class Arg9, class Arg10> -typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9, Arg10 &&arg10) { - return std::unique_ptr<T>( - new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), - std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), - std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), - std::forward<Arg7>(arg7), std::forward<Arg8>(arg8), - std::forward<Arg9>(arg9), std::forward<Arg10>(arg10))); -} - -template <class T> -typename std::enable_if<std::is_array<T>::value &&std::extent<T>::value == 0, - std::unique_ptr<T>>::type -make_unique(size_t n) { - return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]()); -} - -#endif +make_unique(Args &&...) = delete; struct FreeDeleter { void operator()(void* v) { @@ -558,6 +388,35 @@ struct pair_hash { } }; +/// A functor like C++14's std::less<void> in its absence. +struct less { + template <typename A, typename B> bool operator()(A &&a, B &&b) const { + return std::forward<A>(a) < std::forward<B>(b); + } +}; + +/// A functor like C++14's std::equal<void> in its absence. +struct equal { + template <typename A, typename B> bool operator()(A &&a, B &&b) const { + return std::forward<A>(a) == std::forward<B>(b); + } +}; + +/// Binary functor that adapts to any other binary functor after dereferencing +/// operands. +template <typename T> struct deref { + T func; + // Could be further improved to cope with non-derivable functors and + // non-binary functors (should be a variadic template member function + // operator()). + template <typename A, typename B> + auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { + assert(lhs); + assert(rhs); + return func(*lhs, *rhs); + } +}; + } // End llvm namespace #endif diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h index 2f60ecc92043..5abe76c12259 100644 --- a/include/llvm/ADT/ScopedHashTable.h +++ b/include/llvm/ADT/ScopedHashTable.h @@ -90,8 +90,8 @@ class ScopedHashTableScope { /// LastValInScope - This is the last value that was inserted for this scope /// or null if none have been inserted yet. ScopedHashTableVal<K, V> *LastValInScope; - void operator=(ScopedHashTableScope&) LLVM_DELETED_FUNCTION; - ScopedHashTableScope(ScopedHashTableScope&) LLVM_DELETED_FUNCTION; + void operator=(ScopedHashTableScope&) = delete; + ScopedHashTableScope(ScopedHashTableScope&) = delete; public: ScopedHashTableScope(ScopedHashTable<K, V, KInfo, AllocatorTy> &HT); ~ScopedHashTableScope(); diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index 1e2f365b1040..ae3d645396fd 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -53,6 +53,9 @@ class SmallBitVector { SmallNumDataBits = SmallNumRawBits - SmallNumSizeBits }; + static_assert(NumBaseBits == 64 || NumBaseBits == 32, + "Unsupported word size"); + public: typedef unsigned size_type; // Encapsulation of a single bit. @@ -63,6 +66,8 @@ public: public: reference(SmallBitVector &b, unsigned Idx) : TheVector(b), BitPos(Idx) {} + reference(const reference&) = default; + reference& operator=(reference t) { *this = bool(t); return *this; @@ -177,11 +182,7 @@ public: size_type count() const { if (isSmall()) { uintptr_t Bits = getSmallBits(); - if (NumBaseBits == 32) - return CountPopulation_32(Bits); - if (NumBaseBits == 64) - return CountPopulation_64(Bits); - llvm_unreachable("Unsupported!"); + return countPopulation(Bits); } return getPointer()->count(); } @@ -214,11 +215,7 @@ public: uintptr_t Bits = getSmallBits(); if (Bits == 0) return -1; - if (NumBaseBits == 32) - return countTrailingZeros(Bits); - if (NumBaseBits == 64) - return countTrailingZeros(Bits); - llvm_unreachable("Unsupported!"); + return countTrailingZeros(Bits); } return getPointer()->find_first(); } @@ -232,11 +229,7 @@ public: Bits &= ~uintptr_t(0) << (Prev + 1); if (Bits == 0 || Prev + 1 >= getSmallSize()) return -1; - if (NumBaseBits == 32) - return countTrailingZeros(Bits); - if (NumBaseBits == 64) - return countTrailingZeros(Bits); - llvm_unreachable("Unsupported!"); + return countTrailingZeros(Bits); } return getPointer()->find_next(Prev); } @@ -560,7 +553,6 @@ public: private: template<bool AddBits, bool InvertMask> void applyMask(const uint32_t *Mask, unsigned MaskWords) { - assert((NumBaseBits == 64 || NumBaseBits == 32) && "Unsupported word size"); if (NumBaseBits == 64 && MaskWords >= 2) { uint64_t M = Mask[0] | (uint64_t(Mask[1]) << 32); if (InvertMask) M = ~M; diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index cb1c5e1fa96a..3e3c9c154ef4 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -132,7 +132,7 @@ private: /// Grow - Allocate a larger backing store for the buckets and move it over. void Grow(unsigned NewSize); - void operator=(const SmallPtrSetImplBase &RHS) LLVM_DELETED_FUNCTION; + void operator=(const SmallPtrSetImplBase &RHS) = delete; protected: /// swap - Swaps the elements of two sets. /// Note: This method assumes that both sets have the same small size. @@ -242,7 +242,7 @@ template <typename PtrType> class SmallPtrSetImpl : public SmallPtrSetImplBase { typedef PointerLikeTypeTraits<PtrType> PtrTraits; - SmallPtrSetImpl(const SmallPtrSetImpl&) LLVM_DELETED_FUNCTION; + SmallPtrSetImpl(const SmallPtrSetImpl&) = delete; protected: // Constructors that forward to the base. SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that) diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 44a352119b09..5b208b76a21f 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -24,6 +24,7 @@ #include <cstddef> #include <cstdlib> #include <cstring> +#include <initializer_list> #include <iterator> #include <memory> @@ -236,51 +237,6 @@ public: this->setEnd(this->end()-1); this->end()->~T(); } - -#if LLVM_HAS_VARIADIC_TEMPLATES - template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) { - if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) - this->grow(); - ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...); - this->setEnd(this->end() + 1); - } -#else -private: - template <typename Constructor> void emplace_back_impl(Constructor construct) { - if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) - this->grow(); - construct((void *)this->end()); - this->setEnd(this->end() + 1); - } - -public: - void emplace_back() { - emplace_back_impl([](void *Mem) { ::new (Mem) T(); }); - } - template <typename T1> void emplace_back(T1 &&A1) { - emplace_back_impl([&](void *Mem) { ::new (Mem) T(std::forward<T1>(A1)); }); - } - template <typename T1, typename T2> void emplace_back(T1 &&A1, T2 &&A2) { - emplace_back_impl([&](void *Mem) { - ::new (Mem) T(std::forward<T1>(A1), std::forward<T2>(A2)); - }); - } - template <typename T1, typename T2, typename T3> - void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3) { - T(std::forward<T1>(A1), std::forward<T2>(A2), std::forward<T3>(A3)); - emplace_back_impl([&](void *Mem) { - ::new (Mem) - T(std::forward<T1>(A1), std::forward<T2>(A2), std::forward<T3>(A3)); - }); - } - template <typename T1, typename T2, typename T3, typename T4> - void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) { - emplace_back_impl([&](void *Mem) { - ::new (Mem) T(std::forward<T1>(A1), std::forward<T2>(A2), - std::forward<T3>(A3), std::forward<T4>(A4)); - }); - } -#endif // LLVM_HAS_VARIADIC_TEMPLATES }; // Define this out-of-line to dissuade the C++ compiler from inlining it. @@ -352,8 +308,11 @@ protected: /// Copy the range [I, E) onto the uninitialized memory /// starting with "Dest", constructing elements into it as needed. - template<typename T1, typename T2> - static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) { + template <typename T1, typename T2> + static void uninitialized_copy( + T1 *I, T1 *E, T2 *Dest, + typename std::enable_if<std::is_same<typename std::remove_const<T1>::type, + T2>::value>::type * = nullptr) { // Use memcpy for PODs iterated by pointers (which includes SmallVector // iterators): std::uninitialized_copy optimizes to memmove, but we can // use memcpy here. @@ -385,7 +344,7 @@ template <typename T> class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> { typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass; - SmallVectorImpl(const SmallVectorImpl&) LLVM_DELETED_FUNCTION; + SmallVectorImpl(const SmallVectorImpl&) = delete; public: typedef typename SuperClass::iterator iterator; typedef typename SuperClass::size_type size_type; @@ -459,9 +418,7 @@ public: this->grow(this->size()+NumInputs); // Copy the new elements over. - // TODO: NEED To compile time dispatch on whether in_iter is a random access - // iterator to use the fast uninitialized_copy. - std::uninitialized_copy(in_start, in_end, this->end()); + this->uninitialized_copy(in_start, in_end, this->end()); this->setEnd(this->end() + NumInputs); } @@ -476,6 +433,10 @@ public: this->setEnd(this->end() + NumInputs); } + void append(std::initializer_list<T> IL) { + append(IL.begin(), IL.end()); + } + void assign(size_type NumElts, const T &Elt) { clear(); if (this->capacity() < NumElts) @@ -484,6 +445,11 @@ public: std::uninitialized_fill(this->begin(), this->end(), Elt); } + void assign(std::initializer_list<T> IL) { + clear(); + append(IL); + } + iterator erase(iterator I) { assert(I >= this->begin() && "Iterator to erase is out of bounds."); assert(I < this->end() && "Erasing at past-the-end iterator."); @@ -677,6 +643,17 @@ public: return I; } + void insert(iterator I, std::initializer_list<T> IL) { + insert(I, IL.begin(), IL.end()); + } + + template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) { + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...); + this->setEnd(this->end() + 1); + } + SmallVectorImpl &operator=(const SmallVectorImpl &RHS); SmallVectorImpl &operator=(SmallVectorImpl &&RHS); @@ -902,6 +879,10 @@ public: this->append(R.begin(), R.end()); } + SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) { + this->assign(IL); + } + SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) { if (!RHS.empty()) SmallVectorImpl<T>::operator=(RHS); @@ -921,6 +902,21 @@ public: SmallVectorImpl<T>::operator=(::std::move(RHS)); return *this; } + + SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) { + if (!RHS.empty()) + SmallVectorImpl<T>::operator=(::std::move(RHS)); + } + + const SmallVector &operator=(SmallVectorImpl<T> &&RHS) { + SmallVectorImpl<T>::operator=(::std::move(RHS)); + return *this; + } + + const SmallVector &operator=(std::initializer_list<T> IL) { + this->assign(IL); + return *this; + } }; template<typename T, unsigned N> diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index d5bde2963fbd..20cbe2cddfc2 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -124,25 +124,15 @@ public: size_type count() const { unsigned NumBits = 0; for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) - if (sizeof(BitWord) == 4) - NumBits += CountPopulation_32(Bits[i]); - else if (sizeof(BitWord) == 8) - NumBits += CountPopulation_64(Bits[i]); - else - llvm_unreachable("Unsupported!"); + NumBits += countPopulation(Bits[i]); return NumBits; } /// find_first - Returns the index of the first set bit. int find_first() const { for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) - if (Bits[i] != 0) { - if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - llvm_unreachable("Unsupported!"); - } + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); llvm_unreachable("Illegal empty element"); } @@ -161,23 +151,13 @@ public: // Mask off previous bits. Copy &= ~0UL << BitPos; - if (Copy != 0) { - if (sizeof(BitWord) == 4) - return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); - if (sizeof(BitWord) == 8) - return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); - llvm_unreachable("Unsupported!"); - } + if (Copy != 0) + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); // Check subsequent words. for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i) - if (Bits[i] != 0) { - if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - llvm_unreachable("Unsupported!"); - } + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); return -1; } diff --git a/include/llvm/ADT/SparseMultiSet.h b/include/llvm/ADT/SparseMultiSet.h index f858536b6ed8..e3aa2589b79f 100644 --- a/include/llvm/ADT/SparseMultiSet.h +++ b/include/llvm/ADT/SparseMultiSet.h @@ -133,8 +133,8 @@ class SparseMultiSet { // Disable copy construction and assignment. // This data structure is not meant to be used that way. - SparseMultiSet(const SparseMultiSet&) LLVM_DELETED_FUNCTION; - SparseMultiSet &operator=(const SparseMultiSet&) LLVM_DELETED_FUNCTION; + SparseMultiSet(const SparseMultiSet&) = delete; + SparseMultiSet &operator=(const SparseMultiSet&) = delete; /// Whether the given entry is the head of the list. List heads's previous /// pointers are to the tail of the list, allowing for efficient access to the diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h index 9a13440000ac..a45d1c8d6b8a 100644 --- a/include/llvm/ADT/SparseSet.h +++ b/include/llvm/ADT/SparseSet.h @@ -133,8 +133,8 @@ class SparseSet { // Disable copy construction and assignment. // This data structure is not meant to be used that way. - SparseSet(const SparseSet&) LLVM_DELETED_FUNCTION; - SparseSet &operator=(const SparseSet&) LLVM_DELETED_FUNCTION; + SparseSet(const SparseSet&) = delete; + SparseSet &operator=(const SparseSet&) = delete; public: typedef ValueT value_type; diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index 3437607a0bd0..8721c73b95b1 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -111,7 +111,7 @@ public: /// and data. template<typename ValueTy> class StringMapEntry : public StringMapEntryBase { - StringMapEntry(StringMapEntry &E) LLVM_DELETED_FUNCTION; + StringMapEntry(StringMapEntry &E) = delete; public: ValueTy second; diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index 6111c42da9dc..95660a49f1f1 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -238,9 +238,12 @@ namespace llvm { /// \returns The index of the first occurrence of \p C, or npos if not /// found. size_t find(char C, size_t From = 0) const { - for (size_t i = std::min(From, Length), e = Length; i != e; ++i) - if (Data[i] == C) - return i; + size_t FindBegin = std::min(From, Length); + if (FindBegin < Length) { // Avoid calling memchr with nullptr. + // Just forward to memchr, which is faster than a hand-rolled loop. + if (const void *P = ::memchr(Data + FindBegin, C, Length - FindBegin)) + return static_cast<const char *>(P) - Data; + } return npos; } diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h index 15137f5ebf8c..f29608f3d3d1 100644 --- a/include/llvm/ADT/TinyPtrVector.h +++ b/include/llvm/ADT/TinyPtrVector.h @@ -27,9 +27,12 @@ class TinyPtrVector { public: typedef llvm::SmallVector<EltTy, 4> VecTy; typedef typename VecTy::value_type value_type; + typedef llvm::PointerUnion<EltTy, VecTy *> PtrUnion; - llvm::PointerUnion<EltTy, VecTy*> Val; +private: + PtrUnion Val; +public: TinyPtrVector() {} ~TinyPtrVector() { if (VecTy *V = Val.template dyn_cast<VecTy*>()) @@ -96,12 +99,13 @@ public: return *this; } - /// Constructor from a single element. - explicit TinyPtrVector(EltTy Elt) : Val(Elt) {} - /// Constructor from an ArrayRef. + /// + /// This also is a constructor for individual array elements due to the single + /// element constructor for ArrayRef. explicit TinyPtrVector(ArrayRef<EltTy> Elts) - : Val(new VecTy(Elts.begin(), Elts.end())) {} + : Val(Elts.size() == 1 ? PtrUnion(Elts[0]) + : PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {} // implicit conversion operator to ArrayRef. operator ArrayRef<EltTy>() const { @@ -112,6 +116,15 @@ public: return *Val.template get<VecTy*>(); } + // implicit conversion operator to MutableArrayRef. + operator MutableArrayRef<EltTy>() { + if (Val.isNull()) + return None; + if (Val.template is<EltTy>()) + return *Val.getAddrOfPtr1(); + return *Val.template get<VecTy*>(); + } + bool empty() const { // This vector can be empty if it contains no element, or if it // contains a pointer to an empty vector. diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 8a685995256b..2416ce342c9b 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -50,6 +50,7 @@ public: armeb, // ARM (big endian): armeb aarch64, // AArch64 (little endian): aarch64 aarch64_be, // AArch64 (big endian): aarch64_be + bpf, // eBPF or extended BPF or 64-bit BPF (little endian) hexagon, // Hexagon: hexagon mips, // MIPS: mips, mipsallegrex mipsel, // MIPSEL: mipsel, mipsallegrexel @@ -63,6 +64,7 @@ public: amdgcn, // AMDGCN: AMD GCN GPUs sparc, // Sparc: sparc sparcv9, // Sparcv9: Sparcv9 + sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant systemz, // SystemZ: s390x tce, // TCE (http://tce.cs.tut.fi/): tce thumb, // Thumb (little endian): thumb, thumbv.* @@ -80,11 +82,13 @@ public: hsail64, // AMD HSAIL with 64-bit pointers spir, // SPIR: standard portable IR for OpenCL 32-bit version spir64, // SPIR: standard portable IR for OpenCL 64-bit version - kalimba // Kalimba: generic kalimba + kalimba, // Kalimba: generic kalimba + LastArchType = kalimba }; enum SubArchType { NoSubArch, + ARMSubArch_v8_1a, ARMSubArch_v8, ARMSubArch_v7, ARMSubArch_v7em, @@ -92,6 +96,7 @@ public: ARMSubArch_v7s, ARMSubArch_v6, ARMSubArch_v6m, + ARMSubArch_v6k, ARMSubArch_v6t2, ARMSubArch_v5, ARMSubArch_v5te, @@ -114,11 +119,13 @@ public: ImaginationTechnologies, MipsTechnologies, NVIDIA, - CSR + CSR, + LastVendorType = CSR }; enum OSType { UnknownOS, + CloudABI, Darwin, DragonFly, FreeBSD, @@ -140,7 +147,9 @@ public: AIX, CUDA, // NVIDIA CUDA NVCL, // NVIDIA OpenCL - AMDHSA // AMD HSA Runtime + AMDHSA, // AMD HSA Runtime + PS4, + LastOSType = PS4 }; enum EnvironmentType { UnknownEnvironment, @@ -157,6 +166,7 @@ public: MSVC, Itanium, Cygnus, + LastEnvironmentType = Cygnus }; enum ObjectFormatType { UnknownObjectFormat, @@ -200,6 +210,13 @@ public: Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr, const Twine &EnvironmentStr); + bool operator==(const Triple &Other) const { + return Arch == Other.Arch && SubArch == Other.SubArch && + Vendor == Other.Vendor && OS == Other.OS && + Environment == Other.Environment && + ObjectFormat == Other.ObjectFormat; + } + /// @} /// @name Normalization /// @{ @@ -210,6 +227,9 @@ public: /// common case in which otherwise valid components are in the wrong order. static std::string normalize(StringRef Str); + /// \brief Return the normalized form of this triple's string. + std::string normalize() const { return normalize(Data); } + /// @} /// @name Typed Component Access /// @{ @@ -334,6 +354,12 @@ public: return false; } + bool isOSVersionLT(const Triple &Other) const { + unsigned RHS[3]; + Other.getOSVersion(RHS[0], RHS[1], RHS[2]); + return isOSVersionLT(RHS[0], RHS[1], RHS[2]); + } + /// isMacOSXVersionLT - Comparison function for checking OS X version /// compatibility, which handles supporting skewed version numbering schemes /// used by the "darwin" triples. @@ -423,7 +449,7 @@ public: /// \brief Tests whether the OS is Windows. bool isOSWindows() const { - return getOS() == Triple::Win32 || isOSCygMing(); + return getOS() == Triple::Win32; } /// \brief Tests whether the OS is NaCl (Native Client) @@ -451,6 +477,19 @@ public: return getObjectFormat() == Triple::MachO; } + /// \brief Tests whether the target is the PS4 CPU + bool isPS4CPU() const { + return getArch() == Triple::x86_64 && + getVendor() == Triple::SCEI && + getOS() == Triple::PS4; + } + + /// \brief Tests whether the target is the PS4 platform + bool isPS4() const { + return getVendor() == Triple::SCEI && + getOS() == Triple::PS4; + } + /// @} /// @name Mutators /// @{ diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index 05d2fea117cf..db0bf4b68de8 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -10,6 +10,7 @@ #ifndef LLVM_ADT_TWINE_H #define LLVM_ADT_TWINE_H +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -17,9 +18,6 @@ #include <string> namespace llvm { - template <typename T> - class SmallVectorImpl; - class StringRef; class raw_ostream; /// Twine - A lightweight data structure for efficiently representing the @@ -100,6 +98,9 @@ namespace llvm { /// A pointer to a StringRef instance. StringRefKind, + /// A pointer to a SmallString instance. + SmallStringKind, + /// A char value reinterpreted as a pointer, to render as a character. CharKind, @@ -136,6 +137,7 @@ namespace llvm { const char *cString; const std::string *stdString; const StringRef *stringRef; + const SmallVectorImpl<char> *smallString; char character; unsigned int decUI; int decI; @@ -166,50 +168,49 @@ namespace llvm { } /// Construct a binary twine. - explicit Twine(const Twine &_LHS, const Twine &_RHS) - : LHSKind(TwineKind), RHSKind(TwineKind) { - LHS.twine = &_LHS; - RHS.twine = &_RHS; + explicit Twine(const Twine &LHS, const Twine &RHS) + : LHSKind(TwineKind), RHSKind(TwineKind) { + this->LHS.twine = &LHS; + this->RHS.twine = &RHS; assert(isValid() && "Invalid twine!"); } /// Construct a twine from explicit values. - explicit Twine(Child _LHS, NodeKind _LHSKind, - Child _RHS, NodeKind _RHSKind) - : LHS(_LHS), RHS(_RHS), LHSKind(_LHSKind), RHSKind(_RHSKind) { + explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind) + : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) { assert(isValid() && "Invalid twine!"); } /// Since the intended use of twines is as temporary objects, assignments /// when concatenating might cause undefined behavior or stack corruptions - Twine &operator=(const Twine &Other) LLVM_DELETED_FUNCTION; + Twine &operator=(const Twine &Other) = delete; - /// isNull - Check for the null twine. + /// Check for the null twine. bool isNull() const { return getLHSKind() == NullKind; } - /// isEmpty - Check for the empty twine. + /// Check for the empty twine. bool isEmpty() const { return getLHSKind() == EmptyKind; } - /// isNullary - Check if this is a nullary twine (null or empty). + /// Check if this is a nullary twine (null or empty). bool isNullary() const { return isNull() || isEmpty(); } - /// isUnary - Check if this is a unary twine. + /// Check if this is a unary twine. bool isUnary() const { return getRHSKind() == EmptyKind && !isNullary(); } - /// isBinary - Check if this is a binary twine. + /// Check if this is a binary twine. bool isBinary() const { return getLHSKind() != NullKind && getRHSKind() != EmptyKind; } - /// isValid - Check if this is a valid twine (satisfying the invariants on + /// Check if this is a valid twine (satisfying the invariants on /// order and number of arguments). bool isValid() const { // Nullary twines always have Empty on the RHS. @@ -235,16 +236,16 @@ namespace llvm { return true; } - /// getLHSKind - Get the NodeKind of the left-hand side. + /// Get the NodeKind of the left-hand side. NodeKind getLHSKind() const { return LHSKind; } - /// getRHSKind - Get the NodeKind of the right-hand side. + /// Get the NodeKind of the right-hand side. NodeKind getRHSKind() const { return RHSKind; } - /// printOneChild - Print one child from a twine. + /// Print one child from a twine. void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; - /// printOneChildRepr - Print the representation of one child from a twine. + /// Print the representation of one child from a twine. void printOneChildRepr(raw_ostream &OS, Child Ptr, NodeKind Kind) const; @@ -257,6 +258,8 @@ namespace llvm { assert(isValid() && "Invalid twine!"); } + Twine(const Twine &) = default; + /// Construct from a C string. /// /// We take care here to optimize "" into the empty twine -- this will be @@ -287,6 +290,13 @@ namespace llvm { assert(isValid() && "Invalid twine!"); } + /// Construct from a SmallString. + /*implicit*/ Twine(const SmallVectorImpl<char> &Str) + : LHSKind(SmallStringKind), RHSKind(EmptyKind) { + LHS.smallString = &Str; + assert(isValid() && "Invalid twine!"); + } + /// Construct from a char. explicit Twine(char Val) : LHSKind(CharKind), RHSKind(EmptyKind) { @@ -347,18 +357,18 @@ namespace llvm { // right thing. Yet. /// Construct as the concatenation of a C string and a StringRef. - /*implicit*/ Twine(const char *_LHS, const StringRef &_RHS) - : LHSKind(CStringKind), RHSKind(StringRefKind) { - LHS.cString = _LHS; - RHS.stringRef = &_RHS; + /*implicit*/ Twine(const char *LHS, const StringRef &RHS) + : LHSKind(CStringKind), RHSKind(StringRefKind) { + this->LHS.cString = LHS; + this->RHS.stringRef = &RHS; assert(isValid() && "Invalid twine!"); } /// Construct as the concatenation of a StringRef and a C string. - /*implicit*/ Twine(const StringRef &_LHS, const char *_RHS) - : LHSKind(StringRefKind), RHSKind(CStringKind) { - LHS.stringRef = &_LHS; - RHS.cString = _RHS; + /*implicit*/ Twine(const StringRef &LHS, const char *RHS) + : LHSKind(StringRefKind), RHSKind(CStringKind) { + this->LHS.stringRef = &LHS; + this->RHS.cString = RHS; assert(isValid() && "Invalid twine!"); } @@ -384,14 +394,14 @@ namespace llvm { /// @name Predicate Operations /// @{ - /// isTriviallyEmpty - Check if this twine is trivially empty; a false - /// return value does not necessarily mean the twine is empty. + /// Check if this twine is trivially empty; a false return value does not + /// necessarily mean the twine is empty. bool isTriviallyEmpty() const { return isNullary(); } - /// isSingleStringRef - Return true if this twine can be dynamically - /// accessed as a single StringRef value with getSingleStringRef(). + /// Return true if this twine can be dynamically accessed as a single + /// StringRef value with getSingleStringRef(). bool isSingleStringRef() const { if (getRHSKind() != EmptyKind) return false; @@ -400,6 +410,7 @@ namespace llvm { case CStringKind: case StdStringKind: case StringRefKind: + case SmallStringKind: return true; default: return false; @@ -416,15 +427,14 @@ namespace llvm { /// @name Output & Conversion. /// @{ - /// str - Return the twine contents as a std::string. + /// Return the twine contents as a std::string. std::string str() const; - /// toVector - Write the concatenated string into the given SmallString or - /// SmallVector. + /// Append the concatenated string into the given SmallString or SmallVector. void toVector(SmallVectorImpl<char> &Out) const; - /// getSingleStringRef - This returns the twine as a single StringRef. This - /// method is only valid if isSingleStringRef() is true. + /// This returns the twine as a single StringRef. This method is only valid + /// if isSingleStringRef() is true. StringRef getSingleStringRef() const { assert(isSingleStringRef() &&"This cannot be had as a single stringref!"); switch (getLHSKind()) { @@ -433,18 +443,24 @@ namespace llvm { case CStringKind: return StringRef(LHS.cString); case StdStringKind: return StringRef(*LHS.stdString); case StringRefKind: return *LHS.stringRef; + case SmallStringKind: + return StringRef(LHS.smallString->data(), LHS.smallString->size()); } } - /// toStringRef - This returns the twine as a single StringRef if it can be + /// This returns the twine as a single StringRef if it can be /// represented as such. Otherwise the twine is written into the given /// SmallVector and a StringRef to the SmallVector's data is returned. - StringRef toStringRef(SmallVectorImpl<char> &Out) const; + StringRef toStringRef(SmallVectorImpl<char> &Out) const { + if (isSingleStringRef()) + return getSingleStringRef(); + toVector(Out); + return StringRef(Out.data(), Out.size()); + } - /// 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. + /// 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; diff --git a/include/llvm/ADT/edit_distance.h b/include/llvm/ADT/edit_distance.h index 9ee1edc54e05..c2b2041242aa 100644 --- a/include/llvm/ADT/edit_distance.h +++ b/include/llvm/ADT/edit_distance.h @@ -50,7 +50,7 @@ unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray, // http://en.wikipedia.org/wiki/Levenshtein_distance // // Although the algorithm is typically described using an m x n - // array, only two rows are used at a time, so this implemenation + // array, only two rows are used at a time, so this implementation // just keeps two separate vectors for those two rows. typename ArrayRef<T>::size_type m = FromArray.size(); typename ArrayRef<T>::size_type n = ToArray.size(); diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index 8c19a6f4547a..a7b9306b3a73 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -237,14 +237,14 @@ public: // These are to catch errors when people try to use them as random access // iterators. template<typename T> -void operator-(int, ilist_iterator<T>) LLVM_DELETED_FUNCTION; +void operator-(int, ilist_iterator<T>) = delete; template<typename T> -void operator-(ilist_iterator<T>,int) LLVM_DELETED_FUNCTION; +void operator-(ilist_iterator<T>,int) = delete; template<typename T> -void operator+(int, ilist_iterator<T>) LLVM_DELETED_FUNCTION; +void operator+(int, ilist_iterator<T>) = delete; template<typename T> -void operator+(ilist_iterator<T>,int) LLVM_DELETED_FUNCTION; +void operator+(ilist_iterator<T>,int) = delete; // operator!=/operator== - Allow mixed comparisons without dereferencing // the iterator, which could very likely be pointing to end(). @@ -332,8 +332,8 @@ class iplist : public Traits { // No fundamental reason why iplist can't be copyable, but the default // copy/copy-assign won't do. - iplist(const iplist &) LLVM_DELETED_FUNCTION; - void operator=(const iplist &) LLVM_DELETED_FUNCTION; + iplist(const iplist &) = delete; + void operator=(const iplist &) = delete; public: typedef NodeTy *pointer; diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h index e2c9e5ea6bda..54a288df0173 100644 --- a/include/llvm/ADT/iterator.h +++ b/include/llvm/ADT/iterator.h @@ -150,7 +150,7 @@ class iterator_adaptor_base protected: WrappedIteratorT I; - iterator_adaptor_base() {} + iterator_adaptor_base() = default; template <typename U> explicit iterator_adaptor_base( @@ -231,7 +231,7 @@ struct pointee_iterator pointee_iterator<WrappedIteratorT>, WrappedIteratorT, typename std::iterator_traits<WrappedIteratorT>::iterator_category, T> { - pointee_iterator() {} + pointee_iterator() = default; template <typename U> pointee_iterator(U &&u) : pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {} diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 763f37298811..ac9d21c590a4 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -68,7 +68,7 @@ protected: /// typically called by the run* methods of these subclasses. This may be /// called multiple times. /// - void InitializeAliasAnalysis(Pass *P); + void InitializeAliasAnalysis(Pass *P, const DataLayout *DL); /// getAnalysisUsage - All alias analysis implementations should invoke this /// directly (using AliasAnalysis::getAnalysisUsage(AU)). @@ -84,11 +84,6 @@ public: /// know the sizes of the potential memory references. static uint64_t const UnknownSize = ~UINT64_C(0); - /// getDataLayout - Return a pointer to the current DataLayout object, or - /// null if no DataLayout object is available. - /// - const DataLayout *getDataLayout() const { return DL; } - /// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo /// object, or null if no TargetLibraryInfo object is available. /// @@ -139,6 +134,10 @@ public: Copy.AATags = AAMDNodes(); return Copy; } + + bool operator==(const AliasAnalysis::Location &Other) const { + return Ptr == Other.Ptr && Size == Other.Size && AATags == Other.AATags; + } }; /// getLocation - Fill in Loc with information about the memory reference by @@ -150,6 +149,19 @@ public: Location getLocation(const AtomicRMWInst *RMWI); static Location getLocationForSource(const MemTransferInst *MTI); static Location getLocationForDest(const MemIntrinsic *MI); + Location getLocation(const Instruction *Inst) { + if (auto *I = dyn_cast<LoadInst>(Inst)) + return getLocation(I); + else if (auto *I = dyn_cast<StoreInst>(Inst)) + return getLocation(I); + else if (auto *I = dyn_cast<VAArgInst>(Inst)) + return getLocation(I); + else if (auto *I = dyn_cast<AtomicCmpXchgInst>(Inst)) + return getLocation(I); + else if (auto *I = dyn_cast<AtomicRMWInst>(Inst)) + return getLocation(I); + llvm_unreachable("unsupported memory instruction"); + } /// 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 @@ -357,6 +369,24 @@ public: return (MRB & ModRef) && (MRB & ArgumentPointees); } + /// getModRefInfo - Return information about whether or not an + /// instruction may read or write memory (without regard to a + /// specific location) + ModRefResult getModRefInfo(const Instruction *I) { + if (auto CS = ImmutableCallSite(I)) { + auto MRB = getModRefBehavior(CS); + if (MRB & ModRef) + return ModRef; + else if (MRB & Ref) + return Ref; + else if (MRB & Mod) + return Mod; + return NoModRef; + } + + return getModRefInfo(I, Location()); + } + /// getModRefInfo - Return information about whether or not an instruction may /// read or write the specified memory location. An instruction /// that doesn't read or write memory may be trivially LICM'd for example. @@ -477,6 +507,10 @@ public: ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){ return getModRefInfo(I, Location(P, Size)); } + /// getModRefInfo - Return information about whether a call and an instruction + /// may refer to the same memory locations. + ModRefResult getModRefInfo(Instruction *I, + ImmutableCallSite Call); /// getModRefInfo - Return information about whether two call sites may refer /// to the same set of memory locations. See @@ -585,9 +619,7 @@ struct DenseMapInfo<AliasAnalysis::Location> { } static bool isEqual(const AliasAnalysis::Location &LHS, const AliasAnalysis::Location &RHS) { - return LHS.Ptr == RHS.Ptr && - LHS.Size == RHS.Size && - LHS.AATags == RHS.AATags; + return LHS == RHS; } }; diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index 036d58dfa810..18f95b401e6a 100644 --- a/include/llvm/Analysis/AliasSetTracker.h +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -192,11 +192,6 @@ public: } bool operator!=(const iterator& x) const { return !operator==(x); } - const iterator &operator=(const iterator &I) { - CurNode = I.CurNode; - return *this; - } - value_type &operator*() const { assert(CurNode && "Dereferencing AliasSet.end()!"); return *CurNode; @@ -226,8 +221,8 @@ private: AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) { } - AliasSet(const AliasSet &AS) LLVM_DELETED_FUNCTION; - void operator=(const AliasSet &AS) LLVM_DELETED_FUNCTION; + AliasSet(const AliasSet &AS) = delete; + void operator=(const AliasSet &AS) = delete; PointerRec *getSomePointer() const { return PtrList; @@ -273,7 +268,7 @@ public: /// bool aliasesPointer(const Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo, AliasAnalysis &AA) const; - bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const; + bool aliasesUnknownInst(const Instruction *Inst, AliasAnalysis &AA) const; }; inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) { @@ -363,7 +358,7 @@ public: /// getAliasSetForPointerIfExists - Return the alias set containing the /// location specified if one exists, otherwise return null. - AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size, + AliasSet *getAliasSetForPointerIfExists(const Value *P, uint64_t Size, const AAMDNodes &AAInfo) { return findAliasSetForPointer(P, Size, AAInfo); } @@ -371,11 +366,12 @@ public: /// containsPointer - Return true if the specified location is represented by /// this alias set, false otherwise. This does not modify the AST object or /// alias sets. - bool containsPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo) const; + bool containsPointer(const Value *P, uint64_t Size, + const AAMDNodes &AAInfo) const; /// Return true if the specified instruction "may" (or must) alias one of the /// members in any of the sets. - bool containsUnknown(Instruction *I) const; + bool containsUnknown(const Instruction *I) const; /// getAliasAnalysis - Return the underlying alias analysis object used by /// this tracker. diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h index b129e6796328..1f00b691b305 100644 --- a/include/llvm/Analysis/AssumptionCache.h +++ b/include/llvm/Analysis/AssumptionCache.h @@ -27,6 +27,11 @@ namespace llvm { +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template <typename IRUnitT> class AnalysisManager; +class PreservedAnalyses; + /// \brief A cache of @llvm.assume calls within a function. /// /// This cache provides fast lookup of assumptions within a function by caching @@ -88,6 +93,42 @@ public: } }; +/// \brief A function analysis which provides an \c AssumptionCache. +/// +/// This analysis is intended for use with the new pass manager and will vend +/// assumption caches for a given function. +class AssumptionAnalysis { + static char PassID; + +public: + typedef AssumptionCache Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Provide a name for the analysis for debugging and logging. + static StringRef name() { return "AssumptionAnalysis"; } + + AssumptionAnalysis() {} + AssumptionAnalysis(const AssumptionAnalysis &Arg) {} + AssumptionAnalysis(AssumptionAnalysis &&Arg) {} + AssumptionAnalysis &operator=(const AssumptionAnalysis &RHS) { return *this; } + AssumptionAnalysis &operator=(AssumptionAnalysis &&RHS) { return *this; } + + AssumptionCache run(Function &F) { return AssumptionCache(F); } +}; + +/// \brief Printer pass for the \c AssumptionAnalysis results. +class AssumptionPrinterPass { + raw_ostream &OS; + +public: + explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM); + + static StringRef name() { return "AssumptionPrinterPass"; } +}; + /// \brief An immutable pass that tracks lazily created \c AssumptionCache /// objects. /// @@ -124,7 +165,7 @@ public: AssumptionCache &getAssumptionCache(Function &F); AssumptionCacheTracker(); - ~AssumptionCacheTracker(); + ~AssumptionCacheTracker() override; void releaseMemory() override { AssumptionCaches.shrink_and_clear(); } diff --git a/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h index 3289a2823c0c..f27c32df9283 100644 --- a/include/llvm/Analysis/BlockFrequencyInfo.h +++ b/include/llvm/Analysis/BlockFrequencyInfo.h @@ -34,7 +34,7 @@ public: BlockFrequencyInfo(); - ~BlockFrequencyInfo(); + ~BlockFrequencyInfo() override; void getAnalysisUsage(AnalysisUsage &AU) const override; diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h index 57b515420925..9acc863a7382 100644 --- a/include/llvm/Analysis/BlockFrequencyInfoImpl.h +++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -718,9 +718,6 @@ void IrreducibleGraph::addEdges(const BlockNode &Node, /// /// It has some known flaws. /// -/// - Loop scale is limited to 4096 per loop (2^12) to avoid exhausting -/// BlockFrequency's 64-bit integer precision. -/// /// - The model of irreducible control flow is a rough approximation. /// /// Modelling irreducible control flow exactly involves setting up and diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h index 0d4fe932481b..6a406cd24402 100644 --- a/include/llvm/Analysis/CGSCCPassManager.h +++ b/include/llvm/Analysis/CGSCCPassManager.h @@ -263,8 +263,7 @@ private: template <typename CGSCCPassT> ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT> createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) { - return std::move( - ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass))); + return ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass)); } /// \brief A CGSCC analysis which acts as a proxy for a function analysis @@ -484,7 +483,7 @@ private: template <typename FunctionPassT> CGSCCToFunctionPassAdaptor<FunctionPassT> createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { - return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass))); + return CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)); } } diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index 76d9073799f8..14b88220202a 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -273,8 +273,8 @@ private: /// CalledFunctions array of this or other CallGraphNodes. unsigned NumReferences; - CallGraphNode(const CallGraphNode &) LLVM_DELETED_FUNCTION; - void operator=(const CallGraphNode &) LLVM_DELETED_FUNCTION; + CallGraphNode(const CallGraphNode &) = delete; + void operator=(const CallGraphNode &) = delete; void DropRef() { --NumReferences; } void AddRef() { ++NumReferences; } @@ -318,7 +318,7 @@ public: static char ID; // Class identification, replacement for typeinfo CallGraphWrapperPass(); - virtual ~CallGraphWrapperPass(); + ~CallGraphWrapperPass() override; /// \brief The internal \c CallGraph around which the rest of this interface /// is wrapped. diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h index 09d45ca2b486..541a2109af6c 100644 --- a/include/llvm/Analysis/ConstantFolding.h +++ b/include/llvm/Analysis/ConstantFolding.h @@ -36,16 +36,15 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI = nullptr); + Constant *ConstantFoldInstruction(Instruction *I, const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr); /// ConstantFoldConstantExpression - Attempt to fold the constant expression /// using the specified DataLayout. If successful, the constant result is /// result is returned, if not, null is returned. -Constant *ConstantFoldConstantExpression(const ConstantExpr *CE, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI =nullptr); + Constant * + ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr); /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the /// specified operands. If successful, the constant result is returned, if not, @@ -53,19 +52,19 @@ Constant *ConstantFoldConstantExpression(const ConstantExpr *CE, /// fold instructions like loads and stores, which have no constant expression /// form. /// -Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, - ArrayRef<Constant *> Ops, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI = nullptr); + Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, + ArrayRef<Constant *> Ops, + const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr); /// ConstantFoldCompareInstOperands - Attempt to constant fold a compare /// instruction (icmp/fcmp) with the specified operands. If it fails, it /// returns a constant expression of the specified operands. /// -Constant *ConstantFoldCompareInstOperands(unsigned Predicate, - Constant *LHS, Constant *RHS, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI=nullptr); + Constant * + ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, + Constant *RHS, const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr); /// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue /// instruction with the specified operands and indices. The constant result is @@ -76,8 +75,7 @@ Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, /// ConstantFoldLoadFromConstPtr - Return the value that a load from C would /// produce if it is constant and determinable. If this is not determinable, /// return null. -Constant *ConstantFoldLoadFromConstPtr(Constant *C, - const DataLayout *TD = nullptr); +Constant *ConstantFoldLoadFromConstPtr(Constant *C, const DataLayout &DL); /// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a /// getelementptr constantexpr, return the constant value being addressed by the diff --git a/include/llvm/Analysis/ConstantsScanner.h b/include/llvm/Analysis/ConstantsScanner.h deleted file mode 100644 index d3d0a44bd6d4..000000000000 --- a/include/llvm/Analysis/ConstantsScanner.h +++ /dev/null @@ -1,93 +0,0 @@ -//==- llvm/Analysis/ConstantsScanner.h - Iterate over constants -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class implements an iterator to walk through the constants referenced by -// a method. This is used by the Bitcode & Assembly writers to build constant -// pools. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_CONSTANTSSCANNER_H -#define LLVM_ANALYSIS_CONSTANTSSCANNER_H - -#include "llvm/IR/InstIterator.h" - -namespace llvm { - -class Constant; - -class constant_iterator : public std::iterator<std::forward_iterator_tag, - const Constant, ptrdiff_t> { - const_inst_iterator InstI; // Method instruction iterator - unsigned OpIdx; // Operand index - - typedef constant_iterator _Self; - - inline bool isAtConstant() const { - assert(!InstI.atEnd() && OpIdx < InstI->getNumOperands() && - "isAtConstant called with invalid arguments!"); - return isa<Constant>(InstI->getOperand(OpIdx)); - } - -public: - inline constant_iterator(const Function *F) : InstI(inst_begin(F)), OpIdx(0) { - // Advance to first constant... if we are not already at constant or end - if (InstI != inst_end(F) && // InstI is valid? - (InstI->getNumOperands() == 0 || !isAtConstant())) // Not at constant? - operator++(); - } - - inline constant_iterator(const Function *F, bool) // end ctor - : InstI(inst_end(F)), OpIdx(0) { - } - - inline bool operator==(const _Self& x) const { return OpIdx == x.OpIdx && - InstI == x.InstI; } - inline bool operator!=(const _Self& x) const { return !operator==(x); } - - inline pointer operator*() const { - assert(isAtConstant() && "Dereferenced an iterator at the end!"); - return cast<Constant>(InstI->getOperand(OpIdx)); - } - inline pointer operator->() const { return operator*(); } - - inline _Self& operator++() { // Preincrement implementation - ++OpIdx; - do { - unsigned NumOperands = InstI->getNumOperands(); - while (OpIdx < NumOperands && !isAtConstant()) { - ++OpIdx; - } - - if (OpIdx < NumOperands) return *this; // Found a constant! - ++InstI; - OpIdx = 0; - } while (!InstI.atEnd()); - - return *this; // At the end of the method - } - - inline _Self operator++(int) { // Postincrement - _Self tmp = *this; ++*this; return tmp; - } - - inline bool atEnd() const { return InstI.atEnd(); } -}; - -inline constant_iterator constant_begin(const Function *F) { - return constant_iterator(F); -} - -inline constant_iterator constant_end(const Function *F) { - return constant_iterator(F, true); -} - -} // End llvm namespace - -#endif diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index 1041e3f0a4a9..0b3b2ea42813 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -217,13 +217,9 @@ namespace llvm { /// input dependences are unordered. class FullDependence : public Dependence { public: - FullDependence(Instruction *Src, - Instruction *Dst, - bool LoopIndependent, + FullDependence(Instruction *Src, Instruction *Dst, bool LoopIndependent, unsigned Levels); - ~FullDependence() { - delete[] DV; - } + ~FullDependence() override { delete[] DV; } /// isLoopIndependent - Returns true if this is a loop-independent /// dependence. @@ -266,6 +262,7 @@ namespace llvm { /// if no subscript in the source or destination mention the induction /// variable associated with the loop at this level. bool isScalar(unsigned Level) const override; + private: unsigned short Levels; bool LoopIndependent; @@ -278,8 +275,8 @@ namespace llvm { /// DependenceAnalysis - This class is the main dependence-analysis driver. /// class DependenceAnalysis : public FunctionPass { - void operator=(const DependenceAnalysis &) LLVM_DELETED_FUNCTION; - DependenceAnalysis(const DependenceAnalysis &) LLVM_DELETED_FUNCTION; + void operator=(const DependenceAnalysis &) = delete; + DependenceAnalysis(const DependenceAnalysis &) = delete; public: /// depends - Tests for a dependence between the Src and Dst instructions. /// Returns NULL if no dependence; otherwise, returns a Dependence (or a diff --git a/include/llvm/Analysis/DominanceFrontierImpl.h b/include/llvm/Analysis/DominanceFrontierImpl.h index 735bfb83671d..629ae3809045 100644 --- a/include/llvm/Analysis/DominanceFrontierImpl.h +++ b/include/llvm/Analysis/DominanceFrontierImpl.h @@ -19,11 +19,12 @@ #define LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/DominanceFrontier.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/GenericDomTree.h" namespace llvm { -namespace { template <class BlockT> class DFCalculateWorkObject { public: @@ -37,7 +38,6 @@ public: const DomTreeNodeT *Node; const DomTreeNodeT *parentNode; }; -} template <class BlockT> void DominanceFrontierBase<BlockT>::removeBlock(BlockT *BB) { diff --git a/include/llvm/Analysis/FunctionTargetTransformInfo.h b/include/llvm/Analysis/FunctionTargetTransformInfo.h deleted file mode 100644 index fce5a1a92bd9..000000000000 --- a/include/llvm/Analysis/FunctionTargetTransformInfo.h +++ /dev/null @@ -1,49 +0,0 @@ -//===- llvm/Analysis/FunctionTargetTransformInfo.h --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass wraps a TargetTransformInfo in a FunctionPass so that it can -// forward along the current Function so that we can make target specific -// decisions based on the particular subtarget specified for each Function. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H -#define LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H - -#include "TargetTransformInfo.h" -#include "llvm/Pass.h" - -namespace llvm { -class FunctionTargetTransformInfo final : public FunctionPass { -private: - const Function *Fn; - const TargetTransformInfo *TTI; - - FunctionTargetTransformInfo(const FunctionTargetTransformInfo &) - LLVM_DELETED_FUNCTION; - void operator=(const FunctionTargetTransformInfo &) LLVM_DELETED_FUNCTION; - -public: - static char ID; - FunctionTargetTransformInfo(); - - // Implementation boilerplate. - void getAnalysisUsage(AnalysisUsage &AU) const override; - void releaseMemory() override; - bool runOnFunction(Function &F) override; - - // Shimmed functions from TargetTransformInfo. - void - getUnrollingPreferences(Loop *L, - TargetTransformInfo::UnrollingPreferences &UP) const { - TTI->getUnrollingPreferences(Fn, L, UP); - } -}; -} -#endif diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h index d1f037021773..ae9c1f5bd9ac 100644 --- a/include/llvm/Analysis/IVUsers.h +++ b/include/llvm/Analysis/IVUsers.h @@ -122,7 +122,6 @@ class IVUsers : public LoopPass { LoopInfo *LI; DominatorTree *DT; ScalarEvolution *SE; - const DataLayout *DL; SmallPtrSet<Instruction*,16> Processed; /// IVUses - A list of all tracked IV uses of induction variable expressions diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index a064cfc897b0..79ed74d82411 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -23,7 +23,7 @@ class AssumptionCacheTracker; class CallSite; class DataLayout; class Function; -class TargetTransformInfo; +class TargetTransformInfoWrapperPass; namespace InlineConstants { // Various magic constants used to adjust heuristics. @@ -77,7 +77,7 @@ public: } /// \brief Test whether the inline cost is low enough for inlining. - LLVM_EXPLICIT operator bool() const { + explicit operator bool() const { return Cost < Threshold; } @@ -100,14 +100,14 @@ public: /// \brief Cost analyzer used by inliner. class InlineCostAnalysis : public CallGraphSCCPass { - const TargetTransformInfo *TTI; + TargetTransformInfoWrapperPass *TTIWP; AssumptionCacheTracker *ACT; public: static char ID; InlineCostAnalysis(); - ~InlineCostAnalysis(); + ~InlineCostAnalysis() override; // Pass interface implementation. void getAnalysisUsage(AnalysisUsage &AU) const override; diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index b88e0899f19a..706bd8000d3a 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -49,7 +49,7 @@ 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 DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -58,7 +58,7 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -67,7 +67,7 @@ namespace llvm { /// Given operands for an FAdd, see if we can fold the result. If not, this /// returns null. Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -76,7 +76,7 @@ namespace llvm { /// Given operands for an FSub, see if we can fold the result. If not, this /// returns null. Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -85,7 +85,7 @@ namespace llvm { /// Given operands for an FMul, see if we can fold the result. If not, this /// returns null. Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -93,7 +93,7 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -101,8 +101,7 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + Value *SimplifySDivInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -110,8 +109,7 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + Value *SimplifyUDivInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -119,8 +117,8 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + Value *SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -128,8 +126,7 @@ namespace llvm { /// SimplifySRemInst - Given operands for an SRem, see if we can /// fold the result. If not, this returns null. - Value *SimplifySRemInst(Value *LHS, Value *RHS, - const DataLayout *TD = nullptr, + Value *SimplifySRemInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -137,8 +134,7 @@ namespace llvm { /// SimplifyURemInst - Given operands for a URem, see if we can /// fold the result. If not, this returns null. - Value *SimplifyURemInst(Value *LHS, Value *RHS, - const DataLayout *TD = nullptr, + Value *SimplifyURemInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -146,8 +142,8 @@ namespace llvm { /// SimplifyFRemInst - Given operands for an FRem, see if we can /// fold the result. If not, this returns null. - Value *SimplifyFRemInst(Value *LHS, Value *RHS, - const DataLayout *TD = nullptr, + Value *SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -156,7 +152,7 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -165,7 +161,7 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -174,7 +170,7 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -182,7 +178,7 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -190,7 +186,7 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -198,7 +194,7 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -207,7 +203,7 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -216,7 +212,7 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -225,7 +221,7 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -233,7 +229,7 @@ namespace llvm { /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can /// fold the result. If not, this returns null. - Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout *TD = nullptr, + Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -242,8 +238,7 @@ namespace llvm { /// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we /// can fold the result. If not, this returns null. Value *SimplifyInsertValueInst(Value *Agg, Value *Val, - ArrayRef<unsigned> Idxs, - const DataLayout *TD = nullptr, + ArrayRef<unsigned> Idxs, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -251,7 +246,7 @@ namespace llvm { /// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold /// the result. If not, this returns null. - Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = nullptr, + Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -263,7 +258,7 @@ 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 DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -272,18 +267,28 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); + /// SimplifyFPBinOp - Given operands for a BinaryOperator, see if we can + /// fold the result. If not, this returns null. + /// In contrast to SimplifyBinOp, try to use FastMathFlag when folding the + /// result. In case we don't need FastMathFlags, simply fall to SimplifyBinOp. + Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS, + const FastMathFlags &FMF, const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// \brief Given a function and iterators over arguments, see if we can fold /// the result. /// /// If this call could not be simplified returns null. Value *SimplifyCall(Value *V, User::op_iterator ArgBegin, - User::op_iterator ArgEnd, const DataLayout *TD = nullptr, + User::op_iterator ArgEnd, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -293,8 +298,7 @@ namespace llvm { /// result. /// /// If this call could not be simplified returns null. - Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, - const DataLayout *TD = nullptr, + Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -302,7 +306,7 @@ namespace llvm { /// SimplifyInstruction - See if we can compute a simplified version of this /// instruction. If not, this returns null. - Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = nullptr, + Value *SimplifyInstruction(Instruction *I, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr); @@ -316,7 +320,6 @@ namespace llvm { /// /// The function returns true if any simplifications were performed. bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV, - const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr); @@ -328,7 +331,6 @@ namespace llvm { /// of the users impacted. It returns true if any simplifications were /// performed. bool recursivelySimplifyInstruction(Instruction *I, - const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr); diff --git a/include/llvm/Analysis/IntervalIterator.h b/include/llvm/Analysis/IntervalIterator.h index 3b51d44099fa..655ce2dab413 100644 --- a/include/llvm/Analysis/IntervalIterator.h +++ b/include/llvm/Analysis/IntervalIterator.h @@ -78,7 +78,7 @@ inline void addNodeToInterval(Interval *Int, BasicBlock *BB) { // inline void addNodeToInterval(Interval *Int, Interval *I) { // Add all of the nodes in I as new nodes in Int. - copy(I->Nodes.begin(), I->Nodes.end(), back_inserter(Int->Nodes)); + Int->Nodes.insert(Int->Nodes.end(), I->Nodes.begin(), I->Nodes.end()); } @@ -94,7 +94,6 @@ class IntervalIterator { bool IOwnMem; // If True, delete intervals when done with them // See file header for conditions of use public: - typedef IntervalIterator<NodeTy, OrigContainer_t> _Self; typedef std::forward_iterator_tag iterator_category; IntervalIterator() {} // End iterator, empty stack @@ -105,6 +104,12 @@ public: } } + IntervalIterator(IntervalIterator &&x) + : IntStack(std::move(x.IntStack)), Visited(std::move(x.Visited)), + OrigContainer(x.OrigContainer), IOwnMem(x.IOwnMem) { + x.IOwnMem = false; + } + IntervalIterator(IntervalPartition &IP, bool OwnMemory) : IOwnMem(OwnMemory) { OrigContainer = &IP; if (!ProcessInterval(IP.getRootInterval())) { @@ -112,7 +117,7 @@ public: } } - inline ~IntervalIterator() { + ~IntervalIterator() { if (IOwnMem) while (!IntStack.empty()) { delete operator*(); @@ -120,15 +125,17 @@ public: } } - inline bool operator==(const _Self& x) const { return IntStack == x.IntStack;} - inline bool operator!=(const _Self& x) const { return !operator==(x); } + bool operator==(const IntervalIterator &x) const { + return IntStack == x.IntStack; + } + bool operator!=(const IntervalIterator &x) const { return !(*this == x); } - inline const Interval *operator*() const { return IntStack.back().first; } - inline Interval *operator*() { return IntStack.back().first; } - inline const Interval *operator->() const { return operator*(); } - inline Interval *operator->() { return operator*(); } + const Interval *operator*() const { return IntStack.back().first; } + Interval *operator*() { return IntStack.back().first; } + const Interval *operator->() const { return operator*(); } + Interval *operator->() { return operator*(); } - _Self& operator++() { // Preincrement + IntervalIterator &operator++() { // Preincrement assert(!IntStack.empty() && "Attempting to use interval iterator at end!"); do { // All of the intervals on the stack have been visited. Try visiting @@ -150,8 +157,10 @@ public: return *this; } - inline _Self operator++(int) { // Postincrement - _Self tmp = *this; ++*this; return tmp; + IntervalIterator operator++(int) { // Postincrement + IntervalIterator tmp = *this; + ++*this; + return tmp; } private: diff --git a/include/llvm/Analysis/IteratedDominanceFrontier.h b/include/llvm/Analysis/IteratedDominanceFrontier.h new file mode 100644 index 000000000000..5a339f10f50f --- /dev/null +++ b/include/llvm/Analysis/IteratedDominanceFrontier.h @@ -0,0 +1,96 @@ +//===- IteratedDominanceFrontier.h - Calculate IDF --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \brief Compute iterated dominance frontiers using a linear time algorithm. +/// +/// The algorithm used here is based on: +/// +/// Sreedhar and Gao. A linear time algorithm for placing phi-nodes. +/// In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium on Principles of +/// Programming Languages +/// POPL '95. ACM, New York, NY, 62-73. +/// +/// It has been modified to not explicitly use the DJ graph data structure and +/// to directly compute pruned SSA using per-variable liveness information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_IDF_H +#define LLVM_ANALYSIS_IDF_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class BasicBlock; +template <class T> class DomTreeNodeBase; +typedef DomTreeNodeBase<BasicBlock> DomTreeNode; +class DominatorTree; + +/// \brief Determine the iterated dominance frontier, given a set of defining +/// blocks, and optionally, a set of live-in blocks. +/// +/// In turn, the results can be used to place phi nodes. +/// +/// This algorithm is a linear time computation of Iterated Dominance Frontiers, +/// pruned using the live-in set. +/// By default, liveness is not used to prune the IDF computation. +class IDFCalculator { + +public: + IDFCalculator(DominatorTree &DT) : DT(DT), useLiveIn(false) {} + + /// \brief Give the IDF calculator the set of blocks in which the value is + /// defined. This is equivalent to the set of starting blocks it should be + /// calculating the IDF for (though later gets pruned based on liveness). + /// + /// Note: This set *must* live for the entire lifetime of the IDF calculator. + void setDefiningBlocks(const SmallPtrSetImpl<BasicBlock *> &Blocks) { + DefBlocks = &Blocks; + } + + /// \brief Give the IDF calculator the set of blocks in which the value is + /// live on entry to the block. This is used to prune the IDF calculation to + /// not include blocks where any phi insertion would be dead. + /// + /// Note: This set *must* live for the entire lifetime of the IDF calculator. + + void setLiveInBlocks(const SmallPtrSetImpl<BasicBlock *> &Blocks) { + LiveInBlocks = &Blocks; + useLiveIn = true; + } + + /// \brief Reset the live-in block set to be empty, and tell the IDF + /// calculator to not use liveness anymore. + void resetLiveInBlocks() { + LiveInBlocks = nullptr; + useLiveIn = false; + } + + /// \brief Calculate iterated dominance frontiers + /// + /// This uses the linear-time phi algorithm based on DJ-graphs mentioned in + /// the file-level comment. It performs DF->IDF pruning using the live-in + /// set, to avoid computing the IDF for blocks where an inserted PHI node + /// would be dead. + void calculate(SmallVectorImpl<BasicBlock *> &IDFBlocks); + +private: + DominatorTree &DT; + bool useLiveIn; + DenseMap<DomTreeNode *, unsigned> DomLevels; + const SmallPtrSetImpl<BasicBlock *> *LiveInBlocks; + const SmallPtrSetImpl<BasicBlock *> *DefBlocks; + SmallVector<BasicBlock *, 32> PHIBlocks; +}; +} +#endif diff --git a/include/llvm/Analysis/JumpInstrTableInfo.h b/include/llvm/Analysis/JumpInstrTableInfo.h index 591e794a3901..b6dad478cdf2 100644 --- a/include/llvm/Analysis/JumpInstrTableInfo.h +++ b/include/llvm/Analysis/JumpInstrTableInfo.h @@ -39,7 +39,7 @@ public: /// The default byte alignment for jump tables is 16, which is large but /// usually safe. JumpInstrTableInfo(uint64_t ByteAlign = 16); - virtual ~JumpInstrTableInfo(); + ~JumpInstrTableInfo() override; const char *getPassName() const override { return "Jump-Instruction Table Info"; } diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h index 9a67d52c3696..1051cff5efb7 100644 --- a/include/llvm/Analysis/LazyValueInfo.h +++ b/include/llvm/Analysis/LazyValueInfo.h @@ -29,18 +29,17 @@ namespace llvm { /// This pass computes, caches, and vends lazy value constraint information. class LazyValueInfo : public FunctionPass { AssumptionCache *AC; - const DataLayout *DL; class TargetLibraryInfo *TLI; DominatorTree *DT; void *PImpl; - LazyValueInfo(const LazyValueInfo&) LLVM_DELETED_FUNCTION; - void operator=(const LazyValueInfo&) LLVM_DELETED_FUNCTION; + LazyValueInfo(const LazyValueInfo&) = delete; + void operator=(const LazyValueInfo&) = delete; public: static char ID; LazyValueInfo() : FunctionPass(ID), PImpl(nullptr) { initializeLazyValueInfoPass(*PassRegistry::getPassRegistry()); } - ~LazyValueInfo() { assert(!PImpl && "releaseMemory not called"); } + ~LazyValueInfo() override { assert(!PImpl && "releaseMemory not called"); } /// This is used to return true/false/dunno results. enum Tristate { diff --git a/include/llvm/Analysis/LibCallAliasAnalysis.h b/include/llvm/Analysis/LibCallAliasAnalysis.h index 4c03c922447c..df95e0e6fdc2 100644 --- a/include/llvm/Analysis/LibCallAliasAnalysis.h +++ b/include/llvm/Analysis/LibCallAliasAnalysis.h @@ -15,6 +15,7 @@ #define LLVM_ANALYSIS_LIBCALLALIASANALYSIS_H #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/IR/Module.h" #include "llvm/Pass.h" namespace llvm { @@ -35,8 +36,8 @@ namespace llvm { : FunctionPass(ID), LCI(LC) { initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry()); } - ~LibCallAliasAnalysis(); - + ~LibCallAliasAnalysis() override; + ModRefResult getModRefInfo(ImmutableCallSite CS, const Location &Loc) override; @@ -48,11 +49,8 @@ namespace llvm { void getAnalysisUsage(AnalysisUsage &AU) const override; - bool runOnFunction(Function &F) override { - InitializeAliasAnalysis(this); // set up super class - return false; - } - + bool runOnFunction(Function &F) override; + /// getAdjustedAnalysisPointer - This method is used when a pass implements /// an analysis interface through multiple inheritance. If needed, it /// should override this to adjust the this pointer as needed for the diff --git a/include/llvm/Analysis/LibCallSemantics.h b/include/llvm/Analysis/LibCallSemantics.h index 8bd747f03970..34831b2849dd 100644 --- a/include/llvm/Analysis/LibCallSemantics.h +++ b/include/llvm/Analysis/LibCallSemantics.h @@ -18,6 +18,7 @@ #include "llvm/Analysis/AliasAnalysis.h" namespace llvm { +class InvokeInst; /// LibCallLocationInfo - This struct describes a set of memory locations that /// are accessed by libcalls. Identification of a location is doing with a @@ -162,6 +163,52 @@ namespace llvm { virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0; }; + enum class EHPersonality { + Unknown, + GNU_Ada, + GNU_C, + GNU_CXX, + GNU_ObjC, + MSVC_X86SEH, + MSVC_Win64SEH, + MSVC_CXX, + }; + + /// \brief See if the given exception handling personality function is one + /// that we understand. If so, return a description of it; otherwise return + /// Unknown. + EHPersonality classifyEHPersonality(const Value *Pers); + + /// \brief Returns true if this personality function catches asynchronous + /// exceptions. + inline bool isAsynchronousEHPersonality(EHPersonality Pers) { + // The two SEH personality functions can catch asynch exceptions. We assume + // unknown personalities don't catch asynch exceptions. + switch (Pers) { + case EHPersonality::MSVC_X86SEH: + case EHPersonality::MSVC_Win64SEH: + return true; + default: return false; + } + llvm_unreachable("invalid enum"); + } + + /// \brief Returns true if this is an MSVC personality function. + inline bool isMSVCEHPersonality(EHPersonality Pers) { + // The two SEH personality functions can catch asynch exceptions. We assume + // unknown personalities don't catch asynch exceptions. + switch (Pers) { + case EHPersonality::MSVC_CXX: + case EHPersonality::MSVC_X86SEH: + case EHPersonality::MSVC_Win64SEH: + return true; + default: return false; + } + llvm_unreachable("invalid enum"); + } + + bool canSimplifyInvokeNoUnwind(const InvokeInst *II); + } // end namespace llvm #endif diff --git a/include/llvm/Analysis/Loads.h b/include/llvm/Analysis/Loads.h index 0fe34539f8f7..42667d2af14a 100644 --- a/include/llvm/Analysis/Loads.h +++ b/include/llvm/Analysis/Loads.h @@ -27,8 +27,7 @@ class MDNode; /// specified pointer, we do a quick local scan of the basic block containing /// ScanFrom, to determine if the address is already accessed. bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, - unsigned Align, - const DataLayout *TD = nullptr); + unsigned Align); /// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at /// the instruction before ScanFrom) checking to see if we have the value at diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h new file mode 100644 index 000000000000..c14e1451f338 --- /dev/null +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -0,0 +1,552 @@ +//===- llvm/Analysis/LoopAccessAnalysis.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 defines the interface for the loop memory dependence framework that +// was originally developed for the Loop Vectorizer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOPACCESSANALYSIS_H +#define LLVM_ANALYSIS_LOOPACCESSANALYSIS_H + +#include "llvm/ADT/EquivalenceClasses.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class Value; +class DataLayout; +class AliasAnalysis; +class ScalarEvolution; +class Loop; +class SCEV; + +/// Optimization analysis message produced during vectorization. Messages inform +/// the user why vectorization did not occur. +class LoopAccessReport { + std::string Message; + const Instruction *Instr; + +protected: + LoopAccessReport(const Twine &Message, const Instruction *I) + : Message(Message.str()), Instr(I) {} + +public: + LoopAccessReport(const Instruction *I = nullptr) : Instr(I) {} + + template <typename A> LoopAccessReport &operator<<(const A &Value) { + raw_string_ostream Out(Message); + Out << Value; + return *this; + } + + const Instruction *getInstr() const { return Instr; } + + std::string &str() { return Message; } + const std::string &str() const { return Message; } + operator Twine() { return Message; } + + /// \brief Emit an analysis note for \p PassName with the debug location from + /// the instruction in \p Message if available. Otherwise use the location of + /// \p TheLoop. + static void emitAnalysis(const LoopAccessReport &Message, + const Function *TheFunction, + const Loop *TheLoop, + const char *PassName); +}; + +/// \brief Collection of parameters shared beetween the Loop Vectorizer and the +/// Loop Access Analysis. +struct VectorizerParams { + /// \brief Maximum SIMD width. + static const unsigned MaxVectorWidth; + + /// \brief VF as overridden by the user. + static unsigned VectorizationFactor; + /// \brief Interleave factor as overridden by the user. + static unsigned VectorizationInterleave; + /// \brief True if force-vector-interleave was specified by the user. + static bool isInterleaveForced(); + + /// \\brief When performing memory disambiguation checks at runtime do not + /// make more than this number of comparisons. + static unsigned RuntimeMemoryCheckThreshold; +}; + +/// \brief Checks memory dependences among accesses to the same underlying +/// object to determine whether there vectorization is legal or not (and at +/// which vectorization factor). +/// +/// Note: This class will compute a conservative dependence for access to +/// different underlying pointers. Clients, such as the loop vectorizer, will +/// sometimes deal these potential dependencies by emitting runtime checks. +/// +/// We use the ScalarEvolution framework to symbolically evalutate access +/// functions pairs. Since we currently don't restructure the loop we can rely +/// on the program order of memory accesses to determine their safety. +/// At the moment we will only deem accesses as safe for: +/// * A negative constant distance assuming program order. +/// +/// Safe: tmp = a[i + 1]; OR a[i + 1] = x; +/// a[i] = tmp; y = a[i]; +/// +/// The latter case is safe because later checks guarantuee that there can't +/// be a cycle through a phi node (that is, we check that "x" and "y" is not +/// the same variable: a header phi can only be an induction or a reduction, a +/// reduction can't have a memory sink, an induction can't have a memory +/// source). This is important and must not be violated (or we have to +/// resort to checking for cycles through memory). +/// +/// * A positive constant distance assuming program order that is bigger +/// than the biggest memory access. +/// +/// tmp = a[i] OR b[i] = x +/// a[i+2] = tmp y = b[i+2]; +/// +/// Safe distance: 2 x sizeof(a[0]), and 2 x sizeof(b[0]), respectively. +/// +/// * Zero distances and all accesses have the same size. +/// +class MemoryDepChecker { +public: + typedef PointerIntPair<Value *, 1, bool> MemAccessInfo; + typedef SmallPtrSet<MemAccessInfo, 8> MemAccessInfoSet; + /// \brief Set of potential dependent memory accesses. + typedef EquivalenceClasses<MemAccessInfo> DepCandidates; + + /// \brief Dependece between memory access instructions. + struct Dependence { + /// \brief The type of the dependence. + enum DepType { + // No dependence. + NoDep, + // We couldn't determine the direction or the distance. + Unknown, + // Lexically forward. + Forward, + // Forward, but if vectorized, is likely to prevent store-to-load + // forwarding. + ForwardButPreventsForwarding, + // Lexically backward. + Backward, + // Backward, but the distance allows a vectorization factor of + // MaxSafeDepDistBytes. + BackwardVectorizable, + // Same, but may prevent store-to-load forwarding. + BackwardVectorizableButPreventsForwarding + }; + + /// \brief String version of the types. + static const char *DepName[]; + + /// \brief Index of the source of the dependence in the InstMap vector. + unsigned Source; + /// \brief Index of the destination of the dependence in the InstMap vector. + unsigned Destination; + /// \brief The type of the dependence. + DepType Type; + + Dependence(unsigned Source, unsigned Destination, DepType Type) + : Source(Source), Destination(Destination), Type(Type) {} + + /// \brief Dependence types that don't prevent vectorization. + static bool isSafeForVectorization(DepType Type); + + /// \brief Dependence types that can be queried from the analysis. + static bool isInterestingDependence(DepType Type); + + /// \brief Lexically backward dependence types. + bool isPossiblyBackward() const; + + /// \brief Print the dependence. \p Instr is used to map the instruction + /// indices to instructions. + void print(raw_ostream &OS, unsigned Depth, + const SmallVectorImpl<Instruction *> &Instrs) const; + }; + + MemoryDepChecker(ScalarEvolution *Se, const Loop *L) + : SE(Se), InnermostLoop(L), AccessIdx(0), + ShouldRetryWithRuntimeCheck(false), SafeForVectorization(true), + RecordInterestingDependences(true) {} + + /// \brief Register the location (instructions are given increasing numbers) + /// of a write access. + void addAccess(StoreInst *SI) { + Value *Ptr = SI->getPointerOperand(); + Accesses[MemAccessInfo(Ptr, true)].push_back(AccessIdx); + InstMap.push_back(SI); + ++AccessIdx; + } + + /// \brief Register the location (instructions are given increasing numbers) + /// of a write access. + void addAccess(LoadInst *LI) { + Value *Ptr = LI->getPointerOperand(); + Accesses[MemAccessInfo(Ptr, false)].push_back(AccessIdx); + InstMap.push_back(LI); + ++AccessIdx; + } + + /// \brief Check whether the dependencies between the accesses are safe. + /// + /// Only checks sets with elements in \p CheckDeps. + bool areDepsSafe(DepCandidates &AccessSets, MemAccessInfoSet &CheckDeps, + const ValueToValueMap &Strides); + + /// \brief No memory dependence was encountered that would inhibit + /// vectorization. + bool isSafeForVectorization() const { return SafeForVectorization; } + + /// \brief The maximum number of bytes of a vector register we can vectorize + /// the accesses safely with. + unsigned getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; } + + /// \brief In same cases when the dependency check fails we can still + /// vectorize the loop with a dynamic array access check. + bool shouldRetryWithRuntimeCheck() { return ShouldRetryWithRuntimeCheck; } + + /// \brief Returns the interesting dependences. If null is returned we + /// exceeded the MaxInterestingDependence threshold and this information is + /// not available. + const SmallVectorImpl<Dependence> *getInterestingDependences() const { + return RecordInterestingDependences ? &InterestingDependences : nullptr; + } + + void clearInterestingDependences() { InterestingDependences.clear(); } + + /// \brief The vector of memory access instructions. The indices are used as + /// instruction identifiers in the Dependence class. + const SmallVectorImpl<Instruction *> &getMemoryInstructions() const { + return InstMap; + } + + /// \brief Find the set of instructions that read or write via \p Ptr. + SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr, + bool isWrite) const; + +private: + ScalarEvolution *SE; + const Loop *InnermostLoop; + + /// \brief Maps access locations (ptr, read/write) to program order. + DenseMap<MemAccessInfo, std::vector<unsigned> > Accesses; + + /// \brief Memory access instructions in program order. + SmallVector<Instruction *, 16> InstMap; + + /// \brief The program order index to be used for the next instruction. + unsigned AccessIdx; + + // We can access this many bytes in parallel safely. + unsigned MaxSafeDepDistBytes; + + /// \brief If we see a non-constant dependence distance we can still try to + /// vectorize this loop with runtime checks. + bool ShouldRetryWithRuntimeCheck; + + /// \brief No memory dependence was encountered that would inhibit + /// vectorization. + bool SafeForVectorization; + + //// \brief True if InterestingDependences reflects the dependences in the + //// loop. If false we exceeded MaxInterestingDependence and + //// InterestingDependences is invalid. + bool RecordInterestingDependences; + + /// \brief Interesting memory dependences collected during the analysis as + /// defined by isInterestingDependence. Only valid if + /// RecordInterestingDependences is true. + SmallVector<Dependence, 8> InterestingDependences; + + /// \brief Check whether there is a plausible dependence between the two + /// accesses. + /// + /// Access \p A must happen before \p B in program order. The two indices + /// identify the index into the program order map. + /// + /// This function checks whether there is a plausible dependence (or the + /// absence of such can't be proved) between the two accesses. If there is a + /// plausible dependence but the dependence distance is bigger than one + /// element access it records this distance in \p MaxSafeDepDistBytes (if this + /// distance is smaller than any other distance encountered so far). + /// Otherwise, this function returns true signaling a possible dependence. + Dependence::DepType isDependent(const MemAccessInfo &A, unsigned AIdx, + const MemAccessInfo &B, unsigned BIdx, + const ValueToValueMap &Strides); + + /// \brief Check whether the data dependence could prevent store-load + /// forwarding. + bool couldPreventStoreLoadForward(unsigned Distance, unsigned TypeByteSize); +}; + +/// \brief Drive the analysis of memory accesses in the loop +/// +/// This class is responsible for analyzing the memory accesses of a loop. It +/// collects the accesses and then its main helper the AccessAnalysis class +/// finds and categorizes the dependences in buildDependenceSets. +/// +/// For memory dependences that can be analyzed at compile time, it determines +/// whether the dependence is part of cycle inhibiting vectorization. This work +/// is delegated to the MemoryDepChecker class. +/// +/// For memory dependences that cannot be determined at compile time, it +/// generates run-time checks to prove independence. This is done by +/// AccessAnalysis::canCheckPtrAtRT and the checks are maintained by the +/// RuntimePointerCheck class. +class LoopAccessInfo { +public: + /// This struct holds information about the memory runtime legality check that + /// a group of pointers do not overlap. + struct RuntimePointerCheck { + RuntimePointerCheck() : Need(false) {} + + /// Reset the state of the pointer runtime information. + void reset() { + Need = false; + Pointers.clear(); + Starts.clear(); + Ends.clear(); + IsWritePtr.clear(); + DependencySetId.clear(); + AliasSetId.clear(); + } + + /// Insert a pointer and calculate the start and end SCEVs. + void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr, + unsigned DepSetId, unsigned ASId, + const ValueToValueMap &Strides); + + /// \brief No run-time memory checking is necessary. + bool empty() const { return Pointers.empty(); } + + /// \brief Decide whether we need to issue a run-time check for pointer at + /// index \p I and \p J to prove their independence. + /// + /// If \p PtrPartition is set, it contains the partition number for + /// pointers (-1 if the pointer belongs to multiple partitions). In this + /// case omit checks between pointers belonging to the same partition. + bool needsChecking(unsigned I, unsigned J, + const SmallVectorImpl<int> *PtrPartition) const; + + /// \brief Return true if any pointer requires run-time checking according + /// to needsChecking. + bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const; + + /// \brief Print the list run-time memory checks necessary. + /// + /// If \p PtrPartition is set, it contains the partition number for + /// pointers (-1 if the pointer belongs to multiple partitions). In this + /// case omit checks between pointers belonging to the same partition. + void print(raw_ostream &OS, unsigned Depth = 0, + const SmallVectorImpl<int> *PtrPartition = nullptr) const; + + /// This flag indicates if we need to add the runtime check. + bool Need; + /// Holds the pointers that we need to check. + SmallVector<TrackingVH<Value>, 2> Pointers; + /// Holds the pointer value at the beginning of the loop. + SmallVector<const SCEV*, 2> Starts; + /// Holds the pointer value at the end of the loop. + SmallVector<const SCEV*, 2> Ends; + /// Holds the information if this pointer is used for writing to memory. + SmallVector<bool, 2> IsWritePtr; + /// Holds the id of the set of pointers that could be dependent because of a + /// shared underlying object. + SmallVector<unsigned, 2> DependencySetId; + /// Holds the id of the disjoint alias set to which this pointer belongs. + SmallVector<unsigned, 2> AliasSetId; + }; + + LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL, + const TargetLibraryInfo *TLI, AliasAnalysis *AA, + DominatorTree *DT, LoopInfo *LI, + const ValueToValueMap &Strides); + + /// Return true we can analyze the memory accesses in the loop and there are + /// no memory dependence cycles. + bool canVectorizeMemory() const { return CanVecMem; } + + const RuntimePointerCheck *getRuntimePointerCheck() const { + return &PtrRtCheck; + } + + /// \brief Number of memchecks required to prove independence of otherwise + /// may-alias pointers. + unsigned getNumRuntimePointerChecks() const { return NumComparisons; } + + /// Return true if the block BB needs to be predicated in order for the loop + /// to be vectorized. + static bool blockNeedsPredication(BasicBlock *BB, Loop *TheLoop, + DominatorTree *DT); + + /// Returns true if the value V is uniform within the loop. + bool isUniform(Value *V) const; + + unsigned getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; } + unsigned getNumStores() const { return NumStores; } + unsigned getNumLoads() const { return NumLoads;} + + /// \brief Add code that checks at runtime if the accessed arrays overlap. + /// + /// Returns a pair of instructions where the first element is the first + /// instruction generated in possibly a sequence of instructions and the + /// second value is the final comparator value or NULL if no check is needed. + /// + /// If \p PtrPartition is set, it contains the partition number for pointers + /// (-1 if the pointer belongs to multiple partitions). In this case omit + /// checks between pointers belonging to the same partition. + std::pair<Instruction *, Instruction *> + addRuntimeCheck(Instruction *Loc, + const SmallVectorImpl<int> *PtrPartition = nullptr) const; + + /// \brief The diagnostics report generated for the analysis. E.g. why we + /// couldn't analyze the loop. + const Optional<LoopAccessReport> &getReport() const { return Report; } + + /// \brief the Memory Dependence Checker which can determine the + /// loop-independent and loop-carried dependences between memory accesses. + const MemoryDepChecker &getDepChecker() const { return DepChecker; } + + /// \brief Return the list of instructions that use \p Ptr to read or write + /// memory. + SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr, + bool isWrite) const { + return DepChecker.getInstructionsForAccess(Ptr, isWrite); + } + + /// \brief Print the information about the memory accesses in the loop. + void print(raw_ostream &OS, unsigned Depth = 0) const; + + /// \brief Used to ensure that if the analysis was run with speculating the + /// value of symbolic strides, the client queries it with the same assumption. + /// Only used in DEBUG build but we don't want NDEBUG-dependent ABI. + unsigned NumSymbolicStrides; + + /// \brief Checks existence of store to invariant address inside loop. + /// If the loop has any store to invariant address, then it returns true, + /// else returns false. + bool hasStoreToLoopInvariantAddress() const { + return StoreToLoopInvariantAddress; + } + +private: + /// \brief Analyze the loop. Substitute symbolic strides using Strides. + void analyzeLoop(const ValueToValueMap &Strides); + + /// \brief Check if the structure of the loop allows it to be analyzed by this + /// pass. + bool canAnalyzeLoop(); + + void emitAnalysis(LoopAccessReport &Message); + + /// We need to check that all of the pointers in this list are disjoint + /// at runtime. + RuntimePointerCheck PtrRtCheck; + + /// \brief the Memory Dependence Checker which can determine the + /// loop-independent and loop-carried dependences between memory accesses. + MemoryDepChecker DepChecker; + + /// \brief Number of memchecks required to prove independence of otherwise + /// may-alias pointers + unsigned NumComparisons; + + Loop *TheLoop; + ScalarEvolution *SE; + const DataLayout &DL; + const TargetLibraryInfo *TLI; + AliasAnalysis *AA; + DominatorTree *DT; + LoopInfo *LI; + + unsigned NumLoads; + unsigned NumStores; + + unsigned MaxSafeDepDistBytes; + + /// \brief Cache the result of analyzeLoop. + bool CanVecMem; + + /// \brief Indicator for storing to uniform addresses. + /// If a loop has write to a loop invariant address then it should be true. + bool StoreToLoopInvariantAddress; + + /// \brief The diagnostics report generated for the analysis. E.g. why we + /// couldn't analyze the loop. + Optional<LoopAccessReport> Report; +}; + +Value *stripIntegerCast(Value *V); + +///\brief Return the SCEV corresponding to a pointer with the symbolic stride +///replaced with constant one. +/// +/// If \p OrigPtr is not null, use it to look up the stride value instead of \p +/// Ptr. \p PtrToStride provides the mapping between the pointer value and its +/// stride as collected by LoopVectorizationLegality::collectStridedAccess. +const SCEV *replaceSymbolicStrideSCEV(ScalarEvolution *SE, + const ValueToValueMap &PtrToStride, + Value *Ptr, Value *OrigPtr = nullptr); + +/// \brief This analysis provides dependence information for the memory accesses +/// of a loop. +/// +/// It runs the analysis for a loop on demand. This can be initiated by +/// querying the loop access info via LAA::getInfo. getInfo return a +/// LoopAccessInfo object. See this class for the specifics of what information +/// is provided. +class LoopAccessAnalysis : public FunctionPass { +public: + static char ID; + + LoopAccessAnalysis() : FunctionPass(ID) { + initializeLoopAccessAnalysisPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + /// \brief Query the result of the loop access information for the loop \p L. + /// + /// If the client speculates (and then issues run-time checks) for the values + /// of symbolic strides, \p Strides provides the mapping (see + /// replaceSymbolicStrideSCEV). If there is no cached result available run + /// the analysis. + const LoopAccessInfo &getInfo(Loop *L, const ValueToValueMap &Strides); + + void releaseMemory() override { + // Invalidate the cache when the pass is freed. + LoopAccessInfoMap.clear(); + } + + /// \brief Print the result of the analysis when invoked with -analyze. + void print(raw_ostream &OS, const Module *M = nullptr) const override; + +private: + /// \brief The cache. + DenseMap<Loop *, std::unique_ptr<LoopAccessInfo>> LoopAccessInfoMap; + + // The used analysis passes. + ScalarEvolution *SE; + const TargetLibraryInfo *TLI; + AliasAnalysis *AA; + DominatorTree *DT; + LoopInfo *LI; +}; +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index bef03e91bbbd..be78c15e7224 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -42,6 +42,11 @@ namespace llvm { +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template <typename IRUnitT> class AnalysisManager; +class PreservedAnalyses; + template<typename T> inline void RemoveFromVector(std::vector<T*> &V, T *N) { typename std::vector<T*>::iterator I = std::find(V.begin(), V.end(), N); @@ -74,9 +79,9 @@ class LoopBase { SmallPtrSet<const BlockT*, 8> DenseBlockSet; - LoopBase(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION; + LoopBase(const LoopBase<BlockT, LoopT> &) = delete; const LoopBase<BlockT, LoopT>& - operator=(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION; + operator=(const LoopBase<BlockT, LoopT> &) = delete; public: /// Loop ctor - This creates an empty loop. LoopBase() : ParentLoop(nullptr) {} @@ -356,11 +361,11 @@ public: /// isLoopInvariant - Return true if the specified value is loop invariant /// - bool isLoopInvariant(Value *V) const; + bool isLoopInvariant(const Value *V) const; /// hasLoopInvariantOperands - Return true if all the operands of the /// specified instruction are loop invariant. - bool hasLoopInvariantOperands(Instruction *I) const; + bool hasLoopInvariantOperands(const Instruction *I) const; /// makeLoopInvariant - If the given value is an instruction inside of the /// loop and it can be hoisted, do so to make it trivially loop-invariant. @@ -459,23 +464,20 @@ public: /// cannot find a terminating instruction with location information, /// it returns an unknown location. DebugLoc getStartLoc() const { - DebugLoc StartLoc; BasicBlock *HeadBB; // Try the pre-header first. - if ((HeadBB = getLoopPreheader()) != nullptr) { - StartLoc = HeadBB->getTerminator()->getDebugLoc(); - if (!StartLoc.isUnknown()) - return StartLoc; - } + if ((HeadBB = getLoopPreheader()) != nullptr) + if (DebugLoc DL = HeadBB->getTerminator()->getDebugLoc()) + return DL; // If we have no pre-header or there are no instructions with debug // info in it, try the header. HeadBB = getHeader(); if (HeadBB) - StartLoc = HeadBB->getTerminator()->getDebugLoc(); + return HeadBB->getTerminator()->getDebugLoc(); - return StartLoc; + return DebugLoc(); } private: @@ -496,18 +498,33 @@ class LoopInfoBase { friend class LoopBase<BlockT, LoopT>; friend class LoopInfo; - void operator=(const LoopInfoBase &) LLVM_DELETED_FUNCTION; - LoopInfoBase(const LoopInfo &) LLVM_DELETED_FUNCTION; + void operator=(const LoopInfoBase &) = delete; + LoopInfoBase(const LoopInfoBase &) = delete; public: LoopInfoBase() { } ~LoopInfoBase() { releaseMemory(); } + LoopInfoBase(LoopInfoBase &&Arg) + : BBMap(std::move(Arg.BBMap)), + TopLevelLoops(std::move(Arg.TopLevelLoops)) { + // We have to clear the arguments top level loops as we've taken ownership. + Arg.TopLevelLoops.clear(); + } + LoopInfoBase &operator=(LoopInfoBase &&RHS) { + BBMap = std::move(RHS.BBMap); + + for (auto *L : TopLevelLoops) + delete L; + TopLevelLoops = std::move(RHS.TopLevelLoops); + RHS.TopLevelLoops.clear(); + return *this; + } + void releaseMemory() { - for (typename std::vector<LoopT *>::iterator I = - TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I) - delete *I; // Delete all of the loops... + BBMap.clear(); - BBMap.clear(); // Reset internal state of analysis + for (auto *L : TopLevelLoops) + delete L; TopLevelLoops.clear(); } @@ -576,8 +593,7 @@ public: /// list with the indicated loop. void changeTopLevelLoop(LoopT *OldLoop, LoopT *NewLoop) { - typename std::vector<LoopT *>::iterator I = - std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop); + auto I = std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop); assert(I != TopLevelLoops.end() && "Old loop not at top level!"); *I = NewLoop; assert(!NewLoop->ParentLoop && !OldLoop->ParentLoop && @@ -595,7 +611,7 @@ public: /// including all of the Loop objects it is nested in and our mapping from /// BasicBlocks to loops. void removeBlock(BlockT *BB) { - typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB); + auto I = BBMap.find(BB); if (I != BBMap.end()) { for (LoopT *L = I->second; L; L = L->getParentLoop()) L->removeBlockFromLoop(BB); @@ -617,8 +633,9 @@ public: void Analyze(DominatorTreeBase<BlockT> &DomTree); // Debugging - void print(raw_ostream &OS) const; + + void verify() const; }; // Implementation in LoopInfoImpl.h @@ -626,99 +643,23 @@ public: __extension__ extern template class LoopInfoBase<BasicBlock, Loop>; #endif -class LoopInfo : public FunctionPass { - LoopInfoBase<BasicBlock, Loop> LI; +class LoopInfo : public LoopInfoBase<BasicBlock, Loop> { + typedef LoopInfoBase<BasicBlock, Loop> BaseT; + friend class LoopBase<BasicBlock, Loop>; - void operator=(const LoopInfo &) LLVM_DELETED_FUNCTION; - LoopInfo(const LoopInfo &) LLVM_DELETED_FUNCTION; + void operator=(const LoopInfo &) = delete; + LoopInfo(const LoopInfo &) = delete; public: - static char ID; // Pass identification, replacement for typeid - - LoopInfo() : FunctionPass(ID) { - initializeLoopInfoPass(*PassRegistry::getPassRegistry()); - } - - LoopInfoBase<BasicBlock, Loop>& getBase() { return LI; } - - /// iterator/begin/end - The interface to the top-level loops in the current - /// function. - /// - typedef LoopInfoBase<BasicBlock, Loop>::iterator iterator; - typedef LoopInfoBase<BasicBlock, Loop>::reverse_iterator reverse_iterator; - inline iterator begin() const { return LI.begin(); } - inline iterator end() const { return LI.end(); } - inline reverse_iterator rbegin() const { return LI.rbegin(); } - inline reverse_iterator rend() const { return LI.rend(); } - bool empty() const { return LI.empty(); } - - /// getLoopFor - Return the inner most loop that BB lives in. If a basic - /// block is in no loop (for example the entry node), null is returned. - /// - inline Loop *getLoopFor(const BasicBlock *BB) const { - return LI.getLoopFor(BB); - } - - /// operator[] - same as getLoopFor... - /// - inline const Loop *operator[](const BasicBlock *BB) const { - return LI.getLoopFor(BB); - } - - /// getLoopDepth - Return the loop nesting level of the specified block. A - /// depth of 0 means the block is not inside any loop. - /// - inline unsigned getLoopDepth(const BasicBlock *BB) const { - return LI.getLoopDepth(BB); - } - - // isLoopHeader - True if the block is a loop header node - inline bool isLoopHeader(BasicBlock *BB) const { - return LI.isLoopHeader(BB); - } - - /// runOnFunction - Calculate the natural loop information. - /// - bool runOnFunction(Function &F) override; - - void verifyAnalysis() const override; - - void releaseMemory() override { LI.releaseMemory(); } - - void print(raw_ostream &O, const Module* M = nullptr) const override; - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - /// removeLoop - This removes the specified top-level loop from this loop info - /// object. The loop is not deleted, as it will presumably be inserted into - /// another loop. - inline Loop *removeLoop(iterator I) { return LI.removeLoop(I); } - - /// changeLoopFor - Change the top-level loop that contains BB to the - /// specified loop. This should be used by transformations that restructure - /// the loop hierarchy tree. - inline void changeLoopFor(BasicBlock *BB, Loop *L) { - LI.changeLoopFor(BB, L); - } + LoopInfo() {} - /// changeTopLevelLoop - Replace the specified loop in the top-level loops - /// list with the indicated loop. - inline void changeTopLevelLoop(Loop *OldLoop, Loop *NewLoop) { - LI.changeTopLevelLoop(OldLoop, NewLoop); - } - - /// addTopLevelLoop - This adds the specified loop to the collection of - /// top-level loops. - inline void addTopLevelLoop(Loop *New) { - LI.addTopLevelLoop(New); + LoopInfo(LoopInfo &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))) {} + LoopInfo &operator=(LoopInfo &&RHS) { + BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); + return *this; } - /// removeBlock - This method completely removes BB from all data structures, - /// including all of the Loop objects it is nested in and our mapping from - /// BasicBlocks to loops. - void removeBlock(BasicBlock *BB) { - LI.removeBlock(BB); - } + // Most of the public interface is provided via LoopInfoBase. /// updateUnloop - Update LoopInfo after removing the last backedge from a /// loop--now the "unloop". This updates the loop forest and parent loops for @@ -748,7 +689,6 @@ public: } }; - // Allow clients to walk the list of nested loops... template <> struct GraphTraits<const Loop*> { typedef const Loop NodeType; @@ -776,6 +716,65 @@ template <> struct GraphTraits<Loop*> { } }; +/// \brief Analysis pass that exposes the \c LoopInfo for a function. +class LoopAnalysis { + static char PassID; + +public: + typedef LoopInfo Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Provide a name for the analysis for debugging and logging. + static StringRef name() { return "LoopAnalysis"; } + + LoopAnalysis() {} + LoopAnalysis(const LoopAnalysis &Arg) {} + LoopAnalysis(LoopAnalysis &&Arg) {} + LoopAnalysis &operator=(const LoopAnalysis &RHS) { return *this; } + LoopAnalysis &operator=(LoopAnalysis &&RHS) { return *this; } + + LoopInfo run(Function &F, AnalysisManager<Function> *AM); +}; + +/// \brief Printer pass for the \c LoopAnalysis results. +class LoopPrinterPass { + raw_ostream &OS; + +public: + explicit LoopPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM); + + static StringRef name() { return "LoopPrinterPass"; } +}; + +/// \brief The legacy pass manager's analysis pass to compute loop information. +class LoopInfoWrapperPass : public FunctionPass { + LoopInfo LI; + +public: + static char ID; // Pass identification, replacement for typeid + + LoopInfoWrapperPass() : FunctionPass(ID) { + initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry()); + } + + LoopInfo &getLoopInfo() { return LI; } + const LoopInfo &getLoopInfo() const { return LI; } + + /// \brief Calculate the natural loop information for a given function. + bool runOnFunction(Function &F) override; + + void verifyAnalysis() const override; + + void releaseMemory() override { LI.releaseMemory(); } + + void print(raw_ostream &O, const Module *M = nullptr) const override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + } // End llvm namespace #endif diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h index 948be0f5ee1e..0490bb1d761a 100644 --- a/include/llvm/Analysis/LoopInfoImpl.h +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -402,7 +402,6 @@ static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges, L->reserveBlocks(NumBlocks); } -namespace { /// Populate all loop data in a stable order during a single forward DFS. template<class BlockT, class LoopT> class PopulateLoopsDFS { @@ -410,9 +409,6 @@ class PopulateLoopsDFS { typedef typename BlockTraits::ChildIteratorType SuccIterTy; LoopInfoBase<BlockT, LoopT> *LI; - DenseSet<const BlockT *> VisitedBlocks; - std::vector<std::pair<BlockT*, SuccIterTy> > DFSStack; - public: PopulateLoopsDFS(LoopInfoBase<BlockT, LoopT> *li): LI(li) {} @@ -421,37 +417,13 @@ public: protected: void insertIntoLoop(BlockT *Block); - - BlockT *dfsSource() { return DFSStack.back().first; } - SuccIterTy &dfsSucc() { return DFSStack.back().second; } - SuccIterTy dfsSuccEnd() { return BlockTraits::child_end(dfsSource()); } - - void pushBlock(BlockT *Block) { - DFSStack.push_back(std::make_pair(Block, BlockTraits::child_begin(Block))); - } }; -} // anonymous /// Top-level driver for the forward DFS within the loop. template<class BlockT, class LoopT> void PopulateLoopsDFS<BlockT, LoopT>::traverse(BlockT *EntryBlock) { - pushBlock(EntryBlock); - VisitedBlocks.insert(EntryBlock); - while (!DFSStack.empty()) { - // Traverse the leftmost path as far as possible. - while (dfsSucc() != dfsSuccEnd()) { - BlockT *BB = *dfsSucc(); - ++dfsSucc(); - if (!VisitedBlocks.insert(BB).second) - continue; - - // Push the next DFS successor onto the stack. - pushBlock(BB); - } - // Visit the top of the stack in postorder and backtrack. - insertIntoLoop(dfsSource()); - DFSStack.pop_back(); - } + for (BlockT *BB : post_order(EntryBlock)) + insertIntoLoop(BB); } /// Add a single Block to its ancestor loops in PostOrder. If the block is a @@ -500,10 +472,9 @@ Analyze(DominatorTreeBase<BlockT> &DomTree) { // Postorder traversal of the dominator tree. DomTreeNodeBase<BlockT>* DomRoot = DomTree.getRootNode(); - for (po_iterator<DomTreeNodeBase<BlockT>*> DomIter = po_begin(DomRoot), - DomEnd = po_end(DomRoot); DomIter != DomEnd; ++DomIter) { + for (auto DomNode : post_order(DomRoot)) { - BlockT *Header = DomIter->getBlock(); + BlockT *Header = DomNode->getBlock(); SmallVector<BlockT *, 4> Backedges; // Check each predecessor of the potential loop header. @@ -545,6 +516,25 @@ void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const { #endif } +template<class BlockT, class LoopT> +void LoopInfoBase<BlockT, LoopT>::verify() const { + DenseSet<const LoopT*> Loops; + for (iterator I = begin(), E = end(); I != E; ++I) { + assert(!(*I)->getParentLoop() && "Top-level loop has a parent!"); + (*I)->verifyLoopNest(&Loops); + } + + // Verify that blocks are mapped to valid loops. +#ifndef NDEBUG + for (auto &Entry : BBMap) { + BlockT *BB = Entry.first; + LoopT *L = Entry.second; + assert(Loops.count(L) && "orphaned loop"); + assert(L->contains(BB) && "orphaned block"); + } +#endif +} + } // End llvm namespace #endif diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index d414680b519d..805a43dfb070 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -82,12 +82,6 @@ static inline CallInst *extractMallocCall(Value *I, return const_cast<CallInst*>(extractMallocCall((const Value*)I, TLI)); } -/// isArrayMalloc - Returns the corresponding CallInst if the instruction -/// is a call to malloc whose array size can be determined and the array size -/// is not constant 1. Otherwise, return NULL. -const CallInst *isArrayMalloc(const Value *I, const DataLayout *DL, - const TargetLibraryInfo *TLI); - /// getMallocType - Returns the PointerType resulting from the malloc call. /// The PointerType depends on the number of bitcast uses of the malloc call: /// 0: PointerType is the malloc calls' return type. @@ -107,11 +101,10 @@ Type *getMallocAllocatedType(const CallInst *CI, const TargetLibraryInfo *TLI); /// then return that multiple. For non-array mallocs, the multiple is /// constant 1. Otherwise, return NULL for mallocs whose array size cannot be /// determined. -Value *getMallocArraySize(CallInst *CI, const DataLayout *DL, +Value *getMallocArraySize(CallInst *CI, const DataLayout &DL, const TargetLibraryInfo *TLI, bool LookThroughSExt = false); - //===----------------------------------------------------------------------===// // calloc Call Utility Functions. // @@ -147,11 +140,9 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) { /// underlying object pointed to by Ptr. /// If RoundToAlign is true, then Size is rounded up to the aligment of allocas, /// byval arguments, and global variables. -bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *DL, +bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, bool RoundToAlign = false); - - typedef std::pair<APInt, APInt> SizeOffsetType; /// \brief Evaluate the size and offset of an object pointed to by a Value* @@ -159,7 +150,7 @@ typedef std::pair<APInt, APInt> SizeOffsetType; class ObjectSizeOffsetVisitor : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> { - const DataLayout *DL; + const DataLayout &DL; const TargetLibraryInfo *TLI; bool RoundToAlign; unsigned IntTyBits; @@ -173,7 +164,7 @@ class ObjectSizeOffsetVisitor } public: - ObjectSizeOffsetVisitor(const DataLayout *DL, const TargetLibraryInfo *TLI, + ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, bool RoundToAlign = false); SizeOffsetType compute(Value *V); @@ -222,7 +213,7 @@ class ObjectSizeOffsetEvaluator typedef DenseMap<const Value*, WeakEvalType> CacheMapTy; typedef SmallPtrSet<const Value*, 8> PtrSetTy; - const DataLayout *DL; + const DataLayout &DL; const TargetLibraryInfo *TLI; LLVMContext &Context; BuilderTy Builder; @@ -238,7 +229,7 @@ class ObjectSizeOffsetEvaluator SizeOffsetEvalType compute_(Value *V); public: - ObjectSizeOffsetEvaluator(const DataLayout *DL, const TargetLibraryInfo *TLI, + ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, bool RoundToAlign = false); SizeOffsetEvalType compute(Value *V); diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index 67fd70a4561f..cf51dd62388f 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/PredIteratorCache.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" @@ -29,7 +30,6 @@ namespace llvm { class CallSite; class AliasAnalysis; class AssumptionCache; - class DataLayout; class MemoryDependenceAnalysis; class PredIteratorCache; class DominatorTree; @@ -324,14 +324,13 @@ namespace llvm { /// Current AA implementation, just a cache. AliasAnalysis *AA; - const DataLayout *DL; DominatorTree *DT; AssumptionCache *AC; - std::unique_ptr<PredIteratorCache> PredCache; + PredIteratorCache PredCache; public: MemoryDependenceAnalysis(); - ~MemoryDependenceAnalysis(); + ~MemoryDependenceAnalysis() override; static char ID; /// Pass Implementation stuff. This doesn't do any analysis eagerly. @@ -421,20 +420,21 @@ namespace llvm { static unsigned getLoadLoadClobberFullWidthSize(const Value *MemLocBase, int64_t MemLocOffs, unsigned MemLocSize, - const LoadInst *LI, - const DataLayout &DL); + const LoadInst *LI); private: MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, BasicBlock::iterator ScanIt, BasicBlock *BB); - bool getNonLocalPointerDepFromBB(const PHITransAddr &Pointer, + bool getNonLocalPointerDepFromBB(Instruction *QueryInst, + const PHITransAddr &Pointer, const AliasAnalysis::Location &Loc, bool isLoad, BasicBlock *BB, SmallVectorImpl<NonLocalDepResult> &Result, DenseMap<BasicBlock*, Value*> &Visited, bool SkipFirstBlock = false); - MemDepResult GetNonLocalInfoForBlock(const AliasAnalysis::Location &Loc, + MemDepResult GetNonLocalInfoForBlock(Instruction *QueryInst, + const AliasAnalysis::Location &Loc, bool isLoad, BasicBlock *BB, NonLocalDepInfo *Cache, unsigned NumSortedEntries); diff --git a/include/llvm/Analysis/PHITransAddr.h b/include/llvm/Analysis/PHITransAddr.h index 38730d8ea4f3..84bb9d8008b5 100644 --- a/include/llvm/Analysis/PHITransAddr.h +++ b/include/llvm/Analysis/PHITransAddr.h @@ -36,9 +36,9 @@ namespace llvm { class PHITransAddr { /// Addr - The actual address we're analyzing. Value *Addr; - - /// The DataLayout we are playing with if known, otherwise null. - const DataLayout *DL; + + /// The DataLayout we are playing with. + const DataLayout &DL; /// TLI - The target library info if known, otherwise null. const TargetLibraryInfo *TLI; @@ -49,7 +49,7 @@ class PHITransAddr { /// InstInputs - The inputs for our symbolic address. SmallVector<Instruction*, 4> InstInputs; public: - PHITransAddr(Value *addr, const DataLayout *DL, AssumptionCache *AC) + PHITransAddr(Value *addr, const DataLayout &DL, AssumptionCache *AC) : Addr(addr), DL(DL), TLI(nullptr), AC(AC) { // If the address is an instruction, the whole thing is considered an input. if (Instruction *I = dyn_cast<Instruction>(Addr)) diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index 10a56059ae10..d112ab1823b4 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -138,6 +138,13 @@ namespace llvm { //===--------------------------------------------------------------------===// // + // createDivergenceAnalysisPass - This pass determines which branches in a GPU + // program are divergent. + // + FunctionPass *createDivergenceAnalysisPass(); + + //===--------------------------------------------------------------------===// + // // Minor pass prototypes, allowing us to expose them through bugpoint and // analyze. FunctionPass *createInstCountPass(); @@ -159,9 +166,13 @@ namespace llvm { // FunctionPass *createMemDepPrinter(); - // createJumpInstrTableInfoPass - This creates a pass that stores information - // about the jump tables created by JumpInstrTables - ImmutablePass *createJumpInstrTableInfoPass(); + //===--------------------------------------------------------------------===// + // + // createMemDerefPrinter - This pass collects memory dereferenceability + // information and prints it with -analyze. + // + FunctionPass *createMemDerefPrinter(); + } #endif diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h index 72cd35754c8a..0f7e2b88d2d7 100644 --- a/include/llvm/Analysis/PostDominators.h +++ b/include/llvm/Analysis/PostDominators.h @@ -30,7 +30,7 @@ struct PostDominatorTree : public FunctionPass { DT = new DominatorTreeBase<BasicBlock>(true); } - ~PostDominatorTree(); + ~PostDominatorTree() override; bool runOnFunction(Function &F) override; diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 6ff7f97d01f5..7ceb086ee0a1 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -115,8 +115,8 @@ public: typedef typename Tr::RegionT RegionT; private: - RegionNodeBase(const RegionNodeBase &) LLVM_DELETED_FUNCTION; - const RegionNodeBase &operator=(const RegionNodeBase &) LLVM_DELETED_FUNCTION; + RegionNodeBase(const RegionNodeBase &) = delete; + const RegionNodeBase &operator=(const RegionNodeBase &) = delete; /// This is the entry basic block that starts this region node. If this is a /// BasicBlock RegionNode, then entry is just the basic block, that this @@ -261,8 +261,8 @@ class RegionBase : public RegionNodeBase<Tr> { typedef typename InvBlockTraits::ChildIteratorType PredIterTy; friend class RegionInfoBase<Tr>; - RegionBase(const RegionBase &) LLVM_DELETED_FUNCTION; - const RegionBase &operator=(const RegionBase &) LLVM_DELETED_FUNCTION; + RegionBase(const RegionBase &) = delete; + const RegionBase &operator=(const RegionBase &) = delete; // Information necessary to manage this Region. RegionInfoT *RI; @@ -674,8 +674,8 @@ class RegionInfoBase { RegionInfoBase(); virtual ~RegionInfoBase(); - RegionInfoBase(const RegionInfoBase &) LLVM_DELETED_FUNCTION; - const RegionInfoBase &operator=(const RegionInfoBase &) LLVM_DELETED_FUNCTION; + RegionInfoBase(const RegionInfoBase &) = delete; + const RegionInfoBase &operator=(const RegionInfoBase &) = delete; DomTreeT *DT; PostDomTreeT *PDT; @@ -820,8 +820,6 @@ public: inline RegionNode(Region *Parent, BasicBlock *Entry, bool isSubRegion = false) : RegionNodeBase<RegionTraits<Function>>(Parent, Entry, isSubRegion) {} - ~RegionNode() {} - bool operator==(const Region &RN) const { return this == reinterpret_cast<const RegionNode *>(&RN); } @@ -842,7 +840,7 @@ class RegionInfo : public RegionInfoBase<RegionTraits<Function>> { public: explicit RegionInfo(); - virtual ~RegionInfo(); + ~RegionInfo() override; // updateStatistics - Update statistic about created regions. void updateStatistics(Region *R) final; @@ -858,7 +856,7 @@ public: static char ID; explicit RegionInfoPass(); - ~RegionInfoPass(); + ~RegionInfoPass() override; RegionInfo &getRegionInfo() { return RI; } diff --git a/include/llvm/Analysis/RegionInfoImpl.h b/include/llvm/Analysis/RegionInfoImpl.h index b0dc26312aaa..b31eefc15f78 100644 --- a/include/llvm/Analysis/RegionInfoImpl.h +++ b/include/llvm/Analysis/RegionInfoImpl.h @@ -487,7 +487,7 @@ void RegionBase<Tr>::print(raw_ostream &OS, bool print_tree, unsigned level, OS.indent(level * 2 + 2); if (Style == PrintBB) { - for (const auto &BB : blocks()) + for (const auto *BB : blocks()) OS << BB->getName() << ", "; // TODO: remove the last "," } else if (Style == PrintRN) { for (const_element_iterator I = element_begin(), E = element_end(); @@ -714,10 +714,8 @@ void RegionInfoBase<Tr>::scanForRegions(FuncT &F, BBtoBBMap *ShortCut) { // regions from the bottom of the dominance tree. If the small regions are // detected first, detection of bigger regions is faster, as we can jump // over the small regions. - for (po_iterator<DomTreeNodeT *> FI = po_begin(N), FE = po_end(N); FI != FE; - ++FI) { - findRegionsWithEntry(FI->getBlock(), ShortCut); - } + for (auto DomNode : post_order(N)) + findRegionsWithEntry(DomNode->getBlock(), ShortCut); } template <class Tr> diff --git a/include/llvm/Analysis/RegionIterator.h b/include/llvm/Analysis/RegionIterator.h index 0daff58475dd..ced58dfabdd5 100644 --- a/include/llvm/Analysis/RegionIterator.h +++ b/include/llvm/Analysis/RegionIterator.h @@ -145,16 +145,6 @@ public: ++*this; return tmp; } - - inline const Self &operator=(const Self &I) { - if (this != &I) { - assert(getNode()->getParent() == I.getNode()->getParent() - && "Cannot assign iterators of two different regions!"); - Node = I.Node; - BItor = I.BItor; - } - return *this; - } }; @@ -240,16 +230,6 @@ public: ++*this; return tmp; } - - inline const Self &operator=(const Self &I) { - if (this != &I) { - assert(Node->getParent() == I.Node->getParent() - && "Cannot assign iterators to two different regions!"); - Node = I.Node; - Itor = I.Itor; - } - return *this; - } }; template<class NodeType, class BlockT, class RegionT> diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index f394e335257f..1d1bd67b61ff 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -71,8 +71,8 @@ namespace llvm { unsigned short SubclassData; private: - SCEV(const SCEV &) LLVM_DELETED_FUNCTION; - void operator=(const SCEV &) LLVM_DELETED_FUNCTION; + SCEV(const SCEV &) = delete; + void operator=(const SCEV &) = delete; public: /// NoWrapFlags are bitfield indices into SubclassData. @@ -82,12 +82,13 @@ namespace llvm { /// operator. NSW is a misnomer that we use to mean no signed overflow or /// underflow. /// - /// AddRec expression may have a no-self-wraparound <NW> property if the - /// result can never reach the start value. This property is independent of - /// the actual start value and step direction. Self-wraparound is defined - /// purely in terms of the recurrence's loop, step size, and - /// bitwidth. Formally, a recurrence with no self-wraparound satisfies: - /// abs(step) * max-iteration(loop) <= unsigned-max(bitwidth). + /// AddRec expressions may have a no-self-wraparound <NW> property if, in + /// the integer domain, abs(step) * max-iteration(loop) <= + /// unsigned-max(bitwidth). This means that the recurrence will never reach + /// its start value if the step is non-zero. Computing the same value on + /// each iteration is not considered wrapping, and recurrences with step = 0 + /// are trivially <NW>. <NW> is independent of the sign of step and the + /// value the add recurrence starts with. /// /// Note that NUW and NSW are also valid properties of a recurrence, and /// either implies NW. For convenience, NW will be set for a recurrence @@ -231,10 +232,6 @@ namespace llvm { /// LoopInfo *LI; - /// The DataLayout information for the target we are targeting. - /// - const DataLayout *DL; - /// TLI - The target library information for the target we are targeting. /// TargetLibraryInfo *TLI; @@ -259,6 +256,10 @@ namespace llvm { /// Mark predicate values currently being processed by isImpliedCond. DenseSet<Value*> PendingLoopPredicates; + /// Set to true by isLoopBackedgeGuardedByCond when we're walking the set of + /// conditions dominating the backedge of a loop. + bool WalkingBEDominatingConds; + /// ExitLimit - Information about the number of loop iterations for which a /// loop exit's branch condition evaluates to the not-taken path. This is a /// temporary pair of exact and max expressions that are eventually @@ -372,44 +373,46 @@ namespace llvm { /// LoopDispositions - Memoized computeLoopDisposition results. DenseMap<const SCEV *, - SmallVector<std::pair<const Loop *, LoopDisposition>, 2> > LoopDispositions; + SmallVector<PointerIntPair<const Loop *, 2, LoopDisposition>, 2>> + LoopDispositions; /// computeLoopDisposition - Compute a LoopDisposition value. LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L); /// BlockDispositions - Memoized computeBlockDisposition results. - DenseMap<const SCEV *, - SmallVector<std::pair<const BasicBlock *, BlockDisposition>, 2> > BlockDispositions; + DenseMap< + const SCEV *, + SmallVector<PointerIntPair<const BasicBlock *, 2, BlockDisposition>, 2>> + BlockDispositions; /// computeBlockDisposition - Compute a BlockDisposition value. BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB); - /// UnsignedRanges - Memoized results from getUnsignedRange + /// UnsignedRanges - Memoized results from getRange DenseMap<const SCEV *, ConstantRange> UnsignedRanges; - /// SignedRanges - Memoized results from getSignedRange + /// SignedRanges - Memoized results from getRange 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; - } + /// RangeSignHint - Used to parameterize getRange + enum RangeSignHint { HINT_RANGE_UNSIGNED, HINT_RANGE_SIGNED }; + + /// setRange - Set the memoized range for the given SCEV. + const ConstantRange &setRange(const SCEV *S, RangeSignHint Hint, + const ConstantRange &CR) { + DenseMap<const SCEV *, ConstantRange> &Cache = + Hint == HINT_RANGE_UNSIGNED ? UnsignedRanges : SignedRanges; - /// 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)); + Cache.insert(std::make_pair(S, CR)); if (!Pair.second) Pair.first->second = CR; return Pair.first->second; } + /// getRange - Determine the range for a particular SCEV. + ConstantRange getRange(const SCEV *S, RangeSignHint Hint); + /// createSCEV - We know that there is no SCEV for the specified value. /// Analyze the expression. const SCEV *createSCEV(Value *V); @@ -536,6 +539,15 @@ namespace llvm { const SCEV *FoundLHS, const SCEV *FoundRHS); + /// isImpliedCondOperandsViaRanges - Test whether the condition described by + /// Pred, LHS, and RHS is true whenever the condition described by Pred, + /// FoundLHS, and FoundRHS is true. Utility function used by + /// isImpliedCondOperands. + bool isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, + const SCEV *FoundRHS); + /// getConstantEvolutionLoopExitValue - If we know that the specified Phi is /// in the header of its containing loop, we know the loop executes a /// constant number of times, and the PHI node is just a recurrence @@ -557,6 +569,15 @@ namespace llvm { /// pointer. bool checkValidity(const SCEV *S) const; + // Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be equal + // to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}. This is equivalent to + // proving no signed (resp. unsigned) wrap in {`Start`,+,`Step`} if + // `ExtendOpTy` is `SCEVSignExtendExpr` (resp. `SCEVZeroExtendExpr`). + // + template<typename ExtendOpTy> + bool proveNoWrapByVaryingStart(const SCEV *Start, const SCEV *Step, + const Loop *L); + public: static char ID; // Pass identification, replacement for typeid ScalarEvolution(); @@ -636,6 +657,15 @@ namespace llvm { SmallVector<const SCEV *, 4> NewOp(Operands.begin(), Operands.end()); return getAddRecExpr(NewOp, L, Flags); } + /// \brief Returns an expression for a GEP + /// + /// \p PointeeType The type used as the basis for the pointer arithmetics + /// \p BaseExpr The expression for the pointer operand. + /// \p IndexExprs The expressions for the indices. + /// \p InBounds Whether the GEP is in bounds. + const SCEV *getGEPExpr(Type *PointeeType, const SCEV *BaseExpr, + const SmallVectorImpl<const SCEV *> &IndexExprs, + bool InBounds = false); const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS); const SCEV *getSMaxExpr(SmallVectorImpl<const SCEV *> &Operands); const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS); @@ -830,11 +860,15 @@ namespace llvm { /// getUnsignedRange - Determine the unsigned range for a particular SCEV. /// - ConstantRange getUnsignedRange(const SCEV *S); + ConstantRange getUnsignedRange(const SCEV *S) { + return getRange(S, HINT_RANGE_UNSIGNED); + } /// getSignedRange - Determine the signed range for a particular SCEV. /// - ConstantRange getSignedRange(const SCEV *S); + ConstantRange getSignedRange(const SCEV *S) { + return getRange(S, HINT_RANGE_SIGNED); + } /// isKnownNegative - Test if the given expression is known to be negative. /// diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index b9bef970b5d3..8ec2078258d1 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -28,7 +28,7 @@ namespace llvm { /// all materialized values are safe to speculate. bool isSafeToExpand(const SCEV *S, ScalarEvolution &SE); - /// SCEVExpander - This class uses information about analyze scalars to + /// This class uses information about analyze scalars to /// rewrite expressions in canonical form. /// /// Clients should create an instance of this class when rewriting is needed, @@ -36,6 +36,7 @@ namespace llvm { /// memory. class SCEVExpander : public SCEVVisitor<SCEVExpander, Value*> { ScalarEvolution &SE; + const DataLayout &DL; // New instructions receive a name to identifies them with the current pass. const char* IVName; @@ -47,37 +48,36 @@ namespace llvm { std::set<AssertingVH<Value> > InsertedValues; std::set<AssertingVH<Value> > InsertedPostIncValues; - /// RelevantLoops - A memoization of the "relevant" loop for a given SCEV. + /// 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 + /// \brief 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>, /// as opposed to a new phi starting at 1. This is only supported in /// non-canonical mode. PostIncLoopSet PostIncLoops; - /// IVIncInsertPos - When this is non-null, addrecs expanded in the - /// loop it indicates should be inserted with increments at - /// IVIncInsertPos. + /// \brief When this is non-null, addrecs expanded in the loop it indicates + /// should be inserted with increments at IVIncInsertPos. const Loop *IVIncInsertLoop; - /// IVIncInsertPos - When expanding addrecs in the IVIncInsertLoop loop, - /// insert the IV increment at this position. + /// \brief When expanding addrecs in the IVIncInsertLoop loop, insert the IV + /// increment at this position. Instruction *IVIncInsertPos; - /// Phis that complete an IV chain. Reuse + /// \brief Phis that complete an IV chain. Reuse std::set<AssertingVH<PHINode> > ChainedPhis; - /// CanonicalMode - When true, expressions are expanded in "canonical" - /// form. In particular, addrecs are expanded as arithmetic based on - /// a canonical induction variable. When false, expression are expanded - /// in a more literal form. + /// \brief When true, expressions are expanded in "canonical" form. In + /// particular, addrecs are expanded as arithmetic based on a canonical + /// induction variable. When false, expression are expanded in a more + /// literal form. bool CanonicalMode; - /// When invoked from LSR, the expander is in "strength reduction" mode. The - /// only difference is that phi's are only reused if they are already in - /// "expanded" form. + /// \brief When invoked from LSR, the expander is in "strength reduction" + /// mode. The only difference is that phi's are only reused if they are + /// already in "expanded" form. bool LSRMode; typedef IRBuilder<true, TargetFolder> BuilderType; @@ -90,11 +90,12 @@ namespace llvm { friend struct SCEVVisitor<SCEVExpander, Value*>; public: - /// SCEVExpander - Construct a SCEVExpander in "canonical" mode. - explicit SCEVExpander(ScalarEvolution &se, const char *name) - : SE(se), IVName(name), IVIncInsertLoop(nullptr), IVIncInsertPos(nullptr), - CanonicalMode(true), LSRMode(false), - Builder(se.getContext(), TargetFolder(se.DL)) { + /// \brief Construct a SCEVExpander in "canonical" mode. + explicit SCEVExpander(ScalarEvolution &se, const DataLayout &DL, + const char *name) + : SE(se), DL(DL), IVName(name), IVIncInsertLoop(nullptr), + IVIncInsertPos(nullptr), CanonicalMode(true), LSRMode(false), + Builder(se.getContext(), TargetFolder(DL)) { #ifndef NDEBUG DebugType = ""; #endif @@ -104,7 +105,7 @@ namespace llvm { void setDebugType(const char* s) { DebugType = s; } #endif - /// clear - Erase the contents of the InsertedExpressions map so that users + /// \brief Erase the contents of the InsertedExpressions map so that users /// trying to expand the same expression into multiple BasicBlocks or /// different places within the same BasicBlock can do so. void clear() { @@ -114,31 +115,38 @@ namespace llvm { ChainedPhis.clear(); } - /// getOrInsertCanonicalInductionVariable - This method returns the - /// canonical induction variable of the specified type for the specified - /// loop (inserting one if there is none). A canonical induction variable - /// starts at zero and steps by one on each iteration. + /// \brief Return true for expressions that may incur non-trivial cost to + /// evaluate at runtime. + bool isHighCostExpansion(const SCEV *Expr, Loop *L) { + SmallPtrSet<const SCEV *, 8> Processed; + return isHighCostExpansionHelper(Expr, L, Processed); + } + + /// \brief This method returns the canonical induction variable of the + /// specified type for the specified loop (inserting one if there is none). + /// A canonical induction variable starts at zero and steps by one on each + /// iteration. PHINode *getOrInsertCanonicalInductionVariable(const Loop *L, Type *Ty); - /// getIVIncOperand - Return the induction variable increment's IV operand. + /// \brief Return the induction variable increment's IV operand. Instruction *getIVIncOperand(Instruction *IncV, Instruction *InsertPos, bool allowScale); - /// hoistIVInc - Utility for hoisting an IV increment. + /// \brief Utility for hoisting an IV increment. bool hoistIVInc(Instruction *IncV, Instruction *InsertPos); - /// replaceCongruentIVs - replace congruent phis with their most canonical + /// \brief replace congruent phis with their most canonical /// representative. Return the number of phis eliminated. unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT, SmallVectorImpl<WeakVH> &DeadInsts, const TargetTransformInfo *TTI = nullptr); - /// expandCodeFor - Insert code to directly compute the specified SCEV - /// expression into the program. The inserted code is inserted into the - /// specified block. + /// \brief Insert code to directly compute the specified SCEV expression + /// into the program. The inserted code is inserted into the specified + /// block. Value *expandCodeFor(const SCEV *SH, Type *Ty, Instruction *I); - /// setIVIncInsertPos - Set the current IV increment loop and position. + /// \brief Set the current IV increment loop and position. void setIVIncInsertPos(const Loop *L, Instruction *Pos) { assert(!CanonicalMode && "IV increment positions are not supported in CanonicalMode"); @@ -146,16 +154,15 @@ namespace llvm { IVIncInsertPos = Pos; } - /// setPostInc - Enable post-inc expansion for addrecs referring to the - /// given loops. Post-inc expansion is only supported in non-canonical - /// mode. + /// \brief Enable post-inc expansion for addrecs referring to the given + /// loops. Post-inc expansion is only supported in non-canonical mode. void setPostInc(const PostIncLoopSet &L) { assert(!CanonicalMode && "Post-inc expansion is not supported in CanonicalMode"); PostIncLoops = L; } - /// clearPostInc - Disable all post-inc expansion. + /// \brief Disable all post-inc expansion. void clearPostInc() { PostIncLoops.clear(); @@ -164,23 +171,22 @@ namespace llvm { InsertedPostIncValues.clear(); } - /// disableCanonicalMode - Disable the behavior of expanding expressions in - /// canonical form rather than in a more literal form. Non-canonical mode - /// is useful for late optimization passes. + /// \brief Disable the behavior of expanding expressions in canonical form + /// rather than in a more literal form. Non-canonical mode is useful for + /// late optimization passes. void disableCanonicalMode() { CanonicalMode = false; } void enableLSRMode() { LSRMode = true; } - /// clearInsertPoint - Clear the current insertion point. This is useful - /// if the instruction that had been serving as the insertion point may - /// have been deleted. + /// \brief Clear the current insertion point. This is useful if the + /// instruction that had been serving as the insertion point may have been + /// deleted. void clearInsertPoint() { Builder.ClearInsertionPoint(); } - /// isInsertedInstruction - Return true if the specified instruction was - /// inserted by the code rewriter. If so, the client should not modify the - /// instruction. + /// \brief Return true if the specified instruction was inserted by the code + /// rewriter. If so, the client should not modify the instruction. bool isInsertedInstruction(Instruction *I) const { return InsertedValues.count(I) || InsertedPostIncValues.count(I); } @@ -190,24 +196,27 @@ namespace llvm { private: LLVMContext &getContext() const { return SE.getContext(); } - /// InsertBinop - Insert the specified binary operator, doing a small amount + /// \brief Recursive helper function for isHighCostExpansion. + bool isHighCostExpansionHelper(const SCEV *S, Loop *L, + SmallPtrSetImpl<const SCEV *> &Processed); + + /// \brief Insert the specified binary operator, doing a small amount /// of work to avoid inserting an obviously redundant operation. Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS); - /// ReuseOrCreateCast - Arange for there to be a cast of V to Ty at IP, - /// reusing an existing cast if a suitable one exists, moving an existing - /// cast if a suitable one exists but isn't in the right place, or - /// or creating a new one. + /// \brief Arrange for there to be a cast of V to Ty at IP, reusing an + /// existing cast if a suitable one exists, moving an existing cast if a + /// suitable one exists but isn't in the right place, or or creating a new + /// one. Value *ReuseOrCreateCast(Value *V, Type *Ty, Instruction::CastOps Op, BasicBlock::iterator IP); - /// InsertNoopCastOfTo - Insert a cast of V to the specified type, - /// which must be possible with a noop cast, doing what we can to - /// share the casts. + /// \brief Insert a cast of V to the specified type, which must be possible + /// with a noop cast, doing what we can to share the casts. Value *InsertNoopCastOfTo(Value *V, Type *Ty); - /// expandAddToGEP - Expand a SCEVAddExpr with a pointer type into a GEP + /// \brief Expand a SCEVAddExpr with a pointer type into a GEP /// instead of using ptrtoint+arithmetic+inttoptr. Value *expandAddToGEP(const SCEV *const *op_begin, const SCEV *const *op_end, @@ -215,13 +224,13 @@ namespace llvm { Value *expand(const SCEV *S); - /// expandCodeFor - Insert code to directly compute the specified SCEV - /// expression into the program. The inserted code is inserted into the - /// SCEVExpander's current insertion point. If a type is specified, the - /// result will be expanded to have that type, with a cast if necessary. + /// \brief Insert code to directly compute the specified SCEV expression + /// into the program. The inserted code is inserted into the SCEVExpander's + /// current insertion point. If a type is specified, the result will be + /// expanded to have that type, with a cast if necessary. Value *expandCodeFor(const SCEV *SH, Type *Ty = nullptr); - /// getRelevantLoop - Determine the most "relevant" loop for the given SCEV. + /// \brief Determine the most "relevant" loop for the given SCEV. const Loop *getRelevantLoop(const SCEV *); Value *visitConstant(const SCEVConstant *S) { diff --git a/include/llvm/Analysis/SparsePropagation.h b/include/llvm/Analysis/SparsePropagation.h index 65ff2f643192..9ccae5ff89b7 100644 --- a/include/llvm/Analysis/SparsePropagation.h +++ b/include/llvm/Analysis/SparsePropagation.h @@ -131,8 +131,8 @@ class SparseSolver { typedef std::pair<BasicBlock*,BasicBlock*> Edge; std::set<Edge> KnownFeasibleEdges; - SparseSolver(const SparseSolver&) LLVM_DELETED_FUNCTION; - void operator=(const SparseSolver&) LLVM_DELETED_FUNCTION; + SparseSolver(const SparseSolver&) = delete; + void operator=(const SparseSolver&) = delete; public: explicit SparseSolver(AbstractLatticeFunction *Lattice) : LatticeFunc(Lattice) {} diff --git a/include/llvm/Analysis/TargetFolder.h b/include/llvm/Analysis/TargetFolder.h index 587a7ef5410a..12bf9fe78a47 100644 --- a/include/llvm/Analysis/TargetFolder.h +++ b/include/llvm/Analysis/TargetFolder.h @@ -30,7 +30,7 @@ class DataLayout; /// TargetFolder - Create constants with target dependent folding. class TargetFolder { - const DataLayout *DL; + const DataLayout &DL; /// Fold - Fold the constant using target specific information. Constant *Fold(Constant *C) const { @@ -41,7 +41,7 @@ class TargetFolder { } public: - explicit TargetFolder(const DataLayout *DL) : DL(DL) {} + explicit TargetFolder(const DataLayout &DL) : DL(DL) {} //===--------------------------------------------------------------------===// // Binary Operators @@ -130,34 +130,35 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return Fold(ConstantExpr::getGetElementPtr(C, IdxList)); + return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList)); } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return Fold(ConstantExpr::getGetElementPtr(C, Idx)); + return Fold(ConstantExpr::getGetElementPtr(Ty, C, Idx)); } - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return Fold(ConstantExpr::getGetElementPtr(C, IdxList)); + return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList)); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList)); + return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList)); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, Idx)); + return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx)); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList)); + return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList)); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/TargetLibraryInfo.def b/include/llvm/Analysis/TargetLibraryInfo.def new file mode 100644 index 000000000000..1c1fdfef980d --- /dev/null +++ b/include/llvm/Analysis/TargetLibraryInfo.def @@ -0,0 +1,1029 @@ +//===-- TargetLibraryInfo.def - Library information -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// This .def file will either fill in the enum definition or fill in the +// string representation array definition for TargetLibraryInfo. +// Which is defined depends on whether TLI_DEFINE_ENUM is defined or +// TLI_DEFINE_STRING is defined. Only one should be defined at a time. + +#if !(defined(TLI_DEFINE_ENUM) || defined(TLI_DEFINE_STRING)) +#error "Must define TLI_DEFINE_ENUM or TLI_DEFINE_STRING for TLI .def." +#elif defined(TLI_DEFINE_ENUM) && defined(TLI_DEFINE_STRING) +#error "Can only define one of TLI_DEFINE_ENUM or TLI_DEFINE_STRING at a time." +#else +// One of TLI_DEFINE_ENUM/STRING are defined. + +#if defined(TLI_DEFINE_ENUM) +#define TLI_DEFINE_ENUM_INTERNAL(enum_variant) enum_variant, +#define TLI_DEFINE_STRING_INTERNAL(string_repr) +#else +#define TLI_DEFINE_ENUM_INTERNAL(enum_variant) +#define TLI_DEFINE_STRING_INTERNAL(string_repr) string_repr, +#endif + +/// int _IO_getc(_IO_FILE * __fp); +TLI_DEFINE_ENUM_INTERNAL(under_IO_getc) +TLI_DEFINE_STRING_INTERNAL("_IO_getc") +/// int _IO_putc(int __c, _IO_FILE * __fp); +TLI_DEFINE_ENUM_INTERNAL(under_IO_putc) +TLI_DEFINE_STRING_INTERNAL("_IO_putc") +/// void operator delete[](void*); +TLI_DEFINE_ENUM_INTERNAL(ZdaPv) +TLI_DEFINE_STRING_INTERNAL("_ZdaPv") +/// void operator delete[](void*, nothrow); +TLI_DEFINE_ENUM_INTERNAL(ZdaPvRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZdaPvRKSt9nothrow_t") +/// void operator delete[](void*, unsigned int); +TLI_DEFINE_ENUM_INTERNAL(ZdaPvj) +TLI_DEFINE_STRING_INTERNAL("_ZdaPvj") +/// void operator delete[](void*, unsigned long); +TLI_DEFINE_ENUM_INTERNAL(ZdaPvm) +TLI_DEFINE_STRING_INTERNAL("_ZdaPvm") +/// void operator delete(void*); +TLI_DEFINE_ENUM_INTERNAL(ZdlPv) +TLI_DEFINE_STRING_INTERNAL("_ZdlPv") +/// void operator delete(void*, nothrow); +TLI_DEFINE_ENUM_INTERNAL(ZdlPvRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZdlPvRKSt9nothrow_t") +/// void operator delete(void*, unsigned int); +TLI_DEFINE_ENUM_INTERNAL(ZdlPvj) +TLI_DEFINE_STRING_INTERNAL("_ZdlPvj") +/// void operator delete(void*, unsigned long); +TLI_DEFINE_ENUM_INTERNAL(ZdlPvm) +TLI_DEFINE_STRING_INTERNAL("_ZdlPvm") +/// void *new[](unsigned int); +TLI_DEFINE_ENUM_INTERNAL(Znaj) +TLI_DEFINE_STRING_INTERNAL("_Znaj") +/// void *new[](unsigned int, nothrow); +TLI_DEFINE_ENUM_INTERNAL(ZnajRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZnajRKSt9nothrow_t") +/// void *new[](unsigned long); +TLI_DEFINE_ENUM_INTERNAL(Znam) +TLI_DEFINE_STRING_INTERNAL("_Znam") +/// void *new[](unsigned long, nothrow); +TLI_DEFINE_ENUM_INTERNAL(ZnamRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZnamRKSt9nothrow_t") +/// void *new(unsigned int); +TLI_DEFINE_ENUM_INTERNAL(Znwj) +TLI_DEFINE_STRING_INTERNAL("_Znwj") +/// void *new(unsigned int, nothrow); +TLI_DEFINE_ENUM_INTERNAL(ZnwjRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZnwjRKSt9nothrow_t") +/// void *new(unsigned long); +TLI_DEFINE_ENUM_INTERNAL(Znwm) +TLI_DEFINE_STRING_INTERNAL("_Znwm") +/// void *new(unsigned long, nothrow); +TLI_DEFINE_ENUM_INTERNAL(ZnwmRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZnwmRKSt9nothrow_t") +/// double __cospi(double x); +TLI_DEFINE_ENUM_INTERNAL(cospi) +TLI_DEFINE_STRING_INTERNAL("__cospi") +/// float __cospif(float x); +TLI_DEFINE_ENUM_INTERNAL(cospif) +TLI_DEFINE_STRING_INTERNAL("__cospif") +/// int __cxa_atexit(void (*f)(void *), void *p, void *d); +TLI_DEFINE_ENUM_INTERNAL(cxa_atexit) +TLI_DEFINE_STRING_INTERNAL("__cxa_atexit") +/// void __cxa_guard_abort(guard_t *guard); +/// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi. +TLI_DEFINE_ENUM_INTERNAL(cxa_guard_abort) +TLI_DEFINE_STRING_INTERNAL("__cxa_guard_abort") +/// int __cxa_guard_acquire(guard_t *guard); +TLI_DEFINE_ENUM_INTERNAL(cxa_guard_acquire) +TLI_DEFINE_STRING_INTERNAL("__cxa_guard_acquire") +/// void __cxa_guard_release(guard_t *guard); +TLI_DEFINE_ENUM_INTERNAL(cxa_guard_release) +TLI_DEFINE_STRING_INTERNAL("__cxa_guard_release") +/// int __isoc99_scanf (const char *format, ...) +TLI_DEFINE_ENUM_INTERNAL(dunder_isoc99_scanf) +TLI_DEFINE_STRING_INTERNAL("__isoc99_scanf") +/// int __isoc99_sscanf(const char *s, const char *format, ...) +TLI_DEFINE_ENUM_INTERNAL(dunder_isoc99_sscanf) +TLI_DEFINE_STRING_INTERNAL("__isoc99_sscanf") +/// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(memcpy_chk) +TLI_DEFINE_STRING_INTERNAL("__memcpy_chk") +/// void *__memmove_chk(void *s1, const void *s2, size_t n, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(memmove_chk) +TLI_DEFINE_STRING_INTERNAL("__memmove_chk") +/// void *__memset_chk(void *s, char v, size_t n, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(memset_chk) +TLI_DEFINE_STRING_INTERNAL("__memset_chk") +/// double __sincospi_stret(double x); +TLI_DEFINE_ENUM_INTERNAL(sincospi_stret) +TLI_DEFINE_STRING_INTERNAL("__sincospi_stret") +/// float __sincospif_stret(float x); +TLI_DEFINE_ENUM_INTERNAL(sincospif_stret) +TLI_DEFINE_STRING_INTERNAL("__sincospif_stret") +/// double __sinpi(double x); +TLI_DEFINE_ENUM_INTERNAL(sinpi) +TLI_DEFINE_STRING_INTERNAL("__sinpi") +/// float __sinpif(float x); +TLI_DEFINE_ENUM_INTERNAL(sinpif) +TLI_DEFINE_STRING_INTERNAL("__sinpif") +/// double __sqrt_finite(double x); +TLI_DEFINE_ENUM_INTERNAL(sqrt_finite) +TLI_DEFINE_STRING_INTERNAL("__sqrt_finite") +/// float __sqrt_finite(float x); +TLI_DEFINE_ENUM_INTERNAL(sqrtf_finite) +TLI_DEFINE_STRING_INTERNAL("__sqrtf_finite") +/// long double __sqrt_finite(long double x); +TLI_DEFINE_ENUM_INTERNAL(sqrtl_finite) +TLI_DEFINE_STRING_INTERNAL("__sqrtl_finite") +/// char *__stpcpy_chk(char *s1, const char *s2, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(stpcpy_chk) +TLI_DEFINE_STRING_INTERNAL("__stpcpy_chk") +/// char *__stpncpy_chk(char *s1, const char *s2, size_t n, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(stpncpy_chk) +TLI_DEFINE_STRING_INTERNAL("__stpncpy_chk") +/// char *__strcpy_chk(char *s1, const char *s2, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(strcpy_chk) +TLI_DEFINE_STRING_INTERNAL("__strcpy_chk") +/// char * __strdup(const char *s); +TLI_DEFINE_ENUM_INTERNAL(dunder_strdup) +TLI_DEFINE_STRING_INTERNAL("__strdup") +/// char *__strncpy_chk(char *s1, const char *s2, size_t n, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(strncpy_chk) +TLI_DEFINE_STRING_INTERNAL("__strncpy_chk") +/// char *__strndup(const char *s, size_t n); +TLI_DEFINE_ENUM_INTERNAL(dunder_strndup) +TLI_DEFINE_STRING_INTERNAL("__strndup") +/// char * __strtok_r(char *s, const char *delim, char **save_ptr); +TLI_DEFINE_ENUM_INTERNAL(dunder_strtok_r) +TLI_DEFINE_STRING_INTERNAL("__strtok_r") +/// int abs(int j); +TLI_DEFINE_ENUM_INTERNAL(abs) +TLI_DEFINE_STRING_INTERNAL("abs") +/// int access(const char *path, int amode); +TLI_DEFINE_ENUM_INTERNAL(access) +TLI_DEFINE_STRING_INTERNAL("access") +/// double acos(double x); +TLI_DEFINE_ENUM_INTERNAL(acos) +TLI_DEFINE_STRING_INTERNAL("acos") +/// float acosf(float x); +TLI_DEFINE_ENUM_INTERNAL(acosf) +TLI_DEFINE_STRING_INTERNAL("acosf") +/// double acosh(double x); +TLI_DEFINE_ENUM_INTERNAL(acosh) +TLI_DEFINE_STRING_INTERNAL("acosh") +/// float acoshf(float x); +TLI_DEFINE_ENUM_INTERNAL(acoshf) +TLI_DEFINE_STRING_INTERNAL("acoshf") +/// long double acoshl(long double x); +TLI_DEFINE_ENUM_INTERNAL(acoshl) +TLI_DEFINE_STRING_INTERNAL("acoshl") +/// long double acosl(long double x); +TLI_DEFINE_ENUM_INTERNAL(acosl) +TLI_DEFINE_STRING_INTERNAL("acosl") +/// double asin(double x); +TLI_DEFINE_ENUM_INTERNAL(asin) +TLI_DEFINE_STRING_INTERNAL("asin") +/// float asinf(float x); +TLI_DEFINE_ENUM_INTERNAL(asinf) +TLI_DEFINE_STRING_INTERNAL("asinf") +/// double asinh(double x); +TLI_DEFINE_ENUM_INTERNAL(asinh) +TLI_DEFINE_STRING_INTERNAL("asinh") +/// float asinhf(float x); +TLI_DEFINE_ENUM_INTERNAL(asinhf) +TLI_DEFINE_STRING_INTERNAL("asinhf") +/// long double asinhl(long double x); +TLI_DEFINE_ENUM_INTERNAL(asinhl) +TLI_DEFINE_STRING_INTERNAL("asinhl") +/// long double asinl(long double x); +TLI_DEFINE_ENUM_INTERNAL(asinl) +TLI_DEFINE_STRING_INTERNAL("asinl") +/// double atan(double x); +TLI_DEFINE_ENUM_INTERNAL(atan) +TLI_DEFINE_STRING_INTERNAL("atan") +/// double atan2(double y, double x); +TLI_DEFINE_ENUM_INTERNAL(atan2) +TLI_DEFINE_STRING_INTERNAL("atan2") +/// float atan2f(float y, float x); +TLI_DEFINE_ENUM_INTERNAL(atan2f) +TLI_DEFINE_STRING_INTERNAL("atan2f") +/// long double atan2l(long double y, long double x); +TLI_DEFINE_ENUM_INTERNAL(atan2l) +TLI_DEFINE_STRING_INTERNAL("atan2l") +/// float atanf(float x); +TLI_DEFINE_ENUM_INTERNAL(atanf) +TLI_DEFINE_STRING_INTERNAL("atanf") +/// double atanh(double x); +TLI_DEFINE_ENUM_INTERNAL(atanh) +TLI_DEFINE_STRING_INTERNAL("atanh") +/// float atanhf(float x); +TLI_DEFINE_ENUM_INTERNAL(atanhf) +TLI_DEFINE_STRING_INTERNAL("atanhf") +/// long double atanhl(long double x); +TLI_DEFINE_ENUM_INTERNAL(atanhl) +TLI_DEFINE_STRING_INTERNAL("atanhl") +/// long double atanl(long double x); +TLI_DEFINE_ENUM_INTERNAL(atanl) +TLI_DEFINE_STRING_INTERNAL("atanl") +/// double atof(const char *str); +TLI_DEFINE_ENUM_INTERNAL(atof) +TLI_DEFINE_STRING_INTERNAL("atof") +/// int atoi(const char *str); +TLI_DEFINE_ENUM_INTERNAL(atoi) +TLI_DEFINE_STRING_INTERNAL("atoi") +/// long atol(const char *str); +TLI_DEFINE_ENUM_INTERNAL(atol) +TLI_DEFINE_STRING_INTERNAL("atol") +/// long long atoll(const char *nptr); +TLI_DEFINE_ENUM_INTERNAL(atoll) +TLI_DEFINE_STRING_INTERNAL("atoll") +/// int bcmp(const void *s1, const void *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(bcmp) +TLI_DEFINE_STRING_INTERNAL("bcmp") +/// void bcopy(const void *s1, void *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(bcopy) +TLI_DEFINE_STRING_INTERNAL("bcopy") +/// void bzero(void *s, size_t n); +TLI_DEFINE_ENUM_INTERNAL(bzero) +TLI_DEFINE_STRING_INTERNAL("bzero") +/// void *calloc(size_t count, size_t size); +TLI_DEFINE_ENUM_INTERNAL(calloc) +TLI_DEFINE_STRING_INTERNAL("calloc") +/// double cbrt(double x); +TLI_DEFINE_ENUM_INTERNAL(cbrt) +TLI_DEFINE_STRING_INTERNAL("cbrt") +/// float cbrtf(float x); +TLI_DEFINE_ENUM_INTERNAL(cbrtf) +TLI_DEFINE_STRING_INTERNAL("cbrtf") +/// long double cbrtl(long double x); +TLI_DEFINE_ENUM_INTERNAL(cbrtl) +TLI_DEFINE_STRING_INTERNAL("cbrtl") +/// double ceil(double x); +TLI_DEFINE_ENUM_INTERNAL(ceil) +TLI_DEFINE_STRING_INTERNAL("ceil") +/// float ceilf(float x); +TLI_DEFINE_ENUM_INTERNAL(ceilf) +TLI_DEFINE_STRING_INTERNAL("ceilf") +/// long double ceill(long double x); +TLI_DEFINE_ENUM_INTERNAL(ceill) +TLI_DEFINE_STRING_INTERNAL("ceill") +/// int chmod(const char *path, mode_t mode); +TLI_DEFINE_ENUM_INTERNAL(chmod) +TLI_DEFINE_STRING_INTERNAL("chmod") +/// int chown(const char *path, uid_t owner, gid_t group); +TLI_DEFINE_ENUM_INTERNAL(chown) +TLI_DEFINE_STRING_INTERNAL("chown") +/// void clearerr(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(clearerr) +TLI_DEFINE_STRING_INTERNAL("clearerr") +/// int closedir(DIR *dirp); +TLI_DEFINE_ENUM_INTERNAL(closedir) +TLI_DEFINE_STRING_INTERNAL("closedir") +/// double copysign(double x, double y); +TLI_DEFINE_ENUM_INTERNAL(copysign) +TLI_DEFINE_STRING_INTERNAL("copysign") +/// float copysignf(float x, float y); +TLI_DEFINE_ENUM_INTERNAL(copysignf) +TLI_DEFINE_STRING_INTERNAL("copysignf") +/// long double copysignl(long double x, long double y); +TLI_DEFINE_ENUM_INTERNAL(copysignl) +TLI_DEFINE_STRING_INTERNAL("copysignl") +/// double cos(double x); +TLI_DEFINE_ENUM_INTERNAL(cos) +TLI_DEFINE_STRING_INTERNAL("cos") +/// float cosf(float x); +TLI_DEFINE_ENUM_INTERNAL(cosf) +TLI_DEFINE_STRING_INTERNAL("cosf") +/// double cosh(double x); +TLI_DEFINE_ENUM_INTERNAL(cosh) +TLI_DEFINE_STRING_INTERNAL("cosh") +/// float coshf(float x); +TLI_DEFINE_ENUM_INTERNAL(coshf) +TLI_DEFINE_STRING_INTERNAL("coshf") +/// long double coshl(long double x); +TLI_DEFINE_ENUM_INTERNAL(coshl) +TLI_DEFINE_STRING_INTERNAL("coshl") +/// long double cosl(long double x); +TLI_DEFINE_ENUM_INTERNAL(cosl) +TLI_DEFINE_STRING_INTERNAL("cosl") +/// char *ctermid(char *s); +TLI_DEFINE_ENUM_INTERNAL(ctermid) +TLI_DEFINE_STRING_INTERNAL("ctermid") +/// double exp(double x); +TLI_DEFINE_ENUM_INTERNAL(exp) +TLI_DEFINE_STRING_INTERNAL("exp") +/// double exp10(double x); +TLI_DEFINE_ENUM_INTERNAL(exp10) +TLI_DEFINE_STRING_INTERNAL("exp10") +/// float exp10f(float x); +TLI_DEFINE_ENUM_INTERNAL(exp10f) +TLI_DEFINE_STRING_INTERNAL("exp10f") +/// long double exp10l(long double x); +TLI_DEFINE_ENUM_INTERNAL(exp10l) +TLI_DEFINE_STRING_INTERNAL("exp10l") +/// double exp2(double x); +TLI_DEFINE_ENUM_INTERNAL(exp2) +TLI_DEFINE_STRING_INTERNAL("exp2") +/// float exp2f(float x); +TLI_DEFINE_ENUM_INTERNAL(exp2f) +TLI_DEFINE_STRING_INTERNAL("exp2f") +/// long double exp2l(long double x); +TLI_DEFINE_ENUM_INTERNAL(exp2l) +TLI_DEFINE_STRING_INTERNAL("exp2l") +/// float expf(float x); +TLI_DEFINE_ENUM_INTERNAL(expf) +TLI_DEFINE_STRING_INTERNAL("expf") +/// long double expl(long double x); +TLI_DEFINE_ENUM_INTERNAL(expl) +TLI_DEFINE_STRING_INTERNAL("expl") +/// double expm1(double x); +TLI_DEFINE_ENUM_INTERNAL(expm1) +TLI_DEFINE_STRING_INTERNAL("expm1") +/// float expm1f(float x); +TLI_DEFINE_ENUM_INTERNAL(expm1f) +TLI_DEFINE_STRING_INTERNAL("expm1f") +/// long double expm1l(long double x); +TLI_DEFINE_ENUM_INTERNAL(expm1l) +TLI_DEFINE_STRING_INTERNAL("expm1l") +/// double fabs(double x); +TLI_DEFINE_ENUM_INTERNAL(fabs) +TLI_DEFINE_STRING_INTERNAL("fabs") +/// float fabsf(float x); +TLI_DEFINE_ENUM_INTERNAL(fabsf) +TLI_DEFINE_STRING_INTERNAL("fabsf") +/// long double fabsl(long double x); +TLI_DEFINE_ENUM_INTERNAL(fabsl) +TLI_DEFINE_STRING_INTERNAL("fabsl") +/// int fclose(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fclose) +TLI_DEFINE_STRING_INTERNAL("fclose") +/// FILE *fdopen(int fildes, const char *mode); +TLI_DEFINE_ENUM_INTERNAL(fdopen) +TLI_DEFINE_STRING_INTERNAL("fdopen") +/// int feof(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(feof) +TLI_DEFINE_STRING_INTERNAL("feof") +/// int ferror(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(ferror) +TLI_DEFINE_STRING_INTERNAL("ferror") +/// int fflush(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fflush) +TLI_DEFINE_STRING_INTERNAL("fflush") +/// int ffs(int i); +TLI_DEFINE_ENUM_INTERNAL(ffs) +TLI_DEFINE_STRING_INTERNAL("ffs") +/// int ffsl(long int i); +TLI_DEFINE_ENUM_INTERNAL(ffsl) +TLI_DEFINE_STRING_INTERNAL("ffsl") +/// int ffsll(long long int i); +TLI_DEFINE_ENUM_INTERNAL(ffsll) +TLI_DEFINE_STRING_INTERNAL("ffsll") +/// int fgetc(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fgetc) +TLI_DEFINE_STRING_INTERNAL("fgetc") +/// int fgetpos(FILE *stream, fpos_t *pos); +TLI_DEFINE_ENUM_INTERNAL(fgetpos) +TLI_DEFINE_STRING_INTERNAL("fgetpos") +/// char *fgets(char *s, int n, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fgets) +TLI_DEFINE_STRING_INTERNAL("fgets") +/// int fileno(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fileno) +TLI_DEFINE_STRING_INTERNAL("fileno") +/// int fiprintf(FILE *stream, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(fiprintf) +TLI_DEFINE_STRING_INTERNAL("fiprintf") +/// void flockfile(FILE *file); +TLI_DEFINE_ENUM_INTERNAL(flockfile) +TLI_DEFINE_STRING_INTERNAL("flockfile") +/// double floor(double x); +TLI_DEFINE_ENUM_INTERNAL(floor) +TLI_DEFINE_STRING_INTERNAL("floor") +/// float floorf(float x); +TLI_DEFINE_ENUM_INTERNAL(floorf) +TLI_DEFINE_STRING_INTERNAL("floorf") +/// long double floorl(long double x); +TLI_DEFINE_ENUM_INTERNAL(floorl) +TLI_DEFINE_STRING_INTERNAL("floorl") +/// double fmax(double x, double y); +TLI_DEFINE_ENUM_INTERNAL(fmax) +TLI_DEFINE_STRING_INTERNAL("fmax") +/// float fmaxf(float x, float y); +TLI_DEFINE_ENUM_INTERNAL(fmaxf) +TLI_DEFINE_STRING_INTERNAL("fmaxf") +/// long double fmaxl(long double x, long double y); +TLI_DEFINE_ENUM_INTERNAL(fmaxl) +TLI_DEFINE_STRING_INTERNAL("fmaxl") +/// double fmin(double x, double y); +TLI_DEFINE_ENUM_INTERNAL(fmin) +TLI_DEFINE_STRING_INTERNAL("fmin") +/// float fminf(float x, float y); +TLI_DEFINE_ENUM_INTERNAL(fminf) +TLI_DEFINE_STRING_INTERNAL("fminf") +/// long double fminl(long double x, long double y); +TLI_DEFINE_ENUM_INTERNAL(fminl) +TLI_DEFINE_STRING_INTERNAL("fminl") +/// double fmod(double x, double y); +TLI_DEFINE_ENUM_INTERNAL(fmod) +TLI_DEFINE_STRING_INTERNAL("fmod") +/// float fmodf(float x, float y); +TLI_DEFINE_ENUM_INTERNAL(fmodf) +TLI_DEFINE_STRING_INTERNAL("fmodf") +/// long double fmodl(long double x, long double y); +TLI_DEFINE_ENUM_INTERNAL(fmodl) +TLI_DEFINE_STRING_INTERNAL("fmodl") +/// FILE *fopen(const char *filename, const char *mode); +TLI_DEFINE_ENUM_INTERNAL(fopen) +TLI_DEFINE_STRING_INTERNAL("fopen") +/// FILE *fopen64(const char *filename, const char *opentype) +TLI_DEFINE_ENUM_INTERNAL(fopen64) +TLI_DEFINE_STRING_INTERNAL("fopen64") +/// int fprintf(FILE *stream, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(fprintf) +TLI_DEFINE_STRING_INTERNAL("fprintf") +/// int fputc(int c, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fputc) +TLI_DEFINE_STRING_INTERNAL("fputc") +/// int fputs(const char *s, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fputs) +TLI_DEFINE_STRING_INTERNAL("fputs") +/// size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fread) +TLI_DEFINE_STRING_INTERNAL("fread") +/// void free(void *ptr); +TLI_DEFINE_ENUM_INTERNAL(free) +TLI_DEFINE_STRING_INTERNAL("free") +/// double frexp(double num, int *exp); +TLI_DEFINE_ENUM_INTERNAL(frexp) +TLI_DEFINE_STRING_INTERNAL("frexp") +/// float frexpf(float num, int *exp); +TLI_DEFINE_ENUM_INTERNAL(frexpf) +TLI_DEFINE_STRING_INTERNAL("frexpf") +/// long double frexpl(long double num, int *exp); +TLI_DEFINE_ENUM_INTERNAL(frexpl) +TLI_DEFINE_STRING_INTERNAL("frexpl") +/// int fscanf(FILE *stream, const char *format, ... ); +TLI_DEFINE_ENUM_INTERNAL(fscanf) +TLI_DEFINE_STRING_INTERNAL("fscanf") +/// int fseek(FILE *stream, long offset, int whence); +TLI_DEFINE_ENUM_INTERNAL(fseek) +TLI_DEFINE_STRING_INTERNAL("fseek") +/// int fseeko(FILE *stream, off_t offset, int whence); +TLI_DEFINE_ENUM_INTERNAL(fseeko) +TLI_DEFINE_STRING_INTERNAL("fseeko") +/// int fseeko64(FILE *stream, off64_t offset, int whence) +TLI_DEFINE_ENUM_INTERNAL(fseeko64) +TLI_DEFINE_STRING_INTERNAL("fseeko64") +/// int fsetpos(FILE *stream, const fpos_t *pos); +TLI_DEFINE_ENUM_INTERNAL(fsetpos) +TLI_DEFINE_STRING_INTERNAL("fsetpos") +/// int fstat(int fildes, struct stat *buf); +TLI_DEFINE_ENUM_INTERNAL(fstat) +TLI_DEFINE_STRING_INTERNAL("fstat") +/// int fstat64(int filedes, struct stat64 *buf) +TLI_DEFINE_ENUM_INTERNAL(fstat64) +TLI_DEFINE_STRING_INTERNAL("fstat64") +/// int fstatvfs(int fildes, struct statvfs *buf); +TLI_DEFINE_ENUM_INTERNAL(fstatvfs) +TLI_DEFINE_STRING_INTERNAL("fstatvfs") +/// int fstatvfs64(int fildes, struct statvfs64 *buf); +TLI_DEFINE_ENUM_INTERNAL(fstatvfs64) +TLI_DEFINE_STRING_INTERNAL("fstatvfs64") +/// long ftell(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(ftell) +TLI_DEFINE_STRING_INTERNAL("ftell") +/// off_t ftello(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(ftello) +TLI_DEFINE_STRING_INTERNAL("ftello") +/// off64_t ftello64(FILE *stream) +TLI_DEFINE_ENUM_INTERNAL(ftello64) +TLI_DEFINE_STRING_INTERNAL("ftello64") +/// int ftrylockfile(FILE *file); +TLI_DEFINE_ENUM_INTERNAL(ftrylockfile) +TLI_DEFINE_STRING_INTERNAL("ftrylockfile") +/// void funlockfile(FILE *file); +TLI_DEFINE_ENUM_INTERNAL(funlockfile) +TLI_DEFINE_STRING_INTERNAL("funlockfile") +/// size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fwrite) +TLI_DEFINE_STRING_INTERNAL("fwrite") +/// int getc(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(getc) +TLI_DEFINE_STRING_INTERNAL("getc") +/// int getc_unlocked(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(getc_unlocked) +TLI_DEFINE_STRING_INTERNAL("getc_unlocked") +/// int getchar(void); +TLI_DEFINE_ENUM_INTERNAL(getchar) +TLI_DEFINE_STRING_INTERNAL("getchar") +/// char *getenv(const char *name); +TLI_DEFINE_ENUM_INTERNAL(getenv) +TLI_DEFINE_STRING_INTERNAL("getenv") +/// int getitimer(int which, struct itimerval *value); +TLI_DEFINE_ENUM_INTERNAL(getitimer) +TLI_DEFINE_STRING_INTERNAL("getitimer") +/// int getlogin_r(char *name, size_t namesize); +TLI_DEFINE_ENUM_INTERNAL(getlogin_r) +TLI_DEFINE_STRING_INTERNAL("getlogin_r") +/// struct passwd *getpwnam(const char *name); +TLI_DEFINE_ENUM_INTERNAL(getpwnam) +TLI_DEFINE_STRING_INTERNAL("getpwnam") +/// char *gets(char *s); +TLI_DEFINE_ENUM_INTERNAL(gets) +TLI_DEFINE_STRING_INTERNAL("gets") +/// int gettimeofday(struct timeval *tp, void *tzp); +TLI_DEFINE_ENUM_INTERNAL(gettimeofday) +TLI_DEFINE_STRING_INTERNAL("gettimeofday") +/// uint32_t htonl(uint32_t hostlong); +TLI_DEFINE_ENUM_INTERNAL(htonl) +TLI_DEFINE_STRING_INTERNAL("htonl") +/// uint16_t htons(uint16_t hostshort); +TLI_DEFINE_ENUM_INTERNAL(htons) +TLI_DEFINE_STRING_INTERNAL("htons") +/// int iprintf(const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(iprintf) +TLI_DEFINE_STRING_INTERNAL("iprintf") +/// int isascii(int c); +TLI_DEFINE_ENUM_INTERNAL(isascii) +TLI_DEFINE_STRING_INTERNAL("isascii") +/// int isdigit(int c); +TLI_DEFINE_ENUM_INTERNAL(isdigit) +TLI_DEFINE_STRING_INTERNAL("isdigit") +/// long int labs(long int j); +TLI_DEFINE_ENUM_INTERNAL(labs) +TLI_DEFINE_STRING_INTERNAL("labs") +/// int lchown(const char *path, uid_t owner, gid_t group); +TLI_DEFINE_ENUM_INTERNAL(lchown) +TLI_DEFINE_STRING_INTERNAL("lchown") +/// double ldexp(double x, int n); +TLI_DEFINE_ENUM_INTERNAL(ldexp) +TLI_DEFINE_STRING_INTERNAL("ldexp") +/// float ldexpf(float x, int n); +TLI_DEFINE_ENUM_INTERNAL(ldexpf) +TLI_DEFINE_STRING_INTERNAL("ldexpf") +/// long double ldexpl(long double x, int n); +TLI_DEFINE_ENUM_INTERNAL(ldexpl) +TLI_DEFINE_STRING_INTERNAL("ldexpl") +/// long long int llabs(long long int j); +TLI_DEFINE_ENUM_INTERNAL(llabs) +TLI_DEFINE_STRING_INTERNAL("llabs") +/// double log(double x); +TLI_DEFINE_ENUM_INTERNAL(log) +TLI_DEFINE_STRING_INTERNAL("log") +/// double log10(double x); +TLI_DEFINE_ENUM_INTERNAL(log10) +TLI_DEFINE_STRING_INTERNAL("log10") +/// float log10f(float x); +TLI_DEFINE_ENUM_INTERNAL(log10f) +TLI_DEFINE_STRING_INTERNAL("log10f") +/// long double log10l(long double x); +TLI_DEFINE_ENUM_INTERNAL(log10l) +TLI_DEFINE_STRING_INTERNAL("log10l") +/// double log1p(double x); +TLI_DEFINE_ENUM_INTERNAL(log1p) +TLI_DEFINE_STRING_INTERNAL("log1p") +/// float log1pf(float x); +TLI_DEFINE_ENUM_INTERNAL(log1pf) +TLI_DEFINE_STRING_INTERNAL("log1pf") +/// long double log1pl(long double x); +TLI_DEFINE_ENUM_INTERNAL(log1pl) +TLI_DEFINE_STRING_INTERNAL("log1pl") +/// double log2(double x); +TLI_DEFINE_ENUM_INTERNAL(log2) +TLI_DEFINE_STRING_INTERNAL("log2") +/// float log2f(float x); +TLI_DEFINE_ENUM_INTERNAL(log2f) +TLI_DEFINE_STRING_INTERNAL("log2f") +/// double long double log2l(long double x); +TLI_DEFINE_ENUM_INTERNAL(log2l) +TLI_DEFINE_STRING_INTERNAL("log2l") +/// double logb(double x); +TLI_DEFINE_ENUM_INTERNAL(logb) +TLI_DEFINE_STRING_INTERNAL("logb") +/// float logbf(float x); +TLI_DEFINE_ENUM_INTERNAL(logbf) +TLI_DEFINE_STRING_INTERNAL("logbf") +/// long double logbl(long double x); +TLI_DEFINE_ENUM_INTERNAL(logbl) +TLI_DEFINE_STRING_INTERNAL("logbl") +/// float logf(float x); +TLI_DEFINE_ENUM_INTERNAL(logf) +TLI_DEFINE_STRING_INTERNAL("logf") +/// long double logl(long double x); +TLI_DEFINE_ENUM_INTERNAL(logl) +TLI_DEFINE_STRING_INTERNAL("logl") +/// int lstat(const char *path, struct stat *buf); +TLI_DEFINE_ENUM_INTERNAL(lstat) +TLI_DEFINE_STRING_INTERNAL("lstat") +/// int lstat64(const char *path, struct stat64 *buf); +TLI_DEFINE_ENUM_INTERNAL(lstat64) +TLI_DEFINE_STRING_INTERNAL("lstat64") +/// void *malloc(size_t size); +TLI_DEFINE_ENUM_INTERNAL(malloc) +TLI_DEFINE_STRING_INTERNAL("malloc") +/// void *memalign(size_t boundary, size_t size); +TLI_DEFINE_ENUM_INTERNAL(memalign) +TLI_DEFINE_STRING_INTERNAL("memalign") +/// void *memccpy(void *s1, const void *s2, int c, size_t n); +TLI_DEFINE_ENUM_INTERNAL(memccpy) +TLI_DEFINE_STRING_INTERNAL("memccpy") +/// void *memchr(const void *s, int c, size_t n); +TLI_DEFINE_ENUM_INTERNAL(memchr) +TLI_DEFINE_STRING_INTERNAL("memchr") +/// int memcmp(const void *s1, const void *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(memcmp) +TLI_DEFINE_STRING_INTERNAL("memcmp") +/// void *memcpy(void *s1, const void *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(memcpy) +TLI_DEFINE_STRING_INTERNAL("memcpy") +/// void *memmove(void *s1, const void *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(memmove) +TLI_DEFINE_STRING_INTERNAL("memmove") +// void *memrchr(const void *s, int c, size_t n); +TLI_DEFINE_ENUM_INTERNAL(memrchr) +TLI_DEFINE_STRING_INTERNAL("memrchr") +/// void *memset(void *b, int c, size_t len); +TLI_DEFINE_ENUM_INTERNAL(memset) +TLI_DEFINE_STRING_INTERNAL("memset") +/// void memset_pattern16(void *b, const void *pattern16, size_t len); +TLI_DEFINE_ENUM_INTERNAL(memset_pattern16) +TLI_DEFINE_STRING_INTERNAL("memset_pattern16") +/// int mkdir(const char *path, mode_t mode); +TLI_DEFINE_ENUM_INTERNAL(mkdir) +TLI_DEFINE_STRING_INTERNAL("mkdir") +/// time_t mktime(struct tm *timeptr); +TLI_DEFINE_ENUM_INTERNAL(mktime) +TLI_DEFINE_STRING_INTERNAL("mktime") +/// double modf(double x, double *iptr); +TLI_DEFINE_ENUM_INTERNAL(modf) +TLI_DEFINE_STRING_INTERNAL("modf") +/// float modff(float, float *iptr); +TLI_DEFINE_ENUM_INTERNAL(modff) +TLI_DEFINE_STRING_INTERNAL("modff") +/// long double modfl(long double value, long double *iptr); +TLI_DEFINE_ENUM_INTERNAL(modfl) +TLI_DEFINE_STRING_INTERNAL("modfl") +/// double nearbyint(double x); +TLI_DEFINE_ENUM_INTERNAL(nearbyint) +TLI_DEFINE_STRING_INTERNAL("nearbyint") +/// float nearbyintf(float x); +TLI_DEFINE_ENUM_INTERNAL(nearbyintf) +TLI_DEFINE_STRING_INTERNAL("nearbyintf") +/// long double nearbyintl(long double x); +TLI_DEFINE_ENUM_INTERNAL(nearbyintl) +TLI_DEFINE_STRING_INTERNAL("nearbyintl") +/// uint32_t ntohl(uint32_t netlong); +TLI_DEFINE_ENUM_INTERNAL(ntohl) +TLI_DEFINE_STRING_INTERNAL("ntohl") +/// uint16_t ntohs(uint16_t netshort); +TLI_DEFINE_ENUM_INTERNAL(ntohs) +TLI_DEFINE_STRING_INTERNAL("ntohs") +/// int open(const char *path, int oflag, ... ); +TLI_DEFINE_ENUM_INTERNAL(open) +TLI_DEFINE_STRING_INTERNAL("open") +/// int open64(const char *filename, int flags[, mode_t mode]) +TLI_DEFINE_ENUM_INTERNAL(open64) +TLI_DEFINE_STRING_INTERNAL("open64") +/// DIR *opendir(const char *dirname); +TLI_DEFINE_ENUM_INTERNAL(opendir) +TLI_DEFINE_STRING_INTERNAL("opendir") +/// int pclose(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(pclose) +TLI_DEFINE_STRING_INTERNAL("pclose") +/// void perror(const char *s); +TLI_DEFINE_ENUM_INTERNAL(perror) +TLI_DEFINE_STRING_INTERNAL("perror") +/// FILE *popen(const char *command, const char *mode); +TLI_DEFINE_ENUM_INTERNAL(popen) +TLI_DEFINE_STRING_INTERNAL("popen") +/// int posix_memalign(void **memptr, size_t alignment, size_t size); +TLI_DEFINE_ENUM_INTERNAL(posix_memalign) +TLI_DEFINE_STRING_INTERNAL("posix_memalign") +/// double pow(double x, double y); +TLI_DEFINE_ENUM_INTERNAL(pow) +TLI_DEFINE_STRING_INTERNAL("pow") +/// float powf(float x, float y); +TLI_DEFINE_ENUM_INTERNAL(powf) +TLI_DEFINE_STRING_INTERNAL("powf") +/// long double powl(long double x, long double y); +TLI_DEFINE_ENUM_INTERNAL(powl) +TLI_DEFINE_STRING_INTERNAL("powl") +/// ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); +TLI_DEFINE_ENUM_INTERNAL(pread) +TLI_DEFINE_STRING_INTERNAL("pread") +/// int printf(const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(printf) +TLI_DEFINE_STRING_INTERNAL("printf") +/// int putc(int c, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(putc) +TLI_DEFINE_STRING_INTERNAL("putc") +/// int putchar(int c); +TLI_DEFINE_ENUM_INTERNAL(putchar) +TLI_DEFINE_STRING_INTERNAL("putchar") +/// int puts(const char *s); +TLI_DEFINE_ENUM_INTERNAL(puts) +TLI_DEFINE_STRING_INTERNAL("puts") +/// ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset); +TLI_DEFINE_ENUM_INTERNAL(pwrite) +TLI_DEFINE_STRING_INTERNAL("pwrite") +/// void qsort(void *base, size_t nel, size_t width, +/// int (*compar)(const void *, const void *)); +TLI_DEFINE_ENUM_INTERNAL(qsort) +TLI_DEFINE_STRING_INTERNAL("qsort") +/// ssize_t read(int fildes, void *buf, size_t nbyte); +TLI_DEFINE_ENUM_INTERNAL(read) +TLI_DEFINE_STRING_INTERNAL("read") +/// ssize_t readlink(const char *path, char *buf, size_t bufsize); +TLI_DEFINE_ENUM_INTERNAL(readlink) +TLI_DEFINE_STRING_INTERNAL("readlink") +/// void *realloc(void *ptr, size_t size); +TLI_DEFINE_ENUM_INTERNAL(realloc) +TLI_DEFINE_STRING_INTERNAL("realloc") +/// void *reallocf(void *ptr, size_t size); +TLI_DEFINE_ENUM_INTERNAL(reallocf) +TLI_DEFINE_STRING_INTERNAL("reallocf") +/// char *realpath(const char *file_name, char *resolved_name); +TLI_DEFINE_ENUM_INTERNAL(realpath) +TLI_DEFINE_STRING_INTERNAL("realpath") +/// int remove(const char *path); +TLI_DEFINE_ENUM_INTERNAL(remove) +TLI_DEFINE_STRING_INTERNAL("remove") +/// int rename(const char *old, const char *new); +TLI_DEFINE_ENUM_INTERNAL(rename) +TLI_DEFINE_STRING_INTERNAL("rename") +/// void rewind(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(rewind) +TLI_DEFINE_STRING_INTERNAL("rewind") +/// double rint(double x); +TLI_DEFINE_ENUM_INTERNAL(rint) +TLI_DEFINE_STRING_INTERNAL("rint") +/// float rintf(float x); +TLI_DEFINE_ENUM_INTERNAL(rintf) +TLI_DEFINE_STRING_INTERNAL("rintf") +/// long double rintl(long double x); +TLI_DEFINE_ENUM_INTERNAL(rintl) +TLI_DEFINE_STRING_INTERNAL("rintl") +/// int rmdir(const char *path); +TLI_DEFINE_ENUM_INTERNAL(rmdir) +TLI_DEFINE_STRING_INTERNAL("rmdir") +/// double round(double x); +TLI_DEFINE_ENUM_INTERNAL(round) +TLI_DEFINE_STRING_INTERNAL("round") +/// float roundf(float x); +TLI_DEFINE_ENUM_INTERNAL(roundf) +TLI_DEFINE_STRING_INTERNAL("roundf") +/// long double roundl(long double x); +TLI_DEFINE_ENUM_INTERNAL(roundl) +TLI_DEFINE_STRING_INTERNAL("roundl") +/// int scanf(const char *restrict format, ... ); +TLI_DEFINE_ENUM_INTERNAL(scanf) +TLI_DEFINE_STRING_INTERNAL("scanf") +/// void setbuf(FILE *stream, char *buf); +TLI_DEFINE_ENUM_INTERNAL(setbuf) +TLI_DEFINE_STRING_INTERNAL("setbuf") +/// int setitimer(int which, const struct itimerval *value, +/// struct itimerval *ovalue); +TLI_DEFINE_ENUM_INTERNAL(setitimer) +TLI_DEFINE_STRING_INTERNAL("setitimer") +/// int setvbuf(FILE *stream, char *buf, int type, size_t size); +TLI_DEFINE_ENUM_INTERNAL(setvbuf) +TLI_DEFINE_STRING_INTERNAL("setvbuf") +/// double sin(double x); +TLI_DEFINE_ENUM_INTERNAL(sin) +TLI_DEFINE_STRING_INTERNAL("sin") +/// float sinf(float x); +TLI_DEFINE_ENUM_INTERNAL(sinf) +TLI_DEFINE_STRING_INTERNAL("sinf") +/// double sinh(double x); +TLI_DEFINE_ENUM_INTERNAL(sinh) +TLI_DEFINE_STRING_INTERNAL("sinh") +/// float sinhf(float x); +TLI_DEFINE_ENUM_INTERNAL(sinhf) +TLI_DEFINE_STRING_INTERNAL("sinhf") +/// long double sinhl(long double x); +TLI_DEFINE_ENUM_INTERNAL(sinhl) +TLI_DEFINE_STRING_INTERNAL("sinhl") +/// long double sinl(long double x); +TLI_DEFINE_ENUM_INTERNAL(sinl) +TLI_DEFINE_STRING_INTERNAL("sinl") +/// int siprintf(char *str, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(siprintf) +TLI_DEFINE_STRING_INTERNAL("siprintf") +/// int snprintf(char *s, size_t n, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(snprintf) +TLI_DEFINE_STRING_INTERNAL("snprintf") +/// int sprintf(char *str, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(sprintf) +TLI_DEFINE_STRING_INTERNAL("sprintf") +/// double sqrt(double x); +TLI_DEFINE_ENUM_INTERNAL(sqrt) +TLI_DEFINE_STRING_INTERNAL("sqrt") +/// float sqrtf(float x); +TLI_DEFINE_ENUM_INTERNAL(sqrtf) +TLI_DEFINE_STRING_INTERNAL("sqrtf") +/// long double sqrtl(long double x); +TLI_DEFINE_ENUM_INTERNAL(sqrtl) +TLI_DEFINE_STRING_INTERNAL("sqrtl") +/// int sscanf(const char *s, const char *format, ... ); +TLI_DEFINE_ENUM_INTERNAL(sscanf) +TLI_DEFINE_STRING_INTERNAL("sscanf") +/// int stat(const char *path, struct stat *buf); +TLI_DEFINE_ENUM_INTERNAL(stat) +TLI_DEFINE_STRING_INTERNAL("stat") +/// int stat64(const char *path, struct stat64 *buf); +TLI_DEFINE_ENUM_INTERNAL(stat64) +TLI_DEFINE_STRING_INTERNAL("stat64") +/// int statvfs(const char *path, struct statvfs *buf); +TLI_DEFINE_ENUM_INTERNAL(statvfs) +TLI_DEFINE_STRING_INTERNAL("statvfs") +/// int statvfs64(const char *path, struct statvfs64 *buf) +TLI_DEFINE_ENUM_INTERNAL(statvfs64) +TLI_DEFINE_STRING_INTERNAL("statvfs64") +/// char *stpcpy(char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(stpcpy) +TLI_DEFINE_STRING_INTERNAL("stpcpy") +/// char *stpncpy(char *s1, const char *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(stpncpy) +TLI_DEFINE_STRING_INTERNAL("stpncpy") +/// int strcasecmp(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strcasecmp) +TLI_DEFINE_STRING_INTERNAL("strcasecmp") +/// char *strcat(char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strcat) +TLI_DEFINE_STRING_INTERNAL("strcat") +/// char *strchr(const char *s, int c); +TLI_DEFINE_ENUM_INTERNAL(strchr) +TLI_DEFINE_STRING_INTERNAL("strchr") +/// int strcmp(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strcmp) +TLI_DEFINE_STRING_INTERNAL("strcmp") +/// int strcoll(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strcoll) +TLI_DEFINE_STRING_INTERNAL("strcoll") +/// char *strcpy(char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strcpy) +TLI_DEFINE_STRING_INTERNAL("strcpy") +/// size_t strcspn(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strcspn) +TLI_DEFINE_STRING_INTERNAL("strcspn") +/// char *strdup(const char *s1); +TLI_DEFINE_ENUM_INTERNAL(strdup) +TLI_DEFINE_STRING_INTERNAL("strdup") +/// size_t strlen(const char *s); +TLI_DEFINE_ENUM_INTERNAL(strlen) +TLI_DEFINE_STRING_INTERNAL("strlen") +/// int strncasecmp(const char *s1, const char *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(strncasecmp) +TLI_DEFINE_STRING_INTERNAL("strncasecmp") +/// char *strncat(char *s1, const char *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(strncat) +TLI_DEFINE_STRING_INTERNAL("strncat") +/// int strncmp(const char *s1, const char *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(strncmp) +TLI_DEFINE_STRING_INTERNAL("strncmp") +/// char *strncpy(char *s1, const char *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(strncpy) +TLI_DEFINE_STRING_INTERNAL("strncpy") +/// char *strndup(const char *s1, size_t n); +TLI_DEFINE_ENUM_INTERNAL(strndup) +TLI_DEFINE_STRING_INTERNAL("strndup") +/// size_t strnlen(const char *s, size_t maxlen); +TLI_DEFINE_ENUM_INTERNAL(strnlen) +TLI_DEFINE_STRING_INTERNAL("strnlen") +/// char *strpbrk(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strpbrk) +TLI_DEFINE_STRING_INTERNAL("strpbrk") +/// char *strrchr(const char *s, int c); +TLI_DEFINE_ENUM_INTERNAL(strrchr) +TLI_DEFINE_STRING_INTERNAL("strrchr") +/// size_t strspn(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strspn) +TLI_DEFINE_STRING_INTERNAL("strspn") +/// char *strstr(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strstr) +TLI_DEFINE_STRING_INTERNAL("strstr") +/// double strtod(const char *nptr, char **endptr); +TLI_DEFINE_ENUM_INTERNAL(strtod) +TLI_DEFINE_STRING_INTERNAL("strtod") +/// float strtof(const char *nptr, char **endptr); +TLI_DEFINE_ENUM_INTERNAL(strtof) +TLI_DEFINE_STRING_INTERNAL("strtof") +// char *strtok(char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strtok) +TLI_DEFINE_STRING_INTERNAL("strtok") +// char *strtok_r(char *s, const char *sep, char **lasts); +TLI_DEFINE_ENUM_INTERNAL(strtok_r) +TLI_DEFINE_STRING_INTERNAL("strtok_r") +/// long int strtol(const char *nptr, char **endptr, int base); +TLI_DEFINE_ENUM_INTERNAL(strtol) +TLI_DEFINE_STRING_INTERNAL("strtol") +/// long double strtold(const char *nptr, char **endptr); +TLI_DEFINE_ENUM_INTERNAL(strtold) +TLI_DEFINE_STRING_INTERNAL("strtold") +/// long long int strtoll(const char *nptr, char **endptr, int base); +TLI_DEFINE_ENUM_INTERNAL(strtoll) +TLI_DEFINE_STRING_INTERNAL("strtoll") +/// unsigned long int strtoul(const char *nptr, char **endptr, int base); +TLI_DEFINE_ENUM_INTERNAL(strtoul) +TLI_DEFINE_STRING_INTERNAL("strtoul") +/// unsigned long long int strtoull(const char *nptr, char **endptr, int base); +TLI_DEFINE_ENUM_INTERNAL(strtoull) +TLI_DEFINE_STRING_INTERNAL("strtoull") +/// size_t strxfrm(char *s1, const char *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(strxfrm) +TLI_DEFINE_STRING_INTERNAL("strxfrm") +/// int system(const char *command); +TLI_DEFINE_ENUM_INTERNAL(system) +TLI_DEFINE_STRING_INTERNAL("system") +/// double tan(double x); +TLI_DEFINE_ENUM_INTERNAL(tan) +TLI_DEFINE_STRING_INTERNAL("tan") +/// float tanf(float x); +TLI_DEFINE_ENUM_INTERNAL(tanf) +TLI_DEFINE_STRING_INTERNAL("tanf") +/// double tanh(double x); +TLI_DEFINE_ENUM_INTERNAL(tanh) +TLI_DEFINE_STRING_INTERNAL("tanh") +/// float tanhf(float x); +TLI_DEFINE_ENUM_INTERNAL(tanhf) +TLI_DEFINE_STRING_INTERNAL("tanhf") +/// long double tanhl(long double x); +TLI_DEFINE_ENUM_INTERNAL(tanhl) +TLI_DEFINE_STRING_INTERNAL("tanhl") +/// long double tanl(long double x); +TLI_DEFINE_ENUM_INTERNAL(tanl) +TLI_DEFINE_STRING_INTERNAL("tanl") +/// clock_t times(struct tms *buffer); +TLI_DEFINE_ENUM_INTERNAL(times) +TLI_DEFINE_STRING_INTERNAL("times") +/// FILE *tmpfile(void); +TLI_DEFINE_ENUM_INTERNAL(tmpfile) +TLI_DEFINE_STRING_INTERNAL("tmpfile") +/// FILE *tmpfile64(void) +TLI_DEFINE_ENUM_INTERNAL(tmpfile64) +TLI_DEFINE_STRING_INTERNAL("tmpfile64") +/// int toascii(int c); +TLI_DEFINE_ENUM_INTERNAL(toascii) +TLI_DEFINE_STRING_INTERNAL("toascii") +/// double trunc(double x); +TLI_DEFINE_ENUM_INTERNAL(trunc) +TLI_DEFINE_STRING_INTERNAL("trunc") +/// float truncf(float x); +TLI_DEFINE_ENUM_INTERNAL(truncf) +TLI_DEFINE_STRING_INTERNAL("truncf") +/// long double truncl(long double x); +TLI_DEFINE_ENUM_INTERNAL(truncl) +TLI_DEFINE_STRING_INTERNAL("truncl") +/// int uname(struct utsname *name); +TLI_DEFINE_ENUM_INTERNAL(uname) +TLI_DEFINE_STRING_INTERNAL("uname") +/// int ungetc(int c, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(ungetc) +TLI_DEFINE_STRING_INTERNAL("ungetc") +/// int unlink(const char *path); +TLI_DEFINE_ENUM_INTERNAL(unlink) +TLI_DEFINE_STRING_INTERNAL("unlink") +/// int unsetenv(const char *name); +TLI_DEFINE_ENUM_INTERNAL(unsetenv) +TLI_DEFINE_STRING_INTERNAL("unsetenv") +/// int utime(const char *path, const struct utimbuf *times); +TLI_DEFINE_ENUM_INTERNAL(utime) +TLI_DEFINE_STRING_INTERNAL("utime") +/// int utimes(const char *path, const struct timeval times[2]); +TLI_DEFINE_ENUM_INTERNAL(utimes) +TLI_DEFINE_STRING_INTERNAL("utimes") +/// void *valloc(size_t size); +TLI_DEFINE_ENUM_INTERNAL(valloc) +TLI_DEFINE_STRING_INTERNAL("valloc") +/// int vfprintf(FILE *stream, const char *format, va_list ap); +TLI_DEFINE_ENUM_INTERNAL(vfprintf) +TLI_DEFINE_STRING_INTERNAL("vfprintf") +/// int vfscanf(FILE *stream, const char *format, va_list arg); +TLI_DEFINE_ENUM_INTERNAL(vfscanf) +TLI_DEFINE_STRING_INTERNAL("vfscanf") +/// int vprintf(const char *restrict format, va_list ap); +TLI_DEFINE_ENUM_INTERNAL(vprintf) +TLI_DEFINE_STRING_INTERNAL("vprintf") +/// int vscanf(const char *format, va_list arg); +TLI_DEFINE_ENUM_INTERNAL(vscanf) +TLI_DEFINE_STRING_INTERNAL("vscanf") +/// int vsnprintf(char *s, size_t n, const char *format, va_list ap); +TLI_DEFINE_ENUM_INTERNAL(vsnprintf) +TLI_DEFINE_STRING_INTERNAL("vsnprintf") +/// int vsprintf(char *s, const char *format, va_list ap); +TLI_DEFINE_ENUM_INTERNAL(vsprintf) +TLI_DEFINE_STRING_INTERNAL("vsprintf") +/// int vsscanf(const char *s, const char *format, va_list arg); +TLI_DEFINE_ENUM_INTERNAL(vsscanf) +TLI_DEFINE_STRING_INTERNAL("vsscanf") +/// ssize_t write(int fildes, const void *buf, size_t nbyte); +TLI_DEFINE_ENUM_INTERNAL(write) +TLI_DEFINE_STRING_INTERNAL("write") + +#undef TLI_DEFINE_ENUM_INTERNAL +#undef TLI_DEFINE_STRING_INTERNAL +#endif // One of TLI_DEFINE_ENUM/STRING are defined. + +#undef TLI_DEFINE_ENUM +#undef TLI_DEFINE_STRING diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h new file mode 100644 index 000000000000..e0a1ee378274 --- /dev/null +++ b/include/llvm/Analysis/TargetLibraryInfo.h @@ -0,0 +1,328 @@ +//===-- 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_ANALYSIS_TARGETLIBRARYINFO_H +#define LLVM_ANALYSIS_TARGETLIBRARYINFO_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/Triple.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" + +namespace llvm { +/// VecDesc - Describes a possible vectorization of a function. +/// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized +/// by a factor 'VectorizationFactor'. +struct VecDesc { + const char *ScalarFnName; + const char *VectorFnName; + unsigned VectorizationFactor; +}; +class PreservedAnalyses; + + namespace LibFunc { + enum Func { +#define TLI_DEFINE_ENUM +#include "llvm/Analysis/TargetLibraryInfo.def" + + NumLibFuncs + }; + } + +/// \brief Implementation of the target library information. +/// +/// This class constructs tables that hold the target library information and +/// make it available. However, it is somewhat expensive to compute and only +/// depends on the triple. So users typicaly interact with the \c +/// TargetLibraryInfo wrapper below. +class TargetLibraryInfoImpl { + friend class TargetLibraryInfo; + + unsigned char AvailableArray[(LibFunc::NumLibFuncs+3)/4]; + llvm::DenseMap<unsigned, std::string> CustomNames; + static const char *const StandardNames[LibFunc::NumLibFuncs]; + + enum AvailabilityState { + StandardName = 3, // (memset to all ones) + CustomName = 1, + Unavailable = 0 // (memset to all zeros) + }; + void setState(LibFunc::Func F, AvailabilityState State) { + AvailableArray[F/4] &= ~(3 << 2*(F&3)); + AvailableArray[F/4] |= State << 2*(F&3); + } + AvailabilityState getState(LibFunc::Func F) const { + return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3); + } + + /// Vectorization descriptors - sorted by ScalarFnName. + std::vector<VecDesc> VectorDescs; + /// Scalarization descriptors - same content as VectorDescs but sorted based + /// on VectorFnName rather than ScalarFnName. + std::vector<VecDesc> ScalarDescs; + +public: + /// \brief List of known vector-functions libraries. + /// + /// The vector-functions library defines, which functions are vectorizable + /// and with which factor. The library can be specified by either frontend, + /// or a commandline option, and then used by + /// addVectorizableFunctionsFromVecLib for filling up the tables of + /// vectorizable functions. + enum VectorLibrary { + NoLibrary, // Don't use any vector library. + Accelerate // Use Accelerate framework. + }; + + TargetLibraryInfoImpl(); + explicit TargetLibraryInfoImpl(const Triple &T); + + // Provide value semantics. + TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI); + TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI); + TargetLibraryInfoImpl &operator=(const TargetLibraryInfoImpl &TLI); + TargetLibraryInfoImpl &operator=(TargetLibraryInfoImpl &&TLI); + + /// \brief Searches for a particular function name. + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. + bool getLibFunc(StringRef funcName, LibFunc::Func &F) const; + + /// \brief Forces a function to be marked as unavailable. + void setUnavailable(LibFunc::Func F) { + setState(F, Unavailable); + } + + /// \brief Forces a function to be marked as available. + void setAvailable(LibFunc::Func F) { + setState(F, StandardName); + } + + /// \brief Forces a function to be marked as available and provide an + /// alternate name that must be used. + void setAvailableWithName(LibFunc::Func F, StringRef Name) { + if (StandardNames[F] != Name) { + setState(F, CustomName); + CustomNames[F] = Name; + assert(CustomNames.find(F) != CustomNames.end()); + } else { + setState(F, StandardName); + } + } + + /// \brief Disables all builtins. + /// + /// This can be used for options like -fno-builtin. + void disableAllFunctions(); + + /// addVectorizableFunctions - Add a set of scalar -> vector mappings, + /// queryable via getVectorizedFunction and getScalarizedFunction. + void addVectorizableFunctions(ArrayRef<VecDesc> Fns); + + /// Calls addVectorizableFunctions with a known preset of functions for the + /// given vector library. + void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib); + + /// isFunctionVectorizable - Return true if the function F has a + /// vector equivalent with vectorization factor VF. + bool isFunctionVectorizable(StringRef F, unsigned VF) const { + return !getVectorizedFunction(F, VF).empty(); + } + + /// isFunctionVectorizable - Return true if the function F has a + /// vector equivalent with any vectorization factor. + bool isFunctionVectorizable(StringRef F) const; + + /// getVectorizedFunction - Return the name of the equivalent of + /// F, vectorized with factor VF. If no such mapping exists, + /// return the empty string. + StringRef getVectorizedFunction(StringRef F, unsigned VF) const; + + /// isFunctionScalarizable - Return true if the function F has a + /// scalar equivalent, and set VF to be the vectorization factor. + bool isFunctionScalarizable(StringRef F, unsigned &VF) const { + return !getScalarizedFunction(F, VF).empty(); + } + + /// getScalarizedFunction - Return the name of the equivalent of + /// F, scalarized. If no such mapping exists, return the empty string. + /// + /// Set VF to the vectorization factor. + StringRef getScalarizedFunction(StringRef F, unsigned &VF) const; +}; + +/// \brief Provides information about what library functions are available for +/// the current target. +/// +/// This both allows optimizations to handle them specially and frontends to +/// disable such optimizations through -fno-builtin etc. +class TargetLibraryInfo { + friend class TargetLibraryAnalysis; + friend class TargetLibraryInfoWrapperPass; + + const TargetLibraryInfoImpl *Impl; + +public: + explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl) : Impl(&Impl) {} + + // Provide value semantics. + TargetLibraryInfo(const TargetLibraryInfo &TLI) : Impl(TLI.Impl) {} + TargetLibraryInfo(TargetLibraryInfo &&TLI) : Impl(TLI.Impl) {} + TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) { + Impl = TLI.Impl; + return *this; + } + TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) { + Impl = TLI.Impl; + return *this; + } + + /// \brief Searches for a particular function name. + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. + bool getLibFunc(StringRef funcName, LibFunc::Func &F) const { + return Impl->getLibFunc(funcName, F); + } + + /// \brief Tests whether a library function is available. + bool has(LibFunc::Func F) const { + return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable; + } + bool isFunctionVectorizable(StringRef F, unsigned VF) const { + return Impl->isFunctionVectorizable(F, VF); + }; + bool isFunctionVectorizable(StringRef F) const { + return Impl->isFunctionVectorizable(F); + }; + StringRef getVectorizedFunction(StringRef F, unsigned VF) const { + return Impl->getVectorizedFunction(F, VF); + }; + + /// \brief Tests if the function is both available and a candidate for + /// optimized code generation. + bool hasOptimizedCodeGen(LibFunc::Func F) const { + if (Impl->getState(F) == TargetLibraryInfoImpl::Unavailable) + return false; + switch (F) { + default: break; + case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl: + case LibFunc::fabs: case LibFunc::fabsf: case LibFunc::fabsl: + case LibFunc::sin: case LibFunc::sinf: case LibFunc::sinl: + case LibFunc::cos: case LibFunc::cosf: case LibFunc::cosl: + case LibFunc::sqrt: case LibFunc::sqrtf: case LibFunc::sqrtl: + case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite: + case LibFunc::sqrtl_finite: + case LibFunc::fmax: case LibFunc::fmaxf: case LibFunc::fmaxl: + case LibFunc::fmin: case LibFunc::fminf: case LibFunc::fminl: + case LibFunc::floor: case LibFunc::floorf: case LibFunc::floorl: + case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl: + case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill: + case LibFunc::rint: case LibFunc::rintf: case LibFunc::rintl: + case LibFunc::round: case LibFunc::roundf: case LibFunc::roundl: + case LibFunc::trunc: case LibFunc::truncf: case LibFunc::truncl: + case LibFunc::log2: case LibFunc::log2f: case LibFunc::log2l: + case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l: + case LibFunc::memcmp: case LibFunc::strcmp: case LibFunc::strcpy: + case LibFunc::stpcpy: case LibFunc::strlen: case LibFunc::strnlen: + case LibFunc::memchr: + return true; + } + return false; + } + + StringRef getName(LibFunc::Func F) const { + auto State = Impl->getState(F); + if (State == TargetLibraryInfoImpl::Unavailable) + return StringRef(); + if (State == TargetLibraryInfoImpl::StandardName) + return Impl->StandardNames[F]; + assert(State == TargetLibraryInfoImpl::CustomName); + return Impl->CustomNames.find(F)->second; + } + + /// \brief Handle invalidation from the pass manager. + /// + /// If we try to invalidate this info, just return false. It cannot become + /// invalid even if the module changes. + bool invalidate(Module &, const PreservedAnalyses &) { return false; } +}; + +/// \brief Analysis pass providing the \c TargetLibraryInfo. +/// +/// Note that this pass's result cannot be invalidated, it is immutable for the +/// life of the module. +class TargetLibraryAnalysis { +public: + typedef TargetLibraryInfo Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Default construct the library analysis. + /// + /// This will use the module's triple to construct the library info for that + /// module. + TargetLibraryAnalysis() {} + + /// \brief Construct a library analysis with preset info. + /// + /// This will directly copy the preset info into the result without + /// consulting the module's triple. + TargetLibraryAnalysis(TargetLibraryInfoImpl PresetInfoImpl) + : PresetInfoImpl(std::move(PresetInfoImpl)) {} + + // Move semantics. We spell out the constructors for MSVC. + TargetLibraryAnalysis(TargetLibraryAnalysis &&Arg) + : PresetInfoImpl(std::move(Arg.PresetInfoImpl)), Impls(std::move(Arg.Impls)) {} + TargetLibraryAnalysis &operator=(TargetLibraryAnalysis &&RHS) { + PresetInfoImpl = std::move(RHS.PresetInfoImpl); + Impls = std::move(RHS.Impls); + return *this; + } + + TargetLibraryInfo run(Module &M); + TargetLibraryInfo run(Function &F); + + /// \brief Provide access to a name for this pass for debugging purposes. + static StringRef name() { return "TargetLibraryAnalysis"; } + +private: + static char PassID; + + Optional<TargetLibraryInfoImpl> PresetInfoImpl; + + StringMap<std::unique_ptr<TargetLibraryInfoImpl>> Impls; + + TargetLibraryInfoImpl &lookupInfoImpl(Triple T); +}; + +class TargetLibraryInfoWrapperPass : public ImmutablePass { + TargetLibraryInfoImpl TLIImpl; + TargetLibraryInfo TLI; + + virtual void anchor(); + +public: + static char ID; + TargetLibraryInfoWrapperPass(); + explicit TargetLibraryInfoWrapperPass(const Triple &T); + explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI); + + TargetLibraryInfo &getTLI() { return TLI; } + const TargetLibraryInfo &getTLI() const { return TLI; } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index 4bd5dd8a221e..86bf1549dc78 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -1,4 +1,4 @@ -//===- llvm/Analysis/TargetTransformInfo.h ----------------------*- C++ -*-===// +//===- TargetTransformInfo.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,66 +6,89 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This pass exposes codegen information to IR-level passes. Every -// transformation that uses codegen information is broken into three parts: -// 1. The IR-level analysis pass. -// 2. The IR-level transformation interface which provides the needed -// information. -// 3. Codegen-level implementation which uses target-specific hooks. -// -// This file defines #2, which is the interface that IR-level transformations -// use for querying the codegen. -// +/// \file +/// This pass exposes codegen information to IR-level passes. Every +/// transformation that uses codegen information is broken into three parts: +/// 1. The IR-level analysis pass. +/// 2. The IR-level transformation interface which provides the needed +/// information. +/// 3. Codegen-level implementation which uses target-specific hooks. +/// +/// This file defines #2, which is the interface that IR-level transformations +/// use for querying the codegen. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFO_H #define LLVM_ANALYSIS_TARGETTRANSFORMINFO_H +#include "llvm/ADT/Optional.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Pass.h" #include "llvm/Support/DataTypes.h" +#include <functional> namespace llvm { class Function; class GlobalValue; class Loop; +class PreservedAnalyses; class Type; class User; class Value; -/// TargetTransformInfo - This pass provides access to the codegen -/// interfaces that are needed for IR-level transformations. +/// \brief Information about a load/store intrinsic defined by the target. +struct MemIntrinsicInfo { + MemIntrinsicInfo() + : ReadMem(false), WriteMem(false), Vol(false), MatchingId(0), + NumMemRefs(0), PtrVal(nullptr) {} + bool ReadMem; + bool WriteMem; + bool Vol; + // Same Id is set by the target for corresponding load/store intrinsics. + unsigned short MatchingId; + int NumMemRefs; + Value *PtrVal; +}; + +/// \brief This pass provides access to the codegen interfaces that are needed +/// for IR-level transformations. class TargetTransformInfo { -protected: - /// \brief The TTI instance one level down the stack. +public: + /// \brief Construct a TTI object using a type implementing the \c Concept + /// API below. /// - /// This is used to implement the default behavior all of the methods which - /// is to delegate up through the stack of TTIs until one can answer the - /// query. - TargetTransformInfo *PrevTTI; + /// This is used by targets to construct a TTI wrapping their target-specific + /// implementaion that encodes appropriate costs for their target. + template <typename T> TargetTransformInfo(T Impl); - /// \brief The top of the stack of TTI analyses available. + /// \brief Construct a baseline TTI object using a minimal implementation of + /// the \c Concept API below. /// - /// This is a convenience routine maintained as TTI analyses become available - /// that complements the PrevTTI delegation chain. When one part of an - /// analysis pass wants to query another part of the analysis pass it can use - /// this to start back at the top of the stack. - TargetTransformInfo *TopTTI; + /// The TTI implementation will reflect the information in the DataLayout + /// provided if non-null. + explicit TargetTransformInfo(const DataLayout *DL); - /// All pass subclasses must in their initializePass routine call - /// pushTTIStack with themselves to update the pointers tracking the previous - /// TTI instance in the analysis group's stack, and the top of the analysis - /// group's stack. - void pushTTIStack(Pass *P); + // Provide move semantics. + TargetTransformInfo(TargetTransformInfo &&Arg); + TargetTransformInfo &operator=(TargetTransformInfo &&RHS); - /// All pass subclasses must call TargetTransformInfo::getAnalysisUsage. - virtual void getAnalysisUsage(AnalysisUsage &AU) const; + // We need to define the destructor out-of-line to define our sub-classes + // out-of-line. + ~TargetTransformInfo(); -public: - /// This class is intended to be subclassed by real implementations. - virtual ~TargetTransformInfo() = 0; + /// \brief Handle the invalidation of this information. + /// + /// When used as a result of \c TargetIRAnalysis this method will be called + /// when the function this was computed for changes. When it returns false, + /// the information is preserved across those changes. + bool invalidate(Function &, const PreservedAnalyses &) { + // FIXME: We should probably in some way ensure that the subtarget + // information for a function hasn't changed. + return false; + } /// \name Generic Target Information /// @{ @@ -86,9 +109,9 @@ public: /// skipped by renaming the registers in the CPU, but they still are encoded /// and thus wouldn't be considered 'free' here. enum TargetCostConstants { - TCC_Free = 0, ///< Expected to fold away in lowering. - TCC_Basic = 1, ///< The cost of a typical 'add' instruction. - TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86. + TCC_Free = 0, ///< Expected to fold away in lowering. + TCC_Basic = 1, ///< The cost of a typical 'add' instruction. + TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86. }; /// \brief Estimate the cost of a specific operation when lowered. @@ -105,16 +128,15 @@ public: /// /// The returned cost is defined in terms of \c TargetCostConstants, see its /// comments for a detailed explanation of the cost values. - virtual unsigned getOperationCost(unsigned Opcode, Type *Ty, - Type *OpTy = nullptr) const; + unsigned getOperationCost(unsigned Opcode, Type *Ty, + Type *OpTy = nullptr) const; /// \brief Estimate the cost of a GEP operation when lowered. /// /// The contract for this function is the same as \c getOperationCost except /// that it supports an interface that provides extra information specific to /// the GEP operation. - virtual unsigned getGEPCost(const Value *Ptr, - ArrayRef<const Value *> Operands) const; + unsigned getGEPCost(const Value *Ptr, ArrayRef<const Value *> Operands) const; /// \brief Estimate the cost of a function call when lowered. /// @@ -125,31 +147,31 @@ public: /// This is the most basic query for estimating call cost: it only knows the /// function type and (potentially) the number of arguments at the call site. /// The latter is only interesting for varargs function types. - virtual unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const; + unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const; /// \brief Estimate the cost of calling a specific function when lowered. /// /// This overload adds the ability to reason about the particular function /// being called in the event it is a library call with special lowering. - virtual unsigned getCallCost(const Function *F, int NumArgs = -1) const; + unsigned getCallCost(const Function *F, int NumArgs = -1) const; /// \brief Estimate the cost of calling a specific function when lowered. /// /// This overload allows specifying a set of candidate argument values. - virtual unsigned getCallCost(const Function *F, - ArrayRef<const Value *> Arguments) const; + unsigned getCallCost(const Function *F, + ArrayRef<const Value *> Arguments) const; /// \brief Estimate the cost of an intrinsic when lowered. /// /// Mirrors the \c getCallCost method but uses an intrinsic identifier. - virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<Type *> ParamTys) const; + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<Type *> ParamTys) const; /// \brief Estimate the cost of an intrinsic when lowered. /// /// Mirrors the \c getCallCost method but uses an intrinsic identifier. - virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<const Value *> Arguments) const; + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<const Value *> Arguments) const; /// \brief Estimate the cost of a given IR user when lowered. /// @@ -166,13 +188,22 @@ public: /// /// The returned cost is defined in terms of \c TargetCostConstants, see its /// comments for a detailed explanation of the cost values. - virtual unsigned getUserCost(const User *U) const; + unsigned getUserCost(const User *U) const; - /// \brief hasBranchDivergence - Return true if branch divergence exists. + /// \brief Return true if branch divergence exists. + /// /// Branch divergence has a significantly negative impact on GPU performance /// when threads in the same wavefront take different paths due to conditional /// branches. - virtual bool hasBranchDivergence() const; + bool hasBranchDivergence() const; + + /// \brief Returns whether V is a source of divergence. + /// + /// This function provides the target-dependent information for + /// the target-independent DivergenceAnalysis. DivergenceAnalysis first + /// builds the dependency graph, and then runs the reachability algorithm + /// starting with the sources of divergence. + bool isSourceOfDivergence(const Value *V) const; /// \brief Test whether calls to a function lower to actual program function /// calls. @@ -186,7 +217,7 @@ public: /// and execution-speed costs. This would allow modelling the core of this /// query more accurately as a call is a single small instruction, but /// incurs significant execution cost. - virtual bool isLoweredToCall(const Function *F) const; + bool isLoweredToCall(const Function *F) const; /// Parameters that control the generic loop unrolling transformation. struct UnrollingPreferences { @@ -196,6 +227,13 @@ public: /// exceed this cost. Set this to UINT_MAX to disable the loop body cost /// restriction. unsigned Threshold; + /// If complete unrolling could help other optimizations (e.g. InstSimplify) + /// to remove N% of instructions, then we can go beyond unroll threshold. + /// This value set the minimal percent for allowing that. + unsigned MinPercentOfOptimized; + /// The absolute cost threshold. We won't go beyond this even if complete + /// unrolling could result in optimizing out 90% of instructions. + unsigned AbsoluteThreshold; /// The cost threshold for the unrolled loop when optimizing for size (set /// to UINT_MAX to disable). unsigned OptSizeThreshold; @@ -203,8 +241,8 @@ public: /// for partial/runtime unrolling (set to UINT_MAX to disable). unsigned PartialThreshold; /// The cost threshold for the unrolled loop when optimizing for size, like - /// OptSizeThreshold, but used for partial/runtime unrolling (set to UINT_MAX - /// to disable). + /// OptSizeThreshold, but used for partial/runtime unrolling (set to + /// UINT_MAX to disable). unsigned PartialOptSizeThreshold; /// A forced unrolling factor (the number of concatenated bodies of the /// original loop in the unrolled loop body). When set to 0, the unrolling @@ -218,18 +256,20 @@ public: unsigned MaxCount; /// Allow partial unrolling (unrolling of loops to expand the size of the /// loop body, not only to eliminate small constant-trip-count loops). - bool Partial; + bool Partial; /// Allow runtime unrolling (unrolling of loops to expand the size of the - /// loop body even when the number of loop iterations is not known at compile - /// time). - bool Runtime; + /// loop body even when the number of loop iterations is not known at + /// compile time). + bool Runtime; + /// Allow emitting expensive instructions (such as divisions) when computing + /// the trip count of a loop for runtime unrolling. + bool AllowExpensiveTripCount; }; /// \brief Get target-customized preferences for the generic loop unrolling /// transformation. The caller will initialize UP with the current /// target-independent defaults. - virtual void getUnrollingPreferences(const Function *F, Loop *L, - UnrollingPreferences &UP) const; + void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const; /// @} @@ -244,38 +284,33 @@ public: /// support is considered as "Fast" if it can outperform, or is on a par /// with, SW implementation when the population is sparse; otherwise, it is /// considered as "Slow". - enum PopcntSupportKind { - PSK_Software, - PSK_SlowHardware, - PSK_FastHardware - }; + enum PopcntSupportKind { PSK_Software, PSK_SlowHardware, PSK_FastHardware }; /// \brief Return true if the specified immediate is legal add immediate, that /// is the target has add instructions which can add a register with the /// immediate without having to materialize the immediate into a register. - virtual bool isLegalAddImmediate(int64_t Imm) const; + bool isLegalAddImmediate(int64_t Imm) const; /// \brief Return true if the specified immediate is legal icmp immediate, /// that is the target has icmp instructions which can compare a register /// against the immediate without having to materialize the immediate into a /// register. - virtual bool isLegalICmpImmediate(int64_t Imm) const; + bool isLegalICmpImmediate(int64_t Imm) const; /// \brief Return true if the addressing mode represented by AM is legal for /// this target, for a load/store of the specified type. /// The type may be VoidTy, in which case only return true if the addressing /// mode is legal for a load/store of any legal type. /// TODO: Handle pre/postinc as well. - virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, - int64_t BaseOffset, bool HasBaseReg, - int64_t Scale) const; + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) const; /// \brief Return true if the target works with masked instruction /// AVX2 allows masks for consecutive load and store for i32 and i64 elements. /// AVX-512 architecture will also allow masks for non-consecutive memory /// accesses. - virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) const; - virtual bool isLegalMaskedLoad (Type *DataType, int Consecutive) const; + bool isLegalMaskedStore(Type *DataType, int Consecutive) const; + bool isLegalMaskedLoad(Type *DataType, int Consecutive) const; /// \brief Return the cost of the scaling factor used in the addressing /// mode represented by AM for this target, for a load/store @@ -283,45 +318,55 @@ public: /// If the AM is supported, the return value must be >= 0. /// If the AM is not supported, it returns a negative value. /// TODO: Handle pre/postinc as well. - virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, - int64_t BaseOffset, bool HasBaseReg, - int64_t Scale) const; + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) const; /// \brief Return true if it's free to truncate a value of type Ty1 to type /// Ty2. e.g. On x86 it's free to truncate a i32 value in register EAX to i16 /// by referencing its sub-register AX. - virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const; + bool isTruncateFree(Type *Ty1, Type *Ty2) const; + + /// \brief Return true if it is profitable to hoist instruction in the + /// then/else to before if. + bool isProfitableToHoist(Instruction *I) const; /// \brief Return true if this type is legal. - virtual bool isTypeLegal(Type *Ty) const; + bool isTypeLegal(Type *Ty) const; /// \brief Returns the target's jmp_buf alignment in bytes. - virtual unsigned getJumpBufAlignment() const; + unsigned getJumpBufAlignment() const; /// \brief Returns the target's jmp_buf size in bytes. - virtual unsigned getJumpBufSize() const; + unsigned getJumpBufSize() const; /// \brief Return true if switches should be turned into lookup tables for the /// target. - virtual bool shouldBuildLookupTables() const; + bool shouldBuildLookupTables() const; + + /// \brief Don't restrict interleaved unrolling to small loops. + bool enableAggressiveInterleaving(bool LoopHasReductions) const; /// \brief Return hardware support for population count. - virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; + PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; /// \brief Return true if the hardware has a fast square-root instruction. - virtual bool haveFastSqrt(Type *Ty) const; + bool haveFastSqrt(Type *Ty) const; + + /// \brief Return the expected cost of supporting the floating point operation + /// of the specified type. + unsigned getFPOpCost(Type *Ty) const; /// \brief Return the expected cost of materializing for the given integer /// immediate of the specified type. - virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; + unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; /// \brief Return the expected cost of materialization for the given integer /// immediate of the specified type for a given instruction. The cost can be /// zero if the immediate can be folded into the specified instruction. - virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, - Type *Ty) const; - virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, - const APInt &Imm, Type *Ty) const; + unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, + Type *Ty) const; + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, + Type *Ty) const; /// @} /// \name Vector Target Information @@ -338,10 +383,10 @@ public: /// \brief Additional information about an operand's possible values. enum OperandValueKind { - OK_AnyValue, // Operand can have any value. - OK_UniformValue, // Operand is uniform (splat of a value). - OK_UniformConstantValue, // Operand is uniform constant. - OK_NonUniformConstantValue // Operand is a non uniform constant value. + OK_AnyValue, // Operand can have any value. + OK_UniformValue, // Operand is uniform (splat of a value). + OK_UniformConstantValue, // Operand is uniform constant. + OK_NonUniformConstantValue // Operand is a non uniform constant value. }; /// \brief Additional properties of an operand's values. @@ -350,18 +395,18 @@ public: /// \return The number of scalar or vector registers that the target has. /// If 'Vectors' is true, it returns the number of vector registers. If it is /// set to false, it returns the number of scalar registers. - virtual unsigned getNumberOfRegisters(bool Vector) const; + unsigned getNumberOfRegisters(bool Vector) const; /// \return The width of the largest scalar or vector register type. - virtual unsigned getRegisterBitWidth(bool Vector) const; + unsigned getRegisterBitWidth(bool Vector) const; /// \return The maximum interleave factor that any transform should try to /// perform for this target. This number depends on the level of parallelism /// and the number of execution units in the CPU. - virtual unsigned getMaxInterleaveFactor() const; + unsigned getMaxInterleaveFactor(unsigned VF) const; /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. - virtual unsigned + unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info = OK_AnyValue, OperandValueKind Opd2Info = OK_AnyValue, @@ -371,31 +416,33 @@ public: /// \return The cost of a shuffle instruction of kind Kind and of type Tp. /// The index and subtype parameters are used by the subvector insertion and /// extraction shuffle kinds. - virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0, - Type *SubTp = nullptr) const; + unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0, + Type *SubTp = nullptr) const; /// \return The expected cost of cast instructions, such as bitcast, trunc, /// zext, etc. - virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst, - Type *Src) const; + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) const; /// \return The expected cost of control-flow related instructions such as /// Phi, Ret, Br. - virtual unsigned getCFInstrCost(unsigned Opcode) const; + unsigned getCFInstrCost(unsigned Opcode) const; /// \returns The expected cost of compare and select instructions. - virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, - Type *CondTy = nullptr) const; + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy = nullptr) const; /// \return The expected cost of vector Insert and Extract. /// Use -1 to indicate that there is no information on the index value. - virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val, - unsigned Index = -1) const; + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index = -1) const; /// \return The cost of Load and Store instructions. - virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src, - unsigned Alignment, - unsigned AddressSpace) const; + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) const; + + /// \return The cost of masked Load and Store instructions. + unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) const; /// \brief Calculate the cost of performing a vector reduction. /// @@ -410,16 +457,20 @@ public: /// Split: /// (v0, v1, v2, v3) /// ((v0+v2), (v1+v3), undef, undef) - virtual unsigned getReductionCost(unsigned Opcode, Type *Ty, - bool IsPairwiseForm) const; + unsigned getReductionCost(unsigned Opcode, Type *Ty, + bool IsPairwiseForm) const; /// \returns The cost of Intrinsic instructions. - virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, - ArrayRef<Type *> Tys) const; + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef<Type *> Tys) const; + + /// \returns The cost of Call instructions. + unsigned getCallInstrCost(Function *F, Type *RetTy, + ArrayRef<Type *> Tys) const; /// \returns The number of pieces into which the provided type must be /// split during legalization. Zero is returned when the answer is unknown. - virtual unsigned getNumberOfParts(Type *Tp) const; + unsigned getNumberOfParts(Type *Tp) const; /// \returns The cost of the address computation. For most targets this can be /// merged into the instruction indexing mode. Some targets might want to @@ -428,28 +479,399 @@ public: /// The 'IsComplex' parameter is a hint that the address computation is likely /// to involve multiple instructions and as such unlikely to be merged into /// the address indexing mode. - virtual unsigned getAddressComputationCost(Type *Ty, - bool IsComplex = false) const; + unsigned getAddressComputationCost(Type *Ty, bool IsComplex = false) const; /// \returns The cost, if any, of keeping values of the given types alive /// over a callsite. /// /// Some types may require the use of register classes that do not have /// any callee-saved registers, so would require a spill and fill. - virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type*> Tys) const; + unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) const; + + /// \returns True if the intrinsic is a supported memory intrinsic. Info + /// will contain additional information - whether the intrinsic may write + /// or read to memory, volatility and the pointer. Info is undefined + /// if false is returned. + bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const; + + /// \returns A value which is the result of the given memory intrinsic. New + /// instructions may be created to extract the result from the given intrinsic + /// memory operation. Returns nullptr if the target cannot create a result + /// from the given intrinsic. + Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) const; /// @} - /// Analysis group identification. +private: + /// \brief The abstract base class used to type erase specific TTI + /// implementations. + class Concept; + + /// \brief The template model for the base class which wraps a concrete + /// implementation in a type erased interface. + template <typename T> class Model; + + std::unique_ptr<Concept> TTIImpl; +}; + +class TargetTransformInfo::Concept { +public: + virtual ~Concept() = 0; + + virtual unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) = 0; + virtual unsigned getGEPCost(const Value *Ptr, + ArrayRef<const Value *> Operands) = 0; + virtual unsigned getCallCost(FunctionType *FTy, int NumArgs) = 0; + virtual unsigned getCallCost(const Function *F, int NumArgs) = 0; + virtual unsigned getCallCost(const Function *F, + ArrayRef<const Value *> Arguments) = 0; + virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<Type *> ParamTys) = 0; + virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<const Value *> Arguments) = 0; + virtual unsigned getUserCost(const User *U) = 0; + virtual bool hasBranchDivergence() = 0; + virtual bool isSourceOfDivergence(const Value *V) = 0; + virtual bool isLoweredToCall(const Function *F) = 0; + virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0; + virtual bool isLegalAddImmediate(int64_t Imm) = 0; + virtual bool isLegalICmpImmediate(int64_t Imm) = 0; + virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, + int64_t BaseOffset, bool HasBaseReg, + int64_t Scale) = 0; + virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) = 0; + virtual bool isLegalMaskedLoad(Type *DataType, int Consecutive) = 0; + virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, + int64_t BaseOffset, bool HasBaseReg, + int64_t Scale) = 0; + virtual bool isTruncateFree(Type *Ty1, Type *Ty2) = 0; + virtual bool isProfitableToHoist(Instruction *I) = 0; + virtual bool isTypeLegal(Type *Ty) = 0; + virtual unsigned getJumpBufAlignment() = 0; + virtual unsigned getJumpBufSize() = 0; + virtual bool shouldBuildLookupTables() = 0; + virtual bool enableAggressiveInterleaving(bool LoopHasReductions) = 0; + virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) = 0; + virtual bool haveFastSqrt(Type *Ty) = 0; + virtual unsigned getFPOpCost(Type *Ty) = 0; + virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) = 0; + virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, + Type *Ty) = 0; + virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, + const APInt &Imm, Type *Ty) = 0; + virtual unsigned getNumberOfRegisters(bool Vector) = 0; + virtual unsigned getRegisterBitWidth(bool Vector) = 0; + virtual unsigned getMaxInterleaveFactor(unsigned VF) = 0; + virtual unsigned + getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info, + OperandValueKind Opd2Info, + OperandValueProperties Opd1PropInfo, + OperandValueProperties Opd2PropInfo) = 0; + virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index, + Type *SubTp) = 0; + virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) = 0; + virtual unsigned getCFInstrCost(unsigned Opcode) = 0; + virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy) = 0; + virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index) = 0; + virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src, + unsigned Alignment, + unsigned AddressSpace) = 0; + virtual unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, + unsigned Alignment, + unsigned AddressSpace) = 0; + virtual unsigned getReductionCost(unsigned Opcode, Type *Ty, + bool IsPairwiseForm) = 0; + virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef<Type *> Tys) = 0; + virtual unsigned getCallInstrCost(Function *F, Type *RetTy, + ArrayRef<Type *> Tys) = 0; + virtual unsigned getNumberOfParts(Type *Tp) = 0; + virtual unsigned getAddressComputationCost(Type *Ty, bool IsComplex) = 0; + virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) = 0; + virtual bool getTgtMemIntrinsic(IntrinsicInst *Inst, + MemIntrinsicInfo &Info) = 0; + virtual Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) = 0; +}; + +template <typename T> +class TargetTransformInfo::Model final : public TargetTransformInfo::Concept { + T Impl; + +public: + Model(T Impl) : Impl(std::move(Impl)) {} + ~Model() override {} + + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) override { + return Impl.getOperationCost(Opcode, Ty, OpTy); + } + unsigned getGEPCost(const Value *Ptr, + ArrayRef<const Value *> Operands) override { + return Impl.getGEPCost(Ptr, Operands); + } + unsigned getCallCost(FunctionType *FTy, int NumArgs) override { + return Impl.getCallCost(FTy, NumArgs); + } + unsigned getCallCost(const Function *F, int NumArgs) override { + return Impl.getCallCost(F, NumArgs); + } + unsigned getCallCost(const Function *F, + ArrayRef<const Value *> Arguments) override { + return Impl.getCallCost(F, Arguments); + } + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<Type *> ParamTys) override { + return Impl.getIntrinsicCost(IID, RetTy, ParamTys); + } + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<const Value *> Arguments) override { + return Impl.getIntrinsicCost(IID, RetTy, Arguments); + } + unsigned getUserCost(const User *U) override { return Impl.getUserCost(U); } + bool hasBranchDivergence() override { return Impl.hasBranchDivergence(); } + bool isSourceOfDivergence(const Value *V) override { + return Impl.isSourceOfDivergence(V); + } + bool isLoweredToCall(const Function *F) override { + return Impl.isLoweredToCall(F); + } + void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) override { + return Impl.getUnrollingPreferences(L, UP); + } + bool isLegalAddImmediate(int64_t Imm) override { + return Impl.isLegalAddImmediate(Imm); + } + bool isLegalICmpImmediate(int64_t Imm) override { + return Impl.isLegalICmpImmediate(Imm); + } + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) override { + return Impl.isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, + Scale); + } + bool isLegalMaskedStore(Type *DataType, int Consecutive) override { + return Impl.isLegalMaskedStore(DataType, Consecutive); + } + bool isLegalMaskedLoad(Type *DataType, int Consecutive) override { + return Impl.isLegalMaskedLoad(DataType, Consecutive); + } + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) override { + return Impl.getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg, Scale); + } + bool isTruncateFree(Type *Ty1, Type *Ty2) override { + return Impl.isTruncateFree(Ty1, Ty2); + } + bool isProfitableToHoist(Instruction *I) override { + return Impl.isProfitableToHoist(I); + } + bool isTypeLegal(Type *Ty) override { return Impl.isTypeLegal(Ty); } + unsigned getJumpBufAlignment() override { return Impl.getJumpBufAlignment(); } + unsigned getJumpBufSize() override { return Impl.getJumpBufSize(); } + bool shouldBuildLookupTables() override { + return Impl.shouldBuildLookupTables(); + } + bool enableAggressiveInterleaving(bool LoopHasReductions) override { + return Impl.enableAggressiveInterleaving(LoopHasReductions); + } + PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) override { + return Impl.getPopcntSupport(IntTyWidthInBit); + } + bool haveFastSqrt(Type *Ty) override { return Impl.haveFastSqrt(Ty); } + + unsigned getFPOpCost(Type *Ty) override { + return Impl.getFPOpCost(Ty); + } + + unsigned getIntImmCost(const APInt &Imm, Type *Ty) override { + return Impl.getIntImmCost(Imm, Ty); + } + unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, + Type *Ty) override { + return Impl.getIntImmCost(Opc, Idx, Imm, Ty); + } + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, + Type *Ty) override { + return Impl.getIntImmCost(IID, Idx, Imm, Ty); + } + unsigned getNumberOfRegisters(bool Vector) override { + return Impl.getNumberOfRegisters(Vector); + } + unsigned getRegisterBitWidth(bool Vector) override { + return Impl.getRegisterBitWidth(Vector); + } + unsigned getMaxInterleaveFactor(unsigned VF) override { + return Impl.getMaxInterleaveFactor(VF); + } + unsigned + getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info, + OperandValueKind Opd2Info, + OperandValueProperties Opd1PropInfo, + OperandValueProperties Opd2PropInfo) override { + return Impl.getArithmeticInstrCost(Opcode, Ty, Opd1Info, Opd2Info, + Opd1PropInfo, Opd2PropInfo); + } + unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index, + Type *SubTp) override { + return Impl.getShuffleCost(Kind, Tp, Index, SubTp); + } + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) override { + return Impl.getCastInstrCost(Opcode, Dst, Src); + } + unsigned getCFInstrCost(unsigned Opcode) override { + return Impl.getCFInstrCost(Opcode); + } + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy) override { + return Impl.getCmpSelInstrCost(Opcode, ValTy, CondTy); + } + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index) override { + return Impl.getVectorInstrCost(Opcode, Val, Index); + } + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) override { + return Impl.getMemoryOpCost(Opcode, Src, Alignment, AddressSpace); + } + unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) override { + return Impl.getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace); + } + unsigned getReductionCost(unsigned Opcode, Type *Ty, + bool IsPairwiseForm) override { + return Impl.getReductionCost(Opcode, Ty, IsPairwiseForm); + } + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef<Type *> Tys) override { + return Impl.getIntrinsicInstrCost(ID, RetTy, Tys); + } + unsigned getCallInstrCost(Function *F, Type *RetTy, + ArrayRef<Type *> Tys) override { + return Impl.getCallInstrCost(F, RetTy, Tys); + } + unsigned getNumberOfParts(Type *Tp) override { + return Impl.getNumberOfParts(Tp); + } + unsigned getAddressComputationCost(Type *Ty, bool IsComplex) override { + return Impl.getAddressComputationCost(Ty, IsComplex); + } + unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) override { + return Impl.getCostOfKeepingLiveOverCall(Tys); + } + bool getTgtMemIntrinsic(IntrinsicInst *Inst, + MemIntrinsicInfo &Info) override { + return Impl.getTgtMemIntrinsic(Inst, Info); + } + Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) override { + return Impl.getOrCreateResultFromMemIntrinsic(Inst, ExpectedType); + } +}; + +template <typename T> +TargetTransformInfo::TargetTransformInfo(T Impl) + : TTIImpl(new Model<T>(Impl)) {} + +/// \brief Analysis pass providing the \c TargetTransformInfo. +/// +/// The core idea of the TargetIRAnalysis is to expose an interface through +/// which LLVM targets can analyze and provide information about the middle +/// end's target-independent IR. This supports use cases such as target-aware +/// cost modeling of IR constructs. +/// +/// This is a function analysis because much of the cost modeling for targets +/// is done in a subtarget specific way and LLVM supports compiling different +/// functions targeting different subtargets in order to support runtime +/// dispatch according to the observed subtarget. +class TargetIRAnalysis { +public: + typedef TargetTransformInfo Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Provide access to a name for this pass for debugging purposes. + static StringRef name() { return "TargetIRAnalysis"; } + + /// \brief Default construct a target IR analysis. + /// + /// This will use the module's datalayout to construct a baseline + /// conservative TTI result. + TargetIRAnalysis(); + + /// \brief Construct an IR analysis pass around a target-provide callback. + /// + /// The callback will be called with a particular function for which the TTI + /// is needed and must return a TTI object for that function. + TargetIRAnalysis(std::function<Result(Function &)> TTICallback); + + // Value semantics. We spell out the constructors for MSVC. + TargetIRAnalysis(const TargetIRAnalysis &Arg) + : TTICallback(Arg.TTICallback) {} + TargetIRAnalysis(TargetIRAnalysis &&Arg) + : TTICallback(std::move(Arg.TTICallback)) {} + TargetIRAnalysis &operator=(const TargetIRAnalysis &RHS) { + TTICallback = RHS.TTICallback; + return *this; + } + TargetIRAnalysis &operator=(TargetIRAnalysis &&RHS) { + TTICallback = std::move(RHS.TTICallback); + return *this; + } + + Result run(Function &F); + +private: + static char PassID; + + /// \brief The callback used to produce a result. + /// + /// We use a completely opaque callback so that targets can provide whatever + /// mechanism they desire for constructing the TTI for a given function. + /// + /// FIXME: Should we really use std::function? It's relatively inefficient. + /// It might be possible to arrange for even stateful callbacks to outlive + /// the analysis and thus use a function_ref which would be lighter weight. + /// This may also be less error prone as the callback is likely to reference + /// the external TargetMachine, and that reference needs to never dangle. + std::function<Result(Function &)> TTICallback; + + /// \brief Helper function used as the callback in the default constructor. + static Result getDefaultTTI(Function &F); +}; + +/// \brief Wrapper pass for TargetTransformInfo. +/// +/// This pass can be constructed from a TTI object which it stores internally +/// and is queried by passes. +class TargetTransformInfoWrapperPass : public ImmutablePass { + TargetIRAnalysis TIRA; + Optional<TargetTransformInfo> TTI; + + virtual void anchor(); + +public: static char ID; + + /// \brief We must provide a default constructor for the pass but it should + /// never be used. + /// + /// Use the constructor below or call one of the creation routines. + TargetTransformInfoWrapperPass(); + + explicit TargetTransformInfoWrapperPass(TargetIRAnalysis TIRA); + + TargetTransformInfo &getTTI(Function &F); }; -/// \brief Create the base case instance of a pass in the TTI analysis group. +/// \brief Create an analysis pass wrapper around a TTI object. /// -/// This class provides the base case for the stack of TTI analyzes. It doesn't -/// delegate to anything and uses the STTI and VTTI objects passed in to -/// satisfy the queries. -ImmutablePass *createNoTargetTransformInfoPass(); +/// This analysis pass just holds the TTI instance and makes it available to +/// clients. +ImmutablePass *createTargetTransformInfoWrapperPass(TargetIRAnalysis TIRA); } // End llvm namespace diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h new file mode 100644 index 000000000000..253319ccd441 --- /dev/null +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -0,0 +1,441 @@ +//===- TargetTransformInfoImpl.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file provides helpers for the implementation of +/// a TargetTransformInfo-conforming class. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H +#define LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H + +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Operator.h" +#include "llvm/IR/Type.h" + +namespace llvm { + +/// \brief Base class for use as a mix-in that aids implementing +/// a TargetTransformInfo-compatible class. +class TargetTransformInfoImplBase { +protected: + typedef TargetTransformInfo TTI; + + const DataLayout *DL; + + explicit TargetTransformInfoImplBase(const DataLayout *DL) + : DL(DL) {} + +public: + // Provide value semantics. MSVC requires that we spell all of these out. + TargetTransformInfoImplBase(const TargetTransformInfoImplBase &Arg) + : DL(Arg.DL) {} + TargetTransformInfoImplBase(TargetTransformInfoImplBase &&Arg) + : DL(std::move(Arg.DL)) {} + TargetTransformInfoImplBase & + operator=(const TargetTransformInfoImplBase &RHS) { + DL = RHS.DL; + return *this; + } + TargetTransformInfoImplBase &operator=(TargetTransformInfoImplBase &&RHS) { + DL = std::move(RHS.DL); + return *this; + } + + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) { + switch (Opcode) { + default: + // By default, just classify everything as 'basic'. + return TTI::TCC_Basic; + + case Instruction::GetElementPtr: + llvm_unreachable("Use getGEPCost for GEP operations!"); + + case Instruction::BitCast: + assert(OpTy && "Cast instructions must provide the operand type"); + if (Ty == OpTy || (Ty->isPointerTy() && OpTy->isPointerTy())) + // Identity and pointer-to-pointer casts are free. + return TTI::TCC_Free; + + // Otherwise, the default basic cost is used. + return TTI::TCC_Basic; + + case Instruction::IntToPtr: { + if (!DL) + return TTI::TCC_Basic; + + // An inttoptr cast is free so long as the input is a legal integer type + // which doesn't contain values outside the range of a pointer. + unsigned OpSize = OpTy->getScalarSizeInBits(); + if (DL->isLegalInteger(OpSize) && + OpSize <= DL->getPointerTypeSizeInBits(Ty)) + return TTI::TCC_Free; + + // Otherwise it's not a no-op. + return TTI::TCC_Basic; + } + case Instruction::PtrToInt: { + if (!DL) + return TTI::TCC_Basic; + + // A ptrtoint cast is free so long as the result is large enough to store + // the pointer, and a legal integer type. + unsigned DestSize = Ty->getScalarSizeInBits(); + if (DL->isLegalInteger(DestSize) && + DestSize >= DL->getPointerTypeSizeInBits(OpTy)) + return TTI::TCC_Free; + + // Otherwise it's not a no-op. + return TTI::TCC_Basic; + } + case Instruction::Trunc: + // trunc to a native type is free (assuming the target has compare and + // shift-right of the same width). + if (DL && DL->isLegalInteger(DL->getTypeSizeInBits(Ty))) + return TTI::TCC_Free; + + return TTI::TCC_Basic; + } + } + + unsigned getGEPCost(const Value *Ptr, ArrayRef<const Value *> Operands) { + // In the basic model, we just assume that all-constant GEPs will be folded + // into their uses via addressing modes. + for (unsigned Idx = 0, Size = Operands.size(); Idx != Size; ++Idx) + if (!isa<Constant>(Operands[Idx])) + return TTI::TCC_Basic; + + return TTI::TCC_Free; + } + + unsigned getCallCost(FunctionType *FTy, int NumArgs) { + assert(FTy && "FunctionType must be provided to this routine."); + + // The target-independent implementation just measures the size of the + // function by approximating that each argument will take on average one + // instruction to prepare. + + if (NumArgs < 0) + // Set the argument number to the number of explicit arguments in the + // function. + NumArgs = FTy->getNumParams(); + + return TTI::TCC_Basic * (NumArgs + 1); + } + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<Type *> ParamTys) { + switch (IID) { + default: + // Intrinsics rarely (if ever) have normal argument setup constraints. + // Model them as having a basic instruction cost. + // FIXME: This is wrong for libc intrinsics. + return TTI::TCC_Basic; + + case Intrinsic::annotation: + case Intrinsic::assume: + case Intrinsic::dbg_declare: + case Intrinsic::dbg_value: + case Intrinsic::invariant_start: + case Intrinsic::invariant_end: + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + case Intrinsic::objectsize: + case Intrinsic::ptr_annotation: + case Intrinsic::var_annotation: + case Intrinsic::experimental_gc_result_int: + case Intrinsic::experimental_gc_result_float: + case Intrinsic::experimental_gc_result_ptr: + case Intrinsic::experimental_gc_result: + case Intrinsic::experimental_gc_relocate: + // These intrinsics don't actually represent code after lowering. + return TTI::TCC_Free; + } + } + + bool hasBranchDivergence() { return false; } + + bool isSourceOfDivergence(const Value *V) { return false; } + + bool isLoweredToCall(const Function *F) { + // FIXME: These should almost certainly not be handled here, and instead + // handled with the help of TLI or the target itself. This was largely + // ported from existing analysis heuristics here so that such refactorings + // can take place in the future. + + if (F->isIntrinsic()) + return false; + + if (F->hasLocalLinkage() || !F->hasName()) + return true; + + StringRef Name = F->getName(); + + // These will all likely lower to a single selection DAG node. + if (Name == "copysign" || Name == "copysignf" || Name == "copysignl" || + Name == "fabs" || Name == "fabsf" || Name == "fabsl" || Name == "sin" || + Name == "fmin" || Name == "fminf" || Name == "fminl" || + Name == "fmax" || Name == "fmaxf" || Name == "fmaxl" || + Name == "sinf" || Name == "sinl" || Name == "cos" || Name == "cosf" || + Name == "cosl" || Name == "sqrt" || Name == "sqrtf" || Name == "sqrtl") + return false; + + // These are all likely to be optimized into something smaller. + if (Name == "pow" || Name == "powf" || Name == "powl" || Name == "exp2" || + Name == "exp2l" || Name == "exp2f" || Name == "floor" || + Name == "floorf" || Name == "ceil" || Name == "round" || + Name == "ffs" || Name == "ffsl" || Name == "abs" || Name == "labs" || + Name == "llabs") + return false; + + return true; + } + + void getUnrollingPreferences(Loop *, TTI::UnrollingPreferences &) {} + + bool isLegalAddImmediate(int64_t Imm) { return false; } + + bool isLegalICmpImmediate(int64_t Imm) { return false; } + + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + // Guess that only reg and reg+reg addressing is allowed. This heuristic is + // taken from the implementation of LSR. + return !BaseGV && BaseOffset == 0 && (Scale == 0 || Scale == 1); + } + + bool isLegalMaskedStore(Type *DataType, int Consecutive) { return false; } + + bool isLegalMaskedLoad(Type *DataType, int Consecutive) { return false; } + + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + // Guess that all legal addressing mode are free. + if (isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, Scale)) + return 0; + return -1; + } + + bool isTruncateFree(Type *Ty1, Type *Ty2) { return false; } + + bool isProfitableToHoist(Instruction *I) { return true; } + + bool isTypeLegal(Type *Ty) { return false; } + + unsigned getJumpBufAlignment() { return 0; } + + unsigned getJumpBufSize() { return 0; } + + bool shouldBuildLookupTables() { return true; } + + bool enableAggressiveInterleaving(bool LoopHasReductions) { return false; } + + TTI::PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) { + return TTI::PSK_Software; + } + + bool haveFastSqrt(Type *Ty) { return false; } + + unsigned getFPOpCost(Type *Ty) { return TargetTransformInfo::TCC_Basic; } + + unsigned getIntImmCost(const APInt &Imm, Type *Ty) { return TTI::TCC_Basic; } + + unsigned getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm, + Type *Ty) { + return TTI::TCC_Free; + } + + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, + Type *Ty) { + return TTI::TCC_Free; + } + + unsigned getNumberOfRegisters(bool Vector) { return 8; } + + unsigned getRegisterBitWidth(bool Vector) { return 32; } + + unsigned getMaxInterleaveFactor(unsigned VF) { return 1; } + + unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, + TTI::OperandValueKind Opd1Info, + TTI::OperandValueKind Opd2Info, + TTI::OperandValueProperties Opd1PropInfo, + TTI::OperandValueProperties Opd2PropInfo) { + return 1; + } + + unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Ty, int Index, + Type *SubTp) { + return 1; + } + + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { return 1; } + + unsigned getCFInstrCost(unsigned Opcode) { return 1; } + + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) { + return 1; + } + + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) { + return 1; + } + + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) { + return 1; + } + + unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) { + return 1; + } + + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef<Type *> Tys) { + return 1; + } + + unsigned getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys) { + return 1; + } + + unsigned getNumberOfParts(Type *Tp) { return 0; } + + unsigned getAddressComputationCost(Type *Tp, bool) { return 0; } + + unsigned getReductionCost(unsigned, Type *, bool) { return 1; } + + unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) { return 0; } + + bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) { + return false; + } + + Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) { + return nullptr; + } +}; + +/// \brief CRTP base class for use as a mix-in that aids implementing +/// a TargetTransformInfo-compatible class. +template <typename T> +class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase { +private: + typedef TargetTransformInfoImplBase BaseT; + +protected: + explicit TargetTransformInfoImplCRTPBase(const DataLayout *DL) + : BaseT(DL) {} + +public: + // Provide value semantics. MSVC requires that we spell all of these out. + TargetTransformInfoImplCRTPBase(const TargetTransformInfoImplCRTPBase &Arg) + : BaseT(static_cast<const BaseT &>(Arg)) {} + TargetTransformInfoImplCRTPBase(TargetTransformInfoImplCRTPBase &&Arg) + : BaseT(std::move(static_cast<BaseT &>(Arg))) {} + TargetTransformInfoImplCRTPBase & + operator=(const TargetTransformInfoImplCRTPBase &RHS) { + BaseT::operator=(static_cast<const BaseT &>(RHS)); + return *this; + } + TargetTransformInfoImplCRTPBase & + operator=(TargetTransformInfoImplCRTPBase &&RHS) { + BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); + return *this; + } + + using BaseT::getCallCost; + + unsigned getCallCost(const Function *F, int NumArgs) { + assert(F && "A concrete function must be provided to this routine."); + + if (NumArgs < 0) + // Set the argument number to the number of explicit arguments in the + // function. + NumArgs = F->arg_size(); + + if (Intrinsic::ID IID = F->getIntrinsicID()) { + FunctionType *FTy = F->getFunctionType(); + SmallVector<Type *, 8> ParamTys(FTy->param_begin(), FTy->param_end()); + return static_cast<T *>(this) + ->getIntrinsicCost(IID, FTy->getReturnType(), ParamTys); + } + + if (!static_cast<T *>(this)->isLoweredToCall(F)) + return TTI::TCC_Basic; // Give a basic cost if it will be lowered + // directly. + + return static_cast<T *>(this)->getCallCost(F->getFunctionType(), NumArgs); + } + + unsigned getCallCost(const Function *F, ArrayRef<const Value *> Arguments) { + // Simply delegate to generic handling of the call. + // FIXME: We should use instsimplify or something else to catch calls which + // will constant fold with these arguments. + return static_cast<T *>(this)->getCallCost(F, Arguments.size()); + } + + using BaseT::getIntrinsicCost; + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<const Value *> Arguments) { + // Delegate to the generic intrinsic handling code. This mostly provides an + // opportunity for targets to (for example) special case the cost of + // certain intrinsics based on constants used as arguments. + SmallVector<Type *, 8> ParamTys; + ParamTys.reserve(Arguments.size()); + for (unsigned Idx = 0, Size = Arguments.size(); Idx != Size; ++Idx) + ParamTys.push_back(Arguments[Idx]->getType()); + return static_cast<T *>(this)->getIntrinsicCost(IID, RetTy, ParamTys); + } + + unsigned getUserCost(const User *U) { + if (isa<PHINode>(U)) + return TTI::TCC_Free; // Model all PHI nodes as free. + + if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) { + SmallVector<const Value *, 4> Indices(GEP->idx_begin(), GEP->idx_end()); + return static_cast<T *>(this) + ->getGEPCost(GEP->getPointerOperand(), Indices); + } + + if (auto CS = ImmutableCallSite(U)) { + const Function *F = CS.getCalledFunction(); + if (!F) { + // Just use the called value type. + Type *FTy = CS.getCalledValue()->getType()->getPointerElementType(); + return static_cast<T *>(this) + ->getCallCost(cast<FunctionType>(FTy), CS.arg_size()); + } + + SmallVector<const Value *, 8> Arguments(CS.arg_begin(), CS.arg_end()); + return static_cast<T *>(this)->getCallCost(F, Arguments); + } + + if (const CastInst *CI = dyn_cast<CastInst>(U)) { + // Result of a cmp instruction is often extended (to be used by other + // cmp instructions, logical or return instructions). These are usually + // nop on most sane targets. + if (isa<CmpInst>(CI->getOperand(0))) + return TTI::TCC_Free; + } + + return static_cast<T *>(this)->getOperationCost( + Operator::getOpcode(U), U->getType(), + U->getNumOperands() == 1 ? U->getOperand(0)->getType() : nullptr); + } +}; +} + +#endif diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index cc588381727d..653821d02271 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -16,6 +16,7 @@ #define LLVM_ANALYSIS_VALUETRACKING_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/IR/Instruction.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -28,17 +29,18 @@ namespace llvm { class AssumptionCache; class DominatorTree; class TargetLibraryInfo; + class LoopInfo; /// Determine which bits of V are known to be either zero or one and return /// them in the KnownZero/KnownOne bit sets. /// /// This function is defined on values with integer type, values with pointer - /// type (but only if TD is non-null), and vectors of integers. In the case + /// type, and vectors of integers. In the case /// where V is a vector, the known zero and known one values are the /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, - const DataLayout *TD = nullptr, unsigned Depth = 0, + const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -46,11 +48,16 @@ namespace llvm { /// \p KnownZero the set of bits that are known to be zero void computeKnownBitsFromRangeMetadata(const MDNode &Ranges, APInt &KnownZero); + /// Returns true if LHS and RHS have no common bits set. + bool haveNoCommonBitsSet(Value *LHS, Value *RHS, const DataLayout &DL, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// ComputeSignBit - Determine whether the sign bit is known to be zero or /// one. Convenience wrapper around computeKnownBits. void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne, - const DataLayout *TD = nullptr, unsigned Depth = 0, + const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -60,7 +67,8 @@ namespace llvm { /// element is known to be a power of two when defined. Supports values with /// integer or pointer type and vectors of integers. If 'OrZero' is set then /// returns true if the given value is either a power of two or zero. - bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero = false, unsigned Depth = 0, + bool isKnownToBeAPowerOfTwo(Value *V, const DataLayout &DL, + bool OrZero = false, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -69,8 +77,8 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, - unsigned Depth = 0, AssumptionCache *AC = nullptr, + bool isKnownNonZero(Value *V, const DataLayout &DL, unsigned Depth = 0, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -79,13 +87,12 @@ namespace llvm { /// zero for bits that V cannot have. /// /// This function is defined on values with integer type, values with pointer - /// type (but only if TD is non-null), and vectors of integers. In the case + /// type, and vectors of integers. In the case /// where V is a vector, the mask, known zero, and known one values are the /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. - bool MaskedValueIsZero(Value *V, const APInt &Mask, - const DataLayout *TD = nullptr, unsigned Depth = 0, - AssumptionCache *AC = nullptr, + bool MaskedValueIsZero(Value *V, const APInt &Mask, const DataLayout &DL, + unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -97,7 +104,7 @@ namespace llvm { /// /// 'Op' must have a scalar integer type. /// - unsigned ComputeNumSignBits(Value *Op, const DataLayout *TD = nullptr, + unsigned ComputeNumSignBits(Value *Op, const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -116,6 +123,11 @@ namespace llvm { /// bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0); + /// CannotBeOrderedLessThanZero - Return true if we can prove that the + /// specified FP value is either a NaN or never less than 0.0. + /// + bool CannotBeOrderedLessThanZero(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, @@ -137,11 +149,12 @@ namespace llvm { /// 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 DataLayout *TD); + const DataLayout &DL); static inline const Value * GetPointerBaseWithConstantOffset(const Value *Ptr, int64_t &Offset, - const DataLayout *TD) { - return GetPointerBaseWithConstantOffset(const_cast<Value*>(Ptr), Offset,TD); + const DataLayout &DL) { + return GetPointerBaseWithConstantOffset(const_cast<Value *>(Ptr), Offset, + DL); } /// getConstantStringInfo - This function computes the length of a @@ -162,26 +175,59 @@ namespace llvm { /// 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 DataLayout *TD = nullptr, + Value *GetUnderlyingObject(Value *V, const DataLayout &DL, unsigned MaxLookup = 6); - static inline const Value * - GetUnderlyingObject(const Value *V, const DataLayout *TD = nullptr, - unsigned MaxLookup = 6) { - return GetUnderlyingObject(const_cast<Value *>(V), TD, MaxLookup); + static inline const Value *GetUnderlyingObject(const Value *V, + const DataLayout &DL, + unsigned MaxLookup = 6) { + return GetUnderlyingObject(const_cast<Value *>(V), DL, MaxLookup); } - /// GetUnderlyingObjects - This method is similar to GetUnderlyingObject - /// except that it can look through phi and select instructions and return - /// multiple objects. - void GetUnderlyingObjects(Value *V, - SmallVectorImpl<Value *> &Objects, - const DataLayout *TD = nullptr, + /// \brief This method is similar to GetUnderlyingObject except that it can + /// look through phi and select instructions and return multiple objects. + /// + /// If LoopInfo is passed, loop phis are further analyzed. If a pointer + /// accesses different objects in each iteration, we don't look through the + /// phi node. E.g. consider this loop nest: + /// + /// int **A; + /// for (i) + /// for (j) { + /// A[i][j] = A[i-1][j] * B[j] + /// } + /// + /// This is transformed by Load-PRE to stash away A[i] for the next iteration + /// of the outer loop: + /// + /// Curr = A[0]; // Prev_0 + /// for (i: 1..N) { + /// Prev = Curr; // Prev = PHI (Prev_0, Curr) + /// Curr = A[i]; + /// for (j: 0..N) { + /// Curr[j] = Prev[j] * B[j] + /// } + /// } + /// + /// Since A[i] and A[i-1] are independent pointers, getUnderlyingObjects + /// should not assume that Curr and Prev share the same underlying object thus + /// it shouldn't look through the phi above. + void GetUnderlyingObjects(Value *V, SmallVectorImpl<Value *> &Objects, + const DataLayout &DL, LoopInfo *LI = nullptr, unsigned MaxLookup = 6); /// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer /// are lifetime markers. bool onlyUsedByLifetimeMarkers(const Value *V); + /// isDereferenceablePointer - Return true if this is always a dereferenceable + /// pointer. If the context instruction is specified perform context-sensitive + /// analysis and return true if the pointer is dereferenceable at the + /// specified instruction. + bool isDereferenceablePointer(const Value *V, const DataLayout &DL, + const Instruction *CtxI = nullptr, + const DominatorTree *DT = nullptr, + const TargetLibraryInfo *TLI = nullptr); + /// isSafeToSpeculativelyExecute - Return true if the instruction does not /// have any effects besides calculating the result and does not have /// undefined behavior. @@ -195,37 +241,82 @@ namespace llvm { /// memory leak. It also returns false for instructions related to control /// flow, specifically terminators and PHI nodes. /// - /// This method only looks at the instruction itself and its operands, so if - /// this method returns true, it is safe to move the instruction as long as - /// the correct dominance relationships for the operands and users hold. - /// However, this method can return true for instructions that read memory; + /// If the CtxI is specified this method performs context-sensitive analysis + /// and returns true if it is safe to execute the instruction immediately + /// before the CtxI. + /// + /// If the CtxI is NOT specified this method only looks at the instruction + /// itself and its operands, so if this method returns true, it is safe to + /// move the instruction as long as the correct dominance relationships for + /// the operands and users hold. + /// + /// This method can return true for instructions that read memory; /// for such instructions, moving them may change the resulting value. bool isSafeToSpeculativelyExecute(const Value *V, - const DataLayout *TD = nullptr); + const Instruction *CtxI = nullptr, + const DominatorTree *DT = nullptr, + const TargetLibraryInfo *TLI = nullptr); /// isKnownNonNull - Return true if this pointer couldn't possibly be null by /// its definition. This returns true for allocas, non-extern-weak globals /// and byval arguments. bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = nullptr); + /// isKnownNonNullAt - Return true if this pointer couldn't possibly be null. + /// If the context instruction is specified perform context-sensitive analysis + /// and return true if the pointer couldn't possibly be null at the specified + /// instruction. + bool isKnownNonNullAt(const Value *V, + const Instruction *CtxI = nullptr, + const DominatorTree *DT = nullptr, + const TargetLibraryInfo *TLI = nullptr); + /// Return true if it is valid to use the assumptions provided by an /// assume intrinsic, I, at the point in the control-flow identified by the /// context instruction, CxtI. bool isValidAssumeForContext(const Instruction *I, const Instruction *CxtI, - const DataLayout *DL = nullptr, const DominatorTree *DT = nullptr); enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows }; OverflowResult computeOverflowForUnsignedMul(Value *LHS, Value *RHS, - const DataLayout *DL, + const DataLayout &DL, AssumptionCache *AC, const Instruction *CxtI, const DominatorTree *DT); OverflowResult computeOverflowForUnsignedAdd(Value *LHS, Value *RHS, - const DataLayout *DL, + const DataLayout &DL, AssumptionCache *AC, const Instruction *CxtI, const DominatorTree *DT); + + /// \brief Specific patterns of select instructions we can match. + enum SelectPatternFlavor { + SPF_UNKNOWN = 0, + SPF_SMIN, // Signed minimum + SPF_UMIN, // Unsigned minimum + SPF_SMAX, // Signed maximum + SPF_UMAX, // Unsigned maximum + SPF_ABS, // Absolute value + SPF_NABS // Negated absolute value + }; + /// Pattern match integer [SU]MIN, [SU]MAX and ABS idioms, returning the kind + /// and providing the out parameter results if we successfully match. + /// + /// If CastOp is not nullptr, also match MIN/MAX idioms where the type does + /// not match that of the original select. If this is the case, the cast + /// operation (one of Trunc,SExt,Zext) that must be done to transform the + /// type of LHS and RHS into the type of V is returned in CastOp. + /// + /// For example: + /// %1 = icmp slt i32 %a, i32 4 + /// %2 = sext i32 %a to i64 + /// %3 = select i1 %1, i64 %2, i64 4 + /// + /// -> LHS = %a, RHS = i32 4, *CastOp = Instruction::SExt + /// + SelectPatternFlavor matchSelectPattern(Value *V, Value *&LHS, Value *&RHS, + Instruction::CastOps *CastOp = nullptr); + } // end namespace llvm #endif diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h index ed2dcf84f924..96c420151858 100644 --- a/include/llvm/Bitcode/BitCodes.h +++ b/include/llvm/Bitcode/BitCodes.h @@ -125,7 +125,7 @@ public: case Blob: return false; } - llvm_unreachable("Invalid encoding"); + report_fatal_error("Invalid encoding"); } /// isChar6 - Return true if this character is legal in the Char6 encoding. @@ -164,8 +164,8 @@ template <> struct isPodLike<BitCodeAbbrevOp> { static const bool value=true; }; /// specialized format instead of the fully-general, fully-vbr, format. class BitCodeAbbrev : public RefCountedBase<BitCodeAbbrev> { SmallVector<BitCodeAbbrevOp, 32> OperandList; - ~BitCodeAbbrev() {} // Only RefCountedBase is allowed to delete. + ~BitCodeAbbrev() = default; friend class RefCountedBase<BitCodeAbbrev>; public: diff --git a/include/llvm/Bitcode/BitcodeWriterPass.h b/include/llvm/Bitcode/BitcodeWriterPass.h index 8fe9b7e8434d..ae915c688ba0 100644 --- a/include/llvm/Bitcode/BitcodeWriterPass.h +++ b/include/llvm/Bitcode/BitcodeWriterPass.h @@ -26,7 +26,11 @@ class PreservedAnalyses; /// \brief Create and return a pass that writes the module to the specified /// ostream. Note that this pass is designed for use with the legacy pass /// manager. -ModulePass *createBitcodeWriterPass(raw_ostream &Str); +/// +/// If \c ShouldPreserveUseListOrder, encode use-list order so it can be +/// reproduced when deserialized. +ModulePass *createBitcodeWriterPass(raw_ostream &Str, + bool ShouldPreserveUseListOrder = false); /// \brief Pass for writing a module of IR out to a bitcode file. /// @@ -34,10 +38,16 @@ ModulePass *createBitcodeWriterPass(raw_ostream &Str); /// a pass for the legacy pass manager, use the function above. class BitcodeWriterPass { raw_ostream &OS; + bool ShouldPreserveUseListOrder; public: /// \brief Construct a bitcode writer pass around a particular output stream. - explicit BitcodeWriterPass(raw_ostream &OS) : OS(OS) {} + /// + /// If \c ShouldPreserveUseListOrder, encode use-list order so it can be + /// reproduced when deserialized. + explicit BitcodeWriterPass(raw_ostream &OS, + bool ShouldPreserveUseListOrder = false) + : OS(OS), ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {} /// \brief Run the bitcode writer pass, and output the module to the selected /// output stream. diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 865a3e668428..46e64d112ea7 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -24,8 +24,6 @@ namespace llvm { -class Deserializer; - /// This class is used to read from an LLVM bitcode stream, maintaining /// information that is global to decoding the entire file. While a file is /// being read, multiple cursors can be independently advanced or skipped around @@ -50,8 +48,8 @@ private: /// information in the BlockInfo block. Only llvm-bcanalyzer uses this. bool IgnoreBlockInfoNames; - BitstreamReader(const BitstreamReader&) LLVM_DELETED_FUNCTION; - void operator=(const BitstreamReader&) LLVM_DELETED_FUNCTION; + BitstreamReader(const BitstreamReader&) = delete; + void operator=(const BitstreamReader&) = delete; public: BitstreamReader() : IgnoreBlockInfoNames(true) { } @@ -164,7 +162,6 @@ struct BitstreamEntry { /// Unlike iterators, BitstreamCursors are heavy-weight objects that should not /// be passed by value. class BitstreamCursor { - friend class Deserializer; BitstreamReader *BitStream; size_t NextChar; @@ -201,6 +198,8 @@ class BitstreamCursor { public: + static const size_t MaxChunkSize = sizeof(word_t) * 8; + BitstreamCursor() { init(nullptr); } explicit BitstreamCursor(BitstreamReader &R) { init(&R); } @@ -258,8 +257,8 @@ public: AF_DontAutoprocessAbbrevs = 2 }; - /// Advance the current bitstream, returning the next entry in the stream. - BitstreamEntry advance(unsigned Flags = 0) { + /// Advance the current bitstream, returning the next entry in the stream. + BitstreamEntry advance(unsigned Flags = 0) { while (1) { unsigned Code = ReadCode(); if (Code == bitc::END_BLOCK) { @@ -301,7 +300,7 @@ public: /// Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { - uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); + size_t ByteNo = size_t(BitNo/8) & ~(sizeof(word_t)-1); unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); assert(canSkipToPos(ByteNo) && "Invalid location"); @@ -315,7 +314,8 @@ public: } void fillCurWord() { - assert(Size == 0 || NextChar < (unsigned)Size); + if (Size != 0 && NextChar >= Size) + report_fatal_error("Unexpected end of file"); // Read the next word from the stream. uint8_t Array[sizeof(word_t)] = {0}; @@ -337,7 +337,7 @@ public: } word_t Read(unsigned NumBits) { - static const unsigned BitsInWord = sizeof(word_t) * 8; + static const unsigned BitsInWord = MaxChunkSize; assert(NumBits && NumBits <= BitsInWord && "Cannot return zero or more than BitsInWord bits!"); @@ -490,11 +490,11 @@ private: //===--------------------------------------------------------------------===// public: - /// Return the abbreviation for the specified AbbrevId. const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) { - unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV; - assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); + unsigned AbbrevNo = AbbrevID - bitc::FIRST_APPLICATION_ABBREV; + if (AbbrevNo >= CurAbbrevs.size()) + report_fatal_error("Invalid abbrev number"); return CurAbbrevs[AbbrevNo].get(); } diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 043ecd3d65d7..3a6b5c704d19 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -146,7 +146,27 @@ namespace bitc { METADATA_OLD_NODE = 8, // OLD_NODE: [n x (type num, value num)] METADATA_OLD_FN_NODE = 9, // OLD_FN_NODE: [n x (type num, value num)] METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes] - METADATA_ATTACHMENT = 11 // [m x [value, [n x [id, mdnode]]] + METADATA_ATTACHMENT = 11, // [m x [value, [n x [id, mdnode]]] + METADATA_GENERIC_DEBUG = 12, // [distinct, tag, vers, header, n x md num] + METADATA_SUBRANGE = 13, // [distinct, count, lo] + METADATA_ENUMERATOR = 14, // [distinct, value, name] + METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc] + METADATA_FILE = 16, // [distinct, filename, directory] + METADATA_DERIVED_TYPE = 17, // [distinct, ...] + METADATA_COMPOSITE_TYPE= 18, // [distinct, ...] + METADATA_SUBROUTINE_TYPE=19, // [distinct, flags, types] + METADATA_COMPILE_UNIT = 20, // [distinct, ...] + METADATA_SUBPROGRAM = 21, // [distinct, ...] + METADATA_LEXICAL_BLOCK = 22, // [distinct, scope, file, line, column] + METADATA_LEXICAL_BLOCK_FILE=23,//[distinct, scope, file, discriminator] + METADATA_NAMESPACE = 24, // [distinct, scope, file, name, line] + METADATA_TEMPLATE_TYPE = 25, // [distinct, scope, name, type, ...] + METADATA_TEMPLATE_VALUE= 26, // [distinct, scope, name, type, value, ...] + METADATA_GLOBAL_VAR = 27, // [distinct, ...] + METADATA_LOCAL_VAR = 28, // [distinct, ...] + METADATA_EXPRESSION = 29, // [distinct, n x element] + METADATA_OBJC_PROPERTY = 30, // [distinct, name, file, line, ...] + METADATA_IMPORTED_ENTITY=31, // [distinct, tag, scope, entity, line, name] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each @@ -273,7 +293,7 @@ namespace bitc { FUNC_CODE_INST_BINOP = 2, // BINOP: [opcode, ty, opval, opval] FUNC_CODE_INST_CAST = 3, // CAST: [opcode, ty, opty, opval] - FUNC_CODE_INST_GEP = 4, // GEP: [n x operands] + FUNC_CODE_INST_GEP_OLD = 4, // GEP: [n x operands] FUNC_CODE_INST_SELECT = 5, // SELECT: [ty, opval, opval, opval] FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opty, opval, opval] FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [ty, opval, opval, opval] @@ -298,7 +318,7 @@ namespace bitc { // This store code encodes the pointer type, rather than the value type // this is so information only available in the pointer type (e.g. address // spaces) is retained. - FUNC_CODE_INST_STORE = 24, // STORE: [ptrty,ptr,val, align, vol] + FUNC_CODE_INST_STORE_OLD = 24, // STORE: [ptrty,ptr,val, align, vol] // 25 is unused. FUNC_CODE_INST_EXTRACTVAL = 26, // EXTRACTVAL: [n x operands] FUNC_CODE_INST_INSERTVAL = 27, // INSERTVAL: [n x operands] @@ -307,7 +327,7 @@ namespace bitc { FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred] // new select on i1 or [N x i1] FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred] - FUNC_CODE_INST_INBOUNDS_GEP= 30, // INBOUNDS_GEP: [n x operands] + FUNC_CODE_INST_INBOUNDS_GEP_OLD = 30, // INBOUNDS_GEP: [n x operands] FUNC_CODE_INST_INDIRECTBR = 31, // INDIRECTBR: [opty, op0, op1, ...] // 32 is unused. FUNC_CODE_DEBUG_LOC_AGAIN = 33, // DEBUG_LOC_AGAIN @@ -316,7 +336,7 @@ namespace bitc { FUNC_CODE_DEBUG_LOC = 35, // DEBUG_LOC: [Line,Col,ScopeVal, IAVal] FUNC_CODE_INST_FENCE = 36, // FENCE: [ordering, synchscope] - FUNC_CODE_INST_CMPXCHG = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol, + FUNC_CODE_INST_CMPXCHG_OLD = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol, // ordering, synchscope] FUNC_CODE_INST_ATOMICRMW = 38, // ATOMICRMW: [ptrty,ptr,val, operation, // align, vol, @@ -325,8 +345,13 @@ namespace bitc { FUNC_CODE_INST_LANDINGPAD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...] FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol, // ordering, synchscope] - FUNC_CODE_INST_STOREATOMIC = 42 // STORE: [ptrty,ptr,val, align, vol + FUNC_CODE_INST_STOREATOMIC_OLD = 42, // STORE: [ptrty,ptr,val, align, vol // ordering, synchscope] + FUNC_CODE_INST_GEP = 43, // GEP: [inbounds, n x operands] + FUNC_CODE_INST_STORE = 44, // STORE: [ptrty,ptr,valty,val, align, vol] + FUNC_CODE_INST_STOREATOMIC = 45, // STORE: [ptrty,ptr,val, align, vol + FUNC_CODE_INST_CMPXCHG = 46, // CMPXCHG: [ptrty,ptr,valty,cmp,new, align, + // vol,ordering,synchscope] }; enum UseListCodes { @@ -376,7 +401,9 @@ namespace bitc { ATTR_KIND_IN_ALLOCA = 38, ATTR_KIND_NON_NULL = 39, ATTR_KIND_JUMP_TABLE = 40, - ATTR_KIND_DEREFERENCEABLE = 41 + ATTR_KIND_DEREFERENCEABLE = 41, + ATTR_KIND_DEREFERENCEABLE_OR_NULL = 42, + ATTR_KIND_CONVERGENT = 43 }; enum ComdatSelectionKindCodes { diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index 48bdabc88391..9d30098fddee 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -29,12 +29,14 @@ namespace llvm { class raw_ostream; /// Read the header of the specified bitcode buffer and prepare for lazy - /// deserialization of function bodies. If successful, this moves Buffer. On + /// deserialization of function bodies. If ShouldLazyLoadMetadata is true, + /// lazily load metadata as well. If successful, this moves Buffer. On /// error, this *does not* move Buffer. ErrorOr<Module *> getLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer, LLVMContext &Context, - DiagnosticHandlerFunction DiagnosticHandler = nullptr); + DiagnosticHandlerFunction DiagnosticHandler = nullptr, + bool ShouldLazyLoadMetadata = false); /// Read the header of the specified stream and prepare for lazy /// deserialization and streaming of function bodies. @@ -54,11 +56,16 @@ namespace llvm { parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, DiagnosticHandlerFunction DiagnosticHandler = nullptr); - /// WriteBitcodeToFile - Write the specified module to the specified - /// raw output stream. For streams where it matters, the given stream - /// should be in "binary" mode. - void WriteBitcodeToFile(const Module *M, raw_ostream &Out); - + /// \brief Write the specified module to the specified raw output stream. + /// + /// For streams where it matters, the given stream should be in "binary" + /// mode. + /// + /// If \c ShouldPreserveUseListOrder, encode the use-list order for each \a + /// Value in \c M. These will be reconstructed exactly when \a M is + /// deserialized. + void WriteBitcodeToFile(const Module *M, raw_ostream &Out, + bool ShouldPreserveUseListOrder = false); /// isBitcodeWrapper - Return true if the given bytes are the magic bytes /// for an LLVM IR bitcode wrapper. diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index e3ce57ad1850..47201e2564e3 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -16,8 +16,10 @@ #ifndef LLVM_CODEGEN_ASMPRINTER_H #define LLVM_CODEGEN_ASMPRINTER_H +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/DwarfStringPoolEntry.h" #include "llvm/IR/InlineAsm.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -29,6 +31,8 @@ class ByteStreamer; class GCStrategy; class Constant; class ConstantArray; +class DIE; +class DIEAbbrev; class GCMetadataPrinter; class GlobalValue; class GlobalVariable; @@ -46,11 +50,11 @@ class MCCFIInstruction; class MCContext; class MCExpr; class MCInst; -class MCInstrInfo; class MCSection; class MCStreamer; class MCSubtargetInfo; class MCSymbol; +class MCTargetOptions; class MDNode; class DwarfDebug; class Mangler; @@ -69,7 +73,6 @@ public: /// const MCAsmInfo *MAI; - const MCInstrInfo *MII; /// This is the context for the output file that we are streaming. This owns /// all of the global MC-related objects for the generated translation unit. MCContext &OutContext; @@ -77,7 +80,7 @@ public: /// This is the MCStreamer object for the file we are generating. This /// contains the transient state for the current translation unit that we are /// generating (such as the current section etc). - MCStreamer &OutStreamer; + std::unique_ptr<MCStreamer> OutStreamer; /// The current machine function. const MachineFunction *MF; @@ -99,7 +102,16 @@ public: /// default, this is equal to CurrentFnSym. MCSymbol *CurrentFnSymForSize; + /// Map global GOT equivalent MCSymbols to GlobalVariables and keep track of + /// its number of uses by other globals. + typedef std::pair<const GlobalVariable *, unsigned> GOTEquivUsePair; + MapVector<const MCSymbol *, GOTEquivUsePair> GlobalGOTEquivs; + private: + MCSymbol *CurrentFnBegin; + MCSymbol *CurrentFnEnd; + MCSymbol *CurExceptionSym; + // The garbage collection metadata printer table. void *GCMetadataPrinters; // Really a DenseMap. @@ -127,10 +139,10 @@ private: DwarfDebug *DD; protected: - explicit AsmPrinter(TargetMachine &TM, MCStreamer &Streamer); + explicit AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer); public: - virtual ~AsmPrinter(); + ~AsmPrinter() override; DwarfDebug *getDwarfDebug() { return DD; } DwarfDebug *getDwarfDebug() const { return DD; } @@ -143,6 +155,10 @@ public: /// unsigned getFunctionNumber() const; + MCSymbol *getFunctionBegin() const { return CurrentFnBegin; } + MCSymbol *getFunctionEnd() const { return CurrentFnEnd; } + MCSymbol *getCurExceptionSym(); + /// Return information about object file lowering. const TargetLoweringObjectFile &getObjFileLowering() const; @@ -184,7 +200,6 @@ public: /// Emit the specified function out to the OutStreamer. bool runOnMachineFunction(MachineFunction &MF) override { SetupMachineFunction(MF); - EmitFunctionHeader(); EmitFunctionBody(); return false; } @@ -197,9 +212,6 @@ public: /// runOnMachineFunction. void SetupMachineFunction(MachineFunction &MF); - /// This method emits the header for the current function. - void EmitFunctionHeader(); - /// This method emits the body and trailer for a function. void EmitFunctionBody(); @@ -238,16 +250,27 @@ public: /// void EmitAlignment(unsigned NumBits, const GlobalObject *GO = nullptr) const; - /// This method prints the label for the specified MachineBasicBlock, an - /// alignment (if present) and a comment describing it if appropriate. - void EmitBasicBlockStart(const MachineBasicBlock &MBB) const; - /// Lower the specified LLVM Constant to an MCExpr. const MCExpr *lowerConstant(const Constant *CV); /// \brief Print a general LLVM constant to the .s file. void EmitGlobalConstant(const Constant *CV); + /// \brief Unnamed constant global variables solely contaning a pointer to + /// another globals variable act like a global variable "proxy", or GOT + /// equivalents, i.e., it's only used to hold the address of the latter. One + /// optimization is to replace accesses to these proxies by using the GOT + /// entry for the final global instead. Hence, we select GOT equivalent + /// candidates among all the module global variables, avoid emitting them + /// unnecessarily and finally replace references to them by pc relative + /// accesses to GOT entries. + void computeGlobalGOTEquivs(Module &M); + + /// \brief Constant expressions using GOT equivalent globals may not be + /// eligible for PC relative GOT entry conversion, in such cases we need to + /// emit the proxies we previously omitted in EmitGlobalVariable. + void emitGlobalGOTEquivs(); + //===------------------------------------------------------------------===// // Overridable Hooks //===------------------------------------------------------------------===// @@ -271,6 +294,12 @@ public: /// function. virtual void EmitFunctionBodyEnd() {} + /// Targets can override this to emit stuff at the start of a basic block. + /// By default, this method prints the label for the specified + /// MachineBasicBlock, an alignment (if present) and a comment describing it + /// if appropriate. + virtual void EmitBasicBlockStart(const MachineBasicBlock &MBB) const; + /// Targets can override this to emit stuff at the end of a basic block. virtual void EmitBasicBlockEnd(const MachineBasicBlock &MBB) {} @@ -304,12 +333,7 @@ public: // Symbol Lowering Routines. //===------------------------------------------------------------------===// public: - /// Return the MCSymbol corresponding to the assembler temporary label with - /// the specified stem and unique ID. - MCSymbol *GetTempSymbol(Twine Name, unsigned ID) const; - - /// Return an assembler temporary label with the specified stem. - MCSymbol *GetTempSymbol(Twine Name) const; + MCSymbol *createTempSymbol(const Twine &Name) const; /// Return the MCSymbol for a private symbol with global value name as its /// base, with the specified suffix. @@ -397,42 +421,21 @@ public: /// Emit the 4-byte offset of Label from the start of its section. This can /// be done with a special directive if the target supports it (e.g. cygwin) /// or by emitting it as an offset from a label at the start of the section. + void emitSectionOffset(const MCSymbol *Label) const; + + /// Emit the 4-byte offset of a string from the start of its section. /// - /// SectionLabel is a temporary label emitted at the start of the section - /// that Label lives in. - void EmitSectionOffset(const MCSymbol *Label, - const MCSymbol *SectionLabel) const; + /// When possible, emit a DwarfStringPool section offset without any + /// relocations, and without using the symbol. Otherwise, defers to \a + /// emitSectionOffset(). + void emitDwarfStringOffset(DwarfStringPoolEntryRef S) const; /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified. virtual unsigned getISAEncoding() { return 0; } - /// Emit a dwarf register operation for describing - /// - a small value occupying only part of a register or - /// - a register representing only part of a value. - void EmitDwarfOpPiece(ByteStreamer &Streamer, unsigned SizeInBits, - unsigned OffsetInBits = 0) const; - - - /// \brief Emit a partial DWARF register operation. - /// \param MLoc the register - /// \param PieceSize size and - /// \param PieceOffset offset of the piece in bits, if this is one - /// piece of an aggregate value. - /// - /// If size and offset is zero an operation for the entire - /// register is emitted: Some targets do not provide a DWARF - /// register number for every register. If this is the case, this - /// function will attempt to emit a DWARF register by emitting a - /// piece of a super-register or by piecing together multiple - /// subregisters that alias the register. - void EmitDwarfRegOpPiece(ByteStreamer &BS, const MachineLocation &MLoc, - unsigned PieceSize = 0, - unsigned PieceOffset = 0) const; - /// EmitDwarfRegOp - Emit a dwarf register operation. - /// \param Indirect whether this is a register-indirect address - virtual void EmitDwarfRegOp(ByteStreamer &BS, const MachineLocation &MLoc, - bool Indirect) const; + virtual void EmitDwarfRegOp(ByteStreamer &BS, + const MachineLocation &MLoc) const; //===------------------------------------------------------------------===// // Dwarf Lowering Routines @@ -441,6 +444,12 @@ public: /// \brief Emit frame instruction to describe the layout of the frame. void emitCFIInstruction(const MCCFIInstruction &Inst) const; + /// \brief Emit Dwarf abbreviation table. + void emitDwarfAbbrevs(const std::vector<DIEAbbrev *>& Abbrevs) const; + + /// \brief Recursively emit Dwarf DIE tree. + void emitDwarfDIE(const DIE &Die) const; + //===------------------------------------------------------------------===// // Inline Asm Support //===------------------------------------------------------------------===// @@ -474,7 +483,7 @@ public: /// Let the target do anything it needs to do before emitting inlineasm. /// \p StartInfo - the subtarget info before parsing inline asm - virtual void emitInlineAsmStart(const MCSubtargetInfo &StartInfo) const; + virtual void emitInlineAsmStart() const; /// Let the target do anything it needs to do after emitting inlineasm. /// This callback can be used restore the original mode in case the @@ -491,11 +500,15 @@ private: mutable const MachineInstr *LastMI; mutable unsigned LastFn; mutable unsigned Counter; - mutable unsigned SetCounter; + + /// This method emits the header for the current function. + virtual void EmitFunctionHeader(); /// Emit a blob of inline asm to the output streamer. void - EmitInlineAsm(StringRef Str, const MDNode *LocMDNode = nullptr, + EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, + const MCTargetOptions &MCOptions, + const MDNode *LocMDNode = nullptr, InlineAsm::AsmDialect AsmDialect = InlineAsm::AD_ATT) const; /// This method formats and emits the specified machine instruction that is an diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h new file mode 100644 index 000000000000..d07265560430 --- /dev/null +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -0,0 +1,767 @@ +//===- BasicTTIImpl.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file provides a helper that implements much of the TTI interface in +/// terms of the target-independent code generator and TargetLowering +/// interfaces. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_BASICTTIIMPL_H +#define LLVM_CODEGEN_BASICTTIIMPL_H + +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/TargetTransformInfoImpl.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/Analysis/TargetLibraryInfo.h" + +namespace llvm { + +extern cl::opt<unsigned> PartialUnrollingThreshold; + +/// \brief Base class which can be used to help build a TTI implementation. +/// +/// This class provides as much implementation of the TTI interface as is +/// possible using the target independent parts of the code generator. +/// +/// In order to subclass it, your class must implement a getST() method to +/// return the subtarget, and a getTLI() method to return the target lowering. +/// We need these methods implemented in the derived class so that this class +/// doesn't have to duplicate storage for them. +template <typename T> +class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> { +private: + typedef TargetTransformInfoImplCRTPBase<T> BaseT; + typedef TargetTransformInfo TTI; + + /// Estimate the overhead of scalarizing an instruction. Insert and Extract + /// are set if the result needs to be inserted and/or extracted from vectors. + unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) { + assert(Ty->isVectorTy() && "Can only scalarize vectors"); + unsigned Cost = 0; + + for (int i = 0, e = Ty->getVectorNumElements(); i < e; ++i) { + if (Insert) + Cost += static_cast<T *>(this) + ->getVectorInstrCost(Instruction::InsertElement, Ty, i); + if (Extract) + Cost += static_cast<T *>(this) + ->getVectorInstrCost(Instruction::ExtractElement, Ty, i); + } + + return Cost; + } + + /// Estimate the cost overhead of SK_Alternate shuffle. + unsigned getAltShuffleOverhead(Type *Ty) { + assert(Ty->isVectorTy() && "Can only shuffle vectors"); + unsigned Cost = 0; + // Shuffle cost is equal to the cost of extracting element from its argument + // plus the cost of inserting them onto the result vector. + + // e.g. <4 x float> has a mask of <0,5,2,7> i.e we need to extract from + // index 0 of first vector, index 1 of second vector,index 2 of first + // vector and finally index 3 of second vector and insert them at index + // <0,1,2,3> of result vector. + for (int i = 0, e = Ty->getVectorNumElements(); i < e; ++i) { + Cost += static_cast<T *>(this) + ->getVectorInstrCost(Instruction::InsertElement, Ty, i); + Cost += static_cast<T *>(this) + ->getVectorInstrCost(Instruction::ExtractElement, Ty, i); + } + return Cost; + } + + /// \brief Local query method delegates up to T which *must* implement this! + const TargetSubtargetInfo *getST() const { + return static_cast<const T *>(this)->getST(); + } + + /// \brief Local query method delegates up to T which *must* implement this! + const TargetLoweringBase *getTLI() const { + return static_cast<const T *>(this)->getTLI(); + } + +protected: + explicit BasicTTIImplBase(const TargetMachine *TM) + : BaseT(TM->getDataLayout()) {} + +public: + // Provide value semantics. MSVC requires that we spell all of these out. + BasicTTIImplBase(const BasicTTIImplBase &Arg) + : BaseT(static_cast<const BaseT &>(Arg)) {} + BasicTTIImplBase(BasicTTIImplBase &&Arg) + : BaseT(std::move(static_cast<BaseT &>(Arg))) {} + BasicTTIImplBase &operator=(const BasicTTIImplBase &RHS) { + BaseT::operator=(static_cast<const BaseT &>(RHS)); + return *this; + } + BasicTTIImplBase &operator=(BasicTTIImplBase &&RHS) { + BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); + return *this; + } + + /// \name Scalar TTI Implementations + /// @{ + + bool hasBranchDivergence() { return false; } + + bool isSourceOfDivergence(const Value *V) { return false; } + + bool isLegalAddImmediate(int64_t imm) { + return getTLI()->isLegalAddImmediate(imm); + } + + bool isLegalICmpImmediate(int64_t imm) { + return getTLI()->isLegalICmpImmediate(imm); + } + + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + TargetLoweringBase::AddrMode AM; + AM.BaseGV = BaseGV; + AM.BaseOffs = BaseOffset; + AM.HasBaseReg = HasBaseReg; + AM.Scale = Scale; + return getTLI()->isLegalAddressingMode(AM, Ty); + } + + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + TargetLoweringBase::AddrMode AM; + AM.BaseGV = BaseGV; + AM.BaseOffs = BaseOffset; + AM.HasBaseReg = HasBaseReg; + AM.Scale = Scale; + return getTLI()->getScalingFactorCost(AM, Ty); + } + + bool isTruncateFree(Type *Ty1, Type *Ty2) { + return getTLI()->isTruncateFree(Ty1, Ty2); + } + + bool isProfitableToHoist(Instruction *I) { + return getTLI()->isProfitableToHoist(I); + } + + bool isTypeLegal(Type *Ty) { + EVT VT = getTLI()->getValueType(Ty); + return getTLI()->isTypeLegal(VT); + } + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<const Value *> Arguments) { + return BaseT::getIntrinsicCost(IID, RetTy, Arguments); + } + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<Type *> ParamTys) { + if (IID == Intrinsic::cttz) { + if (getTLI()->isCheapToSpeculateCttz()) + return TargetTransformInfo::TCC_Basic; + return TargetTransformInfo::TCC_Expensive; + } + + if (IID == Intrinsic::ctlz) { + if (getTLI()->isCheapToSpeculateCtlz()) + return TargetTransformInfo::TCC_Basic; + return TargetTransformInfo::TCC_Expensive; + } + + return BaseT::getIntrinsicCost(IID, RetTy, ParamTys); + } + + unsigned getJumpBufAlignment() { return getTLI()->getJumpBufAlignment(); } + + unsigned getJumpBufSize() { return getTLI()->getJumpBufSize(); } + + bool shouldBuildLookupTables() { + const TargetLoweringBase *TLI = getTLI(); + return TLI->isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) || + TLI->isOperationLegalOrCustom(ISD::BRIND, MVT::Other); + } + + bool haveFastSqrt(Type *Ty) { + const TargetLoweringBase *TLI = getTLI(); + EVT VT = TLI->getValueType(Ty); + return TLI->isTypeLegal(VT) && + TLI->isOperationLegalOrCustom(ISD::FSQRT, VT); + } + + unsigned getFPOpCost(Type *Ty) { + // By default, FP instructions are no more expensive since they are + // implemented in HW. Target specific TTI can override this. + return TargetTransformInfo::TCC_Basic; + } + + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) { + const TargetLoweringBase *TLI = getTLI(); + switch (Opcode) { + default: break; + case Instruction::Trunc: { + if (TLI->isTruncateFree(OpTy, Ty)) + return TargetTransformInfo::TCC_Free; + return TargetTransformInfo::TCC_Basic; + } + case Instruction::ZExt: { + if (TLI->isZExtFree(OpTy, Ty)) + return TargetTransformInfo::TCC_Free; + return TargetTransformInfo::TCC_Basic; + } + } + + return BaseT::getOperationCost(Opcode, Ty, OpTy); + } + + void getUnrollingPreferences(Loop *L, TTI::UnrollingPreferences &UP) { + // This unrolling functionality is target independent, but to provide some + // motivation for its intended use, for x86: + + // According to the Intel 64 and IA-32 Architectures Optimization Reference + // Manual, Intel Core models and later have a loop stream detector (and + // associated uop queue) that can benefit from partial unrolling. + // The relevant requirements are: + // - The loop must have no more than 4 (8 for Nehalem and later) branches + // taken, and none of them may be calls. + // - The loop can have no more than 18 (28 for Nehalem and later) uops. + + // According to the Software Optimization Guide for AMD Family 15h + // Processors, models 30h-4fh (Steamroller and later) have a loop predictor + // and loop buffer which can benefit from partial unrolling. + // The relevant requirements are: + // - The loop must have fewer than 16 branches + // - The loop must have less than 40 uops in all executed loop branches + + // The number of taken branches in a loop is hard to estimate here, and + // benchmarking has revealed that it is better not to be conservative when + // estimating the branch count. As a result, we'll ignore the branch limits + // until someone finds a case where it matters in practice. + + unsigned MaxOps; + const TargetSubtargetInfo *ST = getST(); + if (PartialUnrollingThreshold.getNumOccurrences() > 0) + MaxOps = PartialUnrollingThreshold; + else if (ST->getSchedModel().LoopMicroOpBufferSize > 0) + MaxOps = ST->getSchedModel().LoopMicroOpBufferSize; + else + return; + + // Scan the loop: don't unroll loops with calls. + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); I != E; + ++I) { + BasicBlock *BB = *I; + + for (BasicBlock::iterator J = BB->begin(), JE = BB->end(); J != JE; ++J) + if (isa<CallInst>(J) || isa<InvokeInst>(J)) { + ImmutableCallSite CS(J); + if (const Function *F = CS.getCalledFunction()) { + if (!static_cast<T *>(this)->isLoweredToCall(F)) + continue; + } + + return; + } + } + + // Enable runtime and partial unrolling up to the specified size. + UP.Partial = UP.Runtime = true; + UP.PartialThreshold = UP.PartialOptSizeThreshold = MaxOps; + } + + /// @} + + /// \name Vector TTI Implementations + /// @{ + + unsigned getNumberOfRegisters(bool Vector) { return 1; } + + unsigned getRegisterBitWidth(bool Vector) { return 32; } + + unsigned getMaxInterleaveFactor(unsigned VF) { return 1; } + + unsigned getArithmeticInstrCost( + unsigned Opcode, Type *Ty, + TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue, + TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue, + TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None, + TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None) { + // Check if any of the operands are vector operands. + const TargetLoweringBase *TLI = getTLI(); + int ISD = TLI->InstructionOpcodeToISD(Opcode); + assert(ISD && "Invalid opcode"); + + std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(Ty); + + bool IsFloat = Ty->getScalarType()->isFloatingPointTy(); + // Assume that floating point arithmetic operations cost twice as much as + // integer operations. + unsigned OpCost = (IsFloat ? 2 : 1); + + if (TLI->isOperationLegalOrPromote(ISD, LT.second)) { + // The operation is legal. Assume it costs 1. + // If the type is split to multiple registers, assume that there is some + // overhead to this. + // TODO: Once we have extract/insert subvector cost we need to use them. + if (LT.first > 1) + return LT.first * 2 * OpCost; + return LT.first * 1 * OpCost; + } + + if (!TLI->isOperationExpand(ISD, LT.second)) { + // If the operation is custom lowered then assume + // thare the code is twice as expensive. + return LT.first * 2 * OpCost; + } + + // Else, assume that we need to scalarize this op. + if (Ty->isVectorTy()) { + unsigned Num = Ty->getVectorNumElements(); + unsigned Cost = static_cast<T *>(this) + ->getArithmeticInstrCost(Opcode, Ty->getScalarType()); + // return the cost of multiple scalar invocation plus the cost of + // inserting + // and extracting the values. + return getScalarizationOverhead(Ty, true, true) + Num * Cost; + } + + // We don't know anything about this scalar instruction. + return OpCost; + } + + unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, int Index, + Type *SubTp) { + if (Kind == TTI::SK_Alternate) { + return getAltShuffleOverhead(Tp); + } + return 1; + } + + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { + const TargetLoweringBase *TLI = getTLI(); + int ISD = TLI->InstructionOpcodeToISD(Opcode); + assert(ISD && "Invalid opcode"); + + std::pair<unsigned, MVT> SrcLT = TLI->getTypeLegalizationCost(Src); + std::pair<unsigned, MVT> DstLT = TLI->getTypeLegalizationCost(Dst); + + // Check for NOOP conversions. + if (SrcLT.first == DstLT.first && + SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits()) { + + // Bitcast between types that are legalized to the same type are free. + if (Opcode == Instruction::BitCast || Opcode == Instruction::Trunc) + return 0; + } + + if (Opcode == Instruction::Trunc && + TLI->isTruncateFree(SrcLT.second, DstLT.second)) + return 0; + + if (Opcode == Instruction::ZExt && + TLI->isZExtFree(SrcLT.second, DstLT.second)) + return 0; + + // If the cast is marked as legal (or promote) then assume low cost. + if (SrcLT.first == DstLT.first && + TLI->isOperationLegalOrPromote(ISD, DstLT.second)) + return 1; + + // Handle scalar conversions. + if (!Src->isVectorTy() && !Dst->isVectorTy()) { + + // Scalar bitcasts are usually free. + if (Opcode == Instruction::BitCast) + return 0; + + // Just check the op cost. If the operation is legal then assume it costs + // 1. + if (!TLI->isOperationExpand(ISD, DstLT.second)) + return 1; + + // Assume that illegal scalar instruction are expensive. + return 4; + } + + // Check vector-to-vector casts. + if (Dst->isVectorTy() && Src->isVectorTy()) { + + // If the cast is between same-sized registers, then the check is simple. + if (SrcLT.first == DstLT.first && + SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits()) { + + // Assume that Zext is done using AND. + if (Opcode == Instruction::ZExt) + return 1; + + // Assume that sext is done using SHL and SRA. + if (Opcode == Instruction::SExt) + return 2; + + // Just check the op cost. If the operation is legal then assume it + // costs + // 1 and multiply by the type-legalization overhead. + if (!TLI->isOperationExpand(ISD, DstLT.second)) + return SrcLT.first * 1; + } + + // If we are converting vectors and the operation is illegal, or + // if the vectors are legalized to different types, estimate the + // scalarization costs. + unsigned Num = Dst->getVectorNumElements(); + unsigned Cost = static_cast<T *>(this)->getCastInstrCost( + Opcode, Dst->getScalarType(), Src->getScalarType()); + + // Return the cost of multiple scalar invocation plus the cost of + // inserting and extracting the values. + return getScalarizationOverhead(Dst, true, true) + Num * Cost; + } + + // We already handled vector-to-vector and scalar-to-scalar conversions. + // This + // is where we handle bitcast between vectors and scalars. We need to assume + // that the conversion is scalarized in one way or another. + if (Opcode == Instruction::BitCast) + // Illegal bitcasts are done by storing and loading from a stack slot. + return (Src->isVectorTy() ? getScalarizationOverhead(Src, false, true) + : 0) + + (Dst->isVectorTy() ? getScalarizationOverhead(Dst, true, false) + : 0); + + llvm_unreachable("Unhandled cast"); + } + + unsigned getCFInstrCost(unsigned Opcode) { + // Branches are assumed to be predicted. + return 0; + } + + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) { + const TargetLoweringBase *TLI = getTLI(); + int ISD = TLI->InstructionOpcodeToISD(Opcode); + assert(ISD && "Invalid opcode"); + + // Selects on vectors are actually vector selects. + if (ISD == ISD::SELECT) { + assert(CondTy && "CondTy must exist"); + if (CondTy->isVectorTy()) + ISD = ISD::VSELECT; + } + + std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(ValTy); + + if (!(ValTy->isVectorTy() && !LT.second.isVector()) && + !TLI->isOperationExpand(ISD, LT.second)) { + // The operation is legal. Assume it costs 1. Multiply + // by the type-legalization overhead. + return LT.first * 1; + } + + // Otherwise, assume that the cast is scalarized. + if (ValTy->isVectorTy()) { + unsigned Num = ValTy->getVectorNumElements(); + if (CondTy) + CondTy = CondTy->getScalarType(); + unsigned Cost = static_cast<T *>(this)->getCmpSelInstrCost( + Opcode, ValTy->getScalarType(), CondTy); + + // Return the cost of multiple scalar invocation plus the cost of + // inserting + // and extracting the values. + return getScalarizationOverhead(ValTy, true, false) + Num * Cost; + } + + // Unknown scalar opcode. + return 1; + } + + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) { + std::pair<unsigned, MVT> LT = + getTLI()->getTypeLegalizationCost(Val->getScalarType()); + + return LT.first; + } + + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) { + assert(!Src->isVoidTy() && "Invalid type"); + std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(Src); + + // Assuming that all loads of legal types cost 1. + unsigned Cost = LT.first; + + if (Src->isVectorTy() && + Src->getPrimitiveSizeInBits() < LT.second.getSizeInBits()) { + // This is a vector load that legalizes to a larger type than the vector + // itself. Unless the corresponding extending load or truncating store is + // legal, then this will scalarize. + TargetLowering::LegalizeAction LA = TargetLowering::Expand; + EVT MemVT = getTLI()->getValueType(Src, true); + if (MemVT.isSimple() && MemVT != MVT::Other) { + if (Opcode == Instruction::Store) + LA = getTLI()->getTruncStoreAction(LT.second, MemVT.getSimpleVT()); + else + LA = getTLI()->getLoadExtAction(ISD::EXTLOAD, LT.second, MemVT); + } + + if (LA != TargetLowering::Legal && LA != TargetLowering::Custom) { + // This is a vector load/store for some illegal type that is scalarized. + // We must account for the cost of building or decomposing the vector. + Cost += getScalarizationOverhead(Src, Opcode != Instruction::Store, + Opcode == Instruction::Store); + } + } + + return Cost; + } + + unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<Type *> Tys) { + unsigned ISD = 0; + switch (IID) { + default: { + // Assume that we need to scalarize this intrinsic. + unsigned ScalarizationCost = 0; + unsigned ScalarCalls = 1; + Type *ScalarRetTy = RetTy; + if (RetTy->isVectorTy()) { + ScalarizationCost = getScalarizationOverhead(RetTy, true, false); + ScalarCalls = std::max(ScalarCalls, RetTy->getVectorNumElements()); + ScalarRetTy = RetTy->getScalarType(); + } + SmallVector<Type *, 4> ScalarTys; + for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { + Type *Ty = Tys[i]; + if (Ty->isVectorTy()) { + ScalarizationCost += getScalarizationOverhead(Ty, false, true); + ScalarCalls = std::max(ScalarCalls, Ty->getVectorNumElements()); + Ty = Ty->getScalarType(); + } + ScalarTys.push_back(Ty); + } + if (ScalarCalls == 1) + return 1; // Return cost of a scalar intrinsic. Assume it to be cheap. + + unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost( + IID, ScalarRetTy, ScalarTys); + + return ScalarCalls * ScalarCost + ScalarizationCost; + } + // Look for intrinsics that can be lowered directly or turned into a scalar + // intrinsic call. + case Intrinsic::sqrt: + ISD = ISD::FSQRT; + break; + case Intrinsic::sin: + ISD = ISD::FSIN; + break; + case Intrinsic::cos: + ISD = ISD::FCOS; + break; + case Intrinsic::exp: + ISD = ISD::FEXP; + break; + case Intrinsic::exp2: + ISD = ISD::FEXP2; + break; + case Intrinsic::log: + ISD = ISD::FLOG; + break; + case Intrinsic::log10: + ISD = ISD::FLOG10; + break; + case Intrinsic::log2: + ISD = ISD::FLOG2; + break; + case Intrinsic::fabs: + ISD = ISD::FABS; + break; + case Intrinsic::minnum: + ISD = ISD::FMINNUM; + break; + case Intrinsic::maxnum: + ISD = ISD::FMAXNUM; + break; + case Intrinsic::copysign: + ISD = ISD::FCOPYSIGN; + break; + case Intrinsic::floor: + ISD = ISD::FFLOOR; + break; + case Intrinsic::ceil: + ISD = ISD::FCEIL; + break; + case Intrinsic::trunc: + ISD = ISD::FTRUNC; + break; + case Intrinsic::nearbyint: + ISD = ISD::FNEARBYINT; + break; + case Intrinsic::rint: + ISD = ISD::FRINT; + break; + case Intrinsic::round: + ISD = ISD::FROUND; + break; + case Intrinsic::pow: + ISD = ISD::FPOW; + break; + case Intrinsic::fma: + ISD = ISD::FMA; + break; + case Intrinsic::fmuladd: + ISD = ISD::FMA; + break; + // FIXME: We should return 0 whenever getIntrinsicCost == TCC_Free. + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + return 0; + case Intrinsic::masked_store: + return static_cast<T *>(this) + ->getMaskedMemoryOpCost(Instruction::Store, Tys[0], 0, 0); + case Intrinsic::masked_load: + return static_cast<T *>(this) + ->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0); + } + + const TargetLoweringBase *TLI = getTLI(); + std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(RetTy); + + if (TLI->isOperationLegalOrPromote(ISD, LT.second)) { + // The operation is legal. Assume it costs 1. + // If the type is split to multiple registers, assume that there is some + // overhead to this. + // TODO: Once we have extract/insert subvector cost we need to use them. + if (LT.first > 1) + return LT.first * 2; + return LT.first * 1; + } + + if (!TLI->isOperationExpand(ISD, LT.second)) { + // If the operation is custom lowered then assume + // thare the code is twice as expensive. + return LT.first * 2; + } + + // If we can't lower fmuladd into an FMA estimate the cost as a floating + // point mul followed by an add. + if (IID == Intrinsic::fmuladd) + return static_cast<T *>(this) + ->getArithmeticInstrCost(BinaryOperator::FMul, RetTy) + + static_cast<T *>(this) + ->getArithmeticInstrCost(BinaryOperator::FAdd, RetTy); + + // Else, assume that we need to scalarize this intrinsic. For math builtins + // this will emit a costly libcall, adding call overhead and spills. Make it + // very expensive. + if (RetTy->isVectorTy()) { + unsigned ScalarizationCost = getScalarizationOverhead(RetTy, true, false); + unsigned ScalarCalls = RetTy->getVectorNumElements(); + SmallVector<Type *, 4> ScalarTys; + for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { + Type *Ty = Tys[i]; + if (Ty->isVectorTy()) + Ty = Ty->getScalarType(); + ScalarTys.push_back(Ty); + } + unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost( + IID, RetTy->getScalarType(), ScalarTys); + for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { + if (Tys[i]->isVectorTy()) { + ScalarizationCost += getScalarizationOverhead(Tys[i], false, true); + ScalarCalls = std::max(ScalarCalls, Tys[i]->getVectorNumElements()); + } + } + + return ScalarCalls * ScalarCost + ScalarizationCost; + } + + // This is going to be turned into a library call, make it expensive. + return 10; + } + + /// \brief Compute a cost of the given call instruction. + /// + /// Compute the cost of calling function F with return type RetTy and + /// argument types Tys. F might be nullptr, in this case the cost of an + /// arbitrary call with the specified signature will be returned. + /// This is used, for instance, when we estimate call of a vector + /// counterpart of the given function. + /// \param F Called function, might be nullptr. + /// \param RetTy Return value types. + /// \param Tys Argument types. + /// \returns The cost of Call instruction. + unsigned getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys) { + return 10; + } + + unsigned getNumberOfParts(Type *Tp) { + std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(Tp); + return LT.first; + } + + unsigned getAddressComputationCost(Type *Ty, bool IsComplex) { return 0; } + + unsigned getReductionCost(unsigned Opcode, Type *Ty, bool IsPairwise) { + assert(Ty->isVectorTy() && "Expect a vector type"); + unsigned NumVecElts = Ty->getVectorNumElements(); + unsigned NumReduxLevels = Log2_32(NumVecElts); + unsigned ArithCost = + NumReduxLevels * + static_cast<T *>(this)->getArithmeticInstrCost(Opcode, Ty); + // Assume the pairwise shuffles add a cost. + unsigned ShuffleCost = + NumReduxLevels * (IsPairwise + 1) * + static_cast<T *>(this) + ->getShuffleCost(TTI::SK_ExtractSubvector, Ty, NumVecElts / 2, Ty); + return ShuffleCost + ArithCost + getScalarizationOverhead(Ty, false, true); + } + + /// @} +}; + +/// \brief Concrete BasicTTIImpl that can be used if no further customization +/// is needed. +class BasicTTIImpl : public BasicTTIImplBase<BasicTTIImpl> { + typedef BasicTTIImplBase<BasicTTIImpl> BaseT; + friend class BasicTTIImplBase<BasicTTIImpl>; + + const TargetSubtargetInfo *ST; + const TargetLoweringBase *TLI; + + const TargetSubtargetInfo *getST() const { return ST; } + const TargetLoweringBase *getTLI() const { return TLI; } + +public: + explicit BasicTTIImpl(const TargetMachine *ST, Function &F); + + // Provide value semantics. MSVC requires that we spell all of these out. + BasicTTIImpl(const BasicTTIImpl &Arg) + : BaseT(static_cast<const BaseT &>(Arg)), ST(Arg.ST), TLI(Arg.TLI) {} + BasicTTIImpl(BasicTTIImpl &&Arg) + : BaseT(std::move(static_cast<BaseT &>(Arg))), ST(std::move(Arg.ST)), + TLI(std::move(Arg.TLI)) {} + BasicTTIImpl &operator=(const BasicTTIImpl &RHS) { + BaseT::operator=(static_cast<const BaseT &>(RHS)); + ST = RHS.ST; + TLI = RHS.TLI; + return *this; + } + BasicTTIImpl &operator=(BasicTTIImpl &&RHS) { + BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); + ST = std::move(RHS.ST); + TLI = std::move(RHS.TLI); + return *this; + } +}; + +} + +#endif diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index dd7703b1dbf7..1fd4eeb46b38 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -19,6 +19,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/IR/CallingConv.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/Target/TargetCallingConv.h" namespace llvm { @@ -122,8 +123,8 @@ public: // There is no need to differentiate between a pending CCValAssign and other // kinds, as they are stored in a different list. static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, - LocInfo HTP) { - return getReg(ValNo, ValVT, 0, LocVT, HTP); + LocInfo HTP, unsigned ExtraInfo = 0) { + return getReg(ValNo, ValVT, ExtraInfo, LocVT, HTP); } void convertToReg(unsigned RegNo) { @@ -146,6 +147,7 @@ public: unsigned getLocReg() const { assert(isRegLoc()); return Loc; } unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; } + unsigned getExtraInfo() const { return Loc; } MVT getLocVT() const { return LocVT; } LocInfo getLocInfo() const { return HTP; } @@ -312,13 +314,13 @@ public: /// produce a single value. void AnalyzeCallResult(MVT VT, CCAssignFn Fn); - /// getFirstUnallocated - Return the first unallocated register in the set, or - /// NumRegs if they are all allocated. - unsigned getFirstUnallocated(const MCPhysReg *Regs, unsigned NumRegs) const { - for (unsigned i = 0; i != NumRegs; ++i) + /// getFirstUnallocated - Return the index of the first unallocated register + /// in the set, or Regs.size() if they are all allocated. + unsigned getFirstUnallocated(ArrayRef<MCPhysReg> Regs) const { + for (unsigned i = 0; i < Regs.size(); ++i) if (!isAllocated(Regs[i])) return i; - return NumRegs; + return Regs.size(); } /// AllocateReg - Attempt to allocate one register. If it is not available, @@ -341,9 +343,9 @@ public: /// AllocateReg - Attempt to allocate one of the specified registers. If none /// are available, return zero. Otherwise, return the first one available, /// marking it and any aliases as allocated. - unsigned AllocateReg(const MCPhysReg *Regs, unsigned NumRegs) { - unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); - if (FirstUnalloc == NumRegs) + unsigned AllocateReg(ArrayRef<MCPhysReg> Regs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs); + if (FirstUnalloc == Regs.size()) return 0; // Didn't find the reg. // Mark the register and any aliases as allocated. @@ -382,10 +384,9 @@ public: } /// Version of AllocateReg with list of registers to be shadowed. - unsigned AllocateReg(const MCPhysReg *Regs, const MCPhysReg *ShadowRegs, - unsigned NumRegs) { - unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); - if (FirstUnalloc == NumRegs) + unsigned AllocateReg(ArrayRef<MCPhysReg> Regs, const MCPhysReg *ShadowRegs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs); + if (FirstUnalloc == Regs.size()) return 0; // Didn't find the reg. // Mark the register and any aliases as allocated. @@ -415,8 +416,8 @@ public: /// Version of AllocateStack with list of extra registers to be shadowed. /// Note that, unlike AllocateReg, this shadows ALL of the shadow registers. unsigned AllocateStack(unsigned Size, unsigned Align, - const MCPhysReg *ShadowRegs, unsigned NumShadowRegs) { - for (unsigned i = 0; i < NumShadowRegs; ++i) + ArrayRef<MCPhysReg> ShadowRegs) { + for (unsigned i = 0; i < ShadowRegs.size(); ++i) MarkAllocated(ShadowRegs[i]); return AllocateStack(Size, Align); } diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 973c5954f9ad..a1b9b4e566a2 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -16,9 +16,12 @@ #ifndef LLVM_CODEGEN_COMMANDFLAGS_H #define LLVM_CODEGEN_COMMANDFLAGS_H +#include "llvm/IR/Module.h" #include "llvm/MC/MCTargetOptionsCommandFlags.h" +#include "llvm//MC/SubtargetFeature.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Host.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include <string> @@ -123,11 +126,6 @@ EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math", cl::desc("Force codegen to assume rounding mode can change dynamically"), cl::init(false)); -cl::opt<bool> -GenerateSoftFloatCalls("soft-float", - cl::desc("Generate software floating point library calls"), - cl::init(false)); - cl::opt<llvm::FloatABI::ABIType> FloatABIForCalls("float-abi", cl::desc("Choose float ABI type"), @@ -207,6 +205,10 @@ FunctionSections("function-sections", cl::desc("Emit functions into separate sections"), cl::init(false)); +cl::opt<bool> UniqueSectionNames("unique-section-names", + cl::desc("Give unique names to every section"), + cl::init(true)); + cl::opt<llvm::JumpTable::JumpTableType> JTableType("jump-table-type", cl::desc("Choose the type of Jump-Instruction Table for jumptable."), @@ -222,57 +224,17 @@ JTableType("jump-table-type", "Create one table per unique function type."), clEnumValEnd)); -cl::opt<bool> -FCFI("fcfi", - cl::desc("Apply forward-edge control-flow integrity"), - cl::init(false)); - -cl::opt<llvm::CFIntegrity> -CFIType("cfi-type", - cl::desc("Choose the type of Control-Flow Integrity check to add"), - cl::init(CFIntegrity::Sub), - cl::values( - clEnumValN(CFIntegrity::Sub, "sub", - "Subtract the pointer from the table base, then mask."), - clEnumValN(CFIntegrity::Ror, "ror", - "Use rotate to check the offset from a table base."), - clEnumValN(CFIntegrity::Add, "add", - "Mask out the high bits and add to an aligned base."), - clEnumValEnd)); - -cl::opt<bool> -CFIEnforcing("cfi-enforcing", - cl::desc("Enforce CFI or pass the violation to a function."), - cl::init(false)); - -// Note that this option is linked to the cfi-enforcing option above: if -// cfi-enforcing is set, then the cfi-func-name option is entirely ignored. If -// cfi-enforcing is false and no cfi-func-name is set, then a default function -// will be generated that ignores all CFI violations. The expected signature for -// functions called with CFI violations is -// -// void (i8*, i8*) -// -// The first pointer is a C string containing the name of the function in which -// the violation occurs, and the second pointer is the pointer that violated -// CFI. -cl::opt<std::string> -CFIFuncName("cfi-func-name", cl::desc("The name of the CFI function to call"), - cl::init("")); - // Common utility function tightly tied to the options listed here. Initializes // a TargetOptions object with CodeGen flags and returns it. static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { TargetOptions Options; Options.LessPreciseFPMADOption = EnableFPMAD; - Options.NoFramePointerElim = DisableFPElim; Options.AllowFPOpFusion = FuseFPOps; Options.UnsafeFPMath = EnableUnsafeFPMath; Options.NoInfsFPMath = EnableNoInfsFPMath; Options.NoNaNsFPMath = EnableNoNaNsFPMath; Options.HonorSignDependentRoundingFPMathOption = EnableHonorSignDependentRoundingFPMath; - Options.UseSoftFloat = GenerateSoftFloatCalls; if (FloatABIForCalls != FloatABI::Default) Options.FloatABIType = FloatABIForCalls; Options.NoZerosInBSS = DontPlaceZerosInBSS; @@ -284,17 +246,71 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { Options.UseInitArray = !UseCtors; Options.DataSections = DataSections; Options.FunctionSections = FunctionSections; + Options.UniqueSectionNames = UniqueSectionNames; Options.MCOptions = InitMCTargetOptionsFromFlags(); Options.JTType = JTableType; - Options.FCFI = FCFI; - Options.CFIType = CFIType; - Options.CFIEnforcing = CFIEnforcing; - Options.CFIFuncName = CFIFuncName; Options.ThreadModel = TMModel; return Options; } +static inline std::string getCPUStr() { + // If user asked for the 'native' CPU, autodetect here. If autodection fails, + // this will set the CPU to an empty string which tells the target to + // pick a basic default. + if (MCPU == "native") + return sys::getHostCPUName(); + + return MCPU; +} + +static inline std::string getFeaturesStr() { + SubtargetFeatures Features; + + // If user asked for the 'native' CPU, we need to autodetect features. + // This is necessary for x86 where the CPU might not support all the + // features the autodetected CPU name lists in the target. For example, + // not all Sandybridge processors support AVX. + if (MCPU == "native") { + StringMap<bool> HostFeatures; + if (sys::getHostCPUFeatures(HostFeatures)) + for (auto &F : HostFeatures) + Features.AddFeature(F.first(), F.second); + } + + for (unsigned i = 0; i != MAttrs.size(); ++i) + Features.AddFeature(MAttrs[i]); + + return Features.getString(); +} + +/// \brief Set function attributes of functions in Module M based on CPU, +/// Features, and command line flags. +static inline void setFunctionAttributes(StringRef CPU, StringRef Features, + Module &M) { + for (auto &F : M) { + auto &Ctx = F.getContext(); + AttributeSet Attrs = F.getAttributes(), NewAttrs; + + if (!CPU.empty()) + NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex, + "target-cpu", CPU); + + if (!Features.empty()) + NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex, + "target-features", Features); + + if (DisableFPElim.getNumOccurrences() > 0) + NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex, + "no-frame-pointer-elim", + DisableFPElim ? "true" : "false"); + + // Let NewAttrs override Attrs. + NewAttrs = Attrs.addAttributes(Ctx, AttributeSet::FunctionIndex, NewAttrs); + F.setAttributes(NewAttrs); + } +} + #endif diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h index e310aef3dcbb..8e40ef77d374 100644 --- a/include/llvm/CodeGen/DIE.h +++ b/include/llvm/CodeGen/DIE.h @@ -16,6 +16,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/DwarfStringPoolEntry.h" #include "llvm/Support/Dwarf.h" #include <vector> @@ -95,7 +96,7 @@ public: /// Emit - Print the abbreviation using the specified asm printer. /// - void Emit(AsmPrinter *AP) const; + void Emit(const AsmPrinter *AP) const; #ifndef NDEBUG void print(raw_ostream &O); @@ -200,8 +201,6 @@ public: /// to DWARF attribute classes. /// class DIEValue { - virtual void anchor(); - public: enum Type { isInteger, @@ -216,13 +215,14 @@ public: isLocList, }; -protected: +private: /// Ty - Type of data stored in the value. /// Type Ty; +protected: explicit DIEValue(Type T) : Ty(T) {} - virtual ~DIEValue() {} + ~DIEValue() {} public: // Accessors @@ -230,14 +230,14 @@ public: /// EmitValue - Emit value via the Dwarf writer. /// - virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0; + void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; /// SizeOf - Return the size of a value in bytes. /// - virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0; + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; #ifndef NDEBUG - virtual void print(raw_ostream &O) const = 0; + void print(raw_ostream &O) const; void dump() const; #endif }; @@ -246,6 +246,8 @@ public: /// DIEInteger - An integer value DIE. /// class DIEInteger : public DIEValue { + friend DIEValue; + uint64_t Integer; public: @@ -273,21 +275,18 @@ public: return dwarf::DW_FORM_data8; } - /// EmitValue - Emit integer of appropriate size. - /// - void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - uint64_t getValue() const { return Integer; } - - /// SizeOf - Determine size of integer value in bytes. - /// - unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + void setValue(uint64_t Val) { Integer = Val; } // Implement isa/cast/dyncast. static bool classof(const DIEValue *I) { return I->getType() == isInteger; } +private: + void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const; + #ifndef NDEBUG - void print(raw_ostream &O) const override; + void printImpl(raw_ostream &O) const; #endif }; @@ -295,28 +294,26 @@ public: /// DIEExpr - An expression DIE. // class DIEExpr : public DIEValue { + friend class DIEValue; + const MCExpr *Expr; public: explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {} - /// EmitValue - Emit expression value. - /// - void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - /// getValue - Get MCExpr. /// const MCExpr *getValue() const { return Expr; } - /// SizeOf - Determine size of expression value in bytes. - /// - unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; - // Implement isa/cast/dyncast. static bool classof(const DIEValue *E) { return E->getType() == isExpr; } +private: + void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const; + #ifndef NDEBUG - void print(raw_ostream &O) const override; + void printImpl(raw_ostream &O) const; #endif }; @@ -324,28 +321,26 @@ public: /// DIELabel - A label DIE. // class DIELabel : public DIEValue { + friend class DIEValue; + const MCSymbol *Label; public: explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {} - /// EmitValue - Emit label value. - /// - void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - /// getValue - Get MCSymbol. /// const MCSymbol *getValue() const { return Label; } - /// SizeOf - Determine size of label value in bytes. - /// - unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; - // Implement isa/cast/dyncast. static bool classof(const DIEValue *L) { return L->getType() == isLabel; } +private: + void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const; + #ifndef NDEBUG - void print(raw_ostream &O) const override; + void printImpl(raw_ostream &O) const; #endif }; @@ -353,6 +348,8 @@ public: /// DIEDelta - A simple label difference DIE. /// class DIEDelta : public DIEValue { + friend class DIEValue; + const MCSymbol *LabelHi; const MCSymbol *LabelLo; @@ -360,19 +357,15 @@ public: DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} - /// EmitValue - Emit delta value. - /// - void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - - /// SizeOf - Determine size of delta value in bytes. - /// - unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; - // Implement isa/cast/dyncast. static bool classof(const DIEValue *D) { return D->getType() == isDelta; } +private: + void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const; + #ifndef NDEBUG - void print(raw_ostream &O) const override; + void printImpl(raw_ostream &O) const; #endif }; @@ -380,29 +373,25 @@ public: /// DIEString - A container for string values. /// class DIEString : public DIEValue { - const DIEValue *Access; - StringRef Str; + friend class DIEValue; + + DwarfStringPoolEntryRef S; public: - DIEString(const DIEValue *Acc, StringRef S) - : DIEValue(isString), Access(Acc), Str(S) {} + DIEString(DwarfStringPoolEntryRef S) : DIEValue(isString), S(S) {} /// getString - Grab the string out of the object. - StringRef getString() const { return Str; } - - /// EmitValue - Emit delta value. - /// - void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - - /// SizeOf - Determine size of delta value in bytes. - /// - unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + StringRef getString() const { return S.getString(); } // Implement isa/cast/dyncast. static bool classof(const DIEValue *D) { return D->getType() == isString; } +private: + void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const; + #ifndef NDEBUG - void print(raw_ostream &O) const override; + void printImpl(raw_ostream &O) const; #endif }; @@ -411,6 +400,8 @@ public: /// this class can also be used as a proxy for a debug information entry not /// yet defined (ie. types.) class DIEEntry : public DIEValue { + friend class DIEValue; + DIE &Entry; public: @@ -419,53 +410,49 @@ public: DIE &getEntry() const { return Entry; } - /// EmitValue - Emit debug information entry offset. - /// - void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - - /// SizeOf - Determine size of debug information entry in bytes. - /// - unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { - return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP) - : sizeof(int32_t); - } - /// Returns size of a ref_addr entry. - static unsigned getRefAddrSize(AsmPrinter *AP); + static unsigned getRefAddrSize(const AsmPrinter *AP); // Implement isa/cast/dyncast. static bool classof(const DIEValue *E) { return E->getType() == isEntry; } +private: + void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const { + return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP) + : sizeof(int32_t); + } + #ifndef NDEBUG - void print(raw_ostream &O) const override; + void printImpl(raw_ostream &O) const; #endif }; //===--------------------------------------------------------------------===// /// \brief A signature reference to a type unit. class DIETypeSignature : public DIEValue { + friend class DIEValue; + const DwarfTypeUnit &Unit; public: explicit DIETypeSignature(const DwarfTypeUnit &Unit) : DIEValue(isTypeSignature), Unit(Unit) {} - /// \brief Emit type unit signature. - void EmitValue(AsmPrinter *Asm, dwarf::Form Form) const override; + // \brief Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { + return E->getType() == isTypeSignature; + } - /// Returns size of a ref_sig8 entry. - unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { +private: + void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const { assert(Form == dwarf::DW_FORM_ref_sig8); return 8; } - // \brief Implement isa/cast/dyncast. - static bool classof(const DIEValue *E) { - return E->getType() == isTypeSignature; - } #ifndef NDEBUG - void print(raw_ostream &O) const override; - void dump() const; + void printImpl(raw_ostream &O) const; #endif }; @@ -473,13 +460,15 @@ public: /// DIELoc - Represents an expression location. // class DIELoc : public DIEValue, public DIE { + friend class DIEValue; + mutable unsigned Size; // Size in bytes excluding size header. public: DIELoc() : DIEValue(isLoc), Size(0) {} /// ComputeSize - Calculate the size of the location expression. /// - unsigned ComputeSize(AsmPrinter *AP) const; + unsigned ComputeSize(const AsmPrinter *AP) const; /// BestForm - Choose the best form for data. /// @@ -496,19 +485,15 @@ public: return dwarf::DW_FORM_block; } - /// EmitValue - Emit location data. - /// - void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - - /// SizeOf - Determine size of location data in bytes. - /// - unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; - // Implement isa/cast/dyncast. static bool classof(const DIEValue *E) { return E->getType() == isLoc; } +private: + void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const; + #ifndef NDEBUG - void print(raw_ostream &O) const override; + void printImpl(raw_ostream &O) const; #endif }; @@ -516,13 +501,15 @@ public: /// DIEBlock - Represents a block of values. // class DIEBlock : public DIEValue, public DIE { + friend class DIEValue; + mutable unsigned Size; // Size in bytes excluding size header. public: DIEBlock() : DIEValue(isBlock), Size(0) {} /// ComputeSize - Calculate the size of the location expression. /// - unsigned ComputeSize(AsmPrinter *AP) const; + unsigned ComputeSize(const AsmPrinter *AP) const; /// BestForm - Choose the best form for data. /// @@ -536,19 +523,15 @@ public: return dwarf::DW_FORM_block; } - /// EmitValue - Emit location data. - /// - void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - - /// SizeOf - Determine size of location data in bytes. - /// - unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; - // Implement isa/cast/dyncast. static bool classof(const DIEValue *E) { return E->getType() == isBlock; } +private: + void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const; + #ifndef NDEBUG - void print(raw_ostream &O) const override; + void printImpl(raw_ostream &O) const; #endif }; @@ -557,6 +540,8 @@ public: /// section. // class DIELocList : public DIEValue { + friend class DIEValue; + // Index into the .debug_loc vector. size_t Index; @@ -566,19 +551,15 @@ public: /// getValue - Grab the current index out. size_t getValue() const { return Index; } - /// EmitValue - Emit location data. - /// - void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - - /// SizeOf - Determine size of location data in bytes. - /// - unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; - // Implement isa/cast/dyncast. static bool classof(const DIEValue *E) { return E->getType() == isLocList; } +private: + void EmitValueImpl(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOfImpl(const AsmPrinter *AP, dwarf::Form Form) const; + #ifndef NDEBUG - void print(raw_ostream &O) const override; + void printImpl(raw_ostream &O) const; #endif }; diff --git a/include/llvm/CodeGen/DwarfStringPoolEntry.h b/include/llvm/CodeGen/DwarfStringPoolEntry.h new file mode 100644 index 000000000000..fc2b5ddd2d2c --- /dev/null +++ b/include/llvm/CodeGen/DwarfStringPoolEntry.h @@ -0,0 +1,51 @@ +//===- llvm/CodeGen/DwarfStringPoolEntry.h - String pool entry --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H +#define LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H + +#include "llvm/ADT/StringMap.h" + +namespace llvm { + +class MCSymbol; + +/// Data for a string pool entry. +struct DwarfStringPoolEntry { + MCSymbol *Symbol; + unsigned Offset; + unsigned Index; +}; + +/// String pool entry reference. +struct DwarfStringPoolEntryRef { + const StringMapEntry<DwarfStringPoolEntry> *I = nullptr; + +public: + DwarfStringPoolEntryRef() = default; + explicit DwarfStringPoolEntryRef( + const StringMapEntry<DwarfStringPoolEntry> &I) + : I(&I) {} + + explicit operator bool() const { return I; } + MCSymbol *getSymbol() const { + assert(I->second.Symbol && "No symbol available!"); + return I->second.Symbol; + } + unsigned getOffset() const { return I->second.Offset; } + unsigned getIndex() const { return I->second.Index; } + StringRef getString() const { return I->first(); } + + bool operator==(const DwarfStringPoolEntryRef &X) const { return I == X.I; } + bool operator!=(const DwarfStringPoolEntryRef &X) const { return I != X.I; } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h deleted file mode 100644 index ec8e2ef243b7..000000000000 --- a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h +++ /dev/null @@ -1,122 +0,0 @@ -//===-- ForwardControlFlowIntegrity.h: Forward-Edge CFI ---------*- C++ -*-===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass instruments indirect calls with checks to ensure that these calls -// pass through the appropriate jump-instruction table generated by -// JumpInstrTables. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H -#define LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Pass.h" -#include "llvm/Target/TargetOptions.h" -#include <string> - -namespace llvm { - -class AnalysisUsage; -class BasicBlock; -class Constant; -class Function; -class Instruction; -class Module; -class Value; - -/// ForwardControlFlowIntegrity uses the information from JumpInstrTableInfo to -/// prepend checks to indirect calls to make sure that these calls target valid -/// locations. -class ForwardControlFlowIntegrity : public ModulePass { -public: - static char ID; - - ForwardControlFlowIntegrity(); - ForwardControlFlowIntegrity(JumpTable::JumpTableType JTT, - CFIntegrity CFIType, - bool CFIEnforcing, std::string CFIFuncName); - ~ForwardControlFlowIntegrity() override; - - /// Runs the CFI pass on a given module. This works best if the module in - /// question is the result of link-time optimization (see lib/LTO). - bool runOnModule(Module &M) override; - const char *getPassName() const override { - return "Forward Control-Flow Integrity"; - } - void getAnalysisUsage(AnalysisUsage &AU) const override; - -private: - typedef SmallVector<Instruction *, 64> CallSet; - - /// A structure that is used to keep track of constant table information. - struct CFIConstants { - Constant *StartValue; - Constant *MaskValue; - Constant *Size; - }; - - /// A map from function type to the base of the table for this type and a mask - /// for the table - typedef DenseMap<FunctionType *, CFIConstants> CFITables; - - CallSet IndirectCalls; - - /// The type of jumptable implementation. - JumpTable::JumpTableType JTType; - - /// The type of CFI check to add before each indirect call. - CFIntegrity CFIType; - - /// A value that controls whether or not CFI violations cause a halt. - bool CFIEnforcing; - - /// The name of the function to call in case of a CFI violation when - /// CFIEnforcing is false. There is a default function that ignores - /// violations. - std::string CFIFuncName; - - /// The alignment of each entry in the table, from JumpInstrTableInfo. The - /// JumpInstrTableInfo class always makes this a power of two. - uint64_t ByteAlignment; - - /// The base-2 logarithm of ByteAlignment, needed for some of the transforms - /// (like CFIntegrity::Ror) - unsigned LogByteAlignment; - - /// Adds checks to each indirect call site to make sure that it is calling a - /// function in our jump table. - void updateIndirectCalls(Module &M, CFITables &CFIT); - - /// Walks the instructions to find all the indirect calls. - void getIndirectCalls(Module &M); - - /// Adds a function that handles violations in non-enforcing mode - /// (!CFIEnforcing). The default warning function simply returns, since the - /// exact details of how to handle CFI violations depend on the application. - void addWarningFunction(Module &M); - - /// Rewrites a function pointer in a call/invoke instruction to force it into - /// a table. - void rewriteFunctionPointer(Module &M, Instruction *I, Value *FunPtr, - Constant *JumpTableStart, Constant *JumpTableMask, - Constant *JumpTableSize); - - /// Inserts a check and a call to a warning function at a given instruction - /// that must be an indirect call. - void insertWarning(Module &M, BasicBlock *Block, Instruction *I, - Value *FunPtr); -}; - -ModulePass * -createForwardControlFlowIntegrityPass(JumpTable::JumpTableType JTT, - CFIntegrity CFIType, - bool CFIEnforcing, StringRef CFIFuncName); -} - -#endif // LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 7c574df4ba41..82c762ed850f 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -18,6 +18,7 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/ISDOpcodes.h" @@ -73,6 +74,16 @@ public: /// cross-basic-block values. DenseMap<const Value*, unsigned> ValueMap; + // Keep track of frame indices allocated for statepoints as they could be used + // across basic block boundaries. + // Key of the map is statepoint instruction, value is a map from spilled + // llvm Value to the optional stack stack slot index. + // If optional is unspecified it means that we have visited this value + // but didn't spill it. + typedef DenseMap<const Value*, Optional<int>> StatepointSpilledValueMapTy; + DenseMap<const Instruction*, StatepointSpilledValueMapTy> + StatepointRelocatedValues; + /// StaticAllocaMap - Keep track of frame indices for fixed sized allocas in /// the entry block. This allows the allocas to be efficiently referenced /// anywhere in the function. @@ -221,6 +232,8 @@ public: int getArgumentFrameIndex(const Argument *A); private: + void addSEHHandlersForLPads(ArrayRef<const LandingPadInst *> LPads); + /// LiveOutRegInfo - Information about live out vregs. IndexedMap<LiveOutInfo, VirtReg2IndexFunctor> LiveOutRegInfo; }; @@ -232,11 +245,6 @@ private: /// floating-point support. void ComputeUsesVAFloatArgument(const CallInst &I, MachineModuleInfo *MMI); -/// AddCatchInfo - Extract the personality and type infos from an eh.selector -/// call, and add them to the specified machine basic block. -void AddCatchInfo(const CallInst &I, - MachineModuleInfo *MMI, MachineBasicBlock *MBB); - /// AddLandingPadInfo - Extract the exception handling information from the /// landingpad instruction and add them to the specified machine module info. void AddLandingPadInfo(const LandingPadInst &I, MachineModuleInfo &MMI, diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index c7f1ab87fcb1..357b2d8a7ca7 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -34,184 +34,173 @@ #define LLVM_CODEGEN_GCMETADATA_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/CodeGen/GCStrategy.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Pass.h" #include <memory> namespace llvm { - class AsmPrinter; - class GCStrategy; - class Constant; - class MCSymbol; - - namespace GC { - /// PointKind - The type of a collector-safe point. - /// - enum PointKind { - Loop, ///< Instr is a loop (backwards branch). - Return, ///< Instr is a return instruction. - PreCall, ///< Instr is a call instruction. - PostCall ///< Instr is the return address of a call. - }; +class AsmPrinter; +class Constant; +class MCSymbol; + +/// GCPoint - Metadata for a collector-safe point in machine code. +/// +struct GCPoint { + GC::PointKind Kind; ///< The kind of the safe point. + MCSymbol *Label; ///< A label. + DebugLoc Loc; + + GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL) + : Kind(K), Label(L), Loc(DL) {} +}; + +/// GCRoot - Metadata for a pointer to an object managed by the garbage +/// collector. +struct GCRoot { + int Num; ///< Usually a frame index. + int StackOffset; ///< Offset from the stack pointer. + const Constant *Metadata; ///< Metadata straight from the call + ///< to llvm.gcroot. + + GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {} +}; + +/// Garbage collection metadata for a single function. Currently, this +/// information only applies to GCStrategies which use GCRoot. +class GCFunctionInfo { +public: + typedef std::vector<GCPoint>::iterator iterator; + typedef std::vector<GCRoot>::iterator roots_iterator; + typedef std::vector<GCRoot>::const_iterator live_iterator; + +private: + const Function &F; + GCStrategy &S; + uint64_t FrameSize; + std::vector<GCRoot> Roots; + std::vector<GCPoint> SafePoints; + + // FIXME: Liveness. A 2D BitVector, perhaps? + // + // BitVector Liveness; + // + // bool islive(int point, int root) = + // Liveness[point * SafePoints.size() + root] + // + // The bit vector is the more compact representation where >3.2% of roots + // are live per safe point (1.5% on 64-bit hosts). + +public: + GCFunctionInfo(const Function &F, GCStrategy &S); + ~GCFunctionInfo(); + + /// getFunction - Return the function to which this metadata applies. + /// + const Function &getFunction() const { return F; } + + /// getStrategy - Return the GC strategy for the function. + /// + GCStrategy &getStrategy() { return S; } + + /// addStackRoot - Registers a root that lives on the stack. Num is the + /// stack object ID for the alloca (if the code generator is + // using MachineFrameInfo). + void addStackRoot(int Num, const Constant *Metadata) { + Roots.push_back(GCRoot(Num, Metadata)); + } + + /// removeStackRoot - Removes a root. + roots_iterator removeStackRoot(roots_iterator position) { + return Roots.erase(position); + } + + /// addSafePoint - Notes the existence of a safe point. Num is the ID of the + /// label just prior to the safe point (if the code generator is using + /// MachineModuleInfo). + void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) { + SafePoints.push_back(GCPoint(Kind, Label, DL)); } - /// GCPoint - Metadata for a collector-safe point in machine code. + /// getFrameSize/setFrameSize - Records the function's frame size. /// - struct GCPoint { - GC::PointKind Kind; ///< The kind of the safe point. - MCSymbol *Label; ///< A label. - DebugLoc Loc; - - GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL) - : Kind(K), Label(L), Loc(DL) {} - }; - - /// GCRoot - Metadata for a pointer to an object managed by the garbage - /// collector. - struct GCRoot { - int Num; ///< Usually a frame index. - int StackOffset; ///< Offset from the stack pointer. - const Constant *Metadata; ///< Metadata straight from the call - ///< to llvm.gcroot. - - GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {} - }; - - - /// Garbage collection metadata for a single function. Currently, this - /// information only applies to GCStrategies which use GCRoot. - class GCFunctionInfo { - public: - typedef std::vector<GCPoint>::iterator iterator; - typedef std::vector<GCRoot>::iterator roots_iterator; - typedef std::vector<GCRoot>::const_iterator live_iterator; - - private: - const Function &F; - GCStrategy &S; - uint64_t FrameSize; - std::vector<GCRoot> Roots; - std::vector<GCPoint> SafePoints; - - // FIXME: Liveness. A 2D BitVector, perhaps? - // - // BitVector Liveness; - // - // bool islive(int point, int root) = - // Liveness[point * SafePoints.size() + root] - // - // The bit vector is the more compact representation where >3.2% of roots - // are live per safe point (1.5% on 64-bit hosts). - - public: - GCFunctionInfo(const Function &F, GCStrategy &S); - ~GCFunctionInfo(); - - /// getFunction - Return the function to which this metadata applies. - /// - const Function &getFunction() const { return F; } - - /// getStrategy - Return the GC strategy for the function. - /// - GCStrategy &getStrategy() { return S; } - - /// addStackRoot - Registers a root that lives on the stack. Num is the - /// stack object ID for the alloca (if the code generator is - // using MachineFrameInfo). - void addStackRoot(int Num, const Constant *Metadata) { - Roots.push_back(GCRoot(Num, Metadata)); - } - - /// removeStackRoot - Removes a root. - roots_iterator removeStackRoot(roots_iterator position) { - return Roots.erase(position); - } - - /// addSafePoint - Notes the existence of a safe point. Num is the ID of the - /// label just prior to the safe point (if the code generator is using - /// MachineModuleInfo). - void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) { - SafePoints.push_back(GCPoint(Kind, Label, DL)); - } - - /// getFrameSize/setFrameSize - Records the function's frame size. - /// - uint64_t getFrameSize() const { return FrameSize; } - void setFrameSize(uint64_t S) { FrameSize = S; } - - /// begin/end - Iterators for safe points. - /// - iterator begin() { return SafePoints.begin(); } - iterator end() { return SafePoints.end(); } - size_t size() const { return SafePoints.size(); } - - /// roots_begin/roots_end - Iterators for all roots in the function. - /// - roots_iterator roots_begin() { return Roots.begin(); } - roots_iterator roots_end () { return Roots.end(); } - size_t roots_size() const { return Roots.size(); } - - /// live_begin/live_end - Iterators for live roots at a given safe point. - /// - live_iterator live_begin(const iterator &p) { return roots_begin(); } - live_iterator live_end (const iterator &p) { return roots_end(); } - size_t live_size(const iterator &p) const { return roots_size(); } - }; - - /// An analysis pass which caches information about the entire Module. - /// Records both the function level information used by GCRoots and a - /// cache of the 'active' gc strategy objects for the current Module. - class GCModuleInfo : public ImmutablePass { - typedef StringMap<GCStrategy*> strategy_map_type; - typedef std::vector<std::unique_ptr<GCStrategy>> list_type; - - strategy_map_type StrategyMap; - list_type StrategyList; - - GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name); - - public: - /// List of per function info objects. In theory, Each of these - /// may be associated with a different GC. - typedef std::vector<std::unique_ptr<GCFunctionInfo>> FuncInfoVec; - - FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); } - FuncInfoVec::iterator funcinfo_end() { return Functions.end(); } - - - private: - /// Owning list of all GCFunctionInfos associated with this Module - FuncInfoVec Functions; - - /// Non-owning map to bypass linear search when finding the GCFunctionInfo - /// associated with a particular Function. - typedef DenseMap<const Function*,GCFunctionInfo*> finfo_map_type; - finfo_map_type FInfoMap; - public: - - typedef list_type::const_iterator iterator; - - static char ID; - - GCModuleInfo(); - - /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should - /// call it in doFinalization(). - /// - void clear(); - - /// begin/end - Iterators for used strategies. - /// - iterator begin() const { return StrategyList.begin(); } - iterator end() const { return StrategyList.end(); } - - /// get - Look up function metadata. This is currently assumed - /// have the side effect of initializing the associated GCStrategy. That - /// will soon change. - GCFunctionInfo &getFunctionInfo(const Function &F); - }; + uint64_t getFrameSize() const { return FrameSize; } + void setFrameSize(uint64_t S) { FrameSize = S; } + /// begin/end - Iterators for safe points. + /// + iterator begin() { return SafePoints.begin(); } + iterator end() { return SafePoints.end(); } + size_t size() const { return SafePoints.size(); } + + /// roots_begin/roots_end - Iterators for all roots in the function. + /// + roots_iterator roots_begin() { return Roots.begin(); } + roots_iterator roots_end() { return Roots.end(); } + size_t roots_size() const { return Roots.size(); } + + /// live_begin/live_end - Iterators for live roots at a given safe point. + /// + live_iterator live_begin(const iterator &p) { return roots_begin(); } + live_iterator live_end(const iterator &p) { return roots_end(); } + size_t live_size(const iterator &p) const { return roots_size(); } +}; + +/// An analysis pass which caches information about the entire Module. +/// Records both the function level information used by GCRoots and a +/// cache of the 'active' gc strategy objects for the current Module. +class GCModuleInfo : public ImmutablePass { + /// An owning list of all GCStrategies which have been created + SmallVector<std::unique_ptr<GCStrategy>, 1> GCStrategyList; + /// A helper map to speedup lookups into the above list + StringMap<GCStrategy*> GCStrategyMap; + +public: + /// Lookup the GCStrategy object associated with the given gc name. + /// Objects are owned internally; No caller should attempt to delete the + /// returned objects. + GCStrategy *getGCStrategy(const StringRef Name); + + /// List of per function info objects. In theory, Each of these + /// may be associated with a different GC. + typedef std::vector<std::unique_ptr<GCFunctionInfo>> FuncInfoVec; + + FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); } + FuncInfoVec::iterator funcinfo_end() { return Functions.end(); } + +private: + /// Owning list of all GCFunctionInfos associated with this Module + FuncInfoVec Functions; + + /// Non-owning map to bypass linear search when finding the GCFunctionInfo + /// associated with a particular Function. + typedef DenseMap<const Function *, GCFunctionInfo *> finfo_map_type; + finfo_map_type FInfoMap; + +public: + typedef SmallVector<std::unique_ptr<GCStrategy>,1>::const_iterator iterator; + + static char ID; + + GCModuleInfo(); + + /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should + /// call it in doFinalization(). + /// + void clear(); + + /// begin/end - Iterators for used strategies. + /// + iterator begin() const { return GCStrategyList.begin(); } + iterator end() const { return GCStrategyList.end(); } + + /// get - Look up function metadata. This is currently assumed + /// have the side effect of initializing the associated GCStrategy. That + /// will soon change. + GCFunctionInfo &getFunctionInfo(const Function &F); +}; } #endif diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h index 25fafba93f8b..220847029113 100644 --- a/include/llvm/CodeGen/GCMetadataPrinter.h +++ b/include/llvm/CodeGen/GCMetadataPrinter.h @@ -26,43 +26,39 @@ namespace llvm { - class GCMetadataPrinter; +class GCMetadataPrinter; - /// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the - /// defaults from Registry. - typedef Registry<GCMetadataPrinter> GCMetadataPrinterRegistry; +/// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the +/// defaults from Registry. +typedef Registry<GCMetadataPrinter> GCMetadataPrinterRegistry; - /// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are - /// created, managed, and owned by the AsmPrinter. - class GCMetadataPrinter { - private: - GCStrategy *S; - friend class AsmPrinter; +/// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are +/// created, managed, and owned by the AsmPrinter. +class GCMetadataPrinter { +private: + GCStrategy *S; + friend class AsmPrinter; - protected: - // May only be subclassed. - GCMetadataPrinter(); +protected: + // May only be subclassed. + GCMetadataPrinter(); - private: - GCMetadataPrinter(const GCMetadataPrinter &) LLVM_DELETED_FUNCTION; - GCMetadataPrinter & - operator=(const GCMetadataPrinter &) LLVM_DELETED_FUNCTION; +private: + GCMetadataPrinter(const GCMetadataPrinter &) = delete; + GCMetadataPrinter &operator=(const GCMetadataPrinter &) = delete; - public: - GCStrategy &getStrategy() { return *S; } +public: + GCStrategy &getStrategy() { return *S; } - /// Called before the assembly for the module is generated by - /// the AsmPrinter (but after target specific hooks.) - virtual void beginAssembly(Module &M, GCModuleInfo &Info, - AsmPrinter &AP) {} - /// Called after the assembly for the module is generated by - /// the AsmPrinter (but before target specific hooks) - virtual void finishAssembly(Module &M, GCModuleInfo &Info, - AsmPrinter &AP) {} - - virtual ~GCMetadataPrinter(); - }; + /// Called before the assembly for the module is generated by + /// the AsmPrinter (but after target specific hooks.) + virtual void beginAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) {} + /// Called after the assembly for the module is generated by + /// the AsmPrinter (but before target specific hooks) + virtual void finishAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) {} + virtual ~GCMetadataPrinter(); +}; } #endif diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h index 0b0c3124c537..a1b8e895898f 100644 --- a/include/llvm/CodeGen/GCStrategy.h +++ b/include/llvm/CodeGen/GCStrategy.h @@ -16,11 +16,11 @@ // GCStrategy is relevant for implementations using either gc.root or // gc.statepoint based lowering strategies, but is currently focused mostly on // options for gc.root. This will change over time. -// +// // When requested by a subclass of GCStrategy, the gc.root implementation will // populate GCModuleInfo and GCFunctionInfo with that about each Function in // the Module that opts in to garbage collection. Specifically: -// +// // - Safe points // Garbage collection is generally only possible at certain points in code. // GCStrategy can request that the collector insert such points: @@ -28,7 +28,7 @@ // - At and after any call to a subroutine // - Before returning from the current function // - Before backwards branches (loops) -// +// // - Roots // When a reference to a GC-allocated object exists on the stack, it must be // stored in an alloca registered with llvm.gcoot. @@ -42,155 +42,136 @@ // insertion support is planned. gc.statepoint does not currently support // custom stack map formats; such can be generated by parsing the standard // stack map section if desired. -// +// // The read and write barrier support can be used with either implementation. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_GCSTRATEGY_H -#define LLVM_CODEGEN_GCSTRATEGY_H +#ifndef LLVM_IR_GCSTRATEGY_H +#define LLVM_IR_GCSTRATEGY_H #include "llvm/ADT/Optional.h" -#include "llvm/CodeGen/GCMetadata.h" -#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Registry.h" #include <string> namespace llvm { - /// GCStrategy describes a garbage collector algorithm's code generation - /// requirements, and provides overridable hooks for those needs which cannot - /// be abstractly described. GCStrategy objects currently must be looked up - /// through the GCModuleInfo analysis pass. They are owned by the analysis - /// pass and recreated every time that pass is invalidated. - class GCStrategy { - private: - std::string Name; - friend class GCModuleInfo; - - protected: - bool UseStatepoints; /// Uses gc.statepoints as opposed to gc.roots, - /// if set, none of the other options can be - /// anything but their default values. - - unsigned NeededSafePoints; ///< Bitmask of required safe points. - bool CustomReadBarriers; ///< Default is to insert loads. - bool CustomWriteBarriers; ///< Default is to insert stores. - bool CustomRoots; ///< Default is to pass through to backend. - bool CustomSafePoints; ///< Default is to use NeededSafePoints - ///< to find safe points. - bool InitRoots; ///< If set, roots are nulled during lowering. - bool UsesMetadata; ///< If set, backend must emit metadata tables. - - public: - GCStrategy(); - virtual ~GCStrategy() {} - - /// Return the name of the GC strategy. This is the value of the collector - /// name string specified on functions which use this strategy. - const std::string &getName() const { return Name; } - - /// By default, write barriers are replaced with simple store - /// instructions. If true, then performCustomLowering must instead lower - /// them. - bool customWriteBarrier() const { return CustomWriteBarriers; } - - /// By default, read barriers are replaced with simple load - /// instructions. If true, then performCustomLowering must instead lower - /// them. - bool customReadBarrier() const { return CustomReadBarriers; } - - /// Returns true if this strategy is expecting the use of gc.statepoints, - /// and false otherwise. - bool useStatepoints() const { return UseStatepoints; } - - /** @name Statepoint Specific Properties */ - ///@{ - - /// If the value specified can be reliably distinguished, returns true for - /// pointers to GC managed locations and false for pointers to non-GC - /// managed locations. Note a GCStrategy can always return 'None' (i.e. an - /// empty optional indicating it can't reliably distinguish. - virtual Optional<bool> isGCManagedPointer(const Value *V) const { - return None; - } - ///@} - - /** @name GCRoot Specific Properties - * These properties and overrides only apply to collector strategies using - * GCRoot. - */ - ///@{ - - /// True if safe points of any kind are required. By default, none are - /// recorded. - bool needsSafePoints() const { - return CustomSafePoints || NeededSafePoints != 0; - } - - /// True if the given kind of safe point is required. By default, none are - /// recorded. - bool needsSafePoint(GC::PointKind Kind) const { - return (NeededSafePoints & 1 << Kind) != 0; - } - - /// By default, roots are left for the code generator so it can generate a - /// stack map. If true, then performCustomLowering must delete them. - bool customRoots() const { return CustomRoots; } - - /// By default, the GC analysis will find safe points according to - /// NeededSafePoints. If true, then findCustomSafePoints must create them. - bool customSafePoints() const { return CustomSafePoints; } - - /// If set, gcroot intrinsics should initialize their allocas to null - /// before the first use. This is necessary for most GCs and is enabled by - /// default. - bool initializeRoots() const { return InitRoots; } - - /// If set, appropriate metadata tables must be emitted by the back-end - /// (assembler, JIT, or otherwise). For statepoint, this method is - /// currently unsupported. The stackmap information can be found in the - /// StackMap section as described in the documentation. - bool usesMetadata() const { return UsesMetadata; } - - ///@} - - /// initializeCustomLowering/performCustomLowering - If any of the actions - /// are set to custom, performCustomLowering must be overriden to transform - /// the corresponding actions to LLVM IR. initializeCustomLowering is - /// optional to override. These are the only GCStrategy methods through - /// which the LLVM IR can be modified. These methods apply mostly to - /// gc.root based implementations, but can be overriden to provide custom - /// barrier lowerings with gc.statepoint as well. - ///@{ - virtual bool initializeCustomLowering(Module &F) { - // No changes made - return false; - } - virtual bool performCustomLowering(Function &F) { - llvm_unreachable("GCStrategy subclass specified a configuration which" - "requires a custom lowering without providing one"); - } - ///@} - /// Called if customSafepoints returns true, used only by gc.root - /// implementations. - virtual bool findCustomSafePoints(GCFunctionInfo& FI, MachineFunction& MF) { - llvm_unreachable("GCStrategy subclass specified a configuration which" - "requests custom safepoint identification without" - "providing an implementation for such"); - } - }; - - /// Subclasses of GCStrategy are made available for use during compilation by - /// adding them to the global GCRegistry. This can done either within the - /// LLVM source tree or via a loadable plugin. An example registeration - /// would be: - /// static GCRegistry::Add<CustomGC> X("custom-name", - /// "my custom supper fancy gc strategy"); - /// - /// Note that to use a custom GCMetadataPrinter w/gc.roots, you must also - /// register your GCMetadataPrinter subclass with the - /// GCMetadataPrinterRegistery as well. - typedef Registry<GCStrategy> GCRegistry; +namespace GC { +/// PointKind - Used to indicate whether the address of the call instruction +/// or the address after the call instruction is listed in the stackmap. For +/// most runtimes, PostCall safepoints are appropriate. +/// +enum PointKind { + PreCall, ///< Instr is a call instruction. + PostCall ///< Instr is the return address of a call. +}; +} + +/// GCStrategy describes a garbage collector algorithm's code generation +/// requirements, and provides overridable hooks for those needs which cannot +/// be abstractly described. GCStrategy objects must be looked up through +/// the Function. The objects themselves are owned by the Context and must +/// be immutable. +class GCStrategy { +private: + std::string Name; + friend class GCModuleInfo; + +protected: + bool UseStatepoints; /// Uses gc.statepoints as opposed to gc.roots, + /// if set, none of the other options can be + /// anything but their default values. + + unsigned NeededSafePoints; ///< Bitmask of required safe points. + bool CustomReadBarriers; ///< Default is to insert loads. + bool CustomWriteBarriers; ///< Default is to insert stores. + bool CustomRoots; ///< Default is to pass through to backend. + bool InitRoots; ///< If set, roots are nulled during lowering. + bool UsesMetadata; ///< If set, backend must emit metadata tables. + +public: + GCStrategy(); + virtual ~GCStrategy() {} + + /// Return the name of the GC strategy. This is the value of the collector + /// name string specified on functions which use this strategy. + const std::string &getName() const { return Name; } + + /// By default, write barriers are replaced with simple store + /// instructions. If true, you must provide a custom pass to lower + /// calls to @llvm.gcwrite. + bool customWriteBarrier() const { return CustomWriteBarriers; } + + /// By default, read barriers are replaced with simple load + /// instructions. If true, you must provide a custom pass to lower + /// calls to @llvm.gcread. + bool customReadBarrier() const { return CustomReadBarriers; } + + /// Returns true if this strategy is expecting the use of gc.statepoints, + /// and false otherwise. + bool useStatepoints() const { return UseStatepoints; } + + /** @name Statepoint Specific Properties */ + ///@{ + + /// If the value specified can be reliably distinguished, returns true for + /// pointers to GC managed locations and false for pointers to non-GC + /// managed locations. Note a GCStrategy can always return 'None' (i.e. an + /// empty optional indicating it can't reliably distinguish. + virtual Optional<bool> isGCManagedPointer(const Value *V) const { + return None; + } + ///@} + + /** @name GCRoot Specific Properties + * These properties and overrides only apply to collector strategies using + * GCRoot. + */ + ///@{ + + /// True if safe points of any kind are required. By default, none are + /// recorded. + bool needsSafePoints() const { return NeededSafePoints != 0; } + + /// True if the given kind of safe point is required. By default, none are + /// recorded. + bool needsSafePoint(GC::PointKind Kind) const { + return (NeededSafePoints & 1 << Kind) != 0; + } + + /// By default, roots are left for the code generator so it can generate a + /// stack map. If true, you must provide a custom pass to lower + /// calls to @llvm.gcroot. + bool customRoots() const { return CustomRoots; } + + /// If set, gcroot intrinsics should initialize their allocas to null + /// before the first use. This is necessary for most GCs and is enabled by + /// default. + bool initializeRoots() const { return InitRoots; } + + /// If set, appropriate metadata tables must be emitted by the back-end + /// (assembler, JIT, or otherwise). For statepoint, this method is + /// currently unsupported. The stackmap information can be found in the + /// StackMap section as described in the documentation. + bool usesMetadata() const { return UsesMetadata; } + + ///@} +}; + +/// Subclasses of GCStrategy are made available for use during compilation by +/// adding them to the global GCRegistry. This can done either within the +/// LLVM source tree or via a loadable plugin. An example registeration +/// would be: +/// static GCRegistry::Add<CustomGC> X("custom-name", +/// "my custom supper fancy gc strategy"); +/// +/// Note that to use a custom GCMetadataPrinter w/gc.roots, you must also +/// register your GCMetadataPrinter subclass with the +/// GCMetadataPrinterRegistery as well. +typedef Registry<GCStrategy> GCRegistry; } #endif diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h index 51a31842a5c0..5207f801c84e 100644 --- a/include/llvm/CodeGen/GCs.h +++ b/include/llvm/CodeGen/GCs.h @@ -15,29 +15,32 @@ #define LLVM_CODEGEN_GCS_H namespace llvm { - class GCStrategy; - class GCMetadataPrinter; +class GCStrategy; +class GCMetadataPrinter; - /// FIXME: Collector instances are not useful on their own. These no longer - /// serve any purpose except to link in the plugins. +/// FIXME: Collector instances are not useful on their own. These no longer +/// serve any purpose except to link in the plugins. - /// Creates an ocaml-compatible garbage collector. - void linkOcamlGC(); +/// Creates a CoreCLR-compatible garbage collector. +void linkCoreCLRGC(); - /// Creates an ocaml-compatible metadata printer. - void linkOcamlGCPrinter(); +/// Creates an ocaml-compatible garbage collector. +void linkOcamlGC(); - /// Creates an erlang-compatible garbage collector. - void linkErlangGC(); +/// Creates an ocaml-compatible metadata printer. +void linkOcamlGCPrinter(); - /// Creates an erlang-compatible metadata printer. - void linkErlangGCPrinter(); +/// Creates an erlang-compatible garbage collector. +void linkErlangGC(); - /// Creates a shadow stack garbage collector. This collector requires no code - /// generator support. - void linkShadowStackGC(); +/// Creates an erlang-compatible metadata printer. +void linkErlangGCPrinter(); - void linkStatepointExampleGC(); +/// Creates a shadow stack garbage collector. This collector requires no code +/// generator support. +void linkShadowStackGC(); + +void linkStatepointExampleGC(); } #endif diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 952362ed6ce3..c2071fe5dd2d 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -229,11 +229,18 @@ namespace ISD { SMULO, UMULO, /// Simple binary floating point operators. - FADD, FSUB, FMUL, FMA, FDIV, FREM, + FADD, FSUB, FMUL, FDIV, FREM, + + /// FMA - Perform a * b + c with no intermediate rounding step. + FMA, + + /// FMAD - Perform a * b + c, while getting the same result as the + /// separately rounded operations. + FMAD, /// FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This - /// DAG node does not require that X and Y have the same type, just that the - /// are both floating point. X and the result must have the same type. + /// DAG node does not require that X and Y have the same type, just that + /// they are both floating point. X and the result must have the same type. /// FCOPYSIGN(f32, f64) is allowed. FCOPYSIGN, @@ -301,6 +308,10 @@ namespace ISD { /// part. MULHU, MULHS, + /// [US]{MIN/MAX} - Binary minimum or maximum or signed or unsigned + /// integers. + SMIN, SMAX, UMIN, UMAX, + /// Bitwise operators - logical and, logical or, logical xor. AND, OR, XOR, @@ -680,13 +691,29 @@ namespace ISD { ATOMIC_LOAD_UMIN, ATOMIC_LOAD_UMAX, - // Masked load and store + // Masked load and store - consecutive vector load and store operations + // with additional mask operand that prevents memory accesses to the + // masked-off lanes. MLOAD, MSTORE, + // Masked gather and scatter - load and store operations for a vector of + // random addresses with additional mask operand that prevents memory + // accesses to the masked-off lanes. + MGATHER, MSCATTER, + /// This corresponds to the llvm.lifetime.* intrinsics. The first operand /// is the chain and the second operand is the alloca pointer. LIFETIME_START, LIFETIME_END, + /// GC_TRANSITION_START/GC_TRANSITION_END - These operators mark the + /// beginning and end of GC transition sequence, and carry arbitrary + /// information that target might need for lowering. The first operand is + /// a chain, the rest are specified by the target and not touched by the DAG + /// optimizers. GC_TRANSITION_START..GC_TRANSITION_END pairs may not be + /// nested. + GC_TRANSITION_START, + GC_TRANSITION_END, + /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific pre-isel opcode values start here. BUILTIN_OP_END @@ -696,7 +723,7 @@ namespace ISD { /// which do not reference a specific memory location should be less than /// this value. Those that do must not be less than this value, and can /// be used with SelectionDAG::getMemIntrinsicNode. - static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+180; + static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+200; //===--------------------------------------------------------------------===// /// MemIndexedMode enum - This enum defines the load / store indexed diff --git a/include/llvm/CodeGen/JumpInstrTables.h b/include/llvm/CodeGen/JumpInstrTables.h deleted file mode 100644 index 005bc1eb2b2d..000000000000 --- a/include/llvm/CodeGen/JumpInstrTables.h +++ /dev/null @@ -1,105 +0,0 @@ -//===-- JumpInstrTables.h: Jump-Instruction Tables --------------*- C++ -*-===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief An implementation of tables consisting of jump instructions -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_JUMPINSTRTABLES_H -#define LLVM_CODEGEN_JUMPINSTRTABLES_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/Pass.h" -#include "llvm/Target/TargetOptions.h" - -namespace llvm { -class Constant; -class Function; -class FunctionType; -class JumpInstrTableInfo; -class Module; - -/// A class to manage a set of jump tables indexed on function type. It looks at -/// each function in the module to find all the functions that have the -/// jumptable attribute set. For each such function, it creates a new -/// jump-instruction-table function and stores the mapping in the ImmutablePass -/// JumpInstrTableInfo. -/// -/// These special functions get lowered in AsmPrinter to assembly of the form: -/// \verbatim -/// .globl f -/// .type f,@function -/// .align 8,0x90 -/// f: -/// jmp f_orig@PLT -/// \endverbatim -/// -/// Support for an architecture depends on three functions in TargetInstrInfo: -/// getUnconditionalBranch, getTrap, and getJumpInstrTableEntryBound. AsmPrinter -/// uses these to generate the appropriate instructions for the jump statement -/// (an unconditional branch) and for padding to make the table have a size that -/// is a power of two. This padding uses a trap instruction to ensure that calls -/// to this area halt the program. The default implementations of these -/// functions call llvm_unreachable, except for getJumpInstrTableEntryBound, -/// which returns 0 by default. -class JumpInstrTables : public ModulePass { -public: - static char ID; - - JumpInstrTables(); - JumpInstrTables(JumpTable::JumpTableType JTT); - virtual ~JumpInstrTables(); - bool runOnModule(Module &M) override; - const char *getPassName() const override { return "Jump-Instruction Tables"; } - void getAnalysisUsage(AnalysisUsage &AU) const override; - - /// Creates a jump-instruction table function for the Target and adds it to - /// the tables. - Function *insertEntry(Module &M, Function *Target); - - /// Checks to see if there is already a table for the given FunctionType. - bool hasTable(FunctionType *FunTy); - - /// Maps the function into a subset of function types, depending on the - /// jump-instruction table style selected from JumpTableTypes in - /// JumpInstrTables.cpp. The choice of mapping determines the number of - /// jump-instruction tables generated by this pass. E.g., the simplest mapping - /// converts every function type into void f(); so, all functions end up in a - /// single table. - static FunctionType *transformType(JumpTable::JumpTableType JTT, - FunctionType *FunTy); -private: - /// The metadata used while a jump table is being built - struct TableMeta { - /// The number of this table - unsigned TableNum; - - /// The current number of jump entries in the table. - unsigned Count; - }; - - typedef DenseMap<FunctionType *, struct TableMeta> JumpMap; - - /// The current state of functions and jump entries in the table(s). - JumpMap Metadata; - - /// The ImmutablePass that stores information about the generated tables. - JumpInstrTableInfo *JITI; - - /// The total number of tables. - unsigned TableCount; - - /// The type of tables to build. - JumpTable::JumpTableType JTType; -}; - -/// Creates a JumpInstrTables pass for the given type of jump table. -ModulePass *createJumpInstrTablesPass(JumpTable::JumpTableType JTT); -} - -#endif /* LLVM_CODEGEN_JUMPINSTRTABLES_H */ diff --git a/include/llvm/CodeGen/LatencyPriorityQueue.h b/include/llvm/CodeGen/LatencyPriorityQueue.h index cf601ae5384c..f347f66e0981 100644 --- a/include/llvm/CodeGen/LatencyPriorityQueue.h +++ b/include/llvm/CodeGen/LatencyPriorityQueue.h @@ -83,8 +83,6 @@ namespace llvm { void remove(SUnit *SU) override; - void dump(ScheduleDAG* DAG) const override; - // 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/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 11a360a491a7..7d7e48af2a0f 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -23,7 +23,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/DebugLoc.h" -#include "llvm/IR/Metadata.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/ValueHandle.h" #include <unordered_map> #include <utility> @@ -45,7 +45,8 @@ typedef std::pair<const MachineInstr *, const MachineInstr *> InsnRange; class LexicalScope { public: - LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A) + LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *I, + bool A) : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), LastInsn(nullptr), FirstInsn(nullptr), DFSIn(0), DFSOut(0) { assert((!D || D->isResolved()) && "Expected resolved node"); @@ -57,8 +58,8 @@ public: // Accessors. LexicalScope *getParent() const { return Parent; } const MDNode *getDesc() const { return Desc; } - const MDNode *getInlinedAt() const { return InlinedAtLocation; } - const MDNode *getScopeNode() const { return Desc; } + const DILocation *getInlinedAt() const { return InlinedAtLocation; } + const DILocalScope *getScopeNode() const { return Desc; } bool isAbstractScope() const { return AbstractScope; } SmallVectorImpl<LexicalScope *> &getChildren() { return Children; } SmallVectorImpl<InsnRange> &getRanges() { return Ranges; } @@ -118,8 +119,8 @@ public: private: LexicalScope *Parent; // Parent to this scope. - const MDNode *Desc; // Debug info descriptor. - const MDNode *InlinedAtLocation; // Location at which this + const DILocalScope *Desc; // Debug info descriptor. + const DILocation *InlinedAtLocation; // Location at which this // scope is inlined. bool AbstractScope; // Abstract Scope SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope. @@ -158,16 +159,16 @@ public: /// getMachineBasicBlocks - Populate given set using machine basic blocks /// which have machine instructions that belong to lexical scope identified by /// DebugLoc. - void getMachineBasicBlocks(DebugLoc DL, + void getMachineBasicBlocks(const DILocation *DL, SmallPtrSetImpl<const MachineBasicBlock *> &MBBs); /// dominates - Return true if DebugLoc's lexical scope dominates at least one /// machine instruction's lexical scope in a given machine basic block. - bool dominates(DebugLoc DL, MachineBasicBlock *MBB); + bool dominates(const DILocation *DL, MachineBasicBlock *MBB); /// findLexicalScope - Find lexical scope, either regular or inlined, for the /// given DebugLoc. Return NULL if not found. - LexicalScope *findLexicalScope(DebugLoc DL); + LexicalScope *findLexicalScope(const DILocation *DL); /// getAbstractScopesList - Return a reference to list of abstract scopes. ArrayRef<LexicalScope *> getAbstractScopesList() const { @@ -175,17 +176,19 @@ public: } /// findAbstractScope - Find an abstract scope or return null. - LexicalScope *findAbstractScope(const MDNode *N) { + LexicalScope *findAbstractScope(const DILocalScope *N) { auto I = AbstractScopeMap.find(N); return I != AbstractScopeMap.end() ? &I->second : nullptr; } - /// findInlinedScope - Find an inlined scope for the given DebugLoc or return - /// NULL. - LexicalScope *findInlinedScope(DebugLoc DL); + /// findInlinedScope - Find an inlined scope for the given scope/inlined-at. + LexicalScope *findInlinedScope(const DILocalScope *N, const DILocation *IA) { + auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA)); + return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr; + } /// findLexicalScope - Find regular lexical scope or return null. - LexicalScope *findLexicalScope(const MDNode *N) { + LexicalScope *findLexicalScope(const DILocalScope *N) { auto I = LexicalScopeMap.find(N); return I != LexicalScopeMap.end() ? &I->second : nullptr; } @@ -194,18 +197,24 @@ public: void dump(); /// getOrCreateAbstractScope - Find or create an abstract lexical scope. - LexicalScope *getOrCreateAbstractScope(const MDNode *N); + LexicalScope *getOrCreateAbstractScope(const DILocalScope *Scope); private: - /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If + /// getOrCreateLexicalScope - Find lexical scope for the given Scope/IA. If /// not available then create new lexical scope. - LexicalScope *getOrCreateLexicalScope(DebugLoc DL); + LexicalScope *getOrCreateLexicalScope(const DILocalScope *Scope, + const DILocation *IA = nullptr); + LexicalScope *getOrCreateLexicalScope(const DILocation *DL) { + return DL ? getOrCreateLexicalScope(DL->getScope(), DL->getInlinedAt()) + : nullptr; + } /// getOrCreateRegularScope - Find or create a regular lexical scope. - LexicalScope *getOrCreateRegularScope(MDNode *Scope); + LexicalScope *getOrCreateRegularScope(const DILocalScope *Scope); /// getOrCreateInlinedScope - Find or create an inlined lexical scope. - LexicalScope *getOrCreateInlinedScope(MDNode *Scope, MDNode *InlinedAt); + LexicalScope *getOrCreateInlinedScope(const DILocalScope *Scope, + const DILocation *InlinedAt); /// extractLexicalScopes - Extract instruction ranges for each lexical scopes /// for the given machine function. @@ -221,17 +230,18 @@ private: /// LexicalScopeMap - Tracks the scopes in the current function. // Use an unordered_map to ensure value pointer validity over insertion. - std::unordered_map<const MDNode *, LexicalScope> LexicalScopeMap; + std::unordered_map<const DILocalScope *, LexicalScope> LexicalScopeMap; /// InlinedLexicalScopeMap - Tracks inlined function scopes in current /// function. - std::unordered_map<std::pair<const MDNode *, const MDNode *>, LexicalScope, - pair_hash<const MDNode *, const MDNode *>> - InlinedLexicalScopeMap; + std::unordered_map<std::pair<const DILocalScope *, const DILocation *>, + LexicalScope, + pair_hash<const DILocalScope *, const DILocation *>> + InlinedLexicalScopeMap; /// AbstractScopeMap - These scopes are not included LexicalScopeMap. // Use an unordered_map to ensure value pointer validity over insertion. - std::unordered_map<const MDNode *, LexicalScope> AbstractScopeMap; + std::unordered_map<const DILocalScope *, LexicalScope> AbstractScopeMap; /// AbstractScopesList - Tracks abstract scopes constructed while processing /// a function. diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index e7ccbfa617e5..fee131e4a3c6 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -36,6 +36,7 @@ namespace { (void) llvm::createGreedyRegisterAllocator(); (void) llvm::createDefaultPBQPRegisterAllocator(); + llvm::linkCoreCLRGC(); llvm::linkOcamlGC(); llvm::linkErlangGC(); llvm::linkShadowStackGC(); diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index ce9845ee1673..9b8b91c9b80e 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -27,6 +27,7 @@ #include "llvm/Support/Allocator.h" #include <cassert> #include <climits> +#include <set> namespace llvm { class CoalescerPair; @@ -194,6 +195,12 @@ namespace llvm { Segments segments; // the liveness segments VNInfoList valnos; // value#'s + // The segment set is used temporarily to accelerate initial computation + // of live ranges of physical registers in computeRegUnitRange. + // After that the set is flushed to the segment vector and deleted. + typedef std::set<Segment> SegmentSet; + std::unique_ptr<SegmentSet> segmentSet; + typedef Segments::iterator iterator; iterator begin() { return segments.begin(); } iterator end() { return segments.end(); } @@ -211,12 +218,16 @@ namespace llvm { const_vni_iterator vni_end() const { return valnos.end(); } /// Constructs a new LiveRange object. - LiveRange() { - } + LiveRange(bool UseSegmentSet = false) + : segmentSet(UseSegmentSet ? llvm::make_unique<SegmentSet>() + : nullptr) {} /// Constructs a new LiveRange object by copying segments and valnos from /// another LiveRange. LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) { + assert(Other.segmentSet == nullptr && + "Copying of LiveRanges with active SegmentSets is not supported"); + // Duplicate valnos. for (const VNInfo *VNI : Other.valnos) { createValueCopy(VNI, Allocator); @@ -437,14 +448,12 @@ namespace llvm { /// Add the specified Segment to this range, merging segments as /// appropriate. This returns an iterator to the inserted segment (which /// may have grown since it was inserted). - iterator addSegment(Segment S) { - return addSegmentFrom(S, segments.begin()); - } + iterator addSegment(Segment S); - /// extendInBlock - If this range is live before Kill in the basic block - /// that starts at StartIdx, extend it to be live up to Kill, and return - /// the value. If there is no segment before Kill, return NULL. - VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Kill); + /// If this range is live before @p Use in the basic block that starts at + /// @p StartIdx, extend it to be live up to @p Use, and return the value. If + /// there is no segment before @p Use, return nullptr. + VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Use); /// join - Join two live ranges (this, and other) together. This applies /// mappings to the value numbers in the LHS/RHS ranges as specified. If @@ -540,6 +549,12 @@ namespace llvm { return thisIndex < otherIndex; } + /// Flush segment set into the regular segment vector. + /// The method is to be called after the live range + /// has been created, if use of the segment set was + /// activated in the constructor of the live range. + void flushSegmentSet(); + void print(raw_ostream &OS) const; void dump() const; @@ -557,10 +572,8 @@ namespace llvm { void append(const LiveRange::Segment S); private: - - iterator addSegmentFrom(Segment S, iterator From); - void extendSegmentEndTo(iterator I, SlotIndex NewEnd); - iterator extendSegmentStartTo(iterator I, SlotIndex NewStr); + friend class LiveRangeUpdater; + void addSegmentToSet(Segment S); void markValNoForDeletion(VNInfo *V); }; @@ -606,6 +619,10 @@ namespace llvm { LiveInterval(unsigned Reg, float Weight) : SubRanges(nullptr), reg(Reg), weight(Weight) {} + ~LiveInterval() { + clearSubRanges(); + } + template<typename T> class SingleLinkedListIterator { T *P; @@ -681,9 +698,7 @@ namespace llvm { } /// Removes all subregister liveness information. - void clearSubRanges() { - SubRanges = nullptr; - } + void clearSubRanges(); /// Removes all subranges without any segments (subranges without segments /// are not considered valid and should only exist temporarily). @@ -726,13 +741,14 @@ namespace llvm { #endif private: - LiveInterval& operator=(const LiveInterval& rhs) LLVM_DELETED_FUNCTION; - /// Appends @p Range to SubRanges list. void appendSubRange(SubRange *Range) { Range->Next = SubRanges; SubRanges = Range; } + + /// Free memory held by SubRange. + void freeSubRange(SubRange *S); }; inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) { diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index d8c921fce313..9673f80e0856 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -27,12 +27,15 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/SlotIndexes.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetRegisterInfo.h" #include <cmath> #include <iterator> namespace llvm { +extern cl::opt<bool> UseSegmentSetForPhysRegs; + class AliasAnalysis; class BitVector; class BlockFrequency; @@ -97,7 +100,7 @@ namespace llvm { public: static char ID; // Pass identification, replacement for typeid LiveIntervals(); - virtual ~LiveIntervals(); + ~LiveIntervals() override; // Calculate the spill weight to assign to a single instruction. static float getSpillWeight(bool isDef, bool isUse, @@ -181,12 +184,6 @@ namespace llvm { void pruneValue(LiveRange &LR, SlotIndex Kill, SmallVectorImpl<SlotIndex> *EndPoints); - /// Subregister aware variant of pruneValue(LiveRange &LR, SlotIndex Kill, - /// SmallVectorImpl<SlotIndex> &EndPoints). Prunes the value in the main - /// range and all sub ranges. - void pruneValue(LiveInterval &LI, SlotIndex Kill, - SmallVectorImpl<SlotIndex> *EndPoints); - SlotIndexes *getSlotIndexes() const { return Indexes; } @@ -383,7 +380,8 @@ namespace llvm { LiveRange *LR = RegUnitRanges[Unit]; if (!LR) { // Compute missing ranges on demand. - RegUnitRanges[Unit] = LR = new LiveRange(); + // Use segment set to speed-up initial computation of the live range. + RegUnitRanges[Unit] = LR = new LiveRange(UseSegmentSetForPhysRegs); computeRegUnitRange(*LR, Unit); } return *LR; @@ -399,6 +397,15 @@ namespace llvm { return RegUnitRanges[Unit]; } + /// Remove value numbers and related live segments starting at position + /// @p Pos that are part of any liverange of physical register @p Reg or one + /// of its subregisters. + void removePhysRegDefAt(unsigned Reg, SlotIndex Pos); + + /// Remove value number and related live segments of @p LI and its subranges + /// that start at position @p Pos. + void removeVRegDefAt(LiveInterval &LI, SlotIndex Pos); + private: /// Compute live intervals for all virtual registers. void computeVirtRegs(); diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 1381c46a2750..967f0cbac719 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -179,8 +179,8 @@ public: } private: - Query(const Query&) LLVM_DELETED_FUNCTION; - void operator=(const Query&) LLVM_DELETED_FUNCTION; + Query(const Query&) = delete; + void operator=(const Query&) = delete; }; // Array of LiveIntervalUnions. diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h index 91e4ddcde170..6ffd3eeea351 100644 --- a/include/llvm/CodeGen/LivePhysRegs.h +++ b/include/llvm/CodeGen/LivePhysRegs.h @@ -44,8 +44,8 @@ class LivePhysRegs { const TargetRegisterInfo *TRI; SparseSet<unsigned> LiveRegs; - LivePhysRegs(const LivePhysRegs&) LLVM_DELETED_FUNCTION; - LivePhysRegs &operator=(const LivePhysRegs&) LLVM_DELETED_FUNCTION; + LivePhysRegs(const LivePhysRegs&) = delete; + LivePhysRegs &operator=(const LivePhysRegs&) = delete; public: /// \brief Constructs a new empty LivePhysRegs set. LivePhysRegs() : TRI(nullptr), LiveRegs() {} @@ -57,9 +57,9 @@ public: } /// \brief Clear and initialize the LivePhysRegs set. - void init(const TargetRegisterInfo *_TRI) { - assert(_TRI && "Invalid TargetRegisterInfo pointer."); - TRI = _TRI; + void init(const TargetRegisterInfo *TRI) { + assert(TRI && "Invalid TargetRegisterInfo pointer."); + this->TRI = TRI; LiveRegs.clear(); LiveRegs.setUniverse(TRI->getNumRegs()); } @@ -93,7 +93,8 @@ public: } /// \brief Removes physical registers clobbered by the regmask operand @p MO. - void removeRegsInMask(const MachineOperand &MO); + void removeRegsInMask(const MachineOperand &MO, + SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> *Clobbers); /// \brief Returns true if register @p Reg is contained in the set. This also /// works if only the super register of @p Reg has been defined, because we @@ -109,7 +110,11 @@ public: /// instruction(bundle): Remove killed-uses, add defs. This is the not /// recommended way, because it depends on accurate kill flags. If possible /// use stepBackwards() instead of this function. - void stepForward(const MachineInstr &MI); + /// The clobbers set will be the list of registers either defined or clobbered + /// by a regmask. The operand will identify whether this is a regmask or + /// register operand. + void stepForward(const MachineInstr &MI, + SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> &Clobbers); /// \brief Adds all live-in registers of basic block @p MBB. void addLiveIns(const MachineBasicBlock *MBB) { diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h index 44c3c4eaf7b1..de855f2fe7a0 100644 --- a/include/llvm/CodeGen/LiveRangeEdit.h +++ b/include/llvm/CodeGen/LiveRangeEdit.h @@ -122,7 +122,7 @@ public: MRI.setDelegate(this); } - ~LiveRangeEdit() { MRI.resetDelegate(this); } + ~LiveRangeEdit() override { MRI.resetDelegate(this); } LiveInterval &getParent() const { assert(Parent && "No parent LiveInterval"); diff --git a/include/llvm/CodeGen/LiveStackAnalysis.h b/include/llvm/CodeGen/LiveStackAnalysis.h index df683983fa53..f495507c66ec 100644 --- a/include/llvm/CodeGen/LiveStackAnalysis.h +++ b/include/llvm/CodeGen/LiveStackAnalysis.h @@ -21,6 +21,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/Target/TargetRegisterInfo.h" #include <map> +#include <unordered_map> namespace llvm { @@ -33,7 +34,7 @@ namespace llvm { /// S2IMap - Stack slot indices to live interval mapping. /// - typedef std::map<int, LiveInterval> SS2IntervalMap; + typedef std::unordered_map<int, LiveInterval> SS2IntervalMap; SS2IntervalMap S2IMap; /// S2RCMap - Stack slot indices to register class mapping. diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 1440b967aea2..357aef0ee60d 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -315,9 +315,18 @@ public: // LiveIn management methods. - /// addLiveIn - Add the specified register as a live in. Note that it - /// is an error to add the same register to the same set more than once. - void addLiveIn(unsigned Reg) { LiveIns.push_back(Reg); } + /// Adds the specified register as a live in. Note that it is an error to add + /// the same register to the same set more than once unless the intention is + /// to call sortUniqueLiveIns after all registers are added. + void addLiveIn(unsigned Reg) { LiveIns.push_back(Reg); } + + /// Sorts and uniques the LiveIns vector. It can be significantly faster to do + /// this than repeatedly calling isLiveIn before calling addLiveIn for every + /// LiveIn insertion. + void sortUniqueLiveIns() { + std::sort(LiveIns.begin(), LiveIns.end()); + LiveIns.erase(std::unique(LiveIns.begin(), LiveIns.end()), LiveIns.end()); + } /// Add PhysReg as live in to this block, and ensure that there is a copy of /// PhysReg to a virtual register of class RC. Return the virtual register @@ -624,17 +633,18 @@ public: ///< neighborhood. }; - /// computeRegisterLiveness - Return whether (physical) register \c Reg - /// has been <def>ined and not <kill>ed as of just before \c MI. + /// Return whether (physical) register \p Reg has been <def>ined and not + /// <kill>ed as of just before \p Before. /// - /// Search is localised to a neighborhood of - /// \c Neighborhood instructions before (searching for defs or kills) and - /// Neighborhood instructions after (searching just for defs) MI. + /// Search is localised to a neighborhood of \p Neighborhood instructions + /// before (searching for defs or kills) and \p Neighborhood instructions + /// after (searching just for defs) \p Before. /// - /// \c Reg must be a physical register. + /// \p Reg must be a physical register. LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, - unsigned Reg, MachineInstr *MI, - unsigned Neighborhood=10); + unsigned Reg, + const_iterator Before, + unsigned Neighborhood=10) const; // Debugging methods. void dump() const; diff --git a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h index 1aef689eb7a4..feb394e7a69e 100644 --- a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h +++ b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h @@ -35,7 +35,7 @@ public: MachineBlockFrequencyInfo(); - ~MachineBlockFrequencyInfo(); + ~MachineBlockFrequencyInfo() override; void getAnalysisUsage(AnalysisUsage &AU) const override; diff --git a/include/llvm/CodeGen/MachineDominanceFrontier.h b/include/llvm/CodeGen/MachineDominanceFrontier.h index e099e716c63d..4131194a0c0f 100644 --- a/include/llvm/CodeGen/MachineDominanceFrontier.h +++ b/include/llvm/CodeGen/MachineDominanceFrontier.h @@ -26,8 +26,8 @@ public: typedef DominanceFrontierBase<MachineBasicBlock>::iterator iterator; typedef DominanceFrontierBase<MachineBasicBlock>::const_iterator const_iterator; - void operator=(const MachineDominanceFrontier &) LLVM_DELETED_FUNCTION; - MachineDominanceFrontier(const MachineDominanceFrontier &) LLVM_DELETED_FUNCTION; + void operator=(const MachineDominanceFrontier &) = delete; + MachineDominanceFrontier(const MachineDominanceFrontier &) = delete; static char ID; diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index a6980a6daeac..4428fa618fb0 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -45,9 +45,6 @@ class MachineDominatorTree : public MachineFunctionPass { MachineBasicBlock *FromBB; MachineBasicBlock *ToBB; MachineBasicBlock *NewBB; - CriticalEdge(MachineBasicBlock *FromBB, MachineBasicBlock *ToBB, - MachineBasicBlock *NewBB) - : FromBB(FromBB), ToBB(ToBB), NewBB(NewBB) {} }; /// \brief Pile up all the critical edges to be split. @@ -67,74 +64,7 @@ class MachineDominatorTree : public MachineFunctionPass { /// the fast query path of DT as much as possible. /// /// \post CriticalEdgesToSplit.empty(). - void applySplitCriticalEdges() const { - // Bail out early if there is nothing to do. - if (CriticalEdgesToSplit.empty()) - return; - - // For each element in CriticalEdgesToSplit, remember whether or - // not element is the new immediate domminator of its successor. - // The mapping is done by index, i.e., the information for the ith - // element of CriticalEdgesToSplit is the ith element of IsNewIDom. - SmallVector<bool, 32> IsNewIDom; - IsNewIDom.resize(CriticalEdgesToSplit.size()); - size_t Idx = 0; - - // Collect all the dominance properties info, before invalidating - // the underlying DT. - for (CriticalEdge &Edge : CriticalEdgesToSplit) { - // Update dominator information. - MachineBasicBlock *Succ = Edge.ToBB; - MachineDomTreeNode *SucccDTNode = DT->getNode(Succ); - - IsNewIDom[Idx] = true; - for (MachineBasicBlock *PredBB : Succ->predecessors()) { - if (PredBB == Edge.NewBB) - continue; - // If we are in this situation: - // FromBB1 FromBB2 - // + + - // + + + + - // + + + + - // ... Split1 Split2 ... - // + + - // + + - // + - // Succ - // Instead of checking the domiance property with Split2, we - // check it with FromBB2 since Split2 is still unknown of the - // underlying DT structure. - if (NewBBs.count(PredBB)) { - assert(PredBB->pred_size() == 1 && "A basic block resulting from a " - "critical edge split has more " - "than one predecessor!"); - PredBB = *PredBB->pred_begin(); - } - if (!DT->dominates(SucccDTNode, DT->getNode(PredBB))) { - IsNewIDom[Idx] = false; - break; - } - } - ++Idx; - } - - // Now, update DT with the collected dominance properties info. - Idx = 0; - for (CriticalEdge &Edge : CriticalEdgesToSplit) { - // We know FromBB dominates NewBB. - MachineDomTreeNode *NewDTNode = DT->addNewBlock(Edge.NewBB, Edge.FromBB); - MachineDomTreeNode *SucccDTNode = DT->getNode(Edge.ToBB); - - // If all the other predecessors of "Succ" are dominated by "Succ" itself - // then the new block is the new immediate dominator of "Succ". Otherwise, - // the new block doesn't dominate anything. - if (IsNewIDom[Idx]) - DT->changeImmediateDominator(SucccDTNode, NewDTNode); - ++Idx; - } - NewBBs.clear(); - CriticalEdgesToSplit.clear(); - } + void applySplitCriticalEdges() const; public: static char ID; // Pass ID, replacement for typeid @@ -142,7 +72,7 @@ public: MachineDominatorTree(); - ~MachineDominatorTree(); + ~MachineDominatorTree() override; DominatorTreeBase<MachineBasicBlock> &getBase() { applySplitCriticalEdges(); @@ -307,7 +237,7 @@ public: (void)Inserted; assert(Inserted && "A basic block inserted via edge splitting cannot appear twice"); - CriticalEdgesToSplit.push_back(CriticalEdge(FromBB, ToBB, NewBB)); + CriticalEdgesToSplit.push_back({FromBB, ToBB, NewBB}); } }; diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 667736021f92..40f3b4944cc1 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -246,6 +246,21 @@ class MachineFrameInfo { /// True if this is a varargs function that contains a musttail call. bool HasMustTailInVarArgFunc; + /// True if this function contains a tail call. If so immutable objects like + /// function arguments are no longer so. A tail call *can* override fixed + /// stack objects like arguments so we can't treat them as immutable. + bool HasTailCall; + + /// Not null, if shrink-wrapping found a better place for the prologue. + MachineBasicBlock *Save; + /// Not null, if shrink-wrapping found a better place for the epilogue. + MachineBasicBlock *Restore; + + /// Check if it exists a path from \p MBB leading to the basic + /// block with a SavePoint (a.k.a. prologue). + bool isBeforeSavePoint(const MachineFunction &MF, + const MachineBasicBlock &MBB) const; + public: explicit MachineFrameInfo(unsigned StackAlign, bool isStackRealign, bool RealignOpt) @@ -269,6 +284,9 @@ public: HasInlineAsmWithSPAdjust = false; HasVAStart = false; HasMustTailInVarArgFunc = false; + Save = nullptr; + Restore = nullptr; + HasTailCall = false; } /// hasStackObjects - Return true if there are any stack objects in this @@ -496,6 +514,10 @@ public: bool hasMustTailInVarArgFunc() const { return HasMustTailInVarArgFunc; } void setHasMustTailInVarArgFunc(bool B) { HasMustTailInVarArgFunc = B; } + /// Returns true if the function contains a tail call. + bool hasTailCall() const { return HasTailCall; } + void setHasTailCall() { HasTailCall = true; } + /// getMaxCallFrameSize - Return the maximum size of a call frame that must be /// allocated for an outgoing function call. This is only available if /// CallFrameSetup/Destroy pseudo instructions are used by the target, and @@ -516,10 +538,6 @@ public: /// on the stack. Returns an index with a negative value. int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset); - /// Allocates memory at a fixed, target-specific offset from the frame - /// pointer. Marks the function as having its frame address taken. - int CreateFrameAllocation(uint64_t Size); - /// isFixedObjectIndex - Returns true if the specified index corresponds to a /// fixed stack object. bool isFixedObjectIndex(int ObjectIdx) const { @@ -537,6 +555,9 @@ public: /// isImmutableObjectIndex - Returns true if the specified index corresponds /// to an immutable object. bool isImmutableObjectIndex(int ObjectIdx) const { + // Tail calling functions can clobber their function arguments. + if (HasTailCall) + return false; assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); return Objects[ObjectIdx+NumFixedObjects].isImmutable; @@ -601,6 +622,11 @@ public: void setCalleeSavedInfoValid(bool v) { CSIValid = v; } + MachineBasicBlock *getSavePoint() const { return Save; } + void setSavePoint(MachineBasicBlock *NewSave) { Save = NewSave; } + MachineBasicBlock *getRestorePoint() const { return Restore; } + void setRestorePoint(MachineBasicBlock *NewRestore) { Restore = NewRestore; } + /// getPristineRegs - Return a set of physical registers that are pristine on /// entry to the MBB. /// diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 4e9ff9ebb4fe..94610cabf566 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -145,8 +145,8 @@ class MachineFunction { /// True if the function includes any inline assembly. bool HasInlineAsm; - MachineFunction(const MachineFunction &) LLVM_DELETED_FUNCTION; - void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION; + MachineFunction(const MachineFunction &) = delete; + void operator=(const MachineFunction&) = delete; public: MachineFunction(const Function *Fn, const TargetMachine &TM, unsigned FunctionNum, MachineModuleInfo &MMI); @@ -176,6 +176,13 @@ public: const TargetSubtargetInfo &getSubtarget() const { return *STI; } void setSubtarget(const TargetSubtargetInfo *ST) { STI = ST; } + /// getSubtarget - This method returns a pointer to the specified type of + /// TargetSubtargetInfo. In debug builds, it verifies that the object being + /// returned is of the correct type. + template<typename STC> const STC &getSubtarget() const { + return *static_cast<const STC *>(STI); + } + /// getRegInfo - Return information about the registers currently in use. /// MachineRegisterInfo &getRegInfo() { return *RegInfo; } diff --git a/include/llvm/CodeGen/MachineFunctionAnalysis.h b/include/llvm/CodeGen/MachineFunctionAnalysis.h index 36f1c6627096..023eeb1b4d0e 100644 --- a/include/llvm/CodeGen/MachineFunctionAnalysis.h +++ b/include/llvm/CodeGen/MachineFunctionAnalysis.h @@ -31,7 +31,7 @@ private: public: static char ID; explicit MachineFunctionAnalysis(const TargetMachine &tm); - ~MachineFunctionAnalysis(); + ~MachineFunctionAnalysis() override; MachineFunction &getMF() const { return *MF; } diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index bcf1f5caaa8c..e57257c76bc7 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -42,7 +42,7 @@ class MachineFunction; class MachineMemOperand; //===----------------------------------------------------------------------===// -/// MachineInstr - Representation of each machine instruction. +/// Representation of each machine instruction. /// /// This class isn't a POD type, but it must have a trivial destructor. When a /// MachineFunction is deleted, all the contained MachineInstrs are deallocated @@ -93,25 +93,25 @@ private: DebugLoc debugLoc; // Source line information. - MachineInstr(const MachineInstr&) LLVM_DELETED_FUNCTION; - void operator=(const MachineInstr&) LLVM_DELETED_FUNCTION; + MachineInstr(const MachineInstr&) = delete; + void operator=(const MachineInstr&) = delete; // Use MachineFunction::DeleteMachineInstr() instead. - ~MachineInstr() LLVM_DELETED_FUNCTION; + ~MachineInstr() = delete; // Intrusive list support friend struct ilist_traits<MachineInstr>; friend struct ilist_traits<MachineBasicBlock>; void setParent(MachineBasicBlock *P) { Parent = P; } - /// MachineInstr ctor - This constructor creates a copy of the given + /// This constructor creates a copy of the given /// MachineInstr in the given MachineFunction. MachineInstr(MachineFunction &, const MachineInstr &); - /// MachineInstr ctor - This constructor create a MachineInstr and add the - /// implicit operands. It reserves space for number of operands specified by + /// This constructor create a MachineInstr and add the implicit operands. + /// It reserves space for number of operands specified by /// MCInstrDesc. An explicit DebugLoc is supplied. - MachineInstr(MachineFunction&, const MCInstrDesc &MCID, - const DebugLoc dl, bool NoImp = false); + MachineInstr(MachineFunction &, const MCInstrDesc &MCID, DebugLoc dl, + bool NoImp = false); // MachineInstrs are pool-allocated and owned by MachineFunction. friend class MachineFunction; @@ -120,43 +120,38 @@ public: const MachineBasicBlock* getParent() const { return Parent; } MachineBasicBlock* getParent() { return Parent; } - /// getAsmPrinterFlags - Return the asm printer flags bitvector. - /// + /// Return the asm printer flags bitvector. uint8_t getAsmPrinterFlags() const { return AsmPrinterFlags; } - /// clearAsmPrinterFlags - clear the AsmPrinter bitvector - /// + /// Clear the AsmPrinter bitvector. void clearAsmPrinterFlags() { AsmPrinterFlags = 0; } - /// getAsmPrinterFlag - Return whether an AsmPrinter flag is set. - /// + /// Return whether an AsmPrinter flag is set. bool getAsmPrinterFlag(CommentFlag Flag) const { return AsmPrinterFlags & Flag; } - /// setAsmPrinterFlag - Set a flag for the AsmPrinter. - /// + /// Set a flag for the AsmPrinter. void setAsmPrinterFlag(CommentFlag Flag) { AsmPrinterFlags |= (uint8_t)Flag; } - /// clearAsmPrinterFlag - clear specific AsmPrinter flags - /// + /// Clear specific AsmPrinter flags. void clearAsmPrinterFlag(CommentFlag Flag) { AsmPrinterFlags &= ~Flag; } - /// getFlags - Return the MI flags bitvector. + /// Return the MI flags bitvector. uint8_t getFlags() const { return Flags; } - /// getFlag - Return whether an MI flag is set. + /// Return whether an MI flag is set. bool getFlag(MIFlag Flag) const { return Flags & Flag; } - /// setFlag - Set a MI flag. + /// Set a MI flag. void setFlag(MIFlag Flag) { Flags |= (uint8_t)Flag; } @@ -172,8 +167,7 @@ public: Flags &= ~((uint8_t)Flag); } - /// isInsideBundle - Return true if MI is in a bundle (but not the first MI - /// in a bundle). + /// Return true if MI is in a bundle (but not the first MI in a bundle). /// /// A bundle looks like this before it's finalized: /// ---------------- @@ -212,7 +206,7 @@ public: return getFlag(BundledPred); } - /// isBundled - Return true if this instruction part of a bundle. This is true + /// Return true if this instruction part of a bundle. This is true /// if either itself or its following instruction is marked "InsideBundle". bool isBundled() const { return isBundledWithPred() || isBundledWithSucc(); @@ -240,30 +234,25 @@ public: /// Break bundle below this instruction. void unbundleFromSucc(); - /// getDebugLoc - Returns the debug location id of this MachineInstr. - /// - DebugLoc getDebugLoc() const { return debugLoc; } + /// Returns the debug location id of this MachineInstr. + const DebugLoc &getDebugLoc() const { return debugLoc; } - /// \brief Return the debug variable referenced by + /// Return the debug variable referenced by /// this DBG_VALUE instruction. - DIVariable getDebugVariable() const { + const DILocalVariable *getDebugVariable() const { assert(isDebugValue() && "not a DBG_VALUE"); - DIVariable Var(getOperand(2).getMetadata()); - assert(Var.Verify() && "not a DIVariable"); - return Var; + return cast<DILocalVariable>(getOperand(2).getMetadata()); } - /// \brief Return the complex address expression referenced by + /// Return the complex address expression referenced by /// this DBG_VALUE instruction. - DIExpression getDebugExpression() const { + const DIExpression *getDebugExpression() const { assert(isDebugValue() && "not a DBG_VALUE"); - DIExpression Expr(getOperand(3).getMetadata()); - assert(Expr.Verify() && "not a DIExpression"); - return Expr; + return cast<DIExpression>(getOperand(3).getMetadata()); } - /// emitError - Emit an error referring to the source location of this - /// instruction. This should only be used for inline assembly that is somehow + /// Emit an error referring to the source location of this instruction. + /// This should only be used for inline assembly that is somehow /// impossible to compile. Other errors should have been handled much /// earlier. /// @@ -271,13 +260,11 @@ public: /// void emitError(StringRef Msg) const; - /// getDesc - Returns the target instruction descriptor of this - /// MachineInstr. + /// Returns the target instruction descriptor of this MachineInstr. const MCInstrDesc &getDesc() const { return *MCID; } - /// getOpcode - Returns the opcode of this MachineInstr. - /// - int getOpcode() const { return MCID->Opcode; } + /// Returns the opcode of this MachineInstr. + unsigned getOpcode() const { return MCID->Opcode; } /// Access to explicit operands of the instruction. /// @@ -292,8 +279,7 @@ public: return Operands[i]; } - /// getNumExplicitOperands - Returns the number of non-implicit operands. - /// + /// Returns the number of non-implicit operands. unsigned getNumExplicitOperands() const; /// iterator/begin/end - Iterate over all operands of a machine instruction. @@ -357,8 +343,7 @@ public: return iterator_range<mmo_iterator>(memoperands_begin(), memoperands_end()); } - /// hasOneMemOperand - Return true if this instruction has exactly one - /// MachineMemOperand. + /// Return true if this instruction has exactly one MachineMemOperand. bool hasOneMemOperand() const { return NumMemRefs == 1; } @@ -372,7 +357,7 @@ public: AllInBundle // Return true if all instructions in bundle have property }; - /// hasProperty - Return true if the instruction (or in the case of a bundle, + /// Return true if the instruction (or in the case of a bundle, /// the instructions inside the bundle) has the specified property. /// The first argument is the property being queried. /// The second argument indicates whether the query should look inside @@ -386,23 +371,22 @@ public: return hasPropertyInBundle(1 << MCFlag, Type); } - /// isVariadic - Return true if this instruction can have a variable number of - /// operands. In this case, the variable operands will be after the normal + /// Return true if this instruction can have a variable number of operands. + /// In this case, the variable operands will be after the normal /// operands but before the implicit definitions and uses (if any are /// present). bool isVariadic(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::Variadic, Type); } - /// hasOptionalDef - Set if this instruction has an optional definition, e.g. + /// Set if this instruction has an optional definition, e.g. /// ARM instructions which can set condition code if 's' bit is set. bool hasOptionalDef(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::HasOptionalDef, Type); } - /// isPseudo - Return true if this is a pseudo instruction that doesn't + /// Return true if this is a pseudo instruction that doesn't /// correspond to a real machine instruction. - /// bool isPseudo(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::Pseudo, Type); } @@ -415,16 +399,15 @@ public: return hasProperty(MCID::Call, Type); } - /// isBarrier - Returns true if the specified instruction stops control flow + /// Returns true if the specified instruction stops control flow /// from executing the instruction immediately following it. Examples include /// unconditional branches and return instructions. bool isBarrier(QueryType Type = AnyInBundle) const { return hasProperty(MCID::Barrier, Type); } - /// isTerminator - Returns true if this instruction part of the terminator for - /// a basic block. Typically this is things like return and branch - /// instructions. + /// Returns true if this instruction part of the terminator for a basic block. + /// Typically this is things like return and branch instructions. /// /// Various passes use this to insert code into the bottom of a basic block, /// but before control flow occurs. @@ -432,21 +415,21 @@ public: return hasProperty(MCID::Terminator, Type); } - /// isBranch - Returns true if this is a conditional, unconditional, or - /// indirect branch. Predicates below can be used to discriminate between + /// Returns true if this is a conditional, unconditional, or indirect branch. + /// Predicates below can be used to discriminate between /// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to /// get more information. bool isBranch(QueryType Type = AnyInBundle) const { return hasProperty(MCID::Branch, Type); } - /// isIndirectBranch - Return true if this is an indirect branch, such as a + /// Return true if this is an indirect branch, such as a /// branch through a register. bool isIndirectBranch(QueryType Type = AnyInBundle) const { return hasProperty(MCID::IndirectBranch, Type); } - /// isConditionalBranch - Return true if this is a branch which may fall + /// Return true if this is a branch which may fall /// through to the next instruction or may transfer control flow to some other /// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more /// information about this branch. @@ -454,7 +437,7 @@ public: return isBranch(Type) & !isBarrier(Type) & !isIndirectBranch(Type); } - /// isUnconditionalBranch - Return true if this is a branch which always + /// Return true if this is a branch which always /// transfers control flow to some other block. The /// TargetInstrInfo::AnalyzeBranch method can be used to get more information /// about this branch. @@ -472,43 +455,41 @@ public: return hasProperty(MCID::Predicable, Type); } - /// isCompare - Return true if this instruction is a comparison. + /// Return true if this instruction is a comparison. bool isCompare(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::Compare, Type); } - /// isMoveImmediate - Return true if this instruction is a move immediate + /// Return true if this instruction is a move immediate /// (including conditional moves) instruction. bool isMoveImmediate(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::MoveImm, Type); } - /// isBitcast - Return true if this instruction is a bitcast instruction. - /// + /// Return true if this instruction is a bitcast instruction. bool isBitcast(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::Bitcast, Type); } - /// isSelect - Return true if this instruction is a select instruction. - /// + /// Return true if this instruction is a select instruction. bool isSelect(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::Select, Type); } - /// isNotDuplicable - Return true if this instruction cannot be safely - /// duplicated. For example, if the instruction has a unique labels attached + /// 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. bool isNotDuplicable(QueryType Type = AnyInBundle) const { return hasProperty(MCID::NotDuplicable, Type); } - /// hasDelaySlot - Returns true if the specified instruction has a delay slot + /// Returns true if the specified instruction has a delay slot /// which must be filled by the code generator. bool hasDelaySlot(QueryType Type = AnyInBundle) const { return hasProperty(MCID::DelaySlot, Type); } - /// canFoldAsLoad - Return true for instructions that can be folded as + /// Return true for instructions that can be folded as /// memory operands in other instructions. The most common use for this /// is instructions that are simple loads from memory that don't modify /// the loaded value in any way, but it can also be used for instructions @@ -567,7 +548,7 @@ public: // Side Effect Analysis //===--------------------------------------------------------------------===// - /// mayLoad - Return true if this instruction could possibly read memory. + /// Return true if this instruction could possibly read memory. /// Instructions with this flag set are not necessarily simple load /// instructions, they may load a value and modify it, for example. bool mayLoad(QueryType Type = AnyInBundle) const { @@ -579,8 +560,7 @@ public: return hasProperty(MCID::MayLoad, Type); } - - /// mayStore - Return true if this instruction could possibly modify memory. + /// Return true if this instruction could possibly modify memory. /// Instructions with this flag set are not necessarily simple store /// instructions, they may store a modified value based on their operands, or /// may not actually modify anything, for example. @@ -593,11 +573,16 @@ public: return hasProperty(MCID::MayStore, Type); } + /// Return true if this instruction could possibly read or modify memory. + bool mayLoadOrStore(QueryType Type = AnyInBundle) const { + return mayLoad(Type) || mayStore(Type); + } + //===--------------------------------------------------------------------===// // Flags that indicate whether an instruction can be modified by a method. //===--------------------------------------------------------------------===// - /// isCommutable - Return true if this may be a 2- or 3-address + /// Return true if this may be a 2- or 3-address /// instruction (of the form "X = op Y, Z, ..."), which produces the same /// result if Y and Z are exchanged. If this flag is set, then the /// TargetInstrInfo::commuteInstruction method may be used to hack on the @@ -611,7 +596,7 @@ public: return hasProperty(MCID::Commutable, Type); } - /// isConvertibleTo3Addr - Return true if this is a 2-address instruction + /// Return true if this is a 2-address instruction /// which can be changed into a 3-address instruction if needed. Doing this /// transformation can be profitable in the register allocator, because it /// means that the instruction can use a 2-address form if possible, but @@ -629,7 +614,7 @@ public: return hasProperty(MCID::ConvertibleTo3Addr, Type); } - /// usesCustomInsertionHook - Return true if this instruction requires + /// Return true if this instruction requires /// custom insertion support when the DAG scheduler is inserting it into a /// machine basic block. If this is true for the instruction, it basically /// means that it is a pseudo instruction used at SelectionDAG time that is @@ -641,7 +626,7 @@ public: return hasProperty(MCID::UsesCustomInserter, Type); } - /// hasPostISelHook - Return true if this instruction requires *adjustment* + /// Return true if this instruction requires *adjustment* /// after instruction selection by calling a target hook. For example, this /// can be used to fill in ARM 's' optional operand depending on whether /// the conditional flag register is used. @@ -649,8 +634,8 @@ public: return hasProperty(MCID::HasPostISelHook, Type); } - /// isRematerializable - Returns true if this instruction is a candidate for - /// remat. This flag is deprecated, please don't use it anymore. If this + /// Returns true if this instruction is a candidate for remat. + /// This flag is deprecated, please don't use it anymore. If this /// flag is set, the isReallyTriviallyReMaterializable() method is called to /// verify the instruction is really rematable. bool isRematerializable(QueryType Type = AllInBundle) const { @@ -659,9 +644,9 @@ public: return hasProperty(MCID::Rematerializable, Type); } - /// isAsCheapAsAMove - Returns true if this instruction has the same cost (or - /// less) than a move instruction. This is useful during certain types of - /// optimizations (e.g., remat during two-address conversion or machine licm) + /// Returns true if this instruction has the same cost (or less) than a move + /// instruction. This is useful during certain types of optimizations + /// (e.g., remat during two-address conversion or machine licm) /// where we would like to remat or hoist the instruction, but not if it costs /// more than moving the instruction into the appropriate register. Note, we /// are not marking copies from and to the same register class with this flag. @@ -670,7 +655,7 @@ public: return hasProperty(MCID::CheapAsAMove, Type); } - /// hasExtraSrcRegAllocReq - Returns true if this instruction source operands + /// Returns true if this instruction source operands /// have special register allocation requirements that are not captured by the /// operand register classes. e.g. ARM::STRD's two source registers must be an /// even / odd pair, ARM::STM registers have to be in ascending order. @@ -680,7 +665,7 @@ public: return hasProperty(MCID::ExtraSrcRegAllocReq, Type); } - /// hasExtraDefRegAllocReq - Returns true if this instruction def operands + /// Returns true if this instruction def operands /// have special register allocation requirements that are not captured by the /// operand register classes. e.g. ARM::LDRD's two def registers must be an /// even / odd pair, ARM::LDM registers have to be in ascending order. @@ -698,7 +683,7 @@ public: IgnoreVRegDefs // Ignore virtual register definitions }; - /// isIdenticalTo - Return true if this instruction is identical to (same + /// Return true if this instruction is identical to (same /// opcode and same operands as) the specified instruction. bool isIdenticalTo(const MachineInstr *Other, MICheckType Check = CheckDefs) const; @@ -739,8 +724,7 @@ public: bool isEHLabel() const { return getOpcode() == TargetOpcode::EH_LABEL; } bool isGCLabel() const { return getOpcode() == TargetOpcode::GC_LABEL; } - /// isLabel - Returns true if the MachineInstr represents a label. - /// + /// Returns true if the MachineInstr represents a label. bool isLabel() const { return isEHLabel() || isGCLabel(); } bool isCFIInstruction() const { return getOpcode() == TargetOpcode::CFI_INSTRUCTION; @@ -789,19 +773,19 @@ public: return getOpcode() == TargetOpcode::EXTRACT_SUBREG; } - /// isCopyLike - Return true if the instruction behaves like a copy. + /// Return true if the instruction behaves like a copy. /// This does not include native copy instructions. bool isCopyLike() const { return isCopy() || isSubregToReg(); } - /// isIdentityCopy - Return true is the instruction is an identity copy. + /// Return true is the instruction is an identity copy. bool isIdentityCopy() const { return isCopy() && getOperand(0).getReg() == getOperand(1).getReg() && getOperand(0).getSubReg() == getOperand(1).getSubReg(); } - /// isTransient - Return true if this is a transient instruction that is + /// Return true if this is a transient instruction that is /// either very likely to be eliminated during register allocation (such as /// copy-like instructions), or if this instruction doesn't have an /// execution-time cost. @@ -832,8 +816,8 @@ public: /// skips, 0 for unbundled instructions. unsigned getBundleSize() const; - /// readsRegister - Return true if the MachineInstr reads the specified - /// register. If TargetRegisterInfo is passed, then it also checks if there + /// Return true if the MachineInstr reads the specified register. + /// If TargetRegisterInfo is passed, then it also checks if there /// is a read of a super-register. /// This does not count partial redefines of virtual registers as reads: /// %reg1024:6 = OP. @@ -842,30 +826,29 @@ public: return findRegisterUseOperandIdx(Reg, false, TRI) != -1; } - /// readsVirtualRegister - Return true if the MachineInstr reads the specified - /// virtual register. Take into account that a partial define is a + /// Return true if the MachineInstr reads the specified virtual register. + /// Take into account that a partial define is a /// read-modify-write operation. bool readsVirtualRegister(unsigned Reg) const { return readsWritesVirtualRegister(Reg).first; } - /// readsWritesVirtualRegister - Return a pair of bools (reads, writes) - /// indicating if this instruction reads or writes Reg. This also considers - /// partial defines. + /// Return a pair of bools (reads, writes) indicating if this instruction + /// reads or writes Reg. This also considers partial defines. /// If Ops is not null, all operand indices for Reg are added. std::pair<bool,bool> readsWritesVirtualRegister(unsigned Reg, SmallVectorImpl<unsigned> *Ops = nullptr) const; - /// killsRegister - Return true if the MachineInstr kills the specified - /// register. If TargetRegisterInfo is passed, then it also checks if there is + /// Return true if the MachineInstr kills the specified register. + /// If TargetRegisterInfo is passed, then it also checks if there is /// a kill of a super-register. bool killsRegister(unsigned Reg, const TargetRegisterInfo *TRI = nullptr) const { return findRegisterUseOperandIdx(Reg, true, TRI) != -1; } - /// definesRegister - Return true if the MachineInstr fully defines the - /// specified register. If TargetRegisterInfo is passed, then it also checks + /// Return true if the MachineInstr fully defines the specified register. + /// If TargetRegisterInfo is passed, then it also checks /// if there is a def of a super-register. /// NOTE: It's ignoring subreg indices on virtual registers. bool definesRegister(unsigned Reg, @@ -873,28 +856,28 @@ public: return findRegisterDefOperandIdx(Reg, false, false, TRI) != -1; } - /// modifiesRegister - Return true if the MachineInstr modifies (fully define - /// or partially define) the specified register. + /// Return true if the MachineInstr modifies (fully define or partially + /// define) the specified register. /// NOTE: It's ignoring subreg indices on virtual registers. bool modifiesRegister(unsigned Reg, const TargetRegisterInfo *TRI) const { return findRegisterDefOperandIdx(Reg, false, true, TRI) != -1; } - /// registerDefIsDead - Returns true if the register is dead in this machine - /// instruction. If TargetRegisterInfo is passed, then it also checks + /// Returns true if the register is dead in this machine instruction. + /// If TargetRegisterInfo is passed, then it also checks /// if there is a dead def of a super-register. bool registerDefIsDead(unsigned Reg, const TargetRegisterInfo *TRI = nullptr) const { return findRegisterDefOperandIdx(Reg, true, false, TRI) != -1; } - /// findRegisterUseOperandIdx() - Returns the operand index that is a use of - /// the specific register or -1 if it is not found. It further tightens - /// the search criteria to a use that kills the register if isKill is true. + /// Returns the operand index that is a use of the specific register or -1 + /// if it is not found. It further tightens the search criteria to a use + /// that kills the register if isKill is true. int findRegisterUseOperandIdx(unsigned Reg, bool isKill = false, const TargetRegisterInfo *TRI = nullptr) const; - /// findRegisterUseOperand - Wrapper for findRegisterUseOperandIdx, it returns + /// Wrapper for findRegisterUseOperandIdx, it returns /// a pointer to the MachineOperand rather than an index. MachineOperand *findRegisterUseOperand(unsigned Reg, bool isKill = false, const TargetRegisterInfo *TRI = nullptr) { @@ -902,17 +885,17 @@ public: return (Idx == -1) ? nullptr : &getOperand(Idx); } - /// findRegisterDefOperandIdx() - Returns the operand index that is a def of - /// the specified register or -1 if it is not found. If isDead is true, defs - /// that are not dead are skipped. If Overlap is true, then it also looks for - /// defs that merely overlap the specified register. If TargetRegisterInfo is - /// non-null, then it also checks if there is a def of a super-register. + /// Returns the operand index that is a def of the specified register or + /// -1 if it is not found. If isDead is true, defs that are not dead are + /// skipped. If Overlap is true, then it also looks for defs that merely + /// overlap the specified register. If TargetRegisterInfo is non-null, + /// then it also checks if there is a def of a super-register. /// This may also return a register mask operand when Overlap is true. int findRegisterDefOperandIdx(unsigned Reg, bool isDead = false, bool Overlap = false, const TargetRegisterInfo *TRI = nullptr) const; - /// findRegisterDefOperand - Wrapper for findRegisterDefOperandIdx, it returns + /// Wrapper for findRegisterDefOperandIdx, it returns /// a pointer to the MachineOperand rather than an index. MachineOperand *findRegisterDefOperand(unsigned Reg, bool isDead = false, const TargetRegisterInfo *TRI = nullptr) { @@ -920,12 +903,12 @@ public: return (Idx == -1) ? nullptr : &getOperand(Idx); } - /// findFirstPredOperandIdx() - Find the index of the first operand in the + /// Find the index of the first operand in the /// operand list that is used to represent the predicate. It returns -1 if /// none is found. int findFirstPredOperandIdx() const; - /// findInlineAsmFlagIdx() - Find the index of the flag word operand that + /// Find the index of the flag word operand that /// corresponds to operand OpIdx on an inline asm instruction. Returns -1 if /// getOperand(OpIdx) does not belong to an inline asm operand group. /// @@ -937,9 +920,9 @@ public: /// int findInlineAsmFlagIdx(unsigned OpIdx, unsigned *GroupNo = nullptr) const; - /// getRegClassConstraint - Compute the static register class constraint for - /// operand OpIdx. For normal instructions, this is derived from the - /// MCInstrDesc. For inline assembly it is derived from the flag words. + /// Compute the static register class constraint for operand OpIdx. + /// For normal instructions, this is derived from the MCInstrDesc. + /// For inline assembly it is derived from the flag words. /// /// Returns NULL if the static register classs constraint cannot be /// determined. @@ -980,20 +963,20 @@ public: const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const; - /// tieOperands - Add a tie between the register operands at DefIdx and - /// UseIdx. The tie will cause the register allocator to ensure that the two + /// Add a tie between the register operands at DefIdx and UseIdx. + /// The tie will cause the register allocator to ensure that the two /// operands are assigned the same physical register. /// /// Tied operands are managed automatically for explicit operands in the /// MCInstrDesc. This method is for exceptional cases like inline asm. void tieOperands(unsigned DefIdx, unsigned UseIdx); - /// findTiedOperandIdx - Given the index of a tied register operand, find the + /// Given the index of a tied register operand, find the /// operand it is tied to. Defs are tied to uses and vice versa. Returns the /// index of the tied operand which must exist. unsigned findTiedOperandIdx(unsigned OpIdx) const; - /// isRegTiedToUseOperand - Given the index of a register def operand, + /// Given the index of a register def operand, /// check if the register def is tied to a source operand, due to either /// two-address elimination or inline assembly constraints. Returns the /// first tied use operand index by reference if UseOpIdx is not null. @@ -1007,9 +990,9 @@ public: return true; } - /// isRegTiedToDefOperand - Return true if the use operand of the specified - /// index is tied to a def operand. It also returns the def operand index by - /// reference if DefOpIdx is not null. + /// Return true if the use operand of the specified index is tied to a def + /// operand. It also returns the def operand index by reference if DefOpIdx + /// is not null. bool isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx = nullptr) const { const MachineOperand &MO = getOperand(UseOpIdx); @@ -1020,16 +1003,15 @@ public: return true; } - /// clearKillInfo - Clears kill flags on all operands. - /// + /// Clears kill flags on all operands. void clearKillInfo(); - /// substituteRegister - Replace all occurrences of FromReg with ToReg:SubIdx, + /// Replace all occurrences of FromReg with ToReg:SubIdx, /// properly composing subreg indices where necessary. void substituteRegister(unsigned FromReg, unsigned ToReg, unsigned SubIdx, const TargetRegisterInfo &RegInfo); - /// addRegisterKilled - We have determined MI kills a register. Look for the + /// We have determined MI kills a register. Look for the /// operand that uses it and mark it as IsKill. If AddIfNotFound is true, /// add a implicit operand if it's not found. Returns true if the operand /// exists / is added. @@ -1037,23 +1019,31 @@ public: const TargetRegisterInfo *RegInfo, bool AddIfNotFound = false); - /// clearRegisterKills - Clear all kill flags affecting Reg. If RegInfo is + /// Clear all kill flags affecting Reg. If RegInfo is /// provided, this includes super-register kills. void clearRegisterKills(unsigned Reg, const TargetRegisterInfo *RegInfo); - /// addRegisterDead - We have determined MI defined a register without a use. + /// We have determined MI defined a register without a use. /// Look for the operand that defines it and mark it as IsDead. If /// AddIfNotFound is true, add a implicit operand if it's not found. Returns /// true if the operand exists / is added. bool addRegisterDead(unsigned Reg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound = false); - /// addRegisterDefined - We have determined MI defines a register. Make sure - /// there is an operand defining Reg. + /// Clear all dead flags on operands defining register @p Reg. + void clearRegisterDeads(unsigned Reg); + + /// Mark all subregister defs of register @p Reg with the undef flag. + /// This function is used when we determined to have a subregister def in an + /// otherwise undefined super register. + void addRegisterDefReadUndef(unsigned Reg); + + /// We have determined MI defines a register. Make sure there is an operand + /// defining Reg. void addRegisterDefined(unsigned Reg, const TargetRegisterInfo *RegInfo = nullptr); - /// setPhysRegsDeadExcept - Mark every physreg used by this instruction as + /// Mark every physreg used by this instruction as /// dead except those in the UsedRegs list. /// /// On instructions with register mask operands, also add implicit-def @@ -1061,32 +1051,30 @@ public: void setPhysRegsDeadExcept(ArrayRef<unsigned> UsedRegs, const TargetRegisterInfo &TRI); - /// isSafeToMove - Return true if it is safe to move this instruction. If + /// Return true if it is safe to move this instruction. If /// SawStore is set to true, it means that there is a store (or call) between /// the instruction's location and its intended destination. - bool isSafeToMove(const TargetInstrInfo *TII, AliasAnalysis *AA, - bool &SawStore) const; + bool isSafeToMove(AliasAnalysis *AA, bool &SawStore) const; - /// hasOrderedMemoryRef - Return true if this instruction may have an ordered + /// Return true if this instruction may have an ordered /// or volatile memory reference, or if the information describing the memory /// reference is not available. Return false if it is known to have no /// ordered or volatile memory references. bool hasOrderedMemoryRef() const; - /// isInvariantLoad - Return true if this instruction is loading from a + /// Return true if this instruction is loading from a /// location whose value is invariant across the function. For example, /// loading a value from the constant pool or from the argument area of /// a function if it does not change. This should only return true of *all* /// loads the instruction does are invariant (if it does multiple loads). bool isInvariantLoad(AliasAnalysis *AA) const; - /// isConstantValuePHI - If the specified instruction is a PHI that always - /// merges together the same virtual register, return the register, otherwise - /// return 0. + /// If the specified instruction is a PHI that always merges together the + /// same virtual register, return the register, otherwise return 0. unsigned isConstantValuePHI() const; - /// hasUnmodeledSideEffects - Return true if this instruction has side - /// effects that are not modeled by mayLoad / mayStore, etc. + /// Return true if this instruction has side effects that are not modeled + /// by mayLoad / mayStore, etc. /// For all instructions, the property is encoded in MCInstrDesc::Flags /// (see MCInstrDesc::hasUnmodeledSideEffects(). The only exception is /// INLINEASM instruction, in which case the side effect property is encoded @@ -1094,19 +1082,17 @@ public: /// bool hasUnmodeledSideEffects() const; - /// allDefsAreDead - Return true if all the defs of this instruction are dead. - /// + /// Return true if all the defs of this instruction are dead. bool allDefsAreDead() const; - /// copyImplicitOps - Copy implicit register operands from specified + /// Copy implicit register operands from specified /// instruction to this instruction. void copyImplicitOps(MachineFunction &MF, const MachineInstr *MI); // // Debugging support // - void print(raw_ostream &OS, const TargetMachine *TM = nullptr, - bool SkipOpers = false) const; + void print(raw_ostream &OS, bool SkipOpers = false) const; void dump() const; //===--------------------------------------------------------------------===// @@ -1131,44 +1117,41 @@ public: /// preferred. void addOperand(const MachineOperand &Op); - /// setDesc - Replace the instruction descriptor (thus opcode) of + /// Replace the instruction descriptor (thus opcode) of /// the current instruction with a new one. - /// void setDesc(const MCInstrDesc &tid) { MCID = &tid; } - /// setDebugLoc - Replace current source information with new such. + /// Replace current source information with new such. /// Avoid using this, the constructor argument is preferable. - /// - void setDebugLoc(const DebugLoc dl) { - debugLoc = dl; + void setDebugLoc(DebugLoc dl) { + debugLoc = std::move(dl); assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); } - /// RemoveOperand - Erase an operand from an instruction, leaving it with one + /// Erase an operand from an instruction, leaving it with one /// fewer operand than it started with. - /// void RemoveOperand(unsigned i); - /// addMemOperand - Add a MachineMemOperand to the machine instruction. + /// Add a MachineMemOperand to the machine instruction. /// This function should be used only occasionally. The setMemRefs function /// is the primary method for setting up a MachineInstr's MemRefs list. void addMemOperand(MachineFunction &MF, MachineMemOperand *MO); - /// setMemRefs - Assign this MachineInstr's memory reference descriptor - /// list. This does not transfer ownership. + /// Assign this MachineInstr's memory reference descriptor list. + /// This does not transfer ownership. void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { MemRefs = NewMemRefs; NumMemRefs = uint8_t(NewMemRefsEnd - NewMemRefs); assert(NumMemRefs == NewMemRefsEnd - NewMemRefs && "Too many memrefs"); } -private: - /// getRegInfo - If this instruction is embedded into a MachineFunction, - /// return the MachineRegisterInfo object for the current function, otherwise - /// return null. - MachineRegisterInfo *getRegInfo(); + /// Clear this MachineInstr's memory reference descriptor list. + void clearMemRefs() { + MemRefs = nullptr; + NumMemRefs = 0; + } - /// untieRegOperand - Break any tie involving OpIdx. + /// Break any tie involving OpIdx. void untieRegOperand(unsigned OpIdx) { MachineOperand &MO = getOperand(OpIdx); if (MO.isReg() && MO.isTied()) { @@ -1177,22 +1160,27 @@ private: } } - /// addImplicitDefUseOperands - Add all implicit def and use operands to - /// this instruction. + +private: + /// If this instruction is embedded into a MachineFunction, return the + /// MachineRegisterInfo object for the current function, otherwise + /// return null. + MachineRegisterInfo *getRegInfo(); + + /// Add all implicit def and use operands to this instruction. void addImplicitDefUseOperands(MachineFunction &MF); - /// RemoveRegOperandsFromUseLists - Unlink all of the register operands in - /// this instruction from their respective use lists. This requires that the - /// operands already be on their use lists. + /// Unlink all of the register operands in this instruction from their + /// respective use lists. This requires that the operands already be on their + /// use lists. void RemoveRegOperandsFromUseLists(MachineRegisterInfo&); - /// AddRegOperandsToUseLists - Add all of the register operands in - /// this instruction from their respective use lists. This requires that the - /// operands not be on their use lists yet. + /// Add all of the register operands in this instruction from their + /// respective use lists. This requires that the operands not be on their + /// use lists yet. void AddRegOperandsToUseLists(MachineRegisterInfo&); - /// hasPropertyInBundle - Slow path for hasProperty when we're dealing with a - /// bundle. + /// Slow path for hasProperty when we're dealing with a bundle. bool hasPropertyInBundle(unsigned Mask, QueryType Type) const; /// \brief Implements the logic of getRegClassConstraintEffectForVReg for the @@ -1203,8 +1191,8 @@ private: const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const; }; -/// MachineInstrExpressionTrait - Special DenseMapInfo traits to compare -/// MachineInstr* by *value* of the instruction rather than by pointer value. +/// Special DenseMapInfo traits to compare MachineInstr* by *value* of the +/// instruction rather than by pointer value. /// The hashing and equality testing functions ignore definitions so this is /// useful for CSE, etc. struct MachineInstrExpressionTrait : DenseMapInfo<MachineInstr*> { diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 8859b6a019ea..47397c6d6743 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -174,8 +174,9 @@ public: const MachineInstrBuilder &addMetadata(const MDNode *MD) const { MI->addOperand(*MF, MachineOperand::CreateMetadata(MD)); - assert((MI->isDebugValue() ? MI->getDebugVariable().Verify() : true) && - "first MDNode argument of a DBG_VALUE not a DIVariable"); + assert((MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable()) + : true) && + "first MDNode argument of a DBG_VALUE not a variable"); return *this; } @@ -355,8 +356,10 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID, bool IsIndirect, unsigned Reg, unsigned Offset, const MDNode *Variable, const MDNode *Expr) { - assert(DIVariable(Variable).Verify() && "not a DIVariable"); - assert(DIExpression(Expr).Verify() && "not a DIExpression"); + assert(isa<DILocalVariable>(Variable) && "not a variable"); + assert(cast<DIExpression>(Expr)->isValid() && "not an expression"); + assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) && + "Expected inlined-at fields to agree"); if (IsIndirect) return BuildMI(MF, DL, MCID) .addReg(Reg, RegState::Debug) @@ -382,8 +385,8 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, const MCInstrDesc &MCID, bool IsIndirect, unsigned Reg, unsigned Offset, const MDNode *Variable, const MDNode *Expr) { - assert(DIVariable(Variable).Verify() && "not a DIVariable"); - assert(DIExpression(Expr).Verify() && "not a DIExpression"); + assert(isa<DILocalVariable>(Variable) && "not a variable"); + assert(cast<DIExpression>(Expr)->isValid() && "not an expression"); MachineFunction &MF = *BB.getParent(); MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, Variable, Expr); diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index 4fbd46b6fb57..f7bcf45d93c5 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -74,8 +74,8 @@ class MachineLoopInfo : public MachineFunctionPass { LoopInfoBase<MachineBasicBlock, MachineLoop> LI; friend class LoopBase<MachineBasicBlock, MachineLoop>; - void operator=(const MachineLoopInfo &) LLVM_DELETED_FUNCTION; - MachineLoopInfo(const MachineLoopInfo &) LLVM_DELETED_FUNCTION; + void operator=(const MachineLoopInfo &) = delete; + MachineLoopInfo(const MachineLoopInfo &) = delete; public: static char ID; // Pass identification, replacement for typeid diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h index eb5086cbe5a5..a16c294a0749 100644 --- a/include/llvm/CodeGen/MachineMemOperand.h +++ b/include/llvm/CodeGen/MachineMemOperand.h @@ -199,6 +199,24 @@ public: /// Profile - Gather unique data for the object. /// void Profile(FoldingSetNodeID &ID) const; + + friend bool operator==(const MachineMemOperand &LHS, + const MachineMemOperand &RHS) { + return LHS.getValue() == RHS.getValue() && + LHS.getPseudoValue() == RHS.getPseudoValue() && + LHS.getSize() == RHS.getSize() && + LHS.getOffset() == RHS.getOffset() && + LHS.getFlags() == RHS.getFlags() && + LHS.getAAInfo() == RHS.getAAInfo() && + LHS.getRanges() == RHS.getRanges() && + LHS.getAlignment() == RHS.getAlignment() && + LHS.getAddrSpace() == RHS.getAddrSpace(); + } + + friend bool operator!=(const MachineMemOperand &LHS, + const MachineMemOperand &RHS) { + return !(LHS == RHS); + } }; raw_ostream &operator<<(raw_ostream &OS, const MachineMemOperand &MRO); diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 584ce65c9d17..ce45c1659153 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -35,6 +35,7 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/LibCallSemantics.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" @@ -50,6 +51,7 @@ namespace llvm { // Forward declarations. class Constant; class GlobalVariable; +class BlockAddress; class MDNode; class MMIAddrLabelMap; class MachineBasicBlock; @@ -57,21 +59,33 @@ class MachineFunction; class Module; class PointerType; class StructType; +struct WinEHFuncInfo; + +struct SEHHandler { + // Filter or finally function. Null indicates a catch-all. + const Function *FilterOrFinally; + + // Address of block to recover at. Null for a finally handler. + const BlockAddress *RecoverBA; +}; //===----------------------------------------------------------------------===// /// LandingPadInfo - This structure is used to retain landing pad info for /// the current function. /// struct LandingPadInfo { - MachineBasicBlock *LandingPadBlock; // Landing pad block. - SmallVector<MCSymbol*, 1> BeginLabels; // Labels prior to invoke. - SmallVector<MCSymbol*, 1> EndLabels; // Labels after invoke. - MCSymbol *LandingPadLabel; // Label at beginning of landing pad. - const Function *Personality; // Personality function. - std::vector<int> TypeIds; // List of type ids (filters negative) + MachineBasicBlock *LandingPadBlock; // Landing pad block. + SmallVector<MCSymbol *, 1> BeginLabels; // Labels prior to invoke. + SmallVector<MCSymbol *, 1> EndLabels; // Labels after invoke. + SmallVector<SEHHandler, 1> SEHHandlers; // SEH handlers active at this lpad. + MCSymbol *LandingPadLabel; // Label at beginning of landing pad. + const Function *Personality; // Personality function. + std::vector<int> TypeIds; // List of type ids (filters negative). + int WinEHState; // WinEH specific state number. explicit LandingPadInfo(MachineBasicBlock *MBB) - : LandingPadBlock(MBB), LandingPadLabel(nullptr), Personality(nullptr) {} + : LandingPadBlock(MBB), LandingPadLabel(nullptr), Personality(nullptr), + WinEHState(-1) {} }; //===----------------------------------------------------------------------===// @@ -86,7 +100,10 @@ public: virtual ~MachineModuleInfoImpl(); typedef std::vector<std::pair<MCSymbol*, StubValueTy> > SymbolListTy; protected: - static SymbolListTy GetSortedStubs(const DenseMap<MCSymbol*, StubValueTy>&); + + /// Return the entries from a DenseMap in a deterministic sorted orer. + /// Clears the map. + static SymbolListTy getSortedStubs(DenseMap<MCSymbol*, StubValueTy>&); }; //===----------------------------------------------------------------------===// @@ -168,16 +185,21 @@ class MachineModuleInfo : public ImmutablePass { /// details. bool UsesMorestackAddr; + EHPersonality PersonalityTypeCache; + + DenseMap<const Function *, std::unique_ptr<WinEHFuncInfo>> FuncInfoMap; + public: static char ID; // Pass identification, replacement for typeid struct VariableDbgInfo { - TrackingMDNodeRef Var; - TrackingMDNodeRef Expr; + const DILocalVariable *Var; + const DIExpression *Expr; unsigned Slot; - DebugLoc Loc; + const DILocation *Loc; - VariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, DebugLoc Loc) + VariableDbgInfo(const DILocalVariable *Var, const DIExpression *Expr, + unsigned Slot, const DILocation *Loc) : Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {} }; typedef SmallVector<VariableDbgInfo, 4> VariableDbgInfoMapTy; @@ -187,7 +209,7 @@ public: // Real constructor. MachineModuleInfo(const MCAsmInfo &MAI, const MCRegisterInfo &MRI, const MCObjectFileInfo *MOFI); - ~MachineModuleInfo(); + ~MachineModuleInfo() override; // Initialization and Finalization bool doInitialization(Module &) override; @@ -203,6 +225,12 @@ public: void setModule(const Module *M) { TheModule = M; } const Module *getModule() const { return TheModule; } + const Function *getWinEHParent(const Function *F) const; + WinEHFuncInfo &getWinEHFuncInfo(const Function *F); + bool hasWinEHFuncInfo(const Function *F) const { + return FuncInfoMap.count(getWinEHParent(F)) > 0; + } + /// getInfo - Keep track of various per-function pieces of information for /// backends that would like to do so. /// @@ -300,6 +328,8 @@ public: void addPersonality(MachineBasicBlock *LandingPad, const Function *Personality); + void addWinEHState(MachineBasicBlock *LandingPad, int State); + /// getPersonalityIndex - Get index of the current personality function inside /// Personalitites array unsigned getPersonalityIndex() const; @@ -330,6 +360,12 @@ public: /// void addCleanup(MachineBasicBlock *LandingPad); + void addSEHCatchHandler(MachineBasicBlock *LandingPad, const Function *Filter, + const BlockAddress *RecoverLabel); + + void addSEHCleanupHandler(MachineBasicBlock *LandingPad, + const Function *Cleanup); + /// getTypeIDFor - Return the type id for the specified typeinfo. This is /// function wide. unsigned getTypeIDFor(const GlobalValue *TI); @@ -407,10 +443,13 @@ public: /// of one is required to emit exception handling info. const Function *getPersonality() const; + /// Classify the personality function amongst known EH styles. + EHPersonality getPersonalityType(); + /// setVariableDbgInfo - Collect information used to emit debugging /// information of a variable. - void setVariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, - DebugLoc Loc) { + void setVariableDbgInfo(const DILocalVariable *Var, const DIExpression *Expr, + unsigned Slot, const DILocation *Loc) { VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc); } diff --git a/include/llvm/CodeGen/MachineModuleInfoImpls.h b/include/llvm/CodeGen/MachineModuleInfoImpls.h index 7afc7eb6b357..a67f9b5666b1 100644 --- a/include/llvm/CodeGen/MachineModuleInfoImpls.h +++ b/include/llvm/CodeGen/MachineModuleInfoImpls.h @@ -58,14 +58,14 @@ namespace llvm { } /// Accessor methods to return the set of stubs in sorted order. - SymbolListTy GetFnStubList() const { - return GetSortedStubs(FnStubs); + SymbolListTy GetFnStubList() { + return getSortedStubs(FnStubs); } - SymbolListTy GetGVStubList() const { - return GetSortedStubs(GVStubs); + SymbolListTy GetGVStubList() { + return getSortedStubs(GVStubs); } - SymbolListTy GetHiddenGVStubList() const { - return GetSortedStubs(HiddenGVStubs); + SymbolListTy GetHiddenGVStubList() { + return getSortedStubs(HiddenGVStubs); } }; @@ -87,8 +87,8 @@ namespace llvm { /// Accessor methods to return the set of stubs in sorted order. - SymbolListTy GetGVStubList() const { - return GetSortedStubs(GVStubs); + SymbolListTy GetGVStubList() { + return getSortedStubs(GVStubs); } }; diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index eed1e575f93b..ddffdcaf1e4d 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -65,7 +65,7 @@ public: private: /// OpKind - Specify what kind of operand this is. This discriminates the /// union. - MachineOperandType OpKind; + MachineOperandType OpKind : 8; /// Subregister number for MO_Register. A value of 0 indicates the /// MO_Register has no subReg. @@ -217,7 +217,7 @@ public: /// void clearParent() { ParentMI = nullptr; } - void print(raw_ostream &os, const TargetMachine *TM = nullptr) const; + void print(raw_ostream &os, const TargetRegisterInfo *TRI = nullptr) const; //===--------------------------------------------------------------------===// // Accessors that tell you what kind of MachineOperand you're looking at. @@ -554,6 +554,12 @@ public: /// already, the setFPImm method should be used. void ChangeToFPImmediate(const ConstantFP *FPImm); + /// ChangeToES - Replace this operand with a new external symbol operand. + void ChangeToES(const char *SymName, unsigned char TargetFlags = 0); + + /// ChangeToMCSymbol - Replace this operand with a new MC symbol operand. + void ChangeToMCSymbol(MCSymbol *Sym); + /// ChangeToRegister - Replace this operand with a new register operand of /// the specified value. If an operand is known to be an register already, /// the setReg method should be used. diff --git a/include/llvm/CodeGen/MachinePassRegistry.h b/include/llvm/CodeGen/MachinePassRegistry.h index c962e687243e..6731983c5874 100644 --- a/include/llvm/CodeGen/MachinePassRegistry.h +++ b/include/llvm/CodeGen/MachinePassRegistry.h @@ -122,11 +122,12 @@ template<class RegistryClass> class RegisterPassParser : public MachinePassRegistryListener, public cl::parser<typename RegistryClass::FunctionPassCtor> { public: - RegisterPassParser() {} - ~RegisterPassParser() { RegistryClass::setListener(nullptr); } + RegisterPassParser(cl::Option &O) + : cl::parser<typename RegistryClass::FunctionPassCtor>(O) {} + ~RegisterPassParser() override { RegistryClass::setListener(nullptr); } - void initialize(cl::Option &O) { - cl::parser<typename RegistryClass::FunctionPassCtor>::initialize(O); + void initialize() { + cl::parser<typename RegistryClass::FunctionPassCtor>::initialize(); // Add existing passes to option. for (RegistryClass *Node = RegistryClass::getList(); diff --git a/include/llvm/CodeGen/MachinePostDominators.h b/include/llvm/CodeGen/MachinePostDominators.h index aab5c407629f..70bdb191ad34 100644 --- a/include/llvm/CodeGen/MachinePostDominators.h +++ b/include/llvm/CodeGen/MachinePostDominators.h @@ -33,7 +33,7 @@ public: MachinePostDominatorTree(); - ~MachinePostDominatorTree(); + ~MachinePostDominatorTree() override; FunctionPass *createMachinePostDominatorTreePass(); diff --git a/include/llvm/CodeGen/MachineRegionInfo.h b/include/llvm/CodeGen/MachineRegionInfo.h index 43499dba71c0..cf49c297c288 100644 --- a/include/llvm/CodeGen/MachineRegionInfo.h +++ b/include/llvm/CodeGen/MachineRegionInfo.h @@ -57,8 +57,6 @@ public: } - ~MachineRegionNode() { } - bool operator==(const MachineRegion &RN) const { return this == reinterpret_cast<const MachineRegionNode*>(&RN); } @@ -80,7 +78,7 @@ class MachineRegionInfo : public RegionInfoBase<RegionTraits<MachineFunction>> { public: explicit MachineRegionInfo(); - virtual ~MachineRegionInfo(); + ~MachineRegionInfo() override; // updateStatistics - Update statistic about created regions. void updateStatistics(MachineRegion *R) final; @@ -98,7 +96,7 @@ public: static char ID; explicit MachineRegionInfoPass(); - ~MachineRegionInfoPass(); + ~MachineRegionInfoPass() override; MachineRegionInfo &getRegionInfo() { return RI; diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index caa48a5cf0cf..e5b837aeea28 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -123,8 +123,8 @@ private: /// second element. std::vector<std::pair<unsigned, unsigned> > LiveIns; - MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; - void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; + MachineRegisterInfo(const MachineRegisterInfo&) = delete; + void operator=(const MachineRegisterInfo&) = delete; public: explicit MachineRegisterInfo(const MachineFunction *MF); @@ -182,7 +182,18 @@ public: /// information. void invalidateLiveness() { TracksLiveness = false; } - bool tracksSubRegLiveness() const { return TracksSubRegLiveness; } + /// Returns true if liveness for register class @p RC should be tracked at + /// the subregister level. + bool shouldTrackSubRegLiveness(const TargetRegisterClass &RC) const { + return subRegLivenessEnabled() && RC.HasDisjunctSubRegs; + } + bool shouldTrackSubRegLiveness(unsigned VReg) const { + assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Must pass a VReg"); + return shouldTrackSubRegLiveness(*getRegClass(VReg)); + } + bool subRegLivenessEnabled() const { + return TracksSubRegLiveness; + } void enableSubRegLiveness(bool Enable = true) { TracksSubRegLiveness = Enable; @@ -593,7 +604,7 @@ public: /// virtual register, for example after removing instructions or splitting /// the live range. /// - bool recomputeRegClass(unsigned Reg, const TargetMachine&); + bool recomputeRegClass(unsigned Reg); /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. @@ -609,22 +620,25 @@ public: /// setRegAllocationHint - Specify a register allocation hint for the /// specified virtual register. - void setRegAllocationHint(unsigned Reg, unsigned Type, unsigned PrefReg) { - RegAllocHints[Reg].first = Type; - RegAllocHints[Reg].second = PrefReg; + void setRegAllocationHint(unsigned VReg, unsigned Type, unsigned PrefReg) { + assert(TargetRegisterInfo::isVirtualRegister(VReg)); + RegAllocHints[VReg].first = Type; + RegAllocHints[VReg].second = PrefReg; } /// getRegAllocationHint - Return the register allocation hint for the /// specified virtual register. std::pair<unsigned, unsigned> - getRegAllocationHint(unsigned Reg) const { - return RegAllocHints[Reg]; + getRegAllocationHint(unsigned VReg) const { + assert(TargetRegisterInfo::isVirtualRegister(VReg)); + return RegAllocHints[VReg]; } /// getSimpleHint - Return the preferred register allocation hint, or 0 if a /// standard simple hint (Type == 0) is not set. - unsigned getSimpleHint(unsigned Reg) const { - std::pair<unsigned, unsigned> Hint = getRegAllocationHint(Reg); + unsigned getSimpleHint(unsigned VReg) const { + assert(TargetRegisterInfo::isVirtualRegister(VReg)); + std::pair<unsigned, unsigned> Hint = getRegAllocationHint(VReg); return Hint.first ? 0 : Hint.second; } @@ -829,7 +843,6 @@ public: typedef std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t>::pointer pointer; - defusechain_iterator(const defusechain_iterator &I) : Op(I.Op) {} defusechain_iterator() : Op(nullptr) {} bool operator==(const defusechain_iterator &x) const { @@ -932,7 +945,6 @@ public: typedef std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t>::pointer pointer; - defusechain_instr_iterator(const defusechain_instr_iterator &I) : Op(I.Op){} defusechain_instr_iterator() : Op(nullptr) {} bool operator==(const defusechain_instr_iterator &x) const { diff --git a/include/llvm/CodeGen/MachineSSAUpdater.h b/include/llvm/CodeGen/MachineSSAUpdater.h index 486a26e92714..5f988ad86320 100644 --- a/include/llvm/CodeGen/MachineSSAUpdater.h +++ b/include/llvm/CodeGen/MachineSSAUpdater.h @@ -107,8 +107,8 @@ public: private: unsigned GetValueAtEndOfBlockInternal(MachineBasicBlock *BB); - void operator=(const MachineSSAUpdater&) LLVM_DELETED_FUNCTION; - MachineSSAUpdater(const MachineSSAUpdater&) LLVM_DELETED_FUNCTION; + void operator=(const MachineSSAUpdater&) = delete; + MachineSSAUpdater(const MachineSSAUpdater&) = delete; }; } // End llvm namespace diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index a31940161ca5..e80e14e5ccf7 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -385,7 +385,7 @@ public: ShouldTrackPressure(false), RPTracker(RegPressure), TopRPTracker(TopPressure), BotRPTracker(BotPressure) {} - virtual ~ScheduleDAGMILive(); + ~ScheduleDAGMILive() override; /// Return true if this DAG supports VReg liveness and RegPressure. bool hasVRegLiveness() const override { return true; } @@ -909,7 +909,7 @@ public: PostGenericScheduler(const MachineSchedContext *C): GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ") {} - virtual ~PostGenericScheduler() {} + ~PostGenericScheduler() override {} void initPolicy(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h index e3fbfe89c203..a728df354677 100644 --- a/include/llvm/CodeGen/MachineValueType.h +++ b/include/llvm/CodeGen/MachineValueType.h @@ -26,7 +26,7 @@ namespace llvm { /// MVT - Machine Value Type. Every type that is supported natively by some /// processor targeted by LLVM occurs here. This means that any legal value /// type can be represented by an MVT. - class MVT { +class MVT { public: enum SimpleValueType { // INVALID_SIMPLE_VALUE_TYPE - Simple value types less than zero are @@ -86,22 +86,23 @@ namespace llvm { v4i64 = 39, // 4 x i64 v8i64 = 40, // 8 x i64 v16i64 = 41, // 16 x i64 - + v1i128 = 42, // 1 x i128 + FIRST_INTEGER_VECTOR_VALUETYPE = v2i1, - LAST_INTEGER_VECTOR_VALUETYPE = v16i64, - - v2f16 = 42, // 2 x f16 - v4f16 = 43, // 4 x f16 - v8f16 = 44, // 8 x f16 - v1f32 = 45, // 1 x f32 - v2f32 = 46, // 2 x f32 - v4f32 = 47, // 4 x f32 - v8f32 = 48, // 8 x f32 - v16f32 = 49, // 16 x f32 - v1f64 = 50, // 1 x f64 - v2f64 = 51, // 2 x f64 - v4f64 = 52, // 4 x f64 - v8f64 = 53, // 8 x f64 + LAST_INTEGER_VECTOR_VALUETYPE = v1i128, + + v2f16 = 43, // 2 x f16 + v4f16 = 44, // 4 x f16 + v8f16 = 45, // 8 x f16 + v1f32 = 46, // 1 x f32 + v2f32 = 47, // 2 x f32 + v4f32 = 48, // 4 x f32 + v8f32 = 49, // 8 x f32 + v16f32 = 50, // 16 x f32 + v1f64 = 51, // 1 x f64 + v2f64 = 52, // 2 x f64 + v4f64 = 53, // 4 x f64 + v8f64 = 54, // 8 x f64 FIRST_FP_VECTOR_VALUETYPE = v2f16, LAST_FP_VECTOR_VALUETYPE = v8f64, @@ -109,18 +110,18 @@ namespace llvm { FIRST_VECTOR_VALUETYPE = v2i1, LAST_VECTOR_VALUETYPE = v8f64, - x86mmx = 54, // This is an X86 MMX value + x86mmx = 55, // This is an X86 MMX value - Glue = 55, // This glues nodes together during pre-RA sched + Glue = 56, // This glues nodes together during pre-RA sched - isVoid = 56, // This has no value + isVoid = 57, // This has no value - Untyped = 57, // This value takes a register, but has + Untyped = 58, // This value takes a register, but has // unspecified type. The register class // will be determined by the opcode. FIRST_VALUETYPE = 0, // This is always the beginning of the list. - LAST_VALUETYPE = 58, // This always remains at the end of the list. + LAST_VALUETYPE = 59, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors @@ -152,13 +153,17 @@ namespace llvm { // iPTR - An int value the size of the pointer of the current // target. This should only be used internal to tblgen! - iPTR = 255 + iPTR = 255, + + // Any - Any type. This is used for intrinsics that have overloadings. + // This is only for tblgen's consumption! + Any = 256 }; SimpleValueType SimpleTy; - MVT() : SimpleTy((SimpleValueType)(INVALID_SIMPLE_VALUE_TYPE)) {} - MVT(SimpleValueType SVT) : SimpleTy(SVT) { } + LLVM_CONSTEXPR MVT() : SimpleTy(INVALID_SIMPLE_VALUE_TYPE) {} + LLVM_CONSTEXPR MVT(SimpleValueType SVT) : SimpleTy(SVT) { } bool operator>(const MVT& S) const { return SimpleTy > S.SimpleTy; } bool operator<(const MVT& S) const { return SimpleTy < S.SimpleTy; } @@ -218,10 +223,10 @@ namespace llvm { /// is128BitVector - Return true if this is a 128-bit vector type. bool is128BitVector() const { - return (SimpleTy == MVT::v16i8 || SimpleTy == MVT::v8i16 || - SimpleTy == MVT::v4i32 || SimpleTy == MVT::v2i64 || - SimpleTy == MVT::v8f16 || SimpleTy == MVT::v4f32 || - SimpleTy == MVT::v2f64); + return (SimpleTy == MVT::v16i8 || SimpleTy == MVT::v8i16 || + SimpleTy == MVT::v4i32 || SimpleTy == MVT::v2i64 || + SimpleTy == MVT::v1i128 || SimpleTy == MVT::v8f16 || + SimpleTy == MVT::v4f32 || SimpleTy == MVT::v2f64); } /// is256BitVector - Return true if this is a 256-bit vector type. @@ -245,7 +250,8 @@ namespace llvm { /// isOverloaded - Return true if this is an overloaded type for TableGen. bool isOverloaded() const { - return (SimpleTy==MVT::iAny || SimpleTy==MVT::fAny || + return (SimpleTy==MVT::Any || + SimpleTy==MVT::iAny || SimpleTy==MVT::fAny || SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny); } @@ -305,6 +311,7 @@ namespace llvm { case v4i64: case v8i64: case v16i64: return i64; + case v1i128: return i128; case v2f16: case v4f16: case v8f16: return f16; @@ -363,6 +370,7 @@ namespace llvm { case v1i16: case v1i32: case v1i64: + case v1i128: case v1f32: case v1f64: return 1; } @@ -380,6 +388,7 @@ namespace llvm { case iAny: case fAny: case vAny: + case Any: llvm_unreachable("Value type is overloaded."); case Metadata: llvm_unreachable("Value type is metadata."); @@ -421,6 +430,7 @@ namespace llvm { case v8i16: case v4i32: case v2i64: + case v1i128: case v8f16: case v4f32: case v2f64: return 128; @@ -556,6 +566,9 @@ namespace llvm { if (NumElements == 8) return MVT::v8i64; if (NumElements == 16) return MVT::v16i64; break; + case MVT::i128: + if (NumElements == 1) return MVT::v1i128; + break; case MVT::f16: if (NumElements == 2) return MVT::v2f16; if (NumElements == 4) return MVT::v4f16; diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h index 4dc5674ae134..f73383ed1000 100644 --- a/include/llvm/CodeGen/PBQP/Graph.h +++ b/include/llvm/CodeGen/PBQP/Graph.h @@ -21,6 +21,7 @@ #include <list> #include <map> #include <set> +#include <vector> namespace llvm { namespace PBQP { @@ -507,14 +508,14 @@ namespace PBQP { return getNode(NId).getAdjEdgeIds().size(); } - /// @brief Set an edge's cost matrix. + /// @brief Update an edge's cost matrix. /// @param EId Edge id. /// @param Costs New cost matrix. template <typename OtherMatrixT> - void setEdgeCosts(EdgeId EId, OtherMatrixT Costs) { + void updateEdgeCosts(EdgeId EId, OtherMatrixT Costs) { MatrixPtr AllocatedCosts = CostAlloc.getMatrix(std::move(Costs)); if (Solver) - Solver->handleSetEdgeCosts(EId, *AllocatedCosts); + Solver->handleUpdateCosts(EId, *AllocatedCosts); getEdge(EId).Costs = AllocatedCosts; } @@ -548,14 +549,14 @@ namespace PBQP { /// @brief Get the first node connected to this edge. /// @param EId Edge id. /// @return The first node connected to the given edge. - NodeId getEdgeNode1Id(EdgeId EId) { + NodeId getEdgeNode1Id(EdgeId EId) const { return getEdge(EId).getN1Id(); } /// @brief Get the second node connected to this edge. /// @param EId Edge id. /// @return The second node connected to the given edge. - NodeId getEdgeNode2Id(EdgeId EId) { + NodeId getEdgeNode2Id(EdgeId EId) const { return getEdge(EId).getN2Id(); } @@ -672,69 +673,6 @@ namespace PBQP { Edges.clear(); FreeEdgeIds.clear(); } - - /// @brief Dump a graph to an output stream. - template <typename OStream> - void dumpToStream(OStream &OS) { - OS << nodeIds().size() << " " << edgeIds().size() << "\n"; - - for (auto NId : nodeIds()) { - const Vector& V = getNodeCosts(NId); - OS << "\n" << V.getLength() << "\n"; - assert(V.getLength() != 0 && "Empty vector in graph."); - OS << V[0]; - for (unsigned i = 1; i < V.getLength(); ++i) { - OS << " " << V[i]; - } - OS << "\n"; - } - - for (auto EId : edgeIds()) { - NodeId N1Id = getEdgeNode1Id(EId); - NodeId N2Id = getEdgeNode2Id(EId); - assert(N1Id != N2Id && "PBQP graphs shound not have self-edges."); - const Matrix& M = getEdgeCosts(EId); - OS << "\n" << N1Id << " " << N2Id << "\n" - << M.getRows() << " " << M.getCols() << "\n"; - assert(M.getRows() != 0 && "No rows in matrix."); - assert(M.getCols() != 0 && "No cols in matrix."); - for (unsigned i = 0; i < M.getRows(); ++i) { - OS << M[i][0]; - for (unsigned j = 1; j < M.getCols(); ++j) { - OS << " " << M[i][j]; - } - OS << "\n"; - } - } - } - - /// @brief Dump this graph to dbgs(). - void dump() { - dumpToStream(dbgs()); - } - - /// @brief Print a representation of this graph in DOT format. - /// @param OS Output stream to print on. - template <typename OStream> - void printDot(OStream &OS) { - OS << "graph {\n"; - for (auto NId : nodeIds()) { - OS << " node" << NId << " [ label=\"" - << NId << ": " << getNodeCosts(NId) << "\" ]\n"; - } - OS << " edge [ len=" << nodeIds().size() << " ]\n"; - for (auto EId : edgeIds()) { - OS << " node" << getEdgeNode1Id(EId) - << " -- node" << getEdgeNode2Id(EId) - << " [ label=\""; - const Matrix &EdgeCosts = getEdgeCosts(EId); - for (unsigned i = 0; i < EdgeCosts.getRows(); ++i) { - OS << EdgeCosts.getRowAsVector(i) << "\\n"; - } - OS << "\" ]\n"; - } - OS << "}\n"; - } }; } // namespace PBQP diff --git a/include/llvm/CodeGen/PBQP/ReductionRules.h b/include/llvm/CodeGen/PBQP/ReductionRules.h index 21fde4d8a5cd..d4a544bfe721 100644 --- a/include/llvm/CodeGen/PBQP/ReductionRules.h +++ b/include/llvm/CodeGen/PBQP/ReductionRules.h @@ -132,9 +132,9 @@ namespace PBQP { } else { const Matrix &YZECosts = G.getEdgeCosts(YZEId); if (YNId == G.getEdgeNode1Id(YZEId)) { - G.setEdgeCosts(YZEId, Delta + YZECosts); + G.updateEdgeCosts(YZEId, Delta + YZECosts); } else { - G.setEdgeCosts(YZEId, Delta.transpose() + YZECosts); + G.updateEdgeCosts(YZEId, Delta.transpose() + YZECosts); } } @@ -144,6 +144,25 @@ namespace PBQP { // TODO: Try to normalize newly added/modified edge. } +#ifndef NDEBUG + // Does this Cost vector have any register options ? + template <typename VectorT> + bool hasRegisterOptions(const VectorT &V) { + unsigned VL = V.getLength(); + + // An empty or spill only cost vector does not provide any register option. + if (VL <= 1) + return false; + + // If there are registers in the cost vector, but all of them have infinite + // costs, then ... there is no available register. + for (unsigned i = 1; i < VL; ++i) + if (V[i] != std::numeric_limits<PBQP::PBQPNum>::infinity()) + return true; + + return false; + } +#endif // \brief Find a solution to a fully reduced graph by backpropagation. // @@ -170,6 +189,15 @@ namespace PBQP { RawVector v = G.getNodeCosts(NId); +#ifndef NDEBUG + // Although a conservatively allocatable node can be allocated to a register, + // spilling it may provide a lower cost solution. Assert here that spilling + // is done by choice, not because there were no register available. + if (G.getNodeMetadata(NId).wasConservativelyAllocatable()) + assert(hasRegisterOptions(v) && "A conservatively allocatable node " + "must have available register options"); +#endif + for (auto EId : G.adjEdgeIds(NId)) { const Matrix& edgeCosts = G.getEdgeCosts(EId); if (NId == G.getEdgeNode1Id(EId)) { diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 8ed32b8a8dd5..39f69549d7cf 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -120,12 +120,15 @@ protected: /// Default setting for -enable-tail-merge on this target. bool EnableTailMerge; + /// Default setting for -enable-shrink-wrap on this target. + bool EnableShrinkWrap; + public: TargetPassConfig(TargetMachine *tm, PassManagerBase &pm); // Dummy constructor. TargetPassConfig(); - virtual ~TargetPassConfig(); + ~TargetPassConfig() override; static char ID; @@ -179,6 +182,9 @@ public: /// Return true if the optimized regalloc pipeline is enabled. bool getOptimizeRegAlloc() const; + /// Return true if shrink wrapping is enabled. + bool getEnableShrinkWrap() const; + /// Return true if the default global register allocator is in use and /// has not be overriden on the command line with '-regalloc=...' bool usingDefaultRegAlloc() const; @@ -214,7 +220,7 @@ public: /// /// This can also be used to plug a new MachineSchedStrategy into an instance /// of the standard ScheduleDAGMI: - /// return new ScheduleDAGMI(C, new MyStrategy(C)) + /// return new ScheduleDAGMI(C, make_unique<MyStrategy>(C), /* IsPostRA= */false) /// /// Return NULL to select the default (generic) machine scheduler. virtual ScheduleDAGInstrs * @@ -354,13 +360,6 @@ protected: namespace llvm { FunctionPass *createAtomicExpandPass(const TargetMachine *TM); - /// \brief Create a basic TargetTransformInfo analysis pass. - /// - /// This pass implements the target transform info analysis using the target - /// independent information available to the LLVM code generator. - ImmutablePass * - createBasicTargetTransformInfoPass(const TargetMachine *TM); - /// createUnreachableBlockEliminationPass - The LLVM code generator does not /// work well with unreachable basic blocks (what live ranges make sense for a /// block that cannot be reached?). As such, a code generator should either @@ -433,6 +432,10 @@ namespace llvm { /// basic blocks. extern char &SpillPlacementID; + /// ShrinkWrap pass. Look for the best place to insert save and restore + // instruction and update the MachineFunctionInfo with that information. + extern char &ShrinkWrapID; + /// VirtRegRewriter pass. Rewrite virtual registers to physical registers as /// assigned in VirtRegMap. extern char &VirtRegRewriterID; @@ -517,11 +520,15 @@ namespace llvm { /// information. extern char &MachineBlockPlacementStatsID; - /// GCLowering Pass - Performs target-independent LLVM IR transformations for - /// highly portable strategies. - /// + /// GCLowering Pass - Used by gc.root to perform its default lowering + /// operations. FunctionPass *createGCLoweringPass(); + /// ShadowStackGCLowering - Implements the custom lowering mechanism + /// used by the shadow stack GC. Only runs on functions which opt in to + /// the shadow stack collector. + FunctionPass *createShadowStackGCLoweringPass(); + /// GCMachineCodeAnalysis - Target-independent pass to mark safe points /// in machine code. Must be added very late during code generation, just /// prior to output, and importantly after all CFG transformations (such as @@ -569,6 +576,10 @@ namespace llvm { /// adapted to code generation. Required if using dwarf exception handling. FunctionPass *createDwarfEHPass(const TargetMachine *TM); + /// createWinEHPass - Prepares personality functions used by MSVC on Windows, + /// in addition to the Itanium LSDA based personalities. + FunctionPass *createWinEHPass(const TargetMachine *TM); + /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. /// @@ -611,13 +622,13 @@ namespace llvm { ModulePass *createForwardControlFlowIntegrityPass(); } // End llvm namespace -/// This initializer registers TargetMachine constructor, so the pass being -/// initialized can use target dependent interfaces. Please do not move this -/// macro to be together with INITIALIZE_PASS, which is a complete target -/// independent initializer, and we don't want to make libScalarOpts depend -/// on libCodeGen. -#define INITIALIZE_TM_PASS(passName, arg, name, cfg, analysis) \ - static void* initialize##passName##PassOnce(PassRegistry &Registry) { \ +/// Target machine pass initializer for passes with dependencies. Use with +/// INITIALIZE_TM_PASS_END. +#define INITIALIZE_TM_PASS_BEGIN INITIALIZE_PASS_BEGIN + +/// Target machine pass initializer for passes with dependencies. Use with +/// INITIALIZE_TM_PASS_BEGIN. +#define INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis) \ PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \ PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis, \ PassInfo::TargetMachineCtor_t(callTargetMachineCtor< passName >)); \ @@ -628,4 +639,13 @@ namespace llvm { CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ } +/// This initializer registers TargetMachine constructor, so the pass being +/// initialized can use target dependent interfaces. Please do not move this +/// macro to be together with INITIALIZE_PASS, which is a complete target +/// independent initializer, and we don't want to make libScalarOpts depend +/// on libCodeGen. +#define INITIALIZE_TM_PASS(passName, arg, name, cfg, analysis) \ + INITIALIZE_TM_PASS_BEGIN(passName, arg, name, cfg, analysis) \ + INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis) + #endif diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index 5c0e9859915f..6046e46547b2 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -23,6 +23,9 @@ #include "llvm/Support/ErrorHandling.h" namespace llvm { + +class raw_ostream; + namespace PBQP { namespace RegAlloc { @@ -177,21 +180,34 @@ class NodeMetadata { public: typedef RegAlloc::AllowedRegVector AllowedRegVector; - typedef enum { Unprocessed, - OptimallyReducible, - ConservativelyAllocatable, - NotProvablyAllocatable } ReductionState; + // The node's reduction state. The order in this enum is important, + // as it is assumed nodes can only progress up (i.e. towards being + // optimally reducible) when reducing the graph. + typedef enum { + Unprocessed, + NotProvablyAllocatable, + ConservativelyAllocatable, + OptimallyReducible + } ReductionState; NodeMetadata() : RS(Unprocessed), NumOpts(0), DeniedOpts(0), OptUnsafeEdges(nullptr), - VReg(0) {} + VReg(0) +#ifndef NDEBUG + , everConservativelyAllocatable(false) +#endif + {} // FIXME: Re-implementing default behavior to work around MSVC. Remove once // MSVC synthesizes move constructors properly. NodeMetadata(const NodeMetadata &Other) : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), OptUnsafeEdges(new unsigned[NumOpts]), VReg(Other.VReg), - AllowedRegs(Other.AllowedRegs) { + AllowedRegs(Other.AllowedRegs) +#ifndef NDEBUG + , everConservativelyAllocatable(Other.everConservativelyAllocatable) +#endif + { if (NumOpts > 0) { std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts], &OptUnsafeEdges[0]); @@ -203,7 +219,11 @@ public: NodeMetadata(NodeMetadata &&Other) : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), OptUnsafeEdges(std::move(Other.OptUnsafeEdges)), VReg(Other.VReg), - AllowedRegs(std::move(Other.AllowedRegs)) {} + AllowedRegs(std::move(Other.AllowedRegs)) +#ifndef NDEBUG + , everConservativelyAllocatable(Other.everConservativelyAllocatable) +#endif + {} // FIXME: Re-implementing default behavior to work around MSVC. Remove once // MSVC synthesizes move constructors properly. @@ -216,6 +236,9 @@ public: OptUnsafeEdges.get()); VReg = Other.VReg; AllowedRegs = Other.AllowedRegs; +#ifndef NDEBUG + everConservativelyAllocatable = Other.everConservativelyAllocatable; +#endif return *this; } @@ -228,6 +251,9 @@ public: OptUnsafeEdges = std::move(Other.OptUnsafeEdges); VReg = Other.VReg; AllowedRegs = std::move(Other.AllowedRegs); +#ifndef NDEBUG + everConservativelyAllocatable = Other.everConservativelyAllocatable; +#endif return *this; } @@ -245,7 +271,18 @@ public: } ReductionState getReductionState() const { return RS; } - void setReductionState(ReductionState RS) { this->RS = RS; } + void setReductionState(ReductionState RS) { + assert(RS >= this->RS && "A node's reduction state can not be downgraded"); + this->RS = RS; + +#ifndef NDEBUG + // Remember this state to assert later that a non-infinite register + // option was available. + if (RS == ConservativelyAllocatable) + everConservativelyAllocatable = true; +#endif + } + void handleAddEdge(const MatrixMetadata& MD, bool Transpose) { DeniedOpts += Transpose ? MD.getWorstRow() : MD.getWorstCol(); @@ -269,6 +306,12 @@ public: &OptUnsafeEdges[NumOpts]); } +#ifndef NDEBUG + bool wasConservativelyAllocatable() const { + return everConservativelyAllocatable; + } +#endif + private: ReductionState RS; unsigned NumOpts; @@ -276,6 +319,10 @@ private: std::unique_ptr<unsigned[]> OptUnsafeEdges; unsigned VReg; GraphMetadata::AllowedRegVecRef AllowedRegs; + +#ifndef NDEBUG + bool everConservativelyAllocatable; +#endif }; class RegAllocSolverImpl { @@ -309,6 +356,8 @@ public: } void handleAddNode(NodeId NId) { + assert(G.getNodeCosts(NId).getLength() > 1 && + "PBQP Graph should not contain single or zero-option nodes"); G.getNodeMetadata(NId).setup(G.getNodeCosts(NId)); } void handleRemoveNode(NodeId NId) {} @@ -328,15 +377,7 @@ public: NodeMetadata& NMd = G.getNodeMetadata(NId); const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); NMd.handleRemoveEdge(MMd, NId == G.getEdgeNode2Id(EId)); - if (G.getNodeDegree(NId) == 3) { - // This node is becoming optimally reducible. - moveToOptimallyReducibleNodes(NId); - } else if (NMd.getReductionState() == - NodeMetadata::NotProvablyAllocatable && - NMd.isConservativelyAllocatable()) { - // This node just became conservatively allocatable. - moveToConservativelyAllocatableNodes(NId); - } + promote(NId, NMd); } void handleReconnectEdge(EdgeId EId, NodeId NId) { @@ -345,20 +386,44 @@ public: NMd.handleAddEdge(MMd, NId == G.getEdgeNode2Id(EId)); } - void handleSetEdgeCosts(EdgeId EId, const Matrix& NewCosts) { - handleRemoveEdge(EId); - + void handleUpdateCosts(EdgeId EId, const Matrix& NewCosts) { NodeId N1Id = G.getEdgeNode1Id(EId); NodeId N2Id = G.getEdgeNode2Id(EId); NodeMetadata& N1Md = G.getNodeMetadata(N1Id); NodeMetadata& N2Md = G.getNodeMetadata(N2Id); + bool Transpose = N1Id != G.getEdgeNode1Id(EId); + + // Metadata are computed incrementally. First, update them + // by removing the old cost. + const MatrixMetadata& OldMMd = G.getEdgeCosts(EId).getMetadata(); + N1Md.handleRemoveEdge(OldMMd, Transpose); + N2Md.handleRemoveEdge(OldMMd, !Transpose); + + // And update now the metadata with the new cost. const MatrixMetadata& MMd = NewCosts.getMetadata(); - N1Md.handleAddEdge(MMd, N1Id != G.getEdgeNode1Id(EId)); - N2Md.handleAddEdge(MMd, N2Id != G.getEdgeNode1Id(EId)); + N1Md.handleAddEdge(MMd, Transpose); + N2Md.handleAddEdge(MMd, !Transpose); + + // As the metadata may have changed with the update, the nodes may have + // become ConservativelyAllocatable or OptimallyReducible. + promote(N1Id, N1Md); + promote(N2Id, N2Md); } private: + void promote(NodeId NId, NodeMetadata& NMd) { + if (G.getNodeDegree(NId) == 3) { + // This node is becoming optimally reducible. + moveToOptimallyReducibleNodes(NId); + } else if (NMd.getReductionState() == + NodeMetadata::NotProvablyAllocatable && + NMd.isConservativelyAllocatable()) { + // This node just became conservatively allocatable. + moveToConservativelyAllocatableNodes(NId); + } + } + void removeFromCurrentSet(NodeId NId) { switch (G.getNodeMetadata(NId).getReductionState()) { case NodeMetadata::Unprocessed: break; @@ -479,8 +544,10 @@ private: public: SpillCostComparator(const Graph& G) : G(G) {} bool operator()(NodeId N1Id, NodeId N2Id) { - PBQPNum N1SC = G.getNodeCosts(N1Id)[0] / G.getNodeDegree(N1Id); - PBQPNum N2SC = G.getNodeCosts(N2Id)[0] / G.getNodeDegree(N2Id); + PBQPNum N1SC = G.getNodeCosts(N1Id)[0]; + PBQPNum N2SC = G.getNodeCosts(N2Id)[0]; + if (N1SC == N2SC) + return G.getNodeDegree(N1Id) < G.getNodeDegree(N2Id); return N1SC < N2SC; } private: @@ -499,6 +566,17 @@ private: typedef PBQP::Graph<RegAllocSolverImpl> BaseT; public: PBQPRAGraph(GraphMetadata Metadata) : BaseT(Metadata) {} + + /// @brief Dump this graph to dbgs(). + void dump() const; + + /// @brief Dump this graph to an output stream. + /// @param OS Output stream to print on. + void dump(raw_ostream &OS) const; + + /// @brief Print a representation of this graph in DOT format. + /// @param OS Output stream to print on. + void printDot(raw_ostream &OS) const; }; inline Solution solve(PBQPRAGraph& G) { diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index cc9e00055146..fcb6feed68ca 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -35,21 +35,6 @@ struct RegisterPressure { SmallVector<unsigned,8> LiveInRegs; SmallVector<unsigned,8> LiveOutRegs; - /// Increase register pressure for each pressure set impacted by this register - /// class. Normally called by RegPressureTracker, but may be called manually - /// to account for live through (global liveness). - /// - /// \param Reg is either a virtual register number or register unit number. - void increase(unsigned Reg, const TargetRegisterInfo *TRI, - const MachineRegisterInfo *MRI); - - /// Decrease register pressure for each pressure set impacted by this register - /// class. This is only useful to account for spilling or rematerialization. - /// - /// \param Reg is either a virtual register number or register unit number. - void decrease(unsigned Reg, const TargetRegisterInfo *TRI, - const MachineRegisterInfo *MRI); - void dump(const TargetRegisterInfo *TRI) const; }; diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 474861e45df1..df3fd34e0af6 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -9,7 +9,7 @@ // // This file declares the machine register scavenger class. It can provide // information such as unused register at any point in a machine basic block. -// It also provides a mechanism to make registers availbale by evicting them +// It also provides a mechanism to make registers available by evicting them // to spill slots. // //===----------------------------------------------------------------------===// @@ -36,8 +36,7 @@ class RegScavenger { MachineBasicBlock::iterator MBBI; unsigned NumRegUnits; - /// Tracking - True if RegScavenger is currently tracking the liveness of - /// registers. + /// True if RegScavenger is currently tracking the liveness of registers. bool Tracking; /// Information on scavenged registers (held in a spill slot). @@ -58,8 +57,8 @@ class RegScavenger { /// A vector of information on scavenged registers. SmallVector<ScavengedInfo, 2> Scavenged; - /// RegUnitsAvailable - The current state of each reg unit immediatelly - /// before MBBI. One bit per register unit. If bit is not set it means any + /// The current state of each reg unit immediately before MBBI. + /// One bit per register unit. If bit is not set it means any /// register containing that register unit is currently being used. BitVector RegUnitsAvailable; @@ -72,18 +71,17 @@ public: RegScavenger() : MBB(nullptr), NumRegUnits(0), Tracking(false) {} - /// enterBasicBlock - Start tracking liveness from the begin of the specific - /// basic block. + /// Start tracking liveness from the begin of the specific basic block. void enterBasicBlock(MachineBasicBlock *mbb); - /// initRegState - allow resetting register state info for multiple + /// Allow resetting register state info for multiple /// passes over/within the same function. void initRegState(); - /// forward - Move the internal MBB iterator and update register states. + /// Move the internal MBB iterator and update register states. void forward(); - /// forward - Move the internal MBB iterator and update register states until + /// Move the internal MBB iterator and update register states until /// it has processed the specific iterator. void forward(MachineBasicBlock::iterator I) { if (!Tracking && MBB->begin() != I) forward(); @@ -99,7 +97,7 @@ public: while (MBBI != I) unprocess(); } - /// skipTo - Move the internal MBB iterator but do not update register states. + /// Move the internal MBB iterator but do not update register states. void skipTo(MachineBasicBlock::iterator I) { if (I == MachineBasicBlock::iterator(nullptr)) Tracking = false; @@ -110,14 +108,13 @@ public: return MBBI; } - /// isRegUsed - return if a specific register is currently used. + /// Return if a specific register is currently used. bool isRegUsed(unsigned Reg, bool includeReserved = true) const; - /// getRegsAvailable - Return all available registers in the register class - /// in Mask. + /// Return all available registers in the register class in Mask. BitVector getRegsAvailable(const TargetRegisterClass *RC); - /// FindUnusedReg - Find a unused register of the specified register class. + /// Find an unused register of the specified register class. /// Return 0 if none is found. unsigned FindUnusedReg(const TargetRegisterClass *RegClass) const; @@ -144,7 +141,7 @@ public: A.push_back(I->FrameIndex); } - /// scavengeRegister - Make a register of the specific register class + /// Make a register of the specific register class /// available and do the appropriate bookkeeping. SPAdj is the stack /// adjustment due to call frame, it's passed along to eliminateFrameIndex(). /// Returns the scavenged register. @@ -154,11 +151,10 @@ public: return scavengeRegister(RegClass, MBBI, SPAdj); } - /// setRegUsed - Tell the scavenger a register is used. - /// + /// Tell the scavenger a register is used. void setRegUsed(unsigned Reg); private: - /// isReserved - Returns true if a register is reserved. It is never "unused". + /// Returns true if a register is reserved. It is never "unused". bool isReserved(unsigned Reg) const { return MRI->isReserved(Reg); } /// setUsed / setUnused - Mark the state of one or a number of register units. @@ -177,9 +173,8 @@ private: /// Add all Reg Units that Reg contains to BV. void addRegUnits(BitVector &BV, unsigned Reg); - /// findSurvivorReg - Return the candidate register that is unused for the - /// longest after StartMI. UseMI is set to the instruction where the search - /// stopped. + /// Return the candidate register that is unused for the longest after + /// StartMI. UseMI is set to the instruction where the search stopped. /// /// No more than InstrLimit instructions are inspected. unsigned findSurvivorReg(MachineBasicBlock::iterator StartMI, diff --git a/include/llvm/CodeGen/ResourcePriorityQueue.h b/include/llvm/CodeGen/ResourcePriorityQueue.h index 114fe7c35b82..0097e0472e5c 100644 --- a/include/llvm/CodeGen/ResourcePriorityQueue.h +++ b/include/llvm/CodeGen/ResourcePriorityQueue.h @@ -64,7 +64,7 @@ namespace llvm { /// ResourcesModel - Represents VLIW state. /// Not limited to VLIW targets per say, but assumes /// definition of DFA by a target. - DFAPacketizer *ResourcesModel; + std::unique_ptr<DFAPacketizer> ResourcesModel; /// Resource model - packet/bundle model. Purely /// internal at the time. @@ -77,10 +77,6 @@ namespace llvm { public: ResourcePriorityQueue(SelectionDAGISel *IS); - ~ResourcePriorityQueue() { - delete ResourcesModel; - } - bool isBottomUp() const override { return false; } void initNodes(std::vector<SUnit> &sunits) override; @@ -124,8 +120,6 @@ namespace llvm { void remove(SUnit *SU) override; - void dump(ScheduleDAG* DAG) const override; - /// scheduledNode - Main resource tracking point. void scheduledNode(SUnit *Node) override; bool isResourceAvailable(SUnit *SU); diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index 64c9c4729e92..2be5de640e29 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -425,6 +425,10 @@ namespace RTLIB { /// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or /// UNKNOWN_LIBCALL if there is none. Libcall getUINTTOFP(EVT OpVT, EVT RetVT); + + /// Return the SYNC_FETCH_AND_* value for the given opcode and type, or + /// UNKNOWN_LIBCALL if there is none. + Libcall getATOMIC(unsigned Opc, MVT VT); } } diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 80aee8c62880..839131416560 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -628,12 +628,6 @@ namespace llvm { } bool operator!=(const SUnitIterator& x) const { return !operator==(x); } - const SUnitIterator &operator=(const SUnitIterator &I) { - assert(I.Node==Node && "Cannot assign iterators to two different nodes!"); - Operand = I.Operand; - return *this; - } - pointer operator*() const { return Node->Preds[Operand].getSUnit(); } diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index 00dd8f9a633e..1196783e820b 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -158,7 +158,7 @@ namespace llvm { bool RemoveKillFlags = false, LiveIntervals *LIS = nullptr); - virtual ~ScheduleDAGInstrs() {} + ~ScheduleDAGInstrs() override {} bool isPostRA() const { return IsPostRA; } diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index ee4bc08495ec..89f9005b8b21 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -41,14 +41,16 @@ class TargetSelectionDAGInfo; class SDVTListNode : public FoldingSetNode { friend struct FoldingSetTrait<SDVTListNode>; - /// FastID - A reference to an Interned FoldingSetNodeID for this node. + /// A reference to an Interned FoldingSetNodeID for this node. /// The Allocator in SelectionDAG holds the data. /// SDVTList contains all types which are frequently accessed in SelectionDAG. - /// The size of this list is not expected big so it won't introduce memory penalty. + /// The size of this list is not expected to be big so it won't introduce + /// a memory penalty. FoldingSetNodeIDRef FastID; const EVT *VTs; unsigned int NumVTs; - /// The hash value for SDVTList is fixed so cache it to avoid hash calculation + /// The hash value for SDVTList is fixed, so cache it to avoid + /// hash calculation. unsigned HashValue; public: SDVTListNode(const FoldingSetNodeIDRef ID, const EVT *VT, unsigned int Num) : @@ -61,8 +63,8 @@ public: } }; -// Specialize FoldingSetTrait for SDVTListNode -// To avoid computing temp FoldingSetNodeID and hash value. +/// Specialize FoldingSetTrait for SDVTListNode +/// to avoid computing temp FoldingSetNodeID and hash value. template<> struct FoldingSetTrait<SDVTListNode> : DefaultFoldingSetTrait<SDVTListNode> { static void Profile(const SDVTListNode &X, FoldingSetNodeID& ID) { ID = X.FastID; @@ -98,7 +100,7 @@ private: static void createNode(const SDNode &); }; -/// SDDbgInfo - Keeps track of dbg_value information through SDISel. We do +/// Keeps track of dbg_value information through SDISel. We do /// not build SDNodes for these so as not to perturb the generated code; /// instead the info is kept off to the side in this structure. Each SDNode may /// have one or more associated dbg_value entries. This information is kept in @@ -110,13 +112,14 @@ private: /// motion, and debug info for them is potentially useful even if the parameter /// is unused. Right now only byval parameters are handled separately. class SDDbgInfo { + BumpPtrAllocator Alloc; SmallVector<SDDbgValue*, 32> DbgValues; SmallVector<SDDbgValue*, 32> ByvalParmDbgValues; typedef DenseMap<const SDNode*, SmallVector<SDDbgValue*, 2> > DbgValMapType; DbgValMapType DbgValMap; - void operator=(const SDDbgInfo&) LLVM_DELETED_FUNCTION; - SDDbgInfo(const SDDbgInfo&) LLVM_DELETED_FUNCTION; + void operator=(const SDDbgInfo&) = delete; + SDDbgInfo(const SDDbgInfo&) = delete; public: SDDbgInfo() {} @@ -136,8 +139,11 @@ public: DbgValMap.clear(); DbgValues.clear(); ByvalParmDbgValues.clear(); + Alloc.Reset(); } + BumpPtrAllocator &getAlloc() { return Alloc; } + bool empty() const { return DbgValues.empty() && ByvalParmDbgValues.empty(); } @@ -159,10 +165,10 @@ public: class SelectionDAG; void checkForCycles(const SelectionDAG *DAG, bool force = false); -/// SelectionDAG class - This is used to represent a portion of an LLVM function -/// in a low-level Data Dependence DAG representation suitable for instruction -/// selection. This DAG is constructed as the first step of instruction -/// selection in order to allow implementation of machine specific optimizations +/// This is used to represent a portion of an LLVM function in a low-level +/// Data Dependence DAG representation suitable for instruction selection. +/// This DAG is constructed as the first step of instruction selection in order +/// to allow implementation of machine specific optimizations /// and code simplifications. /// /// The representation used by the SelectionDAG is a target-independent @@ -178,40 +184,39 @@ class SelectionDAG { LLVMContext *Context; CodeGenOpt::Level OptLevel; - /// EntryNode - The starting token. + /// The starting token. SDNode EntryNode; - /// Root - The root of the entire DAG. + /// The root of the entire DAG. SDValue Root; - /// AllNodes - A linked list of nodes in the current DAG. + /// A linked list of nodes in the current DAG. ilist<SDNode> AllNodes; - /// NodeAllocatorType - The AllocatorType for allocating SDNodes. We use + /// The AllocatorType for allocating SDNodes. We use /// pool allocation with recycling. typedef RecyclingAllocator<BumpPtrAllocator, SDNode, sizeof(LargestSDNode), AlignOf<MostAlignedSDNode>::Alignment> NodeAllocatorType; - /// NodeAllocator - Pool allocation for nodes. + /// Pool allocation for nodes. NodeAllocatorType NodeAllocator; - /// CSEMap - This structure is used to memoize nodes, automatically performing + /// This structure is used to memoize nodes, automatically performing /// CSE with existing nodes when a duplicate is requested. FoldingSet<SDNode> CSEMap; - /// OperandAllocator - Pool allocation for machine-opcode SDNode operands. + /// Pool allocation for machine-opcode SDNode operands. BumpPtrAllocator OperandAllocator; - /// Allocator - Pool allocation for misc. objects that are created once per - /// SelectionDAG. + /// Pool allocation for misc. objects that are created once per SelectionDAG. BumpPtrAllocator Allocator; - /// DbgInfo - Tracks dbg_value information through SDISel. + /// Tracks dbg_value information through SDISel. SDDbgInfo *DbgInfo; public: - /// DAGUpdateListener - Clients of various APIs that cause global effects on + /// Clients of various APIs that cause global effects on /// the DAG can optionally implement this interface. This allows the clients /// to handle the various sorts of updates that happen. /// @@ -232,15 +237,15 @@ public: DAG.UpdateListeners = Next; } - /// NodeDeleted - The node N that was deleted and, if E is not null, an + /// The node N that was deleted and, if E is not null, an /// equivalent node E that replaced it. virtual void NodeDeleted(SDNode *N, SDNode *E); - /// NodeUpdated - The node N that was updated. + /// The node N that was updated. virtual void NodeUpdated(SDNode *N); }; - /// NewNodesMustHaveLegalTypes - When true, additional steps are taken to + /// When true, additional steps are taken to /// ensure that getConstant() and similar functions return DAG nodes that /// have legal types. This is important after type legalization since /// any illegally typed nodes generated after this point will not experience @@ -251,32 +256,28 @@ private: /// DAGUpdateListener is a friend so it can manipulate the listener stack. friend struct DAGUpdateListener; - /// UpdateListeners - Linked list of registered DAGUpdateListener instances. + /// Linked list of registered DAGUpdateListener instances. /// This stack is maintained by DAGUpdateListener RAII. DAGUpdateListener *UpdateListeners; - /// setGraphColorHelper - Implementation of setSubgraphColor. + /// Implementation of setSubgraphColor. /// Return whether we had to truncate the search. - /// bool setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet<SDNode *> &visited, int level, bool &printed); - void operator=(const SelectionDAG&) LLVM_DELETED_FUNCTION; - SelectionDAG(const SelectionDAG&) LLVM_DELETED_FUNCTION; + void operator=(const SelectionDAG&) = delete; + SelectionDAG(const SelectionDAG&) = delete; public: explicit SelectionDAG(const TargetMachine &TM, llvm::CodeGenOpt::Level); ~SelectionDAG(); - /// init - Prepare this SelectionDAG to process code in the given - /// MachineFunction. - /// + /// Prepare this SelectionDAG to process code in the given MachineFunction. void init(MachineFunction &mf); - /// clear - Clear state and free memory necessary to make this + /// Clear state and free memory necessary to make this /// SelectionDAG ready to process a new block. - /// void clear(); MachineFunction &getMachineFunction() const { return *MF; } @@ -286,8 +287,7 @@ public: const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return *TSI; } LLVMContext *getContext() const {return Context; } - /// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'. - /// + /// Pop up a GraphViz/gv window with the DAG rendered using 'dot'. void viewGraph(const std::string &Title); void viewGraph(); @@ -295,24 +295,21 @@ public: std::map<const SDNode *, std::string> NodeGraphAttrs; #endif - /// clearGraphAttrs - Clear all previously defined node graph attributes. + /// Clear all previously defined node graph attributes. /// Intended to be used from a debugging tool (eg. gdb). void clearGraphAttrs(); - /// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".) - /// + /// Set graph attributes for a node. (eg. "color=red".) void setGraphAttrs(const SDNode *N, const char *Attrs); - /// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".) + /// Get graph attributes for a node. (eg. "color=red".) /// Used from getNodeAttributes. const std::string getGraphAttrs(const SDNode *N) const; - /// setGraphColor - Convenience for setting node color attribute. - /// + /// Convenience for setting node color attribute. void setGraphColor(const SDNode *N, const char *Color); - /// setGraphColor - Convenience for setting subgraph color attribute. - /// + /// Convenience for setting subgraph color attribute. void setSubgraphColor(SDNode *N, const char *Color); typedef ilist<SDNode>::const_iterator allnodes_const_iterator; @@ -325,17 +322,15 @@ public: return AllNodes.size(); } - /// getRoot - Return the root tag of the SelectionDAG. - /// + /// Return the root tag of the SelectionDAG. const SDValue &getRoot() const { return Root; } - /// getEntryNode - Return the token chain corresponding to the entry of the - /// function. + /// Return the token chain corresponding to the entry of the function. SDValue getEntryNode() const { return SDValue(const_cast<SDNode *>(&EntryNode), 0); } - /// setRoot - Set the current root tag of the SelectionDAG. + /// Set the current root tag of the SelectionDAG. /// const SDValue &setRoot(SDValue N) { assert((!N.getNode() || N.getValueType() == MVT::Other) && @@ -348,22 +343,22 @@ public: return Root; } - /// Combine - This iterates over the nodes in the SelectionDAG, folding + /// This iterates over the nodes in the SelectionDAG, folding /// certain types of nodes together, or eliminating superfluous nodes. The /// Level argument controls whether Combine is allowed to produce nodes and /// types that are illegal on the target. void Combine(CombineLevel Level, AliasAnalysis &AA, CodeGenOpt::Level OptLevel); - /// LegalizeTypes - This transforms the SelectionDAG into a SelectionDAG that - /// only uses types natively supported by the target. Returns "true" if it - /// made any changes. + /// This transforms the SelectionDAG into a SelectionDAG that + /// only uses types natively supported by the target. + /// Returns "true" if it made any changes. /// /// Note that this is an involved process that may invalidate pointers into /// the graph. bool LegalizeTypes(); - /// Legalize - This transforms the SelectionDAG into a SelectionDAG that is + /// This transforms the SelectionDAG into a SelectionDAG that is /// compatible with the target instruction selector, as indicated by the /// TargetLowering object. /// @@ -392,7 +387,7 @@ public: /// UpdatedNodes with any new nodes replacing those originally in the DAG. bool LegalizeOp(SDNode *N, SmallSetVector<SDNode *, 16> &UpdatedNodes); - /// LegalizeVectors - This transforms the SelectionDAG into a SelectionDAG + /// This transforms the SelectionDAG into a SelectionDAG /// that only uses vector math operations supported by the target. This is /// necessary as a separate step from Legalize because unrolling a vector /// operation can introduce illegal types, which requires running @@ -405,16 +400,14 @@ public: /// the graph. bool LegalizeVectors(); - /// RemoveDeadNodes - This method deletes all unreachable nodes in the - /// SelectionDAG. + /// This method deletes all unreachable nodes in the SelectionDAG. void RemoveDeadNodes(); - /// DeleteNode - Remove the specified node from the system. This node must + /// Remove the specified node from the system. This node must /// have no referrers. void DeleteNode(SDNode *N); - /// getVTList - Return an SDVTList that represents the list of values - /// specified. + /// Return an SDVTList that represents the list of values specified. SDVTList getVTList(EVT VT); SDVTList getVTList(EVT VT1, EVT VT2); SDVTList getVTList(EVT VT1, EVT VT2, EVT VT3); @@ -424,36 +417,40 @@ public: //===--------------------------------------------------------------------===// // Node creation methods. // - SDValue getConstant(uint64_t Val, EVT VT, bool isTarget = false, + SDValue getConstant(uint64_t Val, SDLoc DL, EVT VT, bool isTarget = false, bool isOpaque = false); - SDValue getConstant(const APInt &Val, EVT VT, bool isTarget = false, + SDValue getConstant(const APInt &Val, SDLoc DL, EVT VT, bool isTarget = false, bool isOpaque = false); - SDValue getConstant(const ConstantInt &Val, EVT VT, bool isTarget = false, - bool isOpaque = false); - SDValue getIntPtrConstant(uint64_t Val, bool isTarget = false); - SDValue getTargetConstant(uint64_t Val, EVT VT, bool isOpaque = false) { - return getConstant(Val, VT, true, isOpaque); + SDValue getConstant(const ConstantInt &Val, SDLoc DL, EVT VT, + bool isTarget = false, bool isOpaque = false); + SDValue getIntPtrConstant(uint64_t Val, SDLoc DL, bool isTarget = false); + SDValue getTargetConstant(uint64_t Val, SDLoc DL, EVT VT, + bool isOpaque = false) { + return getConstant(Val, DL, VT, true, isOpaque); } - SDValue getTargetConstant(const APInt &Val, EVT VT, bool isOpaque = false) { - return getConstant(Val, VT, true, isOpaque); + SDValue getTargetConstant(const APInt &Val, SDLoc DL, EVT VT, + bool isOpaque = false) { + return getConstant(Val, DL, VT, true, isOpaque); } - SDValue getTargetConstant(const ConstantInt &Val, EVT VT, + SDValue getTargetConstant(const ConstantInt &Val, SDLoc DL, EVT VT, bool isOpaque = false) { - return getConstant(Val, VT, true, isOpaque); + return getConstant(Val, DL, VT, true, isOpaque); } // The forms below that take a double should only be used for simple // constants that can be exactly represented in VT. No checks are made. - SDValue getConstantFP(double Val, EVT VT, bool isTarget = false); - SDValue getConstantFP(const APFloat& Val, EVT VT, bool isTarget = false); - SDValue getConstantFP(const ConstantFP &CF, EVT VT, bool isTarget = false); - SDValue getTargetConstantFP(double Val, EVT VT) { - return getConstantFP(Val, VT, true); + SDValue getConstantFP(double Val, SDLoc DL, EVT VT, bool isTarget = false); + SDValue getConstantFP(const APFloat& Val, SDLoc DL, EVT VT, + bool isTarget = false); + SDValue getConstantFP(const ConstantFP &CF, SDLoc DL, EVT VT, + bool isTarget = false); + SDValue getTargetConstantFP(double Val, SDLoc DL, EVT VT) { + return getConstantFP(Val, DL, VT, true); } - SDValue getTargetConstantFP(const APFloat& Val, EVT VT) { - return getConstantFP(Val, VT, true); + SDValue getTargetConstantFP(const APFloat& Val, SDLoc DL, EVT VT) { + return getConstantFP(Val, DL, VT, true); } - SDValue getTargetConstantFP(const ConstantFP &Val, EVT VT) { - return getConstantFP(Val, VT, true); + SDValue getTargetConstantFP(const ConstantFP &Val, SDLoc DL, EVT VT) { + return getConstantFP(Val, DL, VT, true); } SDValue getGlobalAddress(const GlobalValue *GV, SDLoc DL, EVT VT, int64_t offset = 0, bool isTargetGA = false, @@ -561,10 +558,9 @@ public: SDValue STy, SDValue Rnd, SDValue Sat, ISD::CvtCode Code); - /// getVectorShuffle - Return an ISD::VECTOR_SHUFFLE node. The number of - /// elements in VT, which must be a vector type, must match the number of - /// mask elements NumElts. A integer mask element equal to -1 is treated as - /// undefined. + /// Return an ISD::VECTOR_SHUFFLE node. The number of elements in VT, + /// which must be a vector type, must match the number of mask elements + /// NumElts. An integer mask element equal to -1 is treated as undefined. SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2, const int *MaskElts); SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2, @@ -580,63 +576,62 @@ public: /// Example: shuffle A, B, <0,5,2,7> -> shuffle B, A, <4,1,6,3> SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV); - /// getAnyExtOrTrunc - Convert Op, which must be of integer type, to the + /// Convert Op, which must be of integer type, to the /// integer type VT, by either any-extending or truncating it. SDValue getAnyExtOrTrunc(SDValue Op, SDLoc DL, EVT VT); - /// getSExtOrTrunc - Convert Op, which must be of integer type, to the + /// Convert Op, which must be of integer type, to the /// integer type VT, by either sign-extending or truncating it. SDValue getSExtOrTrunc(SDValue Op, SDLoc DL, EVT VT); - /// getZExtOrTrunc - Convert Op, which must be of integer type, to the + /// Convert Op, which must be of integer type, to the /// integer type VT, by either zero-extending or truncating it. SDValue getZExtOrTrunc(SDValue Op, SDLoc DL, EVT VT); - /// getZeroExtendInReg - Return the expression required to zero extend the Op + /// Return the expression required to zero extend the Op /// value assuming it was the smaller SrcTy value. SDValue getZeroExtendInReg(SDValue Op, SDLoc DL, EVT SrcTy); - /// getAnyExtendVectorInReg - Return an operation which will any-extend the - /// low lanes of the operand into the specified vector type. For example, + /// Return an operation which will any-extend the low lanes of the operand + /// into the specified vector type. For example, /// this can convert a v16i8 into a v4i32 by any-extending the low four /// lanes of the operand from i8 to i32. SDValue getAnyExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT); - /// getSignExtendVectorInReg - Return an operation which will sign extend the - /// low lanes of the operand into the specified vector type. For example, + /// Return an operation which will sign extend the low lanes of the operand + /// into the specified vector type. For example, /// this can convert a v16i8 into a v4i32 by sign extending the low four /// lanes of the operand from i8 to i32. SDValue getSignExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT); - /// getZeroExtendVectorInReg - Return an operation which will zero extend the - /// low lanes of the operand into the specified vector type. For example, + /// Return an operation which will zero extend the low lanes of the operand + /// into the specified vector type. For example, /// this can convert a v16i8 into a v4i32 by zero extending the low four /// lanes of the operand from i8 to i32. SDValue getZeroExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT); - /// getBoolExtOrTrunc - Convert Op, which must be of integer type, to the - /// integer type VT, by using an extension appropriate for the target's + /// Convert Op, which must be of integer type, to the integer type VT, + /// by using an extension appropriate for the target's /// BooleanContent for type OpVT or truncating it. SDValue getBoolExtOrTrunc(SDValue Op, SDLoc SL, EVT VT, EVT OpVT); - /// getNOT - Create a bitwise NOT operation as (XOR Val, -1). + /// Create a bitwise NOT operation as (XOR Val, -1). SDValue getNOT(SDLoc DL, SDValue Val, EVT VT); /// \brief Create a logical NOT operation as (XOR Val, BooleanOne). SDValue getLogicalNOT(SDLoc DL, SDValue Val, EVT VT); - /// getCALLSEQ_START - Return a new CALLSEQ_START node, which always must have - /// a glue result (to ensure it's not CSE'd). CALLSEQ_START does not have a - /// useful SDLoc. + /// Return a new CALLSEQ_START node, which always must have a glue result + /// (to ensure it's not CSE'd). CALLSEQ_START does not have a useful SDLoc. SDValue getCALLSEQ_START(SDValue Chain, SDValue Op, SDLoc DL) { SDVTList VTs = getVTList(MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, Op }; return getNode(ISD::CALLSEQ_START, DL, VTs, Ops); } - /// getCALLSEQ_END - Return a new CALLSEQ_END node, which always must have a - /// glue result (to ensure it's not CSE'd). CALLSEQ_END does not have - /// a useful SDLoc. + /// Return a new CALLSEQ_END node, which always must have a + /// glue result (to ensure it's not CSE'd). + /// CALLSEQ_END does not have a useful SDLoc. SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, SDLoc DL) { SDVTList NodeTys = getVTList(MVT::Other, MVT::Glue); @@ -649,19 +644,28 @@ public: return getNode(ISD::CALLSEQ_END, DL, NodeTys, Ops); } - /// getUNDEF - Return an UNDEF node. UNDEF does not have a useful SDLoc. + /// Return an UNDEF node. UNDEF does not have a useful SDLoc. SDValue getUNDEF(EVT VT) { return getNode(ISD::UNDEF, SDLoc(), VT); } - /// getGLOBAL_OFFSET_TABLE - Return a GLOBAL_OFFSET_TABLE node. This does - /// not have a useful SDLoc. + /// Return a GLOBAL_OFFSET_TABLE node. This does not have a useful SDLoc. SDValue getGLOBAL_OFFSET_TABLE(EVT VT) { return getNode(ISD::GLOBAL_OFFSET_TABLE, SDLoc(), VT); } - /// getNode - Gets or creates the specified node. + /// Gets or creates the specified node. /// + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, + ArrayRef<SDUse> Ops); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, + ArrayRef<SDValue> Ops); + SDValue getNode(unsigned Opcode, SDLoc DL, ArrayRef<EVT> ResultTys, + ArrayRef<SDValue> Ops); + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, + ArrayRef<SDValue> Ops); + + // Specialize based on number of operands. SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, @@ -672,47 +676,40 @@ public: SDValue N3, SDValue N4); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3, SDValue N4, SDValue N5); - SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, ArrayRef<SDUse> Ops); - SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, - ArrayRef<SDValue> Ops); - SDValue getNode(unsigned Opcode, SDLoc DL, - ArrayRef<EVT> ResultTys, - ArrayRef<SDValue> Ops); - SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, - ArrayRef<SDValue> Ops); + + // Specialize again based on number of operands for nodes with a VTList + // rather than a single VT. SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs); SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N); - SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, - SDValue N1, SDValue N2); - SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, - SDValue N1, SDValue N2, SDValue N3); - SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, - SDValue N1, SDValue N2, SDValue N3, SDValue N4); - SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, - SDValue N1, SDValue N2, SDValue N3, SDValue N4, - SDValue N5); - - /// getStackArgumentTokenFactor - Compute a TokenFactor to force all - /// the incoming stack arguments to be loaded from the stack. This is - /// used in tail call lowering to protect stack arguments from being - /// clobbered. + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, + SDValue N2); + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, + SDValue N2, SDValue N3); + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, + SDValue N2, SDValue N3, SDValue N4); + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, + SDValue N2, SDValue N3, SDValue N4, SDValue N5); + + /// Compute a TokenFactor to force all the incoming stack arguments to be + /// loaded from the stack. This is used in tail call lowering to protect + /// stack arguments from being clobbered. SDValue getStackArgumentTokenFactor(SDValue Chain); SDValue getMemcpy(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, bool AlwaysInline, - MachinePointerInfo DstPtrInfo, + bool isTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo); SDValue getMemmove(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src, - SDValue Size, unsigned Align, bool isVol, + SDValue Size, unsigned Align, bool isVol, bool isTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo); SDValue getMemset(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src, - SDValue Size, unsigned Align, bool isVol, + SDValue Size, unsigned Align, bool isVol, bool isTailCall, MachinePointerInfo DstPtrInfo); - /// getSetCC - Helper function to make it easier to build SetCC's if you just + /// Helper function to make it easier to build SetCC's if you just /// have an ISD::CondCode instead of an SDValue. /// SDValue getSetCC(SDLoc DL, EVT VT, SDValue LHS, SDValue RHS, @@ -726,8 +723,8 @@ public: return getNode(ISD::SETCC, DL, VT, LHS, RHS, getCondCode(Cond)); } - // getSelect - Helper function to make it easier to build Select's if you just - // have operands and don't want to check for vector. + /// Helper function to make it easier to build Select's if you just + /// have operands and don't want to check for vector. SDValue getSelect(SDLoc DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS) { assert(LHS.getValueType() == RHS.getValueType() && @@ -738,7 +735,7 @@ public: Cond, LHS, RHS); } - /// getSelectCC - Helper function to make it easier to build SelectCC's if you + /// Helper function to make it easier to build SelectCC's if you /// just have an ISD::CondCode instead of an SDValue. /// SDValue getSelectCC(SDLoc DL, SDValue LHS, SDValue RHS, @@ -747,12 +744,12 @@ public: LHS, RHS, True, False, getCondCode(Cond)); } - /// getVAArg - VAArg produces a result and token chain, and takes a pointer + /// VAArg produces a result and token chain, and takes a pointer /// and a source value as input. SDValue getVAArg(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, SDValue SV, unsigned Align); - /// getAtomicCmpSwap - Gets a node for an atomic cmpxchg op. There are two + /// Gets a node for an atomic cmpxchg op. There are two /// valid Opcodes. ISD::ATOMIC_CMO_SWAP produces the value loaded and a /// chain result. ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS produces the value loaded, /// a success flag (initially i1), and a chain. @@ -769,7 +766,7 @@ public: AtomicOrdering FailureOrdering, SynchronizationScope SynchScope); - /// getAtomic - Gets a node for an atomic op, produces result (if relevant) + /// Gets a node for an atomic op, produces result (if relevant) /// and chain and takes 2 operands. SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, const Value *PtrVal, @@ -780,15 +777,15 @@ public: AtomicOrdering Ordering, SynchronizationScope SynchScope); - /// getAtomic - Gets a node for an atomic op, produces result and chain and + /// Gets a node for an atomic op, produces result and chain and /// takes 1 operand. SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope); - /// getAtomic - Gets a node for an atomic op, produces result and chain and - /// takes N operands. + /// Gets a node for an atomic op, produces result and chain and takes N + /// operands. SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList, ArrayRef<SDValue> Ops, MachineMemOperand *MMO, AtomicOrdering SuccessOrdering, @@ -798,7 +795,7 @@ public: ArrayRef<SDValue> Ops, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope); - /// getMemIntrinsicNode - Creates a MemIntrinsicNode that may produce a + /// Creates a MemIntrinsicNode that may produce a /// result and takes a list of operands. Opcode may be INTRINSIC_VOID, /// INTRINSIC_W_CHAIN, or a target-specific opcode with a value not /// less than FIRST_TARGET_MEMORY_OPCODE. @@ -813,10 +810,10 @@ public: ArrayRef<SDValue> Ops, EVT MemVT, MachineMemOperand *MMO); - /// getMergeValues - Create a MERGE_VALUES node from the given operands. + /// Create a MERGE_VALUES node from the given operands. SDValue getMergeValues(ArrayRef<SDValue> Ops, SDLoc dl); - /// getLoad - Loads are not normal binary operators: their result type is not + /// Loads are not normal binary operators: their result type is not /// determined by their operands, and they produce a value AND a token chain. /// SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, @@ -848,8 +845,7 @@ public: SDValue Chain, SDValue Ptr, SDValue Offset, EVT MemVT, MachineMemOperand *MMO); - /// getStore - Helper function to build ISD::STORE nodes. - /// + /// Helper function to build ISD::STORE nodes. SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, unsigned Alignment, @@ -872,21 +868,25 @@ public: SDValue getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, bool IsTrunc); - /// getSrcValue - Construct a node to track a Value* through the backend. + SDValue getMaskedGather(SDVTList VTs, EVT VT, SDLoc dl, + ArrayRef<SDValue> Ops, MachineMemOperand *MMO); + SDValue getMaskedScatter(SDVTList VTs, EVT VT, SDLoc dl, + ArrayRef<SDValue> Ops, MachineMemOperand *MMO); + /// Construct a node to track a Value* through the backend. SDValue getSrcValue(const Value *v); - /// getMDNode - Return an MDNodeSDNode which holds an MDNode. + /// Return an MDNodeSDNode which holds an MDNode. SDValue getMDNode(const MDNode *MD); - /// getAddrSpaceCast - Return an AddrSpaceCastSDNode. + /// Return an AddrSpaceCastSDNode. SDValue getAddrSpaceCast(SDLoc dl, EVT VT, SDValue Ptr, unsigned SrcAS, unsigned DestAS); - /// getShiftAmountOperand - Return the specified value casted to + /// Return the specified value casted to /// the target's desired shift amount type. SDValue getShiftAmountOperand(EVT LHSTy, SDValue Op); - /// UpdateNodeOperands - *Mutate* the specified node in-place to have the + /// *Mutate* the specified node in-place to have the /// specified operands. If the resultant node already exists in the DAG, /// this does not modify the specified node, instead it returns the node that /// already exists. If the resultant node does not exist in the DAG, the @@ -902,7 +902,7 @@ public: SDValue Op3, SDValue Op4, SDValue Op5); SDNode *UpdateNodeOperands(SDNode *N, ArrayRef<SDValue> Ops); - /// SelectNodeTo - These are used for target selectors to *mutate* the + /// These are used for target selectors to *mutate* the /// specified node to have the specified return type, Target opcode, and /// operands. Note that target opcodes are stored as /// ~TargetOpcode in the node opcode field. The resultant node is returned. @@ -932,12 +932,12 @@ public: SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, SDVTList VTs, ArrayRef<SDValue> Ops); - /// MorphNodeTo - This *mutates* the specified node to have the specified + /// This *mutates* the specified node to have the specified /// return type, opcode, and operands. SDNode *MorphNodeTo(SDNode *N, unsigned Opc, SDVTList VTs, ArrayRef<SDValue> Ops); - /// getMachineNode - These are used for target selectors to create a new node + /// These are used for target selectors to create a new node /// with specified return type(s), MachineInstr opcode, and operands. /// /// Note that getMachineNode returns the resultant node. If there is already @@ -976,25 +976,20 @@ public: MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, SDVTList VTs, ArrayRef<SDValue> Ops); - /// getTargetExtractSubreg - A convenience function for creating - /// TargetInstrInfo::EXTRACT_SUBREG nodes. + /// A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes. SDValue getTargetExtractSubreg(int SRIdx, SDLoc DL, EVT VT, SDValue Operand); - /// getTargetInsertSubreg - A convenience function for creating - /// TargetInstrInfo::INSERT_SUBREG nodes. + /// A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes. SDValue getTargetInsertSubreg(int SRIdx, SDLoc DL, EVT VT, SDValue Operand, SDValue Subreg); - /// getNodeIfExists - Get the specified node if it's already available, or - /// else return NULL. + /// Get the specified node if it's already available, or else return NULL. SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs, ArrayRef<SDValue> Ops, bool nuw = false, bool nsw = false, bool exact = false); - /// getDbgValue - Creates a SDDbgValue node. - /// - /// SDNode + /// Creates a SDDbgValue node. SDDbgValue *getDbgValue(MDNode *Var, MDNode *Expr, SDNode *N, unsigned R, bool IsIndirect, uint64_t Off, DebugLoc DL, unsigned O); @@ -1007,16 +1002,16 @@ public: SDDbgValue *getFrameIndexDbgValue(MDNode *Var, MDNode *Expr, unsigned FI, uint64_t Off, DebugLoc DL, unsigned O); - /// RemoveDeadNode - Remove the specified node from the system. If any of its + /// Remove the specified node from the system. If any of its /// operands then becomes dead, remove them as well. Inform UpdateListener /// for each node deleted. void RemoveDeadNode(SDNode *N); - /// RemoveDeadNodes - This method deletes the unreachable nodes in the + /// This method deletes the unreachable nodes in the /// given list, and any nodes that become unreachable as a result. void RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes); - /// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. + /// Modify anything using 'From' to use 'To' instead. /// This can cause recursive merging of nodes in the DAG. Use the first /// version if 'From' is known to have a single result, use the second /// if you have two nodes with identical results (or if 'To' has a superset @@ -1035,30 +1030,29 @@ public: void ReplaceAllUsesWith(SDNode *From, SDNode *To); void ReplaceAllUsesWith(SDNode *From, const SDValue *To); - /// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving + /// Replace any uses of From with To, leaving /// uses of other values produced by From.Val alone. void ReplaceAllUsesOfValueWith(SDValue From, SDValue To); - /// ReplaceAllUsesOfValuesWith - Like ReplaceAllUsesOfValueWith, but - /// for multiple values at once. This correctly handles the case where + /// Like ReplaceAllUsesOfValueWith, but for multiple values at once. + /// This correctly handles the case where /// there is an overlap between the From values and the To values. void ReplaceAllUsesOfValuesWith(const SDValue *From, const SDValue *To, unsigned Num); - /// AssignTopologicalOrder - Topological-sort the AllNodes list and a + /// Topological-sort the AllNodes list and a /// assign a unique node id for each node in the DAG based on their /// topological order. Returns the number of nodes. unsigned AssignTopologicalOrder(); - /// RepositionNode - Move node N in the AllNodes list to be immediately + /// Move node N in the AllNodes list to be immediately /// before the given iterator Position. This may be used to update the /// topological ordering when the list of nodes is modified. void RepositionNode(allnodes_iterator Position, SDNode *N) { AllNodes.insert(Position, AllNodes.remove(N)); } - /// isCommutativeBinOp - Returns true if the opcode is a commutative binary - /// operation. + /// Returns true if the opcode is a commutative binary operation. static bool isCommutativeBinOp(unsigned Opcode) { // FIXME: This should get its info from the td file, so that we can include // target info. @@ -1099,19 +1093,19 @@ public: } } - /// AddDbgValue - Add a dbg_value SDNode. If SD is non-null that means the + /// Add a dbg_value SDNode. If SD is non-null that means the /// value is produced by SD. void AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter); - /// GetDbgValues - Get the debug values which reference the given SDNode. + /// Get the debug values which reference the given SDNode. ArrayRef<SDDbgValue*> GetDbgValues(const SDNode* SD) { return DbgInfo->getSDDbgValues(SD); } - /// TransferDbgValues - Transfer SDDbgValues. + /// Transfer SDDbgValues. void TransferDbgValues(SDValue From, SDValue To); - /// hasDebugValues - Return true if there are any SDDbgValue nodes associated + /// Return true if there are any SDDbgValue nodes associated /// with this SelectionDAG. bool hasDebugValues() const { return !DbgInfo->empty(); } @@ -1126,28 +1120,31 @@ public: void dump() const; - /// CreateStackTemporary - Create a stack temporary, suitable for holding the + /// Create a stack temporary, suitable for holding the /// specified value type. If minAlign is specified, the slot size will have /// at least that alignment. SDValue CreateStackTemporary(EVT VT, unsigned minAlign = 1); - /// CreateStackTemporary - Create a stack temporary suitable for holding + /// Create a stack temporary suitable for holding /// either of the specified value types. SDValue CreateStackTemporary(EVT VT1, EVT VT2); - /// FoldConstantArithmetic - - SDValue FoldConstantArithmetic(unsigned Opcode, EVT VT, + SDValue FoldConstantArithmetic(unsigned Opcode, SDLoc DL, EVT VT, SDNode *Cst1, SDNode *Cst2); - /// FoldSetCC - Constant fold a setcc to true or false. + SDValue FoldConstantArithmetic(unsigned Opcode, SDLoc DL, EVT VT, + const ConstantSDNode *Cst1, + const ConstantSDNode *Cst2); + + /// Constant fold a setcc to true or false. SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, SDLoc dl); - /// SignBitIsZero - Return true if the sign bit of Op is known to be zero. We - /// use this predicate to simplify operations downstream. + /// Return true if the sign bit of Op is known to be zero. + /// We use this predicate to simplify operations downstream. bool SignBitIsZero(SDValue Op, unsigned Depth = 0) const; - /// MaskedValueIsZero - Return true if 'Op & Mask' is known to be zero. We + /// Return true if 'Op & Mask' is known to be zero. We /// use this predicate to simplify operations downstream. Op and Mask are /// known to be the same type. bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth = 0) @@ -1160,7 +1157,7 @@ public: void computeKnownBits(SDValue Op, APInt &KnownZero, APInt &KnownOne, unsigned Depth = 0) const; - /// ComputeNumSignBits - Return the number of times the sign bit of the + /// Return the number of times the sign bit of the /// register is replicated into the other bits. We know that at least 1 bit /// is always equal to the sign bit (itself), but other cases can give us /// information. For example, immediately after an "SRA X, 2", we know that @@ -1169,26 +1166,26 @@ 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 + /// 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. + /// Test whether the given SDValue is known to never be NaN. bool isKnownNeverNaN(SDValue Op) const; - /// isKnownNeverZero - Test whether the given SDValue is known to never be + /// Test whether the given SDValue is known to never be /// positive or negative Zero. bool isKnownNeverZero(SDValue Op) const; - /// isEqualTo - Test whether two SDValues are known to compare equal. This + /// Test whether two SDValues are known to compare equal. This /// is true if they are the same value, or if one is negative zero and the /// other positive zero. bool isEqualTo(SDValue A, SDValue B) const; - /// UnrollVectorOp - Utility function used by legalize and lowering to + /// Utility function used by legalize and lowering to /// "unroll" a vector operation by splitting out the scalars and operating /// on each element individually. If the ResNE is 0, fully unroll the vector /// op. If ResNE is less than the width of the vector op, unroll up to ResNE. @@ -1196,43 +1193,40 @@ public: /// vector op and fill the end of the resulting vector with UNDEFS. SDValue UnrollVectorOp(SDNode *N, unsigned ResNE = 0); - /// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a - /// location that is 'Dist' units away from the location that the 'Base' load - /// is loading from. + /// Return true if LD is loading 'Bytes' bytes from a location that is 'Dist' + /// units away from the location that the 'Base' load is loading from. bool isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base, unsigned Bytes, int Dist) const; - /// InferPtrAlignment - Infer alignment of a load / store address. Return 0 if + /// Infer alignment of a load / store address. Return 0 if /// it cannot be inferred. unsigned InferPtrAlignment(SDValue Ptr) const; - /// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type + /// Compute the VTs needed for the low/hi parts of a type /// which is split (or expanded) into two not necessarily identical pieces. std::pair<EVT, EVT> GetSplitDestVTs(const EVT &VT) const; - /// SplitVector - Split the vector with EXTRACT_SUBVECTOR using the provides + /// Split the vector with EXTRACT_SUBVECTOR using the provides /// VTs and return the low/high part. std::pair<SDValue, SDValue> SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT); - /// SplitVector - Split the vector with EXTRACT_SUBVECTOR and return the - /// low/high part. + /// Split the vector with EXTRACT_SUBVECTOR and return the low/high part. std::pair<SDValue, SDValue> SplitVector(const SDValue &N, const SDLoc &DL) { EVT LoVT, HiVT; std::tie(LoVT, HiVT) = GetSplitDestVTs(N.getValueType()); return SplitVector(N, DL, LoVT, HiVT); } - /// SplitVectorOperand - Split the node's operand with EXTRACT_SUBVECTOR and + /// Split the node's operand with EXTRACT_SUBVECTOR and /// return the low/high part. std::pair<SDValue, SDValue> SplitVectorOperand(const SDNode *N, unsigned OpNo) { return SplitVector(N->getOperand(OpNo), SDLoc(N)); } - /// ExtractVectorElements - Append the extracted elements from Start to Count - /// out of the vector Op in Args. If Count is 0, all of the elements will be - /// extracted. + /// Append the extracted elements from Start to Count out of the vector Op + /// in Args. If Count is 0, all of the elements will be extracted. void ExtractVectorElements(SDValue Op, SmallVectorImpl<SDValue> &Args, unsigned Start = 0, unsigned Count = 0); @@ -1258,10 +1252,22 @@ private: SDValue N1, SDValue N2, bool nuw, bool nsw, bool exact); - /// VTList - List of non-single value types. + /// Look up the node specified by ID in CSEMap. If it exists, return it. If + /// not, return the insertion token that will make insertion faster. This + /// overload is for nodes other than Constant or ConstantFP, use the other one + /// for those. + SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos); + + /// Look up the node specified by ID in CSEMap. If it exists, return it. If + /// not, return the insertion token that will make insertion faster. Performs + /// additional processing for constant nodes. + SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, DebugLoc DL, + void *&InsertPos); + + /// List of non-single value types. FoldingSet<SDVTListNode> VTListMap; - /// CondCodeNodes - Maps to auto-CSE operations. + /// Maps to auto-CSE operations. std::vector<CondCodeSDNode*> CondCodeNodes; std::vector<SDNode*> ValueTypeNodes; diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index d53e66da5a71..a011e4c338c4 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -58,7 +58,7 @@ public: explicit SelectionDAGISel(TargetMachine &tm, CodeGenOpt::Level OL = CodeGenOpt::Default); - virtual ~SelectionDAGISel(); + ~SelectionDAGISel() override; const TargetLowering *getTargetLowering() const { return TLI; } @@ -80,12 +80,12 @@ public: 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 + /// addressing mode, according to the specified constraint. If this does /// not match or is not implemented, return true. The resultant operands /// (which will appear in the machine instruction) should be added to the /// OutOps vector. virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, - char ConstraintCode, + unsigned ConstraintID, std::vector<SDValue> &OutOps) { return true; } @@ -199,7 +199,7 @@ protected: /// SelectInlineAsmMemoryOperands - Calls to this are automatically generated /// by tblgen. Others should not call it. - void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops); + void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops, SDLoc DL); public: @@ -260,7 +260,10 @@ private: SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTs, ArrayRef<SDValue> Ops, unsigned EmitNodeInfo); - void PrepareEHLandingPad(); + /// Prepares the landing pad to take incoming values or do other EH + /// personality specific tasks. Returns true if the block should be + /// instruction selected, false if no code should be emitted for it. + bool PrepareEHLandingPad(); /// \brief Perform instruction selection on all basic blocks in the function. void SelectAllBasicBlocks(const Function &Fn); diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 933ec7fff483..daa19430192a 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -50,28 +50,10 @@ template <typename T> struct DenseMapInfo; template <typename T> struct simplify_type; template <typename T> struct ilist_traits; -/// isBinOpWithFlags - Returns true if the opcode is a binary operation -/// with flags. -static bool isBinOpWithFlags(unsigned Opcode) { - switch (Opcode) { - case ISD::SDIV: - case ISD::UDIV: - case ISD::SRA: - case ISD::SRL: - case ISD::MUL: - case ISD::ADD: - case ISD::SUB: - case ISD::SHL: - return true; - default: - return false; - } -} - void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr, bool force = false); -/// SDVTList - This represents a list of ValueType's that has been intern'd by +/// This represents a list of ValueType's that has been intern'd by /// a SelectionDAG. Instances of this simple value class are returned by /// SelectionDAG::getVTList(...). /// @@ -83,11 +65,11 @@ struct SDVTList { namespace ISD { /// Node predicates - /// isBuildVectorAllOnes - Return true if the specified node is a + /// Return true if the specified node is a /// BUILD_VECTOR where all of the elements are ~0 or undef. bool isBuildVectorAllOnes(const SDNode *N); - /// isBuildVectorAllZeros - Return true if the specified node is a + /// Return true if the specified node is a /// BUILD_VECTOR where all of the elements are 0 or undef. bool isBuildVectorAllZeros(const SDNode *N); @@ -95,18 +77,22 @@ namespace ISD { /// all ConstantSDNode or undef. bool isBuildVectorOfConstantSDNodes(const SDNode *N); - /// isScalarToVector - Return true if the specified node is a + /// \brief Return true if the specified node is a BUILD_VECTOR node of + /// all ConstantFPSDNode or undef. + bool isBuildVectorOfConstantFPSDNodes(const SDNode *N); + + /// Return true if the specified node is a /// ISD::SCALAR_TO_VECTOR node or a BUILD_VECTOR node where only the low /// element is not an undef. bool isScalarToVector(const SDNode *N); - /// allOperandsUndef - Return true if the node has at least one operand + /// Return true if the node has at least one operand /// and all operands of the specified node are ISD::UNDEF. bool allOperandsUndef(const SDNode *N); } // end llvm:ISD namespace //===----------------------------------------------------------------------===// -/// SDValue - Unlike LLVM values, Selection DAG nodes may return multiple +/// Unlike LLVM values, Selection DAG nodes may return multiple /// values as the result of a computation. Many nodes return multiple values, /// from loads (which define a token and a return value) to ADDC (which returns /// a result and a carry value), to calls (which may return an arbitrary number @@ -145,7 +131,7 @@ public: bool operator<(const SDValue &O) const { return std::tie(Node, ResNo) < std::tie(O.Node, O.ResNo); } - LLVM_EXPLICIT operator bool() const { + explicit operator bool() const { return Node != nullptr; } @@ -153,11 +139,10 @@ public: return SDValue(Node, R); } - // isOperandOf - Return true if this node is an operand of N. + // Return true if this node is an operand of N. bool isOperandOf(SDNode *N) const; - /// getValueType - Return the ValueType of the referenced return value. - /// + /// Return the ValueType of the referenced return value. inline EVT getValueType() const; /// Return the simple ValueType of the referenced return value. @@ -165,8 +150,7 @@ public: return getValueType().getSimpleVT(); } - /// getValueSizeInBits - Returns the size of the value in bits. - /// + /// Returns the size of the value in bits. unsigned getValueSizeInBits() const { return getValueType().getSizeInBits(); } @@ -184,26 +168,22 @@ public: inline bool isTargetOpcode() const; inline bool isMachineOpcode() const; inline unsigned getMachineOpcode() const; - inline const DebugLoc getDebugLoc() const; + inline const DebugLoc &getDebugLoc() const; inline void dump() const; inline void dumpr() const; - /// reachesChainWithoutSideEffects - Return true if this operand (which must - /// be a chain) reaches the specified operand without crossing any - /// side-effecting instructions. In practice, this looks through token - /// factors and non-volatile loads. In order to remain efficient, this only + /// Return true if this operand (which must be a chain) reaches the + /// specified operand without crossing any side-effecting instructions. + /// In practice, this looks through token factors and non-volatile loads. + /// In order to remain efficient, this only /// looks a couple of nodes in, it does not do an exhaustive search. bool reachesChainWithoutSideEffects(SDValue Dest, unsigned Depth = 2) const; - /// use_empty - Return true if there are no nodes using value ResNo - /// of Node. - /// + /// Return true if there are no nodes using value ResNo of Node. inline bool use_empty() const; - /// hasOneUse - Return true if there is exactly one node using value - /// ResNo of Node. - /// + /// Return true if there is exactly one node using value ResNo of Node. inline bool hasOneUse() const; }; @@ -230,7 +210,7 @@ template<> struct DenseMapInfo<SDValue> { template <> struct isPodLike<SDValue> { static const bool value = true; }; -/// simplify_type specializations - Allow casting operators to work directly on +/// Allow casting operators to work directly on /// SDValues as if they were SDNode*'s. template<> struct simplify_type<SDValue> { typedef SDNode* SimpleType; @@ -245,7 +225,7 @@ template<> struct simplify_type<const SDValue> { } }; -/// SDUse - Represents a use of a SDNode. This class holds an SDValue, +/// Represents a use of a SDNode. This class holds an SDValue, /// which records the SDNode being used and the result number, a /// pointer to the SDNode using the value, and Next and Prev pointers, /// which link together all the uses of an SDNode. @@ -259,8 +239,8 @@ class SDUse { /// this operand. SDUse **Prev, *Next; - SDUse(const SDUse &U) LLVM_DELETED_FUNCTION; - void operator=(const SDUse &U) LLVM_DELETED_FUNCTION; + SDUse(const SDUse &U) = delete; + void operator=(const SDUse &U) = delete; public: SDUse() : Val(), User(nullptr), Prev(nullptr), Next(nullptr) {} @@ -272,30 +252,30 @@ public: /// the SDValue. const SDValue &get() const { return Val; } - /// getUser - This returns the SDNode that contains this Use. + /// This returns the SDNode that contains this Use. SDNode *getUser() { return User; } - /// getNext - Get the next SDUse in the use list. + /// Get the next SDUse in the use list. SDUse *getNext() const { return Next; } - /// getNode - Convenience function for get().getNode(). + /// Convenience function for get().getNode(). SDNode *getNode() const { return Val.getNode(); } - /// getResNo - Convenience function for get().getResNo(). + /// Convenience function for get().getResNo(). unsigned getResNo() const { return Val.getResNo(); } - /// getValueType - Convenience function for get().getValueType(). + /// Convenience function for get().getValueType(). EVT getValueType() const { return Val.getValueType(); } - /// operator== - Convenience function for get().operator== + /// Convenience function for get().operator== bool operator==(const SDValue &V) const { return Val == V; } - /// operator!= - Convenience function for get().operator!= + /// Convenience function for get().operator!= bool operator!=(const SDValue &V) const { return Val != V; } - /// operator< - Convenience function for get().operator< + /// Convenience function for get().operator< bool operator<(const SDValue &V) const { return Val < V; } @@ -306,13 +286,13 @@ private: void setUser(SDNode *p) { User = p; } - /// set - Remove this use from its existing use list, assign it the + /// Remove this use from its existing use list, assign it the /// given value, and add it to the new value's node's use list. inline void set(const SDValue &V); - /// setInitial - like set, but only supports initializing a newly-allocated + /// Like set, but only supports initializing a newly-allocated /// SDUse with a non-null value. inline void setInitial(const SDValue &V); - /// setNode - like set, but only sets the Node portion of the value, + /// Like set, but only sets the Node portion of the value, /// leaving the ResNo portion unmodified. inline void setNode(SDNode *N); @@ -339,47 +319,45 @@ template<> struct simplify_type<SDUse> { }; -/// SDNode - Represents one node in the SelectionDAG. +/// Represents one node in the SelectionDAG. /// class SDNode : public FoldingSetNode, public ilist_node<SDNode> { private: - /// NodeType - The operation that this node performs. - /// + /// The operation that this node performs. int16_t NodeType; - /// OperandsNeedDelete - This is true if OperandList was new[]'d. If true, + /// This is true if OperandList was new[]'d. If true, /// then they will be delete[]'d when the node is destroyed. uint16_t OperandsNeedDelete : 1; - /// HasDebugValue - This tracks whether this node has one or more dbg_value + /// This tracks whether this node has one or more dbg_value /// nodes corresponding to it. uint16_t HasDebugValue : 1; protected: - /// SubclassData - This member is defined by this class, but is not used for + /// This member is defined by this class, but is not used for /// anything. Subclasses can use it to hold whatever state they find useful. /// This field is initialized to zero by the ctor. uint16_t SubclassData : 14; private: - /// NodeId - Unique id per SDNode in the DAG. + /// Unique id per SDNode in the DAG. int NodeId; - /// OperandList - The values that are used by this operation. - /// + /// The values that are used by this operation. SDUse *OperandList; - /// ValueList - The types of the values this node defines. SDNode's may + /// The types of the values this node defines. SDNode's may /// define multiple values simultaneously. const EVT *ValueList; - /// UseList - List of uses for this SDNode. + /// List of uses for this SDNode. SDUse *UseList; - /// NumOperands/NumValues - The number of entries in the Operand/Value list. + /// The number of entries in the Operand/Value list. unsigned short NumOperands, NumValues; - /// debugLoc - source line information. + /// Source line information. DebugLoc debugLoc; // The ordering of the SDNodes. It roughly corresponds to the ordering of the @@ -389,7 +367,7 @@ private: // this ordering. unsigned IROrder; - /// getValueTypeList - Return a pointer to the specified value type. + /// Return a pointer to the specified value type. static const EVT *getValueTypeList(EVT VT); friend class SelectionDAG; @@ -400,17 +378,17 @@ public: // Accessors // - /// getOpcode - Return the SelectionDAG opcode value for this node. For + /// Return the SelectionDAG opcode value for this node. For /// pre-isel nodes (those for which isMachineOpcode returns false), these /// are the opcode values in the ISD and <target>ISD namespaces. For /// post-isel opcodes, see getMachineOpcode. unsigned getOpcode() const { return (unsigned short)NodeType; } - /// isTargetOpcode - Test if this node has a target-specific opcode (in the + /// Test if this node has a target-specific opcode (in the /// \<target\>ISD namespace). bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; } - /// isTargetMemoryOpcode - Test if this node has a target-specific + /// Test if this node has a target-specific /// memory-referencing opcode (in the \<target\>ISD namespace and /// greater than FIRST_TARGET_MEMORY_OPCODE). bool isTargetMemoryOpcode() const { @@ -427,11 +405,11 @@ public: NodeType == ISD::INTRINSIC_VOID) && ((SubclassData >> 13) & 1); } - /// isMachineOpcode - Test if this node has a post-isel opcode, directly + /// Test if this node has a post-isel opcode, directly /// corresponding to a MachineInstr opcode. bool isMachineOpcode() const { return NodeType < 0; } - /// getMachineOpcode - This may only be called if isMachineOpcode returns + /// This may only be called if isMachineOpcode returns /// true. It returns the MachineInstr opcode value that the node's opcode /// corresponds to. unsigned getMachineOpcode() const { @@ -439,50 +417,44 @@ public: return ~NodeType; } - /// getHasDebugValue - get this bit. + /// Get this bit. bool getHasDebugValue() const { return HasDebugValue; } - /// setHasDebugValue - set this bit. + /// Set this bit. void setHasDebugValue(bool b) { HasDebugValue = b; } - /// use_empty - Return true if there are no uses of this node. - /// + /// Return true if there are no uses of this node. bool use_empty() const { return UseList == nullptr; } - /// hasOneUse - Return true if there is exactly one use of this node. - /// + /// Return true if there is exactly one use of this node. bool hasOneUse() const { return !use_empty() && std::next(use_begin()) == use_end(); } - /// use_size - Return the number of uses of this node. This method takes + /// Return the number of uses of this node. This method takes /// time proportional to the number of uses. - /// size_t use_size() const { return std::distance(use_begin(), use_end()); } - /// getNodeId - Return the unique node id. - /// + /// Return the unique node id. int getNodeId() const { return NodeId; } - /// setNodeId - Set unique node id. + /// Set unique node id. void setNodeId(int Id) { NodeId = Id; } - /// getIROrder - Return the node ordering. - /// + /// Return the node ordering. unsigned getIROrder() const { return IROrder; } - /// setIROrder - Set the node ordering. - /// + /// Set the node ordering. void setIROrder(unsigned Order) { IROrder = Order; } - /// getDebugLoc - Return the source location info. - const DebugLoc getDebugLoc() const { return debugLoc; } + /// Return the source location info. + const DebugLoc &getDebugLoc() const { return debugLoc; } - /// setDebugLoc - Set source location info. Try to avoid this, putting + /// Set source location info. Try to avoid this, putting /// it in the constructor is preferable. - void setDebugLoc(const DebugLoc dl) { debugLoc = dl; } + void setDebugLoc(DebugLoc dl) { debugLoc = std::move(dl); } - /// use_iterator - This class provides iterator support for SDUse + /// This class provides iterator support for SDUse /// operands that use a specific SDNode. class use_iterator : public std::iterator<std::forward_iterator_tag, SDUse, ptrdiff_t> { @@ -506,7 +478,7 @@ public: return !operator==(x); } - /// atEnd - return true if this iterator is at the end of uses list. + /// Return true if this iterator is at the end of uses list. bool atEnd() const { return Op == nullptr; } // Iterator traversal: forward iteration only. @@ -530,17 +502,14 @@ public: SDUse &getUse() const { return *Op; } - /// getOperandNo - Retrieve the operand # of this use in its user. - /// + /// Retrieve the operand # of this use in its user. unsigned getOperandNo() const { assert(Op && "Cannot dereference end iterator!"); return (unsigned)(Op - Op->getUser()->OperandList); } }; - /// use_begin/use_end - Provide iteration support to walk over all uses - /// of an SDNode. - + /// Provide iteration support to walk over all uses of an SDNode. use_iterator use_begin() const { return use_iterator(UseList); } @@ -554,37 +523,34 @@ public: return iterator_range<use_iterator>(use_begin(), use_end()); } - /// hasNUsesOfValue - Return true if there are exactly NUSES uses of the - /// indicated value. This method ignores uses of other values defined by this - /// operation. + /// Return true if there are exactly NUSES uses of the indicated value. + /// This method ignores uses of other values defined by this operation. bool hasNUsesOfValue(unsigned NUses, unsigned Value) const; - /// hasAnyUseOfValue - Return true if there are any use of the indicated - /// value. This method ignores uses of other values defined by this operation. + /// Return true if there are any use of the indicated value. + /// This method ignores uses of other values defined by this operation. bool hasAnyUseOfValue(unsigned Value) const; - /// isOnlyUserOf - Return true if this node is the only use of N. - /// + /// Return true if this node is the only use of N. bool isOnlyUserOf(SDNode *N) const; - /// isOperandOf - Return true if this node is an operand of N. - /// + /// Return true if this node is an operand of N. bool isOperandOf(SDNode *N) const; - /// isPredecessorOf - Return true if this node is a predecessor of N. + /// Return true if this node is a predecessor of N. /// NOTE: Implemented on top of hasPredecessor and every bit as /// expensive. Use carefully. bool isPredecessorOf(const SDNode *N) const { return N->hasPredecessor(this); } - /// hasPredecessor - Return true if N is a predecessor of this node. + /// Return true if N is a predecessor of this node. /// N is either an operand of this node, or can be reached by recursively /// traversing up the operands. /// NOTE: This is an expensive method. Use it carefully. bool hasPredecessor(const SDNode *N) const; - /// hasPredecesorHelper - Return true if N is a predecessor of this node. + /// Return true if N is a predecessor of this node. /// N is either an operand of this node, or can be reached by recursively /// traversing up the operands. /// In this helper the Visited and worklist sets are held externally to @@ -597,12 +563,10 @@ public: SmallPtrSetImpl<const SDNode *> &Visited, SmallVectorImpl<const SDNode *> &Worklist) const; - /// getNumOperands - Return the number of values used by this operation. - /// + /// Return the number of values used by this operation. unsigned getNumOperands() const { return NumOperands; } - /// getConstantOperandVal - Helper method returns the integer value of a - /// ConstantSDNode operand. + /// Helper method returns the integer value of a ConstantSDNode operand. uint64_t getConstantOperandVal(unsigned Num) const; const SDValue &getOperand(unsigned Num) const { @@ -620,7 +584,7 @@ public: return X; } - /// getGluedNode - If this node has a glue operand, return the node + /// 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 && @@ -645,7 +609,7 @@ public: return FoundNode; } - /// getGluedUser - If this node has a glue value with a user, return + /// If this node has a glue value with a user, return /// the user (there is at most one). Otherwise return NULL. SDNode *getGluedUser() const { for (use_iterator UI = use_begin(), UE = use_end(); UI != UE; ++UI) @@ -654,26 +618,21 @@ public: return nullptr; } - /// getNumValues - Return the number of values defined/returned by this - /// operator. - /// + /// Return the number of values defined/returned by this operator. unsigned getNumValues() const { return NumValues; } - /// getValueType - Return the type of a specified result. - /// + /// Return the type of a specified result. EVT getValueType(unsigned ResNo) const { assert(ResNo < NumValues && "Illegal result number!"); return ValueList[ResNo]; } /// Return the type of a specified result as a simple type. - /// MVT getSimpleValueType(unsigned ResNo) const { return getValueType(ResNo).getSimpleVT(); } - /// getValueSizeInBits - Returns MVT::getSizeInBits(getValueType(ResNo)). - /// + /// Returns MVT::getSizeInBits(getValueType(ResNo)). unsigned getValueSizeInBits(unsigned ResNo) const { return getValueType(ResNo).getSizeInBits(); } @@ -682,8 +641,7 @@ public: value_iterator value_begin() const { return ValueList; } value_iterator value_end() const { return ValueList+NumValues; } - /// getOperationName - Return the opcode of this operation for printing. - /// + /// Return the opcode of this operation for printing. std::string getOperationName(const SelectionDAG *G = nullptr) const; static const char* getIndexedModeName(ISD::MemIndexedMode AM); void print_types(raw_ostream &OS, const SelectionDAG *G) const; @@ -691,7 +649,7 @@ public: void print(raw_ostream &OS, const SelectionDAG *G = nullptr) const; void printr(raw_ostream &OS, const SelectionDAG *G = nullptr) const; - /// printrFull - Print a SelectionDAG node and all children down to + /// Print a SelectionDAG node and all children down to /// the leaves. The given SelectionDAG allows target-specific nodes /// to be printed in human-readable form. Unlike printr, this will /// print the whole DAG, including children that appear multiple @@ -699,7 +657,7 @@ public: /// void printrFull(raw_ostream &O, const SelectionDAG *G = nullptr) const; - /// printrWithDepth - Print a SelectionDAG node and children up to + /// Print a SelectionDAG node and children up to /// depth "depth." The given SelectionDAG allows target-specific /// nodes to be printed in human-readable form. Unlike printr, this /// will print children that appear multiple times wherever they are @@ -709,30 +667,29 @@ public: unsigned depth = 100) const; - /// dump - Dump this node, for debugging. + /// Dump this node, for debugging. void dump() const; - /// dumpr - Dump (recursively) this node and its use-def subgraph. + /// Dump (recursively) this node and its use-def subgraph. void dumpr() const; - /// dump - Dump this node, for debugging. + /// Dump this node, for debugging. /// The given SelectionDAG allows target-specific nodes to be printed /// in human-readable form. void dump(const SelectionDAG *G) const; - /// dumpr - Dump (recursively) this node and its use-def subgraph. + /// Dump (recursively) this node and its use-def subgraph. /// The given SelectionDAG allows target-specific nodes to be printed /// in human-readable form. void dumpr(const SelectionDAG *G) const; - /// dumprFull - printrFull to dbgs(). The given SelectionDAG allows + /// printrFull to dbgs(). The given SelectionDAG allows /// target-specific nodes to be printed in human-readable form. /// Unlike dumpr, this will print the whole DAG, including children /// that appear multiple times. - /// void dumprFull(const SelectionDAG *G = nullptr) const; - /// dumprWithDepth - printrWithDepth to dbgs(). The given + /// printrWithDepth to dbgs(). The given /// SelectionDAG allows target-specific nodes to be printed in /// human-readable form. Unlike dumpr, this will print children /// that appear multiple times wherever they are used. @@ -740,12 +697,10 @@ public: void dumprWithDepth(const SelectionDAG *G = nullptr, unsigned depth = 100) const; - /// Profile - Gather unique data for the node. - /// + /// Gather unique data for the node. void Profile(FoldingSetNodeID &ID) const; - /// addUse - This method should only be used by the SDUse class. - /// + /// This method should only be used by the SDUse class. void addUse(SDUse &U) { U.addToList(&UseList); } protected: @@ -754,14 +709,13 @@ protected: return Ret; } - SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs, + SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, ArrayRef<SDValue> Ops) - : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false), - SubclassData(0), NodeId(-1), - OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr), - ValueList(VTs.VTs), UseList(nullptr), - NumOperands(Ops.size()), NumValues(VTs.NumVTs), - debugLoc(dl), IROrder(Order) { + : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false), + SubclassData(0), NodeId(-1), + OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr), + ValueList(VTs.VTs), UseList(nullptr), NumOperands(Ops.size()), + NumValues(VTs.NumVTs), debugLoc(std::move(dl)), IROrder(Order) { assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumOperands == Ops.size() && "NumOperands wasn't wide enough for its operands!"); @@ -777,17 +731,17 @@ protected: /// This constructor adds no operands itself; operands can be /// set later with InitOperands. - SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs) - : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), - SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), - UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), debugLoc(dl), - IROrder(Order) { + SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs) + : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), + SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), + UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), + debugLoc(std::move(dl)), IROrder(Order) { assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumValues == VTs.NumVTs && "NumValues wasn't wide enough for its operands!"); } - /// InitOperands - Initialize the operands list of this with 1 operand. + /// Initialize the operands list of this with 1 operand. void InitOperands(SDUse *Ops, const SDValue &Op0) { Ops[0].setUser(this); Ops[0].setInitial(Op0); @@ -796,7 +750,7 @@ protected: checkForCycles(this); } - /// InitOperands - Initialize the operands list of this with 2 operands. + /// Initialize the operands list of this with 2 operands. void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1) { Ops[0].setUser(this); Ops[0].setInitial(Op0); @@ -807,7 +761,7 @@ protected: checkForCycles(this); } - /// InitOperands - Initialize the operands list of this with 3 operands. + /// Initialize the operands list of this with 3 operands. void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1, const SDValue &Op2) { Ops[0].setUser(this); @@ -821,7 +775,7 @@ protected: checkForCycles(this); } - /// InitOperands - Initialize the operands list of this with 4 operands. + /// Initialize the operands list of this with 4 operands. void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1, const SDValue &Op2, const SDValue &Op3) { Ops[0].setUser(this); @@ -837,7 +791,7 @@ protected: checkForCycles(this); } - /// InitOperands - Initialize the operands list of this with N operands. + /// Initialize the operands list of this with N operands. void InitOperands(SDUse *Ops, const SDValue *Vals, unsigned N) { for (unsigned i = 0; i != N; ++i) { Ops[i].setUser(this); @@ -850,8 +804,7 @@ protected: checkForCycles(this); } - /// DropOperands - Release the operands and set this node to have - /// zero operands. + /// Release the operands and set this node to have zero operands. void DropOperands(); }; @@ -945,7 +898,7 @@ inline bool SDValue::use_empty() const { inline bool SDValue::hasOneUse() const { return Node->hasNUsesOfValue(1, ResNo); } -inline const DebugLoc SDValue::getDebugLoc() const { +inline const DebugLoc &SDValue::getDebugLoc() const { return Node->getDebugLoc(); } inline void SDValue::dump() const { @@ -973,7 +926,63 @@ inline void SDUse::setNode(SDNode *N) { if (N) N->addUse(*this); } -/// UnarySDNode - This class is used for single-operand SDNodes. This is solely +/// These are IR-level optimization flags that may be propagated to SDNodes. +/// TODO: This data structure should be shared by the IR optimizer and the +/// the backend. +struct SDNodeFlags { +private: + bool NoUnsignedWrap : 1; + bool NoSignedWrap : 1; + bool Exact : 1; + bool UnsafeAlgebra : 1; + bool NoNaNs : 1; + bool NoInfs : 1; + bool NoSignedZeros : 1; + bool AllowReciprocal : 1; + +public: + /// Default constructor turns off all optimization flags. + SDNodeFlags() { + NoUnsignedWrap = false; + NoSignedWrap = false; + Exact = false; + UnsafeAlgebra = false; + NoNaNs = false; + NoInfs = false; + NoSignedZeros = false; + AllowReciprocal = false; + } + + // These are mutators for each flag. + void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; } + void setNoSignedWrap(bool b) { NoSignedWrap = b; } + void setExact(bool b) { Exact = b; } + void setUnsafeAlgebra(bool b) { UnsafeAlgebra = b; } + void setNoNaNs(bool b) { NoNaNs = b; } + void setNoInfs(bool b) { NoInfs = b; } + void setNoSignedZeros(bool b) { NoSignedZeros = b; } + void setAllowReciprocal(bool b) { AllowReciprocal = b; } + + // These are accessors for each flag. + bool hasNoUnsignedWrap() const { return NoUnsignedWrap; } + bool hasNoSignedWrap() const { return NoSignedWrap; } + bool hasExact() const { return Exact; } + bool hasUnsafeAlgebra() const { return UnsafeAlgebra; } + bool hasNoNaNs() const { return NoNaNs; } + bool hasNoInfs() const { return NoInfs; } + bool hasNoSignedZeros() const { return NoSignedZeros; } + bool hasAllowReciprocal() const { return AllowReciprocal; } + + /// Return a raw encoding of the flags. + /// This function should only be used to add data to the NodeID value. + unsigned getRawFlags() const { + return (NoUnsignedWrap << 0) | (NoSignedWrap << 1) | (Exact << 2) | + (UnsafeAlgebra << 3) | (NoNaNs << 4) | (NoInfs << 5) | + (NoSignedZeros << 6) | (AllowReciprocal << 7); + } +}; + +/// This class is used for single-operand SDNodes. This is solely /// to allow co-allocation of node operands with the node itself. class UnarySDNode : public SDNode { SDUse Op; @@ -985,7 +994,7 @@ public: } }; -/// BinarySDNode - This class is used for two-operand SDNodes. This is solely +/// This class is used for two-operand SDNodes. This is solely /// to allow co-allocation of node operands with the node itself. class BinarySDNode : public SDNode { SDUse Ops[2]; @@ -997,37 +1006,37 @@ public: } }; -/// BinaryWithFlagsSDNode - This class is an extension of BinarySDNode +/// Returns true if the opcode is a binary operation with flags. +static bool isBinOpWithFlags(unsigned Opcode) { + switch (Opcode) { + case ISD::SDIV: + case ISD::UDIV: + case ISD::SRA: + case ISD::SRL: + case ISD::MUL: + case ISD::ADD: + case ISD::SUB: + case ISD::SHL: + return true; + default: + return false; + } +} + +/// This class is an extension of BinarySDNode /// used from those opcodes that have associated extra flags. class BinaryWithFlagsSDNode : public BinarySDNode { - enum { NUW = (1 << 0), NSW = (1 << 1), EXACT = (1 << 2) }; - public: + SDNodeFlags Flags; BinaryWithFlagsSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, SDValue X, SDValue Y) - : BinarySDNode(Opc, Order, dl, VTs, X, Y) {} - /// getRawSubclassData - Return the SubclassData value, which contains an - /// encoding of the flags. - /// This function should be used to add subclass data to the NodeID value. - unsigned getRawSubclassData() const { return SubclassData; } - void setHasNoUnsignedWrap(bool b) { - SubclassData = (SubclassData & ~NUW) | (b ? NUW : 0); - } - void setHasNoSignedWrap(bool b) { - SubclassData = (SubclassData & ~NSW) | (b ? NSW : 0); - } - void setIsExact(bool b) { - SubclassData = (SubclassData & ~EXACT) | (b ? EXACT : 0); - } - bool hasNoUnsignedWrap() const { return SubclassData & NUW; } - bool hasNoSignedWrap() const { return SubclassData & NSW; } - bool isExact() const { return SubclassData & EXACT; } + : BinarySDNode(Opc, Order, dl, VTs, X, Y), Flags() {} static bool classof(const SDNode *N) { return isBinOpWithFlags(N->getOpcode()); } }; -/// TernarySDNode - This class is used for three-operand SDNodes. This is solely +/// This class is used for three-operand SDNodes. This is solely /// to allow co-allocation of node operands with the node itself. class TernarySDNode : public SDNode { SDUse Ops[3]; @@ -1040,7 +1049,7 @@ public: }; -/// HandleSDNode - This class is used to form a handle around another node that +/// This class is used to form a handle around another node that /// is persistent and is updated across invocations of replaceAllUsesWith on its /// operand. This node should be directly created by end-users and not added to /// the AllNodes list. @@ -1072,14 +1081,14 @@ public: } }; -/// Abstact virtual class for operations for memory operations +/// This is an abstract virtual class for memory operations. class MemSDNode : public SDNode { private: - // MemoryVT - VT of in-memory value. + // VT of in-memory value. EVT MemoryVT; protected: - /// MMO - Memory reference information. + /// Memory reference information. MachineMemOperand *MMO; public: @@ -1100,7 +1109,7 @@ public: return MMO->getAlignment(); } - /// getRawSubclassData - Return the SubclassData value, which contains an + /// Return the SubclassData value, which contains an /// encoding of the volatile flag, as well as bits used by subclasses. This /// function should only be used to compute a FoldingSetNodeID value. unsigned getRawSubclassData() const { @@ -1129,10 +1138,10 @@ public: /// Returns the Ranges that describes the dereference. const MDNode *getRanges() const { return MMO->getRanges(); } - /// getMemoryVT - Return the type of the in-memory value. + /// Return the type of the in-memory value. EVT getMemoryVT() const { return MemoryVT; } - /// getMemOperand - Return a MachineMemOperand object describing the memory + /// Return a MachineMemOperand object describing the memory /// reference performed by operation. MachineMemOperand *getMemOperand() const { return MMO; } @@ -1140,12 +1149,12 @@ public: return MMO->getPointerInfo(); } - /// getAddressSpace - Return the address space for the associated pointer + /// Return the address space for the associated pointer unsigned getAddressSpace() const { return getPointerInfo().getAddrSpace(); } - /// refineAlignment - Update this MemSDNode's MachineMemOperand information + /// Update this MemSDNode's MachineMemOperand information /// to reflect the alignment of NewMMO, if it has a greater alignment. /// This must only be used when the new alignment applies to all users of /// this MachineMemOperand. @@ -1182,13 +1191,14 @@ public: N->getOpcode() == ISD::ATOMIC_STORE || N->getOpcode() == ISD::MLOAD || N->getOpcode() == ISD::MSTORE || + N->getOpcode() == ISD::MGATHER || + N->getOpcode() == ISD::MSCATTER || N->isMemIntrinsic() || N->isTargetMemoryOpcode(); } }; -/// AtomicSDNode - A SDNode reprenting atomic operations. -/// +/// This is an SDNode representing atomic operations. class AtomicSDNode : public MemSDNode { SDUse Ops[4]; @@ -1301,7 +1311,7 @@ public: } }; -/// MemIntrinsicSDNode - This SDNode is used for target intrinsics that touch +/// This SDNode is used for target intrinsics that touch /// memory and need an associated MachineMemOperand. Its opcode may be /// INTRINSIC_VOID, INTRINSIC_W_CHAIN, PREFETCH, or a target-specific opcode /// with a value not less than FIRST_TARGET_MEMORY_OPCODE. @@ -1324,7 +1334,7 @@ public: } }; -/// ShuffleVectorSDNode - This SDNode is used to implement the code generator +/// This SDNode is used to implement the code generator /// support for the llvm IR shufflevector instruction. It combines elements /// from two input vectors into a new input vector, with the selection and /// ordering of elements determined by an array of integers, referred to as @@ -1368,6 +1378,21 @@ public: } static bool isSplatMask(const int *Mask, EVT VT); + /// Change values in a shuffle permute mask assuming + /// the two vector operands have swapped position. + static void commuteMask(SmallVectorImpl<int> &Mask) { + unsigned NumElems = Mask.size(); + for (unsigned i = 0; i != NumElems; ++i) { + int idx = Mask[i]; + if (idx < 0) + continue; + else if (idx < (int)NumElems) + Mask[i] = idx + NumElems; + else + Mask[i] = idx - NumElems; + } + } + static bool classof(const SDNode *N) { return N->getOpcode() == ISD::VECTOR_SHUFFLE; } @@ -1376,9 +1401,10 @@ public: class ConstantSDNode : public SDNode { const ConstantInt *Value; friend class SelectionDAG; - ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, EVT VT) + ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, + DebugLoc DL, EVT VT) : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, - 0, DebugLoc(), getSDVTList(VT)), Value(val) { + 0, DL, getSDVTList(VT)), Value(val) { SubclassData |= (uint16_t)isOpaque; } public: @@ -1403,28 +1429,28 @@ public: class ConstantFPSDNode : public SDNode { const ConstantFP *Value; friend class SelectionDAG; - ConstantFPSDNode(bool isTarget, const ConstantFP *val, EVT VT) + ConstantFPSDNode(bool isTarget, const ConstantFP *val, DebugLoc DL, EVT VT) : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, - 0, DebugLoc(), getSDVTList(VT)), Value(val) { + 0, DL, getSDVTList(VT)), Value(val) { } public: const APFloat& getValueAPF() const { return Value->getValueAPF(); } const ConstantFP *getConstantFPValue() const { return Value; } - /// isZero - Return true if the value is positive or negative zero. + /// Return true if the value is positive or negative zero. bool isZero() const { return Value->isZero(); } - /// isNaN - Return true if the value is a NaN. + /// Return true if the value is a NaN. bool isNaN() const { return Value->isNaN(); } - /// isInfinity - Return true if the value is an infinity + /// Return true if the value is an infinity bool isInfinity() const { return Value->isInfinity(); } - /// isNegative - Return true if the value is negative. + /// Return true if the value is negative. bool isNegative() const { return Value->isNegative(); } - /// isExactlyValue - We don't rely on operator== working on double values, as + /// We don't rely on operator== working on double values, as /// it returns true for things that are clearly not equal, like -0.0 and 0.0. /// As such, this method can be used to do an exact bit-for-bit comparison of /// two floating point values. @@ -1608,13 +1634,12 @@ public: } }; -/// BuildVectorSDNode - A "pseudo-class" with methods for operating on -/// BUILD_VECTORs. +/// A "pseudo-class" with methods for operating on BUILD_VECTORs. class BuildVectorSDNode : public SDNode { // These are constructed as SDNodes and then cast to BuildVectorSDNodes. - explicit BuildVectorSDNode() LLVM_DELETED_FUNCTION; + explicit BuildVectorSDNode() = delete; public: - /// isConstantSplat - Check if this is a constant splat, and if so, find the + /// Check if this is a constant splat, and if so, find the /// smallest element size that splats the vector. If MinSplatBits is /// nonzero, the element size must be at least that large. Note that the /// splat element may be the entire vector (i.e., a one element vector). @@ -1657,7 +1682,7 @@ public: } }; -/// SrcValueSDNode - An SDNode that holds an arbitrary LLVM IR Value. This is +/// An SDNode that holds an arbitrary LLVM IR Value. This is /// used when the SelectionDAG needs to make a simple reference to something /// in the LLVM IR representation. /// @@ -1669,7 +1694,7 @@ class SrcValueSDNode : public SDNode { : SDNode(ISD::SRCVALUE, 0, DebugLoc(), getSDVTList(MVT::Other)), V(v) {} public: - /// getValue - return the contained Value. + /// Return the contained Value. const Value *getValue() const { return V; } static bool classof(const SDNode *N) { @@ -1796,7 +1821,7 @@ public: } }; -/// CvtRndSatSDNode - NOTE: avoid using this node as this may disappear in the +/// NOTE: avoid using this node as this may disappear in the /// future and most targets don't support it. class CvtRndSatSDNode : public SDNode { ISD::CvtCode CvtCode; @@ -1815,7 +1840,7 @@ public: } }; -/// VTSDNode - This class is used to represent EVT's, which are used +/// This class is used to represent EVT's, which are used /// to parameterize some operations. class VTSDNode : public SDNode { EVT ValueType; @@ -1833,8 +1858,7 @@ public: } }; -/// LSBaseSDNode - Base class for LoadSDNode and StoreSDNode -/// +/// Base class for LoadSDNode and StoreSDNode class LSBaseSDNode : public MemSDNode { //! Operand array for load and store /*! @@ -1860,16 +1884,16 @@ public: return getOperand(getOpcode() == ISD::LOAD ? 2 : 3); } - /// getAddressingMode - Return the addressing mode for this load or store: + /// Return the addressing mode for this load or store: /// unindexed, pre-inc, pre-dec, post-inc, or post-dec. ISD::MemIndexedMode getAddressingMode() const { return ISD::MemIndexedMode((SubclassData >> 2) & 7); } - /// isIndexed - Return true if this is a pre/post inc/dec load/store. + /// Return true if this is a pre/post inc/dec load/store. bool isIndexed() const { return getAddressingMode() != ISD::UNINDEXED; } - /// isUnindexed - Return true if this is NOT a pre/post inc/dec load/store. + /// Return true if this is NOT a pre/post inc/dec load/store. bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; } static bool classof(const SDNode *N) { @@ -1878,8 +1902,7 @@ public: } }; -/// LoadSDNode - This class is used to represent ISD::LOAD nodes. -/// +/// This class is used to represent ISD::LOAD nodes. class LoadSDNode : public LSBaseSDNode { friend class SelectionDAG; LoadSDNode(SDValue *ChainPtrOff, unsigned Order, DebugLoc dl, SDVTList VTs, @@ -1893,7 +1916,7 @@ class LoadSDNode : public LSBaseSDNode { } public: - /// getExtensionType - Return whether this is a plain node, + /// Return whether this is a plain node, /// or one of the varieties of value-extending loads. ISD::LoadExtType getExtensionType() const { return ISD::LoadExtType(SubclassData & 3); @@ -1907,8 +1930,7 @@ public: } }; -/// StoreSDNode - This class is used to represent ISD::STORE nodes. -/// +/// This class is used to represent ISD::STORE nodes. class StoreSDNode : public LSBaseSDNode { friend class SelectionDAG; StoreSDNode(SDValue *ChainValuePtrOff, unsigned Order, DebugLoc dl, @@ -1923,7 +1945,7 @@ class StoreSDNode : public LSBaseSDNode { } public: - /// isTruncatingStore - Return true if the op does a truncation before store. + /// Return true if the op does a truncation before store. /// For integers this is the same as doing a TRUNCATE and storing the result. /// For floats, it is the same as doing an FP_ROUND and storing the result. bool isTruncatingStore() const { return SubclassData & 1; } @@ -1937,9 +1959,7 @@ public: } }; -/// MaskedLoadStoreSDNode - This is a base class is used to represent MLOAD and -/// MSTORE nodes -/// +/// This base class is used to represent MLOAD and MSTORE nodes class MaskedLoadStoreSDNode : public MemSDNode { // Operands SDUse Ops[4]; @@ -1965,8 +1985,7 @@ public: } }; -/// MaskedLoadSDNode - This class is used to represent an MLOAD node -/// +/// This class is used to represent an MLOAD node class MaskedLoadSDNode : public MaskedLoadStoreSDNode { public: friend class SelectionDAG; @@ -1987,8 +2006,7 @@ public: } }; -/// MaskedStoreSDNode - This class is used to represent an MSTORE node -/// +/// This class is used to represent an MSTORE node class MaskedStoreSDNode : public MaskedLoadStoreSDNode { public: @@ -2000,7 +2018,7 @@ public: VTs, MemVT, MMO) { SubclassData |= (unsigned short)isTrunc; } - /// isTruncatingStore - Return true if the op does a truncation before store. + /// Return true if the op does a truncation before store. /// For integers this is the same as doing a TRUNCATE and storing the result. /// For floats, it is the same as doing an FP_ROUND and storing the result. bool isTruncatingStore() const { return SubclassData & 1; } @@ -2012,10 +2030,85 @@ public: } }; -/// MachineSDNode - An SDNode that represents everything that will be needed +/// This is a base class used to represent +/// MGATHER and MSCATTER nodes +/// +class MaskedGatherScatterSDNode : public MemSDNode { + // Operands + SDUse Ops[5]; +public: + friend class SelectionDAG; + MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, + ArrayRef<SDValue> Operands, SDVTList VTs, EVT MemVT, + MachineMemOperand *MMO) + : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { + assert(Operands.size() == 5 && "Incompatible number of operands"); + InitOperands(Ops, Operands.data(), Operands.size()); + } + + // In the both nodes address is Op1, mask is Op2: + // MaskedGatherSDNode (Chain, src0, mask, base, index), src0 is a passthru value + // MaskedScatterSDNode (Chain, value, mask, base, index) + // Mask is a vector of i1 elements + const SDValue &getBasePtr() const { return getOperand(3); } + const SDValue &getIndex() const { return getOperand(4); } + const SDValue &getMask() const { return getOperand(2); } + const SDValue &getValue() const { return getOperand(1); } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MGATHER || + N->getOpcode() == ISD::MSCATTER; + } +}; + +/// This class is used to represent an MGATHER node +/// +class MaskedGatherSDNode : public MaskedGatherScatterSDNode { +public: + friend class SelectionDAG; + MaskedGatherSDNode(unsigned Order, DebugLoc dl, ArrayRef<SDValue> Operands, + SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, Operands, VTs, MemVT, + MMO) { + assert(getValue().getValueType() == getValueType(0) && + "Incompatible type of the PathThru value in MaskedGatherSDNode"); + assert(getMask().getValueType().getVectorNumElements() == + getValueType(0).getVectorNumElements() && + "Vector width mismatch between mask and data"); + assert(getMask().getValueType().getScalarType() == MVT::i1 && + "Vector width mismatch between mask and data"); + } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MGATHER; + } +}; + +/// This class is used to represent an MSCATTER node +/// +class MaskedScatterSDNode : public MaskedGatherScatterSDNode { + +public: + friend class SelectionDAG; + MaskedScatterSDNode(unsigned Order, DebugLoc dl,ArrayRef<SDValue> Operands, + SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, Operands, VTs, MemVT, + MMO) { + assert(getMask().getValueType().getVectorNumElements() == + getValue().getValueType().getVectorNumElements() && + "Vector width mismatch between mask and data"); + assert(getMask().getValueType().getScalarType() == MVT::i1 && + "Vector width mismatch between mask and data"); + } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MSCATTER; + } +}; + +/// An SDNode that represents everything that will be needed /// to construct a MachineInstr. These nodes are created during the /// instruction selection proper phase. -/// class MachineSDNode : public SDNode { public: typedef MachineMemOperand **mmo_iterator; @@ -2025,11 +2118,11 @@ private: MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc DL, SDVTList VTs) : SDNode(Opc, Order, DL, VTs), MemRefs(nullptr), MemRefsEnd(nullptr) {} - /// LocalOperands - Operands for this instruction, if they fit here. If + /// Operands for this instruction, if they fit here. If /// they don't, this field is unused. SDUse LocalOperands[4]; - /// MemRefs - Memory reference descriptions for this instruction. + /// Memory reference descriptions for this instruction. mmo_iterator MemRefs; mmo_iterator MemRefsEnd; @@ -2038,7 +2131,7 @@ public: mmo_iterator memoperands_end() const { return MemRefsEnd; } bool memoperands_empty() const { return MemRefsEnd == MemRefs; } - /// setMemRefs - Assign this MachineSDNodes's memory reference descriptor + /// Assign this MachineSDNodes's memory reference descriptor /// list. This does not transfer ownership. void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { for (mmo_iterator MMI = NewMemRefs, MME = NewMemRefsEnd; MMI != MME; ++MMI) @@ -2064,12 +2157,6 @@ public: } bool operator!=(const SDNodeIterator& x) const { return !operator==(x); } - const SDNodeIterator &operator=(const SDNodeIterator &I) { - assert(I.Node == Node && "Cannot assign iterators to two different nodes!"); - Operand = I.Operand; - return *this; - } - pointer operator*() const { return Node->getOperand(Operand).getNode(); } @@ -2109,60 +2196,51 @@ template <> struct GraphTraits<SDNode*> { } }; -/// LargestSDNode - The largest SDNode class. -/// -typedef AtomicSDNode LargestSDNode; +/// The largest SDNode class. +typedef MaskedGatherScatterSDNode LargestSDNode; -/// MostAlignedSDNode - The SDNode class with the greatest alignment -/// requirement. -/// +/// The SDNode class with the greatest alignment requirement. typedef GlobalAddressSDNode MostAlignedSDNode; namespace ISD { - /// isNormalLoad - Returns true if the specified node is a non-extending - /// and unindexed load. + /// Returns true if the specified node is a non-extending and unindexed load. inline bool isNormalLoad(const SDNode *N) { const LoadSDNode *Ld = dyn_cast<LoadSDNode>(N); return Ld && Ld->getExtensionType() == ISD::NON_EXTLOAD && Ld->getAddressingMode() == ISD::UNINDEXED; } - /// isNON_EXTLoad - Returns true if the specified node is a non-extending - /// load. + /// Returns true if the specified node is a non-extending load. inline bool isNON_EXTLoad(const SDNode *N) { return isa<LoadSDNode>(N) && cast<LoadSDNode>(N)->getExtensionType() == ISD::NON_EXTLOAD; } - /// isEXTLoad - Returns true if the specified node is a EXTLOAD. - /// + /// Returns true if the specified node is a EXTLOAD. inline bool isEXTLoad(const SDNode *N) { return isa<LoadSDNode>(N) && cast<LoadSDNode>(N)->getExtensionType() == ISD::EXTLOAD; } - /// isSEXTLoad - Returns true if the specified node is a SEXTLOAD. - /// + /// Returns true if the specified node is a SEXTLOAD. inline bool isSEXTLoad(const SDNode *N) { return isa<LoadSDNode>(N) && cast<LoadSDNode>(N)->getExtensionType() == ISD::SEXTLOAD; } - /// isZEXTLoad - Returns true if the specified node is a ZEXTLOAD. - /// + /// Returns true if the specified node is a ZEXTLOAD. inline bool isZEXTLoad(const SDNode *N) { return isa<LoadSDNode>(N) && cast<LoadSDNode>(N)->getExtensionType() == ISD::ZEXTLOAD; } - /// isUNINDEXEDLoad - Returns true if the specified node is an unindexed load. - /// + /// Returns true if the specified node is an unindexed load. inline bool isUNINDEXEDLoad(const SDNode *N) { return isa<LoadSDNode>(N) && cast<LoadSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; } - /// isNormalStore - Returns true if the specified node is a non-truncating + /// Returns true if the specified node is a non-truncating /// and unindexed store. inline bool isNormalStore(const SDNode *N) { const StoreSDNode *St = dyn_cast<StoreSDNode>(N); @@ -2170,20 +2248,17 @@ namespace ISD { St->getAddressingMode() == ISD::UNINDEXED; } - /// isNON_TRUNCStore - Returns true if the specified node is a non-truncating - /// store. + /// Returns true if the specified node is a non-truncating store. inline bool isNON_TRUNCStore(const SDNode *N) { return isa<StoreSDNode>(N) && !cast<StoreSDNode>(N)->isTruncatingStore(); } - /// isTRUNCStore - Returns true if the specified node is a truncating - /// store. + /// Returns true if the specified node is a truncating store. inline bool isTRUNCStore(const SDNode *N) { return isa<StoreSDNode>(N) && cast<StoreSDNode>(N)->isTruncatingStore(); } - /// isUNINDEXEDStore - Returns true if the specified node is an - /// unindexed store. + /// Returns true if the specified node is an unindexed store. inline bool isUNINDEXEDStore(const SDNode *N) { return isa<StoreSDNode>(N) && cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index 00bb22b91d32..9d6d6f5b1be0 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -162,7 +162,7 @@ namespace llvm { } /// Return true for a valid index. - LLVM_EXPLICIT operator bool() const { return isValid(); } + explicit operator bool() const { return isValid(); } /// Print this index to the given raw_ostream. void print(raw_ostream &os) const; diff --git a/include/llvm/CodeGen/StackMapLivenessAnalysis.h b/include/llvm/CodeGen/StackMapLivenessAnalysis.h deleted file mode 100644 index f67a6e95191d..000000000000 --- a/include/llvm/CodeGen/StackMapLivenessAnalysis.h +++ /dev/null @@ -1,64 +0,0 @@ -//===--- StackMapLivenessAnalysis - StackMap Liveness Analysis --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass calculates the liveness for each basic block in a function and -// attaches the register live-out information to a patchpoint intrinsic (if -// present). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_STACKMAPLIVENESSANALYSIS_H -#define LLVM_CODEGEN_STACKMAPLIVENESSANALYSIS_H - -#include "llvm/CodeGen/LivePhysRegs.h" -#include "llvm/CodeGen/MachineFunctionPass.h" - - -namespace llvm { - -/// \brief This pass calculates the liveness information for each basic block in -/// a function and attaches the register live-out information to a patchpoint -/// intrinsic if present. -/// -/// This pass can be disabled via the -enable-patchpoint-liveness=false flag. -/// The pass skips functions that don't have any patchpoint intrinsics. The -/// information provided by this pass is optional and not required by the -/// aformentioned intrinsic to function. -class StackMapLiveness : public MachineFunctionPass { - MachineFunction *MF; - const TargetRegisterInfo *TRI; - LivePhysRegs LiveRegs; -public: - static char ID; - - /// \brief Default construct and initialize the pass. - StackMapLiveness(); - - /// \brief Tell the pass manager which passes we depend on and what - /// information we preserve. - void getAnalysisUsage(AnalysisUsage &AU) const override; - - /// \brief Calculate the liveness information for the given machine function. - bool runOnMachineFunction(MachineFunction &MF) override; - -private: - /// \brief Performs the actual liveness calculation for the function. - bool calculateLiveness(); - - /// \brief Add the current register live set to the instruction. - void addLiveOutSetToMI(MachineInstr &MI); - - /// \brief Create a register mask and initialize it with the registers from - /// the register live set. - uint32_t *createRegisterMask() const; -}; - -} // llvm namespace - -#endif diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h index 4e48afe14004..46a773f74aac 100644 --- a/include/llvm/CodeGen/StackMaps.h +++ b/include/llvm/CodeGen/StackMaps.h @@ -14,6 +14,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Support/Debug.h" #include <map> #include <vector> @@ -84,15 +85,23 @@ public: /// MI-level Statepoint operands /// /// Statepoint operands take the form: -/// <num call arguments>, <call target>, [call arguments], -/// <StackMaps::ConstantOp>, <flags>, +/// <id>, <num patch bytes >, <num call arguments>, <call target>, +/// [call arguments], <StackMaps::ConstantOp>, <calling convention>, +/// <StackMaps::ConstantOp>, <statepoint flags>, /// <StackMaps::ConstantOp>, <num other args>, [other args], /// [gc values] class StatepointOpers { private: + // These values are aboolute offsets into the operands of the statepoint + // instruction. + enum { IDPos, NBytesPos, NCallArgsPos, CallTargetPos, MetaEnd }; + + // These values are relative offests from the start of the statepoint meta + // arguments (i.e. the end of the call arguments). enum { - NCallArgsPos = 0, - CallTargetPos = 1 + CCOffset = 1, + FlagsOffset = 3, + NumVMSArgsOffset = 5 }; public: @@ -100,22 +109,17 @@ public: MI(MI) { } /// Get starting index of non call related arguments - /// (statepoint flags, vm state and gc state). + /// (calling convention, statepoint flags, vm state and gc state). unsigned getVarIdx() const { - return MI->getOperand(NCallArgsPos).getImm() + 2; + return MI->getOperand(NCallArgsPos).getImm() + MetaEnd; } - /// Returns the index of the operand containing the number of non-gc non-call - /// arguments. - unsigned getNumVMSArgsIdx() const { - return getVarIdx() + 3; - } + /// Return the ID for the given statepoint. + uint64_t getID() const { return MI->getOperand(IDPos).getImm(); } - /// Returns the number of non-gc non-call arguments attached to the - /// statepoint. Note that this is the number of arguments, not the number of - /// operands required to represent those arguments. - unsigned getNumVMSArgs() const { - return MI->getOperand(getNumVMSArgsIdx()).getImm(); + /// Return the number of patchable bytes the given statepoint should emit. + uint32_t getNumPatchBytes() const { + return MI->getOperand(NBytesPos).getImm(); } /// Returns the target of the underlying call. @@ -245,7 +249,10 @@ private: void emitConstantPoolEntries(MCStreamer &OS); /// \brief Emit the callsite info for each stackmap/patchpoint intrinsic call. - void emitCallsiteEntries(MCStreamer &OS, const TargetRegisterInfo *TRI); + void emitCallsiteEntries(MCStreamer &OS); + + void print(raw_ostream &OS); + void debug() { print(dbgs()); } }; } diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 9209e1c67c1b..9a1b63f91bd4 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -34,25 +34,34 @@ namespace llvm { class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { bool UseInitArray; + mutable unsigned NextUniqueID = 0; public: - virtual ~TargetLoweringObjectFileELF() {} + TargetLoweringObjectFileELF() : UseInitArray(false) {} + + ~TargetLoweringObjectFileELF() override {} void emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM, const MCSymbol *Sym) const override; /// Given a constant with the SectionKind, return a section that it should be /// placed in. - const MCSection *getSectionForConstant(SectionKind Kind, - const Constant *C) const override; + MCSection *getSectionForConstant(SectionKind Kind, + const Constant *C) const override; + + MCSection *getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; + + MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; - const MCSection *getExplicitSectionGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const override; + MCSection *getSectionForJumpTable(const Function &F, Mangler &Mang, + const TargetMachine &TM) const override; - const MCSection *SelectSectionForGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const override; + bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, + const Function &F) const override; /// Return an MCExpr to use for a reference to the specified type info global /// variable from exception handling information. @@ -68,17 +77,18 @@ public: MachineModuleInfo *MMI) const override; void InitializeELF(bool UseInitArray_); - const MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; - const MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; + MCSection *getStaticCtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; + MCSection *getStaticDtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; }; class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { public: - virtual ~TargetLoweringObjectFileMachO() {} + ~TargetLoweringObjectFileMachO() override {} + TargetLoweringObjectFileMachO(); /// Extract the dependent library name from a linker option string. Returns /// StringRef() if the option does not specify a library. @@ -89,18 +99,16 @@ public: ArrayRef<Module::ModuleFlagEntry> ModuleFlags, Mangler &Mang, const TargetMachine &TM) const override; - const MCSection * - SelectSectionForGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const override; + MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; - const MCSection * - getExplicitSectionGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const override; + MCSection *getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; - const MCSection *getSectionForConstant(SectionKind Kind, - const Constant *C) const override; + MCSection *getSectionForConstant(SectionKind Kind, + const Constant *C) const override; /// The mach-o version of this method defaults to returning a stub reference. const MCExpr * @@ -113,23 +121,34 @@ public: MCSymbol *getCFIPersonalitySymbol(const GlobalValue *GV, Mangler &Mang, const TargetMachine &TM, MachineModuleInfo *MMI) const override; + + /// Get MachO PC relative GOT entry relocation + const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym, + const MCValue &MV, int64_t Offset, + MachineModuleInfo *MMI, + MCStreamer &Streamer) const override; }; class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile { public: - virtual ~TargetLoweringObjectFileCOFF() {} + ~TargetLoweringObjectFileCOFF() override {} + + MCSection *getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; + + MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; - const MCSection * - getExplicitSectionGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const override; + void getNameWithPrefix(SmallVectorImpl<char> &OutName, const GlobalValue *GV, + bool CannotUsePrivateLabel, Mangler &Mang, + const TargetMachine &TM) const override; - const MCSection * - SelectSectionForGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const override; + MCSection *getSectionForJumpTable(const Function &F, Mangler &Mang, + const TargetMachine &TM) const override; /// Extract the dependent library name from a linker option string. Returns /// StringRef() if the option does not specify a library. @@ -141,10 +160,10 @@ public: ArrayRef<Module::ModuleFlagEntry> ModuleFlags, Mangler &Mang, const TargetMachine &TM) const override; - const MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; - const MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; + MCSection *getStaticCtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; + MCSection *getStaticDtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; }; } // end namespace llvm diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h index b6136665b968..751fac411ce6 100644 --- a/include/llvm/CodeGen/TargetSchedule.h +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -40,6 +40,9 @@ class TargetSchedModel { SmallVector<unsigned, 16> ResourceFactors; unsigned MicroOpFactor; // Multiply to normalize microops to resource units. unsigned ResourceLCM; // Resource units per cycle. Latency normalization factor. + + unsigned computeInstrLatency(const MCSchedClassDesc &SCDesc) const; + public: TargetSchedModel(): SchedModel(MCSchedModel::GetDefaultSchedModel()), STI(nullptr), TII(nullptr) {} diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index 4e93940e223e..e1a9fd38290b 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -34,10 +34,9 @@ namespace llvm { Type *LLVMTy; public: - EVT() : V((MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE)), - LLVMTy(nullptr) {} - EVT(MVT::SimpleValueType SVT) : V(SVT), LLVMTy(nullptr) { } - EVT(MVT S) : V(S), LLVMTy(nullptr) {} + LLVM_CONSTEXPR EVT() : V(MVT::INVALID_SIMPLE_VALUE_TYPE), LLVMTy(nullptr) {} + LLVM_CONSTEXPR EVT(MVT::SimpleValueType SVT) : V(SVT), LLVMTy(nullptr) {} + LLVM_CONSTEXPR EVT(MVT S) : V(S), LLVMTy(nullptr) {} bool operator==(EVT VT) const { return !(*this != VT); diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index b5fa0e8c6a23..2b30f14f902c 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -62,25 +62,26 @@ def v2i64 : ValueType<128, 38>; // 2 x i64 vector value def v4i64 : ValueType<256, 39>; // 4 x i64 vector value def v8i64 : ValueType<512, 40>; // 8 x i64 vector value def v16i64 : ValueType<1024,41>; // 16 x i64 vector value +def v1i128 : ValueType<128, 42>; // 1 x i128 vector value -def v2f16 : ValueType<32 , 42>; // 2 x f16 vector value -def v4f16 : ValueType<64 , 43>; // 4 x f16 vector value -def v8f16 : ValueType<128, 44>; // 8 x f16 vector value -def v1f32 : ValueType<32 , 45>; // 1 x f32 vector value -def v2f32 : ValueType<64 , 46>; // 2 x f32 vector value -def v4f32 : ValueType<128, 47>; // 4 x f32 vector value -def v8f32 : ValueType<256, 48>; // 8 x f32 vector value -def v16f32 : ValueType<512, 49>; // 16 x f32 vector value -def v1f64 : ValueType<64, 50>; // 1 x f64 vector value -def v2f64 : ValueType<128, 51>; // 2 x f64 vector value -def v4f64 : ValueType<256, 52>; // 4 x f64 vector value -def v8f64 : ValueType<512, 53>; // 8 x f64 vector value +def v2f16 : ValueType<32 , 43>; // 2 x f16 vector value +def v4f16 : ValueType<64 , 44>; // 4 x f16 vector value +def v8f16 : ValueType<128, 45>; // 8 x f16 vector value +def v1f32 : ValueType<32 , 46>; // 1 x f32 vector value +def v2f32 : ValueType<64 , 47>; // 2 x f32 vector value +def v4f32 : ValueType<128, 48>; // 4 x f32 vector value +def v8f32 : ValueType<256, 49>; // 8 x f32 vector value +def v16f32 : ValueType<512, 50>; // 16 x f32 vector value +def v1f64 : ValueType<64, 51>; // 1 x f64 vector value +def v2f64 : ValueType<128, 52>; // 2 x f64 vector value +def v4f64 : ValueType<256, 53>; // 4 x f64 vector value +def v8f64 : ValueType<512, 54>; // 8 x f64 vector value -def x86mmx : ValueType<64 , 54>; // X86 MMX value -def FlagVT : ValueType<0 , 55>; // Pre-RA sched glue -def isVoid : ValueType<0 , 56>; // Produces no value -def untyped: ValueType<8 , 57>; // Produces an untyped value +def x86mmx : ValueType<64 , 55>; // X86 MMX value +def FlagVT : ValueType<0 , 56>; // Pre-RA sched glue +def isVoid : ValueType<0 , 57>; // Produces no value +def untyped: ValueType<8 , 58>; // Produces an untyped value def MetadataVT: ValueType<0, 250>; // Metadata // Pseudo valuetype mapped to the current pointer size to any address space. @@ -98,3 +99,6 @@ def iAny : ValueType<0 , 254>; // Pseudo valuetype mapped to the current pointer size. def iPTR : ValueType<0 , 255>; + +// Pseudo valuetype to represent "any type of any size". +def Any : ValueType<0 , 256>; diff --git a/include/llvm/CodeGen/VirtRegMap.h b/include/llvm/CodeGen/VirtRegMap.h index eceb8755763e..d7e92094877d 100644 --- a/include/llvm/CodeGen/VirtRegMap.h +++ b/include/llvm/CodeGen/VirtRegMap.h @@ -63,8 +63,8 @@ namespace llvm { /// createSpillSlot - Allocate a spill slot for RC from MFI. unsigned createSpillSlot(const TargetRegisterClass *RC); - VirtRegMap(const VirtRegMap&) LLVM_DELETED_FUNCTION; - void operator=(const VirtRegMap&) LLVM_DELETED_FUNCTION; + VirtRegMap(const VirtRegMap&) = delete; + void operator=(const VirtRegMap&) = delete; public: static char ID; diff --git a/include/llvm/CodeGen/WinEHFuncInfo.h b/include/llvm/CodeGen/WinEHFuncInfo.h new file mode 100644 index 000000000000..e2644edd4d12 --- /dev/null +++ b/include/llvm/CodeGen/WinEHFuncInfo.h @@ -0,0 +1,157 @@ +//===-- llvm/CodeGen/WinEHFuncInfo.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Data structures and associated state for Windows exception handling schemes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_WINEHFUNCINFO_H +#define LLVM_CODEGEN_WINEHFUNCINFO_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/TinyPtrVector.h" +#include "llvm/ADT/DenseMap.h" + +namespace llvm { +class BasicBlock; +class Constant; +class Function; +class GlobalVariable; +class IntrinsicInst; +class LandingPadInst; +class MCSymbol; +class Value; + +enum ActionType { Catch, Cleanup }; + +class ActionHandler { +public: + ActionHandler(BasicBlock *BB, ActionType Type) + : StartBB(BB), Type(Type), EHState(-1), HandlerBlockOrFunc(nullptr) {} + + ActionType getType() const { return Type; } + BasicBlock *getStartBlock() const { return StartBB; } + + bool hasBeenProcessed() { return HandlerBlockOrFunc != nullptr; } + + void setHandlerBlockOrFunc(Constant *F) { HandlerBlockOrFunc = F; } + Constant *getHandlerBlockOrFunc() { return HandlerBlockOrFunc; } + + void setEHState(int State) { EHState = State; } + int getEHState() const { return EHState; } + +private: + BasicBlock *StartBB; + ActionType Type; + int EHState; + + // Can be either a BlockAddress or a Function depending on the EH personality. + Constant *HandlerBlockOrFunc; +}; + +class CatchHandler : public ActionHandler { +public: + CatchHandler(BasicBlock *BB, Constant *Selector, BasicBlock *NextBB) + : ActionHandler(BB, ActionType::Catch), Selector(Selector), + NextBB(NextBB), ExceptionObjectVar(nullptr), + ExceptionObjectIndex(-1) {} + + // Method for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ActionHandler *H) { + return H->getType() == ActionType::Catch; + } + + Constant *getSelector() const { return Selector; } + BasicBlock *getNextBB() const { return NextBB; } + + const Value *getExceptionVar() { return ExceptionObjectVar; } + TinyPtrVector<BasicBlock *> &getReturnTargets() { return ReturnTargets; } + + void setExceptionVar(const Value *Val) { ExceptionObjectVar = Val; } + void setExceptionVarIndex(int Index) { ExceptionObjectIndex = Index; } + int getExceptionVarIndex() const { return ExceptionObjectIndex; } + void setReturnTargets(TinyPtrVector<BasicBlock *> &Targets) { + ReturnTargets = Targets; + } + +private: + Constant *Selector; + BasicBlock *NextBB; + // While catch handlers are being outlined the ExceptionObjectVar field will + // be populated with the instruction in the parent frame that corresponds + // to the exception object (or nullptr if the catch does not use an + // exception object) and the ExceptionObjectIndex field will be -1. + // When the parseEHActions function is called to populate a vector of + // instances of this class, the ExceptionObjectVar field will be nullptr + // and the ExceptionObjectIndex will be the index of the exception object in + // the parent function's frameescape block. + const Value *ExceptionObjectVar; + int ExceptionObjectIndex; + TinyPtrVector<BasicBlock *> ReturnTargets; +}; + +class CleanupHandler : public ActionHandler { +public: + CleanupHandler(BasicBlock *BB) : ActionHandler(BB, ActionType::Cleanup) {} + + // Method for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ActionHandler *H) { + return H->getType() == ActionType::Cleanup; + } +}; + +void parseEHActions(const IntrinsicInst *II, + SmallVectorImpl<std::unique_ptr<ActionHandler>> &Actions); + +// The following structs respresent the .xdata for functions using C++ +// exceptions on Windows. + +struct WinEHUnwindMapEntry { + int ToState; + Function *Cleanup; +}; + +struct WinEHHandlerType { + int Adjectives; + GlobalVariable *TypeDescriptor; + int CatchObjRecoverIdx; + Function *Handler; +}; + +struct WinEHTryBlockMapEntry { + int TryLow; + int TryHigh; + SmallVector<WinEHHandlerType, 1> HandlerArray; +}; + +struct WinEHFuncInfo { + DenseMap<const Function *, const LandingPadInst *> RootLPad; + DenseMap<const Function *, const InvokeInst *> LastInvoke; + DenseMap<const Function *, int> HandlerEnclosedState; + DenseMap<const Function *, bool> LastInvokeVisited; + DenseMap<const LandingPadInst *, int> LandingPadStateMap; + DenseMap<const Function *, int> CatchHandlerParentFrameObjIdx; + DenseMap<const Function *, int> CatchHandlerParentFrameObjOffset; + DenseMap<const Function *, int> CatchHandlerMaxState; + DenseMap<const Function *, int> HandlerBaseState; + SmallVector<WinEHUnwindMapEntry, 4> UnwindMap; + SmallVector<WinEHTryBlockMapEntry, 4> TryBlockMap; + SmallVector<std::pair<MCSymbol *, int>, 4> IPToStateList; + int UnwindHelpFrameIdx; + int UnwindHelpFrameOffset; + + unsigned NumIPToStateFuncsVisited; + + WinEHFuncInfo() + : UnwindHelpFrameIdx(INT_MAX), UnwindHelpFrameOffset(-1), + NumIPToStateFuncsVisited(0) {} +}; + +} +#endif // LLVM_CODEGEN_WINEHFUNCINFO_H diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 5c512f6bca6c..bd50d6ee1d6b 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -33,9 +33,6 @@ /* Define to 1 if you have the `bcopy' function. */ #undef HAVE_BCOPY -/* Define to 1 if you have the `ceilf' function. */ -#cmakedefine HAVE_CEILF ${HAVE_CEILF} - /* Define to 1 if you have the `closedir' function. */ #cmakedefine HAVE_CLOSEDIR ${HAVE_CLOSEDIR} @@ -52,6 +49,9 @@ don't. */ #cmakedefine01 HAVE_DECL_STRERROR_S +/* Define to 1 if you have the DIA SDK installed, and to 0 if you don't. */ +#cmakedefine HAVE_DIA_SDK ${HAVE_DIA_SDK} + /* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. */ #cmakedefine HAVE_DIRENT_H ${HAVE_DIRENT_H} @@ -92,33 +92,6 @@ /* 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} - -/* Define to 1 if you have the `log' function. */ -#cmakedefine HAVE_LOG ${HAVE_LOG} - -/* Define to 1 if you have the `log2' function. */ -#cmakedefine HAVE_LOG2 ${HAVE_LOG2} - -/* Define to 1 if you have the `log10' function. */ -#cmakedefine HAVE_LOG10 ${HAVE_LOG10} - -/* Define to 1 if you have the `exp' function. */ -#cmakedefine HAVE_EXP ${HAVE_EXP} - -/* Define to 1 if you have the `exp2' function. */ -#cmakedefine HAVE_EXP2 ${HAVE_EXP2} - -/* Define to 1 if you have the `exp10' function. */ -#cmakedefine HAVE_EXP10 ${HAVE_EXP10} - -/* Define to 1 if you have the `fmodf' function. */ -#cmakedefine HAVE_FMODF ${HAVE_FMODF} - /* Define to 1 if you have the `futimes' function. */ #cmakedefine HAVE_FUTIMES ${HAVE_FUTIMES} @@ -149,18 +122,6 @@ /* Define to 1 if you have the `isatty' function. */ #cmakedefine HAVE_ISATTY 1 -/* Set to 1 if the isinf function is found in <cmath> */ -#cmakedefine HAVE_ISINF_IN_CMATH ${HAVE_ISINF_IN_CMATH} - -/* Set to 1 if the isinf function is found in <math.h> */ -#cmakedefine HAVE_ISINF_IN_MATH_H ${HAVE_ISINF_IN_MATH_H} - -/* Set to 1 if the isnan function is found in <cmath> */ -#cmakedefine HAVE_ISNAN_IN_CMATH ${HAVE_ISNAN_IN_CMATH} - -/* Set to 1 if the isnan function is found in <math.h> */ -#cmakedefine HAVE_ISNAN_IN_MATH_H ${HAVE_ISNAN_IN_MATH_H} - /* Define if you have the libdl library or equivalent. */ #cmakedefine HAVE_LIBDL ${HAVE_LIBDL} @@ -219,6 +180,9 @@ /* Define to 1 if you have the `malloc_zone_statistics' function. */ #cmakedefine HAVE_MALLOC_ZONE_STATISTICS ${HAVE_MALLOC_ZONE_STATISTICS} +/* Define to 1 if you have the `mallctl` function. */ +#cmakedefine HAVE_MALLCTL ${HAVE_MALLCTL} + /* Define to 1 if you have the `mkdtemp' function. */ #cmakedefine HAVE_MKDTEMP ${HAVE_MKDTEMP} @@ -241,18 +205,12 @@ /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ #cmakedefine HAVE_NDIR_H ${HAVE_NDIR_H} -/* Define to 1 if you have the `nearbyintf' function. */ -#cmakedefine HAVE_NEARBYINTF ${HAVE_NEARBYINTF} - /* Define to 1 if you have the `opendir' function. */ #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 to 1 if you have the `pread' function. */ #cmakedefine HAVE_PREAD ${HAVE_PREAD} @@ -283,15 +241,6 @@ /* Define to 1 if you have the `realpath' function. */ #cmakedefine HAVE_REALPATH ${HAVE_REALPATH} -/* Define to 1 if you have the `rintf' function. */ -#undef HAVE_RINTF - -/* 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} @@ -334,9 +283,6 @@ /* Define to 1 if you have the `strerror_r' function. */ #cmakedefine HAVE_STRERROR_R ${HAVE_STRERROR_R} -/* 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} diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index c68c77aa6076..67d7c8485a40 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -39,9 +39,6 @@ /* Define to 1 if you have the `backtrace' function. */ #undef HAVE_BACKTRACE -/* Define to 1 if you have the `ceilf' function. */ -#undef HAVE_CEILF - /* Define to 1 if you have the <CrashReporterClient.h> header file. */ #undef HAVE_CRASHREPORTERCLIENT_H @@ -86,12 +83,6 @@ /* Define to 1 if you have the <execinfo.h> header file. */ #undef HAVE_EXECINFO_H -/* Define to 1 if you have the `exp' function. */ -#undef HAVE_EXP - -/* Define to 1 if you have the `exp2' function. */ -#undef HAVE_EXP2 - /* Define to 1 if you have the <fcntl.h> header file. */ #undef HAVE_FCNTL_H @@ -107,15 +98,6 @@ /* Define to 1 if you have the <ffi.h> header file. */ #undef HAVE_FFI_H -/* Set to 1 if the finite function is found in <ieeefp.h> */ -#undef HAVE_FINITE_IN_IEEEFP_H - -/* Define to 1 if you have the `floorf' function. */ -#undef HAVE_FLOORF - -/* Define to 1 if you have the `fmodf' function. */ -#undef HAVE_FMODF - /* Define to 1 if you have the `futimens' function. */ #undef HAVE_FUTIMENS @@ -146,18 +128,6 @@ /* Define to 1 if you have the `isatty' function. */ #undef HAVE_ISATTY -/* Set to 1 if the isinf function is found in <cmath> */ -#undef HAVE_ISINF_IN_CMATH - -/* Set to 1 if the isinf function is found in <math.h> */ -#undef HAVE_ISINF_IN_MATH_H - -/* Set to 1 if the isnan function is found in <cmath> */ -#undef HAVE_ISNAN_IN_CMATH - -/* Set to 1 if the isnan function is found in <math.h> */ -#undef HAVE_ISNAN_IN_MATH_H - /* Define if libedit is available on this platform. */ #undef HAVE_LIBEDIT @@ -189,15 +159,6 @@ the current directory to the dynamic linker search path. */ #undef HAVE_LINK_R -/* Define to 1 if you have the `log' function. */ -#undef HAVE_LOG - -/* Define to 1 if you have the `log10' function. */ -#undef HAVE_LOG10 - -/* Define to 1 if you have the `log2' function. */ -#undef HAVE_LOG2 - /* Define to 1 if you have the `longjmp' function. */ #undef HAVE_LONGJMP @@ -241,15 +202,9 @@ /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ #undef HAVE_NDIR_H -/* Define to 1 if you have the `nearbyintf' function. */ -#undef HAVE_NEARBYINTF - /* Define to 1 if you have the `posix_spawn' function. */ #undef HAVE_POSIX_SPAWN -/* Define to 1 if you have the `powf' function. */ -#undef HAVE_POWF - /* Define to 1 if you have the `pread' function. */ #undef HAVE_PREAD @@ -274,15 +229,6 @@ /* Define to 1 if you have the `realpath' function. */ #undef HAVE_REALPATH -/* Define to 1 if you have the `rintf' function. */ -#undef HAVE_RINTF - -/* Define to 1 if you have the `round' function. */ -#undef HAVE_ROUND - -/* Define to 1 if you have the `roundf' function. */ -#undef HAVE_ROUNDF - /* Define to 1 if you have the `sbrk' function. */ #undef HAVE_SBRK @@ -313,12 +259,6 @@ /* Define to 1 if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H -/* 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 - /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR @@ -331,9 +271,6 @@ /* Define to 1 if you have the <string.h> header file. */ #undef HAVE_STRING_H -/* Define to 1 if you have the `strtof' function. */ -#undef HAVE_STRTOF - /* Define to 1 if you have the `strtoll' function. */ #undef HAVE_STRTOLL @@ -480,6 +417,9 @@ /* Installation directory for documentation */ #undef LLVM_DOCSDIR +/* Define to enable checks that alter the LLVM C++ ABI */ +#undef LLVM_ENABLE_ABI_BREAKING_CHECKS + /* Define if threads enabled */ #undef LLVM_ENABLE_THREADS diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index d54003d993a9..bb7dc067ea00 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -101,4 +101,8 @@ /* Define if we link Polly to the tools */ #cmakedefine LINK_POLLY_INTO_TOOLS +/* Define if LLVM is built with asserts and checks that change the layout of + client-visible data structures. */ +#cmakedefine LLVM_ENABLE_ABI_BREAKING_CHECKS + #endif diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in index 25a929544832..03e482ac1752 100644 --- a/include/llvm/Config/llvm-config.h.in +++ b/include/llvm/Config/llvm-config.h.in @@ -98,4 +98,7 @@ /* LLVM version string */ #undef LLVM_VERSION_STRING +/* Define to enable checks that alter the LLVM C++ ABI */ +#undef LLVM_ENABLE_ABI_BREAKING_CHECKS + #endif diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 622aa699c435..dddc7faa73e8 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -113,25 +113,16 @@ enum DIDumpType { DIDT_AppleObjC }; -// In place of applying the relocations to the data we've read from disk we use -// a separate mapping table to the side and checking that at locations in the -// dwarf where we expect relocated values. This adds a bit of complexity to the -// dwarf parsing/extraction at the benefit of not allocating memory for the -// entire size of the debug info sections. -typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap; - class DIContext { public: enum DIContextKind { - CK_DWARF + CK_DWARF, + CK_PDB }; DIContextKind getKind() const { return Kind; } DIContext(DIContextKind K) : Kind(K) {} - virtual ~DIContext(); - - /// getDWARFContext - get a context for binary DWARF data. - static DIContext *getDWARFContext(const object::ObjectFile &Obj); + virtual ~DIContext() {} virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0; @@ -145,6 +136,43 @@ private: const DIContextKind Kind; }; +/// An inferface for inquiring the load address of a loaded object file +/// to be used by the DIContext implementations when applying relocations +/// on the fly. +class LoadedObjectInfo { +public: + LoadedObjectInfo() {} + virtual ~LoadedObjectInfo() {} + + /// Obtain the Load Address of a section by Name. + /// + /// Calculate the address of the section identified by the passed in Name. + /// The section need not be present in the local address space. The addresses + /// need to be consistent with the addresses used to query the DIContext and + /// the output of this function should be deterministic, i.e. repeated calls with + /// the same Name should give the same address. + virtual uint64_t getSectionLoadAddress(StringRef Name) const = 0; + + /// If conveniently available, return the content of the given Section. + /// + /// When the section is available in the local address space, in relocated (loaded) + /// form, e.g. because it was relocated by a JIT for execution, this function + /// should provide the contents of said section in `Data`. If the loaded section + /// is not available, or the cost of retrieving it would be prohibitive, this + /// function should return false. In that case, relocations will be read from the + /// local (unrelocated) object file and applied on the fly. Note that this method + /// is used purely for optimzation purposes in the common case of JITting in the + /// local address space, so returning false should always be correct. + virtual bool getLoadedSectionContents(StringRef Name, StringRef &Data) const { + return false; + } + + /// Obtain a copy of this LoadedObjectInfo. + /// + /// The caller is responsible for deallocation once the copy is no longer required. + virtual LoadedObjectInfo *clone() const = 0; +}; + } #endif diff --git a/include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h index bb05c302be9a..6ab5d5ce6f6e 100644 --- a/include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h +++ b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -18,18 +18,14 @@ namespace llvm { class raw_ostream; class DWARFAbbreviationDeclaration { - uint32_t Code; - uint32_t Tag; - bool HasChildren; - +public: struct AttributeSpec { AttributeSpec(uint16_t Attr, uint16_t Form) : Attr(Attr), Form(Form) {} uint16_t Attr; uint16_t Form; }; typedef SmallVector<AttributeSpec, 8> AttributeSpecVector; - AttributeSpecVector AttributeSpecs; -public: + DWARFAbbreviationDeclaration(); uint32_t getCode() const { return Code; } @@ -53,6 +49,12 @@ public: private: void clear(); + + uint32_t Code; + uint32_t Tag; + bool HasChildren; + + AttributeSpecVector AttributeSpecs; }; } diff --git a/include/llvm/DebugInfo/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h index 3fbc1c3b3c79..47dbf5fd4f56 100644 --- a/include/llvm/DebugInfo/DWARFAcceleratorTable.h +++ b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -7,9 +7,12 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_LIB_DEBUGINFO_DWARFACCELERATORTABLE_H +#define LLVM_LIB_DEBUGINFO_DWARFACCELERATORTABLE_H + #include "llvm/ADT/SmallVector.h" -#include "llvm/DebugInfo/DWARFFormValue.h" -#include "llvm/DebugInfo/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include <cstdint> namespace llvm { @@ -47,3 +50,5 @@ public: }; } + +#endif diff --git a/include/llvm/DebugInfo/DWARFCompileUnit.h b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h index dbf777cc71aa..743f9c696e9e 100644 --- a/include/llvm/DebugInfo/DWARFCompileUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h @@ -10,7 +10,7 @@ #ifndef LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H #define LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H -#include "llvm/DebugInfo/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" namespace llvm { diff --git a/include/llvm/DebugInfo/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h index 82b5bb088477..423c0d32f1b5 100644 --- a/include/llvm/DebugInfo/DWARFContext.h +++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -13,18 +13,25 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/DebugInfo/DIContext.h" -#include "llvm/DebugInfo/DWARFCompileUnit.h" -#include "llvm/DebugInfo/DWARFDebugAranges.h" -#include "llvm/DebugInfo/DWARFDebugFrame.h" -#include "llvm/DebugInfo/DWARFDebugLine.h" -#include "llvm/DebugInfo/DWARFDebugLoc.h" -#include "llvm/DebugInfo/DWARFDebugRangeList.h" -#include "llvm/DebugInfo/DWARFSection.h" -#include "llvm/DebugInfo/DWARFTypeUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include <vector> namespace llvm { +// In place of applying the relocations to the data we've read from disk we use +// a separate mapping table to the side and checking that at locations in the +// dwarf where we expect relocated values. This adds a bit of complexity to the +// dwarf parsing/extraction at the benefit of not allocating memory for the +// entire size of the debug info sections. +typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap; + /// DWARFContext /// This data structure is the top level entity that deals with dwarf debug /// information parsing. The actual data is supplied through pure virtual @@ -44,8 +51,8 @@ class DWARFContext : public DIContext { std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO; std::unique_ptr<DWARFDebugLocDWO> LocDWO; - DWARFContext(DWARFContext &) LLVM_DELETED_FUNCTION; - DWARFContext &operator=(DWARFContext &) LLVM_DELETED_FUNCTION; + DWARFContext(DWARFContext &) = delete; + DWARFContext &operator=(DWARFContext &) = delete; /// Read compile units from the debug_info section (if necessary) /// and store them in CUs. @@ -248,7 +255,8 @@ class DWARFContextInMemory : public DWARFContext { SmallVector<SmallString<32>, 4> UncompressedSections; public: - DWARFContextInMemory(const object::ObjectFile &Obj); + DWARFContextInMemory(const object::ObjectFile &Obj, + const LoadedObjectInfo *L = nullptr); bool isLittleEndian() const override { return IsLittleEndian; } uint8_t getAddressSize() const override { return AddressSize; } const DWARFSection &getInfoSection() override { return InfoSection; } diff --git a/include/llvm/DebugInfo/DWARFDebugAbbrev.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h index 6752df9cd728..21142089da6b 100644 --- a/include/llvm/DebugInfo/DWARFDebugAbbrev.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h @@ -10,7 +10,7 @@ #ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H #define LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H -#include "llvm/DebugInfo/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include <list> #include <map> #include <vector> diff --git a/include/llvm/DebugInfo/DWARFDebugArangeSet.h b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h index 837a8e63469e..837a8e63469e 100644 --- a/include/llvm/DebugInfo/DWARFDebugArangeSet.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h diff --git a/include/llvm/DebugInfo/DWARFDebugAranges.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h index 791f010a8892..791f010a8892 100644 --- a/include/llvm/DebugInfo/DWARFDebugAranges.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h diff --git a/include/llvm/DebugInfo/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h index be925cbe7519..be925cbe7519 100644 --- a/include/llvm/DebugInfo/DWARFDebugFrame.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h diff --git a/include/llvm/DebugInfo/DWARFDebugInfoEntry.h b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h index f05d64b6f34b..f29d5fe9ecde 100644 --- a/include/llvm/DebugInfo/DWARFDebugInfoEntry.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h @@ -12,8 +12,8 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/DebugInfo/DIContext.h" -#include "llvm/DebugInfo/DWARFAbbreviationDeclaration.h" -#include "llvm/DebugInfo/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/DebugInfo/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h index c5ee76e39682..37b22c2e82f6 100644 --- a/include/llvm/DebugInfo/DWARFDebugLine.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -11,7 +11,7 @@ #define LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H #include "llvm/DebugInfo/DIContext.h" -#include "llvm/DebugInfo/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/Support/DataExtractor.h" #include <map> #include <string> diff --git a/include/llvm/DebugInfo/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h index a6135a0c9291..bd44c2e5aab9 100644 --- a/include/llvm/DebugInfo/DWARFDebugLoc.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -11,7 +11,7 @@ #define LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H #include "llvm/ADT/SmallVector.h" -#include "llvm/DebugInfo/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/Support/DataExtractor.h" namespace llvm { diff --git a/include/llvm/DebugInfo/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h index 4ee3bdad3299..c930bd603d4d 100644 --- a/include/llvm/DebugInfo/DWARFDebugRangeList.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -66,6 +66,8 @@ public: void clear(); void dump(raw_ostream &OS) const; bool extract(DataExtractor data, uint32_t *offset_ptr); + const std::vector<RangeListEntry> &getEntries() { return Entries; } + /// getAbsoluteRanges - Returns absolute address ranges defined by this range /// list. Has to be passed base address of the compile unit referencing this /// range list. diff --git a/include/llvm/DebugInfo/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index 5bb6d1b9ddb0..7ddcc0d81d59 100644 --- a/include/llvm/DebugInfo/DWARFFormValue.h +++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -63,7 +63,7 @@ public: /// The passed DWARFUnit is allowed to be nullptr, in which /// case no relocation processing will be performed and some /// kind of forms that depend on Unit information are disallowed. - /// \returns wether the extraction succeeded. + /// \returns whether the extraction succeeded. bool extractValue(DataExtractor data, uint32_t *offset_ptr, const DWARFUnit *u); bool isInlinedCStr() const { @@ -74,6 +74,7 @@ public: /// DWARFFormValue has form class is suitable for representing Foo. Optional<uint64_t> getAsReference(const DWARFUnit *U) const; Optional<uint64_t> getAsUnsignedConstant() const; + Optional<int64_t> getAsSignedConstant() const; Optional<const char *> getAsCString(const DWARFUnit *U) const; Optional<uint64_t> getAsAddress(const DWARFUnit *U) const; Optional<uint64_t> getAsSectionOffset() const; @@ -86,6 +87,8 @@ public: static ArrayRef<uint8_t> getFixedFormSizes(uint8_t AddrSize, uint16_t Version); +private: + void dumpString(raw_ostream &OS, const DWARFUnit *U) const; }; } diff --git a/include/llvm/DebugInfo/DWARFRelocMap.h b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h index d7fe3032e505..d7fe3032e505 100644 --- a/include/llvm/DebugInfo/DWARFRelocMap.h +++ b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h diff --git a/include/llvm/DebugInfo/DWARFSection.h b/include/llvm/DebugInfo/DWARF/DWARFSection.h index 5f09d9e37d81..3e27b529e97b 100644 --- a/include/llvm/DebugInfo/DWARFSection.h +++ b/include/llvm/DebugInfo/DWARF/DWARFSection.h @@ -10,7 +10,8 @@ #ifndef LLVM_LIB_DEBUGINFO_DWARFSECTION_H #define LLVM_LIB_DEBUGINFO_DWARFSECTION_H -#include "llvm/DebugInfo/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/ADT/StringRef.h" namespace llvm { diff --git a/include/llvm/DebugInfo/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h index 213b54139e04..f24e27819da2 100644 --- a/include/llvm/DebugInfo/DWARFTypeUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h @@ -10,7 +10,7 @@ #ifndef LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H #define LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H -#include "llvm/DebugInfo/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" namespace llvm { diff --git a/include/llvm/DebugInfo/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h index d71a1b60b731..5604b93f2205 100644 --- a/include/llvm/DebugInfo/DWARFUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -10,11 +10,12 @@ #ifndef LLVM_LIB_DEBUGINFO_DWARFUNIT_H #define LLVM_LIB_DEBUGINFO_DWARFUNIT_H -#include "llvm/DebugInfo/DWARFDebugAbbrev.h" -#include "llvm/DebugInfo/DWARFDebugInfoEntry.h" -#include "llvm/DebugInfo/DWARFDebugRangeList.h" -#include "llvm/DebugInfo/DWARFRelocMap.h" -#include "llvm/DebugInfo/DWARFSection.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFSection.h" #include <vector> namespace llvm { @@ -45,7 +46,7 @@ protected: const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, bool isLittleEndian) = 0; - ~DWARFUnitSectionBase() {} + ~DWARFUnitSectionBase() = default; }; /// Concrete instance of DWARFUnitSection, specialized for one Unit type. @@ -194,9 +195,8 @@ public: BaseAddr = base_addr; } - const DWARFDebugInfoEntryMinimal * - getCompileUnitDIE(bool extract_cu_die_only = true) { - extractDIEsIfNeeded(extract_cu_die_only); + const DWARFDebugInfoEntryMinimal *getUnitDIE(bool ExtractUnitDIEOnly = true) { + extractDIEsIfNeeded(ExtractUnitDIEOnly); return DieArray.empty() ? nullptr : &DieArray[0]; } @@ -213,6 +213,45 @@ public: /// getUnitSection - Return the DWARFUnitSection containing this unit. const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; } + /// \brief Returns the number of DIEs in the unit. Parses the unit + /// if necessary. + unsigned getNumDIEs() { + extractDIEsIfNeeded(false); + return DieArray.size(); + } + + /// \brief Return the index of a DIE inside the unit's DIE vector. + /// + /// It is illegal to call this method with a DIE that hasn't be + /// created by this unit. In other word, it's illegal to call this + /// method on a DIE that isn't accessible by following + /// children/sibling links starting from this unit's getUnitDIE(). + uint32_t getDIEIndex(const DWARFDebugInfoEntryMinimal *DIE) { + assert(!DieArray.empty() && DIE >= &DieArray[0] && + DIE < &DieArray[0] + DieArray.size()); + return DIE - &DieArray[0]; + } + + /// \brief Return the DIE object at the given index. + const DWARFDebugInfoEntryMinimal *getDIEAtIndex(unsigned Index) const { + assert(Index < DieArray.size()); + return &DieArray[Index]; + } + + /// \brief Return the DIE object for a given offset inside the + /// unit's DIE vector. + /// + /// The unit needs to have his DIEs extracted for this method to work. + const DWARFDebugInfoEntryMinimal *getDIEForOffset(uint32_t Offset) const { + assert(!DieArray.empty()); + auto it = std::lower_bound( + DieArray.begin(), DieArray.end(), Offset, + [=](const DWARFDebugInfoEntryMinimal &LHS, uint32_t Offset) { + return LHS.getOffset() < Offset; + }); + return it == DieArray.end() ? nullptr : &*it; + } + private: /// Size in bytes of the .debug_info data associated with this compile unit. size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); } diff --git a/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h new file mode 100644 index 000000000000..b5fa8c33414d --- /dev/null +++ b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h @@ -0,0 +1,59 @@ +//===- ConcreteSymbolEnumerator.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_CONCRETESYMBOLENUMERATOR_H +#define LLVM_DEBUGINFO_PDB_CONCRETESYMBOLENUMERATOR_H + +#include "IPDBEnumChildren.h" +#include "llvm/Support/Casting.h" +#include <memory> + +namespace llvm { + +template <typename ChildType> +class ConcreteSymbolEnumerator : public IPDBEnumChildren<ChildType> { +public: + ConcreteSymbolEnumerator(std::unique_ptr<IPDBEnumSymbols> SymbolEnumerator) + : Enumerator(std::move(SymbolEnumerator)) {} + + ~ConcreteSymbolEnumerator() override {} + + uint32_t getChildCount() const override { + return Enumerator->getChildCount(); + } + + std::unique_ptr<ChildType> getChildAtIndex(uint32_t Index) const override { + std::unique_ptr<PDBSymbol> Child = Enumerator->getChildAtIndex(Index); + return make_concrete_child(std::move(Child)); + } + + std::unique_ptr<ChildType> getNext() override { + std::unique_ptr<PDBSymbol> Child = Enumerator->getNext(); + return make_concrete_child(std::move(Child)); + } + + void reset() override { Enumerator->reset(); } + + ConcreteSymbolEnumerator<ChildType> *clone() const override { + std::unique_ptr<IPDBEnumSymbols> WrappedClone(Enumerator->clone()); + return new ConcreteSymbolEnumerator<ChildType>(std::move(WrappedClone)); + } + +private: + std::unique_ptr<ChildType> + make_concrete_child(std::unique_ptr<PDBSymbol> Child) const { + ChildType *ConcreteChild = dyn_cast_or_null<ChildType>(Child.release()); + return std::unique_ptr<ChildType>(ConcreteChild); + } + + std::unique_ptr<IPDBEnumSymbols> Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h b/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h new file mode 100644 index 000000000000..7b2bc146b32d --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h @@ -0,0 +1,33 @@ +//===- DIADataStream.h - DIA implementation of IPDBDataStream ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIADATASTREAM_H +#define LLVM_DEBUGINFO_PDB_DIA_DIADATASTREAM_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBDataStream.h" + +namespace llvm { +class DIADataStream : public IPDBDataStream { +public: + explicit DIADataStream(CComPtr<IDiaEnumDebugStreamData> DiaStreamData); + + uint32_t getRecordCount() const override; + std::string getName() const override; + llvm::Optional<RecordType> getItemAtIndex(uint32_t Index) const override; + bool getNext(RecordType &Record) override; + void reset() override; + DIADataStream *clone() const override; + +private: + CComPtr<IDiaEnumDebugStreamData> StreamData; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h new file mode 100644 index 000000000000..375bcdd7e3bd --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h @@ -0,0 +1,35 @@ +//==- DIAEnumDebugStreams.h - DIA Debug Stream Enumerator impl ---*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMDEBUGSTREAMS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMDEBUGSTREAMS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" + +namespace llvm { + +class IPDBDataStream; + +class DIAEnumDebugStreams : public IPDBEnumChildren<IPDBDataStream> { +public: + explicit DIAEnumDebugStreams(CComPtr<IDiaEnumDebugStreams> DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + DIAEnumDebugStreams *clone() const override; + +private: + CComPtr<IDiaEnumDebugStreams> Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h new file mode 100644 index 000000000000..4cc85eda477f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h @@ -0,0 +1,35 @@ +//==- DIAEnumLineNumbers.h - DIA Line Number Enumerator impl -----*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMLINENUMBERS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMLINENUMBERS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" + +namespace llvm { + +class IPDBLineNumber; + +class DIAEnumLineNumbers : public IPDBEnumChildren<IPDBLineNumber> { +public: + explicit DIAEnumLineNumbers(CComPtr<IDiaEnumLineNumbers> DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + DIAEnumLineNumbers *clone() const override; + +private: + CComPtr<IDiaEnumLineNumbers> Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h new file mode 100644 index 000000000000..88625f64e49e --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h @@ -0,0 +1,37 @@ +//==- DIAEnumSourceFiles.h - DIA Source File Enumerator impl -----*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMSOURCEFILES_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMSOURCEFILES_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" + +namespace llvm { + +class DIASession; + +class DIAEnumSourceFiles : public IPDBEnumChildren<IPDBSourceFile> { +public: + explicit DIAEnumSourceFiles(const DIASession &PDBSession, + CComPtr<IDiaEnumSourceFiles> DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + DIAEnumSourceFiles *clone() const override; + +private: + const DIASession &Session; + CComPtr<IDiaEnumSourceFiles> Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h new file mode 100644 index 000000000000..fe343f778aad --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h @@ -0,0 +1,37 @@ +//==- DIAEnumSymbols.h - DIA Symbol Enumerator impl --------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMSYMBOLS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMSYMBOLS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" + +namespace llvm { + +class DIASession; + +class DIAEnumSymbols : public IPDBEnumChildren<PDBSymbol> { +public: + explicit DIAEnumSymbols(const DIASession &Session, + CComPtr<IDiaEnumSymbols> DiaEnumerator); + + uint32_t getChildCount() const override; + std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override; + std::unique_ptr<PDBSymbol> getNext() override; + void reset() override; + DIAEnumSymbols *clone() const override; + +private: + const DIASession &Session; + CComPtr<IDiaEnumSymbols> Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h b/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h new file mode 100644 index 000000000000..5950a0d3835f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h @@ -0,0 +1,39 @@ +//===- DIALineNumber.h - DIA implementation of IPDBLineNumber ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIALINENUMBER_H +#define LLVM_DEBUGINFO_PDB_DIA_DIALINENUMBER_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" + +namespace llvm { +class DIALineNumber : public IPDBLineNumber { +public: + explicit DIALineNumber(CComPtr<IDiaLineNumber> DiaLineNumber); + + uint32_t getLineNumber() const override; + uint32_t getLineNumberEnd() const override; + uint32_t getColumnNumber() const override; + uint32_t getColumnNumberEnd() const override; + uint32_t getAddressSection() const override; + uint32_t getAddressOffset() const override; + uint32_t getRelativeVirtualAddress() const override; + uint64_t getVirtualAddress() const override; + uint32_t getLength() const override; + uint32_t getSourceFileId() const override; + uint32_t getCompilandId() const override; + bool isStatement() const override; + +private: + CComPtr<IDiaLineNumber> LineNumber; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h new file mode 100644 index 000000000000..9308b8e82657 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h @@ -0,0 +1,206 @@ +//===- DIARawSymbol.h - DIA implementation of IPDBRawSymbol ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIARAWSYMBOL_H +#define LLVM_DEBUGINFO_PDB_DIA_DIARAWSYMBOL_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" + +namespace llvm { +class DIASession; +class DIARawSymbol : public IPDBRawSymbol { +public: + DIARawSymbol(const DIASession &PDBSession, CComPtr<IDiaSymbol> DiaSymbol); + + void dump(raw_ostream &OS, int Indent) const override; + + CComPtr<IDiaSymbol> getDiaSymbol() const { return Symbol; } + + std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type) const override; + std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr<IPDBEnumSymbols> + findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint32_t RVA) const override; + std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByRVA(uint32_t RVA) const override; + + void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const override; + void getFrontEndVersion(VersionInfo &Version) const override; + void getBackEndVersion(VersionInfo &Version) const override; + PDB_MemberAccess getAccess() const override; + uint32_t getAddressOffset() const override; + uint32_t getAddressSection() const override; + uint32_t getAge() const override; + uint32_t getArrayIndexTypeId() const override; + uint32_t getBaseDataOffset() const override; + uint32_t getBaseDataSlot() const override; + uint32_t getBaseSymbolId() const override; + PDB_BuiltinType getBuiltinType() const override; + uint32_t getBitPosition() const override; + PDB_CallingConv getCallingConvention() const override; + uint32_t getClassParentId() const override; + std::string getCompilerName() const override; + uint32_t getCount() const override; + uint32_t getCountLiveRanges() const override; + PDB_Lang getLanguage() const override; + uint32_t getLexicalParentId() const override; + std::string getLibraryName() const override; + uint32_t getLiveRangeStartAddressOffset() const override; + uint32_t getLiveRangeStartAddressSection() const override; + uint32_t getLiveRangeStartRelativeVirtualAddress() const override; + PDB_RegisterId getLocalBasePointerRegisterId() const override; + uint32_t getLowerBoundId() const override; + uint32_t getMemorySpaceKind() const override; + std::string getName() const override; + uint32_t getNumberOfAcceleratorPointerTags() const override; + uint32_t getNumberOfColumns() const override; + uint32_t getNumberOfModifiers() const override; + uint32_t getNumberOfRegisterIndices() const override; + uint32_t getNumberOfRows() const override; + std::string getObjectFileName() const override; + uint32_t getOemId() const override; + uint32_t getOemSymbolId() const override; + uint32_t getOffsetInUdt() const override; + PDB_Cpu getPlatform() const override; + uint32_t getRank() const override; + PDB_RegisterId getRegisterId() const override; + uint32_t getRegisterType() const override; + uint32_t getRelativeVirtualAddress() const override; + uint32_t getSamplerSlot() const override; + uint32_t getSignature() const override; + uint32_t getSizeInUdt() const override; + uint32_t getSlot() const override; + std::string getSourceFileName() const override; + uint32_t getStride() const override; + uint32_t getSubTypeId() const override; + std::string getSymbolsFileName() const override; + uint32_t getSymIndexId() const override; + uint32_t getTargetOffset() const override; + uint32_t getTargetRelativeVirtualAddress() const override; + uint64_t getTargetVirtualAddress() const override; + uint32_t getTargetSection() const override; + uint32_t getTextureSlot() const override; + uint32_t getTimeStamp() const override; + uint32_t getToken() const override; + uint32_t getTypeId() const override; + uint32_t getUavSlot() const override; + std::string getUndecoratedName() const override; + uint32_t getUnmodifiedTypeId() const override; + uint32_t getUpperBoundId() const override; + Variant getValue() const override; + uint32_t getVirtualBaseDispIndex() const override; + uint32_t getVirtualBaseOffset() const override; + uint32_t getVirtualTableShapeId() const override; + PDB_DataKind getDataKind() const override; + PDB_SymType getSymTag() const override; + PDB_UniqueId getGuid() const override; + int32_t getOffset() const override; + int32_t getThisAdjust() const override; + int32_t getVirtualBasePointerOffset() const override; + PDB_LocType getLocationType() const override; + PDB_Machine getMachineType() const override; + PDB_ThunkOrdinal getThunkOrdinal() const override; + uint64_t getLength() const override; + uint64_t getLiveRangeLength() const override; + uint64_t getVirtualAddress() const override; + PDB_UdtType getUdtKind() const override; + bool hasConstructor() const override; + bool hasCustomCallingConvention() const override; + bool hasFarReturn() const override; + bool isCode() const override; + bool isCompilerGenerated() const override; + bool isConstType() const override; + bool isEditAndContinueEnabled() const override; + bool isFunction() const override; + bool getAddressTaken() const override; + bool getNoStackOrdering() const override; + bool hasAlloca() const override; + bool hasAssignmentOperator() const override; + bool hasCTypes() const override; + bool hasCastOperator() const override; + bool hasDebugInfo() const override; + bool hasEH() const override; + bool hasEHa() const override; + bool hasInlAsm() const override; + bool hasInlineAttribute() const override; + bool hasInterruptReturn() const override; + bool hasFramePointer() const override; + bool hasLongJump() const override; + bool hasManagedCode() const override; + bool hasNestedTypes() const override; + bool hasNoInlineAttribute() const override; + bool hasNoReturnAttribute() const override; + bool hasOptimizedCodeDebugInfo() const override; + bool hasOverloadedOperator() const override; + bool hasSEH() const override; + bool hasSecurityChecks() const override; + bool hasSetJump() const override; + bool hasStrictGSCheck() const override; + bool isAcceleratorGroupSharedLocal() const override; + bool isAcceleratorPointerTagLiveRange() const override; + bool isAcceleratorStubFunction() const override; + bool isAggregated() const override; + bool isIntroVirtualFunction() const override; + bool isCVTCIL() const override; + bool isConstructorVirtualBase() const override; + bool isCxxReturnUdt() const override; + bool isDataAligned() const override; + bool isHLSLData() const override; + bool isHotpatchable() const override; + bool isIndirectVirtualBaseClass() const override; + bool isInterfaceUdt() const override; + bool isIntrinsic() const override; + bool isLTCG() const override; + bool isLocationControlFlowDependent() const override; + bool isMSILNetmodule() const override; + bool isMatrixRowMajor() const override; + bool isManagedCode() const override; + bool isMSILCode() const override; + bool isMultipleInheritance() const override; + bool isNaked() const override; + bool isNested() const override; + bool isOptimizedAway() const override; + bool isPacked() const override; + bool isPointerBasedOnSymbolValue() const override; + bool isPointerToDataMember() const override; + bool isPointerToMemberFunction() const override; + bool isPureVirtual() const override; + bool isRValueReference() const override; + bool isRefUdt() const override; + bool isReference() const override; + bool isRestrictedType() const override; + bool isReturnValue() const override; + bool isSafeBuffers() const override; + bool isScoped() const override; + bool isSdl() const override; + bool isSingleInheritance() const override; + bool isSplitted() const override; + bool isStatic() const override; + bool hasPrivateSymbols() const override; + bool isUnalignedType() const override; + bool isUnreached() const override; + bool isValueUdt() const override; + bool isVirtual() const override; + bool isVirtualBaseClass() const override; + bool isVirtualInheritance() const override; + bool isVolatileType() const override; + bool wasInlined() const override; + std::string getUnused() const override; + +private: + const DIASession &Session; + CComPtr<IDiaSymbol> Symbol; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/include/llvm/DebugInfo/PDB/DIA/DIASession.h new file mode 100644 index 000000000000..9a8600fb85ec --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIASession.h @@ -0,0 +1,51 @@ +//===- DIASession.h - DIA implementation of IPDBSession ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASESSION_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASESSION_H + +#include "DIASupport.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" + +namespace llvm { +class DIASession : public IPDBSession { +public: + explicit DIASession(CComPtr<IDiaSession> DiaSession); + + static PDB_ErrorCode createFromPdb(StringRef Path, + std::unique_ptr<IPDBSession> &Session); + static PDB_ErrorCode createFromExe(StringRef Path, + std::unique_ptr<IPDBSession> &Session); + + uint64_t getLoadAddress() const override; + void setLoadAddress(uint64_t Address) override; + std::unique_ptr<PDBSymbolExe> getGlobalScope() const override; + std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override; + + std::unique_ptr<PDBSymbol> + findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override; + + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override; + + std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const override; + std::unique_ptr<IPDBEnumSourceFiles> getSourceFilesForCompiland( + const PDBSymbolCompiland &Compiland) const override; + std::unique_ptr<IPDBSourceFile> + getSourceFileById(uint32_t FileId) const override; + + std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const override; + +private: + CComPtr<IDiaSession> Session; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h b/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h new file mode 100644 index 000000000000..c424e27493c1 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h @@ -0,0 +1,36 @@ +//===- DIASourceFile.h - DIA implementation of IPDBSourceFile ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASOURCEFILE_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASOURCEFILE_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBSourceFile.h" + +namespace llvm { +class DIASession; + +class DIASourceFile : public IPDBSourceFile { +public: + explicit DIASourceFile(const DIASession &Session, + CComPtr<IDiaSourceFile> DiaSourceFile); + + std::string getFileName() const override; + uint32_t getUniqueId() const override; + std::string getChecksum() const override; + PDB_Checksum getChecksumType() const override; + std::unique_ptr<IPDBEnumSymbols> getCompilands() const override; + +private: + const DIASession &Session; + CComPtr<IDiaSourceFile> SourceFile; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASupport.h b/include/llvm/DebugInfo/PDB/DIA/DIASupport.h new file mode 100644 index 000000000000..407a34551cc7 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIASupport.h @@ -0,0 +1,33 @@ +//===- DIASupport.h - Common header includes for DIA ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Common defines and header includes for all LLVMDebugInfoPDBDIA. The +// definitions here configure the necessary #defines and include system headers +// in the proper order for using DIA. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H + +// Require at least Vista +#define NTDDI_VERSION NTDDI_VISTA +#define _WIN32_WINNT _WIN32_WINNT_VISTA +#define WINVER _WIN32_WINNT_VISTA +#ifndef NOMINMAX +#define NOMINMAX +#endif + +// atlbase.h has to come before windows.h +#include <atlbase.h> +#include <windows.h> + +// DIA headers must come after windows headers. +#include <cvconst.h> +#include <dia2.h> + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H diff --git a/include/llvm/DebugInfo/PDB/IPDBDataStream.h b/include/llvm/DebugInfo/PDB/IPDBDataStream.h new file mode 100644 index 000000000000..808a0f3ec3a9 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBDataStream.h @@ -0,0 +1,37 @@ +//===- IPDBDataStream.h - base interface for child enumerator -*- C++ ---*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBDATASTREAM_H +#define LLVM_DEBUGINFO_PDB_IPDBDATASTREAM_H + +#include "PDBTypes.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +/// IPDBDataStream defines an interface used to represent a stream consisting +/// of a name and a series of records whose formats depend on the particular +/// stream type. +class IPDBDataStream { +public: + typedef llvm::SmallVector<uint8_t, 32> RecordType; + + virtual ~IPDBDataStream(); + + virtual uint32_t getRecordCount() const = 0; + virtual std::string getName() const = 0; + virtual llvm::Optional<RecordType> getItemAtIndex(uint32_t Index) const = 0; + virtual bool getNext(RecordType &Record) = 0; + virtual void reset() = 0; + virtual IPDBDataStream *clone() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h b/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h new file mode 100644 index 000000000000..645ac96e23a5 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h @@ -0,0 +1,33 @@ +//===- IPDBEnumChildren.h - base interface for child enumerator -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H +#define LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H + +#include "PDBTypes.h" +#include <memory> + +namespace llvm { + +template <typename ChildType> class IPDBEnumChildren { +public: + typedef std::unique_ptr<ChildType> ChildTypePtr; + typedef IPDBEnumChildren<ChildType> MyType; + + virtual ~IPDBEnumChildren() {} + + virtual uint32_t getChildCount() const = 0; + virtual ChildTypePtr getChildAtIndex(uint32_t Index) const = 0; + virtual ChildTypePtr getNext() = 0; + virtual void reset() = 0; + virtual MyType *clone() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBLineNumber.h b/include/llvm/DebugInfo/PDB/IPDBLineNumber.h new file mode 100644 index 000000000000..92cd58d86649 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBLineNumber.h @@ -0,0 +1,36 @@ +//===- IPDBLineNumber.h - base interface for PDB line no. 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_DEBUGINFO_PDB_IPDBLINENUMBER_H +#define LLVM_DEBUGINFO_PDB_IPDBLINENUMBER_H + +#include "PDBTypes.h" + +namespace llvm { + +class IPDBLineNumber { +public: + virtual ~IPDBLineNumber(); + + virtual uint32_t getLineNumber() const = 0; + virtual uint32_t getLineNumberEnd() const = 0; + virtual uint32_t getColumnNumber() const = 0; + virtual uint32_t getColumnNumberEnd() const = 0; + virtual uint32_t getAddressSection() const = 0; + virtual uint32_t getAddressOffset() const = 0; + virtual uint32_t getRelativeVirtualAddress() const = 0; + virtual uint64_t getVirtualAddress() const = 0; + virtual uint32_t getLength() const = 0; + virtual uint32_t getSourceFileId() const = 0; + virtual uint32_t getCompilandId() const = 0; + virtual bool isStatement() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h new file mode 100644 index 000000000000..139bff56fd5d --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h @@ -0,0 +1,211 @@ +//===- IPDBRawSymbol.h - base interface for PDB symbol types ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBRAWSYMBOL_H +#define LLVM_DEBUGINFO_PDB_IPDBRAWSYMBOL_H + +#include "PDBTypes.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include <memory> + +namespace llvm { + +class raw_ostream; + +/// IPDBRawSymbol defines an interface used to represent an arbitrary symbol. +/// It exposes a monolithic interface consisting of accessors for the union of +/// all properties that are valid for any symbol type. This interface is then +/// wrapped by a concrete class which exposes only those set of methods valid +/// for this particular symbol type. See PDBSymbol.h for more details. +class IPDBRawSymbol { +public: + virtual ~IPDBRawSymbol(); + + virtual void dump(raw_ostream &OS, int Indent) const = 0; + + virtual std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type) const = 0; + + virtual std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const = 0; + virtual std::unique_ptr<IPDBEnumSymbols> + findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint32_t RVA) const = 0; + virtual std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByRVA(uint32_t RVA) const = 0; + + virtual void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const = 0; + virtual void getBackEndVersion(VersionInfo &Version) const = 0; + virtual PDB_MemberAccess getAccess() const = 0; + virtual uint32_t getAddressOffset() const = 0; + virtual uint32_t getAddressSection() const = 0; + virtual uint32_t getAge() const = 0; + virtual uint32_t getArrayIndexTypeId() const = 0; + virtual uint32_t getBaseDataOffset() const = 0; + virtual uint32_t getBaseDataSlot() const = 0; + virtual uint32_t getBaseSymbolId() const = 0; + virtual PDB_BuiltinType getBuiltinType() const = 0; + virtual uint32_t getBitPosition() const = 0; + virtual PDB_CallingConv getCallingConvention() const = 0; + virtual uint32_t getClassParentId() const = 0; + virtual std::string getCompilerName() const = 0; + virtual uint32_t getCount() const = 0; + virtual uint32_t getCountLiveRanges() const = 0; + virtual void getFrontEndVersion(VersionInfo &Version) const = 0; + virtual PDB_Lang getLanguage() const = 0; + virtual uint32_t getLexicalParentId() const = 0; + virtual std::string getLibraryName() const = 0; + virtual uint32_t getLiveRangeStartAddressOffset() const = 0; + virtual uint32_t getLiveRangeStartAddressSection() const = 0; + virtual uint32_t getLiveRangeStartRelativeVirtualAddress() const = 0; + virtual PDB_RegisterId getLocalBasePointerRegisterId() const = 0; + virtual uint32_t getLowerBoundId() const = 0; + virtual uint32_t getMemorySpaceKind() const = 0; + virtual std::string getName() const = 0; + virtual uint32_t getNumberOfAcceleratorPointerTags() const = 0; + virtual uint32_t getNumberOfColumns() const = 0; + virtual uint32_t getNumberOfModifiers() const = 0; + virtual uint32_t getNumberOfRegisterIndices() const = 0; + virtual uint32_t getNumberOfRows() const = 0; + virtual std::string getObjectFileName() const = 0; + virtual uint32_t getOemId() const = 0; + virtual uint32_t getOemSymbolId() const = 0; + virtual uint32_t getOffsetInUdt() const = 0; + virtual PDB_Cpu getPlatform() const = 0; + virtual uint32_t getRank() const = 0; + virtual PDB_RegisterId getRegisterId() const = 0; + virtual uint32_t getRegisterType() const = 0; + virtual uint32_t getRelativeVirtualAddress() const = 0; + virtual uint32_t getSamplerSlot() const = 0; + virtual uint32_t getSignature() const = 0; + virtual uint32_t getSizeInUdt() const = 0; + virtual uint32_t getSlot() const = 0; + virtual std::string getSourceFileName() const = 0; + virtual uint32_t getStride() const = 0; + virtual uint32_t getSubTypeId() const = 0; + virtual std::string getSymbolsFileName() const = 0; + virtual uint32_t getSymIndexId() const = 0; + virtual uint32_t getTargetOffset() const = 0; + virtual uint32_t getTargetRelativeVirtualAddress() const = 0; + virtual uint64_t getTargetVirtualAddress() const = 0; + virtual uint32_t getTargetSection() const = 0; + virtual uint32_t getTextureSlot() const = 0; + virtual uint32_t getTimeStamp() const = 0; + virtual uint32_t getToken() const = 0; + virtual uint32_t getTypeId() const = 0; + virtual uint32_t getUavSlot() const = 0; + virtual std::string getUndecoratedName() const = 0; + virtual uint32_t getUnmodifiedTypeId() const = 0; + virtual uint32_t getUpperBoundId() const = 0; + virtual Variant getValue() const = 0; + virtual uint32_t getVirtualBaseDispIndex() const = 0; + virtual uint32_t getVirtualBaseOffset() const = 0; + virtual uint32_t getVirtualTableShapeId() const = 0; + virtual PDB_DataKind getDataKind() const = 0; + virtual PDB_SymType getSymTag() const = 0; + virtual PDB_UniqueId getGuid() const = 0; + virtual int32_t getOffset() const = 0; + virtual int32_t getThisAdjust() const = 0; + virtual int32_t getVirtualBasePointerOffset() const = 0; + virtual PDB_LocType getLocationType() const = 0; + virtual PDB_Machine getMachineType() const = 0; + virtual PDB_ThunkOrdinal getThunkOrdinal() const = 0; + virtual uint64_t getLength() const = 0; + virtual uint64_t getLiveRangeLength() const = 0; + virtual uint64_t getVirtualAddress() const = 0; + virtual PDB_UdtType getUdtKind() const = 0; + virtual bool hasConstructor() const = 0; + virtual bool hasCustomCallingConvention() const = 0; + virtual bool hasFarReturn() const = 0; + virtual bool isCode() const = 0; + virtual bool isCompilerGenerated() const = 0; + virtual bool isConstType() const = 0; + virtual bool isEditAndContinueEnabled() const = 0; + virtual bool isFunction() const = 0; + virtual bool getAddressTaken() const = 0; + virtual bool getNoStackOrdering() const = 0; + virtual bool hasAlloca() const = 0; + virtual bool hasAssignmentOperator() const = 0; + virtual bool hasCTypes() const = 0; + virtual bool hasCastOperator() const = 0; + virtual bool hasDebugInfo() const = 0; + virtual bool hasEH() const = 0; + virtual bool hasEHa() const = 0; + virtual bool hasFramePointer() const = 0; + virtual bool hasInlAsm() const = 0; + virtual bool hasInlineAttribute() const = 0; + virtual bool hasInterruptReturn() const = 0; + virtual bool hasLongJump() const = 0; + virtual bool hasManagedCode() const = 0; + virtual bool hasNestedTypes() const = 0; + virtual bool hasNoInlineAttribute() const = 0; + virtual bool hasNoReturnAttribute() const = 0; + virtual bool hasOptimizedCodeDebugInfo() const = 0; + virtual bool hasOverloadedOperator() const = 0; + virtual bool hasSEH() const = 0; + virtual bool hasSecurityChecks() const = 0; + virtual bool hasSetJump() const = 0; + virtual bool hasStrictGSCheck() const = 0; + virtual bool isAcceleratorGroupSharedLocal() const = 0; + virtual bool isAcceleratorPointerTagLiveRange() const = 0; + virtual bool isAcceleratorStubFunction() const = 0; + virtual bool isAggregated() const = 0; + virtual bool isIntroVirtualFunction() const = 0; + virtual bool isCVTCIL() const = 0; + virtual bool isConstructorVirtualBase() const = 0; + virtual bool isCxxReturnUdt() const = 0; + virtual bool isDataAligned() const = 0; + virtual bool isHLSLData() const = 0; + virtual bool isHotpatchable() const = 0; + virtual bool isIndirectVirtualBaseClass() const = 0; + virtual bool isInterfaceUdt() const = 0; + virtual bool isIntrinsic() const = 0; + virtual bool isLTCG() const = 0; + virtual bool isLocationControlFlowDependent() const = 0; + virtual bool isMSILNetmodule() const = 0; + virtual bool isMatrixRowMajor() const = 0; + virtual bool isManagedCode() const = 0; + virtual bool isMSILCode() const = 0; + virtual bool isMultipleInheritance() const = 0; + virtual bool isNaked() const = 0; + virtual bool isNested() const = 0; + virtual bool isOptimizedAway() const = 0; + virtual bool isPacked() const = 0; + virtual bool isPointerBasedOnSymbolValue() const = 0; + virtual bool isPointerToDataMember() const = 0; + virtual bool isPointerToMemberFunction() const = 0; + virtual bool isPureVirtual() const = 0; + virtual bool isRValueReference() const = 0; + virtual bool isRefUdt() const = 0; + virtual bool isReference() const = 0; + virtual bool isRestrictedType() const = 0; + virtual bool isReturnValue() const = 0; + virtual bool isSafeBuffers() const = 0; + virtual bool isScoped() const = 0; + virtual bool isSdl() const = 0; + virtual bool isSingleInheritance() const = 0; + virtual bool isSplitted() const = 0; + virtual bool isStatic() const = 0; + virtual bool hasPrivateSymbols() const = 0; + virtual bool isUnalignedType() const = 0; + virtual bool isUnreached() const = 0; + virtual bool isValueUdt() const = 0; + virtual bool isVirtual() const = 0; + virtual bool isVirtualBaseClass() const = 0; + virtual bool isVirtualInheritance() const = 0; + virtual bool isVolatileType() const = 0; + virtual bool wasInlined() const = 0; + virtual std::string getUnused() const = 0; +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBSession.h b/include/llvm/DebugInfo/PDB/IPDBSession.h new file mode 100644 index 000000000000..a130a38a6538 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBSession.h @@ -0,0 +1,61 @@ +//===- IPDBSession.h - base interface for a PDB symbol context --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBSESSION_H +#define LLVM_DEBUGINFO_PDB_IPDBSESSION_H + +#include "PDBTypes.h" +#include "llvm/Support/Casting.h" +#include <memory> + +namespace llvm { + +class PDBSymbolCompiland; +class PDBSymbolExe; + +/// IPDBSession defines an interface used to provide a context for querying +/// debug information from a debug data source (for example, a PDB). +class IPDBSession { +public: + virtual ~IPDBSession(); + + virtual uint64_t getLoadAddress() const = 0; + virtual void setLoadAddress(uint64_t Address) = 0; + virtual std::unique_ptr<PDBSymbolExe> getGlobalScope() const = 0; + virtual std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const = 0; + + template <typename T> + std::unique_ptr<T> getConcreteSymbolById(uint32_t SymbolId) const { + auto Symbol(getSymbolById(SymbolId)); + if (!Symbol) + return nullptr; + + T *ConcreteSymbol = dyn_cast<T>(Symbol.get()); + if (!ConcreteSymbol) + return nullptr; + Symbol.release(); + return std::unique_ptr<T>(ConcreteSymbol); + } + + virtual std::unique_ptr<PDBSymbol> + findSymbolByAddress(uint64_t Address, PDB_SymType Type) const = 0; + virtual std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersByAddress(uint64_t Address, uint32_t Length) const = 0; + + virtual std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const = 0; + virtual std::unique_ptr<IPDBEnumSourceFiles> + getSourceFilesForCompiland(const PDBSymbolCompiland &Compiland) const = 0; + virtual std::unique_ptr<IPDBSourceFile> + getSourceFileById(uint32_t FileId) const = 0; + + virtual std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBSourceFile.h b/include/llvm/DebugInfo/PDB/IPDBSourceFile.h new file mode 100644 index 000000000000..55000eff02f0 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBSourceFile.h @@ -0,0 +1,37 @@ +//===- IPDBSourceFile.h - base interface for a PDB source file --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBSOURCEFILE_H +#define LLVM_DEBUGINFO_PDB_IPDBSOURCEFILE_H + +#include "PDBTypes.h" +#include <memory> +#include <string> + +namespace llvm { + +class raw_ostream; + +/// IPDBSourceFile defines an interface used to represent source files whose +/// information are stored in the PDB. +class IPDBSourceFile { +public: + virtual ~IPDBSourceFile(); + + void dump(raw_ostream &OS, int Indent) const; + + virtual std::string getFileName() const = 0; + virtual uint32_t getUniqueId() const = 0; + virtual std::string getChecksum() const = 0; + virtual PDB_Checksum getChecksumType() const = 0; + virtual std::unique_ptr<IPDBEnumSymbols> getCompilands() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDB.h b/include/llvm/DebugInfo/PDB/PDB.h new file mode 100644 index 000000000000..5df3be85e381 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDB.h @@ -0,0 +1,26 @@ +//===- PDB.h - base header file for creating a PDB reader -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDB_H +#define LLVM_DEBUGINFO_PDB_PDB_H + +#include "PDBTypes.h" +#include <memory> + +namespace llvm { +class StringRef; + +PDB_ErrorCode loadDataForPDB(PDB_ReaderType Type, StringRef Path, + std::unique_ptr<IPDBSession> &Session); + +PDB_ErrorCode loadDataForEXE(PDB_ReaderType Type, StringRef Path, + std::unique_ptr<IPDBSession> &Session); +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBContext.h b/include/llvm/DebugInfo/PDB/PDBContext.h new file mode 100644 index 000000000000..2bb97463f90d --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBContext.h @@ -0,0 +1,60 @@ +//===-- PDBContext.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===/ + +#ifndef LLVM_DEBUGINFO_PDB_PDBCONTEXT_H +#define LLVM_DEBUGINFO_PDB_PDBCONTEXT_H + +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" + +namespace llvm { + +namespace object { +class COFFObjectFile; +} + +/// PDBContext +/// This data structure is the top level entity that deals with PDB debug +/// information parsing. This data structure exists only when there is a +/// need for a transparent interface to different debug information formats +/// (e.g. PDB and DWARF). More control and power over the debug information +/// access can be had by using the PDB interfaces directly. +class PDBContext : public DIContext { + + PDBContext(PDBContext &) = delete; + PDBContext &operator=(PDBContext &) = delete; + +public: + PDBContext(const object::COFFObjectFile &Object, + std::unique_ptr<IPDBSession> PDBSession, + bool RelativeAddress); + + static bool classof(const DIContext *DICtx) { + return DICtx->getKind() == CK_PDB; + } + + void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override; + + DILineInfo getLineInfoForAddress( + uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DILineInfoTable getLineInfoForAddressRange( + uint64_t Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DIInliningInfo getInliningInfoForAddress( + uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + +private: + std::string getFunctionName(uint64_t Address, DINameKind NameKind) const; + std::unique_ptr<IPDBSession> Session; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBExtras.h b/include/llvm/DebugInfo/PDB/PDBExtras.h new file mode 100644 index 000000000000..48ce1c127196 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBExtras.h @@ -0,0 +1,38 @@ +//===- PDBExtras.h - helper functions and classes for PDBs -------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBEXTRAS_H +#define LLVM_DEBUGINFO_PDB_PDBEXTRAS_H + +#include "PDBTypes.h" +#include "llvm/Support/raw_ostream.h" +#include <unordered_map> + +namespace llvm { +typedef std::unordered_map<PDB_SymType, int> TagStats; + +raw_ostream &operator<<(raw_ostream &OS, const PDB_VariantType &Value); +raw_ostream &operator<<(raw_ostream &OS, const PDB_CallingConv &Conv); +raw_ostream &operator<<(raw_ostream &OS, const PDB_DataKind &Data); +raw_ostream &operator<<(raw_ostream &OS, const PDB_RegisterId &Reg); +raw_ostream &operator<<(raw_ostream &OS, const PDB_LocType &Loc); +raw_ostream &operator<<(raw_ostream &OS, const PDB_ThunkOrdinal &Thunk); +raw_ostream &operator<<(raw_ostream &OS, const PDB_Checksum &Checksum); +raw_ostream &operator<<(raw_ostream &OS, const PDB_Lang &Lang); +raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag); +raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access); +raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type); +raw_ostream &operator<<(raw_ostream &OS, const PDB_UniqueId &Id); + +raw_ostream &operator<<(raw_ostream &OS, const Variant &Value); +raw_ostream &operator<<(raw_ostream &OS, const VersionInfo &Version); +raw_ostream &operator<<(raw_ostream &OS, const TagStats &Stats); +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBSymDumper.h b/include/llvm/DebugInfo/PDB/PDBSymDumper.h new file mode 100644 index 000000000000..65110f39366f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymDumper.h @@ -0,0 +1,61 @@ +//===- PDBSymDumper.h - base interface for PDB symbol dumper *- C++ -----*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMDUMPER_H +#define LLVM_DEBUGINFO_PDB_PDBSYMDUMPER_H + +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymDumper { +public: + PDBSymDumper(bool ShouldRequireImpl); + virtual ~PDBSymDumper(); + + virtual void dump(const PDBSymbolAnnotation &Symbol); + virtual void dump(const PDBSymbolBlock &Symbol); + virtual void dump(const PDBSymbolCompiland &Symbol); + virtual void dump(const PDBSymbolCompilandDetails &Symbol); + virtual void dump(const PDBSymbolCompilandEnv &Symbol); + virtual void dump(const PDBSymbolCustom &Symbol); + virtual void dump(const PDBSymbolData &Symbol); + virtual void dump(const PDBSymbolExe &Symbol); + virtual void dump(const PDBSymbolFunc &Symbol); + virtual void dump(const PDBSymbolFuncDebugEnd &Symbol); + virtual void dump(const PDBSymbolFuncDebugStart &Symbol); + virtual void dump(const PDBSymbolLabel &Symbol); + virtual void dump(const PDBSymbolPublicSymbol &Symbol); + virtual void dump(const PDBSymbolThunk &Symbol); + virtual void dump(const PDBSymbolTypeArray &Symbol); + virtual void dump(const PDBSymbolTypeBaseClass &Symbol); + virtual void dump(const PDBSymbolTypeBuiltin &Symbol); + virtual void dump(const PDBSymbolTypeCustom &Symbol); + virtual void dump(const PDBSymbolTypeDimension &Symbol); + virtual void dump(const PDBSymbolTypeEnum &Symbol); + virtual void dump(const PDBSymbolTypeFriend &Symbol); + virtual void dump(const PDBSymbolTypeFunctionArg &Symbol); + virtual void dump(const PDBSymbolTypeFunctionSig &Symbol); + virtual void dump(const PDBSymbolTypeManaged &Symbol); + virtual void dump(const PDBSymbolTypePointer &Symbol); + virtual void dump(const PDBSymbolTypeTypedef &Symbol); + virtual void dump(const PDBSymbolTypeUDT &Symbol); + virtual void dump(const PDBSymbolTypeVTable &Symbol); + virtual void dump(const PDBSymbolTypeVTableShape &Symbol); + virtual void dump(const PDBSymbolUnknown &Symbol); + virtual void dump(const PDBSymbolUsingNamespace &Symbol); + +private: + bool RequireImpl; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbol.h new file mode 100644 index 000000000000..4360c5431e69 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbol.h @@ -0,0 +1,97 @@ +//===- PDBSymbol.h - base class for user-facing symbol types -----*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H +#define LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H + +#include "ConcreteSymbolEnumerator.h" +#include "IPDBRawSymbol.h" +#include "PDBExtras.h" +#include "PDBTypes.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include <unordered_map> + +#define FORWARD_SYMBOL_METHOD(MethodName) \ + auto MethodName() const->decltype(RawSymbol->MethodName()) { \ + return RawSymbol->MethodName(); \ + } + +namespace llvm { + +class IPDBRawSymbol; +class raw_ostream; + +#define DECLARE_PDB_SYMBOL_CONCRETE_TYPE(TagValue) \ + static const PDB_SymType Tag = TagValue; \ + static bool classof(const PDBSymbol *S) { return S->getSymTag() == Tag; } + +/// PDBSymbol defines the base of the inheritance hierarchy for concrete symbol +/// types (e.g. functions, executables, vtables, etc). All concrete symbol +/// types inherit from PDBSymbol and expose the exact set of methods that are +/// valid for that particular symbol type, as described in the Microsoft +/// reference "Lexical and Class Hierarchy of Symbol Types": +/// https://msdn.microsoft.com/en-us/library/370hs6k4.aspx +class PDBSymbol { +protected: + PDBSymbol(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol); + +public: + static std::unique_ptr<PDBSymbol> + create(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol); + + virtual ~PDBSymbol(); + + /// Dumps the contents of a symbol a raw_ostream. By default this will just + /// call dump() on the underlying RawSymbol, which allows us to discover + /// unknown properties, but individual implementations of PDBSymbol may + /// override the behavior to only dump known fields. + virtual void dump(PDBSymDumper &Dumper) const = 0; + void defaultDump(raw_ostream &OS, int Indent) const; + + PDB_SymType getSymTag() const; + + template <typename T> std::unique_ptr<T> findOneChild() const { + auto Enumerator(findAllChildren<T>()); + return Enumerator->getNext(); + } + + template <typename T> + std::unique_ptr<ConcreteSymbolEnumerator<T>> findAllChildren() const { + auto BaseIter = RawSymbol->findChildren(T::Tag); + return llvm::make_unique<ConcreteSymbolEnumerator<T>>(std::move(BaseIter)); + } + std::unique_ptr<IPDBEnumSymbols> findAllChildren(PDB_SymType Type) const; + std::unique_ptr<IPDBEnumSymbols> findAllChildren() const; + + std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const; + std::unique_ptr<IPDBEnumSymbols> findChildrenByRVA(PDB_SymType Type, + StringRef Name, + PDB_NameSearchFlags Flags, + uint32_t RVA) const; + std::unique_ptr<IPDBEnumSymbols> findInlineFramesByRVA(uint32_t RVA) const; + + const IPDBRawSymbol &getRawSymbol() const { return *RawSymbol; } + IPDBRawSymbol &getRawSymbol() { return *RawSymbol; } + + const IPDBSession &getSession() const { return Session; } + + std::unique_ptr<IPDBEnumSymbols> getChildStats(TagStats &Stats) const; + +protected: + const IPDBSession &Session; + const std::unique_ptr<IPDBRawSymbol> RawSymbol; +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h b/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h new file mode 100644 index 000000000000..c055dd7f3d49 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h @@ -0,0 +1,39 @@ +//===- PDBSymbolAnnotation.h - Accessors for querying PDB annotations ---*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include <string> + +namespace llvm { + +class raw_ostream; + +class PDBSymbolAnnotation : public PDBSymbol { +public: + PDBSymbolAnnotation(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Annotation) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getDataKind) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + // FORWARD_SYMBOL_METHOD(getValue) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h new file mode 100644 index 000000000000..2ca12501d9f6 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h @@ -0,0 +1,41 @@ +//===- PDBSymbolBlock.h - Accessors for querying PDB blocks -------------*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include <string> + +namespace llvm { + +class raw_ostream; + +class PDBSymbolBlock : public PDBSymbol { +public: + PDBSymbolBlock(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Block) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h new file mode 100644 index 000000000000..f8c796ae5bdc --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h @@ -0,0 +1,38 @@ +//===- PDBSymbolCompiland.h - Accessors for querying PDB compilands -----*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include <string> + +namespace llvm { + +class raw_ostream; + +class PDBSymbolCompiland : public PDBSymbol { +public: + PDBSymbolCompiland(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> CompilandSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Compiland) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(isEditAndContinueEnabled) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLibraryName) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSourceFileName) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h new file mode 100644 index 000000000000..7f29d6bde990 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h @@ -0,0 +1,55 @@ +//===- PDBSymbolCompilandDetails.h - PDB compiland details ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDDETAILS_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDDETAILS_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolCompilandDetails : public PDBSymbol { +public: + PDBSymbolCompilandDetails(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandDetails) + + void dump(PDBSymDumper &Dumper) const override; + + void getFrontEndVersion(VersionInfo &Version) const { + RawSymbol->getFrontEndVersion(Version); + } + + void getBackEndVersion(VersionInfo &Version) const { + RawSymbol->getBackEndVersion(Version); + } + + FORWARD_SYMBOL_METHOD(getCompilerName) + FORWARD_SYMBOL_METHOD(isEditAndContinueEnabled) + FORWARD_SYMBOL_METHOD(hasDebugInfo) + FORWARD_SYMBOL_METHOD(hasManagedCode) + FORWARD_SYMBOL_METHOD(hasSecurityChecks) + FORWARD_SYMBOL_METHOD(isCVTCIL) + FORWARD_SYMBOL_METHOD(isDataAligned) + FORWARD_SYMBOL_METHOD(isHotpatchable) + FORWARD_SYMBOL_METHOD(isLTCG) + FORWARD_SYMBOL_METHOD(isMSILNetmodule) + FORWARD_SYMBOL_METHOD(getLanguage) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getPlatform) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBFUNCTION_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h new file mode 100644 index 000000000000..7e2ea9018edb --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h @@ -0,0 +1,37 @@ +//===- PDBSymbolCompilandEnv.h - compiland environment variables *- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolCompilandEnv : public PDBSymbol { +public: + PDBSymbolCompilandEnv(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandEnv) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) + std::string getValue() const; +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h b/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h new file mode 100644 index 000000000000..86bfd5707a31 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h @@ -0,0 +1,39 @@ +//===- PDBSymbolCustom.h - compiler-specific types --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class raw_ostream; + +/// PDBSymbolCustom represents symbols that are compiler-specific and do not +/// fit anywhere else in the lexical hierarchy. +/// https://msdn.microsoft.com/en-us/library/d88sf09h.aspx +class PDBSymbolCustom : public PDBSymbol { +public: + PDBSymbolCustom(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> CustomSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Custom) + + void dump(PDBSymDumper &Dumper) const override; + + void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes); + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/include/llvm/DebugInfo/PDB/PDBSymbolData.h new file mode 100644 index 000000000000..79cbbf0e1683 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolData.h @@ -0,0 +1,61 @@ +//===- PDBSymbolData.h - PDB data (e.g. variable) accessors -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolData : public PDBSymbol { +public: + PDBSymbolData(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> DataSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Data) + + std::unique_ptr<PDBSymbol> getType() const; + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getAddressTaken) + FORWARD_SYMBOL_METHOD(getBitPosition) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(isCompilerGenerated) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getDataKind) + FORWARD_SYMBOL_METHOD(isAggregated) + FORWARD_SYMBOL_METHOD(isSplitted) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(getRegisterId) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSlot) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getToken) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getValue) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolExe.h b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h new file mode 100644 index 000000000000..7c5f302ad634 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h @@ -0,0 +1,46 @@ +//===- PDBSymbolExe.h - Accessors for querying executables in a PDB ----*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include <string> + +namespace llvm { + +class raw_ostream; + +class PDBSymbolExe : public PDBSymbol { +public: + PDBSymbolExe(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> ExeSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Exe) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAge) + FORWARD_SYMBOL_METHOD(getGuid) + FORWARD_SYMBOL_METHOD(hasCTypes) + FORWARD_SYMBOL_METHOD(hasPrivateSymbols) + FORWARD_SYMBOL_METHOD(getMachineType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSignature) + FORWARD_SYMBOL_METHOD(getSymbolsFileName) + FORWARD_SYMBOL_METHOD(getSymIndexId) + +private: + void dumpChildren(raw_ostream &OS, StringRef Label, PDB_SymType ChildType, + int Indent) const; +}; +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h new file mode 100644 index 000000000000..9db41d53532a --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h @@ -0,0 +1,80 @@ +//===- PDBSymbolFunc.h - class representing a function instance -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolFunc : public PDBSymbol { +public: + PDBSymbolFunc(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> FuncSymbol); + + void dump(PDBSymDumper &Dumper) const override; + + std::unique_ptr<PDBSymbolTypeFunctionSig> getSignature() const; + std::unique_ptr<PDBSymbolTypeUDT> getClassParent() const; + std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> getArguments() const; + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function) + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(isCompilerGenerated) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasAlloca) + FORWARD_SYMBOL_METHOD(hasEH) + FORWARD_SYMBOL_METHOD(hasEHa) + FORWARD_SYMBOL_METHOD(hasInlAsm) + FORWARD_SYMBOL_METHOD(hasLongJump) + FORWARD_SYMBOL_METHOD(hasSEH) + FORWARD_SYMBOL_METHOD(hasSecurityChecks) + FORWARD_SYMBOL_METHOD(hasSetJump) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(isIntroVirtualFunction) + FORWARD_SYMBOL_METHOD(hasInlineAttribute) + FORWARD_SYMBOL_METHOD(isNaked) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocalBasePointerRegisterId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(hasFramePointer) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getNoStackOrdering) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(isPureVirtual) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getToken) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getUndecoratedName) + FORWARD_SYMBOL_METHOD(isVirtual) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualBaseOffset) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h new file mode 100644 index 000000000000..34d551cda74c --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h @@ -0,0 +1,49 @@ +//===- PDBSymbolFuncDebugEnd.h - function end bounds 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_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolFuncDebugEnd : public PDBSymbol { +public: + PDBSymbolFuncDebugEnd(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> FuncDebugEndSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugEnd) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h new file mode 100644 index 000000000000..7671be480dac --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h @@ -0,0 +1,49 @@ +//===- PDBSymbolFuncDebugStart.h - function start bounds 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_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolFuncDebugStart : public PDBSymbol { +public: + PDBSymbolFuncDebugStart(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> FuncDebugStartSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugStart) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h new file mode 100644 index 000000000000..9d9903a11b0c --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h @@ -0,0 +1,49 @@ +//===- PDBSymbolLabel.h - label 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_DEBUGINFO_PDB_PDBSYMBOLLABEL_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLLABEL_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolLabel : public PDBSymbol { +public: + PDBSymbolLabel(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> LabelSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Label) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLLABEL_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h new file mode 100644 index 000000000000..70dfcb5ddf4c --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h @@ -0,0 +1,47 @@ +//===- PDBSymbolPublicSymbol.h - public symbol 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_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolPublicSymbol : public PDBSymbol { +public: + PDBSymbolPublicSymbol(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> PublicSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PublicSymbol) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(isCode) + FORWARD_SYMBOL_METHOD(isFunction) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(isManagedCode) + FORWARD_SYMBOL_METHOD(isMSILCode) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(getUndecoratedName) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h new file mode 100644 index 000000000000..bd5a9b2aa8b3 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h @@ -0,0 +1,57 @@ +//===- PDBSymbolThunk.h - Support for querying PDB thunks ---------------*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include <string> + +namespace llvm { + +class raw_ostream; + +class PDBSymbolThunk : public PDBSymbol { +public: + PDBSymbolThunk(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> ThunkSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Thunk) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(isIntroVirtualFunction) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isPureVirtual) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTargetOffset) + FORWARD_SYMBOL_METHOD(getTargetRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getTargetVirtualAddress) + FORWARD_SYMBOL_METHOD(getTargetSection) + FORWARD_SYMBOL_METHOD(getThunkOrdinal) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVirtual) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualBaseOffset) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h new file mode 100644 index 000000000000..513a9ec05ff8 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h @@ -0,0 +1,45 @@ +//===- PDBSymbolTypeArray.h - array type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeArray : public PDBSymbol { +public: + PDBSymbolTypeArray(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> ArrayTypeSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ArrayType) + + std::unique_ptr<PDBSymbol> getElementType() const; + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getArrayIndexTypeId) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getCount) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getRank) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h new file mode 100644 index 000000000000..2a9a8a0788a8 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h @@ -0,0 +1,60 @@ +//===- PDBSymbolTypeBaseClass.h - base class type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeBaseClass : public PDBSymbol { +public: + PDBSymbolTypeBaseClass(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BaseClass) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(isIndirectVirtualBaseClass) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(getUdtKind) + FORWARD_SYMBOL_METHOD(isUnalignedType) + + FORWARD_SYMBOL_METHOD(isVirtualBaseClass) + FORWARD_SYMBOL_METHOD(getVirtualBaseDispIndex) + FORWARD_SYMBOL_METHOD(getVirtualBasePointerOffset) + // FORWARD_SYMBOL_METHOD(getVirtualBaseTableType) + FORWARD_SYMBOL_METHOD(getVirtualTableShapeId) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h new file mode 100644 index 000000000000..69a2028a1b1d --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h @@ -0,0 +1,40 @@ +//===- PDBSymbolTypeBuiltin.h - builtin type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeBuiltin : public PDBSymbol { +public: + PDBSymbolTypeBuiltin(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BuiltinType) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getBuiltinType) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h new file mode 100644 index 000000000000..c41c48933e0d --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h @@ -0,0 +1,36 @@ +//===- PDBSymbolTypeCustom.h - custom compiler type 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_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeCustom : public PDBSymbol { +public: + PDBSymbolTypeCustom(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CustomType) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getOemId) + FORWARD_SYMBOL_METHOD(getOemSymbolId) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h new file mode 100644 index 000000000000..3f22ed8d731e --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h @@ -0,0 +1,36 @@ +//===- PDBSymbolTypeDimension.h - array dimension type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeDimension : public PDBSymbol { +public: + PDBSymbolTypeDimension(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Dimension) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getLowerBoundId) + FORWARD_SYMBOL_METHOD(getUpperBoundId) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h new file mode 100644 index 000000000000..3188c711915c --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h @@ -0,0 +1,55 @@ +//===- PDBSymbolTypeEnum.h - enum type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeEnum : public PDBSymbol { +public: + PDBSymbolTypeEnum(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> EnumTypeSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Enum) + + void dump(PDBSymDumper &Dumper) const override; + + std::unique_ptr<PDBSymbolTypeUDT> getClassParent() const; + std::unique_ptr<PDBSymbolTypeBuiltin> getUnderlyingType() const; + + FORWARD_SYMBOL_METHOD(getBuiltinType) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h new file mode 100644 index 000000000000..4d393d7b6c5c --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h @@ -0,0 +1,37 @@ +//===- PDBSymbolTypeFriend.h - friend type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeFriend : public PDBSymbol { +public: + PDBSymbolTypeFriend(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Friend) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h new file mode 100644 index 000000000000..14f79d99b6f8 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h @@ -0,0 +1,37 @@ +//===- PDBSymbolTypeFunctionArg.h - function arg type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeFunctionArg : public PDBSymbol { +public: + PDBSymbolTypeFunctionArg(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionArg) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h new file mode 100644 index 000000000000..4bb4265a22f6 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h @@ -0,0 +1,50 @@ +//===- PDBSymbolTypeFunctionSig.h - function signature type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeFunctionSig : public PDBSymbol { +public: + PDBSymbolTypeFunctionSig(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionSig) + + std::unique_ptr<PDBSymbol> getReturnType() const; + std::unique_ptr<IPDBEnumSymbols> getArguments() const; + std::unique_ptr<PDBSymbol> getClassParent() const; + + void dump(PDBSymDumper &Dumper) const override; + void dumpArgList(raw_ostream &OS) const; + + FORWARD_SYMBOL_METHOD(getCallingConvention) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getCount) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + // FORWARD_SYMBOL_METHOD(getObjectPointerType) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getThisAdjust) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h new file mode 100644 index 000000000000..cbfcec82a637 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h @@ -0,0 +1,35 @@ +//===- PDBSymbolTypeManaged.h - managed type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeManaged : public PDBSymbol { +public: + PDBSymbolTypeManaged(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ManagedType) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h new file mode 100644 index 000000000000..33578bad0245 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h @@ -0,0 +1,43 @@ +//===- PDBSymbolTypePointer.h - pointer type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypePointer : public PDBSymbol { +public: + PDBSymbolTypePointer(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PointerType) + + std::unique_ptr<PDBSymbol> getPointeeType() const; + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(isReference) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h new file mode 100644 index 000000000000..5ad83bb1ec26 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h @@ -0,0 +1,54 @@ +//===- PDBSymbolTypeTypedef.h - typedef type 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_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeTypedef : public PDBSymbol { +public: + PDBSymbolTypeTypedef(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Typedef) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getBuiltinType) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isReference) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(getUdtKind) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getVirtualTableShapeId) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h new file mode 100644 index 000000000000..99cc307a83e3 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h @@ -0,0 +1,52 @@ +//===- PDBSymbolTypeUDT.h - UDT type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeUDT : public PDBSymbol { +public: + PDBSymbolTypeUDT(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> UDTSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UDT) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getUdtKind) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getVirtualTableShapeId) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h new file mode 100644 index 000000000000..6efc549f0cb7 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h @@ -0,0 +1,40 @@ +//===- PDBSymbolTypeVTable.h - VTable type 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_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeVTable : public PDBSymbol { +public: + PDBSymbolTypeVTable(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> VtblSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTable) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h new file mode 100644 index 000000000000..f407595a4cc8 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h @@ -0,0 +1,39 @@ +//===- PDBSymbolTypeVTableShape.h - VTable shape 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_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeVTableShape : public PDBSymbol { +public: + PDBSymbolTypeVTableShape(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> VtblShapeSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTableShape) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getCount) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h b/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h new file mode 100644 index 000000000000..94bd2c14079f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h @@ -0,0 +1,34 @@ +//===- PDBSymbolUnknown.h - unknown symbol type -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H + +#include "PDBSymbol.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolUnknown : public PDBSymbol { +public: + PDBSymbolUnknown(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> UnknownSymbol); + + void dump(PDBSymDumper &Dumper) const override; + + static bool classof(const PDBSymbol *S) { + return (S->getSymTag() == PDB_SymType::None || + S->getSymTag() >= PDB_SymType::Max); + } +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h new file mode 100644 index 000000000000..7072f342bef3 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h @@ -0,0 +1,36 @@ +//===- PDBSymbolUsingNamespace.h - using namespace 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_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolUsingNamespace : public PDBSymbol { +public: + PDBSymbolUsingNamespace(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UsingNamespace) + + void dump(PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H diff --git a/include/llvm/DebugInfo/PDB/PDBTypes.h b/include/llvm/DebugInfo/PDB/PDBTypes.h new file mode 100644 index 000000000000..2d19e792d3d0 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -0,0 +1,516 @@ +//===- PDBTypes.h - Defines enums for various fields contained in PDB ---*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBTYPES_H +#define LLVM_DEBUGINFO_PDB_PDBTYPES_H + +#include "llvm/Config/llvm-config.h" +#include <functional> +#include <stdint.h> + +namespace llvm { + +class PDBSymDumper; +class PDBSymbol; + +class IPDBDataStream; +template <class T> class IPDBEnumChildren; +class IPDBLineNumber; +class IPDBRawSymbol; +class IPDBSession; +class IPDBSourceFile; + +typedef IPDBEnumChildren<PDBSymbol> IPDBEnumSymbols; +typedef IPDBEnumChildren<IPDBSourceFile> IPDBEnumSourceFiles; +typedef IPDBEnumChildren<IPDBDataStream> IPDBEnumDataStreams; +typedef IPDBEnumChildren<IPDBLineNumber> IPDBEnumLineNumbers; + +class PDBSymbolExe; +class PDBSymbolCompiland; +class PDBSymbolCompilandDetails; +class PDBSymbolCompilandEnv; +class PDBSymbolFunc; +class PDBSymbolBlock; +class PDBSymbolData; +class PDBSymbolAnnotation; +class PDBSymbolLabel; +class PDBSymbolPublicSymbol; +class PDBSymbolTypeUDT; +class PDBSymbolTypeEnum; +class PDBSymbolTypeFunctionSig; +class PDBSymbolTypePointer; +class PDBSymbolTypeArray; +class PDBSymbolTypeBuiltin; +class PDBSymbolTypeTypedef; +class PDBSymbolTypeBaseClass; +class PDBSymbolTypeFriend; +class PDBSymbolTypeFunctionArg; +class PDBSymbolFuncDebugStart; +class PDBSymbolFuncDebugEnd; +class PDBSymbolUsingNamespace; +class PDBSymbolTypeVTableShape; +class PDBSymbolTypeVTable; +class PDBSymbolCustom; +class PDBSymbolThunk; +class PDBSymbolTypeCustom; +class PDBSymbolTypeManaged; +class PDBSymbolTypeDimension; +class PDBSymbolUnknown; + +/// Specifies which PDB reader implementation is to be used. Only a value +/// of PDB_ReaderType::DIA is supported. +enum class PDB_ReaderType { + DIA = 0, +}; + +/// Defines a 128-bit unique identifier. This maps to a GUID on Windows, but +/// is abstracted here for the purposes of non-Windows platforms that don't have +/// the GUID structure defined. +struct PDB_UniqueId { + uint64_t HighPart; + uint64_t LowPart; +}; + +/// An enumeration indicating the type of data contained in this table. +enum class PDB_TableType { + Symbols, + SourceFiles, + LineNumbers, + SectionContribs, + Segments, + InjectedSources, + FrameData +}; + +/// Defines flags used for enumerating child symbols. This corresponds to the +/// NameSearchOptions enumeration which is documented here: +/// https://msdn.microsoft.com/en-us/library/yat28ads.aspx +enum PDB_NameSearchFlags { + NS_Default = 0x0, + NS_CaseSensitive = 0x1, + NS_CaseInsensitive = 0x2, + NS_FileNameExtMatch = 0x4, + NS_Regex = 0x8, + NS_UndecoratedName = 0x10 +}; + +/// Specifies the hash algorithm that a source file from a PDB was hashed with. +/// This corresponds to the CV_SourceChksum_t enumeration and are documented +/// here: https://msdn.microsoft.com/en-us/library/e96az21x.aspx +enum class PDB_Checksum { None = 0, MD5 = 1, SHA1 = 2 }; + +/// These values correspond to the CV_CPU_TYPE_e enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx +enum class PDB_Cpu { + Intel8080 = 0x0, + Intel8086 = 0x1, + Intel80286 = 0x2, + Intel80386 = 0x3, + Intel80486 = 0x4, + Pentium = 0x5, + PentiumPro = 0x6, + Pentium3 = 0x7, + MIPS = 0x10, + MIPS16 = 0x11, + MIPS32 = 0x12, + MIPS64 = 0x13, + MIPSI = 0x14, + MIPSII = 0x15, + MIPSIII = 0x16, + MIPSIV = 0x17, + MIPSV = 0x18, + M68000 = 0x20, + M68010 = 0x21, + M68020 = 0x22, + M68030 = 0x23, + M68040 = 0x24, + Alpha = 0x30, + Alpha21164 = 0x31, + Alpha21164A = 0x32, + Alpha21264 = 0x33, + Alpha21364 = 0x34, + PPC601 = 0x40, + PPC603 = 0x41, + PPC604 = 0x42, + PPC620 = 0x43, + PPCFP = 0x44, + PPCBE = 0x45, + SH3 = 0x50, + SH3E = 0x51, + SH3DSP = 0x52, + SH4 = 0x53, + SHMedia = 0x54, + ARM3 = 0x60, + ARM4 = 0x61, + ARM4T = 0x62, + ARM5 = 0x63, + ARM5T = 0x64, + ARM6 = 0x65, + ARM_XMAC = 0x66, + ARM_WMMX = 0x67, + ARM7 = 0x68, + Omni = 0x70, + Ia64 = 0x80, + Ia64_2 = 0x81, + CEE = 0x90, + AM33 = 0xa0, + M32R = 0xb0, + TriCore = 0xc0, + X64 = 0xd0, + EBC = 0xe0, + Thumb = 0xf0, + ARMNT = 0xf4, + D3D11_Shader = 0x100, +}; + +enum class PDB_Machine { + Invalid = 0xffff, + Unknown = 0x0, + Am33 = 0x13, + Amd64 = 0x8664, + Arm = 0x1C0, + ArmNT = 0x1C4, + Ebc = 0xEBC, + x86 = 0x14C, + Ia64 = 0x200, + M32R = 0x9041, + Mips16 = 0x266, + MipsFpu = 0x366, + MipsFpu16 = 0x466, + PowerPC = 0x1F0, + PowerPCFP = 0x1F1, + R4000 = 0x166, + SH3 = 0x1A2, + SH3DSP = 0x1A3, + SH4 = 0x1A6, + SH5 = 0x1A8, + Thumb = 0x1C2, + WceMipsV2 = 0x169 +}; + +/// These values correspond to the CV_call_e enumeration, and are documented +/// at the following locations: +/// https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx +/// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680207(v=vs.85).aspx +/// +enum class PDB_CallingConv { + NearCdecl = 0x00, + FarCdecl = 0x01, + NearPascal = 0x02, + FarPascal = 0x03, + NearFastcall = 0x04, + FarFastcall = 0x05, + Skipped = 0x06, + NearStdcall = 0x07, + FarStdcall = 0x08, + NearSyscall = 0x09, + FarSyscall = 0x0a, + Thiscall = 0x0b, + MipsCall = 0x0c, + Generic = 0x0d, + Alphacall = 0x0e, + Ppccall = 0x0f, + SuperHCall = 0x10, + Armcall = 0x11, + AM33call = 0x12, + Tricall = 0x13, + Sh5call = 0x14, + M32R = 0x15, + Clrcall = 0x16, + Inline = 0x17, + NearVectorcall = 0x18, + Reserved = 0x19, +}; + +/// These values correspond to the CV_CFL_LANG enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/bw3aekw6.aspx +enum class PDB_Lang { + C = 0x00, + Cpp = 0x01, + Fortran = 0x02, + Masm = 0x03, + Pascal = 0x04, + Basic = 0x05, + Cobol = 0x06, + Link = 0x07, + Cvtres = 0x08, + Cvtpgd = 0x09, + CSharp = 0x0a, + VB = 0x0b, + ILAsm = 0x0c, + Java = 0x0d, + JScript = 0x0e, + MSIL = 0x0f, + HLSL = 0x10 +}; + +/// These values correspond to the DataKind enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/b2x2t313.aspx +enum class PDB_DataKind { + Unknown, + Local, + StaticLocal, + Param, + ObjectPtr, + FileStatic, + Global, + Member, + StaticMember, + Constant +}; + +/// These values correspond to the SymTagEnum enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/bkedss5f.aspx +enum class PDB_SymType { + None, + Exe, + Compiland, + CompilandDetails, + CompilandEnv, + Function, + Block, + Data, + Annotation, + Label, + PublicSymbol, + UDT, + Enum, + FunctionSig, + PointerType, + ArrayType, + BuiltinType, + Typedef, + BaseClass, + Friend, + FunctionArg, + FuncDebugStart, + FuncDebugEnd, + UsingNamespace, + VTableShape, + VTable, + Custom, + Thunk, + CustomType, + ManagedType, + Dimension, + Max +}; + +/// These values correspond to the LocationType enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/f57kaez3.aspx +enum class PDB_LocType { + Null, + Static, + TLS, + RegRel, + ThisRel, + Enregistered, + BitField, + Slot, + IlRel, + MetaData, + Constant, + Max +}; + +/// These values correspond to the THUNK_ORDINAL enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/dh0k8hft.aspx +enum class PDB_ThunkOrdinal { + Standard, + ThisAdjustor, + Vcall, + Pcode, + UnknownLoad, + TrampIncremental, + BranchIsland +}; + +/// These values correspond to the UdtKind enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/wcstk66t.aspx +enum class PDB_UdtType { Struct, Class, Union, Interface }; + +/// These values correspond to the StackFrameTypeEnum enumeration, and are +/// documented here: https://msdn.microsoft.com/en-us/library/bc5207xw.aspx. +enum class PDB_StackFrameType { FPO, KernelTrap, KernelTSS, EBP, FrameData }; + +/// These values correspond to the StackFrameTypeEnum enumeration, and are +/// documented here: https://msdn.microsoft.com/en-us/library/bc5207xw.aspx. +enum class PDB_MemoryType { Code, Data, Stack, HeapCode }; + +/// These values correspond to the Basictype enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/4szdtzc3.aspx +enum class PDB_BuiltinType { + None = 0, + Void = 1, + Char = 2, + WCharT = 3, + Int = 6, + UInt = 7, + Float = 8, + BCD = 9, + Bool = 10, + Long = 13, + ULong = 14, + Currency = 25, + Date = 26, + Variant = 27, + Complex = 28, + Bitfield = 29, + BSTR = 30, + HResult = 31 +}; + +enum class PDB_RegisterId { + Unknown = 0, + VFrame = 30006, + AL = 1, + CL = 2, + DL = 3, + BL = 4, + AH = 5, + CH = 6, + DH = 7, + BH = 8, + AX = 9, + CX = 10, + DX = 11, + BX = 12, + SP = 13, + BP = 14, + SI = 15, + DI = 16, + EAX = 17, + ECX = 18, + EDX = 19, + EBX = 20, + ESP = 21, + EBP = 22, + ESI = 23, + EDI = 24, + ES = 25, + CS = 26, + SS = 27, + DS = 28, + FS = 29, + GS = 30, + IP = 31, + RAX = 328, + RBX = 329, + RCX = 330, + RDX = 331, + RSI = 332, + RDI = 333, + RBP = 334, + RSP = 335, + R8 = 336, + R9 = 337, + R10 = 338, + R11 = 339, + R12 = 340, + R13 = 341, + R14 = 342, + R15 = 343, +}; + +enum class PDB_MemberAccess { Private = 1, Protected = 2, Public = 3 }; + +enum class PDB_ErrorCode { + Success, + NoPdbImpl, + InvalidPath, + InvalidFileFormat, + InvalidParameter, + AlreadyLoaded, + UnknownError, + NoMemory, + DebugInfoMismatch +}; + +struct VersionInfo { + uint32_t Major; + uint32_t Minor; + uint32_t Build; + uint32_t QFE; +}; + +enum PDB_VariantType { + Empty, + Unknown, + Int8, + Int16, + Int32, + Int64, + Single, + Double, + UInt8, + UInt16, + UInt32, + UInt64, + Bool, +}; + +struct Variant { + Variant() + : Type(PDB_VariantType::Empty) { + } + + PDB_VariantType Type; + union { + bool Bool; + int8_t Int8; + int16_t Int16; + int32_t Int32; + int64_t Int64; + float Single; + double Double; + uint8_t UInt8; + uint16_t UInt16; + uint32_t UInt32; + uint64_t UInt64; + }; +#define VARIANT_EQUAL_CASE(Enum) \ + case PDB_VariantType::Enum: \ + return Enum == Other.Enum; + bool operator==(const Variant &Other) const { + if (Type != Other.Type) + return false; + switch (Type) { + VARIANT_EQUAL_CASE(Bool) + VARIANT_EQUAL_CASE(Int8) + VARIANT_EQUAL_CASE(Int16) + VARIANT_EQUAL_CASE(Int32) + VARIANT_EQUAL_CASE(Int64) + VARIANT_EQUAL_CASE(Single) + VARIANT_EQUAL_CASE(Double) + VARIANT_EQUAL_CASE(UInt8) + VARIANT_EQUAL_CASE(UInt16) + VARIANT_EQUAL_CASE(UInt32) + VARIANT_EQUAL_CASE(UInt64) + default: + return true; + } + } +#undef VARIANT_EQUAL_CASE + bool operator!=(const Variant &Other) const { return !(*this == Other); } +}; + +} // namespace llvm + +namespace std { +template <> struct hash<llvm::PDB_SymType> { + typedef llvm::PDB_SymType argument_type; + typedef std::size_t result_type; + + result_type operator()(const argument_type &Arg) const { + return std::hash<int>()(static_cast<int>(Arg)); + } +}; +} + +#endif diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index d79bd3c4dfc8..4b2add8bf5df 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -15,6 +15,7 @@ #ifndef LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H #define LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H +#include "RuntimeDyld.h" #include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -42,6 +43,7 @@ class GlobalVariable; class GlobalValue; class JITEventListener; class MachineCodeInfo; +class MCJITMemoryManager; class MutexGuard; class ObjectCache; class RTDyldMemoryManager; @@ -57,46 +59,34 @@ namespace object { /// table. Access to this class should be serialized under a mutex. class ExecutionEngineState { public: - struct AddressMapConfig : public ValueMapConfig<const GlobalValue*> { - typedef ExecutionEngineState *ExtraData; - static sys::Mutex *getMutex(ExecutionEngineState *EES); - static void onDelete(ExecutionEngineState *EES, const GlobalValue *Old); - static void onRAUW(ExecutionEngineState *, const GlobalValue *, - const GlobalValue *); - }; - - typedef ValueMap<const GlobalValue *, void *, AddressMapConfig> - GlobalAddressMapTy; + typedef StringMap<uint64_t> GlobalAddressMapTy; private: - ExecutionEngine &EE; - /// GlobalAddressMap - A mapping between LLVM global values and their - /// actualized version... + /// GlobalAddressMap - A mapping between LLVM global symbol names values and + /// their actualized version... GlobalAddressMapTy GlobalAddressMap; /// GlobalAddressReverseMap - This is the reverse mapping of GlobalAddressMap, /// used to convert raw addresses into the LLVM global value that is emitted /// at the address. This map is not computed unless getGlobalValueAtAddress /// is called at some point. - std::map<void *, AssertingVH<const GlobalValue> > GlobalAddressReverseMap; + std::map<uint64_t, std::string> GlobalAddressReverseMap; public: - ExecutionEngineState(ExecutionEngine &EE); GlobalAddressMapTy &getGlobalAddressMap() { return GlobalAddressMap; } - std::map<void*, AssertingVH<const GlobalValue> > & - getGlobalAddressReverseMap() { + std::map<uint64_t, std::string> &getGlobalAddressReverseMap() { return GlobalAddressReverseMap; } /// \brief Erase an entry from the mapping table. /// /// \returns The address that \p ToUnmap was happed to. - void *RemoveMapping(const GlobalValue *ToUnmap); + uint64_t RemoveMapping(StringRef Name); }; /// \brief Abstract interface for implementation execution of LLVM modules, @@ -139,10 +129,18 @@ protected: virtual char *getMemoryForGV(const GlobalVariable *GV); static ExecutionEngine *(*MCJITCtor)( - std::unique_ptr<Module> M, - std::string *ErrorStr, - std::unique_ptr<RTDyldMemoryManager> MCJMM, - std::unique_ptr<TargetMachine> TM); + std::unique_ptr<Module> M, + std::string *ErrorStr, + std::shared_ptr<MCJITMemoryManager> MM, + std::shared_ptr<RuntimeDyld::SymbolResolver> SR, + std::unique_ptr<TargetMachine> TM); + + static ExecutionEngine *(*OrcMCJITReplacementCtor)( + std::string *ErrorStr, + std::shared_ptr<MCJITMemoryManager> MM, + std::shared_ptr<RuntimeDyld::SymbolResolver> SR, + std::unique_ptr<TargetMachine> TM); + static ExecutionEngine *(*InterpCtor)(std::unique_ptr<Module> M, std::string *ErrorStr); @@ -151,6 +149,9 @@ protected: /// abort. void *(*LazyFunctionCreator)(const std::string &); + /// getMangledName - Get mangled name. + std::string getMangledName(const GlobalValue *GV); + public: /// lock - This lock protects the ExecutionEngine and MCJIT classes. It must /// be held while changing the internal state of any of those classes. @@ -222,7 +223,8 @@ public: /// Map the address of a JIT section as returned from the memory manager /// to the address in the target process as the running code will see it. /// This is the address which will be used for relocation resolution. - virtual void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) { + virtual void mapSectionAddress(const void *LocalAddress, + uint64_t TargetAddress) { llvm_unreachable("Re-mapping of section addresses not supported with this " "EE!"); } @@ -280,6 +282,7 @@ public: /// existing data in memory. Mappings are automatically removed when their /// GlobalValue is destroyed. void addGlobalMapping(const GlobalValue *GV, void *Addr); + void addGlobalMapping(StringRef Name, uint64_t Addr); /// clearAllGlobalMappings - Clear all global mappings and start over again, /// for use in dynamic compilation scenarios to move globals. @@ -293,14 +296,17 @@ public: /// address. This updates both maps as required. If "Addr" is null, the /// entry for the global is removed from the mappings. This returns the old /// value of the pointer, or null if it was not in the map. - void *updateGlobalMapping(const GlobalValue *GV, void *Addr); + uint64_t updateGlobalMapping(const GlobalValue *GV, void *Addr); + uint64_t updateGlobalMapping(StringRef Name, uint64_t Addr); + + /// getAddressToGlobalIfAvailable - This returns the address of the specified + /// global symbol. + uint64_t getAddressToGlobalIfAvailable(StringRef S); /// getPointerToGlobalIfAvailable - This returns the address of the specified /// global value if it is has already been codegen'd, otherwise it returns /// null. - /// - /// This function is deprecated for the MCJIT execution engine. It doesn't - /// seem to be needed in that case, but an equivalent can be added if it is. + void *getPointerToGlobalIfAvailable(StringRef S); void *getPointerToGlobalIfAvailable(const GlobalValue *GV); /// getPointerToGlobal - This returns the address of the specified global @@ -464,6 +470,7 @@ public: } protected: + ExecutionEngine() {} explicit ExecutionEngine(std::unique_ptr<Module> M); void emitGlobals(); @@ -493,7 +500,8 @@ private: EngineKind::Kind WhichEngine; std::string *ErrorStr; CodeGenOpt::Level OptLevel; - std::unique_ptr<RTDyldMemoryManager> MCJMM; + std::shared_ptr<MCJITMemoryManager> MemMgr; + std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver; TargetOptions Options; Reloc::Model RelocModel; CodeModel::Model CMModel; @@ -501,11 +509,12 @@ private: std::string MCPU; SmallVector<std::string, 4> MAttrs; bool VerifyModules; - - /// InitEngine - Does the common initialization of default options. - void InitEngine(); + bool UseOrcMCJITReplacement; public: + /// Default constructor for EngineBuilder. + EngineBuilder(); + /// Constructor for EngineBuilder. EngineBuilder(std::unique_ptr<Module> M); @@ -527,6 +536,12 @@ public: /// memory manager. This option defaults to NULL. EngineBuilder &setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm); + EngineBuilder& + setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM); + + EngineBuilder& + setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR); + /// setErrorStr - Set the error string to write to on error. This option /// defaults to NULL. EngineBuilder &setErrorStr(std::string *e) { @@ -590,6 +605,11 @@ public: return *this; } + // \brief Use OrcMCJITReplacement instead of MCJIT. Off by default. + void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) { + this->UseOrcMCJITReplacement = UseOrcMCJITReplacement; + } + TargetMachine *selectTarget(); /// selectTarget - Pick a target either via -march or by guessing the native diff --git a/include/llvm/ExecutionEngine/JITSymbolFlags.h b/include/llvm/ExecutionEngine/JITSymbolFlags.h new file mode 100644 index 000000000000..450e9481fa00 --- /dev/null +++ b/include/llvm/ExecutionEngine/JITSymbolFlags.h @@ -0,0 +1,81 @@ +//===------ JITSymbolFlags.h - Flags for symbols in the JIT -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Symbol flags for symbols in the JIT (e.g. weak, exported). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_JITSYMBOLFLAGS_H +#define LLVM_EXECUTIONENGINE_JITSYMBOLFLAGS_H + +#include "llvm/IR/GlobalValue.h" + +namespace llvm { + +/// @brief Flags for symbols in the JIT. +enum class JITSymbolFlags : char { + None = 0, + Weak = 1U << 0, + Exported = 1U << 1 +}; + +inline JITSymbolFlags operator|(JITSymbolFlags LHS, JITSymbolFlags RHS) { + typedef std::underlying_type<JITSymbolFlags>::type UT; + return static_cast<JITSymbolFlags>( + static_cast<UT>(LHS) | static_cast<UT>(RHS)); +} + +inline JITSymbolFlags& operator |=(JITSymbolFlags &LHS, JITSymbolFlags RHS) { + LHS = LHS | RHS; + return LHS; +} + +inline JITSymbolFlags operator&(JITSymbolFlags LHS, JITSymbolFlags RHS) { + typedef std::underlying_type<JITSymbolFlags>::type UT; + return static_cast<JITSymbolFlags>( + static_cast<UT>(LHS) & static_cast<UT>(RHS)); +} + +inline JITSymbolFlags& operator &=(JITSymbolFlags &LHS, JITSymbolFlags RHS) { + LHS = LHS & RHS; + return LHS; +} + +/// @brief Base class for symbols in the JIT. +class JITSymbolBase { +public: + JITSymbolBase(JITSymbolFlags Flags) : Flags(Flags) {} + + JITSymbolFlags getFlags() const { return Flags; } + + bool isWeak() const { + return (Flags & JITSymbolFlags::Weak) == JITSymbolFlags::Weak; + } + + bool isExported() const { + return (Flags & JITSymbolFlags::Exported) == JITSymbolFlags::Exported; + } + + static JITSymbolFlags flagsFromGlobalValue(const GlobalValue &GV) { + JITSymbolFlags Flags = JITSymbolFlags::None; + if (GV.hasWeakLinkage()) + Flags |= JITSymbolFlags::Weak; + if (!GV.hasLocalLinkage() && !GV.hasHiddenVisibility()) + Flags |= JITSymbolFlags::Exported; + return Flags; + + } + +private: + JITSymbolFlags Flags; +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h b/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h new file mode 100644 index 000000000000..b07561152ec0 --- /dev/null +++ b/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h @@ -0,0 +1,63 @@ +//===- ObjectMemoryBuffer.h - SmallVector-backed MemoryBuffrer -*- 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 a wrapper class to hold the memory into which an +// object will be generated. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H +#define LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +/// \brief SmallVector-backed MemoryBuffer instance. +/// +/// This class enables efficient construction of MemoryBuffers from SmallVector +/// instances. This is useful for MCJIT and Orc, where object files are streamed +/// into SmallVectors, then inspected using ObjectFile (which takes a +/// MemoryBuffer). +class ObjectMemoryBuffer : public MemoryBuffer { +public: + + /// \brief Construct an ObjectMemoryBuffer from the given SmallVector r-value. + /// + /// FIXME: It'd be nice for this to be a non-templated constructor taking a + /// SmallVectorImpl here instead of a templated one taking a SmallVector<N>, + /// but SmallVector's move-construction/assignment currently only take + /// SmallVectors. If/when that is fixed we can simplify this constructor and + /// the following one. + ObjectMemoryBuffer(SmallVectorImpl<char> &&SV) + : SV(std::move(SV)), BufferName("<in-memory object>") { + init(this->SV.begin(), this->SV.end(), false); + } + + /// \brief Construct a named ObjectMemoryBuffer from the given SmallVector + /// r-value and StringRef. + ObjectMemoryBuffer(SmallVectorImpl<char> &&SV, StringRef Name) + : SV(std::move(SV)), BufferName(Name) { + init(this->SV.begin(), this->SV.end(), false); + } + + const char* getBufferIdentifier() const override { return BufferName.c_str(); } + + BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; } + +private: + SmallVector<char, 0> SV; + std::string BufferName; +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h new file mode 100644 index 000000000000..719adbc562c2 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -0,0 +1,547 @@ +//===- CompileOnDemandLayer.h - Compile each function on demand -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// JIT layer for breaking up modules and inserting callbacks to allow +// individual functions to be compiled on demand. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H + +//#include "CloneSubModule.h" +#include "IndirectionUtils.h" +#include "LambdaResolver.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include <list> +#include <set> + +#include "llvm/Support/Debug.h" + +namespace llvm { +namespace orc { + +/// @brief Compile-on-demand layer. +/// +/// When a module is added to this layer a stub is created for each of its +/// function definitions. The stubs and other global values are immediately +/// added to the layer below. When a stub is called it triggers the extraction +/// of the function body from the original module. The extracted body is then +/// compiled and executed. +template <typename BaseLayerT, typename CompileCallbackMgrT> +class CompileOnDemandLayer { +private: + + // Utility class for MapValue. Only materializes declarations for global + // variables. + class GlobalDeclMaterializer : public ValueMaterializer { + public: + GlobalDeclMaterializer(Module &Dst) : Dst(Dst) {} + Value* materializeValueFor(Value *V) final { + if (auto *GV = dyn_cast<GlobalVariable>(V)) + return cloneGlobalVariableDecl(Dst, *GV); + else if (auto *F = dyn_cast<Function>(V)) + return cloneFunctionDecl(Dst, *F); + // Else. + return nullptr; + } + private: + Module &Dst; + }; + + typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT; + class UncompiledPartition; + + // Logical module. + // + // This struct contains the handles for the global values and stubs (which + // cover the external symbols of the original module), plus the handes for + // each of the extracted partitions. These handleds are used for lookup (only + // the globals/stubs module is searched) and memory management. The actual + // searching and resource management are handled by the LogicalDylib that owns + // the LogicalModule. + struct LogicalModule { + LogicalModule() {} + + LogicalModule(LogicalModule &&Other) + : SrcM(std::move(Other.SrcM)), + GVsAndStubsHandle(std::move(Other.GVsAndStubsHandle)), + ImplHandles(std::move(Other.ImplHandles)) {} + + std::unique_ptr<Module> SrcM; + BaseLayerModuleSetHandleT GVsAndStubsHandle; + std::vector<BaseLayerModuleSetHandleT> ImplHandles; + }; + + // Logical dylib. + // + // This class handles symbol resolution and resource management for a set of + // modules that were added together as a logical dylib. + // + // A logical dylib contains one-or-more LogicalModules plus a set of + // UncompiledPartitions. LogicalModules support symbol resolution and resource + // management for for code that has already been emitted. UncompiledPartitions + // represent code that has not yet been compiled. + class LogicalDylib { + private: + friend class UncompiledPartition; + typedef std::list<LogicalModule> LogicalModuleList; + public: + + typedef unsigned UncompiledPartitionID; + typedef typename LogicalModuleList::iterator LMHandle; + + // Construct a logical dylib. + LogicalDylib(CompileOnDemandLayer &CODLayer) : CODLayer(CODLayer) { } + + // Delete this logical dylib, release logical module resources. + virtual ~LogicalDylib() { + releaseLogicalModuleResources(); + } + + // Get a reference to the containing layer. + CompileOnDemandLayer& getCODLayer() { return CODLayer; } + + // Get a reference to the base layer. + BaseLayerT& getBaseLayer() { return CODLayer.BaseLayer; } + + // Start a new context for a single logical module. + LMHandle createLogicalModule() { + LogicalModules.push_back(LogicalModule()); + return std::prev(LogicalModules.end()); + } + + // Set the global-values-and-stubs module handle for this logical module. + void setGVsAndStubsHandle(LMHandle LMH, BaseLayerModuleSetHandleT H) { + LMH->GVsAndStubsHandle = H; + } + + // Return the global-values-and-stubs module handle for this logical module. + BaseLayerModuleSetHandleT getGVsAndStubsHandle(LMHandle LMH) { + return LMH->GVsAndStubsHandle; + } + + // Add a handle to a module containing lazy function bodies to the given + // logical module. + void addToLogicalModule(LMHandle LMH, BaseLayerModuleSetHandleT H) { + LMH->ImplHandles.push_back(H); + } + + // Create an UncompiledPartition attached to this LogicalDylib. + UncompiledPartition& createUncompiledPartition(LMHandle LMH, + std::shared_ptr<Module> SrcM); + + // Take ownership of the given UncompiledPartition from the logical dylib. + std::unique_ptr<UncompiledPartition> + takeUPOwnership(UncompiledPartitionID ID); + + // Look up a symbol in this context. + JITSymbol findSymbolInternally(LMHandle LMH, const std::string &Name) { + if (auto Symbol = getBaseLayer().findSymbolIn(LMH->GVsAndStubsHandle, + Name, false)) + return Symbol; + + for (auto I = LogicalModules.begin(), E = LogicalModules.end(); I != E; + ++I) + if (I != LMH) + if (auto Symbol = getBaseLayer().findSymbolIn(I->GVsAndStubsHandle, + Name, false)) + return Symbol; + + return nullptr; + } + + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + for (auto &LM : LogicalModules) + if (auto Symbol = getBaseLayer().findSymbolIn(LM.GVsAndStubsHandle, + Name, + ExportedSymbolsOnly)) + return Symbol; + return nullptr; + } + + // Find an external symbol (via the user supplied SymbolResolver). + virtual RuntimeDyld::SymbolInfo + findSymbolExternally(const std::string &Name) const = 0; + + private: + + void releaseLogicalModuleResources() { + for (auto I = LogicalModules.begin(), E = LogicalModules.end(); I != E; + ++I) { + getBaseLayer().removeModuleSet(I->GVsAndStubsHandle); + for (auto H : I->ImplHandles) + getBaseLayer().removeModuleSet(H); + } + } + + CompileOnDemandLayer &CODLayer; + LogicalModuleList LogicalModules; + std::vector<std::unique_ptr<UncompiledPartition>> UncompiledPartitions; + }; + + template <typename ResolverPtrT> + class LogicalDylibImpl : public LogicalDylib { + public: + LogicalDylibImpl(CompileOnDemandLayer &CODLayer, ResolverPtrT Resolver) + : LogicalDylib(CODLayer), Resolver(std::move(Resolver)) {} + + RuntimeDyld::SymbolInfo + findSymbolExternally(const std::string &Name) const override { + return Resolver->findSymbol(Name); + } + + private: + ResolverPtrT Resolver; + }; + + template <typename ResolverPtrT> + static std::unique_ptr<LogicalDylib> + createLogicalDylib(CompileOnDemandLayer &CODLayer, + ResolverPtrT Resolver) { + typedef LogicalDylibImpl<ResolverPtrT> Impl; + return llvm::make_unique<Impl>(CODLayer, std::move(Resolver)); + } + + // Uncompiled partition. + // + // Represents one as-yet uncompiled portion of a module. + class UncompiledPartition { + public: + + struct PartitionEntry { + PartitionEntry(Function *F, TargetAddress CallbackID) + : F(F), CallbackID(CallbackID) {} + Function *F; + TargetAddress CallbackID; + }; + + typedef std::vector<PartitionEntry> PartitionEntryList; + + // Creates an uncompiled partition with the list of functions that make up + // this partition. + UncompiledPartition(LogicalDylib &LD, typename LogicalDylib::LMHandle LMH, + std::shared_ptr<Module> SrcM) + : LD(LD), LMH(LMH), SrcM(std::move(SrcM)), ID(~0U) {} + + ~UncompiledPartition() { + // FIXME: When we want to support threaded lazy compilation we'll need to + // lock the callback manager here. + auto &CCMgr = LD.getCODLayer().CompileCallbackMgr; + for (auto PEntry : PartitionEntries) + CCMgr.releaseCompileCallback(PEntry.CallbackID); + } + + // Set the ID for this partition. + void setID(typename LogicalDylib::UncompiledPartitionID ID) { + this->ID = ID; + } + + // Set the function set and callbacks for this partition. + void setPartitionEntries(PartitionEntryList PartitionEntries) { + this->PartitionEntries = std::move(PartitionEntries); + } + + // Handle a compile callback for the function at index FnIdx. + TargetAddress compile(unsigned FnIdx) { + // Take ownership of self. This will ensure we delete the partition and + // free all its resources once we're done compiling. + std::unique_ptr<UncompiledPartition> This = LD.takeUPOwnership(ID); + + // Release all other compile callbacks for this partition. + // We skip the callback for this function because that's the one that + // called us, and the callback manager will already have removed it. + auto &CCMgr = LD.getCODLayer().CompileCallbackMgr; + for (unsigned I = 0; I < PartitionEntries.size(); ++I) + if (I != FnIdx) + CCMgr.releaseCompileCallback(PartitionEntries[I].CallbackID); + + // Grab the name of the function being called here. + Function *F = PartitionEntries[FnIdx].F; + std::string CalledFnName = Mangle(F->getName(), SrcM->getDataLayout()); + + // Extract the function and add it to the base layer. + auto PartitionImplH = emitPartition(); + LD.addToLogicalModule(LMH, PartitionImplH); + + // Update body pointers. + // FIXME: When we start supporting remote lazy jitting this will need to + // be replaced with a user-supplied callback for updating the + // remote pointers. + TargetAddress CalledAddr = 0; + for (unsigned I = 0; I < PartitionEntries.size(); ++I) { + auto F = PartitionEntries[I].F; + std::string FName(F->getName()); + auto FnBodySym = + LD.getBaseLayer().findSymbolIn(PartitionImplH, + Mangle(FName, SrcM->getDataLayout()), + false); + auto FnPtrSym = + LD.getBaseLayer().findSymbolIn(LD.getGVsAndStubsHandle(LMH), + Mangle(FName + "$orc_addr", + SrcM->getDataLayout()), + false); + assert(FnBodySym && "Couldn't find function body."); + assert(FnPtrSym && "Couldn't find function body pointer."); + + auto FnBodyAddr = FnBodySym.getAddress(); + void *FnPtrAddr = reinterpret_cast<void*>( + static_cast<uintptr_t>(FnPtrSym.getAddress())); + + // If this is the function we're calling record the address so we can + // return it from this function. + if (I == FnIdx) + CalledAddr = FnBodyAddr; + + memcpy(FnPtrAddr, &FnBodyAddr, sizeof(uintptr_t)); + } + + // Finally, clear the partition structure so we don't try to + // double-release the callbacks in the UncompiledPartition destructor. + PartitionEntries.clear(); + + return CalledAddr; + } + + private: + + BaseLayerModuleSetHandleT emitPartition() { + // Create the module. + std::string NewName(SrcM->getName()); + for (auto &PEntry : PartitionEntries) { + NewName += "."; + NewName += PEntry.F->getName(); + } + auto PM = llvm::make_unique<Module>(NewName, SrcM->getContext()); + PM->setDataLayout(SrcM->getDataLayout()); + ValueToValueMapTy VMap; + GlobalDeclMaterializer GDM(*PM); + + // Create decls in the new module. + for (auto &PEntry : PartitionEntries) + cloneFunctionDecl(*PM, *PEntry.F, &VMap); + + // Move the function bodies. + for (auto &PEntry : PartitionEntries) + moveFunctionBody(*PEntry.F, VMap); + + // Create memory manager and symbol resolver. + auto MemMgr = llvm::make_unique<SectionMemoryManager>(); + auto Resolver = createLambdaResolver( + [this](const std::string &Name) { + if (auto Symbol = LD.findSymbolInternally(LMH, Name)) + return RuntimeDyld::SymbolInfo(Symbol.getAddress(), + Symbol.getFlags()); + return LD.findSymbolExternally(Name); + }, + [this](const std::string &Name) { + if (auto Symbol = LD.findSymbolInternally(LMH, Name)) + return RuntimeDyld::SymbolInfo(Symbol.getAddress(), + Symbol.getFlags()); + return RuntimeDyld::SymbolInfo(nullptr); + }); + std::vector<std::unique_ptr<Module>> PartMSet; + PartMSet.push_back(std::move(PM)); + return LD.getBaseLayer().addModuleSet(std::move(PartMSet), + std::move(MemMgr), + std::move(Resolver)); + } + + LogicalDylib &LD; + typename LogicalDylib::LMHandle LMH; + std::shared_ptr<Module> SrcM; + typename LogicalDylib::UncompiledPartitionID ID; + PartitionEntryList PartitionEntries; + }; + + typedef std::list<std::unique_ptr<LogicalDylib>> LogicalDylibList; + +public: + /// @brief Handle to a set of loaded modules. + typedef typename LogicalDylibList::iterator ModuleSetHandleT; + + /// @brief Construct a compile-on-demand layer instance. + CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr) + : BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr) {} + + /// @brief Add a module to the compile-on-demand layer. + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> + ModuleSetHandleT addModuleSet(ModuleSetT Ms, + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + + assert(MemMgr == nullptr && + "User supplied memory managers not supported with COD yet."); + + LogicalDylibs.push_back(createLogicalDylib(*this, std::move(Resolver))); + + // Process each of the modules in this module set. + for (auto &M : Ms) { + std::vector<std::vector<Function*>> Partitioning; + for (auto &F : *M) { + if (F.isDeclaration()) + continue; + Partitioning.push_back(std::vector<Function*>()); + Partitioning.back().push_back(&F); + } + addLogicalModule(*LogicalDylibs.back(), + std::shared_ptr<Module>(std::move(M)), + std::move(Partitioning)); + } + + return std::prev(LogicalDylibs.end()); + } + + /// @brief Remove the module represented by the given handle. + /// + /// This will remove all modules in the layers below that were derived from + /// the module represented by H. + void removeModuleSet(ModuleSetHandleT H) { + LogicalDylibs.erase(H); + } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { + return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); + } + + /// @brief Get the address of a symbol provided by this layer, or some layer + /// below this one. + JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + return (*H)->findSymbol(Name, ExportedSymbolsOnly); + } + +private: + + void addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcM, + std::vector<std::vector<Function*>> Partitions) { + + // Bump the linkage and rename any anonymous/privote members in SrcM to + // ensure that everything will resolve properly after we partition SrcM. + makeAllSymbolsExternallyAccessible(*SrcM); + + // Create a logical module handle for SrcM within the logical dylib. + auto LMH = LD.createLogicalModule(); + + // Create the GVs-and-stubs module. + auto GVsAndStubsM = llvm::make_unique<Module>( + (SrcM->getName() + ".globals_and_stubs").str(), + SrcM->getContext()); + GVsAndStubsM->setDataLayout(SrcM->getDataLayout()); + ValueToValueMapTy VMap; + + // Process partitions and create stubs. + // We create the stubs before copying the global variables as we know the + // stubs won't refer to any globals (they only refer to their implementation + // pointer) so there's no ordering/value-mapping issues. + for (auto& Partition : Partitions) { + auto &UP = LD.createUncompiledPartition(LMH, SrcM); + typename UncompiledPartition::PartitionEntryList PartitionEntries; + for (auto &F : Partition) { + assert(!F->isDeclaration() && + "Partition should only contain definitions"); + unsigned FnIdx = PartitionEntries.size(); + auto CCI = CompileCallbackMgr.getCompileCallback(SrcM->getContext()); + PartitionEntries.push_back( + typename UncompiledPartition::PartitionEntry(F, CCI.getAddress())); + Function *StubF = cloneFunctionDecl(*GVsAndStubsM, *F, &VMap); + GlobalVariable *FnBodyPtr = + createImplPointer(*StubF->getType(), *StubF->getParent(), + StubF->getName() + "$orc_addr", + createIRTypedAddress(*StubF->getFunctionType(), + CCI.getAddress())); + makeStub(*StubF, *FnBodyPtr); + CCI.setCompileAction([&UP, FnIdx]() { return UP.compile(FnIdx); }); + } + + UP.setPartitionEntries(std::move(PartitionEntries)); + } + + // Now clone the global variable declarations. + GlobalDeclMaterializer GDMat(*GVsAndStubsM); + for (auto &GV : SrcM->globals()) + if (!GV.isDeclaration()) + cloneGlobalVariableDecl(*GVsAndStubsM, GV, &VMap); + + // Then clone the initializers. + for (auto &GV : SrcM->globals()) + if (!GV.isDeclaration()) + moveGlobalVariableInitializer(GV, VMap, &GDMat); + + // Build a resolver for the stubs module and add it to the base layer. + auto GVsAndStubsResolver = createLambdaResolver( + [&LD](const std::string &Name) { + if (auto Symbol = LD.findSymbol(Name, false)) + return RuntimeDyld::SymbolInfo(Symbol.getAddress(), + Symbol.getFlags()); + return LD.findSymbolExternally(Name); + }, + [&LD](const std::string &Name) { + return RuntimeDyld::SymbolInfo(nullptr); + }); + + std::vector<std::unique_ptr<Module>> GVsAndStubsMSet; + GVsAndStubsMSet.push_back(std::move(GVsAndStubsM)); + auto GVsAndStubsH = + BaseLayer.addModuleSet(std::move(GVsAndStubsMSet), + llvm::make_unique<SectionMemoryManager>(), + std::move(GVsAndStubsResolver)); + LD.setGVsAndStubsHandle(LMH, GVsAndStubsH); + } + + static std::string Mangle(StringRef Name, const DataLayout &DL) { + Mangler M(&DL); + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + M.getNameWithPrefix(MangledNameStream, Name); + } + return MangledName; + } + + BaseLayerT &BaseLayer; + CompileCallbackMgrT &CompileCallbackMgr; + LogicalDylibList LogicalDylibs; +}; + +template <typename BaseLayerT, typename CompileCallbackMgrT> +typename CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>:: + UncompiledPartition& +CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::LogicalDylib:: + createUncompiledPartition(LMHandle LMH, std::shared_ptr<Module> SrcM) { + UncompiledPartitions.push_back( + llvm::make_unique<UncompiledPartition>(*this, LMH, std::move(SrcM))); + UncompiledPartitions.back()->setID(UncompiledPartitions.size() - 1); + return *UncompiledPartitions.back(); +} + +template <typename BaseLayerT, typename CompileCallbackMgrT> +std::unique_ptr<typename CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>:: + UncompiledPartition> +CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::LogicalDylib:: + takeUPOwnership(UncompiledPartitionID ID) { + + std::swap(UncompiledPartitions[ID], UncompiledPartitions.back()); + UncompiledPartitions[ID]->setID(ID); + auto UP = std::move(UncompiledPartitions.back()); + UncompiledPartitions.pop_back(); + return UP; +} + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/include/llvm/ExecutionEngine/Orc/CompileUtils.h new file mode 100644 index 000000000000..49a1fbadb295 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/CompileUtils.h @@ -0,0 +1,62 @@ +//===-- CompileUtils.h - Utilities for compiling IR in the JIT --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains utilities for compiling IR to object files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H +#define LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H + +#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { +namespace orc { + +/// @brief Simple compile functor: Takes a single IR module and returns an +/// ObjectFile. +class SimpleCompiler { +public: + /// @brief Construct a simple compile functor with the given target. + SimpleCompiler(TargetMachine &TM) : TM(TM) {} + + /// @brief Compile a Module to an ObjectFile. + object::OwningBinary<object::ObjectFile> operator()(Module &M) const { + SmallVector<char, 0> ObjBufferSV; + raw_svector_ostream ObjStream(ObjBufferSV); + + legacy::PassManager PM; + MCContext *Ctx; + if (TM.addPassesToEmitMC(PM, Ctx, ObjStream)) + llvm_unreachable("Target does not support MC emission."); + PM.run(M); + ObjStream.flush(); + std::unique_ptr<MemoryBuffer> ObjBuffer( + new ObjectMemoryBuffer(std::move(ObjBufferSV))); + ErrorOr<std::unique_ptr<object::ObjectFile>> Obj = + object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); + // TODO: Actually report errors helpfully. + typedef object::OwningBinary<object::ObjectFile> OwningObj; + if (Obj) + return OwningObj(std::move(*Obj), std::move(ObjBuffer)); + return OwningObj(nullptr, nullptr); + } + +private: + TargetMachine &TM; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H diff --git a/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h new file mode 100644 index 000000000000..c10508cc8a62 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -0,0 +1,182 @@ +//===-- ExecutionUtils.h - Utilities for executing code in Orc --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains utilities for executing code in Orc. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H +#define LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H + +#include "JITSymbol.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include <vector> + +namespace llvm { + +class ConstantArray; +class GlobalVariable; +class Function; +class Module; +class Value; + +namespace orc { + +/// @brief This iterator provides a convenient way to iterate over the elements +/// of an llvm.global_ctors/llvm.global_dtors instance. +/// +/// The easiest way to get hold of instances of this class is to use the +/// getConstructors/getDestructors functions. +class CtorDtorIterator { +public: + + /// @brief Accessor for an element of the global_ctors/global_dtors array. + /// + /// This class provides a read-only view of the element with any casts on + /// the function stripped away. + struct Element { + Element(unsigned Priority, const Function *Func, const Value *Data) + : Priority(Priority), Func(Func), Data(Data) {} + + unsigned Priority; + const Function *Func; + const Value *Data; + }; + + /// @brief Construct an iterator instance. If End is true then this iterator + /// acts as the end of the range, otherwise it is the beginning. + CtorDtorIterator(const GlobalVariable *GV, bool End); + + /// @brief Test iterators for equality. + bool operator==(const CtorDtorIterator &Other) const; + + /// @brief Test iterators for inequality. + bool operator!=(const CtorDtorIterator &Other) const; + + /// @brief Pre-increment iterator. + CtorDtorIterator& operator++(); + + /// @brief Post-increment iterator. + CtorDtorIterator operator++(int); + + /// @brief Dereference iterator. The resulting value provides a read-only view + /// of this element of the global_ctors/global_dtors list. + Element operator*() const; + +private: + const ConstantArray *InitList; + unsigned I; +}; + +/// @brief Create an iterator range over the entries of the llvm.global_ctors +/// array. +iterator_range<CtorDtorIterator> getConstructors(const Module &M); + +/// @brief Create an iterator range over the entries of the llvm.global_ctors +/// array. +iterator_range<CtorDtorIterator> getDestructors(const Module &M); + +/// @brief Convenience class for recording constructor/destructor names for +/// later execution. +template <typename JITLayerT> +class CtorDtorRunner { +public: + + /// @brief Construct a CtorDtorRunner for the given range using the given + /// name mangling function. + CtorDtorRunner(std::vector<std::string> CtorDtorNames, + typename JITLayerT::ModuleSetHandleT H) + : CtorDtorNames(std::move(CtorDtorNames)), H(H) {} + + /// @brief Run the recorded constructors/destructors through the given JIT + /// layer. + bool runViaLayer(JITLayerT &JITLayer) const { + typedef void (*CtorDtorTy)(); + + bool Error = false; + for (const auto &CtorDtorName : CtorDtorNames) + if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) { + CtorDtorTy CtorDtor = + reinterpret_cast<CtorDtorTy>( + static_cast<uintptr_t>(CtorDtorSym.getAddress())); + CtorDtor(); + } else + Error = true; + return !Error; + } + +private: + std::vector<std::string> CtorDtorNames; + typename JITLayerT::ModuleSetHandleT H; +}; + +/// @brief Support class for static dtor execution. For hosted (in-process) JITs +/// only! +/// +/// If a __cxa_atexit function isn't found C++ programs that use static +/// destructors will fail to link. However, we don't want to use the host +/// process's __cxa_atexit, because it will schedule JIT'd destructors to run +/// after the JIT has been torn down, which is no good. This class makes it easy +/// to override __cxa_atexit (and the related __dso_handle). +/// +/// To use, clients should manually call searchOverrides from their symbol +/// resolver. This should generally be done after attempting symbol resolution +/// inside the JIT, but before searching the host process's symbol table. When +/// the client determines that destructors should be run (generally at JIT +/// teardown or after a return from main), the runDestructors method should be +/// called. +class LocalCXXRuntimeOverrides { +public: + + /// Create a runtime-overrides class. + template <typename MangleFtorT> + LocalCXXRuntimeOverrides(const MangleFtorT &Mangle) { + addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride)); + addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride)); + } + + /// Search overrided symbols. + RuntimeDyld::SymbolInfo searchOverrides(const std::string &Name) { + auto I = CXXRuntimeOverrides.find(Name); + if (I != CXXRuntimeOverrides.end()) + return RuntimeDyld::SymbolInfo(I->second, JITSymbolFlags::Exported); + return nullptr; + } + + /// Run any destructors recorded by the overriden __cxa_atexit function + /// (CXAAtExitOverride). + void runDestructors(); + +private: + + template <typename PtrTy> + TargetAddress toTargetAddress(PtrTy* P) { + return static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(P)); + } + + void addOverride(const std::string &Name, TargetAddress Addr) { + CXXRuntimeOverrides.insert(std::make_pair(Name, Addr)); + } + + StringMap<TargetAddress> CXXRuntimeOverrides; + + typedef void (*DestructorPtr)(void*); + typedef std::pair<DestructorPtr, void*> CXXDestructorDataPair; + typedef std::vector<CXXDestructorDataPair> CXXDestructorDataPairList; + CXXDestructorDataPairList DSOHandleOverride; + static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg, + void *DSOHandle); +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H diff --git a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h new file mode 100644 index 000000000000..637902200786 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h @@ -0,0 +1,148 @@ +//===------ IRCompileLayer.h -- Eagerly compile IR for JIT ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains the definition for a basic, eagerly compiling layer of the JIT. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H +#define LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H + +#include "JITSymbol.h" +#include "llvm/ExecutionEngine/ObjectCache.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/Object/ObjectFile.h" +#include <memory> + +namespace llvm { +namespace orc { + +/// @brief Eager IR compiling layer. +/// +/// This layer accepts sets of LLVM IR Modules (via addModuleSet). It +/// immediately compiles each IR module to an object file (each IR Module is +/// compiled separately). The resulting set of object files is then added to +/// the layer below, which must implement the object layer concept. +template <typename BaseLayerT> class IRCompileLayer { +public: + typedef std::function<object::OwningBinary<object::ObjectFile>(Module &)> + CompileFtor; + +private: + typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT; + + typedef std::vector<std::unique_ptr<object::ObjectFile>> OwningObjectVec; + typedef std::vector<std::unique_ptr<MemoryBuffer>> OwningBufferVec; + +public: + /// @brief Handle to a set of compiled modules. + typedef ObjSetHandleT ModuleSetHandleT; + + /// @brief Construct an IRCompileLayer with the given BaseLayer, which must + /// implement the ObjectLayer concept. + IRCompileLayer(BaseLayerT &BaseLayer, CompileFtor Compile) + : BaseLayer(BaseLayer), Compile(std::move(Compile)), ObjCache(nullptr) {} + + /// @brief Set an ObjectCache to query before compiling. + void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; } + + /// @brief Compile each module in the given module set, then add the resulting + /// set of objects to the base layer along with the memory manager and + /// symbol resolver. + /// + /// @return A handle for the added modules. + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> + ModuleSetHandleT addModuleSet(ModuleSetT Ms, + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + OwningObjectVec Objects; + OwningBufferVec Buffers; + + for (const auto &M : Ms) { + std::unique_ptr<object::ObjectFile> Object; + std::unique_ptr<MemoryBuffer> Buffer; + + if (ObjCache) + std::tie(Object, Buffer) = tryToLoadFromObjectCache(*M).takeBinary(); + + if (!Object) { + std::tie(Object, Buffer) = Compile(*M).takeBinary(); + if (ObjCache) + ObjCache->notifyObjectCompiled(&*M, Buffer->getMemBufferRef()); + } + + Objects.push_back(std::move(Object)); + Buffers.push_back(std::move(Buffer)); + } + + ModuleSetHandleT H = + BaseLayer.addObjectSet(Objects, std::move(MemMgr), std::move(Resolver)); + + BaseLayer.takeOwnershipOfBuffers(H, std::move(Buffers)); + + return H; + } + + /// @brief Remove the module set associated with the handle H. + void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeObjectSet(H); } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); + } + + /// @brief Get the address of the given symbol in the context of the set of + /// compiled modules represented by the handle H. This call is + /// forwarded to the base layer's implementation. + /// @param H The handle for the module set to search in. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it is found in the + /// given module set. + JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); + } + + /// @brief Immediately emit and finalize the moduleOB set represented by the + /// given handle. + /// @param H Handle for module set to emit/finalize. + void emitAndFinalize(ModuleSetHandleT H) { + BaseLayer.emitAndFinalize(H); + } + +private: + object::OwningBinary<object::ObjectFile> + tryToLoadFromObjectCache(const Module &M) { + std::unique_ptr<MemoryBuffer> ObjBuffer = ObjCache->getObject(&M); + if (!ObjBuffer) + return object::OwningBinary<object::ObjectFile>(); + + ErrorOr<std::unique_ptr<object::ObjectFile>> Obj = + object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); + if (!Obj) + return object::OwningBinary<object::ObjectFile>(); + + return object::OwningBinary<object::ObjectFile>(std::move(*Obj), + std::move(ObjBuffer)); + } + + BaseLayerT &BaseLayer; + CompileFtor Compile; + ObjectCache *ObjCache; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_IRCOMPILINGLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h new file mode 100644 index 000000000000..4dabb9a41494 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h @@ -0,0 +1,101 @@ +//===----- IRTransformLayer.h - Run all IR through a functor ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Run all IR passed in through a user supplied functor. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H + +#include "JITSymbol.h" + +namespace llvm { +namespace orc { + +/// @brief IR mutating layer. +/// +/// This layer accepts sets of LLVM IR Modules (via addModuleSet). It +/// immediately applies the user supplied functor to each module, then adds +/// the set of transformed modules to the layer below. +template <typename BaseLayerT, typename TransformFtor> +class IRTransformLayer { +public: + /// @brief Handle to a set of added modules. + typedef typename BaseLayerT::ModuleSetHandleT ModuleSetHandleT; + + /// @brief Construct an IRTransformLayer with the given BaseLayer + IRTransformLayer(BaseLayerT &BaseLayer, + TransformFtor Transform = TransformFtor()) + : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} + + /// @brief Apply the transform functor to each module in the module set, then + /// add the resulting set of modules to the base layer, along with the + /// memory manager and symbol resolver. + /// + /// @return A handle for the added modules. + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> + ModuleSetHandleT addModuleSet(ModuleSetT Ms, + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + + for (auto I = Ms.begin(), E = Ms.end(); I != E; ++I) + *I = Transform(std::move(*I)); + + return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr), + std::move(Resolver)); + } + + /// @brief Remove the module set associated with the handle H. + void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeModuleSet(H); } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); + } + + /// @brief Get the address of the given symbol in the context of the set of + /// modules represented by the handle H. This call is forwarded to the + /// base layer's implementation. + /// @param H The handle for the module set to search in. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it is found in the + /// given module set. + JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); + } + + /// @brief Immediately emit and finalize the module set represented by the + /// given handle. + /// @param H Handle for module set to emit/finalize. + void emitAndFinalize(ModuleSetHandleT H) { + BaseLayer.emitAndFinalize(H); + } + + /// @brief Access the transform functor directly. + TransformFtor& getTransform() { return Transform; } + + /// @brief Access the mumate functor directly. + const TransformFtor& getTransform() const { return Transform; } + +private: + BaseLayerT &BaseLayer; + TransformFtor Transform; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h new file mode 100644 index 000000000000..4b7fc5e84b9c --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -0,0 +1,295 @@ +//===-- IndirectionUtils.h - Utilities for adding indirections --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains utilities for adding indirections and breaking up modules. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H +#define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H + +#include "JITSymbol.h" +#include "LambdaResolver.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" +#include "llvm/Transforms/Utils/ValueMapper.h" +#include <sstream> + +namespace llvm { +namespace orc { + +/// @brief Base class for JITLayer independent aspects of +/// JITCompileCallbackManager. +class JITCompileCallbackManagerBase { +public: + + typedef std::function<TargetAddress()> CompileFtor; + + /// @brief Handle to a newly created compile callback. Can be used to get an + /// IR constant representing the address of the trampoline, and to set + /// the compile action for the callback. + class CompileCallbackInfo { + public: + CompileCallbackInfo(TargetAddress Addr, CompileFtor &Compile) + : Addr(Addr), Compile(Compile) {} + + TargetAddress getAddress() const { return Addr; } + void setCompileAction(CompileFtor Compile) { + this->Compile = std::move(Compile); + } + private: + TargetAddress Addr; + CompileFtor &Compile; + }; + + /// @brief Construct a JITCompileCallbackManagerBase. + /// @param ErrorHandlerAddress The address of an error handler in the target + /// process to be used if a compile callback fails. + /// @param NumTrampolinesPerBlock Number of trampolines to emit if there is no + /// available trampoline when getCompileCallback is + /// called. + JITCompileCallbackManagerBase(TargetAddress ErrorHandlerAddress, + unsigned NumTrampolinesPerBlock) + : ErrorHandlerAddress(ErrorHandlerAddress), + NumTrampolinesPerBlock(NumTrampolinesPerBlock) {} + + virtual ~JITCompileCallbackManagerBase() {} + + /// @brief Execute the callback for the given trampoline id. Called by the JIT + /// to compile functions on demand. + TargetAddress executeCompileCallback(TargetAddress TrampolineAddr) { + auto I = ActiveTrampolines.find(TrampolineAddr); + // FIXME: Also raise an error in the Orc error-handler when we finally have + // one. + if (I == ActiveTrampolines.end()) + return ErrorHandlerAddress; + + // Found a callback handler. Yank this trampoline out of the active list and + // put it back in the available trampolines list, then try to run the + // handler's compile and update actions. + // Moving the trampoline ID back to the available list first means there's at + // least one available trampoline if the compile action triggers a request for + // a new one. + auto Compile = std::move(I->second); + ActiveTrampolines.erase(I); + AvailableTrampolines.push_back(TrampolineAddr); + + if (auto Addr = Compile()) + return Addr; + + return ErrorHandlerAddress; + } + + /// @brief Reserve a compile callback. + virtual CompileCallbackInfo getCompileCallback(LLVMContext &Context) = 0; + + /// @brief Get a CompileCallbackInfo for an existing callback. + CompileCallbackInfo getCompileCallbackInfo(TargetAddress TrampolineAddr) { + auto I = ActiveTrampolines.find(TrampolineAddr); + assert(I != ActiveTrampolines.end() && "Not an active trampoline."); + return CompileCallbackInfo(I->first, I->second); + } + + /// @brief Release a compile callback. + /// + /// Note: Callbacks are auto-released after they execute. This method should + /// only be called to manually release a callback that is not going to + /// execute. + void releaseCompileCallback(TargetAddress TrampolineAddr) { + auto I = ActiveTrampolines.find(TrampolineAddr); + assert(I != ActiveTrampolines.end() && "Not an active trampoline."); + ActiveTrampolines.erase(I); + AvailableTrampolines.push_back(TrampolineAddr); + } + +protected: + TargetAddress ErrorHandlerAddress; + unsigned NumTrampolinesPerBlock; + + typedef std::map<TargetAddress, CompileFtor> TrampolineMapT; + TrampolineMapT ActiveTrampolines; + std::vector<TargetAddress> AvailableTrampolines; +}; + +/// @brief Manage compile callbacks. +template <typename JITLayerT, typename TargetT> +class JITCompileCallbackManager : public JITCompileCallbackManagerBase { +public: + + /// @brief Construct a JITCompileCallbackManager. + /// @param JIT JIT layer to emit callback trampolines, etc. into. + /// @param Context LLVMContext to use for trampoline & resolve block modules. + /// @param ErrorHandlerAddress The address of an error handler in the target + /// process to be used if a compile callback fails. + /// @param NumTrampolinesPerBlock Number of trampolines to allocate whenever + /// there is no existing callback trampoline. + /// (Trampolines are allocated in blocks for + /// efficiency.) + JITCompileCallbackManager(JITLayerT &JIT, RuntimeDyld::MemoryManager &MemMgr, + LLVMContext &Context, + TargetAddress ErrorHandlerAddress, + unsigned NumTrampolinesPerBlock) + : JITCompileCallbackManagerBase(ErrorHandlerAddress, + NumTrampolinesPerBlock), + JIT(JIT), MemMgr(MemMgr) { + emitResolverBlock(Context); + } + + /// @brief Get/create a compile callback with the given signature. + CompileCallbackInfo getCompileCallback(LLVMContext &Context) final { + TargetAddress TrampolineAddr = getAvailableTrampolineAddr(Context); + auto &Compile = this->ActiveTrampolines[TrampolineAddr]; + return CompileCallbackInfo(TrampolineAddr, Compile); + } + +private: + + std::vector<std::unique_ptr<Module>> + SingletonSet(std::unique_ptr<Module> M) { + std::vector<std::unique_ptr<Module>> Ms; + Ms.push_back(std::move(M)); + return Ms; + } + + void emitResolverBlock(LLVMContext &Context) { + std::unique_ptr<Module> M(new Module("resolver_block_module", + Context)); + TargetT::insertResolverBlock(*M, *this); + auto NonResolver = + createLambdaResolver( + [](const std::string &Name) -> RuntimeDyld::SymbolInfo { + llvm_unreachable("External symbols in resolver block?"); + }, + [](const std::string &Name) -> RuntimeDyld::SymbolInfo { + llvm_unreachable("Dylib symbols in resolver block?"); + }); + auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr, + std::move(NonResolver)); + JIT.emitAndFinalize(H); + auto ResolverBlockSymbol = + JIT.findSymbolIn(H, TargetT::ResolverBlockName, false); + assert(ResolverBlockSymbol && "Failed to insert resolver block"); + ResolverBlockAddr = ResolverBlockSymbol.getAddress(); + } + + TargetAddress getAvailableTrampolineAddr(LLVMContext &Context) { + if (this->AvailableTrampolines.empty()) + grow(Context); + assert(!this->AvailableTrampolines.empty() && + "Failed to grow available trampolines."); + TargetAddress TrampolineAddr = this->AvailableTrampolines.back(); + this->AvailableTrampolines.pop_back(); + return TrampolineAddr; + } + + void grow(LLVMContext &Context) { + assert(this->AvailableTrampolines.empty() && "Growing prematurely?"); + std::unique_ptr<Module> M(new Module("trampoline_block", Context)); + auto GetLabelName = + TargetT::insertCompileCallbackTrampolines(*M, ResolverBlockAddr, + this->NumTrampolinesPerBlock, + this->ActiveTrampolines.size()); + auto NonResolver = + createLambdaResolver( + [](const std::string &Name) -> RuntimeDyld::SymbolInfo { + llvm_unreachable("External symbols in trampoline block?"); + }, + [](const std::string &Name) -> RuntimeDyld::SymbolInfo { + llvm_unreachable("Dylib symbols in trampoline block?"); + }); + auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr, + std::move(NonResolver)); + JIT.emitAndFinalize(H); + for (unsigned I = 0; I < this->NumTrampolinesPerBlock; ++I) { + std::string Name = GetLabelName(I); + auto TrampolineSymbol = JIT.findSymbolIn(H, Name, false); + assert(TrampolineSymbol && "Failed to emit trampoline."); + this->AvailableTrampolines.push_back(TrampolineSymbol.getAddress()); + } + } + + JITLayerT &JIT; + RuntimeDyld::MemoryManager &MemMgr; + TargetAddress ResolverBlockAddr; +}; + +/// @brief Build a function pointer of FunctionType with the given constant +/// address. +/// +/// Usage example: Turn a trampoline address into a function pointer constant +/// for use in a stub. +Constant* createIRTypedAddress(FunctionType &FT, TargetAddress Addr); + +/// @brief Create a function pointer with the given type, name, and initializer +/// in the given Module. +GlobalVariable* createImplPointer(PointerType &PT, Module &M, + const Twine &Name, Constant *Initializer); + +/// @brief Turn a function declaration into a stub function that makes an +/// indirect call using the given function pointer. +void makeStub(Function &F, GlobalVariable &ImplPointer); + +/// @brief Raise linkage types and rename as necessary to ensure that all +/// symbols are accessible for other modules. +/// +/// This should be called before partitioning a module to ensure that the +/// partitions retain access to each other's symbols. +void makeAllSymbolsExternallyAccessible(Module &M); + +/// @brief Clone a function declaration into a new module. +/// +/// This function can be used as the first step towards creating a callback +/// stub (see makeStub), or moving a function body (see moveFunctionBody). +/// +/// If the VMap argument is non-null, a mapping will be added between F and +/// the new declaration, and between each of F's arguments and the new +/// declaration's arguments. This map can then be passed in to moveFunction to +/// move the function body if required. Note: When moving functions between +/// modules with these utilities, all decls should be cloned (and added to a +/// single VMap) before any bodies are moved. This will ensure that references +/// between functions all refer to the versions in the new module. +Function* cloneFunctionDecl(Module &Dst, const Function &F, + ValueToValueMapTy *VMap = nullptr); + +/// @brief Move the body of function 'F' to a cloned function declaration in a +/// different module (See related cloneFunctionDecl). +/// +/// If the target function declaration is not supplied via the NewF parameter +/// then it will be looked up via the VMap. +/// +/// This will delete the body of function 'F' from its original parent module, +/// but leave its declaration. +void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap, + ValueMaterializer *Materializer = nullptr, + Function *NewF = nullptr); + +/// @brief Clone a global variable declaration into a new module. +GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV, + ValueToValueMapTy *VMap = nullptr); + +/// @brief Move global variable GV from its parent module to cloned global +/// declaration in a different module. +/// +/// If the target global declaration is not supplied via the NewGV parameter +/// then it will be looked up via the VMap. +/// +/// This will delete the initializer of GV from its original parent module, +/// but leave its declaration. +void moveGlobalVariableInitializer(GlobalVariable &OrigGV, + ValueToValueMapTy &VMap, + ValueMaterializer *Materializer = nullptr, + GlobalVariable *NewGV = nullptr); + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H diff --git a/include/llvm/ExecutionEngine/Orc/JITSymbol.h b/include/llvm/ExecutionEngine/Orc/JITSymbol.h new file mode 100644 index 000000000000..422a3761837c --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/JITSymbol.h @@ -0,0 +1,77 @@ +//===----------- JITSymbol.h - JIT symbol abstraction -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Abstraction for target process addresses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H +#define LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H + +#include "llvm/ExecutionEngine/JITSymbolFlags.h" +#include "llvm/Support/DataTypes.h" +#include <cassert> +#include <functional> + +namespace llvm { +namespace orc { + +/// @brief Represents an address in the target process's address space. +typedef uint64_t TargetAddress; + +/// @brief Represents a symbol in the JIT. +class JITSymbol : public JITSymbolBase { +public: + + typedef std::function<TargetAddress()> GetAddressFtor; + + /// @brief Create a 'null' symbol that represents failure to find a symbol + /// definition. + JITSymbol(std::nullptr_t) + : JITSymbolBase(JITSymbolFlags::None), CachedAddr(0) {} + + /// @brief Create a symbol for a definition with a known address. + JITSymbol(TargetAddress Addr, JITSymbolFlags Flags) + : JITSymbolBase(Flags), CachedAddr(Addr) {} + + /// @brief Create a symbol for a definition that doesn't have a known address + /// yet. + /// @param GetAddress A functor to materialize a definition (fixing the + /// address) on demand. + /// + /// This constructor allows a JIT layer to provide a reference to a symbol + /// definition without actually materializing the definition up front. The + /// user can materialize the definition at any time by calling the getAddress + /// method. + JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags) + : JITSymbolBase(Flags), GetAddress(std::move(GetAddress)), CachedAddr(0) {} + + /// @brief Returns true if the symbol exists, false otherwise. + explicit operator bool() const { return CachedAddr || GetAddress; } + + /// @brief Get the address of the symbol in the target address space. Returns + /// '0' if the symbol does not exist. + TargetAddress getAddress() { + if (GetAddress) { + CachedAddr = GetAddress(); + assert(CachedAddr && "Symbol could not be materialized."); + GetAddress = nullptr; + } + return CachedAddr; + } + +private: + GetAddressFtor GetAddress; + TargetAddress CachedAddr; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H diff --git a/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h new file mode 100644 index 000000000000..faa23658524f --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h @@ -0,0 +1,62 @@ +//===-- LambdaResolverMM - Redirect symbol lookup via a functor -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a RuntimeDyld::SymbolResolver subclass that uses a user-supplied +// functor for symbol resolution. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H +#define LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include <memory> +#include <vector> + +namespace llvm { +namespace orc { + +template <typename ExternalLookupFtorT, typename DylibLookupFtorT> +class LambdaResolver : public RuntimeDyld::SymbolResolver { +public: + + LambdaResolver(ExternalLookupFtorT ExternalLookupFtor, + DylibLookupFtorT DylibLookupFtor) + : ExternalLookupFtor(ExternalLookupFtor), + DylibLookupFtor(DylibLookupFtor) {} + + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) final { + return ExternalLookupFtor(Name); + } + + RuntimeDyld::SymbolInfo + findSymbolInLogicalDylib(const std::string &Name) final { + return DylibLookupFtor(Name); + } + +private: + ExternalLookupFtorT ExternalLookupFtor; + DylibLookupFtorT DylibLookupFtor; +}; + +template <typename ExternalLookupFtorT, + typename DylibLookupFtorT> +std::unique_ptr<LambdaResolver<ExternalLookupFtorT, DylibLookupFtorT>> +createLambdaResolver(ExternalLookupFtorT ExternalLookupFtor, + DylibLookupFtorT DylibLookupFtor) { + typedef LambdaResolver<ExternalLookupFtorT, DylibLookupFtorT> LR; + return make_unique<LR>(std::move(ExternalLookupFtor), + std::move(DylibLookupFtor)); +} + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H diff --git a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h new file mode 100644 index 000000000000..71c83f7e05f6 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h @@ -0,0 +1,304 @@ +//===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains the definition for a lazy-emitting layer for the JIT. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H + +#include "JITSymbol.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringMap.h" +#include <list> + +namespace llvm { +namespace orc { + +/// @brief Lazy-emitting IR layer. +/// +/// This layer accepts sets of LLVM IR Modules (via addModuleSet), but does +/// not immediately emit them the layer below. Instead, emissing to the base +/// layer is deferred until the first time the client requests the address +/// (via JITSymbol::getAddress) for a symbol contained in this layer. +template <typename BaseLayerT> class LazyEmittingLayer { +public: + typedef typename BaseLayerT::ModuleSetHandleT BaseLayerHandleT; + +private: + class EmissionDeferredSet { + public: + EmissionDeferredSet() : EmitState(NotEmitted) {} + virtual ~EmissionDeferredSet() {} + + JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) { + switch (EmitState) { + case NotEmitted: + if (auto GV = searchGVs(Name, ExportedSymbolsOnly)) { + // Create a std::string version of Name to capture here - the argument + // (a StringRef) may go away before the lambda is executed. + // FIXME: Use capture-init when we move to C++14. + std::string PName = Name; + JITSymbolFlags Flags = JITSymbolBase::flagsFromGlobalValue(*GV); + auto GetAddress = + [this, ExportedSymbolsOnly, PName, &B]() -> TargetAddress { + if (this->EmitState == Emitting) + return 0; + else if (this->EmitState == NotEmitted) { + this->EmitState = Emitting; + Handle = this->emitToBaseLayer(B); + this->EmitState = Emitted; + } + auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly); + return Sym.getAddress(); + }; + return JITSymbol(std::move(GetAddress), Flags); + } else + return nullptr; + case Emitting: + // Calling "emit" can trigger external symbol lookup (e.g. to check for + // pre-existing definitions of common-symbol), but it will never find in + // this module that it would not have found already, so return null from + // here. + return nullptr; + case Emitted: + return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly); + } + llvm_unreachable("Invalid emit-state."); + } + + void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) { + if (EmitState != NotEmitted) + BaseLayer.removeModuleSet(Handle); + } + + void emitAndFinalize(BaseLayerT &BaseLayer) { + assert(EmitState != Emitting && + "Cannot emitAndFinalize while already emitting"); + if (EmitState == NotEmitted) { + EmitState = Emitting; + Handle = emitToBaseLayer(BaseLayer); + EmitState = Emitted; + } + BaseLayer.emitAndFinalize(Handle); + } + + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> + static std::unique_ptr<EmissionDeferredSet> + create(BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver); + + protected: + virtual const GlobalValue* searchGVs(StringRef Name, + bool ExportedSymbolsOnly) const = 0; + virtual BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) = 0; + + private: + enum { NotEmitted, Emitting, Emitted } EmitState; + BaseLayerHandleT Handle; + }; + + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> + class EmissionDeferredSetImpl : public EmissionDeferredSet { + public: + EmissionDeferredSetImpl(ModuleSetT Ms, + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) + : Ms(std::move(Ms)), MemMgr(std::move(MemMgr)), + Resolver(std::move(Resolver)) {} + + protected: + + const GlobalValue* searchGVs(StringRef Name, + bool ExportedSymbolsOnly) const override { + // FIXME: We could clean all this up if we had a way to reliably demangle + // names: We could just demangle name and search, rather than + // mangling everything else. + + // If we have already built the mangled name set then just search it. + if (MangledSymbols) { + auto VI = MangledSymbols->find(Name); + if (VI == MangledSymbols->end()) + return nullptr; + auto GV = VI->second; + if (!ExportedSymbolsOnly || GV->hasDefaultVisibility()) + return GV; + return nullptr; + } + + // If we haven't built the mangled name set yet, try to build it. As an + // optimization this will leave MangledNames set to nullptr if we find + // Name in the process of building the set. + return buildMangledSymbols(Name, ExportedSymbolsOnly); + } + + BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) override { + // We don't need the mangled names set any more: Once we've emitted this + // to the base layer we'll just look for symbols there. + MangledSymbols.reset(); + return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr), + std::move(Resolver)); + } + + private: + // If the mangled name of the given GlobalValue matches the given search + // name (and its visibility conforms to the ExportedSymbolsOnly flag) then + // return the symbol. Otherwise, add the mangled name to the Names map and + // return nullptr. + const GlobalValue* addGlobalValue(StringMap<const GlobalValue*> &Names, + const GlobalValue &GV, + const Mangler &Mang, StringRef SearchName, + bool ExportedSymbolsOnly) const { + // Modules don't "provide" decls or common symbols. + if (GV.isDeclaration() || GV.hasCommonLinkage()) + return nullptr; + + // Mangle the GV name. + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mang.getNameWithPrefix(MangledNameStream, &GV, false); + } + + // Check whether this is the name we were searching for, and if it is then + // bail out early. + if (MangledName == SearchName) + if (!ExportedSymbolsOnly || GV.hasDefaultVisibility()) + return &GV; + + // Otherwise add this to the map for later. + Names[MangledName] = &GV; + return nullptr; + } + + // Build the MangledSymbols map. Bails out early (with MangledSymbols left set + // to nullptr) if the given SearchName is found while building the map. + const GlobalValue* buildMangledSymbols(StringRef SearchName, + bool ExportedSymbolsOnly) const { + assert(!MangledSymbols && "Mangled symbols map already exists?"); + + auto Symbols = llvm::make_unique<StringMap<const GlobalValue*>>(); + + for (const auto &M : Ms) { + Mangler Mang(&M->getDataLayout()); + + for (const auto &V : M->globals()) + if (auto GV = addGlobalValue(*Symbols, V, Mang, SearchName, + ExportedSymbolsOnly)) + return GV; + + for (const auto &F : *M) + if (auto GV = addGlobalValue(*Symbols, F, Mang, SearchName, + ExportedSymbolsOnly)) + return GV; + } + + MangledSymbols = std::move(Symbols); + return nullptr; + } + + ModuleSetT Ms; + MemoryManagerPtrT MemMgr; + SymbolResolverPtrT Resolver; + mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols; + }; + + typedef std::list<std::unique_ptr<EmissionDeferredSet>> ModuleSetListT; + + BaseLayerT &BaseLayer; + ModuleSetListT ModuleSetList; + +public: + /// @brief Handle to a set of loaded modules. + typedef typename ModuleSetListT::iterator ModuleSetHandleT; + + /// @brief Construct a lazy emitting layer. + LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} + + /// @brief Add the given set of modules to the lazy emitting layer. + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> + ModuleSetHandleT addModuleSet(ModuleSetT Ms, + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + return ModuleSetList.insert( + ModuleSetList.end(), + EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MemMgr), + std::move(Resolver))); + } + + /// @brief Remove the module set represented by the given handle. + /// + /// This method will free the memory associated with the given module set, + /// both in this layer, and the base layer. + void removeModuleSet(ModuleSetHandleT H) { + (*H)->removeModulesFromBaseLayer(BaseLayer); + ModuleSetList.erase(H); + } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + // Look for the symbol among existing definitions. + if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly)) + return Symbol; + + // If not found then search the deferred sets. If any of these contain a + // definition of 'Name' then they will return a JITSymbol that will emit + // the corresponding module when the symbol address is requested. + for (auto &DeferredSet : ModuleSetList) + if (auto Symbol = DeferredSet->find(Name, ExportedSymbolsOnly, BaseLayer)) + return Symbol; + + // If no definition found anywhere return a null symbol. + return nullptr; + } + + /// @brief Get the address of the given symbol in the context of the set of + /// compiled modules represented by the handle H. + JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + return (*H)->find(Name, ExportedSymbolsOnly, BaseLayer); + } + + /// @brief Immediately emit and finalize the moduleOB set represented by the + /// given handle. + /// @param H Handle for module set to emit/finalize. + void emitAndFinalize(ModuleSetHandleT H) { + (*H)->emitAndFinalize(BaseLayer); + } + +}; + +template <typename BaseLayerT> +template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> +std::unique_ptr<typename LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet> +LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet::create( + BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + typedef EmissionDeferredSetImpl<ModuleSetT, MemoryManagerPtrT, SymbolResolverPtrT> + EDS; + return llvm::make_unique<EDS>(std::move(Ms), std::move(MemMgr), + std::move(Resolver)); +} + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h new file mode 100644 index 000000000000..f3094dafae3c --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -0,0 +1,284 @@ +//===- ObjectLinkingLayer.h - Add object files to a JIT process -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains the definition for the object layer of the JIT. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H + +#include "JITSymbol.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include <list> +#include <memory> + +namespace llvm { +namespace orc { + +class ObjectLinkingLayerBase { +protected: + + /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT. + /// + /// An instance of this class will be created for each set of objects added + /// via JITObjectLayer::addObjectSet. Deleting the instance (via + /// removeObjectSet) frees its memory, removing all symbol definitions that + /// had been provided by this instance. Higher level layers are responsible + /// for taking any action required to handle the missing symbols. + class LinkedObjectSet { + LinkedObjectSet(const LinkedObjectSet&) = delete; + void operator=(const LinkedObjectSet&) = delete; + public: + LinkedObjectSet(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RTDyld(llvm::make_unique<RuntimeDyld>(MemMgr, Resolver)), + State(Raw) {} + + virtual ~LinkedObjectSet() {} + + std::unique_ptr<RuntimeDyld::LoadedObjectInfo> + addObject(const object::ObjectFile &Obj) { + return RTDyld->loadObject(Obj); + } + + RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const { + return RTDyld->getSymbol(Name); + } + + bool NeedsFinalization() const { return (State == Raw); } + + virtual void Finalize() = 0; + + void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) { + assert((State != Finalized) && + "Attempting to remap sections for finalized objects."); + RTDyld->mapSectionAddress(LocalAddress, TargetAddr); + } + + void takeOwnershipOfBuffer(std::unique_ptr<MemoryBuffer> B) { + OwnedBuffers.push_back(std::move(B)); + } + + protected: + std::unique_ptr<RuntimeDyld> RTDyld; + enum { Raw, Finalizing, Finalized } State; + + // FIXME: This ownership hack only exists because RuntimeDyldELF still + // wants to be able to inspect the original object when resolving + // relocations. As soon as that can be fixed this should be removed. + std::vector<std::unique_ptr<MemoryBuffer>> OwnedBuffers; + }; + + typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT; + +public: + /// @brief Handle to a set of loaded objects. + typedef LinkedObjectSetListT::iterator ObjSetHandleT; + + // Ownership hack. + // FIXME: Remove this as soon as RuntimeDyldELF can apply relocations without + // referencing the original object. + template <typename OwningMBSet> + void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs) { + for (auto &MB : MBs) + (*H)->takeOwnershipOfBuffer(std::move(MB)); + } + +}; + +/// @brief Default (no-op) action to perform when loading objects. +class DoNothingOnNotifyLoaded { +public: + template <typename ObjSetT, typename LoadResult> + void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &, + const LoadResult &) {} +}; + +/// @brief Bare bones object linking layer. +/// +/// This class is intended to be used as the base layer for a JIT. It allows +/// object files to be loaded into memory, linked, and the addresses of their +/// symbols queried. All objects added to this layer can see each other's +/// symbols. +template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded> +class ObjectLinkingLayer : public ObjectLinkingLayerBase { +private: + + template <typename MemoryManagerPtrT, typename SymbolResolverPtrT> + class ConcreteLinkedObjectSet : public LinkedObjectSet { + public: + ConcreteLinkedObjectSet(MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) + : LinkedObjectSet(*MemMgr, *Resolver), MemMgr(std::move(MemMgr)), + Resolver(std::move(Resolver)) { } + + void Finalize() override { + State = Finalizing; + RTDyld->resolveRelocations(); + RTDyld->registerEHFrames(); + MemMgr->finalizeMemory(); + OwnedBuffers.clear(); + State = Finalized; + } + + private: + MemoryManagerPtrT MemMgr; + SymbolResolverPtrT Resolver; + }; + + template <typename MemoryManagerPtrT, typename SymbolResolverPtrT> + std::unique_ptr<LinkedObjectSet> + createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver) { + typedef ConcreteLinkedObjectSet<MemoryManagerPtrT, SymbolResolverPtrT> LOS; + return llvm::make_unique<LOS>(std::move(MemMgr), std::move(Resolver)); + } + +public: + + /// @brief LoadedObjectInfo list. Contains a list of owning pointers to + /// RuntimeDyld::LoadedObjectInfo instances. + typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>> + LoadedObjInfoList; + + /// @brief Functor for receiving finalization notifications. + typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor; + + /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded, + /// and NotifyFinalized functors. + ObjectLinkingLayer( + NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), + NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()) + : NotifyLoaded(std::move(NotifyLoaded)), + NotifyFinalized(std::move(NotifyFinalized)) {} + + /// @brief Add a set of objects (or archives) that will be treated as a unit + /// for the purposes of symbol lookup and memory management. + /// + /// @return A pair containing (1) A handle that can be used to free the memory + /// allocated for the objects, and (2) a LoadedObjInfoList containing + /// one LoadedObjInfo instance for each object at the corresponding + /// index in the Objects list. + /// + /// This version of this method allows the client to pass in an + /// RTDyldMemoryManager instance that will be used to allocate memory and look + /// up external symbol addresses for the given objects. + template <typename ObjSetT, + typename MemoryManagerPtrT, + typename SymbolResolverPtrT> + ObjSetHandleT addObjectSet(const ObjSetT &Objects, + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + ObjSetHandleT Handle = + LinkedObjSetList.insert( + LinkedObjSetList.end(), + createLinkedObjectSet(std::move(MemMgr), std::move(Resolver))); + + LinkedObjectSet &LOS = **Handle; + LoadedObjInfoList LoadedObjInfos; + + for (auto &Obj : Objects) + LoadedObjInfos.push_back(LOS.addObject(*Obj)); + + NotifyLoaded(Handle, Objects, LoadedObjInfos); + + return Handle; + } + + /// @brief Remove the set of objects associated with handle H. + /// + /// All memory allocated for the objects will be freed, and the sections and + /// symbols they provided will no longer be available. No attempt is made to + /// re-emit the missing symbols, and any use of these symbols (directly or + /// indirectly) will result in undefined behavior. If dependence tracking is + /// required to detect or resolve such issues it should be added at a higher + /// layer. + void removeObjectSet(ObjSetHandleT H) { + // How do we invalidate the symbols in H? + LinkedObjSetList.erase(H); + } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { + for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E; + ++I) + if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly)) + return Symbol; + + return nullptr; + } + + /// @brief Search for the given named symbol in the context of the set of + /// loaded objects represented by the handle H. + /// @param H The handle for the object set to search in. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it is found in the + /// given object set. + JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name, + bool ExportedSymbolsOnly) { + if (auto Sym = (*H)->getSymbol(Name)) { + if (Sym.isExported() || !ExportedSymbolsOnly) { + auto Addr = Sym.getAddress(); + auto Flags = Sym.getFlags(); + if (!(*H)->NeedsFinalization()) { + // If this instance has already been finalized then we can just return + // the address. + return JITSymbol(Addr, Flags); + } else { + // If this instance needs finalization return a functor that will do + // it. The functor still needs to double-check whether finalization is + // required, in case someone else finalizes this set before the + // functor is called. + auto GetAddress = + [this, Addr, H]() { + if ((*H)->NeedsFinalization()) { + (*H)->Finalize(); + if (NotifyFinalized) + NotifyFinalized(H); + } + return Addr; + }; + return JITSymbol(std::move(GetAddress), Flags); + } + } + } + return nullptr; + } + + /// @brief Map section addresses for the objects associated with the handle H. + void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress, + TargetAddress TargetAddr) { + (*H)->mapSectionAddress(LocalAddress, TargetAddr); + } + + /// @brief Immediately emit and finalize the object set represented by the + /// given handle. + /// @param H Handle for object set to emit/finalize. + void emitAndFinalize(ObjSetHandleT H) { + (*H)->Finalize(); + if (NotifyFinalized) + NotifyFinalized(H); + } + +private: + LinkedObjectSetListT LinkedObjSetList; + NotifyLoadedFtor NotifyLoaded; + NotifyFinalizedFtor NotifyFinalized; +}; + +} // End namespace orc. +} // End namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h b/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h new file mode 100644 index 000000000000..309f5a96090e --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h @@ -0,0 +1,53 @@ +//===-- OrcTargetSupport.h - Code to support specific targets --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Target specific code for Orc, e.g. callback assembly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H +#define LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H + +#include "IndirectionUtils.h" + +namespace llvm { +namespace orc { + +class OrcX86_64 { +public: + static const char *ResolverBlockName; + + /// @brief Insert module-level inline callback asm into module M for the + /// symbols managed by JITResolveCallbackHandler J. + static void insertResolverBlock(Module &M, + JITCompileCallbackManagerBase &JCBM); + + /// @brief Get a label name from the given index. + typedef std::function<std::string(unsigned)> LabelNameFtor; + + /// @brief Insert the requested number of trampolines into the given module. + /// @param M Module to insert the call block into. + /// @param NumCalls Number of calls to create in the call block. + /// @param StartIndex Optional argument specifying the index suffix to start + /// with. + /// @return A functor that provides the symbol name for each entry in the call + /// block. + /// + static LabelNameFtor insertCompileCallbackTrampolines( + Module &M, + TargetAddress TrampolineAddr, + unsigned NumCalls, + unsigned StartIndex = 0); + +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H diff --git a/include/llvm/ExecutionEngine/OrcMCJITReplacement.h b/include/llvm/ExecutionEngine/OrcMCJITReplacement.h new file mode 100644 index 000000000000..4cd5648b2fc2 --- /dev/null +++ b/include/llvm/ExecutionEngine/OrcMCJITReplacement.h @@ -0,0 +1,38 @@ +//===---- OrcMCJITReplacement.h - Orc-based MCJIT replacement ---*- 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 OrcMCJITReplacement to link in on certain operating systems. +// (Windows). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORCMCJITREPLACEMENT_H +#define LLVM_EXECUTIONENGINE_ORCMCJITREPLACEMENT_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include <cstdlib> + +extern "C" void LLVMLinkInOrcMCJITReplacement(); + +namespace { + struct ForceOrcMCJITReplacementLinking { + ForceOrcMCJITReplacementLinking() { + // We must reference OrcMCJITReplacement 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; + + LLVMLinkInOrcMCJITReplacement(); + } + } ForceOrcMCJITReplacementLinking; +} + +#endif diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index ef81cd328bdb..207bad06c239 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -14,6 +14,7 @@ #ifndef LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H #define LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H +#include "RuntimeDyld.h" #include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CBindingWrapping.h" @@ -27,68 +28,91 @@ class ExecutionEngine; class ObjectFile; } +class MCJITMemoryManager : public RuntimeDyld::MemoryManager { +public: + /// This method is called after an object has been loaded into memory but + /// before relocations are applied to the loaded sections. The object load + /// may have been initiated by MCJIT to resolve an external symbol for another + /// object that is being finalized. In that case, the object about which + /// the memory manager is being notified will be finalized immediately after + /// the memory manager returns from this call. + /// + /// Memory managers which are preparing code for execution in an external + /// address space can use this call to remap the section addresses for the + /// newly loaded object. + virtual void notifyObjectLoaded(ExecutionEngine *EE, + const object::ObjectFile &) {} +}; + // RuntimeDyld clients often want to handle the memory management of // what gets placed where. For JIT clients, this is the subset of // JITMemoryManager required for dynamic loading of binaries. // // FIXME: As the RuntimeDyld fills out, additional routines will be needed // for the varying types of objects to be allocated. -class RTDyldMemoryManager { - RTDyldMemoryManager(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; +class RTDyldMemoryManager : public MCJITMemoryManager, + public RuntimeDyld::SymbolResolver { + RTDyldMemoryManager(const RTDyldMemoryManager&) = delete; + void operator=(const RTDyldMemoryManager&) = delete; public: RTDyldMemoryManager() {} - virtual ~RTDyldMemoryManager(); - - /// Allocate a memory block of (at least) the given size suitable for - /// executable code. The SectionID is a unique identifier assigned by the JIT - /// engine, and optionally recorded by the memory manager to access a loaded - /// section. - virtual uint8_t *allocateCodeSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName) = 0; - - /// Allocate a memory block of (at least) the given size suitable for data. - /// The SectionID is a unique identifier assigned by the JIT engine, and - /// optionally recorded by the memory manager to access a loaded section. - virtual uint8_t *allocateDataSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName, bool IsReadOnly) = 0; - - /// Inform the memory manager about the total amount of memory required to - /// allocate all sections to be loaded: - /// \p CodeSize - the total size of all code sections - /// \p DataSizeRO - the total size of all read-only data sections - /// \p DataSizeRW - the total size of all read-write data sections - /// - /// Note that by default the callback is disabled. To enable it - /// redefine the method needsToReserveAllocationSpace to return true. - virtual void reserveAllocationSpace( - uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) { } - - /// Override to return true to enable the reserveAllocationSpace callback. - virtual bool needsToReserveAllocationSpace() { return false; } - - /// Register the EH frames with the runtime so that c++ exceptions work. - /// - /// \p Addr parameter provides the local address of the EH frame section - /// data, while \p LoadAddr provides the address of the data in the target - /// address space. If the section has not been remapped (which will usually - /// be the case for local execution) these two values will be the same. - virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + ~RTDyldMemoryManager() override; - virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override; + void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override; /// This method returns the address of the specified function or variable in /// the current process. static uint64_t getSymbolAddressInProcess(const std::string &Name); + /// Legacy symbol lookup - DEPRECATED! Please override findSymbol instead. + /// /// This method returns the address of the specified function or variable. /// It is used to resolve symbols during module linking. virtual uint64_t getSymbolAddress(const std::string &Name) { return getSymbolAddressInProcess(Name); } + /// This method returns a RuntimeDyld::SymbolInfo for the specified function + /// or variable. It is used to resolve symbols during module linking. + /// + /// By default this falls back on the legacy lookup method: + /// 'getSymbolAddress'. The address returned by getSymbolAddress is treated as + /// a strong, exported symbol, consistent with historical treatment by + /// RuntimeDyld. + /// + /// Clients writing custom RTDyldMemoryManagers are encouraged to override + /// this method and return a SymbolInfo with the flags set correctly. This is + /// necessary for RuntimeDyld to correctly handle weak and non-exported symbols. + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override { + return RuntimeDyld::SymbolInfo(getSymbolAddress(Name), + JITSymbolFlags::Exported); + } + + /// Legacy symbol lookup -- DEPRECATED! Please override + /// findSymbolInLogicalDylib instead. + /// + /// Default to treating all modules as separate. + virtual uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) { + return 0; + } + + /// Default to treating all modules as separate. + /// + /// By default this falls back on the legacy lookup method: + /// 'getSymbolAddressInLogicalDylib'. The address returned by + /// getSymbolAddressInLogicalDylib is treated as a strong, exported symbol, + /// consistent with historical treatment by RuntimeDyld. + /// + /// Clients writing custom RTDyldMemoryManagers are encouraged to override + /// this method and return a SymbolInfo with the flags set correctly. This is + /// necessary for RuntimeDyld to correctly handle weak and non-exported symbols. + RuntimeDyld::SymbolInfo + findSymbolInLogicalDylib(const std::string &Name) override { + return RuntimeDyld::SymbolInfo(getSymbolAddressInLogicalDylib(Name), + JITSymbolFlags::Exported); + } + /// This method returns the address of the specified function. As such it is /// only useful for resolving library symbols, not code generated symbols. /// @@ -100,30 +124,6 @@ public: /// MCJIT or RuntimeDyld. Use getSymbolAddress instead. virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true); - - /// This method is called after an object has been loaded into memory but - /// before relocations are applied to the loaded sections. The object load - /// may have been initiated by MCJIT to resolve an external symbol for another - /// object that is being finalized. In that case, the object about which - /// the memory manager is being notified will be finalized immediately after - /// the memory manager returns from this call. - /// - /// Memory managers which are preparing code for execution in an external - /// address space can use this call to remap the section addresses for the - /// newly loaded object. - virtual void notifyObjectLoaded(ExecutionEngine *EE, - const object::ObjectFile &) {} - - /// This method is called when object loading is complete and section page - /// permissions can be applied. It is up to the memory manager implementation - /// to decide whether or not to act on this method. The memory manager will - /// typically allocate all sections as read-write and then apply specific - /// permissions when this method is called. Code sections cannot be executed - /// until this function has been called. In addition, any cache coherency - /// operations needed to reliably use the memory are also performed. - /// - /// Returns true if an error occurred, false otherwise. - virtual bool finalizeMemory(std::string *ErrMsg = nullptr) = 0; }; // Create wrappers for C Binding types (see CBindingWrapping.h). @@ -132,4 +132,5 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS( } // namespace llvm + #endif diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 799fc34eb659..ac0151aa7ec1 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -14,9 +14,10 @@ #ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H #define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H +#include "JITSymbolFlags.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/Memory.h" +#include "llvm/DebugInfo/DIContext.h" #include <memory> namespace llvm { @@ -32,30 +33,36 @@ class RuntimeDyldCheckerImpl; class RuntimeDyld { friend class RuntimeDyldCheckerImpl; - RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION; - void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION; + RuntimeDyld(const RuntimeDyld &) = delete; + void operator=(const RuntimeDyld &) = delete; - // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public - // interface. - std::unique_ptr<RuntimeDyldImpl> Dyld; - RTDyldMemoryManager *MM; - bool ProcessAllSections; - RuntimeDyldCheckerImpl *Checker; protected: // Change the address associated with a section when resolving relocations. // Any relocations already associated with the symbol will be re-resolved. void reassignSectionAddress(unsigned SectionID, uint64_t Addr); public: + /// \brief Information about a named symbol. + class SymbolInfo : public JITSymbolBase { + public: + SymbolInfo(std::nullptr_t) : JITSymbolBase(JITSymbolFlags::None), Address(0) {} + SymbolInfo(uint64_t Address, JITSymbolFlags Flags) + : JITSymbolBase(Flags), Address(Address) {} + explicit operator bool() const { return Address != 0; } + uint64_t getAddress() const { return Address; } + private: + uint64_t Address; + }; + /// \brief Information about the loaded object. - class LoadedObjectInfo { + class LoadedObjectInfo : public llvm::LoadedObjectInfo { friend class RuntimeDyldImpl; public: LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, unsigned EndIdx) : RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { } - virtual ~LoadedObjectInfo() {} + virtual ~LoadedObjectInfo() = default; virtual object::OwningBinary<object::ObjectFile> getObjectForDebug(const object::ObjectFile &Obj) const = 0; @@ -69,7 +76,110 @@ public: unsigned BeginIdx, EndIdx; }; - RuntimeDyld(RTDyldMemoryManager *); + template <typename Derived> struct LoadedObjectInfoHelper : LoadedObjectInfo { + LoadedObjectInfoHelper(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {} + llvm::LoadedObjectInfo *clone() const override { + return new Derived(static_cast<const Derived &>(*this)); + } + }; + + /// \brief Memory Management. + class MemoryManager { + public: + virtual ~MemoryManager() {}; + + /// Allocate a memory block of (at least) the given size suitable for + /// executable code. The SectionID is a unique identifier assigned by the + /// RuntimeDyld instance, and optionally recorded by the memory manager to + /// access a loaded section. + virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName) = 0; + + /// Allocate a memory block of (at least) the given size suitable for data. + /// The SectionID is a unique identifier assigned by the JIT engine, and + /// optionally recorded by the memory manager to access a loaded section. + virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName, + bool IsReadOnly) = 0; + + /// Inform the memory manager about the total amount of memory required to + /// allocate all sections to be loaded: + /// \p CodeSize - the total size of all code sections + /// \p DataSizeRO - the total size of all read-only data sections + /// \p DataSizeRW - the total size of all read-write data sections + /// + /// Note that by default the callback is disabled. To enable it + /// redefine the method needsToReserveAllocationSpace to return true. + virtual void reserveAllocationSpace(uintptr_t CodeSize, + uintptr_t DataSizeRO, + uintptr_t DataSizeRW) {} + + /// Override to return true to enable the reserveAllocationSpace callback. + virtual bool needsToReserveAllocationSpace() { return false; } + + /// Register the EH frames with the runtime so that c++ exceptions work. + /// + /// \p Addr parameter provides the local address of the EH frame section + /// data, while \p LoadAddr provides the address of the data in the target + /// address space. If the section has not been remapped (which will usually + /// be the case for local execution) these two values will be the same. + virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) = 0; + virtual void deregisterEHFrames(uint8_t *addr, uint64_t LoadAddr, + size_t Size) = 0; + + /// This method is called when object loading is complete and section page + /// permissions can be applied. It is up to the memory manager implementation + /// to decide whether or not to act on this method. The memory manager will + /// typically allocate all sections as read-write and then apply specific + /// permissions when this method is called. Code sections cannot be executed + /// until this function has been called. In addition, any cache coherency + /// operations needed to reliably use the memory are also performed. + /// + /// Returns true if an error occurred, false otherwise. + virtual bool finalizeMemory(std::string *ErrMsg = nullptr) = 0; + + private: + virtual void anchor(); + }; + + /// \brief Symbol resolution. + class SymbolResolver { + public: + virtual ~SymbolResolver() {}; + + /// This method returns the address of the specified function or variable. + /// It is used to resolve symbols during module linking. + virtual SymbolInfo findSymbol(const std::string &Name) = 0; + + /// This method returns the address of the specified symbol if it exists + /// within the logical dynamic library represented by this + /// RTDyldMemoryManager. Unlike getSymbolAddress, queries through this + /// interface should return addresses for hidden symbols. + /// + /// This is of particular importance for the Orc JIT APIs, which support lazy + /// compilation by breaking up modules: Each of those broken out modules + /// must be able to resolve hidden symbols provided by the others. Clients + /// writing memory managers for MCJIT can usually ignore this method. + /// + /// This method will be queried by RuntimeDyld when checking for previous + /// definitions of common symbols. It will *not* be queried by default when + /// resolving external symbols (this minimises the link-time overhead for + /// MCJIT clients who don't care about Orc features). If you are writing a + /// RTDyldMemoryManager for Orc and want "external" symbol resolution to + /// search the logical dylib, you should override your getSymbolAddress + /// method call this method directly. + virtual SymbolInfo findSymbolInLogicalDylib(const std::string &Name) = 0; + private: + virtual void anchor(); + }; + + /// \brief Construct a RuntimeDyld instance. + RuntimeDyld(MemoryManager &MemMgr, SymbolResolver &Resolver); ~RuntimeDyld(); /// Add the referenced object file to the list of objects to be loaded and @@ -79,11 +189,11 @@ public: /// Get the address of our local copy of the symbol. This may or may not /// be the address used for relocation (clients can copy the data around /// and resolve relocatons based on where they put it). - void *getSymbolAddress(StringRef Name) const; + void *getSymbolLocalAddress(StringRef Name) const; - /// Get the address of the target copy of the symbol. This is the address - /// used for relocation. - uint64_t getSymbolLoadAddress(StringRef Name) const; + /// Get the target address and flags for the named symbol. + /// This address is the one used for relocation. + SymbolInfo getSymbol(StringRef Name) const; /// Resolve the relocations for all symbols we currently know about. void resolveRelocations(); @@ -118,6 +228,15 @@ public: assert(!Dyld && "setProcessAllSections must be called before loadObject."); this->ProcessAllSections = ProcessAllSections; } + +private: + // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public + // interface. + std::unique_ptr<RuntimeDyldImpl> Dyld; + MemoryManager &MemMgr; + SymbolResolver &Resolver; + bool ProcessAllSections; + RuntimeDyldCheckerImpl *Checker; }; } // end namespace llvm diff --git a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h index 35ceba27596c..31ce151c56a3 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h +++ b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h @@ -52,6 +52,7 @@ class raw_ostream; /// /// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')' /// | 'next_pc' '(' symbol ')' +/// | 'stub_addr' '(' file-name ',' section-name ',' symbol ')' /// | symbol /// /// binary_expr = expr '+' expr @@ -85,12 +86,12 @@ public: /// \brief Returns the address of the requested section (or an error message /// in the second element of the pair if the address cannot be found). /// - /// if 'LinkerAddress' is true, this returns the address of the section - /// within the linker's memory. If 'LinkerAddress' is false it returns the + /// if 'LocalAddress' is true, this returns the address of the section + /// within the linker's memory. If 'LocalAddress' is false it returns the /// address within the target process (i.e. the load address). std::pair<uint64_t, std::string> getSectionAddr(StringRef FileName, StringRef SectionName, - bool LinkerAddress); + bool LocalAddress); private: std::unique_ptr<RuntimeDyldCheckerImpl> Impl; diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index 136856390b21..0b0dcb021f14 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -16,7 +16,7 @@ #define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H #include "llvm/ADT/SmallVector.h" -#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Memory.h" @@ -35,12 +35,12 @@ namespace llvm { /// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory /// directly. Clients of MCJIT should call MCJIT::finalizeObject. class SectionMemoryManager : public RTDyldMemoryManager { - SectionMemoryManager(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; + SectionMemoryManager(const SectionMemoryManager&) = delete; + void operator=(const SectionMemoryManager&) = delete; public: SectionMemoryManager() { } - virtual ~SectionMemoryManager(); + ~SectionMemoryManager() override; /// \brief Allocates a memory block of (at least) the given size suitable for /// executable code. diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index dd76a90aa5ea..fc04fe71cbf0 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -64,6 +64,11 @@ public: /// containing function, return the number of bytes known to be /// dereferenceable. Otherwise, zero is returned. uint64_t getDereferenceableBytes() const; + + /// \brief If this argument has the dereferenceable_or_null attribute on + /// it in its containing function, return the number of bytes known to be + /// dereferenceable. Otherwise, zero is returned. + uint64_t getDereferenceableOrNullBytes() const; /// \brief Return true if this argument has the byval attribute on it in its /// containing function. diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 5ff48d688918..e2a0a7ee395a 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -73,6 +73,7 @@ public: ByVal, ///< Pass structure by value InAlloca, ///< Pass structure in an alloca Cold, ///< Marks function as being in a cold path. + Convergent, ///< Can only be moved to control-equivalent blocks InlineHint, ///< Source said inlining was desirable InReg, ///< Force argument to be passed in register JumpTable, ///< Build jump-instruction tables and replace refs. @@ -89,6 +90,7 @@ public: ///< often, so lazy binding isn't worthwhile NonNull, ///< Pointer is known to be not null Dereferenceable, ///< Pointer is known to be dereferenceable + DereferenceableOrNull, ///< Pointer is either null or dereferenceable NoRedZone, ///< Disable redzone NoReturn, ///< Mark the function as not returning NoUnwind, ///< Function doesn't unwind stack @@ -136,6 +138,8 @@ public: static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align); static Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes); + static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context, + uint64_t Bytes); //===--------------------------------------------------------------------===// // Attribute Accessors @@ -185,6 +189,10 @@ public: /// dereferenceable attribute (or zero if unknown). uint64_t getDereferenceableBytes() const; + /// \brief Returns the number of dereferenceable_or_null bytes from the + /// dereferenceable_or_null attribute (or zero if unknown). + uint64_t getDereferenceableOrNullBytes() const; + /// \brief The Attribute is converted to a string of equivalent mnemonic. This /// is, presumably, for writing out the mnemonics for the assembly writer. std::string getAsString(bool InAttrGrp = false) const; @@ -253,35 +261,52 @@ public: ArrayRef<Attribute::AttrKind> Kind); static AttributeSet get(LLVMContext &C, unsigned Index, const AttrBuilder &B); - /// \brief Add an attribute to the attribute set at the given index. Since + /// \brief Add an attribute to the attribute set at the given index. Because /// attribute sets are immutable, this returns a new set. AttributeSet addAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const; - /// \brief Add an attribute to the attribute set at the given index. Since + /// \brief Add an attribute to the attribute set at the given index. Because /// attribute sets are immutable, this returns a new set. AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind) const; AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind, StringRef Value) const; - /// \brief Add attributes to the attribute set at the given index. Since + /// \brief Add attributes to the attribute set at the given index. Because /// attribute sets are immutable, this returns a new set. AttributeSet addAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const; /// \brief Remove the specified attribute at the specified index from this - /// attribute list. Since attribute lists are immutable, this returns the new - /// list. + /// attribute list. Because attribute lists are immutable, this returns the + /// new list. AttributeSet removeAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const; /// \brief Remove the specified attributes at the specified index from this - /// attribute list. Since attribute lists are immutable, this returns the new - /// list. + /// attribute list. Because attribute lists are immutable, this returns the + /// new list. AttributeSet removeAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const; + /// \brief Remove the specified attributes at the specified index from this + /// attribute list. Because attribute lists are immutable, this returns the + /// new list. + AttributeSet removeAttributes(LLVMContext &C, unsigned Index, + const AttrBuilder &Attrs) const; + + /// \brief Add the dereferenceable attribute to the attribute set at the given + /// index. Because attribute sets are immutable, this returns a new set. + AttributeSet addDereferenceableAttr(LLVMContext &C, unsigned Index, + uint64_t Bytes) const; + + /// \brief Add the dereferenceable_or_null attribute to the attribute set at + /// the given index. Because attribute sets are immutable, this returns a new + /// set. + AttributeSet addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index, + uint64_t Bytes) const; + //===--------------------------------------------------------------------===// // AttributeSet Accessors //===--------------------------------------------------------------------===// @@ -326,6 +351,10 @@ public: /// \brief Get the number of dereferenceable bytes (or zero if unknown). uint64_t getDereferenceableBytes(unsigned Index) const; + /// \brief Get the number of dereferenceable_or_null bytes (or zero if + /// unknown). + uint64_t getDereferenceableOrNullBytes(unsigned Index) const; + /// \brief Return the attributes at the index as a string. std::string getAsString(unsigned Index, bool InAttrGrp = false) const; @@ -406,14 +435,19 @@ class AttrBuilder { uint64_t Alignment; uint64_t StackAlignment; uint64_t DerefBytes; + uint64_t DerefOrNullBytes; public: - AttrBuilder() : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) {} + AttrBuilder() + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0), + DerefOrNullBytes(0) {} explicit AttrBuilder(uint64_t Val) - : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) { + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0), + DerefOrNullBytes(0) { addRawValue(Val); } AttrBuilder(const Attribute &A) - : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) { + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0), + DerefOrNullBytes(0) { addAttribute(A); } AttrBuilder(AttributeSet AS, unsigned Idx); @@ -441,6 +475,13 @@ public: /// \brief Add the attributes from the builder. AttrBuilder &merge(const AttrBuilder &B); + /// \brief Remove the attributes from the builder. + AttrBuilder &remove(const AttrBuilder &B); + + /// \brief Return true if the builder has any attribute that's in the + /// specified builder. + bool overlaps(const AttrBuilder &B) const; + /// \brief Return true if the builder has the specified attribute. bool contains(Attribute::AttrKind A) const { assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!"); @@ -471,6 +512,10 @@ public: /// attribute exists (zero is returned otherwise). uint64_t getDereferenceableBytes() const { return DerefBytes; } + /// \brief Retrieve the number of dereferenceable_or_null bytes, if the + /// dereferenceable_or_null attribute exists (zero is returned otherwise). + uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; } + /// \brief This turns an int alignment (which must be a power of 2) into the /// form used internally in Attribute. AttrBuilder &addAlignmentAttr(unsigned Align); @@ -483,6 +528,10 @@ public: /// internally in Attribute. AttrBuilder &addDereferenceableAttr(uint64_t Bytes); + /// \brief This turns the number of dereferenceable_or_null bytes into the + /// form used internally in Attribute. + AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes); + /// \brief Return true if the builder contains no target-independent /// attributes. bool empty() const { return Attrs.none(); } @@ -521,7 +570,7 @@ public: namespace AttributeFuncs { /// \brief Which attributes cannot be applied to a type. -AttributeSet typeIncompatible(Type *Ty, uint64_t Index); +AttrBuilder typeIncompatible(const Type *Ty); } // end AttributeFuncs namespace diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index 7c7dd2ca5643..66581bfedbe6 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -28,33 +28,25 @@ class LandingPadInst; class TerminatorInst; class LLVMContext; class BlockAddress; +class Function; -template<> struct ilist_traits<Instruction> - : public SymbolTableListTraits<Instruction, BasicBlock> { +// Traits for intrusive list of basic blocks... +template<> struct ilist_traits<BasicBlock> + : public SymbolTableListTraits<BasicBlock, Function> { - /// \brief Return a node that marks the end of a list. - /// - /// The sentinel is relative to this instance, so we use a non-static - /// method. - Instruction *createSentinel() const { - // Since i(p)lists always publicly derive from their corresponding traits, - // placing a data member in this class will augment the i(p)list. But since - // the NodeTy is expected to be publicly derive from ilist_node<NodeTy>, - // there is a legal viable downcast from it to NodeTy. We use this trick to - // superimpose an i(p)list with a "ghostly" NodeTy, which becomes the - // sentinel. Dereferencing the sentinel is forbidden (save the - // ilist_node<NodeTy>), so no one will ever notice the superposition. - return static_cast<Instruction*>(&Sentinel); - } - static void destroySentinel(Instruction*) {} + BasicBlock *createSentinel() const; + static void destroySentinel(BasicBlock*) {} - Instruction *provideInitialHead() const { return createSentinel(); } - Instruction *ensureHead(Instruction*) const { return createSentinel(); } - static void noteHead(Instruction*, Instruction*) {} + BasicBlock *provideInitialHead() const { return createSentinel(); } + BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); } + static void noteHead(BasicBlock*, BasicBlock*) {} + + static ValueSymbolTable *getSymTab(Function *ItemParent); private: - mutable ilist_half_node<Instruction> Sentinel; + mutable ilist_half_node<BasicBlock> Sentinel; }; + /// \brief LLVM Basic Block Representation /// /// This represents a single basic block in LLVM. A basic block is simply a @@ -82,8 +74,8 @@ private: void setParent(Function *parent); friend class SymbolTableListTraits<BasicBlock, Function>; - BasicBlock(const BasicBlock &) LLVM_DELETED_FUNCTION; - void operator=(const BasicBlock &) LLVM_DELETED_FUNCTION; + BasicBlock(const BasicBlock &) = delete; + void operator=(const BasicBlock &) = delete; /// \brief Constructor. /// @@ -113,13 +105,18 @@ public: BasicBlock *InsertBefore = nullptr) { return new BasicBlock(Context, Name, Parent, InsertBefore); } - ~BasicBlock(); + ~BasicBlock() override; /// \brief Return the enclosing method, or null if none. const Function *getParent() const { return Parent; } Function *getParent() { return Parent; } - const DataLayout *getDataLayout() const; + /// \brief Return the module owning the function this basic block belongs to, + /// or nullptr it the function does not have a module. + /// + /// Note: this is undefined behavior if the block does not have a parent. + const Module *getModule() const; + Module *getModule(); /// \brief Returns the terminator instruction if the block is well formed or /// null if the block is not well formed. @@ -172,7 +169,9 @@ public: void removeFromParent(); /// \brief Unlink 'this' from the containing function and delete it. - void eraseFromParent(); + /// + // \returns an iterator pointing to the element after the erased one. + iplist<BasicBlock>::iterator eraseFromParent(); /// \brief Unlink this basic block from its current function and insert it /// into the function that \p MovePos lives in, right before \p MovePos. @@ -208,6 +207,24 @@ public: return const_cast<BasicBlock*>(this)->getUniquePredecessor(); } + /// \brief Return the successor of this block if it has a single successor. + /// Otherwise return a null pointer. + /// + /// This method is analogous to getSinglePredecessor above. + BasicBlock *getSingleSuccessor(); + const BasicBlock *getSingleSuccessor() const { + return const_cast<BasicBlock*>(this)->getSingleSuccessor(); + } + + /// \brief Return the successor of this block if it has a unique successor. + /// Otherwise return a null pointer. + /// + /// This method is analogous to getUniquePredecessor above. + BasicBlock *getUniqueSuccessor(); + const BasicBlock *getUniqueSuccessor() const { + return const_cast<BasicBlock*>(this)->getUniqueSuccessor(); + } + //===--------------------------------------------------------------------===// /// Instruction iterator methods /// @@ -320,6 +337,12 @@ private: } }; +// createSentinel is used to get hold of the node that marks the end of the +// list... (same trick used here as in ilist_traits<Instruction>) +inline BasicBlock *ilist_traits<BasicBlock>::createSentinel() const { + return static_cast<BasicBlock*>(&Sentinel); +} + // Create wrappers for C Binding types (see CBindingWrapping.h). DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef) diff --git a/include/llvm/IR/CFG.h b/include/llvm/IR/CFG.h index 5400d2384868..f78220a52033 100644 --- a/include/llvm/IR/CFG.h +++ b/include/llvm/IR/CFG.h @@ -16,6 +16,7 @@ #define LLVM_IR_CFG_H #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" @@ -84,6 +85,8 @@ public: typedef PredIterator<BasicBlock, Value::user_iterator> pred_iterator; typedef PredIterator<const BasicBlock, Value::const_user_iterator> const_pred_iterator; +typedef llvm::iterator_range<pred_iterator> pred_range; +typedef llvm::iterator_range<const_pred_iterator> pred_const_range; inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); } inline const_pred_iterator pred_begin(const BasicBlock *BB) { @@ -96,8 +99,12 @@ inline const_pred_iterator pred_end(const BasicBlock *BB) { inline bool pred_empty(const BasicBlock *BB) { return pred_begin(BB) == pred_end(BB); } - - +inline pred_range predecessors(BasicBlock *BB) { + return pred_range(pred_begin(BB), pred_end(BB)); +} +inline pred_const_range predecessors(const BasicBlock *BB) { + return pred_const_range(pred_begin(BB), pred_end(BB)); +} //===----------------------------------------------------------------------===// // BasicBlock succ_iterator definition @@ -114,7 +121,7 @@ public: typedef typename super::reference reference; private: - const Term_ Term; + Term_ Term; unsigned idx; typedef SuccIterator<Term_, BB_> Self; @@ -129,6 +136,8 @@ private: public: explicit SuccessorProxy(const Self &it) : it(it) {} + SuccessorProxy(const SuccessorProxy&) = default; + SuccessorProxy &operator=(SuccessorProxy r) { *this = reference(r); return *this; @@ -158,12 +167,6 @@ public: idx = 0; } - inline const Self &operator=(const Self &I) { - assert(Term == I.Term &&"Cannot assign iterators to two different blocks!"); - idx = I.idx; - return *this; - } - /// getSuccessorIndex - This is used to interface between code that wants to /// operate on terminator instructions directly. unsigned getSuccessorIndex() const { return idx; } @@ -247,6 +250,8 @@ public: typedef SuccIterator<TerminatorInst*, BasicBlock> succ_iterator; typedef SuccIterator<const TerminatorInst*, const BasicBlock> succ_const_iterator; +typedef llvm::iterator_range<succ_iterator> succ_range; +typedef llvm::iterator_range<succ_const_iterator> succ_const_range; inline succ_iterator succ_begin(BasicBlock *BB) { return succ_iterator(BB->getTerminator()); @@ -263,6 +268,13 @@ inline succ_const_iterator succ_end(const BasicBlock *BB) { inline bool succ_empty(const BasicBlock *BB) { return succ_begin(BB) == succ_end(BB); } +inline succ_range successors(BasicBlock *BB) { + return succ_range(succ_begin(BB), succ_end(BB)); +} +inline succ_const_range successors(const BasicBlock *BB) { + return succ_const_range(succ_begin(BB), succ_end(BB)); +} + template <typename T, typename U> struct isPodLike<SuccIterator<T, U> > { static const bool value = isPodLike<T>::value; diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index df082577a0e2..170d263dfc79 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -46,12 +46,13 @@ template <typename FunTy = const Function, class CallSiteBase { protected: PointerIntPair<InstrTy*, 1, bool> I; -public: + CallSiteBase() : I(nullptr, false) {} CallSiteBase(CallTy *CI) : I(CI, true) { assert(CI); } CallSiteBase(InvokeTy *II) : I(II, false) { assert(II); } - CallSiteBase(ValTy *II) { *this = get(II); } -protected: + explicit CallSiteBase(ValTy *II) { *this = get(II); } + +private: /// 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 /// it can also create a null initialized CallSiteBase object for something @@ -78,7 +79,7 @@ public: InstrTy *getInstruction() const { return I.getPointer(); } InstrTy *operator->() const { return I.getPointer(); } - LLVM_EXPLICIT operator bool() const { return I.getPointer(); } + explicit operator bool() const { return I.getPointer(); } /// getCalledValue - Return the pointer to function that is being called. /// @@ -151,7 +152,7 @@ public: IterTy arg_end() const { return (*this)->op_end() - getArgumentEndOffset(); } bool arg_empty() const { return arg_end() == arg_begin(); } unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); } - + /// getType - Return the type of the instruction that generated this call site /// Type *getType() const { return (*this)->getType(); } @@ -193,6 +194,14 @@ public: CALLSITE_DELEGATE_SETTER(setCallingConv(CC)); } + FunctionType *getFunctionType() const { + CALLSITE_DELEGATE_GETTER(getFunctionType()); + } + + void mutateFunctionType(FunctionType *Ty) const { + CALLSITE_DELEGATE_SETTER(mutateFunctionType(Ty)); + } + /// getAttributes/setAttributes - get or set the parameter attributes of /// the call. const AttributeSet &getAttributes() const { @@ -222,7 +231,13 @@ public: uint64_t getDereferenceableBytes(uint16_t i) const { CALLSITE_DELEGATE_GETTER(getDereferenceableBytes(i)); } - + + /// @brief Extract the number of dereferenceable_or_null bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableOrNullBytes(uint16_t i) const { + CALLSITE_DELEGATE_GETTER(getDereferenceableOrNullBytes(i)); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -349,15 +364,13 @@ private: class CallSite : public CallSiteBase<Function, Value, User, Instruction, CallInst, InvokeInst, User::op_iterator> { - typedef CallSiteBase<Function, Value, User, Instruction, - CallInst, InvokeInst, User::op_iterator> Base; public: CallSite() {} - CallSite(Base B) : Base(B) {} - CallSite(Value* V) : Base(V) {} - CallSite(CallInst *CI) : Base(CI) {} - CallSite(InvokeInst *II) : Base(II) {} - CallSite(Instruction *II) : Base(II) {} + CallSite(CallSiteBase B) : CallSiteBase(B) {} + CallSite(CallInst *CI) : CallSiteBase(CI) {} + CallSite(InvokeInst *II) : CallSiteBase(II) {} + explicit CallSite(Instruction *II) : CallSiteBase(II) {} + explicit CallSite(Value *V) : CallSiteBase(V) {} bool operator==(const CallSite &CS) const { return I == CS.I; } bool operator!=(const CallSite &CS) const { return I != CS.I; } @@ -371,13 +384,13 @@ private: /// ImmutableCallSite - establish a view to a call site for examination class ImmutableCallSite : public CallSiteBase<> { - typedef CallSiteBase<> Base; public: - ImmutableCallSite(const Value* V) : Base(V) {} - ImmutableCallSite(const CallInst *CI) : Base(CI) {} - ImmutableCallSite(const InvokeInst *II) : Base(II) {} - ImmutableCallSite(const Instruction *II) : Base(II) {} - ImmutableCallSite(CallSite CS) : Base(CS.getInstruction()) {} + ImmutableCallSite() {} + ImmutableCallSite(const CallInst *CI) : CallSiteBase(CI) {} + ImmutableCallSite(const InvokeInst *II) : CallSiteBase(II) {} + explicit ImmutableCallSite(const Instruction *II) : CallSiteBase(II) {} + explicit ImmutableCallSite(const Value *V) : CallSiteBase(V) {} + ImmutableCallSite(CallSite CS) : CallSiteBase(CS.getInstruction()) {} }; } // End llvm namespace diff --git a/include/llvm/IR/Comdat.h b/include/llvm/IR/Comdat.h index 3e77a7709d5c..4d4c15fb68cd 100644 --- a/include/llvm/IR/Comdat.h +++ b/include/llvm/IR/Comdat.h @@ -49,7 +49,7 @@ private: friend class Module; Comdat(); Comdat(SelectionKind SK, StringMapEntry<Comdat> *Name); - Comdat(const Comdat &) LLVM_DELETED_FUNCTION; + Comdat(const Comdat &) = delete; // Points to the map in Module. StringMapEntry<Comdat> *Name; diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index d26991eaab75..75499e0a4db3 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -39,8 +39,8 @@ namespace llvm { /// don't have to worry about the lifetime of the objects. /// @brief LLVM Constant Representation class Constant : public User { - void operator=(const Constant &) LLVM_DELETED_FUNCTION; - Constant(const Constant &) LLVM_DELETED_FUNCTION; + void operator=(const Constant &) = delete; + Constant(const Constant &) = delete; void anchor() override; protected: diff --git a/include/llvm/IR/ConstantFolder.h b/include/llvm/IR/ConstantFolder.h index e271a1482117..fb6ca3b3184c 100644 --- a/include/llvm/IR/ConstantFolder.h +++ b/include/llvm/IR/ConstantFolder.h @@ -118,34 +118,35 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); + return ConstantExpr::getGetElementPtr(Ty, C, IdxList); } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getGetElementPtr(C, Idx); + return ConstantExpr::getGetElementPtr(Ty, C, Idx); } - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); + return ConstantExpr::getGetElementPtr(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getInBoundsGetElementPtr(C, Idx); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h index 5e8cd34c4d69..9ded3ca36a70 100644 --- a/include/llvm/IR/ConstantRange.h +++ b/include/llvm/IR/ConstantRange.h @@ -33,6 +33,7 @@ #define LLVM_IR_CONSTANTRANGE_H #include "llvm/ADT/APInt.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -59,15 +60,27 @@ public: /// assert out if the two APInt's are not the same bit width. ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper); - /// Produce the smallest range that contains all values that - /// might satisfy the comparison specified by Pred when compared to any value - /// contained within Other. + /// Produce the smallest range such that all values that may satisfy the given + /// predicate with any value contained within Other is contained in the + /// returned range. Formally, this returns a superset of + /// 'union over all y in Other . { x : icmp op x y is true }'. If the exact + /// answer is not representable as a ConstantRange, the return value will be a + /// proper superset of the above. /// - /// Solves for range X in 'for all x in X, there exists a y in Y such that - /// icmp op x, y is true'. Every value that might make the comparison true - /// is included in the resulting range. - static ConstantRange makeICmpRegion(unsigned Pred, - const ConstantRange &Other); + /// Example: Pred = ult and Other = i8 [2, 5) returns Result = [0, 4) + static ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred, + const ConstantRange &Other); + + /// Produce the largest range such that all values in the returned range + /// satisfy the given predicate with all values contained within Other. + /// Formally, this returns a subset of + /// 'intersection over all y in Other . { x : icmp op x y is true }'. If the + /// exact answer is not representable as a ConstantRange, the return value + /// will be a proper subset of the above. + /// + /// Example: Pred = ult and Other = i8 [2, 5) returns [0, 2) + static ConstantRange makeSatisfyingICmpRegion(CmpInst::Predicate Pred, + const ConstantRange &Other); /// Return the lower value for this range. /// @@ -208,8 +221,8 @@ public: ConstantRange sub(const ConstantRange &Other) const; /// Return a new range representing the possible values resulting - /// from a multiplication of a value in this range and a value in \p Other. - /// TODO: This isn't fully implemented yet. + /// from a multiplication of a value in this range and a value in \p Other, + /// treating both this and \p Other as unsigned ranges. ConstantRange multiply(const ConstantRange &Other) const; /// Return a new range representing the possible values resulting diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 5b098b4f51d6..e97bda54e8f0 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -12,7 +12,7 @@ /// which represent the different flavors of constant values that live in LLVM. /// Note that Constants are immutable (once created they never change) and are /// fully shared by structural equivalence. This means that two structurally -/// equivalent constants will always have the same address. Constant's are +/// equivalent constants will always have the same address. Constants are /// created on demand as needed and never deleted: thus clients don't have to /// worry about the lifetime of the objects. // @@ -46,8 +46,8 @@ template <class ConstantClass> struct ConstantAggrKeyType; /// @brief Class for constant integers. class ConstantInt : public Constant { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantInt(const ConstantInt &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantInt(const ConstantInt &) = delete; ConstantInt(IntegerType *Ty, const APInt& V); APInt Val; protected: @@ -228,8 +228,8 @@ public: class ConstantFP : public Constant { APFloat Val; void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantFP(const ConstantFP &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantFP(const ConstantFP &) = delete; friend class LLVMContextImpl; protected: ConstantFP(Type *Ty, const APFloat& V); @@ -251,6 +251,7 @@ public: static Constant *get(Type* Ty, double V); static Constant *get(Type* Ty, StringRef Str); static ConstantFP *get(LLVMContext &Context, const APFloat &V); + static Constant *getNaN(Type *Ty, bool Negative = false, unsigned type = 0); static Constant *getNegativeZero(Type *Ty); static Constant *getInfinity(Type *Ty, bool Negative = false); @@ -294,8 +295,8 @@ public: /// ConstantAggregateZero - All zero aggregate value /// class ConstantAggregateZero : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantAggregateZero(const ConstantAggregateZero &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantAggregateZero(const ConstantAggregateZero &) = delete; protected: explicit ConstantAggregateZero(Type *ty) : Constant(ty, ConstantAggregateZeroVal, nullptr, 0) {} @@ -341,7 +342,7 @@ public: /// class ConstantArray : public Constant { friend struct ConstantAggrKeyType<ConstantArray>; - ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION; + ConstantArray(const ConstantArray &) = delete; protected: ConstantArray(ArrayType *T, ArrayRef<Constant *> Val); public: @@ -383,7 +384,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant) // class ConstantStruct : public Constant { friend struct ConstantAggrKeyType<ConstantStruct>; - ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION; + ConstantStruct(const ConstantStruct &) = delete; protected: ConstantStruct(StructType *T, ArrayRef<Constant *> Val); public: @@ -442,7 +443,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant) /// class ConstantVector : public Constant { friend struct ConstantAggrKeyType<ConstantVector>; - ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION; + ConstantVector(const ConstantVector &) = delete; protected: ConstantVector(VectorType *T, ArrayRef<Constant *> Val); public: @@ -491,8 +492,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant) /// ConstantPointerNull - a constant pointer value that points to null /// class ConstantPointerNull : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantPointerNull(const ConstantPointerNull &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantPointerNull(const ConstantPointerNull &) = delete; protected: explicit ConstantPointerNull(PointerType *T) : Constant(T, @@ -542,12 +543,12 @@ class ConstantDataSequential : public Constant { /// element array of i8, or a 1-element array of i32. They'll both end up in /// the same StringMap bucket, linked up. ConstantDataSequential *Next; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataSequential(const ConstantDataSequential &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataSequential(const ConstantDataSequential &) = delete; protected: explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) : Constant(ty, VT, nullptr, 0), DataElements(Data), Next(nullptr) {} - ~ConstantDataSequential() { delete Next; } + ~ConstantDataSequential() override { delete Next; } static Constant *getImpl(StringRef Bytes, Type *Ty); @@ -653,8 +654,8 @@ private: /// operands because it stores all of the elements of the constant as densely /// packed data, instead of as Value*'s. class ConstantDataArray : public ConstantDataSequential { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataArray(const ConstantDataArray &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataArray(const ConstantDataArray &) = delete; void anchor() override; friend class ConstantDataSequential; explicit ConstantDataArray(Type *ty, const char *Data) @@ -676,6 +677,15 @@ public: static Constant *get(LLVMContext &Context, ArrayRef<float> Elts); static Constant *get(LLVMContext &Context, ArrayRef<double> Elts); + /// getFP() constructors - Return a constant with array type with an element + /// count and element type of float with precision matching the number of + /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, + /// double for 64bits) Note that this can return a ConstantAggregateZero + /// object. + static Constant *getFP(LLVMContext &Context, ArrayRef<uint16_t> Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef<uint32_t> Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef<uint64_t> Elts); + /// getString - This method constructs a CDS and initializes it with a text /// string. The default behavior (AddNull==true) causes a null terminator to /// be placed at the end of the array (increasing the length of the string by @@ -705,8 +715,8 @@ public: /// operands because it stores all of the elements of the constant as densely /// packed data, instead of as Value*'s. class ConstantDataVector : public ConstantDataSequential { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataVector(const ConstantDataVector &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataVector(const ConstantDataVector &) = delete; void anchor() override; friend class ConstantDataSequential; explicit ConstantDataVector(Type *ty, const char *Data) @@ -728,6 +738,15 @@ public: static Constant *get(LLVMContext &Context, ArrayRef<float> Elts); static Constant *get(LLVMContext &Context, ArrayRef<double> Elts); + /// getFP() constructors - Return a constant with vector type with an element + /// count and element type of float with the precision matching the number of + /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, + /// double for 64bits) Note that this can return a ConstantAggregateZero + /// object. + static Constant *getFP(LLVMContext &Context, ArrayRef<uint16_t> Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef<uint32_t> Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef<uint64_t> Elts); + /// getSplat - Return a ConstantVector with the specified constant in each /// element. The specified constant has to be a of a compatible type (i8/i16/ /// i32/i64/float/double) and must be a ConstantFP or ConstantInt. @@ -756,7 +775,7 @@ public: /// BlockAddress - The address of a basic block. /// class BlockAddress : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void *operator new(size_t s) { return User::operator new(s, 2); } BlockAddress(Function *F, BasicBlock *BB); public: @@ -1036,44 +1055,46 @@ public: bool OnlyIfReduced = false); /// Getelementptr form. Value* is only accepted for convenience; - /// all elements must be Constant's. + /// all elements must be Constants. /// /// \param OnlyIfReducedTy see \a getWithOperands() docs. - static Constant *getGetElementPtr(Constant *C, ArrayRef<Constant *> IdxList, + static Constant *getGetElementPtr(Type *Ty, Constant *C, + ArrayRef<Constant *> IdxList, bool InBounds = false, Type *OnlyIfReducedTy = nullptr) { return getGetElementPtr( - C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()), + Ty, C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()), InBounds, OnlyIfReducedTy); } - static Constant *getGetElementPtr(Constant *C, Constant *Idx, + static Constant *getGetElementPtr(Type *Ty, Constant *C, Constant *Idx, bool InBounds = false, Type *OnlyIfReducedTy = nullptr) { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return getGetElementPtr(C, cast<Value>(Idx), InBounds, OnlyIfReducedTy); + return getGetElementPtr(Ty, C, cast<Value>(Idx), InBounds, OnlyIfReducedTy); } - static Constant *getGetElementPtr(Constant *C, ArrayRef<Value *> IdxList, + static Constant *getGetElementPtr(Type *Ty, Constant *C, + ArrayRef<Value *> IdxList, bool InBounds = false, Type *OnlyIfReducedTy = nullptr); /// Create an "inbounds" getelementptr. See the documentation for the /// "inbounds" flag in LangRef.html for details. - static Constant *getInBoundsGetElementPtr(Constant *C, + static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) { - return getGetElementPtr(C, IdxList, true); + return getGetElementPtr(Ty, C, IdxList, true); } - static Constant *getInBoundsGetElementPtr(Constant *C, + static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, Constant *Idx) { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return getGetElementPtr(C, Idx, true); + return getGetElementPtr(Ty, C, Idx, true); } - static Constant *getInBoundsGetElementPtr(Constant *C, + static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) { - return getGetElementPtr(C, IdxList, true); + return getGetElementPtr(Ty, C, IdxList, true); } static Constant *getExtractElement(Constant *Vec, Constant *Idx, @@ -1125,8 +1146,9 @@ public: Constant *getWithOperands(ArrayRef<Constant *> Ops, Type *Ty, bool OnlyIfReduced = false) const; - /// getAsInstruction - Returns an Instruction which implements the same operation - /// as this ConstantExpr. The instruction is not linked to any basic block. + /// getAsInstruction - Returns an Instruction which implements the same + /// operation as this ConstantExpr. The instruction is not linked to any basic + /// block. /// /// A better approach to this could be to have a constructor for Instruction /// which would take a ConstantExpr parameter, but that would have spread @@ -1168,8 +1190,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant) /// LangRef.html#undefvalues for details. /// class UndefValue : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - UndefValue(const UndefValue &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + UndefValue(const UndefValue &) = delete; protected: explicit UndefValue(Type *T) : Constant(T, UndefValueVal, nullptr, 0) {} protected: diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index ae1ac650a9ec..997113191d19 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -30,38 +30,17 @@ namespace llvm { class Value; class Constant; class LLVMContext; - class MDNode; class StringRef; - class DIBasicType; - class DICompileUnit; - class DICompositeType; - class DIDerivedType; - class DIDescriptor; - class DIFile; - class DIEnumerator; - class DIType; - class DIGlobalVariable; - class DIImportedEntity; - class DINameSpace; - class DIVariable; - class DISubrange; - class DILexicalBlockFile; - class DILexicalBlock; - class DIScope; - class DISubprogram; - class DITemplateTypeParameter; - class DITemplateValueParameter; - class DIObjCProperty; class DIBuilder { Module &M; LLVMContext &VMContext; - MDNode *TempEnumTypes; - MDNode *TempRetainTypes; - MDNode *TempSubprograms; - MDNode *TempGVs; - MDNode *TempImportedModules; + TempMDTuple TempEnumTypes; + TempMDTuple TempRetainTypes; + TempMDTuple TempSubprograms; + TempMDTuple TempGVs; + TempMDTuple TempImportedModules; Function *DeclareFn; // llvm.dbg.declare Function *ValueFn; // llvm.dbg.value @@ -80,12 +59,12 @@ namespace llvm { /// Each subprogram's preserved local variables. DenseMap<MDNode *, std::vector<TrackingMDNodeRef>> PreservedVariables; - DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; - void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION; + DIBuilder(const DIBuilder &) = delete; + void operator=(const DIBuilder &) = delete; /// \brief Create a temporary. /// - /// Create an \a MDNodeFwdDecl and track it in \a UnresolvedNodes. + /// Create an \a temporary node and track it in \a UnresolvedNodes. void trackIfUnresolved(MDNode *N); public: @@ -116,6 +95,7 @@ namespace llvm { /// @param SplitName The name of the file that we'll split debug info out /// into. /// @param Kind The kind of debug information to generate. + /// @param DWOId The DWOId if this is a split skeleton compile unit. /// @param EmitDebugInfo A boolean flag which indicates whether debug /// information should be written to the final /// output or not. When this is false, debug @@ -125,26 +105,25 @@ namespace llvm { /// source location information in the back end /// without actually changing the output (e.g., /// when using optimization remarks). - DICompileUnit createCompileUnit(unsigned Lang, StringRef File, - StringRef Dir, StringRef Producer, - bool isOptimized, StringRef Flags, - unsigned RV, - StringRef SplitName = StringRef(), - DebugEmissionKind Kind = FullDebug, - bool EmitDebugInfo = true); + DICompileUnit * + createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, + StringRef Producer, bool isOptimized, StringRef Flags, + unsigned RV, StringRef SplitName = StringRef(), + DebugEmissionKind Kind = FullDebug, uint64_t DWOId = 0, + bool EmitDebugInfo = true); /// 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, int64_t Val); + DIEnumerator *createEnumerator(StringRef Name, int64_t Val); /// \brief Create a DWARF unspecified type. - DIBasicType createUnspecifiedType(StringRef Name); + DIBasicType *createUnspecifiedType(StringRef Name); /// \brief Create C++11 nullptr type. - DIBasicType createNullPtrType(); + DIBasicType *createNullPtrType(); /// createBasicType - Create debugging information entry for a basic /// type. @@ -152,36 +131,36 @@ namespace llvm { /// @param SizeInBits Size of the type. /// @param AlignInBits Type alignment. /// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. - DIBasicType createBasicType(StringRef Name, uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Encoding); + DIBasicType *createBasicType(StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding); /// 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. - DIDerivedType createQualifiedType(unsigned Tag, DIType FromTy); + DIDerivedType *createQualifiedType(unsigned Tag, DIType *FromTy); /// 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) - DIDerivedType - createPointerType(DIType PointeeTy, uint64_t SizeInBits, - uint64_t AlignInBits = 0, StringRef Name = StringRef()); + DIDerivedType *createPointerType(DIType *PointeeTy, uint64_t SizeInBits, + uint64_t AlignInBits = 0, + StringRef Name = ""); /// \brief Create debugging information entry for a pointer to member. /// @param PointeeTy Type pointed to by this pointer. /// @param SizeInBits Size. /// @param AlignInBits Alignment. (optional) /// @param Class Type for which this pointer points to members of. - DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class, - uint64_t SizeInBits, - uint64_t AlignInBits = 0); + DIDerivedType *createMemberPointerType(DIType *PointeeTy, DIType *Class, + uint64_t SizeInBits, + uint64_t AlignInBits = 0); /// createReferenceType - Create debugging information entry for a c++ /// style reference or rvalue reference type. - DIDerivedType createReferenceType(unsigned Tag, DIType RTy); + DIDerivedType *createReferenceType(unsigned Tag, DIType *RTy); /// createTypedef - Create debugging information entry for a typedef. /// @param Ty Original type. @@ -189,11 +168,11 @@ namespace llvm { /// @param File File where this type is defined. /// @param LineNo Line number. /// @param Context The surrounding context for the typedef. - DIDerivedType createTypedef(DIType Ty, StringRef Name, DIFile File, - unsigned LineNo, DIDescriptor Context); + DIDerivedType *createTypedef(DIType *Ty, StringRef Name, DIFile *File, + unsigned LineNo, DIScope *Context); /// createFriend - Create debugging information entry for a 'friend'. - DIDerivedType createFriend(DIType Ty, DIType FriendTy); + DIDerivedType *createFriend(DIType *Ty, DIType *FriendTy); /// createInheritance - Create debugging information entry to establish /// inheritance relationship between two types. @@ -202,8 +181,8 @@ namespace llvm { /// @param BaseOffset Base offset. /// @param Flags Flags to describe inheritance attribute, /// e.g. private - DIDerivedType createInheritance(DIType Ty, DIType BaseTy, - uint64_t BaseOffset, unsigned Flags); + DIDerivedType *createInheritance(DIType *Ty, DIType *BaseTy, + uint64_t BaseOffset, unsigned Flags); /// createMemberType - Create debugging information entry for a member. /// @param Scope Member scope. @@ -215,10 +194,11 @@ namespace llvm { /// @param OffsetInBits Member offset. /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. - DIDerivedType - createMemberType(DIDescriptor Scope, StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, DIType Ty); + DIDerivedType *createMemberType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNo, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType *Ty); /// createStaticMemberType - Create debugging information entry for a /// C++ static data member. @@ -229,10 +209,10 @@ namespace llvm { /// @param Ty Type of the static member. /// @param Flags Flags to encode member attribute, e.g. private. /// @param Val Const initializer of the member. - DIDerivedType createStaticMemberType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNo, - DIType Ty, unsigned Flags, - llvm::Constant *Val); + DIDerivedType *createStaticMemberType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNo, + DIType *Ty, unsigned Flags, + llvm::Constant *Val); /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. @@ -245,11 +225,10 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. /// @param PropertyNode Property associated with this ivar. - DIDerivedType createObjCIVar(StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, - unsigned Flags, DIType Ty, - MDNode *PropertyNode); + DIDerivedType *createObjCIVar(StringRef Name, DIFile *File, unsigned LineNo, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType *Ty, MDNode *PropertyNode); /// createObjCProperty - Create debugging information entry for Objective-C /// property. @@ -260,12 +239,11 @@ namespace llvm { /// @param SetterName Name of the Objective C property setter selector. /// @param PropertyAttributes Objective C property attributes. /// @param Ty Type. - DIObjCProperty createObjCProperty(StringRef Name, - DIFile File, unsigned LineNumber, - StringRef GetterName, - StringRef SetterName, - unsigned PropertyAttributes, - DIType Ty); + DIObjCProperty *createObjCProperty(StringRef Name, DIFile *File, + unsigned LineNumber, + StringRef GetterName, + StringRef SetterName, + unsigned PropertyAttributes, DIType *Ty); /// createClassType - Create debugging information entry for a class. /// @param Scope Scope in which this class is defined. @@ -283,14 +261,14 @@ namespace llvm { /// for more info. /// @param TemplateParms Template type parameters. /// @param UniqueIdentifier A unique identifier for the class. - DICompositeType createClassType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - DIType DerivedFrom, DIArray Elements, - DIType VTableHolder = DIType(), - MDNode *TemplateParms = nullptr, - StringRef UniqueIdentifier = StringRef()); + DICompositeType *createClassType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType *DerivedFrom, DINodeArray Elements, + DIType *VTableHolder = nullptr, + MDNode *TemplateParms = nullptr, + StringRef UniqueIdentifier = ""); /// createStructType - Create debugging information entry for a struct. /// @param Scope Scope in which this struct is defined. @@ -303,13 +281,11 @@ namespace llvm { /// @param Elements Struct elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. /// @param UniqueIdentifier A unique identifier for the struct. - DICompositeType createStructType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - unsigned Flags, DIType DerivedFrom, - DIArray Elements, unsigned RunTimeLang = 0, - DIType VTableHolder = DIType(), - StringRef UniqueIdentifier = StringRef()); + DICompositeType *createStructType( + DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, + DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang = 0, + DIType *VTableHolder = nullptr, StringRef UniqueIdentifier = ""); /// createUnionType - Create debugging information entry for an union. /// @param Scope Scope in which this union is defined. @@ -322,24 +298,20 @@ namespace llvm { /// @param Elements Union elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. /// @param UniqueIdentifier A unique identifier for the union. - DICompositeType createUnionType( - DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, - DIArray Elements, unsigned RunTimeLang = 0, - StringRef UniqueIdentifier = StringRef()); + DICompositeType *createUnionType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + unsigned Flags, DINodeArray Elements, + unsigned RunTimeLang = 0, + StringRef UniqueIdentifier = ""); /// 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 = nullptr, unsigned LineNo = 0, - unsigned ColumnNo = 0); + DITemplateTypeParameter * + createTemplateTypeParameter(DIScope *Scope, StringRef Name, DIType *Ty); /// createTemplateValueParameter - Create debugging information for template /// value parameter. @@ -347,56 +319,46 @@ namespace llvm { /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val 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, - Constant *Val, MDNode *File = nullptr, - unsigned LineNo = 0, unsigned ColumnNo = 0); + DITemplateValueParameter *createTemplateValueParameter(DIScope *Scope, + StringRef Name, + DIType *Ty, + Constant *Val); /// \brief Create debugging information for a template template parameter. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val The fully qualified name of the template. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. - DITemplateValueParameter - createTemplateTemplateParameter(DIDescriptor Scope, StringRef Name, - DIType Ty, StringRef Val, - MDNode *File = nullptr, unsigned LineNo = 0, - unsigned ColumnNo = 0); + DITemplateValueParameter *createTemplateTemplateParameter(DIScope *Scope, + StringRef Name, + DIType *Ty, + StringRef Val); /// \brief Create debugging information for a template parameter pack. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val An array of types in the pack. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. - DITemplateValueParameter - createTemplateParameterPack(DIDescriptor Scope, StringRef Name, - DIType Ty, DIArray Val, MDNode *File = nullptr, - unsigned LineNo = 0, unsigned ColumnNo = 0); + DITemplateValueParameter *createTemplateParameterPack(DIScope *Scope, + StringRef Name, + DIType *Ty, + DINodeArray Val); /// createArrayType - Create debugging information entry for an array. /// @param Size Array size. /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DICompositeType createArrayType(uint64_t Size, uint64_t AlignInBits, - DIType Ty, DIArray Subscripts); + DICompositeType *createArrayType(uint64_t Size, uint64_t AlignInBits, + DIType *Ty, DINodeArray Subscripts); /// createVectorType - Create debugging information entry for a vector type. /// @param Size Array size. /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DICompositeType createVectorType(uint64_t Size, uint64_t AlignInBits, - DIType Ty, DIArray Subscripts); + DICompositeType *createVectorType(uint64_t Size, uint64_t AlignInBits, + DIType *Ty, DINodeArray Subscripts); /// createEnumerationType - Create debugging information entry for an /// enumeration. @@ -409,10 +371,10 @@ namespace llvm { /// @param Elements Enumeration elements. /// @param UnderlyingType Underlying type of a C++11/ObjC fixed enum. /// @param UniqueIdentifier A unique identifier for the enum. - DICompositeType createEnumerationType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, uint64_t SizeInBits, - uint64_t AlignInBits, DIArray Elements, DIType UnderlyingType, - StringRef UniqueIdentifier = StringRef()); + DICompositeType *createEnumerationType( + DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, DINodeArray Elements, + DIType *UnderlyingType, StringRef UniqueIdentifier = ""); /// createSubroutineType - Create subroutine type. /// @param File File in which this subroutine is defined. @@ -420,49 +382,49 @@ namespace llvm { /// includes return type at 0th index. /// @param Flags E.g.: LValueReference. /// These flags are used to emit dwarf attributes. - DISubroutineType createSubroutineType(DIFile File, - DITypeArray ParameterTypes, - unsigned Flags = 0); + DISubroutineType *createSubroutineType(DIFile *File, + DITypeRefArray ParameterTypes, + unsigned Flags = 0); - /// createArtificialType - Create a new DIType with "artificial" flag set. - DIType createArtificialType(DIType Ty); + /// createArtificialType - Create a new DIType* with "artificial" flag set. + DIType *createArtificialType(DIType *Ty); - /// createObjectPointerType - Create a new DIType with the "object pointer" + /// createObjectPointerType - Create a new DIType* with the "object pointer" /// flag set. - DIType createObjectPointerType(DIType Ty); + DIType *createObjectPointerType(DIType *Ty); /// \brief Create a permanent forward-declared type. - DICompositeType createForwardDecl(unsigned Tag, StringRef Name, - DIDescriptor Scope, DIFile F, - unsigned Line, unsigned RuntimeLang = 0, - uint64_t SizeInBits = 0, - uint64_t AlignInBits = 0, - StringRef UniqueIdentifier = StringRef()); + DICompositeType *createForwardDecl(unsigned Tag, StringRef Name, + DIScope *Scope, DIFile *F, unsigned Line, + unsigned RuntimeLang = 0, + uint64_t SizeInBits = 0, + uint64_t AlignInBits = 0, + StringRef UniqueIdentifier = ""); /// \brief Create a temporary forward-declared type. - DICompositeType createReplaceableForwardDecl( - unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, - unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, - uint64_t AlignInBits = 0, StringRef UniqueIdentifier = StringRef()); + DICompositeType *createReplaceableCompositeType( + unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line, + unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, + uint64_t AlignInBits = 0, unsigned Flags = DINode::FlagFwdDecl, + StringRef UniqueIdentifier = ""); - /// retainType - Retain DIType in a module even if it is not referenced + /// retainType - Retain DIType* in a module even if it is not referenced /// through debug info anchors. - void retainType(DIType T); + void retainType(DIType *T); /// createUnspecifiedParameter - Create unspecified parameter type /// for a subroutine type. - DIBasicType createUnspecifiedParameter(); + DIBasicType *createUnspecifiedParameter(); - /// getOrCreateArray - Get a DIArray, create one if required. - DIArray getOrCreateArray(ArrayRef<Metadata *> Elements); + /// getOrCreateArray - Get a DINodeArray, create one if required. + DINodeArray getOrCreateArray(ArrayRef<Metadata *> Elements); - /// getOrCreateTypeArray - Get a DITypeArray, create one if required. - DITypeArray getOrCreateTypeArray(ArrayRef<Metadata *> Elements); + /// getOrCreateTypeArray - Get a DITypeRefArray, create one if required. + DITypeRefArray getOrCreateTypeArray(ArrayRef<Metadata *> Elements); /// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. - DISubrange getOrCreateSubrange(int64_t Lo, int64_t Count); - + DISubrange *getOrCreateSubrange(int64_t Lo, int64_t Count); /// createGlobalVariable - Create a new descriptor for the specified /// variable. @@ -476,19 +438,19 @@ namespace llvm { /// externally visible or not. /// @param Val llvm::Value of the variable. /// @param Decl Reference to the corresponding declaration. - DIGlobalVariable createGlobalVariable(DIDescriptor Context, StringRef Name, - StringRef LinkageName, DIFile File, - unsigned LineNo, DITypeRef Ty, - bool isLocalToUnit, - llvm::Constant *Val, - MDNode *Decl = nullptr); + DIGlobalVariable *createGlobalVariable(DIScope *Context, StringRef Name, + StringRef LinkageName, DIFile *File, + unsigned LineNo, DIType *Ty, + bool isLocalToUnit, + llvm::Constant *Val, + MDNode *Decl = nullptr); /// createTempGlobalVariableFwdDecl - Identical to createGlobalVariable /// except that the resulting DbgNode is temporary and meant to be RAUWed. - DIGlobalVariable createTempGlobalVariableFwdDecl( - DIDescriptor Context, StringRef Name, StringRef LinkageName, - DIFile File, unsigned LineNo, DITypeRef Ty, bool isLocalToUnit, - llvm::Constant *Val, MDNode *Decl = nullptr); + DIGlobalVariable *createTempGlobalVariableFwdDecl( + DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, + unsigned LineNo, DIType *Ty, bool isLocalToUnit, llvm::Constant *Val, + MDNode *Decl = nullptr); /// createLocalVariable - Create a new descriptor for the specified /// local variable. @@ -504,28 +466,29 @@ namespace llvm { /// @param Flags Flags, e.g. artificial variable. /// @param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. - DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope, - StringRef Name, - DIFile File, unsigned LineNo, - DITypeRef Ty, bool AlwaysPreserve = false, - unsigned Flags = 0, - unsigned ArgNo = 0); + DILocalVariable *createLocalVariable(unsigned Tag, DIScope *Scope, + StringRef Name, DIFile *File, + unsigned LineNo, DIType *Ty, + bool AlwaysPreserve = false, + unsigned Flags = 0, + unsigned ArgNo = 0); /// createExpression - Create a new descriptor for the specified /// variable which has a complex address expression for its address. /// @param Addr An array of complex address operations. - DIExpression createExpression(ArrayRef<int64_t> Addr = None); + DIExpression *createExpression(ArrayRef<uint64_t> Addr = None); + DIExpression *createExpression(ArrayRef<int64_t> Addr); - /// createPieceExpression - Create a descriptor to describe one part + /// createBitPieceExpression - Create a descriptor to describe one part /// of aggregate variable that is fragmented across multiple Values. /// - /// @param OffsetInBytes Offset of the piece in bytes. - /// @param SizeInBytes Size of the piece in bytes. - DIExpression createPieceExpression(unsigned OffsetInBytes, - unsigned SizeInBytes); + /// @param OffsetInBits Offset of the piece in bits. + /// @param SizeInBits Size of the piece in bits. + DIExpression *createBitPieceExpression(unsigned OffsetInBits, + unsigned SizeInBits); /// createFunction - Create a new descriptor for the specified subprogram. - /// See comments in DISubprogram for descriptions of these fields. + /// See comments in DISubprogram* for descriptions of these fields. /// @param Scope Function scope. /// @param Name Function name. /// @param LinkageName Mangled function name. @@ -540,49 +503,35 @@ namespace llvm { /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. /// @param TParam Function template parameters. - DISubprogram createFunction(DIDescriptor Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned ScopeLine, - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr, - MDNode *Decl = nullptr); + DISubprogram * + createFunction(DIScope *Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned LineNo, DISubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, + unsigned Flags = 0, bool isOptimized = false, + Function *Fn = nullptr, MDNode *TParam = nullptr, + MDNode *Decl = nullptr); /// createTempFunctionFwdDecl - Identical to createFunction, /// except that the resulting DbgNode is meant to be RAUWed. - DISubprogram createTempFunctionFwdDecl(DIDescriptor Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned ScopeLine, - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr, - MDNode *Decl = nullptr); - + DISubprogram *createTempFunctionFwdDecl( + DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, + unsigned LineNo, DISubroutineType *Ty, bool isLocalToUnit, + bool isDefinition, unsigned ScopeLine, unsigned Flags = 0, + bool isOptimized = false, Function *Fn = nullptr, + MDNode *TParam = nullptr, MDNode *Decl = nullptr); /// FIXME: this is added for dragonegg. Once we update dragonegg /// to call resolve function, this will be removed. - DISubprogram createFunction(DIScopeRef Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned ScopeLine, - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr, - MDNode *Decl = nullptr); + DISubprogram * + createFunction(DIScopeRef Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned LineNo, DISubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, + unsigned Flags = 0, bool isOptimized = false, + Function *Fn = nullptr, MDNode *TParam = nullptr, + MDNode *Decl = nullptr); /// createMethod - Create a new descriptor for the specified C++ method. - /// See comments in DISubprogram for descriptions of these fields. + /// See comments in DISubprogram* for descriptions of these fields. /// @param Scope Function scope. /// @param Name Function name. /// @param LinkageName Mangled function name. @@ -600,17 +549,13 @@ namespace llvm { /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. /// @param TParam Function template parameters. - DISubprogram createMethod(DIDescriptor Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned Virtuality = 0, unsigned VTableIndex = 0, - DIType VTableHolder = DIType(), - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr); + DISubprogram * + createMethod(DIScope *Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned LineNo, DISubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, unsigned Virtuality = 0, + unsigned VTableIndex = 0, DIType *VTableHolder = nullptr, + unsigned Flags = 0, bool isOptimized = false, + Function *Fn = nullptr, MDNode *TParam = nullptr); /// createNameSpace - This creates new descriptor for a namespace /// with the specified parent scope. @@ -618,9 +563,8 @@ namespace llvm { /// @param Name Name of this namespace /// @param File Source file /// @param LineNo Line number - DINameSpace createNameSpace(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNo); - + DINamespace *createNameSpace(DIScope *Scope, StringRef Name, DIFile *File, + unsigned LineNo); /// createLexicalBlockFile - This creates a descriptor for a lexical /// block with a new file attached. This merely extends the existing @@ -628,8 +572,8 @@ namespace llvm { /// @param Scope Lexical block. /// @param File Source file. /// @param Discriminator DWARF path discriminator value. - DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, DIFile File, - unsigned Discriminator = 0); + DILexicalBlockFile *createLexicalBlockFile(DIScope *Scope, DIFile *File, + unsigned Discriminator = 0); /// createLexicalBlock - This creates a descriptor for a lexical block /// with the specified parent context. @@ -637,60 +581,63 @@ namespace llvm { /// @param File Source file. /// @param Line Line number. /// @param Col Column number. - DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File, - unsigned Line, unsigned Col); + DILexicalBlock *createLexicalBlock(DIScope *Scope, DIFile *File, + unsigned Line, unsigned Col); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into /// @param NS The namespace being imported here /// @param Line Line number - DIImportedEntity createImportedModule(DIScope Context, DINameSpace NS, - unsigned Line); + DIImportedEntity *createImportedModule(DIScope *Context, DINamespace *NS, + unsigned Line); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into /// @param NS An aliased namespace /// @param Line Line number - DIImportedEntity createImportedModule(DIScope Context, DIImportedEntity NS, - unsigned Line); + DIImportedEntity *createImportedModule(DIScope *Context, + DIImportedEntity *NS, unsigned Line); /// \brief Create a descriptor for an imported function. /// @param Context The scope this module is imported into /// @param Decl The declaration (or definition) of a function, type, or /// variable /// @param Line Line number - DIImportedEntity createImportedDeclaration(DIScope Context, DIDescriptor Decl, - unsigned Line, - StringRef Name = StringRef()); - DIImportedEntity createImportedDeclaration(DIScope Context, - DIImportedEntity NS, - unsigned Line, - StringRef Name = StringRef()); + DIImportedEntity *createImportedDeclaration(DIScope *Context, DINode *Decl, + unsigned Line, + StringRef Name = ""); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertAtEnd Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, - DIExpression Expr, BasicBlock *InsertAtEnd); + Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, + 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 Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertBefore Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, - DIExpression Expr, Instruction *InsertBefore); + Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, + 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 Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertAtEnd Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, DIExpression Expr, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, BasicBlock *InsertAtEnd); /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. @@ -698,24 +645,45 @@ namespace llvm { /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertBefore Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, DIExpression Expr, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, Instruction *InsertBefore); /// \brief Replace the vtable holder in the given composite type. /// /// If this creates a self reference, it may orphan some unresolved cycles /// in the operands of \c T, so \a DIBuilder needs to track that. - void replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder); + void replaceVTableHolder(DICompositeType *&T, + DICompositeType *VTableHolder); /// \brief Replace arrays on a composite type. /// /// If \c T is resolved, but the arrays aren't -- which can happen if \c T /// has a self-reference -- \a DIBuilder needs to track the array to /// resolve cycles. - void replaceArrays(DICompositeType &T, DIArray Elements, - DIArray TParems = DIArray()); + void replaceArrays(DICompositeType *&T, DINodeArray Elements, + DINodeArray TParems = DINodeArray()); + + /// \brief Replace a temporary node. + /// + /// Call \a MDNode::replaceAllUsesWith() on \c N, replacing it with \c + /// Replacement. + /// + /// If \c Replacement is the same as \c N.get(), instead call \a + /// MDNode::replaceWithUniqued(). In this case, the uniqued node could + /// have a different address, so we return the final address. + template <class NodeTy> + NodeTy *replaceTemporary(TempMDNode &&N, NodeTy *Replacement) { + if (N.get() == Replacement) + return cast<NodeTy>(MDNode::replaceWithUniqued(std::move(N))); + + N->replaceAllUsesWith(Replacement); + return Replacement; + } }; } // end namespace llvm diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index a9e75955ce74..3e1f9744f9e8 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -53,6 +53,11 @@ enum AlignTypeEnum { AGGREGATE_ALIGN = 'a' }; +// FIXME: Currently the DataLayout string carries a "preferred alignment" +// for types. As the DataLayout is module/global, this should likely be +// sunk down to an FTTI element that is queried rather than a global +// preference. + /// \brief Layout alignment element. /// /// Stores the alignment data associated with a given alignment type (integer, @@ -103,7 +108,14 @@ private: unsigned StackNaturalAlign; - enum ManglingModeT { MM_None, MM_ELF, MM_MachO, MM_WINCOFF, MM_Mips }; + enum ManglingModeT { + MM_None, + MM_ELF, + MM_MachO, + MM_WinCOFF, + MM_WinCOFFX86, + MM_Mips + }; ManglingModeT ManglingMode; SmallVector<unsigned char, 8> LegalIntWidths; @@ -111,6 +123,9 @@ private: /// \brief Primitive type alignment data. SmallVector<LayoutAlignElem, 16> Alignments; + /// \brief The string representation used to create this DataLayout + std::string StringRepresentation; + typedef SmallVector<PointerAlignElem, 8> PointersTy; PointersTy Pointers; @@ -180,6 +195,7 @@ public: DataLayout &operator=(const DataLayout &DL) { clear(); + StringRepresentation = DL.StringRepresentation; BigEndian = DL.isBigEndian(); StackNaturalAlign = DL.StackNaturalAlign; ManglingMode = DL.ManglingMode; @@ -204,8 +220,12 @@ public: /// \brief Returns the string representation of the DataLayout. /// /// This representation is in the same format accepted by the string - /// constructor above. - std::string getStringRepresentation() const; + /// constructor above. This should not be used to compare two DataLayout as + /// different string can represent the same layout. + std::string getStringRepresentation() const { return StringRepresentation; } + + /// \brief Test if the DataLayout was constructed from an empty string. + bool isDefault() const { return StringRepresentation.empty(); } /// \brief Returns true if the specified type is known to be a native integer /// type supported by the CPU. @@ -231,7 +251,7 @@ public: unsigned getStackAlignment() const { return StackNaturalAlign; } bool hasMicrosoftFastStdCallMangling() const { - return ManglingMode == MM_WINCOFF; + return ManglingMode == MM_WinCOFFX86; } bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; } @@ -239,7 +259,7 @@ public: const char *getLinkerPrivateGlobalPrefix() const { if (ManglingMode == MM_MachO) return "l"; - return getPrivateGlobalPrefix(); + return ""; } char getGlobalPrefix() const { @@ -247,9 +267,10 @@ public: case MM_None: case MM_ELF: case MM_Mips: + case MM_WinCOFF: return '\0'; case MM_MachO: - case MM_WINCOFF: + case MM_WinCOFFX86: return '_'; } llvm_unreachable("invalid mangling mode"); @@ -264,7 +285,8 @@ public: case MM_Mips: return "$"; case MM_MachO: - case MM_WINCOFF: + case MM_WinCOFF: + case MM_WinCOFFX86: return "L"; } llvm_unreachable("invalid mangling mode"); @@ -446,22 +468,6 @@ inline LLVMTargetDataRef wrap(const DataLayout *P) { return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout *>(P)); } -class DataLayoutPass : public ImmutablePass { - DataLayout DL; - -public: - /// This has to exist, because this is a pass, but it should never be used. - DataLayoutPass(); - ~DataLayoutPass(); - - const DataLayout &getDataLayout() const { return DL; } - - static char ID; // Pass identification, replacement for typeid - - bool doFinalization(Module &M) override; - bool doInitialization(Module &M) override; -}; - /// Used to lazily calculate structure layout information for a target machine, /// based on the DataLayout structure. class StructLayout { diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 5c85d6d52824..5429648ade2c 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -22,990 +22,30 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" -#include "llvm/IR/Metadata.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include <iterator> namespace llvm { -class BasicBlock; -class Constant; -class Function; -class GlobalVariable; class Module; -class Type; -class Value; class DbgDeclareInst; class DbgValueInst; -class Instruction; -class Metadata; -class MDNode; -class MDString; -class NamedMDNode; -class LLVMContext; -class raw_ostream; - -class DIFile; -class DISubprogram; -class DILexicalBlock; -class DILexicalBlockFile; -class DIVariable; -class DIType; -class DIScope; -class DIObjCProperty; /// \brief Maps from type identifier to the actual MDNode. -typedef DenseMap<const MDString *, MDNode *> DITypeIdentifierMap; - -class DIHeaderFieldIterator - : public std::iterator<std::input_iterator_tag, StringRef, std::ptrdiff_t, - const StringRef *, StringRef> { - StringRef Header; - StringRef Current; - -public: - DIHeaderFieldIterator() {} - DIHeaderFieldIterator(StringRef Header) - : Header(Header), Current(Header.slice(0, Header.find('\0'))) {} - StringRef operator*() const { return Current; } - const StringRef * operator->() const { return &Current; } - DIHeaderFieldIterator &operator++() { - increment(); - return *this; - } - DIHeaderFieldIterator operator++(int) { - DIHeaderFieldIterator X(*this); - increment(); - return X; - } - bool operator==(const DIHeaderFieldIterator &X) const { - return Current.data() == X.Current.data(); - } - bool operator!=(const DIHeaderFieldIterator &X) const { - return !(*this == X); - } - - StringRef getHeader() const { return Header; } - StringRef getCurrent() const { return Current; } - StringRef getPrefix() const { - if (Current.begin() == Header.begin()) - return StringRef(); - return Header.slice(0, Current.begin() - Header.begin() - 1); - } - StringRef getSuffix() const { - if (Current.end() == Header.end()) - return StringRef(); - return Header.slice(Current.end() - Header.begin() + 1, StringRef::npos); - } - -private: - void increment() { - assert(Current.data() != nullptr && "Cannot increment past the end"); - StringRef Suffix = getSuffix(); - Current = Suffix.slice(0, Suffix.find('\0')); - } -}; - -/// \brief A thin wraper around MDNode to access encoded debug info. -/// -/// This should not be stored in a container, because the underlying MDNode may -/// change in certain situations. -class DIDescriptor { - // Befriends DIRef so DIRef can befriend the protected member - // function: getFieldAs<DIRef>. - template <typename T> friend class DIRef; - -public: - /// \brief Accessibility flags. - /// - /// The three accessibility flags are mutually exclusive and rolled together - /// in the first two bits. - enum { - FlagAccessibility = 1 << 0 | 1 << 1, - FlagPrivate = 1, - FlagProtected = 2, - FlagPublic = 3, - - FlagFwdDecl = 1 << 2, - FlagAppleBlock = 1 << 3, - FlagBlockByrefStruct = 1 << 4, - FlagVirtual = 1 << 5, - FlagArtificial = 1 << 6, - FlagExplicit = 1 << 7, - FlagPrototyped = 1 << 8, - FlagObjcClassComplete = 1 << 9, - FlagObjectPointer = 1 << 10, - FlagVector = 1 << 11, - FlagStaticMember = 1 << 12, - FlagIndirectVariable = 1 << 13, - FlagLValueReference = 1 << 14, - FlagRValueReference = 1 << 15 - }; - -protected: - const MDNode *DbgNode; - - StringRef getStringField(unsigned Elt) const; - unsigned getUnsignedField(unsigned Elt) const { - return (unsigned)getUInt64Field(Elt); - } - uint64_t getUInt64Field(unsigned Elt) const; - int64_t getInt64Field(unsigned Elt) const; - DIDescriptor getDescriptorField(unsigned Elt) const; - - template <typename DescTy> DescTy getFieldAs(unsigned Elt) const { - return DescTy(getDescriptorField(Elt)); - } - - GlobalVariable *getGlobalVariableField(unsigned Elt) const; - Constant *getConstantField(unsigned Elt) const; - Function *getFunctionField(unsigned Elt) const; - void replaceFunctionField(unsigned Elt, Function *F); - -public: - explicit DIDescriptor(const MDNode *N = nullptr) : DbgNode(N) {} - - bool Verify() const; - - MDNode *get() const { return const_cast<MDNode *>(DbgNode); } - operator MDNode *() const { return get(); } - MDNode *operator->() const { return get(); } - - // An explicit operator bool so that we can do testing of DI values - // easily. - // FIXME: This operator bool isn't actually protecting anything at the - // moment due to the conversion operator above making DIDescriptor nodes - // implicitly convertable to bool. - LLVM_EXPLICIT operator bool() const { return DbgNode != nullptr; } - - bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; } - bool operator!=(DIDescriptor Other) const { return !operator==(Other); } - - StringRef getHeader() const { - return getStringField(0); - } - - size_t getNumHeaderFields() const { - return std::distance(DIHeaderFieldIterator(getHeader()), - DIHeaderFieldIterator()); - } - - StringRef getHeaderField(unsigned Index) const { - // Since callers expect an empty string for out-of-range accesses, we can't - // use std::advance() here. - for (DIHeaderFieldIterator I(getHeader()), E; I != E; ++I, --Index) - if (!Index) - return *I; - return StringRef(); - } - - template <class T> T getHeaderFieldAs(unsigned Index) const { - T Int; - if (getHeaderField(Index).getAsInteger(0, Int)) - return 0; - return Int; - } - - uint16_t getTag() const { return getHeaderFieldAs<uint16_t>(0); } - - bool isDerivedType() const; - bool isCompositeType() const; - bool isSubroutineType() const; - bool isBasicType() const; - bool isVariable() const; - bool isSubprogram() const; - bool isGlobalVariable() const; - bool isScope() const; - bool isFile() const; - bool isCompileUnit() const; - bool isNameSpace() const; - bool isLexicalBlockFile() const; - bool isLexicalBlock() const; - bool isSubrange() const; - bool isEnumerator() const; - bool isType() const; - bool isTemplateTypeParameter() const; - bool isTemplateValueParameter() const; - bool isObjCProperty() const; - bool isImportedEntity() const; - bool isExpression() const; - - void print(raw_ostream &OS) const; - void dump() const; - - /// \brief Replace all uses of debug info referenced by this descriptor. - void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D); - void replaceAllUsesWith(MDNode *D); -}; - -/// \brief This is used to represent ranges, for array bounds. -class DISubrange : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DISubrange(const MDNode *N = nullptr) : DIDescriptor(N) {} - - int64_t getLo() const { return getHeaderFieldAs<int64_t>(1); } - int64_t getCount() const { return getHeaderFieldAs<int64_t>(2); } - bool Verify() const; -}; - -/// \brief This descriptor holds an array of nodes with type T. -template <typename T> class DITypedArray : public DIDescriptor { -public: - explicit DITypedArray(const MDNode *N = nullptr) : DIDescriptor(N) {} - unsigned getNumElements() const { - return DbgNode ? DbgNode->getNumOperands() : 0; - } - T getElement(unsigned Idx) const { - return getFieldAs<T>(Idx); - } -}; - -typedef DITypedArray<DIDescriptor> DIArray; - -/// \brief A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). -/// -/// FIXME: it seems strange that this doesn't have either a reference to the -/// type/precision or a file/line pair for location info. -class DIEnumerator : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIEnumerator(const MDNode *N = nullptr) : DIDescriptor(N) {} - - StringRef getName() const { return getHeaderField(1); } - int64_t getEnumValue() const { return getHeaderFieldAs<int64_t>(2); } - bool Verify() const; -}; - -template <typename T> class DIRef; -typedef DIRef<DIScope> DIScopeRef; -typedef DIRef<DIType> DITypeRef; -typedef DITypedArray<DITypeRef> DITypeArray; - -/// \brief A base class for various scopes. -/// -/// Although, implementation-wise, DIScope is the parent class of most -/// other DIxxx classes, including DIType and its descendants, most of -/// DIScope's descendants are not a substitutable subtype of -/// DIScope. The DIDescriptor::isScope() method only is true for -/// DIScopes that are scopes in the strict lexical scope sense -/// (DICompileUnit, DISubprogram, etc.), but not for, e.g., a DIType. -class DIScope : public DIDescriptor { -protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIScope(const MDNode *N = nullptr) : DIDescriptor(N) {} - - /// \brief Get the parent scope. - /// - /// Gets the parent scope for this scope node or returns a default - /// constructed scope. - DIScopeRef getContext() const; - /// \brief Get the scope name. - /// - /// If the scope node has a name, return that, else return an empty string. - StringRef getName() const; - StringRef getFilename() const; - StringRef getDirectory() const; - - /// \brief Generate a reference to this DIScope. - /// - /// Uses the type identifier instead of the actual MDNode if possible, to - /// help type uniquing. - DIScopeRef getRef() const; -}; - -/// \brief Represents reference to a DIDescriptor. -/// -/// Abstracts over direct and identifier-based metadata references. -template <typename T> class DIRef { - template <typename DescTy> - friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const; - friend DIScopeRef DIScope::getContext() const; - friend DIScopeRef DIScope::getRef() const; - friend class DIType; - - /// \brief Val can be either a MDNode or a MDString. - /// - /// In the latter, MDString specifies the type identifier. - const Metadata *Val; - explicit DIRef(const Metadata *V); - -public: - T resolve(const DITypeIdentifierMap &Map) const; - StringRef getName() const; - operator Metadata *() const { return const_cast<Metadata *>(Val); } -}; - -template <typename T> -T DIRef<T>::resolve(const DITypeIdentifierMap &Map) const { - if (!Val) - return T(); - - if (const MDNode *MD = dyn_cast<MDNode>(Val)) - return T(MD); - - const MDString *MS = cast<MDString>(Val); - // Find the corresponding MDNode. - DITypeIdentifierMap::const_iterator Iter = Map.find(MS); - assert(Iter != Map.end() && "Identifier not in the type map?"); - assert(DIDescriptor(Iter->second).isType() && - "MDNode in DITypeIdentifierMap should be a DIType."); - return T(Iter->second); -} - -template <typename T> StringRef DIRef<T>::getName() const { - if (!Val) - return StringRef(); - - if (const MDNode *MD = dyn_cast<MDNode>(Val)) - return T(MD).getName(); - - const MDString *MS = cast<MDString>(Val); - return MS->getString(); -} - -/// \brief Handle fields that are references to DIScopes. -template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const; -/// \brief Specialize DIRef constructor for DIScopeRef. -template <> DIRef<DIScope>::DIRef(const Metadata *V); - -/// \brief Handle fields that are references to DITypes. -template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const; -/// \brief Specialize DIRef constructor for DITypeRef. -template <> DIRef<DIType>::DIRef(const Metadata *V); - -/// \briefThis is a wrapper for a type. -/// -/// FIXME: Types should be factored much better so that CV qualifiers and -/// others do not require a huge and empty descriptor full of zeros. -class DIType : public DIScope { -protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIType(const MDNode *N = nullptr) : DIScope(N) {} - operator DITypeRef () const { - assert(isType() && - "constructing DITypeRef from an MDNode that is not a type"); - return DITypeRef(&*getRef()); - } - - bool Verify() const; - - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } - StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { - return getHeaderFieldAs<unsigned>(2); - } - uint64_t getSizeInBits() const { - return getHeaderFieldAs<unsigned>(3); - } - uint64_t getAlignInBits() const { - return getHeaderFieldAs<unsigned>(4); - } - // FIXME: Offset is only used for DW_TAG_member nodes. Making every type - // carry this is just plain insane. - uint64_t getOffsetInBits() const { - return getHeaderFieldAs<unsigned>(5); - } - unsigned getFlags() const { return getHeaderFieldAs<unsigned>(6); } - bool isPrivate() const { - return (getFlags() & FlagAccessibility) == FlagPrivate; - } - bool isProtected() const { - return (getFlags() & FlagAccessibility) == FlagProtected; - } - bool isPublic() const { - return (getFlags() & FlagAccessibility) == FlagPublic; - } - bool isForwardDecl() const { return (getFlags() & FlagFwdDecl) != 0; } - bool isAppleBlockExtension() const { - return (getFlags() & FlagAppleBlock) != 0; - } - bool isBlockByrefStruct() const { - return (getFlags() & FlagBlockByrefStruct) != 0; - } - bool isVirtual() const { return (getFlags() & FlagVirtual) != 0; } - bool isArtificial() const { return (getFlags() & FlagArtificial) != 0; } - bool isObjectPointer() const { return (getFlags() & FlagObjectPointer) != 0; } - bool isObjcClassComplete() const { - return (getFlags() & FlagObjcClassComplete) != 0; - } - bool isVector() const { return (getFlags() & FlagVector) != 0; } - bool isStaticMember() const { return (getFlags() & FlagStaticMember) != 0; } - bool isLValueReference() const { - return (getFlags() & FlagLValueReference) != 0; - } - bool isRValueReference() const { - return (getFlags() & FlagRValueReference) != 0; - } - bool isValid() const { return DbgNode && isType(); } -}; - -/// \brief A basic type, like 'int' or 'float'. -class DIBasicType : public DIType { -public: - explicit DIBasicType(const MDNode *N = nullptr) : DIType(N) {} - - unsigned getEncoding() const { return getHeaderFieldAs<unsigned>(7); } - - bool Verify() const; -}; - -/// \brief A simple derived type -/// -/// Like a const qualified type, a typedef, a pointer or reference, et cetera. -/// Or, a data member of a class/struct/union. -class DIDerivedType : public DIType { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {} - - DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(3); } - - /// \brief Return property node, if this ivar is associated with one. - MDNode *getObjCProperty() const; - - DITypeRef getClassType() const { - assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return getFieldAs<DITypeRef>(4); - } - - Constant *getConstant() const { - assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); - return getConstantField(4); - } - - bool Verify() const; -}; - -/// \brief Types that refer to multiple other types. -/// -/// This descriptor holds a type that can refer to multiple other types, like a -/// function or struct. -/// -/// DICompositeType is derived from DIDerivedType because some -/// composite types (such as enums) can be derived from basic types -// FIXME: Make this derive from DIType directly & just store the -// base type in a single DIType field. -class DICompositeType : public DIDerivedType { - friend class DIBuilder; - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - - /// \brief Set the array of member DITypes. - void setArraysHelper(MDNode *Elements, MDNode *TParams); - -public: - explicit DICompositeType(const MDNode *N = nullptr) : DIDerivedType(N) {} - - DIArray getElements() const { - assert(!isSubroutineType() && "no elements for DISubroutineType"); - return getFieldAs<DIArray>(4); - } - -private: - template <typename T> - void setArrays(DITypedArray<T> Elements, DIArray TParams = DIArray()) { - assert((!TParams || DbgNode->getNumOperands() == 8) && - "If you're setting the template parameters this should include a slot " - "for that!"); - setArraysHelper(Elements, TParams); - } - -public: - unsigned getRunTimeLang() const { - return getHeaderFieldAs<unsigned>(7); - } - DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(5); } - -private: - /// \brief Set the containing type. - void setContainingType(DICompositeType ContainingType); - -public: - DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); } - MDString *getIdentifier() const; - - bool Verify() const; -}; - -class DISubroutineType : public DICompositeType { -public: - explicit DISubroutineType(const MDNode *N = nullptr) : DICompositeType(N) {} - DITypedArray<DITypeRef> getTypeArray() const { - return getFieldAs<DITypedArray<DITypeRef>>(4); - } -}; - -/// \brief This is a wrapper for a file. -class DIFile : public DIScope { - friend class DIDescriptor; - -public: - explicit DIFile(const MDNode *N = nullptr) : DIScope(N) {} - - /// \brief Retrieve the MDNode for the directory/file pair. - MDNode *getFileNode() const; - bool Verify() const; -}; - -/// \brief A wrapper for a compile unit. -class DICompileUnit : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DICompileUnit(const MDNode *N = nullptr) : DIScope(N) {} - - dwarf::SourceLanguage getLanguage() const { - return static_cast<dwarf::SourceLanguage>(getHeaderFieldAs<unsigned>(1)); - } - StringRef getProducer() const { return getHeaderField(2); } - - bool isOptimized() const { return getHeaderFieldAs<bool>(3) != 0; } - StringRef getFlags() const { return getHeaderField(4); } - unsigned getRunTimeVersion() const { return getHeaderFieldAs<unsigned>(5); } - - DIArray getEnumTypes() const; - DIArray getRetainedTypes() const; - DIArray getSubprograms() const; - DIArray getGlobalVariables() const; - DIArray getImportedEntities() const; - - void replaceSubprograms(DIArray Subprograms); - void replaceGlobalVariables(DIArray GlobalVariables); - - StringRef getSplitDebugFilename() const { return getHeaderField(6); } - unsigned getEmissionKind() const { return getHeaderFieldAs<unsigned>(7); } - - bool Verify() const; -}; - -/// \brief This is a wrapper for a subprogram (e.g. a function). -class DISubprogram : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DISubprogram(const MDNode *N = nullptr) : DIScope(N) {} - - StringRef getName() const { return getHeaderField(1); } - StringRef getDisplayName() const { return getHeaderField(2); } - StringRef getLinkageName() const { return getHeaderField(3); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); } - - /// \brief Check if this is local (like 'static' in C). - unsigned isLocalToUnit() const { return getHeaderFieldAs<unsigned>(5); } - unsigned isDefinition() const { return getHeaderFieldAs<unsigned>(6); } - - unsigned getVirtuality() const { return getHeaderFieldAs<unsigned>(7); } - unsigned getVirtualIndex() const { return getHeaderFieldAs<unsigned>(8); } - - unsigned getFlags() const { return getHeaderFieldAs<unsigned>(9); } - - unsigned isOptimized() const { return getHeaderFieldAs<bool>(10); } - - /// \brief Get the beginning of the scope of the function (not the name). - unsigned getScopeLineNumber() const { return getHeaderFieldAs<unsigned>(11); } - - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } - DISubroutineType getType() const { return getFieldAs<DISubroutineType>(3); } - - DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(4); } - - bool Verify() const; - - /// \brief Check if this provides debugging information for the function F. - bool describes(const Function *F); - - Function *getFunction() const { return getFunctionField(5); } - void replaceFunction(Function *F) { replaceFunctionField(5, F); } - DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); } - DISubprogram getFunctionDeclaration() const { - return getFieldAs<DISubprogram>(7); - } - MDNode *getVariablesNodes() const; - DIArray getVariables() const; - - unsigned isArtificial() const { return (getFlags() & FlagArtificial) != 0; } - /// \brief Check for the "private" access specifier. - bool isPrivate() const { - return (getFlags() & FlagAccessibility) == FlagPrivate; - } - /// \brief Check for the "protected" access specifier. - bool isProtected() const { - return (getFlags() & FlagAccessibility) == FlagProtected; - } - /// \brief Check for the "public" access specifier. - bool isPublic() const { - return (getFlags() & FlagAccessibility) == FlagPublic; - } - /// \brief Check for "explicit". - bool isExplicit() const { return (getFlags() & FlagExplicit) != 0; } - /// \brief Check if this is prototyped. - bool isPrototyped() const { return (getFlags() & FlagPrototyped) != 0; } - - /// \brief Check if this is reference-qualified. - /// - /// Return true if this subprogram is a C++11 reference-qualified non-static - /// member function (void foo() &). - unsigned isLValueReference() const { - return (getFlags() & FlagLValueReference) != 0; - } - - /// \brief Check if this is rvalue-reference-qualified. - /// - /// Return true if this subprogram is a C++11 rvalue-reference-qualified - /// non-static member function (void foo() &&). - unsigned isRValueReference() const { - return (getFlags() & FlagRValueReference) != 0; - } - -}; - -/// \brief This is a wrapper for a lexical block. -class DILexicalBlock : public DIScope { -public: - explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(2); } - unsigned getLineNumber() const { - return getHeaderFieldAs<unsigned>(1); - } - unsigned getColumnNumber() const { - return getHeaderFieldAs<unsigned>(2); - } - bool Verify() const; -}; - -/// \brief This is a wrapper for a lexical block with a filename change. -class DILexicalBlockFile : public DIScope { -public: - explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {} - DIScope getContext() const { - if (getScope().isSubprogram()) - return getScope(); - return getScope().getContext(); - } - unsigned getLineNumber() const { return getScope().getLineNumber(); } - unsigned getColumnNumber() const { return getScope().getColumnNumber(); } - DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(2); } - unsigned getDiscriminator() const { return getHeaderFieldAs<unsigned>(1); } - bool Verify() const; -}; - -/// \brief A wrapper for a C++ style name space. -class DINameSpace : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DINameSpace(const MDNode *N = nullptr) : DIScope(N) {} - StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - DIScope getContext() const { return getFieldAs<DIScope>(2); } - bool Verify() const; -}; - -/// \brief This is a wrapper for template type parameter. -class DITemplateTypeParameter : public DIDescriptor { -public: - explicit DITemplateTypeParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} - - StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); } - - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(2); } - StringRef getFilename() const { return getFieldAs<DIFile>(3).getFilename(); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(3).getDirectory(); - } - bool Verify() const; -}; - -/// \brief This is a wrapper for template value parameter. -class DITemplateValueParameter : public DIDescriptor { -public: - explicit DITemplateValueParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} - - StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); } - - DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(2); } - Metadata *getValue() const; - StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(4).getDirectory(); - } - bool Verify() const; -}; - -/// \brief This is a wrapper for a global variable. -class DIGlobalVariable : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIGlobalVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} - - StringRef getName() const { return getHeaderField(1); } - StringRef getDisplayName() const { return getHeaderField(2); } - StringRef getLinkageName() const { return getHeaderField(3); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); } - unsigned isLocalToUnit() const { return getHeaderFieldAs<bool>(5); } - unsigned isDefinition() const { return getHeaderFieldAs<bool>(6); } - - DIScope getContext() const { return getFieldAs<DIScope>(1); } - StringRef getFilename() const { return getFieldAs<DIFile>(2).getFilename(); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(2).getDirectory(); - } - DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } - - GlobalVariable *getGlobal() const { return getGlobalVariableField(4); } - Constant *getConstant() const { return getConstantField(4); } - DIDerivedType getStaticDataMemberDeclaration() const { - return getFieldAs<DIDerivedType>(5); - } - - bool Verify() const; -}; - -/// \brief This is a wrapper for a variable (e.g. parameter, local, global etc). -class DIVariable : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} - - StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { - // FIXME: Line number and arg number shouldn't be merged together like this. - return (getHeaderFieldAs<unsigned>(2) << 8) >> 8; - } - unsigned getArgNumber() const { return getHeaderFieldAs<unsigned>(2) >> 24; } - - DIScope getContext() const { return getFieldAs<DIScope>(1); } - DIFile getFile() const { return getFieldAs<DIFile>(2); } - DITypeRef getType() const { return getFieldAs<DITypeRef>(3); } - - /// \brief Return true if this variable is marked as "artificial". - bool isArtificial() const { - return (getHeaderFieldAs<unsigned>(3) & FlagArtificial) != 0; - } - - bool isObjectPointer() const { - return (getHeaderFieldAs<unsigned>(3) & FlagObjectPointer) != 0; - } - - /// \brief Return true if this variable is represented as a pointer. - bool isIndirect() const { - return (getHeaderFieldAs<unsigned>(3) & FlagIndirectVariable) != 0; - } - - /// \brief If this variable is inlined then return inline location. - MDNode *getInlinedAt() const; - - bool Verify() const; - - /// \brief Check if this is a "__block" variable (Apple Blocks). - bool isBlockByrefVariable(const DITypeIdentifierMap &Map) const { - return (getType().resolve(Map)).isBlockByrefStruct(); - } - - /// \brief Check if this is an inlined function argument. - bool isInlinedFnArgument(const Function *CurFn); - - /// \brief Return the size reported by the variable's type. - unsigned getSizeInBits(const DITypeIdentifierMap &Map); - - void printExtendedName(raw_ostream &OS) const; -}; - -/// \brief A complex location expression. -class DIExpression : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIExpression(const MDNode *N = nullptr) : DIDescriptor(N) {} - - bool Verify() const; - - /// \brief Return the number of elements in the complex expression. - unsigned getNumElements() const { - if (!DbgNode) - return 0; - unsigned N = getNumHeaderFields(); - assert(N > 0 && "missing tag"); - return N - 1; - } - - /// \brief return the Idx'th complex address element. - uint64_t getElement(unsigned Idx) const; - - /// \brief Return whether this is a piece of an aggregate variable. - bool isVariablePiece() const; - /// \brief Return the offset of this piece in bytes. - uint64_t getPieceOffset() const; - /// \brief Return the size of this piece in bytes. - uint64_t getPieceSize() const; -}; - -/// \brief This object holds location information. -/// -/// This object is not associated with any DWARF tag. -class DILocation : public DIDescriptor { -public: - explicit DILocation(const MDNode *N) : DIDescriptor(N) {} - - unsigned getLineNumber() const { - if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) - return L->getLine(); - return 0; - } - unsigned getColumnNumber() const { - if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) - return L->getColumn(); - return 0; - } - DIScope getScope() const { - if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) - return DIScope(dyn_cast_or_null<MDNode>(L->getScope())); - return DIScope(nullptr); - } - DILocation getOrigLocation() const { - if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode)) - return DILocation(dyn_cast_or_null<MDNode>(L->getInlinedAt())); - return DILocation(nullptr); - } - StringRef getFilename() const { return getScope().getFilename(); } - StringRef getDirectory() const { return getScope().getDirectory(); } - bool Verify() const; - bool atSameLineAs(const DILocation &Other) const { - return (getLineNumber() == Other.getLineNumber() && - getFilename() == Other.getFilename()); - } - /// \brief Get the DWAF discriminator. - /// - /// DWARF discriminators are used to distinguish identical file locations for - /// instructions that are on different basic blocks. If two instructions are - /// inside the same lexical block and are in different basic blocks, we - /// create a new lexical block with identical location as the original but - /// with a different discriminator value - /// (lib/Transforms/Util/AddDiscriminators.cpp for details). - unsigned getDiscriminator() const { - // Since discriminators are associated with lexical blocks, make - // sure this location is a lexical block before retrieving its - // value. - return getScope().isLexicalBlockFile() - ? DILexicalBlockFile( - cast<MDNode>(cast<MDLocation>(DbgNode)->getScope())) - .getDiscriminator() - : 0; - } - - /// \brief Generate a new discriminator value for this location. - unsigned computeNewDiscriminator(LLVMContext &Ctx); - - /// \brief Return a copy of this location with a different scope. - DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlockFile NewScope); -}; - -class DIObjCProperty : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {} - - StringRef getObjCPropertyName() const { return getHeaderField(1); } - DIFile getFile() const { return getFieldAs<DIFile>(1); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); } - - StringRef getObjCPropertyGetterName() const { return getHeaderField(3); } - StringRef getObjCPropertySetterName() const { return getHeaderField(4); } - unsigned getAttributes() const { return getHeaderFieldAs<unsigned>(5); } - bool isReadOnlyObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readonly) != 0; - } - bool isReadWriteObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; - } - bool isAssignObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_assign) != 0; - } - bool isRetainObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_retain) != 0; - } - bool isCopyObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_copy) != 0; - } - bool isNonAtomicObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; - } - - /// \brief Get the type. - /// - /// \note Objective-C doesn't have an ODR, so there is no benefit in storing - /// the type as a DITypeRef here. - DIType getType() const { return getFieldAs<DIType>(2); } - - bool Verify() const; -}; - -/// \brief An imported module (C++ using directive or similar). -class DIImportedEntity : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - -public: - explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(1); } - DIScopeRef getEntity() const { return getFieldAs<DIScopeRef>(2); } - unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); } - StringRef getName() const { return getHeaderField(2); } - bool Verify() const; -}; +typedef DenseMap<const MDString *, DIType *> DITypeIdentifierMap; /// \brief Find subprogram that is enclosing this scope. -DISubprogram getDISubprogram(const MDNode *Scope); +DISubprogram *getDISubprogram(const MDNode *Scope); /// \brief Find debug info for a given function. -/// \returns a valid DISubprogram, if found. Otherwise, it returns an empty -/// DISubprogram. -DISubprogram getDISubprogram(const Function *F); - -/// \brief Find underlying composite type. -DICompositeType getDICompositeType(DIType T); - -/// \brief Create a new inlined variable based on current variable. /// -/// @param DV Current Variable. -/// @param InlinedScope Location at current variable is inlined. -DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope, - LLVMContext &VMContext); +/// \returns a valid subprogram, if found. Otherwise, return \c nullptr. +DISubprogram *getDISubprogram(const Function *F); -/// \brief Remove inlined scope from the variable. -DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); +/// \brief Find underlying composite type. +DICompositeTypeBase *getDICompositeType(DIType *T); /// \brief Generate map by visiting all retained types. DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); @@ -1016,6 +56,7 @@ DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); /// metadata for debugging. We also remove debug locations for instructions. /// Return true if module is modified. bool StripDebugInfo(Module &M); +bool stripDebugInfo(Function &F); /// \brief Return Debug Info Metadata Version by checking module flags. unsigned getDebugMetadataVersionFromModule(const Module &M); @@ -1039,8 +80,8 @@ public: void processDeclare(const Module &M, const DbgDeclareInst *DDI); /// \brief Process DbgValueInst. void processValue(const Module &M, const DbgValueInst *DVI); - /// \brief Process DILocation. - void processLocation(const Module &M, DILocation Loc); + /// \brief Process debug info location. + void processLocation(const Module &M, const DILocation *Loc); /// \brief Clear all lists. void reset(); @@ -1048,21 +89,23 @@ public: private: void InitializeTypeMap(const Module &M); - void processType(DIType DT); - void processSubprogram(DISubprogram SP); - void processScope(DIScope Scope); - bool addCompileUnit(DICompileUnit CU); - bool addGlobalVariable(DIGlobalVariable DIG); - bool addSubprogram(DISubprogram SP); - bool addType(DIType DT); - bool addScope(DIScope Scope); + void processType(DIType *DT); + void processSubprogram(DISubprogram *SP); + void processScope(DIScope *Scope); + bool addCompileUnit(DICompileUnit *CU); + bool addGlobalVariable(DIGlobalVariable *DIG); + bool addSubprogram(DISubprogram *SP); + bool addType(DIType *DT); + bool addScope(DIScope *Scope); public: - typedef SmallVectorImpl<DICompileUnit>::const_iterator compile_unit_iterator; - typedef SmallVectorImpl<DISubprogram>::const_iterator subprogram_iterator; - typedef SmallVectorImpl<DIGlobalVariable>::const_iterator global_variable_iterator; - typedef SmallVectorImpl<DIType>::const_iterator type_iterator; - typedef SmallVectorImpl<DIScope>::const_iterator scope_iterator; + typedef SmallVectorImpl<DICompileUnit *>::const_iterator + compile_unit_iterator; + typedef SmallVectorImpl<DISubprogram *>::const_iterator subprogram_iterator; + typedef SmallVectorImpl<DIGlobalVariable *>::const_iterator + global_variable_iterator; + typedef SmallVectorImpl<DIType *>::const_iterator type_iterator; + typedef SmallVectorImpl<DIScope *>::const_iterator scope_iterator; iterator_range<compile_unit_iterator> compile_units() const { return iterator_range<compile_unit_iterator>(CUs.begin(), CUs.end()); @@ -1091,19 +134,19 @@ public: unsigned scope_count() const { return Scopes.size(); } private: - SmallVector<DICompileUnit, 8> CUs; - SmallVector<DISubprogram, 8> SPs; - SmallVector<DIGlobalVariable, 8> GVs; - SmallVector<DIType, 8> TYs; - SmallVector<DIScope, 8> Scopes; - SmallPtrSet<MDNode *, 64> NodesSeen; + SmallVector<DICompileUnit *, 8> CUs; + SmallVector<DISubprogram *, 8> SPs; + SmallVector<DIGlobalVariable *, 8> GVs; + SmallVector<DIType *, 8> TYs; + SmallVector<DIScope *, 8> Scopes; + SmallPtrSet<const MDNode *, 64> NodesSeen; DITypeIdentifierMap TypeIdentifierMap; /// \brief Specify if TypeIdentifierMap is initialized. bool TypeMapInitialized; }; -DenseMap<const Function *, DISubprogram> makeSubprogramMap(const Module &M); +DenseMap<const Function *, DISubprogram *> makeSubprogramMap(const Module &M); } // end namespace llvm diff --git a/include/llvm/IR/DebugInfoFlags.def b/include/llvm/IR/DebugInfoFlags.def new file mode 100644 index 000000000000..d5de8683fd3b --- /dev/null +++ b/include/llvm/IR/DebugInfoFlags.def @@ -0,0 +1,36 @@ +//===- llvm/IR/DebugInfoFlags.def - Debug info flag definitions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through debug info flags. +// +//===----------------------------------------------------------------------===// + +// TODO: Add other DW-based macros. +#ifndef HANDLE_DI_FLAG +#error "Missing macro definition of HANDLE_DI_FLAG" +#endif + +HANDLE_DI_FLAG(1, Private) +HANDLE_DI_FLAG(2, Protected) +HANDLE_DI_FLAG(3, Public) +HANDLE_DI_FLAG((1 << 2), FwdDecl) +HANDLE_DI_FLAG((1 << 3), AppleBlock) +HANDLE_DI_FLAG((1 << 4), BlockByrefStruct) +HANDLE_DI_FLAG((1 << 5), Virtual) +HANDLE_DI_FLAG((1 << 6), Artificial) +HANDLE_DI_FLAG((1 << 7), Explicit) +HANDLE_DI_FLAG((1 << 8), Prototyped) +HANDLE_DI_FLAG((1 << 9), ObjcClassComplete) +HANDLE_DI_FLAG((1 << 10), ObjectPointer) +HANDLE_DI_FLAG((1 << 11), Vector) +HANDLE_DI_FLAG((1 << 12), StaticMember) +HANDLE_DI_FLAG((1 << 13), LValueReference) +HANDLE_DI_FLAG((1 << 14), RValueReference) + +#undef HANDLE_DI_FLAG diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h new file mode 100644 index 000000000000..0125de5d40f5 --- /dev/null +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -0,0 +1,2227 @@ +//===- llvm/IR/DebugInfoMetadata.h - Debug info metadata --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Declarations for metadata specific to debug info. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_DEBUGINFOMETADATA_H +#define LLVM_IR_DEBUGINFOMETADATA_H + +#include "llvm/IR/Metadata.h" +#include "llvm/Support/Dwarf.h" + +// Helper macros for defining get() overrides. +#define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__ +#define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS +#define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS) \ + static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued); \ + } \ + static CLASS *getIfExists(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued, \ + /* ShouldCreate */ false); \ + } \ + static CLASS *getDistinct(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct); \ + } \ + static Temp##CLASS getTemporary(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return Temp##CLASS( \ + getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary)); \ + } + +namespace llvm { + +/// \brief Pointer union between a subclass of DINode and MDString. +/// +/// \a DICompositeType can be referenced via an \a MDString unique identifier. +/// This class allows some type safety in the face of that, requiring either a +/// node of a particular type or an \a MDString. +template <class T> class TypedDINodeRef { + const Metadata *MD = nullptr; + +public: + TypedDINodeRef() = default; + TypedDINodeRef(std::nullptr_t) {} + + /// \brief Construct from a raw pointer. + explicit TypedDINodeRef(const Metadata *MD) : MD(MD) { + assert((!MD || isa<MDString>(MD) || isa<T>(MD)) && "Expected valid ref"); + } + + template <class U> + TypedDINodeRef( + const TypedDINodeRef<U> &X, + typename std::enable_if<std::is_convertible<U *, T *>::value>::type * = + nullptr) + : MD(X) {} + + operator Metadata *() const { return const_cast<Metadata *>(MD); } + + bool operator==(const TypedDINodeRef<T> &X) const { return MD == X.MD; }; + bool operator!=(const TypedDINodeRef<T> &X) const { return MD != X.MD; }; + + /// \brief Create a reference. + /// + /// Get a reference to \c N, using an \a MDString reference if available. + static TypedDINodeRef get(const T *N); + + template <class MapTy> T *resolve(const MapTy &Map) const { + if (!MD) + return nullptr; + + if (auto *Typed = dyn_cast<T>(MD)) + return const_cast<T *>(Typed); + + auto *S = cast<MDString>(MD); + auto I = Map.find(S); + assert(I != Map.end() && "Missing identifier in type map"); + return cast<T>(I->second); + } +}; + +typedef TypedDINodeRef<DINode> DINodeRef; +typedef TypedDINodeRef<DIScope> DIScopeRef; +typedef TypedDINodeRef<DIType> DITypeRef; + +class DITypeRefArray { + const MDTuple *N = nullptr; + +public: + DITypeRefArray(const MDTuple *N) : N(N) {} + + explicit operator bool() const { return get(); } + explicit operator MDTuple *() const { return get(); } + + MDTuple *get() const { return const_cast<MDTuple *>(N); } + MDTuple *operator->() const { return get(); } + MDTuple &operator*() const { return *get(); } + + // FIXME: Fix callers and remove condition on N. + unsigned size() const { return N ? N->getNumOperands() : 0u; } + DITypeRef operator[](unsigned I) const { return DITypeRef(N->getOperand(I)); } + + class iterator : std::iterator<std::input_iterator_tag, DITypeRef, + std::ptrdiff_t, void, DITypeRef> { + MDNode::op_iterator I = nullptr; + + public: + iterator() = default; + explicit iterator(MDNode::op_iterator I) : I(I) {} + DITypeRef operator*() const { return DITypeRef(*I); } + iterator &operator++() { + ++I; + return *this; + } + iterator operator++(int) { + iterator Temp(*this); + ++I; + return Temp; + } + bool operator==(const iterator &X) const { return I == X.I; } + bool operator!=(const iterator &X) const { return I != X.I; } + }; + + // FIXME: Fix callers and remove condition on N. + iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } + iterator end() const { return N ? iterator(N->op_end()) : iterator(); } +}; + +/// \brief Tagged DWARF-like metadata node. +/// +/// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, +/// defined in llvm/Support/Dwarf.h). Called \a DINode because it's +/// potentially used for non-DWARF output. +class DINode : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + +protected: + DINode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None) + : MDNode(C, ID, Storage, Ops1, Ops2) { + assert(Tag < 1u << 16); + SubclassData16 = Tag; + } + ~DINode() = default; + + template <class Ty> Ty *getOperandAs(unsigned I) const { + return cast_or_null<Ty>(getOperand(I)); + } + + StringRef getStringOperand(unsigned I) const { + if (auto *S = getOperandAs<MDString>(I)) + return S->getString(); + return StringRef(); + } + + static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { + if (S.empty()) + return nullptr; + return MDString::get(Context, S); + } + +public: + unsigned getTag() const { return SubclassData16; } + + /// \brief Debug info flags. + /// + /// The three accessibility flags are mutually exclusive and rolled together + /// in the first two bits. + enum DIFlags { +#define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, +#include "llvm/IR/DebugInfoFlags.def" + FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic + }; + + static unsigned getFlag(StringRef Flag); + static const char *getFlagString(unsigned Flag); + + /// \brief Split up a flags bitfield. + /// + /// Split \c Flags into \c SplitFlags, a vector of its components. Returns + /// any remaining (unrecognized) bits. + static unsigned splitFlags(unsigned Flags, + SmallVectorImpl<unsigned> &SplitFlags); + + DINodeRef getRef() const { return DINodeRef::get(this); } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case GenericDINodeKind: + case DISubrangeKind: + case DIEnumeratorKind: + case DIBasicTypeKind: + case DIDerivedTypeKind: + case DICompositeTypeKind: + case DISubroutineTypeKind: + case DIFileKind: + case DICompileUnitKind: + case DISubprogramKind: + case DILexicalBlockKind: + case DILexicalBlockFileKind: + case DINamespaceKind: + case DITemplateTypeParameterKind: + case DITemplateValueParameterKind: + case DIGlobalVariableKind: + case DILocalVariableKind: + case DIObjCPropertyKind: + case DIImportedEntityKind: + return true; + } + } +}; + +template <class T> struct simplify_type<const TypedDINodeRef<T>> { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const TypedDINodeRef<T> &MD) { + return MD; + } +}; + +template <class T> +struct simplify_type<TypedDINodeRef<T>> + : simplify_type<const TypedDINodeRef<T>> {}; + +/// \brief Generic tagged DWARF-like metadata node. +/// +/// An un-specialized DWARF-like metadata node. The first operand is a +/// (possibly empty) null-separated \a MDString header that contains arbitrary +/// fields. The remaining operands are \a dwarf_operands(), and are pointers +/// to other metadata. +class GenericDINode : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + GenericDINode(LLVMContext &C, StorageType Storage, unsigned Hash, + unsigned Tag, ArrayRef<Metadata *> Ops1, + ArrayRef<Metadata *> Ops2) + : DINode(C, GenericDINodeKind, Storage, Tag, Ops1, Ops2) { + setHash(Hash); + } + ~GenericDINode() { dropAllReferences(); } + + void setHash(unsigned Hash) { SubclassData32 = Hash; } + void recalculateHash(); + + static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Header, ArrayRef<Metadata *> DwarfOps, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Header), + DwarfOps, Storage, ShouldCreate); + } + + static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Header, ArrayRef<Metadata *> DwarfOps, + StorageType Storage, bool ShouldCreate = true); + + TempGenericDINode cloneImpl() const { + return getTemporary( + getContext(), getTag(), getHeader(), + SmallVector<Metadata *, 4>(dwarf_op_begin(), dwarf_op_end())); + } + +public: + unsigned getHash() const { return SubclassData32; } + + DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, StringRef Header, + ArrayRef<Metadata *> DwarfOps), + (Tag, Header, DwarfOps)) + DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, MDString *Header, + ArrayRef<Metadata *> DwarfOps), + (Tag, Header, DwarfOps)) + + /// \brief Return a (temporary) clone of this. + TempGenericDINode clone() const { return cloneImpl(); } + + unsigned getTag() const { return SubclassData16; } + StringRef getHeader() const { return getStringOperand(0); } + + op_iterator dwarf_op_begin() const { return op_begin() + 1; } + op_iterator dwarf_op_end() const { return op_end(); } + op_range dwarf_operands() const { + return op_range(dwarf_op_begin(), dwarf_op_end()); + } + + unsigned getNumDwarfOperands() const { return getNumOperands() - 1; } + const MDOperand &getDwarfOperand(unsigned I) const { + return getOperand(I + 1); + } + void replaceDwarfOperandWith(unsigned I, Metadata *New) { + replaceOperandWith(I + 1, New); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == GenericDINodeKind; + } +}; + +/// \brief Array subrange. +/// +/// TODO: Merge into node for DW_TAG_array_type, which should have a custom +/// type. +class DISubrange : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + int64_t Count; + int64_t LowerBound; + + DISubrange(LLVMContext &C, StorageType Storage, int64_t Count, + int64_t LowerBound) + : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, None), + Count(Count), LowerBound(LowerBound) {} + ~DISubrange() = default; + + static DISubrange *getImpl(LLVMContext &Context, int64_t Count, + int64_t LowerBound, StorageType Storage, + bool ShouldCreate = true); + + TempDISubrange cloneImpl() const { + return getTemporary(getContext(), getCount(), getLowerBound()); + } + +public: + DEFINE_MDNODE_GET(DISubrange, (int64_t Count, int64_t LowerBound = 0), + (Count, LowerBound)) + + TempDISubrange clone() const { return cloneImpl(); } + + int64_t getLowerBound() const { return LowerBound; } + int64_t getCount() const { return Count; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DISubrangeKind; + } +}; + +/// \brief Enumeration value. +/// +/// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no +/// longer creates a type cycle. +class DIEnumerator : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + int64_t Value; + + DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, + ArrayRef<Metadata *> Ops) + : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), + Value(Value) {} + ~DIEnumerator() = default; + + static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value, + StringRef Name, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Value, getCanonicalMDString(Context, Name), Storage, + ShouldCreate); + } + static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value, + MDString *Name, StorageType Storage, + bool ShouldCreate = true); + + TempDIEnumerator cloneImpl() const { + return getTemporary(getContext(), getValue(), getName()); + } + +public: + DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, StringRef Name), + (Value, Name)) + DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, MDString *Name), + (Value, Name)) + + TempDIEnumerator clone() const { return cloneImpl(); } + + int64_t getValue() const { return Value; } + StringRef getName() const { return getStringOperand(0); } + + MDString *getRawName() const { return getOperandAs<MDString>(0); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIEnumeratorKind; + } +}; + +/// \brief Base class for scope-like contexts. +/// +/// Base class for lexical scopes and types (which are also declaration +/// contexts). +/// +/// TODO: Separate the concepts of declaration contexts and lexical scopes. +class DIScope : public DINode { +protected: + DIScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef<Metadata *> Ops) + : DINode(C, ID, Storage, Tag, Ops) {} + ~DIScope() = default; + +public: + DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } + + inline StringRef getFilename() const; + inline StringRef getDirectory() const; + + StringRef getName() const; + DIScopeRef getScope() const; + + /// \brief Return the raw underlying file. + /// + /// An \a DIFile is an \a DIScope, but it doesn't point at a separate file + /// (it\em is the file). If \c this is an \a DIFile, we need to return \c + /// this. Otherwise, return the first operand, which is where all other + /// subclasses store their file pointer. + Metadata *getRawFile() const { + return isa<DIFile>(this) ? const_cast<DIScope *>(this) + : static_cast<Metadata *>(getOperand(0)); + } + + DIScopeRef getRef() const { return DIScopeRef::get(this); } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case DIBasicTypeKind: + case DIDerivedTypeKind: + case DICompositeTypeKind: + case DISubroutineTypeKind: + case DIFileKind: + case DICompileUnitKind: + case DISubprogramKind: + case DILexicalBlockKind: + case DILexicalBlockFileKind: + case DINamespaceKind: + return true; + } + } +}; + +/// \brief File. +/// +/// TODO: Merge with directory/file node (including users). +/// TODO: Canonicalize paths on creation. +class DIFile : public DIScope { + friend class LLVMContextImpl; + friend class MDNode; + + DIFile(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops) + : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {} + ~DIFile() = default; + + static DIFile *getImpl(LLVMContext &Context, StringRef Filename, + StringRef Directory, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Filename), + getCanonicalMDString(Context, Directory), Storage, + ShouldCreate); + } + static DIFile *getImpl(LLVMContext &Context, MDString *Filename, + MDString *Directory, StorageType Storage, + bool ShouldCreate = true); + + TempDIFile cloneImpl() const { + return getTemporary(getContext(), getFilename(), getDirectory()); + } + +public: + DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory), + (Filename, Directory)) + DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory), + (Filename, Directory)) + + TempDIFile clone() const { return cloneImpl(); } + + StringRef getFilename() const { return getStringOperand(0); } + StringRef getDirectory() const { return getStringOperand(1); } + + MDString *getRawFilename() const { return getOperandAs<MDString>(0); } + MDString *getRawDirectory() const { return getOperandAs<MDString>(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIFileKind; + } +}; + +StringRef DIScope::getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; +} + +StringRef DIScope::getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; +} + +/// \brief Base class for types. +/// +/// TODO: Remove the hardcoded name and context, since many types don't use +/// them. +/// TODO: Split up flags. +class DIType : public DIScope { + unsigned Line; + unsigned Flags; + uint64_t SizeInBits; + uint64_t AlignInBits; + uint64_t OffsetInBits; + +protected: + DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, ArrayRef<Metadata *> Ops) + : DIScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags), + SizeInBits(SizeInBits), AlignInBits(AlignInBits), + OffsetInBits(OffsetInBits) {} + ~DIType() = default; + +public: + TempDIType clone() const { + return TempDIType(cast<DIType>(MDNode::clone().release())); + } + + unsigned getLine() const { return Line; } + uint64_t getSizeInBits() const { return SizeInBits; } + uint64_t getAlignInBits() const { return AlignInBits; } + uint64_t getOffsetInBits() const { return OffsetInBits; } + unsigned getFlags() const { return Flags; } + + DIScopeRef getScope() const { return DIScopeRef(getRawScope()); } + StringRef getName() const { return getStringOperand(2); } + + + Metadata *getRawScope() const { return getOperand(1); } + MDString *getRawName() const { return getOperandAs<MDString>(2); } + + void setFlags(unsigned NewFlags) { + assert(!isUniqued() && "Cannot set flags on uniqued nodes"); + Flags = NewFlags; + } + + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } + bool isForwardDecl() const { return getFlags() & FlagFwdDecl; } + bool isAppleBlockExtension() const { return getFlags() & FlagAppleBlock; } + bool isBlockByrefStruct() const { return getFlags() & FlagBlockByrefStruct; } + bool isVirtual() const { return getFlags() & FlagVirtual; } + bool isArtificial() const { return getFlags() & FlagArtificial; } + bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } + bool isObjcClassComplete() const { + return getFlags() & FlagObjcClassComplete; + } + bool isVector() const { return getFlags() & FlagVector; } + bool isStaticMember() const { return getFlags() & FlagStaticMember; } + bool isLValueReference() const { return getFlags() & FlagLValueReference; } + bool isRValueReference() const { return getFlags() & FlagRValueReference; } + + DITypeRef getRef() const { return DITypeRef::get(this); } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case DIBasicTypeKind: + case DIDerivedTypeKind: + case DICompositeTypeKind: + case DISubroutineTypeKind: + return true; + } + } +}; + +/// \brief Basic type, like 'int' or 'float'. +/// +/// TODO: Split out DW_TAG_unspecified_type. +/// TODO: Drop unused accessors. +class DIBasicType : public DIType { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Encoding; + + DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, + uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding, + ArrayRef<Metadata *> Ops) + : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, + 0, Ops), + Encoding(Encoding) {} + ~DIBasicType() = default; + + static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), + SizeInBits, AlignInBits, Encoding, Storage, ShouldCreate); + } + static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding, + StorageType Storage, bool ShouldCreate = true); + + TempDIBasicType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), + getAlignInBits(), getEncoding()); + } + +public: + DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name), + (Tag, Name, 0, 0, 0)) + DEFINE_MDNODE_GET(DIBasicType, + (unsigned Tag, StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBits, Encoding)) + DEFINE_MDNODE_GET(DIBasicType, + (unsigned Tag, MDString *Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBits, Encoding)) + + TempDIBasicType clone() const { return cloneImpl(); } + + unsigned getEncoding() const { return Encoding; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIBasicTypeKind; + } +}; + +/// \brief Base class for DIDerivedType and DICompositeType. +/// +/// TODO: Delete; they're not really related. +class DIDerivedTypeBase : public DIType { +protected: + DIDerivedTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, + unsigned Tag, unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + ArrayRef<Metadata *> Ops) + : DIType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, + Flags, Ops) {} + ~DIDerivedTypeBase() = default; + +public: + DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); } + Metadata *getRawBaseType() const { return getOperand(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIDerivedTypeKind || + MD->getMetadataID() == DICompositeTypeKind || + MD->getMetadataID() == DISubroutineTypeKind; + } +}; + +/// \brief Derived types. +/// +/// This includes qualified types, pointers, references, friends, typedefs, and +/// class members. +/// +/// TODO: Split out members (inheritance, fields, methods, etc.). +class DIDerivedType : public DIDerivedTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, ArrayRef<Metadata *> Ops) + : DIDerivedTypeBase(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits, + AlignInBits, OffsetInBits, Flags, Ops) {} + ~DIDerivedType() = default; + + static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, DIFile *File, unsigned Line, + DIScopeRef Scope, DITypeRef BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, + Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, + Flags, ExtraData, Storage, ShouldCreate); + } + static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, Metadata *File, unsigned Line, + Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData, StorageType Storage, + bool ShouldCreate = true); + + TempDIDerivedType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), getFlags(), + getExtraData()); + } + +public: + DEFINE_MDNODE_GET(DIDerivedType, + (unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, ExtraData)) + DEFINE_MDNODE_GET(DIDerivedType, + (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, + DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, Metadata *ExtraData = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, ExtraData)) + + TempDIDerivedType clone() const { return cloneImpl(); } + + /// \brief Get extra data associated with this derived type. + /// + /// Class type for pointer-to-members, objective-c property node for ivars, + /// or global constant wrapper for static members. + /// + /// TODO: Separate out types that need this extra operand: pointer-to-member + /// types and member fields (static members and ivars). + Metadata *getExtraData() const { return getRawExtraData(); } + Metadata *getRawExtraData() const { return getOperand(4); } + + /// \brief Get casted version of extra data. + /// @{ + DITypeRef getClassType() const { + assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); + return DITypeRef(getExtraData()); + } + DIObjCProperty *getObjCProperty() const { + return dyn_cast_or_null<DIObjCProperty>(getExtraData()); + } + Constant *getConstant() const { + assert(getTag() == dwarf::DW_TAG_member && isStaticMember()); + if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) + return C->getValue(); + return nullptr; + } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIDerivedTypeKind; + } +}; + +/// \brief Base class for DICompositeType and DISubroutineType. +/// +/// TODO: Delete; they're not really related. +class DICompositeTypeBase : public DIDerivedTypeBase { + unsigned RuntimeLang; + +protected: + DICompositeTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, + unsigned Tag, unsigned Line, unsigned RuntimeLang, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + ArrayRef<Metadata *> Ops) + : DIDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, + OffsetInBits, Flags, Ops), + RuntimeLang(RuntimeLang) {} + ~DICompositeTypeBase() = default; + +public: + /// \brief Get the elements of the composite type. + /// + /// \note Calling this is only valid for \a DICompositeType. This assertion + /// can be removed once \a DISubroutineType has been separated from + /// "composite types". + DINodeArray getElements() const { + assert(!isa<DISubroutineType>(this) && "no elements for DISubroutineType"); + return cast_or_null<MDTuple>(getRawElements()); + } + DITypeRef getVTableHolder() const { return DITypeRef(getRawVTableHolder()); } + DITemplateParameterArray getTemplateParams() const { + return cast_or_null<MDTuple>(getRawTemplateParams()); + } + StringRef getIdentifier() const { return getStringOperand(7); } + unsigned getRuntimeLang() const { return RuntimeLang; } + + Metadata *getRawElements() const { return getOperand(4); } + Metadata *getRawVTableHolder() const { return getOperand(5); } + Metadata *getRawTemplateParams() const { return getOperand(6); } + MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); } + + /// \brief Replace operands. + /// + /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision + /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track + /// of its movement if necessary. + /// @{ + void replaceElements(DINodeArray Elements) { +#ifndef NDEBUG + for (DINode *Op : getElements()) + assert(std::find(Elements->op_begin(), Elements->op_end(), Op) && + "Lost a member during member list replacement"); +#endif + replaceOperandWith(4, Elements.get()); + } + void replaceVTableHolder(DITypeRef VTableHolder) { + replaceOperandWith(5, VTableHolder); + } + void replaceTemplateParams(DITemplateParameterArray TemplateParams) { + replaceOperandWith(6, TemplateParams.get()); + } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DICompositeTypeKind || + MD->getMetadataID() == DISubroutineTypeKind; + } +}; + +/// \brief Composite types. +/// +/// TODO: Detach from DerivedTypeBase (split out MDEnumType?). +/// TODO: Create a custom, unrelated node for DW_TAG_array_type. +class DICompositeType : public DICompositeTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + ArrayRef<Metadata *> Ops) + : DICompositeTypeBase(C, DICompositeTypeKind, Storage, Tag, Line, + RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, + Flags, Ops) {} + ~DICompositeType() = default; + + static DICompositeType * + getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, + unsigned Line, DIScopeRef Scope, DITypeRef BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + uint64_t Flags, DINodeArray Elements, unsigned RuntimeLang, + DITypeRef VTableHolder, DITemplateParameterArray TemplateParams, + StringRef Identifier, StorageType Storage, bool ShouldCreate = true) { + return getImpl( + Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, + BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), + RuntimeLang, VTableHolder, TemplateParams.get(), + getCanonicalMDString(Context, Identifier), Storage, ShouldCreate); + } + static DICompositeType * + getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, Metadata *Elements, unsigned RuntimeLang, + Metadata *VTableHolder, Metadata *TemplateParams, + MDString *Identifier, StorageType Storage, bool ShouldCreate = true); + + TempDICompositeType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), getFlags(), + getElements(), getRuntimeLang(), getVTableHolder(), + getTemplateParams(), getIdentifier()); + } + +public: + DEFINE_MDNODE_GET(DICompositeType, + (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, + DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DINodeArray Elements, unsigned RuntimeLang, + DITypeRef VTableHolder, + DITemplateParameterArray TemplateParams = nullptr, + StringRef Identifier = ""), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)) + DEFINE_MDNODE_GET(DICompositeType, + (unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, Metadata *Elements, + unsigned RuntimeLang, Metadata *VTableHolder, + Metadata *TemplateParams = nullptr, + MDString *Identifier = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)) + + TempDICompositeType clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DICompositeTypeKind; + } +}; + +template <class T> TypedDINodeRef<T> TypedDINodeRef<T>::get(const T *N) { + if (N) + if (auto *Composite = dyn_cast<DICompositeType>(N)) + if (auto *S = Composite->getRawIdentifier()) + return TypedDINodeRef<T>(S); + return TypedDINodeRef<T>(N); +} + +/// \brief Type array for a subprogram. +/// +/// TODO: Detach from CompositeType, and fold the array of types in directly +/// as operands. +class DISubroutineType : public DICompositeTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + DISubroutineType(LLVMContext &C, StorageType Storage, unsigned Flags, + ArrayRef<Metadata *> Ops) + : DICompositeTypeBase(C, DISubroutineTypeKind, Storage, + dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags, + Ops) {} + ~DISubroutineType() = default; + + static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags, + DITypeRefArray TypeArray, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Flags, TypeArray.get(), Storage, ShouldCreate); + } + static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags, + Metadata *TypeArray, StorageType Storage, + bool ShouldCreate = true); + + TempDISubroutineType cloneImpl() const { + return getTemporary(getContext(), getFlags(), getTypeArray()); + } + +public: + DEFINE_MDNODE_GET(DISubroutineType, + (unsigned Flags, DITypeRefArray TypeArray), + (Flags, TypeArray)) + DEFINE_MDNODE_GET(DISubroutineType, (unsigned Flags, Metadata *TypeArray), + (Flags, TypeArray)) + + TempDISubroutineType clone() const { return cloneImpl(); } + + DITypeRefArray getTypeArray() const { + return cast_or_null<MDTuple>(getRawTypeArray()); + } + Metadata *getRawTypeArray() const { return getRawElements(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DISubroutineTypeKind; + } +}; + +/// \brief Compile unit. +class DICompileUnit : public DIScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned SourceLanguage; + bool IsOptimized; + unsigned RuntimeVersion; + unsigned EmissionKind; + uint64_t DWOId; + + DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, + bool IsOptimized, unsigned RuntimeVersion, + unsigned EmissionKind, uint64_t DWOId, ArrayRef<Metadata *> Ops) + : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), + SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), + RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind), + DWOId(DWOId) {} + ~DICompileUnit() = default; + + static DICompileUnit * + getImpl(LLVMContext &Context, unsigned SourceLanguage, DIFile *File, + StringRef Producer, bool IsOptimized, StringRef Flags, + unsigned RuntimeVersion, StringRef SplitDebugFilename, + unsigned EmissionKind, DICompositeTypeArray EnumTypes, + DITypeArray RetainedTypes, DISubprogramArray Subprograms, + DIGlobalVariableArray GlobalVariables, + DIImportedEntityArray ImportedEntities, uint64_t DWOId, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, SourceLanguage, File, + getCanonicalMDString(Context, Producer), IsOptimized, + getCanonicalMDString(Context, Flags), RuntimeVersion, + getCanonicalMDString(Context, SplitDebugFilename), + EmissionKind, EnumTypes.get(), RetainedTypes.get(), + Subprograms.get(), GlobalVariables.get(), + ImportedEntities.get(), DWOId, Storage, ShouldCreate); + } + static DICompileUnit * + getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + MDString *Producer, bool IsOptimized, MDString *Flags, + unsigned RuntimeVersion, MDString *SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, + Metadata *Subprograms, Metadata *GlobalVariables, + Metadata *ImportedEntities, uint64_t DWOId, StorageType Storage, + bool ShouldCreate = true); + + TempDICompileUnit cloneImpl() const { + return getTemporary( + getContext(), getSourceLanguage(), getFile(), getProducer(), + isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(), + getEmissionKind(), getEnumTypes(), getRetainedTypes(), getSubprograms(), + getGlobalVariables(), getImportedEntities(), DWOId); + } + +public: + DEFINE_MDNODE_GET(DICompileUnit, + (unsigned SourceLanguage, DIFile *File, StringRef Producer, + bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, + StringRef SplitDebugFilename, unsigned EmissionKind, + DICompositeTypeArray EnumTypes, DITypeArray RetainedTypes, + DISubprogramArray Subprograms, + DIGlobalVariableArray GlobalVariables, + DIImportedEntityArray ImportedEntities, uint64_t DWOId), + (SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, + EnumTypes, RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities, DWOId)) + DEFINE_MDNODE_GET( + DICompileUnit, + (unsigned SourceLanguage, Metadata *File, MDString *Producer, + bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, + MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, + Metadata *RetainedTypes, Metadata *Subprograms, + Metadata *GlobalVariables, Metadata *ImportedEntities, uint64_t DWOId), + (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, + SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms, + GlobalVariables, ImportedEntities, DWOId)) + + TempDICompileUnit clone() const { return cloneImpl(); } + + unsigned getSourceLanguage() const { return SourceLanguage; } + bool isOptimized() const { return IsOptimized; } + unsigned getRuntimeVersion() const { return RuntimeVersion; } + unsigned getEmissionKind() const { return EmissionKind; } + StringRef getProducer() const { return getStringOperand(1); } + StringRef getFlags() const { return getStringOperand(2); } + StringRef getSplitDebugFilename() const { return getStringOperand(3); } + DICompositeTypeArray getEnumTypes() const { + return cast_or_null<MDTuple>(getRawEnumTypes()); + } + DITypeArray getRetainedTypes() const { + return cast_or_null<MDTuple>(getRawRetainedTypes()); + } + DISubprogramArray getSubprograms() const { + return cast_or_null<MDTuple>(getRawSubprograms()); + } + DIGlobalVariableArray getGlobalVariables() const { + return cast_or_null<MDTuple>(getRawGlobalVariables()); + } + DIImportedEntityArray getImportedEntities() const { + return cast_or_null<MDTuple>(getRawImportedEntities()); + } + unsigned getDWOId() const { return DWOId; } + + MDString *getRawProducer() const { return getOperandAs<MDString>(1); } + MDString *getRawFlags() const { return getOperandAs<MDString>(2); } + MDString *getRawSplitDebugFilename() const { + return getOperandAs<MDString>(3); + } + Metadata *getRawEnumTypes() const { return getOperand(4); } + Metadata *getRawRetainedTypes() const { return getOperand(5); } + Metadata *getRawSubprograms() const { return getOperand(6); } + Metadata *getRawGlobalVariables() const { return getOperand(7); } + Metadata *getRawImportedEntities() const { return getOperand(8); } + + /// \brief Replace arrays. + /// + /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and + /// deleted on a uniquing collision. In practice, uniquing collisions on \a + /// DICompileUnit should be fairly rare. + /// @{ + void replaceSubprograms(DISubprogramArray N) { + replaceOperandWith(6, N.get()); + } + void replaceGlobalVariables(DIGlobalVariableArray N) { + replaceOperandWith(7, N.get()); + } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DICompileUnitKind; + } +}; + +/// \brief A scope for locals. +/// +/// A legal scope for lexical blocks, local variables, and debug info +/// locations. Subclasses are \a DISubprogram, \a DILexicalBlock, and \a +/// DILexicalBlockFile. +class DILocalScope : public DIScope { +protected: + DILocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef<Metadata *> Ops) + : DIScope(C, ID, Storage, Tag, Ops) {} + ~DILocalScope() = default; + +public: + /// \brief Get the subprogram for this scope. + /// + /// Return this if it's an \a DISubprogram; otherwise, look up the scope + /// chain. + DISubprogram *getSubprogram() const; + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DISubprogramKind || + MD->getMetadataID() == DILexicalBlockKind || + MD->getMetadataID() == DILexicalBlockFileKind; + } +}; + +/// \brief Debug location. +/// +/// A debug location in source code, used for debug info and otherwise. +class DILocation : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + + DILocation(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, ArrayRef<Metadata *> MDs); + ~DILocation() { dropAllReferences(); } + + static DILocation *getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt, StorageType Storage, + bool ShouldCreate = true); + static DILocation *getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, DILocalScope *Scope, + DILocation *InlinedAt, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Line, Column, static_cast<Metadata *>(Scope), + static_cast<Metadata *>(InlinedAt), Storage, ShouldCreate); + } + + TempDILocation cloneImpl() const { + return getTemporary(getContext(), getLine(), getColumn(), getScope(), + getInlinedAt()); + } + + // Disallow replacing operands. + void replaceOperandWith(unsigned I, Metadata *New) = delete; + +public: + DEFINE_MDNODE_GET(DILocation, + (unsigned Line, unsigned Column, Metadata *Scope, + Metadata *InlinedAt = nullptr), + (Line, Column, Scope, InlinedAt)) + DEFINE_MDNODE_GET(DILocation, + (unsigned Line, unsigned Column, DILocalScope *Scope, + DILocation *InlinedAt = nullptr), + (Line, Column, Scope, InlinedAt)) + + /// \brief Return a (temporary) clone of this. + TempDILocation clone() const { return cloneImpl(); } + + unsigned getLine() const { return SubclassData32; } + unsigned getColumn() const { return SubclassData16; } + DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } + DILocation *getInlinedAt() const { + return cast_or_null<DILocation>(getRawInlinedAt()); + } + + DIFile *getFile() const { return getScope()->getFile(); } + StringRef getFilename() const { return getScope()->getFilename(); } + StringRef getDirectory() const { return getScope()->getDirectory(); } + + /// \brief Get the scope where this is inlined. + /// + /// Walk through \a getInlinedAt() and return \a getScope() from the deepest + /// location. + DILocalScope *getInlinedAtScope() const { + if (auto *IA = getInlinedAt()) + return IA->getInlinedAtScope(); + return getScope(); + } + + /// \brief Check whether this can be discriminated from another location. + /// + /// Check \c this can be discriminated from \c RHS in a linetable entry. + /// Scope and inlined-at chains are not recorded in the linetable, so they + /// cannot be used to distinguish basic blocks. + /// + /// The current implementation is weaker than it should be, since it just + /// checks filename and line. + /// + /// FIXME: Add a check for getDiscriminator(). + /// FIXME: Add a check for getColumn(). + /// FIXME: Change the getFilename() check to getFile() (or add one for + /// getDirectory()). + bool canDiscriminate(const DILocation &RHS) const { + return getFilename() != RHS.getFilename() || getLine() != RHS.getLine(); + } + + /// \brief Get the DWARF discriminator. + /// + /// DWARF discriminators distinguish identical file locations between + /// instructions that are on different basic blocks. + inline unsigned getDiscriminator() const; + + /// \brief Compute new discriminator in the given context. + /// + /// This modifies the \a LLVMContext that \c this is in to increment the next + /// discriminator for \c this's line/filename combination. + /// + /// FIXME: Delete this. See comments in implementation and at the only call + /// site in \a AddDiscriminators::runOnFunction(). + unsigned computeNewDiscriminator() const; + + Metadata *getRawScope() const { return getOperand(0); } + Metadata *getRawInlinedAt() const { + if (getNumOperands() == 2) + return getOperand(1); + return nullptr; + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILocationKind; + } +}; + +/// \brief Subprogram description. +/// +/// TODO: Remove DisplayName. It's always equal to Name. +/// TODO: Split up flags. +class DISubprogram : public DILocalScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned ScopeLine; + unsigned Virtuality; + unsigned VirtualIndex; + unsigned Flags; + bool IsLocalToUnit; + bool IsDefinition; + bool IsOptimized; + + DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned ScopeLine, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsLocalToUnit, bool IsDefinition, + bool IsOptimized, ArrayRef<Metadata *> Ops) + : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram, + Ops), + Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality), + VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit), + IsDefinition(IsDefinition), IsOptimized(IsOptimized) {} + ~DISubprogram() = default; + + static DISubprogram * + getImpl(LLVMContext &Context, DIScopeRef Scope, StringRef Name, + StringRef LinkageName, DIFile *File, unsigned Line, + DISubroutineType *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, DITypeRef ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Constant *Function, DITemplateParameterArray TemplateParams, + DISubprogram *Declaration, DILocalVariableArray Variables, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + getCanonicalMDString(Context, LinkageName), File, Line, Type, + IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, + Virtuality, VirtualIndex, Flags, IsOptimized, + Function ? ConstantAsMetadata::get(Function) : nullptr, + TemplateParams.get(), Declaration, Variables.get(), Storage, + ShouldCreate); + } + static DISubprogram * + getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsOptimized, Metadata *Function, + Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + StorageType Storage, bool ShouldCreate = true); + + TempDISubprogram cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getLinkageName(), + getFile(), getLine(), getType(), isLocalToUnit(), + isDefinition(), getScopeLine(), getContainingType(), + getVirtuality(), getVirtualIndex(), getFlags(), + isOptimized(), getFunctionConstant(), + getTemplateParams(), getDeclaration(), getVariables()); + } + +public: + DEFINE_MDNODE_GET(DISubprogram, + (DIScopeRef Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned Line, DISubroutineType *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + DITypeRef ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Constant *Function = nullptr, + DITemplateParameterArray TemplateParams = nullptr, + DISubprogram *Declaration = nullptr, + DILocalVariableArray Variables = nullptr), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, ScopeLine, ContainingType, Virtuality, + VirtualIndex, Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)) + DEFINE_MDNODE_GET( + DISubprogram, + (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, + unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Metadata *Function = nullptr, Metadata *TemplateParams = nullptr, + Metadata *Declaration = nullptr, Metadata *Variables = nullptr), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, + ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized, + Function, TemplateParams, Declaration, Variables)) + + TempDISubprogram clone() const { return cloneImpl(); } + +public: + unsigned getLine() const { return Line; } + unsigned getVirtuality() const { return Virtuality; } + unsigned getVirtualIndex() const { return VirtualIndex; } + unsigned getScopeLine() const { return ScopeLine; } + unsigned getFlags() const { return Flags; } + bool isLocalToUnit() const { return IsLocalToUnit; } + bool isDefinition() const { return IsDefinition; } + bool isOptimized() const { return IsOptimized; } + + unsigned isArtificial() const { return getFlags() & FlagArtificial; } + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } + bool isExplicit() const { return getFlags() & FlagExplicit; } + bool isPrototyped() const { return getFlags() & FlagPrototyped; } + + /// \brief Check if this is reference-qualified. + /// + /// Return true if this subprogram is a C++11 reference-qualified non-static + /// member function (void foo() &). + unsigned isLValueReference() const { + return getFlags() & FlagLValueReference; + } + + /// \brief Check if this is rvalue-reference-qualified. + /// + /// Return true if this subprogram is a C++11 rvalue-reference-qualified + /// non-static member function (void foo() &&). + unsigned isRValueReference() const { + return getFlags() & FlagRValueReference; + } + + DIScopeRef getScope() const { return DIScopeRef(getRawScope()); } + + StringRef getName() const { return getStringOperand(2); } + StringRef getDisplayName() const { return getStringOperand(3); } + StringRef getLinkageName() const { return getStringOperand(4); } + + MDString *getRawName() const { return getOperandAs<MDString>(2); } + MDString *getRawLinkageName() const { return getOperandAs<MDString>(4); } + + DISubroutineType *getType() const { + return cast_or_null<DISubroutineType>(getRawType()); + } + DITypeRef getContainingType() const { + return DITypeRef(getRawContainingType()); + } + + Constant *getFunctionConstant() const { + if (auto *C = cast_or_null<ConstantAsMetadata>(getRawFunction())) + return C->getValue(); + return nullptr; + } + DITemplateParameterArray getTemplateParams() const { + return cast_or_null<MDTuple>(getRawTemplateParams()); + } + DISubprogram *getDeclaration() const { + return cast_or_null<DISubprogram>(getRawDeclaration()); + } + DILocalVariableArray getVariables() const { + return cast_or_null<MDTuple>(getRawVariables()); + } + + Metadata *getRawScope() const { return getOperand(1); } + Metadata *getRawType() const { return getOperand(5); } + Metadata *getRawContainingType() const { return getOperand(6); } + Metadata *getRawFunction() const { return getOperand(7); } + Metadata *getRawTemplateParams() const { return getOperand(8); } + Metadata *getRawDeclaration() const { return getOperand(9); } + Metadata *getRawVariables() const { return getOperand(10); } + + /// \brief Get a pointer to the function this subprogram describes. + /// + /// This dyn_casts \a getFunctionConstant() to \a Function. + /// + /// FIXME: Should this be looking through bitcasts? + Function *getFunction() const; + + /// \brief Replace the function. + /// + /// If \a isUniqued() and not \a isResolved(), this could node will be + /// RAUW'ed and deleted out from under the caller. Use a \a TrackingMDRef if + /// that's a problem. + /// @{ + void replaceFunction(Function *F); + void replaceFunction(ConstantAsMetadata *MD) { replaceOperandWith(7, MD); } + void replaceFunction(std::nullptr_t) { replaceOperandWith(7, nullptr); } + /// @} + + /// \brief Check if this subprogram decribes the given function. + /// + /// FIXME: Should this be looking through bitcasts? + bool describes(const Function *F) const; + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DISubprogramKind; + } +}; + +class DILexicalBlockBase : public DILocalScope { +protected: + DILexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, + ArrayRef<Metadata *> Ops) + : DILocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} + ~DILexicalBlockBase() = default; + +public: + DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } + + Metadata *getRawScope() const { return getOperand(1); } + + /// \brief Forwarding accessors to LexicalBlock. + /// + /// TODO: Remove these and update code to use \a DILexicalBlock directly. + /// @{ + inline unsigned getLine() const; + inline unsigned getColumn() const; + /// @} + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILexicalBlockKind || + MD->getMetadataID() == DILexicalBlockFileKind; + } +}; + +class DILexicalBlock : public DILexicalBlockBase { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned Column; + + DILexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, ArrayRef<Metadata *> Ops) + : DILexicalBlockBase(C, DILexicalBlockKind, Storage, Ops), Line(Line), + Column(Column) {} + ~DILexicalBlock() = default; + + static DILexicalBlock *getImpl(LLVMContext &Context, DILocalScope *Scope, + DIFile *File, unsigned Line, unsigned Column, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, static_cast<Metadata *>(Scope), + static_cast<Metadata *>(File), Line, Column, Storage, + ShouldCreate); + } + + static DILexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, unsigned Line, unsigned Column, + StorageType Storage, bool ShouldCreate = true); + + TempDILexicalBlock cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), getLine(), + getColumn()); + } + +public: + DEFINE_MDNODE_GET(DILexicalBlock, (DILocalScope * Scope, DIFile *File, + unsigned Line, unsigned Column), + (Scope, File, Line, Column)) + DEFINE_MDNODE_GET(DILexicalBlock, (Metadata * Scope, Metadata *File, + unsigned Line, unsigned Column), + (Scope, File, Line, Column)) + + TempDILexicalBlock clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + unsigned getColumn() const { return Column; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILexicalBlockKind; + } +}; + +unsigned DILexicalBlockBase::getLine() const { + if (auto *N = dyn_cast<DILexicalBlock>(this)) + return N->getLine(); + return 0; +} + +unsigned DILexicalBlockBase::getColumn() const { + if (auto *N = dyn_cast<DILexicalBlock>(this)) + return N->getColumn(); + return 0; +} + +class DILexicalBlockFile : public DILexicalBlockBase { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Discriminator; + + DILexicalBlockFile(LLVMContext &C, StorageType Storage, + unsigned Discriminator, ArrayRef<Metadata *> Ops) + : DILexicalBlockBase(C, DILexicalBlockFileKind, Storage, Ops), + Discriminator(Discriminator) {} + ~DILexicalBlockFile() = default; + + static DILexicalBlockFile *getImpl(LLVMContext &Context, DILocalScope *Scope, + DIFile *File, unsigned Discriminator, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, static_cast<Metadata *>(Scope), + static_cast<Metadata *>(File), Discriminator, Storage, + ShouldCreate); + } + + static DILexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, unsigned Discriminator, + StorageType Storage, + bool ShouldCreate = true); + + TempDILexicalBlockFile cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), + getDiscriminator()); + } + +public: + DEFINE_MDNODE_GET(DILexicalBlockFile, (DILocalScope * Scope, DIFile *File, + unsigned Discriminator), + (Scope, File, Discriminator)) + DEFINE_MDNODE_GET(DILexicalBlockFile, + (Metadata * Scope, Metadata *File, unsigned Discriminator), + (Scope, File, Discriminator)) + + TempDILexicalBlockFile clone() const { return cloneImpl(); } + + // TODO: Remove these once they're gone from DILexicalBlockBase. + unsigned getLine() const = delete; + unsigned getColumn() const = delete; + + unsigned getDiscriminator() const { return Discriminator; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILexicalBlockFileKind; + } +}; + +unsigned DILocation::getDiscriminator() const { + if (auto *F = dyn_cast<DILexicalBlockFile>(getScope())) + return F->getDiscriminator(); + return 0; +} + +class DINamespace : public DIScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + DINamespace(LLVMContext &Context, StorageType Storage, unsigned Line, + ArrayRef<Metadata *> Ops) + : DIScope(Context, DINamespaceKind, Storage, dwarf::DW_TAG_namespace, + Ops), + Line(Line) {} + ~DINamespace() = default; + + static DINamespace *getImpl(LLVMContext &Context, DIScope *Scope, + DIFile *File, StringRef Name, unsigned Line, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Scope, File, getCanonicalMDString(Context, Name), + Line, Storage, ShouldCreate); + } + static DINamespace *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, MDString *Name, unsigned Line, + StorageType Storage, bool ShouldCreate = true); + + TempDINamespace cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), getName(), + getLine()); + } + +public: + DEFINE_MDNODE_GET(DINamespace, (DIScope * Scope, DIFile *File, StringRef Name, + unsigned Line), + (Scope, File, Name, Line)) + DEFINE_MDNODE_GET(DINamespace, (Metadata * Scope, Metadata *File, + MDString *Name, unsigned Line), + (Scope, File, Name, Line)) + + TempDINamespace clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } + StringRef getName() const { return getStringOperand(2); } + + Metadata *getRawScope() const { return getOperand(1); } + MDString *getRawName() const { return getOperandAs<MDString>(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DINamespaceKind; + } +}; + +/// \brief Base class for template parameters. +class DITemplateParameter : public DINode { +protected: + DITemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, + unsigned Tag, ArrayRef<Metadata *> Ops) + : DINode(Context, ID, Storage, Tag, Ops) {} + ~DITemplateParameter() = default; + +public: + StringRef getName() const { return getStringOperand(0); } + DITypeRef getType() const { return DITypeRef(getRawType()); } + + MDString *getRawName() const { return getOperandAs<MDString>(0); } + Metadata *getRawType() const { return getOperand(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DITemplateTypeParameterKind || + MD->getMetadataID() == DITemplateValueParameterKind; + } +}; + +class DITemplateTypeParameter : public DITemplateParameter { + friend class LLVMContextImpl; + friend class MDNode; + + DITemplateTypeParameter(LLVMContext &Context, StorageType Storage, + ArrayRef<Metadata *> Ops) + : DITemplateParameter(Context, DITemplateTypeParameterKind, Storage, + dwarf::DW_TAG_template_type_parameter, Ops) {} + ~DITemplateTypeParameter() = default; + + static DITemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, + DITypeRef Type, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage, + ShouldCreate); + } + static DITemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, + Metadata *Type, StorageType Storage, + bool ShouldCreate = true); + + TempDITemplateTypeParameter cloneImpl() const { + return getTemporary(getContext(), getName(), getType()); + } + +public: + DEFINE_MDNODE_GET(DITemplateTypeParameter, (StringRef Name, DITypeRef Type), + (Name, Type)) + DEFINE_MDNODE_GET(DITemplateTypeParameter, (MDString * Name, Metadata *Type), + (Name, Type)) + + TempDITemplateTypeParameter clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DITemplateTypeParameterKind; + } +}; + +class DITemplateValueParameter : public DITemplateParameter { + friend class LLVMContextImpl; + friend class MDNode; + + DITemplateValueParameter(LLVMContext &Context, StorageType Storage, + unsigned Tag, ArrayRef<Metadata *> Ops) + : DITemplateParameter(Context, DITemplateValueParameterKind, Storage, Tag, + Ops) {} + ~DITemplateValueParameter() = default; + + static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, DITypeRef Type, + Metadata *Value, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, + Value, Storage, ShouldCreate); + } + static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, Metadata *Type, + Metadata *Value, StorageType Storage, + bool ShouldCreate = true); + + TempDITemplateValueParameter cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getType(), + getValue()); + } + +public: + DEFINE_MDNODE_GET(DITemplateValueParameter, (unsigned Tag, StringRef Name, + DITypeRef Type, Metadata *Value), + (Tag, Name, Type, Value)) + DEFINE_MDNODE_GET(DITemplateValueParameter, (unsigned Tag, MDString *Name, + Metadata *Type, Metadata *Value), + (Tag, Name, Type, Value)) + + TempDITemplateValueParameter clone() const { return cloneImpl(); } + + Metadata *getValue() const { return getOperand(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DITemplateValueParameterKind; + } +}; + +/// \brief Base class for variables. +/// +/// TODO: Hardcode to DW_TAG_variable. +class DIVariable : public DINode { + unsigned Line; + +protected: + DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + unsigned Line, ArrayRef<Metadata *> Ops) + : DINode(C, ID, Storage, Tag, Ops), Line(Line) {} + ~DIVariable() = default; + +public: + unsigned getLine() const { return Line; } + DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } + StringRef getName() const { return getStringOperand(1); } + DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } + DITypeRef getType() const { return DITypeRef(getRawType()); } + + StringRef getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; + } + StringRef getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; + } + + Metadata *getRawScope() const { return getOperand(0); } + MDString *getRawName() const { return getOperandAs<MDString>(1); } + Metadata *getRawFile() const { return getOperand(2); } + Metadata *getRawType() const { return getOperand(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILocalVariableKind || + MD->getMetadataID() == DIGlobalVariableKind; + } +}; + +/// \brief Global variables. +/// +/// TODO: Remove DisplayName. It's always equal to Name. +class DIGlobalVariable : public DIVariable { + friend class LLVMContextImpl; + friend class MDNode; + + bool IsLocalToUnit; + bool IsDefinition; + + DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, + bool IsLocalToUnit, bool IsDefinition, + ArrayRef<Metadata *> Ops) + : DIVariable(C, DIGlobalVariableKind, Storage, dwarf::DW_TAG_variable, + Line, Ops), + IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} + ~DIGlobalVariable() = default; + + static DIGlobalVariable * + getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, + StringRef LinkageName, DIFile *File, unsigned Line, DITypeRef Type, + bool IsLocalToUnit, bool IsDefinition, Constant *Variable, + DIDerivedType *StaticDataMemberDeclaration, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + getCanonicalMDString(Context, LinkageName), File, Line, Type, + IsLocalToUnit, IsDefinition, + Variable ? ConstantAsMetadata::get(Variable) : nullptr, + StaticDataMemberDeclaration, Storage, ShouldCreate); + } + static DIGlobalVariable * + getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration, StorageType Storage, + bool ShouldCreate = true); + + TempDIGlobalVariable cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getLinkageName(), + getFile(), getLine(), getType(), isLocalToUnit(), + isDefinition(), getVariable(), + getStaticDataMemberDeclaration()); + } + +public: + DEFINE_MDNODE_GET(DIGlobalVariable, + (DIScope * Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned Line, DITypeRef Type, + bool IsLocalToUnit, bool IsDefinition, Constant *Variable, + DIDerivedType *StaticDataMemberDeclaration), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, Variable, StaticDataMemberDeclaration)) + DEFINE_MDNODE_GET(DIGlobalVariable, + (Metadata * Scope, MDString *Name, MDString *LinkageName, + Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, Variable, StaticDataMemberDeclaration)) + + TempDIGlobalVariable clone() const { return cloneImpl(); } + + bool isLocalToUnit() const { return IsLocalToUnit; } + bool isDefinition() const { return IsDefinition; } + StringRef getDisplayName() const { return getStringOperand(4); } + StringRef getLinkageName() const { return getStringOperand(5); } + Constant *getVariable() const { + if (auto *C = cast_or_null<ConstantAsMetadata>(getRawVariable())) + return dyn_cast<Constant>(C->getValue()); + return nullptr; + } + DIDerivedType *getStaticDataMemberDeclaration() const { + return cast_or_null<DIDerivedType>(getRawStaticDataMemberDeclaration()); + } + + MDString *getRawLinkageName() const { return getOperandAs<MDString>(5); } + Metadata *getRawVariable() const { return getOperand(6); } + Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(7); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIGlobalVariableKind; + } +}; + +/// \brief Local variable. +/// +/// TODO: Split between arguments and otherwise. +/// TODO: Use \c DW_TAG_variable instead of fake tags. +/// TODO: Split up flags. +class DILocalVariable : public DIVariable { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Arg; + unsigned Flags; + + DILocalVariable(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, unsigned Arg, unsigned Flags, + ArrayRef<Metadata *> Ops) + : DIVariable(C, DILocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg), + Flags(Flags) {} + ~DILocalVariable() = default; + + static DILocalVariable *getImpl(LLVMContext &Context, unsigned Tag, + DIScope *Scope, StringRef Name, DIFile *File, + unsigned Line, DITypeRef Type, unsigned Arg, + unsigned Flags, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name), + File, Line, Type, Arg, Flags, Storage, ShouldCreate); + } + static DILocalVariable * + getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, unsigned Arg, + unsigned Flags, StorageType Storage, bool ShouldCreate = true); + + TempDILocalVariable cloneImpl() const { + return getTemporary(getContext(), getTag(), getScope(), getName(), + getFile(), getLine(), getType(), getArg(), getFlags()); + } + +public: + DEFINE_MDNODE_GET(DILocalVariable, + (unsigned Tag, DILocalScope *Scope, StringRef Name, + DIFile *File, unsigned Line, DITypeRef Type, unsigned Arg, + unsigned Flags), + (Tag, Scope, Name, File, Line, Type, Arg, Flags)) + DEFINE_MDNODE_GET(DILocalVariable, + (unsigned Tag, Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags), + (Tag, Scope, Name, File, Line, Type, Arg, Flags)) + + TempDILocalVariable clone() const { return cloneImpl(); } + + /// \brief Get the local scope for this variable. + /// + /// Variables must be defined in a local scope. + DILocalScope *getScope() const { + return cast<DILocalScope>(DIVariable::getScope()); + } + + unsigned getArg() const { return Arg; } + unsigned getFlags() const { return Flags; } + + bool isArtificial() const { return getFlags() & FlagArtificial; } + bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } + + /// \brief Check that a location is valid for this variable. + /// + /// Check that \c DL exists, is in the same subprogram, and has the same + /// inlined-at location as \c this. (Otherwise, it's not a valid attachemnt + /// to a \a DbgInfoIntrinsic.) + bool isValidLocationForIntrinsic(const DILocation *DL) const { + return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILocalVariableKind; + } +}; + +/// \brief DWARF expression. +/// +/// This is (almost) a DWARF expression that modifies the location of a +/// variable or (or the location of a single piece of a variable). +/// +/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const +/// and have DW_OP_plus consume the topmost elements on the stack. +/// +/// TODO: Co-allocate the expression elements. +/// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary +/// storage types. +class DIExpression : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + + std::vector<uint64_t> Elements; + + DIExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements) + : MDNode(C, DIExpressionKind, Storage, None), + Elements(Elements.begin(), Elements.end()) {} + ~DIExpression() = default; + + static DIExpression *getImpl(LLVMContext &Context, + ArrayRef<uint64_t> Elements, StorageType Storage, + bool ShouldCreate = true); + + TempDIExpression cloneImpl() const { + return getTemporary(getContext(), getElements()); + } + +public: + DEFINE_MDNODE_GET(DIExpression, (ArrayRef<uint64_t> Elements), (Elements)) + + TempDIExpression clone() const { return cloneImpl(); } + + ArrayRef<uint64_t> getElements() const { return Elements; } + + unsigned getNumElements() const { return Elements.size(); } + uint64_t getElement(unsigned I) const { + assert(I < Elements.size() && "Index out of range"); + return Elements[I]; + } + + /// \brief Return whether this is a piece of an aggregate variable. + bool isBitPiece() const; + + /// \brief Return the offset of this piece in bits. + uint64_t getBitPieceOffset() const; + + /// \brief Return the size of this piece in bits. + uint64_t getBitPieceSize() const; + + typedef ArrayRef<uint64_t>::iterator element_iterator; + element_iterator elements_begin() const { return getElements().begin(); } + element_iterator elements_end() const { return getElements().end(); } + + /// \brief A lightweight wrapper around an expression operand. + /// + /// TODO: Store arguments directly and change \a DIExpression to store a + /// range of these. + class ExprOperand { + const uint64_t *Op; + + public: + explicit ExprOperand(const uint64_t *Op) : Op(Op) {} + + const uint64_t *get() const { return Op; } + + /// \brief Get the operand code. + uint64_t getOp() const { return *Op; } + + /// \brief Get an argument to the operand. + /// + /// Never returns the operand itself. + uint64_t getArg(unsigned I) const { return Op[I + 1]; } + + unsigned getNumArgs() const { return getSize() - 1; } + + /// \brief Return the size of the operand. + /// + /// Return the number of elements in the operand (1 + args). + unsigned getSize() const; + }; + + /// \brief An iterator for expression operands. + class expr_op_iterator + : public std::iterator<std::input_iterator_tag, ExprOperand> { + ExprOperand Op; + + public: + explicit expr_op_iterator(element_iterator I) : Op(I) {} + + element_iterator getBase() const { return Op.get(); } + const ExprOperand &operator*() const { return Op; } + const ExprOperand *operator->() const { return &Op; } + + expr_op_iterator &operator++() { + increment(); + return *this; + } + expr_op_iterator operator++(int) { + expr_op_iterator T(*this); + increment(); + return T; + } + + /// \brief Get the next iterator. + /// + /// \a std::next() doesn't work because this is technically an + /// input_iterator, but it's a perfectly valid operation. This is an + /// accessor to provide the same functionality. + expr_op_iterator getNext() const { return ++expr_op_iterator(*this); } + + bool operator==(const expr_op_iterator &X) const { + return getBase() == X.getBase(); + } + bool operator!=(const expr_op_iterator &X) const { + return getBase() != X.getBase(); + } + + private: + void increment() { Op = ExprOperand(getBase() + Op.getSize()); } + }; + + /// \brief Visit the elements via ExprOperand wrappers. + /// + /// These range iterators visit elements through \a ExprOperand wrappers. + /// This is not guaranteed to be a valid range unless \a isValid() gives \c + /// true. + /// + /// \pre \a isValid() gives \c true. + /// @{ + expr_op_iterator expr_op_begin() const { + return expr_op_iterator(elements_begin()); + } + expr_op_iterator expr_op_end() const { + return expr_op_iterator(elements_end()); + } + /// @} + + bool isValid() const; + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIExpressionKind; + } +}; + +class DIObjCProperty : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned Attributes; + + DIObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Attributes, ArrayRef<Metadata *> Ops) + : DINode(C, DIObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, + Ops), + Line(Line), Attributes(Attributes) {} + ~DIObjCProperty() = default; + + static DIObjCProperty * + getImpl(LLVMContext &Context, StringRef Name, DIFile *File, unsigned Line, + StringRef GetterName, StringRef SetterName, unsigned Attributes, + DIType *Type, StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, + getCanonicalMDString(Context, GetterName), + getCanonicalMDString(Context, SetterName), Attributes, Type, + Storage, ShouldCreate); + } + static DIObjCProperty *getImpl(LLVMContext &Context, MDString *Name, + Metadata *File, unsigned Line, + MDString *GetterName, MDString *SetterName, + unsigned Attributes, Metadata *Type, + StorageType Storage, bool ShouldCreate = true); + + TempDIObjCProperty cloneImpl() const { + return getTemporary(getContext(), getName(), getFile(), getLine(), + getGetterName(), getSetterName(), getAttributes(), + getType()); + } + +public: + DEFINE_MDNODE_GET(DIObjCProperty, + (StringRef Name, DIFile *File, unsigned Line, + StringRef GetterName, StringRef SetterName, + unsigned Attributes, DIType *Type), + (Name, File, Line, GetterName, SetterName, Attributes, + Type)) + DEFINE_MDNODE_GET(DIObjCProperty, + (MDString * Name, Metadata *File, unsigned Line, + MDString *GetterName, MDString *SetterName, + unsigned Attributes, Metadata *Type), + (Name, File, Line, GetterName, SetterName, Attributes, + Type)) + + TempDIObjCProperty clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + unsigned getAttributes() const { return Attributes; } + StringRef getName() const { return getStringOperand(0); } + DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } + StringRef getGetterName() const { return getStringOperand(2); } + StringRef getSetterName() const { return getStringOperand(3); } + + /// \brief Get the type. + /// + /// \note Objective-C doesn't have an ODR, so there is no benefit in storing + /// a type ref here. + DIType *getType() const { return cast_or_null<DIType>(getRawType()); } + + StringRef getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; + } + StringRef getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; + } + + MDString *getRawName() const { return getOperandAs<MDString>(0); } + Metadata *getRawFile() const { return getOperand(1); } + MDString *getRawGetterName() const { return getOperandAs<MDString>(2); } + MDString *getRawSetterName() const { return getOperandAs<MDString>(3); } + Metadata *getRawType() const { return getOperand(4); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIObjCPropertyKind; + } +}; + +/// \brief An imported module (C++ using directive or similar). +class DIImportedEntity : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + DIImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, ArrayRef<Metadata *> Ops) + : DINode(C, DIImportedEntityKind, Storage, Tag, Ops), Line(Line) {} + ~DIImportedEntity() = default; + + static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + DIScope *Scope, DINodeRef Entity, + unsigned Line, StringRef Name, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, Scope, Entity, Line, + getCanonicalMDString(Context, Name), Storage, ShouldCreate); + } + static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, Metadata *Entity, + unsigned Line, MDString *Name, + StorageType Storage, + bool ShouldCreate = true); + + TempDIImportedEntity cloneImpl() const { + return getTemporary(getContext(), getTag(), getScope(), getEntity(), + getLine(), getName()); + } + +public: + DEFINE_MDNODE_GET(DIImportedEntity, + (unsigned Tag, DIScope *Scope, DINodeRef Entity, + unsigned Line, StringRef Name = ""), + (Tag, Scope, Entity, Line, Name)) + DEFINE_MDNODE_GET(DIImportedEntity, + (unsigned Tag, Metadata *Scope, Metadata *Entity, + unsigned Line, MDString *Name), + (Tag, Scope, Entity, Line, Name)) + + TempDIImportedEntity clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } + DINodeRef getEntity() const { return DINodeRef(getRawEntity()); } + StringRef getName() const { return getStringOperand(2); } + + Metadata *getRawScope() const { return getOperand(0); } + Metadata *getRawEntity() const { return getOperand(1); } + MDString *getRawName() const { return getOperandAs<MDString>(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIImportedEntityKind; + } +}; + +} // end namespace llvm + +#undef DEFINE_MDNODE_GET_UNPACK_IMPL +#undef DEFINE_MDNODE_GET_UNPACK +#undef DEFINE_MDNODE_GET + +#endif diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index 86e64417099d..8ea5875e1f85 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -22,11 +22,15 @@ namespace llvm { class LLVMContext; class raw_ostream; - class MDNode; - - /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, - /// and MachineInstr to compactly encode file/line/scope information for an - /// operation. + class DILocation; + + /// \brief A debug info location. + /// + /// This class is a wrapper around a tracking reference to an \a DILocation + /// pointer. + /// + /// To avoid extra includes, \a DebugLoc doubles the \a DILocation API with a + /// one based on relatively opaque \a MDNode pointers. class DebugLoc { TrackingMDNodeRef Loc; @@ -43,67 +47,78 @@ namespace llvm { return *this; } + /// \brief Construct from an \a DILocation. + DebugLoc(const DILocation *L); + + /// \brief Construct from an \a MDNode. + /// + /// Note: if \c N is not an \a DILocation, a verifier check will fail, and + /// accessors will crash. However, construction from other nodes is + /// supported in order to handle forward references when reading textual + /// IR. + explicit DebugLoc(const MDNode *N); + + /// \brief Get the underlying \a DILocation. + /// + /// \pre !*this or \c isa<DILocation>(getAsMDNode()). + /// @{ + DILocation *get() const; + operator DILocation *() const { return get(); } + DILocation *operator->() const { return get(); } + DILocation &operator*() const { return *get(); } + /// @} + + /// \brief Check for null. + /// + /// Check for null in a way that is safe with broken debug info. Unlike + /// the conversion to \c DILocation, this doesn't require that \c Loc is of + /// the right type. Important for cases like \a llvm::StripDebugInfo() and + /// \a Instruction::hasMetadata(). + explicit operator bool() const { return Loc; } + /// \brief Check whether this has a trivial destructor. bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); } - /// get - Get a new DebugLoc that corresponds to the specified line/col - /// scope/inline location. - static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope, - MDNode *InlinedAt = nullptr); - - /// getFromDILocation - Translate the DILocation quad into a DebugLoc. - static DebugLoc getFromDILocation(MDNode *N); - - /// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc. - static DebugLoc getFromDILexicalBlock(MDNode *N); - - /// isUnknown - Return true if this is an unknown location. - bool isUnknown() const { return !Loc; } + /// \brief Create a new DebugLoc. + /// + /// Create a new DebugLoc at the specified line/col and scope/inline. This + /// forwards to \a DILocation::get(). + /// + /// If \c !Scope, returns a default-constructed \a DebugLoc. + /// + /// FIXME: Remove this. Users should use DILocation::get(). + static DebugLoc get(unsigned Line, unsigned Col, const MDNode *Scope, + const MDNode *InlinedAt = nullptr); unsigned getLine() const; unsigned getCol() const; - - /// getScope - This returns the scope pointer for this DebugLoc, or null if - /// invalid. MDNode *getScope() const; - MDNode *getScope(const LLVMContext &) const { return getScope(); } - - /// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or - /// null if invalid or not present. - MDNode *getInlinedAt() const; - MDNode *getInlinedAt(const LLVMContext &) const { return getInlinedAt(); } - - /// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values. - void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const; - void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, - const LLVMContext &) const { - return getScopeAndInlinedAt(Scope, IA); - } - - /// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid. - MDNode *getScopeNode() const; - MDNode *getScopeNode(const LLVMContext &) const { return getScopeNode(); } - - // getFnDebugLoc - Walk up the scope chain of given debug loc and find line - // number info for the function. + DILocation *getInlinedAt() const; + + /// \brief Get the fully inlined-at scope for a DebugLoc. + /// + /// Gets the inlined-at scope for a DebugLoc. + MDNode *getInlinedAtScope() const; + + /// \brief Find the debug info location for the start of the function. + /// + /// Walk up the scope chain of given debug loc and find line number info + /// for the function. + /// + /// FIXME: Remove this. Users should use DILocation/DILocalScope API to + /// find the subprogram, and then DILocation::get(). DebugLoc getFnDebugLoc() const; - DebugLoc getFnDebugLoc(const LLVMContext &) const { - return getFnDebugLoc(); - } - /// getAsMDNode - This method converts the compressed DebugLoc node into a - /// DILocation compatible MDNode. - MDNode *getAsMDNode() const; - MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); } + /// \brief Return \c this as a bar \a MDNode. + MDNode *getAsMDNode() const { return Loc; } bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } - bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } + bool operator!=(const DebugLoc &DL) const { return Loc != DL.Loc; } void dump() const; - void dump(const LLVMContext &) const { dump(); } + /// \brief prints source location /path/to/file.exe:line:col @[inlined at] void print(raw_ostream &OS) const; - void print(const LLVMContext &, raw_ostream &OS) const { print(OS); } }; } // end namespace llvm diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index 182015c98aa2..38f1af0d70da 100644 --- a/include/llvm/IR/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -94,8 +94,8 @@ public: /// FunctionType - Class to represent function types /// class FunctionType : public Type { - FunctionType(const FunctionType &) LLVM_DELETED_FUNCTION; - const FunctionType &operator=(const FunctionType &) LLVM_DELETED_FUNCTION; + FunctionType(const FunctionType &) = delete; + const FunctionType &operator=(const FunctionType &) = delete; FunctionType(Type *Result, ArrayRef<Type*> Params, bool IsVarArgs); public: @@ -188,8 +188,8 @@ public: /// generator for a target expects). /// class StructType : public CompositeType { - StructType(const StructType &) LLVM_DELETED_FUNCTION; - const StructType &operator=(const StructType &) LLVM_DELETED_FUNCTION; + StructType(const StructType &) = delete; + const StructType &operator=(const StructType &) = delete; StructType(LLVMContext &C) : CompositeType(C, StructTyID), SymbolTableEntry(nullptr) {} enum { @@ -308,8 +308,8 @@ public: /// class SequentialType : public CompositeType { Type *ContainedType; ///< Storage for the single contained type. - SequentialType(const SequentialType &) LLVM_DELETED_FUNCTION; - const SequentialType &operator=(const SequentialType &) LLVM_DELETED_FUNCTION; + SequentialType(const SequentialType &) = delete; + const SequentialType &operator=(const SequentialType &) = delete; protected: SequentialType(TypeID TID, Type *ElType) @@ -335,8 +335,8 @@ public: class ArrayType : public SequentialType { uint64_t NumElements; - ArrayType(const ArrayType &) LLVM_DELETED_FUNCTION; - const ArrayType &operator=(const ArrayType &) LLVM_DELETED_FUNCTION; + ArrayType(const ArrayType &) = delete; + const ArrayType &operator=(const ArrayType &) = delete; ArrayType(Type *ElType, uint64_t NumEl); public: /// ArrayType::get - This static method is the primary way to construct an @@ -361,8 +361,8 @@ public: class VectorType : public SequentialType { unsigned NumElements; - VectorType(const VectorType &) LLVM_DELETED_FUNCTION; - const VectorType &operator=(const VectorType &) LLVM_DELETED_FUNCTION; + VectorType(const VectorType &) = delete; + const VectorType &operator=(const VectorType &) = delete; VectorType(Type *ElType, unsigned NumEl); public: /// VectorType::get - This static method is the primary way to construct an @@ -446,8 +446,8 @@ public: /// PointerType - Class to represent pointers. /// class PointerType : public SequentialType { - PointerType(const PointerType &) LLVM_DELETED_FUNCTION; - const PointerType &operator=(const PointerType &) LLVM_DELETED_FUNCTION; + PointerType(const PointerType &) = delete; + const PointerType &operator=(const PointerType &) = delete; explicit PointerType(Type *ElType, unsigned AddrSpace); public: /// PointerType::get - This constructs a pointer to an object of the specified @@ -464,6 +464,9 @@ public: /// element type. static bool isValidElementType(Type *ElemTy); + /// Return true if we can load or store from a pointer to this type. + static bool isLoadableOrStorableType(Type *ElemTy); + /// @brief Return the address space of the Pointer type. inline unsigned getAddressSpace() const { return getSubclassData(); } diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index c6a8854e0774..6db5a40c5772 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -20,6 +20,7 @@ #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Module.h" #include "llvm/Support/Casting.h" +#include <functional> namespace llvm { diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 51403281e964..6c228eae633a 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -19,6 +19,7 @@ #define LLVM_IR_FUNCTION_H #include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/Optional.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" @@ -31,26 +32,6 @@ namespace llvm { class FunctionType; class LLVMContext; -// Traits for intrusive list of basic blocks... -template<> struct ilist_traits<BasicBlock> - : public SymbolTableListTraits<BasicBlock, Function> { - - // createSentinel is used to get hold of the node that marks the end of the - // list... (same trick used here as in ilist_traits<Instruction>) - BasicBlock *createSentinel() const { - return static_cast<BasicBlock*>(&Sentinel); - } - static void destroySentinel(BasicBlock*) {} - - BasicBlock *provideInitialHead() const { return createSentinel(); } - BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); } - static void noteHead(BasicBlock*, BasicBlock*) {} - - static ValueSymbolTable *getSymTab(Function *ItemParent); -private: - mutable ilist_half_node<BasicBlock> Sentinel; -}; - template<> struct ilist_traits<Argument> : public SymbolTableListTraits<Argument, Function> { @@ -86,6 +67,7 @@ private: mutable ArgumentListType ArgumentList; ///< The formal arguments ValueSymbolTable *SymTab; ///< Symbol table of args/instructions AttributeSet AttributeSets; ///< Parameter attributes + FunctionType *Ty; /* * Value::SubclassData @@ -96,6 +78,17 @@ private: * bit 3-6: CallingConvention */ + /// Bits from GlobalObject::GlobalObjectSubclassData. + enum { + /// Whether this function is materializable. + IsMaterializableBit = 1 << 0, + HasMetadataHashEntryBit = 1 << 1 + }; + void setGlobalObjectBit(unsigned Mask, bool Value) { + setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) | + (Value ? Mask : 0u)); + } + friend class SymbolTableListTraits<Function, Module>; void setParent(Module *parent); @@ -113,12 +106,8 @@ private: } void BuildLazyArguments() const; - Function(const Function&) LLVM_DELETED_FUNCTION; - void operator=(const Function&) LLVM_DELETED_FUNCTION; - - /// Do the actual lookup of an intrinsic ID when the query could not be - /// answered from the cache. - unsigned lookupIntrinsicID() const LLVM_READONLY; + Function(const Function&) = delete; + void operator=(const Function&) = delete; /// Function ctor - If the (optional) Module argument is specified, the /// function is automatically inserted into the end of the function list for @@ -133,13 +122,13 @@ public: return new(0) Function(Ty, Linkage, N, M); } - ~Function(); + ~Function() override; Type *getReturnType() const; // Return the type of the ret val FunctionType *getFunctionType() const; // Return the FunctionType for me - /// getContext - Return a pointer to the LLVMContext associated with this - /// function, or NULL if this function is not bound to a context yet. + /// getContext - Return a reference to the LLVMContext associated with this + /// function. LLVMContext &getContext() const; /// isVarArg - Return true if this function takes a variable number of @@ -154,13 +143,17 @@ public: /// intrinsic, or if the pointer is null. This value is always defined to be /// zero to allow easy checking for whether a function is intrinsic or not. /// The particular intrinsic functions which correspond to this value are - /// defined in llvm/Intrinsics.h. Results are cached in the LLVM context, - /// subsequent requests for the same ID return results much faster from the - /// cache. - /// - unsigned getIntrinsicID() const LLVM_READONLY; + /// defined in llvm/Intrinsics.h. + Intrinsic::ID getIntrinsicID() const LLVM_READONLY { return IntID; } bool isIntrinsic() const { return getName().startswith("llvm."); } + /// \brief Recalculate the ID for this function if it is an Intrinsic defined + /// in llvm/Intrinsics.h. Sets the intrinsic ID to Intrinsic::not_intrinsic + /// if the name of this function does not match an intrinsic in that header. + /// Note, this method does not need to be called directly, as it is called + /// from Value::setName() whenever the name of this function changes. + void recalculateIntrinsicID(); + /// getCallingConv()/setCallingConv(CC) - These method get and set the /// calling convention of this function. The enum values for the known /// calling conventions are defined in CallingConv.h. @@ -202,6 +195,12 @@ public: AttributeSet::FunctionIndex, Kind, Value)); } + /// Set the entry count for this function. + void setEntryCount(uint64_t Count); + + /// Get the entry count for this function. + Optional<uint64_t> getEntryCount() const; + /// @brief Return true if the function has the attribute. bool hasFnAttribute(Attribute::AttrKind Kind) const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); @@ -218,6 +217,11 @@ public: return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); } + /// \brief Return the stack alignment for the function. + unsigned getFnStackAlignment() const { + return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex); + } + /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm /// to use during code generation. bool hasGC() const; @@ -234,6 +238,13 @@ public: /// @brief removes the attributes from the list of attributes. void removeAttributes(unsigned i, AttributeSet attr); + /// @brief adds the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + + /// @brief adds the dereferenceable_or_null attribute to the list of + /// attributes. + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); + /// @brief Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned i) const { return AttributeSets.getParamAlignment(i); @@ -244,7 +255,13 @@ public: uint64_t getDereferenceableBytes(unsigned i) const { return AttributeSets.getDereferenceableBytes(i); } - + + /// @brief Extract the number of dereferenceable_or_null bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableOrNullBytes(unsigned i) const { + return AttributeSets.getDereferenceableOrNullBytes(i); + } + /// @brief Determine if the function does not access memory. bool doesNotAccessMemory() const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, @@ -291,6 +308,16 @@ public: addFnAttr(Attribute::NoDuplicate); } + /// @brief Determine if the call is convergent. + bool isConvergent() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::Convergent); + } + void setConvergent() { + addFnAttr(Attribute::Convergent); + } + + /// @brief True if the ABI mandates (or the user requested) that this /// function be in a unwind table. bool hasUWTable() const { @@ -464,6 +491,10 @@ public: Constant *getPrologueData() const; void setPrologueData(Constant *PrologueData); + /// Print the function to an output stream with an optional + /// AssemblyAnnotationWriter. + void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW = nullptr) const; + /// viewCFG - This function is meant for use from the debugger. You can just /// say 'call F->viewCFG()' and a ghostview window should pop up from the /// program, displaying the CFG of the current function with the code for each @@ -514,12 +545,50 @@ public: /// setjmp or other function that gcc recognizes as "returning twice". bool callsFunctionThatReturnsTwice() const; + /// \brief Check if this has any metadata. + bool hasMetadata() const { return hasMetadataHashEntry(); } + + /// \brief Get the current metadata attachment, if any. + /// + /// Returns \c nullptr if such an attachment is missing. + /// @{ + MDNode *getMetadata(unsigned KindID) const; + MDNode *getMetadata(StringRef Kind) const; + /// @} + + /// \brief Set a particular kind of metadata attachment. + /// + /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or + /// replacing it if it already exists. + /// @{ + void setMetadata(unsigned KindID, MDNode *MD); + void setMetadata(StringRef Kind, MDNode *MD); + /// @} + + /// \brief Get all current metadata attachments. + void + getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const; + + /// \brief Drop metadata not in the given list. + /// + /// Drop all metadata from \c this not included in \c KnownIDs. + void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs); + private: // Shadow Value::setValueSubclassData with a private forwarding method so that // subclasses cannot accidentally use it. void setValueSubclassData(unsigned short D) { Value::setValueSubclassData(D); } + + bool hasMetadataHashEntry() const { + return getGlobalObjectSubClassData() & HasMetadataHashEntryBit; + } + void setHasMetadataHashEntry(bool HasEntry) { + setGlobalObjectBit(HasMetadataHashEntryBit, HasEntry); + } + + void clearMetadata(); }; inline ValueSymbolTable * diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index 6f57dc2a98a6..1d6c9157f0b8 100644 --- a/include/llvm/IR/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -47,11 +47,14 @@ public: /// lazily. If the Materializer doesn't support this capability, this method /// is a noop. /// - virtual void Dematerialize(GlobalValue *) {} + virtual void dematerialize(GlobalValue *) {} /// Make sure the entire Module has been completely read. /// - virtual std::error_code MaterializeModule(Module *M) = 0; + virtual std::error_code materializeModule(Module *M) = 0; + + virtual std::error_code materializeMetadata() = 0; + virtual void setStripDebugInfo() = 0; virtual std::vector<StructType *> getIdentifiedStructTypes() const = 0; }; diff --git a/include/llvm/IR/GetElementPtrTypeIterator.h b/include/llvm/IR/GetElementPtrTypeIterator.h index dcf8e64dbb27..6bba0ae29e98 100644 --- a/include/llvm/IR/GetElementPtrTypeIterator.h +++ b/include/llvm/IR/GetElementPtrTypeIterator.h @@ -16,7 +16,9 @@ #define LLVM_IR_GETELEMENTPTRTYPEITERATOR_H #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Operator.h" #include "llvm/IR/User.h" +#include "llvm/ADT/PointerIntPair.h" namespace llvm { template<typename ItTy = User::const_op_iterator> @@ -26,19 +28,28 @@ namespace llvm { Type *, ptrdiff_t> super; ItTy OpIt; - Type *CurTy; + PointerIntPair<Type *, 1> CurTy; + unsigned AddrSpace; generic_gep_type_iterator() {} public: static generic_gep_type_iterator begin(Type *Ty, ItTy It) { generic_gep_type_iterator I; - I.CurTy = Ty; + I.CurTy.setPointer(Ty); + I.OpIt = It; + return I; + } + static generic_gep_type_iterator begin(Type *Ty, unsigned AddrSpace, + ItTy It) { + generic_gep_type_iterator I; + I.CurTy.setPointer(Ty); + I.CurTy.setInt(true); + I.AddrSpace = AddrSpace; I.OpIt = It; return I; } static generic_gep_type_iterator end(ItTy It) { generic_gep_type_iterator I; - I.CurTy = nullptr; I.OpIt = It; return I; } @@ -51,11 +62,15 @@ namespace llvm { } Type *operator*() const { - return CurTy; + if (CurTy.getInt()) + return CurTy.getPointer()->getPointerTo(AddrSpace); + return CurTy.getPointer(); } Type *getIndexedType() const { - CompositeType *CT = cast<CompositeType>(CurTy); + if (CurTy.getInt()) + return CurTy.getPointer(); + CompositeType *CT = cast<CompositeType>(CurTy.getPointer()); return CT->getTypeAtIndex(getOperand()); } @@ -66,10 +81,13 @@ namespace llvm { Value *getOperand() const { return *OpIt; } generic_gep_type_iterator& operator++() { // Preincrement - if (CompositeType *CT = dyn_cast<CompositeType>(CurTy)) { - CurTy = CT->getTypeAtIndex(getOperand()); + if (CurTy.getInt()) { + CurTy.setInt(false); + } else if (CompositeType *CT = + dyn_cast<CompositeType>(CurTy.getPointer())) { + CurTy.setPointer(CT->getTypeAtIndex(getOperand())); } else { - CurTy = nullptr; + CurTy.setPointer(nullptr); } ++OpIt; return *this; @@ -83,15 +101,23 @@ namespace llvm { typedef generic_gep_type_iterator<> gep_type_iterator; inline gep_type_iterator gep_type_begin(const User *GEP) { - return gep_type_iterator::begin - (GEP->getOperand(0)->getType()->getScalarType(), GEP->op_begin()+1); + auto *GEPOp = cast<GEPOperator>(GEP); + return gep_type_iterator::begin( + GEPOp->getSourceElementType(), + cast<PointerType>(GEPOp->getPointerOperandType()->getScalarType()) + ->getAddressSpace(), + GEP->op_begin() + 1); } inline gep_type_iterator gep_type_end(const User *GEP) { return gep_type_iterator::end(GEP->op_end()); } inline gep_type_iterator gep_type_begin(const User &GEP) { - return gep_type_iterator::begin - (GEP.getOperand(0)->getType()->getScalarType(), GEP.op_begin()+1); + auto &GEPOp = cast<GEPOperator>(GEP); + return gep_type_iterator::begin( + GEPOp.getSourceElementType(), + cast<PointerType>(GEPOp.getPointerOperandType()->getScalarType()) + ->getAddressSpace(), + GEP.op_begin() + 1); } inline gep_type_iterator gep_type_end(const User &GEP) { return gep_type_iterator::end(GEP.op_end()); diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index 075b5703bccf..ce73b7af8ca1 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -28,13 +28,13 @@ template<typename ValueSubClass, typename ItemParentClass> class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> { friend class SymbolTableListTraits<GlobalAlias, Module>; - void operator=(const GlobalAlias &) LLVM_DELETED_FUNCTION; - GlobalAlias(const GlobalAlias &) LLVM_DELETED_FUNCTION; + void operator=(const GlobalAlias &) = delete; + GlobalAlias(const GlobalAlias &) = delete; void setParent(Module *parent); - GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, - const Twine &Name, Constant *Aliasee, Module *Parent); + GlobalAlias(PointerType *Ty, LinkageTypes Linkage, const Twine &Name, + Constant *Aliasee, Module *Parent); public: // allocate space for exactly one operand @@ -44,19 +44,17 @@ public: /// If a parent module is specified, the alias is automatically inserted into /// the end of the specified module's alias list. - static GlobalAlias *create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - Constant *Aliasee, Module *Parent); + static GlobalAlias *create(PointerType *Ty, LinkageTypes Linkage, + const Twine &Name, Constant *Aliasee, + Module *Parent); // Without the Aliasee. - static GlobalAlias *create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - Module *Parent); + static GlobalAlias *create(PointerType *Ty, LinkageTypes Linkage, + const Twine &Name, Module *Parent); // The module is taken from the Aliasee. - static GlobalAlias *create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - GlobalValue *Aliasee); + static GlobalAlias *create(PointerType *Ty, LinkageTypes Linkage, + const Twine &Name, GlobalValue *Aliasee); // Type, Parent and AddressSpace taken from the Aliasee. static GlobalAlias *create(LinkageTypes Linkage, const Twine &Name, diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 546fea2dfa9b..f0552410b61d 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -24,10 +24,10 @@ class Comdat; class Module; class GlobalObject : public GlobalValue { - GlobalObject(const GlobalObject &) LLVM_DELETED_FUNCTION; + GlobalObject(const GlobalObject &) = delete; protected: - GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, + GlobalObject(PointerType *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, LinkageTypes Linkage, const Twine &Name) : GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name), ObjComdat(nullptr) { setGlobalValueSubClassData(0); diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index d0f7e9a11790..1dfe0c28b02c 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -28,8 +28,12 @@ class Comdat; class PointerType; class Module; +namespace Intrinsic { + enum ID : unsigned; +} + class GlobalValue : public Constant { - GlobalValue(const GlobalValue &) LLVM_DELETED_FUNCTION; + GlobalValue(const GlobalValue &) = delete; public: /// @brief An enumeration for the kinds of linkage for global values. enum LinkageTypes { @@ -61,12 +65,12 @@ public: }; protected: - GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, + GlobalValue(PointerType *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, LinkageTypes Linkage, const Twine &Name) : Constant(Ty, VTy, Ops, NumOps), Linkage(Linkage), Visibility(DefaultVisibility), UnnamedAddr(0), DllStorageClass(DefaultStorageClass), - ThreadLocal(NotThreadLocal), Parent(nullptr) { + ThreadLocal(NotThreadLocal), IntID((Intrinsic::ID)0U), Parent(nullptr) { setName(Name); } @@ -84,7 +88,16 @@ private: // Give subclasses access to what otherwise would be wasted padding. // (19 + 3 + 2 + 1 + 2 + 5) == 32. unsigned SubClassData : 19; + protected: + /// \brief The intrinsic ID for this subclass (which must be a Function). + /// + /// This member is defined by this class, but not used for anything. + /// Subclasses can use it to store their intrinsic ID, if they have one. + /// + /// This is stored here to save space in Function on 64-bit hosts. + Intrinsic::ID IntID; + static const unsigned GlobalValueSubClassDataBits = 19; unsigned getGlobalValueSubClassData() const { return SubClassData; @@ -104,7 +117,7 @@ public: LocalExecTLSModel }; - ~GlobalValue() { + ~GlobalValue() override { removeDeadConstantUsers(); // remove any dead constants using this. } @@ -165,9 +178,9 @@ public: const char *getSection() const; /// Global values are always pointers. - inline PointerType *getType() const { - return cast<PointerType>(User::getType()); - } + PointerType *getType() const { return cast<PointerType>(User::getType()); } + + Type *getValueType() const { return getType()->getElementType(); } static LinkageTypes getLinkOnceLinkage(bool ODR) { return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; @@ -317,7 +330,7 @@ public: /// If this GlobalValue is read in, and if the GVMaterializer supports it, /// release the memory for the function, and set it up to be materialized /// lazily. If !isDematerializable(), this method is a noop. - void Dematerialize(); + void dematerialize(); /// @} @@ -343,13 +356,11 @@ public: virtual void eraseFromParent() = 0; /// Get the module that this global value is contained inside of... - inline Module *getParent() { return Parent; } - inline const Module *getParent() const { return Parent; } - - const DataLayout *getDataLayout() const; + Module *getParent() { return Parent; } + const Module *getParent() const { return Parent; } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Value *V) { + static bool classof(const Value *V) { return V->getValueID() == Value::FunctionVal || V->getValueID() == Value::GlobalVariableVal || V->getValueID() == Value::GlobalAliasVal; diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 4189ccb90a54..9f57705dae72 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -34,9 +34,9 @@ template<typename ValueSubClass, typename ItemParentClass> class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> { friend class SymbolTableListTraits<GlobalVariable, Module>; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - void operator=(const GlobalVariable &) LLVM_DELETED_FUNCTION; - GlobalVariable(const GlobalVariable &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + void operator=(const GlobalVariable &) = delete; + GlobalVariable(const GlobalVariable &) = delete; void setParent(Module *parent); @@ -66,7 +66,7 @@ public: ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, bool isExternallyInitialized = false); - ~GlobalVariable() { + ~GlobalVariable() override { NumOperands = 1; // FIXME: needed by operator delete } diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index e5f62fb9625e..adf692469ad3 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -21,6 +21,8 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/ConstantFolder.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Operator.h" @@ -115,17 +117,15 @@ public: } /// \brief Set location information used by debugging information. - void SetCurrentDebugLocation(const DebugLoc &L) { - CurDbgLocation = L; - } + void SetCurrentDebugLocation(DebugLoc L) { CurDbgLocation = std::move(L); } /// \brief Get location information used by debugging information. - DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; } + const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; } /// \brief If this builder has a current debug location, set it on the /// specified instruction. void SetInstDebugLocation(Instruction *I) const { - if (!CurDbgLocation.isUnknown()) + if (CurDbgLocation) I->setDebugLoc(CurDbgLocation); } @@ -200,8 +200,8 @@ public: BasicBlock::iterator Point; DebugLoc DbgLoc; - InsertPointGuard(const InsertPointGuard &) LLVM_DELETED_FUNCTION; - InsertPointGuard &operator=(const InsertPointGuard &) LLVM_DELETED_FUNCTION; + InsertPointGuard(const InsertPointGuard &) = delete; + InsertPointGuard &operator=(const InsertPointGuard &) = delete; public: InsertPointGuard(IRBuilderBase &B) @@ -221,9 +221,9 @@ public: FastMathFlags FMF; MDNode *FPMathTag; - FastMathFlagGuard(const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + FastMathFlagGuard(const FastMathFlagGuard &) = delete; FastMathFlagGuard &operator=( - const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + const FastMathFlagGuard &) = delete; public: FastMathFlagGuard(IRBuilderBase &B) @@ -245,7 +245,7 @@ public: /// filled in with the null terminated string value specified. The new global /// variable will be marked mergable with any others of the same contents. If /// Name is specified, it is the name of the global variable created. - Value *CreateGlobalString(StringRef Str, const Twine &Name = ""); + GlobalVariable *CreateGlobalString(StringRef Str, const Twine &Name = ""); /// \brief Get a constant value representing either true or false. ConstantInt *getInt1(bool V) { @@ -322,6 +322,11 @@ public: return Type::getInt64Ty(Context); } + /// \brief Fetch the type representing a 128-bit integer. + IntegerType *getInt128Ty() { + return Type::getInt128Ty(Context); + } + /// \brief Fetch the type representing an N-bit integer. IntegerType *getIntNTy(unsigned N) { return Type::getIntNTy(Context, N); @@ -353,8 +358,8 @@ public: } /// \brief Fetch the type representing a pointer to an integer value. - IntegerType* getIntPtrTy(const DataLayout *DL, unsigned AddrSpace = 0) { - return DL->getIntPtrType(Context, AddrSpace); + IntegerType *getIntPtrTy(const DataLayout &DL, unsigned AddrSpace = 0) { + return DL.getIntPtrType(Context, AddrSpace); } //===--------------------------------------------------------------------===// @@ -443,11 +448,40 @@ public: /// \brief Create a call to the experimental.gc.statepoint intrinsic to /// start a new statepoint sequence. - CallInst *CreateGCStatepoint(Value *ActualCallee, - ArrayRef<Value*> CallArgs, - ArrayRef<Value*> DeoptArgs, - ArrayRef<Value*> GCArgs, - const Twine &Name = ""); + CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualCallee, + ArrayRef<Value *> CallArgs, + ArrayRef<Value *> DeoptArgs, + ArrayRef<Value *> GCArgs, + const Twine &Name = ""); + + // \brief Conveninence function for the common case when CallArgs are filled + // in using makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be + // .get()'ed to get the Value pointer. + CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualCallee, ArrayRef<Use> CallArgs, + ArrayRef<Value *> DeoptArgs, + ArrayRef<Value *> GCArgs, + const Twine &Name = ""); + + /// brief Create an invoke to the experimental.gc.statepoint intrinsic to + /// start a new statepoint sequence. + InvokeInst * + CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualInvokee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, ArrayRef<Value *> InvokeArgs, + ArrayRef<Value *> DeoptArgs, + ArrayRef<Value *> GCArgs, const Twine &Name = ""); + + // Conveninence function for the common case when CallArgs are filled in using + // makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be .get()'ed to + // get the Value *. + InvokeInst * + CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualInvokee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, ArrayRef<Use> InvokeArgs, + ArrayRef<Value *> DeoptArgs, + ArrayRef<Value *> GCArgs, const Twine &Name = ""); /// \brief Create a call to the experimental.gc.result intrinsic to extract /// the result from a call wrapped in a statepoint. @@ -466,7 +500,7 @@ public: private: /// \brief Create a call to a masked intrinsic with given Id. /// Masked intrinsic has only one overloaded type - data type. - CallInst *CreateMaskedIntrinsic(unsigned Id, ArrayRef<Value *> Ops, + CallInst *CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef<Value *> Ops, Type *DataTy, const Twine &Name = ""); Value *getCastedInt8PtrValue(Value *Ptr); @@ -959,6 +993,9 @@ public: LoadInst *CreateLoad(Value *Ptr, const Twine &Name = "") { return Insert(new LoadInst(Ptr), Name); } + LoadInst *CreateLoad(Type *Ty, Value *Ptr, const Twine &Name = "") { + return Insert(new LoadInst(Ty, Ptr), Name); + } LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const Twine &Name = "") { return Insert(new LoadInst(Ptr, nullptr, isVolatile), Name); } @@ -1011,6 +1048,10 @@ public: } Value *CreateGEP(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &Name = "") { + return CreateGEP(nullptr, Ptr, IdxList, Name); + } + Value *CreateGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, + const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) { // Every index must be constant. size_t i, e; @@ -1018,12 +1059,16 @@ public: if (!isa<Constant>(IdxList[i])) break; if (i == e) - return Insert(Folder.CreateGetElementPtr(PC, IdxList), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, IdxList), Name); } - return Insert(GetElementPtrInst::Create(Ptr, IdxList), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, IdxList), Name); } Value *CreateInBoundsGEP(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &Name = "") { + return CreateInBoundsGEP(nullptr, Ptr, IdxList, Name); + } + Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, + const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) { // Every index must be constant. size_t i, e; @@ -1031,79 +1076,88 @@ public: if (!isa<Constant>(IdxList[i])) break; if (i == e) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, IdxList), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IdxList), + Name); } - return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxList), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList), Name); } Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + return CreateGEP(nullptr, Ptr, Idx, Name); + } + Value *CreateGEP(Type *Ty, Value *Ptr, Value *Idx, const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Insert(Folder.CreateGetElementPtr(PC, IC), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, IC), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); } - Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, Value *Idx, + const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, IC), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IC), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { + return CreateConstGEP1_32(nullptr, Ptr, Idx0, Name); + } + Value *CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, + const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, Idx), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); } - Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, + Value *CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idx), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } - Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, - const Twine &Name = "") { + Value *CreateConstGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, + const Twine &Name = "") { Value *Idxs[] = { ConstantInt::get(Type::getInt32Ty(Context), Idx0), ConstantInt::get(Type::getInt32Ty(Context), Idx1) }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, Idxs), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name); } - Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, - const Twine &Name = "") { + Value *CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, + unsigned Idx1, const Twine &Name = "") { Value *Idxs[] = { ConstantInt::get(Type::getInt32Ty(Context), Idx0), ConstantInt::get(Type::getInt32Ty(Context), Idx1) }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idxs), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name); } Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idx), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name); } Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idx), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name); } Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { @@ -1113,9 +1167,9 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idxs), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idxs), Name); } Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { @@ -1125,21 +1179,23 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idxs), + Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idxs), Name); } - Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { - return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); + Value *CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, + const Twine &Name = "") { + return CreateConstInBoundsGEP2_32(Ty, Ptr, 0, Idx, Name); } /// \brief Same as CreateGlobalString, but return a pointer with "i8*" type /// instead of a pointer to array of i8. Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "") { - Value *gv = CreateGlobalString(Str, Name); + GlobalVariable *gv = CreateGlobalString(Str, Name); Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); Value *Args[] = { zero, zero }; - return CreateInBoundsGEP(gv, Args, Name); + return CreateInBoundsGEP(gv->getValueType(), gv, Args, Name); } //===--------------------------------------------------------------------===// @@ -1297,7 +1353,7 @@ private: // \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a // compile time error, instead of converting the string to bool for the // isSigned parameter. - Value *CreateIntCast(Value *, Type *, const char *) LLVM_DELETED_FUNCTION; + Value *CreateIntCast(Value *, Type *, const char *) = delete; public: Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) @@ -1409,36 +1465,19 @@ public: return Insert(PHINode::Create(Ty, NumReservedValues), Name); } - CallInst *CreateCall(Value *Callee, const Twine &Name = "") { - return Insert(CallInst::Create(Callee), Name); - } - CallInst *CreateCall(Value *Callee, Value *Arg, const Twine &Name = "") { - return Insert(CallInst::Create(Callee, Arg), Name); - } - CallInst *CreateCall2(Value *Callee, Value *Arg1, Value *Arg2, - const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2 }; - return Insert(CallInst::Create(Callee, Args), Name); - } - CallInst *CreateCall3(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3 }; - return Insert(CallInst::Create(Callee, Args), Name); - } - CallInst *CreateCall4(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - Value *Arg4, const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3, Arg4 }; + CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args, + const Twine &Name = "") { return Insert(CallInst::Create(Callee, Args), Name); } - CallInst *CreateCall5(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - Value *Arg4, Value *Arg5, const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3, Arg4, Arg5 }; - return Insert(CallInst::Create(Callee, Args), Name); + + CallInst *CreateCall(llvm::FunctionType *FTy, Value *Callee, + ArrayRef<Value *> Args, const Twine &Name = "") { + return Insert(CallInst::Create(FTy, Callee, Args), Name); } - CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args, + CallInst *CreateCall(Function *Callee, ArrayRef<Value *> Args, const Twine &Name = "") { - return Insert(CallInst::Create(Callee, Args), Name); + return CreateCall(Callee->getFunctionType(), Callee, Args, Name); } Value *CreateSelect(Value *C, Value *True, Value *False, @@ -1462,6 +1501,11 @@ public: return Insert(ExtractElementInst::Create(Vec, Idx), Name); } + Value *CreateExtractElement(Value *Vec, uint64_t Idx, + const Twine &Name = "") { + return CreateExtractElement(Vec, getInt64(Idx), Name); + } + Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx, const Twine &Name = "") { if (Constant *VC = dyn_cast<Constant>(Vec)) @@ -1471,6 +1515,11 @@ public: return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name); } + Value *CreateInsertElement(Value *Vec, Value *NewElt, uint64_t Idx, + const Twine &Name = "") { + return CreateInsertElement(Vec, NewElt, getInt64(Idx), Name); + } + Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name = "") { if (Constant *V1C = dyn_cast<Constant>(V1)) @@ -1480,6 +1529,16 @@ public: return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); } + Value *CreateShuffleVector(Value *V1, Value *V2, ArrayRef<int> IntMask, + const Twine &Name = "") { + size_t MaskSize = IntMask.size(); + SmallVector<Constant*, 8> MaskVec(MaskSize); + for (size_t i = 0; i != MaskSize; ++i) + MaskVec[i] = getInt32(IntMask[i]); + Value *Mask = ConstantVector::get(MaskVec); + return CreateShuffleVector(V1, V2, Mask, Name); + } + Value *CreateExtractValue(Value *Agg, ArrayRef<unsigned> Idxs, const Twine &Name = "") { @@ -1589,7 +1648,7 @@ public: "trying to create an alignment assumption on a non-pointer?"); PointerType *PtrTy = cast<PointerType>(PtrValue->getType()); - Type *IntPtrTy = getIntPtrTy(&DL, PtrTy->getAddressSpace()); + Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint"); Value *Mask = ConstantInt::get(IntPtrTy, diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h index 7f2027b6e297..5f1d56f7e831 100644 --- a/include/llvm/IR/IRPrintingPasses.h +++ b/include/llvm/IR/IRPrintingPasses.h @@ -34,7 +34,8 @@ class raw_ostream; /// \brief Create and return a pass that writes the module to the specified /// \c raw_ostream. ModulePass *createPrintModulePass(raw_ostream &OS, - const std::string &Banner = ""); + const std::string &Banner = "", + bool ShouldPreserveUseListOrder = false); /// \brief Create and return a pass that prints functions to the specified /// \c raw_ostream as they are processed. @@ -53,10 +54,12 @@ BasicBlockPass *createPrintBasicBlockPass(raw_ostream &OS, class PrintModulePass { raw_ostream &OS; std::string Banner; + bool ShouldPreserveUseListOrder; public: PrintModulePass(); - PrintModulePass(raw_ostream &OS, const std::string &Banner = ""); + PrintModulePass(raw_ostream &OS, const std::string &Banner = "", + bool ShouldPreserveUseListOrder = false); PreservedAnalyses run(Module &M); diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index b2d79d0f0bfc..15942f16e67e 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -40,8 +40,8 @@ private: friend struct InlineAsmKeyType; friend class ConstantUniqueMap<InlineAsm>; - InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION; - void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION; + InlineAsm(const InlineAsm &) = delete; + void operator=(const InlineAsm&) = delete; std::string AsmString, Constraints; bool HasSideEffects; @@ -51,7 +51,7 @@ private: InlineAsm(PointerType *Ty, const std::string &AsmString, const std::string &Constraints, bool hasSideEffects, bool isAlignStack, AsmDialect asmDialect); - virtual ~InlineAsm(); + ~InlineAsm() override; /// When the ConstantUniqueMap merges two types and makes two InlineAsms /// identical, it destroys one of them with this method. @@ -189,6 +189,20 @@ public: // These are helper methods for dealing with flags in the INLINEASM SDNode // in the backend. + // + // The encoding of the flag word is currently: + // Bits 2-0 - A Kind_* value indicating the kind of the operand. + // Bits 15-3 - The number of SDNode operands associated with this inline + // assembly operand. + // If bit 31 is set: + // Bit 30-16 - The operand number that this operand must match. + // When bits 2-0 are Kind_Mem, the Constraint_* value must be + // obtained from the flags for this operand number. + // Else if bits 2-0 are Kind_Mem: + // Bit 30-16 - A Constraint_* value indicating the original constraint + // code. + // Else: + // Bit 30-16 - The register class ID to use for the operand. enum : uint32_t { // Fixed operands on an INLINEASM SDNode. @@ -220,6 +234,27 @@ public: Kind_Imm = 5, // Immediate. Kind_Mem = 6, // Memory operand, "m". + // Memory constraint codes. + // These could be tablegenerated but there's little need to do that since + // there's plenty of space in the encoding to support the union of all + // constraint codes for all targets. + Constraint_Unknown = 0, + Constraint_es, + Constraint_i, + Constraint_m, + Constraint_o, + Constraint_v, + Constraint_Q, + Constraint_R, + Constraint_S, + Constraint_T, + Constraint_X, + Constraint_Z, + Constraint_ZC, + Constraint_Zy, + Constraints_Max = Constraint_Zy, + Constraints_ShiftAmount = 16, + Flag_MatchingOperand = 0x80000000 }; @@ -252,6 +287,20 @@ public: return InputFlag | (RC << 16); } + /// Augment an existing flag word returned by getFlagWord with the constraint + /// code for a memory constraint. + static unsigned getFlagWordForMem(unsigned InputFlag, unsigned Constraint) { + assert(Constraint <= 0x7fff && "Too large a memory constraint ID"); + assert(Constraint <= Constraints_Max && "Unknown constraint ID"); + assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); + return InputFlag | (Constraint << Constraints_ShiftAmount); + } + + static unsigned convertMemFlagWordToMatchingFlagWord(unsigned InputFlag) { + assert(isMemKind(InputFlag)); + return InputFlag & ~(0x7fff << Constraints_ShiftAmount); + } + static unsigned getKind(unsigned Flags) { return Flags & 7; } @@ -266,6 +315,11 @@ public: return getKind(Flag) == Kind_Clobber; } + static unsigned getMemoryConstraintID(unsigned Flag) { + assert(isMemKind(Flag)); + return (Flag >> Constraints_ShiftAmount) & 0x7fff; + } + /// getNumOperandRegisters - Extract the number of registers field from the /// inline asm operand flag. static unsigned getNumOperandRegisters(unsigned Flag) { diff --git a/include/llvm/IR/InstIterator.h b/include/llvm/IR/InstIterator.h index 75e93bd2ff8c..f3ce6490fb66 100644 --- a/include/llvm/IR/InstIterator.h +++ b/include/llvm/IR/InstIterator.h @@ -27,15 +27,14 @@ namespace llvm { // This class implements inst_begin() & inst_end() for // inst_iterator and const_inst_iterator's. // -template <class _BB_t, class _BB_i_t, class _BI_t, class _II_t> -class InstIterator { - typedef _BB_t BBty; - typedef _BB_i_t BBIty; - typedef _BI_t BIty; - typedef _II_t IIty; - _BB_t *BBs; // BasicBlocksType - _BB_i_t BB; // BasicBlocksType::iterator - _BI_t BI; // BasicBlock::iterator +template <class BB_t, class BB_i_t, class BI_t, class II_t> class InstIterator { + typedef BB_t BBty; + typedef BB_i_t BBIty; + typedef BI_t BIty; + typedef II_t IIty; + BB_t *BBs; // BasicBlocksType + BB_i_t BB; // BasicBlocksType::iterator + BI_t BI; // BasicBlock::iterator public: typedef std::bidirectional_iterator_tag iterator_category; typedef IIty value_type; @@ -127,20 +126,32 @@ typedef InstIterator<const iplist<BasicBlock>, inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); } inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); } +inline iterator_range<inst_iterator> inst_range(Function *F) { + return iterator_range<inst_iterator>(inst_begin(F), inst_end(F)); +} inline const_inst_iterator inst_begin(const Function *F) { return const_inst_iterator(*F); } inline const_inst_iterator inst_end(const Function *F) { return const_inst_iterator(*F, true); } +inline iterator_range<const_inst_iterator> inst_range(const Function *F) { + return iterator_range<const_inst_iterator>(inst_begin(F), inst_end(F)); +} inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); } inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); } +inline iterator_range<inst_iterator> inst_range(Function &F) { + return iterator_range<inst_iterator>(inst_begin(F), inst_end(F)); +} inline const_inst_iterator inst_begin(const Function &F) { return const_inst_iterator(F); } inline const_inst_iterator inst_end(const Function &F) { return const_inst_iterator(F, true); } +inline iterator_range<const_inst_iterator> inst_range(const Function &F) { + return iterator_range<const_inst_iterator>(inst_begin(F), inst_end(F)); +} } // End llvm namespace diff --git a/include/llvm/IR/InstVisitor.h b/include/llvm/IR/InstVisitor.h index 1cdcd55448c9..581e860b8382 100644 --- a/include/llvm/IR/InstVisitor.h +++ b/include/llvm/IR/InstVisitor.h @@ -259,7 +259,7 @@ private: // Special helper function to delegate to CallInst subclass visitors. RetTy delegateCallInst(CallInst &I) { if (const Function *F = I.getCalledFunction()) { - switch ((Intrinsic::ID)F->getIntrinsicID()) { + switch (F->getIntrinsicID()) { default: DELEGATE(IntrinsicInst); case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst); case Intrinsic::dbg_value: DELEGATE(DbgValueInst); diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 030f5d690a0c..108b9eb36b7e 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -44,7 +44,7 @@ protected: : Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {} // Out of line virtual method, so the vtable, etc has a home. - ~TerminatorInst(); + ~TerminatorInst() override; /// Virtual methods - Terminators should overload these and provide inline /// overrides of non-V methods. @@ -83,7 +83,7 @@ public: //===----------------------------------------------------------------------===// class UnaryInstruction : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: UnaryInstruction(Type *Ty, unsigned iType, Value *V, @@ -102,7 +102,7 @@ public: } // Out of line virtual method, so the vtable, etc has a home. - ~UnaryInstruction(); + ~UnaryInstruction() override; /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -132,7 +132,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value) //===----------------------------------------------------------------------===// class BinaryOperator : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: void init(BinaryOps iType); BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, @@ -570,10 +570,9 @@ public: /// This ensures that any pointer<->integer cast has enough bits in the /// integer and any other cast is a bitcast. static bool isBitOrNoopPointerCastable( - Type *SrcTy, ///< The Type from which the value should be cast. - Type *DestTy, ///< The Type to which the value should be cast. - const DataLayout *Layout = 0 ///< Optional DataLayout. - ); + Type *SrcTy, ///< The Type from which the value should be cast. + Type *DestTy, ///< The Type to which the value should be cast. + const DataLayout &DL); /// Returns the opcode necessary to cast Val into Ty using usual casting /// rules. @@ -621,9 +620,9 @@ public: ) const; /// @brief Determine if this cast is a no-op cast. - bool isNoopCast( - const DataLayout *DL ///< DataLayout to get the Int Ptr type from. - ) const; + /// + /// \param DL is the DataLayout to get the Int Ptr type from. + bool isNoopCast(const DataLayout &DL) const; /// Determine how a pair of casts can be eliminated, if they can be at all. /// This is a helper function for both CastInst and ConstantExpr. @@ -674,8 +673,8 @@ public: /// This class is the base class for the comparison instructions. /// @brief Abstract base class of comparison instructions. class CmpInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - CmpInst() LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + CmpInst() = delete; protected: CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, const Twine &Name = "", diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index ba7791c99b6a..752c3f09bded 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ilist_node.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/SymbolTableListTraits.h" #include "llvm/IR/User.h" namespace llvm { @@ -25,14 +26,31 @@ namespace llvm { class FastMathFlags; class LLVMContext; class MDNode; +class BasicBlock; struct AAMDNodes; -template<typename ValueSubClass, typename ItemParentClass> - class SymbolTableListTraits; +template <> +struct ilist_traits<Instruction> + : public SymbolTableListTraits<Instruction, BasicBlock> { + + /// \brief Return a node that marks the end of a list. + /// + /// The sentinel is relative to this instance, so we use a non-static + /// method. + Instruction *createSentinel() const; + static void destroySentinel(Instruction *) {} + + Instruction *provideInitialHead() const { return createSentinel(); } + Instruction *ensureHead(Instruction *) const { return createSentinel(); } + static void noteHead(Instruction *, Instruction *) {} + +private: + mutable ilist_half_node<Instruction> Sentinel; +}; class Instruction : public User, public ilist_node<Instruction> { - void operator=(const Instruction &) LLVM_DELETED_FUNCTION; - Instruction(const Instruction &) LLVM_DELETED_FUNCTION; + void operator=(const Instruction &) = delete; + Instruction(const Instruction &) = delete; BasicBlock *Parent; DebugLoc DbgLoc; // 'dbg' Metadata cache. @@ -44,7 +62,7 @@ class Instruction : public User, public ilist_node<Instruction> { }; public: // Out of line virtual method, so the vtable, etc has a home. - ~Instruction(); + ~Instruction() override; /// user_back - Specialize the methods defined in Value, as we know that an /// instruction can only be used by other instructions. @@ -54,7 +72,13 @@ public: inline const BasicBlock *getParent() const { return Parent; } inline BasicBlock *getParent() { return Parent; } - const DataLayout *getDataLayout() const; + /// \brief Return the module owning the function this instruction belongs to + /// or nullptr it the function does not have a module. + /// + /// Note: this is undefined behavior if the instruction does not have a + /// parent, or the parent basic block does not have a parent function. + const Module *getModule() const; + Module *getModule(); /// removeFromParent - This method unlinks 'this' from the containing basic /// block, but does not delete it. @@ -64,14 +88,15 @@ public: /// eraseFromParent - This method unlinks 'this' from the containing basic /// block and deletes it. /// - void eraseFromParent(); + /// \returns an iterator pointing to the element after the erased one + iplist<Instruction>::iterator eraseFromParent(); - /// insertBefore - Insert an unlinked instructions into a basic block - /// immediately before the specified instruction. + /// Insert an unlinked instruction into a basic block immediately before + /// the specified instruction. void insertBefore(Instruction *InsertPos); - /// insertAfter - Insert an unlinked instructions into a basic block - /// immediately after the specified instruction. + /// Insert an unlinked instruction into a basic block immediately after the + /// specified instruction. void insertAfter(Instruction *InsertPos); /// moveBefore - Unlink this instruction from its current basic block and @@ -129,9 +154,7 @@ public: /// hasMetadata() - Return true if this instruction has any metadata attached /// to it. - bool hasMetadata() const { - return !DbgLoc.isUnknown() || hasMetadataHashEntry(); - } + bool hasMetadata() const { return DbgLoc || hasMetadataHashEntry(); } /// hasMetadataOtherThanDebugLoc - Return true if this instruction has /// metadata attached to it other than a debug location. @@ -201,7 +224,7 @@ public: void setAAMetadata(const AAMDNodes &N); /// setDebugLoc - Set the debug location information for this instruction. - void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; } + void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); } /// getDebugLoc - Return the debug location for this node as a DebugLoc. const DebugLoc &getDebugLoc() const { return DbgLoc; } @@ -490,6 +513,17 @@ protected: }; +inline Instruction *ilist_traits<Instruction>::createSentinel() const { + // Since i(p)lists always publicly derive from their corresponding traits, + // placing a data member in this class will augment the i(p)list. But since + // the NodeTy is expected to be publicly derive from ilist_node<NodeTy>, + // there is a legal viable downcast from it to NodeTy. We use this trick to + // superimpose an i(p)list with a "ghostly" NodeTy, which becomes the + // sentinel. Dereferencing the sentinel is forbidden (save the + // ilist_node<NodeTy>), so no one will ever notice the superposition. + return static_cast<Instruction *>(&Sentinel); +} + // Instruction* is only 4-byte aligned. template<> class PointerLikeTypeTraits<Instruction*> { diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 045e51eb1baa..9f5e244f0021 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -73,6 +73,8 @@ return (Ord == Release || /// AllocaInst - an instruction to allocate memory on the stack /// class AllocaInst : public UnaryInstruction { + Type *AllocatedType; + protected: AllocaInst *clone_impl() const override; public: @@ -91,7 +93,7 @@ public: const Twine &Name, BasicBlock *InsertAtEnd); // Out of line virtual method, so the vtable, etc. has a home. - virtual ~AllocaInst(); + ~AllocaInst() override; /// isArrayAllocation - Return true if there is an allocation size parameter /// to the allocation instruction that is not 1. @@ -113,7 +115,10 @@ public: /// getAllocatedType - Return the type that is being allocated by the /// instruction. /// - Type *getAllocatedType() const; + Type *getAllocatedType() const { return AllocatedType; } + /// \brief for use only in special circumstances that need to generically + /// transform a whole instruction (eg: IR linking and vectorization). + void setAllocatedType(Type *Ty) { AllocatedType = Ty; } /// getAlignment - Return the alignment of the memory that is being allocated /// by the instruction. @@ -172,15 +177,28 @@ protected: public: LoadInst(Value *Ptr, const Twine &NameStr, Instruction *InsertBefore); LoadInst(Value *Ptr, const Twine &NameStr, BasicBlock *InsertAtEnd); - LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false, + LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile = false, Instruction *InsertBefore = nullptr); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false, + Instruction *InsertBefore = nullptr) + : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr, + NameStr, isVolatile, InsertBefore) {} LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, BasicBlock *InsertAtEnd); - LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, + Instruction *InsertBefore = nullptr) + : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr, + NameStr, isVolatile, Align, InsertBefore) {} + LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, Instruction *InsertBefore = nullptr); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, BasicBlock *InsertAtEnd); - LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, + AtomicOrdering Order, SynchronizationScope SynchScope = CrossThread, + Instruction *InsertBefore = nullptr) + : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr, + NameStr, isVolatile, Align, Order, SynchScope, InsertBefore) {} + LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, AtomicOrdering Order, SynchronizationScope SynchScope = CrossThread, Instruction *InsertBefore = nullptr); @@ -191,9 +209,13 @@ public: LoadInst(Value *Ptr, const char *NameStr, Instruction *InsertBefore); LoadInst(Value *Ptr, const char *NameStr, BasicBlock *InsertAtEnd); + LoadInst(Type *Ty, Value *Ptr, const char *NameStr = nullptr, + bool isVolatile = false, Instruction *InsertBefore = nullptr); explicit LoadInst(Value *Ptr, const char *NameStr = nullptr, bool isVolatile = false, - Instruction *InsertBefore = nullptr); + Instruction *InsertBefore = nullptr) + : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr, + NameStr, isVolatile, InsertBefore) {} LoadInst(Value *Ptr, const char *NameStr, bool isVolatile, BasicBlock *InsertAtEnd); @@ -285,7 +307,7 @@ private: /// StoreInst - an instruction for storing to memory /// class StoreInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void AssertOK(); protected: StoreInst *clone_impl() const override; @@ -411,7 +433,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) /// FenceInst - an instruction for ordering other memory operations /// class FenceInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope); protected: FenceInst *clone_impl() const override; @@ -478,7 +500,7 @@ private: /// there. Returns the value that was loaded. /// class AtomicCmpXchgInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void Init(Value *Ptr, Value *Cmp, Value *NewVal, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SynchronizationScope SynchScope); @@ -634,7 +656,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value) /// the old value. /// class AtomicRMWInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: AtomicRMWInst *clone_impl() const override; public: @@ -787,6 +809,8 @@ inline Type *checkGEPType(Type *Ty) { /// access elements of arrays and structs /// class GetElementPtrInst : public Instruction { + Type *SourceElementType; + GetElementPtrInst(const GetElementPtrInst &GEPI); void init(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &NameStr); @@ -794,28 +818,45 @@ class GetElementPtrInst : public Instruction { /// list of indices. The first ctor can optionally insert before an existing /// instruction, the second appends the new instruction to the specified /// BasicBlock. - inline GetElementPtrInst(Value *Ptr, ArrayRef<Value *> IdxList, - unsigned Values, const Twine &NameStr, - Instruction *InsertBefore); - inline GetElementPtrInst(Value *Ptr, ArrayRef<Value *> IdxList, - unsigned Values, const Twine &NameStr, - BasicBlock *InsertAtEnd); + inline GetElementPtrInst(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, unsigned Values, + const Twine &NameStr, Instruction *InsertBefore); + inline GetElementPtrInst(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd); + protected: GetElementPtrInst *clone_impl() const override; public: - static GetElementPtrInst *Create(Value *Ptr, ArrayRef<Value *> IdxList, + static GetElementPtrInst *Create(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { unsigned Values = 1 + unsigned(IdxList.size()); - return new(Values) - GetElementPtrInst(Ptr, IdxList, Values, NameStr, InsertBefore); - } - static GetElementPtrInst *Create(Value *Ptr, ArrayRef<Value *> IdxList, + if (!PointeeType) + PointeeType = + cast<PointerType>(Ptr->getType()->getScalarType())->getElementType(); + else + assert( + PointeeType == + cast<PointerType>(Ptr->getType()->getScalarType())->getElementType()); + return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, + NameStr, InsertBefore); + } + static GetElementPtrInst *Create(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, const Twine &NameStr, BasicBlock *InsertAtEnd) { unsigned Values = 1 + unsigned(IdxList.size()); - return new(Values) - GetElementPtrInst(Ptr, IdxList, Values, NameStr, InsertAtEnd); + if (!PointeeType) + PointeeType = + cast<PointerType>(Ptr->getType()->getScalarType())->getElementType(); + else + assert( + PointeeType == + cast<PointerType>(Ptr->getType()->getScalarType())->getElementType()); + return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, + NameStr, InsertAtEnd); } /// Create an "inbounds" getelementptr. See the documentation for the @@ -824,7 +865,14 @@ public: ArrayRef<Value *> IdxList, const Twine &NameStr = "", Instruction *InsertBefore = nullptr){ - GetElementPtrInst *GEP = Create(Ptr, IdxList, NameStr, InsertBefore); + return CreateInBounds(nullptr, Ptr, IdxList, NameStr, InsertBefore); + } + static GetElementPtrInst * + CreateInBounds(Type *PointeeType, Value *Ptr, ArrayRef<Value *> IdxList, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + GetElementPtrInst *GEP = + Create(PointeeType, Ptr, IdxList, NameStr, InsertBefore); GEP->setIsInBounds(true); return GEP; } @@ -832,7 +880,14 @@ public: ArrayRef<Value *> IdxList, const Twine &NameStr, BasicBlock *InsertAtEnd) { - GetElementPtrInst *GEP = Create(Ptr, IdxList, NameStr, InsertAtEnd); + return CreateInBounds(nullptr, Ptr, IdxList, NameStr, InsertAtEnd); + } + static GetElementPtrInst *CreateInBounds(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + GetElementPtrInst *GEP = + Create(PointeeType, Ptr, IdxList, NameStr, InsertAtEnd); GEP->setIsInBounds(true); return GEP; } @@ -845,6 +900,14 @@ public: return cast<SequentialType>(Instruction::getType()); } + Type *getSourceElementType() const { return SourceElementType; } + + void setSourceElementType(Type *Ty) { SourceElementType = Ty; } + + Type *getResultElementType() const { + return cast<PointerType>(getType()->getScalarType())->getElementType(); + } + /// \brief Returns the address space of this instruction's pointer type. unsigned getAddressSpace() const { // Note that this is always the same as the pointer operand's address space @@ -858,9 +921,9 @@ public: /// Null is returned if the indices are invalid for the specified /// pointer type. /// - static Type *getIndexedType(Type *Ptr, ArrayRef<Value *> IdxList); - static Type *getIndexedType(Type *Ptr, ArrayRef<Constant *> IdxList); - static Type *getIndexedType(Type *Ptr, ArrayRef<uint64_t> IdxList); + static Type *getIndexedType(Type *Ty, ArrayRef<Value *> IdxList); + static Type *getIndexedType(Type *Ty, ArrayRef<Constant *> IdxList); + static Type *getIndexedType(Type *Ty, ArrayRef<uint64_t> IdxList); inline op_iterator idx_begin() { return op_begin()+1; } inline const_op_iterator idx_begin() const { return op_begin()+1; } @@ -891,8 +954,13 @@ public: /// GetGEPReturnType - Returns the pointer type returned by the GEP /// instruction, which may be a vector of pointers. static Type *getGEPReturnType(Value *Ptr, ArrayRef<Value *> IdxList) { - Type *PtrTy = PointerType::get(checkGEPType( - getIndexedType(Ptr->getType(), IdxList)), + return getGEPReturnType( + cast<PointerType>(Ptr->getType()->getScalarType())->getElementType(), + Ptr, IdxList); + } + static Type *getGEPReturnType(Type *ElTy, Value *Ptr, + ArrayRef<Value *> IdxList) { + Type *PtrTy = PointerType::get(checkGEPType(getIndexedType(ElTy, IdxList)), Ptr->getType()->getPointerAddressSpace()); // Vector GEP if (Ptr->getType()->isVectorTy()) { @@ -953,26 +1021,24 @@ struct OperandTraits<GetElementPtrInst> : public VariadicOperandTraits<GetElementPtrInst, 1> { }; -GetElementPtrInst::GetElementPtrInst(Value *Ptr, - ArrayRef<Value *> IdxList, - unsigned Values, +GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, unsigned Values, const Twine &NameStr, Instruction *InsertBefore) - : Instruction(getGEPReturnType(Ptr, IdxList), - GetElementPtr, - OperandTraits<GetElementPtrInst>::op_end(this) - Values, - Values, InsertBefore) { + : Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr, + OperandTraits<GetElementPtrInst>::op_end(this) - Values, + Values, InsertBefore), + SourceElementType(PointeeType) { init(Ptr, IdxList, NameStr); } -GetElementPtrInst::GetElementPtrInst(Value *Ptr, - ArrayRef<Value *> IdxList, - unsigned Values, +GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr, + ArrayRef<Value *> IdxList, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd) - : Instruction(getGEPReturnType(Ptr, IdxList), - GetElementPtr, - OperandTraits<GetElementPtrInst>::op_end(this) - Values, - Values, InsertAtEnd) { + : Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr, + OperandTraits<GetElementPtrInst>::op_end(this) - Values, + Values, InsertAtEnd), + SourceElementType(PointeeType) { init(Ptr, IdxList, NameStr); } @@ -1194,11 +1260,15 @@ public: /// @returns true if the predicate of this instruction is EQ or NE. /// \brief Determine if this is an equality predicate. - bool isEquality() const { - return getPredicate() == FCMP_OEQ || getPredicate() == FCMP_ONE || - getPredicate() == FCMP_UEQ || getPredicate() == FCMP_UNE; + static bool isEquality(Predicate Pred) { + return Pred == FCMP_OEQ || Pred == FCMP_ONE || Pred == FCMP_UEQ || + Pred == FCMP_UNE; } + /// @returns true if the predicate of this instruction is EQ or NE. + /// \brief Determine if this is an equality predicate. + bool isEquality() const { return isEquality(getPredicate()); } + /// @returns true if the predicate of this instruction is commutative. /// \brief Determine if this is a commutative predicate. bool isCommutative() const { @@ -1240,14 +1310,26 @@ public: /// class CallInst : public Instruction { AttributeSet AttributeList; ///< parameter attributes for call + FunctionType *FTy; CallInst(const CallInst &CI); - void init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr); + void init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr) { + init(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, Args, NameStr); + } + void init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args, + const Twine &NameStr); void init(Value *Func, const Twine &NameStr); /// Construct a CallInst given a range of arguments. /// \brief Construct a CallInst from a range of arguments - inline CallInst(Value *Func, ArrayRef<Value *> Args, + inline CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, const Twine &NameStr, Instruction *InsertBefore); + inline CallInst(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr, + Instruction *InsertBefore) + : CallInst(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, Args, NameStr, InsertBefore) {} /// Construct a CallInst given a range of arguments. /// \brief Construct a CallInst from a range of arguments @@ -1264,8 +1346,15 @@ public: ArrayRef<Value *> Args, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { - return new(unsigned(Args.size() + 1)) - CallInst(Func, Args, NameStr, InsertBefore); + return Create(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, Args, NameStr, InsertBefore); + } + static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + return new (unsigned(Args.size() + 1)) + CallInst(Ty, Func, Args, NameStr, InsertBefore); } static CallInst *Create(Value *Func, ArrayRef<Value *> Args, @@ -1301,7 +1390,14 @@ public: static Instruction* CreateFree(Value* Source, Instruction *InsertBefore); static Instruction* CreateFree(Value* Source, BasicBlock *InsertAtEnd); - ~CallInst(); + ~CallInst() override; + + FunctionType *getFunctionType() const { return FTy; } + + void mutateFunctionType(FunctionType *FTy) { + mutateType(FTy->getReturnType()); + this->FTy = FTy; + } // Note that 'musttail' implies 'tail'. enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2 }; @@ -1375,6 +1471,13 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); + /// \brief adds the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + + /// \brief adds the dereferenceable_or_null attribute to the list of + /// attributes. + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && @@ -1396,6 +1499,12 @@ public: return AttributeList.getDereferenceableBytes(i); } + /// \brief Extract the number of dereferenceable_or_null bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableOrNullBytes(unsigned i) const { + return AttributeList.getDereferenceableOrNullBytes(i); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -1477,6 +1586,14 @@ public: /// setCalledFunction - Set the function called. void setCalledFunction(Value* Fn) { + setCalledFunction( + cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()), + Fn); + } + void setCalledFunction(FunctionType *FTy, Value *Fn) { + this->FTy = FTy; + assert(FTy == cast<FunctionType>( + cast<PointerType>(Fn->getType())->getElementType())); Op<-1>() = Fn; } @@ -1517,14 +1634,12 @@ CallInst::CallInst(Value *Func, ArrayRef<Value *> Args, init(Func, Args, NameStr); } -CallInst::CallInst(Value *Func, ArrayRef<Value *> Args, +CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, const Twine &NameStr, Instruction *InsertBefore) - : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Call, - OperandTraits<CallInst>::op_end(this) - (Args.size() + 1), - unsigned(Args.size() + 1), InsertBefore) { - init(Func, Args, NameStr); + : Instruction(Ty->getReturnType(), Instruction::Call, + OperandTraits<CallInst>::op_end(this) - (Args.size() + 1), + unsigned(Args.size() + 1), InsertBefore) { + init(Ty, Func, Args, NameStr); } @@ -1898,6 +2013,9 @@ public: typedef const unsigned* idx_iterator; inline idx_iterator idx_begin() const { return Indices.begin(); } inline idx_iterator idx_end() const { return Indices.end(); } + inline iterator_range<idx_iterator> indices() const { + return iterator_range<idx_iterator>(idx_begin(), idx_end()); + } Value *getAggregateOperand() { return getOperand(0); @@ -1958,7 +2076,7 @@ ExtractValueInst::ExtractValueInst(Value *Agg, class InsertValueInst : public Instruction { SmallVector<unsigned, 4> Indices; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; InsertValueInst(const InsertValueInst &IVI); void init(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs, const Twine &NameStr); @@ -2009,6 +2127,9 @@ public: typedef const unsigned* idx_iterator; inline idx_iterator idx_begin() const { return Indices.begin(); } inline idx_iterator idx_end() const { return Indices.end(); } + inline iterator_range<idx_iterator> indices() const { + return iterator_range<idx_iterator>(idx_begin(), idx_end()); + } Value *getAggregateOperand() { return getOperand(0); @@ -2088,7 +2209,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value) // scientist's overactive imagination. // class PHINode : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; /// ReservedSpace - The number of operands actually allocated. NumOperands is /// the number actually in use. unsigned ReservedSpace; @@ -2132,7 +2253,7 @@ public: const Twine &NameStr, BasicBlock *InsertAtEnd) { return new PHINode(Ty, NumReservedValues, NameStr, InsertAtEnd); } - ~PHINode(); + ~PHINode() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2163,6 +2284,10 @@ public: return block_begin() + getNumOperands(); } + op_range incoming_values() { return operands(); } + + const_op_range incoming_values() const { return operands(); } + /// getNumIncomingValues - Return the number of incoming edges /// unsigned getNumIncomingValues() const { return getNumOperands(); } @@ -2295,7 +2420,7 @@ class LandingPadInst : public Instruction { public: enum ClauseType { Catch, Filter }; private: - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; // Allocate space for exactly zero operands. void *operator new(size_t s) { return User::operator new(s, 0); @@ -2321,7 +2446,7 @@ public: static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, unsigned NumReservedClauses, const Twine &NameStr, BasicBlock *InsertAtEnd); - ~LandingPadInst(); + ~LandingPadInst() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2423,7 +2548,7 @@ public: static ReturnInst* Create(LLVMContext &C, BasicBlock *InsertAtEnd) { return new(0) ReturnInst(C, InsertAtEnd); } - virtual ~ReturnInst(); + ~ReturnInst() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2562,7 +2687,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) /// SwitchInst - Multiway switch /// class SwitchInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; unsigned ReservedSpace; // Operand[0] = Value to switch on // Operand[1] = Default basic block destination @@ -2720,7 +2845,7 @@ public: return new SwitchInst(Value, Default, NumCases, InsertAtEnd); } - ~SwitchInst(); + ~SwitchInst() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2871,7 +2996,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value) /// IndirectBrInst - Indirect Branch Instruction. /// class IndirectBrInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; unsigned ReservedSpace; // Operand[0] = Value to switch on // Operand[1] = Default basic block destination @@ -2906,7 +3031,7 @@ public: BasicBlock *InsertAtEnd) { return new IndirectBrInst(Address, NumDests, InsertAtEnd); } - ~IndirectBrInst(); + ~IndirectBrInst() override; /// Provide fast operand accessors. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2970,17 +3095,33 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value) /// class InvokeInst : public TerminatorInst { AttributeSet AttributeList; + FunctionType *FTy; InvokeInst(const InvokeInst &BI); void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef<Value *> Args, const Twine &NameStr); + ArrayRef<Value *> Args, const Twine &NameStr) { + init(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, IfNormal, IfException, Args, NameStr); + } + void init(FunctionType *FTy, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef<Value *> Args, + const Twine &NameStr); /// Construct an InvokeInst given a range of arguments. /// /// \brief Construct an InvokeInst from a range of arguments inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, unsigned Values, - const Twine &NameStr, Instruction *InsertBefore); - + const Twine &NameStr, Instruction *InsertBefore) + : InvokeInst(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, IfNormal, IfException, Args, Values, NameStr, + InsertBefore) {} + + inline InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef<Value *> Args, + unsigned Values, const Twine &NameStr, + Instruction *InsertBefore); /// Construct an InvokeInst given a range of arguments. /// /// \brief Construct an InvokeInst from a range of arguments @@ -2994,9 +3135,17 @@ public: BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { + return Create(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, IfNormal, IfException, Args, NameStr, InsertBefore); + } + static InvokeInst *Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef<Value *> Args, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { unsigned Values = unsigned(Args.size()) + 3; - return new(Values) InvokeInst(Func, IfNormal, IfException, Args, - Values, NameStr, InsertBefore); + return new (Values) InvokeInst(Ty, Func, IfNormal, IfException, Args, + Values, NameStr, InsertBefore); } static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, @@ -3010,6 +3159,13 @@ public: /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + FunctionType *getFunctionType() const { return FTy; } + + void mutateFunctionType(FunctionType *FTy) { + mutateType(FTy->getReturnType()); + this->FTy = FTy; + } + /// getNumArgOperands - Return the number of invoke arguments. /// unsigned getNumArgOperands() const { return getNumOperands() - 3; } @@ -3056,6 +3212,13 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); + /// \brief adds the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + + /// \brief adds the dereferenceable_or_null attribute to the list of + /// attributes. + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && @@ -3076,6 +3239,12 @@ public: uint64_t getDereferenceableBytes(unsigned i) const { return AttributeList.getDereferenceableBytes(i); } + + /// \brief Extract the number of dereferenceable_or_null bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableOrNullBytes(unsigned i) const { + return AttributeList.getDereferenceableOrNullBytes(i); + } /// \brief Return true if the call should not be treated as a call to a /// builtin. @@ -3152,6 +3321,14 @@ public: /// setCalledFunction - Set the function called. void setCalledFunction(Value* Fn) { + setCalledFunction( + cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()), + Fn); + } + void setCalledFunction(FunctionType *FTy, Value *Fn) { + this->FTy = FTy; + assert(FTy == cast<FunctionType>( + cast<PointerType>(Fn->getType())->getElementType())); Op<-3>() = Fn; } @@ -3211,16 +3388,14 @@ template <> struct OperandTraits<InvokeInst> : public VariadicOperandTraits<InvokeInst, 3> { }; -InvokeInst::InvokeInst(Value *Func, - BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef<Value *> Args, unsigned Values, - const Twine &NameStr, Instruction *InsertBefore) - : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Invoke, - OperandTraits<InvokeInst>::op_end(this) - Values, - Values, InsertBefore) { - init(Func, IfNormal, IfException, Args, NameStr); +InvokeInst::InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef<Value *> Args, + unsigned Values, const Twine &NameStr, + Instruction *InsertBefore) + : TerminatorInst(Ty->getReturnType(), Instruction::Invoke, + OperandTraits<InvokeInst>::op_end(this) - Values, Values, + InsertBefore) { + init(Ty, Func, IfNormal, IfException, Args, NameStr); } InvokeInst::InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, @@ -3296,7 +3471,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) /// end of the block cannot be reached. /// class UnreachableInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: UnreachableInst *clone_impl() const override; diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index c227ea080167..2c8b6eb6f39a 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -35,14 +35,14 @@ namespace llvm { /// functions. This allows the standard isa/dyncast/cast functionality to /// work with calls to intrinsic functions. class IntrinsicInst : public CallInst { - IntrinsicInst() LLVM_DELETED_FUNCTION; - IntrinsicInst(const IntrinsicInst&) LLVM_DELETED_FUNCTION; - void operator=(const IntrinsicInst&) LLVM_DELETED_FUNCTION; + IntrinsicInst() = delete; + IntrinsicInst(const IntrinsicInst&) = delete; + void operator=(const IntrinsicInst&) = delete; public: /// getIntrinsicID - Return the intrinsic ID of this intrinsic. /// Intrinsic::ID getIntrinsicID() const { - return (Intrinsic::ID)getCalledFunction()->getIntrinsicID(); + return getCalledFunction()->getIntrinsicID(); } // Methods for support type inquiry through isa, cast, and dyn_cast: @@ -82,13 +82,18 @@ namespace llvm { class DbgDeclareInst : public DbgInfoIntrinsic { public: Value *getAddress() const; - MDNode *getVariable() const { - return cast<MDNode>( - cast<MetadataAsValue>(getArgOperand(1))->getMetadata()); + DILocalVariable *getVariable() const { + return cast<DILocalVariable>(getRawVariable()); } - MDNode *getExpression() const { - return cast<MDNode>( - cast<MetadataAsValue>(getArgOperand(2))->getMetadata()); + DIExpression *getExpression() const { + return cast<DIExpression>(getRawExpression()); + } + + Metadata *getRawVariable() const { + return cast<MetadataAsValue>(getArgOperand(1))->getMetadata(); + } + Metadata *getRawExpression() const { + return cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); } // Methods for support type inquiry through isa, cast, and dyn_cast: @@ -110,13 +115,18 @@ namespace llvm { return cast<ConstantInt>( const_cast<Value*>(getArgOperand(1)))->getZExtValue(); } - MDNode *getVariable() const { - return cast<MDNode>( - cast<MetadataAsValue>(getArgOperand(2))->getMetadata()); + DILocalVariable *getVariable() const { + return cast<DILocalVariable>(getRawVariable()); + } + DIExpression *getExpression() const { + return cast<DIExpression>(getRawExpression()); + } + + Metadata *getRawVariable() const { + return cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); } - MDNode *getExpression() const { - return cast<MDNode>( - cast<MetadataAsValue>(getArgOperand(3))->getMetadata()); + Metadata *getRawExpression() const { + return cast<MetadataAsValue>(getArgOperand(3))->getMetadata(); } // Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index 56d1e4af26aa..e12ccace25ca 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -32,7 +32,7 @@ class AttributeSet; /// function known by LLVM. The enum values are returned by /// Function::getIntrinsicID(). namespace Intrinsic { - enum ID { + enum ID : unsigned { not_intrinsic = 0, // Must be zero // Get the intrinsic enums generated from Intrinsics.td @@ -41,7 +41,7 @@ namespace Intrinsic { #undef GET_INTRINSIC_ENUM_VALUES , num_intrinsics }; - + /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx". std::string getName(ID id, ArrayRef<Type*> Tys = None); @@ -69,7 +69,7 @@ namespace Intrinsic { /// Map a MS builtin name to an intrinsic ID. ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName); - + /// This is a type descriptor which explains the type requirements of an /// intrinsic. This is returned by getIntrinsicInfoTableEntries. struct IITDescriptor { @@ -77,9 +77,9 @@ namespace Intrinsic { Void, VarArg, MMX, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, Argument, ExtendArgument, TruncArgument, HalfVecArgument, - SameVecWidthArgument, PtrToArgument + SameVecWidthArgument, PtrToArgument, VecOfPtrsToElt } Kind; - + union { unsigned Integer_Width; unsigned Float_Width; @@ -88,8 +88,9 @@ namespace Intrinsic { unsigned Struct_NumElements; unsigned Argument_Info; }; - + enum ArgKind { + AK_Any, AK_AnyInteger, AK_AnyFloat, AK_AnyVector, @@ -98,26 +99,28 @@ namespace Intrinsic { unsigned getArgumentNumber() const { assert(Kind == Argument || Kind == ExtendArgument || Kind == TruncArgument || Kind == HalfVecArgument || - Kind == SameVecWidthArgument || Kind == PtrToArgument); - return Argument_Info >> 2; + Kind == SameVecWidthArgument || Kind == PtrToArgument || + Kind == VecOfPtrsToElt); + return Argument_Info >> 3; } ArgKind getArgumentKind() const { assert(Kind == Argument || Kind == ExtendArgument || Kind == TruncArgument || Kind == HalfVecArgument || - Kind == SameVecWidthArgument || Kind == PtrToArgument); - return (ArgKind)(Argument_Info & 3); + Kind == SameVecWidthArgument || Kind == PtrToArgument || + Kind == VecOfPtrsToElt); + return (ArgKind)(Argument_Info & 7); } - + static IITDescriptor get(IITDescriptorKind K, unsigned Field) { IITDescriptor Result = { K, { Field } }; return Result; } }; - + /// Return the IIT table descriptor for the specified intrinsic into an array /// of IITDescriptors. void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T); - + } // End Intrinsic namespace } // End llvm namespace diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index a1188bccdc25..8f6cdebb0491 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -73,6 +73,11 @@ def IntrNoReturn : IntrinsicProperty; // Parallels the noduplicate attribute on LLVM IR functions. def IntrNoDuplicate : IntrinsicProperty; +// IntrConvergent - Calls to this intrinsic are convergent and may only be +// moved to control equivalent blocks. +// Parallels the convergent attribute on LLVM IR functions. +def IntrConvergent : IntrinsicProperty; + //===----------------------------------------------------------------------===// // Types used by intrinsics. //===----------------------------------------------------------------------===// @@ -117,12 +122,14 @@ class LLVMVectorSameWidth<int num, LLVMType elty> ValueType ElTy = elty.VT; } class LLVMPointerTo<int num> : LLVMMatchType<num>; +class LLVMVectorOfPointersToElt<int num> : LLVMMatchType<num>; // Match the type of another intrinsic parameter that is expected to be a // vector type, but change the element count to be half as many class LLVMHalfElementsVectorType<int num> : LLVMMatchType<num>; def llvm_void_ty : LLVMType<isVoid>; +def llvm_any_ty : LLVMType<Any>; def llvm_anyint_ty : LLVMType<iAny>; def llvm_anyfloat_ty : LLVMType<fAny>; def llvm_anyvector_ty : LLVMType<vAny>; @@ -179,6 +186,8 @@ def llvm_v4i64_ty : LLVMType<v4i64>; // 4 x i64 def llvm_v8i64_ty : LLVMType<v8i64>; // 8 x i64 def llvm_v16i64_ty : LLVMType<v16i64>; // 16 x i64 +def llvm_v1i128_ty : LLVMType<v1i128>; // 1 x i128 + def llvm_v2f16_ty : LLVMType<v2f16>; // 2 x half (__fp16) def llvm_v4f16_ty : LLVMType<v4f16>; // 4 x half (__fp16) def llvm_v8f16_ty : LLVMType<v8f16>; // 8 x half (__fp16) @@ -259,12 +268,12 @@ def int_gcwrite : Intrinsic<[], // def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_frameallocate : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; +def int_frameescape : Intrinsic<[], [llvm_vararg_ty]>; def int_framerecover : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty, llvm_ptr_ty], - [IntrNoMem]>; + [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrNoMem]>; def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], - [IntrNoMem], "llvm.read_register">; + [IntrReadMem], "llvm.read_register">; def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], [], "llvm.write_register">; @@ -409,6 +418,19 @@ def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>; +// eh.begincatch takes a pointer returned by a landingpad instruction and +// copies the exception object into the memory pointed to by the second +// parameter. If the second parameter is null, no copy occurs. +def int_eh_begincatch : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], + [NoCapture<0>, NoCapture<1>]>; +def int_eh_endcatch : Intrinsic<[], []>; + +// Represents the list of actions to take when an exception is thrown. +def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>; + +def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], []>; +def int_eh_exceptioninfo : Intrinsic<[llvm_ptr_ty], []>; + // __builtin_unwind_init is an undocumented GCC intrinsic that causes all // callee-saved registers to be saved and restored (regardless of whether they // are used) in the calling function. It is used by libgcc_eh. @@ -513,17 +535,20 @@ def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], // These are documented in docs/Statepoint.rst def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty], - [llvm_anyptr_ty, llvm_i32_ty, + [llvm_i64_ty, llvm_i32_ty, + llvm_anyptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_vararg_ty]>; +def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_i32_ty]>; +def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>; + +// Deprecated: will be removed in a couple of weeks def int_experimental_gc_result_int : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty]>; -def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty], +def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty], [llvm_i32_ty]>; def int_experimental_gc_result_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty]>; -def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>; - //===-------------------------- Other Intrinsics --------------------------===// // def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, @@ -581,6 +606,23 @@ def int_masked_load : Intrinsic<[llvm_anyvector_ty], [LLVMPointerTo<0>, llvm_i32_ty, LLVMVectorSameWidth<0, llvm_i1_ty>, LLVMMatchType<0>], [IntrReadArgMem]>; + +def int_masked_gather: Intrinsic<[llvm_anyvector_ty], + [LLVMVectorOfPointersToElt<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>, + LLVMMatchType<0>], + [IntrReadArgMem]>; + +def int_masked_scatter: Intrinsic<[], + [llvm_anyvector_ty, + LLVMVectorOfPointersToElt<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>], + [IntrReadWriteArgMem]>; + +// Intrinsics to support bit sets. +def int_bitset_test : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty], + [IntrNoMem]>; + //===----------------------------------------------------------------------===// // Target-specific intrinsics //===----------------------------------------------------------------------===// @@ -594,3 +636,5 @@ include "llvm/IR/IntrinsicsHexagon.td" include "llvm/IR/IntrinsicsNVVM.td" include "llvm/IR/IntrinsicsMips.td" include "llvm/IR/IntrinsicsR600.td" +include "llvm/IR/IntrinsicsBPF.td" +include "llvm/IR/IntrinsicsSystemZ.td" diff --git a/include/llvm/IR/IntrinsicsBPF.td b/include/llvm/IR/IntrinsicsBPF.td new file mode 100644 index 000000000000..94eca8e40332 --- /dev/null +++ b/include/llvm/IR/IntrinsicsBPF.td @@ -0,0 +1,24 @@ +//===- IntrinsicsBPF.td - Defines BPF 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 BPF-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +// Specialized loads from packet +let TargetPrefix = "bpf" in { // All intrinsics start with "llvm.bpf." + def int_bpf_load_byte : GCCBuiltin<"__builtin_bpf_load_byte">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; + def int_bpf_load_half : GCCBuiltin<"__builtin_bpf_load_half">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; + def int_bpf_load_word : GCCBuiltin<"__builtin_bpf_load_word">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; + def int_bpf_pseudo : GCCBuiltin<"__builtin_bpf_pseudo">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty]>; +} diff --git a/include/llvm/IR/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td index 8a8872931f36..78ee651d20f9 100644 --- a/include/llvm/IR/IntrinsicsHexagon.td +++ b/include/llvm/IR/IntrinsicsHexagon.td @@ -254,7 +254,7 @@ class Hexagon_qi_qiqi_Intrinsic<string GCCIntSuffix> // class Hexagon_qi_qiqiqi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, - [llvm_i1_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i1_ty], [llvm_i1_ty, llvm_i1_ty, llvm_i1_ty], [IntrNoMem]>; // // DEF_FUNCTION_TYPE_2(SI_ftype_QIQI,BT_INT,BT_BOOL,BT_BOOL) -> @@ -422,19 +422,49 @@ class Hexagon_di_didisisi_Intrinsic<string GCCIntSuffix> llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +class Hexagon_mem_memmemsi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + +class Hexagon_mem_memsisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + +class Hexagon_mem_memdisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + class Hexagon_mem_memmemsisi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; +class Hexagon_mem_memsisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + +class Hexagon_mem_memdisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty, + llvm_i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + // // Hexagon_sf_df_Intrinsic<string GCCIntSuffix> // class Hexagon_sf_si_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_float_ty], [llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // // Hexagon_sf_df_Intrinsic<string GCCIntSuffix> // @@ -490,21 +520,21 @@ class Hexagon_si_df_Intrinsic<string GCCIntSuffix> class Hexagon_sf_sfsf_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_float_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // -// Hexagon_qi_sfsf_Intrinsic<string GCCIntSuffix> +// Hexagon_si_sfsf_Intrinsic<string GCCIntSuffix> // -class Hexagon_qi_sfsf_Intrinsic<string GCCIntSuffix> +class Hexagon_si_sfsf_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, - [llvm_i1_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; + [llvm_i32_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Throws]>; // -// Hexagon_qi_sfsi_Intrinsic<string GCCIntSuffix> +// Hexagon_si_sfsi_Intrinsic<string GCCIntSuffix> // -class Hexagon_qi_sfsi_Intrinsic<string GCCIntSuffix> +class Hexagon_si_sfsi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, - [llvm_i1_ty], [llvm_float_ty, llvm_i32_ty], - [IntrNoMem]>; + [llvm_i32_ty], [llvm_float_ty, llvm_i32_ty], + [IntrNoMem, Throws]>; // // Hexagon_qi_sfqi_Intrinsic<string GCCIntSuffix> // @@ -519,7 +549,7 @@ class Hexagon_sf_sfsfsf_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // // Hexagon_sf_sfsfsfqi_Intrinsic<string GCCIntSuffix> // @@ -528,7 +558,7 @@ class Hexagon_sf_sfsfsfqi_Intrinsic<string GCCIntSuffix> [llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // // Hexagon_di_dididi_Intrinsic<string GCCIntSuffix> // @@ -543,7 +573,7 @@ class Hexagon_di_dididisi_Intrinsic<string GCCIntSuffix> class Hexagon_df_si_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_double_ty], [llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // // Hexagon_df_di_Intrinsic<string GCCIntSuffix> // @@ -571,21 +601,21 @@ class Hexagon_df_df_Intrinsic<string GCCIntSuffix> class Hexagon_df_dfdf_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_double_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // -// Hexagon_qi_dfdf_Intrinsic<string GCCIntSuffix> +// Hexagon_si_dfdf_Intrinsic<string GCCIntSuffix> // -class Hexagon_qi_dfdf_Intrinsic<string GCCIntSuffix> +class Hexagon_si_dfdf_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, - [llvm_i1_ty], [llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; + [llvm_i32_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Throws]>; // -// Hexagon_qi_dfsi_Intrinsic<string GCCIntSuffix> +// Hexagon_si_dfsi_Intrinsic<string GCCIntSuffix> // -class Hexagon_qi_dfsi_Intrinsic<string GCCIntSuffix> +class Hexagon_si_dfsi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, - [llvm_i1_ty], [llvm_double_ty, llvm_i32_ty], - [IntrNoMem]>; + [llvm_i32_ty], [llvm_double_ty, llvm_i32_ty], + [IntrNoMem, Throws]>; // // // Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix> @@ -594,7 +624,7 @@ class Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_double_ty], [llvm_double_ty, llvm_double_ty, llvm_double_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // // Hexagon_df_dfdfdf_Intrinsic<string GCCIntSuffix> // @@ -603,53 +633,159 @@ class Hexagon_df_dfdfdfqi_Intrinsic<string GCCIntSuffix> [llvm_double_ty], [llvm_double_ty, llvm_double_ty, llvm_double_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; -// This one below will not be generated from iset.py. -// So make sure, you don't overwrite this one. +// This one below will not be auto-generated, +// so make sure, you don't overwrite this one. // // BUILTIN_INFO(SI_to_SXTHI_asrh,SI_ftype_SI,1) // def int_hexagon_SI_to_SXTHI_asrh : Hexagon_si_si_Intrinsic<"SI_to_SXTHI_asrh">; // +// BUILTIN_INFO_NONCONST(brev_ldd,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldd : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldd">; +// +// BUILTIN_INFO_NONCONST(brev_ldw,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldw : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldw">; +// +// BUILTIN_INFO_NONCONST(brev_ldh,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldh : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldh">; +// +// BUILTIN_INFO_NONCONST(brev_lduh,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_lduh : +Hexagon_mem_memmemsi_Intrinsic<"brev_lduh">; +// +// BUILTIN_INFO_NONCONST(brev_ldb,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldb : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldb">; +// +// BUILTIN_INFO_NONCONST(brev_ldub,PTR_ftype_PTRPTRSI,3) +// +def int_hexagon_brev_ldub : +Hexagon_mem_memmemsi_Intrinsic<"brev_ldub">; +// // BUILTIN_INFO_NONCONST(circ_ldd,PTR_ftype_PTRPTRSISI,4) // def int_hexagon_circ_ldd : Hexagon_mem_memmemsisi_Intrinsic<"circ_ldd">; -// This one above will not be generated from iset.py. -// So make sure, you don't overwrite this one. +// +// BUILTIN_INFO_NONCONST(circ_ldw,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_ldw : +Hexagon_mem_memmemsisi_Intrinsic<"circ_ldw">; +// +// BUILTIN_INFO_NONCONST(circ_ldh,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_ldh : +Hexagon_mem_memmemsisi_Intrinsic<"circ_ldh">; +// +// BUILTIN_INFO_NONCONST(circ_lduh,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_lduh : +Hexagon_mem_memmemsisi_Intrinsic<"circ_lduh">; +// +// BUILTIN_INFO_NONCONST(circ_ldb,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_ldb : +Hexagon_mem_memmemsisi_Intrinsic<"circ_ldb">; +// +// BUILTIN_INFO_NONCONST(circ_ldub,PTR_ftype_PTRPTRSISI,4) +// +def int_hexagon_circ_ldub : +Hexagon_mem_memmemsisi_Intrinsic<"circ_ldub">; + +// +// BUILTIN_INFO_NONCONST(brev_stb,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_stb : +Hexagon_mem_memsisi_Intrinsic<"brev_stb">; +// +// BUILTIN_INFO_NONCONST(brev_sthhi,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_sthhi : +Hexagon_mem_memsisi_Intrinsic<"brev_sthhi">; +// +// BUILTIN_INFO_NONCONST(brev_sth,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_sth : +Hexagon_mem_memsisi_Intrinsic<"brev_sth">; +// +// BUILTIN_INFO_NONCONST(brev_stw,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_stw : +Hexagon_mem_memsisi_Intrinsic<"brev_stw">; +// +// BUILTIN_INFO_NONCONST(brev_std,PTR_ftype_PTRSISI,3) +// +def int_hexagon_brev_std : +Hexagon_mem_memdisi_Intrinsic<"brev_std">; +// +// BUILTIN_INFO_NONCONST(circ_std,PTR_ftype_PTRDISISI,4) +// +def int_hexagon_circ_std : +Hexagon_mem_memdisisi_Intrinsic<"circ_std">; +// +// BUILTIN_INFO_NONCONST(circ_stw,PTR_ftype_PTRSISISI,4) +// +def int_hexagon_circ_stw : +Hexagon_mem_memsisisi_Intrinsic<"circ_stw">; +// +// BUILTIN_INFO_NONCONST(circ_sth,PTR_ftype_PTRSISISI,4) +// +def int_hexagon_circ_sth : +Hexagon_mem_memsisisi_Intrinsic<"circ_sth">; +// +// BUILTIN_INFO_NONCONST(circ_sthhi,PTR_ftype_PTRSISISI,4) +// +def int_hexagon_circ_sthhi : +Hexagon_mem_memsisisi_Intrinsic<"circ_sthhi">; +// +// BUILTIN_INFO_NONCONST(circ_stb,PTR_ftype_PTRSISISI,4) +// +def int_hexagon_circ_stb : +Hexagon_mem_memsisisi_Intrinsic<"circ_stb">; + + // // BUILTIN_INFO(HEXAGON.C2_cmpeq,QI_ftype_SISI,2) // def int_hexagon_C2_cmpeq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpeq">; // // BUILTIN_INFO(HEXAGON.C2_cmpgt,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgt">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtu,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgtu">; // // BUILTIN_INFO(HEXAGON.C2_cmpeqp,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpeqp : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpeqp">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpeqp">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtp,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpgtp : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtp">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpgtp">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtup,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpgtup : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtup">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpgtup">; // // BUILTIN_INFO(HEXAGON.A4_rcmpeqi,SI_ftype_SISI,2) // @@ -674,182 +810,182 @@ Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_rcmpneq">; // BUILTIN_INFO(HEXAGON.C2_bitsset,QI_ftype_SISI,2) // def int_hexagon_C2_bitsset : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsset">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsset">; // // BUILTIN_INFO(HEXAGON.C2_bitsclr,QI_ftype_SISI,2) // def int_hexagon_C2_bitsclr : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclr">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsclr">; // // BUILTIN_INFO(HEXAGON.C4_nbitsset,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsset : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsset">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsset">; // // BUILTIN_INFO(HEXAGON.C4_nbitsclr,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsclr : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclr">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsclr">; // // BUILTIN_INFO(HEXAGON.C2_cmpeqi,QI_ftype_SISI,2) // def int_hexagon_C2_cmpeqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpeqi">; // // BUILTIN_INFO(HEXAGON.C2_cmpgti,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgti">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtui,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgtui">; // // BUILTIN_INFO(HEXAGON.C2_cmpgei,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgei : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgei">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgei">; // // BUILTIN_INFO(HEXAGON.C2_cmpgeui,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgeui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgeui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgeui">; // // BUILTIN_INFO(HEXAGON.C2_cmplt,QI_ftype_SISI,2) // def int_hexagon_C2_cmplt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmplt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmplt">; // // BUILTIN_INFO(HEXAGON.C2_cmpltu,QI_ftype_SISI,2) // def int_hexagon_C2_cmpltu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpltu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpltu">; // // BUILTIN_INFO(HEXAGON.C2_bitsclri,QI_ftype_SISI,2) // def int_hexagon_C2_bitsclri : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclri">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsclri">; // // BUILTIN_INFO(HEXAGON.C4_nbitsclri,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsclri : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclri">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsclri">; // // BUILTIN_INFO(HEXAGON.C4_cmpneqi,QI_ftype_SISI,2) // def int_hexagon_C4_cmpneqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpneqi">; // // BUILTIN_INFO(HEXAGON.C4_cmpltei,QI_ftype_SISI,2) // def int_hexagon_C4_cmpltei : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpltei">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpltei">; // // BUILTIN_INFO(HEXAGON.C4_cmplteui,QI_ftype_SISI,2) // def int_hexagon_C4_cmplteui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplteui">; // // BUILTIN_INFO(HEXAGON.C4_cmpneq,QI_ftype_SISI,2) // def int_hexagon_C4_cmpneq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpneq">; // // BUILTIN_INFO(HEXAGON.C4_cmplte,QI_ftype_SISI,2) // def int_hexagon_C4_cmplte : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplte">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplte">; // // BUILTIN_INFO(HEXAGON.C4_cmplteu,QI_ftype_SISI,2) // def int_hexagon_C4_cmplteu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplteu">; // // BUILTIN_INFO(HEXAGON.C2_and,QI_ftype_QIQI,2) // def int_hexagon_C2_and : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_and">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_and">; // // BUILTIN_INFO(HEXAGON.C2_or,QI_ftype_QIQI,2) // def int_hexagon_C2_or : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_or">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_or">; // // BUILTIN_INFO(HEXAGON.C2_xor,QI_ftype_QIQI,2) // def int_hexagon_C2_xor : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_xor">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_xor">; // // BUILTIN_INFO(HEXAGON.C2_andn,QI_ftype_QIQI,2) // def int_hexagon_C2_andn : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_andn">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_andn">; // // BUILTIN_INFO(HEXAGON.C2_not,QI_ftype_QI,1) // def int_hexagon_C2_not : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_not">; +Hexagon_si_si_Intrinsic<"HEXAGON_C2_not">; // // BUILTIN_INFO(HEXAGON.C2_orn,QI_ftype_QIQI,2) // def int_hexagon_C2_orn : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_orn">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_orn">; // // BUILTIN_INFO(HEXAGON.C4_and_and,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_and : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_and">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_and">; // // BUILTIN_INFO(HEXAGON.C4_and_or,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_or : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_or">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_or">; // // BUILTIN_INFO(HEXAGON.C4_or_and,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_and : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_and">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_and">; // // BUILTIN_INFO(HEXAGON.C4_or_or,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_or : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_or">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_or">; // // BUILTIN_INFO(HEXAGON.C4_and_andn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_andn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_andn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_andn">; // // BUILTIN_INFO(HEXAGON.C4_and_orn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_orn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_orn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_orn">; // // BUILTIN_INFO(HEXAGON.C4_or_andn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_andn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_andn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_andn">; // // BUILTIN_INFO(HEXAGON.C4_or_orn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_orn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_orn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_orn">; // // BUILTIN_INFO(HEXAGON.C2_pxfer_map,QI_ftype_QI,1) // def int_hexagon_C2_pxfer_map : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_pxfer_map">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_pxfer_map">; // // BUILTIN_INFO(HEXAGON.C2_any8,QI_ftype_QI,1) // def int_hexagon_C2_any8 : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_any8">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_any8">; // // BUILTIN_INFO(HEXAGON.C2_all8,QI_ftype_QI,1) // def int_hexagon_C2_all8 : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_all8">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_all8">; // // BUILTIN_INFO(HEXAGON.C2_vitpack,SI_ftype_QIQI,2) // @@ -889,167 +1025,167 @@ Hexagon_di_qi_Intrinsic<"HEXAGON_C2_mask">; // BUILTIN_INFO(HEXAGON.A2_vcmpbeq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpbeq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbeq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpbeq">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbeqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbeqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbeqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbeqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbeq_any,QI_ftype_DIDI,2) // def int_hexagon_A4_vcmpbeq_any : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbeq_any">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A4_vcmpbeq_any">; // // BUILTIN_INFO(HEXAGON.A2_vcmpbgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpbgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpbgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbgtui">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgt,QI_ftype_DIDI,2) // def int_hexagon_A4_vcmpbgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A4_vcmpbgt">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbgti">; // // BUILTIN_INFO(HEXAGON.A4_cmpbeq,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbeq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbeq">; // // BUILTIN_INFO(HEXAGON.A4_cmpbeqi,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbeqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbeqi">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgtu,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgtu">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgtui,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgtui">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgt,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgt">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgti,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgti">; // // BUILTIN_INFO(HEXAGON.A2_vcmpheq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpheq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpheq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpheq">; // // BUILTIN_INFO(HEXAGON.A2_vcmphgt,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmphgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmphgt">; // // BUILTIN_INFO(HEXAGON.A2_vcmphgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmphgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmphgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpheqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpheqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpheqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpheqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmphgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmphgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmphgti">; // // BUILTIN_INFO(HEXAGON.A4_vcmphgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmphgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmphgtui">; // // BUILTIN_INFO(HEXAGON.A4_cmpheq,QI_ftype_SISI,2) // def int_hexagon_A4_cmpheq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpheq">; // // BUILTIN_INFO(HEXAGON.A4_cmphgt,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgt">; // // BUILTIN_INFO(HEXAGON.A4_cmphgtu,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgtu">; // // BUILTIN_INFO(HEXAGON.A4_cmpheqi,QI_ftype_SISI,2) // def int_hexagon_A4_cmpheqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpheqi">; // // BUILTIN_INFO(HEXAGON.A4_cmphgti,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgti">; // // BUILTIN_INFO(HEXAGON.A4_cmphgtui,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgtui">; // // BUILTIN_INFO(HEXAGON.A2_vcmpweq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpweq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpweq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpweq">; // // BUILTIN_INFO(HEXAGON.A2_vcmpwgt,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpwgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpwgt">; // // BUILTIN_INFO(HEXAGON.A2_vcmpwgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpwgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpwgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpweqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpweqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpweqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpweqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmpwgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpwgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpwgti">; // // BUILTIN_INFO(HEXAGON.A4_vcmpwgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpwgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpwgtui">; // // BUILTIN_INFO(HEXAGON.A4_boundscheck,QI_ftype_SIDI,2) // def int_hexagon_A4_boundscheck : -Hexagon_qi_sidi_Intrinsic<"HEXAGON_A4_boundscheck">; +Hexagon_si_sidi_Intrinsic<"HEXAGON_A4_boundscheck">; // // BUILTIN_INFO(HEXAGON.A4_tlbmatch,QI_ftype_DISI,2) // def int_hexagon_A4_tlbmatch : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_tlbmatch">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_tlbmatch">; // // BUILTIN_INFO(HEXAGON.C2_tfrpr,SI_ftype_QI,1) // @@ -1059,17 +1195,17 @@ Hexagon_si_qi_Intrinsic<"HEXAGON_C2_tfrpr">; // BUILTIN_INFO(HEXAGON.C2_tfrrp,QI_ftype_SI,1) // def int_hexagon_C2_tfrrp : -Hexagon_qi_si_Intrinsic<"HEXAGON_C2_tfrrp">; +Hexagon_si_si_Intrinsic<"HEXAGON_C2_tfrrp">; // // BUILTIN_INFO(HEXAGON.C4_fastcorner9,QI_ftype_QIQI,2) // def int_hexagon_C4_fastcorner9 : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9">; +Hexagon_si_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9">; // // BUILTIN_INFO(HEXAGON.C4_fastcorner9_not,QI_ftype_QIQI,2) // def int_hexagon_C4_fastcorner9_not : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9_not">; +Hexagon_si_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9_not">; // // BUILTIN_INFO(HEXAGON.M2_mpy_acc_hh_s0,SI_ftype_SISISI,3) // @@ -2849,7 +2985,7 @@ Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrp">; // BUILTIN_INFO(HEXAGON.A2_tfrpi,DI_ftype_SI,1) // def int_hexagon_A2_tfrpi : -Hexagon_di_si_Intrinsic<"HEXAGON_A2_tfrpi">; +Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrpi">; // // BUILTIN_INFO(HEXAGON.A2_zxtb,SI_ftype_SI,1) // @@ -3609,22 +3745,22 @@ Hexagon_sf_sfsfsf_Intrinsic<"HEXAGON_F2_sffms_lib">; // BUILTIN_INFO(HEXAGON.F2_sfcmpeq,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpeq : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpeq">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpeq">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpgt,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpgt : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpgt">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpgt">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpge,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpge : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpge">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpge">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpuo,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpuo : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpuo">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpuo">; // // BUILTIN_INFO(HEXAGON.F2_sfmax,SF_ftype_SFSF,2) // @@ -3639,7 +3775,7 @@ Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sfmin">; // BUILTIN_INFO(HEXAGON.F2_sfclass,QI_ftype_SFSI,2) // def int_hexagon_F2_sfclass : -Hexagon_qi_sfsi_Intrinsic<"HEXAGON_F2_sfclass">; +Hexagon_si_sfsi_Intrinsic<"HEXAGON_F2_sfclass">; // // BUILTIN_INFO(HEXAGON.F2_sfimm_p,SF_ftype_SI,1) // @@ -3666,80 +3802,30 @@ Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sffixupd">; def int_hexagon_F2_sffixupr : Hexagon_sf_sf_Intrinsic<"HEXAGON_F2_sffixupr">; // -// BUILTIN_INFO(HEXAGON.F2_dfadd,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfadd : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfadd">; -// -// BUILTIN_INFO(HEXAGON.F2_dfsub,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfsub : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfsub">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmpy,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmpy : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmpy">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffma : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma">; -// -// BUILTIN_INFO(HEXAGON.F2_dffms,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffms : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma_lib,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffma_lib : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma_lib">; -// -// BUILTIN_INFO(HEXAGON.F2_dffms_lib,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffms_lib : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms_lib">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma_sc,DF_ftype_DFDFDFQI,4) -// -def int_hexagon_F2_dffma_sc : -Hexagon_df_dfdfdfqi_Intrinsic<"HEXAGON_F2_dffma_sc">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmax,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmax : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmax">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmin,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmin : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmin">; -// // BUILTIN_INFO(HEXAGON.F2_dfcmpeq,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpeq : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpeq">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpeq">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpgt,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpgt : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpgt">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpgt">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpge,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpge : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpge">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpge">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpuo,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpuo : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpuo">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpuo">; // // BUILTIN_INFO(HEXAGON.F2_dfclass,QI_ftype_DFSI,2) // def int_hexagon_F2_dfclass : -Hexagon_qi_dfsi_Intrinsic<"HEXAGON_F2_dfclass">; +Hexagon_si_dfsi_Intrinsic<"HEXAGON_F2_dfclass">; // // BUILTIN_INFO(HEXAGON.F2_dfimm_p,DF_ftype_SI,1) // @@ -3751,21 +3837,6 @@ Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_p">; def int_hexagon_F2_dfimm_n : Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_n">; // -// BUILTIN_INFO(HEXAGON.F2_dffixupn,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dffixupn : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupn">; -// -// BUILTIN_INFO(HEXAGON.F2_dffixupd,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dffixupd : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupd">; -// -// BUILTIN_INFO(HEXAGON.F2_dffixupr,DF_ftype_DF,1) -// -def int_hexagon_F2_dffixupr : -Hexagon_df_df_Intrinsic<"HEXAGON_F2_dffixupr">; -// // BUILTIN_INFO(HEXAGON.F2_conv_sf2df,DF_ftype_SF,1) // def int_hexagon_F2_conv_sf2df : @@ -4494,12 +4565,12 @@ Hexagon_di_didi_Intrinsic<"HEXAGON_S2_extractup_rp">; // BUILTIN_INFO(HEXAGON.S2_tstbit_i,QI_ftype_SISI,2) // def int_hexagon_S2_tstbit_i : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_i">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_tstbit_i">; // // BUILTIN_INFO(HEXAGON.S4_ntstbit_i,QI_ftype_SISI,2) // def int_hexagon_S4_ntstbit_i : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_i">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_ntstbit_i">; // // BUILTIN_INFO(HEXAGON.S2_setbit_i,SI_ftype_SISI,2) // @@ -4519,12 +4590,12 @@ Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_clrbit_i">; // BUILTIN_INFO(HEXAGON.S2_tstbit_r,QI_ftype_SISI,2) // def int_hexagon_S2_tstbit_r : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_r">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_tstbit_r">; // // BUILTIN_INFO(HEXAGON.S4_ntstbit_r,QI_ftype_SISI,2) // def int_hexagon_S4_ntstbit_r : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_r">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_ntstbit_r">; // // BUILTIN_INFO(HEXAGON.S2_setbit_r,SI_ftype_SISI,2) // @@ -4875,3 +4946,21 @@ Hexagon_di_di_Intrinsic<"HEXAGON_S2_interleave">; // def int_hexagon_S2_deinterleave : Hexagon_di_di_Intrinsic<"HEXAGON_S2_deinterleave">; + +def llvm_ptr32_ty : LLVMPointerType<llvm_i32_ty>; +def llvm_ptr64_ty : LLVMPointerType<llvm_i64_ty>; + +// Mark locked loads as read/write to prevent any accidental reordering. +def int_hexagon_L2_loadw_locked : +Hexagon_Intrinsic<"HEXAGON_L2_loadw_locked", [llvm_i32_ty], [llvm_ptr32_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; +def int_hexagon_L4_loadd_locked : +Hexagon_Intrinsic<"HEXAGON_L4_loadd_locked", [llvm_i64_ty], [llvm_ptr64_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; + +def int_hexagon_S2_storew_locked : +Hexagon_Intrinsic<"HEXAGON_S2_storew_locked", [llvm_i32_ty], + [llvm_ptr32_ty, llvm_i32_ty], [IntrReadWriteArgMem, NoCapture<0>]>; +def int_hexagon_S4_stored_locked : +Hexagon_Intrinsic<"HEXAGON_S4_stored_locked", [llvm_i32_ty], + [llvm_ptr64_ty, llvm_i64_ty], [IntrReadWriteArgMem, NoCapture<0>]>; diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 5cdabdeadaea..79654695837d 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -24,7 +24,8 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_dcbst : Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbt : Intrinsic<[], [llvm_ptr_ty], [IntrReadWriteArgMem, NoCapture<0>]>; - def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; def int_ppc_dcbz : Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>; @@ -37,6 +38,25 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". // generated by the PowerPC backend! def int_ppc_mtctr : Intrinsic<[], [llvm_anyint_ty], []>; def int_ppc_is_decremented_ctr_nonzero : Intrinsic<[llvm_i1_ty], [], []>; + + // Intrinsics for [double]word extended forms of divide instructions + def int_ppc_divwe : GCCBuiltin<"__builtin_divwe">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_divweu : GCCBuiltin<"__builtin_divweu">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_divde : GCCBuiltin<"__builtin_divde">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_ppc_divdeu : GCCBuiltin<"__builtin_divdeu">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; + + // Bit permute doubleword + def int_ppc_bpermd : GCCBuiltin<"__builtin_bpermd">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; } @@ -73,7 +93,7 @@ class PowerPC_Vec_FFF_Intrinsic<string GCCIntSuffix> [llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; -/// PowerPC_Vec_BBB_Intrinsic - A PowerPC intrinsic that takes two v16f8 +/// PowerPC_Vec_BBB_Intrinsic - A PowerPC intrinsic that takes two v16i8 /// vectors and returns one. These intrinsics have no side effects. class PowerPC_Vec_BBB_Intrinsic<string GCCIntSuffix> : PowerPC_Vec_Intrinsic<GCCIntSuffix, @@ -94,6 +114,19 @@ class PowerPC_Vec_WWW_Intrinsic<string GCCIntSuffix> [llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +/// PowerPC_Vec_DDD_Intrinsic - A PowerPC intrinsic that takes two v2i64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_DDD_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +/// PowerPC_Vec_QQQ_Intrinsic - A PowerPC intrinsic that takes two v1i128 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_QQQ_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v1i128_ty], [llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; //===----------------------------------------------------------------------===// // PowerPC VSX Intrinsic Class Definitions. @@ -120,7 +153,6 @@ class PowerPC_VSX_Sca_DDD_Intrinsic<string GCCIntSuffix> [llvm_double_ty], [llvm_double_ty, llvm_double_ty], [IntrNoMem]>; - //===----------------------------------------------------------------------===// // PowerPC Altivec Intrinsic Definitions. @@ -198,7 +230,17 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_altivec_vcmpgtfp : GCCBuiltin<"__builtin_altivec_vcmpgtfp">, Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; - + + def int_ppc_altivec_vcmpequd : GCCBuiltin<"__builtin_altivec_vcmpequd">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsd : GCCBuiltin<"__builtin_altivec_vcmpgtsd">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtud : GCCBuiltin<"__builtin_altivec_vcmpgtud">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpequw : GCCBuiltin<"__builtin_altivec_vcmpequw">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; @@ -242,7 +284,17 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_altivec_vcmpgtfp_p : GCCBuiltin<"__builtin_altivec_vcmpgtfp_p">, Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], [IntrNoMem]>; - + + def int_ppc_altivec_vcmpequd_p : GCCBuiltin<"__builtin_altivec_vcmpequd_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsd_p : GCCBuiltin<"__builtin_altivec_vcmpgtsd_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtud_p : GCCBuiltin<"__builtin_altivec_vcmpgtud_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v2i64_ty,llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpequw_p : GCCBuiltin<"__builtin_altivec_vcmpequw_p">, Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], [IntrNoMem]>; @@ -287,18 +339,22 @@ def int_ppc_altivec_vmaxfp : PowerPC_Vec_FFF_Intrinsic<"vmaxfp">; def int_ppc_altivec_vmaxsb : PowerPC_Vec_BBB_Intrinsic<"vmaxsb">; def int_ppc_altivec_vmaxsh : PowerPC_Vec_HHH_Intrinsic<"vmaxsh">; def int_ppc_altivec_vmaxsw : PowerPC_Vec_WWW_Intrinsic<"vmaxsw">; +def int_ppc_altivec_vmaxsd : PowerPC_Vec_DDD_Intrinsic<"vmaxsd">; def int_ppc_altivec_vmaxub : PowerPC_Vec_BBB_Intrinsic<"vmaxub">; def int_ppc_altivec_vmaxuh : PowerPC_Vec_HHH_Intrinsic<"vmaxuh">; def int_ppc_altivec_vmaxuw : PowerPC_Vec_WWW_Intrinsic<"vmaxuw">; +def int_ppc_altivec_vmaxud : PowerPC_Vec_DDD_Intrinsic<"vmaxud">; // Vector minimum. def int_ppc_altivec_vminfp : PowerPC_Vec_FFF_Intrinsic<"vminfp">; def int_ppc_altivec_vminsb : PowerPC_Vec_BBB_Intrinsic<"vminsb">; def int_ppc_altivec_vminsh : PowerPC_Vec_HHH_Intrinsic<"vminsh">; def int_ppc_altivec_vminsw : PowerPC_Vec_WWW_Intrinsic<"vminsw">; +def int_ppc_altivec_vminsd : PowerPC_Vec_DDD_Intrinsic<"vminsd">; def int_ppc_altivec_vminub : PowerPC_Vec_BBB_Intrinsic<"vminub">; def int_ppc_altivec_vminuh : PowerPC_Vec_HHH_Intrinsic<"vminuh">; def int_ppc_altivec_vminuw : PowerPC_Vec_WWW_Intrinsic<"vminuw">; +def int_ppc_altivec_vminud : PowerPC_Vec_DDD_Intrinsic<"vminud">; // Saturating adds. def int_ppc_altivec_vaddubs : PowerPC_Vec_BBB_Intrinsic<"vaddubs">; @@ -308,6 +364,7 @@ def int_ppc_altivec_vaddshs : PowerPC_Vec_HHH_Intrinsic<"vaddshs">; def int_ppc_altivec_vadduws : PowerPC_Vec_WWW_Intrinsic<"vadduws">; def int_ppc_altivec_vaddsws : PowerPC_Vec_WWW_Intrinsic<"vaddsws">; def int_ppc_altivec_vaddcuw : PowerPC_Vec_WWW_Intrinsic<"vaddcuw">; +def int_ppc_altivec_vaddcuq : PowerPC_Vec_QQQ_Intrinsic<"vaddcuq">; // Saturating subs. def int_ppc_altivec_vsububs : PowerPC_Vec_BBB_Intrinsic<"vsububs">; @@ -317,6 +374,7 @@ def int_ppc_altivec_vsubshs : PowerPC_Vec_HHH_Intrinsic<"vsubshs">; def int_ppc_altivec_vsubuws : PowerPC_Vec_WWW_Intrinsic<"vsubuws">; def int_ppc_altivec_vsubsws : PowerPC_Vec_WWW_Intrinsic<"vsubsws">; def int_ppc_altivec_vsubcuw : PowerPC_Vec_WWW_Intrinsic<"vsubcuw">; +def int_ppc_altivec_vsubcuq : PowerPC_Vec_QQQ_Intrinsic<"vsubcuq">; let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". // Saturating multiply-adds. @@ -361,12 +419,18 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". def int_ppc_altivec_vmulesh : GCCBuiltin<"__builtin_altivec_vmulesh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmulesw : GCCBuiltin<"__builtin_altivec_vmulesw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; def int_ppc_altivec_vmuleub : GCCBuiltin<"__builtin_altivec_vmuleub">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; def int_ppc_altivec_vmuleuh : GCCBuiltin<"__builtin_altivec_vmuleuh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmuleuw : GCCBuiltin<"__builtin_altivec_vmuleuw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; def int_ppc_altivec_vmulosb : GCCBuiltin<"__builtin_altivec_vmulosb">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], @@ -374,12 +438,18 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". def int_ppc_altivec_vmulosh : GCCBuiltin<"__builtin_altivec_vmulosh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmulosw : GCCBuiltin<"__builtin_altivec_vmulosw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; def int_ppc_altivec_vmuloub : GCCBuiltin<"__builtin_altivec_vmuloub">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; def int_ppc_altivec_vmulouh : GCCBuiltin<"__builtin_altivec_vmulouh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmulouw : GCCBuiltin<"__builtin_altivec_vmulouw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; // Vector Sum Intructions. def int_ppc_altivec_vsumsws : GCCBuiltin<"__builtin_altivec_vsumsws">, @@ -419,6 +489,12 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". def int_ppc_altivec_vpkswus : GCCBuiltin<"__builtin_altivec_vpkswus">, Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vpksdss : GCCBuiltin<"__builtin_altivec_vpksdss">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpksdus : GCCBuiltin<"__builtin_altivec_vpksdus">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; // vpkuhum is lowered to a shuffle. def int_ppc_altivec_vpkuhus : GCCBuiltin<"__builtin_altivec_vpkuhus">, Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], @@ -427,6 +503,10 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". def int_ppc_altivec_vpkuwus : GCCBuiltin<"__builtin_altivec_vpkuwus">, Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + // vpkudum is lowered to a shuffle. + def int_ppc_altivec_vpkudus : GCCBuiltin<"__builtin_altivec_vpkudus">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; // Unpacks. def int_ppc_altivec_vupkhpx : GCCBuiltin<"__builtin_altivec_vupkhpx">, @@ -435,12 +515,16 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; def int_ppc_altivec_vupkhsh : GCCBuiltin<"__builtin_altivec_vupkhsh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupkhsw : GCCBuiltin<"__builtin_altivec_vupkhsw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; def int_ppc_altivec_vupklpx : GCCBuiltin<"__builtin_altivec_vupklpx">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; def int_ppc_altivec_vupklsb : GCCBuiltin<"__builtin_altivec_vupklsb">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; def int_ppc_altivec_vupklsh : GCCBuiltin<"__builtin_altivec_vupklsh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklsw : GCCBuiltin<"__builtin_altivec_vupklsw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; // FP <-> integer conversion. @@ -465,6 +549,26 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; def int_ppc_altivec_vrfiz : GCCBuiltin<"__builtin_altivec_vrfiz">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + + // Add Extended Quadword + def int_ppc_altivec_vaddeuqm : GCCBuiltin<"__builtin_altivec_vaddeuqm">, + Intrinsic<[llvm_v1i128_ty], + [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; + def int_ppc_altivec_vaddecuq : GCCBuiltin<"__builtin_altivec_vaddecuq">, + Intrinsic<[llvm_v1i128_ty], + [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; + + // Sub Extended Quadword + def int_ppc_altivec_vsubeuqm : GCCBuiltin<"__builtin_altivec_vsubeuqm">, + Intrinsic<[llvm_v1i128_ty], + [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsubecuq : GCCBuiltin<"__builtin_altivec_vsubecuq">, + Intrinsic<[llvm_v1i128_ty], + [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; } def int_ppc_altivec_vsl : PowerPC_Vec_WWW_Intrinsic<"vsl">; @@ -489,6 +593,7 @@ def int_ppc_altivec_vsraw : PowerPC_Vec_WWW_Intrinsic<"vsraw">; def int_ppc_altivec_vrlb : PowerPC_Vec_BBB_Intrinsic<"vrlb">; def int_ppc_altivec_vrlh : PowerPC_Vec_HHH_Intrinsic<"vrlh">; def int_ppc_altivec_vrlw : PowerPC_Vec_WWW_Intrinsic<"vrlw">; +def int_ppc_altivec_vrld : PowerPC_Vec_DDD_Intrinsic<"vrld">; let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". // Miscellaneous. @@ -510,6 +615,42 @@ def int_ppc_altivec_vlogefp : PowerPC_Vec_FF_Intrinsic<"vlogefp">; def int_ppc_altivec_vrefp : PowerPC_Vec_FF_Intrinsic<"vrefp">; def int_ppc_altivec_vrsqrtefp : PowerPC_Vec_FF_Intrinsic<"vrsqrtefp">; +// Power8 Intrinsics +// Crypto +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + def int_ppc_altivec_crypto_vsbox : + GCCBuiltin<"__builtin_altivec_crypto_vsbox">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + def int_ppc_altivec_crypto_vpermxor : + GCCBuiltin<"__builtin_altivec_crypto_vpermxor">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_ppc_altivec_crypto_vshasigmad : + GCCBuiltin<"__builtin_altivec_crypto_vshasigmad">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_ppc_altivec_crypto_vshasigmaw : + GCCBuiltin<"__builtin_altivec_crypto_vshasigmaw">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +} +def int_ppc_altivec_crypto_vcipher : + PowerPC_Vec_DDD_Intrinsic<"crypto_vcipher">; +def int_ppc_altivec_crypto_vcipherlast : + PowerPC_Vec_DDD_Intrinsic<"crypto_vcipherlast">; +def int_ppc_altivec_crypto_vncipher : + PowerPC_Vec_DDD_Intrinsic<"crypto_vncipher">; +def int_ppc_altivec_crypto_vncipherlast : + PowerPC_Vec_DDD_Intrinsic<"crypto_vncipherlast">; +def int_ppc_altivec_crypto_vpmsumb : + PowerPC_Vec_BBB_Intrinsic<"crypto_vpmsumb">; +def int_ppc_altivec_crypto_vpmsumh : + PowerPC_Vec_HHH_Intrinsic<"crypto_vpmsumh">; +def int_ppc_altivec_crypto_vpmsumw : + PowerPC_Vec_WWW_Intrinsic<"crypto_vpmsumw">; +def int_ppc_altivec_crypto_vpmsumd : + PowerPC_Vec_DDD_Intrinsic<"crypto_vpmsumd">; //===----------------------------------------------------------------------===// // PowerPC VSX Intrinsic Definitions. @@ -542,3 +683,239 @@ def int_ppc_vsx_xsmindp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmindp">; def int_ppc_vsx_xvdivdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvdivdp">; def int_ppc_vsx_xvdivsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvdivsp">; } + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsics. +// + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + /// PowerPC_QPX_Intrinsic - Base class for all QPX intrinsics. + class PowerPC_QPX_Intrinsic<string GCCIntSuffix, list<LLVMType> ret_types, + list<LLVMType> param_types, + list<IntrinsicProperty> properties> + : GCCBuiltin<!strconcat("__builtin_qpx_", GCCIntSuffix)>, + Intrinsic<ret_types, param_types, properties>; +} + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsic Class Definitions. +// + +/// PowerPC_QPX_FF_Intrinsic - A PowerPC intrinsic that takes one v4f64 +/// vector and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FF_Intrinsic<string GCCIntSuffix> + : PowerPC_QPX_Intrinsic<GCCIntSuffix, + [llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; + +/// PowerPC_QPX_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FFF_Intrinsic<string GCCIntSuffix> + : PowerPC_QPX_Intrinsic<GCCIntSuffix, + [llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty], + [IntrNoMem]>; + +/// PowerPC_QPX_FFFF_Intrinsic - A PowerPC intrinsic that takes three v4f64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FFFF_Intrinsic<string GCCIntSuffix> + : PowerPC_QPX_Intrinsic<GCCIntSuffix, + [llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], + [IntrNoMem]>; + +/// PowerPC_QPX_Load_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and returns a v4f64. +class PowerPC_QPX_Load_Intrinsic<string GCCIntSuffix> + : PowerPC_QPX_Intrinsic<GCCIntSuffix, + [llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + +/// PowerPC_QPX_LoadPerm_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and returns a v4f64 permutation. +class PowerPC_QPX_LoadPerm_Intrinsic<string GCCIntSuffix> + : PowerPC_QPX_Intrinsic<GCCIntSuffix, + [llvm_v4f64_ty], [llvm_ptr_ty], [IntrNoMem]>; + +/// PowerPC_QPX_Store_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and stores a v4f64. +class PowerPC_QPX_Store_Intrinsic<string GCCIntSuffix> + : PowerPC_QPX_Intrinsic<GCCIntSuffix, + [], [llvm_v4f64_ty, llvm_ptr_ty], + [IntrReadWriteArgMem]>; + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + // Add Instructions + def int_ppc_qpx_qvfadd : PowerPC_QPX_FFF_Intrinsic<"qvfadd">; + def int_ppc_qpx_qvfadds : PowerPC_QPX_FFF_Intrinsic<"qvfadds">; + def int_ppc_qpx_qvfsub : PowerPC_QPX_FFF_Intrinsic<"qvfsub">; + def int_ppc_qpx_qvfsubs : PowerPC_QPX_FFF_Intrinsic<"qvfsubs">; + + // Estimate Instructions + def int_ppc_qpx_qvfre : PowerPC_QPX_FF_Intrinsic<"qvfre">; + def int_ppc_qpx_qvfres : PowerPC_QPX_FF_Intrinsic<"qvfres">; + def int_ppc_qpx_qvfrsqrte : PowerPC_QPX_FF_Intrinsic<"qvfrsqrte">; + def int_ppc_qpx_qvfrsqrtes : PowerPC_QPX_FF_Intrinsic<"qvfrsqrtes">; + + // Multiply Instructions + def int_ppc_qpx_qvfmul : PowerPC_QPX_FFF_Intrinsic<"qvfmul">; + def int_ppc_qpx_qvfmuls : PowerPC_QPX_FFF_Intrinsic<"qvfmuls">; + def int_ppc_qpx_qvfxmul : PowerPC_QPX_FFF_Intrinsic<"qvfxmul">; + def int_ppc_qpx_qvfxmuls : PowerPC_QPX_FFF_Intrinsic<"qvfxmuls">; + + // Multiply-add instructions + def int_ppc_qpx_qvfmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfmadd">; + def int_ppc_qpx_qvfmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfmadds">; + def int_ppc_qpx_qvfnmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfnmadd">; + def int_ppc_qpx_qvfnmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfnmadds">; + def int_ppc_qpx_qvfmsub : PowerPC_QPX_FFFF_Intrinsic<"qvfmsub">; + def int_ppc_qpx_qvfmsubs : PowerPC_QPX_FFFF_Intrinsic<"qvfmsubs">; + def int_ppc_qpx_qvfnmsub : PowerPC_QPX_FFFF_Intrinsic<"qvfnmsub">; + def int_ppc_qpx_qvfnmsubs : PowerPC_QPX_FFFF_Intrinsic<"qvfnmsubs">; + def int_ppc_qpx_qvfxmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxmadd">; + def int_ppc_qpx_qvfxmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxmadds">; + def int_ppc_qpx_qvfxxnpmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxnpmadd">; + def int_ppc_qpx_qvfxxnpmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxnpmadds">; + def int_ppc_qpx_qvfxxcpnmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxcpnmadd">; + def int_ppc_qpx_qvfxxcpnmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxcpnmadds">; + def int_ppc_qpx_qvfxxmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxmadd">; + def int_ppc_qpx_qvfxxmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxmadds">; + + // Select Instruction + def int_ppc_qpx_qvfsel : PowerPC_QPX_FFFF_Intrinsic<"qvfsel">; + + // Permute Instruction + def int_ppc_qpx_qvfperm : PowerPC_QPX_FFFF_Intrinsic<"qvfperm">; + + // Convert and Round Instructions + def int_ppc_qpx_qvfctid : PowerPC_QPX_FF_Intrinsic<"qvfctid">; + def int_ppc_qpx_qvfctidu : PowerPC_QPX_FF_Intrinsic<"qvfctidu">; + def int_ppc_qpx_qvfctidz : PowerPC_QPX_FF_Intrinsic<"qvfctidz">; + def int_ppc_qpx_qvfctiduz : PowerPC_QPX_FF_Intrinsic<"qvfctiduz">; + def int_ppc_qpx_qvfctiw : PowerPC_QPX_FF_Intrinsic<"qvfctiw">; + def int_ppc_qpx_qvfctiwu : PowerPC_QPX_FF_Intrinsic<"qvfctiwu">; + def int_ppc_qpx_qvfctiwz : PowerPC_QPX_FF_Intrinsic<"qvfctiwz">; + def int_ppc_qpx_qvfctiwuz : PowerPC_QPX_FF_Intrinsic<"qvfctiwuz">; + def int_ppc_qpx_qvfcfid : PowerPC_QPX_FF_Intrinsic<"qvfcfid">; + def int_ppc_qpx_qvfcfidu : PowerPC_QPX_FF_Intrinsic<"qvfcfidu">; + def int_ppc_qpx_qvfcfids : PowerPC_QPX_FF_Intrinsic<"qvfcfids">; + def int_ppc_qpx_qvfcfidus : PowerPC_QPX_FF_Intrinsic<"qvfcfidus">; + def int_ppc_qpx_qvfrsp : PowerPC_QPX_FF_Intrinsic<"qvfrsp">; + def int_ppc_qpx_qvfriz : PowerPC_QPX_FF_Intrinsic<"qvfriz">; + def int_ppc_qpx_qvfrin : PowerPC_QPX_FF_Intrinsic<"qvfrin">; + def int_ppc_qpx_qvfrip : PowerPC_QPX_FF_Intrinsic<"qvfrip">; + def int_ppc_qpx_qvfrim : PowerPC_QPX_FF_Intrinsic<"qvfrim">; + + // Move Instructions + def int_ppc_qpx_qvfneg : PowerPC_QPX_FF_Intrinsic<"qvfneg">; + def int_ppc_qpx_qvfabs : PowerPC_QPX_FF_Intrinsic<"qvfabs">; + def int_ppc_qpx_qvfnabs : PowerPC_QPX_FF_Intrinsic<"qvfnabs">; + def int_ppc_qpx_qvfcpsgn : PowerPC_QPX_FFF_Intrinsic<"qvfcpsgn">; + + // Compare Instructions + def int_ppc_qpx_qvftstnan : PowerPC_QPX_FFF_Intrinsic<"qvftstnan">; + def int_ppc_qpx_qvfcmplt : PowerPC_QPX_FFF_Intrinsic<"qvfcmplt">; + def int_ppc_qpx_qvfcmpgt : PowerPC_QPX_FFF_Intrinsic<"qvfcmpgt">; + def int_ppc_qpx_qvfcmpeq : PowerPC_QPX_FFF_Intrinsic<"qvfcmpeq">; + + // Load instructions + def int_ppc_qpx_qvlfd : PowerPC_QPX_Load_Intrinsic<"qvlfd">; + def int_ppc_qpx_qvlfda : PowerPC_QPX_Load_Intrinsic<"qvlfda">; + def int_ppc_qpx_qvlfs : PowerPC_QPX_Load_Intrinsic<"qvlfs">; + def int_ppc_qpx_qvlfsa : PowerPC_QPX_Load_Intrinsic<"qvlfsa">; + + def int_ppc_qpx_qvlfcda : PowerPC_QPX_Load_Intrinsic<"qvlfcda">; + def int_ppc_qpx_qvlfcd : PowerPC_QPX_Load_Intrinsic<"qvlfcd">; + def int_ppc_qpx_qvlfcsa : PowerPC_QPX_Load_Intrinsic<"qvlfcsa">; + def int_ppc_qpx_qvlfcs : PowerPC_QPX_Load_Intrinsic<"qvlfcs">; + def int_ppc_qpx_qvlfiwaa : PowerPC_QPX_Load_Intrinsic<"qvlfiwaa">; + def int_ppc_qpx_qvlfiwa : PowerPC_QPX_Load_Intrinsic<"qvlfiwa">; + def int_ppc_qpx_qvlfiwza : PowerPC_QPX_Load_Intrinsic<"qvlfiwza">; + def int_ppc_qpx_qvlfiwz : PowerPC_QPX_Load_Intrinsic<"qvlfiwz">; + + def int_ppc_qpx_qvlpcld : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcld">; + def int_ppc_qpx_qvlpcls : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcls">; + def int_ppc_qpx_qvlpcrd : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcrd">; + def int_ppc_qpx_qvlpcrs : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcrs">; + + // Store instructions + def int_ppc_qpx_qvstfd : PowerPC_QPX_Store_Intrinsic<"qvstfd">; + def int_ppc_qpx_qvstfda : PowerPC_QPX_Store_Intrinsic<"qvstfda">; + def int_ppc_qpx_qvstfs : PowerPC_QPX_Store_Intrinsic<"qvstfs">; + def int_ppc_qpx_qvstfsa : PowerPC_QPX_Store_Intrinsic<"qvstfsa">; + + def int_ppc_qpx_qvstfcda : PowerPC_QPX_Store_Intrinsic<"qvstfcda">; + def int_ppc_qpx_qvstfcd : PowerPC_QPX_Store_Intrinsic<"qvstfcd">; + def int_ppc_qpx_qvstfcsa : PowerPC_QPX_Store_Intrinsic<"qvstfcsa">; + def int_ppc_qpx_qvstfcs : PowerPC_QPX_Store_Intrinsic<"qvstfcs">; + def int_ppc_qpx_qvstfiwa : PowerPC_QPX_Store_Intrinsic<"qvstfiwa">; + def int_ppc_qpx_qvstfiw : PowerPC_QPX_Store_Intrinsic<"qvstfiw">; + + // Logical and permutation formation + def int_ppc_qpx_qvflogical : PowerPC_QPX_Intrinsic<"qvflogical", + [llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_qpx_qvgpci : PowerPC_QPX_Intrinsic<"qvgpci", + [llvm_v4f64_ty], [llvm_i32_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// PowerPC HTM Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + +def int_ppc_tbegin : GCCBuiltin<"__builtin_tbegin">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; +def int_ppc_tend : GCCBuiltin<"__builtin_tend">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + +def int_ppc_tabort : GCCBuiltin<"__builtin_tabort">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; +def int_ppc_tabortwc : GCCBuiltin<"__builtin_tabortwc">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +def int_ppc_tabortwci : GCCBuiltin<"__builtin_tabortwci">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +def int_ppc_tabortdc : GCCBuiltin<"__builtin_tabortdc">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +def int_ppc_tabortdci : GCCBuiltin<"__builtin_tabortdci">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + +def int_ppc_tcheck : GCCBuiltin<"__builtin_tcheck">, + Intrinsic<[llvm_i32_ty], [], []>; +def int_ppc_treclaim : GCCBuiltin<"__builtin_treclaim">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; +def int_ppc_trechkpt : GCCBuiltin<"__builtin_trechkpt">, + Intrinsic<[llvm_i32_ty], [], []>; +def int_ppc_tsr : GCCBuiltin<"__builtin_tsr">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + +def int_ppc_get_texasr : GCCBuiltin<"__builtin_get_texasr">, + Intrinsic<[llvm_i64_ty], [], []>; +def int_ppc_get_texasru : GCCBuiltin<"__builtin_get_texasru">, + Intrinsic<[llvm_i64_ty], [], []>; +def int_ppc_get_tfhar : GCCBuiltin<"__builtin_get_tfhar">, + Intrinsic<[llvm_i64_ty], [], []>; +def int_ppc_get_tfiar : GCCBuiltin<"__builtin_get_tfiar">, + Intrinsic<[llvm_i64_ty], [], []>; + +def int_ppc_set_texasr : GCCBuiltin<"__builtin_set_texasr">, + Intrinsic<[], [llvm_i64_ty], []>; +def int_ppc_set_texasru : GCCBuiltin<"__builtin_set_texasru">, + Intrinsic<[], [llvm_i64_ty], []>; +def int_ppc_set_tfhar : GCCBuiltin<"__builtin_set_tfhar">, + Intrinsic<[], [llvm_i64_ty], []>; +def int_ppc_set_tfiar : GCCBuiltin<"__builtin_set_tfiar">, + Intrinsic<[], [llvm_i64_ty], []>; + +// Extended mnemonics +def int_ppc_tendall : GCCBuiltin<"__builtin_tendall">, + Intrinsic<[llvm_i32_ty], [], []>; +def int_ppc_tresume : GCCBuiltin<"__builtin_tresume">, + Intrinsic<[llvm_i32_ty], [], []>; +def int_ppc_tsuspend : GCCBuiltin<"__builtin_tsuspend">, + Intrinsic<[llvm_i32_ty], [], []>; + +def int_ppc_ttest : GCCBuiltin<"__builtin_ttest">, + Intrinsic<[llvm_i64_ty], [], []>; +} diff --git a/include/llvm/IR/IntrinsicsSystemZ.td b/include/llvm/IR/IntrinsicsSystemZ.td new file mode 100644 index 000000000000..96e7ca525696 --- /dev/null +++ b/include/llvm/IR/IntrinsicsSystemZ.td @@ -0,0 +1,376 @@ +//===- IntrinsicsSystemZ.td - Defines SystemZ 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 SystemZ-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +class SystemZUnaryConv<string name, LLVMType result, LLVMType arg> + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[result], [arg], [IntrNoMem]>; + +class SystemZUnary<string name, LLVMType type> + : SystemZUnaryConv<name, type, type>; + +class SystemZUnaryConvCC<LLVMType result, LLVMType arg> + : Intrinsic<[result, llvm_i32_ty], [arg], [IntrNoMem]>; + +class SystemZUnaryCC<LLVMType type> + : SystemZUnaryConvCC<type, type>; + +class SystemZBinaryConv<string name, LLVMType result, LLVMType arg> + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[result], [arg, arg], [IntrNoMem]>; + +class SystemZBinary<string name, LLVMType type> + : SystemZBinaryConv<name, type, type>; + +class SystemZBinaryInt<string name, LLVMType type> + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[type], [type, llvm_i32_ty], [IntrNoMem]>; + +class SystemZBinaryConvCC<LLVMType result, LLVMType arg> + : Intrinsic<[result, llvm_i32_ty], [arg, arg], [IntrNoMem]>; + +class SystemZBinaryConvIntCC<LLVMType result, LLVMType arg> + : Intrinsic<[result, llvm_i32_ty], [arg, llvm_i32_ty], [IntrNoMem]>; + +class SystemZBinaryCC<LLVMType type> + : SystemZBinaryConvCC<type, type>; + +class SystemZTernaryConv<string name, LLVMType result, LLVMType arg> + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[result], [arg, arg, result], [IntrNoMem]>; + +class SystemZTernary<string name, LLVMType type> + : SystemZTernaryConv<name, type, type>; + +class SystemZTernaryInt<string name, LLVMType type> + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[type], [type, type, llvm_i32_ty], [IntrNoMem]>; + +class SystemZTernaryIntCC<LLVMType type> + : Intrinsic<[type, llvm_i32_ty], [type, type, llvm_i32_ty], [IntrNoMem]>; + +class SystemZQuaternaryInt<string name, LLVMType type> + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[type], [type, type, type, llvm_i32_ty], [IntrNoMem]>; + +class SystemZQuaternaryIntCC<LLVMType type> + : Intrinsic<[type, llvm_i32_ty], [type, type, type, llvm_i32_ty], + [IntrNoMem]>; + +multiclass SystemZUnaryExtBHF<string name> { + def b : SystemZUnaryConv<name##"b", llvm_v8i16_ty, llvm_v16i8_ty>; + def h : SystemZUnaryConv<name##"h", llvm_v4i32_ty, llvm_v8i16_ty>; + def f : SystemZUnaryConv<name##"f", llvm_v2i64_ty, llvm_v4i32_ty>; +} + +multiclass SystemZUnaryExtBHWF<string name> { + def b : SystemZUnaryConv<name##"b", llvm_v8i16_ty, llvm_v16i8_ty>; + def hw : SystemZUnaryConv<name##"hw", llvm_v4i32_ty, llvm_v8i16_ty>; + def f : SystemZUnaryConv<name##"f", llvm_v2i64_ty, llvm_v4i32_ty>; +} + +multiclass SystemZUnaryBHF<string name> { + def b : SystemZUnary<name##"b", llvm_v16i8_ty>; + def h : SystemZUnary<name##"h", llvm_v8i16_ty>; + def f : SystemZUnary<name##"f", llvm_v4i32_ty>; +} + +multiclass SystemZUnaryBHFG<string name> : SystemZUnaryBHF<name> { + def g : SystemZUnary<name##"g", llvm_v2i64_ty>; +} + +multiclass SystemZUnaryCCBHF { + def bs : SystemZUnaryCC<llvm_v16i8_ty>; + def hs : SystemZUnaryCC<llvm_v8i16_ty>; + def fs : SystemZUnaryCC<llvm_v4i32_ty>; +} + +multiclass SystemZBinaryTruncHFG<string name> { + def h : SystemZBinaryConv<name##"h", llvm_v16i8_ty, llvm_v8i16_ty>; + def f : SystemZBinaryConv<name##"f", llvm_v8i16_ty, llvm_v4i32_ty>; + def g : SystemZBinaryConv<name##"g", llvm_v4i32_ty, llvm_v2i64_ty>; +} + +multiclass SystemZBinaryTruncCCHFG { + def hs : SystemZBinaryConvCC<llvm_v16i8_ty, llvm_v8i16_ty>; + def fs : SystemZBinaryConvCC<llvm_v8i16_ty, llvm_v4i32_ty>; + def gs : SystemZBinaryConvCC<llvm_v4i32_ty, llvm_v2i64_ty>; +} + +multiclass SystemZBinaryExtBHF<string name> { + def b : SystemZBinaryConv<name##"b", llvm_v8i16_ty, llvm_v16i8_ty>; + def h : SystemZBinaryConv<name##"h", llvm_v4i32_ty, llvm_v8i16_ty>; + def f : SystemZBinaryConv<name##"f", llvm_v2i64_ty, llvm_v4i32_ty>; +} + +multiclass SystemZBinaryExtBHFG<string name> : SystemZBinaryExtBHF<name> { + def g : SystemZBinaryConv<name##"g", llvm_v16i8_ty, llvm_v2i64_ty>; +} + +multiclass SystemZBinaryBHF<string name> { + def b : SystemZBinary<name##"b", llvm_v16i8_ty>; + def h : SystemZBinary<name##"h", llvm_v8i16_ty>; + def f : SystemZBinary<name##"f", llvm_v4i32_ty>; +} + +multiclass SystemZBinaryBHFG<string name> : SystemZBinaryBHF<name> { + def g : SystemZBinary<name##"g", llvm_v2i64_ty>; +} + +multiclass SystemZBinaryIntBHFG<string name> { + def b : SystemZBinaryInt<name##"b", llvm_v16i8_ty>; + def h : SystemZBinaryInt<name##"h", llvm_v8i16_ty>; + def f : SystemZBinaryInt<name##"f", llvm_v4i32_ty>; + def g : SystemZBinaryInt<name##"g", llvm_v2i64_ty>; +} + +multiclass SystemZBinaryCCBHF { + def bs : SystemZBinaryCC<llvm_v16i8_ty>; + def hs : SystemZBinaryCC<llvm_v8i16_ty>; + def fs : SystemZBinaryCC<llvm_v4i32_ty>; +} + +multiclass SystemZCompareBHFG<string name> { + def bs : SystemZBinaryCC<llvm_v16i8_ty>; + def hs : SystemZBinaryCC<llvm_v8i16_ty>; + def fs : SystemZBinaryCC<llvm_v4i32_ty>; + def gs : SystemZBinaryCC<llvm_v2i64_ty>; +} + +multiclass SystemZTernaryExtBHF<string name> { + def b : SystemZTernaryConv<name##"b", llvm_v8i16_ty, llvm_v16i8_ty>; + def h : SystemZTernaryConv<name##"h", llvm_v4i32_ty, llvm_v8i16_ty>; + def f : SystemZTernaryConv<name##"f", llvm_v2i64_ty, llvm_v4i32_ty>; +} + +multiclass SystemZTernaryExtBHFG<string name> : SystemZTernaryExtBHF<name> { + def g : SystemZTernaryConv<name##"g", llvm_v16i8_ty, llvm_v2i64_ty>; +} + +multiclass SystemZTernaryBHF<string name> { + def b : SystemZTernary<name##"b", llvm_v16i8_ty>; + def h : SystemZTernary<name##"h", llvm_v8i16_ty>; + def f : SystemZTernary<name##"f", llvm_v4i32_ty>; +} + +multiclass SystemZTernaryIntBHF<string name> { + def b : SystemZTernaryInt<name##"b", llvm_v16i8_ty>; + def h : SystemZTernaryInt<name##"h", llvm_v8i16_ty>; + def f : SystemZTernaryInt<name##"f", llvm_v4i32_ty>; +} + +multiclass SystemZTernaryIntCCBHF { + def bs : SystemZTernaryIntCC<llvm_v16i8_ty>; + def hs : SystemZTernaryIntCC<llvm_v8i16_ty>; + def fs : SystemZTernaryIntCC<llvm_v4i32_ty>; +} + +multiclass SystemZQuaternaryIntBHF<string name> { + def b : SystemZQuaternaryInt<name##"b", llvm_v16i8_ty>; + def h : SystemZQuaternaryInt<name##"h", llvm_v8i16_ty>; + def f : SystemZQuaternaryInt<name##"f", llvm_v4i32_ty>; +} + +multiclass SystemZQuaternaryIntBHFG<string name> : SystemZQuaternaryIntBHF<name> { + def g : SystemZQuaternaryInt<name##"g", llvm_v2i64_ty>; +} + +multiclass SystemZQuaternaryIntCCBHF { + def bs : SystemZQuaternaryIntCC<llvm_v16i8_ty>; + def hs : SystemZQuaternaryIntCC<llvm_v8i16_ty>; + def fs : SystemZQuaternaryIntCC<llvm_v4i32_ty>; +} + +//===----------------------------------------------------------------------===// +// +// Transactional-execution intrinsics +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "s390" in { + def int_s390_tbegin : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tbegin_nofloat : Intrinsic<[llvm_i32_ty], + [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tbeginc : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tabort : Intrinsic<[], [llvm_i64_ty], + [IntrNoReturn, Throws]>; + + def int_s390_tend : GCCBuiltin<"__builtin_tend">, + Intrinsic<[llvm_i32_ty], []>; + + def int_s390_etnd : GCCBuiltin<"__builtin_tx_nesting_depth">, + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; + + def int_s390_ntstg : Intrinsic<[], [llvm_i64_ty, llvm_ptr64_ty], + [IntrReadWriteArgMem]>; + + def int_s390_ppa_txassist : GCCBuiltin<"__builtin_tx_assist">, + Intrinsic<[], [llvm_i32_ty]>; +} + +//===----------------------------------------------------------------------===// +// +// Vector intrinsics +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "s390" in { + def int_s390_lcbb : GCCBuiltin<"__builtin_s390_lcbb">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_s390_vlbb : GCCBuiltin<"__builtin_s390_vlbb">, + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_s390_vll : GCCBuiltin<"__builtin_s390_vll">, + Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty, llvm_ptr_ty], + [IntrReadArgMem]>; + + def int_s390_vpdi : GCCBuiltin<"__builtin_s390_vpdi">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_s390_vperm : GCCBuiltin<"__builtin_s390_vperm">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + + defm int_s390_vpks : SystemZBinaryTruncHFG<"vpks">; + defm int_s390_vpks : SystemZBinaryTruncCCHFG; + + defm int_s390_vpkls : SystemZBinaryTruncHFG<"vpkls">; + defm int_s390_vpkls : SystemZBinaryTruncCCHFG; + + def int_s390_vstl : GCCBuiltin<"__builtin_s390_vstl">, + Intrinsic<[], [llvm_v16i8_ty, llvm_i32_ty, llvm_ptr_ty], + // In fact write-only but there's no property + // for that. + [IntrReadWriteArgMem]>; + + defm int_s390_vupl : SystemZUnaryExtBHWF<"vupl">; + defm int_s390_vupll : SystemZUnaryExtBHF<"vupll">; + + defm int_s390_vuph : SystemZUnaryExtBHF<"vuph">; + defm int_s390_vuplh : SystemZUnaryExtBHF<"vuplh">; + + defm int_s390_vacc : SystemZBinaryBHFG<"vacc">; + + def int_s390_vaq : SystemZBinary<"vaq", llvm_v16i8_ty>; + def int_s390_vacq : SystemZTernary<"vacq", llvm_v16i8_ty>; + def int_s390_vaccq : SystemZBinary<"vaccq", llvm_v16i8_ty>; + def int_s390_vacccq : SystemZTernary<"vacccq", llvm_v16i8_ty>; + + defm int_s390_vavg : SystemZBinaryBHFG<"vavg">; + defm int_s390_vavgl : SystemZBinaryBHFG<"vavgl">; + + def int_s390_vcksm : SystemZBinary<"vcksm", llvm_v4i32_ty>; + + defm int_s390_vgfm : SystemZBinaryExtBHFG<"vgfm">; + defm int_s390_vgfma : SystemZTernaryExtBHFG<"vgfma">; + + defm int_s390_vmah : SystemZTernaryBHF<"vmah">; + defm int_s390_vmalh : SystemZTernaryBHF<"vmalh">; + defm int_s390_vmae : SystemZTernaryExtBHF<"vmae">; + defm int_s390_vmale : SystemZTernaryExtBHF<"vmale">; + defm int_s390_vmao : SystemZTernaryExtBHF<"vmao">; + defm int_s390_vmalo : SystemZTernaryExtBHF<"vmalo">; + + defm int_s390_vmh : SystemZBinaryBHF<"vmh">; + defm int_s390_vmlh : SystemZBinaryBHF<"vmlh">; + defm int_s390_vme : SystemZBinaryExtBHF<"vme">; + defm int_s390_vmle : SystemZBinaryExtBHF<"vmle">; + defm int_s390_vmo : SystemZBinaryExtBHF<"vmo">; + defm int_s390_vmlo : SystemZBinaryExtBHF<"vmlo">; + + defm int_s390_verllv : SystemZBinaryBHFG<"verllv">; + defm int_s390_verll : SystemZBinaryIntBHFG<"verll">; + defm int_s390_verim : SystemZQuaternaryIntBHFG<"verim">; + + def int_s390_vsl : SystemZBinary<"vsl", llvm_v16i8_ty>; + def int_s390_vslb : SystemZBinary<"vslb", llvm_v16i8_ty>; + def int_s390_vsra : SystemZBinary<"vsra", llvm_v16i8_ty>; + def int_s390_vsrab : SystemZBinary<"vsrab", llvm_v16i8_ty>; + def int_s390_vsrl : SystemZBinary<"vsrl", llvm_v16i8_ty>; + def int_s390_vsrlb : SystemZBinary<"vsrlb", llvm_v16i8_ty>; + + def int_s390_vsldb : GCCBuiltin<"__builtin_s390_vsldb">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + defm int_s390_vscbi : SystemZBinaryBHFG<"vscbi">; + + def int_s390_vsq : SystemZBinary<"vsq", llvm_v16i8_ty>; + def int_s390_vsbiq : SystemZTernary<"vsbiq", llvm_v16i8_ty>; + def int_s390_vscbiq : SystemZBinary<"vscbiq", llvm_v16i8_ty>; + def int_s390_vsbcbiq : SystemZTernary<"vsbcbiq", llvm_v16i8_ty>; + + def int_s390_vsumb : SystemZBinaryConv<"vsumb", llvm_v4i32_ty, llvm_v16i8_ty>; + def int_s390_vsumh : SystemZBinaryConv<"vsumh", llvm_v4i32_ty, llvm_v8i16_ty>; + + def int_s390_vsumgh : SystemZBinaryConv<"vsumgh", llvm_v2i64_ty, + llvm_v8i16_ty>; + def int_s390_vsumgf : SystemZBinaryConv<"vsumgf", llvm_v2i64_ty, + llvm_v4i32_ty>; + + def int_s390_vsumqf : SystemZBinaryConv<"vsumqf", llvm_v16i8_ty, + llvm_v4i32_ty>; + def int_s390_vsumqg : SystemZBinaryConv<"vsumqg", llvm_v16i8_ty, + llvm_v2i64_ty>; + + def int_s390_vtm : SystemZBinaryConv<"vtm", llvm_i32_ty, llvm_v16i8_ty>; + + defm int_s390_vceq : SystemZCompareBHFG<"vceq">; + defm int_s390_vch : SystemZCompareBHFG<"vch">; + defm int_s390_vchl : SystemZCompareBHFG<"vchl">; + + defm int_s390_vfae : SystemZTernaryIntBHF<"vfae">; + defm int_s390_vfae : SystemZTernaryIntCCBHF; + defm int_s390_vfaez : SystemZTernaryIntBHF<"vfaez">; + defm int_s390_vfaez : SystemZTernaryIntCCBHF; + + defm int_s390_vfee : SystemZBinaryBHF<"vfee">; + defm int_s390_vfee : SystemZBinaryCCBHF; + defm int_s390_vfeez : SystemZBinaryBHF<"vfeez">; + defm int_s390_vfeez : SystemZBinaryCCBHF; + + defm int_s390_vfene : SystemZBinaryBHF<"vfene">; + defm int_s390_vfene : SystemZBinaryCCBHF; + defm int_s390_vfenez : SystemZBinaryBHF<"vfenez">; + defm int_s390_vfenez : SystemZBinaryCCBHF; + + defm int_s390_vistr : SystemZUnaryBHF<"vistr">; + defm int_s390_vistr : SystemZUnaryCCBHF; + + defm int_s390_vstrc : SystemZQuaternaryIntBHF<"vstrc">; + defm int_s390_vstrc : SystemZQuaternaryIntCCBHF; + defm int_s390_vstrcz : SystemZQuaternaryIntBHF<"vstrcz">; + defm int_s390_vstrcz : SystemZQuaternaryIntCCBHF; + + def int_s390_vfcedbs : SystemZBinaryConvCC<llvm_v2i64_ty, llvm_v2f64_ty>; + def int_s390_vfchdbs : SystemZBinaryConvCC<llvm_v2i64_ty, llvm_v2f64_ty>; + def int_s390_vfchedbs : SystemZBinaryConvCC<llvm_v2i64_ty, llvm_v2f64_ty>; + + def int_s390_vftcidb : SystemZBinaryConvIntCC<llvm_v2i64_ty, llvm_v2f64_ty>; + + def int_s390_vfidb : Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +} diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 81c729065505..3a8a4a643a43 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -18,6 +18,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". } //===----------------------------------------------------------------------===// +// SEH LSDA for Windows +let TargetPrefix = "x86" in { + def int_x86_seh_lsda : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// // Read Time Stamp Counter. let TargetPrefix = "x86" in { def int_x86_rdtsc : GCCBuiltin<"__builtin_ia32_rdtsc">, @@ -453,19 +459,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_psrai_d : GCCBuiltin<"__builtin_ia32_psradi128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; - - def int_x86_sse2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi128_byteshift">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi128_byteshift">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; } // Conversion ops @@ -895,15 +888,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_sse41_pblendw : GCCBuiltin<"__builtin_ia32_pblendw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_sse41_blendpd : GCCBuiltin<"__builtin_ia32_blendpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_sse41_blendps : GCCBuiltin<"__builtin_ia32_blendps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; def int_x86_sse41_blendvpd : GCCBuiltin<"__builtin_ia32_blendvpd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_v2f64_ty], [IntrNoMem]>; @@ -1169,12 +1153,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector blend let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx_blendv_pd_256 : GCCBuiltin<"__builtin_ia32_blendvpd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; @@ -1200,32 +1178,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; } -// Vector extract and insert -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_vextractf128_pd_256 : - GCCBuiltin<"__builtin_ia32_vextractf128_pd256">, - Intrinsic<[llvm_v2f64_ty], [llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_vextractf128_ps_256 : - GCCBuiltin<"__builtin_ia32_vextractf128_ps256">, - Intrinsic<[llvm_v4f32_ty], [llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_vextractf128_si_256 : - GCCBuiltin<"__builtin_ia32_vextractf128_si256">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx_vinsertf128_pd_256 : - GCCBuiltin<"__builtin_ia32_vinsertf128_pd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_vinsertf128_ps_256 : - GCCBuiltin<"__builtin_ia32_vinsertf128_ps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx_vinsertf128_si_256 : - GCCBuiltin<"__builtin_ia32_vinsertf128_si256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; -} - // Vector convert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_cvtdq2_pd_256 : GCCBuiltin<"__builtin_ia32_cvtdq2pd256">, @@ -1363,6 +1315,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_mask_loadu_pd_512 : GCCBuiltin<"__builtin_ia32_loadupd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_load_ps_512 : GCCBuiltin<"__builtin_ia32_loadaps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrReadArgMem]>; + def int_x86_avx512_mask_load_pd_512 : GCCBuiltin<"__builtin_ia32_loadapd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrReadArgMem]>; } // Conditional store ops @@ -1389,6 +1347,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_storeupd512_mask">, Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_store_ps_512 : + GCCBuiltin<"__builtin_ia32_storeaps512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_store_pd_512 : + GCCBuiltin<"__builtin_ia32_storeapd512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; def int_x86_avx512_mask_store_ss : GCCBuiltin<"__builtin_ia32_storess_mask">, Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty], @@ -1448,12 +1414,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw256">, Intrinsic<[llvm_v4i64_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem, Commutative]>; - def int_x86_avx512_mask_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Vector min, max @@ -1572,19 +1532,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi256_byteshift">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi256_byteshift">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; @@ -1746,15 +1693,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb256">, Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; - def int_x86_avx2_pblendw : GCCBuiltin<"__builtin_ia32_pblendw256">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx2_pblendd_128 : GCCBuiltin<"__builtin_ia32_pblendd128">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx2_pblendd_256 : GCCBuiltin<"__builtin_ia32_pblendd256">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_i8_ty], [IntrNoMem]>; } // Vector load with broadcast @@ -1768,8 +1706,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_vbroadcast_ss_ps_256 : GCCBuiltin<"__builtin_ia32_vbroadcastss_ps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_avx2_vbroadcasti128 : - Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; def int_x86_avx2_pbroadcastb_128 : GCCBuiltin<"__builtin_ia32_pbroadcastb128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; @@ -1823,13 +1759,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector extract and insert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx2_vextracti128 : GCCBuiltin<"__builtin_ia32_extract128i256">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx2_vinserti128 : GCCBuiltin<"__builtin_ia32_insert128i256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextractf32x4_512 : GCCBuiltin<"__builtin_ia32_extractf32x4_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v16f32_ty, llvm_i8_ty, @@ -3068,6 +2997,46 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_i64_ty], [IntrNoMem]>; } +// Pack ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_mask_packsswb_128 : GCCBuiltin<"__builtin_ia32_packsswb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packsswb_256 : GCCBuiltin<"__builtin_ia32_packsswb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty,llvm_v16i16_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packsswb_512 : GCCBuiltin<"__builtin_ia32_packsswb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packssdw_128 : GCCBuiltin<"__builtin_ia32_packssdw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packssdw_256 : GCCBuiltin<"__builtin_ia32_packssdw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packssdw_512 : GCCBuiltin<"__builtin_ia32_packssdw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packuswb_128 : GCCBuiltin<"__builtin_ia32_packuswb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packuswb_256 : GCCBuiltin<"__builtin_ia32_packuswb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty,llvm_v16i16_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packuswb_512 : GCCBuiltin<"__builtin_ia32_packuswb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packusdw_128 : GCCBuiltin<"__builtin_ia32_packusdw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packusdw_256 : GCCBuiltin<"__builtin_ia32_packusdw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packusdw_512 : GCCBuiltin<"__builtin_ia32_packusdw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; +} + // Vector convert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_mask_cvttps2dq_512: GCCBuiltin<"__builtin_ia32_cvttps2dq512_mask">, @@ -3164,28 +3133,238 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i64_ty], [llvm_v8i32_ty], [IntrNoMem]>; } - +//Bitwise Ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_mask_pand_d_128 : GCCBuiltin<"__builtin_ia32_pandd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_d_256 : GCCBuiltin<"__builtin_ia32_pandd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_q_128 : GCCBuiltin<"__builtin_ia32_pandq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_q_256 : GCCBuiltin<"__builtin_ia32_pandq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_q_512 : GCCBuiltin<"__builtin_ia32_pandq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_d_128 : GCCBuiltin<"__builtin_ia32_pandnd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_d_256 : GCCBuiltin<"__builtin_ia32_pandnd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_d_512 : GCCBuiltin<"__builtin_ia32_pandnd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_q_128 : GCCBuiltin<"__builtin_ia32_pandnq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_q_256 : GCCBuiltin<"__builtin_ia32_pandnq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_q_512 : GCCBuiltin<"__builtin_ia32_pandnq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_d_128 : GCCBuiltin<"__builtin_ia32_pord128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_d_256 : GCCBuiltin<"__builtin_ia32_pord256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_d_512 : GCCBuiltin<"__builtin_ia32_pord512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_q_128 : GCCBuiltin<"__builtin_ia32_porq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_q_256 : GCCBuiltin<"__builtin_ia32_porq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_q_512 : GCCBuiltin<"__builtin_ia32_porq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_d_128 : GCCBuiltin<"__builtin_ia32_pxord128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_d_256 : GCCBuiltin<"__builtin_ia32_pxord256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_d_512 : GCCBuiltin<"__builtin_ia32_pxord512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_q_128 : GCCBuiltin<"__builtin_ia32_pxorq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_q_256 : GCCBuiltin<"__builtin_ia32_pxorq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_q_512 : GCCBuiltin<"__builtin_ia32_pxorq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; +} // Arithmetic ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + + def int_x86_avx512_mask_add_ps_128 : GCCBuiltin<"__builtin_ia32_addps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_ps_256 : GCCBuiltin<"__builtin_ia32_addps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_ps_512 : GCCBuiltin<"__builtin_ia32_addps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_pd_128 : GCCBuiltin<"__builtin_ia32_addpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_pd_256 : GCCBuiltin<"__builtin_ia32_addpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_pd_512 : GCCBuiltin<"__builtin_ia32_addpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ps_128 : GCCBuiltin<"__builtin_ia32_subps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ps_256 : GCCBuiltin<"__builtin_ia32_subps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ps_512 : GCCBuiltin<"__builtin_ia32_subps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_pd_128 : GCCBuiltin<"__builtin_ia32_subpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_pd_256 : GCCBuiltin<"__builtin_ia32_subpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_pd_512 : GCCBuiltin<"__builtin_ia32_subpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ps_128 : GCCBuiltin<"__builtin_ia32_mulps_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ps_256 : GCCBuiltin<"__builtin_ia32_mulps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ps_512 : GCCBuiltin<"__builtin_ia32_mulps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_pd_128 : GCCBuiltin<"__builtin_ia32_mulpd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_pd_256 : GCCBuiltin<"__builtin_ia32_mulpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_pd_512 : GCCBuiltin<"__builtin_ia32_mulpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ps_128 : GCCBuiltin<"__builtin_ia32_divps_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ps_256 : GCCBuiltin<"__builtin_ia32_divps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ps_512 : GCCBuiltin<"__builtin_ia32_divps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_pd_128 : GCCBuiltin<"__builtin_ia32_divpd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_pd_256 : GCCBuiltin<"__builtin_ia32_divpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_pd_512 : GCCBuiltin<"__builtin_ia32_divpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_ps_128 : GCCBuiltin<"__builtin_ia32_maxps_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_ps_256 : GCCBuiltin<"__builtin_ia32_maxps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_pd_128 : GCCBuiltin<"__builtin_ia32_maxpd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_pd_256 : GCCBuiltin<"__builtin_ia32_maxpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_ps_128 : GCCBuiltin<"__builtin_ia32_minps_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_ps_256 : GCCBuiltin<"__builtin_ia32_minps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_pd_128 : GCCBuiltin<"__builtin_ia32_minpd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_pd_256 : GCCBuiltin<"__builtin_ia32_minpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_ss_round : GCCBuiltin<"__builtin_ia32_addss_round">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ss_round : GCCBuiltin<"__builtin_ia32_divss_round">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ss_round : GCCBuiltin<"__builtin_ia32_mulss_round">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ss_round : GCCBuiltin<"__builtin_ia32_subss_round">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_ss_round : GCCBuiltin<"__builtin_ia32_maxss_round">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_ss_round : GCCBuiltin<"__builtin_ia32_minss_round">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_sd_round : GCCBuiltin<"__builtin_ia32_addsd_round">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_sd_round : GCCBuiltin<"__builtin_ia32_divsd_round">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_sd_round : GCCBuiltin<"__builtin_ia32_mulsd_round">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_sd_round : GCCBuiltin<"__builtin_ia32_subsd_round">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_sd_round : GCCBuiltin<"__builtin_ia32_maxsd_round">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_sd_round : GCCBuiltin<"__builtin_ia32_minsd_round">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; def int_x86_avx512_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtrndss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; @@ -3265,21 +3444,273 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; } - -// Integer shift ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi512_byteshift">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi512_byteshift">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; +// FP logical ops +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_and_pd_128 : GCCBuiltin<"__builtin_ia32_andpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_pd_256 : GCCBuiltin<"__builtin_ia32_andpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_pd_512 : GCCBuiltin<"__builtin_ia32_andpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_ps_128 : GCCBuiltin<"__builtin_ia32_andps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_ps_256 : GCCBuiltin<"__builtin_ia32_andps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_ps_512 : GCCBuiltin<"__builtin_ia32_andps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_pd_128 : GCCBuiltin<"__builtin_ia32_andnpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_pd_256 : GCCBuiltin<"__builtin_ia32_andnpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_pd_512 : GCCBuiltin<"__builtin_ia32_andnpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_ps_128 : GCCBuiltin<"__builtin_ia32_andnps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_ps_256 : GCCBuiltin<"__builtin_ia32_andnps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_ps_512 : GCCBuiltin<"__builtin_ia32_andnps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_pd_128 : GCCBuiltin<"__builtin_ia32_orpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_pd_256 : GCCBuiltin<"__builtin_ia32_orpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_pd_512 : GCCBuiltin<"__builtin_ia32_orpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_ps_128 : GCCBuiltin<"__builtin_ia32_orps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_ps_256 : GCCBuiltin<"__builtin_ia32_orps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_ps_512 : GCCBuiltin<"__builtin_ia32_orps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_xor_pd_128 : GCCBuiltin<"__builtin_ia32_xorpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_pd_256 : GCCBuiltin<"__builtin_ia32_xorpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_pd_512 : GCCBuiltin<"__builtin_ia32_xorpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_ps_128 : GCCBuiltin<"__builtin_ia32_xorps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_ps_256 : GCCBuiltin<"__builtin_ia32_xorps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_ps_512 : GCCBuiltin<"__builtin_ia32_xorps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; +} +// Integer arithmetic ops +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_padd_b_128 : GCCBuiltin<"__builtin_ia32_paddb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_b_256 : GCCBuiltin<"__builtin_ia32_paddb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_b_512 : GCCBuiltin<"__builtin_ia32_paddb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_w_128 : GCCBuiltin<"__builtin_ia32_paddw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_w_256 : GCCBuiltin<"__builtin_ia32_paddw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_w_512 : GCCBuiltin<"__builtin_ia32_paddw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_b_128 : GCCBuiltin<"__builtin_ia32_paddsb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_b_256 : GCCBuiltin<"__builtin_ia32_paddsb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_b_512 : GCCBuiltin<"__builtin_ia32_paddsb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_w_128 : GCCBuiltin<"__builtin_ia32_paddsw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_w_256 : GCCBuiltin<"__builtin_ia32_paddsw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_w_512 : GCCBuiltin<"__builtin_ia32_paddsw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_b_128 : GCCBuiltin<"__builtin_ia32_paddusb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_b_256 : GCCBuiltin<"__builtin_ia32_paddusb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_b_512 : GCCBuiltin<"__builtin_ia32_paddusb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_w_128 : GCCBuiltin<"__builtin_ia32_paddusw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_w_256 : GCCBuiltin<"__builtin_ia32_paddusw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_w_512 : GCCBuiltin<"__builtin_ia32_paddusw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_d_128 : GCCBuiltin<"__builtin_ia32_paddd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_d_256 : GCCBuiltin<"__builtin_ia32_paddd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_d_512 : GCCBuiltin<"__builtin_ia32_paddd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_q_128 : GCCBuiltin<"__builtin_ia32_paddq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_q_256 : GCCBuiltin<"__builtin_ia32_paddq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_q_512 : GCCBuiltin<"__builtin_ia32_paddq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_b_128 : GCCBuiltin<"__builtin_ia32_psubb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_b_256 : GCCBuiltin<"__builtin_ia32_psubb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_b_512 : GCCBuiltin<"__builtin_ia32_psubb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_w_128 : GCCBuiltin<"__builtin_ia32_psubw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_w_256 : GCCBuiltin<"__builtin_ia32_psubw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_w_512 : GCCBuiltin<"__builtin_ia32_psubw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_b_128 : GCCBuiltin<"__builtin_ia32_psubsb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_b_256 : GCCBuiltin<"__builtin_ia32_psubsb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_b_512 : GCCBuiltin<"__builtin_ia32_psubsb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_w_128 : GCCBuiltin<"__builtin_ia32_psubsw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_w_256 : GCCBuiltin<"__builtin_ia32_psubsw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_w_512 : GCCBuiltin<"__builtin_ia32_psubsw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_b_128 : GCCBuiltin<"__builtin_ia32_psubusb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_b_256 : GCCBuiltin<"__builtin_ia32_psubusb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_b_512 : GCCBuiltin<"__builtin_ia32_psubusb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_w_128 : GCCBuiltin<"__builtin_ia32_psubusw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_w_256 : GCCBuiltin<"__builtin_ia32_psubusw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_w_512 : GCCBuiltin<"__builtin_ia32_psubusw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_d_128 : GCCBuiltin<"__builtin_ia32_psubd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_d_256 : GCCBuiltin<"__builtin_ia32_psubd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_d_512 : GCCBuiltin<"__builtin_ia32_psubd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_q_128 : GCCBuiltin<"__builtin_ia32_psubq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_q_256 : GCCBuiltin<"__builtin_ia32_psubq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_q_512 : GCCBuiltin<"__builtin_ia32_psubq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulu_dq_128 : GCCBuiltin<"__builtin_ia32_pmuludq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_dq_128 : GCCBuiltin<"__builtin_ia32_pmuldq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulu_dq_256 : GCCBuiltin<"__builtin_ia32_pmuludq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_dq_256 : GCCBuiltin<"__builtin_ia32_pmuldq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_w_128 : GCCBuiltin<"__builtin_ia32_pmullw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_w_256 : GCCBuiltin<"__builtin_ia32_pmullw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_w_512 : GCCBuiltin<"__builtin_ia32_pmullw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_d_128 : GCCBuiltin<"__builtin_ia32_pmulld128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_d_256 : GCCBuiltin<"__builtin_ia32_pmulld256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_d_512 : GCCBuiltin<"__builtin_ia32_pmulld512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_q_128 : GCCBuiltin<"__builtin_ia32_pmullq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_q_256 : GCCBuiltin<"__builtin_ia32_pmullq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_q_512 : GCCBuiltin<"__builtin_ia32_pmullq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Gather and Scatter ops @@ -3390,22 +3821,22 @@ let TargetPrefix = "x86" in { GCCBuiltin<"__builtin_ia32_vpconflictsi_512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_conflict_q_512 : GCCBuiltin<"__builtin_ia32_vpconflictdi_512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_lzcnt_d_512 : GCCBuiltin<"__builtin_ia32_vplzcntd_512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_lzcnt_q_512 : GCCBuiltin<"__builtin_ia32_vplzcntq_512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - []>; + [IntrNoMem]>; } // Vector blend @@ -3867,21 +4298,33 @@ let TargetPrefix = "x86" in { } // Misc. let TargetPrefix = "x86" in { - def int_x86_avx512_mask_cmp_ps_512 : GCCBuiltin<"__builtin_ia32_cmpps512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cmp_pd_512 : GCCBuiltin<"__builtin_ia32_cmppd512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pand_q_512 : GCCBuiltin<"__builtin_ia32_pandq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, - llvm_v8i64_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">, + def int_x86_avx512_mask_cmp_ps_512 : + GCCBuiltin<"__builtin_ia32_cmpps512_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_pd_512 : + GCCBuiltin<"__builtin_ia32_cmppd512_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_ps_256 : + GCCBuiltin<"__builtin_ia32_cmpps256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_pd_256 : + GCCBuiltin<"__builtin_ia32_cmppd256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_ps_128 : + GCCBuiltin<"__builtin_ia32_cmpps128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_pd_128 : + GCCBuiltin<"__builtin_ia32_cmppd128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_movntdqa : + GCCBuiltin<"__builtin_ia32_movntdqa512">, Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>; } diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index 2f18782a0730..e6c22090ab6d 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -58,7 +58,9 @@ public: MD_noalias = 8, // "noalias", MD_nontemporal = 9, // "nontemporal" MD_mem_parallel_loop_access = 10, // "llvm.mem.parallel_loop_access" - MD_nonnull = 11 // "nonnull" + MD_nonnull = 11, // "nonnull" + MD_dereferenceable = 12, // "dereferenceable" + MD_dereferenceable_or_null = 13 // "dereferenceable_or_null" }; /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. @@ -176,8 +178,8 @@ public: } private: - LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION; - void operator=(LLVMContext&) LLVM_DELETED_FUNCTION; + LLVMContext(LLVMContext&) = delete; + void operator=(LLVMContext&) = delete; /// addModule - Register a module as being instantiated in this context. If /// the context is deleted, the module will be deleted as well. diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h index 6c04e9dc3d3f..5257a0eed488 100644 --- a/include/llvm/IR/LegacyPassManager.h +++ b/include/llvm/IR/LegacyPassManager.h @@ -50,7 +50,7 @@ class PassManager : public PassManagerBase { public: PassManager(); - ~PassManager(); + ~PassManager() override; void add(Pass *P) override; @@ -70,7 +70,7 @@ public: /// FunctionPassManager ctor - This initializes the pass manager. It needs, /// but does not take ownership of, the specified Module. explicit FunctionPassManager(Module *M); - ~FunctionPassManager(); + ~FunctionPassManager() override; void add(Pass *P) override; diff --git a/include/llvm/IR/LegacyPassNameParser.h b/include/llvm/IR/LegacyPassNameParser.h index e2e4912ef64e..39ae80d797c7 100644 --- a/include/llvm/IR/LegacyPassNameParser.h +++ b/include/llvm/IR/LegacyPassNameParser.h @@ -41,14 +41,12 @@ namespace llvm { // class PassNameParser : public PassRegistrationListener, public cl::parser<const PassInfo*> { - cl::Option *Opt; public: - PassNameParser(); - virtual ~PassNameParser(); + PassNameParser(cl::Option &O); + ~PassNameParser() override; - void initialize(cl::Option &O) { - Opt = &O; - cl::parser<const PassInfo*>::initialize(O); + void initialize() { + cl::parser<const PassInfo*>::initialize(); // Add all of the passes to the map that got initialized before 'this' did. enumeratePasses(); @@ -69,7 +67,7 @@ public: // Implement the PassRegistrationListener callbacks used to populate our map // void passRegistered(const PassInfo *P) override { - if (ignorablePass(P) || !Opt) return; + if (ignorablePass(P)) return; if (findOption(P->getPassArgument()) != getNumOptions()) { errs() << "Two passes with the same argument (-" << P->getPassArgument() << ") attempted to be registered!\n"; diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h index 91a6685f6125..ba14457f7185 100644 --- a/include/llvm/IR/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -60,6 +60,9 @@ public: /// \brief Return metadata containing a number of branch weights. MDNode *createBranchWeights(ArrayRef<uint32_t> Weights); + /// Return metadata containing the entry count for a function. + MDNode *createFunctionEntryCount(uint64_t Count); + //===------------------------------------------------------------------===// // Range metadata. //===------------------------------------------------------------------===// @@ -67,6 +70,9 @@ public: /// \brief Return metadata describing the range [Lo, Hi). MDNode *createRange(const APInt &Lo, const APInt &Hi); + /// \brief Return metadata describing the range [Lo, Hi). + MDNode *createRange(Constant *Lo, Constant *Hi); + //===------------------------------------------------------------------===// // AA metadata. //===------------------------------------------------------------------===// diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def index 2098bb57eb56..f2abff4752f7 100644 --- a/include/llvm/IR/Metadata.def +++ b/include/llvm/IR/Metadata.def @@ -1,4 +1,4 @@ -//===- llvm/Metadata.def - Metadata definitions -----------------*- C++ -*-===// +//===- llvm/IR/Metadata.def - Metadata definitions --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,10 @@ //===----------------------------------------------------------------------===// #if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \ - defined HANDLE_METADATA_BRANCH || defined HANDLE_UNIQUABLE_LEAF || \ - defined HANDLE_UNIQUABLE_BRANCH) + defined HANDLE_METADATA_BRANCH || defined HANDLE_MDNODE_LEAF || \ + defined HANDLE_MDNODE_BRANCH || \ + defined HANDLE_SPECIALIZED_MDNODE_LEAF || \ + defined HANDLE_SPECIALIZED_MDNODE_BRANCH) #error "Missing macro definition of HANDLE_METADATA*" #endif @@ -32,28 +34,67 @@ #define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS) #endif -// Handler for leaf nodes under UniquableMDNode. -#ifndef HANDLE_UNIQUABLE_LEAF -#define HANDLE_UNIQUABLE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS) +// Handler for leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_LEAF +#define HANDLE_MDNODE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS) #endif -// Handler for non-leaf nodes under UniquableMDNode. -#ifndef HANDLE_UNIQUABLE_BRANCH -#define HANDLE_UNIQUABLE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS) +// Handler for non-leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_BRANCH +#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS) +#endif + +// Handler for specialized leaf nodes under MDNode. +#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF +#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#endif + +// Handler for specialized non-leaf nodes under MDNode. +#ifndef HANDLE_SPECIALIZED_MDNODE_BRANCH +#define HANDLE_SPECIALIZED_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_BRANCH(CLASS) #endif HANDLE_METADATA_LEAF(MDString) HANDLE_METADATA_BRANCH(ValueAsMetadata) HANDLE_METADATA_LEAF(ConstantAsMetadata) HANDLE_METADATA_LEAF(LocalAsMetadata) -HANDLE_METADATA_BRANCH(MDNode) -HANDLE_METADATA_LEAF(MDNodeFwdDecl) -HANDLE_UNIQUABLE_BRANCH(UniquableMDNode) -HANDLE_UNIQUABLE_LEAF(MDTuple) -HANDLE_UNIQUABLE_LEAF(MDLocation) +HANDLE_MDNODE_BRANCH(MDNode) +HANDLE_MDNODE_LEAF(MDTuple) +HANDLE_SPECIALIZED_MDNODE_LEAF(DILocation) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIExpression) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DINode) +HANDLE_SPECIALIZED_MDNODE_LEAF(GenericDINode) +HANDLE_SPECIALIZED_MDNODE_LEAF(DISubrange) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIEnumerator) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIScope) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIType) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIBasicType) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIDerivedTypeBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIDerivedType) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DICompositeTypeBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(DICompositeType) +HANDLE_SPECIALIZED_MDNODE_LEAF(DISubroutineType) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIFile) +HANDLE_SPECIALIZED_MDNODE_LEAF(DICompileUnit) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DILocalScope) +HANDLE_SPECIALIZED_MDNODE_LEAF(DISubprogram) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DILexicalBlockBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(DILexicalBlock) +HANDLE_SPECIALIZED_MDNODE_LEAF(DILexicalBlockFile) +HANDLE_SPECIALIZED_MDNODE_LEAF(DINamespace) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DITemplateParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF(DITemplateTypeParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF(DITemplateValueParameter) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIGlobalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(DILocalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIObjCProperty) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIImportedEntity) #undef HANDLE_METADATA #undef HANDLE_METADATA_LEAF #undef HANDLE_METADATA_BRANCH -#undef HANDLE_UNIQUABLE_LEAF -#undef HANDLE_UNIQUABLE_BRANCH +#undef HANDLE_MDNODE_LEAF +#undef HANDLE_MDNODE_BRANCH +#undef HANDLE_SPECIALIZED_MDNODE_LEAF +#undef HANDLE_SPECIALIZED_MDNODE_BRANCH diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 27a5d6f80041..60718f531bd7 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -1,4 +1,4 @@ -//===-- llvm/Metadata.h - Metadata definitions ------------------*- C++ -*-===// +//===- llvm/IR/Metadata.h - Metadata definitions ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -32,9 +32,8 @@ class Module; template<typename ValueSubClass, typename ItemParentClass> class SymbolTableListTraits; - enum LLVMConstants : uint32_t { - DEBUG_METADATA_VERSION = 2 // Current debug info version number. + DEBUG_METADATA_VERSION = 3 // Current debug info version number. }; /// \brief Root of the metadata hierarchy. @@ -47,8 +46,11 @@ class Metadata { const unsigned char SubclassID; protected: + /// \brief Active type of storage. + enum StorageType { Uniqued, Distinct, Temporary }; + /// \brief Storage flag for non-uniqued, otherwise unowned, metadata. - bool IsDistinctInContext : 1; + unsigned Storage : 2; // TODO: expose remaining bits to subclasses. unsigned short SubclassData16; @@ -57,21 +59,37 @@ protected: public: enum MetadataKind { MDTupleKind, - MDLocationKind, - MDNodeFwdDeclKind, + DILocationKind, + GenericDINodeKind, + DISubrangeKind, + DIEnumeratorKind, + DIBasicTypeKind, + DIDerivedTypeKind, + DICompositeTypeKind, + DISubroutineTypeKind, + DIFileKind, + DICompileUnitKind, + DISubprogramKind, + DILexicalBlockKind, + DILexicalBlockFileKind, + DINamespaceKind, + DITemplateTypeParameterKind, + DITemplateValueParameterKind, + DIGlobalVariableKind, + DILocalVariableKind, + DIExpressionKind, + DIObjCPropertyKind, + DIImportedEntityKind, ConstantAsMetadataKind, LocalAsMetadataKind, MDStringKind }; protected: - Metadata(unsigned ID) - : SubclassID(ID), IsDistinctInContext(false), SubclassData16(0), - SubclassData32(0) {} - ~Metadata() {} - - /// \brief Store this in a big non-uniqued untyped bucket. - bool isStoredDistinctInContext() const { return IsDistinctInContext; } + Metadata(unsigned ID, StorageType Storage) + : SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) { + } + ~Metadata() = default; /// \brief Default handling of a changed operand, which asserts. /// @@ -85,15 +103,48 @@ public: unsigned getMetadataID() const { return SubclassID; } /// \brief User-friendly dump. + /// + /// If \c M is provided, metadata nodes will be numbered canonically; + /// otherwise, pointer addresses are substituted. + /// + /// Note: this uses an explicit overload instead of default arguments so that + /// the nullptr version is easy to call from a debugger. + /// + /// @{ void dump() const; - void print(raw_ostream &OS) const; - void printAsOperand(raw_ostream &OS, bool PrintType = true, - const Module *M = nullptr) const; + void dump(const Module *M) const; + /// @} + + /// \brief Print. + /// + /// Prints definition of \c this. + /// + /// If \c M is provided, metadata nodes will be numbered canonically; + /// otherwise, pointer addresses are substituted. + void print(raw_ostream &OS, const Module *M = nullptr) const; + + /// \brief Print as operand. + /// + /// Prints reference of \c this. + /// + /// If \c M is provided, metadata nodes will be numbered canonically; + /// otherwise, pointer addresses are substituted. + void printAsOperand(raw_ostream &OS, const Module *M = nullptr) const; }; #define HANDLE_METADATA(CLASS) class CLASS; #include "llvm/IR/Metadata.def" +// Provide specializations of isa so that we don't need definitions of +// subclasses to see if the metadata is a subclass. +#define HANDLE_METADATA_LEAF(CLASS) \ + template <> struct isa_impl<CLASS, Metadata> { \ + static inline bool doit(const Metadata &MD) { \ + return MD.getMetadataID() == Metadata::CLASS##Kind; \ + } \ + }; +#include "llvm/IR/Metadata.def" + inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) { MD.print(OS); return OS; @@ -113,7 +164,7 @@ class MetadataAsValue : public Value { Metadata *MD; MetadataAsValue(Type *Ty, Metadata *MD); - ~MetadataAsValue(); + ~MetadataAsValue() override; /// \brief Drop use of metadata (during teardown). void dropUse() { MD = nullptr; } @@ -145,15 +196,19 @@ public: typedef MetadataTracking::OwnerTy OwnerTy; private: + LLVMContext &Context; uint64_t NextIndex; SmallDenseMap<void *, std::pair<OwnerTy, uint64_t>, 4> UseMap; public: - ReplaceableMetadataImpl() : NextIndex(0) {} + ReplaceableMetadataImpl(LLVMContext &Context) + : Context(Context), NextIndex(0) {} ~ReplaceableMetadataImpl() { assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata"); } + LLVMContext &getContext() const { return Context; } + /// \brief Replace all uses of this with MD. /// /// Replace all uses of this with \c MD, which is allowed to be null. @@ -162,8 +217,8 @@ public: /// \brief Resolve all uses of this. /// /// Resolve all uses of this, turning off RAUW permanently. If \c - /// ResolveUsers, call \a UniquableMDNode::resolve() on any users whose last - /// operand is resolved. + /// ResolveUsers, call \a MDNode::resolve() on any users whose last operand + /// is resolved. void resolveAllUses(bool ResolveUsers = true); private: @@ -195,10 +250,10 @@ class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl { protected: ValueAsMetadata(unsigned ID, Value *V) - : Metadata(ID), V(V) { + : Metadata(ID, Uniqued), ReplaceableMetadataImpl(V->getContext()), V(V) { assert(V && "Expected valid value"); } - ~ValueAsMetadata() {} + ~ValueAsMetadata() = default; public: static ValueAsMetadata *get(Value *V); @@ -441,13 +496,13 @@ dyn_extract_or_null(Y &&MD) { class MDString : public Metadata { friend class StringMapEntry<MDString>; - MDString(const MDString &) LLVM_DELETED_FUNCTION; - MDString &operator=(MDString &&) LLVM_DELETED_FUNCTION; - MDString &operator=(const MDString &) LLVM_DELETED_FUNCTION; + MDString(const MDString &) = delete; + MDString &operator=(MDString &&) = delete; + MDString &operator=(const MDString &) = delete; StringMapEntry<MDString> *Entry; - MDString() : Metadata(MDStringKind), Entry(nullptr) {} - MDString(MDString &&) : Metadata(MDStringKind) {} + MDString() : Metadata(MDStringKind, Uniqued), Entry(nullptr) {} + MDString(MDString &&) : Metadata(MDStringKind, Uniqued) {} public: static MDString *get(LLVMContext &Context, StringRef Str); @@ -489,7 +544,7 @@ struct AAMDNodes { bool operator!=(const AAMDNodes &A) const { return !(*this == A); } - LLVM_EXPLICIT operator bool() const { return TBAA || Scope || NoAlias; } + explicit operator bool() const { return TBAA || Scope || NoAlias; } /// \brief The tag for type-based alias analysis. MDNode *TBAA; @@ -528,10 +583,10 @@ struct DenseMapInfo<AAMDNodes> { /// /// In particular, this is used by \a MDNode. class MDOperand { - MDOperand(MDOperand &&) LLVM_DELETED_FUNCTION; - MDOperand(const MDOperand &) LLVM_DELETED_FUNCTION; - MDOperand &operator=(MDOperand &&) LLVM_DELETED_FUNCTION; - MDOperand &operator=(const MDOperand &) LLVM_DELETED_FUNCTION; + MDOperand(MDOperand &&) = delete; + MDOperand(const MDOperand &) = delete; + MDOperand &operator=(MDOperand &&) = delete; + MDOperand &operator=(const MDOperand &) = delete; Metadata *MD; @@ -580,18 +635,109 @@ template <> struct simplify_type<const MDOperand> { static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); } }; -//===----------------------------------------------------------------------===// -/// \brief Tuple of metadata. +/// \brief Pointer to the context, with optional RAUW support. +/// +/// Either a raw (non-null) pointer to the \a LLVMContext, or an owned pointer +/// to \a ReplaceableMetadataImpl (which has a reference to \a LLVMContext). +class ContextAndReplaceableUses { + PointerUnion<LLVMContext *, ReplaceableMetadataImpl *> Ptr; + + ContextAndReplaceableUses() = delete; + ContextAndReplaceableUses(ContextAndReplaceableUses &&) = delete; + ContextAndReplaceableUses(const ContextAndReplaceableUses &) = delete; + ContextAndReplaceableUses &operator=(ContextAndReplaceableUses &&) = delete; + ContextAndReplaceableUses & + operator=(const ContextAndReplaceableUses &) = delete; + +public: + ContextAndReplaceableUses(LLVMContext &Context) : Ptr(&Context) {} + ContextAndReplaceableUses( + std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses) + : Ptr(ReplaceableUses.release()) { + assert(getReplaceableUses() && "Expected non-null replaceable uses"); + } + ~ContextAndReplaceableUses() { delete getReplaceableUses(); } + + operator LLVMContext &() { return getContext(); } + + /// \brief Whether this contains RAUW support. + bool hasReplaceableUses() const { + return Ptr.is<ReplaceableMetadataImpl *>(); + } + LLVMContext &getContext() const { + if (hasReplaceableUses()) + return getReplaceableUses()->getContext(); + return *Ptr.get<LLVMContext *>(); + } + ReplaceableMetadataImpl *getReplaceableUses() const { + if (hasReplaceableUses()) + return Ptr.get<ReplaceableMetadataImpl *>(); + return nullptr; + } + + /// \brief Assign RAUW support to this. + /// + /// Make this replaceable, taking ownership of \c ReplaceableUses (which must + /// not be null). + void + makeReplaceable(std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses) { + assert(ReplaceableUses && "Expected non-null replaceable uses"); + assert(&ReplaceableUses->getContext() == &getContext() && + "Expected same context"); + delete getReplaceableUses(); + Ptr = ReplaceableUses.release(); + } + + /// \brief Drop RAUW support. + /// + /// Cede ownership of RAUW support, returning it. + std::unique_ptr<ReplaceableMetadataImpl> takeReplaceableUses() { + assert(hasReplaceableUses() && "Expected to own replaceable uses"); + std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses( + getReplaceableUses()); + Ptr = &ReplaceableUses->getContext(); + return ReplaceableUses; + } +}; + +struct TempMDNodeDeleter { + inline void operator()(MDNode *Node) const; +}; + +#define HANDLE_MDNODE_LEAF(CLASS) \ + typedef std::unique_ptr<CLASS, TempMDNodeDeleter> Temp##CLASS; +#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#include "llvm/IR/Metadata.def" + +/// \brief Metadata node. +/// +/// Metadata nodes can be uniqued, like constants, or distinct. Temporary +/// metadata nodes (with full support for RAUW) can be used to delay uniquing +/// until forward references are known. The basic metadata node is an \a +/// MDTuple. +/// +/// There is limited support for RAUW at construction time. At construction +/// time, if any operand is a temporary node (or an unresolved uniqued node, +/// which indicates a transitive temporary operand), the node itself will be +/// unresolved. As soon as all operands become resolved, it will drop RAUW +/// support permanently. +/// +/// If an unresolved node is part of a cycle, \a resolveCycles() needs +/// to be called on some member of the cycle once all temporary nodes have been +/// replaced. class MDNode : public Metadata { - MDNode(const MDNode &) LLVM_DELETED_FUNCTION; - void operator=(const MDNode &) LLVM_DELETED_FUNCTION; - void *operator new(size_t) LLVM_DELETED_FUNCTION; + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + MDNode(const MDNode &) = delete; + void operator=(const MDNode &) = delete; + void *operator new(size_t) = delete; - LLVMContext &Context; unsigned NumOperands; + unsigned NumUnresolved; protected: - unsigned MDNodeSubclassData; + ContextAndReplaceableUses Context; void *operator new(size_t Size, unsigned NumOps); void operator delete(void *Mem); @@ -606,56 +752,163 @@ protected: llvm_unreachable("Constructor throws?"); } - MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs); - ~MDNode() {} + MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, + ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None); + ~MDNode() = default; void dropAllReferences(); MDOperand *mutable_begin() { return mutable_end() - NumOperands; } MDOperand *mutable_end() { return reinterpret_cast<MDOperand *>(this); } -public: - static inline MDNode *get(LLVMContext &Context, ArrayRef<Metadata *> MDs); - static inline MDNode *getIfExists(LLVMContext &Context, - ArrayRef<Metadata *> MDs); - static inline MDNode *getDistinct(LLVMContext &Context, - ArrayRef<Metadata *> MDs); + typedef iterator_range<MDOperand *> mutable_op_range; + mutable_op_range mutable_operands() { + return mutable_op_range(mutable_begin(), mutable_end()); + } - /// \brief Return a temporary MDNode - /// - /// For use in constructing cyclic MDNode structures. A temporary MDNode is - /// not uniqued, may be RAUW'd, and must be manually deleted with - /// deleteTemporary. - static MDNodeFwdDecl *getTemporary(LLVMContext &Context, +public: + static inline MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs); + static inline MDTuple *getIfExists(LLVMContext &Context, + ArrayRef<Metadata *> MDs); + static inline MDTuple *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs); + static inline TempMDTuple getTemporary(LLVMContext &Context, + ArrayRef<Metadata *> MDs); + + /// \brief Create a (temporary) clone of this. + TempMDNode clone() const; /// \brief Deallocate a node created by getTemporary. /// - /// The node must not have any users. + /// Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining + /// references will be reset. static void deleteTemporary(MDNode *N); - LLVMContext &getContext() const { return Context; } + LLVMContext &getContext() const { return Context.getContext(); } /// \brief Replace a specific operand. void replaceOperandWith(unsigned I, Metadata *New); /// \brief Check if node is fully resolved. - bool isResolved() const; + /// + /// If \a isTemporary(), this always returns \c false; if \a isDistinct(), + /// this always returns \c true. + /// + /// If \a isUniqued(), returns \c true if this has already dropped RAUW + /// support (because all operands are resolved). + /// + /// As forward declarations are resolved, their containers should get + /// resolved automatically. However, if this (or one of its operands) is + /// involved in a cycle, \a resolveCycles() needs to be called explicitly. + bool isResolved() const { return !Context.hasReplaceableUses(); } + + bool isUniqued() const { return Storage == Uniqued; } + bool isDistinct() const { return Storage == Distinct; } + bool isTemporary() const { return Storage == Temporary; } - /// \brief Check if node is distinct. + /// \brief RAUW a temporary. /// - /// Distinct nodes are not uniqued, and will not be returned by \a - /// MDNode::get(). - bool isDistinct() const { - return isStoredDistinctInContext() || isa<MDNodeFwdDecl>(this); + /// \pre \a isTemporary() must be \c true. + void replaceAllUsesWith(Metadata *MD) { + assert(isTemporary() && "Expected temporary node"); + assert(!isResolved() && "Expected RAUW support"); + Context.getReplaceableUses()->replaceAllUsesWith(MD); } + /// \brief Resolve cycles. + /// + /// Once all forward declarations have been resolved, force cycles to be + /// resolved. + /// + /// \pre No operands (or operands' operands, etc.) have \a isTemporary(). + void resolveCycles(); + + /// \brief Replace a temporary node with a permanent one. + /// + /// Try to create a uniqued version of \c N -- in place, if possible -- and + /// return it. If \c N cannot be uniqued, return a distinct node instead. + template <class T> + static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type + replaceWithPermanent(std::unique_ptr<T, TempMDNodeDeleter> N) { + return cast<T>(N.release()->replaceWithPermanentImpl()); + } + + /// \brief Replace a temporary node with a uniqued one. + /// + /// Create a uniqued version of \c N -- in place, if possible -- and return + /// it. Takes ownership of the temporary node. + /// + /// \pre N does not self-reference. + template <class T> + static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type + replaceWithUniqued(std::unique_ptr<T, TempMDNodeDeleter> N) { + return cast<T>(N.release()->replaceWithUniquedImpl()); + } + + /// \brief Replace a temporary node with a distinct one. + /// + /// Create a distinct version of \c N -- in place, if possible -- and return + /// it. Takes ownership of the temporary node. + template <class T> + static typename std::enable_if<std::is_base_of<MDNode, T>::value, T *>::type + replaceWithDistinct(std::unique_ptr<T, TempMDNodeDeleter> N) { + return cast<T>(N.release()->replaceWithDistinctImpl()); + } + +private: + MDNode *replaceWithPermanentImpl(); + MDNode *replaceWithUniquedImpl(); + MDNode *replaceWithDistinctImpl(); + protected: /// \brief Set an operand. /// /// Sets the operand directly, without worrying about uniquing. void setOperand(unsigned I, Metadata *New); + void storeDistinctInContext(); + template <class T, class StoreT> + static T *storeImpl(T *N, StorageType Storage, StoreT &Store); + +private: + void handleChangedOperand(void *Ref, Metadata *New); + + void resolve(); + void resolveAfterOperandChange(Metadata *Old, Metadata *New); + void decrementUnresolvedOperandCount(); + unsigned countUnresolvedOperands(); + + /// \brief Mutate this to be "uniqued". + /// + /// Mutate this so that \a isUniqued(). + /// \pre \a isTemporary(). + /// \pre already added to uniquing set. + void makeUniqued(); + + /// \brief Mutate this to be "distinct". + /// + /// Mutate this so that \a isDistinct(). + /// \pre \a isTemporary(). + void makeDistinct(); + + void deleteAsSubclass(); + MDNode *uniquify(); + void eraseFromStore(); + + template <class NodeTy> struct HasCachedHash; + template <class NodeTy> + static void dispatchRecalculateHash(NodeTy *N, std::true_type) { + N->recalculateHash(); + } + template <class NodeTy> + static void dispatchRecalculateHash(NodeTy *N, std::false_type) {} + template <class NodeTy> + static void dispatchResetHash(NodeTy *N, std::true_type) { + N->setHash(0); + } + template <class NodeTy> + static void dispatchResetHash(NodeTy *N, std::false_type) {} + public: typedef const MDOperand *op_iterator; typedef iterator_range<op_iterator> op_range; @@ -678,9 +931,14 @@ public: /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDTupleKind || - MD->getMetadataID() == MDLocationKind || - MD->getMetadataID() == MDNodeFwdDeclKind; + switch (MD->getMetadataID()) { + default: + return false; +#define HANDLE_MDNODE_LEAF(CLASS) \ + case CLASS##Kind: \ + return true; +#include "llvm/IR/Metadata.def" + } } /// \brief Check whether MDNode is a vtable access. @@ -690,225 +948,163 @@ public: static MDNode *concatenate(MDNode *A, MDNode *B); static MDNode *intersect(MDNode *A, MDNode *B); static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); - static AAMDNodes getMostGenericAA(const AAMDNodes &A, const AAMDNodes &B); static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); static MDNode *getMostGenericRange(MDNode *A, MDNode *B); static MDNode *getMostGenericAliasScope(MDNode *A, MDNode *B); }; -/// \brief Uniquable metadata node. -/// -/// A uniquable metadata node. This contains the basic functionality -/// for implementing sub-types of \a MDNode that can be uniqued like -/// constants. -/// -/// There is limited support for RAUW at construction time. At -/// construction time, if any operands are an instance of \a -/// MDNodeFwdDecl (or another unresolved \a UniquableMDNode, which -/// indicates an \a MDNodeFwdDecl in its path), the node itself will be -/// unresolved. As soon as all operands become resolved, it will drop -/// RAUW support permanently. -/// -/// If an unresolved node is part of a cycle, \a resolveCycles() needs -/// to be called on some member of the cycle when each \a MDNodeFwdDecl -/// has been removed. -class UniquableMDNode : public MDNode { - friend class ReplaceableMetadataImpl; - friend class MDNode; - friend class LLVMContextImpl; - - /// \brief Support RAUW as long as one of its arguments is replaceable. - /// - /// FIXME: Save memory by storing this in a pointer union with the - /// LLVMContext, and adding an LLVMContext reference to RMI. - std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses; - -protected: - /// \brief Create a new node. - /// - /// If \c AllowRAUW, then if any operands are unresolved support RAUW. RAUW - /// will be dropped once all operands have been resolved (or if \a - /// resolveCycles() is called). - UniquableMDNode(LLVMContext &C, unsigned ID, ArrayRef<Metadata *> Vals, - bool AllowRAUW); - ~UniquableMDNode() {} - - void storeDistinctInContext(); - -public: - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDTupleKind || - MD->getMetadataID() == MDLocationKind; - } - - /// \brief Check whether any operands are forward declarations. - /// - /// Returns \c true as long as any operands (or their operands, etc.) are \a - /// MDNodeFwdDecl. - /// - /// As forward declarations are resolved, their containers should get - /// resolved automatically. However, if this (or one of its operands) is - /// involved in a cycle, \a resolveCycles() needs to be called explicitly. - bool isResolved() const { return !ReplaceableUses; } - - /// \brief Resolve cycles. - /// - /// Once all forward declarations have been resolved, force cycles to be - /// resolved. - /// - /// \pre No operands (or operands' operands, etc.) are \a MDNodeFwdDecl. - void resolveCycles(); - -private: - void handleChangedOperand(void *Ref, Metadata *New); - - void resolve(); - void resolveAfterOperandChange(Metadata *Old, Metadata *New); - void decrementUnresolvedOperandCount(); - - void deleteAsSubclass(); - UniquableMDNode *uniquify(); - void eraseFromStore(); -}; - /// \brief Tuple of metadata. /// /// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by /// default based on their operands. -class MDTuple : public UniquableMDNode { +class MDTuple : public MDNode { friend class LLVMContextImpl; - friend class UniquableMDNode; + friend class MDNode; - MDTuple(LLVMContext &C, ArrayRef<Metadata *> Vals, bool AllowRAUW) - : UniquableMDNode(C, MDTupleKind, Vals, AllowRAUW) {} + MDTuple(LLVMContext &C, StorageType Storage, unsigned Hash, + ArrayRef<Metadata *> Vals) + : MDNode(C, MDTupleKind, Storage, Vals) { + setHash(Hash); + } ~MDTuple() { dropAllReferences(); } - void setHash(unsigned Hash) { MDNodeSubclassData = Hash; } + void setHash(unsigned Hash) { SubclassData32 = Hash; } void recalculateHash(); static MDTuple *getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs, - bool ShouldCreate); + StorageType Storage, bool ShouldCreate = true); + + TempMDTuple cloneImpl() const { + return getTemporary(getContext(), + SmallVector<Metadata *, 4>(op_begin(), op_end())); + } public: /// \brief Get the hash, if any. - unsigned getHash() const { return MDNodeSubclassData; } + unsigned getHash() const { return SubclassData32; } static MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { - return getImpl(Context, MDs, /* ShouldCreate */ true); + return getImpl(Context, MDs, Uniqued); } static MDTuple *getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) { - return getImpl(Context, MDs, /* ShouldCreate */ false); + return getImpl(Context, MDs, Uniqued, /* ShouldCreate */ false); } /// \brief Return a distinct node. /// /// Return a distinct node -- i.e., a node that is not uniqued. - static MDTuple *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs); + static MDTuple *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) { + return getImpl(Context, MDs, Distinct); + } + + /// \brief Return a temporary node. + /// + /// For use in constructing cyclic MDNode structures. A temporary MDNode is + /// not uniqued, may be RAUW'd, and must be manually deleted with + /// deleteTemporary. + static TempMDTuple getTemporary(LLVMContext &Context, + ArrayRef<Metadata *> MDs) { + return TempMDTuple(getImpl(Context, MDs, Temporary)); + } + + /// \brief Return a (temporary) clone of this. + TempMDTuple clone() const { return cloneImpl(); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDTupleKind; } - -private: - MDTuple *uniquifyImpl(); - void eraseFromStoreImpl(); }; -MDNode *MDNode::get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { +MDTuple *MDNode::get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { return MDTuple::get(Context, MDs); } -MDNode *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) { +MDTuple *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) { return MDTuple::getIfExists(Context, MDs); } -MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) { +MDTuple *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) { return MDTuple::getDistinct(Context, MDs); } +TempMDTuple MDNode::getTemporary(LLVMContext &Context, + ArrayRef<Metadata *> MDs) { + return MDTuple::getTemporary(Context, MDs); +} -/// \brief Debug location. -/// -/// A debug location in source code, used for debug info and otherwise. -class MDLocation : public UniquableMDNode { - friend class LLVMContextImpl; - friend class UniquableMDNode; - - MDLocation(LLVMContext &C, unsigned Line, unsigned Column, - ArrayRef<Metadata *> MDs, bool AllowRAUW); - ~MDLocation() { dropAllReferences(); } - - static MDLocation *constructHelper(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt, bool AllowRAUW); - - static MDLocation *getImpl(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt, bool ShouldCreate); +void TempMDNodeDeleter::operator()(MDNode *Node) const { + MDNode::deleteTemporary(Node); +} - // Disallow replacing operands. - void replaceOperandWith(unsigned I, Metadata *New) LLVM_DELETED_FUNCTION; +/// \brief Typed iterator through MDNode operands. +/// +/// An iterator that transforms an \a MDNode::iterator into an iterator over a +/// particular Metadata subclass. +template <class T> +class TypedMDOperandIterator + : std::iterator<std::input_iterator_tag, T *, std::ptrdiff_t, void, T *> { + MDNode::op_iterator I = nullptr; public: - static MDLocation *get(LLVMContext &Context, unsigned Line, unsigned Column, - Metadata *Scope, Metadata *InlinedAt = nullptr) { - return getImpl(Context, Line, Column, Scope, InlinedAt, - /* ShouldCreate */ true); - } - static MDLocation *getIfExists(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt = nullptr) { - return getImpl(Context, Line, Column, Scope, InlinedAt, - /* ShouldCreate */ false); - } - static MDLocation *getDistinct(LLVMContext &Context, unsigned Line, - unsigned Column, Metadata *Scope, - Metadata *InlinedAt = nullptr); - - unsigned getLine() const { return MDNodeSubclassData; } - unsigned getColumn() const { return SubclassData16; } - Metadata *getScope() const { return getOperand(0); } - Metadata *getInlinedAt() const { - if (getNumOperands() == 2) - return getOperand(1); - return nullptr; + TypedMDOperandIterator() = default; + explicit TypedMDOperandIterator(MDNode::op_iterator I) : I(I) {} + T *operator*() const { return cast_or_null<T>(*I); } + TypedMDOperandIterator &operator++() { + ++I; + return *this; } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDLocationKind; + TypedMDOperandIterator operator++(int) { + TypedMDOperandIterator Temp(*this); + ++I; + return Temp; } - -private: - MDLocation *uniquifyImpl(); - void eraseFromStoreImpl(); + bool operator==(const TypedMDOperandIterator &X) const { return I == X.I; } + bool operator!=(const TypedMDOperandIterator &X) const { return I != X.I; } }; -/// \brief Forward declaration of metadata. +/// \brief Typed, array-like tuple of metadata. /// -/// Forward declaration of metadata, in the form of a basic tuple. Unlike \a -/// MDTuple, this class has full support for RAUW, is not owned, is not -/// uniqued, and is suitable for forward references. -class MDNodeFwdDecl : public MDNode, ReplaceableMetadataImpl { - friend class Metadata; - friend class ReplaceableMetadataImpl; - - MDNodeFwdDecl(LLVMContext &C, ArrayRef<Metadata *> Vals) - : MDNode(C, MDNodeFwdDeclKind, Vals) {} +/// This is a wrapper for \a MDTuple that makes it act like an array holding a +/// particular type of metadata. +template <class T> class MDTupleTypedArrayWrapper { + const MDTuple *N = nullptr; public: - ~MDNodeFwdDecl() { dropAllReferences(); } - - // MSVC doesn't see the alternative: "using MDNode::operator delete". - void operator delete(void *Mem) { MDNode::operator delete(Mem); } - - static MDNodeFwdDecl *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { - return new (MDs.size()) MDNodeFwdDecl(Context, MDs); - } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDNodeFwdDeclKind; - } - - using ReplaceableMetadataImpl::replaceAllUsesWith; + MDTupleTypedArrayWrapper() = default; + MDTupleTypedArrayWrapper(const MDTuple *N) : N(N) {} + + template <class U> + MDTupleTypedArrayWrapper( + const MDTupleTypedArrayWrapper<U> &Other, + typename std::enable_if<std::is_convertible<U *, T *>::value>::type * = + nullptr) + : N(Other.get()) {} + + template <class U> + explicit MDTupleTypedArrayWrapper( + const MDTupleTypedArrayWrapper<U> &Other, + typename std::enable_if<!std::is_convertible<U *, T *>::value>::type * = + nullptr) + : N(Other.get()) {} + + explicit operator bool() const { return get(); } + explicit operator MDTuple *() const { return get(); } + + MDTuple *get() const { return const_cast<MDTuple *>(N); } + MDTuple *operator->() const { return get(); } + MDTuple &operator*() const { return *get(); } + + // FIXME: Fix callers and remove condition on N. + unsigned size() const { return N ? N->getNumOperands() : 0u; } + T *operator[](unsigned I) const { return cast_or_null<T>(N->getOperand(I)); } + + // FIXME: Fix callers and remove condition on N. + typedef TypedMDOperandIterator<T> iterator; + iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } + iterator end() const { return N ? iterator(N->op_end()) : iterator(); } }; +#define HANDLE_METADATA(CLASS) \ + typedef MDTupleTypedArrayWrapper<CLASS> CLASS##Array; +#include "llvm/IR/Metadata.def" + //===----------------------------------------------------------------------===// /// \brief A tuple of MDNodes. /// @@ -921,7 +1117,7 @@ class NamedMDNode : public ilist_node<NamedMDNode> { friend struct ilist_traits<NamedMDNode>; friend class LLVMContextImpl; friend class Module; - NamedMDNode(const NamedMDNode &) LLVM_DELETED_FUNCTION; + NamedMDNode(const NamedMDNode &) = delete; std::string Name; Module *Parent; diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index b24023b05e4f..d8636dfb123e 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -219,14 +219,7 @@ private: std::string TargetTriple; ///< Platform target triple Module compiled on ///< Format: (arch)(sub)-(vendor)-(sys0-(abi) void *NamedMDSymTab; ///< NamedMDNode names. - - // We need to keep the string because the C API expects us to own the string - // representation. - // Since we have it, we also use an empty string to represent a module without - // a DataLayout. If it has a DataLayout, these variables are in sync and the - // string is just a cache of getDataLayout()->getStringRepresentation(). - std::string DataLayoutStr; - DataLayout DL; + DataLayout DL; ///< DataLayout associated with the module friend class Constant; @@ -256,10 +249,12 @@ public: /// Get the data layout string for the module's target platform. This is /// equivalent to getDataLayout()->getStringRepresentation(). - const std::string &getDataLayoutStr() const { return DataLayoutStr; } + const std::string getDataLayoutStr() const { + return DL.getStringRepresentation(); + } /// Get the data layout for the module's target platform. - const DataLayout *getDataLayout() const; + const DataLayout &getDataLayout() const; /// Get the target triple which is a string describing the target host. /// @returns a string containing the target triple. @@ -293,12 +288,13 @@ public: /// Set the data layout void setDataLayout(StringRef Desc); - void setDataLayout(const DataLayout *Other); + void setDataLayout(const DataLayout &Other); /// Set the target triple. void setTargetTriple(StringRef T) { TargetTriple = T; } /// Set the module-scope inline assembly blocks. + /// A trailing newline is added if the input doesn't have one. void setModuleInlineAsm(StringRef Asm) { GlobalScopeAsm = Asm; if (!GlobalScopeAsm.empty() && @@ -306,8 +302,8 @@ public: GlobalScopeAsm += '\n'; } - /// Append to the module-scope inline assembly blocks, automatically inserting - /// a separating newline if necessary. + /// Append to the module-scope inline assembly blocks. + /// A trailing newline is added if the input doesn't have one. void appendModuleInlineAsm(StringRef Asm) { GlobalScopeAsm += Asm; if (!GlobalScopeAsm.empty() && @@ -496,7 +492,7 @@ public: /// If the GlobalValue is read in, and if the GVMaterializer supports it, /// release the memory for the function, and set it up to be materialized /// lazily. If !isDematerializable(), this method is a no-op. - void Dematerialize(GlobalValue *GV); + void dematerialize(GlobalValue *GV); /// Make sure all GlobalValues in this Module are fully read. std::error_code materializeAll(); @@ -506,6 +502,8 @@ public: /// Materializer. std::error_code materializeAllPermanently(); + std::error_code materializeMetadata(); + /// @} /// @name Direct access to the globals list, functions list, and symbol table /// @{ @@ -630,13 +628,25 @@ public: named_metadata_end()); } + /// Destroy ConstantArrays in LLVMContext if they are not used. + /// ConstantArrays constructed during linking can cause quadratic memory + /// explosion. Releasing all unused constants can cause a 20% LTO compile-time + /// slowdown for a large application. + /// + /// NOTE: Constants are currently owned by LLVMContext. This can then only + /// be called where all uses of the LLVMContext are understood. + void dropTriviallyDeadConstantArrays(); + /// @} /// @name Utility functions for printing and dumping Module objects /// @{ /// Print the module to an output stream with an optional - /// AssemblyAnnotationWriter. - void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW) const; + /// AssemblyAnnotationWriter. If \c ShouldPreserveUseListOrder, then include + /// uselistorder directives so that use-lists can be recreated when reading + /// the assembly. + void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW, + bool ShouldPreserveUseListOrder = false) const; /// Dump the module to stderr (for debugging). void dump() const; diff --git a/include/llvm/IR/NoFolder.h b/include/llvm/IR/NoFolder.h index a9cdfc36fb4a..61f4817a9b62 100644 --- a/include/llvm/IR/NoFolder.h +++ b/include/llvm/IR/NoFolder.h @@ -177,34 +177,35 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); + return ConstantExpr::getGetElementPtr(Ty, C, IdxList); } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getGetElementPtr(C, Idx); + return ConstantExpr::getGetElementPtr(Ty, C, Idx); } - Instruction *CreateGetElementPtr(Constant *C, + Instruction *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return GetElementPtrInst::Create(C, IdxList); + return GetElementPtrInst::Create(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getInBoundsGetElementPtr(C, Idx); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx); } - Instruction *CreateInBoundsGetElementPtr(Constant *C, + Instruction *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return GetElementPtrInst::CreateInBounds(C, IdxList); + return GetElementPtrInst::CreateInBounds(Ty, C, IdxList); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 0933f2170236..1b9102ecc7e4 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -18,7 +18,6 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Type.h" @@ -34,15 +33,15 @@ class Operator : public User { private: // The Operator class is intended to be used as a utility, and is never itself // instantiated. - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - void *operator new(size_t s) LLVM_DELETED_FUNCTION; - Operator() LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + void *operator new(size_t s) = delete; + Operator() = delete; protected: - // NOTE: Cannot use LLVM_DELETED_FUNCTION because it's not legal to delete + // NOTE: Cannot use = delete because it's not legal to delete // an overridden method that's not deleted in the base class. Cannot leave // this unimplemented because that leads to an ODR-violation. - ~Operator(); + ~Operator() override; public: /// Return the opcode for this Instruction or ConstantExpr. @@ -181,17 +180,17 @@ public: { } /// Whether any flag is set - bool any() { return Flags != 0; } + bool any() const { return Flags != 0; } /// Set all the flags to false void clear() { Flags = 0; } /// Flag queries - bool noNaNs() { return 0 != (Flags & NoNaNs); } - bool noInfs() { return 0 != (Flags & NoInfs); } - bool noSignedZeros() { return 0 != (Flags & NoSignedZeros); } - bool allowReciprocal() { return 0 != (Flags & AllowReciprocal); } - bool unsafeAlgebra() { return 0 != (Flags & UnsafeAlgebra); } + bool noNaNs() const { return 0 != (Flags & NoNaNs); } + bool noInfs() const { return 0 != (Flags & NoInfs); } + bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); } + bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); } + bool unsafeAlgebra() const { return 0 != (Flags & UnsafeAlgebra); } /// Flag setters void setNoNaNs() { Flags |= NoNaNs; } @@ -400,6 +399,8 @@ public: return getPointerOperand()->getType(); } + Type *getSourceElementType() const; + /// Method to return the address space of the pointer operand. unsigned getPointerAddressSpace() const { return getPointerOperandType()->getPointerAddressSpace(); @@ -445,36 +446,7 @@ public: /// undefined (it is *not* preserved!). The APInt passed into this routine /// must be at exactly as wide as the IntPtr type for the address space of the /// base GEP pointer. - bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const { - assert(Offset.getBitWidth() == - DL.getPointerSizeInBits(getPointerAddressSpace()) && - "The offset must have exactly as many bits as our pointer."); - - for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); - GTI != GTE; ++GTI) { - ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand()); - if (!OpC) - return false; - if (OpC->isZero()) - continue; - - // Handle a struct index, which adds its field offset to the pointer. - if (StructType *STy = dyn_cast<StructType>(*GTI)) { - unsigned ElementIdx = OpC->getZExtValue(); - const StructLayout *SL = DL.getStructLayout(STy); - Offset += APInt(Offset.getBitWidth(), - SL->getElementOffset(ElementIdx)); - continue; - } - - // For array or vector indices, scale the index by the size of the type. - APInt Index = OpC->getValue().sextOrTrunc(Offset.getBitWidth()); - Offset += Index * APInt(Offset.getBitWidth(), - DL.getTypeAllocSize(GTI.getIndexedType())); - } - return true; - } - + bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const; }; class PtrToIntOperator @@ -504,6 +476,20 @@ public: } }; +class BitCastOperator + : public ConcreteOperator<Operator, Instruction::BitCast> { + friend class BitCastInst; + friend class ConstantExpr; + +public: + Type *getSrcTy() const { + return getOperand(0)->getType(); + } + + Type *getDestTy() const { + return getType(); + } +}; } // End llvm namespace diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index 262576849264..4166babd63e5 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -46,6 +46,7 @@ #include "llvm/IR/PassManagerInternal.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/type_traits.h" #include <list> #include <memory> @@ -241,8 +242,8 @@ public: private: typedef detail::PassConcept<IRUnitT> PassConceptT; - PassManager(const PassManager &) LLVM_DELETED_FUNCTION; - PassManager &operator=(const PassManager &) LLVM_DELETED_FUNCTION; + PassManager(const PassManager &) = delete; + PassManager &operator=(const PassManager &) = delete; std::vector<std::unique_ptr<PassConceptT>> Passes; @@ -281,9 +282,9 @@ template <typename DerivedT, typename IRUnitT> class AnalysisManagerBase { return static_cast<const DerivedT *>(this); } - AnalysisManagerBase(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION; + AnalysisManagerBase(const AnalysisManagerBase &) = delete; AnalysisManagerBase & - operator=(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION; + operator=(const AnalysisManagerBase &) = delete; protected: typedef detail::AnalysisResultConcept<IRUnitT> ResultConceptT; @@ -453,8 +454,8 @@ public: } private: - AnalysisManager(const AnalysisManager &) LLVM_DELETED_FUNCTION; - AnalysisManager &operator=(const AnalysisManager &) LLVM_DELETED_FUNCTION; + AnalysisManager(const AnalysisManager &) = delete; + AnalysisManager &operator=(const AnalysisManager &) = delete; /// \brief Get an analysis result, running the pass if necessary. ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR) { @@ -471,6 +472,12 @@ private: dbgs() << "Running analysis: " << P.name() << "\n"; AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; ResultList.emplace_back(PassID, P.run(IR, this)); + + // P.run may have inserted elements into AnalysisResults and invalidated + // RI. + RI = AnalysisResults.find(std::make_pair(PassID, &IR)); + assert(RI != AnalysisResults.end() && "we just inserted it!"); + RI->second = std::prev(ResultList.end()); } @@ -502,7 +509,7 @@ private: PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) { // Short circuit for a common case of all analyses being preserved. if (PA.areAllPreserved()) - return std::move(PA); + return PA; if (DebugLogging) dbgs() << "Invalidating all non-preserved analyses for: " @@ -542,7 +549,7 @@ private: if (ResultsList.empty()) AnalysisResultLists.erase(&IR); - return std::move(PA); + return PA; } /// \brief List of function analysis pass IDs and associated concept pointers. @@ -782,8 +789,11 @@ public: FAM = &AM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); PreservedAnalyses PA = PreservedAnalyses::all(); - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { - PreservedAnalyses PassPA = Pass.run(*I, FAM); + for (Function &F : M) { + if (F.isDeclaration()) + continue; + + PreservedAnalyses PassPA = Pass.run(F, FAM); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so @@ -791,7 +801,7 @@ public: // update our preserved set to reflect that these have already been // handled. if (FAM) - PassPA = FAM->invalidate(*I, std::move(PassPA)); + PassPA = FAM->invalidate(F, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -817,7 +827,7 @@ private: template <typename FunctionPassT> ModuleToFunctionPassAdaptor<FunctionPassT> createModuleToFunctionPassAdaptor(FunctionPassT Pass) { - return std::move(ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass))); + return ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)); } /// \brief A template utility pass to force an analysis result to be available. diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h index 297f5f4e07f4..92de10bcd75b 100644 --- a/include/llvm/IR/PassManagerInternal.h +++ b/include/llvm/IR/PassManagerInternal.h @@ -19,6 +19,7 @@ #define LLVM_IR_PASSMANAGERINTERNAL_H #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/STLExtras.h" namespace llvm { diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index f94e10576893..41154e6441a9 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -295,6 +295,9 @@ template <typename Class> struct bind_ty { /// \brief Match a value, capturing it if we match. inline bind_ty<Value> m_Value(Value *&V) { return V; } +/// \brief Match an instruction, capturing it if we match. +inline bind_ty<Instruction> m_Instruction(Instruction *&I) { return I; } + /// \brief Match a binary operator, capturing it if we match. inline bind_ty<BinaryOperator> m_BinOp(BinaryOperator *&I) { return I; } @@ -1103,6 +1106,52 @@ m_UnordFMax(const LHS &L, const RHS &R) { return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R); } +//===----------------------------------------------------------------------===// +// Matchers for overflow check patterns: e.g. (a + b) u< a +// + +template <typename LHS_t, typename RHS_t, typename Sum_t> +struct UAddWithOverflow_match { + LHS_t L; + RHS_t R; + Sum_t S; + + UAddWithOverflow_match(const LHS_t &L, const RHS_t &R, const Sum_t &S) + : L(L), R(R), S(S) {} + + template <typename OpTy> bool match(OpTy *V) { + Value *ICmpLHS, *ICmpRHS; + ICmpInst::Predicate Pred; + if (!m_ICmp(Pred, m_Value(ICmpLHS), m_Value(ICmpRHS)).match(V)) + return false; + + Value *AddLHS, *AddRHS; + auto AddExpr = m_Add(m_Value(AddLHS), m_Value(AddRHS)); + + // (a + b) u< a, (a + b) u< b + if (Pred == ICmpInst::ICMP_ULT) + if (AddExpr.match(ICmpLHS) && (ICmpRHS == AddLHS || ICmpRHS == AddRHS)) + return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpLHS); + + // a >u (a + b), b >u (a + b) + if (Pred == ICmpInst::ICMP_UGT) + if (AddExpr.match(ICmpRHS) && (ICmpLHS == AddLHS || ICmpLHS == AddRHS)) + return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpRHS); + + return false; + } +}; + +/// \brief Match an icmp instruction checking for unsigned overflow on addition. +/// +/// S is matched to the addition whose result is being checked for overflow, and +/// L and R are matched to the LHS and RHS of S. +template <typename LHS_t, typename RHS_t, typename Sum_t> +UAddWithOverflow_match<LHS_t, RHS_t, Sum_t> +m_UAddWithOverflow(const LHS_t &L, const RHS_t &R, const Sum_t &S) { + return UAddWithOverflow_match<LHS_t, RHS_t, Sum_t>(L, R, S); +} + /// \brief Match an 'unordered' floating point minimum function. /// Floating point has one special value 'NaN'. Therefore, there is no total /// order. However, if we can ignore the 'NaN' value (for example, because of a diff --git a/include/llvm/IR/PredIteratorCache.h b/include/llvm/IR/PredIteratorCache.h index 5e1be37805ff..118310aed1d0 100644 --- a/include/llvm/IR/PredIteratorCache.h +++ b/include/llvm/IR/PredIteratorCache.h @@ -14,6 +14,7 @@ #ifndef LLVM_IR_PREDITERATORCACHE_H #define LLVM_IR_PREDITERATORCACHE_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/CFG.h" @@ -21,50 +22,58 @@ namespace llvm { - /// PredIteratorCache - This class is an extremely trivial cache for - /// predecessor iterator queries. This is useful for code that repeatedly - /// wants the predecessor list for the same blocks. - class PredIteratorCache { - /// BlockToPredsMap - Pointer to null-terminated list. - DenseMap<BasicBlock*, BasicBlock**> BlockToPredsMap; - DenseMap<BasicBlock*, unsigned> BlockToPredCountMap; +/// PredIteratorCache - This class is an extremely trivial cache for +/// predecessor iterator queries. This is useful for code that repeatedly +/// wants the predecessor list for the same blocks. +class PredIteratorCache { + /// BlockToPredsMap - Pointer to null-terminated list. + DenseMap<BasicBlock *, BasicBlock **> BlockToPredsMap; + DenseMap<BasicBlock *, unsigned> BlockToPredCountMap; - /// Memory - This is the space that holds cached preds. - BumpPtrAllocator Memory; - public: + /// Memory - This is the space that holds cached preds. + BumpPtrAllocator Memory; - /// GetPreds - Get a cached list for the null-terminated predecessor list of - /// the specified block. This can be used in a loop like this: - /// for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) - /// use(*PI); - /// instead of: - /// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) - BasicBlock **GetPreds(BasicBlock *BB) { - BasicBlock **&Entry = BlockToPredsMap[BB]; - if (Entry) return Entry; +private: + /// GetPreds - Get a cached list for the null-terminated predecessor list of + /// the specified block. This can be used in a loop like this: + /// for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) + /// use(*PI); + /// instead of: + /// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + BasicBlock **GetPreds(BasicBlock *BB) { + BasicBlock **&Entry = BlockToPredsMap[BB]; + if (Entry) + return Entry; - SmallVector<BasicBlock*, 32> PredCache(pred_begin(BB), pred_end(BB)); - PredCache.push_back(nullptr); // null terminator. - - BlockToPredCountMap[BB] = PredCache.size()-1; + SmallVector<BasicBlock *, 32> PredCache(pred_begin(BB), pred_end(BB)); + PredCache.push_back(nullptr); // null terminator. - Entry = Memory.Allocate<BasicBlock*>(PredCache.size()); - std::copy(PredCache.begin(), PredCache.end(), Entry); - return Entry; - } - - unsigned GetNumPreds(BasicBlock *BB) { - GetPreds(BB); - return BlockToPredCountMap[BB]; - } + BlockToPredCountMap[BB] = PredCache.size() - 1; + + Entry = Memory.Allocate<BasicBlock *>(PredCache.size()); + std::copy(PredCache.begin(), PredCache.end(), Entry); + return Entry; + } + + unsigned GetNumPreds(BasicBlock *BB) { + GetPreds(BB); + return BlockToPredCountMap[BB]; + } + +public: + size_t size(BasicBlock *BB) { return GetNumPreds(BB); } + ArrayRef<BasicBlock *> get(BasicBlock *BB) { + return makeArrayRef(GetPreds(BB), GetNumPreds(BB)); + } + + /// clear - Remove all information. + void clear() { + BlockToPredsMap.clear(); + BlockToPredCountMap.clear(); + Memory.Reset(); + } +}; - /// clear - Remove all information. - void clear() { - BlockToPredsMap.clear(); - BlockToPredCountMap.clear(); - Memory.Reset(); - } - }; } // end namespace llvm #endif diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h index e3c4243e9d81..cd09618e3eee 100644 --- a/include/llvm/IR/Statepoint.h +++ b/include/llvm/IR/Statepoint.h @@ -17,21 +17,35 @@ #define __LLVM_IR_STATEPOINT_H #include "llvm/ADT/iterator_range.h" +#include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallSite.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/Compiler.h" namespace llvm { +/// The statepoint intrinsic accepts a set of flags as its third argument. +/// Valid values come out of this set. +enum class StatepointFlags { + None = 0, + GCTransition = 1, ///< Indicates that this statepoint is a transition from + ///< GC-aware code to code that is not GC-aware. + + MaskAll = GCTransition ///< A bitmask that includes all valid flags. +}; + +class GCRelocateOperands; +class ImmutableStatepoint; bool isStatepoint(const ImmutableCallSite &CS); -bool isStatepoint(const Instruction *inst); -bool isStatepoint(const Instruction &inst); +bool isStatepoint(const Value *inst); +bool isStatepoint(const Value &inst); -bool isGCRelocate(const Instruction *inst); +bool isGCRelocate(const Value *inst); bool isGCRelocate(const ImmutableCallSite &CS); -bool isGCResult(const Instruction *inst); +bool isGCResult(const Value *inst); bool isGCResult(const ImmutableCallSite &CS); /// Analogous to CallSiteBase, this provides most of the actual @@ -45,10 +59,10 @@ bool isGCResult(const ImmutableCallSite &CS); template <typename InstructionTy, typename ValueTy, typename CallSiteTy> class StatepointBase { CallSiteTy StatepointCS; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - void *operator new(size_t s) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + void *operator new(size_t s) = delete; - protected: +protected: explicit StatepointBase(InstructionTy *I) : StatepointCS(I) { assert(isStatepoint(I)); } @@ -56,38 +70,68 @@ class StatepointBase { assert(isStatepoint(CS)); } - public: +public: typedef typename CallSiteTy::arg_iterator arg_iterator; + enum { + IDPos = 0, + NumPatchBytesPos = 1, + ActualCalleePos = 2, + NumCallArgsPos = 3, + FlagsPos = 4, + CallArgsBeginPos = 5, + }; + /// Return the underlying CallSite. - CallSiteTy getCallSite() { - return StatepointCS; + CallSiteTy getCallSite() { return StatepointCS; } + + uint64_t getFlags() const { + return cast<ConstantInt>(StatepointCS.getArgument(FlagsPos)) + ->getZExtValue(); + } + + /// Return the ID associated with this statepoint. + uint64_t getID() { + const Value *IDVal = StatepointCS.getArgument(IDPos); + return cast<ConstantInt>(IDVal)->getZExtValue(); + } + + /// Return the number of patchable bytes associated with this statepoint. + uint32_t getNumPatchBytes() { + const Value *NumPatchBytesVal = StatepointCS.getArgument(NumPatchBytesPos); + uint64_t NumPatchBytes = + cast<ConstantInt>(NumPatchBytesVal)->getZExtValue(); + assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!"); + return NumPatchBytes; } /// Return the value actually being called or invoked. - ValueTy *actualCallee() { - return StatepointCS.getArgument(0); + ValueTy *getActualCallee() { + return StatepointCS.getArgument(ActualCalleePos); } - /// Number of arguments to be passed to the actual callee. - int numCallArgs() { - return cast<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue(); + + /// Return the type of the value returned by the call underlying the + /// statepoint. + Type *getActualReturnType() { + auto *FTy = cast<FunctionType>( + cast<PointerType>(getActualCallee()->getType())->getElementType()); + return FTy->getReturnType(); } - /// Number of additional arguments excluding those intended - /// for garbage collection. - int numTotalVMSArgs() { - return cast<ConstantInt>(StatepointCS.getArgument(3 + numCallArgs()))->getZExtValue(); + + /// Number of arguments to be passed to the actual callee. + int getNumCallArgs() { + const Value *NumCallArgsVal = StatepointCS.getArgument(NumCallArgsPos); + return cast<ConstantInt>(NumCallArgsVal)->getZExtValue(); } typename CallSiteTy::arg_iterator call_args_begin() { - // 3 = callTarget, #callArgs, flag - int Offset = 3; - assert(Offset <= (int)StatepointCS.arg_size()); - return StatepointCS.arg_begin() + Offset; + assert(CallArgsBeginPos <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + CallArgsBeginPos; } typename CallSiteTy::arg_iterator call_args_end() { - int Offset = 3 + numCallArgs(); - assert(Offset <= (int)StatepointCS.arg_size()); - return StatepointCS.arg_begin() + Offset; + auto I = call_args_begin() + getNumCallArgs(); + assert((StatepointCS.arg_end() - I) >= 0); + return I; } /// range adapter for call arguments @@ -95,13 +139,44 @@ class StatepointBase { return iterator_range<arg_iterator>(call_args_begin(), call_args_end()); } + /// Number of GC transition args. + int getNumTotalGCTransitionArgs() { + const Value *NumGCTransitionArgs = *call_args_end(); + return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue(); + } + typename CallSiteTy::arg_iterator gc_transition_args_begin() { + auto I = call_args_end() + 1; + assert((StatepointCS.arg_end() - I) >= 0); + return I; + } + typename CallSiteTy::arg_iterator gc_transition_args_end() { + auto I = gc_transition_args_begin() + getNumTotalGCTransitionArgs(); + assert((StatepointCS.arg_end() - I) >= 0); + return I; + } + + /// range adapter for GC transition arguments + iterator_range<arg_iterator> gc_transition_args() { + return iterator_range<arg_iterator>(gc_transition_args_begin(), + gc_transition_args_end()); + } + + /// Number of additional arguments excluding those intended + /// for garbage collection. + int getNumTotalVMSArgs() { + const Value *NumVMSArgs = *gc_transition_args_end(); + return cast<ConstantInt>(NumVMSArgs)->getZExtValue(); + } + typename CallSiteTy::arg_iterator vm_state_begin() { - return call_args_end(); + auto I = gc_transition_args_end() + 1; + assert((StatepointCS.arg_end() - I) >= 0); + return I; } typename CallSiteTy::arg_iterator vm_state_end() { - int Offset = 3 + numCallArgs() + 1 + numTotalVMSArgs(); - assert(Offset <= (int)StatepointCS.arg_size()); - return StatepointCS.arg_begin() + Offset; + auto I = vm_state_begin() + getNumTotalVMSArgs(); + assert((StatepointCS.arg_end() - I) >= 0); + return I; } /// range adapter for vm state arguments @@ -109,15 +184,7 @@ class StatepointBase { return iterator_range<arg_iterator>(vm_state_begin(), vm_state_end()); } - typename CallSiteTy::arg_iterator first_vm_state_stack_begin() { - // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci, - // 1st_#stack, 1st_#local, 1st_#monitor - return vm_state_begin() + 6; - } - - typename CallSiteTy::arg_iterator gc_args_begin() { - return vm_state_end(); - } + typename CallSiteTy::arg_iterator gc_args_begin() { return vm_state_end(); } typename CallSiteTy::arg_iterator gc_args_end() { return StatepointCS.arg_end(); } @@ -127,18 +194,25 @@ class StatepointBase { return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end()); } + /// Get list of all gc reloactes linked to this statepoint + /// May contain several relocations for the same base/derived pair. + /// For example this could happen due to relocations on unwinding + /// path of invoke. + std::vector<GCRelocateOperands> getRelocates(ImmutableStatepoint &IS); #ifndef NDEBUG /// Asserts if this statepoint is malformed. Common cases for failure /// include incorrect length prefixes for variable length sections or /// illegal values for parameters. void verify() { - assert(numCallArgs() >= 0 && + assert(getNumCallArgs() >= 0 && "number of arguments to actually callee can't be negative"); // The internal asserts in the iterator accessors do the rest. (void)call_args_begin(); (void)call_args_end(); + (void)gc_transition_args_begin(); + (void)gc_transition_args_end(); (void)vm_state_begin(); (void)vm_state_end(); (void)gc_args_begin(); @@ -150,8 +224,7 @@ class StatepointBase { /// A specialization of it's base class for read only access /// to a gc.statepoint. class ImmutableStatepoint - : public StatepointBase<const Instruction, const Value, - ImmutableCallSite> { + : public StatepointBase<const Instruction, const Value, ImmutableCallSite> { typedef StatepointBase<const Instruction, const Value, ImmutableCallSite> Base; @@ -176,40 +249,106 @@ public: class GCRelocateOperands { ImmutableCallSite RelocateCS; - public: - GCRelocateOperands(const User* U) : RelocateCS(U) { - assert(isGCRelocate(U)); - } +public: + GCRelocateOperands(const User *U) : RelocateCS(U) { assert(isGCRelocate(U)); } GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) { assert(isGCRelocate(inst)); } - GCRelocateOperands(CallSite CS) : RelocateCS(CS) { - assert(isGCRelocate(CS)); + GCRelocateOperands(CallSite CS) : RelocateCS(CS) { assert(isGCRelocate(CS)); } + + /// Return true if this relocate is tied to the invoke statepoint. + /// This includes relocates which are on the unwinding path. + bool isTiedToInvoke() const { + const Value *Token = RelocateCS.getArgument(0); + + return isa<ExtractValueInst>(Token) || isa<InvokeInst>(Token); } + /// Get enclosed relocate intrinsic + ImmutableCallSite getUnderlyingCallSite() { return RelocateCS; } + /// The statepoint with which this gc.relocate is associated. - const Instruction *statepoint() { - return cast<Instruction>(RelocateCS.getArgument(0)); + const Instruction *getStatepoint() { + const Value *Token = RelocateCS.getArgument(0); + + // This takes care both of relocates for call statepoints and relocates + // on normal path of invoke statepoint. + if (!isa<ExtractValueInst>(Token)) { + return cast<Instruction>(Token); + } + + // This relocate is on exceptional path of an invoke statepoint + const BasicBlock *InvokeBB = + cast<Instruction>(Token)->getParent()->getUniquePredecessor(); + + assert(InvokeBB && "safepoints should have unique landingpads"); + assert(InvokeBB->getTerminator() && + "safepoint block should be well formed"); + assert(isStatepoint(InvokeBB->getTerminator())); + + return InvokeBB->getTerminator(); } + /// The index into the associate statepoint's argument list /// which contains the base pointer of the pointer whose /// relocation this gc.relocate describes. - int basePtrIndex() { + unsigned getBasePtrIndex() { return cast<ConstantInt>(RelocateCS.getArgument(1))->getZExtValue(); } + /// The index into the associate statepoint's argument list which /// contains the pointer whose relocation this gc.relocate describes. - int derivedPtrIndex() { + unsigned getDerivedPtrIndex() { return cast<ConstantInt>(RelocateCS.getArgument(2))->getZExtValue(); } - Value *basePtr() { - ImmutableCallSite CS(statepoint()); - return *(CS.arg_begin() + basePtrIndex()); + + Value *getBasePtr() { + ImmutableCallSite CS(getStatepoint()); + return *(CS.arg_begin() + getBasePtrIndex()); } - Value *derivedPtr() { - ImmutableCallSite CS(statepoint()); - return *(CS.arg_begin() + derivedPtrIndex()); + + Value *getDerivedPtr() { + ImmutableCallSite CS(getStatepoint()); + return *(CS.arg_begin() + getDerivedPtrIndex()); } }; + +template <typename InstructionTy, typename ValueTy, typename CallSiteTy> +std::vector<GCRelocateOperands> +StatepointBase<InstructionTy, ValueTy, CallSiteTy>::getRelocates( + ImmutableStatepoint &IS) { + + std::vector<GCRelocateOperands> Result; + + ImmutableCallSite StatepointCS = IS.getCallSite(); + + // Search for relocated pointers. Note that working backwards from the + // gc_relocates ensures that we only get pairs which are actually relocated + // and used after the statepoint. + for (const User *U : StatepointCS.getInstruction()->users()) + if (isGCRelocate(U)) + Result.push_back(GCRelocateOperands(U)); + + if (!StatepointCS.isInvoke()) + return Result; + + // We need to scan thorough exceptional relocations if it is invoke statepoint + LandingPadInst *LandingPad = + cast<InvokeInst>(StatepointCS.getInstruction())->getLandingPadInst(); + + // Search for extract value from landingpad instruction to which + // gc relocates will be attached + for (const User *LandingPadUser : LandingPad->users()) { + if (!isa<ExtractValueInst>(LandingPadUser)) + continue; + + // gc relocates should be attached to this extract value + for (const User *U : LandingPadUser->users()) + if (isGCRelocate(U)) + Result.push_back(GCRelocateOperands(U)); + } + return Result; +} } + #endif diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index c2073c7750b2..6ab0bd0631a0 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -91,8 +91,8 @@ protected: NumContainedTys(0), ContainedTys(nullptr) { setTypeID(tid); } - ~Type() {} - + ~Type() = default; + void setTypeID(TypeID ID) { IDAndSubclassData = (ID & 0xFF) | (IDAndSubclassData & 0xFFFFFF00); assert(getTypeID() == ID && "TypeID data too large for field"); @@ -395,7 +395,8 @@ public: static IntegerType *getInt16Ty(LLVMContext &C); static IntegerType *getInt32Ty(LLVMContext &C); static IntegerType *getInt64Ty(LLVMContext &C); - + static IntegerType *getInt128Ty(LLVMContext &C); + //===--------------------------------------------------------------------===// // Convenience methods for getting pointer types with one of the above builtin // types as pointee. diff --git a/include/llvm/IR/TypeBuilder.h b/include/llvm/IR/TypeBuilder.h index 5a29e1e10855..d2c6f00079da 100644 --- a/include/llvm/IR/TypeBuilder.h +++ b/include/llvm/IR/TypeBuilder.h @@ -34,6 +34,8 @@ namespace llvm { /// you'll need to specialize it. For example, say you want to call a /// function defined externally as: /// +/// \code{.cpp} +/// /// struct MyType { /// int32 a; /// int32 *b; @@ -41,12 +43,16 @@ namespace llvm { /// }; /// int8 AFunction(struct MyType *value); /// +/// \endcode +/// /// You'll want to use /// Function::Create(TypeBuilder<types::i<8>(MyType*), true>::get(), ...) /// to declare the function, but when you first try this, your compiler will /// complain that TypeBuilder<MyType, true>::get() doesn't exist. To fix this, /// write: /// +/// \code{.cpp} +/// /// namespace llvm { /// template<bool xcompile> class TypeBuilder<MyType, xcompile> { /// public: @@ -57,7 +63,7 @@ namespace llvm { /// TypeBuilder<types::i<32>, xcompile>::get(Context), /// TypeBuilder<types::i<32>*, xcompile>::get(Context), /// TypeBuilder<types::i<8>*[], xcompile>::get(Context), -/// NULL); +/// nullptr); /// } /// /// // You may find this a convenient place to put some constants @@ -71,6 +77,8 @@ namespace llvm { /// } /// } // namespace llvm /// +/// \endcode +/// /// TypeBuilder cannot handle recursive types or types you only know at runtime. /// If you try to give it a recursive type, it will deadlock, infinitely /// recurse, or do something similarly undesirable. diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h index 033cd3e2f5da..160d71b03e7f 100644 --- a/include/llvm/IR/Use.h +++ b/include/llvm/IR/Use.h @@ -77,7 +77,7 @@ public: typedef PointerIntPair<User *, 1, unsigned> UserRef; private: - Use(const Use &U) LLVM_DELETED_FUNCTION; + Use(const Use &U) = delete; /// Destructor - Only for zap() ~Use() { diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h index 5df459b1bd30..b7c2418d348d 100644 --- a/include/llvm/IR/UseListOrder.h +++ b/include/llvm/IR/UseListOrder.h @@ -45,18 +45,12 @@ struct UseListOrder { } private: - UseListOrder(const UseListOrder &X) LLVM_DELETED_FUNCTION; - UseListOrder &operator=(const UseListOrder &X) LLVM_DELETED_FUNCTION; + UseListOrder(const UseListOrder &X) = delete; + UseListOrder &operator=(const UseListOrder &X) = delete; }; typedef std::vector<UseListOrder> UseListOrderStack; -/// \brief Whether to preserve use-list ordering. -bool shouldPreserveBitcodeUseListOrder(); -bool shouldPreserveAssemblyUseListOrder(); -void setPreserveBitcodeUseListOrder(bool ShouldPreserve); -void setPreserveAssemblyUseListOrder(bool ShouldPreserve); - } // end namespace llvm #endif diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index f578227d6cae..455900566afd 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -33,8 +33,8 @@ template <class> struct OperandTraits; class User : public Value { - User(const User &) LLVM_DELETED_FUNCTION; - void *operator new(size_t) LLVM_DELETED_FUNCTION; + User(const User &) = delete; + void *operator new(size_t) = delete; template <unsigned> friend struct HungoffOperandTraits; virtual void anchor(); @@ -60,9 +60,7 @@ protected: NumOperands = 0; } public: - ~User() { - Use::zap(OperandList, OperandList + NumOperands); - } + ~User() override { Use::zap(OperandList, OperandList + NumOperands); } /// \brief Free memory allocated for User and Use objects. void operator delete(void *Usr); /// \brief Placement delete - required by std, but never called. diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 705fc0f52d58..3bf2943a8980 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -106,17 +106,12 @@ protected: private: template <typename UseT> // UseT == 'Use' or 'const Use' class use_iterator_impl - : public std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> { - typedef std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> super; - + : public std::iterator<std::forward_iterator_tag, UseT *> { UseT *U; explicit use_iterator_impl(UseT *u) : U(u) {} friend class Value; public: - typedef typename super::reference reference; - typedef typename super::pointer pointer; - use_iterator_impl() : U() {} bool operator==(const use_iterator_impl &x) const { return U == x.U; } @@ -147,17 +142,12 @@ private: template <typename UserTy> // UserTy == 'User' or 'const User' class user_iterator_impl - : public std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> { - typedef std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> super; - + : public std::iterator<std::forward_iterator_tag, UserTy *> { use_iterator_impl<Use> UI; explicit user_iterator_impl(Use *U) : UI(U) {} friend class Value; public: - typedef typename super::reference reference; - typedef typename super::pointer pointer; - user_iterator_impl() {} bool operator==(const user_iterator_impl &x) const { return UI == x.UI; } @@ -188,15 +178,10 @@ private: } Use &getUse() const { return *UI; } - - /// \brief Return the operand # of this use in its User. - /// - /// FIXME: Replace all callers with a direct call to Use::getOperandNo. - unsigned getOperandNo() const { return UI->getOperandNo(); } }; - void operator=(const Value &) LLVM_DELETED_FUNCTION; - Value(const Value &) LLVM_DELETED_FUNCTION; + void operator=(const Value &) = delete; + Value(const Value &) = delete; protected: Value(Type *Ty, unsigned scid); @@ -231,6 +216,7 @@ public: private: void destroyValueName(); + void setNameImpl(const Twine &Name); public: /// \brief Return a constant reference to the value's name. @@ -461,12 +447,6 @@ public: return const_cast<Value*>(this)->stripInBoundsOffsets(); } - /// \brief Check if this is always a dereferenceable pointer. - /// - /// Test if this value is always a pointer to allocated and suitably aligned - /// memory for a simple load or store. - bool isDereferenceablePointer(const DataLayout *DL = nullptr) const; - /// \brief Translate PHI node to its predecessor from the given basic block. /// /// If this value is a PHI node with CurBB as its parent, return the value in @@ -484,7 +464,8 @@ public: /// /// This is the greatest alignment value supported by load, store, and alloca /// instructions, and global values. - static const unsigned MaximumAlignment = 1u << 29; + static const unsigned MaxAlignmentExponent = 29; + static const unsigned MaximumAlignment = 1u << MaxAlignmentExponent; /// \brief Mutate the type of this Value to be of the specified type. /// diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h index 8fc7fdb03950..355748e05977 100644 --- a/include/llvm/IR/ValueHandle.h +++ b/include/llvm/IR/ValueHandle.h @@ -58,7 +58,7 @@ private: Value* V; - ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION; + ValueHandleBase(const ValueHandleBase&) = delete; public: explicit ValueHandleBase(HandleBaseKind Kind) : PrevPair(nullptr, Kind), Next(nullptr), V(nullptr) {} diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h index f2ea405f1428..4d00b637609c 100644 --- a/include/llvm/IR/ValueMap.h +++ b/include/llvm/IR/ValueMap.h @@ -86,8 +86,8 @@ class ValueMap { MapT Map; std::unique_ptr<MDMapT> MDMap; ExtraData Data; - ValueMap(const ValueMap&) LLVM_DELETED_FUNCTION; - ValueMap& operator=(const ValueMap&) LLVM_DELETED_FUNCTION; + ValueMap(const ValueMap&) = delete; + ValueMap& operator=(const ValueMap&) = delete; public: typedef KeyT key_type; typedef ValueT mapped_type; @@ -99,8 +99,6 @@ public: explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) : Map(NumInitBuckets), Data(Data) {} - ~ValueMap() {} - bool hasMD() const { return MDMap; } MDMapT &MD() { if (!MDMap) @@ -149,9 +147,14 @@ public: // If the key is already in the map, it returns false and doesn't update the // value. std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { - std::pair<typename MapT::iterator, bool> map_result= - Map.insert(std::make_pair(Wrap(KV.first), KV.second)); - return std::make_pair(iterator(map_result.first), map_result.second); + auto MapResult = Map.insert(std::make_pair(Wrap(KV.first), KV.second)); + return std::make_pair(iterator(MapResult.first), MapResult.second); + } + + std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) { + auto MapResult = + Map.insert(std::make_pair(Wrap(KV.first), std::move(KV.second))); + return std::make_pair(iterator(MapResult.first), MapResult.second); } /// insert - Range insertion of pairs. @@ -258,9 +261,9 @@ public: // I could == Copy.Map->Map.end() if the onRAUW callback already // removed the old mapping. if (I != Copy.Map->Map.end()) { - ValueT Target(I->second); + ValueT Target(std::move(I->second)); Copy.Map->Map.erase(I); // Definitely destroys *this. - Copy.Map->insert(std::make_pair(typed_new_key, Target)); + Copy.Map->insert(std::make_pair(typed_new_key, std::move(Target))); } } } diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h index 43bd123e7f44..89039d24195e 100644 --- a/include/llvm/IR/Verifier.h +++ b/include/llvm/IR/Verifier.h @@ -56,20 +56,9 @@ bool verifyModule(const Module &M, raw_ostream *OS = nullptr); /// printed to stderr, and by default they are fatal. You can override that by /// passing \c false to \p FatalErrors. /// -/// Note that this creates a pass suitable for the legacy pass manager. It has nothing to do with \c VerifierPass. -FunctionPass *createVerifierPass(bool FatalErrors = true); - -/// \brief Create a debug-info verifier pass. -/// -/// Check a module for validity of debug info. This is essentially a pass -/// wrapped around the debug-info parts of \a verifyModule(). When the pass -/// detects a verification error it is always printed to stderr, and by default -/// they are fatal. You can override that by passing \c false to \p -/// FatalErrors. -/// /// Note that this creates a pass suitable for the legacy pass manager. It has /// nothing to do with \c VerifierPass. -ModulePass *createDebugInfoVerifierPass(bool FatalErrors = true); +FunctionPass *createVerifierPass(bool FatalErrors = true); class VerifierPass { bool FatalErrors; diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 30280033ee20..497ac55da4b4 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -40,7 +40,7 @@ void initializeObjCARCOpts(PassRegistry&); void initializeVectorization(PassRegistry&); /// initializeInstCombine - Initialize all passes linked into the -/// ScalarOpts library. +/// InstCombine library. void initializeInstCombine(PassRegistry&); /// initializeIPO - Initialize all passes linked into the IPO library. @@ -65,6 +65,7 @@ void initializeTarget(PassRegistry&); void initializeAAEvalPass(PassRegistry&); void initializeAddDiscriminatorsPass(PassRegistry&); void initializeADCEPass(PassRegistry&); +void initializeBDCEPass(PassRegistry&); void initializeAliasAnalysisAnalysisGroup(PassRegistry&); void initializeAliasAnalysisCounterPass(PassRegistry&); void initializeAliasDebuggerPass(PassRegistry&); @@ -77,7 +78,6 @@ void initializeAlignmentFromAssumptionsPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); void initializeCallGraphWrapperPassPass(PassRegistry &); -void initializeBasicTTIPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&); void initializeBlockFrequencyInfoPass(PassRegistry&); void initializeBoundsCheckingPass(PassRegistry&); @@ -106,11 +106,11 @@ void initializeDAEPass(PassRegistry&); void initializeDAHPass(PassRegistry&); void initializeDCEPass(PassRegistry&); void initializeDSEPass(PassRegistry&); -void initializeDebugInfoVerifierLegacyPassPass(PassRegistry &); void initializeDeadInstEliminationPass(PassRegistry&); void initializeDeadMachineInstructionElimPass(PassRegistry&); void initializeDelinearizationPass(PassRegistry &); void initializeDependenceAnalysisPass(PassRegistry&); +void initializeDivergenceAnalysisPass(PassRegistry&); void initializeDomOnlyPrinterPass(PassRegistry&); void initializeDomOnlyViewerPass(PassRegistry&); void initializeDomPrinterPass(PassRegistry&); @@ -129,7 +129,7 @@ void initializeThreadSanitizerPass(PassRegistry&); void initializeSanitizerCoverageModulePass(PassRegistry&); void initializeDataFlowSanitizerPass(PassRegistry&); void initializeScalarizerPass(PassRegistry&); -void initializeEarlyCSEPass(PassRegistry&); +void initializeEarlyCSELegacyPassPass(PassRegistry &); void initializeExpandISelPseudosPass(PassRegistry&); void initializeFunctionAttrsPass(PassRegistry&); void initializeGCMachineCodeAnalysisPass(PassRegistry&); @@ -142,15 +142,14 @@ void initializeIPCPPass(PassRegistry&); void initializeIPSCCPPass(PassRegistry&); void initializeIVUsersPass(PassRegistry&); void initializeIfConverterPass(PassRegistry&); +void initializeInductiveRangeCheckEliminationPass(PassRegistry&); void initializeIndVarSimplifyPass(PassRegistry&); void initializeInlineCostAnalysisPass(PassRegistry&); -void initializeInstCombinerPass(PassRegistry&); +void initializeInstructionCombiningPassPass(PassRegistry&); void initializeInstCountPass(PassRegistry&); void initializeInstNamerPass(PassRegistry&); void initializeInternalizePassPass(PassRegistry&); void initializeIntervalPartitionPass(PassRegistry&); -void initializeJumpInstrTableInfoPass(PassRegistry&); -void initializeJumpInstrTablesPass(PassRegistry&); void initializeJumpThreadingPass(PassRegistry&); void initializeLCSSAPass(PassRegistry&); void initializeLICMPass(PassRegistry&); @@ -166,7 +165,8 @@ void initializeLoaderPassPass(PassRegistry&); void initializeLocalStackSlotPassPass(PassRegistry&); void initializeLoopDeletionPass(PassRegistry&); void initializeLoopExtractorPass(PassRegistry&); -void initializeLoopInfoPass(PassRegistry&); +void initializeLoopInfoWrapperPassPass(PassRegistry&); +void initializeLoopInterchangePass(PassRegistry &); void initializeLoopInstSimplifyPass(PassRegistry&); void initializeLoopRotatePass(PassRegistry&); void initializeLoopSimplifyPass(PassRegistry&); @@ -177,6 +177,7 @@ void initializeLoopUnrollPass(PassRegistry&); void initializeLoopUnswitchPass(PassRegistry&); void initializeLoopIdiomRecognizePass(PassRegistry&); void initializeLowerAtomicPass(PassRegistry&); +void initializeLowerBitSetsPass(PassRegistry&); void initializeLowerExpectIntrinsicPass(PassRegistry&); void initializeLowerIntrinsicsPass(PassRegistry&); void initializeLowerInvokePass(PassRegistry&); @@ -199,11 +200,13 @@ void initializeMachineTraceMetricsPass(PassRegistry&); void initializeMachineVerifierPassPass(PassRegistry&); void initializeMemCpyOptPass(PassRegistry&); void initializeMemDepPrinterPass(PassRegistry&); +void initializeMemDerefPrinterPass(PassRegistry&); void initializeMemoryDependenceAnalysisPass(PassRegistry&); void initializeMergedLoadStoreMotionPass(PassRegistry &); void initializeMetaRenamerPass(PassRegistry&); void initializeMergeFunctionsPass(PassRegistry&); void initializeModuleDebugInfoPrinterPass(PassRegistry&); +void initializeNaryReassociatePass(PassRegistry&); void initializeNoAAPass(PassRegistry&); void initializeObjCARCAliasAnalysisPass(PassRegistry&); void initializeObjCARCAPElimPass(PassRegistry&); @@ -237,22 +240,27 @@ void initializeRegionOnlyPrinterPass(PassRegistry&); void initializeRegionOnlyViewerPass(PassRegistry&); void initializeRegionPrinterPass(PassRegistry&); void initializeRegionViewerPass(PassRegistry&); +void initializeRewriteStatepointsForGCPass(PassRegistry&); void initializeSCCPPass(PassRegistry&); void initializeSROAPass(PassRegistry&); void initializeSROA_DTPass(PassRegistry&); void initializeSROA_SSAUpPass(PassRegistry&); void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); void initializeScalarEvolutionPass(PassRegistry&); +void initializeShrinkWrapPass(PassRegistry &); void initializeSimpleInlinerPass(PassRegistry&); +void initializeShadowStackGCLoweringPass(PassRegistry&); void initializeRegisterCoalescerPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); void initializeSinkingPass(PassRegistry&); void initializeSeparateConstOffsetFromGEPPass(PassRegistry &); void initializeSlotIndexesPass(PassRegistry&); void initializeSpillPlacementPass(PassRegistry&); +void initializeSpeculativeExecutionPass(PassRegistry&); void initializeStackProtectorPass(PassRegistry&); void initializeStackColoringPass(PassRegistry&); void initializeStackSlotColoringPass(PassRegistry&); +void initializeStraightLineStrengthReducePass(PassRegistry &); void initializeStripDeadDebugInfoPass(PassRegistry&); void initializeStripDeadPrototypesPassPass(PassRegistry&); void initializeStripDebugDeclarePass(PassRegistry&); @@ -261,11 +269,8 @@ void initializeStripSymbolsPass(PassRegistry&); void initializeTailCallElimPass(PassRegistry&); void initializeTailDuplicatePassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); -void initializeDataLayoutPassPass(PassRegistry &); -void initializeTargetTransformInfoAnalysisGroup(PassRegistry&); -void initializeFunctionTargetTransformInfoPass(PassRegistry &); -void initializeNoTTIPass(PassRegistry&); -void initializeTargetLibraryInfoPass(PassRegistry&); +void initializeTargetTransformInfoWrapperPassPass(PassRegistry &); +void initializeTargetLibraryInfoWrapperPassPass(PassRegistry &); void initializeAssumptionCacheTrackerPass(PassRegistry &); void initializeTwoAddressInstructionPassPass(PassRegistry&); void initializeTypeBasedAliasAnalysisPass(PassRegistry&); @@ -279,6 +284,7 @@ void initializeVirtRegRewriterPass(PassRegistry&); void initializeInstSimplifierPass(PassRegistry&); void initializeUnpackMachineBundlesPass(PassRegistry&); void initializeFinalizeMachineBundlesPass(PassRegistry&); +void initializeLoopAccessAnalysisPass(PassRegistry&); void initializeLoopVectorizePass(PassRegistry&); void initializeSLPVectorizerPass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); @@ -287,6 +293,12 @@ void initializeStackMapLivenessPass(PassRegistry&); void initializeMachineCombinerPass(PassRegistry &); void initializeLoadCombinePass(PassRegistry&); void initializeRewriteSymbolsPass(PassRegistry&); +void initializeWinEHPreparePass(PassRegistry&); +void initializePlaceBackedgeSafepointsImplPass(PassRegistry&); +void initializePlaceSafepointsPass(PassRegistry&); +void initializeDwarfEHPreparePass(PassRegistry&); +void initializeFloat2IntPass(PassRegistry&); +void initializeLoopDistributePass(PassRegistry&); } #endif diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index 0c9ce4a54f02..3b4be81b223c 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -53,6 +53,7 @@ namespace llvm { class TargetLibraryInfo; class TargetMachine; class raw_ostream; + class raw_pwrite_stream; //===----------------------------------------------------------------------===// /// C++ class which implements the opaque lto_code_gen_t type. @@ -67,12 +68,19 @@ struct LTOCodeGenerator { // Merge given module, return true on success. bool addModule(struct LTOModule *); + // Set the destination module. + void setModule(struct LTOModule *); + void setTargetOptions(TargetOptions options); void setDebugInfo(lto_debug_model); void setCodePICModel(lto_codegen_model); void setCpu(const char *mCpu) { MCpu = mCpu; } void setAttr(const char *mAttr) { MAttr = mAttr; } + void setOptLevel(unsigned optLevel) { OptLevel = optLevel; } + + void setShouldInternalize(bool Value) { ShouldInternalize = Value; } + void setShouldEmbedUselists(bool Value) { ShouldEmbedUselists = Value; } void addMustPreserveSymbol(const char *sym) { MustPreserveSymbols[sym] = 1; } @@ -99,7 +107,6 @@ struct LTOCodeGenerator { // Do not try to remove the object file in LTOCodeGenerator's destructor // as we don't who (LTOCodeGenerator or the obj file) will last longer. bool compile_to_file(const char **name, - bool disableOpt, bool disableInline, bool disableGVNLoadPRE, bool disableVectorization, @@ -111,12 +118,22 @@ struct LTOCodeGenerator { // caller. This function should delete intermediate object file once its content // is brought to memory. Return NULL if the compilation was not successful. const void *compile(size_t *length, - bool disableOpt, bool disableInline, bool disableGVNLoadPRE, bool disableVectorization, std::string &errMsg); + // Optimizes the merged module. Returns true on success. + bool optimize(bool disableInline, + bool disableGVNLoadPRE, + bool disableVectorization, + std::string &errMsg); + + // Compiles the merged optimized module into a single object file. It brings + // the object to a buffer, and returns the buffer to the caller. Return NULL + // if the compilation was not successful. + const void *compileOptimized(size_t *length, std::string &errMsg); + void setDiagnosticHandler(lto_diagnostic_handler_t, void *); LLVMContext &getContext() { return Context; } @@ -124,9 +141,8 @@ struct LTOCodeGenerator { private: void initializeLTOPasses(); - bool generateObjectFile(raw_ostream &out, bool disableOpt, bool disableInline, - bool disableGVNLoadPRE, bool disableVectorization, - std::string &errMsg); + bool compileOptimized(raw_pwrite_stream &out, std::string &errMsg); + bool compileOptimizedToFile(const char **name, std::string &errMsg); void applyScopeRestrictions(); void applyRestriction(GlobalValue &GV, ArrayRef<StringRef> Libcalls, std::vector<const char *> &MustPreserveList, @@ -140,14 +156,14 @@ private: typedef StringMap<uint8_t> StringSet; - void initialize(); + void destroyMergedModule(); std::unique_ptr<LLVMContext> OwnedContext; LLVMContext &Context; Linker IRLinker; - TargetMachine *TargetMach; - bool EmitDwarfDebugInfo; - bool ScopeRestrictionsDone; - lto_codegen_model CodeModel; + TargetMachine *TargetMach = nullptr; + bool EmitDwarfDebugInfo = false; + bool ScopeRestrictionsDone = false; + lto_codegen_model CodeModel = LTO_CODEGEN_PIC_MODEL_DEFAULT; StringSet MustPreserveSymbols; StringSet AsmUndefinedRefs; std::unique_ptr<MemoryBuffer> NativeObjectFile; @@ -156,8 +172,12 @@ private: std::string MAttr; std::string NativeObjectPath; TargetOptions Options; - lto_diagnostic_handler_t DiagHandler; - void *DiagContext; + unsigned OptLevel = 2; + lto_diagnostic_handler_t DiagHandler = nullptr; + void *DiagContext = nullptr; + LTOModule *OwnedModule = nullptr; + bool ShouldInternalize = true; + bool ShouldEmbedUselists = false; }; } #endif diff --git a/include/llvm/LineEditor/LineEditor.h b/include/llvm/LineEditor/LineEditor.h index 1a9a69106032..bb106f87ca48 100644 --- a/include/llvm/LineEditor/LineEditor.h +++ b/include/llvm/LineEditor/LineEditor.h @@ -119,7 +119,7 @@ private: }; struct ListCompleterConcept : CompleterConcept { - ~ListCompleterConcept(); + ~ListCompleterConcept() override; CompletionAction complete(StringRef Buffer, size_t Pos) const override; static std::string getCommonPrefix(const std::vector<Completion> &Comps); virtual std::vector<Completion> getCompletions(StringRef Buffer, diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 2e8feab6d29d..bf21678b71cb 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -15,6 +15,7 @@ #ifndef LLVM_LINKALLPASSES_H #define LLVM_LINKALLPASSES_H +#include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/CallPrinter.h" #include "llvm/Analysis/DomPrinter.h" @@ -35,6 +36,7 @@ #include "llvm/Transforms/Utils/SymbolRewriter.h" #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" #include "llvm/Transforms/Vectorize.h" +#include "llvm/Support/Valgrind.h" #include <cstdlib> namespace { @@ -49,6 +51,7 @@ namespace { (void) llvm::createAAEvalPass(); (void) llvm::createAggressiveDCEPass(); + (void) llvm::createBitTrackingDCEPass(); (void) llvm::createAliasAnalysisCounterPass(); (void) llvm::createAliasDebugger(); (void) llvm::createArgumentPromotionPass(); @@ -73,6 +76,7 @@ namespace { (void) llvm::createDeadInstEliminationPass(); (void) llvm::createDeadStoreEliminationPass(); (void) llvm::createDependenceAnalysisPass(); + (void) llvm::createDivergenceAnalysisPass(); (void) llvm::createDomOnlyPrinterPass(); (void) llvm::createDomPrinterPass(); (void) llvm::createDomOnlyViewerPass(); @@ -86,15 +90,15 @@ namespace { (void) llvm::createGlobalsModRefPass(); (void) llvm::createIPConstantPropagationPass(); (void) llvm::createIPSCCPPass(); + (void) llvm::createInductiveRangeCheckEliminationPass(); (void) llvm::createIndVarSimplifyPass(); (void) llvm::createInstructionCombiningPass(); (void) llvm::createInternalizePass(); - (void) llvm::createJumpInstrTableInfoPass(); - (void) llvm::createJumpInstrTablesPass(); (void) llvm::createLCSSAPass(); (void) llvm::createLICMPass(); (void) llvm::createLazyValueInfoPass(); (void) llvm::createLoopExtractorPass(); + (void)llvm::createLoopInterchangePass(); (void) llvm::createLoopSimplifyPass(); (void) llvm::createLoopStrengthReducePass(); (void) llvm::createLoopRerollPass(); @@ -105,6 +109,7 @@ namespace { (void) llvm::createLowerExpectIntrinsicPass(); (void) llvm::createLowerInvokePass(); (void) llvm::createLowerSwitchPass(); + (void) llvm::createNaryReassociatePass(); (void) llvm::createNoAAPass(); (void) llvm::createObjCARCAliasAnalysisPass(); (void) llvm::createObjCARCAPElimPass(); @@ -165,7 +170,11 @@ namespace { (void) llvm::createPartiallyInlineLibCallsPass(); (void) llvm::createScalarizerPass(); (void) llvm::createSeparateConstOffsetFromGEPPass(); + (void) llvm::createSpeculativeExecutionPass(); (void) llvm::createRewriteSymbolsPass(); + (void) llvm::createStraightLineStrengthReducePass(); + (void) llvm::createMemDerefPrinter(); + (void) llvm::createFloat2IntPass(); (void)new llvm::IntervalPartition(); (void)new llvm::ScalarEvolution(); @@ -174,6 +183,8 @@ namespace { ((llvm::RegionPass*)nullptr)->runOnRegion((llvm::Region*)nullptr, RGM); llvm::AliasSetTracker X(*(llvm::AliasAnalysis*)nullptr); X.add(nullptr, 0, llvm::AAMDNodes()); // for -print-alias-sets + (void) llvm::AreStatisticsEnabled(); + (void) llvm::sys::RunningOnValgrind(); } } ForcePassLinking; // Force link by creating a global definition. } diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h index 9c3ecea590bd..c43b90e9cd26 100644 --- a/include/llvm/Linker/Linker.h +++ b/include/llvm/Linker/Linker.h @@ -54,6 +54,7 @@ public: NonOpaqueStructTypeSet NonOpaqueStructTypes; void addNonOpaque(StructType *Ty); + void switchToNonOpaque(StructType *Ty); void addOpaque(StructType *Ty); StructType *findNonOpaque(ArrayRef<Type *> ETypes, bool IsPacked); bool hasType(StructType *Ty); @@ -67,8 +68,13 @@ public: void deleteModule(); /// \brief Link \p Src into the composite. The source is destroyed. + /// Passing OverrideSymbols as true will have symbols from Src + /// shadow those in the Dest. /// Returns true on error. - bool linkInModule(Module *Src); + bool linkInModule(Module *Src, bool OverrideSymbols = false); + + /// \brief Set the composite to the passed-in module. + void setModule(Module *Dst); static bool LinkModules(Module *Dest, Module *Src, DiagnosticHandlerFunction DiagnosticHandler); diff --git a/include/llvm/MC/ConstantPools.h b/include/llvm/MC/ConstantPools.h index 1fc0332f63c2..9aa4663ba0fc 100644 --- a/include/llvm/MC/ConstantPools.h +++ b/include/llvm/MC/ConstantPools.h @@ -73,21 +73,18 @@ class AssemblerConstantPools { // sections in a stable order to ensure that we have print the // constant pools in a deterministic order when printing an assembly // file. - typedef MapVector<const MCSection *, ConstantPool> ConstantPoolMapTy; + typedef MapVector<MCSection *, ConstantPool> ConstantPoolMapTy; ConstantPoolMapTy ConstantPools; public: - AssemblerConstantPools() {} - ~AssemblerConstantPools() {} - void emitAll(MCStreamer &Streamer); void emitForCurrentSection(MCStreamer &Streamer); const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr, unsigned Size); private: - ConstantPool *getConstantPool(const MCSection *Section); - ConstantPool &getOrCreateConstantPool(const MCSection *Section); + ConstantPool *getConstantPool(MCSection *Section); + ConstantPool &getOrCreateConstantPool(MCSection *Section); }; } // end namespace llvm diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index a6d41392724e..c0a95d48e370 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -30,10 +30,10 @@ class MCSection; class MCValue; class raw_ostream; -/// MCAsmBackend - Generic interface to target specific assembler backends. +/// Generic interface to target specific assembler backends. class MCAsmBackend { - MCAsmBackend(const MCAsmBackend &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmBackend &) LLVM_DELETED_FUNCTION; + MCAsmBackend(const MCAsmBackend &) = delete; + void operator=(const MCAsmBackend &) = delete; protected: // Can only create subclasses. MCAsmBackend(); @@ -46,70 +46,62 @@ public: /// lifetime management virtual void reset() {} - /// 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; + /// Create a new MCObjectWriter instance for use by the assembler backend to + /// emit the final object file. + virtual MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const = 0; - /// createELFObjectTargetWriter - Create a new ELFObjectTargetWriter to enable - /// non-standard ELFObjectWriters. + /// Create a new ELFObjectTargetWriter to enable non-standard + /// ELFObjectWriters. virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const { llvm_unreachable("createELFObjectTargetWriter is not supported by asm " "backend"); } - /// hasDataInCodeSupport - Check whether this target implements data-in-code - /// markers. If not, data region directives will be ignored. + /// Check whether this target implements data-in-code markers. If not, data + /// region directives will be ignored. bool hasDataInCodeSupport() const { return HasDataInCodeSupport; } - /// doesSectionRequireSymbols - Check whether the given section requires that - /// all symbols (even temporaries) have symbol table entries. - virtual bool doesSectionRequireSymbols(const MCSection &Section) const { - return false; - } - - /// @name Target Fixup Interfaces + /// \name Target Fixup Interfaces /// @{ - /// getNumFixupKinds - Get the number of target specific fixup kinds. + /// Get the number of target specific fixup kinds. virtual unsigned getNumFixupKinds() const = 0; - /// getFixupKindInfo - Get information on a fixup kind. + /// Get information on a fixup kind. virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const; - /// processFixupValue - Target hook to adjust the literal value of a fixup - /// if necessary. IsResolved signals whether the caller believes a relocation - /// is needed; the target can modify the value. The default does nothing. + /// Target hook to adjust the literal value of a fixup if necessary. + /// IsResolved signals whether the caller believes a relocation is needed; the + /// target can modify the value. The default does nothing. virtual void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, const MCValue &Target, uint64_t &Value, bool &IsResolved) {} - /// applyFixup - Apply the \p Value for given \p Fixup into the provided - /// data fragment, at the offset specified by the fixup and following the - /// fixup kind as appropriate. + /// Apply the \p Value for given \p 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, char *Data, unsigned DataSize, uint64_t Value, bool IsPCRel) const = 0; /// @} - /// @name Target Relaxation Interfaces + /// \name Target Relaxation Interfaces /// @{ - /// mayNeedRelaxation - Check whether the given instruction may need - /// relaxation. + /// Check whether the given instruction may need relaxation. /// /// \param Inst - The instruction to test. virtual bool mayNeedRelaxation(const MCInst &Inst) const = 0; - /// fixupNeedsRelaxation - Target specific predicate for whether a given - /// fixup requires the associated instruction to be relaxed. + /// Target specific predicate for whether a given fixup requires the + /// associated instruction to be relaxed. virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const = 0; - /// RelaxInstruction - Relax the instruction in the given fragment to the next - /// wider instruction. + /// Relax the instruction in the given fragment to the next wider instruction. /// /// \param Inst The instruction to relax, which may be the same as the /// output. @@ -118,22 +110,19 @@ public: /// @} - /// getMinimumNopSize - Returns the minimum size of a nop in bytes on this - /// target. The assembler will use this to emit excess padding in situations - /// where the padding required for simple alignment would be less than the - /// minimum nop size. + /// Returns the minimum size of a nop in bytes on this target. The assembler + /// will use this to emit excess padding in situations where the padding + /// required for simple alignment would be less than the minimum nop size. /// virtual unsigned getMinimumNopSize() const { return 1; } - /// 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. + /// 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. + /// Handle any target-specific assembler flags. By default, do nothing. virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {} /// \brief Generate the compact unwind encoding for the CFI instructions. diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index a750a0fd5cef..0335f3188fc3 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -18,7 +18,6 @@ #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MachineLocation.h" #include <cassert> #include <vector> @@ -37,17 +36,17 @@ enum class EncodingType { ARM, /// Windows NT (Windows on ARM) CE, /// Windows CE ARM, PowerPC, SH3, SH4 Itanium, /// Windows x64, Windows Itanium (IA-64) + X86, /// Windows x86, uses no CFI, just EH tables MIPS = Alpha, }; } enum class ExceptionHandling { - None, /// No exception support - DwarfCFI, /// DWARF-like instruction based exceptions - SjLj, /// setjmp/longjmp based exceptions - ARM, /// ARM EHABI - ItaniumWinEH, /// Itanium EH built on Windows unwind info (.pdata and .xdata) - MSVC, /// MSVC compatible exception handling + None, /// No exception support + DwarfCFI, /// DWARF-like instruction based exceptions + SjLj, /// setjmp/longjmp based exceptions + ARM, /// ARM EHABI + WinEH, /// Windows Exception Handling }; namespace LCOMM { @@ -119,6 +118,9 @@ protected: // Print the EH begin symbol with an assignment. Defaults to false. bool UseAssignmentForEHBegin; + // Do we need to create a local symbol for .size? + bool NeedsLocalForSize; + /// This prefix is used for globals like constant pool entries that are /// completely private to the .s file and should not have names in the .o /// file. Defaults to "L" @@ -226,7 +228,7 @@ protected: /// True if the expression /// .long f - g - /// uses an relocation but it can be supressed by writting + /// uses a relocation but it can be suppressed by writing /// a = f - g /// .long a bool SetDirectiveSuppressesReloc; @@ -254,6 +256,10 @@ protected: /// argument and how it is interpreted. Defaults to NoAlignment. LCOMM::LCOMMType LCOMMDirectiveAlignmentType; + // True if the target allows .align directives on functions. This is true for + // most targets, so defaults to true. + bool HasFunctionAlignment; + /// True if the target has .type and .size directives, this is true for most /// ELF targets. Defaults to true. bool HasDotTypeDotSizeDirective; @@ -333,7 +339,7 @@ protected: std::vector<MCCFIInstruction> InitialFrameState; - //===--- Integrated Assembler State ----------------------------------===// + //===--- Integrated Assembler Information ----------------------------===// /// Should we use the integrated assembler? /// The integrated assembler should be enabled by default (by the @@ -345,6 +351,10 @@ protected: /// Compress DWARF debug sections. Defaults to false. bool CompressDebugSections; + /// True if the integrated assembler should interpret 'a >> b' constant + /// expressions as logical rather than arithmetic. + bool UseLogicalShr; + public: explicit MCAsmInfo(); virtual ~MCAsmInfo(); @@ -378,7 +388,7 @@ public: /// Targets can implement this method to specify a section to switch to if the /// translation unit doesn't have any trampolines that require an executable /// stack. - virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const { + virtual MCSection *getNonexecutableStackSection(MCContext &Ctx) const { return nullptr; } @@ -428,6 +438,7 @@ public: const char *getLabelSuffix() const { return LabelSuffix; } bool useAssignmentForEHBegin() const { return UseAssignmentForEHBegin; } + bool needsLocalForSize() const { return NeedsLocalForSize; } const char *getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; } const char *getPrivateLabelPrefix() const { return PrivateLabelPrefix; } bool hasLinkerPrivateGlobalPrefix() const { @@ -464,6 +475,7 @@ public: LCOMM::LCOMMType getLCOMMDirectiveAlignmentType() const { return LCOMMDirectiveAlignmentType; } + bool hasFunctionAlignment() const { return HasFunctionAlignment; } bool hasDotTypeDotSizeDirective() const { return HasDotTypeDotSizeDirective; } bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } bool hasIdentDirective() const { return HasIdentDirective; } @@ -490,18 +502,17 @@ public: ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; } WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; } - /// Return true if the exception handling type uses the language-specific data - /// area (LSDA) format specified by the Itanium C++ ABI. - bool usesItaniumLSDAForExceptions() const { + /// Returns true if the exception handling method for the platform uses call + /// frame information to unwind. + bool usesCFIForEH() const { return (ExceptionsType == ExceptionHandling::DwarfCFI || - ExceptionsType == ExceptionHandling::ARM || - // This Windows EH type uses the Itanium LSDA encoding. - ExceptionsType == ExceptionHandling::ItaniumWinEH); + ExceptionsType == ExceptionHandling::ARM || usesWindowsCFI()); } bool usesWindowsCFI() const { - return ExceptionsType == ExceptionHandling::ItaniumWinEH || - ExceptionsType == ExceptionHandling::MSVC; + return ExceptionsType == ExceptionHandling::WinEH && + (WinEHEncodingType != WinEH::EncodingType::Invalid && + WinEHEncodingType != WinEH::EncodingType::X86); } bool doesDwarfUseRelocationsAcrossSections() const { @@ -532,6 +543,8 @@ public: void setCompressDebugSections(bool CompressDebugSections) { this->CompressDebugSections = CompressDebugSections; } + + bool shouldUseLogicalShr() const { return UseLogicalShr; } }; } diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h index 7bd246056eca..7125f5c7ad7a 100644 --- a/include/llvm/MC/MCAsmInfoELF.h +++ b/include/llvm/MC/MCAsmInfoELF.h @@ -15,8 +15,7 @@ namespace llvm { class MCAsmInfoELF : public MCAsmInfo { virtual void anchor(); - const MCSection * - getNonexecutableStackSection(MCContext &Ctx) const override final; + MCSection *getNonexecutableStackSection(MCContext &Ctx) const final; protected: MCAsmInfoELF(); diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index f048e34671db..fb28420e0fa3 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -16,7 +16,7 @@ namespace llvm { class MCAssembler; class MCFragment; -class MCSectionData; +class MCSection; class MCSymbol; class MCSymbolData; @@ -28,20 +28,15 @@ class MCSymbolData; /// efficiently compute the exact address of any symbol in the assembly file, /// even during the relaxation process. class MCAsmLayout { -public: - typedef llvm::SmallVectorImpl<MCSectionData*>::const_iterator const_iterator; - typedef llvm::SmallVectorImpl<MCSectionData*>::iterator iterator; - -private: MCAssembler &Assembler; /// List of sections in layout order. - llvm::SmallVector<MCSectionData*, 16> SectionOrder; + llvm::SmallVector<MCSection *, 16> SectionOrder; /// The last fragment which was laid out, or 0 if nothing has been laid /// out. Fragments are always laid out in order, so all fragments with a /// lower ordinal will be valid. - mutable DenseMap<const MCSectionData*, MCFragment*> LastValidFragment; + mutable DenseMap<const MCSection *, MCFragment *> LastValidFragment; /// \brief Make sure that the layout for the given fragment is valid, lazily /// computing it if necessary. @@ -50,13 +45,8 @@ private: /// \brief Is the layout for this fragment valid? bool isFragmentValid(const MCFragment *F) const; - /// \brief Compute the amount of padding required before this fragment to - /// obey bundling restrictions. - uint64_t computeBundlePadding(const MCFragment *F, - uint64_t FOffset, uint64_t FSize); - public: - MCAsmLayout(MCAssembler &_Assembler); + MCAsmLayout(MCAssembler &Assembler); /// Get the assembler object this is a layout for. MCAssembler &getAssembler() const { return Assembler; } @@ -71,43 +61,41 @@ public: /// been initialized. void layoutFragment(MCFragment *Fragment); - /// @name Section Access (in layout order) + /// \name Section Access (in layout order) /// @{ - llvm::SmallVectorImpl<MCSectionData*> &getSectionOrder() { - return SectionOrder; - } - const llvm::SmallVectorImpl<MCSectionData*> &getSectionOrder() const { + llvm::SmallVectorImpl<MCSection *> &getSectionOrder() { return SectionOrder; } + const llvm::SmallVectorImpl<MCSection *> &getSectionOrder() const { return SectionOrder; } /// @} - /// @name Fragment Layout Data + /// \name Fragment Layout Data /// @{ /// \brief Get the offset of the given fragment inside its containing section. uint64_t getFragmentOffset(const MCFragment *F) const; /// @} - /// @name Utility Functions + /// \name Utility Functions /// @{ /// \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. - uint64_t getSectionAddressSize(const MCSectionData *SD) const; + uint64_t getSectionAddressSize(const MCSection *Sec) const; /// \brief Get the data size of the given section, as emitted to the object /// file. This may include additional padding, or be 0 for virtual sections. - uint64_t getSectionFileSize(const MCSectionData *SD) const; + uint64_t getSectionFileSize(const MCSection *Sec) const; /// \brief Get the offset of the given symbol, as computed in the current /// layout. - /// \result True on success. - bool getSymbolOffset(const MCSymbolData *SD, uint64_t &Val) const; + /// \return True on success. + bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const; /// \brief Variant that reports a fatal error if the offset is not computable. - uint64_t getSymbolOffset(const MCSymbolData *SD) const; + uint64_t getSymbolOffset(const MCSymbol &S) const; /// \brief If this symbol is equivalent to A + Constant, return A. const MCSymbol *getBaseSymbol(const MCSymbol &Symbol) const; diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 681a31728799..593504ce0607 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -11,16 +11,20 @@ #define LLVM_MC_MCASSEMBLER_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCLinkerOptimizationHint.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" #include <algorithm> @@ -36,18 +40,15 @@ class MCExpr; class MCFragment; class MCObjectWriter; class MCSection; -class MCSectionData; class MCSubtargetInfo; -class MCSymbol; -class MCSymbolData; class MCValue; class MCAsmBackend; class MCFragment : public ilist_node<MCFragment> { friend class MCAsmLayout; - MCFragment(const MCFragment&) LLVM_DELETED_FUNCTION; - void operator=(const MCFragment&) LLVM_DELETED_FUNCTION; + MCFragment(const MCFragment &) = delete; + void operator=(const MCFragment &) = delete; public: enum FragmentType { @@ -65,14 +66,14 @@ public: private: FragmentType Kind; - /// Parent - The data for the section this fragment is in. - MCSectionData *Parent; + /// The data for the section this fragment is in. + MCSection *Parent; /// Atom - The atom this fragment is in, as represented by it's defining /// symbol. - MCSymbolData *Atom; + const MCSymbol *Atom; - /// @name Assembler Backend Data + /// \name Assembler Backend Data /// @{ // // FIXME: This could all be kept private to the assembler implementation. @@ -87,7 +88,7 @@ private: /// @} protected: - MCFragment(FragmentType _Kind, MCSectionData *_Parent = nullptr); + MCFragment(FragmentType Kind, MCSection *Parent = nullptr); public: // Only for sentinel. @@ -96,11 +97,11 @@ public: FragmentType getKind() const { return Kind; } - MCSectionData *getParent() const { return Parent; } - void setParent(MCSectionData *Value) { Parent = Value; } + MCSection *getParent() const { return Parent; } + void setParent(MCSection *Value) { Parent = Value; } - MCSymbolData *getAtom() const { return Atom; } - void setAtom(MCSymbolData *Value) { Atom = Value; } + const MCSymbol *getAtom() const { return Atom; } + void setAtom(const MCSymbol *Value) { Atom = Value; } unsigned getLayoutOrder() const { return LayoutOrder; } void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } @@ -111,21 +112,18 @@ public: /// \brief Should this fragment be placed at the end of an aligned bundle? virtual bool alignToBundleEnd() const { return false; } - virtual void setAlignToBundleEnd(bool V) { } + virtual void setAlignToBundleEnd(bool V) {} /// \brief Get the padding size that must be inserted before this fragment. /// Used for bundling. By default, no padding is inserted. /// Note that padding size is restricted to 8 bits. This is an optimization /// to reduce the amount of space used for each fragment. In practice, larger /// padding should never be required. - virtual uint8_t getBundlePadding() const { - return 0; - } + virtual uint8_t getBundlePadding() const { return 0; } /// \brief Set the padding size for this fragment. By default it's a no-op, /// and only some fragments have a meaningful implementation. - virtual void setBundlePadding(uint8_t N) { - } + virtual void setBundlePadding(uint8_t N) {} void dump(); }; @@ -137,33 +135,28 @@ class MCEncodedFragment : public MCFragment { virtual void anchor(); uint8_t BundlePadding; + public: - MCEncodedFragment(MCFragment::FragmentType FType, MCSectionData *SD = nullptr) - : MCFragment(FType, SD), BundlePadding(0) - { - } - virtual ~MCEncodedFragment(); + MCEncodedFragment(MCFragment::FragmentType FType, MCSection *Sec = nullptr) + : MCFragment(FType, Sec), BundlePadding(0) {} + ~MCEncodedFragment() override; virtual SmallVectorImpl<char> &getContents() = 0; virtual const SmallVectorImpl<char> &getContents() const = 0; - uint8_t getBundlePadding() const override { - return BundlePadding; - } + uint8_t getBundlePadding() const override { return BundlePadding; } - void setBundlePadding(uint8_t N) override { - BundlePadding = N; - } + void setBundlePadding(uint8_t N) override { BundlePadding = N; } static bool classof(const MCFragment *F) { MCFragment::FragmentType Kind = F->getKind(); switch (Kind) { - default: - return false; - case MCFragment::FT_Relaxable: - case MCFragment::FT_CompactEncodedInst: - case MCFragment::FT_Data: - return true; + default: + return false; + case MCFragment::FT_Relaxable: + case MCFragment::FT_CompactEncodedInst: + case MCFragment::FT_Data: + return true; } } }; @@ -176,12 +169,10 @@ class MCEncodedFragmentWithFixups : public MCEncodedFragment { public: MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, - MCSectionData *SD = nullptr) - : MCEncodedFragment(FType, SD) - { - } + MCSection *Sec = nullptr) + : MCEncodedFragment(FType, Sec) {} - virtual ~MCEncodedFragmentWithFixups(); + ~MCEncodedFragmentWithFixups() override; typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; @@ -190,7 +181,7 @@ public: virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0; virtual fixup_iterator fixup_begin() = 0; - virtual const_fixup_iterator fixup_begin() const = 0; + virtual const_fixup_iterator fixup_begin() const = 0; virtual fixup_iterator fixup_end() = 0; virtual const_fixup_iterator fixup_end() const = 0; @@ -215,25 +206,18 @@ class MCDataFragment : public MCEncodedFragmentWithFixups { /// Fixups - The list of fixups in this fragment. SmallVector<MCFixup, 4> Fixups; + public: - MCDataFragment(MCSectionData *SD = nullptr) - : MCEncodedFragmentWithFixups(FT_Data, SD), - HasInstructions(false), AlignToBundleEnd(false) - { - } + MCDataFragment(MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups(FT_Data, Sec), HasInstructions(false), + AlignToBundleEnd(false) {} SmallVectorImpl<char> &getContents() override { return Contents; } - const SmallVectorImpl<char> &getContents() const override { - return Contents; - } + const SmallVectorImpl<char> &getContents() const override { return Contents; } - SmallVectorImpl<MCFixup> &getFixups() override { - return Fixups; - } + SmallVectorImpl<MCFixup> &getFixups() override { return Fixups; } - const SmallVectorImpl<MCFixup> &getFixups() const override { - return Fixups; - } + const SmallVectorImpl<MCFixup> &getFixups() const override { return Fixups; } bool hasInstructions() const override { return HasInstructions; } virtual void setHasInstructions(bool V) { HasInstructions = V; } @@ -244,8 +228,8 @@ public: fixup_iterator fixup_begin() override { return Fixups.begin(); } const_fixup_iterator fixup_begin() const override { return Fixups.begin(); } - fixup_iterator fixup_end() override {return Fixups.end();} - const_fixup_iterator fixup_end() const override {return Fixups.end();} + fixup_iterator fixup_end() override { return Fixups.end(); } + const_fixup_iterator fixup_end() const override { return Fixups.end(); } static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Data; @@ -264,15 +248,13 @@ class MCCompactEncodedInstFragment : public MCEncodedFragment { bool AlignToBundleEnd; SmallVector<char, 4> Contents; + public: - MCCompactEncodedInstFragment(MCSectionData *SD = nullptr) - : MCEncodedFragment(FT_CompactEncodedInst, SD), AlignToBundleEnd(false) - { + MCCompactEncodedInstFragment(MCSection *Sec = nullptr) + : MCEncodedFragment(FT_CompactEncodedInst, Sec), AlignToBundleEnd(false) { } - bool hasInstructions() const override { - return true; - } + bool hasInstructions() const override { return true; } SmallVectorImpl<char> &getContents() override { return Contents; } const SmallVectorImpl<char> &getContents() const override { return Contents; } @@ -306,35 +288,29 @@ class MCRelaxableFragment : public MCEncodedFragmentWithFixups { SmallVector<MCFixup, 1> Fixups; public: - MCRelaxableFragment(const MCInst &_Inst, - const MCSubtargetInfo &_STI, - MCSectionData *SD = nullptr) - : MCEncodedFragmentWithFixups(FT_Relaxable, SD), Inst(_Inst), STI(_STI) { - } + MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI, + MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups(FT_Relaxable, Sec), Inst(Inst), STI(STI) {} SmallVectorImpl<char> &getContents() override { return Contents; } const SmallVectorImpl<char> &getContents() const override { return Contents; } const MCInst &getInst() const { return Inst; } - void setInst(const MCInst& Value) { Inst = Value; } + void setInst(const MCInst &Value) { Inst = Value; } const MCSubtargetInfo &getSubtargetInfo() { return STI; } - SmallVectorImpl<MCFixup> &getFixups() override { - return Fixups; - } + SmallVectorImpl<MCFixup> &getFixups() override { return Fixups; } - const SmallVectorImpl<MCFixup> &getFixups() const override { - return Fixups; - } + const SmallVectorImpl<MCFixup> &getFixups() const override { return Fixups; } bool hasInstructions() const override { return true; } fixup_iterator fixup_begin() override { return Fixups.begin(); } const_fixup_iterator fixup_begin() const override { return Fixups.begin(); } - fixup_iterator fixup_end() override {return Fixups.end();} - const_fixup_iterator fixup_end() const override {return Fixups.end();} + fixup_iterator fixup_end() override { return Fixups.end(); } + const_fixup_iterator fixup_end() const override { return Fixups.end(); } static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Relaxable; @@ -363,13 +339,12 @@ class MCAlignFragment : public MCFragment { bool EmitNops : 1; public: - MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, - unsigned _MaxBytesToEmit, MCSectionData *SD = nullptr) - : MCFragment(FT_Align, SD), Alignment(_Alignment), - Value(_Value),ValueSize(_ValueSize), - MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {} + MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize, + unsigned MaxBytesToEmit, MCSection *Sec = nullptr) + : MCFragment(FT_Align, Sec), Alignment(Alignment), Value(Value), + ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit), EmitNops(false) {} - /// @name Accessors + /// \name Accessors /// @{ unsigned getAlignment() const { return Alignment; } @@ -404,15 +379,15 @@ class MCFillFragment : public MCFragment { uint64_t Size; public: - MCFillFragment(int64_t _Value, unsigned _ValueSize, uint64_t _Size, - MCSectionData *SD = nullptr) - : MCFragment(FT_Fill, SD), - Value(_Value), ValueSize(_ValueSize), Size(_Size) { + MCFillFragment(int64_t Value, unsigned ValueSize, uint64_t Size, + MCSection *Sec = nullptr) + : MCFragment(FT_Fill, Sec), Value(Value), ValueSize(ValueSize), + Size(Size) { assert((!ValueSize || (Size % ValueSize) == 0) && "Fill size must be a multiple of the value size!"); } - /// @name Accessors + /// \name Accessors /// @{ int64_t getValue() const { return Value; } @@ -438,12 +413,10 @@ class MCOrgFragment : public MCFragment { int8_t Value; public: - MCOrgFragment(const MCExpr &_Offset, int8_t _Value, - MCSectionData *SD = nullptr) - : MCFragment(FT_Org, SD), - Offset(&_Offset), Value(_Value) {} + MCOrgFragment(const MCExpr &Offset, int8_t Value, MCSection *Sec = nullptr) + : MCFragment(FT_Org, Sec), Offset(&Offset), Value(Value) {} - /// @name Accessors + /// \name Accessors /// @{ const MCExpr &getOffset() const { return *Offset; } @@ -467,13 +440,14 @@ class MCLEBFragment : public MCFragment { bool IsSigned; SmallString<8> Contents; + public: - MCLEBFragment(const MCExpr &Value_, bool IsSigned_, - MCSectionData *SD = nullptr) - : MCFragment(FT_LEB, SD), - Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); } + MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr) + : MCFragment(FT_LEB, Sec), Value(&Value_), IsSigned(IsSigned_) { + Contents.push_back(0); + } - /// @name Accessors + /// \name Accessors /// @{ const MCExpr &getValue() const { return *Value; } @@ -504,12 +478,13 @@ class MCDwarfLineAddrFragment : public MCFragment { SmallString<8> Contents; public: - MCDwarfLineAddrFragment(int64_t _LineDelta, const MCExpr &_AddrDelta, - MCSectionData *SD = nullptr) - : MCFragment(FT_Dwarf, SD), - LineDelta(_LineDelta), AddrDelta(&_AddrDelta) { Contents.push_back(0); } + MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta, + MCSection *Sec = nullptr) + : MCFragment(FT_Dwarf, Sec), LineDelta(LineDelta), AddrDelta(&AddrDelta) { + Contents.push_back(0); + } - /// @name Accessors + /// \name Accessors /// @{ int64_t getLineDelta() const { return LineDelta; } @@ -536,12 +511,12 @@ class MCDwarfCallFrameFragment : public MCFragment { SmallString<8> Contents; public: - MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, - MCSectionData *SD = nullptr) - : MCFragment(FT_DwarfFrame, SD), - AddrDelta(&_AddrDelta) { Contents.push_back(0); } + MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr) + : MCFragment(FT_DwarfFrame, Sec), AddrDelta(&AddrDelta) { + Contents.push_back(0); + } - /// @name Accessors + /// \name Accessors /// @{ const MCExpr &getAddrDelta() const { return *AddrDelta; } @@ -556,265 +531,10 @@ public: } }; -// 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. -class MCSectionData : public ilist_node<MCSectionData> { - friend class MCAsmLayout; - - MCSectionData(const MCSectionData&) LLVM_DELETED_FUNCTION; - void operator=(const MCSectionData&) LLVM_DELETED_FUNCTION; - -public: - typedef iplist<MCFragment> FragmentListType; - - typedef FragmentListType::const_iterator const_iterator; - typedef FragmentListType::iterator iterator; - - typedef FragmentListType::const_reverse_iterator const_reverse_iterator; - typedef FragmentListType::reverse_iterator reverse_iterator; - - /// \brief Express the state of bundle locked groups while emitting code. - enum BundleLockStateType { - NotBundleLocked, - BundleLocked, - BundleLockedAlignToEnd - }; -private: - FragmentListType Fragments; - const MCSection *Section; - - /// Ordinal - The section index in the assemblers section list. - unsigned Ordinal; - - /// LayoutOrder - The index of this section in the layout order. - unsigned LayoutOrder; - - /// Alignment - The maximum alignment seen in this section. - unsigned Alignment; - - /// \brief Keeping track of bundle-locked state. - BundleLockStateType BundleLockState; - - /// \brief Current nesting depth of bundle_lock directives. - unsigned BundleLockNestingDepth; - - /// \brief We've seen a bundle_lock directive but not its first instruction - /// yet. - bool BundleGroupBeforeFirstInst; - - /// @name Assembler Backend Data - /// @{ - // - // FIXME: This could all be kept private to the assembler implementation. - - /// HasInstructions - Whether this section has had instructions emitted into - /// it. - unsigned HasInstructions : 1; - - /// Mapping from subsection number to insertion point for subsection numbers - /// below that number. - SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap; - - /// @} - -public: - // Only for use as sentinel. - MCSectionData(); - MCSectionData(const MCSection &Section, MCAssembler *A = nullptr); - - const MCSection &getSection() const { return *Section; } - - unsigned getAlignment() const { return Alignment; } - void setAlignment(unsigned Value) { Alignment = Value; } - - bool hasInstructions() const { return HasInstructions; } - void setHasInstructions(bool Value) { HasInstructions = Value; } - - unsigned getOrdinal() const { return Ordinal; } - void setOrdinal(unsigned Value) { Ordinal = Value; } - - unsigned getLayoutOrder() const { return LayoutOrder; } - void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } - - /// @name Fragment Access - /// @{ - - const FragmentListType &getFragmentList() const { return Fragments; } - FragmentListType &getFragmentList() { return Fragments; } - - iterator begin() { return Fragments.begin(); } - const_iterator begin() const { return Fragments.begin(); } - - iterator end() { return Fragments.end(); } - const_iterator end() const { return Fragments.end(); } - - reverse_iterator rbegin() { return Fragments.rbegin(); } - const_reverse_iterator rbegin() const { return Fragments.rbegin(); } - - reverse_iterator rend() { return Fragments.rend(); } - const_reverse_iterator rend() const { return Fragments.rend(); } - - size_t size() const { return Fragments.size(); } - - bool empty() const { return Fragments.empty(); } - - iterator getSubsectionInsertionPoint(unsigned Subsection); - - bool isBundleLocked() const { - return BundleLockState != NotBundleLocked; - } - - BundleLockStateType getBundleLockState() const { - return BundleLockState; - } - - void setBundleLockState(BundleLockStateType NewState); - - bool isBundleGroupBeforeFirstInst() const { - return BundleGroupBeforeFirstInst; - } - - void setBundleGroupBeforeFirstInst(bool IsFirst) { - BundleGroupBeforeFirstInst = IsFirst; - } - - void dump(); - - /// @} -}; - -// FIXME: Same concerns as with SectionData. -class MCSymbolData : public ilist_node<MCSymbolData> { - const MCSymbol *Symbol; - - /// Fragment - The fragment this symbol's value is relative to, if any. Also - /// stores if this symbol is visible outside this translation unit (bit 0) or - /// if it is private extern (bit 1). - PointerIntPair<MCFragment *, 2> Fragment; - - union { - /// Offset - The offset to apply to the fragment address to form this - /// symbol's value. - uint64_t Offset; - - /// CommonSize - The size of the symbol, if it is 'common'. - uint64_t CommonSize; - }; - - /// SymbolSize - An expression describing how to calculate the size of - /// a symbol. If a symbol has no size this field will be NULL. - const MCExpr *SymbolSize; - - /// CommonAlign - The alignment of the symbol, if it is 'common', or -1. - // - // FIXME: Pack this in with other fields? - unsigned CommonAlign; - - /// Flags - The Flags field is used by object file implementations to store - /// additional per symbol information which is not easily classified. - uint32_t Flags; - - /// Index - Index field, for use by the object file implementation. - uint64_t Index; - -public: - // Only for use as sentinel. - MCSymbolData(); - MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset, - MCAssembler *A = nullptr); - - /// @name Accessors - /// @{ - - const MCSymbol &getSymbol() const { return *Symbol; } - - MCFragment *getFragment() const { return Fragment.getPointer(); } - void setFragment(MCFragment *Value) { Fragment.setPointer(Value); } - - uint64_t getOffset() const { - assert(!isCommon()); - return Offset; - } - void setOffset(uint64_t Value) { - assert(!isCommon()); - Offset = Value; - } - - /// @} - /// @name Symbol Attributes - /// @{ - - bool isExternal() const { return Fragment.getInt() & 1; } - void setExternal(bool Value) { - Fragment.setInt((Fragment.getInt() & ~1) | unsigned(Value)); - } - - bool isPrivateExtern() const { return Fragment.getInt() & 2; } - void setPrivateExtern(bool Value) { - Fragment.setInt((Fragment.getInt() & ~2) | (unsigned(Value) << 1)); - } - - /// isCommon - Is this a 'common' symbol. - bool isCommon() const { return CommonAlign != -1U; } - - /// setCommon - Mark this symbol as being 'common'. - /// - /// \param Size - The size of the symbol. - /// \param Align - The alignment of the symbol. - void setCommon(uint64_t Size, unsigned Align) { - assert(getOffset() == 0); - CommonSize = Size; - CommonAlign = Align; - } - - /// getCommonSize - Return the size of a 'common' symbol. - uint64_t getCommonSize() const { - assert(isCommon() && "Not a 'common' symbol!"); - return CommonSize; - } - - void setSize(const MCExpr *SS) { - SymbolSize = SS; - } - - const MCExpr *getSize() const { - return SymbolSize; - } - - - /// getCommonAlignment - Return the alignment of a 'common' symbol. - unsigned getCommonAlignment() const { - assert(isCommon() && "Not a 'common' symbol!"); - return CommonAlign; - } - - /// getFlags - Get the (implementation defined) symbol flags. - uint32_t getFlags() const { return Flags; } - - /// setFlags - Set the (implementation defined) symbol flags. - void setFlags(uint32_t Value) { Flags = Value; } - - /// modifyFlags - Modify the flags via a mask - void modifyFlags(uint32_t Value, uint32_t Mask) { - Flags = (Flags & ~Mask) | Value; - } - - /// getIndex - Get the (implementation defined) index. - uint64_t getIndex() const { return Index; } - - /// setIndex - Set the (implementation defined) index. - void setIndex(uint64_t Value) { Index = Value; } - - /// @} - - void dump() const; -}; - // FIXME: This really doesn't belong here. See comments below. struct IndirectSymbolData { MCSymbol *Symbol; - MCSectionData *SectionData; + MCSection *Section; }; // FIXME: Ditto this. Purely so the Streamer and the ObjectWriter can talk @@ -831,14 +551,15 @@ class MCAssembler { friend class MCAsmLayout; public: - typedef iplist<MCSectionData> SectionDataListType; - typedef iplist<MCSymbolData> SymbolDataListType; + typedef SetVector<MCSection *> SectionListType; + typedef std::vector<const MCSymbol *> SymbolDataListType; - typedef SectionDataListType::const_iterator const_iterator; - typedef SectionDataListType::iterator iterator; + typedef pointee_iterator<SectionListType::const_iterator> const_iterator; + typedef pointee_iterator<SectionListType::iterator> iterator; - typedef SymbolDataListType::const_iterator const_symbol_iterator; - typedef SymbolDataListType::iterator symbol_iterator; + typedef pointee_iterator<SymbolDataListType::const_iterator> + const_symbol_iterator; + typedef pointee_iterator<SymbolDataListType::iterator> symbol_iterator; typedef iterator_range<symbol_iterator> symbol_range; typedef iterator_range<const_symbol_iterator> const_symbol_range; @@ -847,11 +568,11 @@ public: typedef FileNameVectorType::const_iterator const_file_name_iterator; typedef std::vector<IndirectSymbolData>::const_iterator - const_indirect_symbol_iterator; + const_indirect_symbol_iterator; typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator; typedef std::vector<DataRegionData>::const_iterator - const_data_region_iterator; + const_data_region_iterator; typedef std::vector<DataRegionData>::iterator data_region_iterator; /// MachO specific deployment target version info. @@ -863,9 +584,10 @@ public: unsigned Minor; unsigned Update; } VersionMinInfoType; + private: - MCAssembler(const MCAssembler&) LLVM_DELETED_FUNCTION; - void operator=(const MCAssembler&) LLVM_DELETED_FUNCTION; + MCAssembler(const MCAssembler &) = delete; + void operator=(const MCAssembler &) = delete; MCContext &Context; @@ -877,26 +599,18 @@ private: raw_ostream &OS; - iplist<MCSectionData> Sections; + SectionListType Sections; - iplist<MCSymbolData> Symbols; + SymbolDataListType Symbols; - /// The map of sections to their associated assembler backend data. - // - // FIXME: Avoid this indirection? - DenseMap<const MCSection*, MCSectionData*> SectionMap; - - /// The map of symbols to their associated assembler backend data. - // - // FIXME: Avoid this indirection? - DenseMap<const MCSymbol*, MCSymbolData*> SymbolMap; + DenseSet<const MCSymbol *> LocalsUsedInReloc; std::vector<IndirectSymbolData> IndirectSymbols; std::vector<DataRegionData> DataRegions; /// The list of linker options to propagate into the object file. - std::vector<std::vector<std::string> > LinkerOptions; + std::vector<std::vector<std::string>> LinkerOptions; /// List of declared file names FileNameVectorType FileNames; @@ -908,7 +622,7 @@ private: // here. Maybe when the relocation stuff moves to target specific, // this can go with it? The streamer would need some target specific // refactoring too. - mutable SmallPtrSet<const MCSymbol*, 64> ThumbFuncs; + mutable SmallPtrSet<const MCSymbol *, 64> ThumbFuncs; /// \brief The bundle alignment size currently set in the assembler. /// @@ -930,6 +644,7 @@ private: MCLOHContainer LOHContainer; VersionMinInfoType VersionMinInfo; + private: /// Evaluate a fixup to a relocatable expression and the value which should be /// placed into the fixup. @@ -944,9 +659,9 @@ private: /// \return Whether the fixup value was fully resolved. This is true if the /// \p Value result is fixed, otherwise the value may change due to /// relocation. - bool evaluateFixup(const MCAsmLayout &Layout, - const MCFixup &Fixup, const MCFragment *DF, - MCValue &Target, uint64_t &Value) const; + 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). @@ -963,7 +678,7 @@ private: /// \brief Perform one layout iteration of the given section and return true /// if any offsets were adjusted. - bool layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD); + bool layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec); bool relaxInstruction(MCAsmLayout &Layout, MCRelaxableFragment &IF); @@ -980,6 +695,9 @@ private: MCFragment &F, const MCFixup &Fixup); public: + void addLocalUsedInReloc(const MCSymbol &Sym); + bool isLocalUsedInReloc(const MCSymbol &Sym) const; + /// Compute the effective fragment size assuming it is laid out at the given /// \p SectionAddress and \p FragmentOffset. uint64_t computeFragmentSize(const MCAsmLayout &Layout, @@ -987,7 +705,7 @@ public: /// 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; + const MCSymbol *getAtom(const MCSymbol &S) const; /// Check whether a particular symbol is visible to the linker and is required /// in the symbol table, or whether it can be discarded by the assembler. This @@ -996,7 +714,7 @@ public: bool isSymbolLinkerVisible(const MCSymbol &SD) const; /// Emit the section contents using the given object writer. - void writeSectionData(const MCSectionData *Section, + void writeSectionData(const MCSection *Section, const MCAsmLayout &Layout) const; /// Check whether a given symbol has been flagged with .thumb_func. @@ -1006,8 +724,8 @@ public: void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); } /// ELF e_header flags - unsigned getELFHeaderEFlags() const {return ELFHeaderEFlags;} - void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags;} + unsigned getELFHeaderEFlags() const { return ELFHeaderEFlags; } + void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags; } /// MachO deployment target version information. const VersionMinInfoType &getVersionMinInfo() const { return VersionMinInfo; } @@ -1051,36 +769,25 @@ public: void Finish(); // FIXME: This does not belong here. - bool getSubsectionsViaSymbols() const { - return SubsectionsViaSymbols; - } - void setSubsectionsViaSymbols(bool Value) { - SubsectionsViaSymbols = Value; - } + bool getSubsectionsViaSymbols() const { return SubsectionsViaSymbols; } + void setSubsectionsViaSymbols(bool Value) { SubsectionsViaSymbols = Value; } bool getRelaxAll() const { return RelaxAll; } void setRelaxAll(bool Value) { RelaxAll = Value; } - bool isBundlingEnabled() const { - return BundleAlignSize != 0; - } + bool isBundlingEnabled() const { return BundleAlignSize != 0; } - unsigned getBundleAlignSize() const { - return BundleAlignSize; - } + unsigned getBundleAlignSize() const { return BundleAlignSize; } void setBundleAlignSize(unsigned Size) { - assert((Size == 0 || !(Size & (Size - 1))) && + assert((Size == 0 || !(Size & (Size - 1))) && "Expect a power-of-two bundle align size"); BundleAlignSize = Size; } - /// @name Section List Access + /// \name Section List Access /// @{ - const SectionDataListType &getSectionList() const { return Sections; } - SectionDataListType &getSectionList() { return Sections; } - iterator begin() { return Sections.begin(); } const_iterator begin() const { return Sections.begin(); } @@ -1090,12 +797,8 @@ public: size_t size() const { return Sections.size(); } /// @} - /// @name Symbol List Access + /// \name Symbol List Access /// @{ - - const SymbolDataListType &getSymbolList() const { return Symbols; } - SymbolDataListType &getSymbolList() { return Symbols; } - symbol_iterator symbol_begin() { return Symbols.begin(); } const_symbol_iterator symbol_begin() const { return Symbols.begin(); } @@ -1103,12 +806,14 @@ public: const_symbol_iterator symbol_end() const { return Symbols.end(); } symbol_range symbols() { return make_range(symbol_begin(), symbol_end()); } - const_symbol_range symbols() const { return make_range(symbol_begin(), symbol_end()); } + const_symbol_range symbols() const { + return make_range(symbol_begin(), symbol_end()); + } size_t symbol_size() const { return Symbols.size(); } /// @} - /// @name Indirect Symbol List Access + /// \name Indirect Symbol List Access /// @{ // FIXME: This is a total hack, this should not be here. Once things are @@ -1135,34 +840,28 @@ public: size_t indirect_symbol_size() const { return IndirectSymbols.size(); } /// @} - /// @name Linker Option List Access + /// \name Linker Option List Access /// @{ - std::vector<std::vector<std::string> > &getLinkerOptions() { + std::vector<std::vector<std::string>> &getLinkerOptions() { return LinkerOptions; } /// @} - /// @name Data Region List Access + /// \name Data Region List Access /// @{ // FIXME: This is a total hack, this should not be here. Once things are // factored so that the streamer has direct access to the .o writer, it can // disappear. - std::vector<DataRegionData> &getDataRegions() { - return DataRegions; - } + std::vector<DataRegionData> &getDataRegions() { return DataRegions; } - data_region_iterator data_region_begin() { - return DataRegions.begin(); - } + data_region_iterator data_region_begin() { return DataRegions.begin(); } const_data_region_iterator data_region_begin() const { return DataRegions.begin(); } - data_region_iterator data_region_end() { - return DataRegions.end(); - } + data_region_iterator data_region_end() { return DataRegions.end(); } const_data_region_iterator data_region_end() const { return DataRegions.end(); } @@ -1170,42 +869,23 @@ public: size_t data_region_size() const { return DataRegions.size(); } /// @} - /// @name Data Region List Access + /// \name Data Region List Access /// @{ // FIXME: This is a total hack, this should not be here. Once things are // factored so that the streamer has direct access to the .o writer, it can // disappear. - MCLOHContainer & getLOHContainer() { - return LOHContainer; - } - const MCLOHContainer & getLOHContainer() const { + MCLOHContainer &getLOHContainer() { return LOHContainer; } + const MCLOHContainer &getLOHContainer() const { return const_cast<MCAssembler *>(this)->getLOHContainer(); } /// @} - /// @name Backend Data Access + /// \name Backend Data Access /// @{ - MCSectionData &getSectionData(const MCSection &Section) const { - MCSectionData *Entry = SectionMap.lookup(&Section); - assert(Entry && "Missing section data!"); - return *Entry; - } - - MCSectionData &getOrCreateSectionData(const MCSection &Section, - bool *Created = nullptr) { - MCSectionData *&Entry = SectionMap[&Section]; + bool registerSection(MCSection &Section) { return Sections.insert(&Section); } - if (Created) *Created = !Entry; - if (!Entry) - Entry = new MCSectionData(Section, this); - - return *Entry; - } - - bool hasSymbolData(const MCSymbol &Symbol) const { - return SymbolMap.lookup(&Symbol) != nullptr; - } + bool hasSymbolData(const MCSymbol &Symbol) const { return Symbol.hasData(); } MCSymbolData &getSymbolData(const MCSymbol &Symbol) { return const_cast<MCSymbolData &>( @@ -1213,29 +893,25 @@ public: } const MCSymbolData &getSymbolData(const MCSymbol &Symbol) const { - MCSymbolData *Entry = SymbolMap.lookup(&Symbol); - assert(Entry && "Missing symbol data!"); - return *Entry; + return Symbol.getData(); } MCSymbolData &getOrCreateSymbolData(const MCSymbol &Symbol, bool *Created = nullptr) { - MCSymbolData *&Entry = SymbolMap[&Symbol]; - - if (Created) *Created = !Entry; - if (!Entry) - Entry = new MCSymbolData(Symbol, nullptr, 0, this); - - return *Entry; + if (Created) + *Created = !hasSymbolData(Symbol); + if (!hasSymbolData(Symbol)) { + Symbol.initializeData(); + Symbols.push_back(&Symbol); + } + return Symbol.getData(); } const_file_name_iterator file_names_begin() const { return FileNames.begin(); } - const_file_name_iterator file_names_end() const { - return FileNames.end(); - } + const_file_name_iterator file_names_end() const { return FileNames.end(); } void addFileName(StringRef FileName) { if (std::find(file_names_begin(), file_names_end(), FileName) == @@ -1243,11 +919,22 @@ public: FileNames.push_back(FileName); } + /// \brief Write the necessary bundle padding to the given object writer. + /// Expects a fragment \p F containing instructions and its size \p FSize. + void writeFragmentPadding(const MCFragment &F, uint64_t FSize, + MCObjectWriter *OW) const; + /// @} void dump(); }; +/// \brief Compute the amount of padding required before the fragment \p F to +/// obey bundling restrictions, where \p FOffset is the fragment's offset in +/// its section and \p FSize is the fragment's size. +uint64_t computeBundlePadding(const MCAssembler &Assembler, const MCFragment *F, + uint64_t FOffset, uint64_t FSize); + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h index d3b56177d50a..b6c19150c12a 100644 --- a/include/llvm/MC/MCCodeEmitter.h +++ b/include/llvm/MC/MCCodeEmitter.h @@ -22,8 +22,9 @@ template<typename T> class SmallVectorImpl; /// MCCodeEmitter - Generic instruction encoding interface. class MCCodeEmitter { private: - MCCodeEmitter(const MCCodeEmitter &) LLVM_DELETED_FUNCTION; - void operator=(const MCCodeEmitter &) LLVM_DELETED_FUNCTION; + MCCodeEmitter(const MCCodeEmitter &) = delete; + void operator=(const MCCodeEmitter &) = delete; + protected: // Can only create subclasses. MCCodeEmitter(); @@ -31,11 +32,11 @@ public: virtual ~MCCodeEmitter(); /// Lifetime management - virtual void reset() { } + virtual void reset() {} /// EncodeInstruction - Encode the given \p Inst to bytes on the output /// stream \p OS. - virtual void EncodeInstruction(const MCInst &Inst, raw_ostream &OS, + virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const = 0; }; diff --git a/include/llvm/MC/MCCodeGenInfo.h b/include/llvm/MC/MCCodeGenInfo.h index 84ce934d822e..0a4744f1d0f7 100644 --- a/include/llvm/MC/MCCodeGenInfo.h +++ b/include/llvm/MC/MCCodeGenInfo.h @@ -19,33 +19,33 @@ namespace llvm { - class MCCodeGenInfo { - /// RelocationModel - Relocation model: static, pic, etc. - /// - Reloc::Model RelocationModel; +class MCCodeGenInfo { + /// RelocationModel - Relocation model: static, pic, etc. + /// + Reloc::Model RelocationModel; - /// CMModel - Code model. - /// - CodeModel::Model CMModel; + /// CMModel - Code model. + /// + CodeModel::Model CMModel; - /// OptLevel - Optimization level. - /// - CodeGenOpt::Level OptLevel; + /// OptLevel - Optimization level. + /// + CodeGenOpt::Level OptLevel; - public: - void InitMCCodeGenInfo(Reloc::Model RM = Reloc::Default, - CodeModel::Model CM = CodeModel::Default, - CodeGenOpt::Level OL = CodeGenOpt::Default); +public: + void initMCCodeGenInfo(Reloc::Model RM = Reloc::Default, + CodeModel::Model CM = CodeModel::Default, + CodeGenOpt::Level OL = CodeGenOpt::Default); - Reloc::Model getRelocationModel() const { return RelocationModel; } + Reloc::Model getRelocationModel() const { return RelocationModel; } - CodeModel::Model getCodeModel() const { return CMModel; } + CodeModel::Model getCodeModel() const { return CMModel; } - CodeGenOpt::Level getOptLevel() const { return OptLevel; } + CodeGenOpt::Level getOptLevel() const { return OptLevel; } - // Allow overriding OptLevel on a per-function basis. - void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; } - }; + // Allow overriding OptLevel on a per-function basis. + void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; } +}; } // namespace llvm #endif diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index e3163a7946a7..5b57b9d448e8 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -15,8 +15,8 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" #include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MCStreamer.h" #include "llvm/MC/SectionKind.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" @@ -37,20 +37,20 @@ namespace llvm { class MCRegisterInfo; class MCLineSection; class SMLoc; - class StringRef; - class Twine; class MCSectionMachO; class MCSectionELF; class MCSectionCOFF; - /// MCContext - Context object for machine code objects. This class owns all - /// of the sections that it creates. + /// Context object for machine code objects. This class owns all of the + /// sections that it creates. /// class MCContext { - MCContext(const MCContext&) LLVM_DELETED_FUNCTION; - MCContext &operator=(const MCContext&) LLVM_DELETED_FUNCTION; + MCContext(const MCContext &) = delete; + MCContext &operator=(const MCContext &) = delete; + public: - typedef StringMap<MCSymbol*, BumpPtrAllocator&> SymbolTable; + typedef StringMap<MCSymbol *, BumpPtrAllocator &> SymbolTable; + private: /// The SourceMgr for this object, if any. const SourceMgr *SrcMgr; @@ -64,34 +64,34 @@ namespace llvm { /// The MCObjectFileInfo for this target. const MCObjectFileInfo *MOFI; - /// Allocator - Allocator object used for creating machine code objects. + /// 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; - /// Symbols - Bindings of names to symbols. + /// Bindings of names to symbols. SymbolTable Symbols; /// ELF sections can have a corresponding symbol. This maps one to the /// other. - DenseMap<const MCSectionELF*, MCSymbol*> SectionSymbols; + DenseMap<const MCSectionELF *, MCSymbol *> SectionSymbols; - /// A maping from a local label number and an instance count to a symbol. + /// A mapping from a local label number and an instance count to a symbol. /// For example, in the assembly /// 1: /// 2: /// 1: /// We have three labels represented by the pairs (1, 0), (2, 0) and (1, 1) - DenseMap<std::pair<unsigned, unsigned>, MCSymbol*> LocalSymbols; + DenseMap<std::pair<unsigned, unsigned>, MCSymbol *> LocalSymbols; - /// UsedNames - Keeps tracks of names that were used both for used declared - /// and artificial symbols. - StringMap<bool, BumpPtrAllocator&> UsedNames; + /// Keeps tracks of names that were used both for used declared and + /// artificial symbols. + StringMap<bool, BumpPtrAllocator &> UsedNames; - /// NextUniqueID - The next ID to dole out to an unnamed assembler temporary - /// symbol. - unsigned NextUniqueID; + /// The next ID to dole out to an unnamed assembler temporary symbol with + /// a given prefix. + StringMap<unsigned> NextID; /// Instances of directional local labels. DenseMap<unsigned, MCLabel *> Instances; @@ -136,10 +136,8 @@ namespace llvm { /// assembly source files. unsigned GenDwarfFileNumber; - /// Symbols created for the start and end of each section, used for - /// generating the .debug_ranges and .debug_aranges sections. - MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> > - SectionStartEndSyms; + /// Sections for generating the .debug_ranges and .debug_aranges sections. + SetVector<MCSection *> SectionsForRanges; /// The information gathered from labels that will have dwarf label /// entries when generating dwarf assembly source files. @@ -160,21 +158,54 @@ namespace llvm { /// differences between temporary and non-temporary labels (primarily on /// Darwin). bool AllowTemporaryLabels; + bool UseNamesOnTempLabels = true; /// The Compile Unit ID that we are currently processing. unsigned DwarfCompileUnitID; - typedef std::pair<std::string, std::string> SectionGroupPair; - typedef std::tuple<std::string, std::string, int> SectionGroupTriple; - - StringMap<const MCSectionMachO*> MachOUniquingMap; - std::map<SectionGroupPair, const MCSectionELF *> ELFUniquingMap; - std::map<SectionGroupTriple, const MCSectionCOFF *> COFFUniquingMap; + struct ELFSectionKey { + std::string SectionName; + StringRef GroupName; + unsigned UniqueID; + ELFSectionKey(StringRef SectionName, StringRef GroupName, + unsigned UniqueID) + : SectionName(SectionName), GroupName(GroupName), UniqueID(UniqueID) { + } + bool operator<(const ELFSectionKey &Other) const { + if (SectionName != Other.SectionName) + return SectionName < Other.SectionName; + if (GroupName != Other.GroupName) + return GroupName < Other.GroupName; + return UniqueID < Other.UniqueID; + } + }; + + struct COFFSectionKey { + std::string SectionName; + StringRef GroupName; + int SelectionKey; + COFFSectionKey(StringRef SectionName, StringRef GroupName, + int SelectionKey) + : SectionName(SectionName), GroupName(GroupName), + SelectionKey(SelectionKey) {} + bool operator<(const COFFSectionKey &Other) const { + if (SectionName != Other.SectionName) + return SectionName < Other.SectionName; + if (GroupName != Other.GroupName) + return GroupName < Other.GroupName; + return SelectionKey < Other.SelectionKey; + } + }; + + StringMap<MCSectionMachO *> MachOUniquingMap; + std::map<ELFSectionKey, MCSectionELF *> ELFUniquingMap; + std::map<COFFSectionKey, MCSectionCOFF *> COFFUniquingMap; + StringMap<bool> ELFRelSecNames; /// Do automatic reset in destructor bool AutoReset; - MCSymbol *CreateSymbol(StringRef Name); + MCSymbol *CreateSymbol(StringRef Name, bool AlwaysAddSuffix); MCSymbol *getOrCreateDirectionalLocalSymbol(unsigned LocalLabelVal, unsigned Instance); @@ -194,8 +225,9 @@ namespace llvm { const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; } void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; } + void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels = Value; } - /// @name Module Lifetime Management + /// \name Module Lifetime Management /// @{ /// reset - return object to right after construction state to prepare @@ -204,104 +236,144 @@ namespace llvm { /// @} - /// @name Symbol Management + /// \name Symbol Management /// @{ - /// CreateLinkerPrivateTempSymbol - Create and return a new linker temporary - /// symbol with a unique but unspecified name. - MCSymbol *CreateLinkerPrivateTempSymbol(); + /// Create and return a new linker temporary symbol with a unique but + /// unspecified name. + MCSymbol *createLinkerPrivateTempSymbol(); - /// CreateTempSymbol - Create and return a new assembler temporary symbol - /// with a unique but unspecified name. - MCSymbol *CreateTempSymbol(); + /// Create and return a new assembler temporary symbol with a unique but + /// unspecified name. + MCSymbol *createTempSymbol(); - /// getUniqueSymbolID() - Return a unique identifier for use in constructing - /// symbol names. - unsigned getUniqueSymbolID() { return NextUniqueID++; } + MCSymbol *createTempSymbol(const Twine &Name, bool AlwaysAddSuffix); /// Create the definition of a directional local symbol for numbered label /// (used for "1:" definitions). - MCSymbol *CreateDirectionalLocalSymbol(unsigned LocalLabelVal); + MCSymbol *createDirectionalLocalSymbol(unsigned LocalLabelVal); /// Create and return a directional local symbol for numbered label (used /// for "1b" or 1f" references). - MCSymbol *GetDirectionalLocalSymbol(unsigned LocalLabelVal, bool Before); + MCSymbol *getDirectionalLocalSymbol(unsigned LocalLabelVal, bool Before); - /// GetOrCreateSymbol - Lookup the symbol inside with the specified - /// @p Name. If it exists, return it. If not, create a forward - /// reference and return it. + /// Lookup the symbol inside with the specified \p Name. If it exists, + /// return it. If not, create a forward reference and return it. /// - /// @param Name - The symbol name, which must be unique across all symbols. - MCSymbol *GetOrCreateSymbol(StringRef Name); - MCSymbol *GetOrCreateSymbol(const Twine &Name); + /// \param Name - The symbol name, which must be unique across all symbols. + MCSymbol *getOrCreateSymbol(const Twine &Name); MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section); - MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName); + /// Gets a symbol that will be defined to the final stack offset of a local + /// variable after codegen. + /// + /// \param Idx - The index of a local variable passed to @llvm.frameescape. + MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned Idx); + + MCSymbol *getOrCreateParentFrameOffsetSymbol(StringRef FuncName); + + MCSymbol *getOrCreateLSDASymbol(StringRef FuncName); - /// LookupSymbol - Get the symbol for \p Name, or null. - MCSymbol *LookupSymbol(StringRef Name) const; - MCSymbol *LookupSymbol(const Twine &Name) const; + /// Get the symbol for \p Name, or null. + MCSymbol *lookupSymbol(const Twine &Name) const; /// getSymbols - Get a reference for the symbol table for clients that /// want to, for example, iterate over all symbols. 'const' because we /// still want any modifications to the table itself to use the MCContext /// APIs. - const SymbolTable &getSymbols() const { - return Symbols; - } + const SymbolTable &getSymbols() const { return Symbols; } /// @} - /// @name Section Management + /// \name Section Management /// @{ - /// getMachOSection - Return the MCSection for the specified mach-o section. - /// This requires the operands to be valid. - const MCSectionMachO *getMachOSection(StringRef Segment, - StringRef Section, - unsigned TypeAndAttributes, - unsigned Reserved2, - SectionKind K); - const MCSectionMachO *getMachOSection(StringRef Segment, - StringRef Section, - unsigned TypeAndAttributes, - SectionKind K) { - return getMachOSection(Segment, Section, TypeAndAttributes, 0, K); + /// Return the MCSection for the specified mach-o section. This requires + /// the operands to be valid. + MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, + unsigned Reserved2, SectionKind K, + const char *BeginSymName = nullptr); + + MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, SectionKind K, + const char *BeginSymName = nullptr) { + return getMachOSection(Segment, Section, TypeAndAttributes, 0, K, + BeginSymName); } - const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags) { + return getELFSection(Section, Type, Flags, nullptr); + } - const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind, - unsigned EntrySize, StringRef Group); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, const char *BeginSymName) { + return getELFSection(Section, Type, Flags, 0, "", BeginSymName); + } - void renameELFSection(const MCSectionELF *Section, StringRef Name); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group) { + return getELFSection(Section, Type, Flags, EntrySize, Group, nullptr); + } - const MCSectionELF *CreateELFGroupSection(); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group, const char *BeginSymName) { + return getELFSection(Section, Type, Flags, EntrySize, Group, ~0, + BeginSymName); + } - const MCSectionCOFF *getCOFFSection(StringRef Section, - unsigned Characteristics, - SectionKind Kind, - StringRef COMDATSymName, int Selection); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group, unsigned UniqueID) { + return getELFSection(Section, Type, Flags, EntrySize, Group, UniqueID, + nullptr); + } - const MCSectionCOFF *getCOFFSection(StringRef Section, - unsigned Characteristics, - SectionKind Kind); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group, unsigned UniqueID, + const char *BeginSymName); - const MCSectionCOFF *getCOFFSection(StringRef Section); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + const MCSymbol *Group, unsigned UniqueID, + const char *BeginSymName, + const MCSectionELF *Associated); + + MCSectionELF *createELFRelSection(StringRef Name, unsigned Type, + unsigned Flags, unsigned EntrySize, + const MCSymbol *Group, + const MCSectionELF *Associated); + + void renameELFSection(MCSectionELF *Section, StringRef Name); + + MCSectionELF *createELFGroupSection(const MCSymbol *Group); + + MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, + SectionKind Kind, StringRef COMDATSymName, + int Selection, + const char *BeginSymName = nullptr); + + MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, + SectionKind Kind, + const char *BeginSymName = nullptr); + + MCSectionCOFF *getCOFFSection(StringRef Section); /// Gets or creates a section equivalent to Sec that is associated with the /// section containing KeySym. For example, to create a debug info section /// associated with an inline function, pass the normal debug info section /// as Sec and the function symbol as KeySym. - const MCSectionCOFF *getAssociativeCOFFSection(const MCSectionCOFF *Sec, - const MCSymbol *KeySym); + MCSectionCOFF *getAssociativeCOFFSection(MCSectionCOFF *Sec, + const MCSymbol *KeySym); /// @} - /// @name Dwarf Management + /// \name Dwarf Management /// @{ /// \brief Get the compilation directory for DW_AT_comp_dir @@ -323,8 +395,8 @@ namespace llvm { /// \brief Set the main file name and override the default. void setMainFileName(StringRef S) { MainFileName = S; } - /// GetDwarfFile - creates an entry in the dwarf file and directory tables. - unsigned GetDwarfFile(StringRef Directory, StringRef FileName, + /// Creates an entry in the dwarf file and directory tables. + unsigned getDwarfFile(StringRef Directory, StringRef FileName, unsigned FileNumber, unsigned CUID); bool isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID = 0); @@ -356,9 +428,7 @@ namespace llvm { return true; return false; } - unsigned getDwarfCompileUnitID() { - return DwarfCompileUnitID; - } + unsigned getDwarfCompileUnitID() { return DwarfCompileUnitID; } void setDwarfCompileUnitID(unsigned CUIndex) { DwarfCompileUnitID = CUIndex; } @@ -366,10 +436,10 @@ namespace llvm { getMCDwarfLineTable(CUID).setCompilationDir(CompilationDir); } - /// setCurrentDwarfLoc - saves the information from the currently parsed - /// dwarf .loc directive and sets DwarfLocSeen. When the next instruction - /// is assembled an entry in the line number table with this information and - /// the address of the instruction will be created. + /// Saves the information from the currently parsed dwarf .loc directive + /// and sets DwarfLocSeen. When the next instruction is assembled an entry + /// in the line number table with this information and the address of the + /// instruction will be created. void setCurrentDwarfLoc(unsigned FileNum, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, unsigned Discriminator) { @@ -381,7 +451,7 @@ namespace llvm { CurrentDwarfLoc.setDiscriminator(Discriminator); DwarfLocSeen = true; } - void ClearDwarfLocSeen() { DwarfLocSeen = false; } + void clearDwarfLocSeen() { DwarfLocSeen = false; } bool getDwarfLocSeen() { return DwarfLocSeen; } const MCDwarfLoc &getCurrentDwarfLoc() { return CurrentDwarfLoc; } @@ -392,17 +462,13 @@ namespace llvm { void setGenDwarfFileNumber(unsigned FileNumber) { GenDwarfFileNumber = FileNumber; } - MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> > & - getGenDwarfSectionSyms() { - return SectionStartEndSyms; + const SetVector<MCSection *> &getGenDwarfSectionSyms() { + return SectionsForRanges; } - std::pair<MapVector<const MCSection *, - std::pair<MCSymbol *, MCSymbol *> >::iterator, - bool> - addGenDwarfSection(const MCSection *Sec) { - return SectionStartEndSyms.insert( - std::make_pair(Sec, std::make_pair(nullptr, nullptr))); + bool addGenDwarfSection(MCSection *Sec) { + return SectionsForRanges.insert(Sec); } + void finalizeDwarfSections(MCStreamer &MCOS); const std::vector<MCGenDwarfLabelEntry> &getMCGenDwarfLabelEntries() const { return MCGenDwarfLabelEntries; @@ -425,56 +491,52 @@ namespace llvm { char *getSecureLogFile() { return SecureLogFile; } raw_ostream *getSecureLog() { return SecureLog; } bool getSecureLogUsed() { return SecureLogUsed; } - void setSecureLog(raw_ostream *Value) { - SecureLog = Value; - } - void setSecureLogUsed(bool Value) { - SecureLogUsed = Value; - } + void setSecureLog(raw_ostream *Value) { SecureLog = Value; } + void setSecureLogUsed(bool Value) { SecureLogUsed = Value; } - void *Allocate(unsigned Size, unsigned Align = 8) { + void *allocate(unsigned Size, unsigned Align = 8) { return Allocator.Allocate(Size, Align); } - void Deallocate(void *Ptr) { - } + void deallocate(void *Ptr) {} // Unrecoverable error has occurred. Display the best diagnostic we can // and bail via exit(1). For now, most MC backend errors are unrecoverable. // FIXME: We should really do something about that. - LLVM_ATTRIBUTE_NORETURN void FatalError(SMLoc L, const Twine &Msg) const; + LLVM_ATTRIBUTE_NORETURN void reportFatalError(SMLoc L, + const Twine &Msg) const; }; } // end namespace llvm // operator new and delete aren't allowed inside namespaces. // The throw specifications are mandated by the standard. -/// @brief Placement new for using the MCContext's allocator. +/// \brief Placement new for using the MCContext's allocator. /// /// This placement form of operator new uses the MCContext's allocator for /// obtaining memory. It is a non-throwing new, which means that it returns /// null on error. (If that is what the allocator does. The current does, so if /// this ever changes, this operator will have to be changed, too.) /// Usage looks like this (assuming there's an MCContext 'Context' in scope): -/// @code -/// // Default alignment (16) +/// \code +/// // Default alignment (8) /// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments); /// // Specific alignment -/// IntegerLiteral *Ex2 = new (Context, 8) IntegerLiteral(arguments); -/// @endcode +/// IntegerLiteral *Ex2 = new (Context, 4) IntegerLiteral(arguments); +/// \endcode /// Please note that you cannot use delete on the pointer; it must be /// deallocated using an explicit destructor call followed by -/// @c Context.Deallocate(Ptr). +/// \c Context.Deallocate(Ptr). /// -/// @param Bytes The number of bytes to allocate. Calculated by the compiler. -/// @param C The MCContext that provides the allocator. -/// @param Alignment The alignment of the allocated memory (if the underlying +/// \param Bytes The number of bytes to allocate. Calculated by the compiler. +/// \param C The MCContext that provides the allocator. +/// \param Alignment The alignment of the allocated memory (if the underlying /// allocator supports it). -/// @return The allocated memory. Could be NULL. +/// \return The allocated memory. Could be NULL. inline void *operator new(size_t Bytes, llvm::MCContext &C, - size_t Alignment = 16) throw () { - return C.Allocate(Bytes, Alignment); + size_t Alignment = 8) throw() { + return C.allocate(Bytes, Alignment); } -/// @brief Placement delete companion to the new above. +/// \brief Placement delete companion to the new above. /// /// This operator is just a companion to the new above. There is no way of /// invoking it directly; see the new operator for more details. This operator @@ -482,41 +544,41 @@ inline void *operator new(size_t Bytes, llvm::MCContext &C, /// the MCContext throws in the object constructor. inline void operator delete(void *Ptr, llvm::MCContext &C, size_t) throw () { - C.Deallocate(Ptr); + C.deallocate(Ptr); } /// This placement form of operator new[] uses the MCContext's allocator for /// obtaining memory. It is a non-throwing new[], which means that it returns /// null on error. /// Usage looks like this (assuming there's an MCContext 'Context' in scope): -/// @code -/// // Default alignment (16) +/// \code +/// // Default alignment (8) /// char *data = new (Context) char[10]; /// // Specific alignment -/// char *data = new (Context, 8) char[10]; -/// @endcode +/// char *data = new (Context, 4) char[10]; +/// \endcode /// Please note that you cannot use delete on the pointer; it must be /// deallocated using an explicit destructor call followed by -/// @c Context.Deallocate(Ptr). +/// \c Context.Deallocate(Ptr). /// -/// @param Bytes The number of bytes to allocate. Calculated by the compiler. -/// @param C The MCContext that provides the allocator. -/// @param Alignment The alignment of the allocated memory (if the underlying +/// \param Bytes The number of bytes to allocate. Calculated by the compiler. +/// \param C The MCContext that provides the allocator. +/// \param Alignment The alignment of the allocated memory (if the underlying /// allocator supports it). -/// @return The allocated memory. Could be NULL. +/// \return The allocated memory. Could be NULL. inline void *operator new[](size_t Bytes, llvm::MCContext& C, - size_t Alignment = 16) throw () { - return C.Allocate(Bytes, Alignment); + size_t Alignment = 8) throw() { + return C.allocate(Bytes, Alignment); } -/// @brief Placement delete[] companion to the new[] above. +/// \brief Placement delete[] companion to the new[] above. /// /// This operator is just a companion to the new[] above. There is no way of /// invoking it directly; see the new[] operator for more details. This operator /// is called implicitly by the compiler if a placement new[] expression using /// the MCContext throws in the object constructor. inline void operator delete[](void *Ptr, llvm::MCContext &C) throw () { - C.Deallocate(Ptr); + C.deallocate(Ptr); } #endif diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h index d6b0a305b1da..57c40d660f64 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -11,7 +11,6 @@ #include "llvm-c/Disassembler.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSymbolizer.h" #include "llvm/Support/DataTypes.h" @@ -61,16 +60,16 @@ public: /// Returns the disassembly of a single instruction. /// - /// @param Instr - An MCInst to populate with the contents of the + /// \param Instr - An MCInst to populate with the contents of the /// instruction. - /// @param Size - A value to populate with the size of the instruction, or + /// \param Size - A value to populate with the size of the instruction, or /// the number of bytes consumed while attempting to decode /// an invalid instruction. - /// @param Address - The address, in the memory space of region, of the first + /// \param Address - The address, in the memory space of region, of the first /// byte of the instruction. - /// @param VStream - The stream to print warnings and diagnostic messages on. - /// @param CStream - The stream to print comments and annotations on. - /// @return - MCDisassembler::Success if the instruction is valid, + /// \param VStream - The stream to print warnings and diagnostic messages on. + /// \param CStream - The stream to print comments and annotations on. + /// \return - MCDisassembler::Success if the instruction is valid, /// MCDisassembler::SoftFail if the instruction was /// disassemblable but invalid, /// MCDisassembler::Fail if the instruction was invalid. diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index c266acf2f09c..c7bed8eccda9 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -37,34 +37,29 @@ class MCSymbol; class SourceMgr; class SMLoc; -/// MCDwarfFile - Instances of this class represent the name of the dwarf +/// \brief Instances of this class represent the name of the dwarf /// .file directive and its associated dwarf file number in the MC file, -/// and MCDwarfFile's are created and unique'd by the MCContext class where +/// and MCDwarfFile's are created and uniqued by the MCContext class where /// the file number for each is its index into the vector of DwarfFiles (note /// index 0 is not used and not a valid dwarf file number). struct MCDwarfFile { - // Name - the base name of the file without its directory path. + // \brief The base name of the file without its directory path. // The StringRef references memory allocated in the MCContext. std::string Name; - // DirIndex - the index into the list of directory names for this file name. + // \brief The index into the list of directory names for this file name. unsigned DirIndex; }; -/// MCDwarfLoc - Instances of this class represent the information from a +/// \brief Instances of this class represent the information from a /// dwarf .loc directive. class MCDwarfLoc { - // FileNum - the file number. unsigned FileNum; - // Line - the line number. unsigned Line; - // Column - the column position. unsigned Column; // Flags (see #define's below) unsigned Flags; - // Isa unsigned Isa; - // Discriminator unsigned Discriminator; // Flag that indicates the initial value of the is_stmt_start flag. @@ -87,46 +82,46 @@ private: // MCContext manages these // for an MCDwarfLoc object. public: - /// getFileNum - Get the FileNum of this MCDwarfLoc. + /// \brief Get the FileNum of this MCDwarfLoc. unsigned getFileNum() const { return FileNum; } - /// getLine - Get the Line of this MCDwarfLoc. + /// \brief Get the Line of this MCDwarfLoc. unsigned getLine() const { return Line; } - /// getColumn - Get the Column of this MCDwarfLoc. + /// \brief Get the Column of this MCDwarfLoc. unsigned getColumn() const { return Column; } - /// getFlags - Get the Flags of this MCDwarfLoc. + /// \brief Get the Flags of this MCDwarfLoc. unsigned getFlags() const { return Flags; } - /// getIsa - Get the Isa of this MCDwarfLoc. + /// \brief Get the Isa of this MCDwarfLoc. unsigned getIsa() const { return Isa; } - /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. + /// \brief Get the Discriminator of this MCDwarfLoc. unsigned getDiscriminator() const { return Discriminator; } - /// setFileNum - Set the FileNum of this MCDwarfLoc. + /// \brief Set the FileNum of this MCDwarfLoc. void setFileNum(unsigned fileNum) { FileNum = fileNum; } - /// setLine - Set the Line of this MCDwarfLoc. + /// \brief Set the Line of this MCDwarfLoc. void setLine(unsigned line) { Line = line; } - /// setColumn - Set the Column of this MCDwarfLoc. + /// \brief Set the Column of this MCDwarfLoc. void setColumn(unsigned column) { Column = column; } - /// setFlags - Set the Flags of this MCDwarfLoc. + /// \brief Set the Flags of this MCDwarfLoc. void setFlags(unsigned flags) { Flags = flags; } - /// setIsa - Set the Isa of this MCDwarfLoc. + /// \brief Set the Isa of this MCDwarfLoc. void setIsa(unsigned isa) { Isa = isa; } - /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. + /// \brief Set the Discriminator of this MCDwarfLoc. void setDiscriminator(unsigned discriminator) { Discriminator = discriminator; } }; -/// MCLineEntry - Instances of this class represent the line information for +/// \brief Instances of this class represent the line information for /// the dwarf line table entries. Which is created after a machine /// instruction is assembled and uses an address from a temporary label /// created at the current address in the current section and the info from @@ -148,24 +143,24 @@ public: // 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(MCObjectStreamer *MCOS, MCSection *Section); }; -/// MCLineSection - Instances of this class represent the line information -/// for a compile unit where machine instructions have been assembled after seeing -/// .loc directives. This is the information used to build the dwarf line +/// \brief Instances of this class represent the line information for a compile +/// unit where machine instructions have been assembled after seeing .loc +/// directives. This is the information used to build the dwarf line /// table for a section. class MCLineSection { public: - // addLineEntry - adds an entry to this MCLineSection's line entries - void addLineEntry(const MCLineEntry &LineEntry, const MCSection *Sec) { + // \brief Add an entry to this MCLineSection's line entries. + void addLineEntry(const MCLineEntry &LineEntry, MCSection *Sec) { MCLineDivisions[Sec].push_back(LineEntry); } typedef std::vector<MCLineEntry> MCLineEntryCollection; typedef MCLineEntryCollection::iterator iterator; typedef MCLineEntryCollection::const_iterator const_iterator; - typedef MapVector<const MCSection *, MCLineEntryCollection> MCLineDivisionMap; + typedef MapVector<MCSection *, MCLineEntryCollection> MCLineDivisionMap; private: // A collection of MCLineEntry for each section. diff --git a/include/llvm/MC/MCELF.h b/include/llvm/MC/MCELF.h index 294a51bf7c76..f409988d5726 100644 --- a/include/llvm/MC/MCELF.h +++ b/include/llvm/MC/MCELF.h @@ -15,8 +15,6 @@ #ifndef LLVM_MC_MCELF_H #define LLVM_MC_MCELF_H -#include "llvm/MC/MCExpr.h" - namespace llvm { class MCSymbolData; diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index 421e7a0b2c19..cf73eca340d7 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -20,10 +20,21 @@ class MCAssembler; class MCFixup; class MCFragment; class MCObjectWriter; -class MCSectionData; class MCSymbol; class MCSymbolData; class MCValue; +class raw_pwrite_stream; + +struct ELFRelocationEntry { + uint64_t Offset; // Where is the relocation. + const MCSymbol *Symbol; // The symbol to relocate with. + unsigned Type; // The type of the relocation. + uint64_t Addend; // The addend to use. + + ELFRelocationEntry(uint64_t Offset, const MCSymbol *Symbol, unsigned Type, + uint64_t Addend) + : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {} +}; class MCELFObjectTargetWriter { const uint8_t OSABI; @@ -41,6 +52,9 @@ protected: public: static uint8_t getOSABI(Triple::OSType OSType) { switch (OSType) { + case Triple::CloudABI: + return ELF::ELFOSABI_CLOUDABI; + case Triple::PS4: case Triple::FreeBSD: return ELF::ELFOSABI_FREEBSD; case Triple::Linux: @@ -58,7 +72,10 @@ public: virtual bool needsRelocateWithSymbol(const MCSymbolData &SD, unsigned Type) const; - /// @name Accessors + virtual void sortRelocs(const MCAssembler &Asm, + std::vector<ELFRelocationEntry> &Relocs); + + /// \name Accessors /// @{ uint8_t getOSABI() const { return OSABI; } uint16_t getEMachine() const { return EMachine; } @@ -113,7 +130,8 @@ public: /// \param OS - The stream to write to. /// \returns The constructed object writer. MCObjectWriter *createELFObjectWriter(MCELFObjectTargetWriter *MOTW, - raw_ostream &OS, bool IsLittleEndian); + raw_pwrite_stream &OS, + bool IsLittleEndian); } // End llvm namespace #endif diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index ab6c5e3d6124..97058f5e9981 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -29,32 +29,26 @@ class raw_ostream; class MCELFStreamer : public MCObjectStreamer { public: - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, + MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, TAB, OS, Emitter), - SeenIdent(false) {} + : MCObjectStreamer(Context, TAB, OS, Emitter), SeenIdent(false) {} - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter, MCAssembler *Assembler) - : MCObjectStreamer(Context, TAB, OS, Emitter, Assembler), - SeenIdent(false) {} - - virtual ~MCELFStreamer(); + ~MCELFStreamer() override; /// state management void reset() override { + SeenIdent = false; LocalCommons.clear(); BindingExplicitlySet.clear(); - SeenIdent = false; + BundleGroups.clear(); MCObjectStreamer::reset(); } - /// @name MCStreamer Interface + /// \name MCStreamer Interface /// @{ void InitSections(bool NoExecStack) override; - void ChangeSection(const MCSection *Section, - const MCExpr *Subsection) override; + void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; void EmitLabel(MCSymbol *Symbol) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitThumbFunc(MCSymbol *Func) override; @@ -73,10 +67,10 @@ public: void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; - void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr, + void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, uint64_t Size = 0, unsigned ByteAlignment = 0) override; - void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0) override; + void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment = 0) override; void EmitValueImpl(const MCExpr *Value, unsigned Size, const SMLoc &Loc = SMLoc()) override; @@ -95,15 +89,19 @@ public: void EmitBundleUnlock() override; private: + bool isBundleLocked() const; void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override; void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; void fixSymbolsInTLSFixups(const MCExpr *expr); + /// \brief Merge the content of the fragment \p EF into the fragment \p DF. + void mergeFragment(MCDataFragment *, MCEncodedFragmentWithFixups *); + bool SeenIdent; struct LocalCommon { - MCSymbolData *SD; + const MCSymbol *Symbol; uint64_t Size; unsigned ByteAlignment; }; @@ -111,11 +109,16 @@ private: std::vector<LocalCommon> LocalCommons; SmallPtrSet<MCSymbol *, 16> BindingExplicitlySet; + + /// BundleGroups - The stack of fragments holding the bundle-locked + /// instructions. + llvm::SmallVector<MCDataFragment *, 4> BundleGroups; }; MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *Emitter, - bool RelaxAll, bool IsThumb); + raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, bool RelaxAll, + bool IsThumb); } // end namespace llvm diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index bd9b2bc4751a..b38ad7daee3e 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -21,15 +21,14 @@ class MCAssembler; class MCContext; class MCFixup; class MCSection; -class MCSectionData; class MCStreamer; class MCSymbol; class MCValue; class raw_ostream; class StringRef; -typedef DenseMap<const MCSectionData*, uint64_t> SectionAddrMap; +typedef DenseMap<const MCSection *, uint64_t> SectionAddrMap; -/// MCExpr - Base class for the full range of assembler expressions which are +/// \brief Base class for the full range of assembler expressions which are /// needed for parsing. class MCExpr { public: @@ -44,8 +43,8 @@ public: private: ExprKind Kind; - MCExpr(const MCExpr&) LLVM_DELETED_FUNCTION; - void operator=(const MCExpr&) LLVM_DELETED_FUNCTION; + MCExpr(const MCExpr&) = delete; + void operator=(const MCExpr&) = delete; bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, @@ -56,53 +55,52 @@ private: const SectionAddrMap *Addrs, bool InSet) const; protected: - explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {} + explicit MCExpr(ExprKind Kind) : Kind(Kind) {} bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, const MCFixup *Fixup, - const SectionAddrMap *Addrs, bool InSet, - bool ForceVarExpansion) const; + const SectionAddrMap *Addrs, bool InSet) const; public: - /// @name Accessors + /// \name Accessors /// @{ ExprKind getKind() const { return Kind; } /// @} - /// @name Utility Methods + /// \name Utility Methods /// @{ void print(raw_ostream &OS) const; void dump() const; /// @} - /// @name Expression Evaluation + /// \name Expression Evaluation /// @{ - /// EvaluateAsAbsolute - Try to evaluate the expression to an absolute value. + /// \brief Try to evaluate the expression to an absolute value. /// - /// @param Res - The absolute value, if evaluation succeeds. - /// @param Layout - The assembler layout object to use for evaluating symbol + /// \param Res - The absolute value, if evaluation succeeds. + /// \param Layout - The assembler layout object to use for evaluating symbol /// values. If not given, then only non-symbolic expressions will be /// evaluated. - /// @result - True on success. + /// \return - True on success. bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout, const SectionAddrMap &Addrs) 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; - int64_t evaluateKnownAbsolute(const MCAsmLayout &Layout) const; + bool evaluateKnownAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; - /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable - /// value, i.e. an expression of the fixed form (a - b + constant). + /// \brief Try to evaluate the expression to a relocatable value, i.e. an + /// expression of the fixed form (a - b + constant). /// - /// @param Res - The relocatable value, if evaluation succeeds. - /// @param Layout - The assembler layout object to use for evaluating values. - /// @param Fixup - The Fixup object if available. - /// @result - True on success. + /// \param Res - The relocatable value, if evaluation succeeds. + /// \param Layout - The assembler layout object to use for evaluating values. + /// \param Fixup - The Fixup object if available. + /// \return - True on success. bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const; @@ -110,16 +108,14 @@ public: /// neither a nor b are variables. /// /// This is a more aggressive variant of EvaluateAsRelocatable. The intended - /// use is for when relocations are not available, like the symbol value in - /// the symbol table. - bool EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout, - const MCFixup *Fixup) const; + /// use is for when relocations are not available, like the .size directive. + bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const; - /// FindAssociatedSection - Find the "associated section" for this expression, - /// which is currently defined as the absolute section for constants, or + /// \brief Find the "associated section" for this expression, which is + /// currently defined as the absolute section for constants, or /// otherwise the section associated with the first defined symbol in the /// expression. - const MCSection *FindAssociatedSection() const; + MCSection *FindAssociatedSection() const; /// @} }; @@ -129,21 +125,21 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) { return OS; } -//// MCConstantExpr - Represent a constant integer expression. +//// \brief Represent a constant integer expression. class MCConstantExpr : public MCExpr { int64_t Value; - explicit MCConstantExpr(int64_t _Value) - : MCExpr(MCExpr::Constant), Value(_Value) {} + explicit MCConstantExpr(int64_t Value) + : MCExpr(MCExpr::Constant), Value(Value) {} public: - /// @name Construction + /// \name Construction /// @{ static const MCConstantExpr *Create(int64_t Value, MCContext &Ctx); /// @} - /// @name Accessors + /// \name Accessors /// @{ int64_t getValue() const { return Value; } @@ -155,15 +151,14 @@ public: } }; -/// MCSymbolRefExpr - Represent a reference to a symbol from inside an -/// expression. +/// \brief Represent a reference to a symbol from inside an expression. /// /// A symbol reference in an expression may be a use of a label, a use of an /// assembler variable (defined constant), or constitute an implicit definition /// of the symbol as external. class MCSymbolRefExpr : public MCExpr { public: - enum VariantKind { + enum VariantKind : uint16_t { VK_None, VK_Invalid, @@ -188,6 +183,7 @@ public: VK_GOTPAGE, VK_GOTPAGEOFF, VK_SECREL, + VK_SIZE, // symbol@SIZE VK_WEAKREF, // The link between the symbols in .weakref foo, bar VK_ARM_NONE, @@ -280,12 +276,25 @@ public: VK_Mips_PCREL_HI16, VK_Mips_PCREL_LO16, - VK_COFF_IMGREL32 // symbol@imgrel (image-relative) + VK_COFF_IMGREL32, // symbol@imgrel (image-relative) + + VK_Hexagon_PCREL, + VK_Hexagon_LO16, + VK_Hexagon_HI16, + VK_Hexagon_GPREL, + VK_Hexagon_GD_GOT, + VK_Hexagon_LD_GOT, + VK_Hexagon_GD_PLT, + VK_Hexagon_LD_PLT, + VK_Hexagon_IE, + VK_Hexagon_IE_GOT, + VK_TPREL, + VK_DTPREL }; private: /// The symbol reference modifier. - const unsigned Kind : 16; + const VariantKind Kind; /// Specifies how the variant kind should be printed. const unsigned UseParensForSymbolVariant : 1; @@ -300,7 +309,7 @@ private: const MCAsmInfo *MAI); public: - /// @name Construction + /// \name Construction /// @{ static const MCSymbolRefExpr *Create(const MCSymbol *Symbol, MCContext &Ctx) { @@ -313,19 +322,19 @@ public: MCContext &Ctx); /// @} - /// @name Accessors + /// \name Accessors /// @{ const MCSymbol &getSymbol() const { return *Symbol; } - VariantKind getKind() const { return static_cast<VariantKind>(Kind); } + VariantKind getKind() const { return Kind; } void printVariantKind(raw_ostream &OS) const; bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } /// @} - /// @name Static Utility Functions + /// \name Static Utility Functions /// @{ static StringRef getVariantKindName(VariantKind Kind); @@ -339,7 +348,7 @@ public: } }; -/// MCUnaryExpr - Unary assembler expressions. +/// \brief Unary assembler expressions. class MCUnaryExpr : public MCExpr { public: enum Opcode { @@ -353,11 +362,11 @@ private: Opcode Op; const MCExpr *Expr; - MCUnaryExpr(Opcode _Op, const MCExpr *_Expr) - : MCExpr(MCExpr::Unary), Op(_Op), Expr(_Expr) {} + MCUnaryExpr(Opcode Op, const MCExpr *Expr) + : MCExpr(MCExpr::Unary), Op(Op), Expr(Expr) {} public: - /// @name Construction + /// \name Construction /// @{ static const MCUnaryExpr *Create(Opcode Op, const MCExpr *Expr, @@ -376,13 +385,13 @@ public: } /// @} - /// @name Accessors + /// \name Accessors /// @{ - /// getOpcode - Get the kind of this unary expression. + /// \brief Get the kind of this unary expression. Opcode getOpcode() const { return Op; } - /// getSubExpr - Get the child of this unary expression. + /// \brief Get the child of this unary expression. const MCExpr *getSubExpr() const { return Expr; } /// @} @@ -392,7 +401,7 @@ public: } }; -/// MCBinaryExpr - Binary assembler expressions. +/// \brief Binary assembler expressions. class MCBinaryExpr : public MCExpr { public: enum Opcode { @@ -415,7 +424,8 @@ public: NE, ///< Inequality comparison. Or, ///< Bitwise or. Shl, ///< Shift left. - Shr, ///< Shift right (arithmetic or logical, depending on target) + AShr, ///< Arithmetic shift right. + LShr, ///< Logical shift right. Sub, ///< Subtraction. Xor ///< Bitwise exclusive or. }; @@ -424,11 +434,11 @@ private: Opcode Op; const MCExpr *LHS, *RHS; - MCBinaryExpr(Opcode _Op, const MCExpr *_LHS, const MCExpr *_RHS) - : MCExpr(MCExpr::Binary), Op(_Op), LHS(_LHS), RHS(_RHS) {} + MCBinaryExpr(Opcode Op, const MCExpr *LHS, const MCExpr *RHS) + : MCExpr(MCExpr::Binary), Op(Op), LHS(LHS), RHS(RHS) {} public: - /// @name Construction + /// \name Construction /// @{ static const MCBinaryExpr *Create(Opcode Op, const MCExpr *LHS, @@ -493,9 +503,13 @@ public: MCContext &Ctx) { return Create(Shl, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateShr(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *CreateAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(Shr, LHS, RHS, Ctx); + return Create(AShr, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateLShr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(LShr, LHS, RHS, Ctx); } static const MCBinaryExpr *CreateSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { @@ -507,16 +521,16 @@ public: } /// @} - /// @name Accessors + /// \name Accessors /// @{ - /// getOpcode - Get the kind of this binary expression. + /// \brief Get the kind of this binary expression. Opcode getOpcode() const { return Op; } - /// getLHS - Get the left-hand side expression of the binary operator. + /// \brief Get the left-hand side expression of the binary operator. const MCExpr *getLHS() const { return LHS; } - /// getRHS - Get the right-hand side expression of the binary operator. + /// \brief Get the right-hand side expression of the binary operator. const MCExpr *getRHS() const { return RHS; } /// @} @@ -526,8 +540,8 @@ public: } }; -/// MCTargetExpr - This is an extension point for target-specific MCExpr -/// subclasses to implement. +/// \brief This is an extension point for target-specific MCExpr subclasses to +/// implement. /// /// NOTE: All subclasses are required to have trivial destructors because /// MCExprs are bump pointer allocated and not destructed. @@ -543,7 +557,7 @@ public: const MCAsmLayout *Layout, const MCFixup *Fixup) const = 0; virtual void visitUsedExpr(MCStreamer& Streamer) const = 0; - virtual const MCSection *FindAssociatedSection() const = 0; + virtual MCSection *FindAssociatedSection() const = 0; virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0; diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h index 98a1419a1934..8ab477c401a1 100644 --- a/include/llvm/MC/MCFixup.h +++ b/include/llvm/MC/MCFixup.h @@ -19,7 +19,7 @@ namespace llvm { class MCExpr; -/// MCFixupKind - Extensible enumeration to represent the type of a fixup. +/// \brief Extensible enumeration to represent the type of a fixup. enum MCFixupKind { FK_Data_1 = 0, ///< A one-byte fixup. FK_Data_2, ///< A two-byte fixup. @@ -45,7 +45,7 @@ enum MCFixupKind { MaxTargetFixupKind = (1 << 8) }; -/// MCFixup - Encode information on a single operation to perform on a byte +/// \brief Encode information on a single operation to perform on a byte /// sequence (e.g., an encoded instruction) which requires assemble- or run- /// time patching. /// @@ -75,7 +75,7 @@ class MCFixup { /// The source location which gave rise to the fixup, if any. SMLoc Loc; public: - static MCFixup Create(uint32_t Offset, const MCExpr *Value, + static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc = SMLoc()) { assert(unsigned(Kind) < MaxTargetFixupKind && "Kind out of range!"); MCFixup FI; @@ -93,8 +93,8 @@ public: const MCExpr *getValue() const { return Value; } - /// getKindForSize - Return the generic fixup kind for a value with the given - /// size. It is an error to pass an unsupported size. + /// \brief 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, bool isPCRel) { switch (Size) { default: llvm_unreachable("Invalid generic fixup size!"); diff --git a/include/llvm/MC/MCFixupKindInfo.h b/include/llvm/MC/MCFixupKindInfo.h index 6979ad5807d0..58183bd778e6 100644 --- a/include/llvm/MC/MCFixupKindInfo.h +++ b/include/llvm/MC/MCFixupKindInfo.h @@ -12,7 +12,7 @@ namespace llvm { -/// MCFixupKindInfo - Target independent information on a fixup kind. +/// \brief Target independent information on a fixup kind. struct MCFixupKindInfo { enum FixupKindFlags { /// Is this fixup kind PCrelative? This is used by the assembler backend to diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index 25cd5ccb08fd..2fc509148403 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -28,7 +28,7 @@ class MCInstPrinter; class MCExpr; class MCInst; -/// MCOperand - Instances of this class represent operands of the MCInst class. +/// \brief Instances of this class represent operands of the MCInst class. /// This is a simple discriminated union. class MCOperand { enum MachineOperandType : unsigned char { @@ -59,13 +59,13 @@ public: bool isExpr() const { return Kind == kExpr; } bool isInst() const { return Kind == kInst; } - /// getReg - Returns the register number. + /// \brief Returns the register number. unsigned getReg() const { assert(isReg() && "This is not a register operand!"); return RegVal; } - /// setReg - Set the register number. + /// \brief Set the register number. void setReg(unsigned Reg) { assert(isReg() && "This is not a register operand!"); RegVal = Reg; @@ -108,44 +108,44 @@ public: InstVal = Val; } - static MCOperand CreateReg(unsigned Reg) { + static MCOperand createReg(unsigned Reg) { MCOperand Op; Op.Kind = kRegister; Op.RegVal = Reg; return Op; } - static MCOperand CreateImm(int64_t Val) { + static MCOperand createImm(int64_t Val) { MCOperand Op; Op.Kind = kImmediate; Op.ImmVal = Val; return Op; } - static MCOperand CreateFPImm(double Val) { + static MCOperand createFPImm(double Val) { MCOperand Op; Op.Kind = kFPImmediate; Op.FPImmVal = Val; return Op; } - static MCOperand CreateExpr(const MCExpr *Val) { + static MCOperand createExpr(const MCExpr *Val) { MCOperand Op; Op.Kind = kExpr; Op.ExprVal = Val; return Op; } - static MCOperand CreateInst(const MCInst *Val) { + static MCOperand createInst(const MCInst *Val) { MCOperand Op; Op.Kind = kInst; Op.InstVal = Val; return Op; } - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void print(raw_ostream &OS) const; void dump() const; }; template <> struct isPodLike<MCOperand> { static const bool value = true; }; -/// MCInst - Instances of this class represent a single low-level machine +/// \brief Instances of this class represent a single low-level machine /// instruction. class MCInst { unsigned Opcode; @@ -169,7 +169,7 @@ public: } void clear() { Operands.clear(); } - size_t size() { return Operands.size(); } + size_t size() const { return Operands.size(); } typedef SmallVectorImpl<MCOperand>::iterator iterator; typedef SmallVectorImpl<MCOperand>::const_iterator const_iterator; @@ -181,24 +181,23 @@ public: return Operands.insert(I, Op); } - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void print(raw_ostream &OS) const; void dump() const; /// \brief Dump the MCInst as prettily as possible using the additional MC /// structures, if given. Operators are separated by the \p Separator /// string. - void dump_pretty(raw_ostream &OS, const MCAsmInfo *MAI = nullptr, - const MCInstPrinter *Printer = nullptr, + void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer = nullptr, StringRef Separator = " ") const; }; inline raw_ostream& operator<<(raw_ostream &OS, const MCOperand &MO) { - MO.print(OS, nullptr); + MO.print(OS); return OS; } inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) { - MI.print(OS, nullptr); + MI.print(OS); return OS; } diff --git a/include/llvm/MC/MCInstBuilder.h b/include/llvm/MC/MCInstBuilder.h index c5acb26eecac..30609bdb8b27 100644 --- a/include/llvm/MC/MCInstBuilder.h +++ b/include/llvm/MC/MCInstBuilder.h @@ -30,31 +30,37 @@ public: /// \brief Add a new register operand. MCInstBuilder &addReg(unsigned Reg) { - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return *this; } /// \brief Add a new integer immediate operand. MCInstBuilder &addImm(int64_t Val) { - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createImm(Val)); return *this; } /// \brief Add a new floating point immediate operand. MCInstBuilder &addFPImm(double Val) { - Inst.addOperand(MCOperand::CreateFPImm(Val)); + Inst.addOperand(MCOperand::createFPImm(Val)); return *this; } /// \brief Add a new MCExpr operand. MCInstBuilder &addExpr(const MCExpr *Val) { - Inst.addOperand(MCOperand::CreateExpr(Val)); + Inst.addOperand(MCOperand::createExpr(Val)); return *this; } /// \brief Add a new MCInst operand. MCInstBuilder &addInst(const MCInst *Val) { - Inst.addOperand(MCOperand::CreateInst(Val)); + Inst.addOperand(MCOperand::createInst(Val)); + return *this; + } + + /// \brief Add an operand. + MCInstBuilder &addOperand(const MCOperand &Op) { + Inst.addOperand(Op); return *this; } diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index 95124c3021dd..7e8563a195d0 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -19,6 +19,7 @@ class raw_ostream; class MCAsmInfo; class MCInstrInfo; class MCRegisterInfo; +class MCSubtargetInfo; class StringRef; namespace HexStyle { @@ -28,21 +29,18 @@ namespace HexStyle { }; } -/// MCInstPrinter - This is an instance of a target assembly language printer -/// that converts an MCInst to valid target assembly syntax. +/// \brief This is an instance of a target assembly language printer that +/// converts an MCInst to valid target assembly syntax. class MCInstPrinter { protected: - /// CommentStream - a stream that comments can be emitted to if desired. - /// Each comment must end with a newline. This will be null if verbose - /// assembly emission is disable. + /// \brief A stream that comments can be emitted to if desired. Each comment + /// must end with a newline. This will be null if verbose assembly emission + /// is disable. raw_ostream *CommentStream; const MCAsmInfo &MAI; const MCInstrInfo &MII; const MCRegisterInfo &MRI; - /// The current set of available features. - uint64_t AvailableFeatures; - /// True if we are printing marked up assembly. bool UseMarkup; @@ -58,29 +56,25 @@ public: MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, const MCRegisterInfo &mri) : CommentStream(nullptr), MAI(mai), MII(mii), MRI(mri), - AvailableFeatures(0), UseMarkup(0), PrintImmHex(0), + UseMarkup(0), PrintImmHex(0), PrintHexStyle(HexStyle::C) {} virtual ~MCInstPrinter(); - /// setCommentStream - Specify a stream to emit comments to. + /// \brief Specify a stream to emit comments to. void setCommentStream(raw_ostream &OS) { CommentStream = &OS; } - /// printInst - Print the specified MCInst to the specified raw_ostream. - /// + /// \brief Print the specified MCInst to the specified raw_ostream. virtual void printInst(const MCInst *MI, raw_ostream &OS, - StringRef Annot) = 0; + StringRef Annot, const MCSubtargetInfo &STI) = 0; - /// getOpcodeName - Return the name of the specified opcode enum (e.g. - /// "MOV32ri") or empty if we can't resolve it. + /// \brief Return the name of the specified opcode enum (e.g. "MOV32ri") or + /// empty if we can't resolve it. StringRef getOpcodeName(unsigned Opcode) const; - /// printRegName - Print the assembler register name. + /// \brief Print the assembler register name. virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; - uint64_t getAvailableFeatures() const { return AvailableFeatures; } - void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } - bool getUseMarkup() const { return UseMarkup; } void setUseMarkup(bool Value) { UseMarkup = Value; } @@ -95,12 +89,14 @@ public: void setPrintImmHex(HexStyle::Style Value) { PrintHexStyle = Value; } /// Utility function to print immediates in decimal or hex. - format_object1<int64_t> formatImm(const int64_t Value) const { return PrintImmHex ? formatHex(Value) : formatDec(Value); } + format_object<int64_t> formatImm(int64_t Value) const { + return PrintImmHex ? formatHex(Value) : formatDec(Value); + } /// Utility functions to print decimal/hexadecimal values. - format_object1<int64_t> formatDec(const int64_t Value) const; - format_object1<int64_t> formatHex(const int64_t Value) const; - format_object1<uint64_t> formatHex(const uint64_t Value) const; + format_object<int64_t> formatDec(int64_t Value) const; + format_object<int64_t> formatHex(int64_t Value) const; + format_object<uint64_t> formatHex(uint64_t Value) const; }; } // namespace llvm diff --git a/include/llvm/MC/MCInstrAnalysis.h b/include/llvm/MC/MCInstrAnalysis.h index e921f768ac45..8f5159e9e1c8 100644 --- a/include/llvm/MC/MCInstrAnalysis.h +++ b/include/llvm/MC/MCInstrAnalysis.h @@ -59,8 +59,8 @@ public: return Info->get(Inst.getOpcode()).isTerminator(); } - /// evaluateBranch - Given a branch instruction try to get the address the - /// branch targets. Return true on success, and the address in Target. + /// \brief Given a branch instruction try to get the address the branch + /// targets. Return true on success, and the address in Target. virtual bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, uint64_t &Target) const; diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 360989305d3a..de3a1959e05c 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -15,142 +15,142 @@ #ifndef LLVM_MC_MCINSTRDESC_H #define LLVM_MC_MCINSTRDESC_H -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/DataTypes.h" +#include <string> namespace llvm { + class MCInst; + class MCRegisterInfo; + class MCSubtargetInfo; + class FeatureBitset; //===----------------------------------------------------------------------===// // Machine Operand Flags and Description //===----------------------------------------------------------------------===// namespace MCOI { - // Operand constraints - enum OperandConstraint { - TIED_TO = 0, // Must be allocated the same register as. - EARLY_CLOBBER // Operand is an early clobber register operand - }; - - /// OperandFlags - These are flags set on operands, but should be considered - /// private, all access should go through the MCOperandInfo accessors. - /// See the accessors for a description of what these are. - enum OperandFlags { - LookupPtrRegClass = 0, - Predicate, - OptionalDef - }; - - /// Operand Type - Operands are tagged with one of the values of this enum. - enum OperandType { - OPERAND_UNKNOWN = 0, - OPERAND_IMMEDIATE = 1, - OPERAND_REGISTER = 2, - OPERAND_MEMORY = 3, - OPERAND_PCREL = 4, - OPERAND_FIRST_TARGET = 5 - }; +// Operand constraints +enum OperandConstraint { + TIED_TO = 0, // Must be allocated the same register as. + EARLY_CLOBBER // Operand is an early clobber register operand +}; + +/// \brief These are flags set on operands, but should be considered +/// private, all access should go through the MCOperandInfo accessors. +/// See the accessors for a description of what these are. +enum OperandFlags { LookupPtrRegClass = 0, Predicate, OptionalDef }; + +/// \brief Operands are tagged with one of the values of this enum. +enum OperandType { + OPERAND_UNKNOWN = 0, + OPERAND_IMMEDIATE = 1, + OPERAND_REGISTER = 2, + OPERAND_MEMORY = 3, + OPERAND_PCREL = 4, + OPERAND_FIRST_TARGET = 5 +}; } -/// MCOperandInfo - This holds information about one operand of a machine -/// instruction, indicating the register class for register operands, etc. -/// +/// \brief This holds information about one operand of a machine instruction, +/// indicating the register class for register operands, etc. class MCOperandInfo { public: - /// RegClass - This specifies the register class enumeration of the operand + /// \brief This specifies the register class enumeration of the operand /// if the operand is a register. If isLookupPtrRegClass is set, then this is /// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to /// get a dynamic register class. int16_t RegClass; - /// Flags - These are flags from the MCOI::OperandFlags enum. + /// \brief These are flags from the MCOI::OperandFlags enum. uint8_t Flags; - /// OperandType - Information about the type of the operand. + /// \brief Information about the type of the operand. uint8_t OperandType; - - /// Lower 16 bits are used to specify which constraints are set. The higher 16 - /// bits are used to specify the value of constraints (4 bits each). + /// \brief The lower 16 bits are used to specify which constraints are set. + /// The higher 16 bits are used to specify the value of constraints (4 bits + /// each). uint32_t Constraints; - /// Currently no other information. - /// isLookupPtrRegClass - Set if this operand is a pointer value and it - /// requires a callback to look up its register class. - bool isLookupPtrRegClass() const {return Flags&(1 <<MCOI::LookupPtrRegClass);} + /// \brief Set if this operand is a pointer value and it requires a callback + /// to look up its register class. + bool isLookupPtrRegClass() const { + return Flags & (1 << MCOI::LookupPtrRegClass); + } - /// isPredicate - Set if this is one of the operands that made up of - /// the predicate operand that controls an isPredicable() instruction. + /// \brief Set if this is one of the operands that made up of the predicate + /// operand that controls an isPredicable() instruction. bool isPredicate() const { return Flags & (1 << MCOI::Predicate); } - /// isOptionalDef - Set if this operand is a optional def. - /// + /// \brief Set if this operand is a optional def. bool isOptionalDef() const { return Flags & (1 << MCOI::OptionalDef); } }; - //===----------------------------------------------------------------------===// // Machine Instruction Flags and Description //===----------------------------------------------------------------------===// -/// MCInstrDesc flags - These should be considered private to the -/// implementation of the MCInstrDesc class. Clients should use the predicate -/// methods on MCInstrDesc, not use these directly. These all correspond to -/// bitfields in the MCInstrDesc::Flags field. namespace MCID { - enum { - Variadic = 0, - HasOptionalDef, - Pseudo, - Return, - Call, - Barrier, - Terminator, - Branch, - IndirectBranch, - Compare, - MoveImm, - Bitcast, - Select, - DelaySlot, - FoldableAsLoad, - MayLoad, - MayStore, - Predicable, - NotDuplicable, - UnmodeledSideEffects, - Commutable, - ConvertibleTo3Addr, - UsesCustomInserter, - HasPostISelHook, - Rematerializable, - CheapAsAMove, - ExtraSrcRegAllocReq, - ExtraDefRegAllocReq, - RegSequence, - ExtractSubreg, - InsertSubreg - }; +/// \brief These should be considered private to the implementation of the +/// MCInstrDesc class. Clients should use the predicate methods on MCInstrDesc, +/// not use these directly. These all correspond to bitfields in the +/// MCInstrDesc::Flags field. +enum Flag { + Variadic = 0, + HasOptionalDef, + Pseudo, + Return, + Call, + Barrier, + Terminator, + Branch, + IndirectBranch, + Compare, + MoveImm, + Bitcast, + Select, + DelaySlot, + FoldableAsLoad, + MayLoad, + MayStore, + Predicable, + NotDuplicable, + UnmodeledSideEffects, + Commutable, + ConvertibleTo3Addr, + UsesCustomInserter, + HasPostISelHook, + Rematerializable, + CheapAsAMove, + ExtraSrcRegAllocReq, + ExtraDefRegAllocReq, + RegSequence, + ExtractSubreg, + InsertSubreg +}; } -/// MCInstrDesc - Describe properties that are true of each instruction in the -/// target description file. This captures information about side effects, -/// register use and many other things. There is one instance of this struct -/// for each target instruction class, and the MachineInstr class points to -/// this struct directly to describe itself. +/// \brief Describe properties that are true of each instruction in the target +/// description file. This captures information about side effects, register +/// use and many other things. There is one instance of this struct for each +/// target instruction class, and the MachineInstr class points to this struct +/// directly to describe itself. class MCInstrDesc { public: - unsigned short Opcode; // The opcode number - unsigned short NumOperands; // Num of args (may be more if variable_ops) - unsigned short NumDefs; // Num of args that are definitions - unsigned short SchedClass; // enum identifying instr sched class - unsigned short Size; // Number of bytes in encoding. - unsigned Flags; // Flags identifying machine instr class - uint64_t TSFlags; // Target Specific Flag values - const uint16_t *ImplicitUses; // Registers implicitly read by this instr - const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr - const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands - uint64_t DeprecatedFeatureMask;// Feature bits that this is deprecated on, if any + unsigned short Opcode; // The opcode number + unsigned short NumOperands; // Num of args (may be more if variable_ops) + unsigned short NumDefs; // Num of args that are definitions + unsigned short SchedClass; // enum identifying instr sched class + unsigned short Size; // Number of bytes in encoding. + unsigned Flags; // Flags identifying machine instr class + uint64_t TSFlags; // Target Specific Flag values + const uint16_t *ImplicitUses; // Registers implicitly read by this instr + const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr + const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands + // Subtarget feature that this is deprecated on, if any + // -1 implies this is not deprecated by any single feature. It may still be + // deprecated due to a "complex" reason, below. + int64_t DeprecatedFeature; + // A complex method to determine is a certain is deprecated or not, and return // the reason for deprecation. bool (*ComplexDeprecationInfo)(MCInst &, MCSubtargetInfo &, std::string &); @@ -170,38 +170,23 @@ public: /// \brief Returns true if a certain instruction is deprecated and if so /// returns the reason in \p Info. bool getDeprecatedInfo(MCInst &MI, MCSubtargetInfo &STI, - std::string &Info) const { - if (ComplexDeprecationInfo) - return ComplexDeprecationInfo(MI, STI, Info); - if ((DeprecatedFeatureMask & STI.getFeatureBits()) != 0) { - // FIXME: it would be nice to include the subtarget feature here. - Info = "deprecated"; - return true; - } - return false; - } + std::string &Info) const; /// \brief Return the opcode number for this descriptor. - unsigned getOpcode() const { - return Opcode; - } + unsigned getOpcode() const { return Opcode; } /// \brief Return the number of declared MachineOperands for this /// MachineInstruction. Note that variadic (isVariadic() returns true) /// instructions may have additional operands at the end of the list, and note /// that the machine instruction may include implicit register def/uses as /// well. - unsigned getNumOperands() const { - return NumOperands; - } + unsigned getNumOperands() const { return NumOperands; } /// \brief Return the number of MachineOperands that are register /// definitions. Register definitions always occur at the start of the /// machine operand list. This is the number of "outs" in the .td file, /// and does not include implicit defs. - unsigned getNumDefs() const { - return NumDefs; - } + unsigned getNumDefs() const { return NumDefs; } /// \brief Return flags of this instruction. unsigned getFlags() const { return Flags; } @@ -210,39 +195,26 @@ public: /// operands. In this case, the variable operands will be after the normal /// operands but before the implicit definitions and uses (if any are /// present). - bool isVariadic() const { - return Flags & (1 << MCID::Variadic); - } + bool isVariadic() const { return Flags & (1 << MCID::Variadic); } /// \brief Set if this instruction has an optional definition, e.g. /// ARM instructions which can set condition code if 's' bit is set. - bool hasOptionalDef() const { - return Flags & (1 << MCID::HasOptionalDef); - } + bool hasOptionalDef() const { return Flags & (1 << MCID::HasOptionalDef); } /// \brief Return true if this is a pseudo instruction that doesn't /// correspond to a real machine instruction. - /// - bool isPseudo() const { - return Flags & (1 << MCID::Pseudo); - } + bool isPseudo() const { return Flags & (1 << MCID::Pseudo); } /// \brief Return true if the instruction is a return. - bool isReturn() const { - return Flags & (1 << MCID::Return); - } + bool isReturn() const { return Flags & (1 << MCID::Return); } /// \brief Return true if the instruction is a call. - bool isCall() const { - return Flags & (1 << MCID::Call); - } + bool isCall() const { return Flags & (1 << MCID::Call); } /// \brief Returns true if the specified instruction stops control flow /// from executing the instruction immediately following it. Examples include /// unconditional branches and return instructions. - bool isBarrier() const { - return Flags & (1 << MCID::Barrier); - } + bool isBarrier() const { return Flags & (1 << MCID::Barrier); } /// \brief Returns true if this instruction part of the terminator for /// a basic block. Typically this is things like return and branch @@ -250,23 +222,17 @@ public: /// /// Various passes use this to insert code into the bottom of a basic block, /// but before control flow occurs. - bool isTerminator() const { - return Flags & (1 << MCID::Terminator); - } + bool isTerminator() const { return Flags & (1 << MCID::Terminator); } /// \brief Returns true if this is a conditional, unconditional, or /// indirect branch. Predicates below can be used to discriminate between /// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to /// get more information. - bool isBranch() const { - return Flags & (1 << MCID::Branch); - } + bool isBranch() const { return Flags & (1 << MCID::Branch); } /// \brief Return true if this is an indirect branch, such as a /// branch through a register. - bool isIndirectBranch() const { - return Flags & (1 << MCID::IndirectBranch); - } + bool isIndirectBranch() const { return Flags & (1 << MCID::IndirectBranch); } /// \brief Return true if this is a branch which may fall /// through to the next instruction or may transfer control flow to some other @@ -287,79 +253,44 @@ public: /// \brief Return true if this is a branch or an instruction which directly /// writes to the program counter. Considered 'may' affect rather than /// 'does' affect as things like predication are not taken into account. - bool mayAffectControlFlow(const MCInst &MI, const MCRegisterInfo &RI) const { - if (isBranch() || isCall() || isReturn() || isIndirectBranch()) - return true; - unsigned PC = RI.getProgramCounter(); - if (PC == 0) - return false; - if (hasDefOfPhysReg(MI, PC, RI)) - return true; - // A variadic instruction may define PC in the variable operand list. - // There's currently no indication of which entries in a variable - // list are defs and which are uses. While that's the case, this function - // needs to assume they're defs in order to be conservatively correct. - for (int i = NumOperands, e = MI.getNumOperands(); i != e; ++i) { - if (MI.getOperand(i).isReg() && - RI.isSubRegisterEq(PC, MI.getOperand(i).getReg())) - return true; - } - return false; - } + bool mayAffectControlFlow(const MCInst &MI, const MCRegisterInfo &RI) const; /// \brief Return true if this instruction has a predicate operand /// that controls execution. It may be set to 'always', or may be set to other /// values. There are various methods in TargetInstrInfo that can be used to /// control and modify the predicate in this instruction. - bool isPredicable() const { - return Flags & (1 << MCID::Predicable); - } + bool isPredicable() const { return Flags & (1 << MCID::Predicable); } /// \brief Return true if this instruction is a comparison. - bool isCompare() const { - return Flags & (1 << MCID::Compare); - } + bool isCompare() const { return Flags & (1 << MCID::Compare); } /// \brief Return true if this instruction is a move immediate /// (including conditional moves) instruction. - bool isMoveImmediate() const { - return Flags & (1 << MCID::MoveImm); - } + bool isMoveImmediate() const { return Flags & (1 << MCID::MoveImm); } /// \brief Return true if this instruction is a bitcast instruction. - bool isBitcast() const { - return Flags & (1 << MCID::Bitcast); - } + bool isBitcast() const { return Flags & (1 << MCID::Bitcast); } /// \brief Return true if this is a select instruction. - bool isSelect() const { - return Flags & (1 << MCID::Select); - } + bool isSelect() const { return Flags & (1 << MCID::Select); } /// \brief 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. - bool isNotDuplicable() const { - return Flags & (1 << MCID::NotDuplicable); - } + bool isNotDuplicable() const { return Flags & (1 << MCID::NotDuplicable); } - /// hasDelaySlot - Returns true if the specified instruction has a delay slot - /// which must be filled by the code generator. - bool hasDelaySlot() const { - return Flags & (1 << MCID::DelaySlot); - } + /// \brief Returns true if the specified instruction has a delay slot which + /// must be filled by the code generator. + bool hasDelaySlot() const { return Flags & (1 << MCID::DelaySlot); } - /// canFoldAsLoad - Return true for instructions that can be folded as - /// memory operands in other instructions. The most common use for this - /// is instructions that are simple loads from memory that don't modify - /// the loaded value in any way, but it can also be used for instructions - /// that can be expressed as constant-pool loads, such as V_SETALLONES - /// on x86, to allow them to be folded when it is beneficial. - /// This should only be set on instructions that return a value in their - /// only virtual register definition. - bool canFoldAsLoad() const { - return Flags & (1 << MCID::FoldableAsLoad); - } + /// \brief Return true for instructions that can be folded as memory operands + /// in other instructions. The most common use for this is instructions that + /// are simple loads from memory that don't modify the loaded value in any + /// way, but it can also be used for instructions that can be expressed as + /// constant-pool loads, such as V_SETALLONES on x86, to allow them to be + /// folded when it is beneficial. This should only be set on instructions + /// that return a value in their only virtual register definition. + bool canFoldAsLoad() const { return Flags & (1 << MCID::FoldableAsLoad); } /// \brief Return true if this instruction behaves /// the same way as the generic REG_SEQUENCE instructions. @@ -398,9 +329,7 @@ public: /// Note that for the optimizers to be able to take advantage of /// this property, TargetInstrInfo::getInsertSubregLikeInputs has to be /// override accordingly. - bool isInsertSubregLike() const { - return Flags & (1 << MCID::InsertSubreg); - } + bool isInsertSubregLike() const { return Flags & (1 << MCID::InsertSubreg); } //===--------------------------------------------------------------------===// // Side Effect Analysis @@ -409,20 +338,15 @@ public: /// \brief Return true if this instruction could possibly read memory. /// Instructions with this flag set are not necessarily simple load /// instructions, they may load a value and modify it, for example. - bool mayLoad() const { - return Flags & (1 << MCID::MayLoad); - } - + bool mayLoad() const { return Flags & (1 << MCID::MayLoad); } /// \brief Return true if this instruction could possibly modify memory. /// Instructions with this flag set are not necessarily simple store /// instructions, they may store a modified value based on their operands, or /// may not actually modify anything, for example. - bool mayStore() const { - return Flags & (1 << MCID::MayStore); - } + bool mayStore() const { return Flags & (1 << MCID::MayStore); } - /// hasUnmodeledSideEffects - Return true if this instruction has side + /// \brief Return true if this instruction has side /// effects that are not modeled by other flags. This does not return true /// for instructions whose effects are captured by: /// @@ -434,7 +358,6 @@ public: /// Examples of side effects would be modifying 'invisible' machine state like /// a control register, flushing a cache, modifying a register invisible to /// LLVM, etc. - /// bool hasUnmodeledSideEffects() const { return Flags & (1 << MCID::UnmodeledSideEffects); } @@ -443,9 +366,9 @@ public: // Flags that indicate whether an instruction can be modified by a method. //===--------------------------------------------------------------------===// - /// isCommutable - Return true if this may be a 2- or 3-address - /// instruction (of the form "X = op Y, Z, ..."), which produces the same - /// result if Y and Z are exchanged. If this flag is set, then the + /// \brief Return true if this may be a 2- or 3-address instruction (of the + /// form "X = op Y, Z, ..."), which produces the same result if Y and Z are + /// exchanged. If this flag is set, then the /// TargetInstrInfo::commuteInstruction method may be used to hack on the /// instruction. /// @@ -453,18 +376,16 @@ public: /// sometimes. In these cases, the call to commuteInstruction will fail. /// Also note that some instructions require non-trivial modification to /// commute them. - bool isCommutable() const { - return Flags & (1 << MCID::Commutable); - } - - /// isConvertibleTo3Addr - Return true if this is a 2-address instruction - /// which can be changed into a 3-address instruction if needed. Doing this - /// transformation can be profitable in the register allocator, because it - /// means that the instruction can use a 2-address form if possible, but - /// degrade into a less efficient form if the source and dest register cannot - /// be assigned to the same register. For example, this allows the x86 - /// backend to turn a "shl reg, 3" instruction into an LEA instruction, which - /// is the same speed as the shift but has bigger code size. + bool isCommutable() const { return Flags & (1 << MCID::Commutable); } + + /// \brief Return true if this is a 2-address instruction which can be changed + /// into a 3-address instruction if needed. Doing this transformation can be + /// profitable in the register allocator, because it means that the + /// instruction can use a 2-address form if possible, but degrade into a less + /// efficient form if the source and dest register cannot be assigned to the + /// same register. For example, this allows the x86 backend to turn a "shl + /// reg, 3" instruction into an LEA instruction, which is the same speed as + /// the shift but has bigger code size. /// /// If this returns true, then the target must implement the /// TargetInstrInfo::convertToThreeAddress method for this instruction, which @@ -475,11 +396,11 @@ public: return Flags & (1 << MCID::ConvertibleTo3Addr); } - /// usesCustomInsertionHook - Return true if this instruction requires - /// custom insertion support when the DAG scheduler is inserting it into a - /// machine basic block. If this is true for the instruction, it basically - /// means that it is a pseudo instruction used at SelectionDAG time that is - /// expanded out into magic code by the target when MachineInstrs are formed. + /// \brief Return true if this instruction requires custom insertion support + /// when the DAG scheduler is inserting it into a machine basic block. If + /// this is true for the instruction, it basically means that it is a pseudo + /// instruction used at SelectionDAG time that is expanded out into magic code + /// by the target when MachineInstrs are formed. /// /// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method /// is used to insert this into the MachineBasicBlock. @@ -487,17 +408,14 @@ public: return Flags & (1 << MCID::UsesCustomInserter); } - /// hasPostISelHook - Return true if this instruction requires *adjustment* - /// after instruction selection by calling a target hook. For example, this - /// can be used to fill in ARM 's' optional operand depending on whether - /// the conditional flag register is used. - bool hasPostISelHook() const { - return Flags & (1 << MCID::HasPostISelHook); - } + /// \brief Return true if this instruction requires *adjustment* after + /// instruction selection by calling a target hook. For example, this can be + /// used to fill in ARM 's' optional operand depending on whether the + /// conditional flag register is used. + bool hasPostISelHook() const { return Flags & (1 << MCID::HasPostISelHook); } - /// isRematerializable - Returns true if this instruction is a candidate for - /// remat. This flag is only used in TargetInstrInfo method - /// isTriviallyRematerializable. + /// \brief Returns true if this instruction is a candidate for remat. This + /// flag is only used in TargetInstrInfo method isTriviallyRematerializable. /// /// If this flag is set, the isReallyTriviallyReMaterializable() /// or isReallyTriviallyReMaterializableGeneric methods are called to verify @@ -506,80 +424,76 @@ public: return Flags & (1 << MCID::Rematerializable); } - /// isAsCheapAsAMove - Returns true if this instruction has the same cost (or - /// less) than a move instruction. This is useful during certain types of - /// optimizations (e.g., remat during two-address conversion or machine licm) - /// where we would like to remat or hoist the instruction, but not if it costs - /// more than moving the instruction into the appropriate register. Note, we - /// are not marking copies from and to the same register class with this flag. + /// \brief Returns true if this instruction has the same cost (or less) than a + /// move instruction. This is useful during certain types of optimizations + /// (e.g., remat during two-address conversion or machine licm) where we would + /// like to remat or hoist the instruction, but not if it costs more than + /// moving the instruction into the appropriate register. Note, we are not + /// marking copies from and to the same register class with this flag. /// /// This method could be called by interface TargetInstrInfo::isAsCheapAsAMove /// for different subtargets. - bool isAsCheapAsAMove() const { - return Flags & (1 << MCID::CheapAsAMove); - } - - /// hasExtraSrcRegAllocReq - Returns true if this instruction source operands - /// have special register allocation requirements that are not captured by the - /// operand register classes. e.g. ARM::STRD's two source registers must be an - /// even / odd pair, ARM::STM registers have to be in ascending order. - /// Post-register allocation passes should not attempt to change allocations - /// for sources of instructions with this flag. + bool isAsCheapAsAMove() const { return Flags & (1 << MCID::CheapAsAMove); } + + /// \brief Returns true if this instruction source operands have special + /// register allocation requirements that are not captured by the operand + /// register classes. e.g. ARM::STRD's two source registers must be an even / + /// odd pair, ARM::STM registers have to be in ascending order. Post-register + /// allocation passes should not attempt to change allocations for sources of + /// instructions with this flag. bool hasExtraSrcRegAllocReq() const { return Flags & (1 << MCID::ExtraSrcRegAllocReq); } - /// hasExtraDefRegAllocReq - Returns true if this instruction def operands - /// have special register allocation requirements that are not captured by the - /// operand register classes. e.g. ARM::LDRD's two def registers must be an - /// even / odd pair, ARM::LDM registers have to be in ascending order. - /// Post-register allocation passes should not attempt to change allocations - /// for definitions of instructions with this flag. + /// \brief Returns true if this instruction def operands have special register + /// allocation requirements that are not captured by the operand register + /// classes. e.g. ARM::LDRD's two def registers must be an even / odd pair, + /// ARM::LDM registers have to be in ascending order. Post-register + /// allocation passes should not attempt to change allocations for definitions + /// of instructions with this flag. bool hasExtraDefRegAllocReq() const { return Flags & (1 << MCID::ExtraDefRegAllocReq); } - - /// getImplicitUses - Return a list of registers that are potentially - /// read by any instance of this machine instruction. For example, on X86, - /// the "adc" instruction adds two register operands and adds the carry bit in - /// from the flags register. In this case, the instruction is marked as - /// implicitly reading the flags. Likewise, the variable shift instruction on - /// X86 is marked as implicitly reading the 'CL' register, which it always - /// does. + /// \brief Return a list of registers that are potentially read by any + /// instance of this machine instruction. For example, on X86, the "adc" + /// instruction adds two register operands and adds the carry bit in from the + /// flags register. In this case, the instruction is marked as implicitly + /// reading the flags. Likewise, the variable shift instruction on X86 is + /// marked as implicitly reading the 'CL' register, which it always does. /// /// This method returns null if the instruction has no implicit uses. - const uint16_t *getImplicitUses() const { - return ImplicitUses; - } + const uint16_t *getImplicitUses() const { return ImplicitUses; } /// \brief Return the number of implicit uses this instruction has. unsigned getNumImplicitUses() const { - if (!ImplicitUses) return 0; + if (!ImplicitUses) + return 0; unsigned i = 0; - for (; ImplicitUses[i]; ++i) /*empty*/; + for (; ImplicitUses[i]; ++i) /*empty*/ + ; return i; } - /// getImplicitDefs - Return a list of registers that are potentially - /// written by any instance of this machine instruction. For example, on X86, - /// many instructions implicitly set the flags register. In this case, they - /// are marked as setting the FLAGS. Likewise, many instructions always - /// deposit their result in a physical register. For example, the X86 divide + /// \brief Return a list of registers that are potentially written by any + /// instance of this machine instruction. For example, on X86, many + /// instructions implicitly set the flags register. In this case, they are + /// marked as setting the FLAGS. Likewise, many instructions always deposit + /// their result in a physical register. For example, the X86 divide /// instruction always deposits the quotient and remainder in the EAX/EDX /// registers. For that instruction, this will return a list containing the /// EAX/EDX/EFLAGS registers. /// /// This method returns null if the instruction has no implicit defs. - const uint16_t *getImplicitDefs() const { - return ImplicitDefs; - } + const uint16_t *getImplicitDefs() const { return ImplicitDefs; } /// \brief Return the number of implicit defs this instruct has. unsigned getNumImplicitDefs() const { - if (!ImplicitDefs) return 0; + if (!ImplicitDefs) + return 0; unsigned i = 0; - for (; ImplicitDefs[i]; ++i) /*empty*/; + for (; ImplicitDefs[i]; ++i) /*empty*/ + ; return i; } @@ -588,45 +502,25 @@ public: bool hasImplicitUseOfPhysReg(unsigned Reg) const { if (const uint16_t *ImpUses = ImplicitUses) for (; *ImpUses; ++ImpUses) - if (*ImpUses == Reg) return true; + if (*ImpUses == Reg) + return true; return false; } /// \brief Return true if this instruction implicitly /// defines the specified physical register. bool hasImplicitDefOfPhysReg(unsigned Reg, - const MCRegisterInfo *MRI = nullptr) const { - if (const uint16_t *ImpDefs = ImplicitDefs) - for (; *ImpDefs; ++ImpDefs) - if (*ImpDefs == Reg || (MRI && MRI->isSubRegister(Reg, *ImpDefs))) - return true; - return false; - } - - /// \brief Return true if this instruction defines the specified physical - /// register, either explicitly or implicitly. - bool hasDefOfPhysReg(const MCInst &MI, unsigned Reg, - const MCRegisterInfo &RI) const { - for (int i = 0, e = NumDefs; i != e; ++i) - if (MI.getOperand(i).isReg() && - RI.isSubRegisterEq(Reg, MI.getOperand(i).getReg())) - return true; - return hasImplicitDefOfPhysReg(Reg, &RI); - } + const MCRegisterInfo *MRI = nullptr) const; /// \brief Return the scheduling class for this instruction. The /// scheduling class is an index into the InstrItineraryData table. This /// returns zero if there is no known scheduling information for the /// instruction. - unsigned getSchedClass() const { - return SchedClass; - } + unsigned getSchedClass() const { return SchedClass; } /// \brief Return the number of bytes in the encoding of this instruction, /// or zero if the encoding size cannot be known from the opcode. - unsigned getSize() const { - return Size; - } + unsigned getSize() const { return Size; } /// \brief Find the index of the first operand in the /// operand list that is used to represent the predicate. It returns -1 if @@ -639,6 +533,13 @@ public: } return -1; } + +private: + + /// \brief Return true if this instruction defines the specified physical + /// register, either explicitly or implicitly. + bool hasDefOfPhysReg(const MCInst &MI, unsigned Reg, + const MCRegisterInfo &RI) const; }; } // end namespace llvm diff --git a/include/llvm/MC/MCInstrInfo.h b/include/llvm/MC/MCInstrInfo.h index 1d3a36ca7c73..70c86587b08c 100644 --- a/include/llvm/MC/MCInstrInfo.h +++ b/include/llvm/MC/MCInstrInfo.h @@ -20,9 +20,7 @@ namespace llvm { //--------------------------------------------------------------------------- -/// -/// MCInstrInfo - Interface to description of machine instruction set -/// +/// \brief Interface to description of machine instruction set. class MCInstrInfo { const MCInstrDesc *Desc; // Raw array to allow static init'n const unsigned *InstrNameIndices; // Array for name indices in InstrNameData @@ -30,8 +28,8 @@ class MCInstrInfo { unsigned NumOpcodes; // Number of entries in the desc array public: - /// InitMCInstrInfo - Initialize MCInstrInfo, called by TableGen - /// auto-generated routines. *DO NOT USE*. + /// \brief Initialize MCInstrInfo, called by TableGen auto-generated routines. + /// *DO NOT USE*. void InitMCInstrInfo(const MCInstrDesc *D, const unsigned *NI, const char *ND, unsigned NO) { Desc = D; @@ -42,15 +40,14 @@ public: unsigned getNumOpcodes() const { return NumOpcodes; } - /// get - Return the machine instruction descriptor that corresponds to the + /// \brief Return the machine instruction descriptor that corresponds to the /// specified instruction opcode. - /// const MCInstrDesc &get(unsigned Opcode) const { assert(Opcode < NumOpcodes && "Invalid opcode!"); return Desc[Opcode]; } - /// getName - Returns the name for the instructions with the given opcode. + /// \brief Returns the name for the instructions with the given opcode. const char *getName(unsigned Opcode) const { assert(Opcode < NumOpcodes && "Invalid opcode!"); return &InstrNameData[InstrNameIndices[Opcode]]; diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h index 94d599f672af..161705de7c4e 100644 --- a/include/llvm/MC/MCInstrItineraries.h +++ b/include/llvm/MC/MCInstrItineraries.h @@ -67,12 +67,12 @@ struct InstrStage { int NextCycles_; ///< Number of machine cycles to next stage ReservationKinds Kind_; ///< Kind of the FU reservation - /// Returns the number of cycles the stage is occupied. + /// \brief Returns the number of cycles the stage is occupied. unsigned getCycles() const { return Cycles_; } - /// Returns the choice of FUs. + /// \brief Returns the choice of FUs. unsigned getUnits() const { return Units_; } @@ -81,8 +81,8 @@ struct InstrStage { return Kind_; } - /// Returns the number of cycles from the start of - /// this stage to the start of the next stage in the itinerary + /// \brief Returns the number of cycles from the start of this stage to the + /// start of the next stage in the itinerary unsigned getNextCycles() const { return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_; } @@ -115,7 +115,6 @@ public: const InstrItinerary *Itineraries; ///< Array of itineraries selected /// Ctors. - /// InstrItineraryData() : SchedModel(MCSchedModel::GetDefaultSchedModel()), Stages(nullptr), OperandCycles(nullptr), Forwardings(nullptr), Itineraries(nullptr) {} @@ -125,30 +124,30 @@ public: : SchedModel(SM), Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(SchedModel.InstrItineraries) {} - /// Returns true if there are no itineraries. + /// \brief Returns true if there are no itineraries. bool isEmpty() const { return Itineraries == nullptr; } - /// Returns true if the index is for the end marker itinerary. + /// \brief Returns true if the index is for the end marker itinerary. bool isEndMarker(unsigned ItinClassIndx) const { return ((Itineraries[ItinClassIndx].FirstStage == ~0U) && (Itineraries[ItinClassIndx].LastStage == ~0U)); } - /// Return the first stage of the itinerary. + /// \brief Return the first stage of the itinerary. const InstrStage *beginStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; return Stages + StageIdx; } - /// Return the last+1 stage of the itinerary. + /// \brief Return the last+1 stage of the itinerary. const InstrStage *endStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; return Stages + StageIdx; } - /// Return the total stage latency of the given class. - /// The latency is the maximum completion time for any stage in the itinerary. - /// If no stages exist, it defaults to one cycle. + /// \brief Return the total stage latency of the given class. The latency is + /// the maximum completion time for any stage in the itinerary. If no stages + /// exist, it defaults to one cycle. unsigned getStageLatency(unsigned ItinClassIndx) const { // If the target doesn't provide itinerary information, use a simple // non-zero default value for all instructions. @@ -165,8 +164,8 @@ public: return Latency; } - /// Return the cycle for the given class and operand. - /// Return -1 if no cycle is specified for the operand. + /// \brief Return the cycle for the given class and operand. Return -1 if no + /// cycle is specified for the operand. int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const { if (isEmpty()) return -1; @@ -179,11 +178,11 @@ public: return (int)OperandCycles[FirstIdx + OperandIdx]; } - /// Return true if there is a pipeline forwarding - /// between instructions of itinerary classes DefClass and UseClasses so that - /// value produced by an instruction of itinerary class DefClass, operand - /// index DefIdx can be bypassed when it's read by an instruction of - /// itinerary class UseClass, operand index UseIdx. + /// \brief Return true if there is a pipeline forwarding between instructions + /// of itinerary classes DefClass and UseClasses so that value produced by an + /// instruction of itinerary class DefClass, operand index DefIdx can be + /// bypassed when it's read by an instruction of itinerary class UseClass, + /// operand index UseIdx. bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const { unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle; @@ -202,9 +201,9 @@ public: Forwardings[FirstUseIdx + UseIdx]; } - /// Compute and return the use operand latency of a given - /// itinerary class and operand index if the value is produced by an - /// instruction of the specified itinerary class and def operand index. + /// \brief Compute and return the use operand latency of a given itinerary + /// class and operand index if the value is produced by an instruction of the + /// specified itinerary class and def operand index. int getOperandLatency(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const { if (isEmpty()) @@ -226,7 +225,7 @@ public: return UseCycle; } - /// Return the number of micro-ops that the given class decodes to. + /// \brief Return the number of micro-ops that the given class decodes to. /// Return -1 for classes that require dynamic lookup via TargetInstrInfo. int getNumMicroOps(unsigned ItinClassIndx) const { if (isEmpty()) diff --git a/include/llvm/MC/MCLabel.h b/include/llvm/MC/MCLabel.h index f531de8b40d9..de2d0af1423a 100644 --- a/include/llvm/MC/MCLabel.h +++ b/include/llvm/MC/MCLabel.h @@ -20,11 +20,11 @@ namespace llvm { class MCContext; class raw_ostream; - /// MCLabel - Instances of this class represent a label name in the MC file, - /// and MCLabel are created and unique'd by the MCContext class. MCLabel + /// \brief Instances of this class represent a label name in the MC file, + /// and MCLabel are created and uniqued by the MCContext class. MCLabel /// should only be constructed for valid instances in the object file. class MCLabel { - // Instance - the instance number of this Directional Local Label + // \brief The instance number of this Directional Local Label. unsigned Instance; private: // MCContext creates and uniques these. @@ -32,20 +32,19 @@ namespace llvm { MCLabel(unsigned instance) : Instance(instance) {} - MCLabel(const MCLabel&) LLVM_DELETED_FUNCTION; - void operator=(const MCLabel&) LLVM_DELETED_FUNCTION; + MCLabel(const MCLabel&) = delete; + void operator=(const MCLabel&) = delete; public: - /// getInstance - Get the current instance of this Directional Local Label. + /// \brief Get the current instance of this Directional Local Label. unsigned getInstance() const { return Instance; } - /// incInstance - Increment the current instance of this Directional Local - /// Label. + /// \brief Increment the current instance of this Directional Local Label. unsigned incInstance() { return ++Instance; } - /// print - Print the value to the stream \p OS. + /// \brief Print the value to the stream \p OS. void print(raw_ostream &OS) const; - /// dump - Print the value to stderr. + /// \brief Print the value to stderr. void dump() const; }; diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h index 890d6385aacd..a186a14b8001 100644 --- a/include/llvm/MC/MCLinkerOptimizationHint.h +++ b/include/llvm/MC/MCLinkerOptimizationHint.h @@ -103,8 +103,8 @@ class MCLOHDirective { /// Arguments of this directive. Order matters. SmallVector<MCSymbol *, 3> Args; - /// Emit this directive in @p OutStream using the information available - /// in the given @p ObjWriter and @p Layout to get the address of the + /// Emit this directive in \p OutStream using the information available + /// in the given \p ObjWriter and \p Layout to get the address of the /// arguments within the object file. void Emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const; @@ -128,8 +128,8 @@ public: Emit_impl(OutStream, ObjWriter, Layout); } - /// Get the size in bytes of this directive if emitted in @p ObjWriter with - /// the given @p Layout. + /// Get the size in bytes of this directive if emitted in \p ObjWriter with + /// the given \p Layout. uint64_t getEmitSize(const MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { class raw_counting_ostream : public raw_ostream { @@ -141,7 +141,7 @@ public: public: raw_counting_ostream() : Count(0) {} - ~raw_counting_ostream() { flush(); } + ~raw_counting_ostream() override { flush(); } }; raw_counting_ostream OutStream; @@ -167,8 +167,8 @@ public: return Directives; } - /// Add the directive of the given kind @p Kind with the given arguments - /// @p Args to the container. + /// Add the directive of the given kind \p Kind with the given arguments + /// \p Args to the container. void addDirective(MCLOHType Kind, const MCLOHDirective::LOHArgs &Args) { Directives.push_back(MCLOHDirective(Kind, Args)); } diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 0c5aa8a18063..63c2a28a7c9c 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -21,7 +21,6 @@ namespace llvm { -class MCSectionData; class MachObjectWriter; class MCMachObjectTargetWriter { @@ -45,14 +44,14 @@ protected: public: virtual ~MCMachObjectTargetWriter(); - /// @name Lifetime Management + /// \name Lifetime Management /// @{ virtual void reset() {}; /// @} - /// @name Accessors + /// \name Accessors /// @{ bool is64Bit() const { return Is64Bit; } @@ -65,15 +64,13 @@ public: /// @} - /// @name API + /// \name API /// @{ - virtual void RecordRelocation(MachObjectWriter *Writer, - const MCAssembler &Asm, + virtual void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, + const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) = 0; /// @} @@ -83,7 +80,7 @@ class MachObjectWriter : public MCObjectWriter { /// MachSymbolData - Helper struct for containing some precomputed information /// on symbols. struct MachSymbolData { - MCSymbolData *SymbolData; + const MCSymbol *Symbol; uint64_t StringIndex; uint8_t SectionIndex; @@ -94,15 +91,21 @@ class MachObjectWriter : public MCObjectWriter { /// The target specific Mach-O writer instance. std::unique_ptr<MCMachObjectTargetWriter> TargetObjectWriter; - /// @name Relocation Data + /// \name Relocation Data /// @{ - llvm::DenseMap<const MCSectionData*, - std::vector<MachO::any_relocation_info> > Relocations; - llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase; + struct RelAndSymbol { + const MCSymbol *Sym; + MachO::any_relocation_info MRE; + RelAndSymbol(const MCSymbol *Sym, const MachO::any_relocation_info &MRE) + : Sym(Sym), MRE(MRE) {} + }; + + llvm::DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations; + llvm::DenseMap<const MCSection *, unsigned> IndirectSymBase; /// @} - /// @name Symbol Table Data + /// \name Symbol Table Data /// @{ StringTableBuilder StringTable; @@ -115,19 +118,20 @@ class MachObjectWriter : public MCObjectWriter { MachSymbolData *findSymbolData(const MCSymbol &Sym); public: - MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS, - bool _IsLittleEndian) - : MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) { - } + MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_pwrite_stream &OS, + bool IsLittleEndian) + : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {} + + const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const; - /// @name Lifetime management Methods + /// \name Lifetime management Methods /// @{ void reset() override; /// @} - /// @name Utility Methods + /// \name Utility Methods /// @{ bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); @@ -136,23 +140,21 @@ public: SectionAddrMap &getSectionAddressMap() { return SectionAddress; } - uint64_t getSectionAddress(const MCSectionData* SD) const { - return SectionAddress.lookup(SD); + uint64_t getSectionAddress(const MCSection *Sec) const { + return SectionAddress.lookup(Sec); } - uint64_t getSymbolAddress(const MCSymbolData* SD, - const MCAsmLayout &Layout) const; + uint64_t getSymbolAddress(const MCSymbol &S, const MCAsmLayout &Layout) const; uint64_t getFragmentAddress(const MCFragment *Fragment, const MCAsmLayout &Layout) const; - uint64_t getPaddingSize(const MCSectionData *SD, - const MCAsmLayout &Layout) const; + uint64_t getPaddingSize(const MCSection *SD, const MCAsmLayout &Layout) const; - bool doesSymbolRequireExternRelocation(const MCSymbolData *SD); + bool doesSymbolRequireExternRelocation(const MCSymbol &S); /// @} - /// @name Target Writer Proxy Accessors + /// \name Target Writer Proxy Accessors /// @{ bool is64Bit() const { return TargetObjectWriter->is64Bit(); } @@ -176,7 +178,7 @@ public: uint64_t SectionDataSize); void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout, - const MCSectionData &SD, uint64_t FileOffset, + const MCSection &Sec, uint64_t FileOffset, uint64_t RelocationsStart, unsigned NumRelocations); void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, @@ -213,9 +215,15 @@ public: // - Input errors, where something cannot be correctly encoded. 'as' allows // these through in many cases. - void addRelocation(const MCSectionData *SD, + // Add a relocation to be output in the object file. At the time this is + // called, the symbol indexes are not know, so if the relocation refers + // to a symbol it should be passed as \p RelSymbol so that it can be updated + // afterwards. If the relocation doesn't refer to a symbol, nullptr should be + // used. + void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec, MachO::any_relocation_info &MRE) { - Relocations[SD].push_back(MRE); + RelAndSymbol P(RelSymbol, MRE); + Relocations[Sec].push_back(P); } void RecordScatteredRelocation(const MCAssembler &Asm, @@ -231,7 +239,7 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue); - void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) override; @@ -248,15 +256,12 @@ public: void computeSectionAddresses(const MCAssembler &Asm, const MCAsmLayout &Layout); - void markAbsoluteVariableSymbols(MCAssembler &Asm, - const MCAsmLayout &Layout); void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbolData &DataA, - const MCFragment &FB, - bool InSet, + const MCSymbol &SymA, + const MCFragment &FB, bool InSet, bool IsPCRel) const override; void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; @@ -271,7 +276,8 @@ public: /// \param OS - The stream to write to. /// \returns The constructed object writer. MCObjectWriter *createMachObjectWriter(MCMachObjectTargetWriter *MOTW, - raw_ostream &OS, bool IsLittleEndian); + raw_pwrite_stream &OS, + bool IsLittleEndian); } // End llvm namespace diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index 321043c522ee..f28b9c668cdc 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -53,144 +53,139 @@ protected: /// should emit only an EH frame. unsigned CompactUnwindDwarfEHFrameOnly; - /// TextSection - Section directive for standard text. + /// Section directive for standard text. /// - const MCSection *TextSection; + MCSection *TextSection; - /// DataSection - Section directive for standard data. + /// Section directive for standard data. /// - const MCSection *DataSection; + MCSection *DataSection; - /// BSSSection - Section that is default initialized to zero. - const MCSection *BSSSection; + /// Section that is default initialized to zero. + MCSection *BSSSection; - /// ReadOnlySection - Section that is readonly and can contain arbitrary - /// initialized data. Targets are not required to have a readonly section. - /// If they don't, various bits of code will fall back to using the data - /// section for constants. - const MCSection *ReadOnlySection; + /// Section that is readonly and can contain arbitrary initialized data. + /// Targets are not required to have a readonly section. If they don't, + /// various bits of code will fall back to using the data section for + /// constants. + MCSection *ReadOnlySection; - /// StaticCtorSection - This section contains the static constructor pointer - /// list. - const MCSection *StaticCtorSection; + /// This section contains the static constructor pointer list. + MCSection *StaticCtorSection; - /// StaticDtorSection - This section contains the static destructor pointer - /// list. - const MCSection *StaticDtorSection; + /// This section contains the static destructor pointer list. + MCSection *StaticDtorSection; - /// LSDASection - If exception handling is supported by the target, this is - /// the section the Language Specific Data Area information is emitted to. - const MCSection *LSDASection; + /// If exception handling is supported by the target, this is the section the + /// Language Specific Data Area information is emitted to. + MCSection *LSDASection; - /// CompactUnwindSection - If exception handling is supported by the target - /// and the target can support a compact representation of the CIE and FDE, - /// this is the section to emit them into. - const MCSection *CompactUnwindSection; + /// If exception handling is supported by the target and the target can + /// support a compact representation of the CIE and FDE, this is the section + /// to emit them into. + MCSection *CompactUnwindSection; // Dwarf sections for debug info. If a target supports debug info, these must // be set. - const MCSection *DwarfAbbrevSection; - const MCSection *DwarfInfoSection; - const MCSection *DwarfLineSection; - const MCSection *DwarfFrameSection; - const MCSection *DwarfPubTypesSection; + MCSection *DwarfAbbrevSection; + MCSection *DwarfInfoSection; + MCSection *DwarfLineSection; + MCSection *DwarfFrameSection; + MCSection *DwarfPubTypesSection; const MCSection *DwarfDebugInlineSection; - const MCSection *DwarfStrSection; - const MCSection *DwarfLocSection; - const MCSection *DwarfARangesSection; - const MCSection *DwarfRangesSection; - const MCSection *DwarfMacroInfoSection; + MCSection *DwarfStrSection; + MCSection *DwarfLocSection; + MCSection *DwarfARangesSection; + MCSection *DwarfRangesSection; // The pubnames section is no longer generated by default. The generation // can be enabled by a compiler flag. - const MCSection *DwarfPubNamesSection; + MCSection *DwarfPubNamesSection; // DWARF5 Experimental Debug Info Sections /// DwarfAccelNamesSection, DwarfAccelObjCSection, /// DwarfAccelNamespaceSection, DwarfAccelTypesSection - /// If we use the DWARF accelerated hash tables then we want to emit these /// sections. - const MCSection *DwarfAccelNamesSection; - const MCSection *DwarfAccelObjCSection; - const MCSection *DwarfAccelNamespaceSection; - const MCSection *DwarfAccelTypesSection; + MCSection *DwarfAccelNamesSection; + MCSection *DwarfAccelObjCSection; + MCSection *DwarfAccelNamespaceSection; + MCSection *DwarfAccelTypesSection; /// These are used for the Fission separate debug information files. - const MCSection *DwarfInfoDWOSection; - const MCSection *DwarfTypesDWOSection; - const MCSection *DwarfAbbrevDWOSection; - const MCSection *DwarfStrDWOSection; - const MCSection *DwarfLineDWOSection; - const MCSection *DwarfLocDWOSection; - const MCSection *DwarfStrOffDWOSection; - const MCSection *DwarfAddrSection; + MCSection *DwarfInfoDWOSection; + MCSection *DwarfTypesDWOSection; + MCSection *DwarfAbbrevDWOSection; + MCSection *DwarfStrDWOSection; + MCSection *DwarfLineDWOSection; + MCSection *DwarfLocDWOSection; + MCSection *DwarfStrOffDWOSection; + MCSection *DwarfAddrSection; /// Sections for newer gnu pubnames and pubtypes. - const MCSection *DwarfGnuPubNamesSection; - const MCSection *DwarfGnuPubTypesSection; + MCSection *DwarfGnuPubNamesSection; + MCSection *DwarfGnuPubTypesSection; - const MCSection *COFFDebugSymbolsSection; + MCSection *COFFDebugSymbolsSection; // Extra TLS Variable Data section. If the target needs to put additional // information for a TLS variable, it'll go here. - const MCSection *TLSExtraDataSection; + MCSection *TLSExtraDataSection; - /// TLSDataSection - Section directive for Thread Local data. - /// ELF, MachO and COFF. - const MCSection *TLSDataSection; // Defaults to ".tdata". + /// Section directive for Thread Local data. ELF, MachO and COFF. + MCSection *TLSDataSection; // Defaults to ".tdata". - /// TLSBSSSection - Section directive for Thread Local uninitialized data. - /// Null if this target doesn't support a BSS section. - /// ELF and MachO only. - const MCSection *TLSBSSSection; // Defaults to ".tbss". + /// Section directive for Thread Local uninitialized data. Null if this target + /// doesn't support a BSS section. ELF and MachO only. + MCSection *TLSBSSSection; // Defaults to ".tbss". /// StackMap section. - const MCSection *StackMapSection; + MCSection *StackMapSection; - /// EHFrameSection - EH frame section. It is initialized on demand so it - /// can be overwritten (with uniquing). - const MCSection *EHFrameSection; + /// EH frame section. It is initialized on demand so it can be overwritten + /// (with uniquing). + MCSection *EHFrameSection; /// ELF specific sections. /// - const MCSection *DataRelSection; + MCSection *DataRelSection; const MCSection *DataRelLocalSection; - const MCSection *DataRelROSection; - const MCSection *DataRelROLocalSection; - const MCSection *MergeableConst4Section; - const MCSection *MergeableConst8Section; - const MCSection *MergeableConst16Section; + MCSection *DataRelROSection; + MCSection *DataRelROLocalSection; + MCSection *MergeableConst4Section; + MCSection *MergeableConst8Section; + MCSection *MergeableConst16Section; /// MachO specific sections. /// - /// TLSTLVSection - Section for thread local structure information. - /// Contains the source code name of the variable, visibility and a pointer - /// to the initial value (.tdata or .tbss). - const MCSection *TLSTLVSection; // Defaults to ".tlv". + /// Section for thread local structure information. Contains the source code + /// name of the variable, visibility and a pointer to the initial value + /// (.tdata or .tbss). + MCSection *TLSTLVSection; // Defaults to ".tlv". /// TLSThreadInitSection - Section for thread local data initialization /// functions. const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func". - const MCSection *CStringSection; - const MCSection *UStringSection; - const MCSection *TextCoalSection; - const MCSection *ConstTextCoalSection; - const MCSection *ConstDataSection; - const MCSection *DataCoalSection; - const MCSection *DataCommonSection; - const MCSection *DataBSSSection; - const MCSection *FourByteConstantSection; - const MCSection *EightByteConstantSection; - const MCSection *SixteenByteConstantSection; - const MCSection *LazySymbolPointerSection; - const MCSection *NonLazySymbolPointerSection; + MCSection *CStringSection; + MCSection *UStringSection; + MCSection *TextCoalSection; + MCSection *ConstTextCoalSection; + MCSection *ConstDataSection; + MCSection *DataCoalSection; + MCSection *DataCommonSection; + MCSection *DataBSSSection; + MCSection *FourByteConstantSection; + MCSection *EightByteConstantSection; + MCSection *SixteenByteConstantSection; + MCSection *LazySymbolPointerSection; + MCSection *NonLazySymbolPointerSection; /// COFF specific sections. /// - const MCSection *DrectveSection; - const MCSection *PDataSection; - const MCSection *XDataSection; + MCSection *DrectveSection; + MCSection *PDataSection; + MCSection *XDataSection; public: void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM, @@ -215,97 +210,70 @@ public: return CompactUnwindDwarfEHFrameOnly; } - const MCSection *getTextSection() const { return TextSection; } - const MCSection *getDataSection() const { return DataSection; } - const MCSection *getBSSSection() const { return BSSSection; } - const MCSection *getLSDASection() const { return LSDASection; } - const MCSection *getCompactUnwindSection() const{ - return CompactUnwindSection; - } - const MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } - const MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } - const MCSection *getDwarfLineSection() const { return DwarfLineSection; } - const MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } - const MCSection *getDwarfPubNamesSection() const{return DwarfPubNamesSection;} - const MCSection *getDwarfPubTypesSection() const{return DwarfPubTypesSection;} - const MCSection *getDwarfGnuPubNamesSection() const { + MCSection *getTextSection() const { return TextSection; } + MCSection *getDataSection() const { return DataSection; } + MCSection *getBSSSection() const { return BSSSection; } + MCSection *getLSDASection() const { return LSDASection; } + MCSection *getCompactUnwindSection() const { return CompactUnwindSection; } + MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } + MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } + MCSection *getDwarfLineSection() const { return DwarfLineSection; } + MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } + MCSection *getDwarfPubNamesSection() const { return DwarfPubNamesSection; } + MCSection *getDwarfPubTypesSection() const { return DwarfPubTypesSection; } + MCSection *getDwarfGnuPubNamesSection() const { return DwarfGnuPubNamesSection; } - const MCSection *getDwarfGnuPubTypesSection() const { + MCSection *getDwarfGnuPubTypesSection() const { return DwarfGnuPubTypesSection; } const MCSection *getDwarfDebugInlineSection() const { return DwarfDebugInlineSection; } - const MCSection *getDwarfStrSection() const { return DwarfStrSection; } - const MCSection *getDwarfLocSection() const { return DwarfLocSection; } - const MCSection *getDwarfARangesSection() const { return DwarfARangesSection;} - const MCSection *getDwarfRangesSection() const { return DwarfRangesSection; } - const MCSection *getDwarfMacroInfoSection() const { - return DwarfMacroInfoSection; - } + MCSection *getDwarfStrSection() const { return DwarfStrSection; } + MCSection *getDwarfLocSection() const { return DwarfLocSection; } + MCSection *getDwarfARangesSection() const { return DwarfARangesSection; } + MCSection *getDwarfRangesSection() const { return DwarfRangesSection; } // DWARF5 Experimental Debug Info Sections - const MCSection *getDwarfAccelNamesSection() const { + MCSection *getDwarfAccelNamesSection() const { return DwarfAccelNamesSection; } - const MCSection *getDwarfAccelObjCSection() const { - return DwarfAccelObjCSection; - } - const MCSection *getDwarfAccelNamespaceSection() const { + MCSection *getDwarfAccelObjCSection() const { return DwarfAccelObjCSection; } + MCSection *getDwarfAccelNamespaceSection() const { return DwarfAccelNamespaceSection; } - const MCSection *getDwarfAccelTypesSection() const { + MCSection *getDwarfAccelTypesSection() const { return DwarfAccelTypesSection; } - const MCSection *getDwarfInfoDWOSection() const { - return DwarfInfoDWOSection; - } - const MCSection *getDwarfTypesSection(uint64_t Hash) const; - const MCSection *getDwarfTypesDWOSection() const { - return DwarfTypesDWOSection; - } - const MCSection *getDwarfAbbrevDWOSection() const { - return DwarfAbbrevDWOSection; - } - const MCSection *getDwarfStrDWOSection() const { - return DwarfStrDWOSection; - } - const MCSection *getDwarfLineDWOSection() const { - return DwarfLineDWOSection; - } - const MCSection *getDwarfLocDWOSection() const { - return DwarfLocDWOSection; - } - const MCSection *getDwarfStrOffDWOSection() const { - return DwarfStrOffDWOSection; - } - const MCSection *getDwarfAddrSection() const { - return DwarfAddrSection; - } - - const MCSection *getCOFFDebugSymbolsSection() const { + MCSection *getDwarfInfoDWOSection() const { return DwarfInfoDWOSection; } + MCSection *getDwarfTypesSection(uint64_t Hash) const; + MCSection *getDwarfTypesDWOSection() const { return DwarfTypesDWOSection; } + MCSection *getDwarfAbbrevDWOSection() const { return DwarfAbbrevDWOSection; } + MCSection *getDwarfStrDWOSection() const { return DwarfStrDWOSection; } + MCSection *getDwarfLineDWOSection() const { return DwarfLineDWOSection; } + MCSection *getDwarfLocDWOSection() const { return DwarfLocDWOSection; } + MCSection *getDwarfStrOffDWOSection() const { return DwarfStrOffDWOSection; } + MCSection *getDwarfAddrSection() const { return DwarfAddrSection; } + + MCSection *getCOFFDebugSymbolsSection() const { return COFFDebugSymbolsSection; } - const MCSection *getTLSExtraDataSection() const { - return TLSExtraDataSection; - } + MCSection *getTLSExtraDataSection() const { return TLSExtraDataSection; } const MCSection *getTLSDataSection() const { return TLSDataSection; } - const MCSection *getTLSBSSSection() const { return TLSBSSSection; } + MCSection *getTLSBSSSection() const { return TLSBSSSection; } - const MCSection *getStackMapSection() const { return StackMapSection; } + MCSection *getStackMapSection() const { return StackMapSection; } /// ELF specific sections. /// - const MCSection *getDataRelSection() const { return DataRelSection; } + MCSection *getDataRelSection() const { return DataRelSection; } const MCSection *getDataRelLocalSection() const { return DataRelLocalSection; } - const MCSection *getDataRelROSection() const { return DataRelROSection; } - const MCSection *getDataRelROLocalSection() const { - return DataRelROLocalSection; - } + MCSection *getDataRelROSection() const { return DataRelROSection; } + MCSection *getDataRelROLocalSection() const { return DataRelROLocalSection; } const MCSection *getMergeableConst4Section() const { return MergeableConst4Section; } @@ -324,14 +292,14 @@ public: } const MCSection *getCStringSection() const { return CStringSection; } const MCSection *getUStringSection() const { return UStringSection; } - const MCSection *getTextCoalSection() const { return TextCoalSection; } + MCSection *getTextCoalSection() const { return TextCoalSection; } const MCSection *getConstTextCoalSection() const { return ConstTextCoalSection; } const MCSection *getConstDataSection() const { return ConstDataSection; } const MCSection *getDataCoalSection() const { return DataCoalSection; } const MCSection *getDataCommonSection() const { return DataCommonSection; } - const MCSection *getDataBSSSection() const { return DataBSSSection; } + MCSection *getDataBSSSection() const { return DataBSSSection; } const MCSection *getFourByteConstantSection() const { return FourByteConstantSection; } @@ -341,20 +309,20 @@ public: const MCSection *getSixteenByteConstantSection() const { return SixteenByteConstantSection; } - const MCSection *getLazySymbolPointerSection() const { + MCSection *getLazySymbolPointerSection() const { return LazySymbolPointerSection; } - const MCSection *getNonLazySymbolPointerSection() const { + MCSection *getNonLazySymbolPointerSection() const { return NonLazySymbolPointerSection; } /// COFF specific sections. /// - const MCSection *getDrectveSection() const { return DrectveSection; } - const MCSection *getPDataSection() const { return PDataSection; } - const MCSection *getXDataSection() const { return XDataSection; } + MCSection *getDrectveSection() const { return DrectveSection; } + MCSection *getPDataSection() const { return PDataSection; } + MCSection *getXDataSection() const { return XDataSection; } - const MCSection *getEHFrameSection() { + MCSection *getEHFrameSection() { if (!EHFrameSection) InitEHFrameSection(); return EHFrameSection; diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 0866ff5a9fc0..e75bc86cc131 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -12,18 +12,19 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" namespace llvm { class MCAssembler; class MCCodeEmitter; -class MCSectionData; class MCSubtargetInfo; class MCExpr; class MCFragment; class MCDataFragment; class MCAsmBackend; class raw_ostream; +class raw_pwrite_stream; /// \brief Streaming object file generation interface. /// @@ -34,8 +35,8 @@ class raw_ostream; /// implementation. class MCObjectStreamer : public MCStreamer { MCAssembler *Assembler; - MCSectionData *CurSectionData; - MCSectionData::iterator CurInsertionPoint; + MCSection *CurSectionData; + MCSection::iterator CurInsertionPoint; bool EmitEHFrame; bool EmitDebugFrame; SmallVector<MCSymbolData *, 2> PendingLabels; @@ -44,16 +45,10 @@ class MCObjectStreamer : public MCStreamer { void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; - // If any labels have been emitted but not assigned fragments, ensure that - // they get assigned, either to F if possible or to a new data fragment. - void flushPendingLabels(MCFragment *F); - protected: - MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS, - MCCodeEmitter *_Emitter); - MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS, - MCCodeEmitter *_Emitter, MCAssembler *_Assembler); - ~MCObjectStreamer(); + MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS, + MCCodeEmitter *Emitter); + ~MCObjectStreamer() override; public: /// state management @@ -69,9 +64,7 @@ public: void EmitCFISections(bool EH, bool Debug) override; protected: - MCSectionData *getCurrentSectionData() const { - return CurSectionData; - } + MCSection *getCurrentSectionData() const { return CurSectionData; } MCFragment *getCurrentFragment() const; @@ -85,12 +78,20 @@ protected: /// fragment is not a data fragment. MCDataFragment *getOrCreateDataFragment(); + bool changeSectionImpl(MCSection *Section, const MCExpr *Subsection); + + /// If any labels have been emitted but not assigned fragments, ensure that + /// they get assigned, either to F if possible or to a new data fragment. + /// Optionally, it is also possible to provide an offset \p FOffset, which + /// will be used as a symbol offset within the fragment. + void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0); + public: void visitUsedSymbol(const MCSymbol &Sym) override; MCAssembler &getAssembler() { return *Assembler; } - /// @name MCStreamer Interface + /// \name MCStreamer Interface /// @{ void EmitLabel(MCSymbol *Symbol) override; @@ -100,8 +101,7 @@ public: void EmitULEB128Value(const MCExpr *Value) override; void EmitSLEB128Value(const MCExpr *Value) override; void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; - void ChangeSection(const MCSection *Section, - const MCExpr *Subsection) override; + void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo& STI) override; /// \brief Emit an instruction to a special fragment, because this instruction @@ -133,9 +133,18 @@ public: void EmitZeros(uint64_t NumBytes) override; void FinishImpl() override; - bool mayHaveInstructions() const override { - return getCurrentSectionData()->hasInstructions(); - } + /// Emit the absolute difference between two symbols if possible. + /// + /// Emit the absolute difference between \c Hi and \c Lo, as long as we can + /// compute it. Currently, that requires that both symbols are in the same + /// data fragment. Otherwise, do nothing and return \c false. + /// + /// \pre Offset of \c Hi is greater than the offset \c Lo. + /// \return true on success. + bool emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Size) override; + + bool mayHaveInstructions(MCSection &Sec) const override; }; } // end namespace llvm diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 55c828c6c179..999d29471270 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -13,6 +13,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/EndianStream.h" #include "llvm/Support/raw_ostream.h" #include <cassert> @@ -37,17 +38,17 @@ class MCValue; /// The object writer also contains a number of helper methods for writing /// binary data to the output stream. class MCObjectWriter { - MCObjectWriter(const MCObjectWriter &) LLVM_DELETED_FUNCTION; - void operator=(const MCObjectWriter &) LLVM_DELETED_FUNCTION; + MCObjectWriter(const MCObjectWriter &) = delete; + void operator=(const MCObjectWriter &) = delete; protected: - raw_ostream &OS; + raw_pwrite_stream &OS; unsigned IsLittleEndian : 1; protected: // Can only create subclasses. - MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian) - : OS(_OS), IsLittleEndian(_IsLittleEndian) {} + MCObjectWriter(raw_pwrite_stream &OS, bool IsLittleEndian) + : OS(OS), IsLittleEndian(IsLittleEndian) {} public: virtual ~MCObjectWriter(); @@ -59,7 +60,7 @@ public: raw_ostream &getStream() { return OS; } - /// @name High-Level API + /// \name High-Level API /// @{ /// \brief Perform any late binding of symbols (for example, to assign symbol @@ -76,30 +77,31 @@ public: /// post layout binding. The implementation is responsible for storing /// information about the relocation so that it can be emitted during /// WriteObject(). - virtual void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, + virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, - bool &IsPCRel, - uint64_t &FixedValue) = 0; + bool &IsPCRel, uint64_t &FixedValue) = 0; /// \brief Check whether the difference (A - B) between two symbol /// references is fully resolved. /// /// 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; + bool IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, + const MCSymbolRefExpr *A, + const MCSymbolRefExpr *B, + bool InSet) const; + + virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbol &SymA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const; + + /// \brief True if this symbol (which is a variable) is weak. This is not + /// just STB_WEAK, but more generally whether or not we can evaluate + /// past it. + virtual bool isWeak(const MCSymbol &Sym) const; /// \brief Write the object file. /// @@ -110,7 +112,7 @@ public: const MCAsmLayout &Layout) = 0; /// @} - /// @name Binary Output + /// \name Binary Output /// @{ void Write8(uint8_t Value) { @@ -118,33 +120,27 @@ public: } void WriteLE16(uint16_t Value) { - Write8(uint8_t(Value >> 0)); - Write8(uint8_t(Value >> 8)); + support::endian::Writer<support::little>(OS).write(Value); } void WriteLE32(uint32_t Value) { - WriteLE16(uint16_t(Value >> 0)); - WriteLE16(uint16_t(Value >> 16)); + support::endian::Writer<support::little>(OS).write(Value); } void WriteLE64(uint64_t Value) { - WriteLE32(uint32_t(Value >> 0)); - WriteLE32(uint32_t(Value >> 32)); + support::endian::Writer<support::little>(OS).write(Value); } void WriteBE16(uint16_t Value) { - Write8(uint8_t(Value >> 8)); - Write8(uint8_t(Value >> 0)); + support::endian::Writer<support::big>(OS).write(Value); } void WriteBE32(uint32_t Value) { - WriteBE16(uint16_t(Value >> 16)); - WriteBE16(uint16_t(Value >> 0)); + support::endian::Writer<support::big>(OS).write(Value); } void WriteBE64(uint64_t Value) { - WriteBE32(uint32_t(Value >> 32)); - WriteBE32(uint32_t(Value >> 0)); + support::endian::Writer<support::big>(OS).write(Value); } void Write16(uint16_t Value) { diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index a9a30f172071..62d39b26c860 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -31,8 +31,8 @@ class AsmLexer : public MCAsmLexer { StringRef CurBuf; bool isAtStartOfLine; - void operator=(const AsmLexer&) LLVM_DELETED_FUNCTION; - AsmLexer(const AsmLexer&) LLVM_DELETED_FUNCTION; + void operator=(const AsmLexer&) = delete; + AsmLexer(const AsmLexer&) = delete; protected: /// LexToken - Read the next token and return its code. @@ -40,7 +40,7 @@ protected: public: AsmLexer(const MCAsmInfo &MAI); - ~AsmLexer(); + ~AsmLexer() override; void setBuffer(StringRef Buf, const char *ptr = nullptr); diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index b05891c13250..71f15b37c331 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -63,10 +63,10 @@ private: public: AsmToken() {} - AsmToken(TokenKind _Kind, StringRef _Str, APInt _IntVal) - : Kind(_Kind), Str(_Str), IntVal(_IntVal) {} - AsmToken(TokenKind _Kind, StringRef _Str, int64_t _IntVal = 0) - : Kind(_Kind), Str(_Str), IntVal(64, _IntVal, true) {} + AsmToken(TokenKind Kind, StringRef Str, APInt IntVal) + : Kind(Kind), Str(Str), IntVal(IntVal) {} + AsmToken(TokenKind Kind, StringRef Str, int64_t IntVal = 0) + : Kind(Kind), Str(Str), IntVal(64, IntVal, true) {} TokenKind getKind() const { return Kind; } bool is(TokenKind K) const { return Kind == K; } @@ -124,8 +124,8 @@ class MCAsmLexer { SMLoc ErrLoc; std::string Err; - MCAsmLexer(const MCAsmLexer &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmLexer &) LLVM_DELETED_FUNCTION; + MCAsmLexer(const MCAsmLexer &) = delete; + void operator=(const MCAsmLexer &) = delete; protected: // Can only create subclasses. const char *TokStart; bool SkipSpace; diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index 34188e66e62d..0538b9457f9e 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -45,7 +45,7 @@ public: } }; -/// Generic Sema callback for assembly parser. +/// \brief Generic Sema callback for assembly parser. class MCAsmParserSemaCallback { public: virtual ~MCAsmParserSemaCallback(); @@ -59,8 +59,8 @@ public: unsigned &Offset) = 0; }; -/// Generic assembler parser interface, for use by target specific assembly -/// parsers. +/// \brief Generic assembler parser interface, for use by target specific +/// assembly parsers. class MCAsmParser { public: typedef bool (*DirectiveHandler)(MCAsmParserExtension*, StringRef, SMLoc); @@ -68,8 +68,8 @@ public: ExtensionDirectiveHandler; private: - MCAsmParser(const MCAsmParser &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmParser &) LLVM_DELETED_FUNCTION; + MCAsmParser(const MCAsmParser &) = delete; + void operator=(const MCAsmParser &) = delete; MCTargetAsmParser *TargetParser; @@ -84,6 +84,8 @@ public: virtual void addDirectiveHandler(StringRef Directive, ExtensionDirectiveHandler Handler) = 0; + virtual void addAliasForDirective(StringRef Directive, StringRef Alias) = 0; + virtual SourceMgr &getSourceManager() = 0; virtual MCAsmLexer &getLexer() = 0; @@ -93,7 +95,7 @@ public: virtual MCContext &getContext() = 0; - /// Return the output streamer for the assembler. + /// \brief Return the output streamer for the assembler. virtual MCStreamer &getStreamer() = 0; MCTargetAsmParser &getTargetParser() const { return *TargetParser; } @@ -105,13 +107,13 @@ public: bool getShowParsedOperands() const { return ShowParsedOperands; } void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; } - /// Run the parser on the input source buffer. + /// \brief Run the parser on the input source buffer. virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0; virtual void setParsingInlineAsm(bool V) = 0; virtual bool isParsingInlineAsm() = 0; - /// Parse ms-style inline assembly. + /// \brief Parse MS-style inline assembly. virtual bool parseMSInlineAsm( void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls, @@ -119,35 +121,35 @@ public: SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) = 0; - /// Emit a note at the location \p L, with the message \p Msg. + /// \brief Emit a note at the location \p L, with the message \p Msg. virtual void Note(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = None) = 0; - /// Emit a warning at the location \p L, with the message \p Msg. + /// \brief Emit a warning at the location \p L, with the message \p Msg. /// /// \return The return value is true, if warnings are fatal. virtual bool Warning(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = None) = 0; - /// Emit an error at the location \p L, with the message \p Msg. + /// \brief Emit an error at the location \p L, with the message \p Msg. /// /// \return The return value is always true, as an idiomatic convenience to /// clients. virtual bool Error(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = None) = 0; - /// Get the next AsmToken in the stream, possibly handling file inclusion - /// first. + /// \brief Get the next AsmToken in the stream, possibly handling file + /// inclusion first. virtual const AsmToken &Lex() = 0; - /// Get the current AsmToken from the stream. + /// \brief Get the current AsmToken from the stream. const AsmToken &getTok() const; /// \brief Report an error at the current lexer location. bool TokError(const Twine &Msg, ArrayRef<SMRange> Ranges = None); - /// Parse an identifier or string (as a quoted identifier) and set \p Res to - /// the identifier contents. + /// \brief Parse an identifier or string (as a quoted identifier) and set \p + /// Res to the identifier contents. virtual bool parseIdentifier(StringRef &Res) = 0; /// \brief Parse up to the end of statement and return the contents from the @@ -155,51 +157,51 @@ public: /// will be either the EndOfStatement or EOF. virtual StringRef parseStringToEndOfStatement() = 0; - /// Parse the current token as a string which may include escaped characters - /// and return the string contents. + /// \brief Parse the current token as a string which may include escaped + /// characters and return the string contents. virtual bool parseEscapedString(std::string &Data) = 0; - /// Skip to the end of the current statement, for error recovery. + /// \brief Skip to the end of the current statement, for error recovery. virtual void eatToEndOfStatement() = 0; - /// Parse an arbitrary expression. + /// \brief Parse an arbitrary expression. /// - /// @param Res - The value of the expression. The result is undefined + /// \param Res - The value of the expression. The result is undefined /// on error. - /// @result - False on success. + /// \return - False on success. virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; bool parseExpression(const MCExpr *&Res); - /// Parse a primary expression. + /// \brief Parse a primary expression. /// - /// @param Res - The value of the expression. The result is undefined + /// \param Res - The value of the expression. The result is undefined /// on error. - /// @result - False on success. + /// \return - False on success. virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) = 0; - /// Parse an arbitrary expression, assuming that an initial '(' has already - /// been consumed. + /// \brief Parse an arbitrary expression, assuming that an initial '(' has + /// already been consumed. /// - /// @param Res - The value of the expression. The result is undefined + /// \param Res - The value of the expression. The result is undefined /// on error. - /// @result - False on success. + /// \return - False on success. virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; - /// Parse an expression which must evaluate to an absolute value. + /// \brief Parse an expression which must evaluate to an absolute value. /// - /// @param Res - The value of the absolute expression. The result is undefined + /// \param Res - The value of the absolute expression. The result is undefined /// on error. - /// @result - False on success. + /// \return - False on success. virtual bool parseAbsoluteExpression(int64_t &Res) = 0; - /// Ensure that we have a valid section set in the streamer. Otherwise, report - /// an error and switch to .text. + /// \brief Ensure that we have a valid section set in the streamer. Otherwise, + /// report an error and switch to .text. virtual void checkForValidSection() = 0; }; /// \brief Create an MCAsmParser instance. -MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, - MCStreamer &, const MCAsmInfo &); +MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &, + const MCAsmInfo &); } // End llvm namespace diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h index bfc0afa132b7..077fd21e073c 100644 --- a/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -21,8 +21,8 @@ class Twine; /// which is implemented by target and object file assembly parser /// implementations. class MCAsmParserExtension { - MCAsmParserExtension(const MCAsmParserExtension &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmParserExtension &) LLVM_DELETED_FUNCTION; + MCAsmParserExtension(const MCAsmParserExtension &) = delete; + void operator=(const MCAsmParserExtension &) = delete; MCAsmParser *Parser; @@ -48,7 +48,7 @@ public: /// parsing routines. virtual void Initialize(MCAsmParser &Parser); - /// @name MCAsmParser Proxy Interfaces + /// \name MCAsmParser Proxy Interfaces /// @{ MCContext &getContext() { return getParser().getContext(); } diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h index e8740aa10aa2..a25108a0effb 100644 --- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -10,8 +10,11 @@ #ifndef LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H #define LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H +#include <string> +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SMLoc.h" + namespace llvm { -class SMLoc; class raw_ostream; /// MCParsedAsmOperand - This abstract class represents a source-level assembly diff --git a/include/llvm/MC/MCRelocationInfo.h b/include/llvm/MC/MCRelocationInfo.h index 9dab90099b7d..40e0217b8d83 100644 --- a/include/llvm/MC/MCRelocationInfo.h +++ b/include/llvm/MC/MCRelocationInfo.h @@ -28,8 +28,8 @@ class MCContext; /// \brief Create MCExprs from relocations found in an object file. class MCRelocationInfo { - MCRelocationInfo(const MCRelocationInfo &) LLVM_DELETED_FUNCTION; - void operator=(const MCRelocationInfo &) LLVM_DELETED_FUNCTION; + MCRelocationInfo(const MCRelocationInfo &) = delete; + void operator=(const MCRelocationInfo &) = delete; protected: MCContext &Ctx; diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index de2678adad61..96a4ef135f21 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -14,66 +14,163 @@ #ifndef LLVM_MC_MCSECTION_H #define LLVM_MC_MCSECTION_H +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" #include "llvm/MC/SectionKind.h" #include "llvm/Support/Compiler.h" namespace llvm { - class MCAsmInfo; - class MCExpr; - class raw_ostream; - - /// MCSection - Instances of this class represent a uniqued identifier for a - /// section in the current translation unit. The MCContext class uniques and - /// creates these. - class MCSection { - public: - enum SectionVariant { - SV_COFF = 0, - SV_ELF, - SV_MachO - }; - - private: - MCSection(const MCSection&) LLVM_DELETED_FUNCTION; - void operator=(const MCSection&) LLVM_DELETED_FUNCTION; - protected: - MCSection(SectionVariant V, SectionKind K) : Variant(V), Kind(K) {} - SectionVariant Variant; - SectionKind Kind; - public: - virtual ~MCSection(); - - SectionKind getKind() const { return Kind; } - - SectionVariant getVariant() const { return Variant; } - - virtual void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS, - const MCExpr *Subsection) const = 0; - - // Convenience routines to get label names for the beginning/end of a - // section. - virtual std::string getLabelBeginName() const = 0; - virtual std::string getLabelEndName() const = 0; - - /// isBaseAddressKnownZero - Return true if we know that this section will - /// get a base address of zero. In cases where we know that this is true we - /// can emit section offsets as direct references to avoid a subtraction - /// from the base of the section, saving a relocation. - virtual bool isBaseAddressKnownZero() const { - return false; - } - - // UseCodeAlign - Return true if a .align directive should use - // "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; +class MCAssembler; +class MCAsmInfo; +class MCContext; +class MCExpr; +class MCFragment; +class MCSection; +class MCSymbol; +class raw_ostream; + +/// Instances of this class represent a uniqued identifier for a section in the +/// current translation unit. The MCContext class uniques and creates these. +class MCSection { +public: + enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO }; + + /// \brief Express the state of bundle locked groups while emitting code. + enum BundleLockStateType { + NotBundleLocked, + BundleLocked, + BundleLockedAlignToEnd }; + typedef iplist<MCFragment> FragmentListType; + + typedef FragmentListType::const_iterator const_iterator; + typedef FragmentListType::iterator iterator; + + typedef FragmentListType::const_reverse_iterator const_reverse_iterator; + typedef FragmentListType::reverse_iterator reverse_iterator; + +private: + MCSection(const MCSection &) = delete; + void operator=(const MCSection &) = delete; + + MCSymbol *Begin; + MCSymbol *End = nullptr; + /// The alignment requirement of this section. + unsigned Alignment = 1; + /// The section index in the assemblers section list. + unsigned Ordinal = 0; + /// The index of this section in the layout order. + unsigned LayoutOrder; + + /// \brief Keeping track of bundle-locked state. + BundleLockStateType BundleLockState = NotBundleLocked; + + /// \brief Current nesting depth of bundle_lock directives. + unsigned BundleLockNestingDepth = 0; + + /// \brief We've seen a bundle_lock directive but not its first instruction + /// yet. + bool BundleGroupBeforeFirstInst = false; + + /// Whether this section has had instructions emitted into it. + unsigned HasInstructions : 1; + + FragmentListType Fragments; + + /// Mapping from subsection number to insertion point for subsection numbers + /// below that number. + SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap; + +protected: + MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin); + SectionVariant Variant; + SectionKind Kind; + +public: + virtual ~MCSection(); + + SectionKind getKind() const { return Kind; } + + SectionVariant getVariant() const { return Variant; } + + MCSymbol *getBeginSymbol() { return Begin; } + const MCSymbol *getBeginSymbol() const { + return const_cast<MCSection *>(this)->getBeginSymbol(); + } + void setBeginSymbol(MCSymbol *Sym) { + assert(!Begin); + Begin = Sym; + } + MCSymbol *getEndSymbol(MCContext &Ctx); + bool hasEnded() const; + + unsigned getAlignment() const { return Alignment; } + void setAlignment(unsigned Value) { Alignment = Value; } + + unsigned getOrdinal() const { return Ordinal; } + void setOrdinal(unsigned Value) { Ordinal = Value; } + + unsigned getLayoutOrder() const { return LayoutOrder; } + void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + + BundleLockStateType getBundleLockState() const { return BundleLockState; } + void setBundleLockState(BundleLockStateType NewState); + bool isBundleLocked() const { return BundleLockState != NotBundleLocked; } + + bool isBundleGroupBeforeFirstInst() const { + return BundleGroupBeforeFirstInst; + } + void setBundleGroupBeforeFirstInst(bool IsFirst) { + BundleGroupBeforeFirstInst = IsFirst; + } + + bool hasInstructions() const { return HasInstructions; } + void setHasInstructions(bool Value) { HasInstructions = Value; } + + MCSection::FragmentListType &getFragmentList() { return Fragments; } + const MCSection::FragmentListType &getFragmentList() const { + return const_cast<MCSection *>(this)->getFragmentList(); + } + + MCSection::iterator begin(); + MCSection::const_iterator begin() const { + return const_cast<MCSection *>(this)->begin(); + } + + MCSection::iterator end(); + MCSection::const_iterator end() const { + return const_cast<MCSection *>(this)->end(); + } + + MCSection::reverse_iterator rbegin(); + MCSection::const_reverse_iterator rbegin() const { + return const_cast<MCSection *>(this)->rbegin(); + } + + MCSection::reverse_iterator rend(); + MCSection::const_reverse_iterator rend() const { + return const_cast<MCSection *>(this)->rend(); + } + + MCSection::iterator getSubsectionInsertionPoint(unsigned Subsection); + + void dump(); + + virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, + const MCExpr *Subsection) const = 0; + + /// Return true if a .align directive should use "optimized nops" to fill + /// instead of 0s. + virtual bool UseCodeAlign() const = 0; + + /// Check whether this section is "virtual", that is has no actual object + /// file contents. + virtual bool isVirtualSection() const = 0; +}; + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index 0bbf3696686e..237f6d31fb1b 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -45,14 +45,15 @@ class MCSymbol; private: friend class MCContext; MCSectionCOFF(StringRef Section, unsigned Characteristics, - MCSymbol *COMDATSymbol, int Selection, SectionKind K) - : MCSection(SV_COFF, K), SectionName(Section), + MCSymbol *COMDATSymbol, int Selection, SectionKind K, + MCSymbol *Begin) + : MCSection(SV_COFF, K, Begin), SectionName(Section), Characteristics(Characteristics), COMDATSymbol(COMDATSymbol), Selection(Selection) { assert ((Characteristics & 0x00F00000) == 0 && "alignment must not be set upon section creation"); } - ~MCSectionCOFF(); + ~MCSectionCOFF() override; public: /// ShouldOmitSectionDirective - Decides whether a '.section' directive @@ -60,12 +61,6 @@ class MCSymbol; bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; StringRef getSectionName() const { return SectionName; } - std::string getLabelBeginName() const override { - return SectionName.str() + "_begin"; - } - std::string getLabelEndName() const override { - return SectionName.str() + "_end"; - } unsigned getCharacteristics() const { return Characteristics; } MCSymbol *getCOMDATSymbol() const { return COMDATSymbol; } int getSelection() const { return Selection; } diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 5ec23f1afad2..9efe1022f295 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -39,6 +39,8 @@ class MCSectionELF : public MCSection { /// below. unsigned Flags; + unsigned UniqueID; + /// EntrySize - The size of each entry in this section. This size only /// makes sense for sections that contain fixed-sized entries. If a /// section does not contain fixed-sized entries 'EntrySize' will be 0. @@ -46,13 +48,18 @@ class MCSectionELF : public MCSection { const MCSymbol *Group; + /// Depending on the type of the section this is sh_link or sh_info. + const MCSectionELF *Associated; + private: friend class MCContext; - MCSectionELF(StringRef Section, unsigned type, unsigned flags, - SectionKind K, unsigned entrySize, const MCSymbol *group) - : MCSection(SV_ELF, K), SectionName(Section), Type(type), Flags(flags), - EntrySize(entrySize), Group(group) {} - ~MCSectionELF(); + MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K, + unsigned entrySize, const MCSymbol *group, unsigned UniqueID, + MCSymbol *Begin, const MCSectionELF *Associated) + : MCSection(SV_ELF, K, Begin), SectionName(Section), Type(type), + Flags(flags), UniqueID(UniqueID), EntrySize(entrySize), Group(group), + Associated(Associated) {} + ~MCSectionELF() override; void setSectionName(StringRef Name) { SectionName = Name; } @@ -63,16 +70,6 @@ public: bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; StringRef getSectionName() const { return SectionName; } - std::string getLabelBeginName() const override { - if (Group) - return (SectionName.str() + '_' + Group->getName() + "_begin").str(); - return SectionName.str() + "_begin"; - } - std::string getLabelEndName() const override { - if (Group) - return (SectionName.str() + '_' + Group->getName() + "_end").str(); - return SectionName.str() + "_end"; - } unsigned getType() const { return Type; } unsigned getFlags() const { return Flags; } unsigned getEntrySize() const { return EntrySize; } @@ -83,19 +80,14 @@ public: bool UseCodeAlign() const override; bool isVirtualSection() const override; - /// isBaseAddressKnownZero - We know that non-allocatable sections (like - /// debug info) have a base of zero. - bool isBaseAddressKnownZero() const override { - return (getFlags() & ELF::SHF_ALLOC) == 0; - } + bool isUnique() const { return UniqueID != ~0U; } + unsigned getUniqueID() const { return UniqueID; } + + const MCSectionELF *getAssociatedSection() const { return Associated; } static bool classof(const MCSection *S) { return S->getVariant() == SV_ELF; } - - // Return the entry size for sections with fixed-width data. - static unsigned DetermineEntrySize(SectionKind Kind); - }; } // end namespace llvm diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h index a5a2089a2974..97227517c82d 100644 --- a/include/llvm/MC/MCSectionMachO.h +++ b/include/llvm/MC/MCSectionMachO.h @@ -35,8 +35,8 @@ class MCSectionMachO : public MCSection { /// size of stubs, for example. unsigned Reserved2; - MCSectionMachO(StringRef Segment, StringRef Section, - unsigned TAA, unsigned reserved2, SectionKind K); + MCSectionMachO(StringRef Segment, StringRef Section, unsigned TAA, + unsigned reserved2, SectionKind K, MCSymbol *Begin); friend class MCContext; public: @@ -53,14 +53,6 @@ public: return StringRef(SectionName); } - std::string getLabelBeginName() const override { - return StringRef(getSegmentName().str() + getSectionName().str() + "_begin"); - } - - std::string getLabelEndName() const override { - return StringRef(getSegmentName().str() + getSectionName().str() + "_end"); - } - unsigned getTypeAndAttributes() const { return TypeAndAttributes; } unsigned getStubSize() const { return Reserved2; } diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 18855f9cf03d..957913e934c4 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -16,12 +16,12 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCLinkerOptimizationHint.h" #include "llvm/MC/MCWinEH.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/SMLoc.h" #include <string> namespace llvm { @@ -42,7 +42,7 @@ class raw_ostream; class formatted_raw_ostream; class AssemblerConstantPools; -typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair; +typedef std::pair<MCSection *, const MCExpr *> MCSectionSubPair; /// Target specific streamer interface. This is used so that targets can /// implement support for target specific assembly directives. @@ -87,35 +87,12 @@ public: virtual void finish(); }; -class AArch64TargetStreamer : public MCTargetStreamer { -public: - AArch64TargetStreamer(MCStreamer &S); - ~AArch64TargetStreamer(); - - void finish() override; - - /// Callback used to implement the ldr= pseudo. - /// Add a new entry to the constant pool for the current section and return an - /// MCExpr that can be used to refer to the constant pool location. - const MCExpr *addConstantPoolEntry(const MCExpr *, unsigned Size); - - /// Callback used to implemnt the .ltorg directive. - /// Emit contents of constant pool for the current section. - void emitCurrentConstantPool(); - - /// Callback used to implement the .inst directive. - virtual void emitInst(uint32_t Inst); - -private: - std::unique_ptr<AssemblerConstantPools> ConstantPools; -}; - // FIXME: declared here because it is used from // lib/CodeGen/AsmPrinter/ARMException.cpp. class ARMTargetStreamer : public MCTargetStreamer { public: ARMTargetStreamer(MCStreamer &S); - ~ARMTargetStreamer(); + ~ARMTargetStreamer() override; virtual void emitFnStart(); virtual void emitFnEnd(); @@ -139,6 +116,7 @@ public: StringRef StringValue = ""); virtual void emitFPU(unsigned FPU); virtual void emitArch(unsigned Arch); + virtual void emitArchExtension(unsigned ArchExt); virtual void emitObjectArch(unsigned Arch); virtual void finishAttributeSection(); virtual void emitInst(uint32_t Inst, char Suffix = '\0'); @@ -162,11 +140,12 @@ private: std::unique_ptr<AssemblerConstantPools> ConstantPools; }; -/// MCStreamer - Streaming machine code generation interface. This interface -/// is intended to provide a programatic interface that is very similar to the -/// level that an assembler .s file provides. It has callbacks to emit bytes, -/// handle directives, etc. The implementation of this interface retains -/// state to know what the current section is etc. +/// \brief Streaming machine code generation interface. +/// +/// This interface is intended to provide a programatic interface that is very +/// similar to the level that an assembler .s file provides. It has callbacks +/// to emit bytes, handle directives, etc. The implementation of this interface +/// retains state to know what the current section is etc. /// /// There are multiple implementations of this interface: one for writing out /// a .s file, and implementations that write out .o files of various formats. @@ -175,8 +154,8 @@ class MCStreamer { MCContext &Context; std::unique_ptr<MCTargetStreamer> TargetStreamer; - MCStreamer(const MCStreamer &) LLVM_DELETED_FUNCTION; - MCStreamer &operator=(const MCStreamer &) LLVM_DELETED_FUNCTION; + MCStreamer(const MCStreamer &) = delete; + MCStreamer &operator=(const MCStreamer &) = delete; std::vector<MCDwarfFrameInfo> DwarfFrameInfos; MCDwarfFrameInfo *getCurrentDwarfFrameInfo(); @@ -188,12 +167,12 @@ class MCStreamer { WinEH::FrameInfo *CurrentWinFrameInfo; void EnsureValidWinFrameInfo(); - // SymbolOrdering - Tracks an index to represent the order - // a symbol was emitted in. Zero means we did not emit that symbol. + /// \brief Tracks an index to represent the order a symbol was emitted in. + /// Zero means we did not emit that symbol. DenseMap<const MCSymbol *, unsigned> SymbolOrdering; - /// SectionStack - This is stack of current and previous section - /// values saved by PushSection. + /// \brief This is stack of current and previous section values saved by + /// PushSection. SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack; protected: @@ -242,22 +221,24 @@ public: void generateCompactUnwindEncodings(MCAsmBackend *MAB); - /// @name Assembly File Formatting. + /// \name Assembly File Formatting. /// @{ - /// isVerboseAsm - Return true if this streamer supports verbose assembly - /// and if it is enabled. + /// \brief Return true if this streamer supports verbose assembly and if it is + /// enabled. virtual bool isVerboseAsm() const { return false; } - /// hasRawTextSupport - Return true if this asm streamer supports emitting - /// unformatted text to the .s file with EmitRawText. + /// \brief Return true if this asm streamer supports emitting unformatted text + /// to the .s file with EmitRawText. virtual bool hasRawTextSupport() const { return false; } - /// Is the integrated assembler required for this streamer to function + /// \brief Is the integrated assembler required for this streamer to function /// correctly? virtual bool isIntegratedAssemblerRequired() const { return false; } - /// AddComment - Add a comment that can be emitted to the generated .s + /// \brief Add a textual command. + /// + /// Typically for comments that can be emitted to the generated .s /// file if applicable as a QoI issue to make the output of the compiler /// more readable. This only affects the MCAsmStreamer, and only when /// verbose assembly output is enabled. @@ -266,14 +247,14 @@ public: /// prefix as appropriate. The added comment should not end with a \n. virtual void AddComment(const Twine &T) {} - /// GetCommentOS - Return a raw_ostream that comments can be written to. - /// Unlike AddComment, you are required to terminate comments with \n if you - /// use this method. + /// \brief Return a raw_ostream that comments can be written to. Unlike + /// AddComment, you are required to terminate comments with \n if you use this + /// method. virtual raw_ostream &GetCommentOS(); - /// Print T and prefix it with the comment string (normally #) and optionally - /// a tab. This prints the comment immediately, not at the end of the - /// current line. It is basically a safe version of EmitRawText: since it + /// \brief Print T and prefix it with the comment string (normally #) and + /// optionally a tab. This prints the comment immediately, not at the end of + /// the current line. It is basically a safe version of EmitRawText: since it /// only prints comments, the object streamer ignores it instead of asserting. virtual void emitRawComment(const Twine &T, bool TabPrefix = true); @@ -282,46 +263,43 @@ public: /// @} - /// @name Symbol & Section Management + /// \name Symbol & Section Management /// @{ - /// getCurrentSection - Return the current section that the streamer is - /// emitting code to. + /// \brief Return the current section that the streamer is emitting code to. MCSectionSubPair getCurrentSection() const { if (!SectionStack.empty()) return SectionStack.back().first; return MCSectionSubPair(); } - /// getPreviousSection - Return the previous section that the streamer is - /// emitting code to. + /// \brief Return the previous section that the streamer is emitting code to. MCSectionSubPair getPreviousSection() const { if (!SectionStack.empty()) return SectionStack.back().second; return MCSectionSubPair(); } - /// GetSymbolOrder - Returns an index to represent the order - /// a symbol was emitted in. (zero if we did not emit that symbol) + /// \brief Returns an index to represent the order a symbol was emitted in. + /// (zero if we did not emit that symbol) unsigned GetSymbolOrder(const MCSymbol *Sym) const { return SymbolOrdering.lookup(Sym); } - /// ChangeSection - Update streamer for a new active section. + /// \brief Update streamer for a new active section. /// /// This is called by PopSection and SwitchSection, if the current /// section changes. - virtual void ChangeSection(const MCSection *, const MCExpr *); + virtual void ChangeSection(MCSection *, const MCExpr *); - /// pushSection - Save the current and previous section on the - /// section stack. + /// \brief 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. + /// \brief Restore the current and previous section from the section stack. + /// Calls ChangeSection as needed. /// /// Returns false if the stack was empty. bool PopSection() { @@ -343,25 +321,17 @@ public: return true; } - /// SwitchSection - Set the current section where code is being emitted to - /// @p Section. This is required to update CurSection. + /// 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, - const MCExpr *Subsection = nullptr) { - assert(Section && "Cannot switch to a null section!"); - MCSectionSubPair curSection = SectionStack.back().first; - SectionStack.back().second = curSection; - if (MCSectionSubPair(Section, Subsection) != curSection) { - SectionStack.back().first = MCSectionSubPair(Section, Subsection); - ChangeSection(Section, Subsection); - } - } + virtual void SwitchSection(MCSection *Section, + const MCExpr *Subsection = nullptr); - /// SwitchSectionNoChange - Set the current section where code is being - /// emitted to @p Section. This is required to update CurSection. This - /// version does not call ChangeSection. - void SwitchSectionNoChange(const MCSection *Section, + /// \brief Set the current section where code is being emitted to \p Section. + /// This is required to update CurSection. This version does not call + /// ChangeSection. + void SwitchSectionNoChange(MCSection *Section, const MCExpr *Subsection = nullptr) { assert(Section && "Cannot switch to a null section!"); MCSectionSubPair curSection = SectionStack.back().first; @@ -370,21 +340,23 @@ public: SectionStack.back().first = MCSectionSubPair(Section, Subsection); } - /// Create the default sections and set the initial one. + /// \brief Create the default sections and set the initial one. virtual void InitSections(bool NoExecStack); - /// AssignSection - Sets the symbol's section. + MCSymbol *endSection(MCSection *Section); + + /// \brief Sets the symbol's section. /// /// Each emitted symbol will be tracked in the ordering table, /// so we can sort on them later. - void AssignSection(MCSymbol *Symbol, const MCSection *Section); + void AssignSection(MCSymbol *Symbol, MCSection *Section); - /// EmitLabel - Emit a label for @p Symbol into the current section. + /// \brief Emit a label for \p Symbol into the current section. /// /// This corresponds to an assembler statement such as: /// foo: /// - /// @param Symbol - The symbol to emit. A given symbol should only be + /// \param Symbol - The symbol to emit. A given symbol should only be /// emitted as a label once, and symbols emitted as a label should never be /// used in an assignment. // FIXME: These emission are non-const because we mutate the symbol to @@ -393,25 +365,25 @@ public: virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); - /// EmitAssemblerFlag - Note in the output the specified @p Flag. + /// \brief Note in the output the specified \p Flag. virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); - /// EmitLinkerOptions - Emit the given list @p Options of strings as linker + /// \brief Emit the given list \p Options of strings as linker /// options into the output. virtual void EmitLinkerOptions(ArrayRef<std::string> Kind) {} - /// EmitDataRegion - Note in the output the specified region @p Kind. + /// \brief Note in the output the specified region \p Kind. virtual void EmitDataRegion(MCDataRegionType Kind) {} - /// EmitVersionMin - Specify the MachO minimum deployment target version. + /// \brief Specify the MachO minimum deployment target version. virtual void EmitVersionMin(MCVersionMinType, unsigned Major, unsigned Minor, unsigned Update) {} - /// EmitThumbFunc - Note in the output that the specified @p Func is - /// a Thumb mode function (ARM target only). + /// \brief Note in the output that the specified \p Func is a Thumb mode + /// function (ARM target only). virtual void EmitThumbFunc(MCSymbol *Func); - /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. + /// \brief Emit an assignment of \p Value to \p Symbol. /// /// This corresponds to an assembler statement such as: /// symbol = value @@ -420,133 +392,131 @@ public: /// value in the current context. For the assembly streamer, this prints the /// binding into the .s file. /// - /// @param Symbol - The symbol being assigned to. - /// @param Value - The value for the symbol. + /// \param Symbol - The symbol being assigned to. + /// \param Value - The value for the symbol. virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); - /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol. + /// \brief Emit an weak reference from \p Alias to \p Symbol. /// /// This corresponds to an assembler statement such as: /// .weakref alias, symbol /// - /// @param Alias - The alias that is being created. - /// @param Symbol - The symbol being aliased. + /// \param Alias - The alias that is being created. + /// \param Symbol - The symbol being aliased. virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. + /// \brief Add the given \p Attribute to \p Symbol. virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) = 0; - /// EmitSymbolDesc - Set the @p DescValue for the @p Symbol. + /// \brief Set the \p DescValue for the \p Symbol. /// - /// @param Symbol - The symbol to have its n_desc field set. - /// @param DescValue - The value to set into the n_desc field. + /// \param Symbol - The symbol to have its n_desc field set. + /// \param DescValue - The value to set into the n_desc field. virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); - /// BeginCOFFSymbolDef - Start emitting COFF symbol definition + /// \brief Start emitting COFF symbol definition /// - /// @param Symbol - The symbol to have its External & Type fields set. + /// \param Symbol - The symbol to have its External & Type fields set. virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol); - /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol. + /// \brief Emit the storage class of the symbol. /// - /// @param StorageClass - The storage class the symbol should have. + /// \param StorageClass - The storage class the symbol should have. virtual void EmitCOFFSymbolStorageClass(int StorageClass); - /// EmitCOFFSymbolType - Emit the type of the symbol. + /// \brief Emit the type of the symbol. /// - /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) + /// \param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) virtual void EmitCOFFSymbolType(int Type); - /// EndCOFFSymbolDef - Marks the end of the symbol definition. + /// \brief Marks the end of the symbol definition. virtual void EndCOFFSymbolDef(); - /// EmitCOFFSectionIndex - Emits a COFF section index. + /// \brief Emits a COFF section index. /// - /// @param Symbol - Symbol the section number relocation should point to. + /// \param Symbol - Symbol the section number relocation should point to. virtual void EmitCOFFSectionIndex(MCSymbol const *Symbol); - /// EmitCOFFSecRel32 - Emits a COFF section relative relocation. + /// \brief Emits a COFF section relative relocation. /// - /// @param Symbol - Symbol the section relative relocation should point to. + /// \param Symbol - Symbol the section relative relocation should point to. virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); - /// EmitELFSize - Emit an ELF .size directive. + /// \brief Emit an ELF .size directive. /// /// This corresponds to an assembler statement such as: /// .size symbol, expression - /// virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); /// \brief Emit a Linker Optimization Hint (LOH) directive. /// \param Args - Arguments of the LOH. virtual void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {} - /// EmitCommonSymbol - Emit a common symbol. + /// \brief Emit a common symbol. /// - /// @param Symbol - The common symbol to emit. - /// @param Size - The size of the common symbol. - /// @param ByteAlignment - The alignment of the symbol if + /// \param Symbol - The common symbol to emit. + /// \param Size - The size of the common symbol. + /// \param ByteAlignment - The alignment of the symbol if /// non-zero. This must be a power of 2. virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) = 0; - /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. + /// \brief Emit a local common (.lcomm) symbol. /// - /// @param Symbol - The common symbol to emit. - /// @param Size - The size of the common symbol. - /// @param ByteAlignment - The alignment of the common symbol in bytes. + /// \param Symbol - The common symbol to emit. + /// \param Size - The size of the common symbol. + /// \param ByteAlignment - The alignment of the common symbol in bytes. virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); - /// EmitZerofill - Emit the zerofill section and an optional symbol. + /// \brief Emit the zerofill section and an optional symbol. /// - /// @param Section - The zerofill section to create and or to put the symbol - /// @param Symbol - The zerofill symbol to emit, if non-NULL. - /// @param Size - The size of the zerofill symbol. - /// @param ByteAlignment - The alignment of the zerofill symbol if + /// \param Section - The zerofill section to create and or to put the symbol + /// \param Symbol - The zerofill symbol to emit, if non-NULL. + /// \param Size - The size of the zerofill symbol. + /// \param ByteAlignment - The alignment of the zerofill symbol if /// non-zero. This must be a power of 2 on some targets. - virtual void EmitZerofill(const MCSection *Section, - MCSymbol *Symbol = nullptr, uint64_t Size = 0, - unsigned ByteAlignment = 0) = 0; + virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, unsigned ByteAlignment = 0) = 0; - /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol. + /// \brief Emit a thread local bss (.tbss) symbol. /// - /// @param Section - The thread local common section. - /// @param Symbol - The thread local common symbol to emit. - /// @param Size - The size of the symbol. - /// @param ByteAlignment - The alignment of the thread local common symbol + /// \param Section - The thread local common section. + /// \param Symbol - The thread local common symbol to emit. + /// \param Size - The size of the symbol. + /// \param ByteAlignment - The alignment of the thread local common symbol /// if non-zero. This must be a power of 2 on some targets. - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + virtual void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment = 0); /// @} - /// @name Generating Data + /// \name Generating Data /// @{ - /// EmitBytes - Emit the bytes in \p Data into the output. + /// \brief Emit the bytes in \p Data into the output. /// /// This is used to implement assembler directives such as .byte, .ascii, /// etc. virtual void EmitBytes(StringRef Data); - /// EmitValue - Emit the expression @p Value into the output as a native - /// integer of the given @p Size bytes. + /// \brief Emit the expression \p Value into the output as a native + /// integer of the given \p Size bytes. /// /// This is used to implement assembler directives such as .word, .quad, /// etc. /// - /// @param Value - The value to emit. - /// @param Size - The size of the integer (in bytes) to emit. This must + /// \param Value - The value to emit. + /// \param Size - The size of the integer (in bytes) to emit. This must /// match a native machine width. - /// @param Loc - The location of the expression for error reporting. + /// \param Loc - The location of the expression for error reporting. virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, const SMLoc &Loc = SMLoc()); void EmitValue(const MCExpr *Value, unsigned Size, const SMLoc &Loc = SMLoc()); - /// EmitIntValue - Special case of EmitValue that avoids the client having + /// \brief 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); @@ -554,112 +524,119 @@ public: virtual void EmitSLEB128Value(const MCExpr *Value); - /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the - /// client having to pass in a MCExpr for constant integers. + /// \brief Special case of EmitULEB128Value that avoids the client having to + /// pass in a MCExpr for constant integers. void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0); - /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the - /// client having to pass in a MCExpr for constant integers. + /// \brief Special case of EmitSLEB128Value that avoids the client having to + /// pass in a MCExpr for constant integers. void EmitSLEB128IntValue(int64_t Value); - /// EmitSymbolValue - Special case of EmitValue that avoids the client - /// having to pass in a MCExpr for MCSymbols. + /// \brief Special case of EmitValue that avoids the client having to pass in + /// a MCExpr for MCSymbols. void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, bool IsSectionRelative = false); - /// EmitGPRel64Value - Emit the expression @p Value into the output as a - /// gprel64 (64-bit GP relative) value. + /// \brief Emit the expression \p Value into the output as a gprel64 (64-bit + /// GP relative) value. /// /// This is used to implement assembler directives such as .gpdword on /// targets that support them. virtual void EmitGPRel64Value(const MCExpr *Value); - /// EmitGPRel32Value - Emit the expression @p Value into the output as a - /// gprel32 (32-bit GP relative) value. + /// \brief 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); - /// EmitFill - Emit NumBytes bytes worth of the value specified by - /// FillValue. This implements directives such as '.space'. + /// \brief Emit NumBytes bytes worth of the value specified by FillValue. + /// This implements directives such as '.space'. virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); /// \brief Emit NumBytes worth of zeros. /// This function properly handles data in virtual sections. virtual void EmitZeros(uint64_t NumBytes); - /// EmitValueToAlignment - Emit some number of copies of @p Value until - /// the byte alignment @p ByteAlignment is reached. + /// \brief Emit some number of copies of \p Value until the byte alignment \p + /// ByteAlignment is reached. /// /// If the number of bytes need to emit for the alignment is not a multiple - /// of @p ValueSize, then the contents of the emitted fill bytes is + /// of \p ValueSize, then the contents of the emitted fill bytes is /// undefined. /// /// This used to implement the .align assembler directive. /// - /// @param ByteAlignment - The alignment to reach. This must be a power of + /// \param ByteAlignment - The alignment to reach. This must be a power of /// two on some targets. - /// @param Value - The value to use when filling bytes. - /// @param ValueSize - The size of the integer (in bytes) to emit for - /// @p Value. This must match a native machine width. - /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// \param Value - The value to use when filling bytes. + /// \param ValueSize - The size of the integer (in bytes) to emit for + /// \p Value. This must match a native machine width. + /// \param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If /// the alignment cannot be reached in this many bytes, no bytes are /// emitted. virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, unsigned MaxBytesToEmit = 0); - /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment - /// is reached. + /// \brief Emit nops until the byte alignment \p ByteAlignment is reached. /// /// This used to align code where the alignment bytes may be executed. This /// can emit different bytes for different sizes to optimize execution. /// - /// @param ByteAlignment - The alignment to reach. This must be a power of + /// \param ByteAlignment - The alignment to reach. This must be a power of /// two on some targets. - /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// \param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If /// the alignment cannot be reached in this many bytes, no bytes are /// emitted. virtual void EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit = 0); - /// EmitValueToOffset - Emit some number of copies of @p Value until the - /// byte offset @p Offset is reached. + /// \brief Emit some number of copies of \p Value until the byte offset \p + /// Offset is reached. /// /// This is used to implement assembler directives such as .org. /// - /// @param Offset - The offset to reach. This may be an expression, but the + /// \param Offset - The offset to reach. This may be an expression, but the /// expression must be associated with the current section. - /// @param Value - The value to use when filling bytes. - /// @return false on success, true if the offset was invalid. + /// \param Value - The value to use when filling bytes. + /// \return false on success, true if the offset was invalid. virtual bool EmitValueToOffset(const MCExpr *Offset, unsigned char Value = 0); /// @} - /// EmitFileDirective - Switch to a new logical file. This is used to - /// implement the '.file "foo.c"' assembler directive. + /// \brief Switch to a new logical file. This is used to implement the '.file + /// "foo.c"' assembler directive. virtual void EmitFileDirective(StringRef Filename); - /// Emit the "identifiers" directive. This implements the + /// \brief Emit the "identifiers" directive. This implements the /// '.ident "version foo"' assembler directive. virtual void EmitIdent(StringRef IdentString) {} - /// EmitDwarfFileDirective - Associate a filename with a specified logical - /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler - /// directive. + /// \brief Associate a filename with a specified logical file number. This + /// implements the DWARF2 '.file 4 "foo.c"' assembler directive. virtual unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, StringRef Filename, unsigned CUID = 0); - /// EmitDwarfLocDirective - This implements the DWARF2 - // '.loc fileno lineno ...' assembler directive. + /// \brief This implements the DWARF2 '.loc fileno lineno ...' assembler + /// directive. virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, unsigned Discriminator, StringRef FileName); + /// Emit the absolute difference between two symbols if possible. + /// + /// \pre Offset of \c Hi is greater than the offset \c Lo. + /// \return true on success. + virtual bool emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Size) { + return false; + } + virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID); virtual void EmitCFISections(bool EH, bool Debug); void EmitCFIStartProc(bool IsSimple); @@ -697,8 +674,7 @@ public: virtual void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except); virtual void EmitWinEHHandlerData(); - /// EmitInstruction - Emit the given @p Instruction into the current - /// section. + /// \brief Emit the given \p Instruction into the current section. virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI); /// \brief Set the bundle alignment mode from now on in the section. @@ -715,29 +691,28 @@ public: /// \brief Ends a bundle-locked group. virtual void EmitBundleUnlock(); - /// EmitRawText - If this file is backed by a assembly streamer, this dumps - /// the specified string in the output .s file. This capability is - /// indicated by the hasRawTextSupport() predicate. By default this aborts. + /// \brief If this file is backed by a assembly streamer, this dumps the + /// specified string in the output .s file. This capability is indicated by + /// the hasRawTextSupport() predicate. By default this aborts. void EmitRawText(const Twine &String); - /// Flush - Causes any cached state to be written out. + /// \brief Causes any cached state to be written out. virtual void Flush() {} - /// FinishImpl - Streamer specific finalization. + /// \brief Streamer specific finalization. virtual void FinishImpl(); - /// Finish - Finish emission of machine code. + /// \brief Finish emission of machine code. void Finish(); - virtual bool mayHaveInstructions() const { return true; } + virtual bool mayHaveInstructions(MCSection &Sec) const { return true; } }; -/// createNullStreamer - Create a dummy machine code streamer, which does -/// nothing. This is useful for timing the assembler front end. +/// Create a dummy machine code streamer, which does nothing. This is useful for +/// timing the assembler front end. MCStreamer *createNullStreamer(MCContext &Ctx); -/// createAsmStreamer - Create a machine code streamer which will print out -/// assembly for the native target, suitable for compiling with a native -/// assembler. +/// Create a machine code streamer which will print out assembly for the native +/// target, suitable for compiling with a native assembler. /// /// \param InstPrint - If given, the instruction printer to use. If not given /// the MCInst representation will be printed. This method takes ownership of @@ -752,26 +727,11 @@ MCStreamer *createNullStreamer(MCContext &Ctx); /// /// \param ShowInst - Whether to show the MCInst representation inline with /// the assembly. -MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, +MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr<formatted_raw_ostream> OS, bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); - -/// createMachOStreamer - Create a machine code streamer which will generate -/// Mach-O format object files. -/// -/// Takes ownership of \p TAB and \p CE. -MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll = false, - bool LabelSections = false); - -/// createELFStreamer - Create a machine code streamer which will generate -/// ELF format object files. -MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll); - } // end namespace llvm #endif diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 3f38bd59a576..1778a6d13fb8 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -28,6 +28,7 @@ class StringRef; /// class MCSubtargetInfo { std::string TargetTriple; // Target triple + std::string CPU; // CPU being targeted. ArrayRef<SubtargetFeatureKV> ProcFeatures; // Processor feature list ArrayRef<SubtargetFeatureKV> ProcDesc; // Processor descriptions @@ -41,7 +42,7 @@ class MCSubtargetInfo { const InstrStage *Stages; // Instruction itinerary stages const unsigned *OperandCycles; // Itinerary operand cycles const unsigned *ForwardingPaths; // Forwarding paths - uint64_t FeatureBits; // Feature bits for current CPU + FS + FeatureBitset FeatureBits; // Feature bits for current CPU + FS public: void InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS, @@ -59,15 +60,20 @@ public: return TargetTriple; } + /// getCPU - Return the CPU string. + StringRef getCPU() const { + return CPU; + } + /// getFeatureBits - Return the feature bits. /// - uint64_t getFeatureBits() const { + const FeatureBitset& getFeatureBits() const { return FeatureBits; } /// setFeatureBits - Set the feature bits. /// - void setFeatureBits(uint64_t FeatureBits_) { FeatureBits = FeatureBits_; } + void setFeatureBits(FeatureBitset& FeatureBits_) { FeatureBits = FeatureBits_; } /// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with /// feature string). Recompute feature bits and scheduling model. @@ -78,11 +84,15 @@ public: /// ToggleFeature - Toggle a feature and returns the re-computed feature /// bits. This version does not change the implied bits. - uint64_t ToggleFeature(uint64_t FB); + FeatureBitset ToggleFeature(uint64_t FB); /// ToggleFeature - Toggle a feature and returns the re-computed feature - /// bits. This version will also change all implied bits. - uint64_t ToggleFeature(StringRef FS); + /// bits. This version does not change the implied bits. + FeatureBitset ToggleFeature(const FeatureBitset& FB); + + /// ToggleFeature - Toggle a set of features and returns the re-computed + /// feature bits. This version will also change all implied bits. + FeatureBitset ToggleFeature(StringRef FS); /// getSchedModelForCPU - Get the machine model of a CPU. /// diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index 47a8789d463b..cf99c919281e 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -14,168 +14,298 @@ #ifndef LLVM_MC_MCSYMBOL_H #define LLVM_MC_MCSYMBOL_H -#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/MC/MCExpr.h" #include "llvm/Support/Compiler.h" namespace llvm { - class MCExpr; - class MCSection; - class MCContext; - class raw_ostream; - - /// MCSymbol - Instances of this class represent a symbol name in the MC file, - /// and MCSymbols are created and unique'd by the MCContext class. MCSymbols - /// should only be constructed with valid names for the object file. +class MCExpr; +class MCSymbol; +class MCFragment; +class MCSection; +class MCContext; +class raw_ostream; + +// TODO: Merge completely with MCSymbol. +class MCSymbolData { + /// Fragment - The fragment this symbol's value is relative to, if any. Also + /// stores if this symbol is visible outside this translation unit (bit 0) or + /// if it is private extern (bit 1). + PointerIntPair<MCFragment *, 2> Fragment; + + union { + /// Offset - The offset to apply to the fragment address to form this + /// symbol's value. + uint64_t Offset; + + /// CommonSize - The size of the symbol, if it is 'common'. + uint64_t CommonSize; + }; + + /// SymbolSize - An expression describing how to calculate the size of + /// a symbol. If a symbol has no size this field will be NULL. + const MCExpr *SymbolSize = nullptr; + + /// CommonAlign - The alignment of the symbol, if it is 'common', or -1. + // + // FIXME: Pack this in with other fields? + unsigned CommonAlign = -1U; + + /// Flags - The Flags field is used by object file implementations to store + /// additional per symbol information which is not easily classified. + uint32_t Flags = 0; + +public: + MCSymbolData() { Offset = 0; } + + MCFragment *getFragment() const { return Fragment.getPointer(); } + void setFragment(MCFragment *Value) { Fragment.setPointer(Value); } + + uint64_t getOffset() const { + assert(!isCommon()); + return Offset; + } + void setOffset(uint64_t Value) { + assert(!isCommon()); + Offset = Value; + } + + /// @} + /// \name Symbol Attributes + /// @{ + + bool isExternal() const { return Fragment.getInt() & 1; } + void setExternal(bool Value) { + Fragment.setInt((Fragment.getInt() & ~1) | unsigned(Value)); + } + + bool isPrivateExtern() const { return Fragment.getInt() & 2; } + void setPrivateExtern(bool Value) { + Fragment.setInt((Fragment.getInt() & ~2) | (unsigned(Value) << 1)); + } + + /// isCommon - Is this a 'common' symbol. + bool isCommon() const { return CommonAlign != -1U; } + + /// setCommon - Mark this symbol as being 'common'. /// - /// If the symbol is defined/emitted into the current translation unit, the - /// Section member is set to indicate what section it lives in. Otherwise, if - /// it is a reference to an external entity, it has a null section. - class MCSymbol { - // Special sentinal value for the absolute pseudo section. - // - // FIXME: Use a PointerInt wrapper for this? - static const MCSection *AbsolutePseudoSection; - - /// Name - The name of the symbol. The referred-to string data is actually - /// held by the StringMap that lives in MCContext. - StringRef Name; - - /// Section - The section the symbol is defined in. This is null for - /// undefined symbols, and the special AbsolutePseudoSection value for - /// absolute symbols. - const MCSection *Section; - - /// Value - If non-null, the value for a variable symbol. - const MCExpr *Value; - - /// IsTemporary - True if this is an assembler temporary label, which - /// typically does not survive in the .o file's symbol table. Usually - /// "Lfoo" or ".foo". - unsigned IsTemporary : 1; - - /// \brief True if this symbol can be redefined. - unsigned IsRedefinable : 1; - - /// IsUsed - True if this symbol has been used. - mutable unsigned IsUsed : 1; - - private: // MCContext creates and uniques these. - friend class MCExpr; - friend class MCContext; - MCSymbol(StringRef name, bool isTemporary) - : Name(name), Section(nullptr), Value(nullptr), - IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false) {} - - MCSymbol(const MCSymbol&) LLVM_DELETED_FUNCTION; - void operator=(const MCSymbol&) LLVM_DELETED_FUNCTION; - public: - /// getName - Get the symbol name. - StringRef getName() const { return Name; } - - /// @name Accessors - /// @{ - - /// isTemporary - Check if this is an assembler temporary symbol. - bool isTemporary() const { return IsTemporary; } - - /// isUsed - Check if this is used. - bool isUsed() const { return IsUsed; } - void setUsed(bool Value) const { IsUsed = Value; } - - /// \brief Check if this symbol is redefinable. - bool isRedefinable() const { return IsRedefinable; } - /// \brief Mark this symbol as redefinable. - void setRedefinable(bool Value) { IsRedefinable = Value; } - /// \brief Prepare this symbol to be redefined. - void redefineIfPossible() { - if (IsRedefinable) { - Value = nullptr; - Section = nullptr; - IsRedefinable = false; - } - } + /// \param Size - The size of the symbol. + /// \param Align - The alignment of the symbol. + void setCommon(uint64_t Size, unsigned Align) { + assert(getOffset() == 0); + CommonSize = Size; + CommonAlign = Align; + } - /// @} - /// @name Associated Sections - /// @{ + /// getCommonSize - Return the size of a 'common' symbol. + uint64_t getCommonSize() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonSize; + } - /// isDefined - Check if this symbol is defined (i.e., it has an address). - /// - /// Defined symbols are either absolute or in some section. - bool isDefined() const { - return Section != nullptr; - } + void setSize(const MCExpr *SS) { SymbolSize = SS; } - /// isInSection - Check if this symbol is defined in some section (i.e., it - /// is defined but not absolute). - bool isInSection() const { - return isDefined() && !isAbsolute(); - } + const MCExpr *getSize() const { return SymbolSize; } - /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). - bool isUndefined() const { - return !isDefined(); - } + /// getCommonAlignment - Return the alignment of a 'common' symbol. + unsigned getCommonAlignment() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonAlign; + } - /// isAbsolute - Check if this is an absolute symbol. - bool isAbsolute() const { - return Section == AbsolutePseudoSection; - } + /// getFlags - Get the (implementation defined) symbol flags. + uint32_t getFlags() const { return Flags; } - /// getSection - Get the section associated with a defined, non-absolute - /// symbol. - const MCSection &getSection() const { - assert(isInSection() && "Invalid accessor!"); - return *Section; - } + /// setFlags - Set the (implementation defined) symbol flags. + void setFlags(uint32_t Value) { Flags = Value; } - /// setSection - Mark the symbol as defined in the section \p S. - void setSection(const MCSection &S) { Section = &S; } + /// modifyFlags - Modify the flags via a mask + void modifyFlags(uint32_t Value, uint32_t Mask) { + Flags = (Flags & ~Mask) | Value; + } + + /// @} + + void dump() const; +}; + +/// MCSymbol - Instances of this class represent a symbol name in the MC file, +/// and MCSymbols are created and uniqued by the MCContext class. MCSymbols +/// should only be constructed with valid names for the object file. +/// +/// If the symbol is defined/emitted into the current translation unit, the +/// Section member is set to indicate what section it lives in. Otherwise, if +/// it is a reference to an external entity, it has a null section. +class MCSymbol { + // Special sentinal value for the absolute pseudo section. + // + // FIXME: Use a PointerInt wrapper for this? + static MCSection *AbsolutePseudoSection; + + /// Name - The name of the symbol. The referred-to string data is actually + /// held by the StringMap that lives in MCContext. + const StringMapEntry<bool> *Name; + + /// The section the symbol is defined in. This is null for undefined symbols, + /// and the special AbsolutePseudoSection value for absolute symbols. If this + /// is a variable symbol, this caches the variable value's section. + mutable MCSection *Section; + + /// Value - If non-null, the value for a variable symbol. + const MCExpr *Value; + + /// IsTemporary - True if this is an assembler temporary label, which + /// typically does not survive in the .o file's symbol table. Usually + /// "Lfoo" or ".foo". + unsigned IsTemporary : 1; + + /// \brief True if this symbol can be redefined. + unsigned IsRedefinable : 1; + + /// IsUsed - True if this symbol has been used. + mutable unsigned IsUsed : 1; + + mutable bool HasData : 1; + + /// Index field, for use by the object file implementation. + mutable uint64_t Index : 60; + + mutable MCSymbolData Data; + +private: // MCContext creates and uniques these. + friend class MCExpr; + friend class MCContext; + MCSymbol(const StringMapEntry<bool> *Name, bool isTemporary) + : Name(Name), Section(nullptr), Value(nullptr), IsTemporary(isTemporary), + IsRedefinable(false), IsUsed(false), HasData(false), Index(0) {} + + MCSymbol(const MCSymbol &) = delete; + void operator=(const MCSymbol &) = delete; + MCSection *getSectionPtr() const { + if (Section || !Value) + return Section; + return Section = Value->FindAssociatedSection(); + } + +public: + /// getName - Get the symbol name. + StringRef getName() const { return Name ? Name->first() : ""; } + + bool hasData() const { return HasData; } + + /// Get associated symbol data. + MCSymbolData &getData() const { + assert(HasData && "Missing symbol data!"); + return Data; + } - /// setUndefined - Mark the symbol as undefined. - void setUndefined() { + /// Initialize symbol data. + /// + /// Nothing really to do here, but this is enables an assertion that \a + /// MCAssembler::getOrCreateSymbolData() has actually been called before + /// anyone calls \a getData(). + void initializeData() const { HasData = true; } + + /// \name Accessors + /// @{ + + /// isTemporary - Check if this is an assembler temporary symbol. + bool isTemporary() const { return IsTemporary; } + + /// isUsed - Check if this is used. + bool isUsed() const { return IsUsed; } + void setUsed(bool Value) const { IsUsed = Value; } + + /// \brief Check if this symbol is redefinable. + bool isRedefinable() const { return IsRedefinable; } + /// \brief Mark this symbol as redefinable. + void setRedefinable(bool Value) { IsRedefinable = Value; } + /// \brief Prepare this symbol to be redefined. + void redefineIfPossible() { + if (IsRedefinable) { + Value = nullptr; Section = nullptr; + IsRedefinable = false; } + } - /// setAbsolute - Mark the symbol as absolute. - void setAbsolute() { Section = AbsolutePseudoSection; } + /// @} + /// \name Associated Sections + /// @{ - /// @} - /// @name Variable Symbols - /// @{ + /// isDefined - Check if this symbol is defined (i.e., it has an address). + /// + /// Defined symbols are either absolute or in some section. + bool isDefined() const { return getSectionPtr() != nullptr; } - /// isVariable - Check if this is a variable symbol. - bool isVariable() const { - return Value != nullptr; - } + /// isInSection - Check if this symbol is defined in some section (i.e., it + /// is defined but not absolute). + bool isInSection() const { return isDefined() && !isAbsolute(); } - /// getVariableValue() - Get the value for variable symbols. - const MCExpr *getVariableValue() const { - assert(isVariable() && "Invalid accessor!"); - IsUsed = true; - return Value; - } + /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). + bool isUndefined() const { return !isDefined(); } - // AliasedSymbol() - If this is an alias (a = b), return the symbol - // we ultimately point to. For a non-alias, this just returns the symbol - // itself. - const MCSymbol &AliasedSymbol() const; + /// isAbsolute - Check if this is an absolute symbol. + bool isAbsolute() const { return getSectionPtr() == AbsolutePseudoSection; } - void setVariableValue(const MCExpr *Value); + /// Get the section associated with a defined, non-absolute symbol. + MCSection &getSection() const { + assert(isInSection() && "Invalid accessor!"); + return *getSectionPtr(); + } - /// @} + /// Mark the symbol as defined in the section \p S. + void setSection(MCSection &S) { + assert(!isVariable() && "Cannot set section of variable"); + Section = &S; + } - /// print - Print the value to the stream \p OS. - void print(raw_ostream &OS) const; + /// setUndefined - Mark the symbol as undefined. + void setUndefined() { Section = nullptr; } - /// dump - Print the value to stderr. - void dump() const; - }; + /// @} + /// \name Variable Symbols + /// @{ + + /// isVariable - Check if this is a variable symbol. + bool isVariable() const { return Value != nullptr; } + + /// getVariableValue() - Get the value for variable symbols. + const MCExpr *getVariableValue() const { + assert(isVariable() && "Invalid accessor!"); + IsUsed = true; + return Value; + } + + void setVariableValue(const MCExpr *Value); - inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { - Sym.print(OS); - return OS; + /// @} + + /// Get the (implementation defined) index. + uint64_t getIndex() const { + assert(HasData && "Uninitialized symbol data"); + return Index; + } + + /// Set the (implementation defined) index. + void setIndex(uint64_t Value) const { + assert(HasData && "Uninitialized symbol data"); + assert(!(Value >> 60) && "Not enough bits for value"); + Index = Value; } + + /// print - Print the value to the stream \p OS. + void print(raw_ostream &OS) const; + + /// dump - Print the value to stderr. + void dump() const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { + Sym.print(OS); + return OS; +} } // end namespace llvm #endif diff --git a/include/llvm/MC/MCSymbolizer.h b/include/llvm/MC/MCSymbolizer.h index cbbb591f1b80..2ef17673f091 100644 --- a/include/llvm/MC/MCSymbolizer.h +++ b/include/llvm/MC/MCSymbolizer.h @@ -38,8 +38,8 @@ class raw_ostream; /// operands are actually symbolizable, and in what way. I don't think this /// information exists right now. class MCSymbolizer { - MCSymbolizer(const MCSymbolizer &) LLVM_DELETED_FUNCTION; - void operator=(const MCSymbolizer &) LLVM_DELETED_FUNCTION; + MCSymbolizer(const MCSymbolizer &) = delete; + void operator=(const MCSymbolizer &) = delete; protected: MCContext &Ctx; @@ -59,14 +59,14 @@ public: /// represent this immediate in a more understandable way, for instance as a /// symbol or an offset from a symbol. Relocations can also be used to enrich /// the symbolic expression. - /// @param Inst - The MCInst where to insert the symbolic operand. - /// @param cStream - Stream to print comments and annotations on. - /// @param Value - Operand value, pc-adjusted by the caller if necessary. - /// @param Address - Load address of the instruction. - /// @param IsBranch - Is the instruction a branch? - /// @param Offset - Byte offset of the operand inside the inst. - /// @param InstSize - Size of the instruction in bytes. - /// @return Whether a symbolic operand was added. + /// \param Inst - The MCInst where to insert the symbolic operand. + /// \param cStream - Stream to print comments and annotations on. + /// \param Value - Operand value, pc-adjusted by the caller if necessary. + /// \param Address - Load address of the instruction. + /// \param IsBranch - Is the instruction a branch? + /// \param Offset - Byte offset of the operand inside the inst. + /// \param InstSize - Size of the instruction in bytes. + /// \return Whether a symbolic operand was added. virtual bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream, int64_t Value, uint64_t Address, bool IsBranch, uint64_t Offset, diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index ea71d1f433a4..36db3914f017 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -75,8 +75,6 @@ struct ParseInstructionInfo { ParseInstructionInfo() : AsmRewrites(nullptr) {} ParseInstructionInfo(SmallVectorImpl<AsmRewrite> *rewrites) : AsmRewrites(rewrites) {} - - ~ParseInstructionInfo() {} }; /// MCTargetAsmParser - Generic interface to target specific assembly parsers. @@ -91,8 +89,8 @@ public: }; private: - MCTargetAsmParser(const MCTargetAsmParser &) LLVM_DELETED_FUNCTION; - void operator=(const MCTargetAsmParser &) LLVM_DELETED_FUNCTION; + MCTargetAsmParser(const MCTargetAsmParser &) = delete; + void operator=(const MCTargetAsmParser &) = delete; protected: // Can only create subclasses. MCTargetAsmParser(); @@ -110,7 +108,7 @@ protected: // Can only create subclasses. MCTargetOptions MCOptions; public: - virtual ~MCTargetAsmParser(); + ~MCTargetAsmParser() override; uint64_t getAvailableFeatures() const { return AvailableFeatures; } void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } diff --git a/include/llvm/MC/MCValue.h b/include/llvm/MC/MCValue.h index dd86979690cf..6bdf43685f21 100644 --- a/include/llvm/MC/MCValue.h +++ b/include/llvm/MC/MCValue.h @@ -23,10 +23,11 @@ namespace llvm { class MCAsmInfo; class raw_ostream; -/// MCValue - This represents an "assembler immediate". In its most -/// general form, this can hold ":Kind:(SymbolA - SymbolB + imm64)". -/// Not all targets supports relocations of this general form, but we -/// need to represent this anyway. +/// \brief This represents an "assembler immediate". +/// +/// In its most general form, this can hold ":Kind:(SymbolA - SymbolB + +/// imm64)". Not all targets supports relocations of this general form, but we +/// need to represent this anyway. /// /// In general both SymbolA and SymbolB will also have a modifier /// analogous to the top-level Kind. Current targets are not expected @@ -51,13 +52,13 @@ public: const MCSymbolRefExpr *getSymB() const { return SymB; } uint32_t getRefKind() const { return RefKind; } - /// isAbsolute - Is this an absolute (as opposed to relocatable) value. + /// \brief Is this an absolute (as opposed to relocatable) value. bool isAbsolute() const { return !SymA && !SymB; } - /// print - Print the value to the stream \p OS. - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + /// \brief Print the value to the stream \p OS. + void print(raw_ostream &OS) const; - /// dump - Print the value to stderr. + /// \brief Print the value to stderr. void dump() const; MCSymbolRefExpr::VariantKind getAccessVariant() const; diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h index dad7bb597039..e2e95c7df710 100644 --- a/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -11,10 +11,12 @@ #define LLVM_MC_MCWINCOFFOBJECTWRITER_H namespace llvm { - class MCFixup; - class MCObjectWriter; - class MCValue; - class raw_ostream; +class MCAsmBackend; +class MCFixup; +class MCObjectWriter; +class MCValue; +class raw_ostream; +class raw_pwrite_stream; class MCWinCOFFObjectTargetWriter { virtual void anchor(); @@ -27,9 +29,9 @@ namespace llvm { virtual ~MCWinCOFFObjectTargetWriter() {} unsigned getMachine() const { return Machine; } - virtual unsigned getRelocType(const MCValue &Target, - const MCFixup &Fixup, - bool IsCrossSection) const = 0; + virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsCrossSection, + const MCAsmBackend &MAB) const = 0; virtual bool recordRelocation(const MCFixup &) const { return true; } }; @@ -39,7 +41,7 @@ namespace llvm { /// \param OS - The stream to write to. /// \returns The constructed object writer. MCObjectWriter *createWinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, - raw_ostream &OS); + raw_pwrite_stream &OS); } // End llvm namespace #endif diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h index 57a75cec2204..6a83e02298ff 100644 --- a/include/llvm/MC/MCWinCOFFStreamer.h +++ b/include/llvm/MC/MCWinCOFFStreamer.h @@ -24,11 +24,12 @@ class MCSubtargetInfo; class MCSymbol; class StringRef; class raw_ostream; +class raw_pwrite_stream; class MCWinCOFFStreamer : public MCObjectStreamer { public: MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, MCCodeEmitter &CE, - raw_ostream &OS); + raw_pwrite_stream &OS); /// state management void reset() override { @@ -56,9 +57,9 @@ public: unsigned ByteAlignment) override; void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; - void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, + void EmitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; - void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, + void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; void EmitFileDirective(StringRef Filename) override; void EmitIdent(StringRef IdentString) override; diff --git a/include/llvm/MC/MCWinEH.h b/include/llvm/MC/MCWinEH.h index 05b58c753b66..723d7a397c49 100644 --- a/include/llvm/MC/MCWinEH.h +++ b/include/llvm/MC/MCWinEH.h @@ -65,10 +65,10 @@ struct FrameInfo { class UnwindEmitter { public: - static const MCSection *getPDataSection(const MCSymbol *Function, - MCContext &Context); - static const MCSection *getXDataSection(const MCSymbol *Function, - MCContext &Context); + static MCSection *getPDataSection(const MCSymbol *Function, + MCContext &Context); + static MCSection *getXDataSection(const MCSymbol *Function, + MCContext &Context); virtual ~UnwindEmitter() { } diff --git a/include/llvm/MC/SectionKind.h b/include/llvm/MC/SectionKind.h index 85a91c6b1698..9e8b68f4340c 100644 --- a/include/llvm/MC/SectionKind.h +++ b/include/llvm/MC/SectionKind.h @@ -55,7 +55,6 @@ class SectionKind { /// MergeableConst - These are sections for merging fixed-length /// constants together. For example, this can be used to unique /// constant pool entries etc. - MergeableConst, /// MergeableConst4 - This is a section used by 4-byte constants, /// for example, floats. @@ -151,8 +150,8 @@ public: bool isMergeable4ByteCString() const { return K == Mergeable4ByteCString; } bool isMergeableConst() const { - return K == MergeableConst || K == MergeableConst4 || - K == MergeableConst8 || K == MergeableConst16; + return K == MergeableConst4 || K == MergeableConst8 || + K == MergeableConst16; } bool isMergeableConst4() const { return K == MergeableConst4; } bool isMergeableConst8() const { return K == MergeableConst8; } @@ -216,7 +215,6 @@ public: static SectionKind getMergeable4ByteCString() { return get(Mergeable4ByteCString); } - static SectionKind getMergeableConst() { return get(MergeableConst); } static SectionKind getMergeableConst4() { return get(MergeableConst4); } static SectionKind getMergeableConst8() { return get(MergeableConst8); } static SectionKind getMergeableConst16() { return get(MergeableConst16); } diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index bfecb8ba6ab0..6a631ffe79bd 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -21,11 +21,29 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/DataTypes.h" +#include <bitset> namespace llvm { class raw_ostream; class StringRef; +// A container class for subtarget features. +// This is convenient because std::bitset does not have a constructor +// with an initializer list of set bits. +const unsigned MAX_SUBTARGET_FEATURES = 64; +class FeatureBitset : public std::bitset<MAX_SUBTARGET_FEATURES> { +public: + // Cannot inherit constructors because it's not supported by VC++.. + FeatureBitset() : bitset() {} + + FeatureBitset(const bitset<MAX_SUBTARGET_FEATURES>& B) : bitset(B) {} + + FeatureBitset(std::initializer_list<unsigned> Init) : bitset() { + for (auto I = Init.begin() , E = Init.end(); I != E; ++I) + set(*I); + } +}; + //===----------------------------------------------------------------------===// /// /// SubtargetFeatureKV - Used to provide key value pairs for feature and @@ -34,8 +52,8 @@ namespace llvm { struct SubtargetFeatureKV { const char *Key; // K-V key string const char *Desc; // Help descriptor - uint64_t Value; // K-V integer value - uint64_t Implies; // K-V bit mask + FeatureBitset Value; // K-V integer value + FeatureBitset Implies; // K-V bit mask // Compare routine for std::lower_bound bool operator<(StringRef S) const { @@ -78,15 +96,15 @@ public: std::string getString() const; /// Adding Features. - void AddFeature(StringRef String); + void AddFeature(StringRef String, bool Enable = true); /// ToggleFeature - Toggle a feature and returns the newly updated feature /// bits. - uint64_t ToggleFeature(uint64_t Bits, StringRef String, + FeatureBitset ToggleFeature(FeatureBitset Bits, StringRef String, ArrayRef<SubtargetFeatureKV> FeatureTable); /// Get feature bits of a CPU. - uint64_t getFeatureBits(StringRef CPU, + FeatureBitset getFeatureBits(StringRef CPU, ArrayRef<SubtargetFeatureKV> CPUTable, ArrayRef<SubtargetFeatureKV> FeatureTable); diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index 4e96205a93ba..8da6919a4655 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -41,6 +41,9 @@ struct ArchiveMemberHeader { sys::fs::perms getAccessMode() const; sys::TimeValue getLastModified() const; + llvm::StringRef getRawLastModified() const { + return StringRef(LastModified, sizeof(LastModified)).rtrim(" "); + } unsigned getUID() const; unsigned getGID() const; }; @@ -78,6 +81,9 @@ public: sys::TimeValue getLastModified() const { return getHeader()->getLastModified(); } + StringRef getRawLastModified() const { + return getHeader()->getRawLastModified(); + } unsigned getUID() const { return getHeader()->getUID(); } unsigned getGID() const { return getHeader()->getGID(); } sys::fs::perms getAccessMode() const { @@ -85,10 +91,13 @@ public: } /// \return the size of the archive member without the header or padding. uint64_t getSize() const; + /// \return the size in the archive header for this member. + uint64_t getRawSize() const; StringRef getBuffer() const { return StringRef(Data.data() + StartOfFile, getSize()); } + uint64_t getChildOffset() const; ErrorOr<MemoryBufferRef> getMemoryBufferRef() const; @@ -146,9 +155,8 @@ public: Symbol symbol; public: symbol_iterator(const Symbol &s) : symbol(s) {} - const Symbol *operator->() const { - return &symbol; - } + const Symbol *operator->() const { return &symbol; } + const Symbol &operator*() const { return symbol; } bool operator==(const symbol_iterator &other) const { return symbol == other.symbol; @@ -169,6 +177,7 @@ public: enum Kind { K_GNU, + K_MIPS64, K_BSD, K_COFF }; @@ -184,6 +193,9 @@ public: symbol_iterator symbol_begin() const; symbol_iterator symbol_end() const; + iterator_range<symbol_iterator> symbols() const { + return iterator_range<symbol_iterator>(symbol_begin(), symbol_end()); + } // Cast methods. static inline bool classof(Binary const *v) { @@ -194,6 +206,8 @@ public: child_iterator findSym(StringRef name) const; bool hasSymbolTable() const; + child_iterator getSymbolTableChild() const { return SymbolTable; } + uint32_t getNumberOfSymbols() const; private: child_iterator SymbolTable; diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 4b2b7e6835cc..a3d6d0d4d428 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -28,8 +28,8 @@ namespace object { class Binary { private: - Binary() LLVM_DELETED_FUNCTION; - Binary(const Binary &other) LLVM_DELETED_FUNCTION; + Binary() = delete; + Binary(const Binary &other) = delete; unsigned int TypeID; diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 522bf68c6cbd..ccac02036adc 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -314,6 +314,10 @@ public: return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT; } + bool isAbsolute() const { + return getSectionNumber() == -1; + } + bool isExternal() const { return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL; } @@ -350,6 +354,10 @@ public: return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE; } + bool isSection() const { + return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION; + } + bool isSectionDefinition() const { // C++/CLI creates external ABS symbols for non-const appdomain globals. // These are also followed by an auxiliary section definition. @@ -441,6 +449,27 @@ struct coff_aux_clr_token { support::ulittle32_t SymbolTableIndex; }; +struct coff_import_header { + support::ulittle16_t Sig1; + support::ulittle16_t Sig2; + support::ulittle16_t Version; + support::ulittle16_t Machine; + support::ulittle32_t TimeDateStamp; + support::ulittle32_t SizeOfData; + support::ulittle16_t OrdinalHint; + support::ulittle16_t TypeInfo; + int getType() const { return TypeInfo & 0x3; } + int getNameType() const { return (TypeInfo & 0x7) >> 2; } +}; + +struct coff_import_directory_table_entry { + support::ulittle32_t ImportLookupTableRVA; + support::ulittle32_t TimeDateStamp; + support::ulittle32_t ForwarderChain; + support::ulittle32_t NameRVA; + support::ulittle32_t ImportAddressTableRVA; +}; + struct coff_load_configuration32 { support::ulittle32_t Characteristics; support::ulittle32_t TimeDateStamp; @@ -612,6 +641,7 @@ protected: std::error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + section_iterator getRelocationSection(DataRefImpl Rel) const override; std::error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; std::error_code diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 7c10bbf6e5ab..ddabf59f309e 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -94,18 +94,24 @@ public: return *this; } + ELFEntityIterator &operator+(difference_type n) { + assert(Current && "Attempted to increment an invalid iterator!"); + Current += (n * EntitySize); + return *this; + } + + ELFEntityIterator &operator-(difference_type n) { + assert(Current && "Attempted to subtract an invalid iterator!"); + Current -= (n * EntitySize); + return *this; + } + ELFEntityIterator operator ++(int) { ELFEntityIterator Tmp = *this; ++*this; return Tmp; } - ELFEntityIterator &operator =(const ELFEntityIterator &Other) { - EntitySize = Other.EntitySize; - Current = Other.Current; - return *this; - } - difference_type operator -(const ELFEntityIterator &Other) const { assert(EntitySize == Other.EntitySize && "Subtracting iterators of different EntitySize!"); @@ -203,12 +209,6 @@ public: return *this; } - Elf_Sym_Iter &operator=(const Elf_Sym_Iter &Other) { - EntitySize = Other.EntitySize; - Current = Other.Current; - return *this; - } - difference_type operator-(const Elf_Sym_Iter &Other) const { assert(EntitySize == Other.EntitySize && "Subtracting iterators of different EntitySize!"); diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index c2d6438f45ba..9bd4c3241118 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -86,6 +86,7 @@ protected: std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override; std::error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const override; + section_iterator getSymbolSection(const Elf_Sym *Symb) const; std::error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const override; @@ -112,6 +113,7 @@ protected: std::error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + section_iterator getRelocationSection(DataRefImpl Rel) const override; std::error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; std::error_code @@ -177,6 +179,20 @@ protected: return DRI; } + bool isExportedToOtherDSO(const Elf_Sym *ESym) const { + unsigned char Binding = ESym->getBinding(); + unsigned char Visibility = ESym->getVisibility(); + + // A symbol is exported if its binding is either GLOBAL or WEAK, and its + // visibility is either DEFAULT or PROTECTED. All other symbols are not + // exported. + if ((Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK) && + (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED)) + return true; + + return false; + } + // This flag is used for classof, to distinguish ELFObjectFile from // its subclass. If more subclasses will be created, this flag will // have to become an enum. @@ -300,8 +316,11 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, ESym->getType() == ELF::STT_FUNC) Result &= ~1; - if (Header->e_type == ELF::ET_REL) - Result += EF.getSection(ESym)->sh_addr; + if (Header->e_type == ELF::ET_REL) { + const typename ELFFile<ELFT>::Elf_Shdr * Section = EF.getSection(ESym); + if (Section != nullptr) + Result += Section->sh_addr; + } return object_error::success; } @@ -389,22 +408,33 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb) const { EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON) Result |= SymbolRef::SF_Common; + if (isExportedToOtherDSO(ESym)) + Result |= SymbolRef::SF_Exported; + + if (ESym->getVisibility() == ELF::STV_HIDDEN) + Result |= SymbolRef::SF_Hidden; + return Result; } template <class ELFT> -std::error_code -ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { - const Elf_Sym *ESym = getSymbol(Symb); +section_iterator +ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym) const { const Elf_Shdr *ESec = EF.getSection(ESym); if (!ESec) - Res = section_end(); + return section_end(); else { DataRefImpl Sec; Sec.p = reinterpret_cast<intptr_t>(ESec); - Res = section_iterator(SectionRef(Sec, this)); + return section_iterator(SectionRef(Sec, this)); } +} + +template <class ELFT> +std::error_code +ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { + Res = getSymbolSection(getSymbol(Symb)); return object_error::success; } @@ -565,6 +595,20 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { return symbol_iterator(SymbolRef(SymbolData, this)); } +// ELF relocations can target sections, by targetting a symbol of type +// STT_SECTION +template <class ELFT> +section_iterator +ELFObjectFile<ELFT>::getRelocationSection(DataRefImpl Rel) const { + symbol_iterator Sym = getRelocationSymbol(Rel); + if (Sym == symbol_end()) + return section_end(); + const Elf_Sym *ESym = getSymbol(Sym->getRawDataRefImpl()); + if (ESym->getType() != ELF::STT_SECTION) + return section_end(); + return getSymbolSection(ESym); +} + template <class ELFT> std::error_code ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, @@ -908,7 +952,7 @@ unsigned ELFObjectFile<ELFT>::getArch() const { case ELF::EM_SPARC: case ELF::EM_SPARC32PLUS: - return Triple::sparc; + return IsLittleEndian ? Triple::sparcel : Triple::sparc; case ELF::EM_SPARCV9: return Triple::sparcv9; diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h index 4bc0c7c2016e..287d3670678a 100644 --- a/include/llvm/Object/ELFTypes.h +++ b/include/llvm/Object/ELFTypes.h @@ -189,7 +189,15 @@ struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { } /// Access to the STV_xxx flag stored in the first two bits of st_other. + /// STV_DEFAULT: 0 + /// STV_INTERNAL: 1 + /// STV_HIDDEN: 2 + /// STV_PROTECTED: 3 unsigned char getVisibility() const { return st_other & 0x3; } + void setVisibility(unsigned char v) { + assert(v < 4 && "Invalid value for visibility"); + st_other = (st_other & ~0x3) | v; + } }; /// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section @@ -302,7 +310,10 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> { assert(!isMips64EL); return r_info; } - void setRInfo(uint32_t R) { r_info = R; } + void setRInfo(uint32_t R, bool IsMips64EL) { + assert(!IsMips64EL); + r_info = R; + } }; template <endianness TargetEndianness, std::size_t MaxAlign> @@ -321,9 +332,12 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> { return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); } - void setRInfo(uint64_t R) { - // FIXME: Add mips64el support. - r_info = R; + void setRInfo(uint64_t R, bool IsMips64EL) { + if (IsMips64EL) + r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) | + ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56); + else + r_info = R; } }; @@ -338,7 +352,10 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> { assert(!isMips64EL); return r_info; } - void setRInfo(uint32_t R) { r_info = R; } + void setRInfo(uint32_t R, bool IsMips64EL) { + assert(!IsMips64EL); + r_info = R; + } }; template <endianness TargetEndianness, std::size_t MaxAlign> @@ -358,9 +375,12 @@ struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, true> { return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); } - void setRInfo(uint64_t R) { - // FIXME: Add mips64el support. - r_info = R; + void setRInfo(uint64_t R, bool IsMips64EL) { + if (IsMips64EL) + r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) | + ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56); + else + r_info = R; } }; @@ -380,10 +400,14 @@ struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, true>, uint32_t getType(bool isMips64EL) const { return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL); } - void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } - void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint32_t s, uint32_t t) { - this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL)); + void setSymbol(uint32_t s, bool IsMips64EL) { + setSymbolAndType(s, getType(), IsMips64EL); + } + void setType(uint32_t t, bool IsMips64EL) { + setSymbolAndType(getSymbol(), t, IsMips64EL); + } + void setSymbolAndType(uint32_t s, uint32_t t, bool IsMips64EL) { + this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL), IsMips64EL); } }; @@ -401,10 +425,14 @@ struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, false>, unsigned char getType(bool isMips64EL) const { return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff); } - void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } - void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint32_t s, unsigned char t) { - this->setRInfo((s << 8) + t); + void setSymbol(uint32_t s, bool IsMips64EL) { + setSymbolAndType(s, getType(), IsMips64EL); + } + void setType(unsigned char t, bool IsMips64EL) { + setSymbolAndType(getSymbol(), t, IsMips64EL); + } + void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) { + this->setRInfo((s << 8) + t, IsMips64EL); } }; @@ -461,6 +489,59 @@ struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, true> > { Elf_Xword p_align; // Segment alignment constraint }; +// MIPS .reginfo section +template <class ELFT> +struct Elf_Mips_RegInfo; + +template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Mips_RegInfo<ELFType<TargetEndianness, MaxAlign, false>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Word ri_gprmask; // bit-mask of used general registers + Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers + Elf_Addr ri_gp_value; // gp register value +}; + +template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Mips_RegInfo<ELFType<TargetEndianness, MaxAlign, true>> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Word ri_gprmask; // bit-mask of used general registers + Elf_Word ri_pad; // unused padding field + Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers + Elf_Addr ri_gp_value; // gp register value +}; + +// .MIPS.options section +template <class ELFT> struct Elf_Mips_Options { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + uint8_t kind; // Determines interpretation of variable part of descriptor + uint8_t size; // Byte size of descriptor, including this header + Elf_Half section; // Section header index of section affected, + // or 0 for global options + Elf_Word info; // Kind-specific information + + const Elf_Mips_RegInfo<ELFT> &getRegInfo() const { + assert(kind == llvm::ELF::ODK_REGINFO); + return *reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>( + (const uint8_t *)this + sizeof(Elf_Mips_Options)); + } +}; + +// .MIPS.abiflags section content +template <class ELFT> struct Elf_Mips_ABIFlags { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Half version; // Version of the structure + uint8_t isa_level; // ISA level: 1-5, 32, and 64 + uint8_t isa_rev; // ISA revision (0 for MIPS I - MIPS V) + uint8_t gpr_size; // General purpose registers size + uint8_t cpr1_size; // Co-processor 1 registers size + uint8_t cpr2_size; // Co-processor 2 registers size + uint8_t fp_abi; // Floating-point ABI flag + Elf_Word isa_ext; // Processor-specific extension + Elf_Word ases; // ASEs flags + Elf_Word flags1; // General flags + Elf_Word flags2; // General flags +}; + } // end namespace object. } // end namespace llvm. diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index b71946d98b5d..b45507920a9c 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -41,12 +41,20 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_RSS) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STV) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STO) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_ASE) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_FLAGS1) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_ISA) + // For now, hardcode 64 bits everywhere that 32 or 64 would be needed // since 64-bit can hold 32-bit values too. struct FileHeader { @@ -71,14 +79,20 @@ struct LocalGlobalWeakSymbols { std::vector<Symbol> Global; std::vector<Symbol> Weak; }; + +struct SectionOrType { + StringRef sectionNameOrType; +}; + struct Section { - enum class SectionKind { RawContent, Relocation }; + enum class SectionKind { Group, RawContent, Relocation, MipsABIFlags }; SectionKind Kind; StringRef Name; ELF_SHT Type; ELF_SHF Flags; llvm::yaml::Hex64 Address; StringRef Link; + StringRef Info; llvm::yaml::Hex64 AddressAlign; Section(SectionKind Kind) : Kind(Kind) {} virtual ~Section(); @@ -91,6 +105,17 @@ struct RawContentSection : Section { return S->Kind == SectionKind::RawContent; } }; + +struct Group : Section { + // Members of a group contain a flag and a list of section indices + // that are part of the group. + std::vector<SectionOrType> Members; + Group() : Section(SectionKind::Group) {} + static bool classof(const Section *S) { + return S->Kind == SectionKind::Group; + } +}; + struct Relocation { llvm::yaml::Hex64 Offset; int64_t Addend; @@ -98,13 +123,32 @@ struct Relocation { StringRef Symbol; }; struct RelocationSection : Section { - StringRef Info; std::vector<Relocation> Relocations; RelocationSection() : Section(SectionKind::Relocation) {} static bool classof(const Section *S) { return S->Kind == SectionKind::Relocation; } }; + +// Represents .MIPS.abiflags section +struct MipsABIFlags : Section { + llvm::yaml::Hex16 Version; + MIPS_ISA ISALevel; + llvm::yaml::Hex8 ISARevision; + MIPS_AFL_REG GPRSize; + MIPS_AFL_REG CPR1Size; + MIPS_AFL_REG CPR2Size; + MIPS_ABI_FP FpABI; + MIPS_AFL_EXT ISAExtension; + MIPS_AFL_ASE ASEs; + MIPS_AFL_FLAGS1 Flags1; + llvm::yaml::Hex32 Flags2; + MipsABIFlags() : Section(SectionKind::MipsABIFlags) {} + static bool classof(const Section *S) { + return S->Kind == SectionKind::MipsABIFlags; + } +}; + struct Object { FileHeader Header; std::vector<std::unique_ptr<Section>> Sections; @@ -121,6 +165,7 @@ struct Object { LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Section>) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionOrType) namespace llvm { namespace yaml { @@ -186,6 +231,41 @@ struct ScalarEnumerationTraits<ELFYAML::ELF_REL> { }; template <> +struct ScalarEnumerationTraits<ELFYAML::ELF_RSS> { + static void enumeration(IO &IO, ELFYAML::ELF_RSS &Value); +}; + +template <> +struct ScalarEnumerationTraits<ELFYAML::MIPS_AFL_REG> { + static void enumeration(IO &IO, ELFYAML::MIPS_AFL_REG &Value); +}; + +template <> +struct ScalarEnumerationTraits<ELFYAML::MIPS_ABI_FP> { + static void enumeration(IO &IO, ELFYAML::MIPS_ABI_FP &Value); +}; + +template <> +struct ScalarEnumerationTraits<ELFYAML::MIPS_AFL_EXT> { + static void enumeration(IO &IO, ELFYAML::MIPS_AFL_EXT &Value); +}; + +template <> +struct ScalarEnumerationTraits<ELFYAML::MIPS_ISA> { + static void enumeration(IO &IO, ELFYAML::MIPS_ISA &Value); +}; + +template <> +struct ScalarBitSetTraits<ELFYAML::MIPS_AFL_ASE> { + static void bitset(IO &IO, ELFYAML::MIPS_AFL_ASE &Value); +}; + +template <> +struct ScalarBitSetTraits<ELFYAML::MIPS_AFL_FLAGS1> { + static void bitset(IO &IO, ELFYAML::MIPS_AFL_FLAGS1 &Value); +}; + +template <> struct MappingTraits<ELFYAML::FileHeader> { static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); }; @@ -215,6 +295,10 @@ struct MappingTraits<ELFYAML::Object> { static void mapping(IO &IO, ELFYAML::Object &Object); }; +template <> struct MappingTraits<ELFYAML::SectionOrType> { + static void mapping(IO &IO, ELFYAML::SectionOrType §ionOrType); +}; + } // end namespace yaml } // end namespace llvm diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h index 74f46667ce64..ef655287c34c 100644 --- a/include/llvm/Object/IRObjectFile.h +++ b/include/llvm/Object/IRObjectFile.h @@ -31,7 +31,7 @@ class IRObjectFile : public SymbolicFile { public: IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> M); - ~IRObjectFile(); + ~IRObjectFile() override; void moveSymbolNext(DataRefImpl &Symb) const override; std::error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index bee1f6ce0b01..0a9b62c9055f 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -235,6 +235,7 @@ public: std::error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + section_iterator getRelocationSection(DataRefImpl Rel) const override; std::error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; std::error_code @@ -326,7 +327,7 @@ public: unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const; unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const; unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const; - SectionRef getRelocationSection(const MachO::any_relocation_info &RE) const; + SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const; // Walk load commands. LoadCommandInfo getFirstLoadCommandInfo() const; @@ -395,6 +396,7 @@ public: MachO::symtab_command getSymtabLoadCommand() const; MachO::dysymtab_command getDysymtabLoadCommand() const; MachO::linkedit_data_command getDataInCodeLoadCommand() const; + MachO::linkedit_data_command getLinkOptHintsLoadCommand() const; ArrayRef<uint8_t> getDyldInfoRebaseOpcodes() const; ArrayRef<uint8_t> getDyldInfoBindOpcodes() const; ArrayRef<uint8_t> getDyldInfoWeakBindOpcodes() const; @@ -437,6 +439,7 @@ private: const char *SymtabLoadCmd; const char *DysymtabLoadCmd; const char *DataInCodeLoadCmd; + const char *LinkOptHintsLoadCmd; const char *DyldInfoLoadCmd; const char *UuidLoadCmd; bool HasPageZeroSegment; diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index 93f665438821..05119b293310 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -16,6 +16,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Object/Archive.h" #include "llvm/Object/Binary.h" #include "llvm/Object/MachO.h" @@ -69,9 +70,8 @@ public: ObjectForArch Obj; public: object_iterator(const ObjectForArch &Obj) : Obj(Obj) {} - const ObjectForArch* operator->() const { - return &Obj; - } + const ObjectForArch *operator->() const { return &Obj; } + const ObjectForArch &operator*() const { return Obj; } bool operator==(const object_iterator &Other) const { return Obj == Other.Obj; @@ -97,6 +97,10 @@ public: return ObjectForArch(nullptr, 0); } + iterator_range<object_iterator> objects() const { + return make_range(begin_objects(), end_objects()); + } + uint32_t getNumberOfObjects() const { return NumberOfObjects; } // Cast methods. diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 6aa985d7e67b..14cd082870b0 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -32,6 +32,8 @@ class MachOObjectFile; class SymbolRef; class symbol_iterator; +class SectionRef; +typedef content_iterator<SectionRef> section_iterator; /// RelocationRef - This is a value type class that represents a single /// relocation in the list of relocations in the object file. @@ -51,6 +53,7 @@ public: std::error_code getAddress(uint64_t &Result) const; std::error_code getOffset(uint64_t &Result) const; symbol_iterator getSymbol() const; + section_iterator getSection() const; std::error_code getType(uint64_t &Result) const; /// @brief Indicates whether this relocation should hidden when listing @@ -76,8 +79,6 @@ typedef content_iterator<RelocationRef> relocation_iterator; /// SectionRef - This is a value type class that represents a single section in /// the list of sections in the object file. -class SectionRef; -typedef content_iterator<SectionRef> section_iterator; class SectionRef { friend class SymbolRef; DataRefImpl SectionPimpl; @@ -180,8 +181,8 @@ public: /// figures out which type to create. class ObjectFile : public SymbolicFile { virtual void anchor(); - ObjectFile() LLVM_DELETED_FUNCTION; - ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; + ObjectFile() = delete; + ObjectFile(const ObjectFile &other) = delete; protected: ObjectFile(unsigned int Type, MemoryBufferRef Source); @@ -247,6 +248,7 @@ protected: virtual std::error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const = 0; virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; + virtual section_iterator getRelocationSection(DataRefImpl Rel) const = 0; virtual std::error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const = 0; virtual std::error_code @@ -467,6 +469,10 @@ inline symbol_iterator RelocationRef::getSymbol() const { return OwningObject->getRelocationSymbol(RelocationPimpl); } +inline section_iterator RelocationRef::getSection() const { + return OwningObject->getRelocationSection(RelocationPimpl); +} + inline std::error_code RelocationRef::getType(uint64_t &Result) const { return OwningObject->getRelocationType(RelocationPimpl, Result); } diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index 435799a34ebc..2bfff4c6b5a0 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -45,7 +45,9 @@ inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0; } -template <class content_type> class content_iterator { +template <class content_type> +class content_iterator + : public std::iterator<std::forward_iterator_tag, content_type> { content_type Current; public: @@ -87,9 +89,11 @@ public: SF_Absolute = 1U << 3, // Absolute symbol SF_Common = 1U << 4, // Symbol has common linkage SF_Indirect = 1U << 5, // Symbol is an alias to another symbol - SF_FormatSpecific = 1U << 6, // Specific to the object file format + SF_Exported = 1U << 6, // Symbol is visible to other DSOs + SF_FormatSpecific = 1U << 7, // Specific to the object file format // (e.g. section symbols) - SF_Thumb = 1U << 7 // Thumb symbol in a 32-bit ARM binary + SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary + SF_Hidden = 1U << 9, // Symbol has hidden visibility }; BasicSymbolRef() : OwningObject(nullptr) { } @@ -115,7 +119,7 @@ const uint64_t UnknownAddressOrSize = ~0ULL; class SymbolicFile : public Binary { public: - virtual ~SymbolicFile(); + ~SymbolicFile() override; SymbolicFile(unsigned int Type, MemoryBufferRef Source); // virtual interface. diff --git a/include/llvm/Option/Arg.h b/include/llvm/Option/Arg.h index dcaa5405ba7c..5f6941a53d0c 100644 --- a/include/llvm/Option/Arg.h +++ b/include/llvm/Option/Arg.h @@ -29,8 +29,8 @@ class ArgList; /// The Arg class encodes just enough information to be able to /// derive the argument values efficiently. class Arg { - Arg(const Arg &) LLVM_DELETED_FUNCTION; - void operator=(const Arg &) LLVM_DELETED_FUNCTION; + Arg(const Arg &) = delete; + void operator=(const Arg &) = delete; private: /// \brief The option this argument is an instance of. @@ -78,9 +78,7 @@ public: const Arg &getBaseArg() const { return BaseArg ? *BaseArg : *this; } - void setBaseArg(const Arg *_BaseArg) { - BaseArg = _BaseArg; - } + void setBaseArg(const Arg *BaseArg) { this->BaseArg = BaseArg; } bool getOwnsValues() const { return OwnsValues; } void setOwnsValues(bool Value) const { OwnsValues = Value; } diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index 3f8547e7fe41..23b04513178c 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -11,7 +11,9 @@ #define LLVM_OPTION_ARGLIST_H #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include "llvm/Option/OptSpecifier.h" #include "llvm/Option/Option.h" #include <list> @@ -52,10 +54,10 @@ public: typedef std::forward_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; - arg_iterator(SmallVectorImpl<Arg*>::const_iterator it, - const ArgList &_Args, OptSpecifier _Id0 = 0U, - OptSpecifier _Id1 = 0U, OptSpecifier _Id2 = 0U) - : Current(it), Args(_Args), Id0(_Id0), Id1(_Id1), Id2(_Id2) { + arg_iterator(SmallVectorImpl<Arg *>::const_iterator it, const ArgList &Args, + OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U, + OptSpecifier Id2 = 0U) + : Current(it), Args(Args), Id0(Id0), Id1(Id1), Id2(Id2) { SkipToNextArg(); } @@ -91,8 +93,8 @@ public: /// and to iterate over groups of arguments. class ArgList { private: - ArgList(const ArgList &) LLVM_DELETED_FUNCTION; - void operator=(const ArgList &) LLVM_DELETED_FUNCTION; + ArgList(const ArgList &) = delete; + void operator=(const ArgList &) = delete; public: typedef SmallVector<Arg*, 16> arglist_type; @@ -188,6 +190,10 @@ public: /// \p Claim Whether the argument should be claimed, if it exists. Arg *getLastArgNoClaim(OptSpecifier Id) const; Arg *getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1) const; + Arg *getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1, + OptSpecifier Id2) const; + Arg *getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, + OptSpecifier Id3) const; Arg *getLastArg(OptSpecifier Id) const; Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const; Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const; @@ -277,16 +283,13 @@ public: /// @name Arg Synthesis /// @{ - /// MakeArgString - Construct a constant string pointer whose + /// Construct a constant string pointer whose /// lifetime will match that of the ArgList. - virtual const char *MakeArgString(StringRef Str) const = 0; - const char *MakeArgString(const char *Str) const { - return MakeArgString(StringRef(Str)); + virtual const char *MakeArgStringRef(StringRef Str) const = 0; + const char *MakeArgString(const Twine &Str) const { + SmallString<256> Buf; + return MakeArgStringRef(Str.toStringRef(Buf)); } - const char *MakeArgString(std::string Str) const { - return MakeArgString(StringRef(Str)); - } - const char *MakeArgString(const Twine &Str) const; /// \brief Create an arg string for (\p LHS + \p RHS), reusing the /// string at \p Index if possible. @@ -317,7 +320,7 @@ private: public: InputArgList(const char* const *ArgBegin, const char* const *ArgEnd); - ~InputArgList(); + ~InputArgList() override; const char *getArgString(unsigned Index) const override { return ArgStrings[Index]; @@ -336,7 +339,7 @@ public: unsigned MakeIndex(StringRef String0, StringRef String1) const; using ArgList::MakeArgString; - const char *MakeArgString(StringRef Str) const override; + const char *MakeArgStringRef(StringRef Str) const override; /// @} }; @@ -352,7 +355,7 @@ class DerivedArgList : public ArgList { public: /// Construct a new derived arg list from \p BaseArgs. DerivedArgList(const InputArgList &BaseArgs); - ~DerivedArgList(); + ~DerivedArgList() override; const char *getArgString(unsigned Index) const override { return BaseArgs.getArgString(Index); @@ -374,7 +377,7 @@ public: void AddSynthesizedArg(Arg *A); using ArgList::MakeArgString; - const char *MakeArgString(StringRef Str) const override; + const char *MakeArgStringRef(StringRef Str) const override; /// AddFlagArg - Construct a new FlagArg for the given option \p Id and /// append it to the argument list. diff --git a/include/llvm/Option/OptSpecifier.h b/include/llvm/Option/OptSpecifier.h index b7caa6e85a7d..0b2aaaec3afc 100644 --- a/include/llvm/Option/OptSpecifier.h +++ b/include/llvm/Option/OptSpecifier.h @@ -21,11 +21,11 @@ namespace opt { unsigned ID; private: - explicit OptSpecifier(bool) LLVM_DELETED_FUNCTION; + explicit OptSpecifier(bool) = delete; public: OptSpecifier() : ID(0) {} - /*implicit*/ OptSpecifier(unsigned _ID) : ID(_ID) {} + /*implicit*/ OptSpecifier(unsigned ID) : ID(ID) {} /*implicit*/ OptSpecifier(const Option *Opt); bool isValid() const { return ID != 0; } diff --git a/include/llvm/Option/OptTable.h b/include/llvm/Option/OptTable.h index 5035940af06b..a7ff46919cd6 100644 --- a/include/llvm/Option/OptTable.h +++ b/include/llvm/Option/OptTable.h @@ -73,8 +73,9 @@ private: } protected: - OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos, - bool _IgnoreCase = false); + OptTable(const Info *OptionInfos, unsigned NumOptionInfos, + bool IgnoreCase = false); + public: ~OptTable(); diff --git a/include/llvm/Option/Option.h b/include/llvm/Option/Option.h index b2cfacbaf344..09be26c7cf20 100644 --- a/include/llvm/Option/Option.h +++ b/include/llvm/Option/Option.h @@ -70,7 +70,6 @@ protected: public: Option(const OptTable::Info *Info, const OptTable *Owner); - ~Option(); bool isValid() const { return Info != nullptr; diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h index c2b9f95956e8..3c4d838a4652 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -83,8 +83,8 @@ class Pass { AnalysisResolver *Resolver; // Used to resolve analysis const void *PassID; PassKind Kind; - void operator=(const Pass&) LLVM_DELETED_FUNCTION; - Pass(const Pass &) LLVM_DELETED_FUNCTION; + void operator=(const Pass&) = delete; + Pass(const Pass &) = delete; public: explicit Pass(PassKind K, char &pid) @@ -250,7 +250,7 @@ public: explicit ModulePass(char &pid) : Pass(PT_Module, pid) {} // Force out-of-line virtual method. - virtual ~ModulePass(); + ~ModulePass() override; }; @@ -279,7 +279,7 @@ public: : ModulePass(pid) {} // Force out-of-line virtual method. - virtual ~ImmutablePass(); + ~ImmutablePass() override; }; //===----------------------------------------------------------------------===// diff --git a/include/llvm/PassAnalysisSupport.h b/include/llvm/PassAnalysisSupport.h index 916430541809..38adb2dbb69b 100644 --- a/include/llvm/PassAnalysisSupport.h +++ b/include/llvm/PassAnalysisSupport.h @@ -120,7 +120,7 @@ public: class PMDataManager; class AnalysisResolver { private: - AnalysisResolver() LLVM_DELETED_FUNCTION; + AnalysisResolver() = delete; public: explicit AnalysisResolver(PMDataManager &P) : PM(P) { } diff --git a/include/llvm/PassInfo.h b/include/llvm/PassInfo.h index d53daf1cf72c..d10761831b3a 100644 --- a/include/llvm/PassInfo.h +++ b/include/llvm/PassInfo.h @@ -138,8 +138,8 @@ public: } private: - void operator=(const PassInfo &) LLVM_DELETED_FUNCTION; - PassInfo(const PassInfo &) LLVM_DELETED_FUNCTION; + void operator=(const PassInfo &) = delete; + PassInfo(const PassInfo &) = delete; }; } diff --git a/include/llvm/PassManager.h b/include/llvm/PassManager.h deleted file mode 100644 index 2a191b339931..000000000000 --- a/include/llvm/PassManager.h +++ /dev/null @@ -1,39 +0,0 @@ -//===- llvm/PassManager.h - Container for Passes ----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is a legacy redirect header for the old PassManager. It is intended to -// be used by clients that have not been converted to be aware of the new pass -// management infrastructure being built for LLVM, which is every client -// initially. Eventually this header (and the legacy management layer) will go -// away, but we want to minimize changes to out-of-tree users of LLVM in the -// interim. -// -// Note that this header *must not* be included into the same file as the new -// pass management infrastructure is included. Things will break spectacularly. -// If you are starting that conversion, you should switch to explicitly -// including LegacyPassManager.h and using the legacy namespace. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PASSMANAGER_H -#define LLVM_PASSMANAGER_H - -#include "llvm/IR/LegacyPassManager.h" - -namespace llvm { - -// Pull these into the llvm namespace so that existing code that expects it -// there can find it. -using legacy::PassManagerBase; -using legacy::PassManager; -using legacy::FunctionPassManager; - -} - -#endif diff --git a/include/llvm/Passes/PassBuilder.h b/include/llvm/Passes/PassBuilder.h new file mode 100644 index 000000000000..1e605e374178 --- /dev/null +++ b/include/llvm/Passes/PassBuilder.h @@ -0,0 +1,105 @@ +//===- Parsing, selection, and construction of pass pipelines --*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// Interfaces for registering analysis passes, producing common pass manager +/// configurations, and parsing of pass pipelines. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSES_PASSBUILDER_H +#define LLVM_PASSES_PASSBUILDER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/CGSCCPassManager.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { +class TargetMachine; + +/// \brief This class provides access to building LLVM's passes. +/// +/// It's members provide the baseline state available to passes during their +/// construction. The \c PassRegistry.def file specifies how to construct all +/// of the built-in passes, and those may reference these members during +/// construction. +class PassBuilder { + TargetMachine *TM; + +public: + explicit PassBuilder(TargetMachine *TM = nullptr) : TM(TM) {} + + /// \brief Registers all available module analysis passes. + /// + /// This is an interface that can be used to populate a \c + /// ModuleAnalysisManager with all registered module analyses. Callers can + /// still manually register any additional analyses. + void registerModuleAnalyses(ModuleAnalysisManager &MAM); + + /// \brief Registers all available CGSCC analysis passes. + /// + /// This is an interface that can be used to populate a \c CGSCCAnalysisManager + /// with all registered CGSCC analyses. Callers can still manually register any + /// additional analyses. + void registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM); + + /// \brief Registers all available function analysis passes. + /// + /// This is an interface that can be used to populate a \c + /// FunctionAnalysisManager with all registered function analyses. Callers can + /// still manually register any additional analyses. + void registerFunctionAnalyses(FunctionAnalysisManager &FAM); + + /// \brief Parse a textual pass pipeline description into a \c ModulePassManager. + /// + /// The format of the textual pass pipeline description looks something like: + /// + /// module(function(instcombine,sroa),dce,cgscc(inliner,function(...)),...) + /// + /// Pass managers have ()s describing the nest structure of passes. All passes + /// are comma separated. As a special shortcut, if the very first pass is not + /// a module pass (as a module pass manager is), this will automatically form + /// the shortest stack of pass managers that allow inserting that first pass. + /// So, assuming function passes 'fpassN', CGSCC passes 'cgpassN', and loop passes + /// 'lpassN', all of these are valid: + /// + /// fpass1,fpass2,fpass3 + /// cgpass1,cgpass2,cgpass3 + /// lpass1,lpass2,lpass3 + /// + /// And they are equivalent to the following (resp.): + /// + /// module(function(fpass1,fpass2,fpass3)) + /// module(cgscc(cgpass1,cgpass2,cgpass3)) + /// module(function(loop(lpass1,lpass2,lpass3))) + /// + /// This shortcut is especially useful for debugging and testing small pass + /// combinations. Note that these shortcuts don't introduce any other magic. If + /// the sequence of passes aren't all the exact same kind of pass, it will be + /// an error. You cannot mix different levels implicitly, you must explicitly + /// form a pass manager in which to nest passes. + bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, + bool VerifyEachPass = true, bool DebugLogging = false); + +private: + bool parseModulePassName(ModulePassManager &MPM, StringRef Name); + bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name); + bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name); + bool parseFunctionPassPipeline(FunctionPassManager &FPM, + StringRef &PipelineText, bool VerifyEachPass, + bool DebugLogging); + bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM, StringRef &PipelineText, + bool VerifyEachPass, bool DebugLogging); + bool parseModulePassPipeline(ModulePassManager &MPM, StringRef &PipelineText, + bool VerifyEachPass, bool DebugLogging); +}; + +} + +#endif diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h index 38fc8ca7c77c..94e655c3edcb 100644 --- a/include/llvm/ProfileData/CoverageMapping.h +++ b/include/llvm/ProfileData/CoverageMapping.h @@ -18,16 +18,19 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/Triple.h" #include "llvm/ADT/iterator.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/raw_ostream.h" #include <system_error> +#include <tuple> namespace llvm { class IndexedInstrProfReader; namespace coverage { -class ObjectFileCoverageMappingReader; +class CoverageMappingReader; class CoverageMapping; struct CounterExpressions; @@ -62,8 +65,12 @@ public: unsigned getExpressionID() const { return ID; } - bool operator==(const Counter &Other) const { - return Kind == Other.Kind && ID == Other.ID; + friend bool operator==(const Counter &LHS, const Counter &RHS) { + return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID; + } + + friend bool operator!=(const Counter &LHS, const Counter &RHS) { + return !(LHS == RHS); } friend bool operator<(const Counter &LHS, const Counter &RHS) { @@ -153,24 +160,40 @@ struct CounterMappingRegion { SkippedRegion }; - static const unsigned EncodingHasCodeBeforeBits = 1; - Counter Count; unsigned FileID, ExpandedFileID; unsigned LineStart, ColumnStart, LineEnd, ColumnEnd; RegionKind Kind; - /// \brief A flag that is set to true when there is already code before - /// this region on the same line. - /// This is useful to accurately compute the execution counts for a line. - bool HasCodeBefore; - - CounterMappingRegion(Counter Count, unsigned FileID, unsigned LineStart, - unsigned ColumnStart, unsigned LineEnd, - unsigned ColumnEnd, bool HasCodeBefore = false, - RegionKind Kind = CodeRegion) - : Count(Count), FileID(FileID), ExpandedFileID(0), LineStart(LineStart), - ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd), - Kind(Kind), HasCodeBefore(HasCodeBefore) {} + + CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID, + unsigned LineStart, unsigned ColumnStart, + unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind) + : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID), + LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd), + ColumnEnd(ColumnEnd), Kind(Kind) {} + + static CounterMappingRegion + makeRegion(Counter Count, unsigned FileID, unsigned LineStart, + unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { + return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, + LineEnd, ColumnEnd, CodeRegion); + } + + static CounterMappingRegion + makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, + unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { + return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart, + ColumnStart, LineEnd, ColumnEnd, + ExpansionRegion); + } + + static CounterMappingRegion + makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart, + unsigned LineEnd, unsigned ColumnEnd) { + return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart, + LineEnd, ColumnEnd, SkippedRegion); + } + inline std::pair<unsigned, unsigned> startLoc() const { return std::pair<unsigned, unsigned>(LineStart, ColumnStart); @@ -216,8 +239,10 @@ public: ArrayRef<uint64_t> CounterValues = ArrayRef<uint64_t>()) : Expressions(Expressions), CounterValues(CounterValues) {} + void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; } + void dump(const Counter &C, llvm::raw_ostream &OS) const; - void dump(const Counter &C) const { dump(C, llvm::outs()); } + void dump(const Counter &C) const { dump(C, dbgs()); } /// \brief Return the number of times that a region of code associated with /// this counter was executed. @@ -235,10 +260,14 @@ struct FunctionRecord { /// \brief The number of times this function was executed. uint64_t ExecutionCount; - FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames, - uint64_t ExecutionCount) - : Name(Name), Filenames(Filenames.begin(), Filenames.end()), - ExecutionCount(ExecutionCount) {} + FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames) + : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {} + + void pushRegion(CounterMappingRegion Region, uint64_t Count) { + if (CountedRegions.empty()) + ExecutionCount = Count; + CountedRegions.emplace_back(Region, Count); + } }; /// \brief Iterator over Functions, optionally filtered to a single file. @@ -312,10 +341,22 @@ struct CoverageSegment { CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) : Line(Line), Col(Col), Count(0), HasCount(false), IsRegionEntry(IsRegionEntry) {} + + CoverageSegment(unsigned Line, unsigned Col, uint64_t Count, + bool IsRegionEntry) + : Line(Line), Col(Col), Count(Count), HasCount(true), + IsRegionEntry(IsRegionEntry) {} + + friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) { + return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry) == + std::tie(R.Line, R.Col, R.Count, R.HasCount, R.IsRegionEntry); + } + void setCount(uint64_t NewCount) { Count = NewCount; HasCount = true; } + void addCount(uint64_t NewCount) { setCount(Count + NewCount); } }; @@ -363,12 +404,13 @@ class CoverageMapping { public: /// \brief Load the coverage mapping using the given readers. static ErrorOr<std::unique_ptr<CoverageMapping>> - load(ObjectFileCoverageMappingReader &CoverageReader, + load(CoverageMappingReader &CoverageReader, IndexedInstrProfReader &ProfileReader); /// \brief Load the coverage mapping from the given files. static ErrorOr<std::unique_ptr<CoverageMapping>> - load(StringRef ObjectFilename, StringRef ProfileFilename); + load(StringRef ObjectFilename, StringRef ProfileFilename, + Triple::ArchType Arch = Triple::ArchType::UnknownArch); /// \brief The number of functions that couldn't have their profiles mapped. /// @@ -442,7 +484,26 @@ template<> struct DenseMapInfo<coverage::CounterExpression> { } }; +const std::error_category &coveragemap_category(); + +enum class coveragemap_error { + success = 0, + eof, + no_data_found, + unsupported_version, + truncated, + malformed +}; + +inline std::error_code make_error_code(coveragemap_error E) { + return std::error_code(static_cast<int>(E), coveragemap_category()); +} } // end namespace llvm +namespace std { +template <> +struct is_error_code_enum<llvm::coveragemap_error> : std::true_type {}; +} + #endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_ diff --git a/include/llvm/ProfileData/CoverageMappingReader.h b/include/llvm/ProfileData/CoverageMappingReader.h index 5a6b44b8d9ef..020edbd3e6c1 100644 --- a/include/llvm/ProfileData/CoverageMappingReader.h +++ b/include/llvm/ProfileData/CoverageMappingReader.h @@ -17,6 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" #include "llvm/Object/ObjectFile.h" #include "llvm/ProfileData/CoverageMapping.h" #include "llvm/ProfileData/InstrProf.h" @@ -27,7 +28,7 @@ namespace llvm { namespace coverage { -class ObjectFileCoverageMappingReader; +class CoverageMappingReader; /// \brief Coverage mapping information for a single function. struct CoverageMappingRecord { @@ -41,15 +42,14 @@ struct CoverageMappingRecord { /// \brief A file format agnostic iterator over coverage mapping data. class CoverageMappingIterator : public std::iterator<std::input_iterator_tag, CoverageMappingRecord> { - ObjectFileCoverageMappingReader *Reader; + CoverageMappingReader *Reader; CoverageMappingRecord Record; void increment(); public: CoverageMappingIterator() : Reader(nullptr) {} - CoverageMappingIterator(ObjectFileCoverageMappingReader *Reader) - : Reader(Reader) { + CoverageMappingIterator(CoverageMappingReader *Reader) : Reader(Reader) { increment(); } @@ -67,17 +67,19 @@ public: CoverageMappingRecord *operator->() { return &Record; } }; +class CoverageMappingReader { +public: + virtual std::error_code readNextRecord(CoverageMappingRecord &Record) = 0; + CoverageMappingIterator begin() { return CoverageMappingIterator(this); } + CoverageMappingIterator end() { return CoverageMappingIterator(); } + virtual ~CoverageMappingReader() {} +}; + /// \brief Base class for the raw coverage mapping and filenames data readers. class RawCoverageReader { protected: StringRef Data; - /// \brief Return the error code. - std::error_code error(std::error_code EC) { return EC; } - - /// \brief Clear the current error code and return a successful one. - std::error_code success() { return error(instrprof_error::success); } - RawCoverageReader(StringRef Data) : Data(Data) {} std::error_code readULEB128(uint64_t &Result); @@ -90,10 +92,9 @@ protected: class RawCoverageFilenamesReader : public RawCoverageReader { std::vector<StringRef> &Filenames; - RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) - LLVM_DELETED_FUNCTION; + RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete; RawCoverageFilenamesReader & - operator=(const RawCoverageFilenamesReader &) LLVM_DELETED_FUNCTION; + operator=(const RawCoverageFilenamesReader &) = delete; public: RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames) @@ -104,29 +105,27 @@ public: /// \brief Reader for the raw coverage mapping data. class RawCoverageMappingReader : public RawCoverageReader { - StringRef FunctionName; ArrayRef<StringRef> TranslationUnitFilenames; std::vector<StringRef> &Filenames; std::vector<CounterExpression> &Expressions; std::vector<CounterMappingRegion> &MappingRegions; - RawCoverageMappingReader(const RawCoverageMappingReader &) - LLVM_DELETED_FUNCTION; + RawCoverageMappingReader(const RawCoverageMappingReader &) = delete; RawCoverageMappingReader & - operator=(const RawCoverageMappingReader &) LLVM_DELETED_FUNCTION; + operator=(const RawCoverageMappingReader &) = delete; public: - RawCoverageMappingReader(StringRef FunctionName, StringRef MappingData, + RawCoverageMappingReader(StringRef MappingData, ArrayRef<StringRef> TranslationUnitFilenames, std::vector<StringRef> &Filenames, std::vector<CounterExpression> &Expressions, std::vector<CounterMappingRegion> &MappingRegions) - : RawCoverageReader(MappingData), FunctionName(FunctionName), + : RawCoverageReader(MappingData), TranslationUnitFilenames(TranslationUnitFilenames), Filenames(Filenames), Expressions(Expressions), MappingRegions(MappingRegions) {} - std::error_code read(CoverageMappingRecord &Record); + std::error_code read(); private: std::error_code decodeCounter(unsigned Value, Counter &C); @@ -138,7 +137,7 @@ private: /// \brief Reader for the coverage mapping data that is emitted by the /// frontend and stored in an object file. -class ObjectFileCoverageMappingReader { +class BinaryCoverageReader : public CoverageMappingReader { public: struct ProfileMappingRecord { CoverageMappingVersion Version; @@ -157,8 +156,6 @@ public: }; private: - std::error_code LastError; - object::OwningBinary<object::ObjectFile> Object; std::vector<StringRef> Filenames; std::vector<ProfileMappingRecord> MappingRecords; size_t CurrentRecord; @@ -166,40 +163,17 @@ private: std::vector<CounterExpression> Expressions; std::vector<CounterMappingRegion> MappingRegions; - ObjectFileCoverageMappingReader(const ObjectFileCoverageMappingReader &) - LLVM_DELETED_FUNCTION; - ObjectFileCoverageMappingReader & - operator=(const ObjectFileCoverageMappingReader &) LLVM_DELETED_FUNCTION; - - /// \brief Set the current error_code and return same. - std::error_code error(std::error_code EC) { - LastError = EC; - return EC; - } + BinaryCoverageReader(const BinaryCoverageReader &) = delete; + BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete; - /// \brief Clear the current error code and return a successful one. - std::error_code success() { return error(instrprof_error::success); } + BinaryCoverageReader() : CurrentRecord(0) {} public: - ObjectFileCoverageMappingReader(StringRef FileName); - ObjectFileCoverageMappingReader( - std::unique_ptr<MemoryBuffer> &ObjectBuffer, - sys::fs::file_magic Type = sys::fs::file_magic::unknown); - - std::error_code readHeader(); - std::error_code readNextRecord(CoverageMappingRecord &Record); - - /// Iterator over profile data. - CoverageMappingIterator begin() { return CoverageMappingIterator(this); } - CoverageMappingIterator end() { return CoverageMappingIterator(); } + static ErrorOr<std::unique_ptr<BinaryCoverageReader>> + create(std::unique_ptr<MemoryBuffer> &ObjectBuffer, + Triple::ArchType Arch = Triple::ArchType::UnknownArch); - /// \brief Return true if the reader has finished reading the profile data. - bool isEOF() { return LastError == instrprof_error::eof; } - /// \brief Return true if the reader encountered an error reading profiling - /// data. - bool hasError() { return LastError && !isEOF(); } - /// \brief Get the current error code. - std::error_code getError() { return LastError; } + std::error_code readNextRecord(CoverageMappingRecord &Record) override; }; } // end namespace coverage diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 9655d66edc92..63a6ac671f2b 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -95,6 +95,9 @@ public: /// Factory method to create an appropriately typed reader for the given /// instrprof file. static ErrorOr<std::unique_ptr<InstrProfReader>> create(std::string Path); + + static ErrorOr<std::unique_ptr<InstrProfReader>> + create(std::unique_ptr<MemoryBuffer> Buffer); }; /// Reader for the simple text based instrprof format. @@ -114,9 +117,8 @@ private: /// The current set of counter values. std::vector<uint64_t> Counts; - TextInstrProfReader(const TextInstrProfReader &) LLVM_DELETED_FUNCTION; - TextInstrProfReader &operator=(const TextInstrProfReader &) - LLVM_DELETED_FUNCTION; + TextInstrProfReader(const TextInstrProfReader &) = delete; + TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; public: TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_) : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} @@ -167,9 +169,8 @@ private: const char *NamesStart; const char *ProfileEnd; - RawInstrProfReader(const RawInstrProfReader &) LLVM_DELETED_FUNCTION; - RawInstrProfReader &operator=(const RawInstrProfReader &) - LLVM_DELETED_FUNCTION; + RawInstrProfReader(const RawInstrProfReader &) = delete; + RawInstrProfReader &operator=(const RawInstrProfReader &) = delete; public: RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) : DataBuffer(std::move(DataBuffer)) { } @@ -273,9 +274,8 @@ private: /// The maximal execution count among all functions. uint64_t MaxFunctionCount; - IndexedInstrProfReader(const IndexedInstrProfReader &) LLVM_DELETED_FUNCTION; - IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) - LLVM_DELETED_FUNCTION; + IndexedInstrProfReader(const IndexedInstrProfReader &) = delete; + IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete; public: IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) : DataBuffer(std::move(DataBuffer)), Index(nullptr), CurrentOffset(0) {} @@ -295,8 +295,11 @@ public: uint64_t getMaximumFunctionCount() { return MaxFunctionCount; } /// Factory method to create an indexed reader. - static std::error_code - create(std::string Path, std::unique_ptr<IndexedInstrProfReader> &Result); + static ErrorOr<std::unique_ptr<IndexedInstrProfReader>> + create(std::string Path); + + static ErrorOr<std::unique_ptr<IndexedInstrProfReader>> + create(std::unique_ptr<MemoryBuffer> Buffer); }; } // end namespace llvm diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h index a23c56772a2f..ce0bb5242498 100644 --- a/include/llvm/ProfileData/InstrProfWriter.h +++ b/include/llvm/ProfileData/InstrProfWriter.h @@ -20,6 +20,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include <vector> @@ -41,8 +42,13 @@ public: std::error_code addFunctionCounts(StringRef FunctionName, uint64_t FunctionHash, ArrayRef<uint64_t> Counters); - /// Ensure that all data is written to disk. + /// Write the profile to \c OS void write(raw_fd_ostream &OS); + /// Write the profile, returning the raw data. For testing. + std::unique_ptr<MemoryBuffer> writeBuffer(); + +private: + std::pair<uint64_t, uint64_t> writeImpl(raw_ostream &OS); }; } // end namespace llvm diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h index df0a055c2a79..1b82e55aa77a 100644 --- a/include/llvm/ProfileData/SampleProf.h +++ b/include/llvm/ProfileData/SampleProf.h @@ -59,7 +59,7 @@ static inline uint64_t SPMagic() { static inline uint64_t SPVersion() { return 100; } -/// \brief Represents the relative location of an instruction. +/// Represents the relative location of an instruction. /// /// Instruction locations are specified by the line offset from the /// beginning of the function (marked by the line where the function @@ -100,7 +100,7 @@ template <> struct DenseMapInfo<sampleprof::LineLocation> { namespace sampleprof { -/// \brief Representation of a single sample record. +/// Representation of a single sample record. /// /// A sample record is represented by a positive integer value, which /// indicates how frequently was the associated line location executed. @@ -116,7 +116,7 @@ public: SampleRecord() : NumSamples(0), CallTargets() {} - /// \brief Increment the number of samples for this record by \p S. + /// Increment the number of samples for this record by \p S. /// /// Sample counts accumulate using saturating arithmetic, to avoid wrapping /// around unsigned integers. @@ -127,7 +127,7 @@ public: NumSamples = std::numeric_limits<unsigned>::max(); } - /// \brief Add called function \p F with samples \p S. + /// Add called function \p F with samples \p S. /// /// Sample counts accumulate using saturating arithmetic, to avoid wrapping /// around unsigned integers. @@ -139,13 +139,13 @@ public: TargetSamples = std::numeric_limits<unsigned>::max(); } - /// \brief Return true if this sample record contains function calls. + /// Return true if this sample record contains function calls. bool hasCalls() const { return CallTargets.size() > 0; } unsigned getSamples() const { return NumSamples; } const CallTargetMap &getCallTargets() const { return CallTargets; } - /// \brief Merge the samples in \p Other into this record. + /// Merge the samples in \p Other into this record. void merge(const SampleRecord &Other) { addSamples(Other.getSamples()); for (const auto &I : Other.getCallTargets()) @@ -159,7 +159,7 @@ private: typedef DenseMap<LineLocation, SampleRecord> BodySampleMap; -/// \brief Representation of the samples collected for a function. +/// Representation of the samples collected for a function. /// /// This data structure contains all the collected samples for the body /// of a function. Each sample corresponds to a LineLocation instance @@ -187,13 +187,13 @@ public: Num); } - /// \brief Return the sample record at the given location. + /// Return the sample record at the given location. /// Each location is specified by \p LineOffset and \p Discriminator. SampleRecord &sampleRecordAt(const LineLocation &Loc) { return BodySamples[Loc]; } - /// \brief Return the number of samples collected at the given location. + /// Return the number of samples collected at the given location. /// Each location is specified by \p LineOffset and \p Discriminator. unsigned samplesAt(int LineOffset, unsigned Discriminator) { return sampleRecordAt(LineLocation(LineOffset, Discriminator)).getSamples(); @@ -201,17 +201,17 @@ public: bool empty() const { return BodySamples.empty(); } - /// \brief Return the total number of samples collected inside the function. + /// Return the total number of samples collected inside the function. unsigned getTotalSamples() const { return TotalSamples; } - /// \brief Return the total number of samples collected at the head of the + /// Return the total number of samples collected at the head of the /// function. unsigned getHeadSamples() const { return TotalHeadSamples; } - /// \brief Return all the samples collected in the body of the function. + /// Return all the samples collected in the body of the function. const BodySampleMap &getBodySamples() const { return BodySamples; } - /// \brief Merge the samples in \p Other into this one. + /// Merge the samples in \p Other into this one. void merge(const FunctionSamples &Other) { addTotalSamples(Other.getTotalSamples()); addHeadSamples(Other.getHeadSamples()); @@ -223,16 +223,18 @@ public: } private: - /// \brief Total number of samples collected inside this function. + /// Total number of samples collected inside this function. /// /// Samples are cumulative, they include all the samples collected /// inside this function and all its inlined callees. unsigned TotalSamples; - /// \brief Total number of samples collected at the head of the function. + /// Total number of samples collected at the head of the function. + /// This is an approximation of the number of calls made to this function + /// at runtime. unsigned TotalHeadSamples; - /// \brief Map instruction locations to collected samples. + /// Map instruction locations to collected samples. /// /// Each entry in this map contains the number of samples /// collected at the corresponding line offset. All line locations diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h index 96a8219bfb85..fc14cb2d0b0c 100644 --- a/include/llvm/Support/ARMBuildAttributes.h +++ b/include/llvm/Support/ARMBuildAttributes.h @@ -100,13 +100,13 @@ enum CPUArch { v5TEJ = 5, // e.g. ARM926EJ_S v6 = 6, // e.g. ARM1136J_S v6KZ = 7, // e.g. ARM1176JZ_S - v6T2 = 8, // e.g. ARM1156T2F_S - v6K = 9, // e.g. ARM1136J_S + v6T2 = 8, // e.g. ARM1156T2_S + v6K = 9, // e.g. ARM1176JZ_S v7 = 10, // e.g. Cortex A8, Cortex M3 v6_M = 11, // e.g. Cortex M1 v6S_M = 12, // v6_M with the System extensions v7E_M = 13, // v7_M with DSP extensions - v8 = 14 // v8, AArch32 + v8 = 14, // v8,v8.1a AArch32 }; enum CPUArchProfile { // (=7), uleb128 @@ -145,6 +145,7 @@ enum { AllowNeon = 1, // SIMDv1 was permitted AllowNeon2 = 2, // SIMDv2 was permitted (Half-precision FP, MAC operations) AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted + AllowNeonARMv8_1a = 4,// ARM v8.1-A SIMD was permitted (RDMA) // Tag_ABI_PCS_R9_use, (=14), uleb128 R9IsGPR = 0, // R9 used as v6 (just another callee-saved register) diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index 061d5acf2322..574b514aef39 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -22,6 +22,14 @@ namespace llvm { template <typename T> struct AlignmentCalcImpl { char x; +#if defined(_MSC_VER) +// Disables "structure was padded due to __declspec(align())" warnings that are +// generated by any class using AlignOf<T> with a manually specified alignment. +// Although the warning is disabled in the LLVM project we need this pragma +// as AlignOf.h is a published support header that's available for use +// out-of-tree, and we would like that to compile cleanly at /W4. +#pragma warning(suppress : 4324) +#endif T t; private: AlignmentCalcImpl() {} // Never instantiate. @@ -190,12 +198,12 @@ union SizerImpl { } // end namespace detail /// \brief This union template exposes a suitably aligned and sized character -/// array member which can hold elements of any of up to four types. +/// array member which can hold elements of any of up to ten types. /// /// These types may be arrays, structs, or any other types. The goal is to /// expose a char array buffer member which can be used as suitable storage for -/// a placement new of any of these types. Support for more than seven types can -/// be added at the cost of more boiler plate. +/// a placement new of any of these types. Support for more than ten types can +/// be added at the cost of more boilerplate. template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char, typename T5 = char, typename T6 = char, typename T7 = char, diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index de317719714d..f9b5cf22f97d 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -148,7 +148,7 @@ public: : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator(std::forward<T &&>(Allocator)) {} - // Manually implement a move constructor as we must clear the old allocators + // Manually implement a move constructor as we must clear the old allocator's // slabs as a matter of correctness. BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old) : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)), @@ -187,6 +187,9 @@ public: /// \brief Deallocate all but the current slab and reset the current pointer /// to the beginning of it, freeing all memory allocated so far. void Reset() { + DeallocateCustomSizedSlabs(); + CustomSizedSlabs.clear(); + if (Slabs.empty()) return; @@ -195,15 +198,14 @@ public: CurPtr = (char *)Slabs.front(); End = CurPtr + SlabSize; - // Deallocate all but the first slab, and all custome sized slabs. + // Deallocate all but the first slab, and deallocate all custom-sized slabs. DeallocateSlabs(std::next(Slabs.begin()), Slabs.end()); Slabs.erase(std::next(Slabs.begin()), Slabs.end()); - DeallocateCustomSizedSlabs(); - CustomSizedSlabs.clear(); } /// \brief Allocate space at the specified alignment. - LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) { + LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * + Allocate(size_t Size, size_t Alignment) { assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead."); // Keep track of how many bytes we've allocated. @@ -319,14 +321,6 @@ private: for (; I != E; ++I) { size_t AllocatedSlabSize = computeSlabSize(std::distance(Slabs.begin(), I)); -#ifndef NDEBUG - // Poison the memory so stale pointers crash sooner. Note we must - // preserve the Size and NextPtr fields at the beginning. - if (AllocatedSlabSize != 0) { - sys::Memory::setRangeWritable(*I, AllocatedSlabSize); - memset(*I, 0xCD, AllocatedSlabSize); - } -#endif Allocator.Deallocate(*I, AllocatedSlabSize); } } @@ -336,12 +330,6 @@ private: for (auto &PtrAndSize : CustomSizedSlabs) { void *Ptr = PtrAndSize.first; size_t Size = PtrAndSize.second; -#ifndef NDEBUG - // Poison the memory so stale pointers crash sooner. Note we must - // preserve the Size and NextPtr fields at the beginning. - sys::Memory::setRangeWritable(Ptr, Size); - memset(Ptr, 0xCD, Size); -#endif Allocator.Deallocate(Ptr, Size); } } diff --git a/include/llvm/Support/BranchProbability.h b/include/llvm/Support/BranchProbability.h index 9aab6ace6e3f..a6429dd22a3b 100644 --- a/include/llvm/Support/BranchProbability.h +++ b/include/llvm/Support/BranchProbability.h @@ -31,7 +31,7 @@ class BranchProbability { public: BranchProbability(uint32_t n, uint32_t d) : N(n), D(d) { - assert(d > 0 && "Denomiator cannot be 0!"); + assert(d > 0 && "Denominator cannot be 0!"); assert(n <= d && "Probability cannot be bigger than 1!"); } diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 150bce50d9ae..7f54822d503f 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -664,16 +664,16 @@ namespace COFF { } }; - enum CodeViewLineTableIdentifiers { - DEBUG_SECTION_MAGIC = 0x4, - DEBUG_SYMBOL_SUBSECTION = 0xF1, - DEBUG_LINE_TABLE_SUBSECTION = 0xF2, + enum CodeViewIdentifiers { + DEBUG_SECTION_MAGIC = 0x4, + DEBUG_SYMBOL_SUBSECTION = 0xF1, + DEBUG_LINE_TABLE_SUBSECTION = 0xF2, DEBUG_STRING_TABLE_SUBSECTION = 0xF3, - DEBUG_INDEX_SUBSECTION = 0xF4, + DEBUG_INDEX_SUBSECTION = 0xF4, // Symbol subsections are split into records of different types. DEBUG_SYMBOL_TYPE_PROC_START = 0x1147, - DEBUG_SYMBOL_TYPE_PROC_END = 0x114F + DEBUG_SYMBOL_TYPE_PROC_END = 0x114F }; inline bool isReservedSectionNumber(int32_t SectionNumber) { diff --git a/include/llvm/Support/COM.h b/include/llvm/Support/COM.h new file mode 100644 index 000000000000..a2d5a7a68ba9 --- /dev/null +++ b/include/llvm/Support/COM.h @@ -0,0 +1,36 @@ +//===- llvm/Support/COM.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// Provides a library for accessing COM functionality of the Host OS. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COM_H +#define LLVM_SUPPORT_COM_H + +namespace llvm { +namespace sys { + +enum class COMThreadingMode { SingleThreaded, MultiThreaded }; + +class InitializeCOMRAII { +public: + explicit InitializeCOMRAII(COMThreadingMode Threading, + bool SpeedOverMemory = false); + ~InitializeCOMRAII(); + +private: + InitializeCOMRAII(const InitializeCOMRAII &) = delete; + void operator=(const InitializeCOMRAII &) = delete; +}; +} +} + +#endif diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 1c06bf5f8c07..bd1d1cb6dc97 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -20,6 +20,7 @@ #ifndef LLVM_SUPPORT_COMMANDLINE_H #define LLVM_SUPPORT_COMMANDLINE_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" @@ -72,8 +73,17 @@ void AddExtraVersionPrinter(void (*func)()); // (Currently not perfect, but best-effort.) void PrintOptionValues(); -// MarkOptionsChanged - Internal helper function. -void MarkOptionsChanged(); +// Forward declaration - AddLiteralOption needs to be up here to make gcc happy. +class Option; + +/// \brief Adds a new option for parsing and provides the option it refers to. +/// +/// \param O pointer to the option +/// \param Name the string name for the option to handle during parsing +/// +/// Literal options are used by some parsers to register special option values. +/// This is how the PassNameParser registers pass names for opt. +void AddLiteralOption(Option &O, const char *Name); //===----------------------------------------------------------------------===// // Flags permitted to be passed to command line arguments @@ -191,13 +201,13 @@ class Option { unsigned Misc : 3; unsigned Position; // Position of last occurrence of the option unsigned AdditionalVals; // Greater than 0 for multi-valued option. - Option *NextRegistered; // Singly linked list of registered options. public: const char *ArgStr; // The argument string itself (ex: "help", "o") const char *HelpStr; // The descriptive text message for -help const char *ValueStr; // String describing what the value of this option is OptionCategory *Category; // The Category this option belongs to + bool FullyInitialized; // Has addArguemnt been called? inline enum NumOccurrencesFlag getNumOccurrencesFlag() const { return (enum NumOccurrencesFlag)Occurrences; @@ -221,7 +231,7 @@ public: //-------------------------------------------------------------------------=== // Accessor functions set by OptionModifiers // - void setArgStr(const char *S) { ArgStr = S; } + void setArgStr(const char *S); void setDescription(const char *S) { HelpStr = S; } void setValueStr(const char *S) { ValueStr = S; } void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; } @@ -237,8 +247,8 @@ protected: enum OptionHidden Hidden) : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), Position(0), - AdditionalVals(0), NextRegistered(nullptr), ArgStr(""), HelpStr(""), - ValueStr(""), Category(&GeneralCategory) {} + AdditionalVals(0), ArgStr(""), HelpStr(""), ValueStr(""), + Category(&GeneralCategory), FullyInitialized(false) {} inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } @@ -253,8 +263,6 @@ public: /// For testing purposes only. void removeArgument(); - Option *getNextRegisteredOption() const { return NextRegistered; } - // Return the width of the option tag for printing... virtual size_t getOptionWidth() const = 0; @@ -344,9 +352,14 @@ struct cat { // Support value comparison outside the template. struct GenericOptionValue { - virtual ~GenericOptionValue() {} virtual bool compare(const GenericOptionValue &V) const = 0; +protected: + ~GenericOptionValue() = default; + GenericOptionValue() = default; + GenericOptionValue(const GenericOptionValue&) = default; + GenericOptionValue &operator=(const GenericOptionValue &) = default; + private: virtual void anchor(); }; @@ -372,6 +385,9 @@ struct OptionValueBase : public GenericOptionValue { bool compare(const GenericOptionValue & /*V*/) const override { return false; } + +protected: + ~OptionValueBase() = default; }; // Simple copy of the option value. @@ -379,6 +395,11 @@ template <class DataType> class OptionValueCopy : public GenericOptionValue { DataType Value; bool Valid; +protected: + ~OptionValueCopy() = default; + OptionValueCopy(const OptionValueCopy&) = default; + OptionValueCopy &operator=(const OptionValueCopy&) = default; + public: OptionValueCopy() : Valid(false) {} @@ -409,12 +430,19 @@ public: template <class DataType> struct OptionValueBase<DataType, false> : OptionValueCopy<DataType> { typedef DataType WrapperType; + +protected: + ~OptionValueBase() = default; + OptionValueBase() = default; + OptionValueBase(const OptionValueBase&) = default; + OptionValueBase &operator=(const OptionValueBase&) = default; }; // Top-level option class. template <class DataType> -struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::value> { - OptionValue() {} +struct OptionValue final + : OptionValueBase<DataType, std::is_class<DataType>::value> { + OptionValue() = default; OptionValue(const DataType &V) { this->setValue(V); } // Some options may take their value from a different data type. @@ -427,7 +455,8 @@ struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::value> { // Other safe-to-copy-by-value common option types. enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; template <> -struct OptionValue<cl::boolOrDefault> : OptionValueCopy<cl::boolOrDefault> { +struct OptionValue<cl::boolOrDefault> final + : OptionValueCopy<cl::boolOrDefault> { typedef cl::boolOrDefault WrapperType; OptionValue() {} @@ -442,7 +471,8 @@ private: void anchor() override; }; -template <> struct OptionValue<std::string> : OptionValueCopy<std::string> { +template <> +struct OptionValue<std::string> final : OptionValueCopy<std::string> { typedef StringRef WrapperType; OptionValue() {} @@ -531,6 +561,8 @@ protected: }; public: + generic_parser_base(Option &O) : Owner(O) {} + virtual ~generic_parser_base() {} // Base class should have virtual-dtor // getNumOptions - Virtual function implemented by generic subclass to @@ -569,18 +601,13 @@ public: printGenericOptionDiff(O, V, Default, GlobalWidth); } - void initialize(Option &O) { - // All of the modifiers for the option have been processed by now, so the - // argstr field should be stable, copy it down now. - // - hasArgStr = O.hasArgStr(); - } + void initialize() {} void getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) { // If there has been no argstr specified, that means that we need to add an // argument for every possible option. This ensures that our options are // vectored to us. - if (!hasArgStr) + if (!Owner.hasArgStr()) for (unsigned i = 0, e = getNumOptions(); i != e; ++i) OptionNames.push_back(getOption(i)); } @@ -597,7 +624,7 @@ public: // // If this is the case, we cannot allow a value. // - if (hasArgStr) + if (Owner.hasArgStr()) return ValueRequired; else return ValueDisallowed; @@ -609,7 +636,7 @@ public: unsigned findOption(const char *Name); protected: - bool hasArgStr; + Option &Owner; }; // Default parser implementation - This implementation depends on having a @@ -629,6 +656,7 @@ protected: SmallVector<OptionInfo, 8> Values; public: + parser(Option &O) : generic_parser_base(O) {} typedef DataType parser_data_type; // Implement virtual functions needed by generic_parser_base @@ -646,7 +674,7 @@ public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V) { StringRef ArgVal; - if (hasArgStr) + if (Owner.hasArgStr()) ArgVal = Arg; else ArgVal = ArgName; @@ -667,7 +695,7 @@ public: assert(findOption(Name) == Values.size() && "Option already exists!"); OptionInfo X(Name, static_cast<DataType>(V), HelpStr); Values.push_back(X); - MarkOptionsChanged(); + AddLiteralOption(Owner, Name); } /// removeLiteralOption - Remove the specified option. @@ -684,7 +712,8 @@ public: // class basic_parser_impl { // non-template implementation of basic_parser<t> public: - virtual ~basic_parser_impl() {} + basic_parser_impl(Option &O) {} + enum ValueExpected getValueExpectedFlagDefault() const { return ValueRequired; @@ -692,7 +721,7 @@ public: void getExtraOptionNames(SmallVectorImpl<const char *> &) {} - void initialize(Option &) {} + void initialize() {} // Return the width of the option tag for printing... size_t getOptionWidth(const Option &O) const; @@ -713,6 +742,7 @@ public: virtual void anchor(); protected: + ~basic_parser_impl() = default; // A helper for basic_parser::printOptionDiff. void printOptionName(const Option &O, size_t GlobalWidth) const; }; @@ -722,21 +752,26 @@ protected: // template <class DataType> class basic_parser : public basic_parser_impl { public: + basic_parser(Option &O) : basic_parser_impl(O) {} typedef DataType parser_data_type; typedef OptionValue<DataType> OptVal; + +protected: + // Workaround Clang PR22793 + ~basic_parser() {} }; //-------------------------------------------------- // parser<bool> // -template <> class parser<bool> : public basic_parser<bool> { - const char *ArgStr; - +template <> class parser<bool> final : public basic_parser<bool> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val); - template <class Opt> void initialize(Opt &O) { ArgStr = O.ArgStr; } + void initialize() {} enum ValueExpected getValueExpectedFlagDefault() const { return ValueOptional; @@ -756,8 +791,11 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<bool>); //-------------------------------------------------- // parser<boolOrDefault> -template <> class parser<boolOrDefault> : public basic_parser<boolOrDefault> { +template <> +class parser<boolOrDefault> final : public basic_parser<boolOrDefault> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val); @@ -780,8 +818,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>); //-------------------------------------------------- // parser<int> // -template <> class parser<int> : public basic_parser<int> { +template <> class parser<int> final : public basic_parser<int> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val); @@ -800,8 +840,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<int>); //-------------------------------------------------- // parser<unsigned> // -template <> class parser<unsigned> : public basic_parser<unsigned> { +template <> class parser<unsigned> final : public basic_parser<unsigned> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val); @@ -821,8 +863,11 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned>); // parser<unsigned long long> // template <> -class parser<unsigned long long> : public basic_parser<unsigned long long> { +class parser<unsigned long long> final + : public basic_parser<unsigned long long> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned long long &Val); @@ -842,8 +887,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned long long>); //-------------------------------------------------- // parser<double> // -template <> class parser<double> : public basic_parser<double> { +template <> class parser<double> final : public basic_parser<double> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val); @@ -862,8 +909,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<double>); //-------------------------------------------------- // parser<float> // -template <> class parser<float> : public basic_parser<float> { +template <> class parser<float> final : public basic_parser<float> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val); @@ -882,8 +931,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<float>); //-------------------------------------------------- // parser<std::string> // -template <> class parser<std::string> : public basic_parser<std::string> { +template <> class parser<std::string> final : public basic_parser<std::string> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, std::string &Value) { Value = Arg.str(); @@ -905,8 +956,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<std::string>); //-------------------------------------------------- // parser<char> // -template <> class parser<char> : public basic_parser<char> { +template <> class parser<char> final : public basic_parser<char> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, char &Value) { Value = Arg[0]; @@ -942,7 +995,7 @@ void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V, // This is instantiated for basic parsers when the parsed value has a different // type than the option value. e.g. HelpPrinter. template <class ParserDT, class ValDT> struct OptionDiffPrinter { - void print(const Option &O, const parser<ParserDT> P, const ValDT & /*V*/, + void print(const Option &O, const parser<ParserDT> &P, const ValDT & /*V*/, const OptionValue<ValDT> & /*Default*/, size_t GlobalWidth) { P.printOptionNoValue(O, GlobalWidth); } @@ -951,7 +1004,7 @@ template <class ParserDT, class ValDT> struct OptionDiffPrinter { // This is instantiated for basic parsers when the parsed value has the same // type as the option value. template <class DT> struct OptionDiffPrinter<DT, DT> { - void print(const Option &O, const parser<DT> P, const DT &V, + void print(const Option &O, const parser<DT> &P, const DT &V, const OptionValue<DT> &Default, size_t GlobalWidth) { P.printOptionDiff(O, V, Default, GlobalWidth); } @@ -1015,8 +1068,14 @@ template <> struct applicator<MiscFlags> { static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); } }; -// apply method - Apply a modifier to an option in a type safe way. -template <class Mod, class Opt> void apply(const Mod &M, Opt *O) { +// apply method - Apply modifiers to an option in a type safe way. +template <class Opt, class Mod, class... Mods> +void apply(Opt *O, const Mod &M, const Mods &... Ms) { + applicator<Mod>::opt(M, *O); + apply(O, Ms...); +} + +template <class Opt, class Mod> void apply(Opt *O, const Mod &M) { applicator<Mod>::opt(M, *O); } @@ -1166,9 +1225,13 @@ class opt : public Option, void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + // Command line options should not be copyable + opt(const opt &) = delete; + opt &operator=(const opt &) = delete; + public: // setInitialValue - Used by the cl::init modifier... void setInitialValue(const DataType &V) { this->setValue(V, true); } @@ -1180,95 +1243,10 @@ public: return this->getValue(); } - // One option... - template <class M0t> - explicit opt(const M0t &M0) - : Option(Optional, NotHidden) { - apply(M0, this); - done(); - } - - // Two options... - template <class M0t, class M1t> - opt(const M0t &M0, const M1t &M1) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - done(); - } - - // Three options... - template <class M0t, class M1t, class M2t> - opt(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - done(); - } - // Four options... - template <class M0t, class M1t, class M2t, class M3t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - done(); - } - // Five options... - template <class M0t, class M1t, class M2t, class M3t, class M4t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, - const M5t &M5) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - done(); - } - // Seven options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, - class M6t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, - const M5t &M5, const M6t &M6) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - apply(M6, this); - done(); - } - // Eight options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, - class M6t, class M7t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, - const M5t &M5, const M6t &M6, const M7t &M7) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - apply(M6, this); - apply(M7, this); + template <class... Mods> + explicit opt(const Mods &... Ms) + : Option(Optional, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1361,9 +1339,13 @@ class list : public Option, public list_storage<DataType, Storage> { void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + // Command line options should not be copyable + list(const list &) = delete; + list &operator=(const list &) = delete; + public: ParserClass &getParser() { return Parser; } @@ -1374,94 +1356,10 @@ public: void setNumAdditionalVals(unsigned n) { Option::setNumAdditionalVals(n); } - // One option... - template <class M0t> - explicit list(const M0t &M0) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - done(); - } - // Two options... - template <class M0t, class M1t> - list(const M0t &M0, const M1t &M1) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - done(); - } - // Three options... - template <class M0t, class M1t, class M2t> - list(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - done(); - } - // Four options... - template <class M0t, class M1t, class M2t, class M3t> - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - done(); - } - // Five options... - template <class M0t, class M1t, class M2t, class M3t, class M4t> - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t> - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - done(); - } - // Seven options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, - class M6t> - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - apply(M6, this); - done(); - } - // Eight options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, - class M6t, class M7t> - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - apply(M6, this); - apply(M7, this); + template <class... Mods> + explicit list(const Mods &... Ms) + : Option(ZeroOrMore, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1581,9 +1479,13 @@ class bits : public Option, public bits_storage<DataType, Storage> { void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + // Command line options should not be copyable + bits(const bits &) = delete; + bits &operator=(const bits &) = delete; + public: ParserClass &getParser() { return Parser; } @@ -1592,94 +1494,10 @@ public: return Positions[optnum]; } - // One option... - template <class M0t> - explicit bits(const M0t &M0) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - done(); - } - // Two options... - template <class M0t, class M1t> - bits(const M0t &M0, const M1t &M1) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - done(); - } - // Three options... - template <class M0t, class M1t, class M2t> - bits(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - done(); - } - // Four options... - template <class M0t, class M1t, class M2t, class M3t> - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - done(); - } - // Five options... - template <class M0t, class M1t, class M2t, class M3t, class M4t> - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t> - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - done(); - } - // Seven options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, - class M6t> - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - apply(M6, this); - done(); - } - // Eight options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, - class M6t, class M7t> - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - apply(M6, this); - apply(M7, this); + template <class... Mods> + explicit bits(const Mods &... Ms) + : Option(ZeroOrMore, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1718,6 +1536,10 @@ class alias : public Option { addArgument(); } + // Command line options should not be copyable + alias(const alias &) = delete; + alias &operator=(const alias &) = delete; + public: void setAliasFor(Option &O) { if (AliasFor) @@ -1725,38 +1547,10 @@ public: AliasFor = &O; } - // One option... - template <class M0t> - explicit alias(const M0t &M0) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); - done(); - } - // Two options... - template <class M0t, class M1t> - alias(const M0t &M0, const M1t &M1) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); - apply(M1, this); - done(); - } - // Three options... - template <class M0t, class M1t, class M2t> - alias(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - done(); - } - // Four options... - template <class M0t, class M1t, class M2t, class M3t> - alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + template <class... Mods> + explicit alias(const Mods &... Ms) : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); + apply(this, Ms...); done(); } }; @@ -1795,9 +1589,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false); /// \brief Use this to get a StringMap to all registered named options /// (e.g. -help). Note \p Map Should be an empty StringMap. /// -/// \param [out] Map will be filled with mappings where the key is the -/// Option argument string (e.g. "help") and value is the corresponding -/// Option*. +/// \return A reference to the StringMap used by the cl APIs to parse options. /// /// Access to unnamed arguments (i.e. positional) are not provided because /// it is expected that the client already has access to these. @@ -1805,8 +1597,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false); /// Typical usage: /// \code /// main(int argc,char* argv[]) { -/// StringMap<llvm::cl::Option*> opts; -/// llvm::cl::getRegisteredOptions(opts); +/// StringMap<llvm::cl::Option*> &opts = llvm::cl::getRegisteredOptions(); /// assert(opts.count("help") == 1) /// opts["help"]->setDescription("Show alphabetical help information") /// // More code @@ -1818,7 +1609,11 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false); /// This interface is useful for modifying options in libraries that are out of /// the control of the client. The options should be modified before calling /// llvm::cl::ParseCommandLineOptions(). -void getRegisteredOptions(StringMap<Option *> &Map); +/// +/// Hopefully this API can be depricated soon. Any situation where options need +/// to be modified by tools or libraries should be handled by sane APIs rather +/// than just handing around a global list. +StringMap<Option *> &getRegisteredOptions(); //===----------------------------------------------------------------------===// // Standalone command line processing utilities. @@ -1889,6 +1684,24 @@ bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, SmallVectorImpl<const char *> &Argv, bool MarkEOLs = false); +/// \brief Mark all options not part of this category as cl::ReallyHidden. +/// +/// \param Category the category of options to keep displaying +/// +/// Some tools (like clang-format) like to be able to hide all options that are +/// not specific to the tool. This function allows a tool to specify a single +/// option category to display in the -help output. +void HideUnrelatedOptions(cl::OptionCategory &Category); + +/// \brief Mark all options not part of the categories as cl::ReallyHidden. +/// +/// \param Categories the categories of options to keep displaying. +/// +/// Some tools (like clang-format) like to be able to hide all options that are +/// not specific to the tool. This function allows a tool to specify a single +/// option category to display in the -help output. +void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories); + } // End namespace cl } // End namespace llvm diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index d008fec89d64..c81fbaff9dba 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -52,14 +52,14 @@ /// \macro LLVM_MSC_PREREQ /// \brief Is the compiler MSVC of at least the specified version? /// The common \param version values to check for are: -/// * 1700: Microsoft Visual Studio 2012 / 11.0 /// * 1800: Microsoft Visual Studio 2013 / 12.0 +/// * 1900: Microsoft Visual Studio 2015 / 14.0 #ifdef _MSC_VER #define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version)) -// We require at least MSVC 2012. -#if !LLVM_MSC_PREREQ(1700) -#error LLVM requires at least MSVC 2012. +// We require at least MSVC 2013. +#if !LLVM_MSC_PREREQ(1800) +#error LLVM requires at least MSVC 2013. #endif #else @@ -72,54 +72,26 @@ #define LLVM_NOEXCEPT #endif -/// \brief Does the compiler support r-value reference *this? +/// \brief Does the compiler support ref-qualifiers for *this? /// -/// Sadly, this is separate from just r-value reference support because GCC -/// implemented this later than everything else. +/// Sadly, this is separate from just rvalue reference support because GCC +/// and MSVC implemented this later than everything else. #if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1) #define LLVM_HAS_RVALUE_REFERENCE_THIS 1 #else #define LLVM_HAS_RVALUE_REFERENCE_THIS 0 #endif -/// \macro LLVM_HAS_VARIADIC_TEMPLATES -/// \brief Does this compiler support variadic templates. +/// Expands to '&' if ref-qualifiers for *this are supported. /// -/// Implies LLVM_HAS_RVALUE_REFERENCES and the existence of std::forward. -#if __has_feature(cxx_variadic_templates) || LLVM_MSC_PREREQ(1800) -# define LLVM_HAS_VARIADIC_TEMPLATES 1 -#else -# define LLVM_HAS_VARIADIC_TEMPLATES 0 -#endif - -/// Expands to '&' if r-value references are supported. -/// -/// This can be used to provide l-value/r-value overrides of member functions. -/// The r-value override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS +/// This can be used to provide lvalue/rvalue overrides of member functions. +/// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS #if LLVM_HAS_RVALUE_REFERENCE_THIS #define LLVM_LVALUE_FUNCTION & #else #define LLVM_LVALUE_FUNCTION #endif -/// LLVM_DELETED_FUNCTION - Expands to = delete if the compiler supports it. -/// Use to mark functions as uncallable. Member functions with this should -/// be declared private so that some behavior is kept in C++03 mode. -/// -/// class DontCopy { -/// private: -/// DontCopy(const DontCopy&) LLVM_DELETED_FUNCTION; -/// DontCopy &operator =(const DontCopy&) LLVM_DELETED_FUNCTION; -/// public: -/// ... -/// }; -#if __has_feature(cxx_deleted_functions) || \ - defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1800) -#define LLVM_DELETED_FUNCTION = delete -#else -#define LLVM_DELETED_FUNCTION -#endif - #if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define LLVM_CONSTEXPR constexpr #else @@ -251,6 +223,16 @@ #define LLVM_ATTRIBUTE_RETURNS_NONNULL #endif +/// \macro LLVM_ATTRIBUTE_RETURNS_NOALIAS Used to mark a function as returning a +/// pointer that does not alias any other valid pointer. +#ifdef __GNUC__ +#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict) +#else +#define LLVM_ATTRIBUTE_RETURNS_NOALIAS +#endif + /// LLVM_EXTENSION - Support compilers where we have a keyword to suppress /// pedantic diagnostics. #ifdef __GNUC__ @@ -287,6 +269,12 @@ /// which causes the program to exit abnormally. #if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0) # define LLVM_BUILTIN_TRAP __builtin_trap() +#elif defined(_MSC_VER) +// The __debugbreak intrinsic is supported by MSVC, does not require forward +// declarations involving platform-specific typedefs (unlike RaiseException), +// results in a call to vectored exception handlers, and encodes to a short +// instruction that still causes the trapping behavior we want. +# define LLVM_BUILTIN_TRAP __debugbreak() #else # define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0 #endif @@ -303,6 +291,37 @@ # define LLVM_ASSUME_ALIGNED(p, a) (p) #endif +/// \macro LLVM_ALIGNAS +/// \brief Used to specify a minimum alignment for a structure or variable. The +/// alignment must be a constant integer. Use LLVM_PTR_SIZE to compute +/// alignments in terms of the size of a pointer. +/// +/// Note that __declspec(align) has special quirks, it's not legal to pass a +/// structure with __declspec(align) as a formal parameter. +#ifdef _MSC_VER +# define LLVM_ALIGNAS(x) __declspec(align(x)) +#elif __GNUC__ && !__has_feature(cxx_alignas) && !LLVM_GNUC_PREREQ(4, 8, 0) +# define LLVM_ALIGNAS(x) __attribute__((aligned(x))) +#else +# define LLVM_ALIGNAS(x) alignas(x) +#endif + +/// \macro LLVM_PTR_SIZE +/// \brief A constant integer equivalent to the value of sizeof(void*). +/// Generally used in combination with LLVM_ALIGNAS or when doing computation in +/// the preprocessor. +#ifdef __SIZEOF_POINTER__ +# define LLVM_PTR_SIZE __SIZEOF_POINTER__ +#elif defined(_WIN64) +# define LLVM_PTR_SIZE 8 +#elif defined(_WIN32) +# define LLVM_PTR_SIZE 4 +#elif defined(_MSC_VER) +# error "could not determine LLVM_PTR_SIZE as a constant int for MSVC" +#else +# define LLVM_PTR_SIZE sizeof(void *) +#endif + /// \macro LLVM_FUNCTION_NAME /// \brief Expands to __func__ on compilers which support it. Otherwise, /// expands to a compiler-dependent replacement. @@ -344,26 +363,6 @@ # define LLVM_IS_UNALIGNED_ACCESS_FAST 0 #endif -/// \macro LLVM_EXPLICIT -/// \brief Expands to explicit on compilers which support explicit conversion -/// operators. Otherwise expands to nothing. -#if __has_feature(cxx_explicit_conversions) || \ - defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1800) -#define LLVM_EXPLICIT explicit -#else -#define LLVM_EXPLICIT -#endif - -/// \brief Does the compiler support generalized initializers (using braced -/// lists and std::initializer_list). While clang may claim it supports general -/// initializers, if we're using MSVC's headers, we might not have a usable -/// std::initializer list type from the STL. Disable this for now. -#if __has_feature(cxx_generalized_initializers) && !defined(_MSC_VER) -#define LLVM_HAS_INITIALIZER_LISTS 1 -#else -#define LLVM_HAS_INITIALIZER_LISTS 0 -#endif - /// \brief Mark debug helper function definitions like dump() that should not be /// stripped from debug builds. // FIXME: Move this to a private config.h as it's not usable in public headers. @@ -373,4 +372,33 @@ #define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE #endif +/// \macro LLVM_THREAD_LOCAL +/// \brief A thread-local storage specifier which can be used with globals, +/// extern globals, and static globals. +/// +/// This is essentially an extremely restricted analog to C++11's thread_local +/// support, and uses that when available. However, it falls back on +/// platform-specific or vendor-provided extensions when necessary. These +/// extensions don't support many of the C++11 thread_local's features. You +/// should only use this for PODs that you can statically initialize to +/// some constant value. In almost all circumstances this is most appropriate +/// for use with a pointer, integer, or small aggregation of pointers and +/// integers. +#if LLVM_ENABLE_THREADS +#if __has_feature(cxx_thread_local) +#define LLVM_THREAD_LOCAL thread_local +#elif defined(_MSC_VER) +// MSVC supports this with a __declspec. +#define LLVM_THREAD_LOCAL __declspec(thread) +#else +// Clang, GCC, and other compatible compilers used __thread prior to C++11 and +// we only need the restricted functionality that provides. +#define LLVM_THREAD_LOCAL __thread +#endif +#else // !LLVM_ENABLE_THREADS +// If threading is disabled entirely, this compiles to nothing and you get +// a normal global variable. +#define LLVM_THREAD_LOCAL +#endif + #endif diff --git a/include/llvm/Support/Compression.h b/include/llvm/Support/Compression.h index 88727fa3fcfc..28274d67aad2 100644 --- a/include/llvm/Support/Compression.h +++ b/include/llvm/Support/Compression.h @@ -14,12 +14,10 @@ #ifndef LLVM_SUPPORT_COMPRESSION_H #define LLVM_SUPPORT_COMPRESSION_H -#include "llvm/ADT/SmallVector.h" #include "llvm/Support/DataTypes.h" -#include <memory> namespace llvm { - +template <typename T> class SmallVectorImpl; class StringRef; namespace zlib { diff --git a/include/llvm/Support/ConvertUTF.h b/include/llvm/Support/ConvertUTF.h index a184d0df2132..38952ec99e61 100644 --- a/include/llvm/Support/ConvertUTF.h +++ b/include/llvm/Support/ConvertUTF.h @@ -251,6 +251,14 @@ bool hasUTF16ByteOrderMark(ArrayRef<char> SrcBytes); */ bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out); +/** + * Converts a UTF-8 string into a UTF-16 string with native endianness. + * + * \returns true on success + */ +bool convertUTF8ToUTF16String(StringRef SrcUTF8, + SmallVectorImpl<UTF16> &DstUTF16); + } /* end namespace llvm */ #endif diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index 1f3965c8ade4..c08c3c1f0d21 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -14,8 +14,6 @@ #include <string> namespace llvm { -class StringRef; - class CrashRecoveryContextCleanup; /// \brief Crash recovery helper object. diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h index 48235d4145bd..3ffa9bc90dd1 100644 --- a/include/llvm/Support/DataExtractor.h +++ b/include/llvm/Support/DataExtractor.h @@ -10,7 +10,6 @@ #ifndef LLVM_SUPPORT_DATAEXTRACTOR_H #define LLVM_SUPPORT_DATAEXTRACTOR_H -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/Support/Debug.h b/include/llvm/Support/Debug.h index e93e6ca34498..fff4f986a6c0 100644 --- a/include/llvm/Support/Debug.h +++ b/include/llvm/Support/Debug.h @@ -28,9 +28,8 @@ #ifndef LLVM_SUPPORT_DEBUG_H #define LLVM_SUPPORT_DEBUG_H -#include "llvm/Support/raw_ostream.h" - namespace llvm { +class raw_ostream; #ifndef NDEBUG /// DebugFlag - This boolean is set to true if the '-debug' command line option diff --git a/include/llvm/Support/Dwarf.def b/include/llvm/Support/Dwarf.def new file mode 100644 index 000000000000..4b923b897e6f --- /dev/null +++ b/include/llvm/Support/Dwarf.def @@ -0,0 +1,350 @@ +//===- llvm/Support/Dwarf.def - Dwarf definitions ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through Dwarf enumerators. +// +//===----------------------------------------------------------------------===// + +// TODO: Add other DW-based macros. +#if !(defined HANDLE_DW_TAG || defined HANDLE_DW_OP || \ + defined HANDLE_DW_LANG || defined HANDLE_DW_ATE || \ + defined HANDLE_DW_VIRTUALITY) +#error "Missing macro definition of HANDLE_DW*" +#endif + +#ifndef HANDLE_DW_TAG +#define HANDLE_DW_TAG(ID, NAME) +#endif + +#ifndef HANDLE_DW_OP +#define HANDLE_DW_OP(ID, NAME) +#endif + +#ifndef HANDLE_DW_LANG +#define HANDLE_DW_LANG(ID, NAME) +#endif + +#ifndef HANDLE_DW_ATE +#define HANDLE_DW_ATE(ID, NAME) +#endif + +#ifndef HANDLE_DW_VIRTUALITY +#define HANDLE_DW_VIRTUALITY(ID, NAME) +#endif + +HANDLE_DW_TAG(0x0001, array_type) +HANDLE_DW_TAG(0x0002, class_type) +HANDLE_DW_TAG(0x0003, entry_point) +HANDLE_DW_TAG(0x0004, enumeration_type) +HANDLE_DW_TAG(0x0005, formal_parameter) +HANDLE_DW_TAG(0x0008, imported_declaration) +HANDLE_DW_TAG(0x000a, label) +HANDLE_DW_TAG(0x000b, lexical_block) +HANDLE_DW_TAG(0x000d, member) +HANDLE_DW_TAG(0x000f, pointer_type) +HANDLE_DW_TAG(0x0010, reference_type) +HANDLE_DW_TAG(0x0011, compile_unit) +HANDLE_DW_TAG(0x0012, string_type) +HANDLE_DW_TAG(0x0013, structure_type) +HANDLE_DW_TAG(0x0015, subroutine_type) +HANDLE_DW_TAG(0x0016, typedef) +HANDLE_DW_TAG(0x0017, union_type) +HANDLE_DW_TAG(0x0018, unspecified_parameters) +HANDLE_DW_TAG(0x0019, variant) +HANDLE_DW_TAG(0x001a, common_block) +HANDLE_DW_TAG(0x001b, common_inclusion) +HANDLE_DW_TAG(0x001c, inheritance) +HANDLE_DW_TAG(0x001d, inlined_subroutine) +HANDLE_DW_TAG(0x001e, module) +HANDLE_DW_TAG(0x001f, ptr_to_member_type) +HANDLE_DW_TAG(0x0020, set_type) +HANDLE_DW_TAG(0x0021, subrange_type) +HANDLE_DW_TAG(0x0022, with_stmt) +HANDLE_DW_TAG(0x0023, access_declaration) +HANDLE_DW_TAG(0x0024, base_type) +HANDLE_DW_TAG(0x0025, catch_block) +HANDLE_DW_TAG(0x0026, const_type) +HANDLE_DW_TAG(0x0027, constant) +HANDLE_DW_TAG(0x0028, enumerator) +HANDLE_DW_TAG(0x0029, file_type) +HANDLE_DW_TAG(0x002a, friend) +HANDLE_DW_TAG(0x002b, namelist) +HANDLE_DW_TAG(0x002c, namelist_item) +HANDLE_DW_TAG(0x002d, packed_type) +HANDLE_DW_TAG(0x002e, subprogram) +HANDLE_DW_TAG(0x002f, template_type_parameter) +HANDLE_DW_TAG(0x0030, template_value_parameter) +HANDLE_DW_TAG(0x0031, thrown_type) +HANDLE_DW_TAG(0x0032, try_block) +HANDLE_DW_TAG(0x0033, variant_part) +HANDLE_DW_TAG(0x0034, variable) +HANDLE_DW_TAG(0x0035, volatile_type) +HANDLE_DW_TAG(0x0036, dwarf_procedure) +HANDLE_DW_TAG(0x0037, restrict_type) +HANDLE_DW_TAG(0x0038, interface_type) +HANDLE_DW_TAG(0x0039, namespace) +HANDLE_DW_TAG(0x003a, imported_module) +HANDLE_DW_TAG(0x003b, unspecified_type) +HANDLE_DW_TAG(0x003c, partial_unit) +HANDLE_DW_TAG(0x003d, imported_unit) +HANDLE_DW_TAG(0x003f, condition) +HANDLE_DW_TAG(0x0040, shared_type) +HANDLE_DW_TAG(0x0041, type_unit) +HANDLE_DW_TAG(0x0042, rvalue_reference_type) +HANDLE_DW_TAG(0x0043, template_alias) + +// Mock tags we use as discriminators. +HANDLE_DW_TAG(0x0100, auto_variable) // Tag for local (auto) variables. +HANDLE_DW_TAG(0x0101, arg_variable) // Tag for argument variables. + +// New in DWARF v5. +HANDLE_DW_TAG(0x0044, coarray_type) +HANDLE_DW_TAG(0x0045, generic_subrange) +HANDLE_DW_TAG(0x0046, dynamic_type) + +// User-defined tags. +HANDLE_DW_TAG(0x4081, MIPS_loop) +HANDLE_DW_TAG(0x4101, format_label) +HANDLE_DW_TAG(0x4102, function_template) +HANDLE_DW_TAG(0x4103, class_template) +HANDLE_DW_TAG(0x4106, GNU_template_template_param) +HANDLE_DW_TAG(0x4107, GNU_template_parameter_pack) +HANDLE_DW_TAG(0x4108, GNU_formal_parameter_pack) +HANDLE_DW_TAG(0x4200, APPLE_property) + +HANDLE_DW_OP(0x03, addr) +HANDLE_DW_OP(0x06, deref) +HANDLE_DW_OP(0x08, const1u) +HANDLE_DW_OP(0x09, const1s) +HANDLE_DW_OP(0x0a, const2u) +HANDLE_DW_OP(0x0b, const2s) +HANDLE_DW_OP(0x0c, const4u) +HANDLE_DW_OP(0x0d, const4s) +HANDLE_DW_OP(0x0e, const8u) +HANDLE_DW_OP(0x0f, const8s) +HANDLE_DW_OP(0x10, constu) +HANDLE_DW_OP(0x11, consts) +HANDLE_DW_OP(0x12, dup) +HANDLE_DW_OP(0x13, drop) +HANDLE_DW_OP(0x14, over) +HANDLE_DW_OP(0x15, pick) +HANDLE_DW_OP(0x16, swap) +HANDLE_DW_OP(0x17, rot) +HANDLE_DW_OP(0x18, xderef) +HANDLE_DW_OP(0x19, abs) +HANDLE_DW_OP(0x1a, and) +HANDLE_DW_OP(0x1b, div) +HANDLE_DW_OP(0x1c, minus) +HANDLE_DW_OP(0x1d, mod) +HANDLE_DW_OP(0x1e, mul) +HANDLE_DW_OP(0x1f, neg) +HANDLE_DW_OP(0x20, not) +HANDLE_DW_OP(0x21, or ) +HANDLE_DW_OP(0x22, plus) +HANDLE_DW_OP(0x23, plus_uconst) +HANDLE_DW_OP(0x24, shl) +HANDLE_DW_OP(0x25, shr) +HANDLE_DW_OP(0x26, shra) +HANDLE_DW_OP(0x27, xor) +HANDLE_DW_OP(0x2f, skip) +HANDLE_DW_OP(0x28, bra) +HANDLE_DW_OP(0x29, eq) +HANDLE_DW_OP(0x2a, ge) +HANDLE_DW_OP(0x2b, gt) +HANDLE_DW_OP(0x2c, le) +HANDLE_DW_OP(0x2d, lt) +HANDLE_DW_OP(0x2e, ne) +HANDLE_DW_OP(0x30, lit0) +HANDLE_DW_OP(0x31, lit1) +HANDLE_DW_OP(0x32, lit2) +HANDLE_DW_OP(0x33, lit3) +HANDLE_DW_OP(0x34, lit4) +HANDLE_DW_OP(0x35, lit5) +HANDLE_DW_OP(0x36, lit6) +HANDLE_DW_OP(0x37, lit7) +HANDLE_DW_OP(0x38, lit8) +HANDLE_DW_OP(0x39, lit9) +HANDLE_DW_OP(0x3a, lit10) +HANDLE_DW_OP(0x3b, lit11) +HANDLE_DW_OP(0x3c, lit12) +HANDLE_DW_OP(0x3d, lit13) +HANDLE_DW_OP(0x3e, lit14) +HANDLE_DW_OP(0x3f, lit15) +HANDLE_DW_OP(0x40, lit16) +HANDLE_DW_OP(0x41, lit17) +HANDLE_DW_OP(0x42, lit18) +HANDLE_DW_OP(0x43, lit19) +HANDLE_DW_OP(0x44, lit20) +HANDLE_DW_OP(0x45, lit21) +HANDLE_DW_OP(0x46, lit22) +HANDLE_DW_OP(0x47, lit23) +HANDLE_DW_OP(0x48, lit24) +HANDLE_DW_OP(0x49, lit25) +HANDLE_DW_OP(0x4a, lit26) +HANDLE_DW_OP(0x4b, lit27) +HANDLE_DW_OP(0x4c, lit28) +HANDLE_DW_OP(0x4d, lit29) +HANDLE_DW_OP(0x4e, lit30) +HANDLE_DW_OP(0x4f, lit31) +HANDLE_DW_OP(0x50, reg0) +HANDLE_DW_OP(0x51, reg1) +HANDLE_DW_OP(0x52, reg2) +HANDLE_DW_OP(0x53, reg3) +HANDLE_DW_OP(0x54, reg4) +HANDLE_DW_OP(0x55, reg5) +HANDLE_DW_OP(0x56, reg6) +HANDLE_DW_OP(0x57, reg7) +HANDLE_DW_OP(0x58, reg8) +HANDLE_DW_OP(0x59, reg9) +HANDLE_DW_OP(0x5a, reg10) +HANDLE_DW_OP(0x5b, reg11) +HANDLE_DW_OP(0x5c, reg12) +HANDLE_DW_OP(0x5d, reg13) +HANDLE_DW_OP(0x5e, reg14) +HANDLE_DW_OP(0x5f, reg15) +HANDLE_DW_OP(0x60, reg16) +HANDLE_DW_OP(0x61, reg17) +HANDLE_DW_OP(0x62, reg18) +HANDLE_DW_OP(0x63, reg19) +HANDLE_DW_OP(0x64, reg20) +HANDLE_DW_OP(0x65, reg21) +HANDLE_DW_OP(0x66, reg22) +HANDLE_DW_OP(0x67, reg23) +HANDLE_DW_OP(0x68, reg24) +HANDLE_DW_OP(0x69, reg25) +HANDLE_DW_OP(0x6a, reg26) +HANDLE_DW_OP(0x6b, reg27) +HANDLE_DW_OP(0x6c, reg28) +HANDLE_DW_OP(0x6d, reg29) +HANDLE_DW_OP(0x6e, reg30) +HANDLE_DW_OP(0x6f, reg31) +HANDLE_DW_OP(0x70, breg0) +HANDLE_DW_OP(0x71, breg1) +HANDLE_DW_OP(0x72, breg2) +HANDLE_DW_OP(0x73, breg3) +HANDLE_DW_OP(0x74, breg4) +HANDLE_DW_OP(0x75, breg5) +HANDLE_DW_OP(0x76, breg6) +HANDLE_DW_OP(0x77, breg7) +HANDLE_DW_OP(0x78, breg8) +HANDLE_DW_OP(0x79, breg9) +HANDLE_DW_OP(0x7a, breg10) +HANDLE_DW_OP(0x7b, breg11) +HANDLE_DW_OP(0x7c, breg12) +HANDLE_DW_OP(0x7d, breg13) +HANDLE_DW_OP(0x7e, breg14) +HANDLE_DW_OP(0x7f, breg15) +HANDLE_DW_OP(0x80, breg16) +HANDLE_DW_OP(0x81, breg17) +HANDLE_DW_OP(0x82, breg18) +HANDLE_DW_OP(0x83, breg19) +HANDLE_DW_OP(0x84, breg20) +HANDLE_DW_OP(0x85, breg21) +HANDLE_DW_OP(0x86, breg22) +HANDLE_DW_OP(0x87, breg23) +HANDLE_DW_OP(0x88, breg24) +HANDLE_DW_OP(0x89, breg25) +HANDLE_DW_OP(0x8a, breg26) +HANDLE_DW_OP(0x8b, breg27) +HANDLE_DW_OP(0x8c, breg28) +HANDLE_DW_OP(0x8d, breg29) +HANDLE_DW_OP(0x8e, breg30) +HANDLE_DW_OP(0x8f, breg31) +HANDLE_DW_OP(0x90, regx) +HANDLE_DW_OP(0x91, fbreg) +HANDLE_DW_OP(0x92, bregx) +HANDLE_DW_OP(0x93, piece) +HANDLE_DW_OP(0x94, deref_size) +HANDLE_DW_OP(0x95, xderef_size) +HANDLE_DW_OP(0x96, nop) +HANDLE_DW_OP(0x97, push_object_address) +HANDLE_DW_OP(0x98, call2) +HANDLE_DW_OP(0x99, call4) +HANDLE_DW_OP(0x9a, call_ref) +HANDLE_DW_OP(0x9b, form_tls_address) +HANDLE_DW_OP(0x9c, call_frame_cfa) +HANDLE_DW_OP(0x9d, bit_piece) +HANDLE_DW_OP(0x9e, implicit_value) +HANDLE_DW_OP(0x9f, stack_value) + +// Extensions for GNU-style thread-local storage. +HANDLE_DW_OP(0xe0, GNU_push_tls_address) + +// Extensions for Fission proposal. +HANDLE_DW_OP(0xfb, GNU_addr_index) +HANDLE_DW_OP(0xfc, GNU_const_index) + +// DWARF languages. +HANDLE_DW_LANG(0x0001, C89) +HANDLE_DW_LANG(0x0002, C) +HANDLE_DW_LANG(0x0003, Ada83) +HANDLE_DW_LANG(0x0004, C_plus_plus) +HANDLE_DW_LANG(0x0005, Cobol74) +HANDLE_DW_LANG(0x0006, Cobol85) +HANDLE_DW_LANG(0x0007, Fortran77) +HANDLE_DW_LANG(0x0008, Fortran90) +HANDLE_DW_LANG(0x0009, Pascal83) +HANDLE_DW_LANG(0x000a, Modula2) +HANDLE_DW_LANG(0x000b, Java) +HANDLE_DW_LANG(0x000c, C99) +HANDLE_DW_LANG(0x000d, Ada95) +HANDLE_DW_LANG(0x000e, Fortran95) +HANDLE_DW_LANG(0x000f, PLI) +HANDLE_DW_LANG(0x0010, ObjC) +HANDLE_DW_LANG(0x0011, ObjC_plus_plus) +HANDLE_DW_LANG(0x0012, UPC) +HANDLE_DW_LANG(0x0013, D) + +// New in DWARF 5: +HANDLE_DW_LANG(0x0014, Python) +HANDLE_DW_LANG(0x0015, OpenCL) +HANDLE_DW_LANG(0x0016, Go) +HANDLE_DW_LANG(0x0017, Modula3) +HANDLE_DW_LANG(0x0018, Haskell) +HANDLE_DW_LANG(0x0019, C_plus_plus_03) +HANDLE_DW_LANG(0x001a, C_plus_plus_11) +HANDLE_DW_LANG(0x001b, OCaml) +HANDLE_DW_LANG(0x001c, Rust) +HANDLE_DW_LANG(0x001d, C11) +HANDLE_DW_LANG(0x001e, Swift) +HANDLE_DW_LANG(0x001f, Julia) +HANDLE_DW_LANG(0x0020, Dylan) +HANDLE_DW_LANG(0x0021, C_plus_plus_14) +HANDLE_DW_LANG(0x0022, Fortran03) +HANDLE_DW_LANG(0x0023, Fortran08) +HANDLE_DW_LANG(0x8001, Mips_Assembler) + +// DWARF attribute type encodings. +HANDLE_DW_ATE(0x01, address) +HANDLE_DW_ATE(0x02, boolean) +HANDLE_DW_ATE(0x03, complex_float) +HANDLE_DW_ATE(0x04, float) +HANDLE_DW_ATE(0x05, signed) +HANDLE_DW_ATE(0x06, signed_char) +HANDLE_DW_ATE(0x07, unsigned) +HANDLE_DW_ATE(0x08, unsigned_char) +HANDLE_DW_ATE(0x09, imaginary_float) +HANDLE_DW_ATE(0x0a, packed_decimal) +HANDLE_DW_ATE(0x0b, numeric_string) +HANDLE_DW_ATE(0x0c, edited) +HANDLE_DW_ATE(0x0d, signed_fixed) +HANDLE_DW_ATE(0x0e, unsigned_fixed) +HANDLE_DW_ATE(0x0f, decimal_float) +HANDLE_DW_ATE(0x10, UTF) + +// DWARF virtuality codes. +HANDLE_DW_VIRTUALITY(0x00, none) +HANDLE_DW_VIRTUALITY(0x01, virtual) +HANDLE_DW_VIRTUALITY(0x02, pure_virtual) + +#undef HANDLE_DW_TAG +#undef HANDLE_DW_OP +#undef HANDLE_DW_LANG +#undef HANDLE_DW_ATE +#undef HANDLE_DW_VIRTUALITY diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index 47b00b1f09d8..c3d94d19f919 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -20,6 +20,7 @@ #ifndef LLVM_SUPPORT_DWARF_H #define LLVM_SUPPORT_DWARF_H +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" @@ -36,15 +37,11 @@ namespace dwarf { // enumeration base type. enum LLVMConstants : uint32_t { - // llvm mock tags - DW_TAG_invalid = ~0U, // Tag for invalid results. - - DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables. - DW_TAG_arg_variable = 0x101, // Tag for argument variables. - DW_TAG_expression = 0x102, // Tag for complex address expressions. - - DW_TAG_user_base = 0x1000, // Recommended base for user tags. + // LLVM mock tags (see also llvm/Support/Dwarf.def). + DW_TAG_invalid = ~0U, // Tag for invalid results. + DW_VIRTUALITY_invalid = ~0U, // Virtuality for invalid results. + // Other constants. DWARF_VERSION = 4, // Default dwarf version we output. DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes. DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames. @@ -57,82 +54,11 @@ const uint32_t DW_CIE_ID = UINT32_MAX; const uint64_t DW64_CIE_ID = UINT64_MAX; enum Tag : uint16_t { - DW_TAG_array_type = 0x01, - DW_TAG_class_type = 0x02, - DW_TAG_entry_point = 0x03, - DW_TAG_enumeration_type = 0x04, - DW_TAG_formal_parameter = 0x05, - DW_TAG_imported_declaration = 0x08, - DW_TAG_label = 0x0a, - DW_TAG_lexical_block = 0x0b, - DW_TAG_member = 0x0d, - DW_TAG_pointer_type = 0x0f, - DW_TAG_reference_type = 0x10, - DW_TAG_compile_unit = 0x11, - DW_TAG_string_type = 0x12, - DW_TAG_structure_type = 0x13, - DW_TAG_subroutine_type = 0x15, - DW_TAG_typedef = 0x16, - DW_TAG_union_type = 0x17, - DW_TAG_unspecified_parameters = 0x18, - DW_TAG_variant = 0x19, - DW_TAG_common_block = 0x1a, - DW_TAG_common_inclusion = 0x1b, - DW_TAG_inheritance = 0x1c, - DW_TAG_inlined_subroutine = 0x1d, - DW_TAG_module = 0x1e, - DW_TAG_ptr_to_member_type = 0x1f, - DW_TAG_set_type = 0x20, - DW_TAG_subrange_type = 0x21, - DW_TAG_with_stmt = 0x22, - DW_TAG_access_declaration = 0x23, - DW_TAG_base_type = 0x24, - DW_TAG_catch_block = 0x25, - DW_TAG_const_type = 0x26, - DW_TAG_constant = 0x27, - DW_TAG_enumerator = 0x28, - DW_TAG_file_type = 0x29, - DW_TAG_friend = 0x2a, - DW_TAG_namelist = 0x2b, - DW_TAG_namelist_item = 0x2c, - DW_TAG_packed_type = 0x2d, - DW_TAG_subprogram = 0x2e, - DW_TAG_template_type_parameter = 0x2f, - DW_TAG_template_value_parameter = 0x30, - DW_TAG_thrown_type = 0x31, - DW_TAG_try_block = 0x32, - DW_TAG_variant_part = 0x33, - DW_TAG_variable = 0x34, - DW_TAG_volatile_type = 0x35, - DW_TAG_dwarf_procedure = 0x36, - DW_TAG_restrict_type = 0x37, - DW_TAG_interface_type = 0x38, - DW_TAG_namespace = 0x39, - DW_TAG_imported_module = 0x3a, - DW_TAG_unspecified_type = 0x3b, - DW_TAG_partial_unit = 0x3c, - DW_TAG_imported_unit = 0x3d, - DW_TAG_condition = 0x3f, - DW_TAG_shared_type = 0x40, - DW_TAG_type_unit = 0x41, - DW_TAG_rvalue_reference_type = 0x42, - DW_TAG_template_alias = 0x43, - - // New in DWARF 5: - DW_TAG_coarray_type = 0x44, - DW_TAG_generic_subrange = 0x45, - DW_TAG_dynamic_type = 0x46, - - DW_TAG_MIPS_loop = 0x4081, - DW_TAG_format_label = 0x4101, - DW_TAG_function_template = 0x4102, - DW_TAG_class_template = 0x4103, - DW_TAG_GNU_template_template_param = 0x4106, - DW_TAG_GNU_template_parameter_pack = 0x4107, - DW_TAG_GNU_formal_parameter_pack = 0x4108, +#define HANDLE_DW_TAG(ID, NAME) DW_TAG_##NAME = ID, +#include "llvm/Support/Dwarf.def" DW_TAG_lo_user = 0x4080, - DW_TAG_APPLE_property = 0x4200, - DW_TAG_hi_user = 0xffff + DW_TAG_hi_user = 0xffff, + DW_TAG_user_base = 0x1000 // Recommended base for user tags. }; inline bool isType(Tag T) { @@ -359,194 +285,23 @@ enum Form : uint16_t { // Extensions for Fission proposal DW_FORM_GNU_addr_index = 0x1f01, - DW_FORM_GNU_str_index = 0x1f02 + DW_FORM_GNU_str_index = 0x1f02, + + // Alternate debug sections proposal (output of "dwz" tool). + DW_FORM_GNU_ref_alt = 0x1f20, + DW_FORM_GNU_strp_alt = 0x1f21 }; enum LocationAtom { - // Operation encodings - DW_OP_addr = 0x03, - DW_OP_deref = 0x06, - DW_OP_const1u = 0x08, - DW_OP_const1s = 0x09, - DW_OP_const2u = 0x0a, - DW_OP_const2s = 0x0b, - DW_OP_const4u = 0x0c, - DW_OP_const4s = 0x0d, - DW_OP_const8u = 0x0e, - DW_OP_const8s = 0x0f, - DW_OP_constu = 0x10, - DW_OP_consts = 0x11, - DW_OP_dup = 0x12, - DW_OP_drop = 0x13, - DW_OP_over = 0x14, - DW_OP_pick = 0x15, - DW_OP_swap = 0x16, - DW_OP_rot = 0x17, - DW_OP_xderef = 0x18, - DW_OP_abs = 0x19, - DW_OP_and = 0x1a, - DW_OP_div = 0x1b, - DW_OP_minus = 0x1c, - DW_OP_mod = 0x1d, - DW_OP_mul = 0x1e, - DW_OP_neg = 0x1f, - DW_OP_not = 0x20, - DW_OP_or = 0x21, - DW_OP_plus = 0x22, - DW_OP_plus_uconst = 0x23, - DW_OP_shl = 0x24, - DW_OP_shr = 0x25, - DW_OP_shra = 0x26, - DW_OP_xor = 0x27, - DW_OP_skip = 0x2f, - DW_OP_bra = 0x28, - DW_OP_eq = 0x29, - DW_OP_ge = 0x2a, - DW_OP_gt = 0x2b, - DW_OP_le = 0x2c, - DW_OP_lt = 0x2d, - DW_OP_ne = 0x2e, - DW_OP_lit0 = 0x30, - DW_OP_lit1 = 0x31, - DW_OP_lit2 = 0x32, - DW_OP_lit3 = 0x33, - DW_OP_lit4 = 0x34, - DW_OP_lit5 = 0x35, - DW_OP_lit6 = 0x36, - DW_OP_lit7 = 0x37, - DW_OP_lit8 = 0x38, - DW_OP_lit9 = 0x39, - DW_OP_lit10 = 0x3a, - DW_OP_lit11 = 0x3b, - DW_OP_lit12 = 0x3c, - DW_OP_lit13 = 0x3d, - DW_OP_lit14 = 0x3e, - DW_OP_lit15 = 0x3f, - DW_OP_lit16 = 0x40, - DW_OP_lit17 = 0x41, - DW_OP_lit18 = 0x42, - DW_OP_lit19 = 0x43, - DW_OP_lit20 = 0x44, - DW_OP_lit21 = 0x45, - DW_OP_lit22 = 0x46, - DW_OP_lit23 = 0x47, - DW_OP_lit24 = 0x48, - DW_OP_lit25 = 0x49, - DW_OP_lit26 = 0x4a, - DW_OP_lit27 = 0x4b, - DW_OP_lit28 = 0x4c, - DW_OP_lit29 = 0x4d, - DW_OP_lit30 = 0x4e, - DW_OP_lit31 = 0x4f, - DW_OP_reg0 = 0x50, - DW_OP_reg1 = 0x51, - DW_OP_reg2 = 0x52, - DW_OP_reg3 = 0x53, - DW_OP_reg4 = 0x54, - DW_OP_reg5 = 0x55, - DW_OP_reg6 = 0x56, - DW_OP_reg7 = 0x57, - DW_OP_reg8 = 0x58, - DW_OP_reg9 = 0x59, - DW_OP_reg10 = 0x5a, - DW_OP_reg11 = 0x5b, - DW_OP_reg12 = 0x5c, - DW_OP_reg13 = 0x5d, - DW_OP_reg14 = 0x5e, - DW_OP_reg15 = 0x5f, - DW_OP_reg16 = 0x60, - DW_OP_reg17 = 0x61, - DW_OP_reg18 = 0x62, - DW_OP_reg19 = 0x63, - DW_OP_reg20 = 0x64, - DW_OP_reg21 = 0x65, - DW_OP_reg22 = 0x66, - DW_OP_reg23 = 0x67, - DW_OP_reg24 = 0x68, - DW_OP_reg25 = 0x69, - DW_OP_reg26 = 0x6a, - DW_OP_reg27 = 0x6b, - DW_OP_reg28 = 0x6c, - DW_OP_reg29 = 0x6d, - DW_OP_reg30 = 0x6e, - DW_OP_reg31 = 0x6f, - DW_OP_breg0 = 0x70, - DW_OP_breg1 = 0x71, - DW_OP_breg2 = 0x72, - DW_OP_breg3 = 0x73, - DW_OP_breg4 = 0x74, - DW_OP_breg5 = 0x75, - DW_OP_breg6 = 0x76, - DW_OP_breg7 = 0x77, - DW_OP_breg8 = 0x78, - DW_OP_breg9 = 0x79, - DW_OP_breg10 = 0x7a, - DW_OP_breg11 = 0x7b, - DW_OP_breg12 = 0x7c, - DW_OP_breg13 = 0x7d, - DW_OP_breg14 = 0x7e, - DW_OP_breg15 = 0x7f, - DW_OP_breg16 = 0x80, - DW_OP_breg17 = 0x81, - DW_OP_breg18 = 0x82, - DW_OP_breg19 = 0x83, - DW_OP_breg20 = 0x84, - DW_OP_breg21 = 0x85, - DW_OP_breg22 = 0x86, - DW_OP_breg23 = 0x87, - DW_OP_breg24 = 0x88, - DW_OP_breg25 = 0x89, - DW_OP_breg26 = 0x8a, - DW_OP_breg27 = 0x8b, - DW_OP_breg28 = 0x8c, - DW_OP_breg29 = 0x8d, - DW_OP_breg30 = 0x8e, - DW_OP_breg31 = 0x8f, - DW_OP_regx = 0x90, - DW_OP_fbreg = 0x91, - DW_OP_bregx = 0x92, - DW_OP_piece = 0x93, - DW_OP_deref_size = 0x94, - DW_OP_xderef_size = 0x95, - DW_OP_nop = 0x96, - DW_OP_push_object_address = 0x97, - DW_OP_call2 = 0x98, - DW_OP_call4 = 0x99, - DW_OP_call_ref = 0x9a, - DW_OP_form_tls_address = 0x9b, - DW_OP_call_frame_cfa = 0x9c, - DW_OP_bit_piece = 0x9d, - DW_OP_implicit_value = 0x9e, - DW_OP_stack_value = 0x9f, +#define HANDLE_DW_OP(ID, NAME) DW_OP_##NAME = ID, +#include "llvm/Support/Dwarf.def" DW_OP_lo_user = 0xe0, - DW_OP_hi_user = 0xff, - - // Extensions for GNU-style thread-local storage. - DW_OP_GNU_push_tls_address = 0xe0, - - // Extensions for Fission proposal. - DW_OP_GNU_addr_index = 0xfb, - DW_OP_GNU_const_index = 0xfc + DW_OP_hi_user = 0xff }; enum TypeKind { - // Encoding attribute values - DW_ATE_address = 0x01, - DW_ATE_boolean = 0x02, - DW_ATE_complex_float = 0x03, - DW_ATE_float = 0x04, - DW_ATE_signed = 0x05, - DW_ATE_signed_char = 0x06, - DW_ATE_unsigned = 0x07, - DW_ATE_unsigned_char = 0x08, - DW_ATE_imaginary_float = 0x09, - DW_ATE_packed_decimal = 0x0a, - DW_ATE_numeric_string = 0x0b, - DW_ATE_edited = 0x0c, - DW_ATE_signed_fixed = 0x0d, - DW_ATE_unsigned_fixed = 0x0e, - DW_ATE_decimal_float = 0x0f, - DW_ATE_UTF = 0x10, +#define HANDLE_DW_ATE(ID, NAME) DW_ATE_##NAME = ID, +#include "llvm/Support/Dwarf.def" DW_ATE_lo_user = 0x80, DW_ATE_hi_user = 0xff }; @@ -584,45 +339,15 @@ enum VisibilityAttribute { }; enum VirtualityAttribute { - // Virtuality codes - DW_VIRTUALITY_none = 0x00, - DW_VIRTUALITY_virtual = 0x01, - DW_VIRTUALITY_pure_virtual = 0x02 +#define HANDLE_DW_VIRTUALITY(ID, NAME) DW_VIRTUALITY_##NAME = ID, +#include "llvm/Support/Dwarf.def" + DW_VIRTUALITY_max = 0x02 }; enum SourceLanguage { - // Language names - DW_LANG_C89 = 0x0001, - DW_LANG_C = 0x0002, - DW_LANG_Ada83 = 0x0003, - DW_LANG_C_plus_plus = 0x0004, - DW_LANG_Cobol74 = 0x0005, - DW_LANG_Cobol85 = 0x0006, - DW_LANG_Fortran77 = 0x0007, - DW_LANG_Fortran90 = 0x0008, - DW_LANG_Pascal83 = 0x0009, - DW_LANG_Modula2 = 0x000a, - DW_LANG_Java = 0x000b, - DW_LANG_C99 = 0x000c, - DW_LANG_Ada95 = 0x000d, - DW_LANG_Fortran95 = 0x000e, - DW_LANG_PLI = 0x000f, - DW_LANG_ObjC = 0x0010, - DW_LANG_ObjC_plus_plus = 0x0011, - DW_LANG_UPC = 0x0012, - DW_LANG_D = 0x0013, - // New in DWARF 5: - DW_LANG_Python = 0x0014, - DW_LANG_OpenCL = 0x0015, - DW_LANG_Go = 0x0016, - DW_LANG_Modula3 = 0x0017, - DW_LANG_Haskell = 0x0018, - DW_LANG_C_plus_plus_03 = 0x0019, - DW_LANG_C_plus_plus_11 = 0x001a, - DW_LANG_OCaml = 0x001b, - +#define HANDLE_DW_LANG(ID, NAME) DW_LANG_##NAME = ID, +#include "llvm/Support/Dwarf.def" DW_LANG_lo_user = 0x8000, - DW_LANG_Mips_Assembler = 0x8001, DW_LANG_hi_user = 0xffff }; @@ -859,6 +584,22 @@ const char *GDBIndexEntryKindString(GDBIndexEntryKind Kind); const char *GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage); /// @} +/// \defgroup DwarfConstantsParsing Dwarf constants parsing functions +/// +/// These functions map their strings back to the corresponding enumeration +/// value or return 0 if there is none, except for these exceptions: +/// +/// \li \a getTag() returns \a DW_TAG_invalid on invalid input. +/// \li \a getVirtuality() returns \a DW_VIRTUALITY_invalid on invalid input. +/// +/// @{ +unsigned getTag(StringRef TagString); +unsigned getOperationEncoding(StringRef OperationEncodingString); +unsigned getVirtuality(StringRef VirtualityString); +unsigned getLanguage(StringRef LanguageString); +unsigned getAttributeEncoding(StringRef EncodingString); +/// @} + /// \brief Returns the symbolic string representing Val when used as a value /// for attribute Attr. const char *AttributeValueString(uint16_t Attr, unsigned Val); diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index 3d49205fa168..8b915ff0581d 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -344,6 +344,7 @@ enum { ELFOSABI_NSK = 14, // Hewlett-Packard Non-Stop Kernel ELFOSABI_AROS = 15, // AROS ELFOSABI_FENIXOS = 16, // FenixOS + ELFOSABI_CLOUDABI = 17, // Nuxi CloudABI ELFOSABI_C6000_ELFABI = 64, // Bare-metal TMS320C6000 ELFOSABI_C6000_LINUX = 65, // Linux TMS320C6000 ELFOSABI_ARM = 97, // ARM @@ -431,22 +432,50 @@ enum : unsigned { EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions EF_MIPS_PIC = 0x00000002, // Position independent code EF_MIPS_CPIC = 0x00000004, // Call object with Position independent code - EF_MIPS_ABI2 = 0x00000020, - EF_MIPS_32BITMODE = 0x00000100, + EF_MIPS_ABI2 = 0x00000020, // File uses N32 ABI + EF_MIPS_32BITMODE = 0x00000100, // Code compiled for a 64-bit machine + // in 32-bit mode + EF_MIPS_FP64 = 0x00000200, // Code compiled for a 32-bit machine + // but uses 64-bit FP registers EF_MIPS_NAN2008 = 0x00000400, // Uses IEE 754-2008 NaN encoding // ABI flags - EF_MIPS_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI + EF_MIPS_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI EF_MIPS_ABI_O64 = 0x00002000, // O32 ABI extended for 64-bit architecture. EF_MIPS_ABI_EABI32 = 0x00003000, // EABI in 32 bit mode. EF_MIPS_ABI_EABI64 = 0x00004000, // EABI in 64 bit mode. EF_MIPS_ABI = 0x0000f000, // Mask for selecting EF_MIPS_ABI_ variant. - //ARCH_ASE + // MIPS machine variant + EF_MIPS_MACH_3900 = 0x00810000, // Toshiba R3900 + EF_MIPS_MACH_4010 = 0x00820000, // LSI R4010 + EF_MIPS_MACH_4100 = 0x00830000, // NEC VR4100 + EF_MIPS_MACH_4650 = 0x00850000, // MIPS R4650 + EF_MIPS_MACH_4120 = 0x00870000, // NEC VR4120 + EF_MIPS_MACH_4111 = 0x00880000, // NEC VR4111/VR4181 + EF_MIPS_MACH_SB1 = 0x008a0000, // Broadcom SB-1 + EF_MIPS_MACH_OCTEON = 0x008b0000, // Cavium Networks Octeon + EF_MIPS_MACH_XLR = 0x008c0000, // RMI Xlr + EF_MIPS_MACH_OCTEON2 = 0x008d0000, // Cavium Networks Octeon2 + EF_MIPS_MACH_OCTEON3 = 0x008e0000, // Cavium Networks Octeon3 + EF_MIPS_MACH_5400 = 0x00910000, // NEC VR5400 + EF_MIPS_MACH_5900 = 0x00920000, // MIPS R5900 + EF_MIPS_MACH_5500 = 0x00980000, // NEC VR5500 + EF_MIPS_MACH_9000 = 0x00990000, // Unknown + EF_MIPS_MACH_LS2E = 0x00a00000, // ST Microelectronics Loongson 2E + EF_MIPS_MACH_LS2F = 0x00a10000, // ST Microelectronics Loongson 2F + EF_MIPS_MACH_LS3A = 0x00a20000, // Loongson 3A + EF_MIPS_MACH = 0x00ff0000, // EF_MIPS_MACH_xxx selection mask + + // ARCH_ASE EF_MIPS_MICROMIPS = 0x02000000, // microMIPS EF_MIPS_ARCH_ASE_M16 = 0x04000000, // Has Mips-16 ISA extensions - //ARCH + EF_MIPS_ARCH_ASE_MDMX = + 0x08000000, // Has MDMX multimedia extensions + EF_MIPS_ARCH_ASE = 0x0f000000, // Mask for EF_MIPS_ARCH_ASE_xxx flags + + // ARCH EF_MIPS_ARCH_1 = 0x00000000, // MIPS1 instruction set EF_MIPS_ARCH_2 = 0x10000000, // MIPS2 instruction set EF_MIPS_ARCH_3 = 0x20000000, // MIPS3 instruction set @@ -454,8 +483,8 @@ enum : unsigned { EF_MIPS_ARCH_5 = 0x40000000, // MIPS5 instruction set EF_MIPS_ARCH_32 = 0x50000000, // MIPS32 instruction set per linux not elf.h EF_MIPS_ARCH_64 = 0x60000000, // MIPS64 instruction set per linux not elf.h - EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2 - EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2 + EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2, mips32r3, mips32r5 + EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2, mips64r3, mips64r5 EF_MIPS_ARCH_32R6 = 0x90000000, // mips32r6 EF_MIPS_ARCH_64R6 = 0xa0000000, // mips64r6 EF_MIPS_ARCH = 0xf0000000 // Mask for applying EF_MIPS_ARCH_ variant @@ -475,6 +504,22 @@ enum { STO_MIPS_MIPS16 = 0xf0 // MIPS Specific ISA for Mips16 }; +// .MIPS.options section descriptor kinds +enum { + ODK_NULL = 0, // Undefined + ODK_REGINFO = 1, // Register usage information + ODK_EXCEPTIONS = 2, // Exception processing options + ODK_PAD = 3, // Section padding options + ODK_HWPATCH = 4, // Hardware patches applied + ODK_FILL = 5, // Linker fill value + ODK_TAGS = 6, // Space for tool identification + ODK_HWAND = 7, // Hardware AND patches applied + ODK_HWOR = 8, // Hardware OR patches applied + ODK_GP_GROUP = 9, // GP group to use for text/data sections + ODK_IDENT = 10, // ID information + ODK_PAGESIZE = 11 // Page size information +}; + // Hexagon Specific e_flags // Release 5 ABI enum { @@ -761,6 +806,7 @@ enum { STB_LOCAL = 0, // Local symbol, not visible outside obj file containing def STB_GLOBAL = 1, // Global symbol, visible to all object files being combined STB_WEAK = 2, // Weak symbol, like global but lower-precedence + STB_GNU_UNIQUE = 10, STB_LOOS = 10, // Lowest operating system-specific binding type STB_HIOS = 12, // Highest operating system-specific binding type STB_LOPROC = 13, // Lowest processor-specific binding type @@ -795,6 +841,14 @@ enum { STN_UNDEF = 0 }; +// Special relocation symbols used in the MIPS64 ELF relocation entries +enum { + RSS_UNDEF = 0, // None + RSS_GP = 1, // Value of gp + RSS_GP0 = 2, // Value of gp used to create object being relocated + RSS_LOC = 3 // Address of location being relocated +}; + // Relocation entry, without explicit addend. struct Elf32_Rel { Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) @@ -1114,7 +1168,16 @@ enum { DF_1_CONFALT = 0x00002000, // Configuration alternative created. DF_1_ENDFILTEE = 0x00004000, // Filtee terminates filters search. DF_1_DISPRELDNE = 0x00008000, // Disp reloc applied at build time. - DF_1_DISPRELPND = 0x00010000 // Disp reloc applied at run-time. + DF_1_DISPRELPND = 0x00010000, // Disp reloc applied at run-time. + DF_1_NODIRECT = 0x00020000, // Object has no-direct binding. + DF_1_IGNMULDEF = 0x00040000, + DF_1_NOKSYMS = 0x00080000, + DF_1_NOHDR = 0x00100000, + DF_1_EDITED = 0x00200000, // Object is modified after built. + DF_1_NORELOC = 0x00400000, + DF_1_SYMINTPOSE = 0x00800000, // Object has individual interposers. + DF_1_GLOBAUDIT = 0x01000000, // Global auditing required. + DF_1_SINGLETON = 0x02000000 // Singleton symbols are used. }; // DT_MIPS_FLAGS values. diff --git a/include/llvm/Support/ELFRelocs/Mips.def b/include/llvm/Support/ELFRelocs/Mips.def index dc573464dcf2..77e7f8e8712b 100644 --- a/include/llvm/Support/ELFRelocs/Mips.def +++ b/include/llvm/Support/ELFRelocs/Mips.def @@ -108,5 +108,10 @@ ELF_RELOC(R_MICROMIPS_TLS_TPREL_HI16, 169) ELF_RELOC(R_MICROMIPS_TLS_TPREL_LO16, 170) ELF_RELOC(R_MICROMIPS_GPREL7_S2, 172) ELF_RELOC(R_MICROMIPS_PC23_S2, 173) +ELF_RELOC(R_MICROMIPS_PC21_S2, 174) +ELF_RELOC(R_MICROMIPS_PC26_S2, 175) +ELF_RELOC(R_MICROMIPS_PC18_S3, 176) +ELF_RELOC(R_MICROMIPS_PC19_S2, 177) ELF_RELOC(R_MIPS_NUM, 218) ELF_RELOC(R_MIPS_PC32, 248) +ELF_RELOC(R_MIPS_EH, 249) diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index 47b82fdc4975..e9fe22e5eda8 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -58,8 +58,9 @@ inline value_type read(const void *memory) { /// Read a value of a particular endianness from a buffer, and increment the /// buffer past that value. -template<typename value_type, endianness endian, std::size_t alignment> -inline value_type readNext(const unsigned char *&memory) { +template<typename value_type, endianness endian, std::size_t alignment, + typename CharT> +inline value_type readNext(const CharT *&memory) { value_type ret = read<value_type, endian, alignment>(memory); memory += sizeof(value_type); return ret; @@ -195,7 +196,23 @@ typedef detail::packed_endian_specific_integral <int32_t, native, unaligned> unaligned_int32_t; typedef detail::packed_endian_specific_integral <int64_t, native, unaligned> unaligned_int64_t; -} // end namespace llvm + +namespace endian { +inline uint16_t read16le(const void *p) { return *(const ulittle16_t *)p; } +inline uint32_t read32le(const void *p) { return *(const ulittle32_t *)p; } +inline uint64_t read64le(const void *p) { return *(const ulittle64_t *)p; } +inline uint16_t read16be(const void *p) { return *(const ubig16_t *)p; } +inline uint32_t read32be(const void *p) { return *(const ubig32_t *)p; } +inline uint64_t read64be(const void *p) { return *(const ubig64_t *)p; } + +inline void write16le(void *p, uint16_t v) { *(ulittle16_t *)p = v; } +inline void write32le(void *p, uint32_t v) { *(ulittle32_t *)p = v; } +inline void write64le(void *p, uint64_t v) { *(ulittle64_t *)p = v; } +inline void write16be(void *p, uint16_t v) { *(ubig16_t *)p = v; } +inline void write32be(void *p, uint32_t v) { *(ubig32_t *)p = v; } +inline void write64be(void *p, uint64_t v) { *(ubig64_t *)p = v; } +} // end namespace endian } // end namespace support +} // end namespace llvm #endif diff --git a/include/llvm/Support/EndianStream.h b/include/llvm/Support/EndianStream.h index 94f372f020b4..d44a9b3b7ce8 100644 --- a/include/llvm/Support/EndianStream.h +++ b/include/llvm/Support/EndianStream.h @@ -31,6 +31,31 @@ template <endianness endian> struct Writer { OS.write((const char *)&Val, sizeof(value_type)); } }; + +template <> +template <> +inline void Writer<little>::write<float>(float Val) { + write(FloatToBits(Val)); +} + +template <> +template <> +inline void Writer<little>::write<double>(double Val) { + write(DoubleToBits(Val)); +} + +template <> +template <> +inline void Writer<big>::write<float>(float Val) { + write(FloatToBits(Val)); +} + +template <> +template <> +inline void Writer<big>::write<double>(double Val) { + write(DoubleToBits(Val)); +} + } // end namespace endian } // end namespace support diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h index 84763deea0f9..589404f9b4ee 100644 --- a/include/llvm/Support/ErrorOr.h +++ b/include/llvm/Support/ErrorOr.h @@ -168,7 +168,7 @@ public: } /// \brief Return false if there is an error. - LLVM_EXPLICIT operator bool() const { + explicit operator bool() const { return !HasError; } @@ -281,8 +281,8 @@ template <class T, class E> typename std::enable_if<std::is_error_code_enum<E>::value || std::is_error_condition_enum<E>::value, bool>::type -operator==(ErrorOr<T> &Err, E Code) { - return std::error_code(Err) == Code; +operator==(const ErrorOr<T> &Err, E Code) { + return Err.getError() == Code; } } // end namespace llvm diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h index 9f02a16e3d65..fd8879c84622 100644 --- a/include/llvm/Support/FileOutputBuffer.h +++ b/include/llvm/Support/FileOutputBuffer.h @@ -74,8 +74,8 @@ public: ~FileOutputBuffer(); private: - FileOutputBuffer(const FileOutputBuffer &) LLVM_DELETED_FUNCTION; - FileOutputBuffer &operator=(const FileOutputBuffer &) LLVM_DELETED_FUNCTION; + FileOutputBuffer(const FileOutputBuffer &) = delete; + FileOutputBuffer &operator=(const FileOutputBuffer &) = delete; FileOutputBuffer(std::unique_ptr<llvm::sys::fs::mapped_file_region> R, StringRef Path, StringRef TempPath); diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index b60c1b07043b..a736c324f8aa 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -120,7 +120,7 @@ class UniqueID { uint64_t File; public: - UniqueID() {} + UniqueID() = default; UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {} bool operator==(const UniqueID &Other) const { return Device == Other.Device && File == Other.File; @@ -241,6 +241,7 @@ struct file_magic { macho_bundle, ///< Mach-O Bundle file macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub macho_dsym_companion, ///< Mach-O dSYM companion file + macho_kext_bundle, ///< Mach-O kext bundle file macho_universal_binary, ///< Mach-O universal binary coff_object, ///< COFF object file coff_import_library, ///< COFF import library @@ -624,9 +625,9 @@ std::error_code getUniqueID(const Twine Path, UniqueID &Result); /// This class represents a memory mapped file. It is based on /// boost::iostreams::mapped_file. class mapped_file_region { - mapped_file_region() LLVM_DELETED_FUNCTION; - mapped_file_region(mapped_file_region&) LLVM_DELETED_FUNCTION; - mapped_file_region &operator =(mapped_file_region&) LLVM_DELETED_FUNCTION; + mapped_file_region() = delete; + mapped_file_region(mapped_file_region&) = delete; + mapped_file_region &operator =(mapped_file_region&) = delete; public: enum mapmode { diff --git a/include/llvm/Support/FileUtilities.h b/include/llvm/Support/FileUtilities.h index 3f2f176eb469..2ee2c60b9964 100644 --- a/include/llvm/Support/FileUtilities.h +++ b/include/llvm/Support/FileUtilities.h @@ -51,7 +51,7 @@ namespace llvm { ~FileRemover() { if (DeleteIt) { // Ignore problems deleting the file. - sys::fs::remove(Filename.str()); + sys::fs::remove(Filename); } } @@ -61,7 +61,7 @@ namespace llvm { void setFile(const Twine& filename, bool deleteIt = true) { if (DeleteIt) { // Ignore problems deleting the file. - sys::fs::remove(Filename.str()); + sys::fs::remove(Filename); } Filename.clear(); diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h index 5d599e96ec3a..4319a3ba2745 100644 --- a/include/llvm/Support/Format.h +++ b/include/llvm/Support/Format.h @@ -23,18 +23,12 @@ #ifndef LLVM_SUPPORT_FORMAT_H #define LLVM_SUPPORT_FORMAT_H +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" #include <cassert> #include <cstdio> -#ifdef _MSC_VER -// FIXME: This define is wrong: -// - _snprintf does not guarantee that trailing null is always added - if -// there is no space for null, it does not report any error. -// - According to C++ standard, snprintf should be visible in the 'std' -// namespace - this define makes this impossible. -#define snprintf _snprintf -#endif +#include <tuple> namespace llvm { @@ -43,7 +37,8 @@ namespace llvm { class format_object_base { protected: const char *Fmt; - ~format_object_base() {} // Disallow polymorphic deletion. + ~format_object_base() = default; // Disallow polymorphic deletion. + format_object_base(const format_object_base &) = default; virtual void home(); // Out of line virtual method. /// Call snprintf() for this object, on the given buffer and size. @@ -80,101 +75,26 @@ public: /// printed, this synthesizes the string into a temporary buffer provided and /// returns whether or not it is big enough. -template <typename T> -class format_object1 final : public format_object_base { - T Val; -public: - format_object1(const char *fmt, const T &val) - : format_object_base(fmt), Val(val) { - } - - int snprint(char *Buffer, unsigned BufferSize) const override { - return snprintf(Buffer, BufferSize, Fmt, Val); - } -}; - -template <typename T1, typename T2> -class format_object2 final : public format_object_base { - T1 Val1; - T2 Val2; -public: - format_object2(const char *fmt, const T1 &val1, const T2 &val2) - : format_object_base(fmt), Val1(val1), Val2(val2) { - } - - int snprint(char *Buffer, unsigned BufferSize) const override { - return snprintf(Buffer, BufferSize, Fmt, Val1, Val2); - } -}; - -template <typename T1, typename T2, typename T3> -class format_object3 final : public format_object_base { - T1 Val1; - T2 Val2; - T3 Val3; -public: - format_object3(const char *fmt, const T1 &val1, const T2 &val2,const T3 &val3) - : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3) { - } - - int snprint(char *Buffer, unsigned BufferSize) const override { - return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3); - } -}; - -template <typename T1, typename T2, typename T3, typename T4> -class format_object4 final : public format_object_base { - T1 Val1; - T2 Val2; - T3 Val3; - T4 Val4; -public: - format_object4(const char *fmt, const T1 &val1, const T2 &val2, - const T3 &val3, const T4 &val4) - : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4) { - } +template <typename... Ts> +class format_object final : public format_object_base { + std::tuple<Ts...> Vals; - int snprint(char *Buffer, unsigned BufferSize) const override { - return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4); - } -}; - -template <typename T1, typename T2, typename T3, typename T4, typename T5> -class format_object5 final : public format_object_base { - T1 Val1; - T2 Val2; - T3 Val3; - T4 Val4; - T5 Val5; -public: - format_object5(const char *fmt, const T1 &val1, const T2 &val2, - const T3 &val3, const T4 &val4, const T5 &val5) - : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4), - Val5(val5) { - } - - int snprint(char *Buffer, unsigned BufferSize) const override { - return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5); + template <std::size_t... Is> + int snprint_tuple(char *Buffer, unsigned BufferSize, + index_sequence<Is...>) const { +#ifdef _MSC_VER + return _snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...); +#else + return snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...); +#endif } -}; -template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6> -class format_object6 final : public format_object_base { - T1 Val1; - T2 Val2; - T3 Val3; - T4 Val4; - T5 Val5; - T6 Val6; public: - format_object6(const char *Fmt, const T1 &Val1, const T2 &Val2, - const T3 &Val3, const T4 &Val4, const T5 &Val5, const T6 &Val6) - : format_object_base(Fmt), Val1(Val1), Val2(Val2), Val3(Val3), Val4(Val4), - Val5(Val5), Val6(Val6) { } + format_object(const char *fmt, const Ts &... vals) + : format_object_base(fmt), Vals(vals...) {} int snprint(char *Buffer, unsigned BufferSize) const override { - return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5, Val6); + return snprint_tuple(Buffer, BufferSize, index_sequence_for<Ts...>()); } }; @@ -187,44 +107,9 @@ public: /// OS << format("%0.4f", myfloat) << '\n'; /// \endcode -template <typename T> -inline format_object1<T> format(const char *Fmt, const T &Val) { - return format_object1<T>(Fmt, Val); -} - -template <typename T1, typename T2> -inline format_object2<T1, T2> format(const char *Fmt, const T1 &Val1, - const T2 &Val2) { - return format_object2<T1, T2>(Fmt, Val1, Val2); -} - -template <typename T1, typename T2, typename T3> - inline format_object3<T1, T2, T3> format(const char *Fmt, const T1 &Val1, - const T2 &Val2, const T3 &Val3) { - return format_object3<T1, T2, T3>(Fmt, Val1, Val2, Val3); -} - -template <typename T1, typename T2, typename T3, typename T4> -inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1, - const T2 &Val2, const T3 &Val3, - const T4 &Val4) { - return format_object4<T1, T2, T3, T4>(Fmt, Val1, Val2, Val3, Val4); -} - -template <typename T1, typename T2, typename T3, typename T4, typename T5> -inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1, - const T2 &Val2, const T3 &Val3, - const T4 &Val4, const T5 &Val5) { - return format_object5<T1, T2, T3, T4, T5>(Fmt, Val1, Val2, Val3, Val4, Val5); -} - -template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6> -inline format_object6<T1, T2, T3, T4, T5, T6> -format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3, - const T4 &Val4, const T5 &Val5, const T6 &Val6) { - return format_object6<T1, T2, T3, T4, T5, T6>(Fmt, Val1, Val2, Val3, Val4, - Val5, Val6); +template <typename... Ts> +inline format_object<Ts...> format(const char *Fmt, const Ts &... Vals) { + return format_object<Ts...>(Fmt, Vals...); } /// This is a helper class used for left_justify() and right_justify(). @@ -259,21 +144,38 @@ class FormattedNumber { unsigned Width; bool Hex; bool Upper; + bool HexPrefix; friend class raw_ostream; public: - FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U) - : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U) { } + FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U, + bool Prefix) + : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U), + HexPrefix(Prefix) {} }; /// format_hex - Output \p N as a fixed width hexadecimal. If number will not /// fit in width, full number is still printed. Examples: -/// OS << format_hex(255, 4) => 0xff -/// OS << format_hex(255, 4, true) => 0xFF -/// OS << format_hex(255, 6) => 0x00ff -/// OS << format_hex(255, 2) => 0xff -inline FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false) { +/// OS << format_hex(255, 4) => 0xff +/// OS << format_hex(255, 4, true) => 0xFF +/// OS << format_hex(255, 6) => 0x00ff +/// OS << format_hex(255, 2) => 0xff +inline FormattedNumber format_hex(uint64_t N, unsigned Width, + bool Upper = false) { + assert(Width <= 18 && "hex width must be <= 18"); + return FormattedNumber(N, 0, Width, true, Upper, true); +} + +/// format_hex_no_prefix - Output \p N as a fixed width hexadecimal. Does not +/// prepend '0x' to the outputted string. If number will not fit in width, +/// full number is still printed. Examples: +/// OS << format_hex_no_prefix(255, 4) => ff +/// OS << format_hex_no_prefix(255, 4, true) => FF +/// OS << format_hex_no_prefix(255, 6) => 00ff +/// OS << format_hex_no_prefix(255, 2) => ff +inline FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, + bool Upper = false) { assert(Width <= 18 && "hex width must be <= 18"); - return FormattedNumber(N, 0, Width, true, Upper); + return FormattedNumber(N, 0, Width, true, Upper, false); } /// format_decimal - Output \p N as a right justified, fixed-width decimal. If @@ -283,7 +185,7 @@ inline FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false) /// OS << format_decimal(-1, 3) => " -1" /// OS << format_decimal(12345, 3) => "12345" inline FormattedNumber format_decimal(int64_t N, unsigned Width) { - return FormattedNumber(0, N, Width, false, false); + return FormattedNumber(0, N, Width, false, false, false); } diff --git a/include/llvm/Support/FormattedStream.h b/include/llvm/Support/FormattedStream.h index 8137daaff1f8..4a135cd23174 100644 --- a/include/llvm/Support/FormattedStream.h +++ b/include/llvm/Support/FormattedStream.h @@ -25,27 +25,11 @@ namespace llvm { /// boundaries and querying the number of lines written to the stream. /// class formatted_raw_ostream : public raw_ostream { -public: - /// DELETE_STREAM - Tell the destructor to delete the held stream. - /// - static const bool DELETE_STREAM = true; - - /// PRESERVE_STREAM - Tell the destructor to not delete the held - /// stream. - /// - static const bool PRESERVE_STREAM = false; - -private: /// TheStream - The real stream we output to. We set it to be /// unbuffered, since we're already doing our own buffering. /// raw_ostream *TheStream; - /// DeleteStream - Do we need to delete TheStream in the - /// destructor? - /// - bool DeleteStream; - /// Position - The current output column and line of the data that's /// been flushed and the portion of the buffer that's been /// scanned. The line and column scheme is zero-based. @@ -73,6 +57,24 @@ private: /// void ComputePosition(const char *Ptr, size_t size); + void setStream(raw_ostream &Stream) { + releaseStream(); + + TheStream = &Stream; + + // This formatted_raw_ostream inherits from raw_ostream, so it'll do its + // own buffering, and it doesn't need or want TheStream to do another + // layer of buffering underneath. Resize the buffer to what TheStream + // had been using, and tell TheStream not to do its own buffering. + if (size_t BufferSize = TheStream->GetBufferSize()) + SetBufferSize(BufferSize); + else + SetUnbuffered(); + TheStream->SetUnbuffered(); + + Scanned = nullptr; + } + public: /// formatted_raw_ostream - Open the specified file for /// writing. If an error occurs, information about the error is @@ -84,39 +86,19 @@ public: /// so it doesn't want another layer of buffering to be happening /// underneath it. /// - formatted_raw_ostream(raw_ostream &Stream, bool Delete = false) - : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) { - setStream(Stream, Delete); + formatted_raw_ostream(raw_ostream &Stream) + : TheStream(nullptr), Position(0, 0) { + setStream(Stream); } - explicit formatted_raw_ostream() - : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) { + explicit formatted_raw_ostream() : TheStream(nullptr), Position(0, 0) { Scanned = nullptr; } - ~formatted_raw_ostream() { + ~formatted_raw_ostream() override { flush(); releaseStream(); } - void setStream(raw_ostream &Stream, bool Delete = false) { - releaseStream(); - - TheStream = &Stream; - DeleteStream = Delete; - - // This formatted_raw_ostream inherits from raw_ostream, so it'll do its - // own buffering, and it doesn't need or want TheStream to do another - // layer of buffering underneath. Resize the buffer to what TheStream - // had been using, and tell TheStream not to do its own buffering. - if (size_t BufferSize = TheStream->GetBufferSize()) - SetBufferSize(BufferSize); - else - SetUnbuffered(); - TheStream->SetUnbuffered(); - - Scanned = nullptr; - } - /// PadToColumn - Align the output to some column number. If the current /// column is already equal to or more than NewCol, PadToColumn inserts one /// space. @@ -151,13 +133,11 @@ public: private: void releaseStream() { - // Delete the stream if needed. Otherwise, transfer the buffer - // settings from this raw_ostream back to the underlying stream. + // Transfer the buffer settings from this raw_ostream back to the underlying + // stream. if (!TheStream) return; - if (DeleteStream) - delete TheStream; - else if (size_t BufferSize = GetBufferSize()) + if (size_t BufferSize = GetBufferSize()) TheStream->SetBufferSize(BufferSize); else TheStream->SetUnbuffered(); diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h index e378602c7bb3..c2e34bd3eaeb 100644 --- a/include/llvm/Support/GCOV.h +++ b/include/llvm/Support/GCOV.h @@ -19,6 +19,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/iterator.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" @@ -29,10 +30,7 @@ class GCOVBlock; class FileInfo; namespace GCOV { - enum GCOVVersion { - V402, - V404 - }; +enum GCOVVersion { V402, V404 }; } // end GCOV namespace /// GCOVOptions - A struct for passing gcov options between functions. @@ -56,7 +54,7 @@ struct GCOVOptions { class GCOVBuffer { public: GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {} - + /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer. bool readGCNOFormat() { StringRef File = Buffer->getBuffer().slice(0, 4); @@ -81,7 +79,7 @@ public: /// readGCOVVersion - Read GCOV version. bool readGCOVVersion(GCOV::GCOVVersion &Version) { - StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor+4); + StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor + 4); if (VersionStr == "*204") { Cursor += 4; Version = GCOV::V402; @@ -99,10 +97,9 @@ public: /// readFunctionTag - If cursor points to a function tag then increment the /// cursor and return true otherwise return false. bool readFunctionTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\0' || Tag[3] != '\1') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || + Tag[3] != '\1') { return false; } Cursor += 4; @@ -112,10 +109,9 @@ public: /// readBlockTag - If cursor points to a block tag then increment the /// cursor and return true otherwise return false. bool readBlockTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\x41' || Tag[3] != '\x01') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' || + Tag[3] != '\x01') { return false; } Cursor += 4; @@ -125,10 +121,9 @@ public: /// readEdgeTag - If cursor points to an edge tag then increment the /// cursor and return true otherwise return false. bool readEdgeTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\x43' || Tag[3] != '\x01') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' || + Tag[3] != '\x01') { return false; } Cursor += 4; @@ -138,10 +133,9 @@ public: /// readLineTag - If cursor points to a line tag then increment the /// cursor and return true otherwise return false. bool readLineTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\x45' || Tag[3] != '\x01') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' || + Tag[3] != '\x01') { return false; } Cursor += 4; @@ -151,10 +145,9 @@ public: /// readArcTag - If cursor points to an gcda arc tag then increment the /// cursor and return true otherwise return false. bool readArcTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\xa1' || Tag[3] != '\1') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' || + Tag[3] != '\1') { return false; } Cursor += 4; @@ -164,10 +157,9 @@ public: /// readObjectTag - If cursor points to an object summary tag then increment /// the cursor and return true otherwise return false. bool readObjectTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\0' || Tag[3] != '\xa1') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || + Tag[3] != '\xa1') { return false; } Cursor += 4; @@ -177,10 +169,9 @@ public: /// readProgramTag - If cursor points to a program summary tag then increment /// the cursor and return true otherwise return false. bool readProgramTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\0' || Tag[3] != '\xa3') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || + Tag[3] != '\xa3') { return false; } Cursor += 4; @@ -188,11 +179,11 @@ public: } bool readInt(uint32_t &Val) { - if (Buffer->getBuffer().size() < Cursor+4) { - errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n"; + if (Buffer->getBuffer().size() < Cursor + 4) { + errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n"; return false; } - StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4); + StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4); Cursor += 4; Val = *(const uint32_t *)(Str.data()); return true; @@ -200,7 +191,8 @@ public: bool readInt64(uint64_t &Val) { uint32_t Lo, Hi; - if (!readInt(Lo) || !readInt(Hi)) return false; + if (!readInt(Lo) || !readInt(Hi)) + return false; Val = ((uint64_t)Hi << 32) | Lo; return true; } @@ -210,19 +202,21 @@ public: // Keep reading until we find a non-zero length. This emulates gcov's // behaviour, which appears to do the same. while (Len == 0) - if (!readInt(Len)) return false; + if (!readInt(Len)) + return false; Len *= 4; - if (Buffer->getBuffer().size() < Cursor+Len) { - errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n"; + if (Buffer->getBuffer().size() < Cursor + Len) { + errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n"; return false; } - Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first; + Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first; Cursor += Len; return true; } uint64_t getCursor() const { return Cursor; } - void advanceCursor(uint32_t n) { Cursor += n*4; } + void advanceCursor(uint32_t n) { Cursor += n * 4; } + private: MemoryBuffer *Buffer; uint64_t Cursor; @@ -232,13 +226,15 @@ private: /// (.gcno and .gcda). class GCOVFile { public: - GCOVFile() : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0), - ProgramCount(0) {} + GCOVFile() + : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0), + ProgramCount(0) {} bool readGCNO(GCOVBuffer &Buffer); bool readGCDA(GCOVBuffer &Buffer); uint32_t getChecksum() const { return Checksum; } void dump() const; void collectLineCounts(FileInfo &FI); + private: bool GCNOInitialized; GCOV::GCOVVersion Version; @@ -260,8 +256,8 @@ struct GCOVEdge { /// GCOVFunction - Collects function information. class GCOVFunction { public: - typedef SmallVectorImpl<std::unique_ptr<GCOVBlock>>::const_iterator - BlockIterator; + typedef pointee_iterator<SmallVectorImpl< + std::unique_ptr<GCOVBlock>>::const_iterator> BlockIterator; GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {} bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version); @@ -274,9 +270,13 @@ public: BlockIterator block_begin() const { return Blocks.begin(); } BlockIterator block_end() const { return Blocks.end(); } + iterator_range<BlockIterator> blocks() const { + return make_range(block_begin(), block_end()); + } void dump() const; void collectLineCounts(FileInfo &FI); + private: GCOVFile &Parent; uint32_t Ident; @@ -291,7 +291,7 @@ private: /// GCOVBlock - Collects block information. class GCOVBlock { struct EdgeWeight { - EdgeWeight(GCOVBlock *D): Dst(D), Count(0) {} + EdgeWeight(GCOVBlock *D) : Dst(D), Count(0) {} GCOVBlock *Dst; uint64_t Count; @@ -302,11 +302,13 @@ class GCOVBlock { return E1->Dst.Number < E2->Dst.Number; } }; + public: typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator; - GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N), Counter(0), - DstEdgesAreSorted(true), SrcEdges(), DstEdges(), Lines() {} + GCOVBlock(GCOVFunction &P, uint32_t N) + : Parent(P), Number(N), Counter(0), DstEdgesAreSorted(true), SrcEdges(), + DstEdges(), Lines() {} ~GCOVBlock(); const GCOVFunction &getParent() const { return Parent; } void addLine(uint32_t N) { Lines.push_back(N); } @@ -331,11 +333,19 @@ public: EdgeIterator src_begin() const { return SrcEdges.begin(); } EdgeIterator src_end() const { return SrcEdges.end(); } + iterator_range<EdgeIterator> srcs() const { + return make_range(src_begin(), src_end()); + } + EdgeIterator dst_begin() const { return DstEdges.begin(); } EdgeIterator dst_end() const { return DstEdges.end(); } + iterator_range<EdgeIterator> dsts() const { + return make_range(dst_begin(), dst_end()); + } void dump() const; void collectLineCounts(FileInfo &FI); + private: GCOVFunction &Parent; uint32_t Number; @@ -347,8 +357,10 @@ private: }; class FileInfo { - // It is unlikely--but possible--for multiple functions to be on the same line. - // Therefore this typedef allows LineData.Functions to store multiple functions + // It is unlikely--but possible--for multiple functions to be on the same + // line. + // Therefore this typedef allows LineData.Functions to store multiple + // functions // per instance. This is rare, however, so optimize for the common case. typedef SmallVector<const GCOVFunction *, 1> FunctionVector; typedef DenseMap<uint32_t, FunctionVector> FunctionLines; @@ -363,9 +375,9 @@ class FileInfo { }; struct GCOVCoverage { - GCOVCoverage(StringRef Name) : - Name(Name), LogicalLines(0), LinesExec(0), Branches(0), BranchesExec(0), - BranchesTaken(0) {} + GCOVCoverage(StringRef Name) + : Name(Name), LogicalLines(0), LinesExec(0), Branches(0), + BranchesExec(0), BranchesTaken(0) {} StringRef Name; @@ -376,30 +388,31 @@ class FileInfo { uint32_t BranchesExec; uint32_t BranchesTaken; }; + public: - FileInfo(const GCOVOptions &Options) : - Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {} + FileInfo(const GCOVOptions &Options) + : Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {} void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) { if (Line > LineInfo[Filename].LastLine) LineInfo[Filename].LastLine = Line; - LineInfo[Filename].Blocks[Line-1].push_back(Block); + LineInfo[Filename].Blocks[Line - 1].push_back(Block); } void addFunctionLine(StringRef Filename, uint32_t Line, const GCOVFunction *Function) { if (Line > LineInfo[Filename].LastLine) LineInfo[Filename].LastLine = Line; - LineInfo[Filename].Functions[Line-1].push_back(Function); + LineInfo[Filename].Functions[Line - 1].push_back(Function); } void setRunCount(uint32_t Runs) { RunCount = Runs; } void setProgramCount(uint32_t Programs) { ProgramCount = Programs; } - void print(StringRef MainFilename, StringRef GCNOFile, StringRef GCDAFile); + void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile, + StringRef GCDAFile); private: std::string getCoveragePath(StringRef Filename, StringRef MainFilename); std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath); - void printFunctionSummary(raw_ostream &OS, - const FunctionVector &Funcs) const; + void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const; void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block, uint32_t LineIndex, uint32_t &BlockNo) const; void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block, @@ -407,23 +420,21 @@ private: void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo, uint64_t Count) const; - void printCoverage(const GCOVCoverage &Coverage) const; - void printFuncCoverage() const; - void printFileCoverage() const; + void printCoverage(raw_ostream &OS, const GCOVCoverage &Coverage) const; + void printFuncCoverage(raw_ostream &OS) const; + void printFileCoverage(raw_ostream &OS) const; const GCOVOptions &Options; StringMap<LineData> LineInfo; uint32_t RunCount; uint32_t ProgramCount; - typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> - FileCoverageList; + typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> FileCoverageList; typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap; FileCoverageList FileCoverages; FuncCoverageMap FuncCoverages; }; - } #endif diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h index fde56135a962..63678bb98bb1 100644 --- a/include/llvm/Support/GenericDomTree.h +++ b/include/llvm/Support/GenericDomTree.h @@ -21,6 +21,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" @@ -93,8 +94,9 @@ public: DomTreeNodeBase(NodeT *BB, DomTreeNodeBase<NodeT> *iDom) : TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) {} - DomTreeNodeBase<NodeT> *addChild(DomTreeNodeBase<NodeT> *C) { - Children.push_back(C); + std::unique_ptr<DomTreeNodeBase<NodeT>> + addChild(std::unique_ptr<DomTreeNodeBase<NodeT>> C) { + Children.push_back(C.get()); return C; } @@ -182,8 +184,8 @@ void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType> &DT, /// This class is a generic template over graph nodes. It is instantiated for /// various graphs in the LLVM IR or in the code generator. template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> { - DominatorTreeBase(const DominatorTreeBase &) LLVM_DELETED_FUNCTION; - DominatorTreeBase &operator=(const DominatorTreeBase &) LLVM_DELETED_FUNCTION; + DominatorTreeBase(const DominatorTreeBase &) = delete; + DominatorTreeBase &operator=(const DominatorTreeBase &) = delete; bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A, const DomTreeNodeBase<NodeT> *B) const { @@ -210,7 +212,8 @@ template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> { } protected: - typedef DenseMap<NodeT *, DomTreeNodeBase<NodeT> *> DomTreeNodeMapType; + typedef DenseMap<NodeT *, std::unique_ptr<DomTreeNodeBase<NodeT>>> + DomTreeNodeMapType; DomTreeNodeMapType DomTreeNodes; DomTreeNodeBase<NodeT> *RootNode; @@ -235,15 +238,13 @@ protected: DenseMap<NodeT *, InfoRec> Info; void reset() { - for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(), - E = DomTreeNodes.end(); - I != E; ++I) - delete I->second; DomTreeNodes.clear(); IDoms.clear(); this->Roots.clear(); Vertex.clear(); RootNode = nullptr; + DFSInfoValid = false; + SlowQueries = 0; } // NewBB is split and now it has one successor. Update dominator tree to @@ -314,7 +315,6 @@ protected: public: explicit DominatorTreeBase(bool isPostDom) : DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {} - ~DominatorTreeBase() { reset(); } DominatorTreeBase(DominatorTreeBase &&Arg) : DominatorBase<NodeT>( @@ -358,10 +358,10 @@ public: if (OI == OtherDomTreeNodes.end()) return true; - DomTreeNodeBase<NodeT> *MyNd = I->second; - DomTreeNodeBase<NodeT> *OtherNd = OI->second; + DomTreeNodeBase<NodeT> &MyNd = *I->second; + DomTreeNodeBase<NodeT> &OtherNd = *OI->second; - if (MyNd->compare(OtherNd)) + if (MyNd.compare(&OtherNd)) return true; } @@ -374,7 +374,10 @@ public: /// block. This is the same as using operator[] on this class. /// DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const { - return DomTreeNodes.lookup(BB); + auto I = DomTreeNodes.find(BB); + if (I != DomTreeNodes.end()) + return I->second.get(); + return nullptr; } DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const { return getNode(BB); } @@ -555,8 +558,8 @@ public: DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB); assert(IDomNode && "Not immediate dominator specified for block!"); DFSInfoValid = false; - return DomTreeNodes[BB] = - IDomNode->addChild(new DomTreeNodeBase<NodeT>(BB, IDomNode)); + return (DomTreeNodes[BB] = IDomNode->addChild( + llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get(); } /// changeImmediateDominator - This method is used to update the dominator @@ -593,15 +596,6 @@ public: } DomTreeNodes.erase(BB); - delete Node; - } - - /// removeNode - Removes a node from the dominator tree. Block must not - /// dominate any other blocks. Invalidates any node pointing to removed - /// block. - void removeNode(NodeT *BB) { - assert(getNode(BB) && "Removing node that isn't in dominator tree."); - DomTreeNodes.erase(BB); } /// splitBlock - BB is split and now it has one successor. Update dominator @@ -645,9 +639,38 @@ protected: friend void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType> &DT, FuncT &F); + + DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) { + if (DomTreeNodeBase<NodeT> *Node = getNode(BB)) + return Node; + + // Haven't calculated this node yet? Get or calculate the node for the + // immediate dominator. + NodeT *IDom = getIDom(BB); + + assert(IDom || this->DomTreeNodes[nullptr]); + DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom); + + // Add a new tree node for this NodeT, and link it as a child of + // IDomNode + return (this->DomTreeNodes[BB] = IDomNode->addChild( + llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get(); + } + + NodeT *getIDom(NodeT *BB) const { return IDoms.lookup(BB); } + + void addRoot(NodeT *BB) { this->Roots.push_back(BB); } + +public: /// updateDFSNumbers - Assign In and Out numbers to the nodes while walking /// dominator tree in dfs order. void updateDFSNumbers() const { + + if (DFSInfoValid) { + SlowQueries = 0; + return; + } + unsigned DFSNum = 0; SmallVector<std::pair<const DomTreeNodeBase<NodeT> *, @@ -690,28 +713,6 @@ protected: DFSInfoValid = true; } - DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) { - if (DomTreeNodeBase<NodeT> *Node = getNode(BB)) - return Node; - - // Haven't calculated this node yet? Get or calculate the node for the - // immediate dominator. - NodeT *IDom = getIDom(BB); - - assert(IDom || this->DomTreeNodes[nullptr]); - DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom); - - // Add a new tree node for this NodeT, and link it as a child of - // IDomNode - DomTreeNodeBase<NodeT> *C = new DomTreeNodeBase<NodeT>(BB, IDomNode); - return this->DomTreeNodes[BB] = IDomNode->addChild(C); - } - - NodeT *getIDom(NodeT *BB) const { return IDoms.lookup(BB); } - - void addRoot(NodeT *BB) { this->Roots.push_back(BB); } - -public: /// recalculate - compute a dominator tree for the given function template <class FT> void recalculate(FT &F) { typedef GraphTraits<FT *> TraitsTy; diff --git a/include/llvm/Support/GenericDomTreeConstruction.h b/include/llvm/Support/GenericDomTreeConstruction.h index ad4f8a9f429a..7c065f939256 100644 --- a/include/llvm/Support/GenericDomTreeConstruction.h +++ b/include/llvm/Support/GenericDomTreeConstruction.h @@ -251,15 +251,18 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, // an infinite loop. typename GraphT::NodeType* Root = !MultipleRoots ? DT.Roots[0] : nullptr; - DT.DomTreeNodes[Root] = DT.RootNode = - new DomTreeNodeBase<typename GraphT::NodeType>(Root, nullptr); + DT.RootNode = + (DT.DomTreeNodes[Root] = + llvm::make_unique<DomTreeNodeBase<typename GraphT::NodeType>>( + Root, nullptr)).get(); // Loop over all of the reachable blocks in the function... for (unsigned i = 2; i <= N; ++i) { typename GraphT::NodeType* W = DT.Vertex[i]; - DomTreeNodeBase<typename GraphT::NodeType> *BBNode = DT.DomTreeNodes[W]; - if (BBNode) continue; // Haven't calculated this node yet? + // Don't replace this with 'count', the insertion side effect is important + if (DT.DomTreeNodes[W]) + continue; // Haven't calculated this node yet? typename GraphT::NodeType* ImmDom = DT.getIDom(W); @@ -271,15 +274,16 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, // Add a new tree node for this BasicBlock, and link it as a child of // IDomNode - DomTreeNodeBase<typename GraphT::NodeType> *C = - new DomTreeNodeBase<typename GraphT::NodeType>(W, IDomNode); - DT.DomTreeNodes[W] = IDomNode->addChild(C); + DT.DomTreeNodes[W] = IDomNode->addChild( + llvm::make_unique<DomTreeNodeBase<typename GraphT::NodeType>>( + W, IDomNode)); } // Free temporary memory used to construct idom's DT.IDoms.clear(); DT.Info.clear(); - std::vector<typename GraphT::NodeType*>().swap(DT.Vertex); + DT.Vertex.clear(); + DT.Vertex.shrink_to_fit(); DT.updateDFSNumbers(); } diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index 2f02aa7a1c19..7d1c273c988d 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -24,10 +24,9 @@ #define LLVM_SUPPORT_GRAPHWRITER_H #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/DOTGraphTraits.h" -#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" -#include <cassert> #include <vector> namespace llvm { diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h index 61c65dabae3c..8e88d4279bd8 100644 --- a/include/llvm/Support/LockFileManager.h +++ b/include/llvm/Support/LockFileManager.h @@ -57,8 +57,8 @@ private: Optional<std::pair<std::string, int> > Owner; Optional<std::error_code> Error; - LockFileManager(const LockFileManager &) LLVM_DELETED_FUNCTION; - LockFileManager &operator=(const LockFileManager &) LLVM_DELETED_FUNCTION; + LockFileManager(const LockFileManager &) = delete; + LockFileManager &operator=(const LockFileManager &) = delete; static Optional<std::pair<std::string, int> > readLockFile(StringRef LockFileName); @@ -77,6 +77,10 @@ public: /// \brief For a shared lock, wait until the owner releases the lock. WaitForUnlockResult waitForUnlock(); + + /// \brief Remove the lock file. This may delete a different lock file than + /// the one previously read if there is a race. + std::error_code unsafeRemoveLockFile(); }; } // end namespace llvm diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index 698363614ac5..e3166165a483 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -24,6 +24,10 @@ #include <intrin.h> #endif +#ifdef __ANDROID_NDK__ +#include <android/api-level.h> +#endif + namespace llvm { /// \brief The behavior an operation has on an input of 0. enum ZeroBehavior { @@ -35,78 +39,66 @@ enum ZeroBehavior { ZB_Width }; -/// \brief Count number of 0's from the least significant bit to the most -/// stopping at the first 1. -/// -/// Only unsigned integral types are allowed. -/// -/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are -/// valid arguments. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, std::size_t>::type -countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { - (void)ZB; - - if (!Val) - return std::numeric_limits<T>::digits; - if (Val & 0x1) - return 0; - - // Bisection method. - std::size_t ZeroBits = 0; - T Shift = std::numeric_limits<T>::digits >> 1; - T Mask = std::numeric_limits<T>::max() >> Shift; - while (Shift) { - if ((Val & Mask) == 0) { - Val >>= Shift; - ZeroBits |= Shift; +namespace detail { +template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter { + static std::size_t count(T Val, ZeroBehavior) { + if (!Val) + return std::numeric_limits<T>::digits; + if (Val & 0x1) + return 0; + + // Bisection method. + std::size_t ZeroBits = 0; + T Shift = std::numeric_limits<T>::digits >> 1; + T Mask = std::numeric_limits<T>::max() >> Shift; + while (Shift) { + if ((Val & Mask) == 0) { + Val >>= Shift; + ZeroBits |= Shift; + } + Shift >>= 1; + Mask >>= Shift; } - Shift >>= 1; - Mask >>= Shift; + return ZeroBits; } - return ZeroBits; -} - -// Disable signed. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, std::size_t>::type -countTrailingZeros(T, ZeroBehavior = ZB_Width) LLVM_DELETED_FUNCTION; +}; #if __GNUC__ >= 4 || _MSC_VER -template <> -inline std::size_t countTrailingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) { - if (ZB != ZB_Undefined && Val == 0) - return 32; +template <typename T> struct TrailingZerosCounter<T, 4> { + static std::size_t count(T Val, ZeroBehavior ZB) { + if (ZB != ZB_Undefined && Val == 0) + return 32; #if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0) - return __builtin_ctz(Val); + return __builtin_ctz(Val); #elif _MSC_VER - unsigned long Index; - _BitScanForward(&Index, Val); - return Index; + unsigned long Index; + _BitScanForward(&Index, Val); + return Index; #endif -} + } +}; #if !defined(_MSC_VER) || defined(_M_X64) -template <> -inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { - if (ZB != ZB_Undefined && Val == 0) - return 64; +template <typename T> struct TrailingZerosCounter<T, 8> { + static std::size_t count(T Val, ZeroBehavior ZB) { + if (ZB != ZB_Undefined && Val == 0) + return 64; #if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0) - return __builtin_ctzll(Val); + return __builtin_ctzll(Val); #elif _MSC_VER - unsigned long Index; - _BitScanForward64(&Index, Val); - return Index; + unsigned long Index; + _BitScanForward64(&Index, Val); + return Index; #endif -} + } +}; #endif #endif +} // namespace detail -/// \brief Count number of 0's from the most significant bit to the least +/// \brief Count number of 0's from the least significant bit to the most /// stopping at the first 1. /// /// Only unsigned integral types are allowed. @@ -114,63 +106,81 @@ inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are /// valid arguments. template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, std::size_t>::type -countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { - (void)ZB; - - if (!Val) - return std::numeric_limits<T>::digits; - - // Bisection method. - std::size_t ZeroBits = 0; - for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) { - T Tmp = Val >> Shift; - if (Tmp) - Val = Tmp; - else - ZeroBits |= Shift; +std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return detail::TrailingZerosCounter<T, sizeof(T)>::count(Val, ZB); +} + +namespace detail { +template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter { + static std::size_t count(T Val, ZeroBehavior) { + if (!Val) + return std::numeric_limits<T>::digits; + + // Bisection method. + std::size_t ZeroBits = 0; + for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) { + T Tmp = Val >> Shift; + if (Tmp) + Val = Tmp; + else + ZeroBits |= Shift; + } + return ZeroBits; } - return ZeroBits; -} - -// Disable signed. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, std::size_t>::type -countLeadingZeros(T, ZeroBehavior = ZB_Width) LLVM_DELETED_FUNCTION; +}; #if __GNUC__ >= 4 || _MSC_VER -template <> -inline std::size_t countLeadingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) { - if (ZB != ZB_Undefined && Val == 0) - return 32; +template <typename T> struct LeadingZerosCounter<T, 4> { + static std::size_t count(T Val, ZeroBehavior ZB) { + if (ZB != ZB_Undefined && Val == 0) + return 32; #if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0) - return __builtin_clz(Val); + return __builtin_clz(Val); #elif _MSC_VER - unsigned long Index; - _BitScanReverse(&Index, Val); - return Index ^ 31; + unsigned long Index; + _BitScanReverse(&Index, Val); + return Index ^ 31; #endif -} + } +}; #if !defined(_MSC_VER) || defined(_M_X64) -template <> -inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { - if (ZB != ZB_Undefined && Val == 0) - return 64; +template <typename T> struct LeadingZerosCounter<T, 8> { + static std::size_t count(T Val, ZeroBehavior ZB) { + if (ZB != ZB_Undefined && Val == 0) + return 64; #if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0) - return __builtin_clzll(Val); + return __builtin_clzll(Val); #elif _MSC_VER - unsigned long Index; - _BitScanReverse64(&Index, Val); - return Index ^ 63; + unsigned long Index; + _BitScanReverse64(&Index, Val); + return Index ^ 63; #endif -} + } +}; #endif #endif +} // namespace detail + +/// \brief Count number of 0's from the most significant bit to the least +/// stopping at the first 1. +/// +/// Only unsigned integral types are allowed. +/// +/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are +/// valid arguments. +template <typename T> +std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB); +} /// \brief Get the index of the first set bit starting from the least /// significant bit. @@ -179,22 +189,13 @@ inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { /// /// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are /// valid arguments. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, T>::type -findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { +template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { if (ZB == ZB_Max && Val == 0) return std::numeric_limits<T>::max(); return countTrailingZeros(Val, ZB_Undefined); } -// Disable signed. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, T>::type -findFirstSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION; - /// \brief Get the index of the last set bit starting from the least /// significant bit. /// @@ -202,10 +203,7 @@ findFirstSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION; /// /// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are /// valid arguments. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, T>::type -findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { +template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { if (ZB == ZB_Max && Val == 0) return std::numeric_limits<T>::max(); @@ -215,12 +213,6 @@ findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { (std::numeric_limits<T>::digits - 1); } -// Disable signed. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, T>::type -findLastSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION; - /// \brief Macro compressed bit reversal table for 256 bits. /// /// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable @@ -330,31 +322,31 @@ 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. +/// isMask_32 - This function returns true if the argument is a non-empty +/// sequence of ones starting at the least significant bit with the remainder +/// zero (32 bit version). Ex. isMask_32(0x0000FFFFU) == true. inline bool isMask_32(uint32_t Value) { return Value && ((Value + 1) & Value) == 0; } -/// isMask_64 - This function returns true if the argument is a sequence of ones -/// starting at the least significant bit with the remainder zero (64 bit -/// version). +/// isMask_64 - This function returns true if the argument is a non-empty +/// sequence of ones starting at the least significant bit with the remainder +/// zero (64 bit version). inline bool isMask_64(uint64_t Value) { return Value && ((Value + 1) & Value) == 0; } /// isShiftedMask_32 - This function returns true if the argument contains a -/// sequence of ones with the remainder zero (32 bit version.) +/// non-empty sequence of ones with the remainder zero (32 bit version.) /// Ex. isShiftedMask_32(0x0000FF00U) == true. inline bool isShiftedMask_32(uint32_t Value) { - return isMask_32((Value - 1) | Value); + return Value && isMask_32((Value - 1) | Value); } /// isShiftedMask_64 - This function returns true if the argument contains a -/// sequence of ones with the remainder zero (64 bit version.) +/// non-empty sequence of ones with the remainder zero (64 bit version.) inline bool isShiftedMask_64(uint64_t Value) { - return isMask_64((Value - 1) | Value); + return Value && isMask_64((Value - 1) | Value); } /// isPowerOf2_32 - This function returns true if the argument is a power of @@ -387,61 +379,86 @@ inline uint64_t ByteSwap_64(uint64_t Value) { return sys::SwapByteOrder_64(Value); } -/// CountLeadingOnes_32 - this function performs the operation of -/// counting the number of ones from the most significant bit to the first zero -/// bit. Ex. CountLeadingOnes_32(0xFF0FFF00) == 8. -/// Returns 32 if the word is all ones. -inline unsigned CountLeadingOnes_32(uint32_t Value) { - return countLeadingZeros(~Value); -} - -/// CountLeadingOnes_64 - This function performs the operation -/// of counting the number of ones from the most significant bit to the first -/// zero bit (64 bit edition.) -/// Returns 64 if the word is all ones. -inline unsigned CountLeadingOnes_64(uint64_t Value) { - return countLeadingZeros(~Value); -} - -/// CountTrailingOnes_32 - this function performs the operation of -/// counting the number of ones from the least significant bit to the first zero -/// bit. Ex. CountTrailingOnes_32(0x00FF00FF) == 8. -/// Returns 32 if the word is all ones. -inline unsigned CountTrailingOnes_32(uint32_t Value) { - return countTrailingZeros(~Value); +/// \brief Count the number of ones from the most significant bit to the first +/// zero bit. +/// +/// Ex. CountLeadingOnes(0xFF0FFF00) == 8. +/// Only unsigned integral types are allowed. +/// +/// \param ZB the behavior on an input of all ones. Only ZB_Width and +/// ZB_Undefined are valid arguments. +template <typename T> +std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return countLeadingZeros(~Value, ZB); } -/// CountTrailingOnes_64 - This function performs the operation -/// of counting the number of ones from the least significant bit to the first -/// zero bit (64 bit edition.) -/// Returns 64 if the word is all ones. -inline unsigned CountTrailingOnes_64(uint64_t Value) { - return countTrailingZeros(~Value); -} +/// \brief Count the number of ones from the least significant bit to the first +/// zero bit. +/// +/// Ex. countTrailingOnes(0x00FF00FF) == 8. +/// Only unsigned integral types are allowed. +/// +/// \param ZB the behavior on an input of all ones. Only ZB_Width and +/// ZB_Undefined are valid arguments. +template <typename T> +std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return countTrailingZeros(~Value, ZB); +} + +namespace detail { +template <typename T, std::size_t SizeOfT> struct PopulationCounter { + static unsigned count(T Value) { + // Generic version, forward to 32 bits. + static_assert(SizeOfT <= 4, "Not implemented!"); +#if __GNUC__ >= 4 + return __builtin_popcount(Value); +#else + uint32_t v = Value; + v = v - ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; +#endif + } +}; -/// CountPopulation_32 - this function counts the number of set bits in a value. -/// Ex. CountPopulation(0xF000F000) = 8 -/// Returns 0 if the word is zero. -inline unsigned CountPopulation_32(uint32_t Value) { +template <typename T> struct PopulationCounter<T, 8> { + static unsigned count(T Value) { #if __GNUC__ >= 4 - return __builtin_popcount(Value); + return __builtin_popcountll(Value); #else - uint32_t v = Value - ((Value >> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >> 2) & 0x33333333); - return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; + uint64_t v = Value; + v = v - ((v >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); + v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); #endif + } +}; +} // namespace detail + +/// \brief Count the number of set bits in a value. +/// Ex. countPopulation(0xF000F000) = 8 +/// Returns 0 if the word is zero. +template <typename T> +inline unsigned countPopulation(T Value) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return detail::PopulationCounter<T, sizeof(T)>::count(Value); } -/// CountPopulation_64 - this function counts the number of set bits in a value, -/// (64 bit edition.) -inline unsigned CountPopulation_64(uint64_t Value) { -#if __GNUC__ >= 4 - return __builtin_popcountll(Value); +/// Log2 - This function returns the log base 2 of the specified value +inline double Log2(double Value) { +#if defined(__ANDROID_API__) && __ANDROID_API__ < 18 + return __builtin_log(Value) / __builtin_log(2.0); #else - uint64_t v = Value - ((Value >> 1) & 0x5555555555555555ULL); - v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); - v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; - return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); + return log2(Value); #endif } @@ -530,14 +547,6 @@ inline uint32_t FloatToBits(float Float) { return T.I; } -/// Platform-independent wrappers for the C99 isnan() function. -int IsNAN(float f); -int IsNAN(double d); - -/// Platform-independent wrappers for the C99 isinf() function. -int IsInf(float f); -int IsInf(double d); - /// MinAlign - A and B are either alignments or offsets. Return the minimum /// alignment that may be assumed after adding the two together. inline uint64_t MinAlign(uint64_t A, uint64_t B) { @@ -608,13 +617,6 @@ inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { return RoundUpToAlignment(Value, Align) - Value; } -/// abs64 - absolute value of a 64-bit int. Not all environments support -/// "abs" on whatever their name for the 64-bit int type is. The absolute -/// value of the largest negative number is undefined, as with "abs". -inline int64_t abs64(int64_t x) { - return (x < 0) ? -x : x; -} - /// SignExtend32 - Sign extend B-bit number x to 32-bit int. /// Usage int32_t r = SignExtend32<5>(x); template <unsigned B> inline int32_t SignExtend32(uint32_t x) { diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index e2f8d7e90fef..35a7bdb004a9 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -17,11 +17,9 @@ #include "llvm-c/Support.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/CBindingWrapping.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorOr.h" #include <memory> -#include <system_error> namespace llvm { class MemoryBufferRef; @@ -40,8 +38,8 @@ class MemoryBuffer { const char *BufferStart; // Start of the buffer. const char *BufferEnd; // End of the buffer. - MemoryBuffer(const MemoryBuffer &) LLVM_DELETED_FUNCTION; - MemoryBuffer &operator=(const MemoryBuffer &) LLVM_DELETED_FUNCTION; + MemoryBuffer(const MemoryBuffer &) = delete; + MemoryBuffer &operator=(const MemoryBuffer &) = delete; protected: MemoryBuffer() {} void init(const char *BufStart, const char *BufEnd, diff --git a/include/llvm/Support/MipsABIFlags.h b/include/llvm/Support/MipsABIFlags.h new file mode 100644 index 000000000000..93f6b416ba88 --- /dev/null +++ b/include/llvm/Support/MipsABIFlags.h @@ -0,0 +1,102 @@ +//===--- MipsABIFlags.h - MIPS ABI flags ----------------------------------===// +// +// 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 constants for the ABI flags structure contained +// in the .MIPS.abiflags section. +// +// https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MIPSABIFLAGS_H +#define LLVM_SUPPORT_MIPSABIFLAGS_H + +namespace llvm { +namespace Mips { + +// Values for the xxx_size bytes of an ABI flags structure. +enum AFL_REG { + AFL_REG_NONE = 0x00, // No registers + AFL_REG_32 = 0x01, // 32-bit registers + AFL_REG_64 = 0x02, // 64-bit registers + AFL_REG_128 = 0x03 // 128-bit registers +}; + +// Masks for the ases word of an ABI flags structure. +enum AFL_ASE { + AFL_ASE_DSP = 0x00000001, // DSP ASE + AFL_ASE_DSPR2 = 0x00000002, // DSP R2 ASE + AFL_ASE_EVA = 0x00000004, // Enhanced VA Scheme + AFL_ASE_MCU = 0x00000008, // MCU (MicroController) ASE + AFL_ASE_MDMX = 0x00000010, // MDMX ASE + AFL_ASE_MIPS3D = 0x00000020, // MIPS-3D ASE + AFL_ASE_MT = 0x00000040, // MT ASE + AFL_ASE_SMARTMIPS = 0x00000080, // SmartMIPS ASE + AFL_ASE_VIRT = 0x00000100, // VZ ASE + AFL_ASE_MSA = 0x00000200, // MSA ASE + AFL_ASE_MIPS16 = 0x00000400, // MIPS16 ASE + AFL_ASE_MICROMIPS = 0x00000800, // MICROMIPS ASE + AFL_ASE_XPA = 0x00001000 // XPA ASE +}; + +// Values for the isa_ext word of an ABI flags structure. +enum AFL_EXT { + AFL_EXT_NONE = 0, // None + AFL_EXT_XLR = 1, // RMI Xlr instruction + AFL_EXT_OCTEON2 = 2, // Cavium Networks Octeon2 + AFL_EXT_OCTEONP = 3, // Cavium Networks OcteonP + AFL_EXT_LOONGSON_3A = 4, // Loongson 3A + AFL_EXT_OCTEON = 5, // Cavium Networks Octeon + AFL_EXT_5900 = 6, // MIPS R5900 instruction + AFL_EXT_4650 = 7, // MIPS R4650 instruction + AFL_EXT_4010 = 8, // LSI R4010 instruction + AFL_EXT_4100 = 9, // NEC VR4100 instruction + AFL_EXT_3900 = 10, // Toshiba R3900 instruction + AFL_EXT_10000 = 11, // MIPS R10000 instruction + AFL_EXT_SB1 = 12, // Broadcom SB-1 instruction + AFL_EXT_4111 = 13, // NEC VR4111/VR4181 instruction + AFL_EXT_4120 = 14, // NEC VR4120 instruction + AFL_EXT_5400 = 15, // NEC VR5400 instruction + AFL_EXT_5500 = 16, // NEC VR5500 instruction + AFL_EXT_LOONGSON_2E = 17, // ST Microelectronics Loongson 2E + AFL_EXT_LOONGSON_2F = 18, // ST Microelectronics Loongson 2F + AFL_EXT_OCTEON3 = 19 // Cavium Networks Octeon3 +}; + +// Values for the flags1 word of an ABI flags structure. +enum AFL_FLAGS1 { AFL_FLAGS1_ODDSPREG = 1 }; + +// MIPS object attribute tags +enum { + Tag_GNU_MIPS_ABI_FP = 4, // Floating-point ABI used by this object file + Tag_GNU_MIPS_ABI_MSA = 8, // MSA ABI used by this object file +}; + +// Values for the fp_abi word of an ABI flags structure +// and for the Tag_GNU_MIPS_ABI_FP attribute tag. +enum Val_GNU_MIPS_ABI_FP { + Val_GNU_MIPS_ABI_FP_ANY = 0, // not tagged + Val_GNU_MIPS_ABI_FP_DOUBLE = 1, // hard float / -mdouble-float + Val_GNU_MIPS_ABI_FP_SINGLE = 2, // hard float / -msingle-float + Val_GNU_MIPS_ABI_FP_SOFT = 3, // soft float + Val_GNU_MIPS_ABI_FP_OLD_64 = 4, // -mips32r2 -mfp64 + Val_GNU_MIPS_ABI_FP_XX = 5, // -mfpxx + Val_GNU_MIPS_ABI_FP_64 = 6, // -mips32r2 -mfp64 + Val_GNU_MIPS_ABI_FP_64A = 7 // -mips32r2 -mfp64 -mno-odd-spreg +}; + +// Values for the Tag_GNU_MIPS_ABI_MSA attribute tag. +enum Val_GNU_MIPS_ABI_MSA { + Val_GNU_MIPS_ABI_MSA_ANY = 0, // not tagged + Val_GNU_MIPS_ABI_MSA_128 = 1 // 128-bit MSA +}; +} +} + +#endif diff --git a/include/llvm/Support/Mutex.h b/include/llvm/Support/Mutex.h index 97dd50115322..0f4e61af4439 100644 --- a/include/llvm/Support/Mutex.h +++ b/include/llvm/Support/Mutex.h @@ -70,14 +70,16 @@ namespace llvm /// @name Platform Dependent Data /// @{ private: +#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0 void* data_; ///< We don't know what the data will be +#endif /// @} /// @name Do Not Implement /// @{ private: - MutexImpl(const MutexImpl &) LLVM_DELETED_FUNCTION; - void operator=(const MutexImpl &) LLVM_DELETED_FUNCTION; + MutexImpl(const MutexImpl &) = delete; + void operator=(const MutexImpl &) = delete; /// @} }; diff --git a/include/llvm/Support/MutexGuard.h b/include/llvm/Support/MutexGuard.h index b9f941dab323..07b64b611960 100644 --- a/include/llvm/Support/MutexGuard.h +++ b/include/llvm/Support/MutexGuard.h @@ -26,8 +26,8 @@ namespace llvm { /// @brief Guard a section of code with a Mutex. class MutexGuard { sys::Mutex &M; - MutexGuard(const MutexGuard &) LLVM_DELETED_FUNCTION; - void operator=(const MutexGuard &) LLVM_DELETED_FUNCTION; + MutexGuard(const MutexGuard &) = delete; + void operator=(const MutexGuard &) = delete; public: MutexGuard(sys::Mutex &m) : M(m) { M.lock(); } ~MutexGuard() { M.unlock(); } diff --git a/include/llvm/Support/OnDiskHashTable.h b/include/llvm/Support/OnDiskHashTable.h index 52f133ccff68..0f097f287286 100644 --- a/include/llvm/Support/OnDiskHashTable.h +++ b/include/llvm/Support/OnDiskHashTable.h @@ -75,13 +75,10 @@ template <typename Info> class OnDiskChainedHashTableGenerator { llvm::SpecificBumpPtrAllocator<Item> BA; /// \brief A linked list of values in a particular hash bucket. - class Bucket { - public: + struct Bucket { offset_type Off; - Item *Head; unsigned Length; - - Bucket() {} + Item *Head; }; Bucket *Buckets; diff --git a/include/llvm/Support/Options.h b/include/llvm/Support/Options.h index 4fd1bff358fd..2742d3907c62 100644 --- a/include/llvm/Support/Options.h +++ b/include/llvm/Support/Options.h @@ -61,7 +61,7 @@ char OptionKey<ValT, Base, Mem>::ID = 0; /// The OptionRegistry is responsible for managing lifetimes of the options and /// provides interfaces for option registration and reading values from options. /// This object is a singleton, only one instance should ever exist so that all -/// options are registered in teh same place. +/// options are registered in the same place. class OptionRegistry { private: DenseMap<void *, cl::Option *> Options; diff --git a/include/llvm/Support/PrettyStackTrace.h b/include/llvm/Support/PrettyStackTrace.h index 914141ad3c4b..96afb60d8e51 100644 --- a/include/llvm/Support/PrettyStackTrace.h +++ b/include/llvm/Support/PrettyStackTrace.h @@ -30,8 +30,8 @@ namespace llvm { /// virtual stack trace. This gets dumped out if the program crashes. class PrettyStackTraceEntry { const PrettyStackTraceEntry *NextEntry; - PrettyStackTraceEntry(const PrettyStackTraceEntry &) LLVM_DELETED_FUNCTION; - void operator=(const PrettyStackTraceEntry&) LLVM_DELETED_FUNCTION; + PrettyStackTraceEntry(const PrettyStackTraceEntry &) = delete; + void operator=(const PrettyStackTraceEntry&) = delete; public: PrettyStackTraceEntry(); virtual ~PrettyStackTraceEntry(); diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index 40dc60fa30d6..b89a0f73ec68 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -16,10 +16,11 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/ErrorOr.h" -#include "llvm/Support/Path.h" #include <system_error> namespace llvm { +class StringRef; + namespace sys { /// This is the OS-specific separator for PATH like environment variables: diff --git a/include/llvm/Support/RWMutex.h b/include/llvm/Support/RWMutex.h index b80b8557576b..4be931337765 100644 --- a/include/llvm/Support/RWMutex.h +++ b/include/llvm/Support/RWMutex.h @@ -70,14 +70,16 @@ namespace llvm /// @name Platform Dependent Data /// @{ private: +#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0 void* data_; ///< We don't know what the data will be +#endif /// @} /// @name Do Not Implement /// @{ private: - RWMutexImpl(const RWMutexImpl & original) LLVM_DELETED_FUNCTION; - void operator=(const RWMutexImpl &) LLVM_DELETED_FUNCTION; + RWMutexImpl(const RWMutexImpl & original) = delete; + void operator=(const RWMutexImpl &) = delete; /// @} }; diff --git a/include/llvm/Support/RandomNumberGenerator.h b/include/llvm/Support/RandomNumberGenerator.h index 7ada34f075e4..7446558f0c88 100644 --- a/include/llvm/Support/RandomNumberGenerator.h +++ b/include/llvm/Support/RandomNumberGenerator.h @@ -48,10 +48,8 @@ private: std::mt19937_64 Generator; // Noncopyable. - RandomNumberGenerator(const RandomNumberGenerator &other) - LLVM_DELETED_FUNCTION; - RandomNumberGenerator & - operator=(const RandomNumberGenerator &other) LLVM_DELETED_FUNCTION; + RandomNumberGenerator(const RandomNumberGenerator &other) = delete; + RandomNumberGenerator &operator=(const RandomNumberGenerator &other) = delete; friend class Module; }; diff --git a/include/llvm/Support/Regex.h b/include/llvm/Support/Regex.h index bf533ca1aa60..31b35ed0cad6 100644 --- a/include/llvm/Support/Regex.h +++ b/include/llvm/Support/Regex.h @@ -17,7 +17,6 @@ #ifndef LLVM_SUPPORT_REGEX_H #define LLVM_SUPPORT_REGEX_H -#include "llvm/Support/Compiler.h" #include <string> struct llvm_regex; @@ -46,7 +45,7 @@ namespace llvm { /// Compiles the given regular expression \p Regex. Regex(StringRef Regex, unsigned Flags = NoFlags); - Regex(const Regex &) LLVM_DELETED_FUNCTION; + Regex(const Regex &) = delete; Regex &operator=(Regex regex) { std::swap(preg, regex.preg); std::swap(error, regex.error); diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h index e21269b2f1d5..95c4e96f7f29 100644 --- a/include/llvm/Support/Registry.h +++ b/include/llvm/Support/Registry.h @@ -14,6 +14,7 @@ #ifndef LLVM_SUPPORT_REGISTRY_H #define LLVM_SUPPORT_REGISTRY_H +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" #include <memory> @@ -41,7 +42,7 @@ namespace llvm { /// is necessary to define an alternate traits class. template <typename T> class RegistryTraits { - RegistryTraits() LLVM_DELETED_FUNCTION; + RegistryTraits() = delete; public: typedef SimpleRegistryEntry<T> entry; @@ -67,7 +68,7 @@ namespace llvm { class iterator; private: - Registry() LLVM_DELETED_FUNCTION; + Registry() = delete; static void Announce(const entry &E) { for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next) @@ -120,6 +121,10 @@ namespace llvm { static iterator begin() { return iterator(Head); } static iterator end() { return iterator(nullptr); } + static iterator_range<iterator> entries() { + return iterator_range<iterator>(begin(), end()); + } + /// Abstract base class for registry listeners, which are informed when new /// entries are added to the registry. Simply subclass and instantiate: diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h index a1c4c80c356f..0a4262b7eec5 100644 --- a/include/llvm/Support/ScaledNumber.h +++ b/include/llvm/Support/ScaledNumber.h @@ -514,7 +514,7 @@ public: : Digits(Digits), Scale(Scale) {} private: - ScaledNumber(const std::pair<uint64_t, int16_t> &X) + ScaledNumber(const std::pair<DigitsT, int16_t> &X) : Digits(X.first), Scale(X.second) {} public: @@ -670,14 +670,7 @@ public: return ScaledNumbers::compare(Digits, Scale, X.Digits, X.Scale); } int compareTo(uint64_t N) const { - ScaledNumber Scaled = get(N); - int Compare = compare(Scaled); - if (Width == 64 || Compare != 0) - return Compare; - - // Check for precision loss. We know *this == RoundTrip. - uint64_t RoundTrip = Scaled.template toInt<uint64_t>(); - return N == RoundTrip ? 0 : RoundTrip < N ? -1 : 1; + return ScaledNumbers::compare<uint64_t>(Digits, Scale, N, 0); } int compareTo(int64_t N) const { return N < 0 ? 1 : compareTo(uint64_t(N)); } @@ -732,11 +725,21 @@ SCALED_NUMBER_BOP(+, += ) SCALED_NUMBER_BOP(-, -= ) SCALED_NUMBER_BOP(*, *= ) SCALED_NUMBER_BOP(/, /= ) -SCALED_NUMBER_BOP(<<, <<= ) -SCALED_NUMBER_BOP(>>, >>= ) #undef SCALED_NUMBER_BOP template <class DigitsT> +ScaledNumber<DigitsT> operator<<(const ScaledNumber<DigitsT> &L, + int16_t Shift) { + return ScaledNumber<DigitsT>(L) <<= Shift; +} + +template <class DigitsT> +ScaledNumber<DigitsT> operator>>(const ScaledNumber<DigitsT> &L, + int16_t Shift) { + return ScaledNumber<DigitsT>(L) >>= Shift; +} + +template <class DigitsT> raw_ostream &operator<<(raw_ostream &OS, const ScaledNumber<DigitsT> &X) { return X.print(OS, 10); } diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h index 6cbc1f6854a6..7e165d7f3a42 100644 --- a/include/llvm/Support/Signals.h +++ b/include/llvm/Support/Signals.h @@ -15,10 +15,12 @@ #ifndef LLVM_SUPPORT_SIGNALS_H #define LLVM_SUPPORT_SIGNALS_H -#include "llvm/Support/Path.h" -#include <cstdio> +#include <string> namespace llvm { +class StringRef; +class raw_ostream; + namespace sys { /// This function runs all the registered interrupt handlers, including the @@ -37,10 +39,13 @@ namespace sys { /// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the /// process, print a stack trace and then exit. /// @brief Print a stack trace if a fatal signal occurs. - void PrintStackTraceOnErrorSignal(); + void PrintStackTraceOnErrorSignal(bool DisableCrashReporting = false); + + /// Disable all system dialog boxes that appear when the process crashes. + void DisableSystemDialogsOnCrash(); - /// \brief Print the stack trace using the given \c FILE object. - void PrintStackTrace(FILE *); + /// \brief Print the stack trace using the given \c raw_ostream object. + void PrintStackTrace(raw_ostream &OS); /// AddSignalHandler - Add a function to be called when an abort/kill signal /// is delivered to the process. The handler can have a cookie passed to it diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index f9e114b67cb4..d492748e7781 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -73,8 +73,8 @@ private: bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); } - SourceMgr(const SourceMgr&) LLVM_DELETED_FUNCTION; - void operator=(const SourceMgr&) LLVM_DELETED_FUNCTION; + SourceMgr(const SourceMgr&) = delete; + void operator=(const SourceMgr&) = delete; public: SourceMgr() : LineNoCache(nullptr), DiagHandler(nullptr), DiagContext(nullptr) {} diff --git a/include/llvm/Support/SpecialCaseList.h b/include/llvm/Support/SpecialCaseList.h index 313212e59dd2..ce693c501312 100644 --- a/include/llvm/Support/SpecialCaseList.h +++ b/include/llvm/Support/SpecialCaseList.h @@ -49,6 +49,8 @@ #define LLVM_SUPPORT_SPECIALCASELIST_H #include "llvm/ADT/StringMap.h" +#include <string> +#include <vector> namespace llvm { class MemoryBuffer; @@ -57,18 +59,18 @@ class StringRef; class SpecialCaseList { public: - /// Parses the special case list from a file. If Path is empty, returns - /// an empty special case list. On failure, returns 0 and writes an error - /// message to string. - static std::unique_ptr<SpecialCaseList> create(StringRef Path, - std::string &Error); + /// Parses the special case list entries from files. On failure, returns + /// 0 and writes an error message to string. + static std::unique_ptr<SpecialCaseList> + create(const std::vector<std::string> &Paths, std::string &Error); /// Parses the special case list from a memory buffer. On failure, returns /// 0 and writes an error message to string. static std::unique_ptr<SpecialCaseList> create(const MemoryBuffer *MB, - std::string &Error); - /// Parses the special case list from a file. On failure, reports a fatal - /// error. - static std::unique_ptr<SpecialCaseList> createOrDie(StringRef Path); + std::string &Error); + /// Parses the special case list entries from files. On failure, reports a + /// fatal error. + static std::unique_ptr<SpecialCaseList> + createOrDie(const std::vector<std::string> &Paths); ~SpecialCaseList(); @@ -81,15 +83,19 @@ public: StringRef Category = StringRef()) const; private: - SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION; - SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION; + SpecialCaseList(SpecialCaseList const &) = delete; + SpecialCaseList &operator=(SpecialCaseList const &) = delete; struct Entry; - StringMap<StringMap<Entry> > Entries; + StringMap<StringMap<Entry>> Entries; + StringMap<StringMap<std::string>> Regexps; + bool IsCompiled; SpecialCaseList(); /// Parses just-constructed SpecialCaseList entries from a memory buffer. bool parse(const MemoryBuffer *MB, std::string &Error); + /// compile() should be called once, after parsing all the memory buffers. + void compile(); }; } // namespace llvm diff --git a/include/llvm/Support/StreamingMemoryObject.h b/include/llvm/Support/StreamingMemoryObject.h index 66ed521a411c..932e635cd072 100644 --- a/include/llvm/Support/StreamingMemoryObject.h +++ b/include/llvm/Support/StreamingMemoryObject.h @@ -14,7 +14,6 @@ #include "llvm/Support/DataStream.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryObject.h" -#include <cassert> #include <memory> #include <vector> @@ -30,11 +29,12 @@ public: uint64_t readBytes(uint8_t *Buf, uint64_t Size, uint64_t Address) const override; const uint8_t *getPointer(uint64_t address, uint64_t size) const override { - // This could be fixed by ensuring the bytes are fetched and making a copy, - // requiring that the bitcode size be known, or otherwise ensuring that - // the memory doesn't go away/get reallocated, but it's - // not currently necessary. Users that need the pointer don't stream. - llvm_unreachable("getPointer in streaming memory objects not allowed"); + // FIXME: This could be fixed by ensuring the bytes are fetched and + // making a copy, requiring that the bitcode size be known, or + // otherwise ensuring that the memory doesn't go away/get reallocated, + // but it's not currently necessary. Users that need the pointer (any + // that need Blobs) don't stream. + report_fatal_error("getPointer in streaming memory objects not allowed"); return nullptr; } bool isValidAddress(uint64_t address) const override; @@ -59,30 +59,31 @@ private: mutable size_t ObjectSize; // 0 if unknown, set if wrapper seen or EOF reached mutable bool EOFReached; - // Fetch enough bytes such that Pos can be read or EOF is reached - // (i.e. BytesRead > Pos). Return true if Pos can be read. - // Unlike most of the functions in BitcodeReader, returns true on success. - // Most of the requests will be small, but we fetch at kChunkSize bytes - // at a time to avoid making too many potentially expensive GetBytes calls + // Fetch enough bytes such that Pos can be read (i.e. BytesRead > + // Pos). Returns true if Pos can be read. Unlike most of the + // functions in BitcodeReader, returns true on success. Most of the + // requests will be small, but we fetch at kChunkSize bytes at a + // time to avoid making too many potentially expensive GetBytes + // calls. bool fetchToPos(size_t Pos) const { - if (EOFReached) - return Pos < ObjectSize; while (Pos >= BytesRead) { + if (EOFReached) + return false; Bytes.resize(BytesRead + BytesSkipped + kChunkSize); size_t bytes = Streamer->GetBytes(&Bytes[BytesRead + BytesSkipped], kChunkSize); BytesRead += bytes; - if (bytes != kChunkSize) { // reached EOF/ran out of bytes - ObjectSize = BytesRead; + if (bytes == 0) { // reached EOF/ran out of bytes + if (ObjectSize == 0) + ObjectSize = BytesRead; EOFReached = true; - break; } } - return Pos < BytesRead; + return !ObjectSize || Pos < ObjectSize; } - StreamingMemoryObject(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; - void operator=(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; + StreamingMemoryObject(const StreamingMemoryObject&) = delete; + void operator=(const StreamingMemoryObject&) = delete; }; MemoryObject *getNonStreamedMemoryObject( diff --git a/include/llvm/Support/StringPool.h b/include/llvm/Support/StringPool.h index b51974c946e0..2ec0c3b76c11 100644 --- a/include/llvm/Support/StringPool.h +++ b/include/llvm/Support/StringPool.h @@ -30,9 +30,7 @@ #define LLVM_SUPPORT_STRINGPOOL_H #include "llvm/ADT/StringMap.h" -#include "llvm/Support/Compiler.h" #include <cassert> -#include <new> namespace llvm { @@ -129,7 +127,7 @@ namespace llvm { } inline const char *operator*() const { return begin(); } - inline LLVM_EXPLICIT operator bool() const { return S != nullptr; } + inline explicit operator bool() const { return S != nullptr; } inline bool operator==(const PooledStringPtr &That) const { return S == That.S; } inline bool operator!=(const PooledStringPtr &That) const { return S != That.S; } diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h index 9c5a3c59122e..7761fa1d7e01 100644 --- a/include/llvm/Support/SwapByteOrder.h +++ b/include/llvm/Support/SwapByteOrder.h @@ -94,6 +94,26 @@ inline signed long long getSwappedBytes(signed long long C) { return SwapByteOrder_64(C); } +inline float getSwappedBytes(float C) { + union { + uint32_t i; + float f; + } in, out; + in.f = C; + out.i = SwapByteOrder_32(in.i); + return out.f; +} + +inline double getSwappedBytes(double C) { + union { + uint64_t i; + double d; + } in, out; + in.d = C; + out.i = SwapByteOrder_64(in.i); + return out.d; +} + template<typename T> inline void swapByteOrder(T &Value) { Value = getSwappedBytes(Value); diff --git a/include/llvm/Support/SystemUtils.h b/include/llvm/Support/SystemUtils.h index d2d08b234272..2997b1b0c9cf 100644 --- a/include/llvm/Support/SystemUtils.h +++ b/include/llvm/Support/SystemUtils.h @@ -15,8 +15,6 @@ #ifndef LLVM_SUPPORT_SYSTEMUTILS_H #define LLVM_SUPPORT_SYSTEMUTILS_H -#include <string> - namespace llvm { class raw_ostream; diff --git a/include/llvm/Support/TargetParser.h b/include/llvm/Support/TargetParser.h new file mode 100644 index 000000000000..ca626f271d51 --- /dev/null +++ b/include/llvm/Support/TargetParser.h @@ -0,0 +1,155 @@ +//===-- TargetParser - Parser for target features ---------------*- 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 target parser to recognise hardware features such as +// FPU/CPU/ARCH names as well as specific support such as HDIV, etc. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TARGETPARSER_H +#define LLVM_SUPPORT_TARGETPARSER_H + +namespace llvm { + class StringRef; + +// Target specific information into their own namespaces. These should be +// generated from TableGen because the information is already there, and there +// is where new information about targets will be added. +// FIXME: To TableGen this we need to make some table generated files available +// even if the back-end is not compiled with LLVM, plus we need to create a new +// back-end to TableGen to create these clean tables. +namespace ARM { + // FPU names. + enum FPUKind { + FK_INVALID = 0, + FK_VFP, + FK_VFPV2, + FK_VFPV3, + FK_VFPV3_D16, + FK_VFPV4, + FK_VFPV4_D16, + FK_FPV5_D16, + FK_FP_ARMV8, + FK_NEON, + FK_NEON_VFPV4, + FK_NEON_FP_ARMV8, + FK_CRYPTO_NEON_FP_ARMV8, + FK_SOFTVFP, + FK_LAST + }; + + // Arch names. + enum ArchKind { + AK_INVALID = 0, + AK_ARMV2, + AK_ARMV2A, + AK_ARMV3, + AK_ARMV3M, + AK_ARMV4, + AK_ARMV4T, + AK_ARMV5, + AK_ARMV5T, + AK_ARMV5TE, + AK_ARMV6, + AK_ARMV6J, + AK_ARMV6K, + AK_ARMV6T2, + AK_ARMV6Z, + AK_ARMV6ZK, + AK_ARMV6M, + AK_ARMV7, + AK_ARMV7A, + AK_ARMV7R, + AK_ARMV7M, + AK_ARMV8A, + AK_ARMV8_1A, + // Non-standard Arch names. + AK_IWMMXT, + AK_IWMMXT2, + AK_XSCALE, + AK_ARMV5E, + AK_ARMV5TEJ, + AK_ARMV6SM, + AK_ARMV6HL, + AK_ARMV7L, + AK_ARMV7HL, + AK_ARMV7S, + AK_ARMV7EM, + AK_LAST + }; + + // Arch extension modifiers for CPUs. + enum ArchExtKind { + AEK_INVALID = 0, + AEK_CRC, + AEK_CRYPTO, + AEK_FP, + AEK_HWDIV, + AEK_MP, + AEK_SEC, + AEK_VIRT, + AEK_LAST + }; + + // ISA kinds. + enum ISAKind { + IK_INVALID = 0, + IK_ARM, + IK_THUMB, + IK_AARCH64 + }; + + // Endianness + // FIXME: BE8 vs. BE32? + enum EndianKind { + EK_INVALID = 0, + EK_LITTLE, + EK_BIG + }; + + // v6/v7/v8 Profile + enum ProfileKind { + PK_INVALID = 0, + PK_A, + PK_R, + PK_M + }; +} // namespace ARM + +// Target Parsers, one per architecture. +class ARMTargetParser { + static StringRef getFPUSynonym(StringRef FPU); + static StringRef getArchSynonym(StringRef Arch); + +public: + static StringRef getCanonicalArchName(StringRef Arch); + + // Information by ID + static const char * getFPUName(unsigned FPUKind); + static const char * getArchName(unsigned ArchKind); + static unsigned getArchDefaultCPUArch(unsigned ArchKind); + static const char * getArchDefaultCPUName(unsigned ArchKind); + static const char * getArchExtName(unsigned ArchExtKind); + static const char * getDefaultCPU(StringRef Arch); + + // Parser + static unsigned parseFPU(StringRef FPU); + static unsigned parseArch(StringRef Arch); + static unsigned parseArchExt(StringRef ArchExt); + static unsigned parseCPUArch(StringRef CPU); + static unsigned parseArchISA(StringRef Arch); + static unsigned parseArchEndian(StringRef Arch); + static unsigned parseArchProfile(StringRef Arch); + static unsigned parseArchVersion(StringRef Arch); + +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index 8ac4b904bb88..408e908aa04c 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -22,1133 +22,1161 @@ #include "llvm-c/Disassembler.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/CodeGen.h" +#include "llvm/Support/FormattedStream.h" #include <cassert> +#include <memory> #include <string> namespace llvm { - class AsmPrinter; - class Module; - class MCAssembler; - class MCAsmBackend; - class MCAsmInfo; - class MCAsmParser; - class MCCodeEmitter; - class MCCodeGenInfo; - class MCContext; - class MCDisassembler; - class MCInstrAnalysis; - class MCInstPrinter; - class MCInstrInfo; - class MCRegisterInfo; - class MCStreamer; - class MCSubtargetInfo; - class MCSymbolizer; - class MCRelocationInfo; - class MCTargetAsmParser; - class MCTargetOptions; - class TargetMachine; - class TargetOptions; - class raw_ostream; - class formatted_raw_ostream; - - MCStreamer *createNullStreamer(MCContext &Ctx); - MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isVerboseAsm, bool useDwarfDirectory, - MCInstPrinter *InstPrint, MCCodeEmitter *CE, - MCAsmBackend *TAB, bool ShowInst); - - MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx); - - MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp, - void *DisInfo, - MCContext *Ctx, - MCRelocationInfo *RelInfo); - - /// Target - Wrapper for Target specific information. - /// - /// For registration purposes, this is a POD type so that targets can be - /// registered without the use of static constructors. - /// - /// Targets should implement a single global instance of this class (which - /// will be zero initialized), and pass that instance to the TargetRegistry as - /// part of their initialization. - class Target { - public: - friend struct TargetRegistry; - - typedef bool (*ArchMatchFnTy)(Triple::ArchType Arch); - - typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI, - StringRef TT); - typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT, - Reloc::Model RM, - CodeModel::Model CM, - CodeGenOpt::Level OL); - typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void); - typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo*Info); - typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(StringRef TT); - typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(StringRef TT, - StringRef CPU, - StringRef Features); - typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T, - StringRef TT, - StringRef CPU, - StringRef Features, - const TargetOptions &Options, - Reloc::Model RM, +class AsmPrinter; +class MCAsmBackend; +class MCAsmInfo; +class MCAsmParser; +class MCCodeEmitter; +class MCCodeGenInfo; +class MCContext; +class MCDisassembler; +class MCInstrAnalysis; +class MCInstPrinter; +class MCInstrInfo; +class MCRegisterInfo; +class MCStreamer; +class MCSubtargetInfo; +class MCSymbolizer; +class MCRelocationInfo; +class MCTargetAsmParser; +class MCTargetOptions; +class MCTargetStreamer; +class TargetMachine; +class TargetOptions; +class raw_ostream; +class raw_pwrite_stream; +class formatted_raw_ostream; + +MCStreamer *createNullStreamer(MCContext &Ctx); +MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr<formatted_raw_ostream> OS, + bool isVerboseAsm, bool useDwarfDirectory, + MCInstPrinter *InstPrint, MCCodeEmitter *CE, + MCAsmBackend *TAB, bool ShowInst); + +/// Takes ownership of \p TAB and \p CE. +MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, + raw_pwrite_stream &OS, MCCodeEmitter *CE, + bool RelaxAll); +MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, + raw_pwrite_stream &OS, MCCodeEmitter *CE, + bool RelaxAll, bool DWARFMustBeAtTheEnd, + bool LabelSections = false); + +MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx); + +MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp, + void *DisInfo, MCContext *Ctx, + std::unique_ptr<MCRelocationInfo> &&RelInfo); + +/// Target - Wrapper for Target specific information. +/// +/// For registration purposes, this is a POD type so that targets can be +/// registered without the use of static constructors. +/// +/// Targets should implement a single global instance of this class (which +/// will be zero initialized), and pass that instance to the TargetRegistry as +/// part of their initialization. +class Target { +public: + friend struct TargetRegistry; + + typedef bool (*ArchMatchFnTy)(Triple::ArchType Arch); + + typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI, + StringRef TT); + typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL); - typedef AsmPrinter *(*AsmPrinterCtorTy)(TargetMachine &TM, - MCStreamer &Streamer); - typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T, - const MCRegisterInfo &MRI, - StringRef TT, - StringRef CPU); - typedef MCTargetAsmParser *(*MCAsmParserCtorTy)( - MCSubtargetInfo &STI, - MCAsmParser &P, - const MCInstrInfo &MII, - const MCTargetOptions &Options); - typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T, - const MCSubtargetInfo &STI, - MCContext &Ctx); - typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T, - unsigned SyntaxVariant, - const MCAsmInfo &MAI, - const MCInstrInfo &MII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI); - typedef MCCodeEmitter *(*MCCodeEmitterCtorTy)(const MCInstrInfo &II, - const MCRegisterInfo &MRI, + typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void); + typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo *Info); + typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(StringRef TT); + typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(StringRef TT, + StringRef CPU, + StringRef Features); + typedef TargetMachine *(*TargetMachineCtorTy)( + const Target &T, StringRef TT, StringRef CPU, StringRef Features, + const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL); + // If it weren't for layering issues (this header is in llvm/Support, but + // depends on MC?) this should take the Streamer by value rather than rvalue + // reference. + typedef AsmPrinter *(*AsmPrinterCtorTy)( + TargetMachine &TM, std::unique_ptr<MCStreamer> &&Streamer); + typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T, + const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU); + typedef MCTargetAsmParser *(*MCAsmParserCtorTy)( + MCSubtargetInfo &STI, MCAsmParser &P, const MCInstrInfo &MII, + const MCTargetOptions &Options); + typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T, const MCSubtargetInfo &STI, MCContext &Ctx); - typedef MCStreamer *(*MCObjectStreamerCtorTy)( - const Target &T, StringRef TT, MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &_OS, MCCodeEmitter *_Emitter, const MCSubtargetInfo &STI, - bool RelaxAll); - typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx, - formatted_raw_ostream &OS, - bool isVerboseAsm, - bool useDwarfDirectory, - MCInstPrinter *InstPrint, - MCCodeEmitter *CE, - MCAsmBackend *TAB, - bool ShowInst); - typedef MCStreamer *(*NullStreamerCtorTy)(MCContext &Ctx); - typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(StringRef TT, - MCContext &Ctx); - typedef MCSymbolizer *(*MCSymbolizerCtorTy)(StringRef TT, - LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp, - void *DisInfo, - MCContext *Ctx, - MCRelocationInfo *RelInfo); - - private: - /// Next - The next registered target in the linked list, maintained by the - /// TargetRegistry. - Target *Next; - - /// The target function for checking if an architecture is supported. - ArchMatchFnTy ArchMatchFn; - - /// Name - The target name. - const char *Name; - - /// ShortDesc - A short description of the target. - const char *ShortDesc; - - /// HasJIT - Whether this target supports the JIT. - bool HasJIT; - - /// MCAsmInfoCtorFn - Constructor function for this target's MCAsmInfo, if - /// registered. - MCAsmInfoCtorFnTy MCAsmInfoCtorFn; - - /// MCCodeGenInfoCtorFn - Constructor function for this target's - /// MCCodeGenInfo, if registered. - MCCodeGenInfoCtorFnTy MCCodeGenInfoCtorFn; - - /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo, - /// if registered. - MCInstrInfoCtorFnTy MCInstrInfoCtorFn; - - /// MCInstrAnalysisCtorFn - Constructor function for this target's - /// MCInstrAnalysis, if registered. - MCInstrAnalysisCtorFnTy MCInstrAnalysisCtorFn; - - /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo, - /// if registered. - MCRegInfoCtorFnTy MCRegInfoCtorFn; - - /// MCSubtargetInfoCtorFn - Constructor function for this target's - /// MCSubtargetInfo, if registered. - MCSubtargetInfoCtorFnTy MCSubtargetInfoCtorFn; - - /// TargetMachineCtorFn - Construction function for this target's - /// TargetMachine, if registered. - TargetMachineCtorTy TargetMachineCtorFn; - - /// MCAsmBackendCtorFn - Construction function for this target's - /// MCAsmBackend, if registered. - MCAsmBackendCtorTy MCAsmBackendCtorFn; - - /// MCAsmParserCtorFn - Construction function for this target's - /// MCTargetAsmParser, if registered. - MCAsmParserCtorTy MCAsmParserCtorFn; - - /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter, - /// if registered. - AsmPrinterCtorTy AsmPrinterCtorFn; - - /// MCDisassemblerCtorFn - Construction function for this target's - /// MCDisassembler, if registered. - MCDisassemblerCtorTy MCDisassemblerCtorFn; - - /// MCInstPrinterCtorFn - Construction function for this target's - /// MCInstPrinter, if registered. - MCInstPrinterCtorTy MCInstPrinterCtorFn; - - /// MCCodeEmitterCtorFn - Construction function for this target's - /// CodeEmitter, if registered. - MCCodeEmitterCtorTy MCCodeEmitterCtorFn; - - /// MCObjectStreamerCtorFn - Construction function for this target's - /// MCObjectStreamer, if registered. - MCObjectStreamerCtorTy MCObjectStreamerCtorFn; - - /// AsmStreamerCtorFn - Construction function for this target's - /// AsmStreamer, if registered (default = llvm::createAsmStreamer). - AsmStreamerCtorTy AsmStreamerCtorFn; - - /// Construction function for this target's NullStreamer, if registered - /// (default = llvm::createNullStreamer). - NullStreamerCtorTy NullStreamerCtorFn; - - /// MCRelocationInfoCtorFn - Construction function for this target's - /// MCRelocationInfo, if registered (default = llvm::createMCRelocationInfo) - MCRelocationInfoCtorTy MCRelocationInfoCtorFn; - - /// MCSymbolizerCtorFn - Construction function for this target's - /// MCSymbolizer, if registered (default = llvm::createMCSymbolizer) - MCSymbolizerCtorTy MCSymbolizerCtorFn; + typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Triple &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI); + typedef MCCodeEmitter *(*MCCodeEmitterCtorTy)(const MCInstrInfo &II, + const MCRegisterInfo &MRI, + MCContext &Ctx); + typedef MCStreamer *(*ELFStreamerCtorTy)(const Triple &T, MCContext &Ctx, + MCAsmBackend &TAB, + raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, + bool RelaxAll); + typedef MCStreamer *(*MachOStreamerCtorTy)(MCContext &Ctx, MCAsmBackend &TAB, + raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, + bool RelaxAll, + bool DWARFMustBeAtTheEnd); + typedef MCStreamer *(*COFFStreamerCtorTy)(MCContext &Ctx, MCAsmBackend &TAB, + raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, + bool RelaxAll); + typedef MCTargetStreamer *(*NullTargetStreamerCtorTy)(MCStreamer &S); + typedef MCTargetStreamer *(*AsmTargetStreamerCtorTy)( + MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint, + bool IsVerboseAsm); + typedef MCTargetStreamer *(*ObjectTargetStreamerCtorTy)( + MCStreamer &S, const MCSubtargetInfo &STI); + typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(StringRef TT, + MCContext &Ctx); + typedef MCSymbolizer *(*MCSymbolizerCtorTy)( + StringRef TT, LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, MCContext *Ctx, + std::unique_ptr<MCRelocationInfo> &&RelInfo); + +private: + /// Next - The next registered target in the linked list, maintained by the + /// TargetRegistry. + Target *Next; + + /// The target function for checking if an architecture is supported. + ArchMatchFnTy ArchMatchFn; + + /// Name - The target name. + const char *Name; + + /// ShortDesc - A short description of the target. + const char *ShortDesc; + + /// HasJIT - Whether this target supports the JIT. + bool HasJIT; + + /// MCAsmInfoCtorFn - Constructor function for this target's MCAsmInfo, if + /// registered. + MCAsmInfoCtorFnTy MCAsmInfoCtorFn; + + /// MCCodeGenInfoCtorFn - Constructor function for this target's + /// MCCodeGenInfo, if registered. + MCCodeGenInfoCtorFnTy MCCodeGenInfoCtorFn; + + /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo, + /// if registered. + MCInstrInfoCtorFnTy MCInstrInfoCtorFn; + + /// MCInstrAnalysisCtorFn - Constructor function for this target's + /// MCInstrAnalysis, if registered. + MCInstrAnalysisCtorFnTy MCInstrAnalysisCtorFn; + + /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo, + /// if registered. + MCRegInfoCtorFnTy MCRegInfoCtorFn; + + /// MCSubtargetInfoCtorFn - Constructor function for this target's + /// MCSubtargetInfo, if registered. + MCSubtargetInfoCtorFnTy MCSubtargetInfoCtorFn; + + /// TargetMachineCtorFn - Construction function for this target's + /// TargetMachine, if registered. + TargetMachineCtorTy TargetMachineCtorFn; + + /// MCAsmBackendCtorFn - Construction function for this target's + /// MCAsmBackend, if registered. + MCAsmBackendCtorTy MCAsmBackendCtorFn; + + /// MCAsmParserCtorFn - Construction function for this target's + /// MCTargetAsmParser, if registered. + MCAsmParserCtorTy MCAsmParserCtorFn; + + /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter, + /// if registered. + AsmPrinterCtorTy AsmPrinterCtorFn; + + /// MCDisassemblerCtorFn - Construction function for this target's + /// MCDisassembler, if registered. + MCDisassemblerCtorTy MCDisassemblerCtorFn; + + /// MCInstPrinterCtorFn - Construction function for this target's + /// MCInstPrinter, if registered. + MCInstPrinterCtorTy MCInstPrinterCtorFn; + + /// MCCodeEmitterCtorFn - Construction function for this target's + /// CodeEmitter, if registered. + MCCodeEmitterCtorTy MCCodeEmitterCtorFn; + + // Construction functions for the various object formats, if registered. + COFFStreamerCtorTy COFFStreamerCtorFn; + MachOStreamerCtorTy MachOStreamerCtorFn; + ELFStreamerCtorTy ELFStreamerCtorFn; + + /// Construction function for this target's null TargetStreamer, if + /// registered (default = nullptr). + NullTargetStreamerCtorTy NullTargetStreamerCtorFn; + + /// Construction function for this target's asm TargetStreamer, if + /// registered (default = nullptr). + AsmTargetStreamerCtorTy AsmTargetStreamerCtorFn; + + /// Construction function for this target's obj TargetStreamer, if + /// registered (default = nullptr). + ObjectTargetStreamerCtorTy ObjectTargetStreamerCtorFn; + + /// MCRelocationInfoCtorFn - Construction function for this target's + /// MCRelocationInfo, if registered (default = llvm::createMCRelocationInfo) + MCRelocationInfoCtorTy MCRelocationInfoCtorFn; - public: - Target() - : AsmStreamerCtorFn(nullptr), NullStreamerCtorFn(nullptr), - MCRelocationInfoCtorFn(nullptr), MCSymbolizerCtorFn(nullptr) {} - - /// @name Target Information - /// @{ - - // getNext - Return the next registered target. - const Target *getNext() const { return Next; } - - /// getName - Get the target name. - const char *getName() const { return Name; } - - /// getShortDescription - Get a short description of the target. - const char *getShortDescription() const { return ShortDesc; } - - /// @} - /// @name Feature Predicates - /// @{ - - /// hasJIT - Check if this targets supports the just-in-time compilation. - bool hasJIT() const { return HasJIT; } - - /// hasTargetMachine - Check if this target supports code generation. - bool hasTargetMachine() const { return TargetMachineCtorFn != nullptr; } - - /// hasMCAsmBackend - Check if this target supports .o generation. - bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != nullptr; } - - /// @} - /// @name Feature Constructors - /// @{ - - /// createMCAsmInfo - Create a MCAsmInfo implementation for the specified - /// target triple. - /// - /// \param Triple This argument is used to determine the target machine - /// feature set; it should always be provided. Generally this should be - /// either the target triple from the module, or the target triple of the - /// host if that does not exist. - MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI, - StringRef Triple) const { - if (!MCAsmInfoCtorFn) - return nullptr; - return MCAsmInfoCtorFn(MRI, Triple); - } + /// MCSymbolizerCtorFn - Construction function for this target's + /// MCSymbolizer, if registered (default = llvm::createMCSymbolizer) + MCSymbolizerCtorTy MCSymbolizerCtorFn; - /// createMCCodeGenInfo - Create a MCCodeGenInfo implementation. - /// - MCCodeGenInfo *createMCCodeGenInfo(StringRef Triple, Reloc::Model RM, - CodeModel::Model CM, - CodeGenOpt::Level OL) const { - if (!MCCodeGenInfoCtorFn) - return nullptr; - return MCCodeGenInfoCtorFn(Triple, RM, CM, OL); - } +public: + Target() + : COFFStreamerCtorFn(nullptr), MachOStreamerCtorFn(nullptr), + ELFStreamerCtorFn(nullptr), NullTargetStreamerCtorFn(nullptr), + AsmTargetStreamerCtorFn(nullptr), ObjectTargetStreamerCtorFn(nullptr), + MCRelocationInfoCtorFn(nullptr), MCSymbolizerCtorFn(nullptr) {} - /// createMCInstrInfo - Create a MCInstrInfo implementation. - /// - MCInstrInfo *createMCInstrInfo() const { - if (!MCInstrInfoCtorFn) - return nullptr; - return MCInstrInfoCtorFn(); - } + /// @name Target Information + /// @{ - /// createMCInstrAnalysis - Create a MCInstrAnalysis implementation. - /// - MCInstrAnalysis *createMCInstrAnalysis(const MCInstrInfo *Info) const { - if (!MCInstrAnalysisCtorFn) - return nullptr; - return MCInstrAnalysisCtorFn(Info); - } + // getNext - Return the next registered target. + const Target *getNext() const { return Next; } - /// createMCRegInfo - Create a MCRegisterInfo implementation. - /// - MCRegisterInfo *createMCRegInfo(StringRef Triple) const { - if (!MCRegInfoCtorFn) - return nullptr; - return MCRegInfoCtorFn(Triple); - } + /// getName - Get the target name. + const char *getName() const { return Name; } - /// createMCSubtargetInfo - Create a MCSubtargetInfo implementation. - /// - /// \param Triple This argument is used to determine the target machine - /// feature set; it should always be provided. Generally this should be - /// either the target triple from the module, or the target triple of the - /// host if that does not exist. - /// \param CPU This specifies the name of the target CPU. - /// \param Features This specifies the string representation of the - /// additional target features. - MCSubtargetInfo *createMCSubtargetInfo(StringRef Triple, StringRef CPU, - StringRef Features) const { - if (!MCSubtargetInfoCtorFn) - return nullptr; - return MCSubtargetInfoCtorFn(Triple, CPU, Features); - } + /// getShortDescription - Get a short description of the target. + const char *getShortDescription() const { return ShortDesc; } - /// createTargetMachine - Create a target specific machine implementation - /// for the specified \p Triple. - /// - /// \param Triple This argument is used to determine the target machine - /// feature set; it should always be provided. Generally this should be - /// either the target triple from the module, or the target triple of the - /// host if that does not exist. - TargetMachine *createTargetMachine(StringRef Triple, StringRef CPU, - StringRef Features, const TargetOptions &Options, - Reloc::Model RM = Reloc::Default, - CodeModel::Model CM = CodeModel::Default, - CodeGenOpt::Level OL = CodeGenOpt::Default) const { - if (!TargetMachineCtorFn) - return nullptr; - return TargetMachineCtorFn(*this, Triple, CPU, Features, Options, - RM, CM, OL); - } + /// @} + /// @name Feature Predicates + /// @{ - /// createMCAsmBackend - Create a target specific assembly parser. - /// - /// \param Triple The target triple string. - MCAsmBackend *createMCAsmBackend(const MCRegisterInfo &MRI, - StringRef Triple, StringRef CPU) const { - if (!MCAsmBackendCtorFn) - return nullptr; - return MCAsmBackendCtorFn(*this, MRI, Triple, CPU); - } + /// hasJIT - Check if this targets supports the just-in-time compilation. + bool hasJIT() const { return HasJIT; } - /// createMCAsmParser - Create a target specific assembly parser. - /// - /// \param Parser The target independent parser implementation to use for - /// parsing and lexing. - MCTargetAsmParser *createMCAsmParser( - MCSubtargetInfo &STI, - MCAsmParser &Parser, - const MCInstrInfo &MII, - const MCTargetOptions &Options) const { - if (!MCAsmParserCtorFn) - return nullptr; - return MCAsmParserCtorFn(STI, Parser, MII, Options); - } + /// hasTargetMachine - Check if this target supports code generation. + bool hasTargetMachine() const { return TargetMachineCtorFn != nullptr; } - /// createAsmPrinter - Create a target specific assembly printer pass. This - /// takes ownership of the MCStreamer object. - AsmPrinter *createAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) const{ - if (!AsmPrinterCtorFn) - return nullptr; - return AsmPrinterCtorFn(TM, Streamer); - } + /// hasMCAsmBackend - Check if this target supports .o generation. + bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != nullptr; } - MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI, - MCContext &Ctx) const { - if (!MCDisassemblerCtorFn) - return nullptr; - return MCDisassemblerCtorFn(*this, STI, Ctx); - } + /// @} + /// @name Feature Constructors + /// @{ - MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant, - const MCAsmInfo &MAI, - const MCInstrInfo &MII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI) const { - if (!MCInstPrinterCtorFn) - return nullptr; - return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI, MII, MRI, STI); - } + /// createMCAsmInfo - Create a MCAsmInfo implementation for the specified + /// target triple. + /// + /// \param Triple This argument is used to determine the target machine + /// feature set; it should always be provided. Generally this should be + /// either the target triple from the module, or the target triple of the + /// host if that does not exist. + MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI, + StringRef Triple) const { + if (!MCAsmInfoCtorFn) + return nullptr; + return MCAsmInfoCtorFn(MRI, Triple); + } + + /// createMCCodeGenInfo - Create a MCCodeGenInfo implementation. + /// + MCCodeGenInfo *createMCCodeGenInfo(StringRef Triple, Reloc::Model RM, + CodeModel::Model CM, + CodeGenOpt::Level OL) const { + if (!MCCodeGenInfoCtorFn) + return nullptr; + return MCCodeGenInfoCtorFn(Triple, RM, CM, OL); + } + + /// createMCInstrInfo - Create a MCInstrInfo implementation. + /// + MCInstrInfo *createMCInstrInfo() const { + if (!MCInstrInfoCtorFn) + return nullptr; + return MCInstrInfoCtorFn(); + } + /// createMCInstrAnalysis - Create a MCInstrAnalysis implementation. + /// + MCInstrAnalysis *createMCInstrAnalysis(const MCInstrInfo *Info) const { + if (!MCInstrAnalysisCtorFn) + return nullptr; + return MCInstrAnalysisCtorFn(Info); + } - /// createMCCodeEmitter - Create a target specific code emitter. - MCCodeEmitter *createMCCodeEmitter(const MCInstrInfo &II, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, + /// createMCRegInfo - Create a MCRegisterInfo implementation. + /// + MCRegisterInfo *createMCRegInfo(StringRef Triple) const { + if (!MCRegInfoCtorFn) + return nullptr; + return MCRegInfoCtorFn(Triple); + } + + /// createMCSubtargetInfo - Create a MCSubtargetInfo implementation. + /// + /// \param Triple This argument is used to determine the target machine + /// feature set; it should always be provided. Generally this should be + /// either the target triple from the module, or the target triple of the + /// host if that does not exist. + /// \param CPU This specifies the name of the target CPU. + /// \param Features This specifies the string representation of the + /// additional target features. + MCSubtargetInfo *createMCSubtargetInfo(StringRef Triple, StringRef CPU, + StringRef Features) const { + if (!MCSubtargetInfoCtorFn) + return nullptr; + return MCSubtargetInfoCtorFn(Triple, CPU, Features); + } + + /// createTargetMachine - Create a target specific machine implementation + /// for the specified \p Triple. + /// + /// \param Triple This argument is used to determine the target machine + /// feature set; it should always be provided. Generally this should be + /// either the target triple from the module, or the target triple of the + /// host if that does not exist. + TargetMachine * + createTargetMachine(StringRef Triple, StringRef CPU, StringRef Features, + const TargetOptions &Options, + Reloc::Model RM = Reloc::Default, + CodeModel::Model CM = CodeModel::Default, + CodeGenOpt::Level OL = CodeGenOpt::Default) const { + if (!TargetMachineCtorFn) + return nullptr; + return TargetMachineCtorFn(*this, Triple, CPU, Features, Options, RM, CM, + OL); + } + + /// createMCAsmBackend - Create a target specific assembly parser. + /// + /// \param Triple The target triple string. + MCAsmBackend *createMCAsmBackend(const MCRegisterInfo &MRI, StringRef Triple, + StringRef CPU) const { + if (!MCAsmBackendCtorFn) + return nullptr; + return MCAsmBackendCtorFn(*this, MRI, Triple, CPU); + } + + /// createMCAsmParser - Create a target specific assembly parser. + /// + /// \param Parser The target independent parser implementation to use for + /// parsing and lexing. + MCTargetAsmParser *createMCAsmParser(MCSubtargetInfo &STI, + MCAsmParser &Parser, + const MCInstrInfo &MII, + const MCTargetOptions &Options) const { + if (!MCAsmParserCtorFn) + return nullptr; + return MCAsmParserCtorFn(STI, Parser, MII, Options); + } + + /// createAsmPrinter - Create a target specific assembly printer pass. This + /// takes ownership of the MCStreamer object. + AsmPrinter *createAsmPrinter(TargetMachine &TM, + std::unique_ptr<MCStreamer> &&Streamer) const { + if (!AsmPrinterCtorFn) + return nullptr; + return AsmPrinterCtorFn(TM, std::move(Streamer)); + } + + MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) const { - if (!MCCodeEmitterCtorFn) - return nullptr; - return MCCodeEmitterCtorFn(II, MRI, STI, Ctx); - } + if (!MCDisassemblerCtorFn) + return nullptr; + return MCDisassemblerCtorFn(*this, STI, Ctx); + } + + MCInstPrinter *createMCInstPrinter(const Triple &T, unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI) const { + if (!MCInstPrinterCtorFn) + return nullptr; + return MCInstPrinterCtorFn(T, SyntaxVariant, MAI, MII, MRI); + } + + /// createMCCodeEmitter - Create a target specific code emitter. + MCCodeEmitter *createMCCodeEmitter(const MCInstrInfo &II, + const MCRegisterInfo &MRI, + MCContext &Ctx) const { + if (!MCCodeEmitterCtorFn) + return nullptr; + return MCCodeEmitterCtorFn(II, MRI, Ctx); + } + + /// Create a target specific MCStreamer. + /// + /// \param T The target triple. + /// \param Ctx The target context. + /// \param TAB The target assembler backend object. Takes ownership. + /// \param OS The stream object. + /// \param Emitter The target independent assembler object.Takes ownership. + /// \param RelaxAll Relax all fixups? + MCStreamer *createMCObjectStreamer(const Triple &T, MCContext &Ctx, + MCAsmBackend &TAB, raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, + const MCSubtargetInfo &STI, bool RelaxAll, + bool DWARFMustBeAtTheEnd) const { + MCStreamer *S; + switch (T.getObjectFormat()) { + default: + llvm_unreachable("Unknown object format"); + case Triple::COFF: + assert(T.isOSWindows() && "only Windows COFF is supported"); + S = COFFStreamerCtorFn(Ctx, TAB, OS, Emitter, RelaxAll); + break; + case Triple::MachO: + if (MachOStreamerCtorFn) + S = MachOStreamerCtorFn(Ctx, TAB, OS, Emitter, RelaxAll, + DWARFMustBeAtTheEnd); + else + S = createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll, + DWARFMustBeAtTheEnd); + break; + case Triple::ELF: + if (ELFStreamerCtorFn) + S = ELFStreamerCtorFn(T, Ctx, TAB, OS, Emitter, RelaxAll); + else + S = createELFStreamer(Ctx, TAB, OS, Emitter, RelaxAll); + break; + } + if (ObjectTargetStreamerCtorFn) + ObjectTargetStreamerCtorFn(*S, STI); + return S; + } + + MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr<formatted_raw_ostream> OS, + bool IsVerboseAsm, bool UseDwarfDirectory, + MCInstPrinter *InstPrint, MCCodeEmitter *CE, + MCAsmBackend *TAB, bool ShowInst) const { + formatted_raw_ostream &OSRef = *OS; + MCStreamer *S = llvm::createAsmStreamer(Ctx, std::move(OS), IsVerboseAsm, + UseDwarfDirectory, InstPrint, CE, + TAB, ShowInst); + createAsmTargetStreamer(*S, OSRef, InstPrint, IsVerboseAsm); + return S; + } + + MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S, + formatted_raw_ostream &OS, + MCInstPrinter *InstPrint, + bool IsVerboseAsm) const { + if (AsmTargetStreamerCtorFn) + return AsmTargetStreamerCtorFn(S, OS, InstPrint, IsVerboseAsm); + return nullptr; + } + + MCStreamer *createNullStreamer(MCContext &Ctx) const { + MCStreamer *S = llvm::createNullStreamer(Ctx); + createNullTargetStreamer(*S); + return S; + } + + MCTargetStreamer *createNullTargetStreamer(MCStreamer &S) const { + if (NullTargetStreamerCtorFn) + return NullTargetStreamerCtorFn(S); + return nullptr; + } + + /// createMCRelocationInfo - Create a target specific MCRelocationInfo. + /// + /// \param TT The target triple. + /// \param Ctx The target context. + MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx) const { + MCRelocationInfoCtorTy Fn = MCRelocationInfoCtorFn + ? MCRelocationInfoCtorFn + : llvm::createMCRelocationInfo; + return Fn(TT, Ctx); + } + + /// createMCSymbolizer - Create a target specific MCSymbolizer. + /// + /// \param TT The target triple. + /// \param GetOpInfo The function to get the symbolic information for + /// operands. + /// \param SymbolLookUp The function to lookup a symbol name. + /// \param DisInfo The pointer to the block of symbolic information for above + /// call + /// back. + /// \param Ctx The target context. + /// \param RelInfo The relocation information for this target. Takes + /// ownership. + MCSymbolizer * + createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, + MCContext *Ctx, + std::unique_ptr<MCRelocationInfo> &&RelInfo) const { + MCSymbolizerCtorTy Fn = + MCSymbolizerCtorFn ? MCSymbolizerCtorFn : llvm::createMCSymbolizer; + return Fn(TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx, std::move(RelInfo)); + } + + /// @} +}; + +/// TargetRegistry - Generic interface to target specific features. +struct TargetRegistry { + // FIXME: Make this a namespace, probably just move all the Register* + // functions into Target (currently they all just set members on the Target + // anyway, and Target friends this class so those functions can... + // function). + TargetRegistry() = delete; + + class iterator + : public std::iterator<std::forward_iterator_tag, Target, ptrdiff_t> { + const Target *Current; + explicit iterator(Target *T) : Current(T) {} + friend struct TargetRegistry; - /// createMCObjectStreamer - Create a target specific MCStreamer. - /// - /// \param TT The target triple. - /// \param Ctx The target context. - /// \param TAB The target assembler backend object. Takes ownership. - /// \param _OS The stream object. - /// \param _Emitter The target independent assembler object.Takes ownership. - /// \param RelaxAll Relax all fixups? - MCStreamer *createMCObjectStreamer(StringRef TT, MCContext &Ctx, - MCAsmBackend &TAB, raw_ostream &_OS, - MCCodeEmitter *_Emitter, - const MCSubtargetInfo &STI, - bool RelaxAll) const { - if (!MCObjectStreamerCtorFn) - return nullptr; - return MCObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, STI, - RelaxAll); - } + public: + iterator() : Current(nullptr) {} - /// createAsmStreamer - Create a target specific MCStreamer. - MCStreamer *createAsmStreamer(MCContext &Ctx, - formatted_raw_ostream &OS, - bool isVerboseAsm, - bool useDwarfDirectory, - MCInstPrinter *InstPrint, - MCCodeEmitter *CE, - MCAsmBackend *TAB, - bool ShowInst) const { - if (AsmStreamerCtorFn) - return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useDwarfDirectory, - InstPrint, CE, TAB, ShowInst); - return llvm::createAsmStreamer(Ctx, OS, isVerboseAsm, useDwarfDirectory, - InstPrint, CE, TAB, ShowInst); - } + bool operator==(const iterator &x) const { return Current == x.Current; } + bool operator!=(const iterator &x) const { return !operator==(x); } - MCStreamer *createNullStreamer(MCContext &Ctx) const { - if (NullStreamerCtorFn) - return NullStreamerCtorFn(Ctx); - return llvm::createNullStreamer(Ctx); + // Iterator traversal: forward iteration only + iterator &operator++() { // Preincrement + assert(Current && "Cannot increment end iterator!"); + Current = Current->getNext(); + return *this; } - - /// createMCRelocationInfo - Create a target specific MCRelocationInfo. - /// - /// \param TT The target triple. - /// \param Ctx The target context. - MCRelocationInfo * - createMCRelocationInfo(StringRef TT, MCContext &Ctx) const { - MCRelocationInfoCtorTy Fn = MCRelocationInfoCtorFn - ? MCRelocationInfoCtorFn - : llvm::createMCRelocationInfo; - return Fn(TT, Ctx); + iterator operator++(int) { // Postincrement + iterator tmp = *this; + ++*this; + return tmp; } - /// createMCSymbolizer - Create a target specific MCSymbolizer. - /// - /// \param TT The target triple. - /// \param GetOpInfo The function to get the symbolic information for operands. - /// \param SymbolLookUp The function to lookup a symbol name. - /// \param DisInfo The pointer to the block of symbolic information for above call - /// back. - /// \param Ctx The target context. - /// \param RelInfo The relocation information for this target. Takes ownership. - MCSymbolizer * - createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp, - void *DisInfo, - MCContext *Ctx, MCRelocationInfo *RelInfo) const { - MCSymbolizerCtorTy Fn = - MCSymbolizerCtorFn ? MCSymbolizerCtorFn : llvm::createMCSymbolizer; - return Fn(TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx, RelInfo); + const Target &operator*() const { + assert(Current && "Cannot dereference end iterator!"); + return *Current; } - /// @} + const Target *operator->() const { return &operator*(); } }; - /// TargetRegistry - Generic interface to target specific features. - struct TargetRegistry { - class iterator { - const Target *Current; - explicit iterator(Target *T) : Current(T) {} - friend struct TargetRegistry; - public: - iterator() : Current(nullptr) {} - - bool operator==(const iterator &x) const { - return Current == x.Current; - } - bool operator!=(const iterator &x) const { - return !operator==(x); - } - - // Iterator traversal: forward iteration only - iterator &operator++() { // Preincrement - assert(Current && "Cannot increment end iterator!"); - Current = Current->getNext(); - return *this; - } - iterator operator++(int) { // Postincrement - iterator tmp = *this; - ++*this; - return tmp; - } - - const Target &operator*() const { - assert(Current && "Cannot dereference end iterator!"); - return *Current; - } - - const Target *operator->() const { - return &operator*(); - } - }; - - /// printRegisteredTargetsForVersion - Print the registered targets - /// appropriately for inclusion in a tool's version output. - static void printRegisteredTargetsForVersion(); - - /// @name Registry Access - /// @{ - - static iterator begin(); - - static iterator end() { return iterator(); } - - /// lookupTarget - Lookup a target based on a target triple. - /// - /// \param Triple - The triple to use for finding a target. - /// \param Error - On failure, an error string describing why no target was - /// found. - static const Target *lookupTarget(const std::string &Triple, - std::string &Error); - - /// lookupTarget - Lookup a target based on an architecture name - /// and a target triple. If the architecture name is non-empty, - /// then the lookup is done by architecture. Otherwise, the target - /// triple is used. - /// - /// \param ArchName - The architecture to use for finding a target. - /// \param TheTriple - The triple to use for finding a target. The - /// triple is updated with canonical architecture name if a lookup - /// by architecture is done. - /// \param Error - On failure, an error string describing why no target was - /// found. - static const Target *lookupTarget(const std::string &ArchName, - Triple &TheTriple, - std::string &Error); - - /// @} - /// @name Target Registration - /// @{ - - /// RegisterTarget - Register the given target. Attempts to register a - /// target which has already been registered will be ignored. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Name - The target name. This should be a static string. - /// @param ShortDesc - A short target description. This should be a static - /// string. - /// @param ArchMatchFn - The arch match checking function for this target. - /// @param HasJIT - Whether the target supports JIT code - /// generation. - static void RegisterTarget(Target &T, - const char *Name, - const char *ShortDesc, - Target::ArchMatchFnTy ArchMatchFn, - bool HasJIT = false); - - /// RegisterMCAsmInfo - Register a MCAsmInfo implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct a MCAsmInfo for the target. - static void RegisterMCAsmInfo(Target &T, Target::MCAsmInfoCtorFnTy Fn) { - T.MCAsmInfoCtorFn = Fn; - } - - /// RegisterMCCodeGenInfo - Register a MCCodeGenInfo implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct a MCCodeGenInfo for the target. - static void RegisterMCCodeGenInfo(Target &T, - Target::MCCodeGenInfoCtorFnTy Fn) { - T.MCCodeGenInfoCtorFn = Fn; - } - - /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct a MCInstrInfo for the target. - static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn) { - T.MCInstrInfoCtorFn = Fn; - } - - /// RegisterMCInstrAnalysis - Register a MCInstrAnalysis implementation for - /// the given target. - static void RegisterMCInstrAnalysis(Target &T, - Target::MCInstrAnalysisCtorFnTy Fn) { - T.MCInstrAnalysisCtorFn = Fn; - } - - /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct a MCRegisterInfo for the target. - static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn) { - T.MCRegInfoCtorFn = Fn; - } - - /// RegisterMCSubtargetInfo - Register a MCSubtargetInfo implementation for - /// the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct a MCSubtargetInfo for the target. - static void RegisterMCSubtargetInfo(Target &T, - Target::MCSubtargetInfoCtorFnTy Fn) { - T.MCSubtargetInfoCtorFn = Fn; - } - - /// RegisterTargetMachine - Register a TargetMachine implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct a TargetMachine for the target. - static void RegisterTargetMachine(Target &T, - Target::TargetMachineCtorTy Fn) { - T.TargetMachineCtorFn = Fn; - } - - /// RegisterMCAsmBackend - Register a MCAsmBackend implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an AsmBackend for the target. - static void RegisterMCAsmBackend(Target &T, Target::MCAsmBackendCtorTy Fn) { - T.MCAsmBackendCtorFn = Fn; - } - - /// RegisterMCAsmParser - Register a MCTargetAsmParser implementation for - /// the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCTargetAsmParser for the target. - static void RegisterMCAsmParser(Target &T, Target::MCAsmParserCtorTy Fn) { - T.MCAsmParserCtorFn = Fn; - } - - /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given - /// target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an AsmPrinter for the target. - static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) { - T.AsmPrinterCtorFn = Fn; - } - - /// RegisterMCDisassembler - Register a MCDisassembler implementation for - /// the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCDisassembler for the target. - static void RegisterMCDisassembler(Target &T, - Target::MCDisassemblerCtorTy Fn) { - T.MCDisassemblerCtorFn = Fn; - } + /// printRegisteredTargetsForVersion - Print the registered targets + /// appropriately for inclusion in a tool's version output. + static void printRegisteredTargetsForVersion(); - /// RegisterMCInstPrinter - Register a MCInstPrinter implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCInstPrinter for the target. - static void RegisterMCInstPrinter(Target &T, - Target::MCInstPrinterCtorTy Fn) { - T.MCInstPrinterCtorFn = Fn; - } + /// @name Registry Access + /// @{ - /// RegisterMCCodeEmitter - Register a MCCodeEmitter implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCCodeEmitter for the target. - static void RegisterMCCodeEmitter(Target &T, - Target::MCCodeEmitterCtorTy Fn) { - T.MCCodeEmitterCtorFn = Fn; - } + static iterator_range<iterator> targets(); - /// RegisterMCObjectStreamer - Register a object code MCStreamer - /// implementation for the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCStreamer for the target. - static void RegisterMCObjectStreamer(Target &T, - Target::MCObjectStreamerCtorTy Fn) { - T.MCObjectStreamerCtorFn = Fn; - } - - /// RegisterAsmStreamer - Register an assembly MCStreamer implementation - /// for the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCStreamer for the target. - static void RegisterAsmStreamer(Target &T, Target::AsmStreamerCtorTy Fn) { - T.AsmStreamerCtorFn = Fn; - } - - static void RegisterNullStreamer(Target &T, Target::NullStreamerCtorTy Fn) { - T.NullStreamerCtorFn = Fn; - } - - /// RegisterMCRelocationInfo - Register an MCRelocationInfo - /// implementation for the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCRelocationInfo for the target. - static void RegisterMCRelocationInfo(Target &T, - Target::MCRelocationInfoCtorTy Fn) { - T.MCRelocationInfoCtorFn = Fn; - } - - /// RegisterMCSymbolizer - Register an MCSymbolizer - /// implementation for the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCSymbolizer for the target. - static void RegisterMCSymbolizer(Target &T, - Target::MCSymbolizerCtorTy Fn) { - T.MCSymbolizerCtorFn = Fn; - } - - /// @} - }; - - - //===--------------------------------------------------------------------===// - - /// RegisterTarget - Helper template for registering a target, for use in the - /// target's initialization function. Usage: + /// lookupTarget - Lookup a target based on a target triple. /// + /// \param Triple - The triple to use for finding a target. + /// \param Error - On failure, an error string describing why no target was + /// found. + static const Target *lookupTarget(const std::string &Triple, + std::string &Error); + + /// lookupTarget - Lookup a target based on an architecture name + /// and a target triple. If the architecture name is non-empty, + /// then the lookup is done by architecture. Otherwise, the target + /// triple is used. /// - /// Target TheFooTarget; // The global target instance. + /// \param ArchName - The architecture to use for finding a target. + /// \param TheTriple - The triple to use for finding a target. The + /// triple is updated with canonical architecture name if a lookup + /// by architecture is done. + /// \param Error - On failure, an error string describing why no target was + /// found. + static const Target *lookupTarget(const std::string &ArchName, + Triple &TheTriple, std::string &Error); + + /// @} + /// @name Target Registration + /// @{ + + /// RegisterTarget - Register the given target. Attempts to register a + /// target which has already been registered will be ignored. /// - /// extern "C" void LLVMInitializeFooTargetInfo() { - /// RegisterTarget<Triple::foo> X(TheFooTarget, "foo", "Foo description"); - /// } - template<Triple::ArchType TargetArchType = Triple::UnknownArch, - bool HasJIT = false> - struct RegisterTarget { - RegisterTarget(Target &T, const char *Name, const char *Desc) { - TargetRegistry::RegisterTarget(T, Name, Desc, &getArchMatch, HasJIT); - } - - static bool getArchMatch(Triple::ArchType Arch) { - return Arch == TargetArchType; - } - }; - - /// RegisterMCAsmInfo - Helper template for registering a target assembly info - /// implementation. This invokes the static "Create" method on the class to - /// actually do the construction. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCAsmInfo<FooMCAsmInfo> X(TheFooTarget); - /// } - template<class MCAsmInfoImpl> - struct RegisterMCAsmInfo { - RegisterMCAsmInfo(Target &T) { - TargetRegistry::RegisterMCAsmInfo(T, &Allocator); - } - private: - static MCAsmInfo *Allocator(const MCRegisterInfo &/*MRI*/, StringRef TT) { - return new MCAsmInfoImpl(TT); - } - - }; - - /// RegisterMCAsmInfoFn - Helper template for registering a target assembly info - /// implementation. This invokes the specified function to do the - /// construction. Usage: + /// @param T - The target being registered. + /// @param Name - The target name. This should be a static string. + /// @param ShortDesc - A short target description. This should be a static + /// string. + /// @param ArchMatchFn - The arch match checking function for this target. + /// @param HasJIT - Whether the target supports JIT code + /// generation. + static void RegisterTarget(Target &T, const char *Name, const char *ShortDesc, + Target::ArchMatchFnTy ArchMatchFn, + bool HasJIT = false); + + /// RegisterMCAsmInfo - Register a MCAsmInfo implementation for the + /// given target. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCAsmInfoFn X(TheFooTarget, TheFunction); - /// } - struct RegisterMCAsmInfoFn { - RegisterMCAsmInfoFn(Target &T, Target::MCAsmInfoCtorFnTy Fn) { - TargetRegistry::RegisterMCAsmInfo(T, Fn); - } - }; - - /// RegisterMCCodeGenInfo - Helper template for registering a target codegen info - /// implementation. This invokes the static "Create" method on the class - /// to actually do the construction. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCCodeGenInfo<FooMCCodeGenInfo> X(TheFooTarget); - /// } - template<class MCCodeGenInfoImpl> - struct RegisterMCCodeGenInfo { - RegisterMCCodeGenInfo(Target &T) { - TargetRegistry::RegisterMCCodeGenInfo(T, &Allocator); - } - private: - static MCCodeGenInfo *Allocator(StringRef /*TT*/, Reloc::Model /*RM*/, - CodeModel::Model /*CM*/, - CodeGenOpt::Level /*OL*/) { - return new MCCodeGenInfoImpl(); - } - }; - - /// RegisterMCCodeGenInfoFn - Helper template for registering a target codegen - /// info implementation. This invokes the specified function to do the - /// construction. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCAsmInfo for the target. + static void RegisterMCAsmInfo(Target &T, Target::MCAsmInfoCtorFnTy Fn) { + T.MCAsmInfoCtorFn = Fn; + } + + /// RegisterMCCodeGenInfo - Register a MCCodeGenInfo implementation for the + /// given target. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCCodeGenInfoFn X(TheFooTarget, TheFunction); - /// } - struct RegisterMCCodeGenInfoFn { - RegisterMCCodeGenInfoFn(Target &T, Target::MCCodeGenInfoCtorFnTy Fn) { - TargetRegistry::RegisterMCCodeGenInfo(T, Fn); - } - }; - - /// RegisterMCInstrInfo - Helper template for registering a target instruction - /// info implementation. This invokes the static "Create" method on the class - /// to actually do the construction. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCInstrInfo<FooMCInstrInfo> X(TheFooTarget); - /// } - template<class MCInstrInfoImpl> - struct RegisterMCInstrInfo { - RegisterMCInstrInfo(Target &T) { - TargetRegistry::RegisterMCInstrInfo(T, &Allocator); - } - private: - static MCInstrInfo *Allocator() { - return new MCInstrInfoImpl(); - } - }; - - /// RegisterMCInstrInfoFn - Helper template for registering a target - /// instruction info implementation. This invokes the specified function to - /// do the construction. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCCodeGenInfo for the target. + static void RegisterMCCodeGenInfo(Target &T, + Target::MCCodeGenInfoCtorFnTy Fn) { + T.MCCodeGenInfoCtorFn = Fn; + } + + /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the + /// given target. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCInstrInfoFn X(TheFooTarget, TheFunction); - /// } - struct RegisterMCInstrInfoFn { - RegisterMCInstrInfoFn(Target &T, Target::MCInstrInfoCtorFnTy Fn) { - TargetRegistry::RegisterMCInstrInfo(T, Fn); - } - }; - - /// RegisterMCInstrAnalysis - Helper template for registering a target - /// instruction analyzer implementation. This invokes the static "Create" - /// method on the class to actually do the construction. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCInstrAnalysis<FooMCInstrAnalysis> X(TheFooTarget); - /// } - template<class MCInstrAnalysisImpl> - struct RegisterMCInstrAnalysis { - RegisterMCInstrAnalysis(Target &T) { - TargetRegistry::RegisterMCInstrAnalysis(T, &Allocator); - } - private: - static MCInstrAnalysis *Allocator(const MCInstrInfo *Info) { - return new MCInstrAnalysisImpl(Info); - } - }; - - /// RegisterMCInstrAnalysisFn - Helper template for registering a target - /// instruction analyzer implementation. This invokes the specified function - /// to do the construction. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCInstrInfo for the target. + static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn) { + T.MCInstrInfoCtorFn = Fn; + } + + /// RegisterMCInstrAnalysis - Register a MCInstrAnalysis implementation for + /// the given target. + static void RegisterMCInstrAnalysis(Target &T, + Target::MCInstrAnalysisCtorFnTy Fn) { + T.MCInstrAnalysisCtorFn = Fn; + } + + /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the + /// given target. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCInstrAnalysisFn X(TheFooTarget, TheFunction); - /// } - struct RegisterMCInstrAnalysisFn { - RegisterMCInstrAnalysisFn(Target &T, Target::MCInstrAnalysisCtorFnTy Fn) { - TargetRegistry::RegisterMCInstrAnalysis(T, Fn); - } - }; - - /// RegisterMCRegInfo - Helper template for registering a target register info - /// implementation. This invokes the static "Create" method on the class to - /// actually do the construction. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCRegInfo<FooMCRegInfo> X(TheFooTarget); - /// } - template<class MCRegisterInfoImpl> - struct RegisterMCRegInfo { - RegisterMCRegInfo(Target &T) { - TargetRegistry::RegisterMCRegInfo(T, &Allocator); - } - private: - static MCRegisterInfo *Allocator(StringRef /*TT*/) { - return new MCRegisterInfoImpl(); - } - }; - - /// RegisterMCRegInfoFn - Helper template for registering a target register - /// info implementation. This invokes the specified function to do the - /// construction. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCRegisterInfo for the target. + static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn) { + T.MCRegInfoCtorFn = Fn; + } + + /// RegisterMCSubtargetInfo - Register a MCSubtargetInfo implementation for + /// the given target. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCRegInfoFn X(TheFooTarget, TheFunction); - /// } - struct RegisterMCRegInfoFn { - RegisterMCRegInfoFn(Target &T, Target::MCRegInfoCtorFnTy Fn) { - TargetRegistry::RegisterMCRegInfo(T, Fn); - } - }; - - /// RegisterMCSubtargetInfo - Helper template for registering a target - /// subtarget info implementation. This invokes the static "Create" method - /// on the class to actually do the construction. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCSubtargetInfo<FooMCSubtargetInfo> X(TheFooTarget); - /// } - template<class MCSubtargetInfoImpl> - struct RegisterMCSubtargetInfo { - RegisterMCSubtargetInfo(Target &T) { - TargetRegistry::RegisterMCSubtargetInfo(T, &Allocator); - } - private: - static MCSubtargetInfo *Allocator(StringRef /*TT*/, StringRef /*CPU*/, - StringRef /*FS*/) { - return new MCSubtargetInfoImpl(); - } - }; - - /// RegisterMCSubtargetInfoFn - Helper template for registering a target - /// subtarget info implementation. This invokes the specified function to - /// do the construction. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCSubtargetInfo for the target. + static void RegisterMCSubtargetInfo(Target &T, + Target::MCSubtargetInfoCtorFnTy Fn) { + T.MCSubtargetInfoCtorFn = Fn; + } + + /// RegisterTargetMachine - Register a TargetMachine implementation for the + /// given target. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCSubtargetInfoFn X(TheFooTarget, TheFunction); - /// } - struct RegisterMCSubtargetInfoFn { - RegisterMCSubtargetInfoFn(Target &T, Target::MCSubtargetInfoCtorFnTy Fn) { - TargetRegistry::RegisterMCSubtargetInfo(T, Fn); - } - }; - - /// RegisterTargetMachine - Helper template for registering a target machine - /// implementation, for use in the target machine initialization - /// function. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterTargetMachine<FooTargetMachine> X(TheFooTarget); - /// } - template<class TargetMachineImpl> - struct RegisterTargetMachine { - RegisterTargetMachine(Target &T) { - TargetRegistry::RegisterTargetMachine(T, &Allocator); - } - - private: - static TargetMachine *Allocator(const Target &T, StringRef TT, - StringRef CPU, StringRef FS, - const TargetOptions &Options, - Reloc::Model RM, - CodeModel::Model CM, - CodeGenOpt::Level OL) { - return new TargetMachineImpl(T, TT, CPU, FS, Options, RM, CM, OL); - } - }; - - /// RegisterMCAsmBackend - Helper template for registering a target specific - /// assembler backend. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct a TargetMachine for the target. + static void RegisterTargetMachine(Target &T, Target::TargetMachineCtorTy Fn) { + T.TargetMachineCtorFn = Fn; + } + + /// RegisterMCAsmBackend - Register a MCAsmBackend implementation for the + /// given target. /// - /// extern "C" void LLVMInitializeFooMCAsmBackend() { - /// extern Target TheFooTarget; - /// RegisterMCAsmBackend<FooAsmLexer> X(TheFooTarget); - /// } - template<class MCAsmBackendImpl> - struct RegisterMCAsmBackend { - RegisterMCAsmBackend(Target &T) { - TargetRegistry::RegisterMCAsmBackend(T, &Allocator); - } - - private: - static MCAsmBackend *Allocator(const Target &T, - const MCRegisterInfo &MRI, - StringRef Triple, StringRef CPU) { - return new MCAsmBackendImpl(T, MRI, Triple, CPU); - } - }; - - /// RegisterMCAsmParser - Helper template for registering a target specific - /// assembly parser, for use in the target machine initialization - /// function. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooMCAsmParser() { - /// extern Target TheFooTarget; - /// RegisterMCAsmParser<FooAsmParser> X(TheFooTarget); - /// } - template<class MCAsmParserImpl> - struct RegisterMCAsmParser { - RegisterMCAsmParser(Target &T) { - TargetRegistry::RegisterMCAsmParser(T, &Allocator); - } - - private: - static MCTargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P, - const MCInstrInfo &MII, - const MCTargetOptions &Options) { - return new MCAsmParserImpl(STI, P, MII, Options); - } - }; - - /// RegisterAsmPrinter - Helper template for registering a target specific - /// assembly printer, for use in the target machine initialization - /// function. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct an AsmBackend for the target. + static void RegisterMCAsmBackend(Target &T, Target::MCAsmBackendCtorTy Fn) { + T.MCAsmBackendCtorFn = Fn; + } + + /// RegisterMCAsmParser - Register a MCTargetAsmParser implementation for + /// the given target. /// - /// extern "C" void LLVMInitializeFooAsmPrinter() { - /// extern Target TheFooTarget; - /// RegisterAsmPrinter<FooAsmPrinter> X(TheFooTarget); - /// } - template<class AsmPrinterImpl> - struct RegisterAsmPrinter { - RegisterAsmPrinter(Target &T) { - TargetRegistry::RegisterAsmPrinter(T, &Allocator); - } - - private: - static AsmPrinter *Allocator(TargetMachine &TM, MCStreamer &Streamer) { - return new AsmPrinterImpl(TM, Streamer); - } - }; - - /// RegisterMCCodeEmitter - Helper template for registering a target specific - /// machine code emitter, for use in the target initialization - /// function. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooMCCodeEmitter() { - /// extern Target TheFooTarget; - /// RegisterMCCodeEmitter<FooCodeEmitter> X(TheFooTarget); - /// } - template<class MCCodeEmitterImpl> - struct RegisterMCCodeEmitter { - RegisterMCCodeEmitter(Target &T) { - TargetRegistry::RegisterMCCodeEmitter(T, &Allocator); - } - - private: - static MCCodeEmitter *Allocator(const MCInstrInfo &/*II*/, - const MCRegisterInfo &/*MRI*/, - const MCSubtargetInfo &/*STI*/, - MCContext &/*Ctx*/) { - return new MCCodeEmitterImpl(); - } - }; - + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCTargetAsmParser for the target. + static void RegisterMCAsmParser(Target &T, Target::MCAsmParserCtorTy Fn) { + T.MCAsmParserCtorFn = Fn; + } + + /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given + /// target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an AsmPrinter for the target. + static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) { + T.AsmPrinterCtorFn = Fn; + } + + /// RegisterMCDisassembler - Register a MCDisassembler implementation for + /// the given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCDisassembler for the target. + static void RegisterMCDisassembler(Target &T, + Target::MCDisassemblerCtorTy Fn) { + T.MCDisassemblerCtorFn = Fn; + } + + /// RegisterMCInstPrinter - Register a MCInstPrinter implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCInstPrinter for the target. + static void RegisterMCInstPrinter(Target &T, Target::MCInstPrinterCtorTy Fn) { + T.MCInstPrinterCtorFn = Fn; + } + + /// RegisterMCCodeEmitter - Register a MCCodeEmitter implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCCodeEmitter for the target. + static void RegisterMCCodeEmitter(Target &T, Target::MCCodeEmitterCtorTy Fn) { + T.MCCodeEmitterCtorFn = Fn; + } + + static void RegisterCOFFStreamer(Target &T, Target::COFFStreamerCtorTy Fn) { + T.COFFStreamerCtorFn = Fn; + } + + static void RegisterMachOStreamer(Target &T, Target::MachOStreamerCtorTy Fn) { + T.MachOStreamerCtorFn = Fn; + } + + static void RegisterELFStreamer(Target &T, Target::ELFStreamerCtorTy Fn) { + T.ELFStreamerCtorFn = Fn; + } + + static void RegisterNullTargetStreamer(Target &T, + Target::NullTargetStreamerCtorTy Fn) { + T.NullTargetStreamerCtorFn = Fn; + } + + static void RegisterAsmTargetStreamer(Target &T, + Target::AsmTargetStreamerCtorTy Fn) { + T.AsmTargetStreamerCtorFn = Fn; + } + + static void + RegisterObjectTargetStreamer(Target &T, + Target::ObjectTargetStreamerCtorTy Fn) { + T.ObjectTargetStreamerCtorFn = Fn; + } + + /// RegisterMCRelocationInfo - Register an MCRelocationInfo + /// implementation for the given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCRelocationInfo for the target. + static void RegisterMCRelocationInfo(Target &T, + Target::MCRelocationInfoCtorTy Fn) { + T.MCRelocationInfoCtorFn = Fn; + } + + /// RegisterMCSymbolizer - Register an MCSymbolizer + /// implementation for the given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCSymbolizer for the target. + static void RegisterMCSymbolizer(Target &T, Target::MCSymbolizerCtorTy Fn) { + T.MCSymbolizerCtorFn = Fn; + } + + /// @} +}; + +//===--------------------------------------------------------------------===// + +/// RegisterTarget - Helper template for registering a target, for use in the +/// target's initialization function. Usage: +/// +/// +/// Target TheFooTarget; // The global target instance. +/// +/// extern "C" void LLVMInitializeFooTargetInfo() { +/// RegisterTarget<Triple::foo> X(TheFooTarget, "foo", "Foo description"); +/// } +template <Triple::ArchType TargetArchType = Triple::UnknownArch, + bool HasJIT = false> +struct RegisterTarget { + RegisterTarget(Target &T, const char *Name, const char *Desc) { + TargetRegistry::RegisterTarget(T, Name, Desc, &getArchMatch, HasJIT); + } + + static bool getArchMatch(Triple::ArchType Arch) { + return Arch == TargetArchType; + } +}; + +/// RegisterMCAsmInfo - Helper template for registering a target assembly info +/// implementation. This invokes the static "Create" method on the class to +/// actually do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCAsmInfo<FooMCAsmInfo> X(TheFooTarget); +/// } +template <class MCAsmInfoImpl> struct RegisterMCAsmInfo { + RegisterMCAsmInfo(Target &T) { + TargetRegistry::RegisterMCAsmInfo(T, &Allocator); + } + +private: + static MCAsmInfo *Allocator(const MCRegisterInfo & /*MRI*/, StringRef TT) { + return new MCAsmInfoImpl(TT); + } +}; + +/// RegisterMCAsmInfoFn - Helper template for registering a target assembly info +/// implementation. This invokes the specified function to do the +/// construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCAsmInfoFn X(TheFooTarget, TheFunction); +/// } +struct RegisterMCAsmInfoFn { + RegisterMCAsmInfoFn(Target &T, Target::MCAsmInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCAsmInfo(T, Fn); + } +}; + +/// RegisterMCCodeGenInfo - Helper template for registering a target codegen +/// info +/// implementation. This invokes the static "Create" method on the class +/// to actually do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCCodeGenInfo<FooMCCodeGenInfo> X(TheFooTarget); +/// } +template <class MCCodeGenInfoImpl> struct RegisterMCCodeGenInfo { + RegisterMCCodeGenInfo(Target &T) { + TargetRegistry::RegisterMCCodeGenInfo(T, &Allocator); + } + +private: + static MCCodeGenInfo *Allocator(StringRef /*TT*/, Reloc::Model /*RM*/, + CodeModel::Model /*CM*/, + CodeGenOpt::Level /*OL*/) { + return new MCCodeGenInfoImpl(); + } +}; + +/// RegisterMCCodeGenInfoFn - Helper template for registering a target codegen +/// info implementation. This invokes the specified function to do the +/// construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCCodeGenInfoFn X(TheFooTarget, TheFunction); +/// } +struct RegisterMCCodeGenInfoFn { + RegisterMCCodeGenInfoFn(Target &T, Target::MCCodeGenInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCCodeGenInfo(T, Fn); + } +}; + +/// RegisterMCInstrInfo - Helper template for registering a target instruction +/// info implementation. This invokes the static "Create" method on the class +/// to actually do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCInstrInfo<FooMCInstrInfo> X(TheFooTarget); +/// } +template <class MCInstrInfoImpl> struct RegisterMCInstrInfo { + RegisterMCInstrInfo(Target &T) { + TargetRegistry::RegisterMCInstrInfo(T, &Allocator); + } + +private: + static MCInstrInfo *Allocator() { return new MCInstrInfoImpl(); } +}; + +/// RegisterMCInstrInfoFn - Helper template for registering a target +/// instruction info implementation. This invokes the specified function to +/// do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCInstrInfoFn X(TheFooTarget, TheFunction); +/// } +struct RegisterMCInstrInfoFn { + RegisterMCInstrInfoFn(Target &T, Target::MCInstrInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCInstrInfo(T, Fn); + } +}; + +/// RegisterMCInstrAnalysis - Helper template for registering a target +/// instruction analyzer implementation. This invokes the static "Create" +/// method on the class to actually do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCInstrAnalysis<FooMCInstrAnalysis> X(TheFooTarget); +/// } +template <class MCInstrAnalysisImpl> struct RegisterMCInstrAnalysis { + RegisterMCInstrAnalysis(Target &T) { + TargetRegistry::RegisterMCInstrAnalysis(T, &Allocator); + } + +private: + static MCInstrAnalysis *Allocator(const MCInstrInfo *Info) { + return new MCInstrAnalysisImpl(Info); + } +}; + +/// RegisterMCInstrAnalysisFn - Helper template for registering a target +/// instruction analyzer implementation. This invokes the specified function +/// to do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCInstrAnalysisFn X(TheFooTarget, TheFunction); +/// } +struct RegisterMCInstrAnalysisFn { + RegisterMCInstrAnalysisFn(Target &T, Target::MCInstrAnalysisCtorFnTy Fn) { + TargetRegistry::RegisterMCInstrAnalysis(T, Fn); + } +}; + +/// RegisterMCRegInfo - Helper template for registering a target register info +/// implementation. This invokes the static "Create" method on the class to +/// actually do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCRegInfo<FooMCRegInfo> X(TheFooTarget); +/// } +template <class MCRegisterInfoImpl> struct RegisterMCRegInfo { + RegisterMCRegInfo(Target &T) { + TargetRegistry::RegisterMCRegInfo(T, &Allocator); + } + +private: + static MCRegisterInfo *Allocator(StringRef /*TT*/) { + return new MCRegisterInfoImpl(); + } +}; + +/// RegisterMCRegInfoFn - Helper template for registering a target register +/// info implementation. This invokes the specified function to do the +/// construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCRegInfoFn X(TheFooTarget, TheFunction); +/// } +struct RegisterMCRegInfoFn { + RegisterMCRegInfoFn(Target &T, Target::MCRegInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCRegInfo(T, Fn); + } +}; + +/// RegisterMCSubtargetInfo - Helper template for registering a target +/// subtarget info implementation. This invokes the static "Create" method +/// on the class to actually do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCSubtargetInfo<FooMCSubtargetInfo> X(TheFooTarget); +/// } +template <class MCSubtargetInfoImpl> struct RegisterMCSubtargetInfo { + RegisterMCSubtargetInfo(Target &T) { + TargetRegistry::RegisterMCSubtargetInfo(T, &Allocator); + } + +private: + static MCSubtargetInfo *Allocator(StringRef /*TT*/, StringRef /*CPU*/, + StringRef /*FS*/) { + return new MCSubtargetInfoImpl(); + } +}; + +/// RegisterMCSubtargetInfoFn - Helper template for registering a target +/// subtarget info implementation. This invokes the specified function to +/// do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCSubtargetInfoFn X(TheFooTarget, TheFunction); +/// } +struct RegisterMCSubtargetInfoFn { + RegisterMCSubtargetInfoFn(Target &T, Target::MCSubtargetInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCSubtargetInfo(T, Fn); + } +}; + +/// RegisterTargetMachine - Helper template for registering a target machine +/// implementation, for use in the target machine initialization +/// function. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterTargetMachine<FooTargetMachine> X(TheFooTarget); +/// } +template <class TargetMachineImpl> struct RegisterTargetMachine { + RegisterTargetMachine(Target &T) { + TargetRegistry::RegisterTargetMachine(T, &Allocator); + } + +private: + static TargetMachine *Allocator(const Target &T, StringRef TT, StringRef CPU, + StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL) { + return new TargetMachineImpl(T, TT, CPU, FS, Options, RM, CM, OL); + } +}; + +/// RegisterMCAsmBackend - Helper template for registering a target specific +/// assembler backend. Usage: +/// +/// extern "C" void LLVMInitializeFooMCAsmBackend() { +/// extern Target TheFooTarget; +/// RegisterMCAsmBackend<FooAsmLexer> X(TheFooTarget); +/// } +template <class MCAsmBackendImpl> struct RegisterMCAsmBackend { + RegisterMCAsmBackend(Target &T) { + TargetRegistry::RegisterMCAsmBackend(T, &Allocator); + } + +private: + static MCAsmBackend *Allocator(const Target &T, const MCRegisterInfo &MRI, + StringRef Triple, StringRef CPU) { + return new MCAsmBackendImpl(T, MRI, Triple, CPU); + } +}; + +/// RegisterMCAsmParser - Helper template for registering a target specific +/// assembly parser, for use in the target machine initialization +/// function. Usage: +/// +/// extern "C" void LLVMInitializeFooMCAsmParser() { +/// extern Target TheFooTarget; +/// RegisterMCAsmParser<FooAsmParser> X(TheFooTarget); +/// } +template <class MCAsmParserImpl> struct RegisterMCAsmParser { + RegisterMCAsmParser(Target &T) { + TargetRegistry::RegisterMCAsmParser(T, &Allocator); + } + +private: + static MCTargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P, + const MCInstrInfo &MII, + const MCTargetOptions &Options) { + return new MCAsmParserImpl(STI, P, MII, Options); + } +}; + +/// RegisterAsmPrinter - Helper template for registering a target specific +/// assembly printer, for use in the target machine initialization +/// function. Usage: +/// +/// extern "C" void LLVMInitializeFooAsmPrinter() { +/// extern Target TheFooTarget; +/// RegisterAsmPrinter<FooAsmPrinter> X(TheFooTarget); +/// } +template <class AsmPrinterImpl> struct RegisterAsmPrinter { + RegisterAsmPrinter(Target &T) { + TargetRegistry::RegisterAsmPrinter(T, &Allocator); + } + +private: + static AsmPrinter *Allocator(TargetMachine &TM, + std::unique_ptr<MCStreamer> &&Streamer) { + return new AsmPrinterImpl(TM, std::move(Streamer)); + } +}; + +/// RegisterMCCodeEmitter - Helper template for registering a target specific +/// machine code emitter, for use in the target initialization +/// function. Usage: +/// +/// extern "C" void LLVMInitializeFooMCCodeEmitter() { +/// extern Target TheFooTarget; +/// RegisterMCCodeEmitter<FooCodeEmitter> X(TheFooTarget); +/// } +template <class MCCodeEmitterImpl> struct RegisterMCCodeEmitter { + RegisterMCCodeEmitter(Target &T) { + TargetRegistry::RegisterMCCodeEmitter(T, &Allocator); + } + +private: + static MCCodeEmitter *Allocator(const MCInstrInfo & /*II*/, + const MCRegisterInfo & /*MRI*/, + MCContext & /*Ctx*/) { + return new MCCodeEmitterImpl(); + } +}; } #endif diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h index 45c182831b2a..2cd30e2aaf32 100644 --- a/include/llvm/Support/Timer.h +++ b/include/llvm/Support/Timer.h @@ -11,7 +11,6 @@ #define LLVM_SUPPORT_TIMER_H #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include <cassert> #include <string> @@ -126,7 +125,7 @@ private: /// class TimeRegion { Timer *T; - TimeRegion(const TimeRegion &) LLVM_DELETED_FUNCTION; + TimeRegion(const TimeRegion &) = delete; public: explicit TimeRegion(Timer &t) : T(&t) { T->startTimer(); @@ -164,8 +163,8 @@ class TimerGroup { std::vector<std::pair<TimeRecord, std::string> > TimersToPrint; TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's. - TimerGroup(const TimerGroup &TG) LLVM_DELETED_FUNCTION; - void operator=(const TimerGroup &TG) LLVM_DELETED_FUNCTION; + TimerGroup(const TimerGroup &TG) = delete; + void operator=(const TimerGroup &TG) = delete; public: explicit TimerGroup(StringRef name); ~TimerGroup(); diff --git a/include/llvm/Support/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h index d98e7bbd51d4..1be26c2cb58b 100644 --- a/include/llvm/Support/ToolOutputFile.h +++ b/include/llvm/Support/ToolOutputFile.h @@ -18,16 +18,16 @@ namespace llvm { -/// tool_output_file - This class contains a raw_fd_ostream and adds a -/// few extra features commonly needed for compiler-like tool output files: +/// This class contains a raw_fd_ostream and adds a few extra features commonly +/// needed for compiler-like tool output files: /// - The file is automatically deleted if the process is killed. /// - The file is automatically deleted when the tool_output_file /// object is destroyed unless the client calls keep(). class tool_output_file { - /// Installer - This class is declared before the raw_fd_ostream so that - /// it is constructed before the raw_fd_ostream is constructed and - /// destructed after the raw_fd_ostream is destructed. It installs - /// cleanups in its constructor and uninstalls them in its destructor. + /// This class is declared before the raw_fd_ostream so that it is constructed + /// before the raw_fd_ostream is constructed and destructed after the + /// raw_fd_ostream is destructed. It installs cleanups in its constructor and + /// uninstalls them in its destructor. class CleanupInstaller { /// The name of the file. std::string Filename; @@ -39,8 +39,7 @@ class tool_output_file { ~CleanupInstaller(); } Installer; - /// OS - The contained stream. This is intentionally declared after - /// Installer. + /// The contained stream. This is intentionally declared after Installer. raw_fd_ostream OS; public: @@ -51,11 +50,11 @@ public: tool_output_file(StringRef Filename, int FD); - /// os - Return the contained raw_fd_ostream. + /// Return the contained raw_fd_ostream. raw_fd_ostream &os() { return OS; } - /// keep - Indicate that the tool's job wrt this output file has been - /// successful and the file should not be deleted. + /// Indicate that the tool's job wrt this output file has been successful and + /// the file should not be deleted. void keep() { Installer.Keep = true; } }; diff --git a/include/llvm/Support/UnicodeCharRanges.h b/include/llvm/Support/UnicodeCharRanges.h index 79137bf35363..9f738dff1107 100644 --- a/include/llvm/Support/UnicodeCharRanges.h +++ b/include/llvm/Support/UnicodeCharRanges.h @@ -50,9 +50,13 @@ public: /// the UnicodeCharSet instance, and should not change. Array is validated by /// the constructor, so it makes sense to create as few UnicodeCharSet /// instances per each array of ranges, as possible. +#ifdef NDEBUG + LLVM_CONSTEXPR UnicodeCharSet(CharRanges Ranges) : Ranges(Ranges) {} +#else UnicodeCharSet(CharRanges Ranges) : Ranges(Ranges) { assert(rangesAreValid()); } +#endif /// \brief Returns true if the character set contains the Unicode code point /// \p C. diff --git a/include/llvm/Support/UniqueLock.h b/include/llvm/Support/UniqueLock.h index 5a4c273e83e2..529284d3868b 100644 --- a/include/llvm/Support/UniqueLock.h +++ b/include/llvm/Support/UniqueLock.h @@ -29,8 +29,8 @@ namespace llvm { MutexT *M; bool locked; - unique_lock(const unique_lock &) LLVM_DELETED_FUNCTION; - void operator=(const unique_lock &) LLVM_DELETED_FUNCTION; + unique_lock(const unique_lock &) = delete; + void operator=(const unique_lock &) = delete; public: unique_lock() : M(nullptr), locked(false) {} explicit unique_lock(MutexT &m) : M(&m), locked(true) { M->lock(); } diff --git a/include/llvm/Support/Watchdog.h b/include/llvm/Support/Watchdog.h index b58496b2fb8e..01e1d926eb95 100644 --- a/include/llvm/Support/Watchdog.h +++ b/include/llvm/Support/Watchdog.h @@ -29,8 +29,8 @@ namespace llvm { ~Watchdog(); private: // Noncopyable. - Watchdog(const Watchdog &other) LLVM_DELETED_FUNCTION; - Watchdog &operator=(const Watchdog &other) LLVM_DELETED_FUNCTION; + Watchdog(const Watchdog &other) = delete; + Watchdog &operator=(const Watchdog &other) = delete; }; } } diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h index de6e6544e25b..0fbb7d2e6c7e 100644 --- a/include/llvm/Support/YAMLParser.h +++ b/include/llvm/Support/YAMLParser.h @@ -38,19 +38,18 @@ #ifndef LLVM_SUPPORT_YAMLPARSER_H #define LLVM_SUPPORT_YAMLPARSER_H -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SMLoc.h" #include <limits> #include <map> #include <utility> namespace llvm { +class MemoryBufferRef; class SourceMgr; -class raw_ostream; class Twine; +class raw_ostream; namespace yaml { @@ -77,9 +76,9 @@ std::string escape(StringRef Input); class Stream { public: /// \brief This keeps a reference to the string referenced by \p Input. - Stream(StringRef Input, SourceMgr &); + Stream(StringRef Input, SourceMgr &, bool ShowColors = true); - Stream(MemoryBufferRef InputBuffer, SourceMgr &); + Stream(MemoryBufferRef InputBuffer, SourceMgr &, bool ShowColors = true); ~Stream(); document_iterator begin(); @@ -108,6 +107,7 @@ public: enum NodeKind { NK_Null, NK_Scalar, + NK_BlockScalar, NK_KeyValue, NK_Mapping, NK_Sequence, @@ -159,7 +159,7 @@ protected: void operator delete(void *) throw() {} - virtual ~Node() {} + ~Node() = default; private: unsigned int TypeID; @@ -172,7 +172,7 @@ private: /// /// Example: /// !!null null -class NullNode : public Node { +class NullNode final : public Node { void anchor() override; public: @@ -187,7 +187,7 @@ public: /// /// Example: /// Adena -class ScalarNode : public Node { +class ScalarNode final : public Node { void anchor() override; public: @@ -223,6 +223,36 @@ private: SmallVectorImpl<char> &Storage) const; }; +/// \brief A block scalar node is an opaque datum that can be presented as a +/// series of zero or more Unicode scalar values. +/// +/// Example: +/// | +/// Hello +/// World +class BlockScalarNode final : public Node { + void anchor() override; + +public: + BlockScalarNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, + StringRef Value, StringRef RawVal) + : Node(NK_BlockScalar, D, Anchor, Tag), Value(Value) { + SMLoc Start = SMLoc::getFromPointer(RawVal.begin()); + SMLoc End = SMLoc::getFromPointer(RawVal.end()); + SourceRange = SMRange(Start, End); + } + + /// \brief Gets the value of this node as a StringRef. + StringRef getValue() const { return Value; } + + static inline bool classof(const Node *N) { + return N->getType() == NK_BlockScalar; + } + +private: + StringRef Value; +}; + /// \brief A key and value pair. While not technically a Node under the YAML /// representation graph, it is easier to treat them this way. /// @@ -230,7 +260,7 @@ private: /// /// Example: /// Section: .text -class KeyValueNode : public Node { +class KeyValueNode final : public Node { void anchor() override; public: @@ -254,7 +284,8 @@ public: void skip() override { getKey()->skip(); - getValue()->skip(); + if (Node *Val = getValue()) + Val->skip(); } static inline bool classof(const Node *N) { @@ -340,7 +371,7 @@ template <class CollectionType> void skip(CollectionType &C) { /// Example: /// Name: _main /// Scope: Global -class MappingNode : public Node { +class MappingNode final : public Node { void anchor() override; public: @@ -387,7 +418,7 @@ private: /// Example: /// - Hello /// - World -class SequenceNode : public Node { +class SequenceNode final : public Node { void anchor() override; public: @@ -440,7 +471,7 @@ private: /// /// Example: /// *AnchorName -class AliasNode : public Node { +class AliasNode final : public Node { void anchor() override; public: diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index 023dcee7d54c..3bdff2091809 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -46,6 +46,10 @@ struct MappingTraits { // static void mapping(IO &io, T &fields); // Optionally may provide: // static StringRef validate(IO &io, T &fields); + // + // The optional flow flag will cause generated YAML to use a flow mapping + // (e.g. { a: 0, b: 1 }): + // static const bool flow = true; }; @@ -117,6 +121,35 @@ struct ScalarTraits { }; +/// This class should be specialized by type that requires custom conversion +/// to/from a YAML literal block scalar. For example: +/// +/// template <> +/// struct BlockScalarTraits<MyType> { +/// static void output(const MyType &Value, void*, llvm::raw_ostream &Out) +/// { +/// // stream out custom formatting +/// Out << Val; +/// } +/// static StringRef input(StringRef Scalar, void*, MyType &Value) { +/// // parse scalar and set `value` +/// // return empty string on success, or error string +/// return StringRef(); +/// } +/// }; +template <typename T> +struct BlockScalarTraits { + // Must provide: + // + // Function to write the value as a string: + // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out); + // + // Function to convert a string to a value. Returns the empty + // StringRef on success or an error string if string is malformed: + // static StringRef input(StringRef Scalar, void *ctxt, T &Value); +}; + + /// This class should be specialized by any type that needs to be converted /// to/from a YAML sequence. For example: /// @@ -220,6 +253,26 @@ public: }; +// Test if BlockScalarTraits<T> is defined on type T. +template <class T> +struct has_BlockScalarTraits +{ + typedef StringRef (*Signature_input)(StringRef, void *, T &); + typedef void (*Signature_output)(const T &, void *, llvm::raw_ostream &); + + template <typename U> + static char test(SameType<Signature_input, &U::input> *, + SameType<Signature_output, &U::output> *); + + template <typename U> + static double test(...); + +public: + static bool const value = + (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1); +}; + + // Test if MappingTraits<T> is defined on type T. template <class T> struct has_MappingTraits @@ -406,6 +459,7 @@ struct missingTraits : public std::integral_constant<bool, !has_ScalarEnumerationTraits<T>::value && !has_ScalarBitSetTraits<T>::value && !has_ScalarTraits<T>::value + && !has_BlockScalarTraits<T>::value && !has_MappingTraits<T>::value && !has_SequenceTraits<T>::value && !has_DocumentListTraits<T>::value > {}; @@ -445,8 +499,12 @@ public: virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0; virtual void postflightKey(void*) = 0; + virtual void beginFlowMapping() = 0; + virtual void endFlowMapping() = 0; + virtual void beginEnumScalar() = 0; virtual bool matchEnumScalar(const char*, bool) = 0; + virtual bool matchEnumFallback() = 0; virtual void endEnumScalar() = 0; virtual bool beginBitSetScalar(bool &) = 0; @@ -454,6 +512,7 @@ public: virtual void endBitSetScalar() = 0; virtual void scalarString(StringRef &, bool) = 0; + virtual void blockScalarString(StringRef &) = 0; virtual void setError(const Twine &) = 0; @@ -472,6 +531,16 @@ public: } } + template <typename FBT, typename T> + void enumFallback(T &Val) { + if ( matchEnumFallback() ) { + // FIXME: Force integral conversion to allow strong typedefs to convert. + FBT Res = (uint64_t)Val; + yamlize(*this, Res, true); + Val = (uint64_t)Res; + } + } + template <typename T> void bitSetCase(T &Val, const char* Str, const T ConstVal) { if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { @@ -532,7 +601,7 @@ public: void mapOptional(const char* Key, T& Val, const T& Default) { this->processKeyWithDefault(Key, Val, Default, false); } - + private: template <typename T> void processKeyWithDefault(const char *Key, Optional<T> &Val, @@ -628,11 +697,32 @@ yamlize(IO &io, T &Val, bool) { } } +template <typename T> +typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type +yamlize(IO &YamlIO, T &Val, bool) { + if (YamlIO.outputting()) { + std::string Storage; + llvm::raw_string_ostream Buffer(Storage); + BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer); + StringRef Str = Buffer.str(); + YamlIO.blockScalarString(Str); + } else { + StringRef Str; + YamlIO.blockScalarString(Str); + StringRef Result = + BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val); + if (!Result.empty()) + YamlIO.setError(llvm::Twine(Result)); + } +} template<typename T> typename std::enable_if<validatedMappingTraits<T>::value, void>::type yamlize(IO &io, T &Val, bool) { - io.beginMapping(); + if (has_FlowTraits<MappingTraits<T>>::value) + io.beginFlowMapping(); + else + io.beginMapping(); if (io.outputting()) { StringRef Err = MappingTraits<T>::validate(io, Val); if (!Err.empty()) { @@ -646,15 +736,24 @@ yamlize(IO &io, T &Val, bool) { if (!Err.empty()) io.setError(Err); } - io.endMapping(); + if (has_FlowTraits<MappingTraits<T>>::value) + io.endFlowMapping(); + else + io.endMapping(); } template<typename T> typename std::enable_if<unvalidatedMappingTraits<T>::value, void>::type yamlize(IO &io, T &Val, bool) { - io.beginMapping(); - MappingTraits<T>::mapping(io, Val); - io.endMapping(); + if (has_FlowTraits<MappingTraits<T>>::value) { + io.beginFlowMapping(); + MappingTraits<T>::mapping(io, Val); + io.endFlowMapping(); + } else { + io.beginMapping(); + MappingTraits<T>::mapping(io, Val); + io.endMapping(); + } } template<typename T> @@ -706,7 +805,7 @@ struct ScalarTraits<StringRef> { static StringRef input(StringRef, void*, StringRef &); static bool mustQuote(StringRef S) { return needsQuotes(S); } }; - + template<> struct ScalarTraits<std::string> { static void output(const std::string &, void*, llvm::raw_ostream &); @@ -877,7 +976,7 @@ public: void *Ctxt = nullptr, SourceMgr::DiagHandlerTy DiagHandler = nullptr, void *DiagHandlerCtxt = nullptr); - ~Input(); + ~Input() override; // Check if there was an syntax or semantic error during parsing. std::error_code error(); @@ -889,6 +988,8 @@ private: void endMapping() override; bool preflightKey(const char *, bool, bool, bool &, void *&) override; void postflightKey(void *) override; + void beginFlowMapping() override; + void endFlowMapping() override; unsigned beginSequence() override; void endSequence() override; bool preflightElement(unsigned index, void *&) override; @@ -899,11 +1000,13 @@ private: void endFlowSequence() override; void beginEnumScalar() override; bool matchEnumScalar(const char*, bool) override; + bool matchEnumFallback() override; void endEnumScalar() override; bool beginBitSetScalar(bool &) override; bool bitSetMatch(const char *, bool ) override; void endBitSetScalar() override; void scalarString(StringRef &, bool) override; + void blockScalarString(StringRef &) override; void setError(const Twine &message) override; bool canElideEmptySequence() override; @@ -935,7 +1038,8 @@ private: StringRef value() const { return _value; } static inline bool classof(const HNode *n) { - return ScalarNode::classof(n->_node); + return ScalarNode::classof(n->_node) || + BlockScalarNode::classof(n->_node); } static inline bool classof(const ScalarHNode *) { return true; } protected: @@ -943,7 +1047,7 @@ private: }; class MapHNode : public HNode { - virtual void anchor(); + void anchor() override; public: MapHNode(Node *n) : HNode(n) { } @@ -962,7 +1066,7 @@ private: }; class SequenceHNode : public HNode { - virtual void anchor(); + void anchor() override; public: SequenceHNode(Node *n) : HNode(n) { } @@ -1008,7 +1112,7 @@ private: class Output : public IO { public: Output(llvm::raw_ostream &, void *Ctxt=nullptr); - virtual ~Output(); + ~Output() override; bool outputting() override; bool mapTag(StringRef, bool) override; @@ -1016,6 +1120,8 @@ public: void endMapping() override; bool preflightKey(const char *key, bool, bool, bool &, void *&) override; void postflightKey(void *) override; + void beginFlowMapping() override; + void endFlowMapping() override; unsigned beginSequence() override; void endSequence() override; bool preflightElement(unsigned, void *&) override; @@ -1026,11 +1132,13 @@ public: void endFlowSequence() override; void beginEnumScalar() override; bool matchEnumScalar(const char*, bool) override; + bool matchEnumFallback() override; void endEnumScalar() override; bool beginBitSetScalar(bool &) override; bool bitSetMatch(const char *, bool ) override; void endBitSetScalar() override; void scalarString(StringRef &, bool) override; + void blockScalarString(StringRef &) override; void setError(const Twine &message) override; bool canElideEmptySequence() override; public: @@ -1047,13 +1155,22 @@ private: void newLineCheck(); void outputNewLine(); void paddedKey(StringRef key); - - enum InState { inSeq, inFlowSeq, inMapFirstKey, inMapOtherKey }; + void flowKey(StringRef Key); + + enum InState { + inSeq, + inFlowSeq, + inMapFirstKey, + inMapOtherKey, + inFlowMapFirstKey, + inFlowMapOtherKey + }; llvm::raw_ostream &Out; SmallVector<InState, 8> StateStack; int Column; int ColumnAtFlowStart; + int ColumnAtMapFlowStart; bool NeedBitValueComma; bool NeedFlowSequenceComma; bool EnumerationMatchFound; @@ -1163,6 +1280,16 @@ operator>>(Input &yin, T &docSeq) { return yin; } +// Define non-member operator>> so that Input can stream in a block scalar. +template <typename T> +inline +typename std::enable_if<has_BlockScalarTraits<T>::value, Input &>::type +operator>>(Input &In, T &Val) { + if (In.setCurrentDocument()) + yamlize(In, Val, true); + return In; +} + // Provide better error message about types missing a trait specialization template <typename T> inline @@ -1218,6 +1345,20 @@ operator<<(Output &yout, T &seq) { return yout; } +// Define non-member operator<< so that Output can stream out a block scalar. +template <typename T> +inline +typename std::enable_if<has_BlockScalarTraits<T>::value, Output &>::type +operator<<(Output &Out, T &Val) { + Out.beginDocuments(); + if (Out.preflightDocument(0)) { + yamlize(Out, Val, true); + Out.postflightDocument(); + } + Out.endDocuments(); + return Out; +} + // Provide better error message about types missing a trait specialization template <typename T> inline diff --git a/include/llvm/Support/circular_raw_ostream.h b/include/llvm/Support/circular_raw_ostream.h index ee7b89fe8c8d..19f9c2c4b155 100644 --- a/include/llvm/Support/circular_raw_ostream.h +++ b/include/llvm/Support/circular_raw_ostream.h @@ -107,30 +107,17 @@ namespace llvm /// management of it, etc. /// circular_raw_ostream(raw_ostream &Stream, const char *Header, - size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) - : raw_ostream(/*unbuffered*/true), - TheStream(nullptr), - OwnsStream(Owns), - BufferSize(BuffSize), - BufferArray(nullptr), - Filled(false), - Banner(Header) { + size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) + : raw_ostream(/*unbuffered*/ true), TheStream(nullptr), + OwnsStream(Owns), BufferSize(BuffSize), BufferArray(nullptr), + Filled(false), Banner(Header) { if (BufferSize != 0) BufferArray = new char[BufferSize]; Cur = BufferArray; setStream(Stream, Owns); } - explicit circular_raw_ostream() - : raw_ostream(/*unbuffered*/true), - TheStream(nullptr), - OwnsStream(REFERENCE_ONLY), - BufferArray(nullptr), - Filled(false), - Banner("") { - Cur = BufferArray; - } - ~circular_raw_ostream() { + ~circular_raw_ostream() override { flush(); flushBufferWithBanner(); releaseStream(); diff --git a/include/llvm/Support/raw_os_ostream.h b/include/llvm/Support/raw_os_ostream.h index 04cf3b6202c4..a983aeb90879 100644 --- a/include/llvm/Support/raw_os_ostream.h +++ b/include/llvm/Support/raw_os_ostream.h @@ -34,7 +34,7 @@ class raw_os_ostream : public raw_ostream { public: raw_os_ostream(std::ostream &O) : OS(O) {} - ~raw_os_ostream(); + ~raw_os_ostream() override; }; } // end llvm namespace diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index c9ef637940db..b59317112c44 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -14,32 +14,31 @@ #ifndef LLVM_SUPPORT_RAW_OSTREAM_H #define LLVM_SUPPORT_RAW_OSTREAM_H +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include <system_error> namespace llvm { - class format_object_base; - class FormattedString; - class FormattedNumber; - template <typename T> - class SmallVectorImpl; - - namespace sys { - namespace fs { - enum OpenFlags : unsigned; - } - } - -/// raw_ostream - This class implements an extremely fast bulk output stream -/// that can *only* output to a stream. It does not support seeking, reopening, -/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs +class format_object_base; +class FormattedString; +class FormattedNumber; +template <typename T> class SmallVectorImpl; + +namespace sys { +namespace fs { +enum OpenFlags : unsigned; +} +} + +/// This class implements an extremely fast bulk output stream that can *only* +/// output to a stream. It does not support seeking, reopening, rewinding, line +/// buffered disciplines etc. It is a simple buffer that outputs /// a chunk at a time. class raw_ostream { private: - void operator=(const raw_ostream &) LLVM_DELETED_FUNCTION; - raw_ostream(const raw_ostream &) LLVM_DELETED_FUNCTION; + void operator=(const raw_ostream &) = delete; + raw_ostream(const raw_ostream &) = delete; /// The buffer is handled in such a way that the buffer is /// uninitialized, unbuffered, or out of space when OutBufCur >= @@ -81,8 +80,8 @@ public: SAVEDCOLOR }; - explicit raw_ostream(bool unbuffered=false) - : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { + explicit raw_ostream(bool unbuffered = false) + : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { // Start out ready to flush. OutBufStart = OutBufEnd = OutBufCur = nullptr; } @@ -96,12 +95,11 @@ public: // Configuration Interface //===--------------------------------------------------------------------===// - /// SetBuffered - Set the stream to be buffered, with an automatically - /// determined buffer size. + /// Set the stream to be buffered, with an automatically determined buffer + /// size. void SetBuffered(); - /// SetBufferSize - Set the stream to be buffered, using the - /// specified buffer size. + /// Set the stream to be buffered, using the specified buffer size. void SetBufferSize(size_t Size) { flush(); SetBufferAndMode(new char[Size], Size, InternalBuffer); @@ -117,10 +115,9 @@ public: return OutBufEnd - OutBufStart; } - /// SetUnbuffered - Set the stream to be unbuffered. When - /// unbuffered, the stream will flush after every write. This routine - /// will also flush the buffer immediately when the stream is being - /// set to unbuffered. + /// Set the stream to be unbuffered. When unbuffered, the stream will flush + /// after every write. This routine will also flush the buffer immediately + /// when the stream is being set to unbuffered. void SetUnbuffered() { flush(); SetBufferAndMode(nullptr, 0, Unbuffered); @@ -185,6 +182,10 @@ public: return write(Str.data(), Str.length()); } + raw_ostream &operator<<(const llvm::SmallVectorImpl<char> &Str) { + return write(Str.data(), Str.size()); + } + raw_ostream &operator<<(unsigned long N); raw_ostream &operator<<(long N); raw_ostream &operator<<(unsigned long long N); @@ -200,11 +201,11 @@ public: raw_ostream &operator<<(double N); - /// write_hex - Output \p N in hexadecimal, without any prefix or padding. + /// Output \p N in hexadecimal, without any prefix or padding. raw_ostream &write_hex(unsigned long long N); - /// write_escaped - Output \p Str, turning '\\', '\t', '\n', '"', and - /// anything that doesn't satisfy std::isprint into an escape sequence. + /// Output \p Str, turning '\\', '\t', '\n', '"', and anything that doesn't + /// satisfy std::isprint into an escape sequence. raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); raw_ostream &write(unsigned char C); @@ -259,8 +260,8 @@ public: //===--------------------------------------------------------------------===// private: - /// write_impl - The is the piece of the class that is implemented - /// by subclasses. This writes the \p Size bytes starting at + /// The is the piece of the class that is implemented by subclasses. This + /// writes the \p Size bytes starting at /// \p Ptr to the underlying stream. /// /// This function is guaranteed to only be called at a point at which it is @@ -277,51 +278,69 @@ private: // An out of line virtual method to provide a home for the class vtable. virtual void handle(); - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. virtual uint64_t current_pos() const = 0; protected: - /// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is - /// intended for use only by subclasses which can arrange for the output to go - /// directly into the desired output buffer, instead of being copied on each - /// flush. + /// Use the provided buffer as the raw_ostream buffer. This is intended for + /// use only by subclasses which can arrange for the output to go directly + /// into the desired output buffer, instead of being copied on each flush. void SetBuffer(char *BufferStart, size_t Size) { SetBufferAndMode(BufferStart, Size, ExternalBuffer); } - /// preferred_buffer_size - Return an efficient buffer size for the - /// underlying output mechanism. + /// Return an efficient buffer size for the underlying output mechanism. virtual size_t preferred_buffer_size() const; - /// getBufferStart - Return the beginning of the current stream buffer, or 0 - /// if the stream is unbuffered. + /// Return the beginning of the current stream buffer, or 0 if the stream is + /// unbuffered. const char *getBufferStart() const { return OutBufStart; } //===--------------------------------------------------------------------===// // Private Interface //===--------------------------------------------------------------------===// private: - /// SetBufferAndMode - Install the given buffer and mode. + /// Install the given buffer and mode. void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode); - /// flush_nonempty - Flush the current buffer, which is known to be - /// non-empty. This outputs the currently buffered data and resets - /// the buffer to empty. + /// Flush the current buffer, which is known to be non-empty. This outputs the + /// currently buffered data and resets the buffer to empty. void flush_nonempty(); - /// copy_to_buffer - Copy data into the buffer. Size must not be - /// greater than the number of unused bytes in the buffer. + /// Copy data into the buffer. Size must not be greater than the number of + /// unused bytes in the buffer. void copy_to_buffer(const char *Ptr, size_t Size); }; +/// An abstract base class for streams implementations that also support a +/// pwrite operation. This is usefull for code that can mostly stream out data, +/// but needs to patch in a header that needs to know the output size. +class raw_pwrite_stream : public raw_ostream { + virtual void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) = 0; + +public: + explicit raw_pwrite_stream(bool Unbuffered = false) + : raw_ostream(Unbuffered) {} + void pwrite(const char *Ptr, size_t Size, uint64_t Offset) { +#ifndef NDBEBUG + uint64_t Pos = tell(); + // /dev/null always reports a pos of 0, so we cannot perform this check + // in that case. + if (Pos) + assert(Size + Offset <= Pos && "We don't support extending the stream"); +#endif + pwrite_impl(Ptr, Size, Offset); + } +}; + //===----------------------------------------------------------------------===// // File Output Streams //===----------------------------------------------------------------------===// -/// raw_fd_ostream - A raw_ostream that writes to a file descriptor. +/// A raw_ostream that writes to a file descriptor. /// -class raw_fd_ostream : public raw_ostream { +class raw_fd_ostream : public raw_pwrite_stream { int FD; bool ShouldClose; @@ -335,18 +354,21 @@ class raw_fd_ostream : public raw_ostream { uint64_t pos; - /// write_impl - See raw_ostream::write_impl. + bool SupportsSeeking; + + /// See raw_ostream::write_impl. void write_impl(const char *Ptr, size_t Size) override; - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; + + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. uint64_t current_pos() const override { return pos; } - /// preferred_buffer_size - Determine an efficient buffer size. + /// Determine an efficient buffer size. size_t preferred_buffer_size() const override; - /// error_detected - Set the flag indicating that an output error has - /// been encountered. + /// Set the flag indicating that an output error has been encountered. void error_detected() { Error = true; } public: @@ -363,22 +385,24 @@ public: raw_fd_ostream(StringRef Filename, std::error_code &EC, sys::fs::OpenFlags Flags); - /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If - /// ShouldClose is true, this closes the file when the stream is destroyed. + /// FD is the file descriptor that this writes to. If ShouldClose is true, + /// this closes the file when the stream is destroyed. raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false); - ~raw_fd_ostream(); + ~raw_fd_ostream() override; - /// close - Manually flush the stream and close the file. - /// Note that this does not call fsync. + /// Manually flush the stream and close the file. Note that this does not call + /// fsync. void close(); - /// seek - Flushes the stream and repositions the underlying file descriptor - /// position to the offset specified from the beginning of the file. + bool supportsSeeking() { return SupportsSeeking; } + + /// Flushes the stream and repositions the underlying file descriptor 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. + /// 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 @@ -397,18 +421,18 @@ public: bool has_colors() const override; - /// has_error - Return the value of the flag in this raw_fd_ostream indicating - /// whether an output error has been encountered. + /// Return the value of the flag in this raw_fd_ostream indicating whether an + /// output error has been encountered. /// This doesn't implicitly flush any pending output. Also, it doesn't /// guarantee to detect all errors unless the stream has been closed. bool has_error() const { return Error; } - /// clear_error - Set the flag read by has_error() to false. If the error - /// flag is set at the time when this raw_ostream's destructor is called, - /// report_fatal_error is called to report the error. Use clear_error() - /// after handling the error to avoid this behavior. + /// Set the flag read by has_error() to false. If the error flag is set at the + /// time when this raw_ostream's destructor is called, report_fatal_error is + /// called to report the error. Use clear_error() after handling the error to + /// avoid this behavior. /// /// "Errors should never pass silently. /// Unless explicitly silenced." @@ -419,87 +443,106 @@ public: } }; -/// outs() - This returns a reference to a raw_ostream for standard output. -/// Use it like: outs() << "foo" << "bar"; +/// This returns a reference to a raw_ostream for standard output. Use it like: +/// outs() << "foo" << "bar"; raw_ostream &outs(); -/// errs() - This returns a reference to a raw_ostream for standard error. -/// Use it like: errs() << "foo" << "bar"; +/// This returns a reference to a raw_ostream for standard error. Use it like: +/// errs() << "foo" << "bar"; raw_ostream &errs(); -/// nulls() - This returns a reference to a raw_ostream which simply discards -/// output. +/// This returns a reference to a raw_ostream which simply discards output. raw_ostream &nulls(); //===----------------------------------------------------------------------===// // Output Stream Adaptors //===----------------------------------------------------------------------===// -/// raw_string_ostream - A raw_ostream that writes to an std::string. This is a -/// simple adaptor class. This class does not encounter output errors. +/// A raw_ostream that writes to an std::string. This is a simple adaptor +/// class. This class does not encounter output errors. class raw_string_ostream : public raw_ostream { std::string &OS; - /// write_impl - See raw_ostream::write_impl. + /// See raw_ostream::write_impl. void write_impl(const char *Ptr, size_t Size) override; - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. uint64_t current_pos() const override { return OS.size(); } public: explicit raw_string_ostream(std::string &O) : OS(O) {} - ~raw_string_ostream(); + ~raw_string_ostream() override; - /// str - Flushes the stream contents to the target string and returns - /// the string's reference. + /// Flushes the stream contents to the target string and returns the string's + /// reference. std::string& str() { flush(); return OS; } }; -/// raw_svector_ostream - A raw_ostream that writes to an SmallVector or -/// SmallString. This is a simple adaptor class. This class does not -/// encounter output errors. -class raw_svector_ostream : public raw_ostream { +/// A raw_ostream that writes to an SmallVector or SmallString. This is a +/// simple adaptor class. This class does not encounter output errors. +class raw_svector_ostream : public raw_pwrite_stream { SmallVectorImpl<char> &OS; - /// write_impl - See raw_ostream::write_impl. + /// See raw_ostream::write_impl. void write_impl(const char *Ptr, size_t Size) override; - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; + + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. uint64_t current_pos() const override; + +protected: + // Like the regular constructor, but doesn't call init. + explicit raw_svector_ostream(SmallVectorImpl<char> &O, unsigned); + void init(); + public: /// Construct a new raw_svector_ostream. /// /// \param O The vector to write to; this should generally have at least 128 /// bytes free to avoid any extraneous memory overhead. explicit raw_svector_ostream(SmallVectorImpl<char> &O); - ~raw_svector_ostream(); + ~raw_svector_ostream() override; - /// resync - This is called when the SmallVector we're appending to is changed - /// outside of the raw_svector_ostream's control. It is only safe to do this - /// if the raw_svector_ostream has previously been flushed. + + /// This is called when the SmallVector we're appending to is changed outside + /// of the raw_svector_ostream's control. It is only safe to do this if the + /// raw_svector_ostream has previously been flushed. void resync(); - /// str - Flushes the stream contents to the target vector and return a - /// StringRef for the vector contents. + /// Flushes the stream contents to the target vector and return a StringRef + /// for the vector contents. StringRef str(); }; -/// raw_null_ostream - A raw_ostream that discards all output. -class raw_null_ostream : public raw_ostream { - /// write_impl - See raw_ostream::write_impl. +/// A raw_ostream that discards all output. +class raw_null_ostream : public raw_pwrite_stream { + /// See raw_ostream::write_impl. void write_impl(const char *Ptr, size_t size) override; + void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. uint64_t current_pos() const override; public: explicit raw_null_ostream() {} - ~raw_null_ostream(); + ~raw_null_ostream() override; +}; + +class buffer_ostream : public raw_svector_ostream { + raw_ostream &OS; + SmallVector<char, 0> Buffer; + +public: + buffer_ostream(raw_ostream &OS) : raw_svector_ostream(Buffer, 0), OS(OS) { + init(); + } + ~buffer_ostream() { OS << str(); } }; } // end llvm namespace diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index 70953a9cb70e..45465aea004b 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -28,9 +28,17 @@ namespace llvm { /// type can be copied around with memcpy instead of running ctors etc. template <typename T> struct isPodLike { -#if __has_feature(is_trivially_copyable) + // std::is_trivially_copyable is available in libc++ with clang, libstdc++ + // that comes with GCC 5. +#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \ + (defined(__GNUC__) && __GNUC__ >= 5) // If the compiler supports the is_trivially_copyable trait use it, as it // matches the definition of isPodLike closely. + static const bool value = std::is_trivially_copyable<T>::value; +#elif __has_feature(is_trivially_copyable) + // Use the internal name if the compiler supports is_trivially_copyable but we + // don't know if the standard library does. This is the case for clang in + // conjunction with libstdc++ from GCC 4.x. static const bool value = __is_trivially_copyable(T); #else // If we don't know anything else, we can (at least) assume that all non-class diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 4abeddd6be29..75765557a776 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -26,7 +26,6 @@ #include <map> namespace llvm { -class raw_ostream; // RecTy subclasses. class BitRecTy; @@ -81,7 +80,7 @@ public: private: RecTyKind Kind; - ListRecTy *ListTy; + std::unique_ptr<ListRecTy> ListTy; virtual void anchor(); public: @@ -108,14 +107,14 @@ public: // These methods should only be called from subclasses of Init virtual Init *convertValue( IntInit *II) { return nullptr; } virtual Init *convertValue(StringInit *SI) { return nullptr; } virtual Init *convertValue( ListInit *LI) { return nullptr; } - virtual Init *convertValue( UnOpInit *UI) { - return convertValue((TypedInit*)UI); + virtual Init *convertValue( UnOpInit *UO) { + return convertValue((TypedInit*)UO); } - virtual Init *convertValue( BinOpInit *UI) { - return convertValue((TypedInit*)UI); + virtual Init *convertValue( BinOpInit *BO) { + return convertValue((TypedInit*)BO); } - virtual Init *convertValue( TernOpInit *UI) { - return convertValue((TypedInit*)UI); + virtual Init *convertValue( TernOpInit *TO) { + return convertValue((TypedInit*)TO); } virtual Init *convertValue(VarBitInit *VB) { return nullptr; } virtual Init *convertValue( DefInit *DI) { return nullptr; } @@ -150,21 +149,13 @@ public: static BitRecTy *get() { return &Shared; } + using RecTy::convertValue; Init *convertValue( UnsetInit *UI) override { return (Init*)UI; } Init *convertValue( BitInit *BI) override { return (Init*)BI; } Init *convertValue( BitsInit *BI) override; Init *convertValue( IntInit *II) override; - Init *convertValue(StringInit *SI) override { return nullptr; } - Init *convertValue( ListInit *LI) override { return nullptr; } Init *convertValue(VarBitInit *VB) override { return (Init*)VB; } - Init *convertValue( DefInit *DI) override { return nullptr; } - Init *convertValue( DagInit *DI) override { return nullptr; } - Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);} - Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);} - Init *convertValue( TernOpInit *UI) override {return RecTy::convertValue(UI);} Init *convertValue( TypedInit *TI) override; - Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} - Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} std::string getAsString() const override { return "bit"; } @@ -189,21 +180,12 @@ public: unsigned getNumBits() const { return Size; } + using RecTy::convertValue; Init *convertValue( UnsetInit *UI) override; Init *convertValue( BitInit *UI) override; Init *convertValue( BitsInit *BI) override; Init *convertValue( IntInit *II) override; - Init *convertValue(StringInit *SI) override { return nullptr; } - Init *convertValue( ListInit *LI) override { return nullptr; } - Init *convertValue(VarBitInit *VB) override { return nullptr; } - Init *convertValue( DefInit *DI) override { return nullptr; } - Init *convertValue( DagInit *DI) override { return nullptr; } - Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);} - Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);} - Init *convertValue(TernOpInit *UI) override { return RecTy::convertValue(UI);} Init *convertValue( TypedInit *TI) override; - Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} - Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} std::string getAsString() const override; @@ -226,21 +208,12 @@ public: static IntRecTy *get() { return &Shared; } + using RecTy::convertValue; Init *convertValue( UnsetInit *UI) override { return (Init*)UI; } Init *convertValue( BitInit *BI) override; Init *convertValue( BitsInit *BI) override; Init *convertValue( IntInit *II) override { return (Init*)II; } - Init *convertValue(StringInit *SI) override { return nullptr; } - Init *convertValue( ListInit *LI) override { return nullptr; } - Init *convertValue(VarBitInit *VB) override { return nullptr; } - Init *convertValue( DefInit *DI) override { return nullptr; } - Init *convertValue( DagInit *DI) override { return nullptr; } - Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);} - Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);} - Init *convertValue( TernOpInit *UI) override {return RecTy::convertValue(UI);} Init *convertValue( TypedInit *TI) override; - Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} - Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} std::string getAsString() const override { return "int"; } @@ -264,22 +237,12 @@ public: static StringRecTy *get() { return &Shared; } + using RecTy::convertValue; Init *convertValue( UnsetInit *UI) override { return (Init*)UI; } - Init *convertValue( BitInit *BI) override { return nullptr; } - Init *convertValue( BitsInit *BI) override { return nullptr; } - Init *convertValue( IntInit *II) override { return nullptr; } Init *convertValue(StringInit *SI) override { return (Init*)SI; } - Init *convertValue( ListInit *LI) override { return nullptr; } - Init *convertValue( UnOpInit *BO) override; + Init *convertValue( UnOpInit *UO) override; Init *convertValue( BinOpInit *BO) override; - Init *convertValue( TernOpInit *BO) override {return RecTy::convertValue(BO);} - - Init *convertValue(VarBitInit *VB) override { return nullptr; } - Init *convertValue( DefInit *DI) override { return nullptr; } - Init *convertValue( DagInit *DI) override { return nullptr; } Init *convertValue( TypedInit *TI) override; - Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} - Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} std::string getAsString() const override { return "string"; } @@ -304,21 +267,10 @@ public: static ListRecTy *get(RecTy *T) { return T->getListTy(); } RecTy *getElementType() const { return Ty; } + using RecTy::convertValue; Init *convertValue( UnsetInit *UI) override { return (Init*)UI; } - Init *convertValue( BitInit *BI) override { return nullptr; } - Init *convertValue( BitsInit *BI) override { return nullptr; } - Init *convertValue( IntInit *II) override { return nullptr; } - Init *convertValue(StringInit *SI) override { return nullptr; } Init *convertValue( ListInit *LI) override; - Init *convertValue(VarBitInit *VB) override { return nullptr; } - Init *convertValue( DefInit *DI) override { return nullptr; } - Init *convertValue( DagInit *DI) override { return nullptr; } - Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);} - Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);} - Init *convertValue(TernOpInit *UI) override { return RecTy::convertValue(UI);} Init *convertValue( TypedInit *TI) override; - Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} - Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} std::string getAsString() const override; @@ -342,21 +294,12 @@ public: static DagRecTy *get() { return &Shared; } + using RecTy::convertValue; Init *convertValue( UnsetInit *UI) override { return (Init*)UI; } - Init *convertValue( BitInit *BI) override { return nullptr; } - Init *convertValue( BitsInit *BI) override { return nullptr; } - Init *convertValue( IntInit *II) override { return nullptr; } - Init *convertValue(StringInit *SI) override { return nullptr; } - Init *convertValue( ListInit *LI) override { return nullptr; } - Init *convertValue(VarBitInit *VB) override { return nullptr; } - Init *convertValue( DefInit *DI) override { return nullptr; } - Init *convertValue( UnOpInit *BO) override; + Init *convertValue( UnOpInit *UO) override; Init *convertValue( BinOpInit *BO) override; - Init *convertValue( TernOpInit *BO) override {return RecTy::convertValue(BO);} - Init *convertValue( DagInit *CI) override { return (Init*)CI; } + Init *convertValue( DagInit *DI) override { return (Init*)DI; } Init *convertValue( TypedInit *TI) override; - Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} - Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} std::string getAsString() const override { return "dag"; } @@ -382,21 +325,10 @@ public: Record *getRecord() const { return Rec; } + using RecTy::convertValue; Init *convertValue( UnsetInit *UI) override { return (Init*)UI; } - Init *convertValue( BitInit *BI) override { return nullptr; } - Init *convertValue( BitsInit *BI) override { return nullptr; } - Init *convertValue( IntInit *II) override { return nullptr; } - Init *convertValue(StringInit *SI) override { return nullptr; } - Init *convertValue( ListInit *LI) override { return nullptr; } - Init *convertValue(VarBitInit *VB) override { return nullptr; } - Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);} - Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);} - Init *convertValue( TernOpInit *UI) override {return RecTy::convertValue(UI);} Init *convertValue( DefInit *DI) override; - Init *convertValue( DagInit *DI) override { return nullptr; } - Init *convertValue( TypedInit *VI) override; - Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} - Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} + Init *convertValue( TypedInit *TI) override; std::string getAsString() const override; @@ -454,8 +386,8 @@ protected: private: const InitKind Kind; - Init(const Init &) LLVM_DELETED_FUNCTION; - Init &operator=(const Init &) LLVM_DELETED_FUNCTION; + Init(const Init &) = delete; + Init &operator=(const Init &) = delete; virtual void anchor(); public: @@ -561,11 +493,16 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) { class TypedInit : public Init { RecTy *Ty; - TypedInit(const TypedInit &Other) LLVM_DELETED_FUNCTION; - TypedInit &operator=(const TypedInit &Other) LLVM_DELETED_FUNCTION; + TypedInit(const TypedInit &Other) = delete; + TypedInit &operator=(const TypedInit &Other) = delete; protected: explicit TypedInit(InitKind K, RecTy *T) : Init(K), Ty(T) {} + ~TypedInit() { + // If this is a DefInit we need to delete the RecordRecTy. + if (getKind() == IK_DefInit) + delete Ty; + } public: static bool classof(const Init *I) { @@ -596,8 +533,8 @@ public: /// class UnsetInit : public Init { UnsetInit() : Init(IK_UnsetInit) {} - UnsetInit(const UnsetInit &) LLVM_DELETED_FUNCTION; - UnsetInit &operator=(const UnsetInit &Other) LLVM_DELETED_FUNCTION; + UnsetInit(const UnsetInit &) = delete; + UnsetInit &operator=(const UnsetInit &Other) = delete; void anchor() override; public: @@ -624,8 +561,8 @@ class BitInit : public Init { bool Value; explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {} - BitInit(const BitInit &Other) LLVM_DELETED_FUNCTION; - BitInit &operator=(BitInit &Other) LLVM_DELETED_FUNCTION; + BitInit(const BitInit &Other) = delete; + BitInit &operator=(BitInit &Other) = delete; void anchor() override; public: @@ -658,8 +595,8 @@ class BitsInit : public TypedInit, public FoldingSetNode { : TypedInit(IK_BitsInit, BitsRecTy::get(Range.size())), Bits(Range.begin(), Range.end()) {} - BitsInit(const BitsInit &Other) LLVM_DELETED_FUNCTION; - BitsInit &operator=(const BitsInit &Other) LLVM_DELETED_FUNCTION; + BitsInit(const BitsInit &Other) = delete; + BitsInit &operator=(const BitsInit &Other) = delete; public: static bool classof(const Init *I) { @@ -713,8 +650,8 @@ class IntInit : public TypedInit { explicit IntInit(int64_t V) : TypedInit(IK_IntInit, IntRecTy::get()), Value(V) {} - IntInit(const IntInit &Other) LLVM_DELETED_FUNCTION; - IntInit &operator=(const IntInit &Other) LLVM_DELETED_FUNCTION; + IntInit(const IntInit &Other) = delete; + IntInit &operator=(const IntInit &Other) = delete; public: static bool classof(const Init *I) { @@ -753,8 +690,8 @@ class StringInit : public TypedInit { explicit StringInit(const std::string &V) : TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {} - StringInit(const StringInit &Other) LLVM_DELETED_FUNCTION; - StringInit &operator=(const StringInit &Other) LLVM_DELETED_FUNCTION; + StringInit(const StringInit &Other) = delete; + StringInit &operator=(const StringInit &Other) = delete; void anchor() override; public: @@ -798,8 +735,8 @@ private: : TypedInit(IK_ListInit, ListRecTy::get(EltTy)), Values(Range.begin(), Range.end()) {} - ListInit(const ListInit &Other) LLVM_DELETED_FUNCTION; - ListInit &operator=(const ListInit &Other) LLVM_DELETED_FUNCTION; + ListInit(const ListInit &Other) = delete; + ListInit &operator=(const ListInit &Other) = delete; public: static bool classof(const Init *I) { @@ -838,7 +775,6 @@ public: inline const_iterator begin() const { return Values.begin(); } inline const_iterator end () const { return Values.end(); } - inline size_t size () const { return Values.size(); } inline bool empty() const { return Values.empty(); } /// resolveListElementReference - This method is used to implement @@ -855,8 +791,8 @@ public: /// OpInit - Base class for operators /// class OpInit : public TypedInit { - OpInit(const OpInit &Other) LLVM_DELETED_FUNCTION; - OpInit &operator=(OpInit &Other) LLVM_DELETED_FUNCTION; + OpInit(const OpInit &Other) = delete; + OpInit &operator=(OpInit &Other) = delete; protected: explicit OpInit(InitKind K, RecTy *Type) : TypedInit(K, Type) {} @@ -899,8 +835,8 @@ private: UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type) : OpInit(IK_UnOpInit, Type), Opc(opc), LHS(lhs) {} - UnOpInit(const UnOpInit &Other) LLVM_DELETED_FUNCTION; - UnOpInit &operator=(const UnOpInit &Other) LLVM_DELETED_FUNCTION; + UnOpInit(const UnOpInit &Other) = delete; + UnOpInit &operator=(const UnOpInit &Other) = delete; public: static bool classof(const Init *I) { @@ -946,8 +882,8 @@ private: BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) : OpInit(IK_BinOpInit, Type), Opc(opc), LHS(lhs), RHS(rhs) {} - BinOpInit(const BinOpInit &Other) LLVM_DELETED_FUNCTION; - BinOpInit &operator=(const BinOpInit &Other) LLVM_DELETED_FUNCTION; + BinOpInit(const BinOpInit &Other) = delete; + BinOpInit &operator=(const BinOpInit &Other) = delete; public: static bool classof(const Init *I) { @@ -1000,8 +936,8 @@ private: RecTy *Type) : OpInit(IK_TernOpInit, Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {} - TernOpInit(const TernOpInit &Other) LLVM_DELETED_FUNCTION; - TernOpInit &operator=(const TernOpInit &Other) LLVM_DELETED_FUNCTION; + TernOpInit(const TernOpInit &Other) = delete; + TernOpInit &operator=(const TernOpInit &Other) = delete; public: static bool classof(const Init *I) { @@ -1058,8 +994,8 @@ class VarInit : public TypedInit { explicit VarInit(Init *VN, RecTy *T) : TypedInit(IK_VarInit, T), VarName(VN) {} - VarInit(const VarInit &Other) LLVM_DELETED_FUNCTION; - VarInit &operator=(const VarInit &Other) LLVM_DELETED_FUNCTION; + VarInit(const VarInit &Other) = delete; + VarInit &operator=(const VarInit &Other) = delete; public: static bool classof(const Init *I) { @@ -1111,8 +1047,8 @@ class VarBitInit : public Init { "Illegal VarBitInit expression!"); } - VarBitInit(const VarBitInit &Other) LLVM_DELETED_FUNCTION; - VarBitInit &operator=(const VarBitInit &Other) LLVM_DELETED_FUNCTION; + VarBitInit(const VarBitInit &Other) = delete; + VarBitInit &operator=(const VarBitInit &Other) = delete; public: static bool classof(const Init *I) { @@ -1150,8 +1086,8 @@ class VarListElementInit : public TypedInit { "Illegal VarBitInit expression!"); } - VarListElementInit(const VarListElementInit &Other) LLVM_DELETED_FUNCTION; - void operator=(const VarListElementInit &Other) LLVM_DELETED_FUNCTION; + VarListElementInit(const VarListElementInit &Other) = delete; + void operator=(const VarListElementInit &Other) = delete; public: static bool classof(const Init *I) { @@ -1186,8 +1122,8 @@ class DefInit : public TypedInit { DefInit(Record *D, RecordRecTy *T) : TypedInit(IK_DefInit, T), Def(D) {} friend class Record; - DefInit(const DefInit &Other) LLVM_DELETED_FUNCTION; - DefInit &operator=(const DefInit &Other) LLVM_DELETED_FUNCTION; + DefInit(const DefInit &Other) = delete; + DefInit &operator=(const DefInit &Other) = delete; public: static bool classof(const Init *I) { @@ -1233,8 +1169,8 @@ class FieldInit : public TypedInit { assert(getType() && "FieldInit with non-record type!"); } - FieldInit(const FieldInit &Other) LLVM_DELETED_FUNCTION; - FieldInit &operator=(const FieldInit &Other) LLVM_DELETED_FUNCTION; + FieldInit(const FieldInit &Other) = delete; + FieldInit &operator=(const FieldInit &Other) = delete; public: static bool classof(const Init *I) { @@ -1276,8 +1212,8 @@ class DagInit : public TypedInit, public FoldingSetNode { Args(ArgRange.begin(), ArgRange.end()), ArgNames(NameRange.begin(), NameRange.end()) {} - DagInit(const DagInit &Other) LLVM_DELETED_FUNCTION; - DagInit &operator=(const DagInit &Other) LLVM_DELETED_FUNCTION; + DagInit(const DagInit &Other) = delete; + DagInit &operator=(const DagInit &Other) = delete; public: static bool classof(const Init *I) { @@ -1442,8 +1378,6 @@ public: TheInit(O.TheInit), IsAnonymous(O.IsAnonymous), ResolveFirst(O.ResolveFirst) { } - ~Record() {} - static unsigned getNewUID() { return LastID++; } unsigned getID() const { return ID; } @@ -1477,7 +1411,7 @@ public: return false; } bool isTemplateArg(StringRef Name) const { - return isTemplateArg(StringInit::get(Name.str())); + return isTemplateArg(StringInit::get(Name)); } const RecordVal *getValue(const Init *Name) const { @@ -1502,7 +1436,7 @@ public: TemplateArgs.push_back(Name); } void addTemplateArg(StringRef Name) { - addTemplateArg(StringInit::get(Name.str())); + addTemplateArg(StringInit::get(Name)); } void addValue(const RecordVal &RV) { @@ -1527,7 +1461,7 @@ public: } void removeValue(StringRef Name) { - removeValue(StringInit::get(Name.str())); + removeValue(StringInit::get(Name)); } bool isSubClassOf(const Record *R) const { diff --git a/include/llvm/TableGen/SetTheory.h b/include/llvm/TableGen/SetTheory.h index 76e56ec6443e..595c29f2ee1d 100644 --- a/include/llvm/TableGen/SetTheory.h +++ b/include/llvm/TableGen/SetTheory.h @@ -95,17 +95,17 @@ private: ExpandMap Expansions; // Known DAG operators by name. - StringMap<Operator*> Operators; + StringMap<std::unique_ptr<Operator>> Operators; // Typed expanders by class name. - StringMap<Expander*> Expanders; + StringMap<std::unique_ptr<Expander>> Expanders; public: /// Create a SetTheory instance with only the standard operators. SetTheory(); /// addExpander - Add an expander for Records with the named super class. - void addExpander(StringRef ClassName, Expander*); + void addExpander(StringRef ClassName, std::unique_ptr<Expander>); /// addFieldExpander - Add an expander for ClassName that simply evaluates /// FieldName in the Record to get the set elements. That is all that is @@ -118,7 +118,7 @@ public: void addFieldExpander(StringRef ClassName, StringRef FieldName); /// addOperator - Add a DAG operator. - void addOperator(StringRef Name, Operator*); + void addOperator(StringRef Name, std::unique_ptr<Operator>); /// evaluate - Evaluate Expr and append the resulting set to Elts. void evaluate(Init *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc); diff --git a/include/llvm/TableGen/TableGenBackend.h b/include/llvm/TableGen/TableGenBackend.h index 3e4f3cc917a8..d226f1f1af7b 100644 --- a/include/llvm/TableGen/TableGenBackend.h +++ b/include/llvm/TableGen/TableGenBackend.h @@ -14,10 +14,9 @@ #ifndef LLVM_TABLEGEN_TABLEGENBACKEND_H #define LLVM_TABLEGEN_TABLEGENBACKEND_H -#include "llvm/ADT/StringRef.h" - namespace llvm { +class StringRef; class raw_ostream; /// emitSourceFileHeader - Output an LLVM style file header to the specified diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 6c970d0c19db..ec8a12df9fc6 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -207,6 +207,12 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, // The function should return 0 to select the default order defined by // MemberList, 1 to select the first AltOrders entry and so on. code AltOrderSelect = [{}]; + + // Specify allocation priority for register allocators using a greedy + // heuristic. Classes with higher priority values are assigned first. This is + // useful as it is sometimes beneficial to assign registers to highly + // constrained classes first. The value has to be in the range [0,63]. + int AllocationPriority = 0; } // The memberList in a RegisterClass is a dag of set operations. TableGen @@ -1000,6 +1006,15 @@ class InstAlias<string Asm, dag Result, int Emit = 1> { // Predicates - Predicates that must be true for this to match. list<Predicate> Predicates = []; + + // If the instruction specified in Result has defined an AsmMatchConverter + // then setting this to 1 will cause the alias to use the AsmMatchConverter + // function when converting the OperandVector into an MCInst instead of the + // function that is generated by the dag Result. + // Setting this to 0 will cause the alias to ignore the Result instruction's + // defined AsmMatchConverter and instead use the function generated by the + // dag Result. + bit UseInstAsmMatchConverter = 1; } //===----------------------------------------------------------------------===// @@ -1015,6 +1030,11 @@ class AsmWriter { // name. string AsmWriterClassName = "InstPrinter"; + // PassSubtarget - Determines whether MCSubtargetInfo should be passed to + // the various print methods. + // FIXME: Remove after all ports are updated. + int PassSubtarget = 0; + // Variant - AsmWriters can be of multiple different variants. Variants are // used to support targets that need to emit assembly code in ways that are // mostly the same for different targets, but have minor differences in diff --git a/include/llvm/Target/TargetCallingConv.h b/include/llvm/Target/TargetCallingConv.h index 9071bfeec7ed..9d4e7a04d905 100644 --- a/include/llvm/Target/TargetCallingConv.h +++ b/include/llvm/Target/TargetCallingConv.h @@ -18,6 +18,7 @@ #include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" #include <string> +#include <limits.h> namespace llvm { diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h index 277bd98d371c..0e317247a59f 100644 --- a/include/llvm/Target/TargetFrameLowering.h +++ b/include/llvm/Target/TargetFrameLowering.h @@ -130,21 +130,26 @@ public: /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. - virtual void emitPrologue(MachineFunction &MF) const = 0; + virtual void emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const = 0; virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const = 0; /// Adjust the prologue to have the function use segmented stacks. This works /// by adding a check even before the "normal" function prologue. - virtual void adjustForSegmentedStacks(MachineFunction &MF) const { } + virtual void adjustForSegmentedStacks(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const {} /// Adjust the prologue to add Erlang Run-Time System (ERTS) specific code in /// the assembly prologue to explicitly handle the stack. - virtual void adjustForHiPEPrologue(MachineFunction &MF) const { } + virtual void adjustForHiPEPrologue(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const {} /// Adjust the prologue to add an allocation at a fixed offset from the frame /// pointer. - virtual void adjustForFrameAllocatePrologue(MachineFunction &MF) const { } + virtual void + adjustForFrameAllocatePrologue(MachineFunction &MF, + MachineBasicBlock &PrologueMBB) const {} /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee /// saved registers and returns true if it isn't possible / profitable to do @@ -168,6 +173,9 @@ public: return false; } + /// Return true if the target needs to disable frame pointer elimination. + virtual bool noFramePointerElim(const MachineFunction &MF) const; + /// 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. @@ -193,6 +201,11 @@ public: return hasReservedCallFrame(MF) || hasFP(MF); } + // needsFrameIndexResolution - Do we need to perform FI resolution for + // this function. Normally, this is required only when the function + // has any stack objects. However, targets may want to override this. + virtual bool needsFrameIndexResolution(const MachineFunction &MF) 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; @@ -244,6 +257,30 @@ public: llvm_unreachable("Call Frame Pseudo Instructions do not exist on this " "target!"); } + + /// Check whether or not the given \p MBB can be used as a prologue + /// for the target. + /// The prologue will be inserted first in this basic block. + /// This method is used by the shrink-wrapping pass to decide if + /// \p MBB will be correctly handled by the target. + /// As soon as the target enable shrink-wrapping without overriding + /// this method, we assume that each basic block is a valid + /// prologue. + virtual bool canUseAsPrologue(const MachineBasicBlock &MBB) const { + return true; + } + + /// Check whether or not the given \p MBB can be used as a epilogue + /// for the target. + /// The epilogue will be inserted before the first terminator of that block. + /// This method is used by the shrink-wrapping pass to decide if + /// \p MBB will be correctly handled by the target. + /// As soon as the target enable shrink-wrapping without overriding + /// this method, we assume that each basic block is a valid + /// epilogue. + virtual bool canUseAsEpilogue(const MachineBasicBlock &MBB) const { + return true; + } }; } // End llvm namespace diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index e8a50fff1fe8..5ec15658b696 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -50,26 +50,28 @@ template<class T> class SmallVectorImpl; /// TargetInstrInfo - Interface to description of machine instruction set /// class TargetInstrInfo : public MCInstrInfo { - TargetInstrInfo(const TargetInstrInfo &) LLVM_DELETED_FUNCTION; - void operator=(const TargetInstrInfo &) LLVM_DELETED_FUNCTION; + TargetInstrInfo(const TargetInstrInfo &) = delete; + void operator=(const TargetInstrInfo &) = delete; public: - TargetInstrInfo(int CFSetupOpcode = -1, int CFDestroyOpcode = -1) + TargetInstrInfo(unsigned CFSetupOpcode = ~0u, unsigned CFDestroyOpcode = ~0u) : CallFrameSetupOpcode(CFSetupOpcode), CallFrameDestroyOpcode(CFDestroyOpcode) { } virtual ~TargetInstrInfo(); - /// getRegClass - Givem a machine instruction descriptor, returns the register + /// Given a machine instruction descriptor, returns the register /// class constraint for OpNum, or NULL. const TargetRegisterClass *getRegClass(const MCInstrDesc &TID, unsigned OpNum, const TargetRegisterInfo *TRI, const MachineFunction &MF) const; - /// isTriviallyReMaterializable - Return true if the instruction is trivially - /// rematerializable, meaning it has no side effects and requires no operands - /// that aren't always available. + /// Return true if the instruction is trivially rematerializable, meaning it + /// has no side effects and requires no operands that aren't always available. + /// This means the only allowed uses are constants and unallocatable physical + /// registers so that the instructions result is independent of the place + /// in the function. bool isTriviallyReMaterializable(const MachineInstr *MI, AliasAnalysis *AA = nullptr) const { return MI->getOpcode() == TargetOpcode::IMPLICIT_DEF || @@ -79,35 +81,34 @@ public: } protected: - /// isReallyTriviallyReMaterializable - For instructions with opcodes for - /// which the M_REMATERIALIZABLE flag is set, this hook lets the target - /// specify whether the instruction is actually trivially rematerializable, - /// taking into consideration its operands. This predicate must return false - /// if the instruction has any side effects other than producing a value, or - /// if it requres any address registers that are not always available. + /// For instructions with opcodes for which the M_REMATERIALIZABLE flag is + /// set, this hook lets the target specify whether the instruction is actually + /// trivially rematerializable, taking into consideration its operands. This + /// predicate must return false if the instruction has any side effects other + /// than producing a value, or if it requres any address registers that are + /// not always available. + /// Requirements must be check as stated in isTriviallyReMaterializable() . virtual bool isReallyTriviallyReMaterializable(const MachineInstr *MI, AliasAnalysis *AA) const { return false; } private: - /// isReallyTriviallyReMaterializableGeneric - For instructions with opcodes - /// for which the M_REMATERIALIZABLE flag is set and the target hook - /// isReallyTriviallyReMaterializable returns false, this function does - /// target-independent tests to determine if the instruction is really - /// trivially rematerializable. + /// For instructions with opcodes for which the M_REMATERIALIZABLE flag is + /// set and the target hook isReallyTriviallyReMaterializable returns false, + /// this function does target-independent tests to determine if the + /// instruction is really trivially rematerializable. bool isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI, AliasAnalysis *AA) const; public: - /// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the - /// frame setup/destroy instructions if they exist (-1 otherwise). Some - /// targets use pseudo instructions in order to abstract away the difference - /// between operating with a frame pointer and operating without, through the - /// use of these two instructions. + /// These methods return the opcode of the frame setup/destroy instructions + /// if they exist (-1 otherwise). Some targets use pseudo instructions in + /// order to abstract away the difference between operating with a frame + /// pointer and operating without, through the use of these two instructions. /// - int getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } - int getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } + unsigned getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } + unsigned getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } /// Returns the actual stack pointer adjustment made by an instruction /// as part of a call sequence. By default, only call frame setup/destroy @@ -115,19 +116,18 @@ public: /// to enable more fine-grained adjustment, or adjust by a different value. virtual int getSPAdjust(const MachineInstr *MI) const; - /// isCoalescableExtInstr - Return true if the instruction is a "coalescable" - /// extension instruction. That is, it's like a copy where it's legal for the - /// source to overlap the destination. e.g. X86::MOVSX64rr32. If this returns - /// true, then it's expected the pre-extension value is available as a subreg - /// of the result register. This also returns the sub-register index in - /// SubIdx. + /// Return true if the instruction is a "coalescable" extension instruction. + /// That is, it's like a copy where it's legal for the source to overlap the + /// destination. e.g. X86::MOVSX64rr32. If this returns true, then it's + /// expected the pre-extension value is available as a subreg of the result + /// register. This also returns the sub-register index in SubIdx. virtual bool isCoalescableExtInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DstReg, unsigned &SubIdx) const { return false; } - /// isLoadFromStackSlot - If the specified machine instruction is a direct + /// If the specified machine instruction is a direct /// load from a stack slot, return the virtual or physical register number of /// the destination along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has @@ -137,26 +137,24 @@ public: return 0; } - /// isLoadFromStackSlotPostFE - Check for post-frame ptr elimination - /// stack locations as well. This uses a heuristic so it isn't - /// reliable for correctness. + /// Check for post-frame ptr elimination stack locations as well. + /// This uses a heuristic so it isn't reliable for correctness. virtual unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI, int &FrameIndex) const { return 0; } - /// hasLoadFromStackSlot - If the specified machine instruction has - /// a load from a stack slot, return true along with the FrameIndex - /// of the loaded stack slot and the machine mem operand containing - /// the reference. If not, return false. Unlike - /// isLoadFromStackSlot, this returns true for any instructions that - /// loads from the stack. This is just a hint, as some cases may be - /// missed. + /// If the specified machine instruction has a load from a stack slot, + /// return true along with the FrameIndex of the loaded stack slot and the + /// machine mem operand containing the reference. + /// If not, return false. Unlike isLoadFromStackSlot, this returns true for + /// any instructions that loads from the stack. This is just a hint, as some + /// cases may be missed. virtual bool hasLoadFromStackSlot(const MachineInstr *MI, const MachineMemOperand *&MMO, int &FrameIndex) const; - /// isStoreToStackSlot - If the specified machine instruction is a direct + /// 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 /// not, return 0. This predicate must return 0 if the instruction has @@ -166,25 +164,24 @@ public: return 0; } - /// isStoreToStackSlotPostFE - Check for post-frame ptr elimination - /// stack locations as well. This uses a heuristic so it isn't - /// reliable for correctness. + /// Check for post-frame ptr elimination stack locations as well. + /// This uses a heuristic, so it isn't reliable for correctness. virtual unsigned isStoreToStackSlotPostFE(const MachineInstr *MI, int &FrameIndex) const { return 0; } - /// hasStoreToStackSlot - If the specified machine instruction has a - /// store to a stack slot, return true along with the FrameIndex of - /// the loaded stack slot and the machine mem operand containing the - /// reference. If not, return false. Unlike isStoreToStackSlot, + /// If the specified machine instruction has a store to a stack slot, + /// return true along with the FrameIndex of the loaded stack slot and the + /// machine mem operand containing the reference. + /// If not, return false. Unlike isStoreToStackSlot, /// this returns true for any instructions that stores to the /// stack. This is just a hint, as some cases may be missed. virtual bool hasStoreToStackSlot(const MachineInstr *MI, const MachineMemOperand *&MMO, int &FrameIndex) const; - /// isStackSlotCopy - Return true if the specified machine instruction + /// Return true if the specified machine instruction /// is a copy of one stack slot to another and has no other effect. /// Provide the identity of the two frame indices. virtual bool isStackSlotCopy(const MachineInstr *MI, int &DestFrameIndex, @@ -207,10 +204,9 @@ public: /// this, particularly to support spilled vector registers. virtual bool getStackSlotRange(const TargetRegisterClass *RC, unsigned SubIdx, unsigned &Size, unsigned &Offset, - const TargetMachine *TM) const; + const MachineFunction &MF) const; - /// isAsCheapAsAMove - Return true if the instruction is as cheap as a move - /// instruction. + /// Return true if the instruction is as cheap as a move instruction. /// /// Targets for different archs need to override this, and different /// micro-architectures can also be finely tuned inside. @@ -218,7 +214,7 @@ public: return MI->isAsCheapAsAMove(); } - /// reMaterialize - Re-issue the specified 'original' instruction at the + /// Re-issue the specified 'original' instruction at the /// specific location targeting a new destination register. /// The register in Orig->getOperand(0).getReg() will be substituted by /// DestReg:SubIdx. Any existing subreg index is preserved or composed with @@ -229,7 +225,7 @@ public: const MachineInstr *Orig, const TargetRegisterInfo &TRI) const; - /// duplicate - Create a duplicate of the Orig instruction in MF. This is like + /// Create a duplicate of the Orig instruction in MF. This is like /// MachineFunction::CloneMachineInstr(), but the target may update operands /// that are required to be unique. /// @@ -237,7 +233,7 @@ public: virtual MachineInstr *duplicate(MachineInstr *Orig, MachineFunction &MF) const; - /// convertToThreeAddress - This method must be implemented by targets that + /// This method must be implemented by targets that /// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target /// may be able to convert a two-address instruction into one or more true /// three-address instructions on demand. This allows the X86 target (for @@ -253,10 +249,10 @@ public: return nullptr; } - /// commuteInstruction - If a target has any instructions that are - /// commutable but require converting to different instructions or making - /// non-trivial changes to commute them, this method can overloaded to do - /// that. The default implementation simply swaps the commutable operands. + /// If a target has any instructions that are commutable but require + /// converting to different instructions or making non-trivial changes to + /// commute them, this method can overloaded to do that. + /// The default implementation simply swaps the commutable operands. /// If NewMI is false, MI is modified in place and returned; otherwise, a /// new machine instruction is created and returned. Do not call this /// method for a non-commutable instruction, but there may be some cases @@ -264,8 +260,8 @@ public: virtual MachineInstr *commuteInstruction(MachineInstr *MI, bool NewMI = false) const; - /// findCommutedOpIndices - If specified MI is commutable, return the two - /// operand indices that would swap value. Return false if the instruction + /// If specified MI is commutable, return the two operand indices that would + /// swap value. Return false if the instruction /// is not in a form which this routine understands. virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const; @@ -349,8 +345,8 @@ public: RegSubRegPairAndIdx &InsertedReg) const; - /// produceSameValue - Return true if two machine instructions would produce - /// identical values. By default, this is only true when the two instructions + /// 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. If this function is called when the /// IR is still in SSA form, the caller can pass the MachineRegisterInfo for /// aggressive checks. @@ -358,7 +354,7 @@ public: const MachineInstr *MI1, const MachineRegisterInfo *MRI = nullptr) const; - /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning + /// 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 /// implemented for a target). Upon success, this returns false and returns /// with the following information in various cases: @@ -390,15 +386,15 @@ public: return true; } - /// RemoveBranch - Remove the branching code at the end of the specific MBB. + /// Remove the branching code at the end of the specific MBB. /// 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 { llvm_unreachable("Target didn't implement TargetInstrInfo::RemoveBranch!"); } - /// InsertBranch - Insert branch code into the end of the specified - /// MachineBasicBlock. The operands to this method are the same as those + /// Insert branch code into the end of the specified MachineBasicBlock. + /// The operands to this method are the same as those /// returned by AnalyzeBranch. This is only invoked in cases where /// AnalyzeBranch returns success. It returns the number of instructions /// inserted. @@ -414,14 +410,13 @@ public: llvm_unreachable("Target didn't implement TargetInstrInfo::InsertBranch!"); } - /// ReplaceTailWithBranchTo - Delete the instruction OldInst and everything - /// after it, replacing it with an unconditional branch to NewDest. This is - /// used by the tail merging pass. + /// Delete the instruction OldInst and everything after it, replacing it with + /// an unconditional branch to NewDest. This is used by the tail merging pass. virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, MachineBasicBlock *NewDest) const; - /// getUnconditionalBranch - Get an instruction that performs an unconditional - /// branch to the given symbol. + /// Get an instruction that performs an unconditional branch to the given + /// symbol. virtual void getUnconditionalBranch(MCInst &MI, const MCSymbolRefExpr *BranchTarget) const { @@ -429,12 +424,12 @@ public: "TargetInstrInfo::getUnconditionalBranch!"); } - /// getTrap - Get a machine trap instruction + /// Get a machine trap instruction. virtual void getTrap(MCInst &MI) const { llvm_unreachable("Target didn't implement TargetInstrInfo::getTrap!"); } - /// getJumpInstrTableEntryBound - Get a number of bytes that suffices to hold + /// Get a number of bytes that suffices to hold /// either the instruction returned by getUnconditionalBranch or the /// instruction returned by getTrap. This only makes sense because /// getUnconditionalBranch returns a single, specific instruction. This @@ -454,7 +449,7 @@ public: return 0; } - /// isLegalToSplitMBBAt - Return true if it's legal to split the given basic + /// Return true if it's legal to split the given basic /// block at the specified instruction (i.e. instruction would be the start /// of a new basic block). virtual bool isLegalToSplitMBBAt(MachineBasicBlock &MBB, @@ -462,7 +457,7 @@ public: return true; } - /// isProfitableToIfCvt - Return true if it's profitable to predicate + /// Return true if it's profitable to predicate /// instructions with accumulated instruction latency of "NumCycles" /// of the specified basic block, where the probability of the instructions /// being executed is given by Probability, and Confidence is a measure @@ -474,7 +469,7 @@ public: return false; } - /// isProfitableToIfCvt - Second variant of isProfitableToIfCvt, this one + /// 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 /// predicates, where the probability of the true path being taken is given @@ -489,9 +484,9 @@ public: return false; } - /// isProfitableToDupForIfCvt - Return true if it's profitable for - /// if-converter to duplicate instructions of specified accumulated - /// instruction latencies in the specified MBB to enable if-conversion. + /// Return true if it's profitable for if-converter to duplicate instructions + /// of specified accumulated instruction latencies in the specified MBB to + /// enable if-conversion. /// The probability of the instructions being executed is given by /// Probability, and Confidence is a measure of our confidence that it /// will be properly predicted. @@ -501,7 +496,7 @@ public: return false; } - /// isProfitableToUnpredicate - Return true if it's profitable to unpredicate + /// Return true if it's profitable to unpredicate /// one side of a 'diamond', i.e. two sides of if-else predicated on mutually /// exclusive predicates. /// e.g. @@ -517,7 +512,7 @@ public: return false; } - /// canInsertSelect - Return true if it is possible to insert a select + /// Return true if it is possible to insert a select /// instruction that chooses between TrueReg and FalseReg based on the /// condition code in Cond. /// @@ -542,9 +537,8 @@ public: return false; } - /// insertSelect - Insert a select instruction into MBB before I that will - /// copy TrueReg to DstReg when Cond is true, and FalseReg to DstReg when - /// Cond is false. + /// Insert a select instruction into MBB before I that will copy TrueReg to + /// DstReg when Cond is true, and FalseReg to DstReg when Cond is false. /// /// This function can only be called after canInsertSelect() returned true. /// The condition in Cond comes from AnalyzeBranch, and it can be assumed @@ -566,7 +560,7 @@ public: llvm_unreachable("Target didn't implement TargetInstrInfo::insertSelect!"); } - /// analyzeSelect - Analyze the given select instruction, returning true if + /// Analyze the given select instruction, returning true if /// it cannot be understood. It is assumed that MI->isSelect() is true. /// /// When successful, return the controlling condition and the operands that @@ -592,7 +586,7 @@ public: return true; } - /// optimizeSelect - Given a select instruction that was understood by + /// Given a select instruction that was understood by /// analyzeSelect and returned Optimizable = true, attempt to optimize MI by /// merging it with one of its operands. Returns NULL on failure. /// @@ -614,7 +608,7 @@ public: llvm_unreachable("Target must implement TargetInstrInfo::optimizeSelect!"); } - /// copyPhysReg - Emit instructions to copy a pair of physical registers. + /// Emit instructions to copy a pair of physical registers. /// /// This function should support copies within any legal register class as /// well as any cross-class copies created during instruction selection. @@ -629,11 +623,10 @@ public: llvm_unreachable("Target didn't implement TargetInstrInfo::copyPhysReg!"); } - /// storeRegToStackSlot - Store the specified register of the given register - /// class to the specified stack frame index. The store instruction is to be - /// added to the given machine basic block before the specified machine - /// instruction. If isKill is true, the register operand is the last use and - /// must be marked kill. + /// Store the specified register of the given register class to the specified + /// stack frame index. The store instruction is to be added to the given + /// machine basic block before the specified machine instruction. If isKill + /// is true, the register operand is the last use and must be marked kill. virtual void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, bool isKill, int FrameIndex, @@ -643,10 +636,9 @@ public: "TargetInstrInfo::storeRegToStackSlot!"); } - /// loadRegFromStackSlot - Load the specified register of the given register - /// class from the specified stack frame index. The load instruction is to be - /// added to the given machine basic block before the specified machine - /// instruction. + /// Load the specified register of the given register class from the specified + /// stack frame index. The load instruction is to be added to the given + /// machine basic block before the specified machine instruction. virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg, int FrameIndex, @@ -656,7 +648,7 @@ public: "TargetInstrInfo::loadRegFromStackSlot!"); } - /// expandPostRAPseudo - This function is called for all pseudo instructions + /// This function is called for all pseudo instructions /// that remain after register allocation. Many pseudo instructions are /// created to help register allocation. This is the place to convert them /// into real instructions. The target can edit MI in place, or it can insert @@ -666,46 +658,42 @@ public: return false; } - /// foldMemoryOperand - Attempt to fold a load or store of the specified stack + /// Attempt to fold a load or store of the specified stack /// slot into the specified machine instruction for the specified operand(s). /// If this is possible, a new instruction is returned with the specified /// operand folded, otherwise NULL is returned. /// The new instruction is inserted before MI, and the client is responsible /// for removing the old instruction. - MachineInstr* foldMemoryOperand(MachineBasicBlock::iterator MI, - const SmallVectorImpl<unsigned> &Ops, - int FrameIndex) const; - - /// foldMemoryOperand - Same as the previous version except it allows folding - /// of any load and store from / to any address, not just from a specific - /// stack slot. - MachineInstr* foldMemoryOperand(MachineBasicBlock::iterator MI, - const SmallVectorImpl<unsigned> &Ops, - MachineInstr* LoadMI) const; - - /// hasPattern - return true when there is potentially a faster code sequence - /// for an instruction chain ending in \p Root. All potential pattern are + MachineInstr *foldMemoryOperand(MachineBasicBlock::iterator MI, + ArrayRef<unsigned> Ops, int FrameIndex) const; + + /// Same as the previous version except it allows folding of any load and + /// store from / to any address, not just from a specific stack slot. + MachineInstr *foldMemoryOperand(MachineBasicBlock::iterator MI, + ArrayRef<unsigned> Ops, + MachineInstr *LoadMI) const; + + /// Return true when there is potentially a faster code sequence + /// for an instruction chain ending in \p Root. All potential patterns are /// returned in the \p Pattern vector. Pattern should be sorted in priority /// order since the pattern evaluator stops checking as soon as it finds a /// faster sequence. /// \param Root - Instruction that could be combined with one of its operands /// \param Pattern - Vector of possible combination pattern - virtual bool hasPattern( MachineInstr &Root, SmallVectorImpl<MachineCombinerPattern::MC_PATTERN> &Pattern) const { return false; } - /// genAlternativeCodeSequence - when hasPattern() finds a pattern this - /// function generates the instructions that could replace the original code - /// sequence. The client has to decide whether the actual replacementment is - /// beneficial or not. + /// When hasPattern() finds a pattern this function generates the instructions + /// that could replace the original code sequence. The client has to decide + /// whether the actual replacement is beneficial or not. /// \param Root - Instruction that could be combined with one of its operands /// \param P - Combination pattern for Root /// \param InsInstrs - Vector of new instructions that implement P - /// \param DelInstrs - Old instructions, including Root, that could be replaced - /// by InsInstr + /// \param DelInstrs - Old instructions, including Root, that could be + /// replaced by InsInstr /// \param InstrIdxForVirtReg - map of virtual register to instruction in /// InsInstr that defines it virtual void genAlternativeCodeSequence( @@ -716,27 +704,27 @@ public: return; } - /// useMachineCombiner - return true when a target supports MachineCombiner + /// Return true when a target supports MachineCombiner. virtual bool useMachineCombiner() const { return false; } protected: - /// foldMemoryOperandImpl - Target-dependent implementation for - /// foldMemoryOperand. Target-independent code in foldMemoryOperand will + /// Target-dependent implementation for foldMemoryOperand. + /// Target-independent code in foldMemoryOperand will /// take care of adding a MachineMemOperand to the newly created instruction. - virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, - MachineInstr* MI, - const SmallVectorImpl<unsigned> &Ops, - int FrameIndex) const { + virtual MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr *MI, + ArrayRef<unsigned> Ops, + int FrameIndex) const { return nullptr; } - /// foldMemoryOperandImpl - Target-dependent implementation for - /// foldMemoryOperand. Target-independent code in foldMemoryOperand will + /// Target-dependent implementation for foldMemoryOperand. + /// Target-independent code in foldMemoryOperand will /// take care of adding a MachineMemOperand to the newly created instruction. - virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, - MachineInstr* MI, - const SmallVectorImpl<unsigned> &Ops, - MachineInstr* LoadMI) const { + virtual MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr *MI, + ArrayRef<unsigned> Ops, + MachineInstr *LoadMI) const { return nullptr; } @@ -784,11 +772,9 @@ protected: } public: - /// canFoldMemoryOperand - Returns true for the specified load / store if - /// folding is possible. - virtual - bool canFoldMemoryOperand(const MachineInstr *MI, - const SmallVectorImpl<unsigned> &Ops) const; + /// Returns true for the specified load / store if folding is possible. + virtual bool canFoldMemoryOperand(const MachineInstr *MI, + ArrayRef<unsigned> Ops) const; /// unfoldMemoryOperand - Separate a single instruction which folded a load or /// a store or a load and a store into two or more instruction. If this is @@ -804,7 +790,7 @@ public: return false; } - /// getOpcodeAfterMemoryUnfold - Returns the opcode of the would be new + /// Returns the opcode of the would be new /// instruction after load / store are unfolded from an instruction of the /// specified opcode. It returns zero if the specified unfolding is not /// possible. If LoadRegIndex is non-null, it is filled in with the operand @@ -816,19 +802,18 @@ public: return 0; } - /// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler - /// to determine if two loads are loading from the same base address. It - /// should only return true if the base pointers are the same and the - /// only differences between the two addresses are the offset. It also returns - /// the offsets by reference. + /// This is used by the pre-regalloc scheduler to determine if two loads are + /// loading from the same base address. It should only return true if the base + /// pointers are the same and the only differences between the two addresses + /// are the offset. It also returns the offsets by reference. virtual bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, int64_t &Offset1, int64_t &Offset2) const { return false; } - /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to - /// determine (in conjunction with areLoadsFromSameBasePtr) if two loads should - /// be scheduled togther. On some targets if two loads are loading from + /// This is a used by the pre-regalloc scheduler to determine (in conjunction + /// with areLoadsFromSameBasePtr) if two loads should be scheduled together. + /// On some targets if two loads are loading from /// addresses in the same cache line, it's better if they are scheduled /// together. This function takes two integers that represent the load offsets /// from the common base address. It returns true if it decides it's desirable @@ -840,7 +825,7 @@ public: return false; } - /// \brief Get the base register and byte offset of a load/store instr. + /// Get the base register and byte offset of a load/store instr. virtual bool getLdStBaseRegImmOfs(MachineInstr *LdSt, unsigned &BaseReg, unsigned &Offset, const TargetRegisterInfo *TRI) const { @@ -855,23 +840,21 @@ public: return false; } - /// \brief Can this target fuse the given instructions if they are scheduled + /// Can this target fuse the given instructions if they are scheduled /// adjacent. virtual bool shouldScheduleAdjacent(MachineInstr* First, MachineInstr *Second) const { return false; } - /// ReverseBranchCondition - Reverses the branch condition of the specified - /// condition list, returning false on success and true if it cannot be - /// reversed. + /// Reverses the branch condition of the specified condition list, + /// returning false on success and true if it cannot be reversed. virtual bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { return true; } - /// insertNoop - Insert a noop into the instruction stream at the specified - /// point. + /// Insert a noop into the instruction stream at the specified point. virtual void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const; @@ -880,23 +863,22 @@ public: virtual void getNoopForMachoTarget(MCInst &NopInst) const; - /// isPredicated - Returns true if the instruction is already predicated. - /// + /// Returns true if the instruction is already predicated. virtual bool isPredicated(const MachineInstr *MI) const { return false; } - /// isUnpredicatedTerminator - Returns true if the instruction is a + /// Returns true if the instruction is a /// terminator instruction that has not been predicated. virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const; - /// PredicateInstruction - Convert the instruction into a predicated - /// instruction. It returns true if the operation was successful. + /// Convert the instruction into a predicated instruction. + /// It returns true if the operation was successful. virtual bool PredicateInstruction(MachineInstr *MI, const SmallVectorImpl<MachineOperand> &Pred) const; - /// SubsumesPredicate - Returns true if the first specified predicate + /// Returns true if the first specified predicate /// subsumes the second, e.g. GE subsumes GT. virtual bool SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1, @@ -904,7 +886,7 @@ public: return false; } - /// DefinesPredicate - If the specified instruction defines any predicate + /// If the specified instruction defines any predicate /// or condition code register(s) used for predication, returns true as well /// as the definition predicate(s) by reference. virtual bool DefinesPredicate(MachineInstr *MI, @@ -912,22 +894,21 @@ public: return false; } - /// isPredicable - Return true if the specified instruction can be predicated. + /// Return true if the specified instruction can be predicated. /// By default, this returns true for every instruction with a /// PredicateOperand. virtual bool isPredicable(MachineInstr *MI) const { return MI->getDesc().isPredicable(); } - /// isSafeToMoveRegClassDefs - Return true if it's safe to move a machine + /// Return true if it's safe to move a machine /// instruction that defines the specified register class. virtual bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const { return true; } - /// isSchedulingBoundary - Test if the given instruction should be - /// considered a scheduling boundary. This primarily includes labels and - /// terminators. + /// Test if the given instruction should be considered a scheduling boundary. + /// This primarily includes labels and terminators. virtual bool isSchedulingBoundary(const MachineInstr *MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const; @@ -937,23 +918,20 @@ 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 before - /// register allocation. + /// Allocate and return a hazard recognizer to use for this target when + /// scheduling the machine instructions before register allocation. virtual ScheduleHazardRecognizer* CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const; - /// CreateTargetMIHazardRecognizer - Allocate and return a hazard recognizer - /// to use for this target when scheduling the machine instructions before - /// register allocation. + /// Allocate and return a hazard recognizer to use for this target when + /// scheduling the machine instructions before register allocation. virtual ScheduleHazardRecognizer* CreateTargetMIHazardRecognizer(const InstrItineraryData*, const ScheduleDAG *DAG) const; - /// CreateTargetPostRAHazardRecognizer - Allocate and return a hazard - /// recognizer to use for this target when scheduling the machine instructions - /// after register allocation. + /// 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; @@ -962,7 +940,7 @@ public: /// targets may choose to honor. bool usePreRAHazardRecognizer() const; - /// analyzeCompare - For a comparison instruction, return the source registers + /// For a comparison instruction, return the source registers /// in SrcReg and SrcReg2 if having two register operands, and the value it /// compares against in CmpValue. Return true if the comparison instruction /// can be analyzed. @@ -972,7 +950,7 @@ public: return false; } - /// optimizeCompareInstr - See if the comparison instruction can be converted + /// See if the comparison instruction can be converted /// into something more efficient. E.g., on ARM most instructions can set the /// flags register, obviating the need for a separate CMP. virtual bool optimizeCompareInstr(MachineInstr *CmpInstr, @@ -983,8 +961,8 @@ public: } virtual bool optimizeCondBranch(MachineInstr *MI) const { return false; } - /// optimizeLoadInstr - Try to remove the load by folding it to a register - /// operand at the use. We fold the load instructions if and only if the + /// Try to remove the load by folding it to a register operand at the use. + /// We fold the load instructions if and only if the /// def and use are in the same BB. We only look at one load and see /// whether it can be folded into MI. FoldAsLoadDefReg is the virtual register /// defined by the load we are trying to fold. DefMI returns the machine @@ -997,8 +975,8 @@ public: return nullptr; } - /// FoldImmediate - 'Reg' is known to be defined by a move immediate - /// instruction, try to fold the immediate into the use instruction. + /// 'Reg' is known to be defined by a move immediate instruction, + /// try to fold the immediate into the use instruction. /// If MRI->hasOneNonDBGUse(Reg) is true, and this function returns true, /// then the caller may assume that DefMI has been erased from its parent /// block. The caller may assume that it will not be erased by this @@ -1008,14 +986,14 @@ public: return false; } - /// getNumMicroOps - Return the number of u-operations the given machine + /// Return the number of u-operations the given machine /// instruction will be decoded to on the target cpu. The itinerary's /// IssueWidth is the number of microops that can be dispatched each /// cycle. An instruction with zero microops takes no dispatch resources. virtual unsigned getNumMicroOps(const InstrItineraryData *ItinData, const MachineInstr *MI) const; - /// isZeroCost - Return true for pseudo instructions that don't consume any + /// 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. @@ -1027,27 +1005,27 @@ public: SDNode *DefNode, unsigned DefIdx, SDNode *UseNode, unsigned UseIdx) const; - /// getOperandLatency - Compute and return the use operand latency of a given - /// pair of def and use. + /// 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 /// operand latency. But it may not be possible for instructions with variable /// number of defs / uses. /// - /// This is a raw interface to the itinerary that may be directly overriden by - /// a target. Use computeOperandLatency to get the best estimate of latency. + /// This is a raw interface to the itinerary that may be directly overridden + /// by a target. Use computeOperandLatency to get the best estimate of + /// latency. virtual int getOperandLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *UseMI, unsigned UseIdx) const; - /// computeOperandLatency - Compute and return the latency of the given data + /// Compute and return the latency of the given data /// dependent def and use when the operand indices are already known. unsigned computeOperandLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *UseMI, unsigned UseIdx) const; - /// getInstrLatency - Compute the instruction latency of a given instruction. + /// Compute the instruction latency of a given instruction. /// If the instruction has higher cost when predicated, it's returned via /// PredCost. virtual unsigned getInstrLatency(const InstrItineraryData *ItinData, @@ -1066,14 +1044,13 @@ public: int computeDefOperandLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI) const; - /// isHighLatencyDef - Return true if this opcode has high latency to its - /// result. + /// 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 + /// Compute operand latency between a def of 'Reg' + /// and a use in the current loop. Return true if the target considered /// it 'high'. This is used by optimization passes such as machine LICM to - /// determine whether it makes sense to hoist an instruction out even in + /// determine whether it makes sense to hoist an instruction out even in a /// high register pressure situation. virtual bool hasHighOperandLatency(const InstrItineraryData *ItinData, @@ -1083,19 +1060,19 @@ public: return false; } - /// hasLowDefLatency - Compute operand latency of a def of 'Reg', return true + /// Compute operand latency of a def of 'Reg'. Return true /// if the target considered it 'low'. virtual bool hasLowDefLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx) const; - /// verifyInstruction - Perform target specific instruction verification. + /// Perform target-specific instruction verification. virtual bool verifyInstruction(const MachineInstr *MI, StringRef &ErrInfo) const { return true; } - /// getExecutionDomain - Return the current execution domain and bit mask of + /// Return the current execution domain and bit mask of /// possible domains for instruction. /// /// Some micro-architectures have multiple execution domains, and multiple @@ -1119,15 +1096,14 @@ public: return std::make_pair(0, 0); } - /// setExecutionDomain - Change the opcode of MI to execute in Domain. + /// Change the opcode of MI to execute in Domain. /// /// The bit (1 << Domain) must be set in the mask returned from /// getExecutionDomain(MI). - /// virtual void setExecutionDomain(MachineInstr *MI, unsigned Domain) const {} - /// getPartialRegUpdateClearance - Returns the preferred minimum clearance + /// Returns the preferred minimum clearance /// before an instruction with an unwanted partial register update. /// /// Some instructions only write part of a register, and implicitly need to @@ -1176,7 +1152,7 @@ public: /// \brief Return the minimum clearance before an instruction that reads an /// unused register. /// - /// For example, AVX instructions may copy part of an register operand into + /// For example, AVX instructions may copy part of a register operand into /// the unused high bits of the destination register. /// /// vcvtsi2sdq %rax, %xmm0<undef>, %xmm14 @@ -1193,7 +1169,7 @@ public: return 0; } - /// breakPartialRegDependency - Insert a dependency-breaking instruction + /// Insert a dependency-breaking instruction /// before MI to eliminate an unwanted dependency on OpNum. /// /// If it wasn't possible to avoid a def in the last N instructions before MI @@ -1220,10 +1196,10 @@ public: return nullptr; } - // areMemAccessesTriviallyDisjoint - Sometimes, it is possible for the target + // Sometimes, it is possible for the target // to tell, even without aliasing information, that two MIs access different // memory addresses. This function returns true if two MIs access different - // memory addresses, and false otherwise. + // memory addresses and false otherwise. virtual bool areMemAccessesTriviallyDisjoint(MachineInstr *MIa, MachineInstr *MIb, AliasAnalysis *AA = nullptr) const { @@ -1234,8 +1210,16 @@ public: return false; } + /// \brief Return the value to use for the MachineCSE's LookAheadLimit, + /// which is a heuristic used for CSE'ing phys reg defs. + virtual unsigned getMachineCSELookAheadLimit () const { + // The default lookahead is small to prevent unprofitable quadratic + // behavior. + return 5; + } + private: - int CallFrameSetupOpcode, CallFrameDestroyOpcode; + unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode; }; } // End llvm namespace diff --git a/include/llvm/Target/TargetIntrinsicInfo.h b/include/llvm/Target/TargetIntrinsicInfo.h index 71c0166d49b0..c630f5b12a15 100644 --- a/include/llvm/Target/TargetIntrinsicInfo.h +++ b/include/llvm/Target/TargetIntrinsicInfo.h @@ -28,8 +28,8 @@ class Type; /// TargetIntrinsicInfo - Interface to description of machine instruction set /// class TargetIntrinsicInfo { - TargetIntrinsicInfo(const TargetIntrinsicInfo &) LLVM_DELETED_FUNCTION; - void operator=(const TargetIntrinsicInfo &) LLVM_DELETED_FUNCTION; + TargetIntrinsicInfo(const TargetIntrinsicInfo &) = delete; + void operator=(const TargetIntrinsicInfo &) = delete; public: TargetIntrinsicInfo(); virtual ~TargetIntrinsicInfo(); diff --git a/include/llvm/Target/TargetLibraryInfo.h b/include/llvm/Target/TargetLibraryInfo.h deleted file mode 100644 index 46f87b93b001..000000000000 --- a/include/llvm/Target/TargetLibraryInfo.h +++ /dev/null @@ -1,802 +0,0 @@ -//===-- 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/ADT/DenseMap.h" -#include "llvm/Pass.h" - -namespace llvm { - class Triple; - - namespace LibFunc { - enum Func { - /// int _IO_getc(_IO_FILE * __fp); - under_IO_getc, - /// int _IO_putc(int __c, _IO_FILE * __fp); - under_IO_putc, - /// void operator delete[](void*); - ZdaPv, - /// void operator delete[](void*, nothrow); - ZdaPvRKSt9nothrow_t, - /// void operator delete[](void*, unsigned int); - ZdaPvj, - /// void operator delete[](void*, unsigned long); - ZdaPvm, - /// void operator delete(void*); - ZdlPv, - /// void operator delete(void*, nothrow); - ZdlPvRKSt9nothrow_t, - /// void operator delete(void*, unsigned int); - ZdlPvj, - /// void operator delete(void*, unsigned long); - ZdlPvm, - /// void *new[](unsigned int); - Znaj, - /// void *new[](unsigned int, nothrow); - ZnajRKSt9nothrow_t, - /// void *new[](unsigned long); - Znam, - /// void *new[](unsigned long, nothrow); - ZnamRKSt9nothrow_t, - /// void *new(unsigned int); - Znwj, - /// void *new(unsigned int, nothrow); - ZnwjRKSt9nothrow_t, - /// void *new(unsigned long); - Znwm, - /// void *new(unsigned long, nothrow); - ZnwmRKSt9nothrow_t, - /// double __cospi(double x); - cospi, - /// float __cospif(float x); - cospif, - /// int __cxa_atexit(void (*f)(void *), void *p, void *d); - cxa_atexit, - /// void __cxa_guard_abort(guard_t *guard); - /// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi. - cxa_guard_abort, - /// int __cxa_guard_acquire(guard_t *guard); - cxa_guard_acquire, - /// void __cxa_guard_release(guard_t *guard); - cxa_guard_release, - /// int __isoc99_scanf (const char *format, ...) - dunder_isoc99_scanf, - /// int __isoc99_sscanf(const char *s, const char *format, ...) - dunder_isoc99_sscanf, - /// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size); - memcpy_chk, - /// void *__memmove_chk(void *s1, const void *s2, size_t n, - /// size_t s1size); - memmove_chk, - /// void *__memset_chk(void *s, char v, size_t n, size_t s1size); - memset_chk, - /// double __sincospi_stret(double x); - sincospi_stret, - /// float __sincospif_stret(float x); - sincospif_stret, - /// double __sinpi(double x); - sinpi, - /// float __sinpif(float x); - sinpif, - /// double __sqrt_finite(double x); - sqrt_finite, - /// float __sqrt_finite(float x); - sqrtf_finite, - /// long double __sqrt_finite(long double x); - sqrtl_finite, - /// char *__stpcpy_chk(char *s1, const char *s2, size_t s1size); - stpcpy_chk, - /// char *__stpncpy_chk(char *s1, const char *s2, size_t n, - /// size_t s1size); - stpncpy_chk, - /// char *__strcpy_chk(char *s1, const char *s2, size_t s1size); - strcpy_chk, - /// char * __strdup(const char *s); - dunder_strdup, - /// char *__strncpy_chk(char *s1, const char *s2, size_t n, - /// size_t s1size); - strncpy_chk, - /// char *__strndup(const char *s, size_t n); - dunder_strndup, - /// char * __strtok_r(char *s, const char *delim, char **save_ptr); - dunder_strtok_r, - /// int abs(int j); - abs, - /// int access(const char *path, int amode); - access, - /// double acos(double x); - acos, - /// float acosf(float x); - acosf, - /// double acosh(double x); - acosh, - /// float acoshf(float x); - acoshf, - /// long double acoshl(long double x); - acoshl, - /// long double acosl(long double x); - acosl, - /// double asin(double x); - asin, - /// float asinf(float x); - asinf, - /// double asinh(double x); - asinh, - /// float asinhf(float x); - asinhf, - /// long double asinhl(long double x); - asinhl, - /// long double asinl(long double x); - asinl, - /// double atan(double x); - atan, - /// double atan2(double y, double x); - atan2, - /// float atan2f(float y, float x); - atan2f, - /// long double atan2l(long double y, long double x); - atan2l, - /// float atanf(float x); - atanf, - /// double atanh(double x); - atanh, - /// float atanhf(float x); - atanhf, - /// long double atanhl(long double x); - atanhl, - /// long double atanl(long double x); - atanl, - /// double atof(const char *str); - atof, - /// int atoi(const char *str); - atoi, - /// long atol(const char *str); - atol, - /// long long atoll(const char *nptr); - atoll, - /// int bcmp(const void *s1, const void *s2, size_t n); - bcmp, - /// void bcopy(const void *s1, void *s2, size_t n); - bcopy, - /// void bzero(void *s, size_t n); - bzero, - /// void *calloc(size_t count, size_t size); - calloc, - /// double cbrt(double x); - cbrt, - /// float cbrtf(float x); - cbrtf, - /// long double cbrtl(long double x); - cbrtl, - /// double ceil(double x); - ceil, - /// float ceilf(float x); - ceilf, - /// long double ceill(long double x); - ceill, - /// int chmod(const char *path, mode_t mode); - chmod, - /// int chown(const char *path, uid_t owner, gid_t group); - chown, - /// void clearerr(FILE *stream); - clearerr, - /// int closedir(DIR *dirp); - closedir, - /// double copysign(double x, double y); - copysign, - /// float copysignf(float x, float y); - copysignf, - /// long double copysignl(long double x, long double y); - copysignl, - /// double cos(double x); - cos, - /// float cosf(float x); - cosf, - /// double cosh(double x); - cosh, - /// float coshf(float x); - coshf, - /// long double coshl(long double x); - coshl, - /// long double cosl(long double x); - cosl, - /// char *ctermid(char *s); - ctermid, - /// double exp(double x); - exp, - /// double exp10(double x); - exp10, - /// float exp10f(float x); - exp10f, - /// long double exp10l(long double x); - exp10l, - /// double exp2(double x); - exp2, - /// float exp2f(float x); - exp2f, - /// long double exp2l(long double x); - exp2l, - /// float expf(float x); - expf, - /// long double expl(long double x); - expl, - /// double expm1(double x); - expm1, - /// float expm1f(float x); - expm1f, - /// long double expm1l(long double x); - expm1l, - /// double fabs(double x); - fabs, - /// float fabsf(float x); - fabsf, - /// long double fabsl(long double x); - fabsl, - /// int fclose(FILE *stream); - fclose, - /// FILE *fdopen(int fildes, const char *mode); - fdopen, - /// int feof(FILE *stream); - feof, - /// int ferror(FILE *stream); - ferror, - /// int fflush(FILE *stream); - fflush, - /// int ffs(int i); - ffs, - /// int ffsl(long int i); - ffsl, - /// int ffsll(long long int i); - ffsll, - /// int fgetc(FILE *stream); - fgetc, - /// int fgetpos(FILE *stream, fpos_t *pos); - fgetpos, - /// char *fgets(char *s, int n, FILE *stream); - fgets, - /// int fileno(FILE *stream); - fileno, - /// int fiprintf(FILE *stream, const char *format, ...); - fiprintf, - /// void flockfile(FILE *file); - flockfile, - /// double floor(double x); - floor, - /// float floorf(float x); - floorf, - /// long double floorl(long double x); - floorl, - /// double fmax(double x, double y); - fmax, - /// float fmaxf(float x, float y); - fmaxf, - /// long double fmaxl(long double x, long double y); - fmaxl, - /// double fmin(double x, double y); - fmin, - /// float fminf(float x, float y); - fminf, - /// long double fminl(long double x, long double y); - fminl, - /// double fmod(double x, double y); - fmod, - /// float fmodf(float x, float y); - fmodf, - /// long double fmodl(long double x, long double y); - fmodl, - /// FILE *fopen(const char *filename, const char *mode); - fopen, - /// FILE *fopen64(const char *filename, const char *opentype) - fopen64, - /// int fprintf(FILE *stream, const char *format, ...); - fprintf, - /// int fputc(int c, FILE *stream); - fputc, - /// int fputs(const char *s, FILE *stream); - fputs, - /// size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream); - fread, - /// void free(void *ptr); - free, - /// double frexp(double num, int *exp); - frexp, - /// float frexpf(float num, int *exp); - frexpf, - /// long double frexpl(long double num, int *exp); - frexpl, - /// int fscanf(FILE *stream, const char *format, ... ); - fscanf, - /// int fseek(FILE *stream, long offset, int whence); - fseek, - /// int fseeko(FILE *stream, off_t offset, int whence); - fseeko, - /// int fseeko64(FILE *stream, off64_t offset, int whence) - fseeko64, - /// int fsetpos(FILE *stream, const fpos_t *pos); - fsetpos, - /// int fstat(int fildes, struct stat *buf); - fstat, - /// int fstat64(int filedes, struct stat64 *buf) - fstat64, - /// int fstatvfs(int fildes, struct statvfs *buf); - fstatvfs, - /// int fstatvfs64(int fildes, struct statvfs64 *buf); - fstatvfs64, - /// long ftell(FILE *stream); - ftell, - /// off_t ftello(FILE *stream); - ftello, - /// off64_t ftello64(FILE *stream) - ftello64, - /// int ftrylockfile(FILE *file); - ftrylockfile, - /// void funlockfile(FILE *file); - funlockfile, - /// size_t fwrite(const void *ptr, size_t size, size_t nitems, - /// FILE *stream); - fwrite, - /// int getc(FILE *stream); - getc, - /// int getc_unlocked(FILE *stream); - getc_unlocked, - /// int getchar(void); - getchar, - /// char *getenv(const char *name); - getenv, - /// int getitimer(int which, struct itimerval *value); - getitimer, - /// int getlogin_r(char *name, size_t namesize); - getlogin_r, - /// struct passwd *getpwnam(const char *name); - getpwnam, - /// char *gets(char *s); - gets, - /// int gettimeofday(struct timeval *tp, void *tzp); - gettimeofday, - /// uint32_t htonl(uint32_t hostlong); - htonl, - /// uint16_t htons(uint16_t hostshort); - htons, - /// int iprintf(const char *format, ...); - iprintf, - /// int isascii(int c); - isascii, - /// int isdigit(int c); - isdigit, - /// long int labs(long int j); - labs, - /// int lchown(const char *path, uid_t owner, gid_t group); - lchown, - /// double ldexp(double x, int n); - ldexp, - /// float ldexpf(float x, int n); - ldexpf, - /// long double ldexpl(long double x, int n); - ldexpl, - /// long long int llabs(long long int j); - llabs, - /// double log(double x); - log, - /// double log10(double x); - log10, - /// float log10f(float x); - log10f, - /// long double log10l(long double x); - log10l, - /// double log1p(double x); - log1p, - /// float log1pf(float x); - log1pf, - /// long double log1pl(long double x); - log1pl, - /// double log2(double x); - log2, - /// float log2f(float x); - log2f, - /// double long double log2l(long double x); - log2l, - /// double logb(double x); - logb, - /// float logbf(float x); - logbf, - /// long double logbl(long double x); - logbl, - /// float logf(float x); - logf, - /// long double logl(long double x); - logl, - /// int lstat(const char *path, struct stat *buf); - lstat, - /// int lstat64(const char *path, struct stat64 *buf); - lstat64, - /// void *malloc(size_t size); - malloc, - /// void *memalign(size_t boundary, size_t size); - memalign, - /// void *memccpy(void *s1, const void *s2, int c, size_t n); - memccpy, - /// void *memchr(const void *s, int c, size_t n); - memchr, - /// int memcmp(const void *s1, const void *s2, size_t n); - memcmp, - /// void *memcpy(void *s1, const void *s2, size_t n); - memcpy, - /// void *memmove(void *s1, const void *s2, size_t n); - memmove, - // void *memrchr(const void *s, int c, size_t n); - memrchr, - /// void *memset(void *b, int c, size_t len); - memset, - /// void memset_pattern16(void *b, const void *pattern16, size_t len); - memset_pattern16, - /// int mkdir(const char *path, mode_t mode); - mkdir, - /// time_t mktime(struct tm *timeptr); - mktime, - /// double modf(double x, double *iptr); - modf, - /// float modff(float, float *iptr); - modff, - /// long double modfl(long double value, long double *iptr); - modfl, - /// double nearbyint(double x); - nearbyint, - /// float nearbyintf(float x); - nearbyintf, - /// long double nearbyintl(long double x); - nearbyintl, - /// uint32_t ntohl(uint32_t netlong); - ntohl, - /// uint16_t ntohs(uint16_t netshort); - ntohs, - /// int open(const char *path, int oflag, ... ); - open, - /// int open64(const char *filename, int flags[, mode_t mode]) - open64, - /// DIR *opendir(const char *dirname); - opendir, - /// int pclose(FILE *stream); - pclose, - /// void perror(const char *s); - perror, - /// FILE *popen(const char *command, const char *mode); - popen, - /// int posix_memalign(void **memptr, size_t alignment, size_t size); - posix_memalign, - /// double pow(double x, double y); - pow, - /// float powf(float x, float y); - powf, - /// long double powl(long double x, long double y); - powl, - /// ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); - pread, - /// int printf(const char *format, ...); - printf, - /// int putc(int c, FILE *stream); - putc, - /// int putchar(int c); - putchar, - /// int puts(const char *s); - puts, - /// ssize_t pwrite(int fildes, const void *buf, size_t nbyte, - /// off_t offset); - pwrite, - /// void qsort(void *base, size_t nel, size_t width, - /// int (*compar)(const void *, const void *)); - qsort, - /// ssize_t read(int fildes, void *buf, size_t nbyte); - read, - /// ssize_t readlink(const char *path, char *buf, size_t bufsize); - readlink, - /// void *realloc(void *ptr, size_t size); - realloc, - /// void *reallocf(void *ptr, size_t size); - reallocf, - /// char *realpath(const char *file_name, char *resolved_name); - realpath, - /// int remove(const char *path); - remove, - /// int rename(const char *old, const char *new); - rename, - /// void rewind(FILE *stream); - rewind, - /// double rint(double x); - rint, - /// float rintf(float x); - rintf, - /// long double rintl(long double x); - rintl, - /// int rmdir(const char *path); - rmdir, - /// double round(double x); - round, - /// float roundf(float x); - roundf, - /// long double roundl(long double x); - roundl, - /// int scanf(const char *restrict format, ... ); - scanf, - /// void setbuf(FILE *stream, char *buf); - setbuf, - /// int setitimer(int which, const struct itimerval *value, - /// struct itimerval *ovalue); - setitimer, - /// int setvbuf(FILE *stream, char *buf, int type, size_t size); - setvbuf, - /// double sin(double x); - sin, - /// float sinf(float x); - sinf, - /// double sinh(double x); - sinh, - /// float sinhf(float x); - sinhf, - /// long double sinhl(long double x); - sinhl, - /// long double sinl(long double x); - sinl, - /// int siprintf(char *str, const char *format, ...); - siprintf, - /// int snprintf(char *s, size_t n, const char *format, ...); - snprintf, - /// int sprintf(char *str, const char *format, ...); - sprintf, - /// double sqrt(double x); - sqrt, - /// float sqrtf(float x); - sqrtf, - /// long double sqrtl(long double x); - sqrtl, - /// int sscanf(const char *s, const char *format, ... ); - sscanf, - /// int stat(const char *path, struct stat *buf); - stat, - /// int stat64(const char *path, struct stat64 *buf); - stat64, - /// int statvfs(const char *path, struct statvfs *buf); - statvfs, - /// int statvfs64(const char *path, struct statvfs64 *buf) - statvfs64, - /// char *stpcpy(char *s1, const char *s2); - stpcpy, - /// char *stpncpy(char *s1, const char *s2, size_t n); - stpncpy, - /// int strcasecmp(const char *s1, const char *s2); - strcasecmp, - /// char *strcat(char *s1, const char *s2); - strcat, - /// char *strchr(const char *s, int c); - strchr, - /// int strcmp(const char *s1, const char *s2); - strcmp, - /// int strcoll(const char *s1, const char *s2); - strcoll, - /// char *strcpy(char *s1, const char *s2); - strcpy, - /// size_t strcspn(const char *s1, const char *s2); - strcspn, - /// char *strdup(const char *s1); - strdup, - /// size_t strlen(const char *s); - strlen, - /// int strncasecmp(const char *s1, const char *s2, size_t n); - strncasecmp, - /// char *strncat(char *s1, const char *s2, size_t n); - strncat, - /// int strncmp(const char *s1, const char *s2, size_t n); - strncmp, - /// char *strncpy(char *s1, const char *s2, size_t n); - strncpy, - /// char *strndup(const char *s1, size_t n); - strndup, - /// size_t strnlen(const char *s, size_t maxlen); - strnlen, - /// char *strpbrk(const char *s1, const char *s2); - strpbrk, - /// char *strrchr(const char *s, int c); - strrchr, - /// size_t strspn(const char *s1, const char *s2); - strspn, - /// char *strstr(const char *s1, const char *s2); - strstr, - /// double strtod(const char *nptr, char **endptr); - strtod, - /// float strtof(const char *nptr, char **endptr); - strtof, - // char *strtok(char *s1, const char *s2); - strtok, - // char *strtok_r(char *s, const char *sep, char **lasts); - strtok_r, - /// long int strtol(const char *nptr, char **endptr, int base); - strtol, - /// long double strtold(const char *nptr, char **endptr); - strtold, - /// long long int strtoll(const char *nptr, char **endptr, int base); - strtoll, - /// unsigned long int strtoul(const char *nptr, char **endptr, int base); - strtoul, - /// unsigned long long int strtoull(const char *nptr, char **endptr, - /// int base); - strtoull, - /// size_t strxfrm(char *s1, const char *s2, size_t n); - strxfrm, - /// int system(const char *command); - system, - /// double tan(double x); - tan, - /// float tanf(float x); - tanf, - /// double tanh(double x); - tanh, - /// float tanhf(float x); - tanhf, - /// long double tanhl(long double x); - tanhl, - /// long double tanl(long double x); - tanl, - /// clock_t times(struct tms *buffer); - times, - /// FILE *tmpfile(void); - tmpfile, - /// FILE *tmpfile64(void) - tmpfile64, - /// int toascii(int c); - toascii, - /// double trunc(double x); - trunc, - /// float truncf(float x); - truncf, - /// long double truncl(long double x); - truncl, - /// int uname(struct utsname *name); - uname, - /// int ungetc(int c, FILE *stream); - ungetc, - /// int unlink(const char *path); - unlink, - /// int unsetenv(const char *name); - unsetenv, - /// int utime(const char *path, const struct utimbuf *times); - utime, - /// int utimes(const char *path, const struct timeval times[2]); - utimes, - /// void *valloc(size_t size); - valloc, - /// int vfprintf(FILE *stream, const char *format, va_list ap); - vfprintf, - /// int vfscanf(FILE *stream, const char *format, va_list arg); - vfscanf, - /// int vprintf(const char *restrict format, va_list ap); - vprintf, - /// int vscanf(const char *format, va_list arg); - vscanf, - /// int vsnprintf(char *s, size_t n, const char *format, va_list ap); - vsnprintf, - /// int vsprintf(char *s, const char *format, va_list ap); - vsprintf, - /// int vsscanf(const char *s, const char *format, va_list arg); - vsscanf, - /// ssize_t write(int fildes, const void *buf, size_t nbyte); - write, - - 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 { - virtual void anchor(); - unsigned char AvailableArray[(LibFunc::NumLibFuncs+3)/4]; - llvm::DenseMap<unsigned, std::string> CustomNames; - static const char* StandardNames[LibFunc::NumLibFuncs]; - - enum AvailabilityState { - StandardName = 3, // (memset to all ones) - CustomName = 1, - Unavailable = 0 // (memset to all zeros) - }; - void setState(LibFunc::Func F, AvailabilityState State) { - AvailableArray[F/4] &= ~(3 << 2*(F&3)); - AvailableArray[F/4] |= State << 2*(F&3); - } - AvailabilityState getState(LibFunc::Func F) const { - return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3); - } - -public: - static char ID; - TargetLibraryInfo(); - TargetLibraryInfo(const Triple &T); - explicit TargetLibraryInfo(const TargetLibraryInfo &TLI); - - /// getLibFunc - Search for a particular function name. If it is one of the - /// known library functions, return true and set F to the corresponding value. - bool getLibFunc(StringRef funcName, LibFunc::Func &F) const; - - /// 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 getState(F) != Unavailable; - } - - /// hasOptimizedCodeGen - Return true if the function is both available as - /// a builtin and a candidate for optimized code generation. - bool hasOptimizedCodeGen(LibFunc::Func F) const { - if (getState(F) == Unavailable) - return false; - switch (F) { - default: break; - case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl: - case LibFunc::fabs: case LibFunc::fabsf: case LibFunc::fabsl: - case LibFunc::sin: case LibFunc::sinf: case LibFunc::sinl: - case LibFunc::cos: case LibFunc::cosf: case LibFunc::cosl: - case LibFunc::sqrt: case LibFunc::sqrtf: case LibFunc::sqrtl: - case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite: - case LibFunc::sqrtl_finite: - case LibFunc::fmax: case LibFunc::fmaxf: case LibFunc::fmaxl: - case LibFunc::fmin: case LibFunc::fminf: case LibFunc::fminl: - case LibFunc::floor: case LibFunc::floorf: case LibFunc::floorl: - case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl: - case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill: - case LibFunc::rint: case LibFunc::rintf: case LibFunc::rintl: - case LibFunc::round: case LibFunc::roundf: case LibFunc::roundl: - case LibFunc::trunc: case LibFunc::truncf: case LibFunc::truncl: - case LibFunc::log2: case LibFunc::log2f: case LibFunc::log2l: - case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l: - case LibFunc::memcmp: case LibFunc::strcmp: case LibFunc::strcpy: - case LibFunc::stpcpy: case LibFunc::strlen: case LibFunc::strnlen: - case LibFunc::memchr: - return true; - } - return false; - } - - StringRef getName(LibFunc::Func F) const { - AvailabilityState State = getState(F); - if (State == Unavailable) - return StringRef(); - if (State == StandardName) - return StandardNames[F]; - assert(State == CustomName); - return CustomNames.find(F)->second; - } - - /// setUnavailable - this can be used by whatever sets up TargetLibraryInfo to - /// ban use of specific library functions. - void setUnavailable(LibFunc::Func F) { - setState(F, Unavailable); - } - - void setAvailable(LibFunc::Func F) { - setState(F, StandardName); - } - - void setAvailableWithName(LibFunc::Func F, StringRef Name) { - if (StandardNames[F] != Name) { - setState(F, CustomName); - CustomNames[F] = Name; - assert(CustomNames.find(F) != CustomNames.end()); - } else { - setState(F, StandardName); - } - } - - /// 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 43d6f2772c5e..e2fe9e85fc92 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -77,8 +77,8 @@ namespace llvm { /// This base class for TargetLowering contains the SelectionDAG-independent /// parts that can be used from the rest of CodeGen. class TargetLoweringBase { - TargetLoweringBase(const TargetLoweringBase&) LLVM_DELETED_FUNCTION; - void operator=(const TargetLoweringBase&) LLVM_DELETED_FUNCTION; + TargetLoweringBase(const TargetLoweringBase&) = delete; + void operator=(const TargetLoweringBase&) = delete; public: /// This enum indicates whether operations are valid for a target, and if not, @@ -100,7 +100,8 @@ public: TypeExpandFloat, // Split this float into two of half the size. TypeScalarizeVector, // Replace this one-element vector with its element. TypeSplitVector, // Split this vector into two of half the size. - TypeWidenVector // This vector should be widened into a larger vector. + TypeWidenVector, // This vector should be widened into a larger vector. + TypePromoteFloat // Replace this float with a larger one. }; /// LegalizeKind holds the legalization kind that needs to happen to EVT @@ -123,6 +124,18 @@ public: // mask (ex: x86 blends). }; + /// Enum that specifies what a AtomicRMWInst is expanded to, if at all. Exists + /// because different targets have different levels of support for these + /// atomic RMW instructions, and also have different options w.r.t. what they + /// should expand to. + enum class AtomicRMWExpansionKind { + None, // Don't expand the instruction. + LLSC, // Expand the instruction into loadlinked/storeconditional; used + // by ARM/AArch64. Implies `hasLoadLinkedStoreConditional` + // returns true. + CmpXChg, // Expand the instruction into cmpxchg; used by at least X86. + }; + static ISD::NodeType getExtendForContent(BooleanContent Content) { switch (Content) { case UndefinedBooleanContent: @@ -148,13 +161,11 @@ protected: public: const TargetMachine &getTargetMachine() const { return TM; } - const DataLayout *getDataLayout() const { return DL; } - const TargetLoweringObjectFile &getObjFileLowering() const { - return *TM.getObjFileLowering(); - } + const DataLayout *getDataLayout() const { return TM.getDataLayout(); } bool isBigEndian() const { return !IsLittleEndian; } bool isLittleEndian() const { return IsLittleEndian; } + virtual bool useSoftFloat() const { return false; } /// Return the pointer type for the given address space, defaults to /// the pointer type from the data layout. @@ -247,19 +258,29 @@ public: /// isLoadBitCastBeneficial() - Return true if the following transform /// is beneficial. /// fold (conv (load x)) -> (load (conv*)x) - /// On architectures that don't natively support some vector loads efficiently, - /// casting the load to a smaller vector of larger types and loading - /// is more efficient, however, this can be undone by optimizations in + /// On architectures that don't natively support some vector loads + /// efficiently, casting the load to a smaller vector of larger types and + /// loading is more efficient, however, this can be undone by optimizations in /// dag combiner. - virtual bool isLoadBitCastBeneficial(EVT /* Load */, EVT /* Bitcast */) const { + virtual bool isLoadBitCastBeneficial(EVT /* Load */, + EVT /* Bitcast */) const { return true; } + /// Return true if it is expected to be cheaper to do a store of a non-zero + /// vector constant with the given size and type for the address space than to + /// store the individual scalar element constants. + virtual bool storeOfVectorConstantIsCheap(EVT MemVT, + unsigned NumElem, + unsigned AddrSpace) const { + return false; + } + /// \brief Return true if it is cheap to speculate a call to intrinsic cttz. virtual bool isCheapToSpeculateCttz() const { return false; } - + /// \brief Return true if it is cheap to speculate a call to intrinsic ctlz. virtual bool isCheapToSpeculateCtlz() const { return false; @@ -562,7 +583,8 @@ public: /// Return how this load with extension should be treated: either it is legal, /// needs to be promoted to a larger size, needs to be expanded to some other /// code sequence, or the target has a custom expander for it. - LegalizeAction getLoadExtAction(unsigned ExtType, EVT ValVT, EVT MemVT) const { + LegalizeAction getLoadExtAction(unsigned ExtType, EVT ValVT, + EVT MemVT) const { if (ValVT.isExtended() || MemVT.isExtended()) return Expand; unsigned ValI = (unsigned) ValVT.getSimpleVT().SimpleTy; unsigned MemI = (unsigned) MemVT.getSimpleVT().SimpleTy; @@ -577,6 +599,14 @@ public: getLoadExtAction(ExtType, ValVT, MemVT) == Legal; } + /// Return true if the specified load with extension is legal or custom + /// on this target. + bool isLoadExtLegalOrCustom(unsigned ExtType, EVT ValVT, EVT MemVT) const { + return ValVT.isSimple() && MemVT.isSimple() && + (getLoadExtAction(ExtType, ValVT, MemVT) == Legal || + getLoadExtAction(ExtType, ValVT, MemVT) == Custom); + } + /// Return how this store with truncation should be treated: either it is /// legal, needs to be promoted to a larger size, needs to be expanded to some /// other code sequence, or the target has a custom expander for it. @@ -954,17 +984,20 @@ public: return false; } - /// Returns the maximal possible offset which can be used for loads / stores - /// from the global. - virtual unsigned getMaximalGlobalOffset() const { - return 0; - } - /// Returns true if a cast between SrcAS and DestAS is a noop. virtual bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const { return false; } + /// Return true if the pointer arguments to CI should be aligned by aligning + /// the object whose address is being passed. If so then MinSize is set to the + /// minimum size the object must be to be aligned and PrefAlign is set to the + /// preferred alignment. + virtual bool shouldAlignPointerArgs(CallInst * /*CI*/, unsigned & /*MinSize*/, + unsigned & /*PrefAlign*/) const { + return false; + } + //===--------------------------------------------------------------------===// /// \name Helpers for TargetTransformInfo implementations /// @{ @@ -1031,8 +1064,9 @@ public: /// seq_cst. But if they are lowered to monotonic accesses, no amount of /// IR-level fences can prevent it. /// @{ - virtual Instruction* emitLeadingFence(IRBuilder<> &Builder, AtomicOrdering Ord, - bool IsStore, bool IsLoad) const { + virtual Instruction *emitLeadingFence(IRBuilder<> &Builder, + AtomicOrdering Ord, bool IsStore, + bool IsLoad) const { if (!getInsertFencesForAtomic()) return nullptr; @@ -1042,8 +1076,9 @@ public: return nullptr; } - virtual Instruction* emitTrailingFence(IRBuilder<> &Builder, AtomicOrdering Ord, - bool IsStore, bool IsLoad) const { + virtual Instruction *emitTrailingFence(IRBuilder<> &Builder, + AtomicOrdering Ord, bool IsStore, + bool IsLoad) const { if (!getInsertFencesForAtomic()) return nullptr; @@ -1060,15 +1095,21 @@ public: return false; } + /// Returns true if arguments should be sign-extended in lib calls. + virtual bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const { + return IsSigned; + } + /// Returns true if the given (atomic) load should be expanded by the /// IR-level AtomicExpand pass into a load-linked instruction /// (through emitLoadLinked()). virtual bool shouldExpandAtomicLoadInIR(LoadInst *LI) const { return false; } - /// Returns true if the given AtomicRMW should be expanded by the - /// IR-level AtomicExpand pass into a loop using LoadLinked/StoreConditional. - virtual bool shouldExpandAtomicRMWInIR(AtomicRMWInst *RMWI) const { - return false; + /// Returns how the IR-level AtomicExpand pass should expand the given + /// AtomicRMW, if at all. Default is to never expand. + virtual AtomicRMWExpansionKind + shouldExpandAtomicRMWInIR(AtomicRMWInst *) const { + return AtomicRMWExpansionKind::None; } /// On some platforms, an AtomicRMW that never actually modifies the value @@ -1082,17 +1123,33 @@ public: /// it succeeds, and nullptr otherwise. /// If shouldExpandAtomicLoadInIR returns true on that load, it will undergo /// another round of expansion. - virtual LoadInst *lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *RMWI) const { + virtual LoadInst * + lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *RMWI) const { return nullptr; } + + /// Returns true if we should normalize + /// select(N0&N1, X, Y) => select(N0, select(N1, X, Y), Y) and + /// select(N0|N1, X, Y) => select(N0, select(N1, X, Y, Y)) if it is likely + /// that it saves us from materializing N0 and N1 in an integer register. + /// Targets that are able to perform and/or on flags should return false here. + virtual bool shouldNormalizeToSelectSequence(LLVMContext &Context, + EVT VT) const { + // If a target has multiple condition registers, then it likely has logical + // operations on those registers. + if (hasMultipleConditionRegisters()) + return false; + // Only do the transform if the value won't be split into multiple + // registers. + LegalizeTypeAction Action = getTypeAction(Context, VT); + return Action != TypeExpandInteger && Action != TypeExpandFloat && + Action != TypeSplitVector; + } + //===--------------------------------------------------------------------===// // TargetLowering Configuration Methods - These methods should be invoked by // the derived class constructor to configure this object for the target. // - - /// \brief Reset the operation actions based on target options. - virtual void resetOperationActions() {} - protected: /// Specify how the target extends the result of integer and floating point /// boolean values from i1 to a wider type. See getBooleanContents. @@ -1230,12 +1287,12 @@ protected: /// Return the largest legal super-reg register class of the register class /// for the specified type and its associated "cost". - virtual std::pair<const TargetRegisterClass*, uint8_t> - findRepresentativeClass(MVT VT) const; + virtual std::pair<const TargetRegisterClass *, uint8_t> + findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const; /// Once all of the register classes are added, this allows us to compute /// derived properties we expose. - void computeRegisterProperties(); + void computeRegisterProperties(const TargetRegisterInfo *TRI); /// Indicate that the specified operation does not work with the specified /// type and indicate what to do about it. @@ -1455,6 +1512,35 @@ public: return false; } + virtual bool isProfitableToHoist(Instruction *I) const { return true; } + + /// Return true if the extension represented by \p I is free. + /// Unlikely the is[Z|FP]ExtFree family which is based on types, + /// this method can use the context provided by \p I to decide + /// whether or not \p I is free. + /// This method extends the behavior of the is[Z|FP]ExtFree family. + /// In other words, if is[Z|FP]Free returns true, then this method + /// returns true as well. The converse is not true. + /// The target can perform the adequate checks by overriding isExtFreeImpl. + /// \pre \p I must be a sign, zero, or fp extension. + bool isExtFree(const Instruction *I) const { + switch (I->getOpcode()) { + case Instruction::FPExt: + if (isFPExtFree(EVT::getEVT(I->getType()))) + return true; + break; + case Instruction::ZExt: + if (isZExtFree(I->getOperand(0)->getType(), I->getType())) + return true; + break; + case Instruction::SExt: + break; + default: + llvm_unreachable("Instruction is not an extension"); + } + return isExtFreeImpl(I); + } + /// Return true if any actual instruction that defines a value of type Ty1 /// implicitly zero-extends the value to Ty2 in the result register. /// @@ -1517,6 +1603,10 @@ public: return false; } + /// Return true if folding a vector load into ExtVal (a sign, zero, or any + /// extend node) is profitable. + virtual bool isVectorLoadExtDesirable(SDValue ExtVal) const { return false; } + /// Return true if an fneg operation is free to the point where it is never /// worthwhile to replace it with a bitwise operation. virtual bool isFNegFree(EVT VT) const { @@ -1606,7 +1696,6 @@ public: private: const TargetMachine &TM; - const DataLayout *DL; /// True if this is a little endian target. bool IsLittleEndian; @@ -1783,136 +1872,8 @@ private: ValueTypeActionImpl ValueTypeActions; -public: - LegalizeKind - getTypeConversion(LLVMContext &Context, EVT VT) const { - // If this is a simple type, use the ComputeRegisterProp mechanism. - if (VT.isSimple()) { - MVT SVT = VT.getSimpleVT(); - assert((unsigned)SVT.SimpleTy < array_lengthof(TransformToType)); - MVT NVT = TransformToType[SVT.SimpleTy]; - LegalizeTypeAction LA = ValueTypeActions.getTypeAction(SVT); - - assert( - (LA == TypeLegal || LA == TypeSoftenFloat || - ValueTypeActions.getTypeAction(NVT) != TypePromoteInteger) - && "Promote may not follow Expand or Promote"); - - if (LA == TypeSplitVector) - return LegalizeKind(LA, EVT::getVectorVT(Context, - SVT.getVectorElementType(), - SVT.getVectorNumElements()/2)); - if (LA == TypeScalarizeVector) - return LegalizeKind(LA, SVT.getVectorElementType()); - return LegalizeKind(LA, NVT); - } - - // Handle Extended Scalar Types. - if (!VT.isVector()) { - assert(VT.isInteger() && "Float types must be simple"); - unsigned BitSize = VT.getSizeInBits(); - // First promote to a power-of-two size, then expand if necessary. - if (BitSize < 8 || !isPowerOf2_32(BitSize)) { - EVT NVT = VT.getRoundIntegerType(Context); - assert(NVT != VT && "Unable to round integer VT"); - LegalizeKind NextStep = getTypeConversion(Context, NVT); - // Avoid multi-step promotion. - if (NextStep.first == TypePromoteInteger) return NextStep; - // Return rounded integer type. - return LegalizeKind(TypePromoteInteger, NVT); - } - - return LegalizeKind(TypeExpandInteger, - EVT::getIntegerVT(Context, VT.getSizeInBits()/2)); - } - - // Handle vector types. - unsigned NumElts = VT.getVectorNumElements(); - EVT EltVT = VT.getVectorElementType(); - - // Vectors with only one element are always scalarized. - if (NumElts == 1) - return LegalizeKind(TypeScalarizeVector, EltVT); - - // Try to widen vector elements until the element type is a power of two and - // promote it to a legal type later on, for example: - // <3 x i8> -> <4 x i8> -> <4 x i32> - if (EltVT.isInteger()) { - // Vectors with a number of elements that is not a power of two are always - // widened, for example <3 x i8> -> <4 x i8>. - if (!VT.isPow2VectorType()) { - NumElts = (unsigned)NextPowerOf2(NumElts); - EVT NVT = EVT::getVectorVT(Context, EltVT, NumElts); - return LegalizeKind(TypeWidenVector, NVT); - } - - // Examine the element type. - LegalizeKind LK = getTypeConversion(Context, EltVT); - - // If type is to be expanded, split the vector. - // <4 x i140> -> <2 x i140> - if (LK.first == TypeExpandInteger) - return LegalizeKind(TypeSplitVector, - EVT::getVectorVT(Context, EltVT, NumElts / 2)); - - // Promote the integer element types until a legal vector type is found - // or until the element integer type is too big. If a legal type was not - // found, fallback to the usual mechanism of widening/splitting the - // vector. - EVT OldEltVT = EltVT; - while (1) { - // Increase the bitwidth of the element to the next pow-of-two - // (which is greater than 8 bits). - EltVT = EVT::getIntegerVT(Context, 1 + EltVT.getSizeInBits() - ).getRoundIntegerType(Context); - - // Stop trying when getting a non-simple element type. - // Note that vector elements may be greater than legal vector element - // types. Example: X86 XMM registers hold 64bit element on 32bit - // systems. - if (!EltVT.isSimple()) break; - - // Build a new vector type and check if it is legal. - MVT NVT = MVT::getVectorVT(EltVT.getSimpleVT(), NumElts); - // Found a legal promoted vector type. - if (NVT != MVT() && ValueTypeActions.getTypeAction(NVT) == TypeLegal) - return LegalizeKind(TypePromoteInteger, - EVT::getVectorVT(Context, EltVT, NumElts)); - } - - // Reset the type to the unexpanded type if we did not find a legal vector - // type with a promoted vector element type. - EltVT = OldEltVT; - } - - // Try to widen the vector until a legal type is found. - // If there is no wider legal type, split the vector. - 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. - if (!EltVT.isSimple()) break; - MVT LargerVector = MVT::getVectorVT(EltVT.getSimpleVT(), NumElts); - if (LargerVector == MVT()) break; - - // If this type is legal then widen the vector. - if (ValueTypeActions.getTypeAction(LargerVector) == TypeLegal) - return LegalizeKind(TypeWidenVector, LargerVector); - } - - // Widen odd vectors to next power of two. - if (!VT.isPow2VectorType()) { - EVT NVT = VT.getPow2VectorType(Context); - return LegalizeKind(TypeWidenVector, NVT); - } - - // Vectors with illegal element types are expanded. - EVT NVT = EVT::getVectorVT(Context, EltVT, VT.getVectorNumElements() / 2); - return LegalizeKind(TypeSplitVector, NVT); - } +private: + LegalizeKind getTypeConversion(LLVMContext &Context, EVT VT) const; private: std::vector<std::pair<MVT, const TargetRegisterClass*> > AvailableRegClasses; @@ -1943,6 +1904,11 @@ private: CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL]; protected: + /// Return true if the extension represented by \p I is free. + /// \pre \p I is a sign, zero, or fp extension and + /// is[Z|FP]ExtFree of the related types is not true. + virtual bool isExtFreeImpl(const Instruction *I) const { return false; } + /// \brief Specify maximum number of store instructions per memset call. /// /// When lowering \@llvm.memset this field specifies the maximum number of @@ -2010,7 +1976,8 @@ protected: /// Replace/modify any TargetFrameIndex operands with a targte-dependent /// sequence of memory operands that is recognized by PrologEpilogInserter. - MachineBasicBlock *emitPatchPoint(MachineInstr *MI, MachineBasicBlock *MBB) const; + MachineBasicBlock *emitPatchPoint(MachineInstr *MI, + MachineBasicBlock *MBB) const; }; /// This class defines information used to lower LLVM code to legal SelectionDAG @@ -2019,8 +1986,8 @@ protected: /// This class also defines callbacks that targets must implement to lower /// target-specific constructs to SelectionDAG operators. class TargetLowering : public TargetLoweringBase { - TargetLowering(const TargetLowering&) LLVM_DELETED_FUNCTION; - void operator=(const TargetLowering&) LLVM_DELETED_FUNCTION; + TargetLowering(const TargetLowering&) = delete; + void operator=(const TargetLowering&) = delete; public: /// NOTE: The TargetMachine owns TLOF. @@ -2080,6 +2047,7 @@ public: ISD::CondCode &CCCode, SDLoc DL) const; /// Returns a pair of (return value, chain). + /// It is an error to pass RTLIB::UNKNOWN_LIBCALL as \p LC. std::pair<SDValue, SDValue> makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, const SDValue *Ops, unsigned NumOps, bool isSigned, @@ -2171,8 +2139,7 @@ public: void AddToWorklist(SDNode *N); void RemoveFromWorklist(SDNode *N); - SDValue CombineTo(SDNode *N, const std::vector<SDValue> &To, - bool AddTo = true); + SDValue CombineTo(SDNode *N, ArrayRef<SDValue> To, bool AddTo = true); SDValue CombineTo(SDNode *N, SDValue Res, bool AddTo = true); SDValue CombineTo(SDNode *N, SDValue Res0, SDValue Res1, bool AddTo = true); @@ -2653,7 +2620,8 @@ public: /// 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; + virtual AsmOperandInfoVector ParseConstraints(const TargetRegisterInfo *TRI, + 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. @@ -2684,10 +2652,19 @@ public: /// pointer. /// /// This should only be used for C_Register constraints. On error, this - /// returns a register number of 0 and a null register class pointer.. - virtual std::pair<unsigned, const TargetRegisterClass*> - getRegForInlineAsmConstraint(const std::string &Constraint, - MVT VT) const; + /// returns a register number of 0 and a null register class pointer. + virtual std::pair<unsigned, const TargetRegisterClass *> + getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, + const std::string &Constraint, MVT VT) const; + + virtual unsigned + getInlineAsmMemConstraint(const std::string &ConstraintCode) const { + if (ConstraintCode == "i") + return InlineAsm::Constraint_i; + else if (ConstraintCode == "m") + return InlineAsm::Constraint_m; + return InlineAsm::Constraint_Unknown; + } /// Try to replace an X constraint, which matches anything, with another that /// has more specific requirements based on the type of the corresponding @@ -2725,7 +2702,7 @@ public: /// Hooks for building estimates in place of slower divisions and square /// roots. - + /// Return a reciprocal square root estimate value for the input operand. /// The RefinementSteps output is the number of Newton-Raphson refinement /// iterations required to generate a sufficient (though not necessarily @@ -2736,10 +2713,9 @@ public: /// If that's true, then return '0' as the number of RefinementSteps to avoid /// any further refinement of the estimate. /// An empty SDValue return means no estimate sequence can be created. - virtual SDValue getRsqrtEstimate(SDValue Operand, - DAGCombinerInfo &DCI, - unsigned &RefinementSteps, - bool &UseOneConstNR) const { + virtual SDValue getRsqrtEstimate(SDValue Operand, DAGCombinerInfo &DCI, + unsigned &RefinementSteps, + bool &UseOneConstNR) const { return SDValue(); } @@ -2751,8 +2727,7 @@ public: /// If that's true, then return '0' as the number of RefinementSteps to avoid /// any further refinement of the estimate. /// An empty SDValue return means no estimate sequence can be created. - virtual SDValue getRecipEstimate(SDValue Operand, - DAGCombinerInfo &DCI, + virtual SDValue getRecipEstimate(SDValue Operand, DAGCombinerInfo &DCI, unsigned &RefinementSteps) const { return SDValue(); } @@ -2791,6 +2766,8 @@ public: /// is created but not inserted into any basic blocks, and this method is /// called to expand it into a sequence of instructions, potentially also /// creating new basic blocks and control flow. + /// As long as the returned basic block is different (i.e., we created a new + /// one), the custom inserter is free to modify the rest of \p MBB. virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; @@ -2806,11 +2783,6 @@ public: virtual bool useLoadStackGuardNode() const { return false; } - - /// Returns true if arguments should be sign-extended in lib calls. - virtual bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const { - return IsSigned; - } }; /// Given an LLVM IR type and return type attributes, compute the return value diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 73bf56f018e9..2a17bd200f4d 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -29,22 +29,29 @@ namespace llvm { class MCSymbol; class MCSymbolRefExpr; class MCStreamer; + class MCValue; class ConstantExpr; class GlobalValue; class TargetMachine; class TargetLoweringObjectFile : public MCObjectFileInfo { MCContext *Ctx; - const DataLayout *DL; TargetLoweringObjectFile( - const TargetLoweringObjectFile&) LLVM_DELETED_FUNCTION; - void operator=(const TargetLoweringObjectFile&) LLVM_DELETED_FUNCTION; + const TargetLoweringObjectFile&) = delete; + void operator=(const TargetLoweringObjectFile&) = delete; + +protected: + const DataLayout *DL; + bool SupportIndirectSymViaGOTPCRel; + bool SupportGOTPCRelWithOffset; public: MCContext &getContext() const { return *Ctx; } - TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(nullptr), DL(nullptr) {} + TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(nullptr), DL(nullptr), + SupportIndirectSymViaGOTPCRel(false), + SupportGOTPCRelWithOffset(true) {} virtual ~TargetLoweringObjectFile(); @@ -70,8 +77,8 @@ public: /// Given a constant with the SectionKind, return a section that it should be /// placed in. - virtual const MCSection *getSectionForConstant(SectionKind Kind, - const Constant *C) const; + virtual MCSection *getSectionForConstant(SectionKind Kind, + const Constant *C) const; /// Classify the specified global variable into a set of target independent /// categories embodied in SectionKind. @@ -81,23 +88,32 @@ public: /// This method computes the appropriate section to emit the specified global /// variable or function definition. This should not be passed external (or /// available externally) globals. - const MCSection *SectionForGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const; + MCSection *SectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, const TargetMachine &TM) const; /// This method computes the appropriate section to emit the specified global /// variable or function definition. This should not be passed external (or /// available externally) globals. - const MCSection *SectionForGlobal(const GlobalValue *GV, - Mangler &Mang, - const TargetMachine &TM) const { + MCSection *SectionForGlobal(const GlobalValue *GV, Mangler &Mang, + const TargetMachine &TM) const { return SectionForGlobal(GV, getKindForGlobal(GV, TM), Mang, TM); } + virtual void getNameWithPrefix(SmallVectorImpl<char> &OutName, + const GlobalValue *GV, + bool CannotUsePrivateLabel, Mangler &Mang, + const TargetMachine &TM) const; + + virtual MCSection *getSectionForJumpTable(const Function &F, Mangler &Mang, + const TargetMachine &TM) const; + + virtual bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, + const Function &F) const; + /// Targets should implement this method to assign a section to globals with /// an explicit section specfied. The implementation of this method can /// assume that GV->hasSection() is true. - virtual const MCSection * + virtual MCSection * getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const = 0; @@ -131,13 +147,13 @@ public: getTTypeReference(const MCSymbolRefExpr *Sym, unsigned Encoding, MCStreamer &Streamer) const; - virtual const MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym) const { + virtual MCSection *getStaticCtorSection(unsigned Priority, + const MCSymbol *KeySym) const { return StaticCtorSection; } - virtual const MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym) const { + virtual MCSection *getStaticDtorSection(unsigned Priority, + const MCSymbol *KeySym) const { return StaticDtorSection; } @@ -151,10 +167,31 @@ public: return nullptr; } + /// \brief Target supports replacing a data "PC"-relative access to a symbol + /// through another symbol, by accessing the later via a GOT entry instead? + bool supportIndirectSymViaGOTPCRel() const { + return SupportIndirectSymViaGOTPCRel; + } + + /// \brief Target GOT "PC"-relative relocation supports encoding an additional + /// binary expression with an offset? + bool supportGOTPCRelWithOffset() const { + return SupportGOTPCRelWithOffset; + } + + /// \brief Get the target specific PC relative GOT entry relocation + virtual const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym, + const MCValue &MV, + int64_t Offset, + MachineModuleInfo *MMI, + MCStreamer &Streamer) const { + return nullptr; + } + protected: - virtual const MCSection * - SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler &Mang, const TargetMachine &TM) const = 0; + virtual MCSection *SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, Mangler &Mang, + const TargetMachine &TM) const = 0; }; } // end namespace llvm diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index a4f95c061283..2a1ce0483e10 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -15,6 +15,7 @@ #define LLVM_TARGET_TARGETMACHINE_H #include "llvm/ADT/StringRef.h" +#include "llvm/IR/DataLayout.h" #include "llvm/Pass.h" #include "llvm/Support/CodeGen.h" #include "llvm/Target/TargetOptions.h" @@ -29,21 +30,25 @@ class Mangler; class MCAsmInfo; class MCCodeGenInfo; class MCContext; +class MCInstrInfo; +class MCRegisterInfo; +class MCSubtargetInfo; class MCSymbol; class Target; class DataLayout; class TargetLibraryInfo; class TargetFrameLowering; +class TargetIRAnalysis; class TargetIntrinsicInfo; class TargetLowering; class TargetPassConfig; class TargetRegisterInfo; class TargetSelectionDAGInfo; class TargetSubtargetInfo; -class ScalarTargetTransformInfo; -class VectorTargetTransformInfo; +class TargetTransformInfo; class formatted_raw_ostream; class raw_ostream; +class raw_pwrite_stream; class TargetLoweringObjectFile; // The old pass manager infrastructure is hidden in a legacy namespace now. @@ -54,34 +59,41 @@ using legacy::PassManagerBase; //===----------------------------------------------------------------------===// /// -/// TargetMachine - Primary interface to the complete machine description for -/// the target machine. All target-specific information should be accessible -/// through this interface. +/// Primary interface to the complete machine description for the target +/// machine. All target-specific information should be accessible through this +/// interface. /// class TargetMachine { - TargetMachine(const TargetMachine &) LLVM_DELETED_FUNCTION; - void operator=(const TargetMachine &) LLVM_DELETED_FUNCTION; + TargetMachine(const TargetMachine &) = delete; + void operator=(const TargetMachine &) = delete; protected: // Can only create subclasses. - TargetMachine(const Target &T, StringRef TargetTriple, - StringRef CPU, StringRef FS, const TargetOptions &Options); + TargetMachine(const Target &T, StringRef DataLayoutString, + StringRef TargetTriple, StringRef CPU, StringRef FS, + const TargetOptions &Options); - /// TheTarget - The Target that this machine was created for. + /// The Target that this machine was created for. const Target &TheTarget; - /// TargetTriple, TargetCPU, TargetFS - Triple string, CPU name, and target - /// feature strings the TargetMachine instance is created with. + /// For ABI type size and alignment. + const DataLayout DL; + + /// Triple string, CPU name, and target feature strings the TargetMachine + /// instance is created with. std::string TargetTriple; std::string TargetCPU; std::string TargetFS; - /// CodeGenInfo - Low level target information such as relocation model. - /// Non-const to allow resetting optimization level per-function. + /// Low level target information such as relocation model. Non-const to + /// allow resetting optimization level per-function. MCCodeGenInfo *CodeGenInfo; - /// AsmInfo - Contains target specific asm information. - /// + /// Contains target specific asm information. const MCAsmInfo *AsmInfo; + const MCRegisterInfo *MRI; + const MCInstrInfo *MII; + const MCSubtargetInfo *STI; + unsigned RequireStructuredCFG : 1; public: @@ -95,40 +107,39 @@ public: StringRef getTargetCPU() const { return TargetCPU; } StringRef getTargetFeatureString() const { return TargetFS; } - /// getSubtargetImpl - virtual method implemented by subclasses that returns - /// a reference to that target's TargetSubtargetInfo-derived member variable. - virtual const TargetSubtargetInfo *getSubtargetImpl() const { - return nullptr; - } + /// Virtual method implemented by subclasses that returns a reference to that + /// target's TargetSubtargetInfo-derived member variable. virtual const TargetSubtargetInfo *getSubtargetImpl(const Function &) const { - return getSubtargetImpl(); + return nullptr; } virtual TargetLoweringObjectFile *getObjFileLowering() const { return nullptr; } - /// getSubtarget - This method returns a pointer to the specified type of + /// This method returns a pointer to the specified type of /// TargetSubtargetInfo. In debug builds, it verifies that the object being /// returned is of the correct type. - template<typename STC> const STC &getSubtarget() const { - return *static_cast<const STC*>(getSubtargetImpl()); - } - template <typename STC> const STC &getSubtarget(const Function *) const { - return *static_cast<const STC*>(getSubtargetImpl()); + template <typename STC> const STC &getSubtarget(const Function &F) const { + return *static_cast<const STC*>(getSubtargetImpl(F)); } + /// This method returns a pointer to the DataLayout for the target. It should + /// be unchanging for every subtarget. + const DataLayout *getDataLayout() const { return &DL; } + /// \brief Reset the target options based on the function's attributes. // FIXME: Remove TargetOptions that affect per-function code generation // from TargetMachine. void resetTargetOptions(const Function &F) const; - /// getMCAsmInfo - Return target specific asm information. - /// + /// Return target specific asm information. const MCAsmInfo *getMCAsmInfo() const { return AsmInfo; } - /// getIntrinsicInfo - If intrinsic information is available, return it. If - /// not, return null. - /// + const MCRegisterInfo *getMCRegisterInfo() const { return MRI; } + const MCInstrInfo *getMCInstrInfo() const { return MII; } + const MCSubtargetInfo *getMCSubtargetInfo() const { return STI; } + + /// If intrinsic information is available, return it. If not, return null. virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { return nullptr; } @@ -136,20 +147,18 @@ public: bool requiresStructuredCFG() const { return RequireStructuredCFG; } void setRequiresStructuredCFG(bool Value) { RequireStructuredCFG = Value; } - /// getRelocationModel - Returns the code generation relocation model. The - /// choices are static, PIC, and dynamic-no-pic, and target default. + /// Returns the code generation relocation model. The choices are static, PIC, + /// and dynamic-no-pic, and target default. Reloc::Model getRelocationModel() const; - /// getCodeModel - Returns the code model. The choices are small, kernel, - /// medium, large, and target default. + /// Returns the code model. The choices are small, kernel, medium, large, and + /// target default. CodeModel::Model getCodeModel() const; - /// getTLSModel - Returns the TLS model which should be used for the given - /// global variable. + /// Returns the TLS model which should be used for the given global variable. TLSModel::Model getTLSModel(const GlobalValue *GV) const; - /// getOptLevel - Returns the optimization level: None, Less, - /// Default, or Aggressive. + /// Returns the optimization level: None, Less, Default, or Aggressive. CodeGenOpt::Level getOptLevel() const; /// \brief Overrides the optimization level. @@ -159,47 +168,47 @@ public: bool shouldPrintMachineCode() const { return Options.PrintMachineCode; } - /// getAsmVerbosityDefault - Returns the default value of asm verbosity. + /// Returns the default value of asm verbosity. /// - bool getAsmVerbosityDefault() const ; - - /// setAsmVerbosityDefault - Set the default value of asm verbosity. Default - /// is false. - void setAsmVerbosityDefault(bool); - - /// getDataSections - Return true if data objects should be emitted into their - /// own section, corresponds to -fdata-sections. - bool getDataSections() const; - - /// getFunctionSections - Return true if functions should be emitted into - /// their own section, corresponding to -ffunction-sections. - bool getFunctionSections() const; + bool getAsmVerbosityDefault() const { + return Options.MCOptions.AsmVerbose; + } - /// setDataSections - Set if the data are emit into separate sections. - void setDataSections(bool); + bool getUniqueSectionNames() const { return Options.UniqueSectionNames; } - /// setFunctionSections - Set if the functions are emit into separate - /// sections. - void setFunctionSections(bool); + /// Return true if data objects should be emitted into their own section, + /// corresponds to -fdata-sections. + bool getDataSections() const { + return Options.DataSections; + } - /// \brief Register analysis passes for this target with a pass manager. - virtual void addAnalysisPasses(PassManagerBase &) {} + /// Return true if functions should be emitted into their own section, + /// corresponding to -ffunction-sections. + bool getFunctionSections() const { + return Options.FunctionSections; + } - /// CodeGenFileType - These enums are meant to be passed into - /// addPassesToEmitFile to indicate what type of file to emit, and returned by - /// it to indicate what type of file could actually be made. + /// \brief Get a \c TargetIRAnalysis appropriate for the target. + /// + /// This is used to construct the new pass manager's target IR analysis pass, + /// set up appropriately for this target machine. Even the old pass manager + /// uses this to answer queries about the IR. + virtual TargetIRAnalysis getTargetIRAnalysis(); + + /// These enums are meant to be passed into addPassesToEmitFile to indicate + /// what type of file to emit, and returned by it to indicate what type of + /// file could actually be made. enum CodeGenFileType { CGFT_AssemblyFile, CGFT_ObjectFile, CGFT_Null // Do not emit any output. }; - /// addPassesToEmitFile - Add passes to the specified pass manager to get the - /// specified file emitted. Typically this will involve several steps of code - /// generation. This method should return true if emission of this file type - /// is not supported, or false on success. - virtual bool addPassesToEmitFile(PassManagerBase &, - formatted_raw_ostream &, + /// Add passes to the specified pass manager to get the specified file + /// emitted. Typically this will involve several steps of code generation. + /// This method should return true if emission of this file type is not + /// supported, or false on success. + virtual bool addPassesToEmitFile(PassManagerBase &, raw_pwrite_stream &, CodeGenFileType, bool /*DisableVerify*/ = true, AnalysisID /*StartAfter*/ = nullptr, @@ -207,14 +216,13 @@ public: return true; } - /// addPassesToEmitMC - Add passes to the specified pass manager to get - /// machine code emitted with the MCJIT. This method returns true if machine - /// code is not supported. It fills the MCContext Ctx pointer which can be - /// used to build custom MCStreamer. + /// Add passes to the specified pass manager to get machine code emitted with + /// the MCJIT. This method returns true if machine code is not supported. It + /// fills the MCContext Ctx pointer which can be used to build custom + /// MCStreamer. /// - virtual bool addPassesToEmitMC(PassManagerBase &, - MCContext *&, - raw_ostream &, + virtual bool addPassesToEmitMC(PassManagerBase &, MCContext *&, + raw_pwrite_stream &, bool /*DisableVerify*/ = true) { return true; } @@ -224,42 +232,42 @@ public: MCSymbol *getSymbol(const GlobalValue *GV, Mangler &Mang) const; }; -/// LLVMTargetMachine - This class describes a target machine that is -/// implemented with the LLVM target-independent code generator. +/// This class describes a target machine that is implemented with the LLVM +/// target-independent code generator. /// class LLVMTargetMachine : public TargetMachine { protected: // Can only create subclasses. - LLVMTargetMachine(const Target &T, StringRef TargetTriple, - StringRef CPU, StringRef FS, TargetOptions Options, - Reloc::Model RM, CodeModel::Model CM, + LLVMTargetMachine(const Target &T, StringRef DataLayoutString, + StringRef TargetTriple, StringRef CPU, StringRef FS, + TargetOptions Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL); void initAsmInfo(); public: - /// \brief Register analysis passes for this target with a pass manager. + /// \brief Get a TargetIRAnalysis implementation for the target. /// - /// This registers target independent analysis passes. - void addAnalysisPasses(PassManagerBase &PM) override; + /// This analysis will produce a TTI result which uses the common code + /// generator to answer queries about the IR. + TargetIRAnalysis getTargetIRAnalysis() override; - /// createPassConfig - Create a pass configuration object to be used by - /// addPassToEmitX methods for generating a pipeline of CodeGen passes. + /// Create a pass configuration object to be used by addPassToEmitX methods + /// for generating a pipeline of CodeGen passes. virtual TargetPassConfig *createPassConfig(PassManagerBase &PM); - /// addPassesToEmitFile - Add passes to the specified pass manager to get the - /// specified file emitted. Typically this will involve several steps of code - /// generation. - bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out, + /// Add passes to the specified pass manager to get the specified file + /// emitted. Typically this will involve several steps of code generation. + bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType, bool DisableVerify = true, AnalysisID StartAfter = nullptr, AnalysisID StopAfter = nullptr) override; - /// addPassesToEmitMC - Add passes to the specified pass manager to get - /// machine code emitted with the MCJIT. This method returns true if machine - /// code is not supported. It fills the MCContext Ctx pointer which can be - /// used to build custom MCStreamer. - /// + /// Add passes to the specified pass manager to get machine code emitted with + /// the MCJIT. This method returns true if machine code is not supported. It + /// fills the MCContext Ctx pointer which can be used to build custom + /// MCStreamer. bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx, - raw_ostream &OS, bool DisableVerify = true) override; + raw_pwrite_stream &OS, + bool DisableVerify = true) override; }; } // End llvm namespace diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index 9ab8242578fd..07a8f6d3d4cd 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -20,14 +20,14 @@ namespace llvm { class MachineFunction; + class Module; class StringRef; - // Possible float ABI settings. Used with FloatABIType in TargetOptions.h. namespace FloatABI { enum ABIType { - Default, // Target-specific (either soft or hard depending on triple,etc). - Soft, // Soft float. - Hard // Hard float. + Default, // Target-specific (either soft or hard depending on triple, etc). + Soft, // Soft float. + Hard // Hard float. }; } @@ -57,43 +57,29 @@ namespace llvm { }; } - enum class CFIntegrity { - Sub, // Use subtraction-based checks. - Ror, // Use rotation-based checks. - Add // Use addition-based checks. This depends on having - // sufficient alignment in the code and is usually not - // feasible. - }; - class TargetOptions { public: TargetOptions() - : PrintMachineCode(false), NoFramePointerElim(false), + : PrintMachineCode(false), LessPreciseFPMADOption(false), UnsafeFPMath(false), NoInfsFPMath(false), NoNaNsFPMath(false), - HonorSignDependentRoundingFPMathOption(false), UseSoftFloat(false), - NoZerosInBSS(false), JITEmitDebugInfo(false), - JITEmitDebugInfoToDisk(false), GuaranteedTailCallOpt(false), + HonorSignDependentRoundingFPMathOption(false), + NoZerosInBSS(false), + GuaranteedTailCallOpt(false), DisableTailCalls(false), StackAlignmentOverride(0), EnableFastISel(false), PositionIndependentExecutable(false), UseInitArray(false), DisableIntegratedAS(false), CompressDebugSections(false), FunctionSections(false), - DataSections(false), TrapUnreachable(false), TrapFuncName(), - FloatABIType(FloatABI::Default), + DataSections(false), UniqueSectionNames(true), TrapUnreachable(false), + TrapFuncName(), FloatABIType(FloatABI::Default), AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single), - FCFI(false), ThreadModel(ThreadModel::POSIX), - CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName() {} + ThreadModel(ThreadModel::POSIX) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging /// output from the code generator. unsigned PrintMachineCode : 1; - /// NoFramePointerElim - This flag is enabled when the -disable-fp-elim is - /// specified on the command line. If the target supports the frame pointer - /// elimination optimization, this option should disable it. - unsigned NoFramePointerElim : 1; - /// DisableFramePointerElim - This returns true if frame pointer elimination /// optimization should be disabled for the given machine function. bool DisableFramePointerElim(const MachineFunction &MF) const; @@ -136,26 +122,11 @@ namespace llvm { unsigned HonorSignDependentRoundingFPMathOption : 1; bool HonorSignDependentRoundingFPMath() const; - /// UseSoftFloat - This flag is enabled when the -soft-float flag is - /// specified on the command line. When this flag is on, the code generator - /// will generate libcalls to the software floating point library instead of - /// target FP instructions. - unsigned UseSoftFloat : 1; - /// NoZerosInBSS - By default some codegens place zero-initialized data to /// .bss section. This flag disables such behaviour (necessary, e.g. for /// crt*.o compiling). unsigned NoZerosInBSS : 1; - /// JITEmitDebugInfo - This flag indicates that the JIT should try to emit - /// debug information and notify a debugger about it. - unsigned JITEmitDebugInfo : 1; - - /// JITEmitDebugInfoToDisk - This flag indicates that the JIT should write - /// the object files generated by the JITEmitDebugInfo flag to disk. This - /// flag is hidden and is only for debugging the debug info. - unsigned JITEmitDebugInfoToDisk : 1; - /// GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is /// specified on the commandline. When the flag is on, participating targets /// will perform tail call optimization on all calls which use the fastcc @@ -198,6 +169,8 @@ namespace llvm { /// Emit data into separate sections. unsigned DataSections : 1; + unsigned UniqueSectionNames : 1; + /// Emit target-specific trap instruction for 'unreachable' IR instructions. unsigned TrapUnreachable : 1; @@ -210,9 +183,9 @@ namespace llvm { /// FloatABIType - This setting is set by -float-abi=xxx option is specfied /// on the command line. This setting may either be Default, Soft, or Hard. /// Default selects the target's default behavior. Soft selects the ABI for - /// UseSoftFloat, but does not indicate that FP hardware may not be used. - /// Such a combination is unfortunately popular (e.g. arm-apple-darwin). - /// Hard presumes that the normal FP ABI is used. + /// software floating point, but does not indicate that FP hardware may not + /// be used. Such a combination is unfortunately popular (e.g. + /// arm-apple-darwin). Hard presumes that the normal FP ABI is used. FloatABI::ABIType FloatABIType; /// AllowFPOpFusion - This flag is set by the -fuse-fp-ops=xxx option. @@ -237,28 +210,10 @@ namespace llvm { /// create for functions that have the jumptable attribute. JumpTable::JumpTableType JTType; - /// FCFI - This flags controls whether or not forward-edge control-flow - /// integrity is applied. - bool FCFI; - /// ThreadModel - This flag specifies the type of threading model to assume /// for things like atomics ThreadModel::Model ThreadModel; - /// CFIType - This flag specifies the type of control-flow integrity check - /// to add as a preamble to indirect calls. - CFIntegrity CFIType; - - /// CFIEnforcing - This flags controls whether or not CFI violations cause - /// the program to halt. - bool CFIEnforcing; - - /// getCFIFuncName - If this returns a non-empty string, then this is the - /// name of the function that will be called for each CFI violation in - /// non-enforcing mode. - std::string CFIFuncName; - StringRef getCFIFuncName() const; - /// Machine level options. MCTargetOptions MCOptions; }; @@ -274,10 +229,7 @@ inline bool operator==(const TargetOptions &LHS, ARE_EQUAL(NoInfsFPMath) && ARE_EQUAL(NoNaNsFPMath) && ARE_EQUAL(HonorSignDependentRoundingFPMathOption) && - ARE_EQUAL(UseSoftFloat) && ARE_EQUAL(NoZerosInBSS) && - ARE_EQUAL(JITEmitDebugInfo) && - ARE_EQUAL(JITEmitDebugInfoToDisk) && ARE_EQUAL(GuaranteedTailCallOpt) && ARE_EQUAL(DisableTailCalls) && ARE_EQUAL(StackAlignmentOverride) && @@ -289,11 +241,7 @@ inline bool operator==(const TargetOptions &LHS, ARE_EQUAL(FloatABIType) && ARE_EQUAL(AllowFPOpFusion) && ARE_EQUAL(JTType) && - ARE_EQUAL(FCFI) && ARE_EQUAL(ThreadModel) && - ARE_EQUAL(CFIType) && - ARE_EQUAL(CFIEnforcing) && - ARE_EQUAL(CFIFuncName) && ARE_EQUAL(MCOptions); #undef ARE_EQUAL } diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index a7552565c938..121b8a232526 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -46,6 +46,11 @@ public: const uint32_t *SubClassMask; const uint16_t *SuperRegIndices; const unsigned LaneMask; + /// Classes with a higher priority value are assigned first by register + /// allocators using a greedy heuristic. The value is in the range [0,63]. + const uint8_t AllocationPriority; + /// Whether the class supports two (or more) disjunct subregister indices. + const bool HasDisjunctSubRegs; const sc_iterator SuperClasses; ArrayRef<MCPhysReg> (*OrderFunc)(const MachineFunction&); @@ -357,13 +362,13 @@ public: /// /// then: /// - /// getSubRegIndexLaneMask(A) & getSubRegIndexLaneMask(B) != 0 + /// (getSubRegIndexLaneMask(A) & getSubRegIndexLaneMask(B)) != 0 /// /// The converse is not necessarily true. If two lane masks have a common /// bit, the corresponding sub-registers may not overlap, but it can be /// assumed that they usually will. + /// SubIdx == 0 is allowed, it has the lane mask ~0u. unsigned getSubRegIndexLaneMask(unsigned SubIdx) const { - // SubIdx == 0 is allowed, it has the lane mask ~0u. assert(SubIdx < getNumSubRegIndices() && "This is not a subregister index"); return SubRegIndexLaneMasks[SubIdx]; } @@ -425,10 +430,10 @@ public: /// closest to the incoming stack pointer if stack grows down, and vice versa. /// virtual const MCPhysReg* - getCalleeSavedRegs(const MachineFunction *MF = nullptr) const = 0; + getCalleeSavedRegs(const MachineFunction *MF) const = 0; /// getCallPreservedMask - Return a mask of call-preserved registers for the - /// given calling convention on the current sub-target. The mask should + /// given calling convention on the current function. The mask should /// include all call-preserved aliases. This is used by the register /// allocator to determine which registers can be live across a call. /// @@ -445,7 +450,8 @@ public: /// instructions should use implicit-def operands to indicate call clobbered /// registers. /// - virtual const uint32_t *getCallPreservedMask(CallingConv::ID) const { + virtual const uint32_t *getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID) const { // The default mask clobbers everything. All targets should override. return nullptr; } @@ -622,8 +628,9 @@ public: /// legal to use in the current sub-target and has the same spill size. /// The returned register class can be used to create virtual registers which /// means that all its registers can be copied and spilled. - virtual const TargetRegisterClass* - getLargestLegalSuperClass(const TargetRegisterClass *RC) const { + virtual const TargetRegisterClass * + getLargestLegalSuperClass(const TargetRegisterClass *RC, + const MachineFunction &) const { /// The default implementation is very conservative and doesn't allow the /// register allocator to inflate register classes. return RC; @@ -655,7 +662,8 @@ public: /// Get the register unit pressure limit for this dimension. /// This limit must be adjusted dynamically for reserved registers. - virtual unsigned getRegPressureSetLimit(unsigned Idx) const = 0; + virtual unsigned getRegPressureSetLimit(const MachineFunction &MF, + unsigned Idx) const = 0; /// Get the dimensions of register pressure impacted by this register class. /// Returns a -1 terminated array of pressure set IDs. @@ -686,21 +694,13 @@ public: const MachineFunction &MF, const VirtRegMap *VRM = nullptr) const; - /// avoidWriteAfterWrite - Return true if the register allocator should avoid - /// writing a register from RC in two consecutive instructions. - /// This can avoid pipeline stalls on certain architectures. - /// It does cause increased register pressure, though. - virtual bool avoidWriteAfterWrite(const TargetRegisterClass *RC) const { - return false; - } - - /// UpdateRegAllocHint - A callback to allow target a chance to update + /// updateRegAllocHint - A callback to allow target a chance to update /// register allocation hints when a register is "changed" (e.g. coalesced) /// to another register. e.g. On ARM, some virtual registers should target /// register pairs, if one of pair is coalesced to another register, the /// allocation hint of the other half of the pair should be changed to point /// to the new register. - virtual void UpdateRegAllocHint(unsigned Reg, unsigned NewReg, + virtual void updateRegAllocHint(unsigned Reg, unsigned NewReg, MachineFunction &MF) const { // Do nothing. } @@ -802,9 +802,9 @@ public: llvm_unreachable("resolveFrameIndex does not exist on this target"); } - /// isFrameOffsetLegal - Determine whether a given offset immediate is - /// encodable to resolve a frame index. - virtual bool isFrameOffsetLegal(const MachineInstr *MI, + /// isFrameOffsetLegal - Determine whether a given base register plus offset + /// immediate is encodable to resolve a frame index. + virtual bool isFrameOffsetLegal(const MachineInstr *MI, unsigned BaseReg, int64_t Offset) const { llvm_unreachable("isFrameOffsetLegal does not exist on this target"); } diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 907baa1b9b1f..7a788cef0237 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -68,6 +68,18 @@ class SDTCisSubVecOfVec<int ThisOp, int OtherOp> int OtherOpNum = OtherOp; } +// SDTCVecEltisVT - The specified operand is vector type with element type +// of VT. +class SDTCVecEltisVT<int OpNum, ValueType vt> : SDTypeConstraint<OpNum> { + ValueType VT = vt; +} + +// SDTCisSameNumEltsAs - The two specified operands have identical number +// of elements. +class SDTCisSameNumEltsAs<int OpNum, int OtherOp> : SDTypeConstraint<OpNum> { + int OtherOperandNum = OtherOp; +} + //===----------------------------------------------------------------------===// // Selection DAG Type Profile definitions. // @@ -196,6 +208,16 @@ def SDTMaskedLoad: SDTypeProfile<1, 3, [ // masked load SDTCisVec<0>, SDTCisPtrTy<1>, SDTCisVec<2>, SDTCisSameAs<0, 3> ]>; +def SDTMaskedGather: SDTypeProfile<2, 3, [ // masked gather + SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<1, 3>, + SDTCisPtrTy<4>, SDTCVecEltisVT<1, i1>, SDTCisSameNumEltsAs<0, 1> +]>; + +def SDTMaskedScatter: SDTypeProfile<1, 3, [ // masked scatter + SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<0, 2>, SDTCisSameNumEltsAs<0, 1>, + SDTCVecEltisVT<0, i1>, SDTCisPtrTy<3> +]>; + def SDTVecShuffle : SDTypeProfile<1, 2, [ SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2> ]>; @@ -358,6 +380,10 @@ def subc : SDNode<"ISD::SUBC" , SDTIntBinOp, [SDNPOutGlue]>; def sube : SDNode<"ISD::SUBE" , SDTIntBinOp, [SDNPOutGlue, SDNPInGlue]>; +def smin : SDNode<"ISD::SMIN" , SDTIntBinOp>; +def smax : SDNode<"ISD::SMAX" , SDTIntBinOp>; +def umin : SDNode<"ISD::UMIN" , SDTIntBinOp>; +def umax : SDNode<"ISD::UMAX" , SDTIntBinOp>; def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>; def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>; @@ -371,6 +397,7 @@ def zext : SDNode<"ISD::ZERO_EXTEND", SDTIntExtendOp>; def anyext : SDNode<"ISD::ANY_EXTEND" , SDTIntExtendOp>; def trunc : SDNode<"ISD::TRUNCATE" , SDTIntTruncOp>; def bitconvert : SDNode<"ISD::BITCAST" , SDTUnaryOp>; +def addrspacecast : SDNode<"ISD::ADDRSPACECAST", SDTUnaryOp>; def extractelt : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTVecExtract>; def insertelt : SDNode<"ISD::INSERT_VECTOR_ELT", SDTVecInsert>; @@ -380,6 +407,7 @@ def fmul : SDNode<"ISD::FMUL" , SDTFPBinOp, [SDNPCommutative]>; def fdiv : SDNode<"ISD::FDIV" , SDTFPBinOp>; def frem : SDNode<"ISD::FREM" , SDTFPBinOp>; def fma : SDNode<"ISD::FMA" , SDTFPTernaryOp>; +def fmad : SDNode<"ISD::FMAD" , SDTFPTernaryOp>; def fabs : SDNode<"ISD::FABS" , SDTFPUnaryOp>; def fminnum : SDNode<"ISD::FMINNUM" , SDTFPBinOp>; def fmaxnum : SDNode<"ISD::FMAXNUM" , SDTFPBinOp>; @@ -466,6 +494,10 @@ def masked_store : SDNode<"ISD::MSTORE", SDTMaskedStore, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; def masked_load : SDNode<"ISD::MLOAD", SDTMaskedLoad, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def masked_scatter : SDNode<"ISD::MSCATTER", SDTMaskedScatter, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def masked_gather : SDNode<"ISD::MGATHER", SDTMaskedGather, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; // Do not use ld, st directly. Use load, extload, sextload, zextload, store, // and truncst (see below). diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/Target/TargetSelectionDAGInfo.h index d1a3fcf4a50e..bacdd950705b 100644 --- a/include/llvm/Target/TargetSelectionDAGInfo.h +++ b/include/llvm/Target/TargetSelectionDAGInfo.h @@ -21,15 +21,14 @@ namespace llvm { class DataLayout; -class TargetMachine; //===----------------------------------------------------------------------===// /// TargetSelectionDAGInfo - Targets can subclass this to parameterize the /// SelectionDAG lowering and instruction selection process. /// class TargetSelectionDAGInfo { - TargetSelectionDAGInfo(const TargetSelectionDAGInfo &) LLVM_DELETED_FUNCTION; - void operator=(const TargetSelectionDAGInfo &) LLVM_DELETED_FUNCTION; + TargetSelectionDAGInfo(const TargetSelectionDAGInfo &) = delete; + void operator=(const TargetSelectionDAGInfo &) = delete; const DataLayout *DL; diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h index 4ff88d07bf27..0f427901a8ec 100644 --- a/include/llvm/Target/TargetSubtargetInfo.h +++ b/include/llvm/Target/TargetSubtargetInfo.h @@ -42,15 +42,17 @@ template <typename T> class SmallVectorImpl; /// be exposed through a TargetSubtargetInfo-derived class. /// class TargetSubtargetInfo : public MCSubtargetInfo { - TargetSubtargetInfo(const TargetSubtargetInfo&) LLVM_DELETED_FUNCTION; - void operator=(const TargetSubtargetInfo&) LLVM_DELETED_FUNCTION; + TargetSubtargetInfo(const TargetSubtargetInfo &) = delete; + void operator=(const TargetSubtargetInfo &) = delete; + protected: // Can only create subclasses... TargetSubtargetInfo(); + public: // AntiDepBreakMode - Type of anti-dependence breaking that should // be performed before post-RA scheduling. typedef enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode; - typedef SmallVectorImpl<const TargetRegisterClass*> RegClassVector; + typedef SmallVectorImpl<const TargetRegisterClass *> RegClassVector; virtual ~TargetSubtargetInfo(); @@ -71,7 +73,6 @@ public: virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const { return nullptr; } - virtual const DataLayout *getDataLayout() const { return nullptr; } /// getRegisterInfo - If register information is available, return it. If /// not, return null. This is kept separate from RegInfo until RegInfo has @@ -90,21 +91,30 @@ public: /// MCSchedClassDesc with the isVariant property. This may return the ID of /// another variant SchedClass, but repeated invocation must quickly terminate /// in a nonvariant SchedClass. - virtual unsigned resolveSchedClass(unsigned SchedClass, const MachineInstr *MI, - const TargetSchedModel* SchedModel) const { + virtual unsigned resolveSchedClass(unsigned SchedClass, + const MachineInstr *MI, + const TargetSchedModel *SchedModel) const { return 0; } - /// \brief Temporary API to test migration to MI scheduler. - bool useMachineScheduler() const; - /// \brief True if the subtarget should run MachineScheduler after aggressive /// coalescing. /// /// This currently replaces the SelectionDAG scheduler with the "source" order - /// scheduler. It does not yet disable the postRA scheduler. + /// scheduler (though see below for an option to turn this off and use the + /// TargetLowering preference). It does not yet disable the postRA scheduler. virtual bool enableMachineScheduler() const; + /// \brief True if the machine scheduler should disable the TLI preference + /// for preRA scheduling with the source level scheduler. + virtual bool enableMachineSchedDefaultSched() const { return true; } + + /// \brief True if the subtarget should enable joining global copies. + /// + /// By default this is enabled if the machine scheduler is enabled, but + /// can be overridden. + virtual bool enableJoinGlobalCopies() const; + /// \brief True if the subtarget should run PostMachineScheduler. /// /// This only takes effect if the target has configured the @@ -121,20 +131,16 @@ public: /// scheduling heuristics (no custom MachineSchedStrategy) to make /// changes to the generic scheduling policy. virtual void overrideSchedPolicy(MachineSchedPolicy &Policy, - MachineInstr *begin, - MachineInstr *end, + MachineInstr *begin, MachineInstr *end, unsigned NumRegionInstrs) const {} // \brief Perform target specific adjustments to the latency of a schedule // dependency. - virtual void adjustSchedDependency(SUnit *def, SUnit *use, - SDep& dep) const { } + virtual void adjustSchedDependency(SUnit *def, SUnit *use, SDep &dep) const {} // For use with PostRAScheduling: get the anti-dependence breaking that should // be performed before post-RA scheduling. - virtual AntiDepBreakMode getAntiDepBreakMode() const { - return ANTIDEP_NONE; - } + virtual AntiDepBreakMode getAntiDepBreakMode() const { return ANTIDEP_NONE; } // For use with PostRAScheduling: in CriticalPathRCs, return any register // classes that should only be considered for anti-dependence breaking if they @@ -170,9 +176,7 @@ public: } /// Enable tracking of subregister liveness in register allocator. - virtual bool enableSubRegLiveness() const { - return false; - } + virtual bool enableSubRegLiveness() const { return false; } }; } // End llvm namespace diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index ce1a7d6a5230..fbd999cbc946 100644 --- a/include/llvm/Transforms/IPO.h +++ b/include/llvm/Transforms/IPO.h @@ -199,6 +199,10 @@ ModulePass *createMetaRenamerPass(); /// manager. ModulePass *createBarrierNoopPass(); +/// \brief This pass lowers bitset metadata and the llvm.bitset.test intrinsic +/// to bitsets. +ModulePass *createLowerBitSetsPass(); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/IPO/LowerBitSets.h b/include/llvm/Transforms/IPO/LowerBitSets.h new file mode 100644 index 000000000000..55d7d84560a0 --- /dev/null +++ b/include/llvm/Transforms/IPO/LowerBitSets.h @@ -0,0 +1,198 @@ +//===- LowerBitSets.h - Bitset lowering pass --------------------*- 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 parts of the bitset lowering pass implementation that may +// be usefully unit tested. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_LOWERBITSETS_H +#define LLVM_TRANSFORMS_IPO_LOWERBITSETS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" + +#include <stdint.h> +#include <limits> +#include <set> +#include <vector> + +namespace llvm { + +class DataLayout; +class GlobalVariable; +class Value; + +struct BitSetInfo { + // The indices of the set bits in the bitset. + std::set<uint64_t> Bits; + + // The byte offset into the combined global represented by the bitset. + uint64_t ByteOffset; + + // The size of the bitset in bits. + uint64_t BitSize; + + // Log2 alignment of the bit set relative to the combined global. + // For example, a log2 alignment of 3 means that bits in the bitset + // represent addresses 8 bytes apart. + unsigned AlignLog2; + + bool isSingleOffset() const { + return Bits.size() == 1; + } + + bool isAllOnes() const { + return Bits.size() == BitSize; + } + + bool containsGlobalOffset(uint64_t Offset) const; + + bool containsValue(const DataLayout &DL, + const DenseMap<GlobalVariable *, uint64_t> &GlobalLayout, + Value *V, uint64_t COffset = 0) const; +}; + +struct BitSetBuilder { + SmallVector<uint64_t, 16> Offsets; + uint64_t Min, Max; + + BitSetBuilder() : Min(std::numeric_limits<uint64_t>::max()), Max(0) {} + + void addOffset(uint64_t Offset) { + if (Min > Offset) + Min = Offset; + if (Max < Offset) + Max = Offset; + + Offsets.push_back(Offset); + } + + BitSetInfo build(); +}; + +/// This class implements a layout algorithm for globals referenced by bit sets +/// that tries to keep members of small bit sets together. This can +/// significantly reduce bit set sizes in many cases. +/// +/// It works by assembling fragments of layout from sets of referenced globals. +/// Each set of referenced globals causes the algorithm to create a new +/// fragment, which is assembled by appending each referenced global in the set +/// into the fragment. If a referenced global has already been referenced by an +/// fragment created earlier, we instead delete that fragment and append its +/// contents into the fragment we are assembling. +/// +/// By starting with the smallest fragments, we minimize the size of the +/// fragments that are copied into larger fragments. This is most intuitively +/// thought about when considering the case where the globals are virtual tables +/// and the bit sets represent their derived classes: in a single inheritance +/// hierarchy, the optimum layout would involve a depth-first search of the +/// class hierarchy (and in fact the computed layout ends up looking a lot like +/// a DFS), but a naive DFS would not work well in the presence of multiple +/// inheritance. This aspect of the algorithm ends up fitting smaller +/// hierarchies inside larger ones where that would be beneficial. +/// +/// For example, consider this class hierarchy: +/// +/// A B +/// \ / | \ +/// C D E +/// +/// We have five bit sets: bsA (A, C), bsB (B, C, D, E), bsC (C), bsD (D) and +/// bsE (E). If we laid out our objects by DFS traversing B followed by A, our +/// layout would be {B, C, D, E, A}. This is optimal for bsB as it needs to +/// cover the only 4 objects in its hierarchy, but not for bsA as it needs to +/// cover 5 objects, i.e. the entire layout. Our algorithm proceeds as follows: +/// +/// Add bsC, fragments {{C}} +/// Add bsD, fragments {{C}, {D}} +/// Add bsE, fragments {{C}, {D}, {E}} +/// Add bsA, fragments {{A, C}, {D}, {E}} +/// Add bsB, fragments {{B, A, C, D, E}} +/// +/// This layout is optimal for bsA, as it now only needs to cover two (i.e. 3 +/// fewer) objects, at the cost of bsB needing to cover 1 more object. +/// +/// The bit set lowering pass assigns an object index to each object that needs +/// to be laid out, and calls addFragment for each bit set passing the object +/// indices of its referenced globals. It then assembles a layout from the +/// computed layout in the Fragments field. +struct GlobalLayoutBuilder { + /// The computed layout. Each element of this vector contains a fragment of + /// layout (which may be empty) consisting of object indices. + std::vector<std::vector<uint64_t>> Fragments; + + /// Mapping from object index to fragment index. + std::vector<uint64_t> FragmentMap; + + GlobalLayoutBuilder(uint64_t NumObjects) + : Fragments(1), FragmentMap(NumObjects) {} + + /// Add F to the layout while trying to keep its indices contiguous. + /// If a previously seen fragment uses any of F's indices, that + /// fragment will be laid out inside F. + void addFragment(const std::set<uint64_t> &F); +}; + +/// This class is used to build a byte array containing overlapping bit sets. By +/// loading from indexed offsets into the byte array and applying a mask, a +/// program can test bits from the bit set with a relatively short instruction +/// sequence. For example, suppose we have 15 bit sets to lay out: +/// +/// A (16 bits), B (15 bits), C (14 bits), D (13 bits), E (12 bits), +/// F (11 bits), G (10 bits), H (9 bits), I (7 bits), J (6 bits), K (5 bits), +/// L (4 bits), M (3 bits), N (2 bits), O (1 bit) +/// +/// These bits can be laid out in a 16-byte array like this: +/// +/// Byte Offset +/// 0123456789ABCDEF +/// Bit +/// 7 HHHHHHHHHIIIIIII +/// 6 GGGGGGGGGGJJJJJJ +/// 5 FFFFFFFFFFFKKKKK +/// 4 EEEEEEEEEEEELLLL +/// 3 DDDDDDDDDDDDDMMM +/// 2 CCCCCCCCCCCCCCNN +/// 1 BBBBBBBBBBBBBBBO +/// 0 AAAAAAAAAAAAAAAA +/// +/// For example, to test bit X of A, we evaluate ((bits[X] & 1) != 0), or to +/// test bit X of I, we evaluate ((bits[9 + X] & 0x80) != 0). This can be done +/// in 1-2 machine instructions on x86, or 4-6 instructions on ARM. +/// +/// This is a byte array, rather than (say) a 2-byte array or a 4-byte array, +/// because for one thing it gives us better packing (the more bins there are, +/// the less evenly they will be filled), and for another, the instruction +/// sequences can be slightly shorter, both on x86 and ARM. +struct ByteArrayBuilder { + /// The byte array built so far. + std::vector<uint8_t> Bytes; + + enum { BitsPerByte = 8 }; + + /// The number of bytes allocated so far for each of the bits. + uint64_t BitAllocs[BitsPerByte]; + + ByteArrayBuilder() { + memset(BitAllocs, 0, sizeof(BitAllocs)); + } + + /// Allocate BitSize bits in the byte array where Bits contains the bits to + /// set. AllocByteOffset is set to the offset within the byte array and + /// AllocMask is set to the bitmask for those bits. This uses the LPT (Longest + /// Processing Time) multiprocessor scheduling algorithm to lay out the bits + /// efficiently; the pass allocates bit sets in decreasing size order. + void allocate(const std::set<uint64_t> &Bits, uint64_t BitSize, + uint64_t &AllocByteOffset, uint8_t &AllocMask); +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h index b1426b4f45ca..5d574ae0bf0f 100644 --- a/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -19,7 +19,7 @@ namespace llvm { class Pass; -class TargetLibraryInfo; +class TargetLibraryInfoImpl; class TargetMachine; // The old pass manager infrastructure is hidden in a legacy namespace now. @@ -27,8 +27,6 @@ namespace legacy { class FunctionPassManager; class PassManagerBase; } -using legacy::FunctionPassManager; -using legacy::PassManagerBase; /// PassManagerBuilder - This class is used to set up a standard optimization /// sequence for languages like C and C++, allowing some APIs to customize the @@ -59,7 +57,7 @@ public: /// Extensions are passed the builder itself (so they can see how it is /// configured) as well as the pass manager to add stuff to. typedef void (*ExtensionFn)(const PassManagerBuilder &Builder, - PassManagerBase &PM); + legacy::PassManagerBase &PM); enum ExtensionPointTy { /// EP_EarlyAsPossible - This extension point allows adding passes before /// any other transformations, allowing them to see the code as it is coming @@ -105,7 +103,7 @@ public: /// LibraryInfo - Specifies information about the runtime library for the /// optimizer. If this is non-null, it is added to both the function and /// per-module pass pipeline. - TargetLibraryInfo *LibraryInfo; + TargetLibraryInfoImpl *LibraryInfo; /// Inliner - Specifies the inliner to use. If this is non-null, it is /// added to the per-module passes. @@ -122,7 +120,6 @@ public: bool DisableGVNLoadPRE; bool VerifyInput; bool VerifyOutput; - bool StripDebug; bool MergeFunctions; private: @@ -139,19 +136,21 @@ public: void addExtension(ExtensionPointTy Ty, ExtensionFn Fn); private: - void addExtensionsToPM(ExtensionPointTy ETy, PassManagerBase &PM) const; - void addInitialAliasAnalysisPasses(PassManagerBase &PM) const; - void addLTOOptimizationPasses(PassManagerBase &PM); + void addExtensionsToPM(ExtensionPointTy ETy, + legacy::PassManagerBase &PM) const; + void addInitialAliasAnalysisPasses(legacy::PassManagerBase &PM) const; + void addLTOOptimizationPasses(legacy::PassManagerBase &PM); + void addLateLTOOptimizationPasses(legacy::PassManagerBase &PM); public: /// populateFunctionPassManager - This fills in the function pass manager, /// which is expected to be run on each function immediately as it is /// generated. The idea is to reduce the size of the IR in memory. - void populateFunctionPassManager(FunctionPassManager &FPM); + void populateFunctionPassManager(legacy::FunctionPassManager &FPM); /// populateModulePassManager - This sets up the primary pass manager. - void populateModulePassManager(PassManagerBase &MPM); - void populateLTOPassManager(PassManagerBase &PM, TargetMachine *TM = nullptr); + void populateModulePassManager(legacy::PassManagerBase &MPM); + void populateLTOPassManager(legacy::PassManagerBase &PM); }; /// Registers a function for adding a standard set of passes. This should be diff --git a/include/llvm/Transforms/InstCombine/InstCombine.h b/include/llvm/Transforms/InstCombine/InstCombine.h new file mode 100644 index 000000000000..f48ec13107bc --- /dev/null +++ b/include/llvm/Transforms/InstCombine/InstCombine.h @@ -0,0 +1,46 @@ +//===- InstCombine.h - InstCombine pass -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file provides the primary interface to the instcombine pass. This pass +/// is suitable for use in the new pass manager. For a pass that works with the +/// legacy pass manager, please look for \c createInstructionCombiningPass() in +/// Scalar.h. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINE_H +#define LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINE_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Transforms/InstCombine/InstCombineWorklist.h" + +namespace llvm { + +class InstCombinePass { + InstCombineWorklist Worklist; + +public: + static StringRef name() { return "InstCombinePass"; } + + // Explicitly define constructors for MSVC. + InstCombinePass() {} + InstCombinePass(InstCombinePass &&Arg) : Worklist(std::move(Arg.Worklist)) {} + InstCombinePass &operator=(InstCombinePass &&RHS) { + Worklist = std::move(RHS.Worklist); + return *this; + } + + PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM); +}; + +} + +#endif diff --git a/include/llvm/Transforms/InstCombine/InstCombineWorklist.h b/include/llvm/Transforms/InstCombine/InstCombineWorklist.h new file mode 100644 index 000000000000..a6bad343db43 --- /dev/null +++ b/include/llvm/Transforms/InstCombine/InstCombineWorklist.h @@ -0,0 +1,116 @@ +//===- InstCombineWorklist.h - Worklist for InstCombine pass ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINEWORKLIST_H +#define LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINEWORKLIST_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Instruction.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +#define DEBUG_TYPE "instcombine" + +namespace llvm { + +/// InstCombineWorklist - This is the worklist management logic for +/// InstCombine. +class InstCombineWorklist { + SmallVector<Instruction*, 256> Worklist; + DenseMap<Instruction*, unsigned> WorklistMap; + + void operator=(const InstCombineWorklist&RHS) = delete; + InstCombineWorklist(const InstCombineWorklist&) = delete; +public: + InstCombineWorklist() {} + + InstCombineWorklist(InstCombineWorklist &&Arg) + : Worklist(std::move(Arg.Worklist)), + WorklistMap(std::move(Arg.WorklistMap)) {} + InstCombineWorklist &operator=(InstCombineWorklist &&RHS) { + Worklist = std::move(RHS.Worklist); + WorklistMap = std::move(RHS.WorklistMap); + return *this; + } + + bool isEmpty() const { return Worklist.empty(); } + + /// Add - Add the specified instruction to the worklist if it isn't already + /// in it. + void Add(Instruction *I) { + if (WorklistMap.insert(std::make_pair(I, Worklist.size())).second) { + DEBUG(dbgs() << "IC: ADD: " << *I << '\n'); + Worklist.push_back(I); + } + } + + void AddValue(Value *V) { + if (Instruction *I = dyn_cast<Instruction>(V)) + Add(I); + } + + /// AddInitialGroup - Add the specified batch of stuff in reverse order. + /// which should only be done when the worklist is empty and when the group + /// has no duplicates. + void AddInitialGroup(Instruction *const *List, unsigned NumEntries) { + assert(Worklist.empty() && "Worklist must be empty to add initial group"); + Worklist.reserve(NumEntries+16); + WorklistMap.resize(NumEntries); + DEBUG(dbgs() << "IC: ADDING: " << NumEntries << " instrs to worklist\n"); + for (unsigned Idx = 0; NumEntries; --NumEntries) { + Instruction *I = List[NumEntries-1]; + WorklistMap.insert(std::make_pair(I, Idx++)); + Worklist.push_back(I); + } + } + + // Remove - remove I from the worklist if it exists. + void Remove(Instruction *I) { + DenseMap<Instruction*, unsigned>::iterator It = WorklistMap.find(I); + if (It == WorklistMap.end()) return; // Not in worklist. + + // Don't bother moving everything down, just null out the slot. + Worklist[It->second] = nullptr; + + WorklistMap.erase(It); + } + + Instruction *RemoveOne() { + Instruction *I = Worklist.pop_back_val(); + WorklistMap.erase(I); + return I; + } + + /// AddUsersToWorkList - When an instruction is simplified, add all users of + /// the instruction to the work lists because they might get more simplified + /// now. + /// + void AddUsersToWorkList(Instruction &I) { + for (User *U : I.users()) + Add(cast<Instruction>(U)); + } + + + /// Zap - check that the worklist is empty and nuke the backing store for + /// the map if it is large. + void Zap() { + assert(WorklistMap.empty() && "Worklist empty, but map not?"); + + // Do an explicit clear, this shrinks the map if needed. + WorklistMap.clear(); + } +}; + +} // end namespace llvm. + +#undef DEBUG_TYPE + +#endif diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index 24e3ef783ee6..884f54fd3737 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -15,6 +15,7 @@ #define LLVM_TRANSFORMS_INSTRUMENTATION_H #include "llvm/ADT/StringRef.h" +#include <vector> #if defined(__GNUC__) && defined(__linux__) && !defined(ANDROID) inline void *getDFSanArgTLSPtrForJIT() { @@ -59,6 +60,10 @@ struct GCOVOptions { // Emit the name of the function in the .gcda files. This is redundant, as // the function identifier can be used to find the name from the .gcno file. bool FunctionNamesInData; + + // Emit the exit block immediately after the start block, rather than after + // all of the function body's blocks. + bool ExitBlockBeforeBody; }; ModulePass *createGCOVProfilerPass(const GCOVOptions &Options = GCOVOptions::getDefault()); @@ -69,6 +74,9 @@ struct InstrProfOptions { // Add the 'noredzone' attribute to added runtime library calls. bool NoRedZone; + + // Name of the profile file to use as output + std::string InstrProfileOutput; }; /// Insert frontend instrumentation based profiling. @@ -86,17 +94,36 @@ FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0); FunctionPass *createThreadSanitizerPass(); // Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation -ModulePass *createDataFlowSanitizerPass(StringRef ABIListFile = StringRef(), - void *(*getArgTLS)() = nullptr, - void *(*getRetValTLS)() = nullptr); +ModulePass *createDataFlowSanitizerPass( + const std::vector<std::string> &ABIListFiles = std::vector<std::string>(), + void *(*getArgTLS)() = nullptr, void *(*getRetValTLS)() = nullptr); + +// Options for sanitizer coverage instrumentation. +struct SanitizerCoverageOptions { + SanitizerCoverageOptions() + : CoverageType(SCK_None), IndirectCalls(false), TraceBB(false), + TraceCmp(false), Use8bitCounters(false) {} + + enum Type { + SCK_None = 0, + SCK_Function, + SCK_BB, + SCK_Edge + } CoverageType; + bool IndirectCalls; + bool TraceBB; + bool TraceCmp; + bool Use8bitCounters; +}; // Insert SanitizerCoverage instrumentation. -ModulePass *createSanitizerCoverageModulePass(int CoverageLevel); +ModulePass *createSanitizerCoverageModulePass( + const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()); #if defined(__GNUC__) && defined(__linux__) && !defined(ANDROID) -inline ModulePass *createDataFlowSanitizerPassForJIT(StringRef ABIListFile = - StringRef()) { - return createDataFlowSanitizerPass(ABIListFile, getDFSanArgTLSPtrForJIT, +inline ModulePass *createDataFlowSanitizerPassForJIT( + const std::vector<std::string> &ABIListFiles = std::vector<std::string>()) { + return createDataFlowSanitizerPass(ABIListFiles, getDFSanArgTLSPtrForJIT, getDFSanRetValTLSPtrForJIT); } #endif diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index 5dcd89948759..c4669f121e6a 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -21,6 +21,7 @@ namespace llvm { class BasicBlockPass; class FunctionPass; +class ModulePass; class Pass; class GetElementPtrInst; class PassInfo; @@ -81,6 +82,13 @@ FunctionPass *createAggressiveDCEPass(); //===----------------------------------------------------------------------===// // +// BitTrackingDCE - This pass uses a bit-tracking DCE algorithm in order to +// remove computations of dead bits. +// +FunctionPass *createBitTrackingDCEPass(); + +//===----------------------------------------------------------------------===// +// // SROA - Replace aggregates or pieces of aggregates with scalar SSA values. // FunctionPass *createSROAPass(bool RequiresDomTree = true); @@ -98,6 +106,13 @@ FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1, //===----------------------------------------------------------------------===// // +// InductiveRangeCheckElimination - Transform loops to elide range checks on +// linear functions of the induction variable. +// +Pass *createInductiveRangeCheckEliminationPass(); + +//===----------------------------------------------------------------------===// +// // InductionVariableSimplify - Transform induction variables in a program to all // use a single canonical induction variable per loop. // @@ -125,12 +140,19 @@ Pass *createLICMPass(); //===----------------------------------------------------------------------===// // +// LoopInterchange - This pass interchanges loops to provide a more +// cache-friendly memory access patterns. +// +Pass *createLoopInterchangePass(); + +//===----------------------------------------------------------------------===// +// // LoopStrengthReduce - This pass is strength reduces GEP instructions that use // a loop's canonical induction variable as one of their indices. // Pass *createLoopStrengthReducePass(); -Pass *createGlobalMergePass(const TargetMachine *TM = nullptr); +Pass *createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset); //===----------------------------------------------------------------------===// // @@ -401,10 +423,59 @@ createSeparateConstOffsetFromGEPPass(const TargetMachine *TM = nullptr, //===----------------------------------------------------------------------===// // +// SpeculativeExecution - Aggressively hoist instructions to enable +// speculative execution on targets where branches are expensive. +// +FunctionPass *createSpeculativeExecutionPass(); + +//===----------------------------------------------------------------------===// +// // LoadCombine - Combine loads into bigger loads. // BasicBlockPass *createLoadCombinePass(); +//===----------------------------------------------------------------------===// +// +// StraightLineStrengthReduce - This pass strength-reduces some certain +// instruction patterns in straight-line code. +// +FunctionPass *createStraightLineStrengthReducePass(); + +//===----------------------------------------------------------------------===// +// +// PlaceSafepoints - Rewrite any IR calls to gc.statepoints and insert any +// safepoint polls (method entry, backedge) that might be required. This pass +// does not generate explicit relocation sequences - that's handled by +// RewriteStatepointsForGC which can be run at an arbitrary point in the pass +// order following this pass. +// +FunctionPass *createPlaceSafepointsPass(); + +//===----------------------------------------------------------------------===// +// +// RewriteStatepointsForGC - Rewrite any gc.statepoints which do not yet have +// explicit relocations to include explicit relocations. +// +FunctionPass *createRewriteStatepointsForGCPass(); + +//===----------------------------------------------------------------------===// +// +// Float2Int - Demote floats to ints where possible. +// +FunctionPass *createFloat2IntPass(); + +//===----------------------------------------------------------------------===// +// +// NaryReassociate - Simplify n-ary operations by reassociation. +// +FunctionPass *createNaryReassociatePass(); + +//===----------------------------------------------------------------------===// +// +// LoopDistribute - Distribute loops. +// +FunctionPass *createLoopDistributePass(); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Scalar/EarlyCSE.h b/include/llvm/Transforms/Scalar/EarlyCSE.h new file mode 100644 index 000000000000..e3dd3c050df6 --- /dev/null +++ b/include/llvm/Transforms/Scalar/EarlyCSE.h @@ -0,0 +1,39 @@ +//===- EarlyCSE.h - Simple and fast CSE pass --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file provides the interface for a simple, fast CSE pass. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_EARLYCSE_H +#define LLVM_TRANSFORMS_SCALAR_EARLYCSE_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// \brief A simple and fast domtree-based CSE pass. +/// +/// This pass does a simple depth-first walk over the dominator tree, +/// eliminating trivially redundant instructions and using instsimplify to +/// canonicalize things as it goes. It is intended to be fast and catch obvious +/// cases so that instcombine and other passes are more effective. It is +/// expected that a later pass of GVN will catch the interesting/hard cases. +class EarlyCSEPass { +public: + static StringRef name() { return "EarlyCSEPass"; } + + /// \brief Run the pass over the function. + PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM); +}; + +} + +#endif diff --git a/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h b/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h new file mode 100644 index 000000000000..40283203f3a3 --- /dev/null +++ b/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h @@ -0,0 +1,40 @@ +//===- LowerExpectIntrinsic.h - LowerExpectIntrinsic pass -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// The header file for the LowerExpectIntrinsic pass as used by the new pass +/// manager. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_LOWEREXPECTINTRINSIC_H +#define LLVM_TRANSFORMS_SCALAR_LOWEREXPECTINTRINSIC_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class LowerExpectIntrinsicPass { +public: + static StringRef name() { return "LowerExpectIntrinsicPass"; } + + /// \brief Run the pass over the function. + /// + /// This will lower all of th expect intrinsic calls in this function into + /// branch weight metadata. That metadata will subsequently feed the analysis + /// of the probabilities and frequencies of the CFG. After running this pass, + /// no more expect intrinsics remain, allowing the rest of the optimizer to + /// ignore them. + PreservedAnalyses run(Function &F); +}; + +} + +#endif diff --git a/include/llvm/Transforms/Scalar/SimplifyCFG.h b/include/llvm/Transforms/Scalar/SimplifyCFG.h new file mode 100644 index 000000000000..ef28e0f78a4c --- /dev/null +++ b/include/llvm/Transforms/Scalar/SimplifyCFG.h @@ -0,0 +1,46 @@ +//===- SimplifyCFG.h - Simplify and canonicalize the CFG --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file provides the interface for the pass responsible for both +/// simplifying and canonicalizing the CFG. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_SIMPLIFYCFG_H +#define LLVM_TRANSFORMS_SCALAR_SIMPLIFYCFG_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// \brief A pass to simplify and canonicalize the CFG of a function. +/// +/// This pass iteratively simplifies the entire CFG of a function, removing +/// unnecessary control flows and bringing it into the canonical form expected +/// by the rest of the mid-level optimizer. +class SimplifyCFGPass { + int BonusInstThreshold; + +public: + static StringRef name() { return "SimplifyCFGPass"; } + + /// \brief Construct a pass with the default thresholds. + SimplifyCFGPass(); + + /// \brief Construct a pass with a specific bonus threshold. + SimplifyCFGPass(int BonusInstThreshold); + + /// \brief Run the pass over the function. + PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM); +}; + +} + +#endif diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index 19acf5b2db83..710db03c45d6 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -23,10 +23,11 @@ namespace llvm { class AliasAnalysis; +class MemoryDependenceAnalysis; class DominatorTree; +class LoopInfo; class Instruction; class MDNode; -class Pass; class ReturnInst; class TargetLibraryInfo; class TerminatorInst; @@ -39,7 +40,8 @@ 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, Pass *P = nullptr); +void FoldSingleEntryPHINodes(BasicBlock *BB, AliasAnalysis *AA = nullptr, + MemoryDependenceAnalysis *MemDep = nullptr); /// DeleteDeadPHIs - Examine each PHI in the given block and delete it if it /// is dead. Also recursively delete any operands that become dead as @@ -50,7 +52,10 @@ bool DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI = nullptr); /// MergeBlockIntoPredecessor - Attempts to merge a block into its predecessor, /// if possible. The return value indicates success or failure. -bool MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P = nullptr); +bool MergeBlockIntoPredecessor(BasicBlock *BB, DominatorTree *DT = nullptr, + LoopInfo *LI = nullptr, + AliasAnalysis *AA = nullptr, + MemoryDependenceAnalysis *MemDep = nullptr); // ReplaceInstWithValue - Replace all uses of an instruction (specified by BI) // with a value, then remove and delete the original instruction. @@ -70,18 +75,62 @@ void ReplaceInstWithInst(BasicBlock::InstListType &BIL, // void ReplaceInstWithInst(Instruction *From, Instruction *To); +/// \brief Option class for critical edge splitting. +/// +/// This provides a builder interface for overriding the default options used +/// during critical edge splitting. +struct CriticalEdgeSplittingOptions { + AliasAnalysis *AA; + DominatorTree *DT; + LoopInfo *LI; + bool MergeIdenticalEdges; + bool DontDeleteUselessPHIs; + bool PreserveLCSSA; + + CriticalEdgeSplittingOptions() + : AA(nullptr), DT(nullptr), LI(nullptr), MergeIdenticalEdges(false), + DontDeleteUselessPHIs(false), PreserveLCSSA(false) {} + + /// \brief Basic case of setting up all the analysis. + CriticalEdgeSplittingOptions(AliasAnalysis *AA, DominatorTree *DT = nullptr, + LoopInfo *LI = nullptr) + : AA(AA), DT(DT), LI(LI), MergeIdenticalEdges(false), + DontDeleteUselessPHIs(false), PreserveLCSSA(false) {} + + /// \brief A common pattern is to preserve the dominator tree and loop + /// info but not care about AA. + CriticalEdgeSplittingOptions(DominatorTree *DT, LoopInfo *LI) + : AA(nullptr), DT(DT), LI(LI), MergeIdenticalEdges(false), + DontDeleteUselessPHIs(false), PreserveLCSSA(false) {} + + CriticalEdgeSplittingOptions &setMergeIdenticalEdges() { + MergeIdenticalEdges = true; + return *this; + } + + CriticalEdgeSplittingOptions &setDontDeleteUselessPHIs() { + DontDeleteUselessPHIs = true; + return *this; + } + + CriticalEdgeSplittingOptions &setPreserveLCSSA() { + PreserveLCSSA = true; + return *this; + } +}; + /// SplitCriticalEdge - If this edge is a critical edge, insert a new node to -/// split the critical edge. This will update DominatorTree and -/// DominatorFrontier information if it is available, thus calling this pass -/// will not invalidate either of them. This returns the new block if the edge -/// was split, null otherwise. +/// split the critical edge. This will update the analyses passed in through +/// the option struct. This returns the new block if the edge was split, null +/// otherwise. /// -/// If MergeIdenticalEdges is true (not the default), *all* edges from TI to the -/// specified successor will be merged into the same critical edge block. -/// This is most commonly interesting with switch instructions, which may -/// have many edges to any one destination. This ensures that all edges to that -/// dest go to one block instead of each going to a different block, but isn't -/// the standard definition of a "critical edge". +/// If MergeIdenticalEdges in the options struct is true (not the default), +/// *all* edges from TI to the specified successor will be merged into the same +/// critical edge block. This is most commonly interesting with switch +/// instructions, which may have many edges to any one destination. This +/// ensures that all edges to that dest go to one block instead of each going +/// to a different block, but isn't the standard definition of a "critical +/// edge". /// /// It is invalid to call this function on a critical edge that starts at an /// IndirectBrInst. Splitting these edges will almost always create an invalid @@ -89,14 +138,15 @@ void ReplaceInstWithInst(Instruction *From, Instruction *To); /// to. /// BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, - Pass *P = nullptr, - bool MergeIdenticalEdges = false, - bool DontDeleteUselessPHIs = false, - bool SplitLandingPads = false); - -inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, - Pass *P = nullptr) { - return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(), P); + const CriticalEdgeSplittingOptions &Options = + CriticalEdgeSplittingOptions()); + +inline BasicBlock * +SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, + const CriticalEdgeSplittingOptions &Options = + CriticalEdgeSplittingOptions()) { + return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(), + Options); } /// SplitCriticalEdge - If the edge from *PI to BB is not critical, return @@ -105,55 +155,62 @@ inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, /// function. If P is specified, it updates the analyses /// described above. inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI, - Pass *P = nullptr) { + const CriticalEdgeSplittingOptions &Options = + CriticalEdgeSplittingOptions()) { bool MadeChange = false; TerminatorInst *TI = (*PI)->getTerminator(); for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) if (TI->getSuccessor(i) == Succ) - MadeChange |= !!SplitCriticalEdge(TI, i, P); + MadeChange |= !!SplitCriticalEdge(TI, i, Options); return MadeChange; } /// SplitCriticalEdge - If an edge from Src to Dst is critical, split the edge /// and return true, otherwise return false. This method requires that there be -/// an edge between the two blocks. If P is specified, it updates the analyses -/// described above. -inline BasicBlock *SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, - Pass *P = nullptr, - bool MergeIdenticalEdges = false, - bool DontDeleteUselessPHIs = false) { +/// an edge between the two blocks. It updates the analyses +/// passed in the options struct +inline BasicBlock * +SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, + const CriticalEdgeSplittingOptions &Options = + CriticalEdgeSplittingOptions()) { TerminatorInst *TI = Src->getTerminator(); unsigned i = 0; while (1) { assert(i != TI->getNumSuccessors() && "Edge doesn't exist!"); if (TI->getSuccessor(i) == Dst) - return SplitCriticalEdge(TI, i, P, MergeIdenticalEdges, - DontDeleteUselessPHIs); + return SplitCriticalEdge(TI, i, Options); ++i; } } // SplitAllCriticalEdges - Loop over all of the edges in the CFG, -// breaking critical edges as they are found. Pass P must not be NULL. +// breaking critical edges as they are found. // Returns the number of broken edges. -unsigned SplitAllCriticalEdges(Function &F, Pass *P); +unsigned SplitAllCriticalEdges(Function &F, + const CriticalEdgeSplittingOptions &Options = + CriticalEdgeSplittingOptions()); -/// SplitEdge - Split the edge connecting specified block. Pass P must -/// not be NULL. -BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To, Pass *P); +/// SplitEdge - Split the edge connecting specified block. +BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To, + DominatorTree *DT = nullptr, LoopInfo *LI = nullptr); /// SplitBlock - Split the specified block at the specified instruction - every /// thing before SplitPt stays in Old and everything starting with SplitPt moves /// to a new block. The two blocks are joined by an unconditional branch and /// the loop info is updated. /// -BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P); +BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, + DominatorTree *DT = nullptr, LoopInfo *LI = nullptr); -/// SplitBlockPredecessors - This method transforms BB by introducing a new -/// basic block into the function, and moving some of the predecessors of BB to -/// be predecessors of the new block. The new predecessors are indicated by the -/// Preds array, which has NumPreds elements in it. The new block is given a -/// suffix of 'Suffix'. This function returns the new block. +/// SplitBlockPredecessors - This method introduces at least one new basic block +/// into the function and moves some of the predecessors of BB to be +/// predecessors of the new block. The new predecessors are indicated by the +/// Preds array. The new block is given a suffix of 'Suffix'. Returns new basic +/// block to which predecessors from Preds are now pointing. +/// +/// If BB is a landingpad block then additional basicblock might be introduced. +/// It will have Suffix+".split_lp". See SplitLandingPadPredecessors for more +/// details on this case. /// /// This currently updates the LLVM IR, AliasAnalysis, DominatorTree, /// DominanceFrontier, LoopInfo, and LCCSA but no other analyses. @@ -161,8 +218,12 @@ BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P); /// complicated to handle the case where one of the edges being split /// is an exit of a loop with other exits). /// -BasicBlock *SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock*> Preds, - const char *Suffix, Pass *P = nullptr); +BasicBlock *SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock *> Preds, + const char *Suffix, + AliasAnalysis *AA = nullptr, + DominatorTree *DT = nullptr, + LoopInfo *LI = nullptr, + bool PreserveLCSSA = false); /// SplitLandingPadPredecessors - This method transforms the landing pad, /// OrigBB, by introducing two new basic blocks into the function. One of those @@ -177,9 +238,14 @@ BasicBlock *SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock*> Preds, /// case where one of the edges being split is an exit of a loop with other /// exits). /// -void SplitLandingPadPredecessors(BasicBlock *OrigBB,ArrayRef<BasicBlock*> Preds, +void SplitLandingPadPredecessors(BasicBlock *OrigBB, + ArrayRef<BasicBlock *> Preds, const char *Suffix, const char *Suffix2, - Pass *P, SmallVectorImpl<BasicBlock*> &NewBBs); + SmallVectorImpl<BasicBlock *> &NewBBs, + AliasAnalysis *AA = nullptr, + DominatorTree *DT = nullptr, + LoopInfo *LI = nullptr, + bool PreserveLCSSA = false); /// FoldReturnIntoUncondBranch - This method duplicates the specified return /// instruction into a predecessor which ends in an unconditional branch. If diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h index 6387c166ec71..879f295caf0c 100644 --- a/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -28,52 +28,50 @@ namespace llvm { /// EmitStrLen - Emit a call to the strlen function to the builder, for the /// specified pointer. Ptr is required to be some pointer type, and the /// return value has 'intptr_t' type. - Value *EmitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout *TD, + Value *EmitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout &DL, const TargetLibraryInfo *TLI); /// EmitStrNLen - Emit a call to the strnlen function to the builder, for the /// specified pointer. Ptr is required to be some pointer type, MaxLen must /// be of size_t type, and the return value has 'intptr_t' type. Value *EmitStrNLen(Value *Ptr, Value *MaxLen, IRBuilder<> &B, - const DataLayout *TD, const TargetLibraryInfo *TLI); + const DataLayout &DL, const TargetLibraryInfo *TLI); /// EmitStrChr - Emit a call to the strchr function to the builder, for the /// specified pointer and character. Ptr is required to be some pointer type, /// and the return value has 'i8*' type. - Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B, const DataLayout *TD, + Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B, const TargetLibraryInfo *TLI); /// EmitStrNCmp - Emit a call to the strncmp function to the builder. Value *EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, - const DataLayout *TD, const TargetLibraryInfo *TLI); + const DataLayout &DL, const TargetLibraryInfo *TLI); /// EmitStrCpy - Emit a call to the strcpy function to the builder, for the /// specified pointer arguments. Value *EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B, - const DataLayout *TD, const TargetLibraryInfo *TLI, - StringRef Name = "strcpy"); + const TargetLibraryInfo *TLI, StringRef Name = "strcpy"); /// EmitStrNCpy - Emit a call to the strncpy function to the builder, for the /// specified pointer arguments and length. Value *EmitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, - const DataLayout *TD, const TargetLibraryInfo *TLI, - StringRef Name = "strncpy"); + const TargetLibraryInfo *TLI, StringRef Name = "strncpy"); /// 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 /// are pointers. Value *EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, - IRBuilder<> &B, const DataLayout *TD, + IRBuilder<> &B, const DataLayout &DL, const TargetLibraryInfo *TLI); /// 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, - const DataLayout *TD, const TargetLibraryInfo *TLI); + const DataLayout &DL, const TargetLibraryInfo *TLI); /// EmitMemCmp - Emit a call to the memcmp function. Value *EmitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, - const DataLayout *TD, const TargetLibraryInfo *TLI); + const DataLayout &DL, const TargetLibraryInfo *TLI); /// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' /// (e.g. 'floor'). This function is known to take a single of type matching @@ -93,28 +91,26 @@ namespace llvm { /// EmitPutChar - Emit a call to the putchar function. This assumes that Char /// is an integer. - Value *EmitPutChar(Value *Char, IRBuilder<> &B, const DataLayout *TD, - const TargetLibraryInfo *TLI); + Value *EmitPutChar(Value *Char, IRBuilder<> &B, const TargetLibraryInfo *TLI); /// EmitPutS - Emit a call to the puts function. This assumes that Str is /// some pointer. - Value *EmitPutS(Value *Str, IRBuilder<> &B, const DataLayout *TD, - const TargetLibraryInfo *TLI); + Value *EmitPutS(Value *Str, IRBuilder<> &B, const TargetLibraryInfo *TLI); /// EmitFPutC - Emit a call to the fputc function. This assumes that Char is /// an i32, and File is a pointer to FILE. Value *EmitFPutC(Value *Char, Value *File, IRBuilder<> &B, - const DataLayout *TD, const TargetLibraryInfo *TLI); + const TargetLibraryInfo *TLI); /// EmitFPutS - Emit a call to the puts function. Str is required to be a /// pointer and File is a pointer to FILE. - Value *EmitFPutS(Value *Str, Value *File, IRBuilder<> &B, const DataLayout *TD, + Value *EmitFPutS(Value *Str, Value *File, IRBuilder<> &B, const TargetLibraryInfo *TLI); /// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is /// a pointer, Size is an 'intptr_t', and File is a pointer to FILE. Value *EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B, - const DataLayout *TD, const TargetLibraryInfo *TLI); + const DataLayout &DL, const TargetLibraryInfo *TLI); } #endif diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index 6584abe822d8..cb187ec103d0 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -95,8 +95,7 @@ struct ClonedCodeInfo { /// function, you can specify a ClonedCodeInfo object with the optional fifth /// parameter. /// -BasicBlock *CloneBasicBlock(const BasicBlock *BB, - ValueToValueMapTy &VMap, +BasicBlock *CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, const Twine &NameSuffix = "", Function *F = nullptr, ClonedCodeInfo *CodeInfo = nullptr); @@ -112,8 +111,7 @@ BasicBlock *CloneBasicBlock(const BasicBlock *BB, /// If ModuleLevelChanges is false, VMap contains no non-identity GlobalValue /// mappings, and debug info metadata will not be cloned. /// -Function *CloneFunction(const Function *F, - ValueToValueMapTy &VMap, +Function *CloneFunction(const Function *F, ValueToValueMapTy &VMap, bool ModuleLevelChanges, ClonedCodeInfo *CodeInfo = nullptr); @@ -127,14 +125,50 @@ Function *CloneFunction(const Function *F, /// mappings. /// void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, - ValueToValueMapTy &VMap, - bool ModuleLevelChanges, + ValueToValueMapTy &VMap, bool ModuleLevelChanges, SmallVectorImpl<ReturnInst*> &Returns, const char *NameSuffix = "", ClonedCodeInfo *CodeInfo = nullptr, ValueMapTypeRemapper *TypeMapper = nullptr, ValueMaterializer *Materializer = nullptr); +/// A helper class used with CloneAndPruneIntoFromInst to change the default +/// behavior while instructions are being cloned. +class CloningDirector { +public: + /// This enumeration describes the way CloneAndPruneIntoFromInst should + /// proceed after the CloningDirector has examined an instruction. + enum CloningAction { + ///< Continue cloning the instruction (default behavior). + CloneInstruction, + ///< Skip this instruction but continue cloning the current basic block. + SkipInstruction, + ///< Skip this instruction and stop cloning the current basic block. + StopCloningBB, + ///< Don't clone the terminator but clone the current block's successors. + CloneSuccessors + }; + + virtual ~CloningDirector() {} + + /// Subclasses must override this function to customize cloning behavior. + virtual CloningAction handleInstruction(ValueToValueMapTy &VMap, + const Instruction *Inst, + BasicBlock *NewBB) = 0; + + virtual ValueMapTypeRemapper *getTypeRemapper() { return nullptr; } + virtual ValueMaterializer *getValueMaterializer() { return nullptr; } +}; + +void CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc, + const Instruction *StartingInst, + ValueToValueMapTy &VMap, bool ModuleLevelChanges, + SmallVectorImpl<ReturnInst*> &Returns, + const char *NameSuffix = "", + ClonedCodeInfo *CodeInfo = nullptr, + CloningDirector *Director = nullptr); + + /// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto, /// except that it does some simple constant prop and DCE on the fly. The /// effect of this is to copy significantly less code in cases where (for @@ -147,12 +181,10 @@ void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, /// mappings. /// void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, - ValueToValueMapTy &VMap, - bool ModuleLevelChanges, + ValueToValueMapTy &VMap, bool ModuleLevelChanges, SmallVectorImpl<ReturnInst*> &Returns, const char *NameSuffix = "", ClonedCodeInfo *CodeInfo = nullptr, - const DataLayout *DL = nullptr, Instruction *TheCall = nullptr); /// InlineFunctionInfo - This class captures the data input to the @@ -160,21 +192,19 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, class InlineFunctionInfo { public: explicit InlineFunctionInfo(CallGraph *cg = nullptr, - const DataLayout *DL = nullptr, AliasAnalysis *AA = nullptr, AssumptionCacheTracker *ACT = nullptr) - : CG(cg), DL(DL), AA(AA), ACT(ACT) {} + : CG(cg), AA(AA), ACT(ACT) {} /// CG - If non-null, InlineFunction will update the callgraph to reflect the /// changes it makes. CallGraph *CG; - const DataLayout *DL; AliasAnalysis *AA; AssumptionCacheTracker *ACT; /// StaticAllocas - InlineFunction fills this in with all static allocas that /// get copied into the caller. - SmallVector<AllocaInst*, 4> StaticAllocas; + SmallVector<AllocaInst *, 4> StaticAllocas; /// InlinedCalls - InlineFunction fills this in with callsites that were /// inlined from the callee. This is only filled in if CG is non-null. @@ -196,9 +226,12 @@ public: /// exists in the instruction stream. Similarly this will inline a recursive /// function by one level. /// -bool InlineFunction(CallInst *C, InlineFunctionInfo &IFI, bool InsertLifetime = true); -bool InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI, bool InsertLifetime = true); -bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI, bool InsertLifetime = true); +bool InlineFunction(CallInst *C, InlineFunctionInfo &IFI, + bool InsertLifetime = true); +bool InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI, + bool InsertLifetime = true); +bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI, + bool InsertLifetime = true); } // End llvm namespace diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index 14844117f44f..a1bb367ac7b6 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -16,6 +16,7 @@ #define LLVM_TRANSFORMS_UTILS_LOCAL_H #include "llvm/IR/DataLayout.h" +#include "llvm/IR/Dominators.h" #include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Operator.h" @@ -31,7 +32,6 @@ class DbgDeclareInst; class StoreInst; class LoadInst; class Value; -class Pass; class PHINode; class AllocaInst; class AssumptionCache; @@ -89,7 +89,7 @@ bool RecursivelyDeleteDeadPHINode(PHINode *PN, /// /// This returns true if it changed the code, note that it can delete /// instructions in other blocks as well in this block. -bool SimplifyInstructionsInBlock(BasicBlock *BB, const DataLayout *TD = nullptr, +bool SimplifyInstructionsInBlock(BasicBlock *BB, const TargetLibraryInfo *TLI = nullptr); //===----------------------------------------------------------------------===// @@ -107,15 +107,14 @@ bool SimplifyInstructionsInBlock(BasicBlock *BB, const DataLayout *TD = nullptr, /// /// .. and delete the predecessor corresponding to the '1', this will attempt to /// recursively fold the 'and' to 0. -void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred, - DataLayout *TD = nullptr); +void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred); /// MergeBasicBlockIntoOnlyPred - BB is a block with one predecessor and its /// predecessor is known to have one successor (BB!). Eliminate the edge /// between them, moving the instructions in the predecessor into BB. This /// deletes the predecessor block. /// -void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, Pass *P = nullptr); +void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr); /// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an /// unconditional branch, and contains no instructions other than PHI nodes, @@ -138,8 +137,7 @@ bool EliminateDuplicatePHINodes(BasicBlock *BB); /// the basic block that was pointed to. /// bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, - unsigned BonusInstThreshold, const DataLayout *TD = nullptr, - AssumptionCache *AC = nullptr); + unsigned BonusInstThreshold, AssumptionCache *AC = nullptr); /// FlatternCFG - This function is used to flatten a CFG. For /// example, it uses parallel-and and parallel-or mode to collapse @@ -151,8 +149,7 @@ bool FlattenCFG(BasicBlock *BB, AliasAnalysis *AA = nullptr); /// and if a predecessor branches to us and one of our successors, fold the /// setcc into the predecessor and use logical operations to pick the right /// destination. -bool FoldBranchToCommonDest(BranchInst *BI, const DataLayout *DL = nullptr, - unsigned BonusInstThreshold = 1); +bool FoldBranchToCommonDest(BranchInst *BI, unsigned BonusInstThreshold = 1); /// DemoteRegToStack - This function takes a virtual register computed by an /// Instruction and replaces it with a slot in the stack frame, allocated via @@ -174,18 +171,17 @@ AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = nullptr); /// 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 DataLayout *TD = nullptr, - AssumptionCache *AC = nullptr, + const DataLayout &DL, const Instruction *CxtI = nullptr, + AssumptionCache *AC = nullptr, const DominatorTree *DT = nullptr); /// getKnownAlignment - Try to infer an alignment for the specified pointer. -static inline unsigned getKnownAlignment(Value *V, - const DataLayout *TD = nullptr, - AssumptionCache *AC = nullptr, +static inline unsigned getKnownAlignment(Value *V, const DataLayout &DL, const Instruction *CxtI = nullptr, + AssumptionCache *AC = nullptr, const DominatorTree *DT = nullptr) { - return getOrEnforceKnownAlignment(V, 0, TD, AC, CxtI, DT); + return getOrEnforceKnownAlignment(V, 0, DL, CxtI, AC, DT); } /// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the @@ -193,11 +189,11 @@ static inline unsigned getKnownAlignment(Value *V, /// in the base pointer). Return the result as a signed integer of intptr size. /// When NoAssumptions is true, no assumptions about index computation not /// overflowing is made. -template<typename IRBuilderTy> -Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &TD, User *GEP, +template <typename IRBuilderTy> +Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP, bool NoAssumptions = false) { GEPOperator *GEPOp = cast<GEPOperator>(GEP); - Type *IntPtrTy = TD.getIntPtrType(GEP->getType()); + Type *IntPtrTy = DL.getIntPtrType(GEP->getType()); Value *Result = Constant::getNullValue(IntPtrTy); // If the GEP is inbounds, we know that none of the addressing operations will @@ -212,7 +208,7 @@ Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &TD, User *GEP, for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e; ++i, ++GTI) { Value *Op = *i; - uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask; + uint64_t Size = DL.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask; if (Constant *OpC = dyn_cast<Constant>(Op)) { if (OpC->isZeroValue()) continue; @@ -223,7 +219,7 @@ Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &TD, User *GEP, OpC = OpC->getSplatValue(); uint64_t OpValue = cast<ConstantInt>(OpC)->getZExtValue(); - Size = TD.getStructLayout(STy)->getElementOffset(OpValue); + Size = DL.getStructLayout(STy)->getElementOffset(OpValue); if (Size) Result = Builder->CreateAdd(Result, ConstantInt::get(IntPtrTy, Size), @@ -275,10 +271,11 @@ bool LowerDbgDeclare(Function &F); /// an alloca, if any. DbgDeclareInst *FindAllocaDbgDeclare(Value *V); -/// replaceDbgDeclareForAlloca - Replaces llvm.dbg.declare instruction when -/// alloca is replaced with a new value. +/// \brief Replaces llvm.dbg.declare instruction when an alloca is replaced with +/// a new value. If Deref is true, tan additional DW_OP_deref is prepended to +/// the expression. bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress, - DIBuilder &Builder); + DIBuilder &Builder, bool Deref); /// \brief Remove all blocks that can not be reached from the function's entry. /// @@ -290,6 +287,10 @@ bool removeUnreachableBlocks(Function &F); /// Metadata not listed as known via KnownIDs is removed void combineMetadata(Instruction *K, const Instruction *J, ArrayRef<unsigned> KnownIDs); +/// \brief Replace each use of 'From' with 'To' if that use is dominated by +/// the given edge. Returns the number of replacements made. +unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT, + const BasicBlockEdge &Edge); } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h index f315adc49d15..28791f5f43a8 100644 --- a/include/llvm/Transforms/Utils/LoopUtils.h +++ b/include/llvm/Transforms/Utils/LoopUtils.h @@ -14,8 +14,14 @@ #ifndef LLVM_TRANSFORMS_UTILS_LOOPUTILS_H #define LLVM_TRANSFORMS_UTILS_LOOPUTILS_H +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/IRBuilder.h" + namespace llvm { class AliasAnalysis; +class AliasSet; +class AliasSetTracker; class AssumptionCache; class BasicBlock; class DataLayout; @@ -23,7 +29,147 @@ class DominatorTree; class Loop; class LoopInfo; class Pass; +class PredIteratorCache; class ScalarEvolution; +class TargetLibraryInfo; + +/// \brief Captures loop safety information. +/// It keep information for loop & its header may throw exception. +struct LICMSafetyInfo { + bool MayThrow; // The current loop contains an instruction which + // may throw. + bool HeaderMayThrow; // Same as previous, but specific to loop header + LICMSafetyInfo() : MayThrow(false), HeaderMayThrow(false) + {} +}; + +/// This POD struct holds information about a potential reduction operation. +class ReductionInstDesc { + +public: + // This enum represents the kind of minmax reduction. + enum MinMaxReductionKind { + MRK_Invalid, + MRK_UIntMin, + MRK_UIntMax, + MRK_SIntMin, + MRK_SIntMax, + MRK_FloatMin, + MRK_FloatMax + }; + ReductionInstDesc(bool IsRedux, Instruction *I) + : IsReduction(IsRedux), PatternLastInst(I), MinMaxKind(MRK_Invalid) {} + + ReductionInstDesc(Instruction *I, MinMaxReductionKind K) + : IsReduction(true), PatternLastInst(I), MinMaxKind(K) {} + + bool isReduction() { return IsReduction; } + + MinMaxReductionKind getMinMaxKind() { return MinMaxKind; } + + Instruction *getPatternInst() { return PatternLastInst; } + +private: + // Is this instruction a reduction candidate. + bool IsReduction; + // The last instruction in a min/max pattern (select of the select(icmp()) + // pattern), or the current reduction instruction otherwise. + Instruction *PatternLastInst; + // If this is a min/max pattern the comparison predicate. + MinMaxReductionKind MinMaxKind; +}; + +/// This struct holds information about reduction variables. +class ReductionDescriptor { + +public: + /// This enum represents the kinds of reductions that we support. + enum ReductionKind { + RK_NoReduction, ///< Not a reduction. + RK_IntegerAdd, ///< Sum of integers. + RK_IntegerMult, ///< Product of integers. + RK_IntegerOr, ///< Bitwise or logical OR of numbers. + RK_IntegerAnd, ///< Bitwise or logical AND of numbers. + RK_IntegerXor, ///< Bitwise or logical XOR of numbers. + RK_IntegerMinMax, ///< Min/max implemented in terms of select(cmp()). + RK_FloatAdd, ///< Sum of floats. + RK_FloatMult, ///< Product of floats. + RK_FloatMinMax ///< Min/max implemented in terms of select(cmp()). + }; + + ReductionDescriptor() + : StartValue(nullptr), LoopExitInstr(nullptr), Kind(RK_NoReduction), + MinMaxKind(ReductionInstDesc::MRK_Invalid) {} + + ReductionDescriptor(Value *Start, Instruction *Exit, ReductionKind K, + ReductionInstDesc::MinMaxReductionKind MK) + : StartValue(Start), LoopExitInstr(Exit), Kind(K), MinMaxKind(MK) {} + + /// Returns a struct describing if the instruction 'I' can be a reduction + /// variable of type 'Kind'. If the reduction is a min/max pattern of + /// select(icmp()) this function advances the instruction pointer 'I' from the + /// compare instruction to the select instruction and stores this pointer in + /// 'PatternLastInst' member of the returned struct. + static ReductionInstDesc isReductionInstr(Instruction *I, ReductionKind Kind, + ReductionInstDesc &Prev, + bool HasFunNoNaNAttr); + + /// Returns true if instuction I has multiple uses in Insts + static bool hasMultipleUsesOf(Instruction *I, + SmallPtrSetImpl<Instruction *> &Insts); + + /// Returns true if all uses of the instruction I is within the Set. + static bool areAllUsesIn(Instruction *I, SmallPtrSetImpl<Instruction *> &Set); + + /// Returns a struct describing if the instruction if the instruction is a + /// Select(ICmp(X, Y), X, Y) instruction pattern corresponding to a min(X, Y) + /// or max(X, Y). + static ReductionInstDesc isMinMaxSelectCmpPattern(Instruction *I, + ReductionInstDesc &Prev); + + /// Returns identity corresponding to the ReductionKind. + static Constant *getReductionIdentity(ReductionKind K, Type *Tp); + + /// Returns the opcode of binary operation corresponding to the ReductionKind. + static unsigned getReductionBinOp(ReductionKind Kind); + + /// Returns a Min/Max operation corresponding to MinMaxReductionKind. + static Value *createMinMaxOp(IRBuilder<> &Builder, + ReductionInstDesc::MinMaxReductionKind RK, + Value *Left, Value *Right); + + /// Returns true if Phi is a reduction of type Kind and adds it to the + /// ReductionDescriptor. + static bool AddReductionVar(PHINode *Phi, ReductionKind Kind, Loop *TheLoop, + bool HasFunNoNaNAttr, + ReductionDescriptor &RedDes); + + /// Returns true if Phi is a reduction in TheLoop. The ReductionDescriptor is + /// returned in RedDes. + static bool isReductionPHI(PHINode *Phi, Loop *TheLoop, + ReductionDescriptor &RedDes); + + ReductionKind getReductionKind() { return Kind; } + + ReductionInstDesc::MinMaxReductionKind getMinMaxReductionKind() { + return MinMaxKind; + } + + TrackingVH<Value> getReductionStartValue() { return StartValue; } + + Instruction *getLoopExitInstr() { return LoopExitInstr; } + +private: + // The starting value of the reduction. + // It does not have to be zero! + TrackingVH<Value> StartValue; + // The instruction who's value is used outside the loop. + Instruction *LoopExitInstr; + // The kind of the reduction. + ReductionKind Kind; + // If this a min/max reduction the kind of reduction. + ReductionInstDesc::MinMaxReductionKind MinMaxKind; +}; BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P); @@ -35,7 +181,6 @@ BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P); /// passed into it. bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, Pass *PP, AliasAnalysis *AA = nullptr, ScalarEvolution *SE = nullptr, - const DataLayout *DL = nullptr, AssumptionCache *AC = nullptr); /// \brief Put loop into LCSSA form. @@ -63,6 +208,53 @@ bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI, /// Returns true if any modifications are made to the loop. bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution *SE = nullptr); + +/// \brief Walk the specified region of the CFG (defined by all blocks +/// dominated by the specified block, and that are in the current loop) in +/// reverse depth first order w.r.t the DominatorTree. This allows us to visit +/// uses before definitions, allowing us to sink a loop body in one pass without +/// iteration. Takes DomTreeNode, AliasAnalysis, LoopInfo, DominatorTree, +/// DataLayout, TargetLibraryInfo, Loop, AliasSet information for all +/// instructions of the loop and loop safety information as arguments. +/// It returns changed status. +bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, + TargetLibraryInfo *, Loop *, AliasSetTracker *, + LICMSafetyInfo *); + +/// \brief Walk the specified region of the CFG (defined by all blocks +/// dominated by the specified block, and that are in the current loop) in depth +/// first order w.r.t the DominatorTree. This allows us to visit definitions +/// before uses, allowing us to hoist a loop body in one pass without iteration. +/// Takes DomTreeNode, AliasAnalysis, LoopInfo, DominatorTree, DataLayout, +/// TargetLibraryInfo, Loop, AliasSet information for all instructions of the +/// loop and loop safety information as arguments. It returns changed status. +bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, + TargetLibraryInfo *, Loop *, AliasSetTracker *, + LICMSafetyInfo *); + +/// \brief Try to promote memory values to scalars by sinking stores out of +/// the loop and moving loads to before the loop. We do this by looping over +/// the stores in the loop, looking for stores to Must pointers which are +/// loop invariant. It takes AliasSet, Loop exit blocks vector, loop exit blocks +/// insertion point vector, PredIteratorCache, LoopInfo, DominatorTree, Loop, +/// AliasSet information for all instructions of the loop and loop safety +/// information as arguments. It returns changed status. +bool promoteLoopAccessesToScalars(AliasSet &, SmallVectorImpl<BasicBlock*> &, + SmallVectorImpl<Instruction*> &, + PredIteratorCache &, LoopInfo *, + DominatorTree *, Loop *, AliasSetTracker *, + LICMSafetyInfo *); + +/// \brief Computes safety information for a loop +/// checks loop body & header for the possiblity of may throw +/// exception, it takes LICMSafetyInfo and loop as argument. +/// Updates safety information in LICMSafetyInfo argument. +void computeLICMSafetyInfo(LICMSafetyInfo *, Loop *); + +/// \brief Checks if the given PHINode in a loop header is an induction +/// variable. Returns true if this is an induction PHI along with the step +/// value. +bool isInductionPHI(PHINode *, ScalarEvolution *, ConstantInt *&); } #endif diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h index 16904f16e369..622265bae143 100644 --- a/include/llvm/Transforms/Utils/ModuleUtils.h +++ b/include/llvm/Transforms/Utils/ModuleUtils.h @@ -14,12 +14,19 @@ #ifndef LLVM_TRANSFORMS_UTILS_MODULEUTILS_H #define LLVM_TRANSFORMS_UTILS_MODULEUTILS_H +#include "llvm/ADT/ArrayRef.h" +#include <utility> // for std::pair + namespace llvm { class Module; class Function; class GlobalValue; class GlobalVariable; +class Constant; +class StringRef; +class Value; +class Type; template <class PtrType> class SmallPtrSetImpl; /// Append F to the list of global ctors of module M with the given Priority. @@ -36,6 +43,20 @@ void appendToGlobalDtors(Module &M, Function *F, int Priority); GlobalVariable *collectUsedGlobalVariables(Module &M, SmallPtrSetImpl<GlobalValue *> &Set, bool CompilerUsed); + +// Validate the result of Module::getOrInsertFunction called for an interface +// function of given sanitizer. If the instrumented module defines a function +// with the same name, their prototypes must match, otherwise +// getOrInsertFunction returns a bitcast. +Function *checkSanitizerInterfaceFunction(Constant *FuncOrBitcast); + +/// \brief Creates sanitizer constructor function, and calls sanitizer's init +/// function from it. +/// \return Returns pair of pointers to constructor, and init functions +/// respectively. +std::pair<Function *, Function *> createSanitizerCtorAndInitFunctions( + Module &M, StringRef CtorName, StringRef InitName, + ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs); } // End llvm namespace #endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h index 7874a5fd8119..1c7b2c587a36 100644 --- a/include/llvm/Transforms/Utils/SSAUpdater.h +++ b/include/llvm/Transforms/Utils/SSAUpdater.h @@ -14,6 +14,7 @@ #ifndef LLVM_TRANSFORMS_UTILS_SSAUPDATER_H #define LLVM_TRANSFORMS_UTILS_SSAUPDATER_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" @@ -118,8 +119,8 @@ public: private: Value *GetValueAtEndOfBlockInternal(BasicBlock *BB); - void operator=(const SSAUpdater&) LLVM_DELETED_FUNCTION; - SSAUpdater(const SSAUpdater&) LLVM_DELETED_FUNCTION; + void operator=(const SSAUpdater&) = delete; + SSAUpdater(const SSAUpdater&) = delete; }; /// \brief Helper class for promoting a collection of loads and stores into SSA @@ -135,7 +136,7 @@ protected: SSAUpdater &SSA; public: - LoadAndStorePromoter(const SmallVectorImpl<Instruction*> &Insts, + LoadAndStorePromoter(ArrayRef<const Instruction*> Insts, SSAUpdater &S, StringRef Name = StringRef()); virtual ~LoadAndStorePromoter() {} diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h index 70ef0eb765dd..41159603aae5 100644 --- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -15,9 +15,10 @@ #ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H #define LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/Target/TargetLibraryInfo.h" namespace llvm { class Value; @@ -36,12 +37,11 @@ class Function; /// is unknown) by passing true for OnlyLowerUnknownSize. class FortifiedLibCallSimplifier { private: - const DataLayout *DL; const TargetLibraryInfo *TLI; bool OnlyLowerUnknownSize; public: - FortifiedLibCallSimplifier(const DataLayout *DL, const TargetLibraryInfo *TLI, + FortifiedLibCallSimplifier(const TargetLibraryInfo *TLI, bool OnlyLowerUnknownSize = false); /// \brief Take the given call instruction and return a more @@ -71,15 +71,24 @@ private: class LibCallSimplifier { private: FortifiedLibCallSimplifier FortifiedSimplifier; - const DataLayout *DL; + const DataLayout &DL; const TargetLibraryInfo *TLI; bool UnsafeFPShrink; + function_ref<void(Instruction *, Value *)> Replacer; -protected: - ~LibCallSimplifier() {} + /// \brief Internal wrapper for RAUW that is the default implementation. + /// + /// Other users may provide an alternate function with this signature instead + /// of this one. + static void replaceAllUsesWithDefault(Instruction *I, Value *With); + + /// \brief Replace an instruction's uses with a value using our replacer. + void replaceAllUsesWith(Instruction *I, Value *With); public: - LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI); + LibCallSimplifier(const DataLayout &DL, const TargetLibraryInfo *TLI, + function_ref<void(Instruction *, Value *)> Replacer = + &replaceAllUsesWithDefault); /// optimizeCall - Take the given call instruction and return a more /// optimal value to replace the instruction with or 0 if a more @@ -90,11 +99,6 @@ public: /// The call must not be an indirect call. Value *optimizeCall(CallInst *CI); - /// replaceAllUsesWith - This method is used when the library call - /// simplifier needs to replace instructions other than the library - /// call being modified. - virtual void replaceAllUsesWith(Instruction *I, Value *With) const; - private: // String and Memory Library Call Optimizations Value *optimizeStrCat(CallInst *CI, IRBuilder<> &B); @@ -112,6 +116,7 @@ private: Value *optimizeStrSpn(CallInst *CI, IRBuilder<> &B); Value *optimizeStrCSpn(CallInst *CI, IRBuilder<> &B); Value *optimizeStrStr(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemChr(CallInst *CI, IRBuilder<> &B); Value *optimizeMemCmp(CallInst *CI, IRBuilder<> &B); Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B); Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B); diff --git a/include/llvm/Transforms/Utils/SymbolRewriter.h b/include/llvm/Transforms/Utils/SymbolRewriter.h index af7937265795..5ccee98f97e7 100644 --- a/include/llvm/Transforms/Utils/SymbolRewriter.h +++ b/include/llvm/Transforms/Utils/SymbolRewriter.h @@ -60,10 +60,10 @@ namespace SymbolRewriter { /// select the symbols to rewrite. This descriptor list is passed to the /// SymbolRewriter pass. class RewriteDescriptor : public ilist_node<RewriteDescriptor> { - RewriteDescriptor(const RewriteDescriptor &) LLVM_DELETED_FUNCTION; + RewriteDescriptor(const RewriteDescriptor &) = delete; const RewriteDescriptor & - operator=(const RewriteDescriptor &) LLVM_DELETED_FUNCTION; + operator=(const RewriteDescriptor &) = delete; public: enum class Type { @@ -90,9 +90,6 @@ typedef iplist<RewriteDescriptor> RewriteDescriptorList; class RewriteMapParser { public: - RewriteMapParser() {} - ~RewriteMapParser() {} - bool parse(const std::string &MapFile, RewriteDescriptorList *Descriptors); private: diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h index 807367cd4b12..7f2cf8d7f59e 100644 --- a/include/llvm/Transforms/Utils/UnrollLoop.h +++ b/include/llvm/Transforms/Utils/UnrollLoop.h @@ -16,20 +16,27 @@ #ifndef LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H #define LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H +#include "llvm/ADT/StringRef.h" + namespace llvm { class AssumptionCache; class Loop; class LoopInfo; class LPPassManager; +class MDNode; class Pass; bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool AllowRuntime, - unsigned TripMultiple, LoopInfo *LI, Pass *PP, - LPPassManager *LPM, AssumptionCache *AC); + bool AllowExpensiveTripCount, unsigned TripMultiple, + LoopInfo *LI, Pass *PP, LPPassManager *LPM, + AssumptionCache *AC); + +bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, + bool AllowExpensiveTripCount, LoopInfo *LI, + LPPassManager *LPM); -bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI, - LPPassManager* LPM); +MDNode *GetUnrollMetadata(MDNode *LoopID, StringRef Name); } #endif diff --git a/include/llvm/Transforms/Utils/VectorUtils.h b/include/llvm/Transforms/Utils/VectorUtils.h index b47acf517b37..9f0fb19d667a 100644 --- a/include/llvm/Transforms/Utils/VectorUtils.h +++ b/include/llvm/Transforms/Utils/VectorUtils.h @@ -14,9 +14,9 @@ #ifndef LLVM_TRANSFORMS_UTILS_VECTORUTILS_H #define LLVM_TRANSFORMS_UTILS_VECTORUTILS_H +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" -#include "llvm/Target/TargetLibraryInfo.h" namespace llvm { @@ -59,7 +59,7 @@ static inline bool isTriviallyVectorizable(Intrinsic::ID ID) { } } -static bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID, +static inline bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID, unsigned ScalarOpdIdx) { switch (ID) { case Intrinsic::ctlz: diff --git a/include/llvm/module.modulemap b/include/llvm/module.modulemap index 61f65510c4ea..163cbc3df865 100644 --- a/include/llvm/module.modulemap +++ b/include/llvm/module.modulemap @@ -2,7 +2,12 @@ module LLVM_Analysis { requires cplusplus umbrella "Analysis" module * { export * } + + // FIXME: Why is this excluded? exclude header "Analysis/BlockFrequencyInfoImpl.h" + + // This is intended for (repeated) textual inclusion. + textual header "Analysis/TargetLibraryInfo.def" } module LLVM_AsmParser { requires cplusplus umbrella "AsmParser" module * { export * } } @@ -40,7 +45,48 @@ module LLVM_Backend { module LLVM_Bitcode { requires cplusplus umbrella "Bitcode" module * { export * } } module LLVM_Config { requires cplusplus umbrella "Config" module * { export * } } -module LLVM_DebugInfo { requires cplusplus umbrella "DebugInfo" module * { export * } } + +module LLVM_DebugInfo { + requires cplusplus + module DIContext { header "DebugInfo/DIContext.h" export * } +} + +module LLVM_DebugInfo_DWARF { + requires cplusplus + + umbrella "DebugInfo/DWARF" + module * { export * } +} + +module LLVM_DebugInfo_PDB { + requires cplusplus + + umbrella "DebugInfo/PDB" + module * { export * } + + // Separate out this subdirectory; it's an optional component that depends on + // a separate library which might not be available. + // + // FIXME: There should be a better way to specify this. + exclude header "DebugInfo/PDB/DIA/DIADataStream.h" + exclude header "DebugInfo/PDB/DIA/DIAEnumDebugStreams.h" + exclude header "DebugInfo/PDB/DIA/DIAEnumLineNumbers.h" + exclude header "DebugInfo/PDB/DIA/DIAEnumSourceFiles.h" + exclude header "DebugInfo/PDB/DIA/DIAEnumSymbols.h" + exclude header "DebugInfo/PDB/DIA/DIALineNumber.h" + exclude header "DebugInfo/PDB/DIA/DIARawSymbol.h" + exclude header "DebugInfo/PDB/DIA/DIASession.h" + exclude header "DebugInfo/PDB/DIA/DIASourceFile.h" + exclude header "DebugInfo/PDB/DIA/DIASupport.h" +} + +module LLVM_DebugInfo_PDB_DIA { + requires cplusplus + + umbrella "DebugInfo/PDB/DIA" + module * { export * } +} + module LLVM_ExecutionEngine { requires cplusplus @@ -55,6 +101,7 @@ module LLVM_ExecutionEngine { exclude header "ExecutionEngine/JIT.h" exclude header "ExecutionEngine/MCJIT.h" exclude header "ExecutionEngine/Interpreter.h" + exclude header "ExecutionEngine/OrcMCJITReplacement.h" } module LLVM_IR { @@ -70,29 +117,12 @@ module LLVM_IR { umbrella "IR" module * { export * } - // We cannot have llvm/PassManager.h and llvm/IR/PassManager.h in the same TU, - // so we can't include llvm/IR/PassManager.h in the IR module. - exclude header "IR/PassManager.h" - exclude header "IR/LegacyPassManager.h" - // These are intended for (repeated) textual inclusion. + textual header "IR/DebugInfoFlags.def" textual header "IR/Instruction.def" textual header "IR/Metadata.def" } -module LLVM_LegacyPassManager { - requires cplusplus - module CompatInterface { header "PassManager.h" export * } - module Implementation { header "IR/LegacyPassManager.h" export * } -} - -module LLVM_IR_PassManager { - requires cplusplus - // FIXME PR19358: This doesn't work! conflict LLVM_LegacyPassManager, "cannot use legacy pass manager and new pass manager in same file" - header "IR/PassManager.h" - export * -} - module LLVM_IRReader { requires cplusplus umbrella "IRReader" module * { export * } } module LLVM_LineEditor { requires cplusplus umbrella "LineEditor" module * { export * } } module LLVM_LTO { requires cplusplus umbrella "LTO" module * { export * } } @@ -164,6 +194,7 @@ module LLVM_Utils { exclude header "Support/TargetRegistry.h" // These are intended for textual inclusion. + textual header "Support/Dwarf.def" textual header "Support/ELFRelocs/AArch64.def" textual header "Support/ELFRelocs/ARM.def" textual header "Support/ELFRelocs/Hexagon.def" |