diff options
Diffstat (limited to 'include')
286 files changed, 6979 insertions, 3630 deletions
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index f2fe764..e85fb97 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -173,10 +173,11 @@ typedef enum { LLVMUWTable = 1 << 30, LLVMNonLazyBind = 1 << 31 - /* FIXME: This attribute is currently not included in the C API as + /* FIXME: These attributes are currently not included in the C API as a temporary measure until the API/ABI impact to the C API is understood and the path forward agreed upon. - LLVMAddressSafety = 1ULL << 32 + LLVMAddressSafety = 1ULL << 32, + LLVMStackProtectStrongAttribute = 1ULL<<33 */ } LLVMAttribute; @@ -357,6 +358,11 @@ typedef enum { void LLVMInitializeCore(LLVMPassRegistryRef R); +/** Deallocate and destroy all ManagedStatic variables. + @see llvm::llvm_shutdown + @see ManagedStatic */ +void LLVMShutdown(); + /*===-- Error handling ----------------------------------------------------===*/ @@ -2547,6 +2553,13 @@ LLVMBool LLVMCreateMemoryBufferWithContentsOfFile(const char *Path, char **OutMessage); LLVMBool LLVMCreateMemoryBufferWithSTDIN(LLVMMemoryBufferRef *OutMemBuf, char **OutMessage); +LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRange(const char *InputData, + size_t InputDataLength, + const char *BufferName, + LLVMBool RequiresNullTerminator); +LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRangeCopy(const char *InputData, + size_t InputDataLength, + const char *BufferName); void LLVMDisposeMemoryBuffer(LLVMMemoryBufferRef MemBuf); /** @@ -2619,6 +2632,34 @@ void LLVMDisposePassManager(LLVMPassManagerRef PM); */ /** + * @defgroup LLVMCCoreThreading Threading + * + * Handle the structures needed to make LLVM safe for multithreading. + * + * @{ + */ + +/** Allocate and initialize structures needed to make LLVM safe for + multithreading. The return value indicates whether multithreaded + initialization succeeded. Must be executed in isolation from all + other LLVM api calls. + @see llvm::llvm_start_multithreaded */ +LLVMBool LLVMStartMultithreaded(); + +/** Deallocate structures necessary to make LLVM safe for multithreading. + Must be executed in isolation from all other LLVM api calls. + @see llvm::llvm_stop_multithreaded */ +void LLVMStopMultithreaded(); + +/** Check whether LLVM is executing in thread-safe mode or not. + @see llvm::llvm_is_multithreaded */ +LLVMBool LLVMIsMultithreaded(); + +/** + * @} + */ + +/** * @} */ diff --git a/include/llvm-c/Initialization.h b/include/llvm-c/Initialization.h index cb3ab9e..ada4738 100644 --- a/include/llvm-c/Initialization.h +++ b/include/llvm-c/Initialization.h @@ -34,6 +34,7 @@ extern "C" { void LLVMInitializeCore(LLVMPassRegistryRef R); void LLVMInitializeTransformUtils(LLVMPassRegistryRef R); void LLVMInitializeScalarOpts(LLVMPassRegistryRef R); +void LLVMInitializeObjCARCOpts(LLVMPassRegistryRef R); void LLVMInitializeVectorization(LLVMPassRegistryRef R); void LLVMInitializeInstCombine(LLVMPassRegistryRef R); void LLVMInitializeIPO(LLVMPassRegistryRef R); diff --git a/include/llvm-c/LinkTimeOptimizer.h b/include/llvm-c/LinkTimeOptimizer.h index 5338d3f..7a0fbf6 100644 --- a/include/llvm-c/LinkTimeOptimizer.h +++ b/include/llvm-c/LinkTimeOptimizer.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef __LTO_CAPI_H__ -#define __LTO_CAPI_H__ +#ifndef LLVM_C_LINKTIMEOPTIMIZER_H +#define LLVM_C_LINKTIMEOPTIMIZER_H #ifdef __cplusplus extern "C" { diff --git a/include/llvm-c/Transforms/PassManagerBuilder.h b/include/llvm-c/Transforms/PassManagerBuilder.h index cee6e5a..0e5e3ca 100644 --- a/include/llvm-c/Transforms/PassManagerBuilder.h +++ b/include/llvm-c/Transforms/PassManagerBuilder.h @@ -11,8 +11,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef LLVM_C_PASSMANAGERBUILDER -#define LLVM_C_PASSMANAGERBUILDER +#ifndef LLVM_C_TRANSFORMS_PASSMANAGERBUILDER_H +#define LLVM_C_TRANSFORMS_PASSMANAGERBUILDER_H #include "llvm-c/Core.h" diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index 74915c0..40110fd 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -13,8 +13,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef LTO_H -#define LTO_H 1 +#ifndef LLVM_C_LTO_H +#define LLVM_C_LTO_H #include <stdbool.h> #include <stddef.h> diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 93d343a..14bcaef 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -97,8 +97,8 @@ nexttoward. */ -#ifndef LLVM_FLOAT_H -#define LLVM_FLOAT_H +#ifndef LLVM_ADT_APFLOAT_H +#define LLVM_ADT_APFLOAT_H // APInt contains static functions implementing bignum arithmetic. #include "llvm/ADT/APInt.h" @@ -184,9 +184,9 @@ namespace llvm { APFloat(const fltSemantics &, integerPart); APFloat(const fltSemantics &, fltCategory, bool negative); APFloat(const fltSemantics &, uninitializedTag); + APFloat(const fltSemantics &, const APInt &); explicit APFloat(double d); explicit APFloat(float f); - explicit APFloat(const APInt &, bool isIEEE = false); APFloat(const APFloat &); ~APFloat(); @@ -300,7 +300,7 @@ namespace llvm { /* 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; // DO NOT IMPLEMENT + bool operator==(const APFloat &) const LLVM_DELETED_FUNCTION; /* IEEE comparison with another floating point number (NaNs compare unordered, 0==-0). */ @@ -423,7 +423,7 @@ namespace llvm { APInt convertQuadrupleAPFloatToAPInt() const; APInt convertF80LongDoubleAPFloatToAPInt() const; APInt convertPPCDoubleDoubleAPFloatToAPInt() const; - void initFromAPInt(const APInt& api, bool isIEEE = false); + void initFromAPInt(const fltSemantics *Sem, const APInt& api); void initFromHalfAPInt(const APInt& api); void initFromFloatAPInt(const APInt& api); void initFromDoubleAPInt(const APInt& api); @@ -463,4 +463,4 @@ namespace llvm { hash_code hash_value(const APFloat &Arg); } /* namespace llvm */ -#endif /* LLVM_FLOAT_H */ +#endif /* LLVM_ADT_APFLOAT_H */ diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 95cd23d..13b353c 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_APINT_H -#define LLVM_APINT_H +#ifndef LLVM_ADT_APINT_H +#define LLVM_ADT_APINT_H #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Compiler.h" @@ -505,6 +505,17 @@ public: return getAllOnesValue(numBits).lshr(numBits - loBitsSet); } + /// \brief Return a value containing V broadcasted over NewLen bits. + static APInt getSplat(unsigned NewLen, const APInt &V) { + assert(NewLen >= V.getBitWidth() && "Can't splat to smaller bit width!"); + + APInt Val = V.zextOrSelf(NewLen); + for (unsigned I = V.getBitWidth(); I < NewLen; I <<= 1) + Val |= Val << I; + + return Val; + } + /// \brief Determine if two APInts have the same value, after zero-extending /// one of them (if needed!) to ensure that the bit-widths match. static bool isSameValue(const APInt &I1, const APInt &I2) { @@ -799,16 +810,7 @@ public: /// Signed divide this APInt by APInt RHS. /// @brief Signed division function for APInt. - APInt sdiv(const APInt &RHS) const { - if (isNegative()) - if (RHS.isNegative()) - return (-(*this)).udiv(-RHS); - else - return -((-(*this)).udiv(RHS)); - else if (RHS.isNegative()) - return -(this->udiv(-RHS)); - return this->udiv(RHS); - } + APInt sdiv(const APInt &RHS) const; /// Perform an unsigned remainder operation on this APInt with RHS being the /// divisor. Both this and RHS are treated as unsigned quantities for purposes @@ -821,16 +823,7 @@ public: /// Signed remainder operation on APInt. /// @brief Function for signed remainder operation. - APInt srem(const APInt &RHS) const { - if (isNegative()) - if (RHS.isNegative()) - return -((-(*this)).urem(-RHS)); - else - return -((-(*this)).urem(RHS)); - else if (RHS.isNegative()) - return this->urem(-RHS); - return this->urem(RHS); - } + APInt srem(const APInt &RHS) const; /// Sometimes it is convenient to divide two APInt values and obtain both the /// quotient and remainder. This function does both operations in the same @@ -842,24 +835,9 @@ public: APInt &Quotient, APInt &Remainder); static void sdivrem(const APInt &LHS, const APInt &RHS, - APInt &Quotient, APInt &Remainder) { - if (LHS.isNegative()) { - if (RHS.isNegative()) - APInt::udivrem(-LHS, -RHS, Quotient, Remainder); - else { - APInt::udivrem(-LHS, RHS, Quotient, Remainder); - Quotient = -Quotient; - } - Remainder = -Remainder; - } else if (RHS.isNegative()) { - APInt::udivrem(LHS, -RHS, Quotient, Remainder); - Quotient = -Quotient; - } else { - APInt::udivrem(LHS, RHS, Quotient, Remainder); - } - } - - + APInt &Quotient, APInt &Remainder); + + // Operations that return overflow indicators. APInt sadd_ov(const APInt &RHS, bool &Overflow) const; APInt uadd_ov(const APInt &RHS, bool &Overflow) const; @@ -1191,7 +1169,8 @@ public: /// APInt. This is used in conjunction with getActiveData to extract the raw /// value of the APInt. unsigned getActiveWords() const { - return whichWord(getActiveBits()-1) + 1; + unsigned numActiveBits = getActiveBits(); + return numActiveBits ? whichWord(numActiveBits - 1) + 1 : 1; } /// Computes the minimum bit width for this APInt while considering it to be diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index 4a5e7a3..42e1239 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_APSINT_H -#define LLVM_APSINT_H +#ifndef LLVM_ADT_APSINT_H +#define LLVM_ADT_APSINT_H #include "llvm/ADT/APInt.h" diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index 1e35d62..c555c1c 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -33,6 +33,8 @@ namespace llvm { typedef const T *const_iterator; typedef size_t size_type; + typedef std::reverse_iterator<iterator> reverse_iterator; + private: /// The start of the array, in an external buffer. const T *Data; @@ -84,6 +86,9 @@ namespace llvm { iterator begin() const { return Data; } iterator end() const { return Data + Length; } + reverse_iterator rbegin() const { return reverse_iterator(end()); } + reverse_iterator rend() const { return reverse_iterator(begin()); } + /// empty - Check if the array is empty. bool empty() const { return Length == 0; } @@ -171,41 +176,41 @@ namespace llvm { /// Construct an empty ArrayRef. /*implicit*/ MutableArrayRef() : ArrayRef<T>() {} - + /// Construct an MutableArrayRef from a single element. /*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef<T>(OneElt) {} - + /// Construct an MutableArrayRef from a pointer and length. /*implicit*/ MutableArrayRef(T *data, size_t length) : ArrayRef<T>(data, length) {} - + /// Construct an MutableArrayRef from a range. MutableArrayRef(T *begin, T *end) : ArrayRef<T>(begin, end) {} - + /// Construct an MutableArrayRef from a SmallVector. /*implicit*/ MutableArrayRef(SmallVectorImpl<T> &Vec) : ArrayRef<T>(Vec) {} - + /// Construct a MutableArrayRef from a std::vector. /*implicit*/ MutableArrayRef(std::vector<T> &Vec) : ArrayRef<T>(Vec) {} - + /// Construct an MutableArrayRef from a C array. template <size_t N> /*implicit*/ MutableArrayRef(T (&Arr)[N]) : ArrayRef<T>(Arr) {} - + T *data() const { return const_cast<T*>(ArrayRef<T>::data()); } iterator begin() const { return data(); } iterator end() const { return data() + this->size(); } - + /// front - Get the first element. T &front() const { assert(!this->empty()); return data()[0]; } - + /// back - Get the last element. T &back() const { assert(!this->empty()); @@ -217,14 +222,14 @@ namespace llvm { assert(N <= this->size() && "Invalid specifier"); return MutableArrayRef<T>(data()+N, this->size()-N); } - + /// slice(n, m) - Chop off the first N elements of the array, and keep M /// elements in the array. MutableArrayRef<T> slice(unsigned N, unsigned M) const { assert(N+M <= this->size() && "Invalid specifier"); return MutableArrayRef<T>(data()+N, M); } - + /// @} /// @name Operator Overloads /// @{ @@ -301,5 +306,5 @@ namespace llvm { static const bool value = true; }; } - + #endif diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 01f7e90..d410619 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -159,6 +159,24 @@ public: return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true); } +#if LLVM_HAS_RVALUE_REFERENCES + // Inserts key,value pair into the map if the key isn't already in the map. + // If the key is already in the map, it returns false and doesn't update the + // value. + 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), + 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); + } +#endif + /// insert - Range insertion of pairs. template<typename InputIt> void insert(InputIt I, InputIt E) { @@ -475,7 +493,6 @@ private: if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) { // If we've already seen a tombstone while probing, fill it in instead // of the empty bucket we eventually probed to. - if (FoundTombstone) ThisBucket = FoundTombstone; FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; return false; } diff --git a/include/llvm/ADT/ImmutableIntervalMap.h b/include/llvm/ADT/ImmutableIntervalMap.h index fa7ccb9..6793c6b 100644 --- a/include/llvm/ADT/ImmutableIntervalMap.h +++ b/include/llvm/ADT/ImmutableIntervalMap.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_IMMUTABLE_INTERVAL_MAP_H -#define LLVM_ADT_IMMUTABLE_INTERVAL_MAP_H +#ifndef LLVM_ADT_IMMUTABLEINTERVALMAP_H +#define LLVM_ADT_IMMUTABLEINTERVALMAP_H #include "llvm/ADT/ImmutableMap.h" diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h index 998d785..7f0c239 100644 --- a/include/llvm/ADT/ImmutableList.h +++ b/include/llvm/ADT/ImmutableList.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_IMLIST_H -#define LLVM_ADT_IMLIST_H +#ifndef LLVM_ADT_IMMUTABLELIST_H +#define LLVM_ADT_IMMUTABLELIST_H #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/Allocator.h" diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h index f9baec2..a667479 100644 --- a/include/llvm/ADT/ImmutableMap.h +++ b/include/llvm/ADT/ImmutableMap.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_IMMAP_H -#define LLVM_ADT_IMMAP_H +#ifndef LLVM_ADT_IMMUTABLEMAP_H +#define LLVM_ADT_IMMUTABLEMAP_H #include "llvm/ADT/ImmutableSet.h" @@ -211,17 +211,22 @@ public: friend class ImmutableMap; public: - value_type_ref operator*() const { return itr->getValue(); } - value_type* operator->() const { return &itr->getValue(); } + 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; } }; diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h index 0982657..fbdf066 100644 --- a/include/llvm/ADT/ImmutableSet.h +++ b/include/llvm/ADT/ImmutableSet.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_IMSET_H -#define LLVM_ADT_IMSET_H +#ifndef LLVM_ADT_IMMUTABLESET_H +#define LLVM_ADT_IMMUTABLESET_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -1054,18 +1054,27 @@ public: class iterator { typename TreeTy::iterator itr; + + iterator() {} iterator(TreeTy* t) : itr(t) {} friend class ImmutableSet<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 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; } }; iterator begin() const { return iterator(Root); } diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index 5849503..9e5ab02 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -18,8 +18,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_INTRUSIVE_REF_CNT_PTR -#define LLVM_ADT_INTRUSIVE_REF_CNT_PTR +#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H +#define LLVM_ADT_INTRUSIVEREFCNTPTR_H #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" @@ -240,4 +240,4 @@ namespace llvm { } // end namespace llvm -#endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR +#endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h index c34e32a..f6fcb08 100644 --- a/include/llvm/ADT/MapVector.h +++ b/include/llvm/ADT/MapVector.h @@ -19,6 +19,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include <vector> namespace llvm { @@ -63,6 +64,11 @@ public: return Vector.empty(); } + std::pair<KeyT, ValueT> &front() { return Vector.front(); } + const std::pair<KeyT, ValueT> &front() const { return Vector.front(); } + std::pair<KeyT, ValueT> &back() { return Vector.back(); } + const std::pair<KeyT, ValueT> &back() const { return Vector.back(); } + void clear() { Map.clear(); Vector.clear(); @@ -84,6 +90,18 @@ public: return Pos == Map.end()? ValueT() : Vector[Pos->second].second; } + std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { + std::pair<KeyT, unsigned> Pair = std::make_pair(KV.first, 0); + std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair); + unsigned &I = Result.first->second; + if (Result.second) { + Vector.push_back(std::make_pair(KV.first, KV.second)); + I = Vector.size() - 1; + return std::make_pair(llvm::prior(end()), true); + } + return std::make_pair(begin() + I, false); + } + unsigned count(const KeyT &Key) const { typename MapType::const_iterator Pos = Map.find(Key); return Pos == Map.end()? 0 : 1; @@ -100,6 +118,13 @@ public: return Pos == Map.end()? Vector.end() : (Vector.begin() + Pos->second); } + + /// \brief Remove the last element from the vector. + void pop_back() { + typename MapType::iterator Pos = Map.find(Vector.back().first); + Map.erase(Pos); + Vector.pop_back(); + } }; } diff --git a/include/llvm/ADT/None.h b/include/llvm/ADT/None.h new file mode 100644 index 0000000..5793bd2 --- /dev/null +++ b/include/llvm/ADT/None.h @@ -0,0 +1,27 @@ +//===-- None.h - Simple null value for implicit construction ------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides None, an enumerator for use in implicit constructors +// of various (usually templated) types to make such construction more +// terse. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_NONE_H +#define LLVM_ADT_NONE_H + +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 +}; +} + +#endif diff --git a/include/llvm/ADT/NullablePtr.h b/include/llvm/ADT/NullablePtr.h index a9c47a1..8ddfd5d 100644 --- a/include/llvm/ADT/NullablePtr.h +++ b/include/llvm/ADT/NullablePtr.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_NULLABLE_PTR_H -#define LLVM_ADT_NULLABLE_PTR_H +#ifndef LLVM_ADT_NULLABLEPTR_H +#define LLVM_ADT_NULLABLEPTR_H #include <cassert> #include <cstddef> diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 06e5af0..81d73ed 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -13,10 +13,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_OPTIONAL -#define LLVM_ADT_OPTIONAL +#ifndef LLVM_ADT_OPTIONAL_H +#define LLVM_ADT_OPTIONAL_H +#include "llvm/ADT/None.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/AlignOf.h" #include <cassert> #if LLVM_HAS_RVALUE_REFERENCES @@ -27,37 +29,102 @@ namespace llvm { template<typename T> class Optional { - T x; + AlignedCharArrayUnion<T> storage; bool hasVal; public: - explicit Optional() : x(), hasVal(false) {} - Optional(const T &y) : x(y), hasVal(true) {} + Optional(NoneType) : hasVal(false) {} + explicit Optional() : hasVal(false) {} + Optional(const T &y) : hasVal(true) { + new (storage.buffer) T(y); + } + Optional(const Optional &O) : hasVal(O.hasVal) { + if (hasVal) + new (storage.buffer) T(*O); + } #if LLVM_HAS_RVALUE_REFERENCES - Optional(T &&y) : x(std::forward<T>(y)), hasVal(true) {} + Optional(T &&y) : hasVal(true) { + new (storage.buffer) T(std::forward<T>(y)); + } + Optional(Optional<T> &&O) : hasVal(O) { + if (O) { + new (storage.buffer) T(std::move(*O)); + O.reset(); + } + } + Optional &operator=(T &&y) { + if (hasVal) + **this = std::move(y); + else { + new (storage.buffer) T(std::move(y)); + hasVal = true; + } + return *this; + } + Optional &operator=(Optional &&O) { + if (!O) + reset(); + else { + *this = std::move(*O); + O.reset(); + } + return *this; + } #endif static inline Optional create(const T* y) { return y ? Optional(*y) : Optional(); } + // FIXME: these assignments (& the equivalent const T&/const Optional& ctors) + // could be made more efficient by passing by value, possibly unifying them + // with the rvalue versions above - but this could place a different set of + // requirements (notably: the existence of a default ctor) when implemented + // in that way. Careful SFINAE to avoid such pitfalls would be required. Optional &operator=(const T &y) { - x = y; - hasVal = true; + if (hasVal) + **this = y; + else { + new (storage.buffer) T(y); + hasVal = true; + } + return *this; + } + + Optional &operator=(const Optional &O) { + if (!O) + reset(); + else + *this = *O; return *this; } - - const T* getPointer() const { assert(hasVal); return &x; } - const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return x; } - operator bool() const { return hasVal; } + void reset() { + if (hasVal) { + (**this).~T(); + hasVal = false; + } + } + + ~Optional() { + reset(); + } + + const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); } + T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); } + 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; } bool hasValue() const { return hasVal; } const T* operator->() const { return getPointer(); } - const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return x; } + T* operator->() { return getPointer(); } + const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } + T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } #if LLVM_HAS_RVALUE_REFERENCE_THIS - T&& getValue() && { assert(hasVal); return std::move(x); } - T&& operator*() && { assert(hasVal); return std::move(x); } + T&& getValue() && { assert(hasVal); return std::move(*getPointer()); } + T&& operator*() && { assert(hasVal); return std::move(*getPointer()); } #endif }; @@ -75,11 +142,17 @@ template <typename T> struct simplify_type<Optional<T> > : public simplify_type<const Optional<T> > {}; +template <typename T> struct isPodLike; +template <typename T> struct isPodLike<Optional<T> > { + // An Optional<T> is pod-like if T is. + static const bool value = isPodLike<T>::value; +}; + /// \brief Poison comparison between two \c Optional objects. Clients needs to /// explicitly compare the underlying values and account for empty \c Optional /// objects. /// -/// This routine will never be defined. It returns \c void to help diagnose +/// This routine will never be defined. It returns \c void to help diagnose /// errors at compile time. template<typename T, typename U> void operator==(const Optional<T> &X, const Optional<U> &Y); @@ -88,7 +161,7 @@ void operator==(const Optional<T> &X, const Optional<U> &Y); /// explicitly compare the underlying values and account for empty \c Optional /// objects. /// -/// This routine will never be defined. It returns \c void to help diagnose +/// This routine will never be defined. It returns \c void to help diagnose /// errors at compile time. template<typename T, typename U> void operator!=(const Optional<T> &X, const Optional<U> &Y); @@ -97,7 +170,7 @@ void operator!=(const Optional<T> &X, const Optional<U> &Y); /// explicitly compare the underlying values and account for empty \c Optional /// objects. /// -/// This routine will never be defined. It returns \c void to help diagnose +/// This routine will never be defined. It returns \c void to help diagnose /// errors at compile time. template<typename T, typename U> void operator<(const Optional<T> &X, const Optional<U> &Y); @@ -106,7 +179,7 @@ void operator<(const Optional<T> &X, const Optional<U> &Y); /// explicitly compare the underlying values and account for empty \c Optional /// objects. /// -/// This routine will never be defined. It returns \c void to help diagnose +/// This routine will never be defined. It returns \c void to help diagnose /// errors at compile time. template<typename T, typename U> void operator<=(const Optional<T> &X, const Optional<U> &Y); @@ -115,7 +188,7 @@ void operator<=(const Optional<T> &X, const Optional<U> &Y); /// explicitly compare the underlying values and account for empty \c Optional /// objects. /// -/// This routine will never be defined. It returns \c void to help diagnose +/// This routine will never be defined. It returns \c void to help diagnose /// errors at compile time. template<typename T, typename U> void operator>=(const Optional<T> &X, const Optional<U> &Y); @@ -124,7 +197,7 @@ void operator>=(const Optional<T> &X, const Optional<U> &Y); /// explicitly compare the underlying values and account for empty \c Optional /// objects. /// -/// This routine will never be defined. It returns \c void to help diagnose +/// This routine will never be defined. It returns \c void to help diagnose /// errors at compile time. template<typename T, typename U> void operator>(const Optional<T> &X, const Optional<U> &Y); diff --git a/include/llvm/ADT/OwningPtr.h b/include/llvm/ADT/OwningPtr.h index ea22991..86f9fee 100644 --- a/include/llvm/ADT/OwningPtr.h +++ b/include/llvm/ADT/OwningPtr.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_OWNING_PTR_H -#define LLVM_ADT_OWNING_PTR_H +#ifndef LLVM_ADT_OWNINGPTR_H +#define LLVM_ADT_OWNINGPTR_H #include "llvm/Support/Compiler.h" #include <cassert> diff --git a/include/llvm/ADT/PriorityQueue.h b/include/llvm/ADT/PriorityQueue.h index bf8a687..827d0b3 100644 --- a/include/llvm/ADT/PriorityQueue.h +++ b/include/llvm/ADT/PriorityQueue.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_PRIORITY_QUEUE_H -#define LLVM_ADT_PRIORITY_QUEUE_H +#ifndef LLVM_ADT_PRIORITYQUEUE_H +#define LLVM_ADT_PRIORITYQUEUE_H #include <algorithm> #include <queue> diff --git a/include/llvm/ADT/SmallString.h b/include/llvm/ADT/SmallString.h index 8da99d1..2cfb5b9 100644 --- a/include/llvm/ADT/SmallString.h +++ b/include/llvm/ADT/SmallString.h @@ -77,7 +77,7 @@ public: void append(in_iter S, in_iter E) { SmallVectorImpl<char>::append(S, E); } - + void append(size_t NumInputs, char Elt) { SmallVectorImpl<char>::append(NumInputs, Elt); } diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 951e574..9167f87 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -145,16 +145,20 @@ public: } reference front() { + assert(!empty()); return begin()[0]; } const_reference front() const { + assert(!empty()); return begin()[0]; } reference back() { + assert(!empty()); return end()[-1]; } const_reference back() const { + assert(!empty()); return end()[-1]; } }; diff --git a/include/llvm/ADT/SparseMultiSet.h b/include/llvm/ADT/SparseMultiSet.h new file mode 100644 index 0000000..7f2a6f7 --- /dev/null +++ b/include/llvm/ADT/SparseMultiSet.h @@ -0,0 +1,526 @@ +//===--- llvm/ADT/SparseMultiSet.h - Sparse multiset ------------*- 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 SparseMultiSet class, which adds multiset behavior to +// the SparseSet. +// +// A sparse multiset holds a small number of objects identified by integer keys +// from a moderately sized universe. The sparse multiset uses more memory than +// other containers in order to provide faster operations. Any key can map to +// multiple values. A SparseMultiSetNode class is provided, which serves as a +// convenient base class for the contents of a SparseMultiSet. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SPARSEMULTISET_H +#define LLVM_ADT_SPARSEMULTISET_H + +#include "llvm/ADT/SparseSet.h" + +namespace llvm { + +/// Fast multiset implementation for objects that can be identified by small +/// unsigned keys. +/// +/// SparseMultiSet allocates memory proportional to the size of the key +/// universe, so it is not recommended for building composite data structures. +/// It is useful for algorithms that require a single set with fast operations. +/// +/// Compared to DenseSet and DenseMap, SparseMultiSet provides constant-time +/// fast clear() as fast as a vector. The find(), insert(), and erase() +/// operations are all constant time, and typically faster than a hash table. +/// The iteration order doesn't depend on numerical key values, it only depends +/// on the order of insert() and erase() operations. Iteration order is the +/// insertion order. Iteration is only provided over elements of equivalent +/// keys, but iterators are bidirectional. +/// +/// Compared to BitVector, SparseMultiSet<unsigned> uses 8x-40x more memory, but +/// offers constant-time clear() and size() operations as well as fast iteration +/// independent on the size of the universe. +/// +/// SparseMultiSet contains a dense vector holding all the objects and a sparse +/// array holding indexes into the dense vector. Most of the memory is used by +/// the sparse array which is the size of the key universe. The SparseT template +/// parameter provides a space/speed tradeoff for sets holding many elements. +/// +/// When SparseT is uint32_t, find() only touches up to 3 cache lines, but the +/// sparse array uses 4 x Universe bytes. +/// +/// When SparseT is uint8_t (the default), find() touches up to 3+[N/256] cache +/// lines, but the sparse array is 4x smaller. N is the number of elements in +/// the set. +/// +/// For sets that may grow to thousands of elements, SparseT should be set to +/// uint16_t or uint32_t. +/// +/// Multiset behavior is provided by providing doubly linked lists for values +/// that are inlined in the dense vector. SparseMultiSet is a good choice when +/// one desires a growable number of entries per key, as it will retain the +/// SparseSet algorithmic properties despite being growable. Thus, it is often a +/// better choice than a SparseSet of growable containers or a vector of +/// vectors. SparseMultiSet also keeps iterators valid after erasure (provided +/// the iterators don't point to the element erased), allowing for more +/// intuitive and fast removal. +/// +/// @tparam ValueT The type of objects in the set. +/// @tparam KeyFunctorT A functor that computes an unsigned index from KeyT. +/// @tparam SparseT An unsigned integer type. See above. +/// +template<typename ValueT, + typename KeyFunctorT = llvm::identity<unsigned>, + typename SparseT = uint8_t> +class SparseMultiSet { + /// The actual data that's stored, as a doubly-linked list implemented via + /// indices into the DenseVector. The doubly linked list is implemented + /// circular in Prev indices, and INVALID-terminated in Next indices. This + /// provides efficient access to list tails. These nodes can also be + /// tombstones, in which case they are actually nodes in a single-linked + /// freelist of recyclable slots. + struct SMSNode { + static const unsigned INVALID = ~0U; + + ValueT Data; + unsigned Prev; + unsigned Next; + + SMSNode(ValueT D, unsigned P, unsigned N) : Data(D), Prev(P), Next(N) { } + + /// List tails have invalid Nexts. + bool isTail() const { + return Next == INVALID; + } + + /// Whether this node is a tombstone node, and thus is in our freelist. + bool isTombstone() const { + return Prev == INVALID; + } + + /// Since the list is circular in Prev, all non-tombstone nodes have a valid + /// Prev. + bool isValid() const { return Prev != INVALID; } + }; + + typedef typename KeyFunctorT::argument_type KeyT; + typedef SmallVector<SMSNode, 8> DenseT; + DenseT Dense; + SparseT *Sparse; + unsigned Universe; + KeyFunctorT KeyIndexOf; + SparseSetValFunctor<KeyT, ValueT, KeyFunctorT> ValIndexOf; + + /// We have a built-in recycler for reusing tombstone slots. This recycler + /// puts a singly-linked free list into tombstone slots, allowing us quick + /// erasure, iterator preservation, and dense size. + unsigned FreelistIdx; + unsigned NumFree; + + unsigned sparseIndex(const ValueT &Val) const { + assert(ValIndexOf(Val) < Universe && + "Invalid key in set. Did object mutate?"); + return ValIndexOf(Val); + } + unsigned sparseIndex(const SMSNode &N) const { return sparseIndex(N.Data); } + + // 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; + + /// 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 + /// list tail. D must be a valid entry node. + bool isHead(const SMSNode &D) const { + assert(D.isValid() && "Invalid node for head"); + return Dense[D.Prev].isTail(); + } + + /// Whether the given entry is a singleton entry, i.e. the only entry with + /// that key. + bool isSingleton(const SMSNode &N) const { + assert(N.isValid() && "Invalid node for singleton"); + // Is N its own predecessor? + return &Dense[N.Prev] == &N; + } + + /// Add in the given SMSNode. Uses a free entry in our freelist if + /// available. Returns the index of the added node. + unsigned addValue(const ValueT& V, unsigned Prev, unsigned Next) { + if (NumFree == 0) { + Dense.push_back(SMSNode(V, Prev, Next)); + return Dense.size() - 1; + } + + // Peel off a free slot + unsigned Idx = FreelistIdx; + unsigned NextFree = Dense[Idx].Next; + assert(Dense[Idx].isTombstone() && "Non-tombstone free?"); + + Dense[Idx] = SMSNode(V, Prev, Next); + FreelistIdx = NextFree; + --NumFree; + return Idx; + } + + /// Make the current index a new tombstone. Pushes it onto the freelist. + void makeTombstone(unsigned Idx) { + Dense[Idx].Prev = SMSNode::INVALID; + Dense[Idx].Next = FreelistIdx; + FreelistIdx = Idx; + ++NumFree; + } + +public: + typedef ValueT value_type; + typedef ValueT &reference; + typedef const ValueT &const_reference; + typedef ValueT *pointer; + typedef const ValueT *const_pointer; + + SparseMultiSet() + : Sparse(0), Universe(0), FreelistIdx(SMSNode::INVALID), NumFree(0) { } + + ~SparseMultiSet() { free(Sparse); } + + /// Set the universe size which determines the largest key the set can hold. + /// The universe must be sized before any elements can be added. + /// + /// @param U Universe size. All object keys must be less than U. + /// + void setUniverse(unsigned U) { + // It's not hard to resize the universe on a non-empty set, but it doesn't + // seem like a likely use case, so we can add that code when we need it. + assert(empty() && "Can only resize universe on an empty map"); + // Hysteresis prevents needless reallocations. + if (U >= Universe/4 && U <= Universe) + return; + free(Sparse); + // The Sparse array doesn't actually need to be initialized, so malloc + // would be enough here, but that will cause tools like valgrind to + // complain about branching on uninitialized data. + Sparse = reinterpret_cast<SparseT*>(calloc(U, sizeof(SparseT))); + Universe = U; + } + + /// Our iterators are iterators over the collection of objects that share a + /// key. + template<typename SMSPtrTy> + class iterator_base : public std::iterator<std::bidirectional_iterator_tag, + ValueT> { + friend class SparseMultiSet; + SMSPtrTy SMS; + unsigned Idx; + unsigned SparseIdx; + + iterator_base(SMSPtrTy P, unsigned I, unsigned SI) + : SMS(P), Idx(I), SparseIdx(SI) { } + + /// Whether our iterator has fallen outside our dense vector. + bool isEnd() const { + if (Idx == SMSNode::INVALID) + return true; + + assert(Idx < SMS->Dense.size() && "Out of range, non-INVALID Idx?"); + return false; + } + + /// Whether our iterator is properly keyed, i.e. the SparseIdx is valid + bool isKeyed() const { return SparseIdx < SMS->Universe; } + + unsigned Prev() const { return SMS->Dense[Idx].Prev; } + unsigned Next() const { return SMS->Dense[Idx].Next; } + + void setPrev(unsigned P) { SMS->Dense[Idx].Prev = P; } + void setNext(unsigned N) { SMS->Dense[Idx].Next = N; } + + public: + typedef std::iterator<std::bidirectional_iterator_tag, ValueT> super; + typedef typename super::value_type value_type; + typedef typename super::difference_type difference_type; + typedef typename super::pointer pointer; + typedef typename super::reference reference; + + iterator_base(const iterator_base &RHS) + : SMS(RHS.SMS), Idx(RHS.Idx), SparseIdx(RHS.SparseIdx) { } + + const iterator_base &operator=(const iterator_base &RHS) { + SMS = RHS.SMS; + Idx = RHS.Idx; + SparseIdx = RHS.SparseIdx; + return *this; + } + + reference operator*() const { + assert(isKeyed() && SMS->sparseIndex(SMS->Dense[Idx].Data) == SparseIdx && + "Dereferencing iterator of invalid key or index"); + + return SMS->Dense[Idx].Data; + } + pointer operator->() const { return &operator*(); } + + /// Comparison operators + bool operator==(const iterator_base &RHS) const { + // end compares equal + if (SMS == RHS.SMS && Idx == RHS.Idx) { + assert((isEnd() || SparseIdx == RHS.SparseIdx) && + "Same dense entry, but different keys?"); + return true; + } + + return false; + } + + bool operator!=(const iterator_base &RHS) const { + return !operator==(RHS); + } + + /// Increment and decrement operators + iterator_base &operator--() { // predecrement - Back up + assert(isKeyed() && "Decrementing an invalid iterator"); + assert((isEnd() || !SMS->isHead(SMS->Dense[Idx])) && + "Decrementing head of list"); + + // If we're at the end, then issue a new find() + if (isEnd()) + Idx = SMS->findIndex(SparseIdx).Prev(); + else + Idx = Prev(); + + return *this; + } + iterator_base &operator++() { // preincrement - Advance + assert(!isEnd() && isKeyed() && "Incrementing an invalid/end iterator"); + Idx = Next(); + return *this; + } + iterator_base operator--(int) { // postdecrement + iterator_base I(*this); + --*this; + return I; + } + iterator_base operator++(int) { // postincrement + iterator_base I(*this); + ++*this; + return I; + } + }; + typedef iterator_base<SparseMultiSet *> iterator; + typedef iterator_base<const SparseMultiSet *> const_iterator; + + // Convenience types + typedef std::pair<iterator, iterator> RangePair; + + /// Returns an iterator past this container. Note that such an iterator cannot + /// be decremented, but will compare equal to other end iterators. + iterator end() { return iterator(this, SMSNode::INVALID, SMSNode::INVALID); } + const_iterator end() const { + return const_iterator(this, SMSNode::INVALID, SMSNode::INVALID); + } + + /// Returns true if the set is empty. + /// + /// This is not the same as BitVector::empty(). + /// + bool empty() const { return size() == 0; } + + /// Returns the number of elements in the set. + /// + /// This is not the same as BitVector::size() which returns the size of the + /// universe. + /// + unsigned size() const { + assert(NumFree <= Dense.size() && "Out-of-bounds free entries"); + return Dense.size() - NumFree; + } + + /// Clears the set. This is a very fast constant time operation. + /// + void clear() { + // Sparse does not need to be cleared, see find(). + Dense.clear(); + NumFree = 0; + FreelistIdx = SMSNode::INVALID; + } + + /// Find an element by its index. + /// + /// @param Idx A valid index to find. + /// @returns An iterator to the element identified by key, or end(). + /// + iterator findIndex(unsigned Idx) { + assert(Idx < Universe && "Key out of range"); + assert(std::numeric_limits<SparseT>::is_integer && + !std::numeric_limits<SparseT>::is_signed && + "SparseT must be an unsigned integer type"); + const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u; + for (unsigned i = Sparse[Idx], e = Dense.size(); i < e; i += Stride) { + const unsigned FoundIdx = sparseIndex(Dense[i]); + // Check that we're pointing at the correct entry and that it is the head + // of a valid list. + if (Idx == FoundIdx && Dense[i].isValid() && isHead(Dense[i])) + return iterator(this, i, Idx); + // Stride is 0 when SparseT >= unsigned. We don't need to loop. + if (!Stride) + break; + } + return end(); + } + + /// Find an element by its key. + /// + /// @param Key A valid key to find. + /// @returns An iterator to the element identified by key, or end(). + /// + iterator find(const KeyT &Key) { + return findIndex(KeyIndexOf(Key)); + } + + const_iterator find(const KeyT &Key) const { + iterator I = const_cast<SparseMultiSet*>(this)->findIndex(KeyIndexOf(Key)); + return const_iterator(I.SMS, I.Idx, KeyIndexOf(Key)); + } + + /// Returns the number of elements identified by Key. This will be linear in + /// the number of elements of that key. + unsigned count(const KeyT &Key) const { + unsigned Ret = 0; + for (const_iterator It = find(Key); It != end(); ++It) + ++Ret; + + return Ret; + } + + /// Returns true if this set contains an element identified by Key. + bool contains(const KeyT &Key) const { + return find(Key) != end(); + } + + /// Return the head and tail of the subset's list, otherwise returns end(). + iterator getHead(const KeyT &Key) { return find(Key); } + iterator getTail(const KeyT &Key) { + iterator I = find(Key); + if (I != end()) + I = iterator(this, I.Prev(), KeyIndexOf(Key)); + return I; + } + + /// The bounds of the range of items sharing Key K. First member is the head + /// of the list, and the second member is a decrementable end iterator for + /// that key. + RangePair equal_range(const KeyT &K) { + iterator B = find(K); + iterator E = iterator(this, SMSNode::INVALID, B.SparseIdx); + return make_pair(B, E); + } + + /// Insert a new element at the tail of the subset list. Returns an iterator + /// to the newly added entry. + iterator insert(const ValueT &Val) { + unsigned Idx = sparseIndex(Val); + iterator I = findIndex(Idx); + + unsigned NodeIdx = addValue(Val, SMSNode::INVALID, SMSNode::INVALID); + + if (I == end()) { + // Make a singleton list + Sparse[Idx] = NodeIdx; + Dense[NodeIdx].Prev = NodeIdx; + return iterator(this, NodeIdx, Idx); + } + + // Stick it at the end. + unsigned HeadIdx = I.Idx; + unsigned TailIdx = I.Prev(); + Dense[TailIdx].Next = NodeIdx; + Dense[HeadIdx].Prev = NodeIdx; + Dense[NodeIdx].Prev = TailIdx; + + return iterator(this, NodeIdx, Idx); + } + + /// Erases an existing element identified by a valid iterator. + /// + /// This invalidates iterators pointing at the same entry, but erase() returns + /// an iterator pointing to the next element in the subset's list. This makes + /// it possible to erase selected elements while iterating over the subset: + /// + /// tie(I, E) = Set.equal_range(Key); + /// while (I != E) + /// if (test(*I)) + /// I = Set.erase(I); + /// else + /// ++I; + /// + /// Note that if the last element in the subset list is erased, this will + /// return an end iterator which can be decremented to get the new tail (if it + /// exists): + /// + /// tie(B, I) = Set.equal_range(Key); + /// for (bool isBegin = B == I; !isBegin; /* empty */) { + /// isBegin = (--I) == B; + /// if (test(I)) + /// break; + /// I = erase(I); + /// } + iterator erase(iterator I) { + assert(I.isKeyed() && !I.isEnd() && !Dense[I.Idx].isTombstone() && + "erasing invalid/end/tombstone iterator"); + + // First, unlink the node from its list. Then swap the node out with the + // dense vector's last entry + iterator NextI = unlink(Dense[I.Idx]); + + // Put in a tombstone. + makeTombstone(I.Idx); + + return NextI; + } + + /// Erase all elements with the given key. This invalidates all + /// iterators of that key. + void eraseAll(const KeyT &K) { + for (iterator I = find(K); I != end(); /* empty */) + I = erase(I); + } + +private: + /// Unlink the node from its list. Returns the next node in the list. + iterator unlink(const SMSNode &N) { + if (isSingleton(N)) { + // Singleton is already unlinked + assert(N.Next == SMSNode::INVALID && "Singleton has next?"); + return iterator(this, SMSNode::INVALID, ValIndexOf(N.Data)); + } + + if (isHead(N)) { + // If we're the head, then update the sparse array and our next. + Sparse[sparseIndex(N)] = N.Next; + Dense[N.Next].Prev = N.Prev; + return iterator(this, N.Next, ValIndexOf(N.Data)); + } + + if (N.isTail()) { + // If we're the tail, then update our head and our previous. + findIndex(sparseIndex(N)).setPrev(N.Prev); + Dense[N.Prev].Next = N.Next; + + // Give back an end iterator that can be decremented + iterator I(this, N.Prev, ValIndexOf(N.Data)); + return ++I; + } + + // Otherwise, just drop us + Dense[N.Next].Prev = N.Prev; + Dense[N.Prev].Next = N.Next; + return iterator(this, N.Next, ValIndexOf(N.Data)); + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h index 9503e0f..d2887c5 100644 --- a/include/llvm/ADT/StringExtras.h +++ b/include/llvm/ADT/StringExtras.h @@ -27,6 +27,17 @@ static inline char hexdigit(unsigned X, bool LowerCase = false) { return X < 10 ? '0' + X : HexChar + X - 10; } +/// Interpret the given character \p C as a hexadecimal digit and return its +/// value. +/// +/// If \p C is not a valid hex digit, -1U is returned. +static inline unsigned hexDigitValue(char C) { + if (C >= '0' && C <= '9') return C-'0'; + if (C >= 'a' && C <= 'f') return C-'a'+10U; + if (C >= 'A' && C <= 'F') return C-'A'+10U; + return -1U; +} + /// utohex_buffer - Emit the specified number into the buffer specified by /// BufferEnd, returning a pointer to the start of the string. This can be used /// like this: (note that the buffer must be large enough to handle any number): diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index 0d68d11..d01437b 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -237,6 +237,10 @@ public: explicit StringMap(AllocatorTy A) : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {} + StringMap(unsigned InitialSize, AllocatorTy A) + : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))), + Allocator(A) {} + StringMap(const StringMap &RHS) : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) { assert(RHS.empty() && @@ -334,8 +338,8 @@ public: StringMapEntryBase *&Bucket = TheTable[I]; if (Bucket && Bucket != getTombstoneVal()) { static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator); - Bucket = 0; } + Bucket = 0; } NumItems = 0; diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index 0e93f51..224855e 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -57,14 +57,14 @@ namespace llvm { // integer works around this bug. static size_t min(size_t a, size_t b) { return a < b ? a : b; } static size_t max(size_t a, size_t b) { return a > b ? a : b; } - + // Workaround memcmp issue with null pointers (undefined behavior) // by providing a specialized version static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) { if (Length == 0) { return 0; } return ::memcmp(Lhs,Rhs,Length); } - + public: /// @name Constructors /// @{ @@ -387,7 +387,7 @@ namespace llvm { Start = min(Start, Length); return StringRef(Data + Start, min(N, Length - Start)); } - + /// Return a StringRef equal to 'this' but with the first \p N elements /// dropped. StringRef drop_front(unsigned N = 1) const { @@ -535,7 +535,7 @@ namespace llvm { return LHS.compare(RHS) != -1; } - inline std::string &operator+=(std::string &buffer, llvm::StringRef string) { + inline std::string &operator+=(std::string &buffer, StringRef string) { return buffer.append(string.data(), string.size()); } diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 49d9f68..8fac222 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -44,6 +44,7 @@ public: UnknownArch, arm, // ARM; arm, armv.*, xscale + aarch64, // AArch64: aarch64 hexagon, // Hexagon: hexagon mips, // MIPS: mips, mipsallegrex mipsel, // MIPSEL: mipsel, mipsallegrexel @@ -111,6 +112,7 @@ public: GNU, GNUEABI, GNUEABIHF, + GNUX32, EABI, MachO, Android, @@ -295,9 +297,14 @@ public: return getOS() == Triple::Darwin || getOS() == Triple::MacOSX; } + /// Is this an iOS triple. + bool isiOS() const { + return getOS() == Triple::IOS; + } + /// isOSDarwin - Is this a "Darwin" OS (OS X or iOS). bool isOSDarwin() const { - return isMacOSX() || getOS() == Triple::IOS; + return isMacOSX() || isiOS(); } /// \brief Tests for either Cygwin or MinGW OS diff --git a/include/llvm/ADT/VariadicFunction.h b/include/llvm/ADT/VariadicFunction.h index a7f83a6..0497aa7 100644 --- a/include/llvm/ADT/VariadicFunction.h +++ b/include/llvm/ADT/VariadicFunction.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_VARIADIC_FUNCTION_H -#define LLVM_ADT_VARIADIC_FUNCTION_H +#ifndef LLVM_ADT_VARIADICFUNCTION_H +#define LLVM_ADT_VARIADICFUNCTION_H #include "llvm/ADT/ArrayRef.h" @@ -328,4 +328,4 @@ struct VariadicFunction3 { } // end namespace llvm -#endif // LLVM_ADT_VARIADIC_FUNCTION_H +#endif // LLVM_ADT_VARIADICFUNCTION_H diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index 20cdae3..aeb7848 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -234,17 +234,17 @@ public: pointer getNodePtrUnchecked() const { return NodePtr; } }; -// do not implement. this is to catch errors when people try to use -// them as random access iterators +// These are to catch errors when people try to use them as random access +// iterators. template<typename T> -void operator-(int, ilist_iterator<T>); +void operator-(int, ilist_iterator<T>) LLVM_DELETED_FUNCTION; template<typename T> -void operator-(ilist_iterator<T>,int); +void operator-(ilist_iterator<T>,int) LLVM_DELETED_FUNCTION; template<typename T> -void operator+(int, ilist_iterator<T>); +void operator+(int, ilist_iterator<T>) LLVM_DELETED_FUNCTION; template<typename T> -void operator+(ilist_iterator<T>,int); +void operator+(ilist_iterator<T>,int) LLVM_DELETED_FUNCTION; // operator!=/operator== - Allow mixed comparisons without dereferencing // the iterator, which could very likely be pointing to end(). diff --git a/include/llvm/ADT/ilist_node.h b/include/llvm/ADT/ilist_node.h index f008003..0361244 100644 --- a/include/llvm/ADT/ilist_node.h +++ b/include/llvm/ADT/ilist_node.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_ILIST_NODE_H -#define LLVM_ADT_ILIST_NODE_H +#ifndef LLVM_ADT_ILISTNODE_H +#define LLVM_ADT_ILISTNODE_H namespace llvm { diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 3ce4732..d703f21 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -34,8 +34,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_ALIAS_ANALYSIS_H -#define LLVM_ANALYSIS_ALIAS_ANALYSIS_H +#ifndef LLVM_ANALYSIS_ALIASANALYSIS_H +#define LLVM_ANALYSIS_ALIASANALYSIS_H #include "llvm/ADT/DenseMap.h" #include "llvm/Support/CallSite.h" @@ -593,11 +593,6 @@ bool isNoAliasCall(const Value *V); /// bool isIdentifiedObject(const Value *V); -/// 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); - } // End llvm namespace #endif diff --git a/include/llvm/Analysis/CallGraphSCCPass.h b/include/llvm/Analysis/CallGraphSCCPass.h index 4446777..e609dac 100644 --- a/include/llvm/Analysis/CallGraphSCCPass.h +++ b/include/llvm/Analysis/CallGraphSCCPass.h @@ -18,8 +18,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CALL_GRAPH_SCC_PASS_H -#define LLVM_CALL_GRAPH_SCC_PASS_H +#ifndef LLVM_ANALYSIS_CALLGRAPHSCCPASS_H +#define LLVM_ANALYSIS_CALLGRAPHSCCPASS_H #include "llvm/Analysis/CallGraph.h" #include "llvm/Pass.h" diff --git a/include/llvm/Analysis/CallPrinter.h b/include/llvm/Analysis/CallPrinter.h new file mode 100644 index 0000000..5f5d160 --- /dev/null +++ b/include/llvm/Analysis/CallPrinter.h @@ -0,0 +1,27 @@ +//===-- CallPrinter.h - Call graph printer external interface ----*- 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 external functions that can be called to explicitly +// instantiate the call graph printer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CALLPRINTER_H +#define LLVM_ANALYSIS_CALLPRINTER_H + +namespace llvm { + + class ModulePass; + + ModulePass *createCallGraphViewerPass(); + ModulePass *createCallGraphPrinterPass(); + +} // end namespace llvm + +#endif diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h index 35eabec..086934d 100644 --- a/include/llvm/Analysis/CodeMetrics.h +++ b/include/llvm/Analysis/CodeMetrics.h @@ -19,80 +19,75 @@ #include "llvm/Support/CallSite.h" namespace llvm { - class BasicBlock; - class Function; - class Instruction; - class DataLayout; - class Value; +class BasicBlock; +class Function; +class Instruction; +class DataLayout; +class TargetTransformInfo; +class Value; + +/// \brief Check whether a call will lower to something small. +/// +/// This tests checks whether this callsite will lower to something +/// significantly cheaper than a traditional call, often a single +/// instruction. Note that if isInstructionFree(CS.getInstruction()) would +/// return true, so will this function. +bool callIsSmall(ImmutableCallSite CS); + +/// \brief Utility to calculate the size and a few similar metrics for a set +/// of basic blocks. +struct CodeMetrics { + /// \brief True if this function contains a call to setjmp or other functions + /// with attribute "returns twice" without having the attribute itself. + bool exposesReturnsTwice; + + /// \brief True if this function calls itself. + bool isRecursive; + + /// \brief True if this function cannot be duplicated. + /// + /// True if this function contains one or more indirect branches, or it contains + /// one or more 'noduplicate' instructions. + bool notDuplicatable; + + /// \brief True if this function calls alloca (in the C sense). + bool usesDynamicAlloca; + + /// \brief Number of instructions in the analyzed blocks. + unsigned NumInsts; - /// \brief Check whether an instruction is likely to be "free" when lowered. - bool isInstructionFree(const Instruction *I, const DataLayout *TD = 0); + /// \brief Number of analyzed blocks. + unsigned NumBlocks; - /// \brief Check whether a call will lower to something small. + /// \brief Keeps track of basic block code size estimates. + DenseMap<const BasicBlock *, unsigned> NumBBInsts; + + /// \brief Keep track of the number of calls to 'big' functions. + unsigned NumCalls; + + /// \brief The number of calls to internal functions with a single caller. /// - /// This tests checks whether this callsite will lower to something - /// significantly cheaper than a traditional call, often a single - /// instruction. Note that if isInstructionFree(CS.getInstruction()) would - /// return true, so will this function. - bool callIsSmall(ImmutableCallSite CS); - - /// \brief Utility to calculate the size and a few similar metrics for a set - /// of basic blocks. - struct CodeMetrics { - /// \brief True if this function contains a call to setjmp or other functions - /// with attribute "returns twice" without having the attribute itself. - bool exposesReturnsTwice; - - /// \brief True if this function calls itself. - bool isRecursive; - - /// \brief True if this function cannot be duplicated. - /// - /// True if this function contains one or more indirect branches, or it contains - /// one or more 'noduplicate' instructions. - bool notDuplicatable; - - /// \brief True if this function calls alloca (in the C sense). - bool usesDynamicAlloca; - - /// \brief Number of instructions in the analyzed blocks. - unsigned NumInsts; - - /// \brief Number of analyzed blocks. - unsigned NumBlocks; - - /// \brief Keeps track of basic block code size estimates. - DenseMap<const BasicBlock *, unsigned> NumBBInsts; - - /// \brief Keep track of the number of calls to 'big' functions. - unsigned NumCalls; - - /// \brief The number of calls to internal functions with a single caller. - /// - /// These are likely targets for future inlining, likely exposed by - /// interleaved devirtualization. - unsigned NumInlineCandidates; - - /// \brief How many instructions produce vector values. - /// - /// The inliner is more aggressive with inlining vector kernels. - unsigned NumVectorInsts; - - /// \brief How many 'ret' instructions the blocks contain. - unsigned NumRets; - - CodeMetrics() : exposesReturnsTwice(false), isRecursive(false), - notDuplicatable(false), usesDynamicAlloca(false), - NumInsts(0), NumBlocks(0), NumCalls(0), - NumInlineCandidates(0), NumVectorInsts(0), - NumRets(0) {} - - /// \brief Add information about a block to the current state. - void analyzeBasicBlock(const BasicBlock *BB, const DataLayout *TD = 0); - - /// \brief Add information about a function to the current state. - void analyzeFunction(Function *F, const DataLayout *TD = 0); - }; + /// These are likely targets for future inlining, likely exposed by + /// interleaved devirtualization. + unsigned NumInlineCandidates; + + /// \brief How many instructions produce vector values. + /// + /// The inliner is more aggressive with inlining vector kernels. + unsigned NumVectorInsts; + + /// \brief How many 'ret' instructions the blocks contain. + unsigned NumRets; + + CodeMetrics() + : exposesReturnsTwice(false), isRecursive(false), notDuplicatable(false), + usesDynamicAlloca(false), NumInsts(0), NumBlocks(0), NumCalls(0), + NumInlineCandidates(0), NumVectorInsts(0), NumRets(0) {} + + /// \brief Add information about a block to the current state. + void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI); +}; + } #endif diff --git a/include/llvm/Analysis/DOTGraphTraitsPass.h b/include/llvm/Analysis/DOTGraphTraitsPass.h index bd8c4a1..0fc1c2d 100644 --- a/include/llvm/Analysis/DOTGraphTraitsPass.h +++ b/include/llvm/Analysis/DOTGraphTraitsPass.h @@ -11,27 +11,25 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_DOT_GRAPHTRAITS_PASS_H -#define LLVM_ANALYSIS_DOT_GRAPHTRAITS_PASS_H +#ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H +#define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H #include "llvm/Analysis/CFGPrinter.h" #include "llvm/Pass.h" namespace llvm { -template <class Analysis, bool Simple> -struct DOTGraphTraitsViewer : public FunctionPass { - std::string Name; - DOTGraphTraitsViewer(std::string GraphName, char &ID) : FunctionPass(ID) { - Name = GraphName; - } +template <class Analysis, bool Simple> +class DOTGraphTraitsViewer : public FunctionPass { +public: + DOTGraphTraitsViewer(StringRef GraphName, char &ID) + : FunctionPass(ID), Name(GraphName) {} virtual bool runOnFunction(Function &F) { - Analysis *Graph; - std::string Title, GraphName; - Graph = &getAnalysis<Analysis>(); - GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph); - Title = GraphName + " for '" + F.getName().str() + "' function"; + Analysis *Graph = &getAnalysis<Analysis>(); + std::string GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph); + std::string Title = GraphName + " for '" + F.getName().str() + "' function"; + ViewGraph(Graph, Name, Simple, Title); return false; @@ -41,36 +39,92 @@ struct DOTGraphTraitsViewer : public FunctionPass { AU.setPreservesAll(); AU.addRequired<Analysis>(); } + +private: + std::string Name; }; template <class Analysis, bool Simple> -struct DOTGraphTraitsPrinter : public FunctionPass { +class DOTGraphTraitsPrinter : public FunctionPass { +public: + DOTGraphTraitsPrinter(StringRef GraphName, char &ID) + : FunctionPass(ID), Name(GraphName) {} + + virtual bool runOnFunction(Function &F) { + Analysis *Graph = &getAnalysis<Analysis>(); + std::string Filename = Name + "." + F.getName().str() + ".dot"; + std::string ErrorInfo; + + errs() << "Writing '" << Filename << "'..."; + + raw_fd_ostream File(Filename.c_str(), ErrorInfo); + std::string GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph); + std::string Title = GraphName + " for '" + F.getName().str() + "' function"; + + if (ErrorInfo.empty()) + WriteGraph(File, Graph, Simple, Title); + else + errs() << " error opening file for writing!"; + errs() << "\n"; + + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired<Analysis>(); + } +private: std::string Name; +}; + +template <class Analysis, bool Simple> +class DOTGraphTraitsModuleViewer : public ModulePass { +public: + DOTGraphTraitsModuleViewer(StringRef GraphName, char &ID) + : ModulePass(ID), Name(GraphName) {} + + virtual bool runOnModule(Module &M) { + Analysis *Graph = &getAnalysis<Analysis>(); + std::string Title = DOTGraphTraits<Analysis*>::getGraphName(Graph); - DOTGraphTraitsPrinter(std::string GraphName, char &ID) - : FunctionPass(ID) { - Name = GraphName; + ViewGraph(Graph, Name, Simple, Title); + + return false; } - virtual bool runOnFunction(Function &F) { - Analysis *Graph; - std::string Filename = Name + "." + F.getName().str() + ".dot"; - errs() << "Writing '" << Filename << "'..."; + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired<Analysis>(); + } +private: + std::string Name; +}; + +template <class Analysis, bool Simple> +class DOTGraphTraitsModulePrinter : public ModulePass { +public: + DOTGraphTraitsModulePrinter(StringRef GraphName, char &ID) + : ModulePass(ID), Name(GraphName) {} + + virtual bool runOnModule(Module &M) { + Analysis *Graph = &getAnalysis<Analysis>(); + std::string Filename = Name + ".dot"; std::string ErrorInfo; - raw_fd_ostream File(Filename.c_str(), ErrorInfo); - Graph = &getAnalysis<Analysis>(); - std::string Title, GraphName; - GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph); - Title = GraphName + " for '" + F.getName().str() + "' function"; + errs() << "Writing '" << Filename << "'..."; + + raw_fd_ostream File(Filename.c_str(), ErrorInfo); + std::string Title = DOTGraphTraits<Analysis*>::getGraphName(Graph); if (ErrorInfo.empty()) WriteGraph(File, Graph, Simple, Title); else errs() << " error opening file for writing!"; errs() << "\n"; + return false; } @@ -78,6 +132,11 @@ struct DOTGraphTraitsPrinter : public FunctionPass { AU.setPreservesAll(); AU.addRequired<Analysis>(); } + +private: + std::string Name; }; -} + +} // end namespace llvm + #endif diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index f49efd9..d0ead39 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -244,8 +244,8 @@ namespace llvm { /// DependenceAnalysis - This class is the main dependence-analysis driver. /// class DependenceAnalysis : public FunctionPass { - void operator=(const DependenceAnalysis &); // do not implement - DependenceAnalysis(const DependenceAnalysis &); // do not implement + void operator=(const DependenceAnalysis &) LLVM_DELETED_FUNCTION; + DependenceAnalysis(const DependenceAnalysis &) LLVM_DELETED_FUNCTION; 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/InlineCost.h b/include/llvm/Analysis/InlineCost.h index 42e329e..bc7924e 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -14,125 +14,130 @@ #ifndef LLVM_ANALYSIS_INLINECOST_H #define LLVM_ANALYSIS_INLINECOST_H -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/ValueMap.h" #include "llvm/Analysis/CodeMetrics.h" -#include "llvm/IR/Function.h" +#include "llvm/Analysis/CallGraphSCCPass.h" #include <cassert> #include <climits> -#include <vector> namespace llvm { +class CallSite; +class DataLayout; +class Function; +class TargetTransformInfo; + +namespace InlineConstants { + // Various magic constants used to adjust heuristics. + const int InstrCost = 5; + const int IndirectCallThreshold = 100; + const int CallPenalty = 25; + const int LastCallToStaticBonus = -15000; + const int ColdccPenalty = 2000; + const int NoreturnPenalty = 10000; + /// Do not inline functions which allocate this many bytes on the stack + /// when the caller is recursive. + const unsigned TotalAllocaSizeRecursiveCaller = 1024; +} + +/// \brief Represents the cost of inlining a function. +/// +/// This supports special values for functions which should "always" or +/// "never" be inlined. Otherwise, the cost represents a unitless amount; +/// smaller values increase the likelihood of the function being inlined. +/// +/// Objects of this type also provide the adjusted threshold for inlining +/// based on the information available for a particular callsite. They can be +/// directly tested to determine if inlining should occur given the cost and +/// threshold for this cost metric. +class InlineCost { + enum SentinelValues { + AlwaysInlineCost = INT_MIN, + NeverInlineCost = INT_MAX + }; + + /// \brief The estimated cost of inlining this callsite. + const int Cost; + + /// \brief The adjusted threshold against which this cost was computed. + const int Threshold; + + // Trivial constructor, interesting logic in the factory functions below. + InlineCost(int Cost, int Threshold) : Cost(Cost), Threshold(Threshold) {} + +public: + static InlineCost get(int Cost, int Threshold) { + assert(Cost > AlwaysInlineCost && "Cost crosses sentinel value"); + assert(Cost < NeverInlineCost && "Cost crosses sentinel value"); + return InlineCost(Cost, Threshold); + } + static InlineCost getAlways() { + return InlineCost(AlwaysInlineCost, 0); + } + static InlineCost getNever() { + return InlineCost(NeverInlineCost, 0); + } - class CallSite; - class DataLayout; - - namespace InlineConstants { - // Various magic constants used to adjust heuristics. - const int InstrCost = 5; - const int IndirectCallThreshold = 100; - const int CallPenalty = 25; - const int LastCallToStaticBonus = -15000; - const int ColdccPenalty = 2000; - const int NoreturnPenalty = 10000; - /// Do not inline functions which allocate this many bytes on the stack - /// when the caller is recursive. - const unsigned TotalAllocaSizeRecursiveCaller = 1024; + /// \brief Test whether the inline cost is low enough for inlining. + operator bool() const { + return Cost < Threshold; } - /// \brief Represents the cost of inlining a function. + bool isAlways() const { return Cost == AlwaysInlineCost; } + bool isNever() const { return Cost == NeverInlineCost; } + bool isVariable() const { return !isAlways() && !isNever(); } + + /// \brief Get the inline cost estimate. + /// It is an error to call this on an "always" or "never" InlineCost. + int getCost() const { + assert(isVariable() && "Invalid access of InlineCost"); + return Cost; + } + + /// \brief Get the cost delta from the threshold for inlining. + /// Only valid if the cost is of the variable kind. Returns a negative + /// value if the cost is too high to inline. + int getCostDelta() const { return Threshold - getCost(); } +}; + +/// \brief Cost analyzer used by inliner. +class InlineCostAnalysis : public CallGraphSCCPass { + const DataLayout *TD; + const TargetTransformInfo *TTI; + +public: + static char ID; + + InlineCostAnalysis(); + ~InlineCostAnalysis(); + + // Pass interface implementation. + void getAnalysisUsage(AnalysisUsage &AU) const; + bool runOnSCC(CallGraphSCC &SCC); + + /// \brief Get an InlineCost object representing the cost of inlining this + /// callsite. /// - /// This supports special values for functions which should "always" or - /// "never" be inlined. Otherwise, the cost represents a unitless amount; - /// smaller values increase the likelihood of the function being inlined. + /// Note that threshold is passed into this function. Only costs below the + /// threshold are computed with any accuracy. The threshold can be used to + /// bound the computation necessary to determine whether the cost is + /// sufficiently low to warrant inlining. /// - /// Objects of this type also provide the adjusted threshold for inlining - /// based on the information available for a particular callsite. They can be - /// directly tested to determine if inlining should occur given the cost and - /// threshold for this cost metric. - class InlineCost { - enum SentinelValues { - AlwaysInlineCost = INT_MIN, - NeverInlineCost = INT_MAX - }; - - /// \brief The estimated cost of inlining this callsite. - const int Cost; - - /// \brief The adjusted threshold against which this cost was computed. - const int Threshold; - - // Trivial constructor, interesting logic in the factory functions below. - InlineCost(int Cost, int Threshold) - : Cost(Cost), Threshold(Threshold) {} - - public: - static InlineCost get(int Cost, int Threshold) { - assert(Cost > AlwaysInlineCost && "Cost crosses sentinel value"); - assert(Cost < NeverInlineCost && "Cost crosses sentinel value"); - return InlineCost(Cost, Threshold); - } - static InlineCost getAlways() { - return InlineCost(AlwaysInlineCost, 0); - } - static InlineCost getNever() { - return InlineCost(NeverInlineCost, 0); - } - - /// \brief Test whether the inline cost is low enough for inlining. - operator bool() const { - return Cost < Threshold; - } - - bool isAlways() const { return Cost == AlwaysInlineCost; } - bool isNever() const { return Cost == NeverInlineCost; } - bool isVariable() const { return !isAlways() && !isNever(); } - - /// \brief Get the inline cost estimate. - /// It is an error to call this on an "always" or "never" InlineCost. - int getCost() const { - assert(isVariable() && "Invalid access of InlineCost"); - return Cost; - } - - /// \brief Get the cost delta from the threshold for inlining. - /// Only valid if the cost is of the variable kind. Returns a negative - /// value if the cost is too high to inline. - int getCostDelta() const { return Threshold - getCost(); } - }; + /// Also note that calling this function *dynamically* computes the cost of + /// inlining the callsite. It is an expensive, heavyweight call. + InlineCost getInlineCost(CallSite CS, int Threshold); + + /// \brief Get an InlineCost with the callee explicitly specified. + /// This allows you to calculate the cost of inlining a function via a + /// pointer. This behaves exactly as the version with no explicit callee + /// parameter in all other respects. + // + // Note: This is used by out-of-tree passes, please do not remove without + // adding a replacement API. + InlineCost getInlineCost(CallSite CS, Function *Callee, int Threshold); + + /// \brief Minimal filter to detect invalid constructs for inlining. + bool isInlineViable(Function &Callee); +}; - /// InlineCostAnalyzer - Cost analyzer used by inliner. - class InlineCostAnalyzer { - // DataLayout if available, or null. - const DataLayout *TD; - - public: - InlineCostAnalyzer(): TD(0) {} - - void setDataLayout(const DataLayout *TData) { TD = TData; } - - /// \brief Get an InlineCost object representing the cost of inlining this - /// callsite. - /// - /// Note that threshold is passed into this function. Only costs below the - /// threshold are computed with any accuracy. The threshold can be used to - /// bound the computation necessary to determine whether the cost is - /// sufficiently low to warrant inlining. - InlineCost getInlineCost(CallSite CS, int Threshold); - - /// \brief Get an InlineCost with the callee explicitly specified. - /// This allows you to calculate the cost of inlining a function via a - /// pointer. This behaves exactly as the version with no explicit callee - /// parameter in all other respects. - // - // Note: This is used by out-of-tree passes, please do not remove without - // adding a replacement API. - InlineCost getInlineCost(CallSite CS, Function *Callee, int Threshold); - - /// \brief Minimal filter to detect invalid constructs for inlining. - bool isInlineViable(Function &Callee); - }; } #endif diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index b653e79..d760a4c 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -14,6 +14,19 @@ // ("and i32 %x, %x" -> "%x"). If the simplification is also an instruction // then it dominates the original instruction. // +// These routines implicitly resolve undef uses. The easiest way to be safe when +// using these routines to obtain simplified values for existing instructions is +// to always replace all uses of the instructions with the resulting simplified +// values. This will prevent other code from seeing the same undef uses and +// resolving them to different values. +// +// These routines are designed to tolerate moderately incomplete IR, such as +// instructions that are not connected to basic blocks yet. However, they do +// require that all the IR that they encounter be valid. In particular, they +// require that all non-constant values be defined in the same function, and the +// same call context of that function (and not split between caller and callee +// contexts of a directly recursive call, for example). +// //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H diff --git a/include/llvm/Analysis/Interval.h b/include/llvm/Analysis/Interval.h index ca8ad73..5ce1260 100644 --- a/include/llvm/Analysis/Interval.h +++ b/include/llvm/Analysis/Interval.h @@ -17,8 +17,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_INTERVAL_H -#define LLVM_INTERVAL_H +#ifndef LLVM_ANALYSIS_INTERVAL_H +#define LLVM_ANALYSIS_INTERVAL_H #include "llvm/ADT/GraphTraits.h" #include <vector> diff --git a/include/llvm/Analysis/IntervalIterator.h b/include/llvm/Analysis/IntervalIterator.h index bd9ab20..333f289 100644 --- a/include/llvm/Analysis/IntervalIterator.h +++ b/include/llvm/Analysis/IntervalIterator.h @@ -30,8 +30,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_INTERVAL_ITERATOR_H -#define LLVM_INTERVAL_ITERATOR_H +#ifndef LLVM_ANALYSIS_INTERVALITERATOR_H +#define LLVM_ANALYSIS_INTERVALITERATOR_H #include "llvm/Analysis/IntervalPartition.h" #include "llvm/IR/Function.h" diff --git a/include/llvm/Analysis/IntervalPartition.h b/include/llvm/Analysis/IntervalPartition.h index bce84be..8cade58 100644 --- a/include/llvm/Analysis/IntervalPartition.h +++ b/include/llvm/Analysis/IntervalPartition.h @@ -20,8 +20,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_INTERVAL_PARTITION_H -#define LLVM_INTERVAL_PARTITION_H +#ifndef LLVM_ANALYSIS_INTERVALPARTITION_H +#define LLVM_ANALYSIS_INTERVALPARTITION_H #include "llvm/Analysis/Interval.h" #include "llvm/Pass.h" diff --git a/include/llvm/Analysis/LibCallAliasAnalysis.h b/include/llvm/Analysis/LibCallAliasAnalysis.h index 243234b..c01b210 100644 --- a/include/llvm/Analysis/LibCallAliasAnalysis.h +++ b/include/llvm/Analysis/LibCallAliasAnalysis.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_LIBCALL_AA_H -#define LLVM_ANALYSIS_LIBCALL_AA_H +#ifndef LLVM_ANALYSIS_LIBCALLALIASANALYSIS_H +#define LLVM_ANALYSIS_LIBCALLALIASANALYSIS_H #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Pass.h" diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index 830754d..a20e065 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -27,21 +27,17 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_LOOP_INFO_H -#define LLVM_ANALYSIS_LOOP_INFO_H +#ifndef LLVM_ANALYSIS_LOOPINFO_H +#define LLVM_ANALYSIS_LOOPINFO_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Pass.h" -#include "llvm/Support/CFG.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> -#include <map> namespace llvm { @@ -381,6 +377,20 @@ public: /// isSafeToClone - Return true if the loop body is safe to clone in practice. bool isSafeToClone() const; + /// Returns true if the loop is annotated parallel. + /// + /// A parallel loop can be assumed to not contain any dependencies between + /// iterations by the compiler. That is, any loop-carried dependency checking + /// can be skipped completely when parallelizing the loop on the target + /// machine. Thus, if the parallel loop information originates from the + /// programmer, e.g. via the OpenMP parallel for pragma, it is the + /// programmer's responsibility to ensure there are no loop-carried + /// dependencies. The final execution order of the instructions across + /// iterations is not guaranteed, thus, the end result might or might not + /// implement actual concurrent execution of instructions across multiple + /// iterations. + bool isAnnotatedParallel() const; + /// hasDedicatedExits - Return true if no exit block for the loop /// has a predecessor that is outside the loop. bool hasDedicatedExits() const; diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h index 4b8e4c9..5485f3c 100644 --- a/include/llvm/Analysis/LoopInfoImpl.h +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -12,10 +12,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_LOOP_INFO_IMPL_H -#define LLVM_ANALYSIS_LOOP_INFO_IMPL_H +#ifndef LLVM_ANALYSIS_LOOPINFOIMPL_H +#define LLVM_ANALYSIS_LOOPINFOIMPL_H #include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Analysis/LoopInfo.h" namespace llvm { diff --git a/include/llvm/Analysis/LoopIterator.h b/include/llvm/Analysis/LoopIterator.h index 68f25f7..e3dd963 100644 --- a/include/llvm/Analysis/LoopIterator.h +++ b/include/llvm/Analysis/LoopIterator.h @@ -21,10 +21,9 @@ // reachable from the loop header. //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_LOOP_ITERATOR_H -#define LLVM_ANALYSIS_LOOP_ITERATOR_H +#ifndef LLVM_ANALYSIS_LOOPITERATOR_H +#define LLVM_ANALYSIS_LOOPITERATOR_H -#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/Analysis/LoopInfo.h" diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h index f78472a..5767c19 100644 --- a/include/llvm/Analysis/LoopPass.h +++ b/include/llvm/Analysis/LoopPass.h @@ -12,11 +12,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LOOP_PASS_H -#define LLVM_LOOP_PASS_H +#ifndef LLVM_ANALYSIS_LOOPPASS_H +#define LLVM_ANALYSIS_LOOPPASS_H #include "llvm/Analysis/LoopInfo.h" -#include "llvm/IR/Function.h" #include "llvm/Pass.h" #include "llvm/PassManagers.h" #include <deque> diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index f2c564f..f07658f 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -158,7 +158,7 @@ class ObjectSizeOffsetVisitor bool RoundToAlign; unsigned IntTyBits; APInt Zero; - SmallPtrSet<Value*, 8> SeenInsts; + SmallPtrSet<Instruction *, 8> SeenInsts; APInt align(APInt Size, uint64_t Align); diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index b954840..b87f886 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_MEMORY_DEPENDENCE_H -#define LLVM_ANALYSIS_MEMORY_DEPENDENCE_H +#ifndef LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H +#define LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/OwningPtr.h" @@ -34,14 +34,14 @@ namespace llvm { class PredIteratorCache; class DominatorTree; class PHITransAddr; - + /// MemDepResult - A memory dependence query can return one of three different /// answers, described below. class MemDepResult { enum DepType { /// Invalid - Clients of MemDep never see this. Invalid = 0, - + /// Clobber - This is a dependence on the specified instruction which /// clobbers the desired value. The pointer member of the MemDepResult /// pair holds the instruction that clobbers the memory. For example, @@ -72,7 +72,7 @@ namespace llvm { /// and no intervening clobbers. No validation is done that the /// operands to the calls are the same. Def, - + /// Other - This marker indicates that the query has no known dependency /// in the specified block. More detailed state info is encoded in the /// upper part of the pair (i.e. the Instruction*) @@ -99,7 +99,7 @@ namespace llvm { explicit MemDepResult(PairTy V) : Value(V) {} public: MemDepResult() : Value(0, Invalid) {} - + /// get methods: These are static ctor methods for creating various /// MemDepResult kinds. static MemDepResult getDef(Instruction *Inst) { @@ -130,7 +130,7 @@ namespace llvm { /// isDef - Return true if this MemDepResult represents a query that is /// an instruction definition dependency. bool isDef() const { return Value.getInt() == Def; } - + /// isNonLocal - Return true if this MemDepResult represents a query that /// is transparent to the start of the block, but where a non-local hasn't /// been done. @@ -145,7 +145,7 @@ namespace llvm { return Value.getInt() == Other && Value.getPointer() == reinterpret_cast<Instruction*>(NonFuncLocal); } - + /// isUnknown - Return true if this MemDepResult represents a query which /// cannot and/or will not be computed. bool isUnknown() const { @@ -159,7 +159,7 @@ namespace llvm { if (Value.getInt() == Other) return NULL; return Value.getPointer(); } - + bool operator==(const MemDepResult &M) const { return Value == M.Value; } bool operator!=(const MemDepResult &M) const { return Value != M.Value; } bool operator<(const MemDepResult &M) const { return Value < M.Value; } @@ -175,11 +175,11 @@ namespace llvm { /// In a default-constructed MemDepResult object, the type will be Dirty /// and the instruction pointer will be null. /// - + /// isDirty - Return true if this is a MemDepResult in its dirty/invalid. /// state. bool isDirty() const { return Value.getInt() == Invalid; } - + static MemDepResult getDirty(Instruction *Inst) { return MemDepResult(PairTy(Inst, Invalid)); } @@ -199,16 +199,16 @@ namespace llvm { // BB is the sort key, it can't be changed. BasicBlock *getBB() const { return BB; } - + void setResult(const MemDepResult &R) { Result = R; } const MemDepResult &getResult() const { return Result; } - + bool operator<(const NonLocalDepEntry &RHS) const { return BB < RHS.BB; } }; - + /// NonLocalDepResult - This is a result from a NonLocal dependence query. /// For each BasicBlock (the BB entry) it keeps a MemDepResult and the /// (potentially phi translated) address that was live in the block. @@ -218,17 +218,17 @@ namespace llvm { public: NonLocalDepResult(BasicBlock *bb, MemDepResult result, Value *address) : Entry(bb, result), Address(address) {} - + // BB is the sort key, it can't be changed. BasicBlock *getBB() const { return Entry.getBB(); } - + void setResult(const MemDepResult &R, Value *Addr) { Entry.setResult(R); Address = Addr; } - + const MemDepResult &getResult() const { return Entry.getResult(); } - + /// getAddress - Return the address of this pointer in this block. This can /// be different than the address queried for the non-local result because /// of phi translation. This returns null if the address was not available @@ -238,7 +238,7 @@ namespace llvm { /// The address is always null for a non-local 'call' dependence. Value *getAddress() const { return Address; } }; - + /// MemoryDependenceAnalysis - This is an analysis that determines, for a /// given memory operation, what preceding memory operations it depends on. /// It builds on alias analysis information, and tries to provide a lazy, @@ -297,30 +297,30 @@ namespace llvm { CachedNonLocalPointerInfo NonLocalPointerDeps; // A map from instructions to their non-local pointer dependencies. - typedef DenseMap<Instruction*, + typedef DenseMap<Instruction*, SmallPtrSet<ValueIsLoadPair, 4> > ReverseNonLocalPtrDepTy; ReverseNonLocalPtrDepTy ReverseNonLocalPtrDeps; - + /// PerInstNLInfo - This is the instruction we keep for each cached access /// that we have for an instruction. The pointer is an owning pointer and /// the bool indicates whether we have any dirty bits in the set. typedef std::pair<NonLocalDepInfo, bool> PerInstNLInfo; - + // A map from instructions to their non-local dependencies. typedef DenseMap<Instruction*, PerInstNLInfo> NonLocalDepMapType; - + NonLocalDepMapType NonLocalDeps; - + // A reverse mapping from dependencies to the dependees. This is // used when removing instructions to keep the cache coherent. typedef DenseMap<Instruction*, SmallPtrSet<Instruction*, 4> > ReverseDepMapType; ReverseDepMapType ReverseLocalDeps; - + // A reverse mapping from dependencies to the non-local dependees. ReverseDepMapType ReverseNonLocalDeps; - + /// Current AA implementation, just a cache. AliasAnalysis *AA; DataLayout *TD; @@ -333,15 +333,15 @@ namespace llvm { /// Pass Implementation stuff. This doesn't do any analysis eagerly. bool runOnFunction(Function &); - + /// Clean up memory in between runs void releaseMemory(); - + /// getAnalysisUsage - Does not modify anything. It uses Value Numbering /// and Alias Analysis. /// virtual void getAnalysisUsage(AnalysisUsage &AU) const; - + /// getDependency - Return the instruction on which a memory operation /// depends. See the class comment for more details. It is illegal to call /// this on non-memory instructions. @@ -360,8 +360,8 @@ namespace llvm { /// removed. Clients must copy this data if they want it around longer than /// that. const NonLocalDepInfo &getNonLocalCallDependency(CallSite QueryCS); - - + + /// getNonLocalPointerDependency - Perform a full dependency query for an /// access to the specified (non-volatile) memory location, returning the /// set of instructions that either define or clobber the value. @@ -374,7 +374,7 @@ namespace llvm { /// removeInstruction - Remove an instruction from the dependence analysis, /// updating the dependence of instructions that previously depended on it. void removeInstruction(Instruction *InstToRemove); - + /// invalidateCachedPointerInfo - This method is used to invalidate cached /// information about the specified pointer, because it may be too /// conservative in memdep. This is an optional call that can be used when @@ -387,7 +387,7 @@ namespace llvm { /// This needs to be done when the CFG changes, e.g., due to splitting /// critical edges. void invalidateCachedPredecessors(); - + /// getPointerDependencyFrom - Return the instruction on which a memory /// location depends. If isLoad is true, this routine ignores may-aliases /// with read-only operations. If isLoad is false, this routine ignores @@ -396,11 +396,11 @@ namespace llvm { /// Note that this is an uncached query, and thus may be inefficient. /// MemDepResult getPointerDependencyFrom(const AliasAnalysis::Location &Loc, - bool isLoad, + bool isLoad, BasicBlock::iterator ScanIt, BasicBlock *BB); - - + + /// getLoadLoadClobberFullWidthSize - This is a little bit of analysis that /// looks at a memory location for a load (specified by MemLocBase, Offs, /// and Size) and compares it against a load. If the specified load could @@ -413,7 +413,7 @@ namespace llvm { unsigned MemLocSize, const LoadInst *LI, const DataLayout &TD); - + private: MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, BasicBlock::iterator ScanIt, @@ -430,11 +430,11 @@ namespace llvm { unsigned NumSortedEntries); void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P); - + /// verifyRemoved - Verify that the specified instruction does not occur /// in our internal data structures. void verifyRemoved(Instruction *Inst) const; - + }; } // End llvm namespace diff --git a/include/llvm/Analysis/PathNumbering.h b/include/llvm/Analysis/PathNumbering.h index 86b1520..400a37d 100644 --- a/include/llvm/Analysis/PathNumbering.h +++ b/include/llvm/Analysis/PathNumbering.h @@ -23,8 +23,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PATH_NUMBERING_H -#define LLVM_PATH_NUMBERING_H +#ifndef LLVM_ANALYSIS_PATHNUMBERING_H +#define LLVM_ANALYSIS_PATHNUMBERING_H #include "llvm/Analysis/ProfileInfoTypes.h" #include "llvm/IR/BasicBlock.h" diff --git a/include/llvm/Analysis/PathProfileInfo.h b/include/llvm/Analysis/PathProfileInfo.h index 8684f41..4fce16e 100644 --- a/include/llvm/Analysis/PathProfileInfo.h +++ b/include/llvm/Analysis/PathProfileInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PATHPROFILEINFO_H -#define LLVM_PATHPROFILEINFO_H +#ifndef LLVM_ANALYSIS_PATHPROFILEINFO_H +#define LLVM_ANALYSIS_PATHPROFILEINFO_H #include "llvm/Analysis/PathNumbering.h" #include "llvm/IR/BasicBlock.h" diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h index 0eddb91..d082297 100644 --- a/include/llvm/Analysis/PostDominators.h +++ b/include/llvm/Analysis/PostDominators.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_POST_DOMINATORS_H -#define LLVM_ANALYSIS_POST_DOMINATORS_H +#ifndef LLVM_ANALYSIS_POSTDOMINATORS_H +#define LLVM_ANALYSIS_POSTDOMINATORS_H #include "llvm/Analysis/Dominators.h" diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 48d7ee6..69cc293 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -24,8 +24,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_REGION_INFO_H -#define LLVM_ANALYSIS_REGION_INFO_H +#ifndef LLVM_ANALYSIS_REGIONINFO_H +#define LLVM_ANALYSIS_REGIONINFO_H #include "llvm/ADT/PointerIntPair.h" #include "llvm/Analysis/DominanceFrontier.h" diff --git a/include/llvm/Analysis/RegionIterator.h b/include/llvm/Analysis/RegionIterator.h index bcff227..8fd4263 100644 --- a/include/llvm/Analysis/RegionIterator.h +++ b/include/llvm/Analysis/RegionIterator.h @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// // This file defines the iterators to iterate over the elements of a Region. //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_REGION_ITERATOR_H -#define LLVM_ANALYSIS_REGION_ITERATOR_H +#ifndef LLVM_ANALYSIS_REGIONITERATOR_H +#define LLVM_ANALYSIS_REGIONITERATOR_H #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/PointerIntPair.h" diff --git a/include/llvm/Analysis/RegionPass.h b/include/llvm/Analysis/RegionPass.h index 54f96d6..0690ac5 100644 --- a/include/llvm/Analysis/RegionPass.h +++ b/include/llvm/Analysis/RegionPass.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_REGION_PASS_H -#define LLVM_REGION_PASS_H +#ifndef LLVM_ANALYSIS_REGIONPASS_H +#define LLVM_ANALYSIS_REGIONPASS_H #include "llvm/Analysis/RegionInfo.h" #include "llvm/IR/Function.h" diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index ea45aff..00779fc 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_EXPANDER_H -#define LLVM_ANALYSIS_SCALAREVOLUTION_EXPANDER_H +#ifndef LLVM_ANALYSIS_SCALAREVOLUTIONEXPANDER_H +#define LLVM_ANALYSIS_SCALAREVOLUTIONEXPANDER_H #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ScalarEvolutionNormalization.h" @@ -40,8 +40,10 @@ namespace llvm { // New instructions receive a name to identifies them with the current pass. const char* IVName; - std::map<std::pair<const SCEV *, Instruction *>, AssertingVH<Value> > + // InsertedExpressions caches Values for reuse, so must track RAUW. + std::map<std::pair<const SCEV *, Instruction *>, TrackingVH<Value> > InsertedExpressions; + // InsertedValues only flags inserted instructions so needs no RAUW. std::set<AssertingVH<Value> > InsertedValues; std::set<AssertingVH<Value> > InsertedPostIncValues; diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index b74cb33..eac9113 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_EXPRESSIONS_H -#define LLVM_ANALYSIS_SCALAREVOLUTION_EXPRESSIONS_H +#ifndef LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H +#define LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/ScalarEvolution.h" @@ -548,6 +548,151 @@ namespace llvm { SCEVTraversal<SV> T(Visitor); T.visitAll(Root); } + + /// The SCEVRewriter takes a scalar evolution expression and copies all its + /// components. The result after a rewrite is an identical SCEV. + struct SCEVRewriter + : public SCEVVisitor<SCEVRewriter, const SCEV*> { + public: + SCEVRewriter(ScalarEvolution &S) : SE(S) {} + + virtual ~SCEVRewriter() {} + + virtual const SCEV *visitConstant(const SCEVConstant *Constant) { + return Constant; + } + + virtual const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) { + const SCEV *Operand = visit(Expr->getOperand()); + return SE.getTruncateExpr(Operand, Expr->getType()); + } + + virtual const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { + const SCEV *Operand = visit(Expr->getOperand()); + return SE.getZeroExtendExpr(Operand, Expr->getType()); + } + + virtual const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { + const SCEV *Operand = visit(Expr->getOperand()); + return SE.getSignExtendExpr(Operand, Expr->getType()); + } + + virtual const SCEV *visitAddExpr(const SCEVAddExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getAddExpr(Operands); + } + + virtual const SCEV *visitMulExpr(const SCEVMulExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getMulExpr(Operands); + } + + virtual const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) { + return SE.getUDivExpr(visit(Expr->getLHS()), visit(Expr->getRHS())); + } + + virtual const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getAddRecExpr(Operands, Expr->getLoop(), + Expr->getNoWrapFlags()); + } + + virtual const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getSMaxExpr(Operands); + } + + virtual const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getUMaxExpr(Operands); + } + + virtual const SCEV *visitUnknown(const SCEVUnknown *Expr) { + return Expr; + } + + virtual const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { + return Expr; + } + + protected: + ScalarEvolution &SE; + }; + + typedef DenseMap<const Value*, Value*> ValueToValueMap; + + /// The SCEVParameterRewriter takes a scalar evolution expression and updates + /// the SCEVUnknown components following the Map (Value -> Value). + struct SCEVParameterRewriter: public SCEVRewriter { + public: + static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE, + ValueToValueMap &Map) { + SCEVParameterRewriter Rewriter(SE, Map); + return Rewriter.visit(Scev); + } + SCEVParameterRewriter(ScalarEvolution &S, ValueToValueMap &M) + : SCEVRewriter(S), Map(M) {} + + virtual const SCEV *visitUnknown(const SCEVUnknown *Expr) { + Value *V = Expr->getValue(); + if (Map.count(V)) + return SE.getUnknown(Map[V]); + return Expr; + } + + private: + ValueToValueMap ⤅ + }; + + typedef DenseMap<const Loop*, const SCEV*> LoopToScevMapT; + + /// The SCEVApplyRewriter takes a scalar evolution expression and applies + /// the Map (Loop -> SCEV) to all AddRecExprs. + struct SCEVApplyRewriter: public SCEVRewriter { + public: + static const SCEV *rewrite(const SCEV *Scev, LoopToScevMapT &Map, + ScalarEvolution &SE) { + SCEVApplyRewriter Rewriter(SE, Map); + return Rewriter.visit(Scev); + } + SCEVApplyRewriter(ScalarEvolution &S, LoopToScevMapT &M) + : SCEVRewriter(S), Map(M) {} + + virtual const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { + SmallVector<const SCEV *, 2> Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + + const Loop *L = Expr->getLoop(); + const SCEV *Res = SE.getAddRecExpr(Operands, L, Expr->getNoWrapFlags()); + + if (0 == Map.count(L)) + return Res; + + const SCEVAddRecExpr *Rec = (const SCEVAddRecExpr *) Res; + return Rec->evaluateAtIteration(Map[L], SE); + } + + private: + LoopToScevMapT ⤅ + }; + +/// Applies the Map (Loop -> SCEV) to the given Scev. +static inline const SCEV *apply(const SCEV *Scev, LoopToScevMapT &Map, + ScalarEvolution &SE) { + return SCEVApplyRewriter::rewrite(Scev, Map, SE); +} + } #endif diff --git a/include/llvm/Analysis/ScalarEvolutionNormalization.h b/include/llvm/Analysis/ScalarEvolutionNormalization.h index 342e5937..7c6423a 100644 --- a/include/llvm/Analysis/ScalarEvolutionNormalization.h +++ b/include/llvm/Analysis/ScalarEvolutionNormalization.h @@ -33,8 +33,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_NORMALIZATION_H -#define LLVM_ANALYSIS_SCALAREVOLUTION_NORMALIZATION_H +#ifndef LLVM_ANALYSIS_SCALAREVOLUTIONNORMALIZATION_H +#define LLVM_ANALYSIS_SCALAREVOLUTIONNORMALIZATION_H #include "llvm/ADT/SmallPtrSet.h" diff --git a/include/llvm/Analysis/SparsePropagation.h b/include/llvm/Analysis/SparsePropagation.h index 604e306..76c8ccf 100644 --- a/include/llvm/Analysis/SparsePropagation.h +++ b/include/llvm/Analysis/SparsePropagation.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_SPARSE_PROPAGATION_H -#define LLVM_ANALYSIS_SPARSE_PROPAGATION_H +#ifndef LLVM_ANALYSIS_SPARSEPROPAGATION_H +#define LLVM_ANALYSIS_SPARSEPROPAGATION_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" @@ -203,4 +203,4 @@ private: } // end namespace llvm -#endif // LLVM_ANALYSIS_SPARSE_PROPAGATION_H +#endif // LLVM_ANALYSIS_SPARSEPROPAGATION_H diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index ddf615f..e1331a1 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -19,9 +19,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_TARGET_TRANSFORM_INTERFACE -#define LLVM_ANALYSIS_TARGET_TRANSFORM_INTERFACE +#ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFO_H +#define LLVM_ANALYSIS_TARGETTRANSFORMINFO_H +#include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Type.h" @@ -67,6 +68,123 @@ public: /// This class is intended to be subclassed by real implementations. virtual ~TargetTransformInfo() = 0; + /// \name Generic Target Information + /// @{ + + /// \brief Underlying constants for 'cost' values in this interface. + /// + /// Many APIs in this interface return a cost. This enum defines the + /// fundamental values that should be used to interpret (and produce) those + /// costs. The costs are returned as an unsigned rather than a member of this + /// enumeration because it is expected that the cost of one IR instruction + /// may have a multiplicative factor to it or otherwise won't fit dircetly + /// into the enum. Moreover, it is common to sum or average costs which works + /// better as simple integral values. Thus this enum only provides constants. + /// + /// Note that these costs should usually reflect the intersection of code-size + /// cost and execution cost. A free instruction is typically one that folds + /// into another instruction. For example, reg-to-reg moves can often be + /// 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. + }; + + /// \brief Estimate the cost of a specific operation when lowered. + /// + /// Note that this is designed to work on an arbitrary synthetic opcode, and + /// thus work for hypothetical queries before an instruction has even been + /// formed. However, this does *not* work for GEPs, and must not be called + /// for a GEP instruction. Instead, use the dedicated getGEPCost interface as + /// analyzing a GEP's cost required more information. + /// + /// Typically only the result type is required, and the operand type can be + /// omitted. However, if the opcode is one of the cast instructions, the + /// operand type is required. + /// + /// 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 = 0) 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; + + /// \brief Estimate the cost of a function call when lowered. + /// + /// The contract for this is the same as \c getOperationCost except that it + /// supports an interface that provides extra information specific to call + /// instructions. + /// + /// 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; + + /// \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; + + /// \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; + + /// \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; + + /// \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; + + /// \brief Estimate the cost of a given IR user when lowered. + /// + /// This can estimate the cost of either a ConstantExpr or Instruction when + /// lowered. It has two primary advantages over the \c getOperationCost and + /// \c getGEPCost above, and one significant disadvantage: it can only be + /// used when the IR construct has already been formed. + /// + /// The advantages are that it can inspect the SSA use graph to reason more + /// accurately about the cost. For example, all-constant-GEPs can often be + /// folded into a load or other instruction, but if they are used in some + /// other context they may not be folded. This routine can distinguish such + /// cases. + /// + /// 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; + + /// \brief Test whether calls to a function lower to actual program function + /// calls. + /// + /// The idea is to test whether the program is likely to require a 'call' + /// instruction or equivalent in order to call the given function. + /// + /// FIXME: It's not clear that this is a good or useful query API. Client's + /// should probably move to simpler cost metrics using the above. + /// Alternatively, we could split the cost interface into distinct code-size + /// and execution-speed costs. This would allow modelling the core of this + /// query more accurately as the a call is a single small instruction, but + /// incurs significant execution cost. + virtual bool isLoweredToCall(const Function *F) const; + + /// @} + /// \name Scalar Target Information /// @{ @@ -148,6 +266,14 @@ public: /// set to false, it returns the number of scalar registers. virtual unsigned getNumberOfRegisters(bool Vector) const; + /// \return The width of the largest scalar or vector register type. + virtual unsigned getRegisterBitWidth(bool Vector) const; + + /// \return The maximum unroll factor that the vectorizer 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 getMaximumUnrollFactor() const; + /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. virtual unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty) const; @@ -188,6 +314,12 @@ public: /// split during legalization. Zero is returned when the answer is unknown. virtual 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 + /// distinguish between address computation for memory operations on vector + /// types and scalar types. Such targets should override this function. + virtual unsigned getAddressComputationCost(Type *Ty) const; + /// @} /// Analysis group identification. diff --git a/include/llvm/Analysis/Trace.h b/include/llvm/Analysis/Trace.h index 26947fe..bedd654 100644 --- a/include/llvm/Analysis/Trace.h +++ b/include/llvm/Analysis/Trace.h @@ -116,4 +116,4 @@ public: } // end namespace llvm -#endif // TRACE_H +#endif // LLVM_ANALYSIS_TRACE_H diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 875c47d..3775ec9 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -117,10 +117,10 @@ 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 *TD); static inline const Value * GetPointerBaseWithConstantOffset(const Value *Ptr, int64_t &Offset, - const DataLayout &TD) { + const DataLayout *TD) { return GetPointerBaseWithConstantOffset(const_cast<Value*>(Ptr), Offset,TD); } @@ -183,6 +183,11 @@ namespace llvm { bool isSafeToSpeculativelyExecute(const Value *V, const DataLayout *TD = 0); + /// 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); + } // end namespace llvm #endif diff --git a/include/llvm/Assembly/PrintModulePass.h b/include/llvm/Assembly/PrintModulePass.h index 239fbcc..02b9bd9 100644 --- a/include/llvm/Assembly/PrintModulePass.h +++ b/include/llvm/Assembly/PrintModulePass.h @@ -23,6 +23,7 @@ namespace llvm { class FunctionPass; class ModulePass; + class BasicBlockPass; class raw_ostream; /// createPrintModulePass - Create and return a pass that writes the @@ -37,6 +38,11 @@ namespace llvm { raw_ostream *OS, bool DeleteStream=false); + /// createPrintBasicBlockPass - Create and return a pass that writes the + /// BB to the specified raw_ostream. + BasicBlockPass *createPrintBasicBlockPass(raw_ostream *OS, + bool DeleteStream=false, + const std::string &Banner = ""); } // End llvm namespace #endif diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 5b60f72..2d2976c 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef BITSTREAM_READER_H -#define BITSTREAM_READER_H +#ifndef LLVM_BITCODE_BITSTREAMREADER_H +#define LLVM_BITCODE_BITSTREAMREADER_H #include "llvm/ADT/OwningPtr.h" #include "llvm/Bitcode/BitCodes.h" @@ -27,6 +27,11 @@ namespace llvm { class Deserializer; +/// BitstreamReader - 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 within the file. These are represented by the +/// BitstreamCursor class. class BitstreamReader { public: /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. @@ -119,20 +124,63 @@ public: BlockInfoRecords.back().BlockID = BlockID; return BlockInfoRecords.back(); } +}; + +/// BitstreamEntry - When advancing through a bitstream cursor, each advance can +/// discover a few different kinds of entries: +/// Error - Malformed bitcode was found. +/// EndBlock - We've reached the end of the current block, (or the end of the +/// file, which is treated like a series of EndBlock records. +/// SubBlock - This is the start of a new subblock of a specific ID. +/// Record - This is a record with a specific AbbrevID. +/// +struct BitstreamEntry { + enum { + Error, + EndBlock, + SubBlock, + Record + } Kind; + + unsigned ID; + + static BitstreamEntry getError() { + BitstreamEntry E; E.Kind = Error; return E; + } + static BitstreamEntry getEndBlock() { + BitstreamEntry E; E.Kind = EndBlock; return E; + } + static BitstreamEntry getSubBlock(unsigned ID) { + BitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E; + } + static BitstreamEntry getRecord(unsigned AbbrevID) { + BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E; + } }; +/// BitstreamCursor - This represents a position within a bitcode file. There +/// may be multiple independent cursors reading within one bitstream, each +/// maintaining their own local state. +/// +/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not +/// be passed by value. class BitstreamCursor { friend class Deserializer; BitstreamReader *BitStream; size_t NextChar; - /// CurWord - This is the current data we have pulled from the stream but have - /// not returned to the client. - uint32_t CurWord; + + /// CurWord/word_t - This is the current data we have pulled from the stream + /// but have not returned to the client. This is specifically and + /// intentionally defined to follow the word size of the host machine for + /// efficiency. We use word_t in places that are aware of this to make it + /// perfectly explicit what is going on. + typedef uint32_t word_t; + word_t CurWord; /// BitsInCurWord - This is the number of bits in CurWord that are valid. This - /// is always from [0...31] inclusive. + /// is always from [0...31/63] inclusive (depending on word size). unsigned BitsInCurWord; // CurCodeSize - This is the declared size of code values used for the current @@ -151,6 +199,7 @@ class BitstreamCursor { /// BlockScope - This tracks the codesize of parent blocks. SmallVector<Block, 8> BlockScope; + public: BitstreamCursor() : BitStream(0), NextChar(0) { } @@ -179,53 +228,10 @@ public: freeState(); } - void operator=(const BitstreamCursor &RHS) { - freeState(); - - BitStream = RHS.BitStream; - NextChar = RHS.NextChar; - CurWord = RHS.CurWord; - BitsInCurWord = RHS.BitsInCurWord; - CurCodeSize = RHS.CurCodeSize; - - // Copy abbreviations, and bump ref counts. - CurAbbrevs = RHS.CurAbbrevs; - for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size()); - i != e; ++i) - CurAbbrevs[i]->addRef(); - - // Copy block scope and bump ref counts. - BlockScope = RHS.BlockScope; - for (unsigned S = 0, e = static_cast<unsigned>(BlockScope.size()); - S != e; ++S) { - std::vector<BitCodeAbbrev*> &Abbrevs = BlockScope[S].PrevAbbrevs; - for (unsigned i = 0, e = static_cast<unsigned>(Abbrevs.size()); - i != e; ++i) - Abbrevs[i]->addRef(); - } - } - - void freeState() { - // Free all the Abbrevs. - for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size()); - i != e; ++i) - CurAbbrevs[i]->dropRef(); - CurAbbrevs.clear(); - - // Free all the Abbrevs in the block scope. - for (unsigned S = 0, e = static_cast<unsigned>(BlockScope.size()); - S != e; ++S) { - std::vector<BitCodeAbbrev*> &Abbrevs = BlockScope[S].PrevAbbrevs; - for (unsigned i = 0, e = static_cast<unsigned>(Abbrevs.size()); - i != e; ++i) - Abbrevs[i]->dropRef(); - } - BlockScope.clear(); - } - - /// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #. - unsigned GetAbbrevIDWidth() const { return CurCodeSize; } + void operator=(const BitstreamCursor &RHS); + void freeState(); + bool isEndPos(size_t pos) { return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos)); } @@ -236,26 +242,19 @@ public: static_cast<uint64_t>(pos - 1)); } - unsigned char getByte(size_t pos) { - uint8_t byte = -1; - BitStream->getBitcodeBytes().readByte(pos, &byte); - return byte; - } - uint32_t getWord(size_t pos) { - uint8_t buf[sizeof(uint32_t)]; - memset(buf, 0xFF, sizeof(buf)); - BitStream->getBitcodeBytes().readBytes(pos, - sizeof(buf), - buf, - NULL); + uint8_t buf[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; + BitStream->getBitcodeBytes().readBytes(pos, sizeof(buf), buf, NULL); return *reinterpret_cast<support::ulittle32_t *>(buf); } bool AtEndOfStream() { - return isEndPos(NextChar) && BitsInCurWord == 0; + return BitsInCurWord == 0 && isEndPos(NextChar); } + /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #. + unsigned getAbbrevIDWidth() const { return CurCodeSize; } + /// GetCurrentBitNo - Return the bit # of the bit we are reading. uint64_t GetCurrentBitNo() const { return NextChar*CHAR_BIT - BitsInCurWord; @@ -268,11 +267,64 @@ public: return BitStream; } + /// Flags that modify the behavior of advance(). + enum { + /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does + /// not automatically pop the block scope when the end of a block is + /// reached. + AF_DontPopBlockAtEnd = 1, + + /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are + /// returned just like normal records. + AF_DontAutoprocessAbbrevs = 2 + }; + + /// advance - 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) { + // Pop the end of the block unless Flags tells us not to. + if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) + return BitstreamEntry::getError(); + return BitstreamEntry::getEndBlock(); + } + + if (Code == bitc::ENTER_SUBBLOCK) + return BitstreamEntry::getSubBlock(ReadSubBlockID()); + + if (Code == bitc::DEFINE_ABBREV && + !(Flags & AF_DontAutoprocessAbbrevs)) { + // We read and accumulate abbrev's, the client can't do anything with + // them anyway. + ReadAbbrevRecord(); + continue; + } + + return BitstreamEntry::getRecord(Code); + } + } + + /// advanceSkippingSubblocks - This is a convenience function for clients that + /// don't expect any subblocks. This just skips over them automatically. + BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { + while (1) { + // If we found a normal entry, return it. + BitstreamEntry Entry = advance(Flags); + if (Entry.Kind != BitstreamEntry::SubBlock) + return Entry; + + // If we found a sub-block, just skip over it and check the next entry. + if (SkipBlock()) + return BitstreamEntry::getError(); + } + } /// JumpToBit - Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { - uintptr_t ByteNo = uintptr_t(BitNo/8) & ~3; - uintptr_t WordBitNo = uintptr_t(BitNo) & 31; + uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); + unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); assert(canSkipToPos(ByteNo) && "Invalid location"); // Move the cursor to the right word. @@ -281,16 +333,22 @@ public: CurWord = 0; // Skip over any bits that are already consumed. - if (WordBitNo) - Read(static_cast<unsigned>(WordBitNo)); + if (WordBitNo) { + if (sizeof(word_t) > 4) + Read64(WordBitNo); + else + Read(WordBitNo); + } } uint32_t Read(unsigned NumBits) { - assert(NumBits <= 32 && "Cannot return more than 32 bits!"); + assert(NumBits && NumBits <= 32 && + "Cannot return zero or more than 32 bits!"); + // If the field is fully contained by CurWord, return it quickly. if (BitsInCurWord >= NumBits) { - uint32_t R = CurWord & ((1U << NumBits)-1); + uint32_t R = uint32_t(CurWord) & (~0U >> (32-NumBits)); CurWord >>= NumBits; BitsInCurWord -= NumBits; return R; @@ -303,24 +361,37 @@ public: return 0; } - unsigned R = CurWord; + uint32_t R = uint32_t(CurWord); // Read the next word from the stream. - CurWord = getWord(NextChar); - NextChar += 4; + uint8_t Array[sizeof(word_t)] = {0}; + + BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array), + Array, NULL); + + // Handle big-endian byte-swapping if necessary. + support::detail::packed_endian_specific_integral + <word_t, support::little, support::unaligned> EndianValue; + memcpy(&EndianValue, Array, sizeof(Array)); + + CurWord = EndianValue; + + NextChar += sizeof(word_t); // Extract NumBits-BitsInCurWord from what we just read. unsigned BitsLeft = NumBits-BitsInCurWord; - // Be careful here, BitsLeft is in the range [1..32] inclusive. - R |= (CurWord & (~0U >> (32-BitsLeft))) << BitsInCurWord; + // Be careful here, BitsLeft is in the range [1..32]/[1..64] inclusive. + R |= uint32_t((CurWord & (word_t(~0ULL) >> (sizeof(word_t)*8-BitsLeft))) + << BitsInCurWord); - // BitsLeft bits have just been used up from CurWord. - if (BitsLeft != 32) + // BitsLeft bits have just been used up from CurWord. BitsLeft is in the + // range [1..32]/[1..64] so be careful how we shift. + if (BitsLeft != sizeof(word_t)*8) CurWord >>= BitsLeft; else CurWord = 0; - BitsInCurWord = 32-BitsLeft; + BitsInCurWord = sizeof(word_t)*8-BitsLeft; return R; } @@ -369,10 +440,21 @@ public: } } - void SkipToWord() { +private: + void SkipToFourByteBoundary() { + // If word_t is 64-bits and if we've read less than 32 bits, just dump + // the bits we have up to the next 32-bit boundary. + if (sizeof(word_t) > 4 && + BitsInCurWord >= 32) { + CurWord >>= BitsInCurWord-32; + BitsInCurWord = 32; + return; + } + BitsInCurWord = 0; CurWord = 0; } +public: unsigned ReadCode() { return Read(CurCodeSize); @@ -395,62 +477,37 @@ public: // Read and ignore the codelen value. Since we are skipping this block, we // don't care what code widths are used inside of it. ReadVBR(bitc::CodeLenWidth); - SkipToWord(); - unsigned NumWords = Read(bitc::BlockSizeWidth); + SkipToFourByteBoundary(); + unsigned NumFourBytes = Read(bitc::BlockSizeWidth); // Check that the block wasn't partially defined, and that the offset isn't // bogus. - size_t SkipTo = NextChar + NumWords*4; - if (AtEndOfStream() || !canSkipToPos(SkipTo)) + size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8; + if (AtEndOfStream() || !canSkipToPos(SkipTo/8)) return true; - NextChar = SkipTo; + JumpToBit(SkipTo); return false; } /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter /// the block, and return true if the block has an error. - bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0) { - // Save the current block's state on BlockScope. - BlockScope.push_back(Block(CurCodeSize)); - BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); - - // Add the abbrevs specific to this block to the CurAbbrevs list. - if (const BitstreamReader::BlockInfo *Info = - BitStream->getBlockInfo(BlockID)) { - for (unsigned i = 0, e = static_cast<unsigned>(Info->Abbrevs.size()); - i != e; ++i) { - CurAbbrevs.push_back(Info->Abbrevs[i]); - CurAbbrevs.back()->addRef(); - } - } - - // Get the codesize of this block. - CurCodeSize = ReadVBR(bitc::CodeLenWidth); - SkipToWord(); - unsigned NumWords = Read(bitc::BlockSizeWidth); - if (NumWordsP) *NumWordsP = NumWords; - - // Validate that this block is sane. - if (CurCodeSize == 0 || AtEndOfStream()) - return true; - - return false; - } - + bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0); + bool ReadBlockEnd() { if (BlockScope.empty()) return true; // Block tail: // [END_BLOCK, <align4bytes>] - SkipToWord(); + SkipToFourByteBoundary(); - PopBlockScope(); + popBlockScope(); return false; } private: - void PopBlockScope() { + + void popBlockScope() { CurCodeSize = BlockScope.back().PrevCodeSize; // Delete abbrevs from popped scope. @@ -462,36 +519,17 @@ private: BlockScope.pop_back(); } - //===--------------------------------------------------------------------===// + //===--------------------------------------------------------------------===// // Record Processing //===--------------------------------------------------------------------===// private: - void ReadAbbreviatedLiteral(const BitCodeAbbrevOp &Op, - SmallVectorImpl<uint64_t> &Vals) { - assert(Op.isLiteral() && "Not a literal"); - // If the abbrev specifies the literal value to use, use it. - Vals.push_back(Op.getLiteralValue()); - } - - void ReadAbbreviatedField(const BitCodeAbbrevOp &Op, - SmallVectorImpl<uint64_t> &Vals) { - assert(!Op.isLiteral() && "Use ReadAbbreviatedLiteral for literals!"); - - // Decode the value as we are commanded. - switch (Op.getEncoding()) { - default: llvm_unreachable("Unknown encoding!"); - case BitCodeAbbrevOp::Fixed: - Vals.push_back(Read((unsigned)Op.getEncodingData())); - break; - case BitCodeAbbrevOp::VBR: - Vals.push_back(ReadVBR64((unsigned)Op.getEncodingData())); - break; - case BitCodeAbbrevOp::Char6: - Vals.push_back(BitCodeAbbrevOp::DecodeChar6(Read(6))); - break; - } - } + void readAbbreviatedLiteral(const BitCodeAbbrevOp &Op, + SmallVectorImpl<uint64_t> &Vals); + void readAbbreviatedField(const BitCodeAbbrevOp &Op, + SmallVectorImpl<uint64_t> &Vals); + void skipAbbreviatedField(const BitCodeAbbrevOp &Op); + public: /// getAbbrev - Return the abbreviation for the specified AbbrevId. @@ -501,166 +539,18 @@ public: return CurAbbrevs[AbbrevNo]; } - unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals, - const char **BlobStart = 0, unsigned *BlobLen = 0) { - if (AbbrevID == bitc::UNABBREV_RECORD) { - unsigned Code = ReadVBR(6); - unsigned NumElts = ReadVBR(6); - for (unsigned i = 0; i != NumElts; ++i) - Vals.push_back(ReadVBR64(6)); - return Code; - } - - const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID); - - for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { - const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); - if (Op.isLiteral()) { - ReadAbbreviatedLiteral(Op, Vals); - } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) { - // Array case. Read the number of elements as a vbr6. - unsigned NumElts = ReadVBR(6); - - // Get the element encoding. - assert(i+2 == e && "array op not second to last?"); - const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); - - // Read all the elements. - for (; NumElts; --NumElts) - ReadAbbreviatedField(EltEnc, Vals); - } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) { - // Blob case. Read the number of bytes as a vbr6. - unsigned NumElts = ReadVBR(6); - SkipToWord(); // 32-bit alignment - - // Figure out where the end of this blob will be including tail padding. - size_t NewEnd = NextChar+((NumElts+3)&~3); - - // If this would read off the end of the bitcode file, just set the - // record to empty and return. - if (!canSkipToPos(NewEnd)) { - Vals.append(NumElts, 0); - NextChar = BitStream->getBitcodeBytes().getExtent(); - break; - } - - // Otherwise, read the number of bytes. If we can return a reference to - // the data, do so to avoid copying it. - if (BlobStart) { - *BlobStart = (const char*)BitStream->getBitcodeBytes().getPointer( - NextChar, NumElts); - *BlobLen = NumElts; - } else { - for (; NumElts; ++NextChar, --NumElts) - Vals.push_back(getByte(NextChar)); - } - // Skip over tail padding. - NextChar = NewEnd; - } else { - ReadAbbreviatedField(Op, Vals); - } - } - - unsigned Code = (unsigned)Vals[0]; - Vals.erase(Vals.begin()); - return Code; - } - - unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals, - const char *&BlobStart, unsigned &BlobLen) { - return ReadRecord(AbbrevID, Vals, &BlobStart, &BlobLen); - } - + /// skipRecord - Read the current record and discard it. + void skipRecord(unsigned AbbrevID); + + unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals, + StringRef *Blob = 0); //===--------------------------------------------------------------------===// // Abbrev Processing //===--------------------------------------------------------------------===// - - void ReadAbbrevRecord() { - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); - unsigned NumOpInfo = ReadVBR(5); - for (unsigned i = 0; i != NumOpInfo; ++i) { - bool IsLiteral = Read(1) ? true : false; - if (IsLiteral) { - Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8))); - continue; - } - - BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3); - if (BitCodeAbbrevOp::hasEncodingData(E)) - Abbv->Add(BitCodeAbbrevOp(E, ReadVBR64(5))); - else - Abbv->Add(BitCodeAbbrevOp(E)); - } - CurAbbrevs.push_back(Abbv); - } - -public: - - bool ReadBlockInfoBlock() { - // If this is the second stream to get to the block info block, skip it. - if (BitStream->hasBlockInfoRecords()) - return SkipBlock(); - - if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true; - - SmallVector<uint64_t, 64> Record; - BitstreamReader::BlockInfo *CurBlockInfo = 0; - - // Read all the records for this module. - while (1) { - unsigned Code = ReadCode(); - if (Code == bitc::END_BLOCK) - return ReadBlockEnd(); - if (Code == bitc::ENTER_SUBBLOCK) { - ReadSubBlockID(); - if (SkipBlock()) return true; - continue; - } - - // Read abbrev records, associate them with CurBID. - if (Code == bitc::DEFINE_ABBREV) { - if (!CurBlockInfo) return true; - ReadAbbrevRecord(); - - // ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the - // appropriate BlockInfo. - BitCodeAbbrev *Abbv = CurAbbrevs.back(); - CurAbbrevs.pop_back(); - CurBlockInfo->Abbrevs.push_back(Abbv); - continue; - } - - // Read a record. - Record.clear(); - switch (ReadRecord(Code, Record)) { - default: break; // Default behavior, ignore unknown content. - case bitc::BLOCKINFO_CODE_SETBID: - if (Record.size() < 1) return true; - CurBlockInfo = &BitStream->getOrCreateBlockInfo((unsigned)Record[0]); - break; - case bitc::BLOCKINFO_CODE_BLOCKNAME: { - if (!CurBlockInfo) return true; - if (BitStream->isIgnoringBlockInfoNames()) break; // Ignore name. - std::string Name; - for (unsigned i = 0, e = Record.size(); i != e; ++i) - Name += (char)Record[i]; - CurBlockInfo->Name = Name; - break; - } - case bitc::BLOCKINFO_CODE_SETRECORDNAME: { - if (!CurBlockInfo) return true; - if (BitStream->isIgnoringBlockInfoNames()) break; // Ignore name. - std::string Name; - for (unsigned i = 1, e = Record.size(); i != e; ++i) - Name += (char)Record[i]; - CurBlockInfo->RecordNames.push_back(std::make_pair((unsigned)Record[0], - Name)); - break; - } - } - } - } + void ReadAbbrevRecord(); + + bool ReadBlockInfoBlock(); }; } // End llvm namespace diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index 1021fbd..7b68f87 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef BITSTREAM_WRITER_H -#define BITSTREAM_WRITER_H +#ifndef LLVM_BITCODE_BITSTREAMWRITER_H +#define LLVM_BITCODE_BITSTREAMWRITER_H #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 601777d..f9690d5 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -29,13 +29,12 @@ namespace bitc { // Module sub-block id's. PARAMATTR_BLOCK_ID, - - UNUSED_ID1, + PARAMATTR_GROUP_BLOCK_ID, CONSTANTS_BLOCK_ID, FUNCTION_BLOCK_ID, - UNUSED_ID2, + UNUSED_ID1, VALUE_SYMTAB_BLOCK_ID, METADATA_BLOCK_ID, @@ -69,7 +68,7 @@ namespace bitc { // ALIAS: [alias type, aliasee val#, linkage, visibility] MODULE_CODE_ALIAS = 9, - /// MODULE_CODE_PURGEVALS: [numvals] + // MODULE_CODE_PURGEVALS: [numvals] MODULE_CODE_PURGEVALS = 10, MODULE_CODE_GCNAME = 11 // GCNAME: [strchr x N] @@ -77,7 +76,12 @@ namespace bitc { /// PARAMATTR blocks have code for defining a parameter attribute set. enum AttributeCodes { - PARAMATTR_CODE_ENTRY = 1 // ENTRY: [paramidx0, attr0, paramidx1, attr1...] + // FIXME: Remove `PARAMATTR_CODE_ENTRY_OLD' in 4.0 + PARAMATTR_CODE_ENTRY_OLD = 1, // ENTRY: [paramidx0, attr0, + // paramidx1, attr1...] + PARAMATTR_CODE_ENTRY = 2, // ENTRY: [paramidx0, attrgrp0, + // paramidx1, attrgrp1, ...] + PARAMATTR_GRP_CODE_ENTRY = 3 // ENTRY: [id, attr0, att1, ...] }; /// TYPE blocks have codes for each type primitive they use. @@ -143,6 +147,7 @@ namespace bitc { METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes] METADATA_ATTACHMENT = 11 // [m x [value, [n x [id, mdnode]]] }; + // The constants block (CONSTANTS_BLOCK_ID) describes emission for each // constant and maintains an implicit current type value. enum ConstantsCodes { diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index dd96b04..78f40ca 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_BITCODE_H -#define LLVM_BITCODE_H +#ifndef LLVM_BITCODE_READERWRITER_H +#define LLVM_BITCODE_READERWRITER_H #include <string> diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index 81e75d8..ce9ca0a 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -86,8 +86,7 @@ ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred); /// between it and the return. /// /// This function only tests target-independent requirements. -bool isInTailCallPosition(ImmutableCallSite CS, Attribute CalleeRetAttr, - const TargetLowering &TLI); +bool isInTailCallPosition(ImmutableCallSite CS, const TargetLowering &TLI); } // End llvm namespace diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index a66e05b..9a27661 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_COMMAND_LINE_FLAGS_H -#define LLVM_CODEGEN_COMMAND_LINE_FLAGS_H +#ifndef LLVM_CODEGEN_COMMANDFLAGS_H +#define LLVM_CODEGEN_COMMANDFLAGS_H #include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 0561905..57273d8 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -90,6 +90,11 @@ public: /// getCurDebugLoc() - Return current debug location information. DebugLoc getCurDebugLoc() const { return DL; } + + /// LowerArguments - Do "fast" instruction selection for function arguments + /// and append machine instructions to the current block. Return true if + /// it is successful. + bool LowerArguments(); /// SelectInstruction - Do "fast" instruction selection for the given /// LLVM IR instruction, and append generated machine instructions to @@ -160,6 +165,11 @@ protected: /// virtual bool TargetSelectInstruction(const Instruction *I) = 0; + + /// FastLowerArguments - This method is called by target-independent code to + /// do target specific argument lowering. It returns true if it was + /// successful. + virtual bool FastLowerArguments(); /// FastEmit_r - This method is called by target-independent code /// to request that an instruction with the given type and opcode @@ -362,6 +372,11 @@ protected: return 0; } + /// Whether we should skip target-independent fast-isel + virtual bool SkipTargetIndependentFastISel() { + return false; + } + private: bool SelectBinaryOp(const User *I, unsigned ISDOpcode); diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 72e0937..ea6cb27 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -17,17 +17,13 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Analysis/BranchProbabilityInfo.h" -#include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" -#include "llvm/Support/CallSite.h" #include "llvm/Target/TargetRegisterInfo.h" #include <vector> @@ -35,6 +31,7 @@ namespace llvm { class AllocaInst; class BasicBlock; +class BranchProbabilityInfo; class CallInst; class Function; class GlobalVariable; diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 5d0a3b4..092fa5a 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -455,6 +455,9 @@ namespace ISD { FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, FLOG, FLOG2, FLOG10, FEXP, FEXP2, FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR, + + /// FSINCOS - Compute both fsin and fcos as a single operation. + FSINCOS, /// LOAD and STORE have token chains as their first operand, then the same /// operands as an LLVM load/store instruction, then an offset node that diff --git a/include/llvm/CodeGen/JITCodeEmitter.h b/include/llvm/CodeGen/JITCodeEmitter.h index 21a3f48..9a73214 100644 --- a/include/llvm/CodeGen/JITCodeEmitter.h +++ b/include/llvm/CodeGen/JITCodeEmitter.h @@ -207,8 +207,7 @@ public: /// emitString - This callback is invoked when a String needs to be /// written to the output stream. void emitString(const std::string &String) { - for (unsigned i = 0, N = static_cast<unsigned>(String.size()); - i < N; ++i) { + for (size_t i = 0, N = String.size(); i < N; ++i) { uint8_t C = String[i]; emitByte(C); } diff --git a/include/llvm/CodeGen/LatencyPriorityQueue.h b/include/llvm/CodeGen/LatencyPriorityQueue.h index 8fb31aa..d454347 100644 --- a/include/llvm/CodeGen/LatencyPriorityQueue.h +++ b/include/llvm/CodeGen/LatencyPriorityQueue.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LATENCY_PRIORITY_QUEUE_H -#define LATENCY_PRIORITY_QUEUE_H +#ifndef LLVM_CODEGEN_LATENCYPRIORITYQUEUE_H +#define LLVM_CODEGEN_LATENCYPRIORITYQUEUE_H #include "llvm/CodeGen/ScheduleDAG.h" diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 3cb6b4d..ff65db4 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -159,9 +159,6 @@ public: LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A) : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), LastInsn(0), FirstInsn(0), DFSIn(0), DFSOut(0) { -#ifndef NDEBUG - IndentLevel = 0; -#endif if (Parent) Parent->addChild(this); } @@ -228,7 +225,7 @@ public: void setDFSIn(unsigned I) { DFSIn = I; } /// dump - print lexical scope. - void dump() const; + void dump(unsigned Indent = 0) const; private: LexicalScope *Parent; // Parent to this scope. @@ -244,9 +241,6 @@ private: const MachineInstr *FirstInsn; // First instruction of this scope. unsigned DFSIn, DFSOut; // In & Out Depth use to determine // scope nesting. -#ifndef NDEBUG - mutable unsigned IndentLevel; // Private state for dump() -#endif }; } // end llvm namespace diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index 9576075..244be9c 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -86,9 +86,10 @@ namespace llvm { SlotIndex end; // End point of the interval (exclusive) VNInfo *valno; // identifier for the value contained in this interval. + LiveRange() : valno(0) {} + LiveRange(SlotIndex S, SlotIndex E, VNInfo *V) : start(S), end(E), valno(V) { - assert(S < E && "Cannot create empty or backwards range"); } @@ -373,8 +374,8 @@ namespace llvm { /// addRange - Add the specified LiveRange to this interval, merging /// intervals as appropriate. This returns an iterator to the inserted live /// range (which may have grown since it was inserted. - void addRange(LiveRange LR) { - addRangeFrom(LR, ranges.begin()); + iterator addRange(LiveRange LR) { + return addRangeFrom(LR, ranges.begin()); } /// extendInBlock - If this interval is live before Kill in the basic block @@ -460,9 +461,6 @@ namespace llvm { void extendIntervalEndTo(Ranges::iterator I, SlotIndex NewEnd); Ranges::iterator extendIntervalStartTo(Ranges::iterator I, SlotIndex NewStr); void markValNoForDeletion(VNInfo *V); - void mergeIntervalRanges(const LiveInterval &RHS, - VNInfo *LHSValNo = 0, - const VNInfo *RHSValNo = 0); LiveInterval& operator=(const LiveInterval& rhs) LLVM_DELETED_FUNCTION; @@ -473,6 +471,64 @@ namespace llvm { return OS; } + /// Helper class for performant LiveInterval bulk updates. + /// + /// Calling LiveInterval::addRange() repeatedly can be expensive on large + /// live ranges because segments after the insertion point may need to be + /// shifted. The LiveRangeUpdater class can defer the shifting when adding + /// many segments in order. + /// + /// The LiveInterval will be in an invalid state until flush() is called. + class LiveRangeUpdater { + LiveInterval *LI; + SlotIndex LastStart; + LiveInterval::iterator WriteI; + LiveInterval::iterator ReadI; + SmallVector<LiveRange, 16> Spills; + void mergeSpills(); + + public: + /// Create a LiveRangeUpdater for adding segments to LI. + /// LI will temporarily be in an invalid state until flush() is called. + LiveRangeUpdater(LiveInterval *li = 0) : LI(li) {} + + ~LiveRangeUpdater() { flush(); } + + /// Add a segment to LI and coalesce when possible, just like LI.addRange(). + /// Segments should be added in increasing start order for best performance. + void add(LiveRange); + + void add(SlotIndex Start, SlotIndex End, VNInfo *VNI) { + add(LiveRange(Start, End, VNI)); + } + + /// Return true if the LI is currently in an invalid state, and flush() + /// needs to be called. + bool isDirty() const { return LastStart.isValid(); } + + /// Flush the updater state to LI so it is valid and contains all added + /// segments. + void flush(); + + /// Select a different destination live range. + void setDest(LiveInterval *li) { + if (LI != li && isDirty()) + flush(); + LI = li; + } + + /// Get the current destination live range. + LiveInterval *getDest() const { return LI; } + + void dump() const; + void print(raw_ostream&) const; + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const LiveRangeUpdater &X) { + X.print(OS); + return OS; + } + /// LiveRangeQuery - Query information about a live range around a given /// instruction. This class hides the implementation details of live ranges, /// and it should be used as the primary interface for examining live ranges diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 9e89519..4632368 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -53,7 +53,6 @@ namespace llvm { const TargetRegisterInfo* TRI; const TargetInstrInfo* TII; AliasAnalysis *AA; - LiveVariables* LV; SlotIndexes* Indexes; MachineDominatorTree *DomTree; LiveRangeCalc *LRCalc; @@ -215,6 +214,13 @@ namespace llvm { return Indexes->getMBBFromIndex(index); } + void insertMBBInMaps(MachineBasicBlock *MBB) { + Indexes->insertMBBInMaps(MBB); + assert(unsigned(MBB->getNumber()) == RegMaskBlocks.size() && + "Blocks must be added in order."); + RegMaskBlocks.push_back(std::make_pair(RegMaskSlots.size(), 0)); + } + SlotIndex InsertMachineInstrInMaps(MachineInstr *MI) { return Indexes->insertMachineInstrInMaps(MI); } @@ -275,6 +281,21 @@ namespace llvm { void handleMoveIntoBundle(MachineInstr* MI, MachineInstr* BundleStart, bool UpdateFlags = false); + /// repairIntervalsInRange - Update live intervals for instructions in a + /// range of iterators. It is intended for use after target hooks that may + /// insert or remove instructions, and is only efficient for a small number + /// of instructions. + /// + /// OrigRegs is a vector of registers that were originally used by the + /// instructions in the range between the two iterators. + /// + /// Currently, the only only changes that are supported are simple removal + /// and addition of uses. + void repairIntervalsInRange(MachineBasicBlock *MBB, + MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + ArrayRef<unsigned> OrigRegs); + // Register mask functions. // // Machine instructions may use a register mask operand to indicate that a @@ -352,36 +373,12 @@ namespace llvm { } private: - /// computeIntervals - Compute live intervals. - void computeIntervals(); - /// Compute live intervals for all virtual registers. void computeVirtRegs(); /// Compute RegMaskSlots and RegMaskBits. void computeRegMasks(); - /// handleRegisterDef - update intervals for a register def - /// (calls handleVirtualRegisterDef) - void handleRegisterDef(MachineBasicBlock *MBB, - MachineBasicBlock::iterator MI, - SlotIndex MIIdx, - MachineOperand& MO, unsigned MOIdx); - - /// isPartialRedef - Return true if the specified def at the specific index - /// is partially re-defining the specified live interval. A common case of - /// this is a definition of the sub-register. - bool isPartialRedef(SlotIndex MIIdx, MachineOperand &MO, - LiveInterval &interval); - - /// handleVirtualRegisterDef - update intervals for a virtual - /// register def - void handleVirtualRegisterDef(MachineBasicBlock *MBB, - MachineBasicBlock::iterator MI, - SlotIndex MIIdx, MachineOperand& MO, - unsigned MOIdx, - LiveInterval& interval); - static LiveInterval* createInterval(unsigned Reg); void printInstrs(raw_ostream &O) const; diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 6a61614..615b339 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_LIVEINTERVALUNION -#define LLVM_CODEGEN_LIVEINTERVALUNION +#ifndef LLVM_CODEGEN_LIVEINTERVALUNION_H +#define LLVM_CODEGEN_LIVEINTERVALUNION_H #include "llvm/ADT/IntervalMap.h" #include "llvm/CodeGen/LiveInterval.h" @@ -202,4 +202,4 @@ public: } // end namespace llvm -#endif // !defined(LLVM_CODEGEN_LIVEINTERVALUNION) +#endif // !defined(LLVM_CODEGEN_LIVEINTERVALUNION_H) diff --git a/include/llvm/CodeGen/LiveStackAnalysis.h b/include/llvm/CodeGen/LiveStackAnalysis.h index a3b1855..92c35f7 100644 --- a/include/llvm/CodeGen/LiveStackAnalysis.h +++ b/include/llvm/CodeGen/LiveStackAnalysis.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_LIVESTACK_ANALYSIS_H -#define LLVM_CODEGEN_LIVESTACK_ANALYSIS_H +#ifndef LLVM_CODEGEN_LIVESTACKANALYSIS_H +#define LLVM_CODEGEN_LIVESTACKANALYSIS_H #include "llvm/CodeGen/LiveInterval.h" #include "llvm/CodeGen/MachineFunctionPass.h" diff --git a/include/llvm/CodeGen/MachORelocation.h b/include/llvm/CodeGen/MachORelocation.h index 21fe74f..8c9b7a8 100644 --- a/include/llvm/CodeGen/MachORelocation.h +++ b/include/llvm/CodeGen/MachORelocation.h @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_MACHO_RELOCATION_H -#define LLVM_CODEGEN_MACHO_RELOCATION_H +#ifndef LLVM_CODEGEN_MACHORELOCATION_H +#define LLVM_CODEGEN_MACHORELOCATION_H #include "llvm/Support/DataTypes.h" @@ -53,4 +53,4 @@ namespace llvm { } // end llvm namespace -#endif // LLVM_CODEGEN_MACHO_RELOCATION_H +#endif // LLVM_CODEGEN_MACHORELOCATION_H diff --git a/include/llvm/CodeGen/MachineCodeInfo.h b/include/llvm/CodeGen/MachineCodeInfo.h index c5c0c44..ba9dfab 100644 --- a/include/llvm/CodeGen/MachineCodeInfo.h +++ b/include/llvm/CodeGen/MachineCodeInfo.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef EE_MACHINE_CODE_INFO_H -#define EE_MACHINE_CODE_INFO_H +#ifndef LLVM_CODEGEN_MACHINECODEINFO_H +#define LLVM_CODEGEN_MACHINECODEINFO_H #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index 40b2542..e41d206 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -41,15 +41,15 @@ class MachineDominatorTree : public MachineFunctionPass { public: static char ID; // Pass ID, replacement for typeid DominatorTreeBase<MachineBasicBlock>* DT; - + MachineDominatorTree(); - + ~MachineDominatorTree(); - + DominatorTreeBase<MachineBasicBlock>& getBase() { return *DT; } - + virtual void getAnalysisUsage(AnalysisUsage &AU) const; - + /// getRoots - Return the root blocks of the current CFG. This may include /// multiple blocks if we are computing post dominators. For forward /// dominators, this will always be a single block (the entry node). @@ -57,33 +57,35 @@ public: inline const std::vector<MachineBasicBlock*> &getRoots() const { return DT->getRoots(); } - + inline MachineBasicBlock *getRoot() const { return DT->getRoot(); } - + inline MachineDomTreeNode *getRootNode() const { return DT->getRootNode(); } - + virtual bool runOnMachineFunction(MachineFunction &F); - - inline bool dominates(MachineDomTreeNode* A, MachineDomTreeNode* B) const { + + inline bool dominates(const MachineDomTreeNode* A, + const MachineDomTreeNode* B) const { return DT->dominates(A, B); } - - inline bool dominates(MachineBasicBlock* A, MachineBasicBlock* B) const { + + inline bool dominates(const MachineBasicBlock* A, + const MachineBasicBlock* B) const { return DT->dominates(A, B); } - + // dominates - Return true if A dominates B. This performs the // special checks necessary if A and B are in the same basic block. - bool dominates(MachineInstr *A, MachineInstr *B) const { - MachineBasicBlock *BBA = A->getParent(), *BBB = B->getParent(); + bool dominates(const MachineInstr *A, const MachineInstr *B) const { + const MachineBasicBlock *BBA = A->getParent(), *BBB = B->getParent(); if (BBA != BBB) return DT->dominates(BBA, BBB); // Loop through the basic block until we find A or B. - MachineBasicBlock::iterator I = BBA->begin(); + MachineBasicBlock::const_iterator I = BBA->begin(); for (; &*I != A && &*I != B; ++I) /*empty*/ ; @@ -95,43 +97,43 @@ public: // return &*I == B; //} } - + inline bool properlyDominates(const MachineDomTreeNode* A, - MachineDomTreeNode* B) const { + const MachineDomTreeNode* B) const { return DT->properlyDominates(A, B); } - - inline bool properlyDominates(MachineBasicBlock* A, - MachineBasicBlock* B) const { + + inline bool properlyDominates(const MachineBasicBlock* A, + const MachineBasicBlock* B) const { return DT->properlyDominates(A, B); } - + /// findNearestCommonDominator - Find nearest common dominator basic block /// for basic block A and B. If there is no such block then return NULL. inline MachineBasicBlock *findNearestCommonDominator(MachineBasicBlock *A, MachineBasicBlock *B) { return DT->findNearestCommonDominator(A, B); } - + inline MachineDomTreeNode *operator[](MachineBasicBlock *BB) const { return DT->getNode(BB); } - + /// getNode - return the (Post)DominatorTree node for the specified basic /// block. This is the same as using operator[] on this class. /// inline MachineDomTreeNode *getNode(MachineBasicBlock *BB) const { return DT->getNode(BB); } - + /// addNewBlock - Add a new node to the dominator tree information. This - /// creates a new node as a child of DomBB dominator node,linking it into + /// creates a new node as a child of DomBB dominator node,linking it into /// the children list of the immediate dominator. inline MachineDomTreeNode *addNewBlock(MachineBasicBlock *BB, MachineBasicBlock *DomBB) { return DT->addNewBlock(BB, DomBB); } - + /// changeImmediateDominator - This method is used to update the dominator /// tree information when a node's immediate dominator changes. /// @@ -139,19 +141,19 @@ public: MachineBasicBlock* NewIDom) { DT->changeImmediateDominator(N, NewIDom); } - + inline void changeImmediateDominator(MachineDomTreeNode *N, MachineDomTreeNode* NewIDom) { DT->changeImmediateDominator(N, NewIDom); } - + /// eraseNode - Removes a node from the dominator tree. Block must not /// dominate any other blocks. Removes node from its immediate dominator's /// children list. Deletes dominator node associated with basic block BB. inline void eraseNode(MachineBasicBlock *BB) { DT->eraseNode(BB); } - + /// splitBlock - BB is split and now it has one successor. Update dominator /// tree to reflect this change. inline void splitBlock(MachineBasicBlock* NewBB) { @@ -160,12 +162,12 @@ public: /// isReachableFromEntry - Return true if A is dominated by the entry /// block of the function containing it. - bool isReachableFromEntry(MachineBasicBlock *A) { + bool isReachableFromEntry(const MachineBasicBlock *A) { return DT->isReachableFromEntry(A); } virtual void releaseMemory(); - + virtual void print(raw_ostream &OS, const Module*) const; }; @@ -179,7 +181,7 @@ template<class T> struct GraphTraits; template <> struct GraphTraits<MachineDomTreeNode *> { typedef MachineDomTreeNode NodeType; typedef NodeType::iterator ChildIteratorType; - + static NodeType *getEntryNode(NodeType *N) { return N; } diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index cd704c1..82c4cd6 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -131,6 +131,9 @@ class MachineFunction { /// about the control flow of such functions. bool ExposesReturnsTwice; + /// True if the function includes MS-style inline assembly. + bool HasMSInlineAsm; + MachineFunction(const MachineFunction &) LLVM_DELETED_FUNCTION; void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION; public: @@ -214,6 +217,17 @@ public: void setExposesReturnsTwice(bool B) { ExposesReturnsTwice = B; } + + /// Returns true if the function contains any MS-style inline assembly. + bool hasMSInlineAsm() const { + return HasMSInlineAsm; + } + + /// Set a flag that indicates that the function contains MS-style inline + /// assembly. + void setHasMSInlineAsm(bool B) { + HasMSInlineAsm = B; + } /// getInfo - Keep track of various per-function pieces of information for /// backends that would like to do so. diff --git a/include/llvm/CodeGen/MachineFunctionAnalysis.h b/include/llvm/CodeGen/MachineFunctionAnalysis.h index 50ea206..112f07e 100644 --- a/include/llvm/CodeGen/MachineFunctionAnalysis.h +++ b/include/llvm/CodeGen/MachineFunctionAnalysis.h @@ -11,15 +11,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_MACHINE_FUNCTION_ANALYSIS_H -#define LLVM_CODEGEN_MACHINE_FUNCTION_ANALYSIS_H +#ifndef LLVM_CODEGEN_MACHINEFUNCTIONANALYSIS_H +#define LLVM_CODEGEN_MACHINEFUNCTIONANALYSIS_H #include "llvm/Pass.h" -#include "llvm/Target/TargetMachine.h" namespace llvm { class MachineFunction; +class TargetMachine; /// MachineFunctionAnalysis - This class is a Pass that manages a /// MachineFunction object. diff --git a/include/llvm/CodeGen/MachineFunctionPass.h b/include/llvm/CodeGen/MachineFunctionPass.h index b7bf0a3..04881e5 100644 --- a/include/llvm/CodeGen/MachineFunctionPass.h +++ b/include/llvm/CodeGen/MachineFunctionPass.h @@ -16,8 +16,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_MACHINE_FUNCTION_PASS_H -#define LLVM_CODEGEN_MACHINE_FUNCTION_PASS_H +#ifndef LLVM_CODEGEN_MACHINEFUNCTIONPASS_H +#define LLVM_CODEGEN_MACHINEFUNCTIONPASS_H #include "llvm/Pass.h" diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 89521e8..195cce7 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -313,11 +313,11 @@ public: /// The second argument indicates whether the query should look inside /// instruction bundles. bool hasProperty(unsigned MCFlag, QueryType Type = AnyInBundle) const { - // Inline the fast path. - if (Type == IgnoreBundle || !isBundle()) + // Inline the fast path for unbundled or bundle-internal instructions. + if (Type == IgnoreBundle || !isBundled() || isBundledWithPred()) return getDesc().getFlags() & (1 << MCFlag); - // If we have a bundle, take the slow path. + // If this is the first instruction in a bundle, take the slow path. return hasPropertyInBundle(1 << MCFlag, Type); } @@ -642,6 +642,9 @@ public: bool isKill() const { return getOpcode() == TargetOpcode::KILL; } bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; } bool isInlineAsm() const { return getOpcode() == TargetOpcode::INLINEASM; } + bool isMSInlineAsm() const { + return getOpcode() == TargetOpcode::INLINEASM && getInlineAsmDialect(); + } bool isStackAligningInlineAsm() const; InlineAsm::AsmDialect getInlineAsmDialect() const; bool isInsertSubreg() const { @@ -699,7 +702,11 @@ public: } } - /// getBundleSize - Return the number of instructions inside the MI bundle. + /// Return the number of instructions inside the MI bundle, excluding the + /// bundle header. + /// + /// This is the number of instructions that MachineBasicBlock::iterator + /// skips, 0 for unbundled instructions. unsigned getBundleSize() const; /// readsRegister - Return true if the MachineInstr reads the specified @@ -944,7 +951,8 @@ public: // // Debugging support // - void print(raw_ostream &OS, const TargetMachine *TM = 0) const; + void print(raw_ostream &OS, const TargetMachine *TM = 0, + bool SkipOpers = false) const; void dump() const; //===--------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index a2d3d63..92c8da9 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -18,6 +18,7 @@ #define LLVM_CODEGEN_MACHINEINSTRBUILDER_H #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBundle.h" #include "llvm/Support/ErrorHandling.h" namespace llvm { @@ -391,11 +392,7 @@ public: /// Create an MIBundleBuilder representing an existing instruction or bundle /// that has MI as its head. explicit MIBundleBuilder(MachineInstr *MI) - : MBB(*MI->getParent()), Begin(MI) { - MachineBasicBlock::iterator I = MI; - ++I; - End = I.getInstrIterator(); - } + : MBB(*MI->getParent()), Begin(MI), End(getBundleEnd(MI)) {} /// Return a reference to the basic block containing this bundle. MachineBasicBlock &getMBB() const { return MBB; } diff --git a/include/llvm/CodeGen/MachineInstrBundle.h b/include/llvm/CodeGen/MachineInstrBundle.h index 3c60ad1..9519edb 100644 --- a/include/llvm/CodeGen/MachineInstrBundle.h +++ b/include/llvm/CodeGen/MachineInstrBundle.h @@ -45,18 +45,36 @@ bool finalizeBundles(MachineFunction &MF); /// inline MachineInstr *getBundleStart(MachineInstr *MI) { MachineBasicBlock::instr_iterator I = MI; - while (I->isInsideBundle()) + while (I->isBundledWithPred()) --I; return I; } inline const MachineInstr *getBundleStart(const MachineInstr *MI) { MachineBasicBlock::const_instr_iterator I = MI; - while (I->isInsideBundle()) + while (I->isBundledWithPred()) --I; return I; } +/// Return an iterator pointing beyond the bundle containing MI. +inline MachineBasicBlock::instr_iterator +getBundleEnd(MachineInstr *MI) { + MachineBasicBlock::instr_iterator I = MI; + while (I->isBundledWithSucc()) + ++I; + return ++I; +} + +/// Return an iterator pointing beyond the bundle containing MI. +inline MachineBasicBlock::const_instr_iterator +getBundleEnd(const MachineInstr *MI) { + MachineBasicBlock::const_instr_iterator I = MI; + while (I->isBundledWithSucc()) + ++I; + return ++I; +} + //===----------------------------------------------------------------------===// // MachineOperand iterator // diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index 99da6b2..b058ecb 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -27,8 +27,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_MACHINE_LOOP_INFO_H -#define LLVM_CODEGEN_MACHINE_LOOP_INFO_H +#ifndef LLVM_CODEGEN_MACHINELOOPINFO_H +#define LLVM_CODEGEN_MACHINELOOPINFO_H #include "llvm/Analysis/LoopInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 6194d05..1db6252 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -35,7 +35,6 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/IR/GlobalValue.h" #include "llvm/IR/Metadata.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MachineLocation.h" diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 36427e9..875285b 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -99,13 +99,11 @@ class MachineRegisterInfo { /// started. BitVector ReservedRegs; - /// LiveIns/LiveOuts - Keep track of the physical registers that are - /// livein/liveout of the function. Live in values are typically arguments in - /// registers, live out values are typically return values in registers. - /// LiveIn values are allowed to have virtual registers associated with them, - /// stored in the second element. + /// Keep track of the physical registers that are live in to the function. + /// Live in values are typically arguments in registers, live out values are + /// typically return values in registers. LiveIn values are allowed to have + /// virtual registers associated with them, stored in the second element. std::vector<std::pair<unsigned, unsigned> > LiveIns; - std::vector<unsigned> LiveOuts; MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; @@ -379,6 +377,12 @@ public: return false; } + /// Mark the specified register unit as used in this function. + /// This should only be called during and after register allocation. + void setRegUnitUsed(unsigned RegUnit) { + UsedRegUnits.set(RegUnit); + } + /// setPhysRegUsed - Mark the specified register used in this function. /// This should only be called during and after register allocation. void setPhysRegUsed(unsigned Reg) { @@ -468,7 +472,6 @@ public: void addLiveIn(unsigned Reg, unsigned vreg = 0) { LiveIns.push_back(std::make_pair(Reg, vreg)); } - void addLiveOut(unsigned Reg) { LiveOuts.push_back(Reg); } // Iteration support for live in/out sets. These sets are kept in sorted // order by their register number. @@ -478,12 +481,8 @@ public: livein_iterator livein_begin() const { return LiveIns.begin(); } livein_iterator livein_end() const { return LiveIns.end(); } bool livein_empty() const { return LiveIns.empty(); } - liveout_iterator liveout_begin() const { return LiveOuts.begin(); } - liveout_iterator liveout_end() const { return LiveOuts.end(); } - bool liveout_empty() const { return LiveOuts.empty(); } bool isLiveIn(unsigned Reg) const; - bool isLiveOut(unsigned Reg) const; /// getLiveInPhysReg - If VReg is a live-in virtual register, return the /// corresponding live-in physical register. diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index 88f347e..57febe7 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -24,8 +24,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MACHINESCHEDULER_H -#define MACHINESCHEDULER_H +#ifndef LLVM_CODEGEN_MACHINESCHEDULER_H +#define LLVM_CODEGEN_MACHINESCHEDULER_H #include "llvm/CodeGen/MachinePassRegistry.h" #include "llvm/CodeGen/RegisterPressure.h" @@ -43,6 +43,7 @@ class MachineDominatorTree; class MachineLoopInfo; class RegisterClassInfo; class ScheduleDAGInstrs; +class SchedDFSResult; /// MachineSchedContext provides enough context from the MachineScheduler pass /// for the target to instantiate a scheduler. @@ -119,6 +120,9 @@ public: /// be scheduled at the bottom. virtual SUnit *pickNode(bool &IsTopNode) = 0; + /// \brief Scheduler callback to notify that a new subtree is scheduled. + virtual void scheduleTree(unsigned SubtreeID) {} + /// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an /// instruction and updated scheduled/remaining flags in the DAG nodes. virtual void schedNode(SUnit *SU, bool IsTopNode) = 0; @@ -164,6 +168,8 @@ public: iterator end() { return Queue.end(); } + ArrayRef<SUnit*> elements() { return Queue; } + iterator find(SUnit *SU) { return std::find(Queue.begin(), Queue.end(), SU); } @@ -202,6 +208,11 @@ protected: RegisterClassInfo *RegClassInfo; MachineSchedStrategy *SchedImpl; + /// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees + /// will be empty. + SchedDFSResult *DFSResult; + BitVector ScheduledTrees; + /// Topo - A topological ordering for SUnits which permits fast IsReachable /// and similar queries. ScheduleDAGTopologicalSort Topo; @@ -243,7 +254,7 @@ protected: public: ScheduleDAGMI(MachineSchedContext *C, MachineSchedStrategy *S): ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS), - AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S), + AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S), DFSResult(0), Topo(SUnits, &ExitSU), RPTracker(RegPressure), CurrentTop(), TopRPTracker(TopPressure), CurrentBottom(), BotRPTracker(BotPressure), NextClusterPred(NULL), NextClusterSucc(NULL) { @@ -252,10 +263,7 @@ public: #endif } - virtual ~ScheduleDAGMI() { - DeleteContainerPointers(Mutations); - delete SchedImpl; - } + virtual ~ScheduleDAGMI(); /// Add a postprocessing step to the DAG builder. /// Mutations are applied in the order that they are added after normal DAG @@ -308,6 +316,18 @@ public: const SUnit *getNextClusterSucc() const { return NextClusterSucc; } + /// Compute a DFSResult after DAG building is complete, and before any + /// queue comparisons. + void computeDFSResult(); + + /// Return a non-null DFS result if the scheduling strategy initialized it. + const SchedDFSResult *getDFSResult() const { return DFSResult; } + + BitVector &getScheduledTrees() { return ScheduledTrees; } + + void viewGraph(const Twine &Name, const Twine &Title) LLVM_OVERRIDE; + void viewGraph() LLVM_OVERRIDE; + protected: // Top-Level entry points for the schedule() driver... @@ -321,8 +341,8 @@ protected: /// instances of ScheduleDAGMI to perform custom DAG postprocessing. void postprocessDAG(); - /// Identify DAG roots and setup scheduler queues. - void initQueues(); + /// Release ExitSU predecessors and setup scheduler queues. + void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots); /// Move an instruction and update register pressure. void scheduleMI(SUnit *SU, bool IsTopNode); @@ -340,12 +360,13 @@ protected: void initRegPressure(); - void updateScheduledPressure(std::vector<unsigned> NewMaxPressure); + void updateScheduledPressure(const std::vector<unsigned> &NewMaxPressure); void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos); bool checkSchedLimit(); - void releaseRoots(); + void findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots, + SmallVectorImpl<SUnit*> &BotRoots); void releaseSucc(SUnit *SU, SDep *SuccEdge); void releaseSuccessors(SUnit *SU); diff --git a/include/llvm/CodeGen/MachineTraceMetrics.h b/include/llvm/CodeGen/MachineTraceMetrics.h new file mode 100644 index 0000000..460730b --- /dev/null +++ b/include/llvm/CodeGen/MachineTraceMetrics.h @@ -0,0 +1,350 @@ +//===- lib/CodeGen/MachineTraceMetrics.h - Super-scalar metrics -*- 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 MachineTraceMetrics analysis pass +// that estimates CPU resource usage and critical data dependency paths through +// preferred traces. This is useful for super-scalar CPUs where execution speed +// can be limited both by data dependencies and by limited execution resources. +// +// Out-of-order CPUs will often be executing instructions from multiple basic +// blocks at the same time. This makes it difficult to estimate the resource +// usage accurately in a single basic block. Resources can be estimated better +// by looking at a trace through the current basic block. +// +// For every block, the MachineTraceMetrics pass will pick a preferred trace +// that passes through the block. The trace is chosen based on loop structure, +// branch probabilities, and resource usage. The intention is to pick likely +// traces that would be the most affected by code transformations. +// +// It is expensive to compute a full arbitrary trace for every block, so to +// save some computations, traces are chosen to be convergent. This means that +// if the traces through basic blocks A and B ever cross when moving away from +// A and B, they never diverge again. This applies in both directions - If the +// traces meet above A and B, they won't diverge when going further back. +// +// Traces tend to align with loops. The trace through a block in an inner loop +// will begin at the loop entry block and end at a back edge. If there are +// nested loops, the trace may begin and end at those instead. +// +// For each trace, we compute the critical path length, which is the number of +// cycles required to execute the trace when execution is limited by data +// dependencies only. We also compute the resource height, which is the number +// of cycles required to execute all instructions in the trace when ignoring +// data dependencies. +// +// Every instruction in the current block has a slack - the number of cycles +// execution of the instruction can be delayed without extending the critical +// path. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINE_TRACE_METRICS_H +#define LLVM_CODEGEN_MACHINE_TRACE_METRICS_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/TargetSchedule.h" + +namespace llvm { + +class InstrItineraryData; +class MachineBasicBlock; +class MachineInstr; +class MachineLoop; +class MachineLoopInfo; +class MachineRegisterInfo; +class TargetInstrInfo; +class TargetRegisterInfo; +class raw_ostream; + +class MachineTraceMetrics : public MachineFunctionPass { + const MachineFunction *MF; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + const MachineRegisterInfo *MRI; + const MachineLoopInfo *Loops; + TargetSchedModel SchedModel; + +public: + class Ensemble; + class Trace; + static char ID; + MachineTraceMetrics(); + void getAnalysisUsage(AnalysisUsage&) const; + bool runOnMachineFunction(MachineFunction&); + void releaseMemory(); + void verifyAnalysis() const; + + friend class Ensemble; + friend class Trace; + + /// Per-basic block information that doesn't depend on the trace through the + /// block. + struct FixedBlockInfo { + /// The number of non-trivial instructions in the block. + /// Doesn't count PHI and COPY instructions that are likely to be removed. + unsigned InstrCount; + + /// True when the block contains calls. + bool HasCalls; + + FixedBlockInfo() : InstrCount(~0u), HasCalls(false) {} + + /// Returns true when resource information for this block has been computed. + bool hasResources() const { return InstrCount != ~0u; } + + /// Invalidate resource information. + void invalidate() { InstrCount = ~0u; } + }; + + /// Get the fixed resource information about MBB. Compute it on demand. + const FixedBlockInfo *getResources(const MachineBasicBlock*); + + /// A virtual register or regunit required by a basic block or its trace + /// successors. + struct LiveInReg { + /// The virtual register required, or a register unit. + unsigned Reg; + + /// For virtual registers: Minimum height of the defining instruction. + /// For regunits: Height of the highest user in the trace. + unsigned Height; + + LiveInReg(unsigned Reg, unsigned Height = 0) : Reg(Reg), Height(Height) {} + }; + + /// Per-basic block information that relates to a specific trace through the + /// block. Convergent traces means that only one of these is required per + /// block in a trace ensemble. + struct TraceBlockInfo { + /// Trace predecessor, or NULL for the first block in the trace. + /// Valid when hasValidDepth(). + const MachineBasicBlock *Pred; + + /// Trace successor, or NULL for the last block in the trace. + /// Valid when hasValidHeight(). + const MachineBasicBlock *Succ; + + /// The block number of the head of the trace. (When hasValidDepth()). + unsigned Head; + + /// The block number of the tail of the trace. (When hasValidHeight()). + unsigned Tail; + + /// Accumulated number of instructions in the trace above this block. + /// Does not include instructions in this block. + unsigned InstrDepth; + + /// Accumulated number of instructions in the trace below this block. + /// Includes instructions in this block. + unsigned InstrHeight; + + TraceBlockInfo() : + Pred(0), Succ(0), + InstrDepth(~0u), InstrHeight(~0u), + HasValidInstrDepths(false), HasValidInstrHeights(false) {} + + /// Returns true if the depth resources have been computed from the trace + /// above this block. + bool hasValidDepth() const { return InstrDepth != ~0u; } + + /// Returns true if the height resources have been computed from the trace + /// below this block. + bool hasValidHeight() const { return InstrHeight != ~0u; } + + /// Invalidate depth resources when some block above this one has changed. + void invalidateDepth() { InstrDepth = ~0u; HasValidInstrDepths = false; } + + /// Invalidate height resources when a block below this one has changed. + void invalidateHeight() { InstrHeight = ~0u; HasValidInstrHeights = false; } + + /// Determine if this block belongs to the same trace as TBI and comes + /// before it in the trace. + /// Also returns true when TBI == this. + bool isEarlierInSameTrace(const TraceBlockInfo &TBI) const { + return hasValidDepth() && TBI.hasValidDepth() && + Head == TBI.Head && InstrDepth <= TBI.InstrDepth; + } + + // Data-dependency-related information. Per-instruction depth and height + // are computed from data dependencies in the current trace, using + // itinerary data. + + /// Instruction depths have been computed. This implies hasValidDepth(). + bool HasValidInstrDepths; + + /// Instruction heights have been computed. This implies hasValidHeight(). + bool HasValidInstrHeights; + + /// Critical path length. This is the number of cycles in the longest data + /// dependency chain through the trace. This is only valid when both + /// HasValidInstrDepths and HasValidInstrHeights are set. + unsigned CriticalPath; + + /// Live-in registers. These registers are defined above the current block + /// and used by this block or a block below it. + /// This does not include PHI uses in the current block, but it does + /// include PHI uses in deeper blocks. + SmallVector<LiveInReg, 4> LiveIns; + + void print(raw_ostream&) const; + }; + + /// InstrCycles represents the cycle height and depth of an instruction in a + /// trace. + struct InstrCycles { + /// Earliest issue cycle as determined by data dependencies and instruction + /// latencies from the beginning of the trace. Data dependencies from + /// before the trace are not included. + unsigned Depth; + + /// Minimum number of cycles from this instruction is issued to the of the + /// trace, as determined by data dependencies and instruction latencies. + unsigned Height; + }; + + /// A trace represents a plausible sequence of executed basic blocks that + /// passes through the current basic block one. The Trace class serves as a + /// handle to internal cached data structures. + class Trace { + Ensemble &TE; + TraceBlockInfo &TBI; + + unsigned getBlockNum() const { return &TBI - &TE.BlockInfo[0]; } + + public: + explicit Trace(Ensemble &te, TraceBlockInfo &tbi) : TE(te), TBI(tbi) {} + void print(raw_ostream&) const; + + /// Compute the total number of instructions in the trace. + unsigned getInstrCount() const { + return TBI.InstrDepth + TBI.InstrHeight; + } + + /// Return the resource depth of the top/bottom of the trace center block. + /// This is the number of cycles required to execute all instructions from + /// the trace head to the trace center block. The resource depth only + /// considers execution resources, it ignores data dependencies. + /// When Bottom is set, instructions in the trace center block are included. + unsigned getResourceDepth(bool Bottom) const; + + /// Return the resource length of the trace. This is the number of cycles + /// required to execute the instructions in the trace if they were all + /// independent, exposing the maximum instruction-level parallelism. + /// + /// Any blocks in Extrablocks are included as if they were part of the + /// trace. + unsigned getResourceLength(ArrayRef<const MachineBasicBlock*> Extrablocks = + ArrayRef<const MachineBasicBlock*>()) const; + + /// Return the length of the (data dependency) critical path through the + /// trace. + unsigned getCriticalPath() const { return TBI.CriticalPath; } + + /// Return the depth and height of MI. The depth is only valid for + /// instructions in or above the trace center block. The height is only + /// valid for instructions in or below the trace center block. + InstrCycles getInstrCycles(const MachineInstr *MI) const { + return TE.Cycles.lookup(MI); + } + + /// Return the slack of MI. This is the number of cycles MI can be delayed + /// before the critical path becomes longer. + /// MI must be an instruction in the trace center block. + unsigned getInstrSlack(const MachineInstr *MI) const; + + /// Return the Depth of a PHI instruction in a trace center block successor. + /// The PHI does not have to be part of the trace. + unsigned getPHIDepth(const MachineInstr *PHI) const; + }; + + /// A trace ensemble is a collection of traces selected using the same + /// strategy, for example 'minimum resource height'. There is one trace for + /// every block in the function. + class Ensemble { + SmallVector<TraceBlockInfo, 4> BlockInfo; + DenseMap<const MachineInstr*, InstrCycles> Cycles; + friend class Trace; + + void computeTrace(const MachineBasicBlock*); + void computeDepthResources(const MachineBasicBlock*); + void computeHeightResources(const MachineBasicBlock*); + unsigned computeCrossBlockCriticalPath(const TraceBlockInfo&); + void computeInstrDepths(const MachineBasicBlock*); + void computeInstrHeights(const MachineBasicBlock*); + void addLiveIns(const MachineInstr *DefMI, unsigned DefOp, + ArrayRef<const MachineBasicBlock*> Trace); + + protected: + MachineTraceMetrics &MTM; + virtual const MachineBasicBlock *pickTracePred(const MachineBasicBlock*) =0; + virtual const MachineBasicBlock *pickTraceSucc(const MachineBasicBlock*) =0; + explicit Ensemble(MachineTraceMetrics*); + const MachineLoop *getLoopFor(const MachineBasicBlock*) const; + const TraceBlockInfo *getDepthResources(const MachineBasicBlock*) const; + const TraceBlockInfo *getHeightResources(const MachineBasicBlock*) const; + + public: + virtual ~Ensemble(); + virtual const char *getName() const =0; + void print(raw_ostream&) const; + void invalidate(const MachineBasicBlock *MBB); + void verify() const; + + /// Get the trace that passes through MBB. + /// The trace is computed on demand. + Trace getTrace(const MachineBasicBlock *MBB); + }; + + /// Strategies for selecting traces. + enum Strategy { + /// Select the trace through a block that has the fewest instructions. + TS_MinInstrCount, + + TS_NumStrategies + }; + + /// Get the trace ensemble representing the given trace selection strategy. + /// The returned Ensemble object is owned by the MachineTraceMetrics analysis, + /// and valid for the lifetime of the analysis pass. + Ensemble *getEnsemble(Strategy); + + /// Invalidate cached information about MBB. This must be called *before* MBB + /// is erased, or the CFG is otherwise changed. + /// + /// This invalidates per-block information about resource usage for MBB only, + /// and it invalidates per-trace information for any trace that passes + /// through MBB. + /// + /// Call Ensemble::getTrace() again to update any trace handles. + void invalidate(const MachineBasicBlock *MBB); + +private: + // One entry per basic block, indexed by block number. + SmallVector<FixedBlockInfo, 4> BlockInfo; + + // One ensemble per strategy. + Ensemble* Ensembles[TS_NumStrategies]; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, + const MachineTraceMetrics::Trace &Tr) { + Tr.print(OS); + return OS; +} + +inline raw_ostream &operator<<(raw_ostream &OS, + const MachineTraceMetrics::Ensemble &En) { + En.print(OS); + return OS; +} +} // end namespace llvm + +#endif diff --git a/include/llvm/CodeGen/PBQP/Math.h b/include/llvm/CodeGen/PBQP/Math.h index 4e51913..08f8b98 100644 --- a/include/llvm/CodeGen/PBQP/Math.h +++ b/include/llvm/CodeGen/PBQP/Math.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_PBQP_MATH_H +#ifndef LLVM_CODEGEN_PBQP_MATH_H #define LLVM_CODEGEN_PBQP_MATH_H #include <algorithm> diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 0d02700..5f710e6 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -25,6 +25,7 @@ namespace llvm { class MachineFunctionPass; class PassInfo; class PassManagerBase; + class TargetLoweringBase; class TargetLowering; class TargetRegisterClass; class raw_ostream; @@ -180,6 +181,16 @@ protected: /// instructions in SSA form. virtual void addMachineSSAOptimization(); + /// Add passes that optimize instruction level parallelism for out-of-order + /// targets. These passes are run while the machine code is still in SSA + /// form, so they can use MachineTraceMetrics to control their heuristics. + /// + /// All passes added here should preserve the MachineDominatorTree, + /// MachineLoopInfo, and MachineTraceMetrics analyses. + virtual bool addILPOpts() { + return false; + } + /// addPreRegAlloc - This method may be implemented by targets that want to /// run passes immediately before register allocation. This should return /// true if -print-machineinstrs should print after these passes. @@ -284,7 +295,8 @@ namespace llvm { /// /// This pass implements the target transform info analysis using the target /// independent information available to the LLVM code generator. - ImmutablePass *createBasicTargetTransformInfoPass(const TargetLowering *TLI); + ImmutablePass * + createBasicTargetTransformInfoPass(const TargetLoweringBase *TLI); /// createUnreachableBlockEliminationPass - The LLVM code generator does not /// work well with unreachable basic blocks (what live ranges make sense for a @@ -481,7 +493,7 @@ namespace llvm { /// createStackProtectorPass - This pass adds stack protectors to functions. /// - FunctionPass *createStackProtectorPass(const TargetLowering *tli); + FunctionPass *createStackProtectorPass(const TargetLoweringBase *tli); /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. @@ -495,7 +507,7 @@ namespace llvm { /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. /// - FunctionPass *createSjLjEHPreparePass(const TargetLowering *tli); + FunctionPass *createSjLjEHPreparePass(const TargetLoweringBase *tli); /// LocalStackSlotAllocation - This pass assigns local frame indices to stack /// slots relative to one another and allocates base registers to access them diff --git a/include/llvm/CodeGen/RegAllocRegistry.h b/include/llvm/CodeGen/RegAllocRegistry.h index 100e357..ca49577 100644 --- a/include/llvm/CodeGen/RegAllocRegistry.h +++ b/include/llvm/CodeGen/RegAllocRegistry.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGENREGALLOCREGISTRY_H -#define LLVM_CODEGENREGALLOCREGISTRY_H +#ifndef LLVM_CODEGEN_REGALLOCREGISTRY_H +#define LLVM_CODEGEN_REGALLOCREGISTRY_H #include "llvm/CodeGen/MachinePassRegistry.h" diff --git a/include/llvm/CodeGen/RegisterClassInfo.h b/include/llvm/CodeGen/RegisterClassInfo.h index 12bd1c6..3ad22e6 100644 --- a/include/llvm/CodeGen/RegisterClassInfo.h +++ b/include/llvm/CodeGen/RegisterClassInfo.h @@ -29,9 +29,14 @@ class RegisterClassInfo { unsigned Tag; unsigned NumRegs; bool ProperSubClass; + uint8_t MinCost; + uint16_t LastCostChange; OwningArrayPtr<MCPhysReg> Order; - RCInfo() : Tag(0), NumRegs(0), ProperSubClass(false) {} + RCInfo() + : Tag(0), NumRegs(0), ProperSubClass(false), MinCost(0), + LastCostChange(0) {} + operator ArrayRef<MCPhysReg>() const { return makeArrayRef(Order.get(), NumRegs); } @@ -106,6 +111,21 @@ public: return CalleeSaved[N-1]; return 0; } + + /// Get the minimum register cost in RC's allocation order. + /// This is the smallest value returned by TRI->getCostPerUse(Reg) for all + /// the registers in getOrder(RC). + unsigned getMinCost(const TargetRegisterClass *RC) { + return get(RC).MinCost; + } + + /// Get the position of the last cost change in getOrder(RC). + /// + /// All registers in getOrder(RC).slice(getLastCostChange(RC)) will have the + /// same cost according to TRI->getCostPerUse(). + unsigned getLastCostChange(const TargetRegisterClass *RC) { + return get(RC).LastCostChange; + } }; } // end namespace llvm diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 6604d4c..0119920 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_REGISTER_SCAVENGING_H -#define LLVM_CODEGEN_REGISTER_SCAVENGING_H +#ifndef LLVM_CODEGEN_REGISTERSCAVENGING_H +#define LLVM_CODEGEN_REGISTERSCAVENGING_H #include "llvm/ADT/BitVector.h" #include "llvm/CodeGen/MachineBasicBlock.h" diff --git a/include/llvm/CodeGen/ResourcePriorityQueue.h b/include/llvm/CodeGen/ResourcePriorityQueue.h index 66a6039..f20a9fc 100644 --- a/include/llvm/CodeGen/ResourcePriorityQueue.h +++ b/include/llvm/CodeGen/ResourcePriorityQueue.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef RESOURCE_PRIORITY_QUEUE_H -#define RESOURCE_PRIORITY_QUEUE_H +#ifndef LLVM_CODEGEN_RESOURCEPRIORITYQUEUE_H +#define LLVM_CODEGEN_RESOURCEPRIORITYQUEUE_H #include "llvm/CodeGen/DFAPacketizer.h" #include "llvm/CodeGen/ScheduleDAG.h" diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index 1a9dc1c..41289a4 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -158,6 +158,11 @@ namespace RTLIB { COS_F80, COS_F128, COS_PPCF128, + SINCOS_F32, + SINCOS_F64, + SINCOS_F80, + SINCOS_F128, + SINCOS_PPCF128, POW_F32, POW_F64, POW_F80, diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index aa91b03..d80bdf8 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -17,11 +17,10 @@ #define LLVM_CODEGEN_SCHEDULEDAG_H #include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/Target/TargetLowering.h" namespace llvm { @@ -258,6 +257,8 @@ namespace llvm { /// SUnit - Scheduling unit. This is a node in the scheduling DAG. class SUnit { private: + enum { BoundaryID = ~0u }; + SDNode *Node; // Representative node. MachineInstr *Instr; // Alternatively, a MachineInstr. public: @@ -343,7 +344,7 @@ namespace llvm { /// SUnit - Construct a placeholder SUnit. SUnit() - : Node(0), Instr(0), OrigNode(0), SchedClass(0), NodeNum(~0u), + : Node(0), Instr(0), OrigNode(0), SchedClass(0), NodeNum(BoundaryID), NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), NumRegDefsLeft(0), Latency(0), isVRegCycle(false), isCall(false), isCallOp(false), @@ -354,6 +355,15 @@ namespace llvm { isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} + /// \brief Boundary nodes are placeholders for the boundary of the + /// scheduling region. + /// + /// BoundaryNodes can have DAG edges, including Data edges, but they do not + /// correspond to schedulable entities (e.g. instructions) and do not have a + /// valid ID. Consequently, always check for boundary nodes before accessing + /// an assoicative data structure keyed on node ID. + bool isBoundaryNode() const { return NodeNum == BoundaryID; }; + /// setNode - Assign the representative SDNode for this SUnit. /// This may be used during pre-regalloc scheduling. void setNode(SDNode *N) { @@ -455,6 +465,10 @@ namespace llvm { return NumSuccsLeft == 0; } + /// \brief Order this node's predecessor edges such that the critical path + /// edge occurs first. + void biasCriticalPath(); + void dump(const ScheduleDAG *G) const; void dumpAll(const ScheduleDAG *G) const; void print(raw_ostream &O, const ScheduleDAG *G) const; @@ -563,8 +577,8 @@ namespace llvm { /// viewGraph - Pop up a GraphViz/gv window with the ScheduleDAG rendered /// using 'dot'. /// - void viewGraph(const Twine &Name, const Twine &Title); - void viewGraph(); + virtual void viewGraph(const Twine &Name, const Twine &Title); + virtual void viewGraph(); virtual void dumpNode(const SUnit *SU) const = 0; diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index ffc442e..94abec2 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -12,11 +12,12 @@ // //===----------------------------------------------------------------------===// -#ifndef SCHEDULEDAGINSTRS_H -#define SCHEDULEDAGINSTRS_H +#ifndef LLVM_CODEGEN_SCHEDULEDAGINSTRS_H +#define LLVM_CODEGEN_SCHEDULEDAGINSTRS_H #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SparseSet.h" +#include "llvm/ADT/SparseMultiSet.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/ScheduleDAG.h" @@ -48,56 +49,18 @@ namespace llvm { struct PhysRegSUOper { SUnit *SU; int OpIdx; + unsigned Reg; - PhysRegSUOper(SUnit *su, int op): SU(su), OpIdx(op) {} - }; - - /// Combine a SparseSet with a 1x1 vector to track physical registers. - /// The SparseSet allows iterating over the (few) live registers for quickly - /// comparing against a regmask or clearing the set. - /// - /// Storage for the map is allocated once for the pass. The map can be - /// cleared between scheduling regions without freeing unused entries. - class Reg2SUnitsMap { - SparseSet<unsigned> PhysRegSet; - std::vector<std::vector<PhysRegSUOper> > SUnits; - public: - typedef SparseSet<unsigned>::const_iterator const_iterator; - - // Allow iteration over register numbers (keys) in the map. If needed, we - // can provide an iterator over SUnits (values) as well. - const_iterator reg_begin() const { return PhysRegSet.begin(); } - const_iterator reg_end() const { return PhysRegSet.end(); } - - /// Initialize the map with the number of registers. - /// If the map is already large enough, no allocation occurs. - /// For simplicity we expect the map to be empty(). - void setRegLimit(unsigned Limit); - - /// Returns true if the map is empty. - bool empty() const { return PhysRegSet.empty(); } + PhysRegSUOper(SUnit *su, int op, unsigned R): SU(su), OpIdx(op), Reg(R) {} - /// Clear the map without deallocating storage. - void clear(); - - bool contains(unsigned Reg) const { return PhysRegSet.count(Reg); } - - /// If this register is mapped, return its existing SUnits vector. - /// Otherwise map the register and return an empty SUnits vector. - std::vector<PhysRegSUOper> &operator[](unsigned Reg) { - bool New = PhysRegSet.insert(Reg).second; - assert((!New || SUnits[Reg].empty()) && "stale SUnits vector"); - (void)New; - return SUnits[Reg]; - } - - /// Erase an existing element without freeing memory. - void erase(unsigned Reg) { - PhysRegSet.erase(Reg); - SUnits[Reg].clear(); - } + unsigned getSparseSetIndex() const { return Reg; } }; + /// Use a SparseMultiSet to track physical registers. Storage is only + /// allocated once for the pass. It can be cleared in constant time and reused + /// without any frees. + typedef SparseMultiSet<PhysRegSUOper, llvm::identity<unsigned>, uint16_t> Reg2SUnitsMap; + /// Use SparseSet as a SparseMap by relying on the fact that it never /// compares ValueT's, only unsigned keys. This allows the set to be cleared /// between scheduling regions in constant time as long as ValueT does not diff --git a/include/llvm/CodeGen/ScheduleDFS.h b/include/llvm/CodeGen/ScheduleDFS.h index fbbadd9..73ce99f 100644 --- a/include/llvm/CodeGen/ScheduleDFS.h +++ b/include/llvm/CodeGen/ScheduleDFS.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_SCHEDULEDAGILP_H -#define LLVM_CODEGEN_SCHEDULEDAGILP_H +#ifndef LLVM_CODEGEN_SCHEDULEDFS_H +#define LLVM_CODEGEN_SCHEDULEDFS_H #include "llvm/CodeGen/ScheduleDAG.h" #include "llvm/Support/DataTypes.h" @@ -27,6 +27,9 @@ class SUnit; /// \brief Represent the ILP of the subDAG rooted at a DAG node. /// +/// ILPValues summarize the DAG subtree rooted at each node. ILPValues are +/// valid for all nodes regardless of their subtree membership. +/// /// When computed using bottom-up DFS, this metric assumes that the DAG is a /// forest of trees with roots at the bottom of the schedule branching upward. struct ILPValue { @@ -62,19 +65,30 @@ struct ILPValue { }; /// \brief Compute the values of each DAG node for various metrics during DFS. -/// -/// ILPValues summarize the DAG subtree rooted at each node up to -/// SubtreeLimit. ILPValues are also valid for interior nodes of a subtree, not -/// just the root. class SchedDFSResult { friend class SchedDFSImpl; + static const unsigned InvalidSubtreeID = ~0u; + /// \brief Per-SUnit data computed during DFS for various metrics. + /// + /// A node's SubtreeID is set to itself when it is visited to indicate that it + /// is the root of a subtree. Later it is set to its parent to indicate an + /// interior node. Finally, it is set to a representative subtree ID during + /// finalization. struct NodeData { unsigned InstrCount; unsigned SubtreeID; - NodeData(): InstrCount(0), SubtreeID(0) {} + NodeData(): InstrCount(0), SubtreeID(InvalidSubtreeID) {} + }; + + /// \brief Per-Subtree data computed during DFS. + struct TreeData { + unsigned ParentTreeID; + unsigned SubInstrCount; + + TreeData(): ParentTreeID(InvalidSubtreeID), SubInstrCount(0) {} }; /// \brief Record a connection between subtrees and the connection level. @@ -88,7 +102,10 @@ class SchedDFSResult { bool IsBottomUp; unsigned SubtreeLimit; /// DFS results for each SUnit in this DAG. - std::vector<NodeData> DFSData; + std::vector<NodeData> DFSNodeData; + + // Store per-tree data indexed on tree ID, + SmallVector<TreeData, 16> DFSTreeData; // For each subtree discovered during DFS, record its connections to other // subtrees. @@ -102,41 +119,68 @@ public: SchedDFSResult(bool IsBU, unsigned lim) : IsBottomUp(IsBU), SubtreeLimit(lim) {} + /// \brief Get the node cutoff before subtrees are considered significant. + unsigned getSubtreeLimit() const { return SubtreeLimit; } + + /// \brief Return true if this DFSResult is uninitialized. + /// + /// resize() initializes DFSResult, while compute() populates it. + bool empty() const { return DFSNodeData.empty(); } + /// \brief Clear the results. void clear() { - DFSData.clear(); + DFSNodeData.clear(); + DFSTreeData.clear(); SubtreeConnections.clear(); SubtreeConnectLevels.clear(); } /// \brief Initialize the result data with the size of the DAG. void resize(unsigned NumSUnits) { - DFSData.resize(NumSUnits); + DFSNodeData.resize(NumSUnits); } /// \brief Compute various metrics for the DAG with given roots. - void compute(ArrayRef<SUnit *> Roots); + void compute(ArrayRef<SUnit> SUnits); + + /// \brief Get the number of instructions in the given subtree and its + /// children. + unsigned getNumInstrs(const SUnit *SU) const { + return DFSNodeData[SU->NodeNum].InstrCount; + } + + /// \brief Get the number of instructions in the given subtree not including + /// children. + unsigned getNumSubInstrs(unsigned SubtreeID) const { + return DFSTreeData[SubtreeID].SubInstrCount; + } /// \brief Get the ILP value for a DAG node. /// /// A leaf node has an ILP of 1/1. - ILPValue getILP(const SUnit *SU) { - return ILPValue(DFSData[SU->NodeNum].InstrCount, 1 + SU->getDepth()); + ILPValue getILP(const SUnit *SU) const { + return ILPValue(DFSNodeData[SU->NodeNum].InstrCount, 1 + SU->getDepth()); } /// \brief The number of subtrees detected in this DAG. unsigned getNumSubtrees() const { return SubtreeConnectLevels.size(); } /// \brief Get the ID of the subtree the given DAG node belongs to. - unsigned getSubtreeID(const SUnit *SU) { - return DFSData[SU->NodeNum].SubtreeID; + /// + /// For convenience, if DFSResults have not been computed yet, give everything + /// tree ID 0. + unsigned getSubtreeID(const SUnit *SU) const { + if (empty()) + return 0; + assert(SU->NodeNum < DFSNodeData.size() && "New Node"); + return DFSNodeData[SU->NodeNum].SubtreeID; } /// \brief Get the connection level of a subtree. /// /// For bottom-up trees, the connection level is the latency depth (in cycles) /// of the deepest connection to another subtree. - unsigned getSubtreeLevel(unsigned SubtreeID) { + unsigned getSubtreeLevel(unsigned SubtreeID) const { return SubtreeConnectLevels[SubtreeID]; } diff --git a/include/llvm/CodeGen/SchedulerRegistry.h b/include/llvm/CodeGen/SchedulerRegistry.h index 836b73a..51ac7f2 100644 --- a/include/llvm/CodeGen/SchedulerRegistry.h +++ b/include/llvm/CodeGen/SchedulerRegistry.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGENSCHEDULERREGISTRY_H -#define LLVM_CODEGENSCHEDULERREGISTRY_H +#ifndef LLVM_CODEGEN_SCHEDULERREGISTRY_H +#define LLVM_CODEGEN_SCHEDULERREGISTRY_H #include "llvm/CodeGen/MachinePassRegistry.h" #include "llvm/Target/TargetMachine.h" diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index c5cc8f5..c25497a 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -935,6 +935,20 @@ public: } } + /// Returns an APFloat semantics tag appropriate for the given type. If VT is + /// a vector type, the element semantics are returned. + static const fltSemantics &EVTToAPFloatSemantics(EVT VT) { + switch (VT.getScalarType().getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unknown FP format"); + case MVT::f16: return APFloat::IEEEhalf; + case MVT::f32: return APFloat::IEEEsingle; + case MVT::f64: return APFloat::IEEEdouble; + case MVT::f80: return APFloat::x87DoubleExtended; + case MVT::f128: return APFloat::IEEEquad; + case MVT::ppcf128: return APFloat::PPCDoubleDouble; + } + } + /// AssignOrdering - Assign an order to the SDNode. void AssignOrdering(const SDNode *SD, unsigned Order); @@ -978,10 +992,8 @@ public: SDValue CreateStackTemporary(EVT VT1, EVT VT2); /// FoldConstantArithmetic - - SDValue FoldConstantArithmetic(unsigned Opcode, - EVT VT, - ConstantSDNode *Cst1, - ConstantSDNode *Cst2); + SDValue FoldConstantArithmetic(unsigned Opcode, EVT VT, + SDNode *Cst1, SDNode *Cst2); /// FoldSetCC - Constant fold a setcc to true or false. SDValue FoldSetCC(EVT VT, SDValue N1, diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 16aacc0..af7993f 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_SELECTIONDAG_ISEL_H -#define LLVM_CODEGEN_SELECTIONDAG_ISEL_H +#ifndef LLVM_CODEGEN_SELECTIONDAGISEL_H +#define LLVM_CODEGEN_SELECTIONDAGISEL_H #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/SelectionDAG.h" @@ -281,4 +281,4 @@ private: } -#endif /* LLVM_CODEGEN_SELECTIONDAG_ISEL_H */ +#endif /* LLVM_CODEGEN_SELECTIONDAGISEL_H */ diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index b46d153..78fb233 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -112,7 +112,7 @@ namespace llvm { return lie.getPointer(); } - int getIndex() const { + unsigned getIndex() const { return listEntry()->getIndex() | getSlot(); } @@ -360,6 +360,11 @@ namespace llvm { /// Renumber the index list, providing space for new instructions. void renumberIndexes(); + /// Repair indexes after adding and removing instructions. + void repairIndexesInRange(MachineBasicBlock *MBB, + MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End); + /// Returns the zero index for this analysis. SlotIndex getZeroIndex() { assert(indexList.front().getIndex() == 0 && "First index is not 0?"); @@ -602,29 +607,35 @@ namespace llvm { void insertMBBInMaps(MachineBasicBlock *mbb) { MachineFunction::iterator nextMBB = llvm::next(MachineFunction::iterator(mbb)); - IndexListEntry *startEntry = createEntry(0, 0); - IndexListEntry *stopEntry = createEntry(0, 0); - IndexListEntry *nextEntry = 0; + IndexListEntry *startEntry = 0; + IndexListEntry *endEntry = 0; + IndexList::iterator newItr; if (nextMBB == mbb->getParent()->end()) { - nextEntry = indexList.end(); + startEntry = &indexList.back(); + endEntry = createEntry(0, 0); + newItr = indexList.insertAfter(startEntry, endEntry); } else { - nextEntry = getMBBStartIdx(nextMBB).listEntry(); + startEntry = createEntry(0, 0); + endEntry = getMBBStartIdx(nextMBB).listEntry(); + newItr = indexList.insert(endEntry, startEntry); } - indexList.insert(nextEntry, startEntry); - indexList.insert(nextEntry, stopEntry); - SlotIndex startIdx(startEntry, SlotIndex::Slot_Block); - SlotIndex endIdx(nextEntry, SlotIndex::Slot_Block); + SlotIndex endIdx(endEntry, SlotIndex::Slot_Block); + + MachineFunction::iterator prevMBB(mbb); + assert(prevMBB != mbb->getParent()->end() && + "Can't insert a new block at the beginning of a function."); + --prevMBB; + MBBRanges[prevMBB->getNumber()].second = startIdx; assert(unsigned(mbb->getNumber()) == MBBRanges.size() && "Blocks must be added in order"); MBBRanges.push_back(std::make_pair(startIdx, endIdx)); - idx2MBBMap.push_back(IdxMBBPair(startIdx, mbb)); - renumberIndexes(); + renumberIndexes(newItr); std::sort(idx2MBBMap.begin(), idx2MBBMap.end(), Idx2MBBCompare()); } diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h index 4c4a2a8..3e22252 100644 --- a/include/llvm/CodeGen/TargetSchedule.h +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_TARGETSCHEDMODEL_H -#define LLVM_TARGET_TARGETSCHEDMODEL_H +#ifndef LLVM_CODEGEN_TARGETSCHEDULE_H +#define LLVM_CODEGEN_TARGETSCHEDULE_H #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCInstrItineraries.h" @@ -84,6 +84,9 @@ public: /// \brief Maximum number of micro-ops that may be scheduled per cycle. unsigned getIssueWidth() const { return SchedModel.IssueWidth; } + /// \brief Number of cycles the OOO processor is expected to hide. + unsigned getILPWindow() const { return SchedModel.ILPWindow; } + /// \brief Return the number of issue slots required for this MI. unsigned getNumMicroOps(const MachineInstr *MI, const MCSchedClassDesc *SC = 0) const; diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index f8a6503..ec48b67 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -827,7 +827,7 @@ namespace llvm { /// types are returned as Other, otherwise they are invalid. static EVT getEVT(Type *Ty, bool HandleUnknown = false); - intptr_t getRawBits() { + intptr_t getRawBits() const { if (isSimple()) return V.SimpleTy; else diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index ff765cc..0a26857 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -72,7 +72,7 @@ /* Define to 1 if you have the <CrashReporterClient.h> header file. */ #undef HAVE_CRASHREPORTERCLIENT_H -/* Define if __crashreporter_info__ exists. */ +/* can use __crashreporter_info__ */ #undef HAVE_CRASHREPORTER_INFO /* Define to 1 if you have the <ctype.h> header file. */ @@ -146,6 +146,24 @@ /* 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_LOG} + +/* Define to 1 if you have the `exp2' function. */ +#cmakedefine HAVE_EXP2 ${HAVE_LOG2} + +/* Define to 1 if you have the `exp10' function. */ +#cmakedefine HAVE_EXP10 ${HAVE_LOG10} + /* Define to 1 if you have the `fmodf' function. */ #cmakedefine HAVE_FMODF ${HAVE_FMODF} diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index a4f8af4..2f9e6ff 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -72,7 +72,7 @@ /* Define to 1 if you have the <CrashReporterClient.h> header file. */ #undef HAVE_CRASHREPORTERCLIENT_H -/* Define if __crashreporter_info__ exists. */ +/* can use __crashreporter_info__ */ #undef HAVE_CRASHREPORTER_INFO /* Define to 1 if you have the <ctype.h> header file. */ @@ -122,6 +122,12 @@ /* 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 @@ -225,6 +231,15 @@ 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 diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index fbc3040..eda17ee 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -124,4 +124,7 @@ /* Minor version of the LLVM API */ #cmakedefine LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} +/* Define to 1 if you have the <sanitizer/msan_interface.h> header file. */ +#cmakedefine HAVE_SANITIZER_MSAN_INTERFACE_H ${HAVE_SANITIZER_MSAN_INTERFACE_H} + #endif diff --git a/include/llvm/DIBuilder.h b/include/llvm/DIBuilder.h index 0a59cdd..d598475 100644 --- a/include/llvm/DIBuilder.h +++ b/include/llvm/DIBuilder.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_DIBUILDER_H -#define LLVM_ANALYSIS_DIBUILDER_H +#ifndef LLVM_DIBUILDER_H +#define LLVM_DIBUILDER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" @@ -28,6 +28,9 @@ namespace llvm { class LLVMContext; class MDNode; class StringRef; + class DIBasicType; + class DICompositeType; + class DIDerivedType; class DIDescriptor; class DIFile; class DIEnumerator; @@ -88,9 +91,12 @@ namespace llvm { /// by a tool analyzing generated debugging information. /// @param RV This indicates runtime version for languages like /// Objective-C. + /// @param SplitName The name of the file that we'll split debug info out + /// into. void createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, - StringRef Producer, - bool isOptimized, StringRef Flags, unsigned RV); + StringRef Producer, bool isOptimized, + StringRef Flags, unsigned RV, + StringRef SplitName = StringRef()); /// createFile - Create a file descriptor to hold debugging information /// for a file. @@ -108,32 +114,32 @@ namespace llvm { /// @param SizeInBits Size of the type. /// @param AlignInBits Type alignment. /// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. - DIType createBasicType(StringRef Name, uint64_t SizeInBits, - 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. - DIType 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) - DIType 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 = StringRef()); /// \brief Create debugging information entry for a pointer to member. /// @param PointeeTy Type pointed to by this pointer. /// @param Class Type for which this pointer points to members of. - DIType createMemberPointerType(DIType PointeeTy, DIType Class); + DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class); /// createReferenceType - Create debugging information entry for a c++ /// style reference or rvalue reference type. - DIType createReferenceType(unsigned Tag, DIType RTy); + DIDerivedType createReferenceType(unsigned Tag, DIType RTy); /// createTypedef - Create debugging information entry for a typedef. /// @param Ty Original type. @@ -141,8 +147,8 @@ namespace llvm { /// @param File File where this type is defined. /// @param LineNo Line number. /// @param Context The surrounding context for the typedef. - DIType createTypedef(DIType Ty, StringRef Name, DIFile File, - unsigned LineNo, DIDescriptor Context); + DIDerivedType createTypedef(DIType Ty, StringRef Name, DIFile File, + unsigned LineNo, DIDescriptor Context); /// createFriend - Create debugging information entry for a 'friend'. DIType createFriend(DIType Ty, DIType FriendTy); @@ -154,8 +160,8 @@ namespace llvm { /// @param BaseOffset Base offset. /// @param Flags Flags to describe inheritance attribute, /// e.g. private - DIType createInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset, - unsigned Flags); + DIDerivedType createInheritance(DIType Ty, DIType BaseTy, + uint64_t BaseOffset, unsigned Flags); /// createMemberType - Create debugging information entry for a member. /// @param Scope Member scope. @@ -167,10 +173,23 @@ namespace llvm { /// @param OffsetInBits Member offset. /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. - DIType createMemberType(DIDescriptor Scope, StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, - unsigned Flags, DIType Ty); + DIDerivedType + createMemberType(DIDescriptor 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. + /// @param Scope Member scope. + /// @param Name Member name. + /// @param File File where this member is declared. + /// @param LineNo Line number. + /// @param Ty Type of the static member. + /// @param Flags Flags to encode member attribute, e.g. private. + /// @param Val Const initializer of the member. + DIType createStaticMemberType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNo, DIType Ty, + unsigned Flags, llvm::Value *Val); /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. @@ -263,10 +282,12 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements Struct elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. - DIType createStructType(DIDescriptor Scope, StringRef Name, DIFile File, - unsigned LineNumber, uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Flags, - DIArray Elements, unsigned RunTimeLang = 0); + 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, + MDNode *VTableHolder = 0); /// createUnionType - Create debugging information entry for an union. /// @param Scope Scope in which this union is defined. @@ -278,10 +299,10 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements Union elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. - DIType createUnionType(DIDescriptor Scope, StringRef Name, DIFile File, - unsigned LineNumber, uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Flags, - DIArray Elements, unsigned RunTimeLang = 0); + DICompositeType createUnionType( + DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, + DIArray Elements, unsigned RunTimeLang = 0); /// createTemplateTypeParameter - Create debugging information for template /// type parameter. @@ -316,8 +337,8 @@ namespace llvm { /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DIType createArrayType(uint64_t Size, uint64_t AlignInBits, - DIType Ty, DIArray Subscripts); + DICompositeType createArrayType(uint64_t Size, uint64_t AlignInBits, + DIType Ty, DIArray Subscripts); /// createVectorType - Create debugging information entry for a vector type. /// @param Size Array size. @@ -336,16 +357,16 @@ namespace llvm { /// @param SizeInBits Member size. /// @param AlignInBits Member alignment. /// @param Elements Enumeration elements. - DIType createEnumerationType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - DIArray Elements, DIType ClassType); + DICompositeType createEnumerationType( + DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements, + DIType ClassType); /// createSubroutineType - Create subroutine type. /// @param File File in which this subroutine is defined. /// @param ParameterTypes An array of subroutine parameter types. This /// includes return type at 0th index. - DIType createSubroutineType(DIFile File, DIArray ParameterTypes); + DICompositeType createSubroutineType(DIFile File, DIArray ParameterTypes); /// createArtificialType - Create a new DIType with "artificial" flag set. DIType createArtificialType(DIType Ty); @@ -402,10 +423,12 @@ namespace llvm { /// @param isLocalToUnit Boolean flag indicate whether this variable is /// externally visible or not. /// @param Val llvm::Value of the variable. + /// @param Decl Reference to the corresponding declaration. DIGlobalVariable createStaticVariable(DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, - DIType Ty, bool isLocalToUnit, llvm::Value *Val); + DIType Ty, bool isLocalToUnit, llvm::Value *Val, + MDNode *Decl = NULL); /// createLocalVariable - Create a new descriptor for the specified diff --git a/include/llvm/DebugInfo.h b/include/llvm/DebugInfo.h index cc1c6a0..c557a7a 100644 --- a/include/llvm/DebugInfo.h +++ b/include/llvm/DebugInfo.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_DEBUGINFO_H -#define LLVM_ANALYSIS_DEBUGINFO_H +#ifndef LLVM_DEBUGINFO_H +#define LLVM_DEBUGINFO_H #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" @@ -62,7 +62,8 @@ namespace llvm { FlagPrototyped = 1 << 8, FlagObjcClassComplete = 1 << 9, FlagObjectPointer = 1 << 10, - FlagVector = 1 << 11 + FlagVector = 1 << 11, + FlagStaticMember = 1 << 12 }; protected: const MDNode *DbgNode; @@ -186,12 +187,12 @@ namespace llvm { /// isMain - Each input file is encoded as a separate compile unit in LLVM /// debugging information output. However, many target specific tool chains /// prefer to encode only one compile unit in an object file. In this - /// situation, the LLVM code generator will include debugging information + /// situation, the LLVM code generator will include debugging information /// entities in the compile unit that is marked as main compile unit. The /// code generator accepts maximum one main compile unit per module. If a /// module does not contain any main compile unit then the code generator /// will emit multiple compile units in the output object file. - + // TODO: This can be removed when we remove the legacy debug information. bool isMain() const { return getUnsignedField(6) != 0; } bool isOptimized() const { return getUnsignedField(7) != 0; } StringRef getFlags() const { return getStringField(8); } @@ -202,6 +203,8 @@ namespace llvm { DIArray getSubprograms() const; DIArray getGlobalVariables() const; + StringRef getSplitDebugFilename() const { return getStringField(14); } + /// Verify - Verify that a compile unit is well formed. bool Verify() const; }; @@ -300,6 +303,9 @@ namespace llvm { bool isVector() const { return (getFlags() & FlagVector) != 0; } + bool isStaticMember() const { + return (getFlags() & FlagStaticMember) != 0; + } bool isValid() const { return DbgNode && (isBasicType() || isDerivedType() || isCompositeType()); } @@ -337,7 +343,8 @@ namespace llvm { }; /// DIDerivedType - A simple derived type, like a const qualified type, - /// a typedef, a pointer or reference, etc. + /// 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; @@ -363,6 +370,11 @@ namespace llvm { return getFieldAs<DIType>(10); } + Constant *getConstant() const { + assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); + return getConstantField(10); + } + StringRef getObjCPropertyName() const { if (getVersion() > LLVMDebugVersion11) return StringRef(); @@ -512,6 +524,10 @@ namespace llvm { return getFieldAs<DICompositeType>(13); } + unsigned getFlags() const { + return getUnsignedField(14); + } + unsigned isArtificial() const { if (getVersion() <= llvm::LLVMDebugVersion8) return getUnsignedField(14); @@ -560,6 +576,10 @@ namespace llvm { return getFieldAs<DIFile>(6).getDirectory(); } + DIFile getFile() const { + return getFieldAs<DIFile>(6); + } + /// getScopeLineNumber - Get the beginning of the scope of the /// function, not necessarily where the name of the program /// starts. @@ -620,6 +640,9 @@ namespace llvm { GlobalVariable *getGlobal() const { return getGlobalVariableField(11); } Constant *getConstant() const { return getConstantField(11); } + DIDerivedType getStaticDataMemberDeclaration() const { + return getFieldAs<DIDerivedType>(12); + } /// Verify - Verify that a global variable descriptor is well formed. bool Verify() const; @@ -692,7 +715,7 @@ namespace llvm { return getType().isBlockByrefStruct(); } - /// isInlinedFnArgument - Return trule if this variable provides debugging + /// isInlinedFnArgument - Return true if this variable provides debugging /// information for an inlined function arguments. bool isInlinedFnArgument(const Function *CurFn); @@ -721,7 +744,7 @@ namespace llvm { class DILexicalBlockFile : public DIScope { public: explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { return getScope().getContext(); } + DIScope getContext() const { if (getScope().isSubprogram()) return getScope(); return getScope().getContext(); } unsigned getLineNumber() const { return getScope().getLineNumber(); } unsigned getColumnNumber() const { return getScope().getColumnNumber(); } StringRef getDirectory() const { diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 5ebf4b0..8fcd9e0 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -58,6 +58,8 @@ public: } }; +typedef SmallVector<std::pair<uint64_t, DILineInfo>, 16> DILineInfoTable; + /// DIInliningInfo - a format-neutral container for inlined code description. class DIInliningInfo { SmallVector<DILineInfo, 4> Frames; @@ -92,6 +94,24 @@ public: } }; +/// Selects which debug sections get dumped. +enum DIDumpType { + DIDT_Null, + DIDT_All, + DIDT_Abbrev, + DIDT_AbbrevDwo, + DIDT_Aranges, + DIDT_Frames, + DIDT_Info, + DIDT_InfoDwo, + DIDT_Line, + DIDT_Ranges, + DIDT_Pubnames, + DIDT_Str, + DIDT_StrDwo, + DIDT_StrOffsetsDwo +}; + // 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 @@ -106,10 +126,12 @@ public: /// getDWARFContext - get a context for binary DWARF data. static DIContext *getDWARFContext(object::ObjectFile *); - virtual void dump(raw_ostream &OS) = 0; + virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0; virtual DILineInfo getLineInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address, + uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; }; diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 2d60c36..3fd69e266 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_EXECUTION_ENGINE_H -#define LLVM_EXECUTION_ENGINE_H +#ifndef LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H +#define LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" diff --git a/include/llvm/ExecutionEngine/GenericValue.h b/include/llvm/ExecutionEngine/GenericValue.h index a2fed98..e160e3a 100644 --- a/include/llvm/ExecutionEngine/GenericValue.h +++ b/include/llvm/ExecutionEngine/GenericValue.h @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// -#ifndef GENERIC_VALUE_H -#define GENERIC_VALUE_H +#ifndef LLVM_EXECUTIONENGINE_GENERICVALUE_H +#define LLVM_EXECUTIONENGINE_GENERICVALUE_H #include "llvm/ADT/APInt.h" #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/ExecutionEngine/Interpreter.h b/include/llvm/ExecutionEngine/Interpreter.h index 72d97ef..f49d0c4 100644 --- a/include/llvm/ExecutionEngine/Interpreter.h +++ b/include/llvm/ExecutionEngine/Interpreter.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef EXECUTION_ENGINE_INTERPRETER_H -#define EXECUTION_ENGINE_INTERPRETER_H +#ifndef LLVM_EXECUTIONENGINE_INTERPRETER_H +#define LLVM_EXECUTIONENGINE_INTERPRETER_H #include "llvm/ExecutionEngine/ExecutionEngine.h" #include <cstdlib> diff --git a/include/llvm/ExecutionEngine/JIT.h b/include/llvm/ExecutionEngine/JIT.h index b4cda1d..581d6e6 100644 --- a/include/llvm/ExecutionEngine/JIT.h +++ b/include/llvm/ExecutionEngine/JIT.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_EXECUTION_ENGINE_JIT_H -#define LLVM_EXECUTION_ENGINE_JIT_H +#ifndef LLVM_EXECUTIONENGINE_JIT_H +#define LLVM_EXECUTIONENGINE_JIT_H #include "llvm/ExecutionEngine/ExecutionEngine.h" #include <cstdlib> diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h index 3aa014e..ed66102 100644 --- a/include/llvm/ExecutionEngine/JITEventListener.h +++ b/include/llvm/ExecutionEngine/JITEventListener.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H -#define LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H +#ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H +#define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H #include "llvm/Config/llvm-config.h" #include "llvm/Support/DataTypes.h" @@ -127,4 +127,4 @@ public: } // end namespace llvm. -#endif // defined LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H +#endif // defined LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H diff --git a/include/llvm/ExecutionEngine/JITMemoryManager.h b/include/llvm/ExecutionEngine/JITMemoryManager.h index 29e01aa..714a980 100644 --- a/include/llvm/ExecutionEngine/JITMemoryManager.h +++ b/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H -#define LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H +#ifndef LLVM_EXECUTIONENGINE_JITMEMORYMANAGER_H +#define LLVM_EXECUTIONENGINE_JITMEMORYMANAGER_H #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/ExecutionEngine/MCJIT.h b/include/llvm/ExecutionEngine/MCJIT.h index ac16bdc..66ddb7c 100644 --- a/include/llvm/ExecutionEngine/MCJIT.h +++ b/include/llvm/ExecutionEngine/MCJIT.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_EXECUTION_ENGINE_MCJIT_H -#define LLVM_EXECUTION_ENGINE_MCJIT_H +#ifndef LLVM_EXECUTIONENGINE_MCJIT_H +#define LLVM_EXECUTIONENGINE_MCJIT_H #include "llvm/ExecutionEngine/ExecutionEngine.h" #include <cstdlib> diff --git a/include/llvm/ExecutionEngine/OProfileWrapper.h b/include/llvm/ExecutionEngine/OProfileWrapper.h index 99553a3..05da594 100644 --- a/include/llvm/ExecutionEngine/OProfileWrapper.h +++ b/include/llvm/ExecutionEngine/OProfileWrapper.h @@ -17,8 +17,8 @@ // //===----------------------------------------------------------------------===// -#ifndef OPROFILE_WRAPPER_H -#define OPROFILE_WRAPPER_H +#ifndef LLVM_EXECUTIONENGINE_OPROFILEWRAPPER_H +#define LLVM_EXECUTIONENGINE_OPROFILEWRAPPER_H #include "llvm/Support/DataTypes.h" #include <opagent.h> @@ -121,4 +121,4 @@ private: } // namespace llvm -#endif //OPROFILE_WRAPPER_H +#endif // LLVM_EXECUTIONENGINE_OPROFILEWRAPPER_H diff --git a/include/llvm/ExecutionEngine/ObjectImage.h b/include/llvm/ExecutionEngine/ObjectImage.h index d09e4de..9fddca7 100644 --- a/include/llvm/ExecutionEngine/ObjectImage.h +++ b/include/llvm/ExecutionEngine/ObjectImage.h @@ -50,6 +50,8 @@ public: virtual StringRef getData() const = 0; + virtual object::ObjectFile* getObjectFile() const = 0; + // Subclasses can override these methods to provide JIT debugging support virtual void registerWithDebugger() = 0; virtual void deregisterWithDebugger() = 0; diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index e2905e3..4222d53 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_RUNTIME_DYLD_H -#define LLVM_RUNTIME_DYLD_H +#ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H +#define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/ObjectBuffer.h" diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index ba4ba8d0..ae5004e 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H -#define LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H +#ifndef LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H +#define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H #include "llvm/ADT/SmallVector.h" #include "llvm/ExecutionEngine/JITMemoryManager.h" diff --git a/include/llvm/GVMaterializer.h b/include/llvm/GVMaterializer.h index c143552..1e5c426 100644 --- a/include/llvm/GVMaterializer.h +++ b/include/llvm/GVMaterializer.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef GVMATERIALIZER_H -#define GVMATERIALIZER_H +#ifndef LLVM_GVMATERIALIZER_H +#define LLVM_GVMATERIALIZER_H #include <string> diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index f737e40..ef4e4fc 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// // -// This file declares the Argument class. +// This file declares the Argument class. // //===----------------------------------------------------------------------===// -#ifndef LLVM_ARGUMENT_H -#define LLVM_ARGUMENT_H +#ifndef LLVM_IR_ARGUMENT_H +#define LLVM_IR_ARGUMENT_H #include "llvm/ADT/Twine.h" #include "llvm/ADT/ilist_node.h" @@ -24,11 +24,14 @@ namespace llvm { template<typename ValueSubClass, typename ItemParentClass> class SymbolTableListTraits; -/// A class to represent an incoming formal argument to a Function. An argument -/// is a very simple Value. It is essentially a named (optional) type. When used -/// in the body of a function, it represents the value of the actual argument -/// the function was called with. -/// @brief LLVM Argument representation +/// \brief LLVM Argument representation +/// +/// This class represents an incoming formal argument to a Function. A formal +/// argument, since it is ``formal'', does not contain an actual value but +/// instead represents the type, argument number, and attributes of an argument +/// for a specific function. When used in the body of said function, the +/// argument of course represents the value of the actual argument that the +/// function was called with. class Argument : public Value, public ilist_node<Argument> { virtual void anchor(); Function *Parent; @@ -37,50 +40,52 @@ class Argument : public Value, public ilist_node<Argument> { void setParent(Function *parent); public: - /// Argument ctor - If Function argument is specified, this argument is - /// inserted at the end of the argument list for the function. + /// \brief Constructor. /// + /// If \p F is specified, the argument is inserted at the end of the argument + /// list for \p F. explicit Argument(Type *Ty, const Twine &Name = "", Function *F = 0); inline const Function *getParent() const { return Parent; } inline Function *getParent() { return Parent; } - /// getArgNo - Return the index of this formal argument in its containing - /// function. For example in "void foo(int a, float b)" a is 0 and b is 1. + /// \brief Return the index of this formal argument in its containing + /// function. + /// + /// For example in "void foo(int a, float b)" a is 0 and b is 1. unsigned getArgNo() const; - - /// hasByValAttr - Return true if this argument has the byval attribute on it - /// in its containing function. + + /// \brief Return true if this argument has the byval attribute on it in its + /// containing function. bool hasByValAttr() const; - - /// getParamAlignment - If this is a byval argument, return its alignment. + + /// \brief If this is a byval argument, return its alignment. unsigned getParamAlignment() const; - /// hasNestAttr - Return true if this argument has the nest attribute on - /// it in its containing function. + /// \brief Return true if this argument has the nest attribute on it in its + /// containing function. bool hasNestAttr() const; - /// hasNoAliasAttr - Return true if this argument has the noalias attribute on - /// it in its containing function. + /// \brief Return true if this argument has the noalias attribute on it in its + /// containing function. bool hasNoAliasAttr() const; - - /// hasNoCaptureAttr - Return true if this argument has the nocapture - /// attribute on it in its containing function. + + /// \brief Return true if this argument has the nocapture attribute on it in + /// its containing function. bool hasNoCaptureAttr() const; - - /// hasStructRetAttr - Return true if this argument has the sret attribute on - /// it in its containing function. + + /// \brief Return true if this argument has the sret attribute on it in its + /// containing function. bool hasStructRetAttr() const; - /// addAttr - Add a Attribute to an argument - void addAttr(Attribute); - - /// removeAttr - Remove a Attribute from an argument - void removeAttr(Attribute); + /// \brief Add a Attribute to an argument. + void addAttr(AttributeSet AS); - /// classof - Methods for support type inquiry through isa, cast, and - /// dyn_cast: - /// + /// \brief Remove a Attribute from an argument. + void removeAttr(AttributeSet AS); + + /// \brief Method for support type inquiry through isa, cast, and + /// dyn_cast. static inline bool classof(const Value *V) { return V->getValueID() == ArgumentVal; } diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 95b654c..30c0965 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -13,20 +13,25 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_ATTRIBUTES_H -#define LLVM_ATTRIBUTES_H +#ifndef LLVM_IR_ATTRIBUTES_H +#define LLVM_IR_ATTRIBUTES_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/Support/MathExtras.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include <bitset> #include <cassert> +#include <map> #include <string> namespace llvm { class AttrBuilder; class AttributeImpl; +class AttributeSetImpl; +class AttributeSetNode; class Constant; +template<typename T> struct DenseMapInfo; class LLVMContext; class Type; @@ -39,13 +44,13 @@ class Type; class Attribute { public: /// This enumeration lists the attributes that can be associated with - /// parameters, function results or the function itself. + /// parameters, function results, or the function itself. /// - /// Note: uwtable is about the ABI or the user mandating an entry in the - /// unwind table. The nounwind attribute is about an exception passing by the - /// function. + /// Note: The `uwtable' attribute is about the ABI or the user mandating an + /// entry in the unwind table. The `nounwind' attribute is about an exception + /// passing by the function. /// - /// In a theoretical system that uses tables for profiling and sjlj for + /// In a theoretical system that uses tables for profiling and SjLj for /// exceptions, they would be fully independent. In a normal system that uses /// tables for both, the semantics are: /// @@ -58,7 +63,6 @@ public: enum AttrKind { // IR-Level Attributes None, ///< No attributes have been set - AddressSafety, ///< Address safety checking is on. Alignment, ///< Alignment of parameter (5 bits) ///< stored as log2 of alignment with +1 bias ///< 0 means unaligned (different from align(1)) @@ -70,6 +74,7 @@ public: Naked, ///< Naked function Nest, ///< Nested function static chain NoAlias, ///< Considered to not alias after call + NoBuiltin, ///< Callee isn't recognized as a builtin NoCapture, ///< Function creates no aliases of pointer NoDuplicate, ///< Call cannot be duplicated NoImplicitFloat, ///< Disable implicit floating point insts @@ -90,14 +95,15 @@ public: ///< alignstack=(1)) StackProtect, ///< Stack protection. StackProtectReq, ///< Stack protection required. + StackProtectStrong, ///< Strong Stack protection. StructRet, ///< Hidden pointer to structure to return + SanitizeAddress, ///< AddressSanitizer is on. + SanitizeThread, ///< ThreadSanitizer is on. + SanitizeMemory, ///< MemorySanitizer is on. UWTable, ///< Function must be in a unwind table ZExt, ///< Zero extended before/after call - EndAttrKinds, ///< Sentinal value useful for loops - - AttrKindEmptyKey, ///< Empty key value for DenseMapInfo - AttrKindTombstoneKey ///< Tombstone key value for DenseMapInfo + EndAttrKinds ///< Sentinal value useful for loops }; private: AttributeImpl *pImpl; @@ -105,126 +111,88 @@ private: public: Attribute() : pImpl(0) {} - /// \brief Return a uniquified Attribute object. This takes the uniquified - /// value from the Builder and wraps it in the Attribute class. - static Attribute get(LLVMContext &Context, ArrayRef<AttrKind> Vals); - static Attribute get(LLVMContext &Context, AttrBuilder &B); + //===--------------------------------------------------------------------===// + // Attribute Construction + //===--------------------------------------------------------------------===// - /// \brief Return true if the attribute is present. - bool hasAttribute(AttrKind Val) const; + /// \brief Return a uniquified Attribute object. + static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val = 0); + static Attribute get(LLVMContext &Context, StringRef Kind, + StringRef Val = StringRef()); - /// \brief Return true if attributes exist - bool hasAttributes() const; + /// \brief Return a uniquified Attribute object that has the specific + /// alignment set. + static Attribute getWithAlignment(LLVMContext &Context, uint64_t Align); + static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align); - /// \brief Returns the alignment field of an attribute as a byte alignment - /// value. - unsigned getAlignment() const; + //===--------------------------------------------------------------------===// + // Attribute Accessors + //===--------------------------------------------------------------------===// - /// \brief Set the alignment field of an attribute. - void setAlignment(unsigned Align); + /// \brief Return true if the attribute is an Attribute::AttrKind type. + bool isEnumAttribute() const; - /// \brief Returns the stack alignment field of an attribute as a byte - /// alignment value. - unsigned getStackAlignment() const; + /// \brief Return true if the attribute is an alignment attribute. + bool isAlignAttribute() const; - /// \brief Set the stack alignment field of an attribute. - void setStackAlignment(unsigned Align); + /// \brief Return true if the attribute is a string (target-dependent) + /// attribute. + bool isStringAttribute() const; - /// \brief Equality and non-equality query methods. - bool operator==(AttrKind K) const; - bool operator!=(AttrKind K) const; + /// \brief Return true if the attribute is present. + bool hasAttribute(AttrKind Val) const; - // FIXME: Remove these 'operator' methods. - bool operator==(const Attribute &A) const { - return pImpl == A.pImpl; - } - bool operator!=(const Attribute &A) const { - return pImpl != A.pImpl; - } + /// \brief Return true if the target-dependent attribute is present. + bool hasAttribute(StringRef Val) const; - uint64_t getBitMask() const; + /// \brief Return the attribute's kind as an enum (Attribute::AttrKind). This + /// requires the attribute to be an enum or alignment attribute. + Attribute::AttrKind getKindAsEnum() const; - /// \brief Which attributes cannot be applied to a type. - static Attribute typeIncompatible(Type *Ty); + /// \brief Return the attribute's value as an integer. This requires that the + /// attribute be an alignment attribute. + uint64_t getValueAsInt() const; - /// \brief This returns an integer containing an encoding of all the LLVM - /// attributes found in the given attribute bitset. Any change to this - /// encoding is a breaking change to bitcode compatibility. - static uint64_t encodeLLVMAttributesForBitcode(Attribute Attrs); + /// \brief Return the attribute's kind as a string. This requires the + /// attribute to be a string attribute. + StringRef getKindAsString() const; - /// \brief This returns an attribute bitset containing the LLVM attributes - /// that have been decoded from the given integer. This function must stay in - /// sync with 'encodeLLVMAttributesForBitcode'. - static Attribute decodeLLVMAttributesForBitcode(LLVMContext &C, - uint64_t EncodedAttrs); + /// \brief Return the attribute's value as a string. This requires the + /// attribute to be a string attribute. + StringRef getValueAsString() const; + + /// \brief Returns the alignment field of an attribute as a byte alignment + /// value. + unsigned getAlignment() const; + + /// \brief Returns the stack alignment field of an attribute as a byte + /// alignment value. + unsigned getStackAlignment() 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() const; -}; + std::string getAsString(bool InAttrGrp = false) const; -//===----------------------------------------------------------------------===// -/// \class -/// \brief Provide DenseMapInfo for Attribute::AttrKinds. This is used by -/// AttrBuilder. -template<> struct DenseMapInfo<Attribute::AttrKind> { - static inline Attribute::AttrKind getEmptyKey() { - return Attribute::AttrKindEmptyKey; - } - static inline Attribute::AttrKind getTombstoneKey() { - return Attribute::AttrKindTombstoneKey; - } - static unsigned getHashValue(const Attribute::AttrKind &Val) { - return Val * 37U; - } - static bool isEqual(const Attribute::AttrKind &LHS, - const Attribute::AttrKind &RHS) { - return LHS == RHS; - } -}; + /// \brief Equality and non-equality operators. + bool operator==(Attribute A) const { return pImpl == A.pImpl; } + bool operator!=(Attribute A) const { return pImpl != A.pImpl; } -//===----------------------------------------------------------------------===// -/// \class -/// \brief This is just a pair of values to associate a set of attributes with -/// an index. -struct AttributeWithIndex { - Attribute Attrs; ///< The attributes that are set, or'd together. - Constant *Val; ///< Value attached to attribute, e.g. alignment. - unsigned Index; ///< Index of the parameter for which the attributes apply. - ///< Index 0 is used for return value attributes. - ///< Index ~0U is used for function attributes. - - static AttributeWithIndex get(LLVMContext &C, unsigned Idx, - ArrayRef<Attribute::AttrKind> Attrs) { - return get(Idx, Attribute::get(C, Attrs)); - } - static AttributeWithIndex get(unsigned Idx, Attribute Attrs) { - AttributeWithIndex P; - P.Index = Idx; - P.Attrs = Attrs; - P.Val = 0; - return P; - } - static AttributeWithIndex get(unsigned Idx, Attribute Attrs, Constant *Val) { - AttributeWithIndex P; - P.Index = Idx; - P.Attrs = Attrs; - P.Val = Val; - return P; + /// \brief Less-than operator. Useful for sorting the attributes list. + bool operator<(Attribute A) const; + + void Profile(FoldingSetNodeID &ID) const { + ID.AddPointer(pImpl); } }; //===----------------------------------------------------------------------===// -// AttributeSet Smart Pointer -//===----------------------------------------------------------------------===// - -class AttrBuilder; -class AttributeSetImpl; - -//===----------------------------------------------------------------------===// /// \class -/// \brief This class manages the ref count for the opaque AttributeSetImpl -/// object and provides accessors for it. +/// \brief This class holds the attributes for a function, its return value, and +/// its parameters. You access the attributes for each of them via an index into +/// the AttributeSet object. The function attributes are at index +/// `AttributeSet::FunctionIndex', the return value is at index +/// `AttributeSet::ReturnIndex', and the attributes for the parameters start at +/// index `1'. class AttributeSet { public: enum AttrIndex { @@ -233,105 +201,141 @@ public: }; private: friend class AttrBuilder; + friend class AttributeSetImpl; + template <typename Ty> friend struct DenseMapInfo; - /// \brief The attributes that we are managing. This can be null to represent + /// \brief The attributes that we are managing. This can be null to represent /// the empty attributes list. - AttributeSetImpl *AttrList; + AttributeSetImpl *pImpl; + + /// \brief The attributes for the specified index are returned. + AttributeSetNode *getAttributes(unsigned Idx) const; - /// \brief The attributes for the specified index are returned. Attributes - /// for the result are denoted with Idx = 0. - Attribute getAttributes(unsigned Idx) const; + /// \brief Create an AttributeSet with the specified parameters in it. + static AttributeSet get(LLVMContext &C, + ArrayRef<std::pair<unsigned, Attribute> > Attrs); + static AttributeSet get(LLVMContext &C, + ArrayRef<std::pair<unsigned, + AttributeSetNode*> > Attrs); - explicit AttributeSet(AttributeSetImpl *LI) : AttrList(LI) {} + static AttributeSet getImpl(LLVMContext &C, + ArrayRef<std::pair<unsigned, + AttributeSetNode*> > Attrs); + + + explicit AttributeSet(AttributeSetImpl *LI) : pImpl(LI) {} public: - AttributeSet() : AttrList(0) {} - AttributeSet(const AttributeSet &P) : AttrList(P.AttrList) {} - const AttributeSet &operator=(const AttributeSet &RHS); + AttributeSet() : pImpl(0) {} + AttributeSet(const AttributeSet &P) : pImpl(P.pImpl) {} + const AttributeSet &operator=(const AttributeSet &RHS) { + pImpl = RHS.pImpl; + return *this; + } //===--------------------------------------------------------------------===// - // Attribute List Construction and Mutation + // AttributeSet Construction and Mutation //===--------------------------------------------------------------------===// /// \brief Return an AttributeSet with the specified parameters in it. - static AttributeSet get(LLVMContext &C, ArrayRef<AttributeWithIndex> Attrs); + static AttributeSet get(LLVMContext &C, ArrayRef<AttributeSet> Attrs); + static AttributeSet get(LLVMContext &C, unsigned Idx, + ArrayRef<Attribute::AttrKind> Kind); static AttributeSet get(LLVMContext &C, unsigned Idx, AttrBuilder &B); - /// \brief Add the specified attribute at the specified index to this - /// attribute list. Since attribute lists are immutable, this returns the new - /// list. - AttributeSet addAttr(LLVMContext &C, unsigned Idx, Attribute Attrs) const; + /// \brief Add an attribute to the attribute set at the given index. Since + /// attribute sets are immutable, this returns a new set. + AttributeSet addAttribute(LLVMContext &C, unsigned Idx, + Attribute::AttrKind Attr) const; + + /// \brief Add attributes to the attribute set at the given index. Since + /// attribute sets are immutable, this returns a new set. + AttributeSet addAttributes(LLVMContext &C, unsigned Idx, + 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 + /// attribute list. Since attribute lists are immutable, this returns the new + /// list. + AttributeSet removeAttribute(LLVMContext &C, unsigned Idx, + 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. - AttributeSet removeAttr(LLVMContext &C, unsigned Idx, Attribute Attrs) const; + AttributeSet removeAttributes(LLVMContext &C, unsigned Idx, + AttributeSet Attrs) const; //===--------------------------------------------------------------------===// - // Attribute List Accessors + // AttributeSet Accessors //===--------------------------------------------------------------------===// + /// \brief Retrieve the LLVM context. + LLVMContext &getContext() const; + /// \brief The attributes for the specified index are returned. - Attribute getParamAttributes(unsigned Idx) const { - return getAttributes(Idx); - } + AttributeSet getParamAttributes(unsigned Idx) const; /// \brief The attributes for the ret value are returned. - Attribute getRetAttributes() const { - return getAttributes(ReturnIndex); - } + AttributeSet getRetAttributes() const; /// \brief The function attributes are returned. - Attribute getFnAttributes() const { - return getAttributes(FunctionIndex); - } - - /// \brief Return the alignment for the specified function parameter. - unsigned getParamAlignment(unsigned Idx) const { - return getAttributes(Idx).getAlignment(); - } + AttributeSet getFnAttributes() const; /// \brief Return true if the attribute exists at the given index. bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const; + /// \brief Return true if the attribute exists at the given index. + bool hasAttribute(unsigned Index, StringRef Kind) const; + /// \brief Return true if attribute exists at the given index. bool hasAttributes(unsigned Index) const; + /// \brief Return true if the specified attribute is set for at least one + /// parameter or for the return value. + bool hasAttrSomewhere(Attribute::AttrKind Attr) const; + + /// \brief Return the attribute object that exists at the given index. + Attribute getAttribute(unsigned Index, Attribute::AttrKind Kind) const; + + /// \brief Return the attribute object that exists at the given index. + Attribute getAttribute(unsigned Index, StringRef Kind) const; + + /// \brief Return the alignment for the specified function parameter. + unsigned getParamAlignment(unsigned Idx) const; + /// \brief Get the stack alignment. unsigned getStackAlignment(unsigned Index) const; /// \brief Return the attributes at the index as a string. - std::string getAsString(unsigned Index) const; + std::string getAsString(unsigned Index, bool InAttrGrp = false) const; - uint64_t getBitMask(unsigned Index) const; + typedef ArrayRef<Attribute>::iterator iterator; - /// \brief Return true if the specified attribute is set for at least one - /// parameter or for the return value. - bool hasAttrSomewhere(Attribute::AttrKind Attr) const; + iterator begin(unsigned Idx) const; + iterator end(unsigned Idx) const; /// operator==/!= - Provide equality predicates. bool operator==(const AttributeSet &RHS) const { - return AttrList == RHS.AttrList; + return pImpl == RHS.pImpl; } bool operator!=(const AttributeSet &RHS) const { - return AttrList != RHS.AttrList; + return pImpl != RHS.pImpl; } //===--------------------------------------------------------------------===// - // Attribute List Introspection + // AttributeSet Introspection //===--------------------------------------------------------------------===// + // FIXME: Remove this. + uint64_t Raw(unsigned Index) const; + /// \brief Return a raw pointer that uniquely identifies this attribute list. void *getRawPointer() const { - return AttrList; + return pImpl; } - // Attributes are stored as a dense set of slots, where there is one slot for - // each argument that has an attribute. This allows walking over the dense - // set instead of walking the sparse list of attributes. - /// \brief Return true if there are no attributes. bool isEmpty() const { - return AttrList == 0; + return getNumSlots() == 0; } /// \brief Return the number of slots used in this attribute list. This is @@ -339,56 +343,101 @@ public: /// function itself). unsigned getNumSlots() const; - /// \brief Return the AttributeWithIndex at the specified slot. This holds a - /// index number plus a set of attributes. - const AttributeWithIndex &getSlot(unsigned Slot) const; + /// \brief Return the index for the given slot. + uint64_t getSlotIndex(unsigned Slot) const; + + /// \brief Return the attributes at the given slot. + AttributeSet getSlotAttributes(unsigned Slot) const; void dump() const; }; //===----------------------------------------------------------------------===// /// \class +/// \brief Provide DenseMapInfo for AttributeSet. +template<> struct DenseMapInfo<AttributeSet> { + static inline AttributeSet getEmptyKey() { + uintptr_t Val = static_cast<uintptr_t>(-1); + Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable; + return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val)); + } + static inline AttributeSet getTombstoneKey() { + uintptr_t Val = static_cast<uintptr_t>(-2); + Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable; + return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val)); + } + static unsigned getHashValue(AttributeSet AS) { + return (unsigned((uintptr_t)AS.pImpl) >> 4) ^ + (unsigned((uintptr_t)AS.pImpl) >> 9); + } + static bool isEqual(AttributeSet LHS, AttributeSet RHS) { return LHS == RHS; } +}; + +//===----------------------------------------------------------------------===// +/// \class /// \brief This class is used in conjunction with the Attribute::get method to /// create an Attribute object. The object itself is uniquified. The Builder's /// value, however, is not. So this can be used as a quick way to test for /// equality, presence of attributes, etc. class AttrBuilder { - DenseSet<Attribute::AttrKind> Attrs; + std::bitset<Attribute::EndAttrKinds> Attrs; + std::map<std::string, std::string> TargetDepAttrs; uint64_t Alignment; uint64_t StackAlignment; public: - AttrBuilder() : Alignment(0), StackAlignment(0) {} - explicit AttrBuilder(uint64_t B) : Alignment(0), StackAlignment(0) { - addRawValue(B); + AttrBuilder() : Attrs(0), Alignment(0), StackAlignment(0) {} + explicit AttrBuilder(uint64_t Val) + : Attrs(0), Alignment(0), StackAlignment(0) { + addRawValue(Val); } - AttrBuilder(const Attribute &A) : Alignment(0), StackAlignment(0) { - addAttributes(A); + AttrBuilder(const Attribute &A) : Attrs(0), Alignment(0), StackAlignment(0) { + addAttribute(A); } AttrBuilder(AttributeSet AS, unsigned Idx); + AttrBuilder(const AttrBuilder &B) + : Attrs(B.Attrs), + TargetDepAttrs(B.TargetDepAttrs.begin(), B.TargetDepAttrs.end()), + Alignment(B.Alignment), StackAlignment(B.StackAlignment) {} void clear(); /// \brief Add an attribute to the builder. AttrBuilder &addAttribute(Attribute::AttrKind Val); + /// \brief Add the Attribute object to the builder. + AttrBuilder &addAttribute(Attribute A); + + /// \brief Add the target-dependent attribute to the builder. + AttrBuilder &addAttribute(StringRef A, StringRef V = StringRef()); + /// \brief Remove an attribute from the builder. AttrBuilder &removeAttribute(Attribute::AttrKind Val); - /// \brief Add the attributes from A to the builder. - AttrBuilder &addAttributes(const Attribute &A); + /// \brief Remove the attributes from the builder. + AttrBuilder &removeAttributes(AttributeSet A, uint64_t Index); - /// \brief Remove the attributes from A from the builder. - AttrBuilder &removeAttributes(const Attribute &A); + /// \brief Remove the target-dependent attribute to the builder. + AttrBuilder &removeAttribute(StringRef A); + + /// \brief Add the attributes from the builder. + AttrBuilder &merge(const AttrBuilder &B); /// \brief Return true if the builder has the specified attribute. - bool contains(Attribute::AttrKind A) const; + bool contains(Attribute::AttrKind A) const { + assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!"); + return Attrs[A]; + } + + /// \brief Return true if the builder has the specified target-dependent + /// attribute. + bool contains(StringRef A) const; /// \brief Return true if the builder has IR-level attributes. bool hasAttributes() const; /// \brief Return true if the builder has any attribute that's in the /// specified attribute. - bool hasAttributes(const Attribute &A) const; + bool hasAttributes(AttributeSet A, uint64_t Index) const; /// \brief Return true if the builder has an alignment attribute. bool hasAlignmentAttr() const; @@ -407,52 +456,44 @@ public: /// the form used internally in Attribute. AttrBuilder &addStackAlignmentAttr(unsigned Align); - typedef DenseSet<Attribute::AttrKind>::iterator iterator; - typedef DenseSet<Attribute::AttrKind>::const_iterator const_iterator; + /// \brief Return true if the builder contains no target-independent + /// attributes. + bool empty() const { return Attrs.none(); } - iterator begin() { return Attrs.begin(); } - iterator end() { return Attrs.end(); } + // Iterators for target-dependent attributes. + typedef std::pair<std::string, std::string> td_type; + typedef std::map<std::string, std::string>::iterator td_iterator; + typedef std::map<std::string, std::string>::const_iterator td_const_iterator; - const_iterator begin() const { return Attrs.begin(); } - const_iterator end() const { return Attrs.end(); } + td_iterator td_begin() { return TargetDepAttrs.begin(); } + td_iterator td_end() { return TargetDepAttrs.end(); } - /// \brief Add the raw value to the internal representation. - /// - /// N.B. This should be used ONLY for decoding LLVM bitcode! - AttrBuilder &addRawValue(uint64_t Val); + td_const_iterator td_begin() const { return TargetDepAttrs.begin(); } + td_const_iterator td_end() const { return TargetDepAttrs.end(); } - /// \brief Remove attributes that are used on functions only. - void removeFunctionOnlyAttrs() { - removeAttribute(Attribute::NoReturn) - .removeAttribute(Attribute::NoUnwind) - .removeAttribute(Attribute::ReadNone) - .removeAttribute(Attribute::ReadOnly) - .removeAttribute(Attribute::NoInline) - .removeAttribute(Attribute::AlwaysInline) - .removeAttribute(Attribute::OptimizeForSize) - .removeAttribute(Attribute::StackProtect) - .removeAttribute(Attribute::StackProtectReq) - .removeAttribute(Attribute::NoRedZone) - .removeAttribute(Attribute::NoImplicitFloat) - .removeAttribute(Attribute::Naked) - .removeAttribute(Attribute::InlineHint) - .removeAttribute(Attribute::StackAlignment) - .removeAttribute(Attribute::UWTable) - .removeAttribute(Attribute::NonLazyBind) - .removeAttribute(Attribute::ReturnsTwice) - .removeAttribute(Attribute::AddressSafety) - .removeAttribute(Attribute::MinSize) - .removeAttribute(Attribute::NoDuplicate); - } + bool td_empty() const { return TargetDepAttrs.empty(); } - uint64_t getBitMask() const; + /// \brief Remove attributes that are used on functions only. + void removeFunctionOnlyAttrs(); bool operator==(const AttrBuilder &B); bool operator!=(const AttrBuilder &B) { return !(*this == B); } + + // FIXME: Remove this in 4.0. + + /// \brief Add the raw value to the internal representation. + AttrBuilder &addRawValue(uint64_t Val); }; +namespace AttributeFuncs { + +/// \brief Which attributes cannot be applied to a type. +AttributeSet typeIncompatible(Type *Ty, uint64_t Index); + +} // end AttributeFuncs namespace + } // end llvm namespace #endif diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index 15f4aa7..ea5695a 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_BASICBLOCK_H -#define LLVM_BASICBLOCK_H +#ifndef LLVM_IR_BASICBLOCK_H +#define LLVM_IR_BASICBLOCK_H #include "llvm/ADT/Twine.h" #include "llvm/ADT/ilist.h" @@ -29,19 +29,19 @@ class BlockAddress; template<> struct ilist_traits<Instruction> : public SymbolTableListTraits<Instruction, BasicBlock> { - // createSentinel is used to get hold of a node that marks the end of - // the list... - // The sentinel is relative to this instance, so we use a non-static - // method. + + /// \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 the corresponding - // traits, placing a data member in this class will augment i(p)list. - // But since the NodeTy is expected to publicly derive from - // ilist_node<NodeTy>, there is a legal viable downcast from it - // to NodeTy. We use this trick to superpose 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. + // 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*) {} @@ -53,6 +53,8 @@ private: mutable ilist_half_node<Instruction> Sentinel; }; +/// \brief LLVM Basic Block Representation +/// /// This represents a single basic block in LLVM. A basic block is simply a /// container of instructions that execute sequentially. Basic blocks are Values /// because they are referenced by instructions such as branches and switch @@ -66,7 +68,6 @@ private: /// occur because it may be useful in the intermediate stage of constructing or /// modifying a program. However, the verifier will ensure that basic blocks /// are "well formed". -/// @brief LLVM Basic Block Representation class BasicBlock : public Value, // Basic blocks are data objects also public ilist_node<BasicBlock> { friend class BlockAddress; @@ -82,14 +83,15 @@ private: BasicBlock(const BasicBlock &) LLVM_DELETED_FUNCTION; void operator=(const BasicBlock &) LLVM_DELETED_FUNCTION; - /// BasicBlock ctor - If the function parameter is specified, the basic block - /// is automatically inserted at either the end of the function (if - /// InsertBefore is null), or before the specified basic block. + /// \brief Constructor. /// + /// If the function parameter is specified, the basic block is automatically + /// inserted at either the end of the function (if InsertBefore is null), or + /// before the specified basic block. explicit BasicBlock(LLVMContext &C, const Twine &Name = "", Function *Parent = 0, BasicBlock *InsertBefore = 0); public: - /// getContext - Get the context in which this basic block lives. + /// \brief Get the context in which this basic block lives. LLVMContext &getContext() const; /// Instruction iterators... @@ -98,88 +100,87 @@ public: typedef InstListType::reverse_iterator reverse_iterator; typedef InstListType::const_reverse_iterator const_reverse_iterator; - /// Create - Creates a new BasicBlock. If the Parent parameter is specified, - /// the basic block is automatically inserted at either the end of the - /// function (if InsertBefore is 0), or before the specified basic block. + /// \brief Creates a new BasicBlock. + /// + /// If the Parent parameter is specified, the basic block is automatically + /// inserted at either the end of the function (if InsertBefore is 0), or + /// before the specified basic block. static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "", Function *Parent = 0,BasicBlock *InsertBefore = 0) { return new BasicBlock(Context, Name, Parent, InsertBefore); } ~BasicBlock(); - /// getParent - Return the enclosing method, or null if none - /// + /// \brief Return the enclosing method, or null if none. const Function *getParent() const { return Parent; } Function *getParent() { return Parent; } - /// getTerminator() - If this is a well formed basic block, then this returns - /// a pointer to the terminator instruction. If it is not, then you get a - /// null pointer back. - /// + /// \brief Returns the terminator instruction if the block is well formed or + /// null if the block is not well formed. TerminatorInst *getTerminator(); const TerminatorInst *getTerminator() const; - /// Returns a pointer to the first instructon in this block that is not a - /// PHINode instruction. When adding instruction to the beginning of the - /// basic block, they should be added before the returned value, not before - /// the first instruction, which might be PHI. - /// Returns 0 is there's no non-PHI instruction. + /// \brief Returns a pointer to the first instruction in this block that is + /// not a PHINode instruction. + /// + /// When adding instructions to the beginning of the basic block, they should + /// be added before the returned value, not before the first instruction, + /// which might be PHI. Returns 0 is there's no non-PHI instruction. Instruction* getFirstNonPHI(); const Instruction* getFirstNonPHI() const { return const_cast<BasicBlock*>(this)->getFirstNonPHI(); } - // Same as above, but also skip debug intrinsics. + /// \brief Returns a pointer to the first instruction in this block that is not + /// a PHINode or a debug intrinsic. Instruction* getFirstNonPHIOrDbg(); const Instruction* getFirstNonPHIOrDbg() const { return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbg(); } - // Same as above, but also skip lifetime intrinsics. + /// \brief Returns a pointer to the first instruction in this block that is not + /// a PHINode, a debug intrinsic, or a lifetime intrinsic. Instruction* getFirstNonPHIOrDbgOrLifetime(); const Instruction* getFirstNonPHIOrDbgOrLifetime() const { return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbgOrLifetime(); } - /// getFirstInsertionPt - Returns an iterator to the first instruction in this - /// block that is suitable for inserting a non-PHI instruction. In particular, - /// it skips all PHIs and LandingPad instructions. + /// \brief Returns an iterator to the first instruction in this block that is + /// suitable for inserting a non-PHI instruction. + /// + /// In particular, it skips all PHIs and LandingPad instructions. iterator getFirstInsertionPt(); const_iterator getFirstInsertionPt() const { return const_cast<BasicBlock*>(this)->getFirstInsertionPt(); } - /// removeFromParent - This method unlinks 'this' from the containing - /// function, but does not delete it. - /// + /// \brief Unlink 'this' from the containing function, but do not delete it. void removeFromParent(); - /// eraseFromParent - This method unlinks 'this' from the containing function - /// and deletes it. - /// + /// \brief Unlink 'this' from the containing function and delete it. void eraseFromParent(); - /// moveBefore - Unlink this basic block from its current function and - /// insert it into the function that MovePos lives in, right before MovePos. + /// \brief Unlink this basic block from its current function and insert it + /// into the function that \p MovePos lives in, right before \p MovePos. void moveBefore(BasicBlock *MovePos); - /// moveAfter - Unlink this basic block from its current function and - /// insert it into the function that MovePos lives in, right after MovePos. + /// \brief Unlink this basic block from its current function and insert it + /// right after \p MovePos in the function \p MovePos lives in. void moveAfter(BasicBlock *MovePos); - /// getSinglePredecessor - If this basic block has a single predecessor block, - /// return the block, otherwise return a null pointer. + /// \brief Return this block if it has a single predecessor block. Otherwise + /// return a null pointer. BasicBlock *getSinglePredecessor(); const BasicBlock *getSinglePredecessor() const { return const_cast<BasicBlock*>(this)->getSinglePredecessor(); } - /// getUniquePredecessor - If this basic block has a unique predecessor block, - /// return the block, otherwise return a null pointer. + /// \brief Return this block if it has a unique predecessor block. Otherwise return a null pointer. + /// /// Note that unique predecessor doesn't mean single edge, there can be - /// multiple edges from the unique predecessor to this block (for example - /// a switch statement with multiple cases having the same destination). + /// multiple edges from the unique predecessor to this block (for example a + /// switch statement with multiple cases having the same destination). BasicBlock *getUniquePredecessor(); const BasicBlock *getUniquePredecessor() const { return const_cast<BasicBlock*>(this)->getUniquePredecessor(); @@ -205,49 +206,52 @@ public: inline const Instruction &back() const { return InstList.back(); } inline Instruction &back() { return InstList.back(); } - /// getInstList() - Return the underlying instruction list container. You - /// need to access it directly if you want to modify it currently. + /// \brief Return the underlying instruction list container. /// + /// Currently you need to access the underlying instruction list container + /// directly if you want to modify it. const InstListType &getInstList() const { return InstList; } InstListType &getInstList() { return InstList; } - /// getSublistAccess() - returns pointer to member of instruction list + /// \brief Returns a pointer to a member of the instruction list. static iplist<Instruction> BasicBlock::*getSublistAccess(Instruction*) { return &BasicBlock::InstList; } - /// getValueSymbolTable() - returns pointer to symbol table (if any) + /// \brief Returns a pointer to the symbol table if one exists. ValueSymbolTable *getValueSymbolTable(); - /// Methods for support type inquiry through isa, cast, and dyn_cast: + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast. static inline bool classof(const Value *V) { return V->getValueID() == Value::BasicBlockVal; } - /// dropAllReferences() - This function causes all the subinstructions to "let - /// go" of all references that they are maintaining. This allows one to - /// 'delete' a whole class at a time, even though there may be circular - /// references... first all references are dropped, and all use counts go to - /// zero. Then everything is delete'd for real. Note that no operations are - /// valid on an object that has "dropped all references", except operator - /// delete. + /// \brief Cause all subinstructions to "let go" of all the references that + /// said subinstructions are maintaining. /// + /// This allows one to 'delete' a whole class at a time, even though there may + /// be circular references... first all references are dropped, and all use + /// counts go to zero. Then everything is delete'd for real. Note that no + /// operations are valid on an object that has "dropped all references", + /// except operator delete. void dropAllReferences(); - /// removePredecessor - This method is used to notify a BasicBlock that the - /// specified Predecessor of the block is no longer able to reach it. This is - /// actually not used to update the Predecessor list, but is actually used to - /// update the PHI nodes that reside in the block. Note that this should be - /// called while the predecessor still refers to this block. + /// \brief Notify the BasicBlock that the predecessor \p Pred is no longer + /// able to reach it. /// + /// This is actually not used to update the Predecessor list, but is actually + /// used to update the PHI nodes that reside in the block. Note that this + /// should be called while the predecessor still refers to this block. void removePredecessor(BasicBlock *Pred, bool DontDeleteUselessPHIs = false); - /// splitBasicBlock - This splits a basic block into two at the specified - /// instruction. Note that all instructions BEFORE the specified iterator - /// stay as part of the original basic block, an unconditional branch is added - /// to the original BB, and the rest of the instructions in the BB are moved - /// to the new BB, including the old terminator. The newly formed BasicBlock - /// is returned. This function invalidates the specified iterator. + /// \brief Split the basic block into two basic blocks at the specified + /// instruction. + /// + /// Note that all instructions BEFORE the specified iterator stay as part of + /// the original basic block, an unconditional branch is added to the original + /// BB, and the rest of the instructions in the BB are moved to the new BB, + /// including the old terminator. The newly formed BasicBlock is returned. + /// This function invalidates the specified iterator. /// /// Note that this only works on well formed basic blocks (must have a /// terminator), and 'I' must not be the end of instruction list (which would @@ -256,37 +260,39 @@ public: /// /// Also note that this doesn't preserve any passes. To split blocks while /// keeping loop information consistent, use the SplitBlock utility function. - /// BasicBlock *splitBasicBlock(iterator I, const Twine &BBName = ""); - /// hasAddressTaken - returns true if there are any uses of this basic block - /// other than direct branches, switches, etc. to it. + /// \brief Returns true if there are any uses of this basic block other than + /// direct branches, switches, etc. to it. bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; } - /// replaceSuccessorsPhiUsesWith - Update all phi nodes in all our successors - /// to refer to basic block New instead of to us. + /// \brief Update all phi nodes in this basic block's successors to refer to + /// basic block \p New instead of to it. void replaceSuccessorsPhiUsesWith(BasicBlock *New); - /// isLandingPad - Return true if this basic block is a landing pad. I.e., - /// it's the destination of the 'unwind' edge of an invoke instruction. + /// \brief Return true if this basic block is a landing pad. + /// + /// Being a ``landing pad'' means that the basic block is the destination of + /// the 'unwind' edge of an invoke instruction. bool isLandingPad() const; - /// getLandingPadInst() - Return the landingpad instruction associated with - /// the landing pad. + /// \brief Return the landingpad instruction associated with the landing pad. LandingPadInst *getLandingPadInst(); const LandingPadInst *getLandingPadInst() const; private: - /// AdjustBlockAddressRefCount - BasicBlock stores the number of BlockAddress - /// objects using it. This is almost always 0, sometimes one, possibly but - /// almost never 2, and inconceivably 3 or more. + /// \brief Increment the internal refcount of the number of BlockAddresses + /// referencing this BasicBlock by \p Amt. + /// + /// This is almost always 0, sometimes one possibly, but almost never 2, and + /// inconceivably 3 or more. void AdjustBlockAddressRefCount(int Amt) { setValueSubclassData(getSubclassDataFromValue()+Amt); assert((int)(signed char)getSubclassDataFromValue() >= 0 && "Refcount wrap-around"); } - // Shadow Value::setValueSubclassData with a private forwarding method so that - // any future subclasses cannot accidentally use it. + /// \brief Shadow Value::setValueSubclassData with a private forwarding method + /// so that any future subclasses cannot accidentally use it. void setValueSubclassData(unsigned short D) { Value::setValueSubclassData(D); } diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h index 699cea3..6f3ab20 100644 --- a/include/llvm/IR/CallingConv.h +++ b/include/llvm/IR/CallingConv.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CALLINGCONV_H -#define LLVM_CALLINGCONV_H +#ifndef LLVM_IR_CALLINGCONV_H +#define LLVM_IR_CALLINGCONV_H namespace llvm { diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index 36a4538..26bad1d 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CONSTANT_H -#define LLVM_CONSTANT_H +#ifndef LLVM_IR_CONSTANT_H +#define LLVM_IR_CONSTANT_H #include "llvm/IR/User.h" @@ -61,6 +61,9 @@ public: /// by getZeroValueForNegation. bool isNegativeZeroValue() const; + /// Return true if the value is negative zero or null value. + bool isZeroValue() const; + /// canTrap - Return true if evaluation of this constant could trap. This is /// true for things like constant expressions that could divide by zero. bool canTrap() const; diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 0f49fe5..ad258f9 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -18,8 +18,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CONSTANTS_H -#define LLVM_CONSTANTS_H +#ifndef LLVM_IR_CONSTANTS_H +#define LLVM_IR_CONSTANTS_H #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index cc02017..bfdb057 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -17,8 +17,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DATALAYOUT_H -#define LLVM_DATALAYOUT_H +#ifndef LLVM_IR_DATALAYOUT_H +#define LLVM_IR_DATALAYOUT_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" @@ -100,7 +100,7 @@ private: SmallVector<unsigned char, 8> LegalIntWidths; ///< Legal Integers. - /// Alignments- Where the primitive type alignment data is stored. + /// Alignments - Where the primitive type alignment data is stored. /// /// @sa init(). /// @note Could support multiple size pointer alignments, e.g., 32-bit @@ -324,19 +324,16 @@ public: /// an integer type of the specified bitwidth. unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const; - /// getCallFrameTypeAlignment - Return the minimum ABI-required alignment /// for the specified type when it is part of a call frame. unsigned getCallFrameTypeAlignment(Type *Ty) const; - /// getPrefTypeAlignment - Return the preferred stack/global alignment for /// the specified type. This is always at least as good as the ABI alignment. unsigned getPrefTypeAlignment(Type *Ty) const; /// getPreferredTypeAlignmentShift - Return the preferred alignment for the /// specified type, returned as log2 of the value (a shift amount). - /// unsigned getPreferredTypeAlignmentShift(Type *Ty) const; /// getIntPtrType - Return an integer type with size at least as big as that @@ -350,7 +347,6 @@ public: /// getIndexedOffset - return the offset from the beginning of the type for /// the specified indices. This is used to implement getelementptr. - /// uint64_t getIndexedOffset(Type *Ty, ArrayRef<Value *> Indices) const; /// getStructLayout - Return a StructLayout object, indicating the alignment diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index 5a941520..3bf7885 100644 --- a/include/llvm/IR/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DERIVED_TYPES_H -#define LLVM_DERIVED_TYPES_H +#ifndef LLVM_IR_DERIVEDTYPES_H +#define LLVM_IR_DERIVEDTYPES_H #include "llvm/IR/Type.h" #include "llvm/Support/Compiler.h" diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 1762b2c..568b55c 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_FUNCTION_H -#define LLVM_FUNCTION_H +#ifndef LLVM_IR_FUNCTION_H +#define LLVM_IR_FUNCTION_H #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" @@ -85,7 +85,7 @@ private: BasicBlockListType BasicBlocks; ///< The basic blocks mutable ArgumentListType ArgumentList; ///< The formal arguments ValueSymbolTable *SymTab; ///< Symbol table of args/instructions - AttributeSet AttributeList; ///< Parameter attributes + AttributeSet AttributeSets; ///< Parameter attributes // HasLazyArguments is stored in Value::SubclassData. /*bool HasLazyArguments;*/ @@ -162,24 +162,25 @@ public: /// getAttributes - Return the attribute list for this Function. /// - const AttributeSet &getAttributes() const { return AttributeList; } + AttributeSet getAttributes() const { return AttributeSets; } /// setAttributes - Set the attribute list for this Function. /// - void setAttributes(const AttributeSet &attrs) { AttributeList = attrs; } + void setAttributes(AttributeSet attrs) { AttributeSets = attrs; } /// addFnAttr - Add function attributes to this function. /// void addFnAttr(Attribute::AttrKind N) { - // Function Attribute are stored at ~0 index - addAttribute(AttributeSet::FunctionIndex, Attribute::get(getContext(), N)); + setAttributes(AttributeSets.addAttribute(getContext(), + AttributeSet::FunctionIndex, N)); } - /// removeFnAttr - Remove function attributes from this function. - /// - void removeFnAttr(Attribute N) { - // Function Attribute are stored at ~0 index - removeAttribute(~0U, N); + /// \brief Return true if the function has the attribute. + bool hasFnAttribute(Attribute::AttrKind Kind) const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); + } + bool hasFnAttribute(StringRef Kind) const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); } /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm @@ -189,20 +190,23 @@ public: void setGC(const char *Str); void clearGC(); - /// addAttribute - adds the attribute to the list of attributes. - void addAttribute(unsigned i, Attribute attr); + /// @brief adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attribute::AttrKind attr); + + /// @brief adds the attributes to the list of attributes. + void addAttributes(unsigned i, AttributeSet attrs); - /// removeAttribute - removes the attribute from the list of attributes. - void removeAttribute(unsigned i, Attribute attr); + /// @brief removes the attributes from the list of attributes. + void removeAttributes(unsigned i, AttributeSet attr); /// @brief Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned i) const { - return AttributeList.getParamAlignment(i); + return AttributeSets.getParamAlignment(i); } /// @brief Determine if the function does not access memory. bool doesNotAccessMemory() const { - return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); } void setDoesNotAccessMemory() { @@ -212,7 +216,7 @@ public: /// @brief Determine if the function does not access or only reads memory. bool onlyReadsMemory() const { return doesNotAccessMemory() || - AttributeList.hasAttribute(AttributeSet::FunctionIndex, + AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly); } void setOnlyReadsMemory() { @@ -221,7 +225,7 @@ public: /// @brief Determine if the function cannot return. bool doesNotReturn() const { - return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Attribute::NoReturn); } void setDoesNotReturn() { @@ -230,7 +234,7 @@ public: /// @brief Determine if the function cannot unwind. bool doesNotThrow() const { - return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); } void setDoesNotThrow() { @@ -239,7 +243,7 @@ public: /// @brief Determine if the call cannot be duplicated. bool cannotDuplicate() const { - return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Attribute::NoDuplicate); } void setCannotDuplicate() { @@ -249,7 +253,7 @@ public: /// @brief True if the ABI mandates (or the user requested) that this /// function be in a unwind table. bool hasUWTable() const { - return AttributeList.hasAttribute(AttributeSet::FunctionIndex, + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Attribute::UWTable); } void setHasUWTable() { @@ -264,25 +268,25 @@ public: /// @brief Determine if the function returns a structure through first /// pointer argument. bool hasStructRetAttr() const { - return AttributeList.hasAttribute(1, Attribute::StructRet); + return AttributeSets.hasAttribute(1, Attribute::StructRet); } /// @brief Determine if the parameter does not alias other parameters. /// @param n The parameter to check. 1 is the first parameter, 0 is the return bool doesNotAlias(unsigned n) const { - return AttributeList.hasAttribute(n, Attribute::NoAlias); + return AttributeSets.hasAttribute(n, Attribute::NoAlias); } void setDoesNotAlias(unsigned n) { - addAttribute(n, Attribute::get(getContext(), Attribute::NoAlias)); + addAttribute(n, Attribute::NoAlias); } /// @brief Determine if the parameter can be captured. /// @param n The parameter to check. 1 is the first parameter, 0 is the return bool doesNotCapture(unsigned n) const { - return AttributeList.hasAttribute(n, Attribute::NoCapture); + return AttributeSets.hasAttribute(n, Attribute::NoCapture); } void setDoesNotCapture(unsigned n) { - addAttribute(n, Attribute::get(getContext(), Attribute::NoCapture)); + addAttribute(n, Attribute::NoCapture); } /// copyAttributesFrom - copy all additional attributes (those not needed to diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index 03c1648..883814a 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_GLOBAL_ALIAS_H -#define LLVM_GLOBAL_ALIAS_H +#ifndef LLVM_IR_GLOBALALIAS_H +#define LLVM_IR_GLOBALALIAS_H #include "llvm/ADT/Twine.h" #include "llvm/ADT/ilist_node.h" diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 246e00b..f398bc1 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_GLOBALVALUE_H -#define LLVM_GLOBALVALUE_H +#ifndef LLVM_IR_GLOBALVALUE_H +#define LLVM_IR_GLOBALVALUE_H #include "llvm/IR/Constant.h" diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 5c42d76..bfed507 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -17,8 +17,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_GLOBAL_VARIABLE_H -#define LLVM_GLOBAL_VARIABLE_H +#ifndef LLVM_IR_GLOBALVARIABLE_H +#define LLVM_IR_GLOBALVARIABLE_H #include "llvm/ADT/Twine.h" #include "llvm/ADT/ilist_node.h" @@ -40,9 +40,14 @@ class GlobalVariable : public GlobalValue, public ilist_node<GlobalVariable> { void setParent(Module *parent); - bool isConstantGlobal : 1; // Is this a global constant? - unsigned threadLocalMode : 3; // Is this symbol "Thread Local", - // if so, what is the desired model? + bool isConstantGlobal : 1; // Is this a global constant? + unsigned threadLocalMode : 3; // Is this symbol "Thread Local", + // if so, what is the desired + // model? + bool isExternallyInitializedConstant : 1; // Is this a global whose value + // can change from its initial + // value before global + // initializers are run? public: // allocate space for exactly one operand @@ -62,15 +67,15 @@ public: /// automatically inserted into the end of the specified modules global list. GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage, Constant *Initializer = 0, const Twine &Name = "", - ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0); + ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, + bool isExternallyInitialized = false); /// GlobalVariable ctor - This creates a global and inserts it before the /// specified other global. GlobalVariable(Module &M, Type *Ty, bool isConstant, LinkageTypes Linkage, Constant *Initializer, - const Twine &Name = "", - GlobalVariable *InsertBefore = 0, - ThreadLocalMode = NotThreadLocal, - unsigned AddressSpace = 0); + const Twine &Name = "", GlobalVariable *InsertBefore = 0, + ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, + bool isExternallyInitialized = false); ~GlobalVariable() { NumOperands = 1; // FIXME: needed by operator delete @@ -105,7 +110,10 @@ public: return hasInitializer() && // The initializer of a global variable with weak linkage may change at // link time. - !mayBeOverridden(); + !mayBeOverridden() && + // The initializer of a global variable with the externally_initialized + // marker may change at runtime before C++ initializers are evaluated. + !isExternallyInitialized(); } /// hasUniqueInitializer - Whether the global variable has an initializer, and @@ -118,7 +126,11 @@ public: // instead. It is wrong to modify the initializer of a global variable // with *_odr linkage because then different instances of the global may // have different initializers, breaking the One Definition Rule. - !isWeakForLinker(); + !isWeakForLinker() && + // It is not safe to modify initializers of global variables with the + // external_initializer marker since the value may be changed at runtime + // before C++ initializers are evaluated. + !isExternallyInitialized(); } /// getInitializer - Return the initializer for this global variable. It is @@ -155,6 +167,13 @@ public: return static_cast<ThreadLocalMode>(threadLocalMode); } + bool isExternallyInitialized() const { + return isExternallyInitializedConstant; + } + void setExternallyInitialized(bool Val) { + isExternallyInitializedConstant = Val; + } + /// copyAttributesFrom - copy all additional attributes (those not needed to /// create a GlobalVariable) from the GlobalVariable Src to this one. void copyAttributesFrom(const GlobalValue *Src); diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 27f990e..1c71d0a 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_IRBUILDER_H -#define LLVM_IRBUILDER_H +#ifndef LLVM_IR_IRBUILDER_H +#define LLVM_IR_IRBUILDER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" @@ -28,10 +28,11 @@ namespace llvm { class MDNode; -/// IRBuilderDefaultInserter - This provides the default implementation of the -/// IRBuilder 'InsertHelper' method that is called whenever an instruction is -/// created by IRBuilder and needs to be inserted. By default, this inserts the -/// instruction at the insertion point. +/// \brief This provides the default implementation of the IRBuilder +/// 'InsertHelper' method that is called whenever an instruction is created by +/// IRBuilder and needs to be inserted. +/// +/// By default, this inserts the instruction at the insertion point. template <bool preserveNames = true> class IRBuilderDefaultInserter { protected: @@ -43,7 +44,7 @@ protected: } }; -/// IRBuilderBase - Common base class shared among various IRBuilders. +/// \brief Common base class shared among various IRBuilders. class IRBuilderBase { DebugLoc CurDbgLocation; protected: @@ -61,8 +62,8 @@ public: // Builder configuration methods //===--------------------------------------------------------------------===// - /// ClearInsertionPoint - Clear the insertion point: created instructions will - /// not be inserted into a block. + /// \brief Clear the insertion point: created instructions will not be + /// inserted into a block. void ClearInsertionPoint() { BB = 0; } @@ -71,30 +72,30 @@ public: BasicBlock::iterator GetInsertPoint() const { return InsertPt; } LLVMContext &getContext() const { return Context; } - /// SetInsertPoint - This specifies that created instructions should be - /// appended to the end of the specified block. + /// \brief This specifies that created instructions should be appended to the + /// end of the specified block. void SetInsertPoint(BasicBlock *TheBB) { BB = TheBB; InsertPt = BB->end(); } - /// SetInsertPoint - This specifies that created instructions should be - /// inserted before the specified instruction. + /// \brief This specifies that created instructions should be inserted before + /// the specified instruction. void SetInsertPoint(Instruction *I) { BB = I->getParent(); InsertPt = I; SetCurrentDebugLocation(I->getDebugLoc()); } - /// SetInsertPoint - This specifies that created instructions should be - /// inserted at the specified point. + /// \brief This specifies that created instructions should be inserted at the + /// specified point. void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { BB = TheBB; InsertPt = IP; } - /// SetInsertPoint(Use) - Find the nearest point that dominates this use, and - /// specify that created instructions should be inserted at this point. + /// \brief Find the nearest point that dominates this use, and specify that + /// created instructions should be inserted at this point. void SetInsertPoint(Use &U) { Instruction *UseInst = cast<Instruction>(U.getUser()); if (PHINode *Phi = dyn_cast<PHINode>(UseInst)) { @@ -106,25 +107,23 @@ public: SetInsertPoint(UseInst); } - /// SetCurrentDebugLocation - Set location information used by debugging - /// information. + /// \brief Set location information used by debugging information. void SetCurrentDebugLocation(const DebugLoc &L) { CurDbgLocation = L; } - /// getCurrentDebugLocation - Get location information used by debugging - /// information. + /// \brief Get location information used by debugging information. DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; } - /// SetInstDebugLocation - If this builder has a current debug location, set - /// it on the specified instruction. + /// \brief If this builder has a current debug location, set it on the + /// specified instruction. void SetInstDebugLocation(Instruction *I) const { if (!CurDbgLocation.isUnknown()) I->setDebugLoc(CurDbgLocation); } - /// getCurrentFunctionReturnType - Get the return type of the current function - /// that we're emitting into. + /// \brief Get the return type of the current function that we're emitting + /// into. Type *getCurrentFunctionReturnType() const; /// InsertPoint - A saved insertion point. @@ -133,35 +132,33 @@ public: BasicBlock::iterator Point; public: - /// Creates a new insertion point which doesn't point to anything. + /// \brief Creates a new insertion point which doesn't point to anything. InsertPoint() : Block(0) {} - /// Creates a new insertion point at the given location. + /// \brief Creates a new insertion point at the given location. InsertPoint(BasicBlock *InsertBlock, BasicBlock::iterator InsertPoint) : Block(InsertBlock), Point(InsertPoint) {} - /// isSet - Returns true if this insert point is set. + /// \brief Returns true if this insert point is set. bool isSet() const { return (Block != 0); } llvm::BasicBlock *getBlock() const { return Block; } llvm::BasicBlock::iterator getPoint() const { return Point; } }; - /// saveIP - Returns the current insert point. + /// \brief Returns the current insert point. InsertPoint saveIP() const { return InsertPoint(GetInsertBlock(), GetInsertPoint()); } - /// saveAndClearIP - Returns the current insert point, clearing it - /// in the process. + /// \brief Returns the current insert point, clearing it in the process. InsertPoint saveAndClearIP() { InsertPoint IP(GetInsertBlock(), GetInsertPoint()); ClearInsertionPoint(); return IP; } - /// restoreIP - Sets the current insert point to a previously-saved - /// location. + /// \brief Sets the current insert point to a previously-saved location. void restoreIP(InsertPoint IP) { if (IP.isSet()) SetInsertPoint(IP.getBlock(), IP.getPoint()); @@ -173,49 +170,50 @@ public: // Miscellaneous creation methods. //===--------------------------------------------------------------------===// - /// CreateGlobalString - Make a new global variable with an initializer that - /// has array of i8 type filled in with the nul 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. + /// \brief Make a new global variable with initializer type i8* + /// + /// Make a new global variable with an initializer that has array of i8 type + /// 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 = ""); - /// getInt1 - Get a constant value representing either true or false. + /// \brief Get a constant value representing either true or false. ConstantInt *getInt1(bool V) { return ConstantInt::get(getInt1Ty(), V); } - /// getTrue - Get the constant value for i1 true. + /// \brief Get the constant value for i1 true. ConstantInt *getTrue() { return ConstantInt::getTrue(Context); } - /// getFalse - Get the constant value for i1 false. + /// \brief Get the constant value for i1 false. ConstantInt *getFalse() { return ConstantInt::getFalse(Context); } - /// getInt8 - Get a constant 8-bit value. + /// \brief Get a constant 8-bit value. ConstantInt *getInt8(uint8_t C) { return ConstantInt::get(getInt8Ty(), C); } - /// getInt16 - Get a constant 16-bit value. + /// \brief Get a constant 16-bit value. ConstantInt *getInt16(uint16_t C) { return ConstantInt::get(getInt16Ty(), C); } - /// getInt32 - Get a constant 32-bit value. + /// \brief Get a constant 32-bit value. ConstantInt *getInt32(uint32_t C) { return ConstantInt::get(getInt32Ty(), C); } - /// getInt64 - Get a constant 64-bit value. + /// \brief Get a constant 64-bit value. ConstantInt *getInt64(uint64_t C) { return ConstantInt::get(getInt64Ty(), C); } - /// getInt - Get a constant integer value. + /// \brief Get a constant integer value. ConstantInt *getInt(const APInt &AI) { return ConstantInt::get(Context, AI); } @@ -224,50 +222,52 @@ public: // Type creation methods //===--------------------------------------------------------------------===// - /// getInt1Ty - Fetch the type representing a single bit + /// \brief Fetch the type representing a single bit IntegerType *getInt1Ty() { return Type::getInt1Ty(Context); } - /// getInt8Ty - Fetch the type representing an 8-bit integer. + /// \brief Fetch the type representing an 8-bit integer. IntegerType *getInt8Ty() { return Type::getInt8Ty(Context); } - /// getInt16Ty - Fetch the type representing a 16-bit integer. + /// \brief Fetch the type representing a 16-bit integer. IntegerType *getInt16Ty() { return Type::getInt16Ty(Context); } - /// getInt32Ty - Fetch the type representing a 32-bit integer. + /// \brief Fetch the type representing a 32-bit integer. IntegerType *getInt32Ty() { return Type::getInt32Ty(Context); } - /// getInt64Ty - Fetch the type representing a 64-bit integer. + /// \brief Fetch the type representing a 64-bit integer. IntegerType *getInt64Ty() { return Type::getInt64Ty(Context); } - /// getFloatTy - Fetch the type representing a 32-bit floating point value. + /// \brief Fetch the type representing a 32-bit floating point value. Type *getFloatTy() { return Type::getFloatTy(Context); } - /// getDoubleTy - Fetch the type representing a 64-bit floating point value. + /// \brief Fetch the type representing a 64-bit floating point value. Type *getDoubleTy() { return Type::getDoubleTy(Context); } - /// getVoidTy - Fetch the type representing void. + /// \brief Fetch the type representing void. Type *getVoidTy() { return Type::getVoidTy(Context); } + /// \brief Fetch the type representing a pointer to an 8-bit integer value. PointerType *getInt8PtrTy(unsigned AddrSpace = 0) { return Type::getInt8PtrTy(Context, AddrSpace); } + /// \brief Fetch the type representing a pointer to an integer value. IntegerType* getIntPtrTy(DataLayout *DL, unsigned AddrSpace = 0) { return DL->getIntPtrType(Context, AddrSpace); } @@ -276,9 +276,11 @@ public: // Intrinsic creation methods //===--------------------------------------------------------------------===// - /// CreateMemSet - Create and insert a memset to the specified pointer and the - /// specified value. If the pointer isn't an i8*, it will be converted. If a - /// TBAA tag is specified, it will be added to the instruction. + /// \brief Create and insert a memset to the specified pointer and the + /// specified value. + /// + /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = 0) { return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); @@ -287,7 +289,8 @@ public: CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = 0); - /// CreateMemCpy - Create and insert a memcpy between the specified pointers. + /// \brief Create and insert a memcpy between the specified pointers. + /// /// If the pointers aren't i8*, they will be converted. If a TBAA tag is /// specified, it will be added to the instruction. CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, @@ -301,9 +304,11 @@ public: bool isVolatile = false, MDNode *TBAATag = 0, MDNode *TBAAStructTag = 0); - /// CreateMemMove - Create and insert a memmove between the specified - /// pointers. If the pointers aren't i8*, they will be converted. If a TBAA - /// tag is specified, it will be added to the instruction. + /// \brief Create and insert a memmove between the specified + /// pointers. + /// + /// If the pointers aren't i8*, they will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = 0) { return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); @@ -312,21 +317,23 @@ public: CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = 0); - /// CreateLifetimeStart - Create a lifetime.start intrinsic. If the pointer - /// isn't i8* it will be converted. + /// \brief Create a lifetime.start intrinsic. + /// + /// If the pointer isn't i8* it will be converted. CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = 0); - /// CreateLifetimeEnd - Create a lifetime.end intrinsic. If the pointer isn't - /// i8* it will be converted. + /// \brief Create a lifetime.end intrinsic. + /// + /// If the pointer isn't i8* it will be converted. CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = 0); private: Value *getCastedInt8PtrValue(Value *Ptr); }; -/// IRBuilder - This provides a uniform API for creating instructions and -/// inserting them into a basic block: either at the end of a BasicBlock, or -/// at a specific iterator location in a block. +/// \brief This provides a uniform API for creating instructions and inserting +/// them into a basic block: either at the end of a BasicBlock, or at a specific +/// iterator location in a block. /// /// Note that the builder does not expose the full generality of LLVM /// instructions. For access to extra instruction properties, use the mutators @@ -396,38 +403,37 @@ public: SetInsertPoint(TheBB, IP); } - /// getFolder - Get the constant folder being used. + /// \brief Get the constant folder being used. const T &getFolder() { return Folder; } - /// getDefaultFPMathTag - Get the floating point math metadata being used. + /// \brief Get the floating point math metadata being used. MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } - /// Get the flags to be applied to created floating point ops + /// \brief Get the flags to be applied to created floating point ops FastMathFlags getFastMathFlags() const { return FMF; } - /// Clear the fast-math flags. + /// \brief Clear the fast-math flags. void clearFastMathFlags() { FMF.clear(); } - /// SetDefaultFPMathTag - Set the floating point math metadata to be used. + /// \brief SetDefaultFPMathTag - Set the floating point math metadata to be used. void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } - /// Set the fast-math flags to be used with generated fp-math operators + /// \brief Set the fast-math flags to be used with generated fp-math operators void SetFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } - /// isNamePreserving - Return true if this builder is configured to actually - /// add the requested names to IR created through it. + /// \brief Return true if this builder is configured to actually add the + /// requested names to IR created through it. bool isNamePreserving() const { return preserveNames; } - /// Insert - Insert and return the specified instruction. + /// \brief Insert and return the specified instruction. template<typename InstTy> InstTy *Insert(InstTy *I, const Twine &Name = "") const { this->InsertHelper(I, Name, BB, InsertPt); - if (!getCurrentDebugLocation().isUnknown()) - this->SetInstDebugLocation(I); + this->SetInstDebugLocation(I); return I; } - /// Insert - No-op overload to handle constants. + /// \brief No-op overload to handle constants. Constant *Insert(Constant *C, const Twine& = "") const { return C; } @@ -447,25 +453,23 @@ private: } public: - /// CreateRetVoid - Create a 'ret void' instruction. + /// \brief Create a 'ret void' instruction. ReturnInst *CreateRetVoid() { return Insert(ReturnInst::Create(Context)); } - /// @verbatim - /// CreateRet - Create a 'ret <val>' instruction. - /// @endverbatim + /// \brief Create a 'ret <val>' instruction. ReturnInst *CreateRet(Value *V) { return Insert(ReturnInst::Create(Context, V)); } - /// CreateAggregateRet - Create a sequence of N insertvalue instructions, + /// \brief Create a sequence of N insertvalue instructions, /// with one Value from the retVals array each, that build a aggregate /// return value one value at a time, and a ret instruction to return - /// the resulting aggregate value. This is a convenience function for - /// code that uses aggregate return values as a vehicle for having - /// multiple return values. + /// the resulting aggregate value. /// + /// This is a convenience function for code that uses aggregate return values + /// as a vehicle for having multiple return values. ReturnInst *CreateAggregateRet(Value *const *retVals, unsigned N) { Value *V = UndefValue::get(getCurrentFunctionReturnType()); for (unsigned i = 0; i != N; ++i) @@ -473,12 +477,12 @@ public: return Insert(ReturnInst::Create(Context, V)); } - /// CreateBr - Create an unconditional 'br label X' instruction. + /// \brief Create an unconditional 'br label X' instruction. BranchInst *CreateBr(BasicBlock *Dest) { return Insert(BranchInst::Create(Dest)); } - /// CreateCondBr - Create a conditional 'br Cond, TrueDest, FalseDest' + /// \brief Create a conditional 'br Cond, TrueDest, FalseDest' /// instruction. BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights = 0) { @@ -486,18 +490,18 @@ public: BranchWeights)); } - /// CreateSwitch - Create a switch instruction with the specified value, - /// default dest, and with a hint for the number of cases that will be added - /// (for efficient allocation). + /// \brief Create a switch instruction with the specified value, default dest, + /// and with a hint for the number of cases that will be added (for efficient + /// allocation). SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10, MDNode *BranchWeights = 0) { return Insert(addBranchWeights(SwitchInst::Create(V, Dest, NumCases), BranchWeights)); } - /// CreateIndirectBr - Create an indirect branch instruction with the - /// specified address operand, with an optional hint for the number of - /// destinations that will be added (for efficient allocation). + /// \brief Create an indirect branch instruction with the specified address + /// operand, with an optional hint for the number of destinations that will be + /// added (for efficient allocation). IndirectBrInst *CreateIndirectBr(Value *Addr, unsigned NumDests = 10) { return Insert(IndirectBrInst::Create(Addr, NumDests)); } @@ -522,7 +526,7 @@ public: return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args), Name); } - /// CreateInvoke - Create an invoke instruction. + /// \brief Create an invoke instruction. InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef<Value *> Args, const Twine &Name = "") { @@ -825,7 +829,7 @@ public: const Twine &Name = "") { return Insert(new AllocaInst(Ty, ArraySize), Name); } - // Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of + // \brief Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of // converting the string to 'bool' for the isVolatile parameter. LoadInst *CreateLoad(Value *Ptr, const char *Name) { return Insert(new LoadInst(Ptr), Name); @@ -839,8 +843,9 @@ public: StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { return Insert(new StoreInst(Val, Ptr, isVolatile)); } - // Provided to resolve 'CreateAlignedLoad(Ptr, Align, "...")' correctly, - // instead of converting the string to 'bool' for the isVolatile parameter. + // \brief Provided to resolve 'CreateAlignedLoad(Ptr, Align, "...")' + // correctly, instead of converting the string to 'bool' for the isVolatile + // parameter. LoadInst *CreateAlignedLoad(Value *Ptr, unsigned Align, const char *Name) { LoadInst *LI = CreateLoad(Ptr, Name); LI->setAlignment(Align); @@ -1002,8 +1007,8 @@ public: return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); } - /// CreateGlobalStringPtr - Same as CreateGlobalString, but return a pointer - /// with "i8*" type instead of a pointer to array of i8. + /// \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); Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); @@ -1024,27 +1029,31 @@ public: Value *CreateSExt(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::SExt, V, DestTy, Name); } - /// CreateZExtOrTrunc - Create a ZExt or Trunc from the integer value V to - /// DestTy. Return the value untouched if the type of V is already DestTy. - Value *CreateZExtOrTrunc(Value *V, IntegerType *DestTy, + /// \brief Create a ZExt or Trunc from the integer value V to DestTy. Return + /// the value untouched if the type of V is already DestTy. + Value *CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name = "") { - assert(isa<IntegerType>(V->getType()) && "Can only zero extend integers!"); - IntegerType *IntTy = cast<IntegerType>(V->getType()); - if (IntTy->getBitWidth() < DestTy->getBitWidth()) + assert(V->getType()->isIntOrIntVectorTy() && + DestTy->isIntOrIntVectorTy() && + "Can only zero extend/truncate integers!"); + Type *VTy = V->getType(); + if (VTy->getScalarSizeInBits() < DestTy->getScalarSizeInBits()) return CreateZExt(V, DestTy, Name); - if (IntTy->getBitWidth() > DestTy->getBitWidth()) + if (VTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits()) return CreateTrunc(V, DestTy, Name); return V; } - /// CreateSExtOrTrunc - Create a SExt or Trunc from the integer value V to - /// DestTy. Return the value untouched if the type of V is already DestTy. - Value *CreateSExtOrTrunc(Value *V, IntegerType *DestTy, + /// \brief Create a SExt or Trunc from the integer value V to DestTy. Return + /// the value untouched if the type of V is already DestTy. + Value *CreateSExtOrTrunc(Value *V, Type *DestTy, const Twine &Name = "") { - assert(isa<IntegerType>(V->getType()) && "Can only sign extend integers!"); - IntegerType *IntTy = cast<IntegerType>(V->getType()); - if (IntTy->getBitWidth() < DestTy->getBitWidth()) + assert(V->getType()->isIntOrIntVectorTy() && + DestTy->isIntOrIntVectorTy() && + "Can only sign extend/truncate integers!"); + Type *VTy = V->getType(); + if (VTy->getScalarSizeInBits() < DestTy->getScalarSizeInBits()) return CreateSExt(V, DestTy, Name); - if (IntTy->getBitWidth() > DestTy->getBitWidth()) + if (VTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits()) return CreateTrunc(V, DestTy, Name); return V; } @@ -1128,8 +1137,9 @@ public: return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); } private: - // Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a compile time - // error, instead of converting the string to bool for the isSigned parameter. + // \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; public: Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") { @@ -1339,23 +1349,24 @@ public: // Utility creation methods //===--------------------------------------------------------------------===// - /// CreateIsNull - Return an i1 value testing if \p Arg is null. + /// \brief Return an i1 value testing if \p Arg is null. Value *CreateIsNull(Value *Arg, const Twine &Name = "") { return CreateICmpEQ(Arg, Constant::getNullValue(Arg->getType()), Name); } - /// CreateIsNotNull - Return an i1 value testing if \p Arg is not null. + /// \brief Return an i1 value testing if \p Arg is not null. Value *CreateIsNotNull(Value *Arg, const Twine &Name = "") { return CreateICmpNE(Arg, Constant::getNullValue(Arg->getType()), Name); } - /// CreatePtrDiff - Return the i64 difference between two pointer values, - /// dividing out the size of the pointed-to objects. This is intended to - /// implement C-style pointer subtraction. As such, the pointers must be - /// appropriately aligned for their element types and pointing into the - /// same object. + /// \brief Return the i64 difference between two pointer values, dividing out + /// the size of the pointed-to objects. + /// + /// This is intended to implement C-style pointer subtraction. As such, the + /// pointers must be appropriately aligned for their element types and + /// pointing into the same object. Value *CreatePtrDiff(Value *LHS, Value *RHS, const Twine &Name = "") { assert(LHS->getType() == RHS->getType() && "Pointer subtraction operand types must match!"); @@ -1368,8 +1379,8 @@ public: Name); } - /// CreateVectorSplat - Return a vector value that contains \arg V broadcasted - /// to \p NumElts elements. + /// \brief Return a vector value that contains \arg V broadcasted to \p + /// NumElts elements. Value *CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name = "") { assert(NumElts > 0 && "Cannot splat to an empty vector!"); diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index 15d4fb0..33e4ab8 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_INLINEASM_H -#define LLVM_INLINEASM_H +#ifndef LLVM_IR_INLINEASM_H +#define LLVM_IR_INLINEASM_H #include "llvm/ADT/StringRef.h" #include "llvm/IR/Value.h" diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 66bf8dd..3e6903c 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_INSTRUCTION_TYPES_H -#define LLVM_INSTRUCTION_TYPES_H +#ifndef LLVM_IR_INSTRTYPES_H +#define LLVM_IR_INSTRTYPES_H #include "llvm/ADT/Twine.h" #include "llvm/IR/DerivedTypes.h" @@ -309,7 +309,7 @@ public: /// NEG, FNeg, or NOT instruction. /// static bool isNeg(const Value *V); - static bool isFNeg(const Value *V); + static bool isFNeg(const Value *V, bool IgnoreZeroSign=false); static bool isNot(const Value *V); /// getNegArgument, getNotArgument - Helper functions to extract the diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index 2731bfb..5721d8f 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_INSTRUCTION_H -#define LLVM_INSTRUCTION_H +#ifndef LLVM_IR_INSTRUCTION_H +#define LLVM_IR_INSTRUCTION_H #include "llvm/ADT/ilist_node.h" #include "llvm/IR/User.h" @@ -309,6 +309,12 @@ public: /// bool mayThrow() const; + /// mayReturn - Return true if this is a function that may return. + /// this is true for all normal instructions. The only exception + /// is functions that are marked with the 'noreturn' attribute. + /// + bool mayReturn() const; + /// mayHaveSideEffects - Return true if the instruction may have side effects. /// /// Note that this does not consider malloc and alloca to have side @@ -316,7 +322,7 @@ public: /// instructions which don't used the returned value. For cases where this /// matters, isSafeToSpeculativelyExecute may be more appropriate. bool mayHaveSideEffects() const { - return mayWriteToMemory() || mayThrow(); + return mayWriteToMemory() || mayThrow() || !mayReturn(); } /// clone() - Create a copy of 'this' instruction that is identical in all diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index bb4ea55..1ae8850 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_INSTRUCTIONS_H -#define LLVM_INSTRUCTIONS_H +#ifndef LLVM_IR_INSTRUCTIONS_H +#define LLVM_IR_INSTRUCTIONS_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" @@ -91,7 +91,7 @@ public: /// getType - Overload to return most specific pointer type /// PointerType *getType() const { - return reinterpret_cast<PointerType*>(Instruction::getType()); + return cast<PointerType>(Instruction::getType()); } /// getAllocatedType - Return the type that is being allocated by the @@ -762,9 +762,9 @@ public: /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - // getType - Overload to return most specific pointer type... - PointerType *getType() const { - return reinterpret_cast<PointerType*>(Instruction::getType()); + // getType - Overload to return most specific sequential type. + SequentialType *getType() const { + return cast<SequentialType>(Instruction::getType()); } /// \brief Returns the address space of this instruction's pointer type. @@ -953,7 +953,7 @@ public: "Both operands to ICmp instruction are not of the same type!"); // Check that the operands are the right type assert((getOperand(0)->getType()->isIntOrIntVectorTy() || - getOperand(0)->getType()->isPointerTy()) && + getOperand(0)->getType()->getScalarType()->isPointerTy()) && "Invalid operand types for ICmp instruction"); } @@ -1570,7 +1570,7 @@ public: const Value *getIndexOperand() const { return Op<1>(); } VectorType *getVectorOperandType() const { - return reinterpret_cast<VectorType*>(getVectorOperand()->getType()); + return cast<VectorType>(getVectorOperand()->getType()); } @@ -1629,7 +1629,7 @@ public: /// getType - Overload to return most specific vector type. /// VectorType *getType() const { - return reinterpret_cast<VectorType*>(Instruction::getType()); + return cast<VectorType>(Instruction::getType()); } /// Transparently provide more efficient getOperand methods. @@ -1681,14 +1681,14 @@ public: /// getType - Overload to return most specific vector type. /// VectorType *getType() const { - return reinterpret_cast<VectorType*>(Instruction::getType()); + return cast<VectorType>(Instruction::getType()); } /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); Constant *getMask() const { - return reinterpret_cast<Constant*>(getOperand(2)); + return cast<Constant>(getOperand(2)); } /// getMaskValue - Return the index from the shuffle mask for the specified diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index a8dfcbd..8344c56 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -21,8 +21,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_INTRINSICINST_H -#define LLVM_INTRINSICINST_H +#ifndef LLVM_IR_INTRINSICINST_H +#define LLVM_IR_INTRINSICINST_H #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index 1e20fd7..c97cd91 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_INTRINSICS_H -#define LLVM_INTRINSICS_H +#ifndef LLVM_IR_INTRINSICS_H +#define LLVM_IR_INTRINSICS_H #include "llvm/ADT/ArrayRef.h" #include <string> @@ -79,7 +79,7 @@ namespace Intrinsic { /// getIntrinsicInfoTableEntries. struct IITDescriptor { enum IITDescriptorKind { - Void, MMX, Metadata, Float, Double, + Void, MMX, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, Argument, ExtendVecArgument, TruncVecArgument } Kind; diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index e9fbba9..e252664 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -106,6 +106,7 @@ def llvm_i8_ty : LLVMType<i8>; def llvm_i16_ty : LLVMType<i16>; def llvm_i32_ty : LLVMType<i32>; def llvm_i64_ty : LLVMType<i64>; +def llvm_half_ty : LLVMType<f16>; def llvm_float_ty : LLVMType<f32>; def llvm_double_ty : LLVMType<f64>; def llvm_f80_ty : LLVMType<f80>; diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td index 1853c99..ebfd03e 100644 --- a/include/llvm/IR/IntrinsicsNVVM.td +++ b/include/llvm/IR/IntrinsicsNVVM.td @@ -805,6 +805,16 @@ def int_nvvm_ldu_global_p : Intrinsic<[llvm_anyptr_ty], [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldu.global.p">; +// Generated within nvvm. Use for ldg on sm_35 or later +def int_nvvm_ldg_global_i : Intrinsic<[llvm_anyint_ty], + [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + "llvm.nvvm.ldg.global.i">; +def int_nvvm_ldg_global_f : Intrinsic<[llvm_anyfloat_ty], + [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + "llvm.nvvm.ldg.global.f">; +def int_nvvm_ldg_global_p : Intrinsic<[llvm_anyptr_ty], + [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + "llvm.nvvm.ldg.global.p">; // Use for generic pointers // - These intrinsics are used to convert address spaces. @@ -815,36 +825,36 @@ def int_nvvm_ldu_global_p : Intrinsic<[llvm_anyptr_ty], // of pointer to another type of pointer, while the address space remains // the same. def int_nvvm_ptr_local_to_gen: Intrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + [llvm_anyptr_ty], [IntrNoMem], "llvm.nvvm.ptr.local.to.gen">; def int_nvvm_ptr_shared_to_gen: Intrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + [llvm_anyptr_ty], [IntrNoMem], "llvm.nvvm.ptr.shared.to.gen">; def int_nvvm_ptr_global_to_gen: Intrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + [llvm_anyptr_ty], [IntrNoMem], "llvm.nvvm.ptr.global.to.gen">; def int_nvvm_ptr_constant_to_gen: Intrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + [llvm_anyptr_ty], [IntrNoMem], "llvm.nvvm.ptr.constant.to.gen">; def int_nvvm_ptr_gen_to_global: Intrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + [llvm_anyptr_ty], [IntrNoMem], "llvm.nvvm.ptr.gen.to.global">; def int_nvvm_ptr_gen_to_shared: Intrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + [llvm_anyptr_ty], [IntrNoMem], "llvm.nvvm.ptr.gen.to.shared">; def int_nvvm_ptr_gen_to_local: Intrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + [llvm_anyptr_ty], [IntrNoMem], "llvm.nvvm.ptr.gen.to.local">; def int_nvvm_ptr_gen_to_constant: Intrinsic<[llvm_anyptr_ty], - [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], + [llvm_anyptr_ty], [IntrNoMem], "llvm.nvvm.ptr.gen.to.constant">; // Used in nvvm internally to help address space opt and ptx code generation // This is for params that are passed to kernel functions by pointer by-val. def int_nvvm_ptr_gen_to_param: Intrinsic<[llvm_anyptr_ty], [llvm_anyptr_ty], - [IntrNoMem, NoCapture<0>], + [IntrNoMem], "llvm.nvvm.ptr.gen.to.param">; // Move intrinsics, used in nvvm internally diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index 58fb39f..b3c558b 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LLVMCONTEXT_H -#define LLVM_LLVMCONTEXT_H +#ifndef LLVM_IR_LLVMCONTEXT_H +#define LLVM_IR_LLVMCONTEXT_H #include "llvm/Support/Compiler.h" @@ -58,39 +58,27 @@ public: void getMDKindNames(SmallVectorImpl<StringRef> &Result) const; - typedef void (*DiagHandlerTy)(const SMDiagnostic&, void *Context, - unsigned LocCookie); + typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context, + unsigned LocCookie); - /// setDiagnosticHandler - This method sets a handler that is invoked - /// when problems are detected by the backend. The first argument is a - /// function pointer and the second is a context pointer that gets passed - /// into the DiagHandler. + /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked + /// when problems with inline asm are detected by the backend. The first + /// argument is a function pointer and the second is a context pointer that + /// gets passed into the DiagHandler. /// /// LLVMContext doesn't take ownership or interpret either of these /// pointers. - void setDiagnosticHandler(DiagHandlerTy DiagHandler, void *DiagContext = 0); + void setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, + void *DiagContext = 0); - /// getDiagnosticHandler - Return the diagnostic handler set by - /// setDiagnosticHandler. - DiagHandlerTy getDiagnosticHandler() const; + /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by + /// setInlineAsmDiagnosticHandler. + InlineAsmDiagHandlerTy getInlineAsmDiagnosticHandler() const; - /// getDiagnosticContext - Return the diagnostic context set by - /// setDiagnosticHandler. - void *getDiagnosticContext() const; + /// getInlineAsmDiagnosticContext - Return the diagnostic context set by + /// setInlineAsmDiagnosticHandler. + void *getInlineAsmDiagnosticContext() const; - /// FIXME: Temporary copies of the old names; to be removed as soon as - /// clang switches to the new ones. - typedef DiagHandlerTy InlineAsmDiagHandlerTy; - void setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, - void *DiagContext = 0) { - setDiagnosticHandler(DiagHandler, DiagContext); - } - InlineAsmDiagHandlerTy getInlineAsmDiagnosticHandler() const { - return getDiagnosticHandler(); - } - void *getInlineAsmDiagnosticContext() const { - return getDiagnosticContext(); - } /// emitError - Emit an error message to the currently installed error handler /// with optional location information. This function returns, so code should @@ -101,12 +89,6 @@ public: void emitError(const Instruction *I, const Twine &ErrorStr); void emitError(const Twine &ErrorStr); - /// emitWarning - This is similar to emitError but it emits a warning instead - /// of an error. - void emitWarning(unsigned LocCookie, const Twine &ErrorStr); - void emitWarning(const Instruction *I, const Twine &ErrorStr); - void emitWarning(const Twine &ErrorStr); - private: LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION; void operator=(LLVMContext&) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h index d3ca644..604051b 100644 --- a/include/llvm/IR/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -12,150 +12,151 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MDBUILDER_H -#define LLVM_MDBUILDER_H +#ifndef LLVM_IR_MDBUILDER_H +#define LLVM_IR_MDBUILDER_H -#include "llvm/ADT/APInt.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" namespace llvm { - class MDBuilder { - LLVMContext &Context; - - public: - MDBuilder(LLVMContext &context) : Context(context) {} - - /// \brief Return the given string as metadata. - MDString *createString(StringRef Str) { - return MDString::get(Context, Str); - } - - //===------------------------------------------------------------------===// - // FPMath metadata. - //===------------------------------------------------------------------===// - - /// \brief Return metadata with the given settings. The special value 0.0 - /// for the Accuracy parameter indicates the default (maximal precision) - /// setting. - MDNode *createFPMath(float Accuracy) { - if (Accuracy == 0.0) - return 0; - assert(Accuracy > 0.0 && "Invalid fpmath accuracy!"); - Value *Op = ConstantFP::get(Type::getFloatTy(Context), Accuracy); - return MDNode::get(Context, Op); - } - - //===------------------------------------------------------------------===// - // Prof metadata. - //===------------------------------------------------------------------===// - - /// \brief Return metadata containing two branch weights. - MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight) { - uint32_t Weights[] = { TrueWeight, FalseWeight }; - return createBranchWeights(Weights); - } - - /// \brief Return metadata containing a number of branch weights. - MDNode *createBranchWeights(ArrayRef<uint32_t> Weights) { - assert(Weights.size() >= 2 && "Need at least two branch weights!"); - - SmallVector<Value *, 4> Vals(Weights.size()+1); - Vals[0] = createString("branch_weights"); - - Type *Int32Ty = Type::getInt32Ty(Context); - for (unsigned i = 0, e = Weights.size(); i != e; ++i) - Vals[i+1] = ConstantInt::get(Int32Ty, Weights[i]); - - return MDNode::get(Context, Vals); - } - - //===------------------------------------------------------------------===// - // Range metadata. - //===------------------------------------------------------------------===// - - /// \brief Return metadata describing the range [Lo, Hi). - MDNode *createRange(const APInt &Lo, const APInt &Hi) { - assert(Lo.getBitWidth() == Hi.getBitWidth() && "Mismatched bitwidths!"); - // If the range is everything then it is useless. - if (Hi == Lo) - return 0; - - // Return the range [Lo, Hi). - Type *Ty = IntegerType::get(Context, Lo.getBitWidth()); - Value *Range[2] = { ConstantInt::get(Ty, Lo), ConstantInt::get(Ty, Hi) }; - return MDNode::get(Context, Range); - } - - - //===------------------------------------------------------------------===// - // TBAA metadata. - //===------------------------------------------------------------------===// - - /// \brief Return metadata appropriate for a TBAA root node. Each returned - /// node is distinct from all other metadata and will never be identified - /// (uniqued) with anything else. - MDNode *createAnonymousTBAARoot() { - // To ensure uniqueness the root node is self-referential. - MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef<Value*>()); - MDNode *Root = MDNode::get(Context, Dummy); - // At this point we have - // !0 = metadata !{} <- dummy - // !1 = metadata !{metadata !0} <- root - // Replace the dummy operand with the root node itself and delete the dummy. - Root->replaceOperandWith(0, Root); - MDNode::deleteTemporary(Dummy); - // We now have - // !1 = metadata !{metadata !1} <- self-referential root - return Root; - } - - /// \brief Return metadata appropriate for a TBAA root node with the given - /// name. This may be identified (uniqued) with other roots with the same - /// name. - MDNode *createTBAARoot(StringRef Name) { - return MDNode::get(Context, createString(Name)); - } - - /// \brief Return metadata for a non-root TBAA node with the given name, - /// parent in the TBAA tree, and value for 'pointsToConstantMemory'. - MDNode *createTBAANode(StringRef Name, MDNode *Parent, - bool isConstant = false) { - if (isConstant) { - Constant *Flags = ConstantInt::get(Type::getInt64Ty(Context), 1); - Value *Ops[3] = { createString(Name), Parent, Flags }; - return MDNode::get(Context, Ops); - } else { - Value *Ops[2] = { createString(Name), Parent }; - return MDNode::get(Context, Ops); - } +class APInt; +class LLVMContext; + +class MDBuilder { + LLVMContext &Context; + +public: + MDBuilder(LLVMContext &context) : Context(context) {} + + /// \brief Return the given string as metadata. + MDString *createString(StringRef Str) { + return MDString::get(Context, Str); + } + + //===------------------------------------------------------------------===// + // FPMath metadata. + //===------------------------------------------------------------------===// + + /// \brief Return metadata with the given settings. The special value 0.0 + /// for the Accuracy parameter indicates the default (maximal precision) + /// setting. + MDNode *createFPMath(float Accuracy) { + if (Accuracy == 0.0) + return 0; + assert(Accuracy > 0.0 && "Invalid fpmath accuracy!"); + Value *Op = ConstantFP::get(Type::getFloatTy(Context), Accuracy); + return MDNode::get(Context, Op); + } + + //===------------------------------------------------------------------===// + // Prof metadata. + //===------------------------------------------------------------------===// + + /// \brief Return metadata containing two branch weights. + MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight) { + uint32_t Weights[] = { TrueWeight, FalseWeight }; + return createBranchWeights(Weights); + } + + /// \brief Return metadata containing a number of branch weights. + MDNode *createBranchWeights(ArrayRef<uint32_t> Weights) { + assert(Weights.size() >= 2 && "Need at least two branch weights!"); + + SmallVector<Value *, 4> Vals(Weights.size()+1); + Vals[0] = createString("branch_weights"); + + Type *Int32Ty = Type::getInt32Ty(Context); + for (unsigned i = 0, e = Weights.size(); i != e; ++i) + Vals[i+1] = ConstantInt::get(Int32Ty, Weights[i]); + + return MDNode::get(Context, Vals); + } + + //===------------------------------------------------------------------===// + // Range metadata. + //===------------------------------------------------------------------===// + + /// \brief Return metadata describing the range [Lo, Hi). + MDNode *createRange(const APInt &Lo, const APInt &Hi) { + assert(Lo.getBitWidth() == Hi.getBitWidth() && "Mismatched bitwidths!"); + // If the range is everything then it is useless. + if (Hi == Lo) + return 0; + + // Return the range [Lo, Hi). + Type *Ty = IntegerType::get(Context, Lo.getBitWidth()); + Value *Range[2] = { ConstantInt::get(Ty, Lo), ConstantInt::get(Ty, Hi) }; + return MDNode::get(Context, Range); + } + + + //===------------------------------------------------------------------===// + // TBAA metadata. + //===------------------------------------------------------------------===// + + /// \brief Return metadata appropriate for a TBAA root node. Each returned + /// node is distinct from all other metadata and will never be identified + /// (uniqued) with anything else. + MDNode *createAnonymousTBAARoot() { + // To ensure uniqueness the root node is self-referential. + MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef<Value*>()); + MDNode *Root = MDNode::get(Context, Dummy); + // At this point we have + // !0 = metadata !{} <- dummy + // !1 = metadata !{metadata !0} <- root + // Replace the dummy operand with the root node itself and delete the dummy. + Root->replaceOperandWith(0, Root); + MDNode::deleteTemporary(Dummy); + // We now have + // !1 = metadata !{metadata !1} <- self-referential root + return Root; + } + + /// \brief Return metadata appropriate for a TBAA root node with the given + /// name. This may be identified (uniqued) with other roots with the same + /// name. + MDNode *createTBAARoot(StringRef Name) { + return MDNode::get(Context, createString(Name)); + } + + /// \brief Return metadata for a non-root TBAA node with the given name, + /// parent in the TBAA tree, and value for 'pointsToConstantMemory'. + MDNode *createTBAANode(StringRef Name, MDNode *Parent, + bool isConstant = false) { + if (isConstant) { + Constant *Flags = ConstantInt::get(Type::getInt64Ty(Context), 1); + Value *Ops[3] = { createString(Name), Parent, Flags }; + return MDNode::get(Context, Ops); + } else { + Value *Ops[2] = { createString(Name), Parent }; + return MDNode::get(Context, Ops); } + } + + struct TBAAStructField { + uint64_t Offset; + uint64_t Size; + MDNode *TBAA; + TBAAStructField(uint64_t Offset, uint64_t Size, MDNode *TBAA) : + Offset(Offset), Size(Size), TBAA(TBAA) {} + }; - struct TBAAStructField { - uint64_t Offset; - uint64_t Size; - MDNode *TBAA; - TBAAStructField(uint64_t Offset, uint64_t Size, MDNode *TBAA) : - Offset(Offset), Size(Size), TBAA(TBAA) {} - }; - - /// \brief Return metadata for a tbaa.struct node with the given - /// struct field descriptions. - MDNode *createTBAAStructNode(ArrayRef<TBAAStructField> Fields) { - SmallVector<Value *, 4> Vals(Fields.size() * 3); - Type *Int64 = IntegerType::get(Context, 64); - for (unsigned i = 0, e = Fields.size(); i != e; ++i) { - Vals[i * 3 + 0] = ConstantInt::get(Int64, Fields[i].Offset); - Vals[i * 3 + 1] = ConstantInt::get(Int64, Fields[i].Size); - Vals[i * 3 + 2] = Fields[i].TBAA; - } - return MDNode::get(Context, Vals); + /// \brief Return metadata for a tbaa.struct node with the given + /// struct field descriptions. + MDNode *createTBAAStructNode(ArrayRef<TBAAStructField> Fields) { + SmallVector<Value *, 4> Vals(Fields.size() * 3); + Type *Int64 = IntegerType::get(Context, 64); + for (unsigned i = 0, e = Fields.size(); i != e; ++i) { + Vals[i * 3 + 0] = ConstantInt::get(Int64, Fields[i].Offset); + Vals[i * 3 + 1] = ConstantInt::get(Int64, Fields[i].Size); + Vals[i * 3 + 2] = Fields[i].TBAA; } + return MDNode::get(Context, Vals); + } - }; +}; } // end namespace llvm diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 402abb3..8c2cfac 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_METADATA_H -#define LLVM_METADATA_H +#ifndef LLVM_IR_METADATA_H +#define LLVM_IR_METADATA_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" @@ -29,8 +29,8 @@ class Module; template <typename T> class SmallVectorImpl; template<typename ValueSubClass, typename ItemParentClass> class SymbolTableListTraits; - - + + //===----------------------------------------------------------------------===// /// MDString - a single uniqued string. /// These are used to efficiently contain a byte sequence for metadata. @@ -51,7 +51,7 @@ public: unsigned getLength() const { return (unsigned)getName().size(); } typedef StringRef::iterator iterator; - + /// begin() - Pointer to the first byte of the string. iterator begin() const { return getName().begin(); } @@ -64,9 +64,9 @@ public: } }; - + class MDNodeOperand; - + //===----------------------------------------------------------------------===// /// MDNode - a tuple of other values. class MDNode : public Value, public FoldingSetNode { @@ -82,37 +82,37 @@ class MDNode : public Value, public FoldingSetNode { /// NumOperands - This many 'MDNodeOperand' items are co-allocated onto the /// end of this MDNode. unsigned NumOperands; - + // Subclass data enums. enum { /// FunctionLocalBit - This bit is set if this MDNode is function local. /// This is true when it (potentially transitively) contains a reference to /// something in a function, like an argument, basicblock, or instruction. FunctionLocalBit = 1 << 0, - + /// NotUniquedBit - This is set on MDNodes that are not uniqued because they /// have a null operand. NotUniquedBit = 1 << 1, - + /// DestroyFlag - This bit is set by destroy() so the destructor can assert /// that the node isn't being destroyed with a plain 'delete'. DestroyFlag = 1 << 2 }; - + // FunctionLocal enums. enum FunctionLocalness { FL_Unknown = -1, FL_No = 0, FL_Yes = 1 }; - - /// replaceOperand - Replace each instance of F from the operand list of this + + /// replaceOperand - Replace each instance of F from the operand list of this /// node with T. void replaceOperand(MDNodeOperand *Op, Value *NewVal); ~MDNode(); MDNode(LLVMContext &C, ArrayRef<Value*> Vals, bool isFunctionLocal); - + static MDNode *getMDNode(LLVMContext &C, ArrayRef<Value*> Vals, FunctionLocalness FL, bool Insert = true); public: @@ -123,7 +123,7 @@ public: static MDNode *getWhenValsUnresolved(LLVMContext &Context, ArrayRef<Value*> Vals, bool isFunctionLocal); - + static MDNode *getIfExists(LLVMContext &Context, ArrayRef<Value*> Vals); /// getTemporary - Return a temporary MDNode, for use in constructing @@ -137,22 +137,22 @@ public: /// replaceOperandWith - Replace a specific operand. void replaceOperandWith(unsigned i, Value *NewVal); - + /// getOperand - Return specified operand. Value *getOperand(unsigned i) const; - + /// getNumOperands - Return number of MDNode operands. unsigned getNumOperands() const { return NumOperands; } - + /// isFunctionLocal - Return whether MDNode is local to a function. bool isFunctionLocal() const { return (getSubclassDataFromValue() & FunctionLocalBit) != 0; } - + // getFunction - If this metadata is function-local and recursively has a // function-local operand, return the first such operand's parent function. // Otherwise, return null. getFunction() should not be used for performance- - // critical code because it recursively visits all the MDNode's operands. + // critical code because it recursively visits all the MDNode's operands. const Function *getFunction() const; /// Profile - calculate a unique identifier for this MDNode to collapse @@ -172,11 +172,11 @@ private: // destroy - Delete this node. Only when there are no uses. void destroy(); - bool isNotUniqued() const { + bool isNotUniqued() const { return (getSubclassDataFromValue() & NotUniquedBit) != 0; } void setIsNotUniqued(); - + // Shadow Value::setValueSubclassData with a private forwarding method so that // any future subclasses cannot accidentally use it. void setValueSubclassData(unsigned short D) { @@ -220,7 +220,7 @@ public: /// getOperand - Return specified operand. MDNode *getOperand(unsigned i) const; - + /// getNumOperands - Return the number of NamedMDNode operands. unsigned getNumOperands() const; diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index 4e1ca43..4460aa4 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MODULE_H -#define LLVM_MODULE_H +#ifndef LLVM_IR_MODULE_H +#define LLVM_IR_MODULE_H #include "llvm/ADT/OwningPtr.h" #include "llvm/IR/Function.h" @@ -147,30 +147,38 @@ public: /// An enumeration for describing the size of a pointer on the target machine. enum PointerSize { AnyPointerSize, Pointer32, Pointer64 }; - /// An enumeration for the supported behaviors of module flags. The following - /// module flags behavior values are supported: - /// - /// Value Behavior - /// ----- -------- - /// 1 Error - /// Emits an error if two values disagree. - /// - /// 2 Warning - /// Emits a warning if two values disagree. - /// - /// 3 Require - /// Emits an error when the specified value is not present - /// or doesn't have the specified value. It is an error for - /// two (or more) llvm.module.flags with the same ID to have - /// the Require behavior but different values. There may be - /// multiple Require flags per ID. - /// - /// 4 Override - /// Uses the specified value if the two values disagree. It - /// is an error for two (or more) llvm.module.flags with the - /// same ID to have the Override behavior but different - /// values. - enum ModFlagBehavior { Error = 1, Warning = 2, Require = 3, Override = 4 }; + /// This enumeration defines the supported behaviors of module flags. + enum ModFlagBehavior { + /// Emits an error if two values disagree, otherwise the resulting value is + /// that of the operands. + Error = 1, + + /// Emits a warning if two values disagree. The result value will be the + /// operand for the flag from the first module being linked. + Warning = 2, + + /// Adds a requirement that another module flag be present and have a + /// specified value after linking is performed. The value must be a metadata + /// pair, where the first element of the pair is the ID of the module flag + /// to be restricted, and the second element of the pair is the value the + /// module flag should be restricted to. This behavior can be used to + /// restrict the allowable results (via triggering of an error) of linking + /// IDs with the **Override** behavior. + Require = 3, + + /// Uses the specified value, regardless of the behavior or value of the + /// other module. If both modules specify **Override**, but the values + /// differ, an error will be emitted. + Override = 4, + + /// Appends the two values, which are required to be metadata nodes. + Append = 5, + + /// Appends the two values, which are required to be metadata + /// nodes. However, duplicate entries in the second list are dropped + /// during the append operation. + AppendUnique = 6 + }; struct ModuleFlagEntry { ModFlagBehavior Behavior; diff --git a/include/llvm/IR/OperandTraits.h b/include/llvm/IR/OperandTraits.h index 60c8b09..0e4b195 100644 --- a/include/llvm/IR/OperandTraits.h +++ b/include/llvm/IR/OperandTraits.h @@ -12,8 +12,8 @@ // the operands in the most efficient manner. // -#ifndef LLVM_OPERAND_TRAITS_H -#define LLVM_OPERAND_TRAITS_H +#ifndef LLVM_IR_OPERANDTRAITS_H +#define LLVM_IR_OPERANDTRAITS_H #include "llvm/IR/User.h" diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 577b41a..13ab72c 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_OPERATOR_H -#define LLVM_OPERATOR_H +#ifndef LLVM_IR_OPERATOR_H +#define LLVM_IR_OPERATOR_H #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" @@ -33,8 +33,8 @@ class ConstantExpr; /// class Operator : public User { private: - // Do not implement any of these. The Operator class is intended to be used - // as a utility, and is never itself instantiated. + // 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; diff --git a/include/llvm/IR/SymbolTableListTraits.h b/include/llvm/IR/SymbolTableListTraits.h index ec5c88f..561ce01 100644 --- a/include/llvm/IR/SymbolTableListTraits.h +++ b/include/llvm/IR/SymbolTableListTraits.h @@ -22,8 +22,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYMBOLTABLELISTTRAITS_H -#define LLVM_SYMBOLTABLELISTTRAITS_H +#ifndef LLVM_IR_SYMBOLTABLELISTTRAITS_H +#define LLVM_IR_SYMBOLTABLELISTTRAITS_H #include "llvm/ADT/ilist.h" diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index def4575..d89ae24 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -12,11 +12,13 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TYPE_H -#define LLVM_TYPE_H +#ifndef LLVM_IR_TYPE_H +#define LLVM_IR_TYPE_H +#include "llvm/ADT/APFloat.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" namespace llvm { @@ -162,6 +164,18 @@ public: getTypeID() == PPC_FP128TyID; } + const fltSemantics &getFltSemantics() const { + switch (getTypeID()) { + case HalfTyID: return APFloat::IEEEhalf; + case FloatTyID: return APFloat::IEEEsingle; + case DoubleTyID: return APFloat::IEEEdouble; + case X86_FP80TyID: return APFloat::x87DoubleExtended; + case FP128TyID: return APFloat::IEEEquad; + case PPC_FP128TyID: return APFloat::PPCDoubleDouble; + default: llvm_unreachable("Invalid floating type"); + } + } + /// isX86_MMXTy - Return true if this is X86 MMX. bool isX86_MMXTy() const { return getTypeID() == X86_MMXTyID; } diff --git a/include/llvm/IR/TypeBuilder.h b/include/llvm/IR/TypeBuilder.h index 83ca2a3..80c60a0 100644 --- a/include/llvm/IR/TypeBuilder.h +++ b/include/llvm/IR/TypeBuilder.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TYPEBUILDER_H -#define LLVM_TYPEBUILDER_H +#ifndef LLVM_IR_TYPEBUILDER_H +#define LLVM_IR_TYPEBUILDER_H #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/LLVMContext.h" diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h index 8080445..33a69c4 100644 --- a/include/llvm/IR/Use.h +++ b/include/llvm/IR/Use.h @@ -22,8 +22,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_USE_H -#define LLVM_USE_H +#ifndef LLVM_IR_USE_H +#define LLVM_IR_USE_H #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/Compiler.h" @@ -66,7 +66,6 @@ public: typedef PointerIntPair<User*, 1, unsigned> UserRef; private: - /// Copy ctor - do not implement Use(const Use &U) LLVM_DELETED_FUNCTION; /// Destructor - Only for zap() diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index 843d20b..a4d0a5d 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -16,8 +16,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_USER_H -#define LLVM_USER_H +#ifndef LLVM_IR_USER_H +#define LLVM_IR_USER_H #include "llvm/IR/Value.h" #include "llvm/Support/ErrorHandling.h" diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 85fdfe3..a4f7862 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_VALUE_H -#define LLVM_VALUE_H +#ifndef LLVM_IR_VALUE_H +#define LLVM_IR_VALUE_H #include "llvm/IR/Use.h" #include "llvm/Support/Casting.h" diff --git a/include/llvm/IR/ValueSymbolTable.h b/include/llvm/IR/ValueSymbolTable.h index 3ea095b..bf1fade 100644 --- a/include/llvm/IR/ValueSymbolTable.h +++ b/include/llvm/IR/ValueSymbolTable.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_VALUE_SYMBOL_TABLE_H -#define LLVM_VALUE_SYMBOL_TABLE_H +#ifndef LLVM_IR_VALUESYMBOLTABLE_H +#define LLVM_IR_VALUESYMBOLTABLE_H #include "llvm/ADT/StringMap.h" #include "llvm/IR/Value.h" diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 79037f7..e5e21f3 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -31,6 +31,10 @@ void initializeTransformUtils(PassRegistry&); /// ScalarOpts library. void initializeScalarOpts(PassRegistry&); +/// initializeObjCARCOpts - Initialize all passes linked into the ObjCARCOpts +/// library. +void initializeObjCARCOpts(PassRegistry&); + /// initializeVectorization - Initialize all passes linked into the /// Vectorize library. void initializeVectorization(PassRegistry&); @@ -77,6 +81,8 @@ void initializeBoundsCheckingPass(PassRegistry&); void initializeBranchFolderPassPass(PassRegistry&); void initializeBranchProbabilityInfoPass(PassRegistry&); void initializeBreakCriticalEdgesPass(PassRegistry&); +void initializeCallGraphPrinterPass(PassRegistry&); +void initializeCallGraphViewerPass(PassRegistry&); void initializeCFGOnlyPrinterPass(PassRegistry&); void initializeCFGOnlyViewerPass(PassRegistry&); void initializeCFGPrinterPass(PassRegistry&); @@ -130,6 +136,7 @@ void initializeIPSCCPPass(PassRegistry&); void initializeIVUsersPass(PassRegistry&); void initializeIfConverterPass(PassRegistry&); void initializeIndVarSimplifyPass(PassRegistry&); +void initializeInlineCostAnalysisPass(PassRegistry&); void initializeInstCombinerPass(PassRegistry&); void initializeInstCountPass(PassRegistry&); void initializeInstNamerPass(PassRegistry&); @@ -210,6 +217,7 @@ void initializePreVerifierPass(PassRegistry&); void initializePrintDbgInfoPass(PassRegistry&); void initializePrintFunctionPassPass(PassRegistry&); void initializePrintModulePassPass(PassRegistry&); +void initializePrintBasicBlockPassPass(PassRegistry&); void initializeProcessImplicitDefsPass(PassRegistry&); void initializeProfileEstimatorPassPass(PassRegistry&); void initializeProfileInfoAnalysisGroup(PassRegistry&); diff --git a/include/llvm/LinkAllVMCore.h b/include/llvm/LinkAllIR.h index 6039a63..4c1aaca 100644 --- a/include/llvm/LinkAllVMCore.h +++ b/include/llvm/LinkAllIR.h @@ -1,4 +1,4 @@ -//===- LinkAllVMCore.h - Reference All VMCore Code --------------*- C++ -*-===// +//===----- LinkAllIR.h - Reference All VMCore Code --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LINKALLVMCORE_H -#define LLVM_LINKALLVMCORE_H +#ifndef LLVM_LINKALLIR_H +#define LLVM_LINKALLIR_H #include "llvm/Analysis/Verifier.h" #include "llvm/IR/InlineAsm.h" diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index d29775a..cb727f6 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -16,6 +16,7 @@ #define LLVM_LINKALLPASSES_H #include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/CallPrinter.h" #include "llvm/Analysis/DomPrinter.h" #include "llvm/Analysis/FindUsedTypes.h" #include "llvm/Analysis/IntervalPartition.h" @@ -30,6 +31,7 @@ #include "llvm/IR/Function.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" #include "llvm/Transforms/Vectorize.h" @@ -57,6 +59,8 @@ namespace { (void) llvm::createBlockPlacementPass(); (void) llvm::createBoundsCheckingPass(); (void) llvm::createBreakCriticalEdgesPass(); + (void) llvm::createCallGraphPrinterPass(); + (void) llvm::createCallGraphViewerPass(); (void) llvm::createCFGSimplificationPass(); (void) llvm::createConstantMergePass(); (void) llvm::createConstantPropagationPass(); @@ -147,6 +151,7 @@ namespace { (void) llvm::createMergeFunctionsPass(); (void) llvm::createPrintModulePass(0); (void) llvm::createPrintFunctionPass("", 0); + (void) llvm::createPrintBasicBlockPass(0); (void) llvm::createDbgInfoPrinterPass(); (void) llvm::createModuleDebugInfoPrinterPass(); (void) llvm::createPartialInliningPass(); diff --git a/include/llvm/Linker.h b/include/llvm/Linker.h index 1ebcd6b..a349806 100644 --- a/include/llvm/Linker.h +++ b/include/llvm/Linker.h @@ -43,14 +43,6 @@ class Linker { /// @name Types /// @{ public: - /// This type is used to pass the linkage items (libraries and files) to - /// the LinkItems function. It is composed of string/bool pairs. The string - /// provides the name of the file or library (as with the -l option). The - /// bool should be true for libraries and false for files, signifying - /// "isLibrary". - /// @brief A list of linkage items - typedef std::vector<std::pair<std::string,bool> > ItemList; - /// This enumeration is used to control various optional features of the /// linker. enum ControlFlags { @@ -153,93 +145,6 @@ class Linker { /// @brief Set control flags. void setFlags(unsigned flags) { Flags = flags; } - /// This method is the main interface to the linker. It can be used to - /// link a set of linkage items into a module. A linkage item is either a - /// file name with fully qualified path, or a library for which the Linker's - /// LibraryPath will be utilized to locate the library. The bool value in - /// the LinkItemKind should be set to true for libraries. This function - /// allows linking to preserve the order of specification associated with - /// the command line, or for other purposes. Each item will be linked in - /// turn as it occurs in \p Items. - /// @returns true if an error occurred, false otherwise - /// @see LinkItemKind - /// @see getLastError - bool LinkInItems ( - const ItemList& Items, ///< Set of libraries/files to link in - ItemList& NativeItems ///< Output list of native files/libs - ); - - /// This function links the bitcode \p Files into the composite module. - /// Note that this does not do any linking of unresolved symbols. The \p - /// Files are all completely linked into \p HeadModule regardless of - /// unresolved symbols. This function just loads each bitcode file and - /// calls LinkInModule on them. - /// @returns true if an error occurs, false otherwise - /// @see getLastError - /// @brief Link in multiple files. - bool LinkInFiles ( - const std::vector<sys::Path> & Files ///< Files to link in - ); - - /// This function links a single bitcode file, \p File, into the composite - /// module. Note that this does not attempt to resolve symbols. This method - /// just loads the bitcode file and calls LinkInModule on it. If an error - /// occurs, the Linker's error string is set. - /// @returns true if an error occurs, false otherwise - /// @see getLastError - /// @brief Link in a single file. - bool LinkInFile( - const sys::Path& File, ///< File to link in. - bool &is_native ///< Indicates if the file is native object file - ); - - /// This function provides a way to selectively link in a set of modules, - /// found in libraries, based on the unresolved symbols in the composite - /// module. Each item in \p Libraries should be the base name of a library, - /// as if given with the -l option of a linker tool. The Linker's LibPaths - /// are searched for the \p Libraries and any found will be linked in with - /// LinkInArchive. If an error occurs, the Linker's error string is set. - /// @see LinkInArchive - /// @see getLastError - /// @returns true if an error occurs, false otherwise - /// @brief Link libraries into the module - bool LinkInLibraries ( - const std::vector<std::string> & Libraries ///< Libraries to link in - ); - - /// This function provides a way to selectively link in a set of modules, - /// found in one library, based on the unresolved symbols in the composite - /// module.The \p Library should be the base name of a library, as if given - /// with the -l option of a linker tool. The Linker's LibPaths are searched - /// for the \p Library and if found, it will be linked in with via the - /// LinkInArchive method. If an error occurs, the Linker's error string is - /// set. - /// @see LinkInArchive - /// @see getLastError - /// @returns true if an error occurs, false otherwise - /// @brief Link one library into the module - bool LinkInLibrary ( - StringRef Library, ///< The library to link in - bool& is_native ///< Indicates if lib a native library - ); - - /// This function links one bitcode archive, \p Filename, into the module. - /// The archive is searched to resolve outstanding symbols. Any modules in - /// the archive that resolve outstanding symbols will be linked in. The - /// library is searched repeatedly until no more modules that resolve - /// symbols can be found. If an error occurs, the error string is set. - /// To speed up this function, ensure the archive has been processed - /// llvm-ranlib or the S option was given to llvm-ar when the archive was - /// created. These tools add a symbol table to the archive which makes the - /// search for undefined symbols much faster. - /// @see getLastError - /// @returns true if an error occurs, otherwise false. - /// @brief Link in one archive. - bool LinkInArchive( - const sys::Path& Filename, ///< Filename of the archive to link - bool& is_native ///< Indicates if archive is a native archive - ); - /// This method links the \p Src module into the Linker's Composite module /// by calling LinkModules. All the other LinkIn* methods eventually /// result in calling this method to link a Module into the Linker's @@ -268,21 +173,10 @@ class Linker { static bool LinkModules(Module* Dest, Module* Src, unsigned Mode, std::string* ErrorMsg); - /// This function looks through the Linker's LibPaths to find a library with - /// the name \p Filename. If the library cannot be found, the returned path - /// will be empty (i.e. sys::Path::isEmpty() will return true). - /// @returns A sys::Path to the found library - /// @brief Find a library from its short name. - sys::Path FindLib(StringRef Filename); - /// @} /// @name Implementation /// @{ private: - /// Read in and parse the bitcode file named by FN and return the - /// Module it contains (wrapped in an auto_ptr), or 0 if an error occurs. - std::auto_ptr<Module> LoadObject(const sys::Path& FN); - bool warning(StringRef message); bool error(StringRef message); void verbose(StringRef message); diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 38cf060..28256b3 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_ASM_INFO_H -#define LLVM_TARGET_ASM_INFO_H +#ifndef LLVM_MC_MCASMINFO_H +#define LLVM_MC_MCASMINFO_H #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MachineLocation.h" @@ -48,6 +48,11 @@ namespace llvm { /// Default is 4. unsigned PointerSize; + /// CalleeSaveStackSlotSize - Size of the stack slot reserved for + /// callee-saved registers, in bytes. + /// Default is same as pointer size. + unsigned CalleeSaveStackSlotSize; + /// IsLittleEndian - True if target is little endian. /// Default is true. bool IsLittleEndian; @@ -343,7 +348,13 @@ namespace llvm { return PointerSize; } - /// islittleendian - True if the target is little endian. + /// getCalleeSaveStackSlotSize - Get the callee-saved register stack slot + /// size in bytes. + unsigned getCalleeSaveStackSlotSize() const { + return CalleeSaveStackSlotSize; + } + + /// isLittleEndian - True if the target is little endian. bool isLittleEndian() const { return IsLittleEndian; } diff --git a/include/llvm/MC/MCAsmInfoCOFF.h b/include/llvm/MC/MCAsmInfoCOFF.h index 0ff3e12..7286151 100644 --- a/include/llvm/MC/MCAsmInfoCOFF.h +++ b/include/llvm/MC/MCAsmInfoCOFF.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_COFF_TARGET_ASM_INFO_H -#define LLVM_COFF_TARGET_ASM_INFO_H +#ifndef LLVM_MC_MCASMINFOCOFF_H +#define LLVM_MC_MCASMINFOCOFF_H #include "llvm/MC/MCAsmInfo.h" @@ -33,4 +33,4 @@ namespace llvm { } -#endif // LLVM_COFF_TARGET_ASM_INFO_H +#endif // LLVM_MC_MCASMINFOCOFF_H diff --git a/include/llvm/MC/MCAsmInfoDarwin.h b/include/llvm/MC/MCAsmInfoDarwin.h index af552de..3d249f9 100644 --- a/include/llvm/MC/MCAsmInfoDarwin.h +++ b/include/llvm/MC/MCAsmInfoDarwin.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DARWIN_TARGET_ASM_INFO_H -#define LLVM_DARWIN_TARGET_ASM_INFO_H +#ifndef LLVM_MC_MCASMINFODARWIN_H +#define LLVM_MC_MCASMINFODARWIN_H #include "llvm/MC/MCAsmInfo.h" @@ -26,4 +26,4 @@ namespace llvm { } -#endif // LLVM_DARWIN_TARGET_ASM_INFO_H +#endif // LLVM_MC_MCASMINFODARWIN_H diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index 8cb4601..3058b7b 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -60,9 +60,10 @@ public: /// Get the assembler object this is a layout for. MCAssembler &getAssembler() const { return Assembler; } - /// \brief Invalidate the fragments after F because it has been resized. - /// The fragment's size should have already been updated. - void invalidateFragmentsAfter(MCFragment *F); + /// \brief Invalidate the fragments starting with F because it has been + /// resized. The fragment's size should have already been updated, but + /// its bundle padding will be recomputed. + void invalidateFragmentsFrom(MCFragment *F); /// \brief Perform layout for a single fragment, assuming that the previous /// fragment has already been laid out correctly, and the parent section has diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 40766b4..6aeb8b8 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -52,6 +52,7 @@ public: enum FragmentType { FT_Align, FT_Data, + FT_CompactEncodedInst, FT_Fill, FT_Relaxable, FT_Org, @@ -113,6 +114,7 @@ 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) { } /// \brief Get the padding size that must be inserted before this fragment. /// Used for bundling. By default, no padding is inserted. @@ -131,6 +133,9 @@ public: void dump(); }; +/// Interface implemented by fragments that contain encoded instructions and/or +/// data. +/// class MCEncodedFragment : public MCFragment { virtual void anchor(); @@ -142,20 +147,9 @@ public: } virtual ~MCEncodedFragment(); - typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; - typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; - virtual SmallVectorImpl<char> &getContents() = 0; virtual const SmallVectorImpl<char> &getContents() const = 0; - virtual SmallVectorImpl<MCFixup> &getFixups() = 0; - virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0; - - virtual fixup_iterator fixup_begin() = 0; - virtual const_fixup_iterator fixup_begin() const = 0; - virtual fixup_iterator fixup_end() = 0; - virtual const_fixup_iterator fixup_end() const = 0; - virtual uint8_t getBundlePadding() const { return BundlePadding; } @@ -166,13 +160,52 @@ public: 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; + } + } +}; + +/// Interface implemented by fragments that contain encoded instructions and/or +/// data and also have fixups registered. +/// +class MCEncodedFragmentWithFixups : public MCEncodedFragment { + virtual void anchor(); + +public: + MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, + MCSectionData *SD = 0) + : MCEncodedFragment(FType, SD) + { + } + + virtual ~MCEncodedFragmentWithFixups(); + + typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; + typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; + + virtual SmallVectorImpl<MCFixup> &getFixups() = 0; + virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0; + + virtual fixup_iterator fixup_begin() = 0; + virtual const_fixup_iterator fixup_begin() const = 0; + virtual fixup_iterator fixup_end() = 0; + virtual const_fixup_iterator fixup_end() const = 0; + + static bool classof(const MCFragment *F) { + MCFragment::FragmentType Kind = F->getKind(); return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data; } }; /// Fragment for data and encoded instructions. /// -class MCDataFragment : public MCEncodedFragment { +class MCDataFragment : public MCEncodedFragmentWithFixups { virtual void anchor(); /// \brief Does this fragment contain encoded instructions anywhere in it? @@ -187,7 +220,7 @@ class MCDataFragment : public MCEncodedFragment { SmallVector<MCFixup, 4> Fixups; public: MCDataFragment(MCSectionData *SD = 0) - : MCEncodedFragment(FT_Data, SD), + : MCEncodedFragmentWithFixups(FT_Data, SD), HasInstructions(false), AlignToBundleEnd(false) { } @@ -220,10 +253,43 @@ public: } }; +/// This is a compact (memory-size-wise) fragment for holding an encoded +/// instruction (non-relaxable) that has no fixups registered. When applicable, +/// it can be used instead of MCDataFragment and lead to lower memory +/// consumption. +/// +class MCCompactEncodedInstFragment : public MCEncodedFragment { + virtual void anchor(); + + /// \brief Should this fragment be aligned to the end of a bundle? + bool AlignToBundleEnd; + + SmallVector<char, 4> Contents; +public: + MCCompactEncodedInstFragment(MCSectionData *SD = 0) + : MCEncodedFragment(FT_CompactEncodedInst, SD), AlignToBundleEnd(false) + { + } + + virtual bool hasInstructions() const { + return true; + } + + virtual SmallVectorImpl<char> &getContents() { return Contents; } + virtual const SmallVectorImpl<char> &getContents() const { return Contents; } + + virtual bool alignToBundleEnd() const { return AlignToBundleEnd; } + virtual void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_CompactEncodedInst; + } +}; + /// A relaxable fragment holds on to its MCInst, since it may need to be /// relaxed during the assembler layout and relaxation stage. /// -class MCRelaxableFragment : public MCEncodedFragment { +class MCRelaxableFragment : public MCEncodedFragmentWithFixups { virtual void anchor(); /// Inst - The instruction this is a fragment for. @@ -237,7 +303,7 @@ class MCRelaxableFragment : public MCEncodedFragment { public: MCRelaxableFragment(const MCInst &_Inst, MCSectionData *SD = 0) - : MCEncodedFragment(FT_Relaxable, SD), Inst(_Inst) { + : MCEncodedFragmentWithFixups(FT_Relaxable, SD), Inst(_Inst) { } virtual SmallVectorImpl<char> &getContents() { return Contents; } @@ -791,6 +857,10 @@ private: 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; + /// The set of function symbols for which a .thumb_func directive has /// been seen. // @@ -809,6 +879,12 @@ private: unsigned NoExecStack : 1; unsigned SubsectionsViaSymbols : 1; + /// ELF specific e_header flags + // It would be good if there were an MCELFAssembler class to hold this. + // ELF header flags are used both by the integrated and standalone assemblers. + // Access to the flags is necessary in cases where assembler directives affect + // which flags to be set. + unsigned ELFHeaderEFlags; private: /// Evaluate a fixup to a relocatable expression and the value which should be /// placed into the fixup. @@ -886,6 +962,10 @@ public: /// Flag a function symbol as the target of a .thumb_func directive. void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); } + /// ELF e_header flags + unsigned getELFHeaderEFlags() const {return ELFHeaderEFlags;} + void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags;} + public: /// Construct a new assembler instance. /// @@ -1004,6 +1084,14 @@ public: size_t indirect_symbol_size() const { return IndirectSymbols.size(); } /// @} + /// @name Linker Option List Access + /// @{ + + std::vector<std::vector<std::string> > &getLinkerOptions() { + return LinkerOptions; + } + + /// @} /// @name Data Region List Access /// @{ diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index e92d3b9..20d52eb 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -129,6 +129,10 @@ namespace llvm { /// non-empty. StringRef DwarfDebugFlags; + /// The string to embed in as the dwarf AT_producer for the compile unit, if + /// non-empty. + StringRef DwarfDebugProducer; + /// Honor temporary labels, this is useful for debugging semantic /// differences between temporary and non-temporary labels (primarily on /// Darwin). @@ -140,6 +144,10 @@ namespace llvm { /// We need a deterministic iteration order, so we remember the order /// the elements were added. std::vector<const MCSection *> MCLineSectionOrder; + /// The Compile Unit ID that we are currently processing. + unsigned DwarfCompileUnitID; + /// The line table start symbol for each Compile Unit. + DenseMap<unsigned, MCSymbol *> MCLineTableSymbols; void *MachOUniquingMap, *ELFUniquingMap, *COFFUniquingMap; @@ -300,6 +308,25 @@ namespace llvm { MCLineSections[Sec] = Line; MCLineSectionOrder.push_back(Sec); } + unsigned getDwarfCompileUnitID() { + return DwarfCompileUnitID; + } + void setDwarfCompileUnitID(unsigned CUIndex) { + DwarfCompileUnitID = CUIndex; + } + const DenseMap<unsigned, MCSymbol *> &getMCLineTableSymbols() const { + return MCLineTableSymbols; + } + MCSymbol *getMCLineTableSymbol(unsigned ID) const { + DenseMap<unsigned, MCSymbol *>::const_iterator CIter = + MCLineTableSymbols.find(ID); + if (CIter == MCLineTableSymbols.end()) + return NULL; + return CIter->second; + } + void setMCLineTableSymbol(MCSymbol *Sym, unsigned ID) { + MCLineTableSymbols[ID] = Sym; + } /// setCurrentDwarfLoc - saves the information from the currently parsed /// dwarf .loc directive and sets DwarfLocSeen. When the next instruction @@ -346,6 +373,9 @@ namespace llvm { void setDwarfDebugFlags(StringRef S) { DwarfDebugFlags = S; } StringRef getDwarfDebugFlags() { return DwarfDebugFlags; } + void setDwarfDebugProducer(StringRef S) { DwarfDebugProducer = S; } + StringRef getDwarfDebugProducer() { return DwarfDebugProducer; } + /// @} char *getSecureLogFile() { return SecureLogFile; } diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h index 1b6beb2..36fbcb0 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -6,8 +6,8 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#ifndef MCDISASSEMBLER_H -#define MCDISASSEMBLER_H +#ifndef LLVM_MC_MCDISASSEMBLER_H +#define LLVM_MC_MCDISASSEMBLER_H #include "llvm-c/Disassembler.h" #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 3160b61..1a392e8 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -19,6 +19,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/raw_ostream.h" +#include <map> #include <vector> namespace llvm { @@ -186,29 +187,43 @@ namespace llvm { MCLineSection() {} // addLineEntry - adds an entry to this MCLineSection's line entries - void addLineEntry(const MCLineEntry &LineEntry) { - MCLineEntries.push_back(LineEntry); + void addLineEntry(const MCLineEntry &LineEntry, unsigned CUID) { + MCLineDivisions[CUID].push_back(LineEntry); } typedef std::vector<MCLineEntry> MCLineEntryCollection; typedef MCLineEntryCollection::iterator iterator; typedef MCLineEntryCollection::const_iterator const_iterator; + typedef std::map<unsigned, MCLineEntryCollection> MCLineDivisionMap; private: - MCLineEntryCollection MCLineEntries; + // A collection of MCLineEntry for each Compile Unit ID. + MCLineDivisionMap MCLineDivisions; public: - const MCLineEntryCollection *getMCLineEntries() const { - return &MCLineEntries; + // Returns whether MCLineSection contains entries for a given Compile + // Unit ID. + bool containEntriesForID(unsigned CUID) const { + return MCLineDivisions.count(CUID); + } + // Returns the collection of MCLineEntry for a given Compile Unit ID. + const MCLineEntryCollection &getMCLineEntries(unsigned CUID) const { + MCLineDivisionMap::const_iterator CIter = MCLineDivisions.find(CUID); + assert(CIter != MCLineDivisions.end()); + return CIter->second; } }; class MCDwarfFileTable { public: // - // This emits the Dwarf file and the line tables. + // This emits the Dwarf file and the line tables for all Compile Units. // static const MCSymbol *Emit(MCStreamer *MCOS); + // + // This emits the Dwarf file and the line tables for a given Compile Unit. + // + static const MCSymbol *EmitCU(MCStreamer *MCOS, unsigned ID); }; class MCDwarfLineAddr { diff --git a/include/llvm/MC/MCELF.h b/include/llvm/MC/MCELF.h index e08f1e6..7e59911 100644 --- a/include/llvm/MC/MCELF.h +++ b/include/llvm/MC/MCELF.h @@ -28,6 +28,8 @@ class MCELF { static unsigned GetType(const MCSymbolData &SD); static void SetVisibility(MCSymbolData &SD, unsigned Visibility); static unsigned GetVisibility(MCSymbolData &SD); + static void setOther(MCSymbolData &SD, unsigned Other); + static unsigned getOther(MCSymbolData &SD); }; } diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index 38cdc72..a59776d 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -79,7 +79,6 @@ public: virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel, bool IsRelocWithSymbol, int64_t Addend) const = 0; - virtual unsigned getEFlags() const; virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, const MCValue &Target, const MCFragment &F, diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index ab20ee8..6fb2d22 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -28,15 +28,20 @@ class MCSymbolData; class raw_ostream; class MCELFStreamer : public MCObjectStreamer { -public: - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, +protected: + MCELFStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, TAB, OS, Emitter) {} + : MCObjectStreamer(Kind, Context, TAB, OS, Emitter) {} + +public: + MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *Emitter) + : MCObjectStreamer(SK_ELFStreamer, Context, TAB, OS, Emitter) {} - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *Emitter, - MCAssembler *Assembler) - : MCObjectStreamer(Context, TAB, OS, Emitter, Assembler) {} + MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *Emitter, MCAssembler *Assembler) + : MCObjectStreamer(SK_ELFStreamer, Context, TAB, OS, Emitter, + Assembler) {} virtual ~MCELFStreamer(); @@ -44,6 +49,7 @@ public: /// @{ virtual void InitSections(); + virtual void InitToTextSection(); virtual void ChangeSection(const MCSection *Section); virtual void EmitLabel(MCSymbol *Symbol); virtual void EmitDebugLabel(MCSymbol *Symbol); @@ -59,6 +65,8 @@ public: virtual void EmitCOFFSymbolType(int Type); virtual void EndCOFFSymbolDef(); + virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, @@ -80,6 +88,10 @@ public: virtual void FinishImpl(); /// @} + static bool classof(const MCStreamer *S) { + return S->getKind() == SK_ELFStreamer || S->getKind() == SK_ARMELFStreamer; + } + private: virtual void EmitInstToFragment(const MCInst &Inst); virtual void EmitInstToData(const MCInst &Inst); diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 475981f..b5bfed1 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -472,6 +472,8 @@ public: virtual void AddValueSymbols(MCAssembler *) const = 0; virtual const MCSection *FindAssociatedSection() const = 0; + virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0; + static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Target; } diff --git a/include/llvm/MC/MCFixedLenDisassembler.h b/include/llvm/MC/MCFixedLenDisassembler.h index 22b3c32..ad99943 100644 --- a/include/llvm/MC/MCFixedLenDisassembler.h +++ b/include/llvm/MC/MCFixedLenDisassembler.h @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// // Fixed length disassembler decoder state machine driver. //===----------------------------------------------------------------------===// -#ifndef MCFIXEDLENDISASSEMBLER_H -#define MCFIXEDLENDISASSEMBLER_H +#ifndef LLVM_MC_MCFIXEDLENDISASSEMBLER_H +#define LLVM_MC_MCFIXEDLENDISASSEMBLER_H namespace llvm { diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 3cd278e..3c9a588 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -196,6 +196,8 @@ public: void WriteLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset, uint32_t DataSize); + void WriteLinkerOptionsLoadCommand(const std::vector<std::string> &Options); + // FIXME: We really need to improve the relocation validation. Basically, we // want to implement a separate computation which evaluates the relocation // entry as the linker would, and verifies that the resultant fixup value is diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index c8444fd..c8d7484 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -97,6 +97,9 @@ protected: const MCSection *DwarfARangesSection; const MCSection *DwarfRangesSection; const MCSection *DwarfMacroInfoSection; + // The pubnames section is no longer generated by default. The generation + // can be enabled by a compiler flag. + const MCSection *DwarfPubNamesSection; // DWARF5 Experimental Debug Info Sections /// DwarfAccelNamesSection, DwarfAccelObjCSection, @@ -115,6 +118,7 @@ protected: const MCSection *DwarfLineDWOSection; const MCSection *DwarfLocDWOSection; const MCSection *DwarfStrOffDWOSection; + const MCSection *DwarfAddrSection; // Extra TLS Variable Data section. If the target needs to put additional // information for a TLS variable, it'll go here. @@ -208,6 +212,7 @@ public: 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 *getDwarfDebugInlineSection() const { return DwarfDebugInlineSection; @@ -251,6 +256,9 @@ public: const MCSection *getDwarfStrOffDWOSection() const { return DwarfStrOffDWOSection; } + const MCSection *getDwarfAddrSection() const { + return DwarfAddrSection; + } const MCSection *getTLSExtraDataSection() const { return TLSExtraDataSection; diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 0ece092..f06c49f 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -38,9 +38,9 @@ class MCObjectStreamer : public MCStreamer { virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame); protected: - MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, + MCObjectStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter); - MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, + MCObjectStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, MCAssembler *_Assembler); ~MCObjectStreamer(); @@ -86,7 +86,7 @@ public: virtual void EmitBundleAlignMode(unsigned AlignPow2); virtual void EmitBundleLock(bool AlignToEnd); virtual void EmitBundleUnlock(); - virtual void EmitBytes(StringRef Data, unsigned AddrSpace); + virtual void EmitBytes(StringRef Data, unsigned AddrSpace = 0); virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, @@ -103,10 +103,14 @@ public: virtual void EmitGPRel32Value(const MCExpr *Value); virtual void EmitGPRel64Value(const MCExpr *Value); virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, - unsigned AddrSpace); + unsigned AddrSpace = 0); virtual void FinishImpl(); /// @} + + static bool classof(const MCStreamer *S) { + return S->getKind() >= SK_ELFStreamer && S->getKind() <= SK_WinCOFFStreamer; + } }; } // end namespace llvm diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 9d5c1a7..4939a3f 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -10,6 +10,7 @@ #ifndef LLVM_MC_MCOBJECTWRITER_H #define LLVM_MC_MCOBJECTWRITER_H +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/raw_ostream.h" @@ -61,15 +62,15 @@ public: /// @name High-Level API /// @{ - /// Perform any late binding of symbols (for example, to assign symbol indices - /// for use when generating relocations). + /// \brief Perform any late binding of symbols (for example, to assign symbol + /// indices for use when generating relocations). /// /// This routine is called by the assembler after layout and relaxation is /// complete. virtual void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) = 0; - /// Record a relocation entry. + /// \brief Record a relocation entry. /// /// This routine is called by the assembler after layout and relaxation, and /// post layout binding. The implementation is responsible for storing @@ -99,8 +100,7 @@ public: bool InSet, bool IsPCRel) const; - - /// Write the object file. + /// \brief Write the object file. /// /// This routine is called by the assembler after layout and relaxation is /// complete, fixups have been evaluated and applied, and relocations @@ -176,7 +176,7 @@ public: OS << StringRef(Zeros, N % 16); } - void WriteBytes(SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) { + void WriteBytes(const SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) { WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize); } diff --git a/include/llvm/MC/MCParser/AsmCond.h b/include/llvm/MC/MCParser/AsmCond.h index 92a115e..a918b56 100644 --- a/include/llvm/MC/MCParser/AsmCond.h +++ b/include/llvm/MC/MCParser/AsmCond.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef ASMCOND_H -#define ASMCOND_H +#ifndef LLVM_MC_MCPARSER_ASMCOND_H +#define LLVM_MC_MCPARSER_ASMCOND_H namespace llvm { diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index e102dfb..0dab314 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef ASMLEXER_H -#define ASMLEXER_H +#ifndef LLVM_MC_MCPARSER_ASMLEXER_H +#define LLVM_MC_MCPARSER_ASMLEXER_H #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCParser/MCAsmLexer.h" diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index 37a69e2..53b380f 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCASMLEXER_H -#define LLVM_MC_MCASMLEXER_H +#ifndef LLVM_MC_MCPARSER_MCASMLEXER_H +#define LLVM_MC_MCPARSER_MCASMLEXER_H #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index b9490fa..d7e3902 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -7,14 +7,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCASMPARSER_H -#define LLVM_MC_MCASMPARSER_H +#ifndef LLVM_MC_MCPARSER_MCASMPARSER_H +#define LLVM_MC_MCPARSER_MCASMPARSER_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCParser/AsmLexer.h" #include "llvm/Support/DataTypes.h" namespace llvm { -class AsmToken; class MCAsmInfo; class MCAsmLexer; class MCAsmParserExtension; @@ -22,13 +23,11 @@ class MCContext; class MCExpr; class MCInstPrinter; class MCInstrInfo; -class MCParsedAsmOperand; class MCStreamer; class MCTargetAsmParser; class SMLoc; class SMRange; class SourceMgr; -class StringRef; class Twine; /// MCAsmParserSemaCallback - Generic Sema callback for assembly parser. @@ -36,16 +35,21 @@ class MCAsmParserSemaCallback { public: virtual ~MCAsmParserSemaCallback(); virtual void *LookupInlineAsmIdentifier(StringRef Name, void *Loc, - unsigned &Size) = 0; + unsigned &Length, unsigned &Size, + unsigned &Type, bool &IsVarDecl) = 0; + virtual bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset) = 0; }; + /// MCAsmParser - Generic assembler parser interface, for use by target specific /// assembly parsers. class MCAsmParser { public: typedef bool (*DirectiveHandler)(MCAsmParserExtension*, StringRef, SMLoc); + typedef std::pair<MCAsmParserExtension*, DirectiveHandler> + ExtensionDirectiveHandler; private: MCAsmParser(const MCAsmParser &) LLVM_DELETED_FUNCTION; @@ -61,9 +65,8 @@ protected: // Can only create subclasses. public: virtual ~MCAsmParser(); - virtual void AddDirectiveHandler(MCAsmParserExtension *Object, - StringRef Directive, - DirectiveHandler Handler) = 0; + virtual void addDirectiveHandler(StringRef Directive, + ExtensionDirectiveHandler Handler) = 0; virtual SourceMgr &getSourceManager() = 0; @@ -89,8 +92,8 @@ public: virtual void setParsingInlineAsm(bool V) = 0; virtual bool isParsingInlineAsm() = 0; - /// ParseMSInlineAsm - Parse ms-style inline assembly. - virtual bool ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, + /// parseMSInlineAsm - Parse ms-style inline assembly. + virtual bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool> > &OpDecls, SmallVectorImpl<std::string> &Constraints, @@ -123,42 +126,50 @@ public: bool TokError(const Twine &Msg, ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()); - /// ParseIdentifier - Parse an identifier or string (as a quoted identifier) + /// parseIdentifier - Parse an identifier or string (as a quoted identifier) /// and set \p Res to the identifier contents. - virtual bool ParseIdentifier(StringRef &Res) = 0; + virtual bool parseIdentifier(StringRef &Res) = 0; /// \brief Parse up to the end of statement and return the contents from the /// current token until the end of the statement; the current token on exit /// will be either the EndOfStatement or EOF. - virtual StringRef ParseStringToEndOfStatement() = 0; + virtual StringRef parseStringToEndOfStatement() = 0; - /// EatToEndOfStatement - Skip to the end of the current statement, for error + /// parseEscapedString - Parse the current token as a string which may include + /// escaped characters and return the string contents. + virtual bool parseEscapedString(std::string &Data) = 0; + + /// eatToEndOfStatement - Skip to the end of the current statement, for error /// recovery. - virtual void EatToEndOfStatement() = 0; + virtual void eatToEndOfStatement() = 0; - /// ParseExpression - Parse an arbitrary expression. + /// parseExpression - Parse an arbitrary expression. /// /// @param Res - The value of the expression. The result is undefined /// on error. /// @result - False on success. - virtual bool ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; - bool ParseExpression(const MCExpr *&Res); + virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; + bool parseExpression(const MCExpr *&Res); - /// ParseParenExpression - Parse an arbitrary expression, assuming that an + /// parseParenExpression - Parse an arbitrary expression, assuming that an /// initial '(' has already been consumed. /// /// @param Res - The value of the expression. The result is undefined /// on error. /// @result - False on success. - virtual bool ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; + virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; - /// ParseAbsoluteExpression - Parse an expression which must evaluate to an + /// parseAbsoluteExpression - Parse an expression which must evaluate to an /// absolute value. /// /// @param Res - The value of the absolute expression. The result is undefined /// on error. /// @result - False on success. - virtual bool ParseAbsoluteExpression(int64_t &Res) = 0; + virtual bool parseAbsoluteExpression(int64_t &Res) = 0; + + /// checkForValidSection - 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. diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h index 84b33b5..2eda3a9 100644 --- a/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCASMPARSEREXTENSION_H -#define LLVM_MC_MCASMPARSEREXTENSION_H +#ifndef LLVM_MC_MCPARSER_MCASMPARSEREXTENSION_H +#define LLVM_MC_MCPARSER_MCASMPARSEREXTENSION_H #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCParser/MCAsmParser.h" diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h index 60e7887..c78cd97 100644 --- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCASMOPERAND_H -#define LLVM_MC_MCASMOPERAND_H +#ifndef LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H +#define LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H namespace llvm { class SMLoc; @@ -70,6 +70,10 @@ public: /// care of the rewrites. Only valid when parsing MS-style inline assembly. virtual bool needAsmRewrite() const { return true; } + /// needAddressOf - Do we need to emit code to get the address of the + /// variable/label? Only valid when parsing MS-style inline assembly. + virtual bool needAddressOf() const { return false; } + /// isOffsetOf - Do we need to emit code to get the offset of the variable, /// rather then the value of the variable? Only valid when parsing MS-style /// inline assembly. diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h index 0c71ee5..defa299 100644 --- a/include/llvm/MC/MCSchedule.h +++ b/include/llvm/MC/MCSchedule.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCSCHEDMODEL_H -#define LLVM_MC_MCSCHEDMODEL_H +#ifndef LLVM_MC_MCSCHEDULE_H +#define LLVM_MC_MCSCHEDULE_H #include "llvm/Support/DataTypes.h" #include <cassert> @@ -155,7 +155,7 @@ public: // Optional InstrItinerary OperandCycles provides expected latency. // TODO: can't yet specify both min and expected latency per operand. int MinLatency; - static const unsigned DefaultMinLatency = -1; + static const int DefaultMinLatency = -1; // LoadLatency is the expected latency of load instructions. // @@ -172,6 +172,16 @@ public: unsigned HighLatency; static const unsigned DefaultHighLatency = 10; + // ILPWindow is the number of cycles that the scheduler effectively ignores + // before attempting to hide latency. This should be zero for in-order cpus to + // always hide expected latency. For out-of-order cpus, it may be tweaked as + // desired to roughly approximate instruction buffers. The actual threshold is + // not very important for an OOO processor, as long as it isn't too high. A + // nonzero value helps avoid rescheduling to hide latency when its is fairly + // obviously useless and makes register pressure heuristics more effective. + unsigned ILPWindow; + static const unsigned DefaultILPWindow = 0; + // MispredictPenalty is the typical number of extra cycles the processor // takes to recover from a branch misprediction. unsigned MispredictPenalty; @@ -196,6 +206,7 @@ public: MinLatency(DefaultMinLatency), LoadLatency(DefaultLoadLatency), HighLatency(DefaultHighLatency), + ILPWindow(DefaultILPWindow), MispredictPenalty(DefaultMispredictPenalty), ProcID(0), ProcResourceTable(0), SchedClassTable(0), NumProcResourceKinds(0), NumSchedClasses(0), @@ -205,12 +216,12 @@ public: } // Table-gen driven ctor. - MCSchedModel(unsigned iw, int ml, unsigned ll, unsigned hl, unsigned mp, - unsigned pi, const MCProcResourceDesc *pr, + MCSchedModel(unsigned iw, int ml, unsigned ll, unsigned hl, unsigned ilp, + unsigned mp, unsigned pi, const MCProcResourceDesc *pr, const MCSchedClassDesc *sc, unsigned npr, unsigned nsc, const InstrItinerary *ii): IssueWidth(iw), MinLatency(ml), LoadLatency(ll), HighLatency(hl), - MispredictPenalty(mp), ProcID(pi), ProcResourceTable(pr), + ILPWindow(ilp), MispredictPenalty(mp), ProcID(pi), ProcResourceTable(pr), SchedClassTable(sc), NumProcResourceKinds(npr), NumSchedClasses(nsc), InstrItineraries(ii) {} diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 05a33c5..d247066 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -16,10 +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/MCWin64EH.h" #include "llvm/Support/DataTypes.h" +#include <string> namespace llvm { class MCAsmBackend; @@ -45,6 +47,23 @@ namespace llvm { /// a .s file, and implementations that write out .o files of various formats. /// class MCStreamer { + public: + enum StreamerKind { + SK_AsmStreamer, + SK_NullStreamer, + SK_RecordStreamer, + + // MCObjectStreamer subclasses. + SK_ELFStreamer, + SK_ARMELFStreamer, + SK_MachOStreamer, + SK_PureStreamer, + SK_MipsELFStreamer, + SK_WinCOFFStreamer + }; + + private: + const StreamerKind Kind; MCContext &Context; MCStreamer(const MCStreamer&) LLVM_DELETED_FUNCTION; @@ -73,7 +92,7 @@ namespace llvm { bool AutoInitSections; protected: - MCStreamer(MCContext &Ctx); + MCStreamer(StreamerKind Kind, MCContext &Ctx); const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, const MCSymbol *B); @@ -92,6 +111,8 @@ namespace llvm { public: virtual ~MCStreamer(); + StreamerKind getKind() const { return Kind; } + /// State management /// virtual void reset(); @@ -234,6 +255,9 @@ namespace llvm { /// InitSections - Create the default sections and set the initial one. virtual void InitSections() = 0; + /// InitToTextSection - Create a text section and switch the streamer to it. + virtual void InitToTextSection() = 0; + /// EmitLabel - Emit a label for @p Symbol into the current section. /// /// This corresponds to an assembler statement such as: @@ -252,6 +276,10 @@ namespace llvm { /// EmitAssemblerFlag - Note in the output the specified @p Flag. virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; + /// EmitLinkerOptions - 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. virtual void EmitDataRegion(MCDataRegionType Kind) {} @@ -259,6 +287,9 @@ namespace llvm { /// a Thumb mode function (ARM target only). virtual void EmitThumbFunc(MCSymbol *Func) = 0; + /// getOrCreateSymbolData - Get symbol data for given symbol. + virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); + /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. /// /// This corresponds to an assembler statement such as: @@ -366,7 +397,7 @@ namespace llvm { /// /// This is used to implement assembler directives such as .byte, .ascii, /// etc. - virtual void EmitBytes(StringRef Data, unsigned AddrSpace) = 0; + virtual void EmitBytes(StringRef Data, unsigned AddrSpace = 0) = 0; /// EmitValue - Emit the expression @p Value into the output as a native /// integer of the given @p Size bytes. @@ -400,8 +431,8 @@ namespace llvm { /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. - void EmitULEB128IntValue(uint64_t Value, unsigned AddrSpace = 0, - unsigned Padding = 0); + void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0, + unsigned AddrSpace = 0); /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. @@ -429,11 +460,11 @@ namespace llvm { /// EmitFill - 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, - unsigned AddrSpace); + unsigned AddrSpace = 0); /// EmitZeros - Emit NumBytes worth of zeros. This is a convenience /// function that just wraps EmitFill. - void EmitZeros(uint64_t NumBytes, unsigned AddrSpace) { + void EmitZeros(uint64_t NumBytes, unsigned AddrSpace = 0) { EmitFill(NumBytes, 0, AddrSpace); } diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index 483a80b..4c5b176 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -22,6 +22,7 @@ class MCInst; template <typename T> class SmallVectorImpl; enum AsmRewriteKind { + AOK_Align, // Rewrite align as .align. AOK_DotOperator, // Rewrite a dot operator expression as an immediate. // E.g., [eax].foo.bar -> [eax].8 AOK_Emit, // Rewrite _emit as .byte. @@ -142,6 +143,15 @@ public: MCStreamer &Out, unsigned &ErrorInfo, bool MatchingInlineAsm) = 0; + /// Allow a target to add special case operand matching for things that + /// tblgen doesn't/can't handle effectively. For example, literal + /// immediates on ARM. TableGen expects a token operand, but the parser + /// will recognize them as immediates. + virtual unsigned validateTargetOperandClass(MCParsedAsmOperand *Op, + unsigned Kind) { + return Match_InvalidOperand; + } + /// checkTargetMatchPredicate - Validate the instruction match against /// any complex target predicates not expressible via match classes. virtual unsigned checkTargetMatchPredicate(MCInst &Inst) { diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index 8046efd..e2478f6 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -14,22 +14,78 @@ #ifndef LLVM_OBJECT_ARCHIVE_H #define LLVM_OBJECT_ARCHIVE_H +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include "llvm/Object/Binary.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" namespace llvm { namespace object { +struct ArchiveMemberHeader { + char Name[16]; + char LastModified[12]; + char UID[6]; + char GID[6]; + char AccessMode[8]; + char Size[10]; ///< Size of data, not including header or padding. + char Terminator[2]; + + ///! Get the name without looking up long names. + llvm::StringRef getName() const { + char EndCond; + if (Name[0] == '/' || Name[0] == '#') + EndCond = ' '; + else + EndCond = '/'; + llvm::StringRef::size_type end = + llvm::StringRef(Name, sizeof(Name)).find(EndCond); + if (end == llvm::StringRef::npos) + end = sizeof(Name); + assert(end <= sizeof(Name) && end > 0); + // Don't include the EndCond if there is one. + return llvm::StringRef(Name, end); + } + + uint64_t getSize() const { + uint64_t ret; + if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, ret)) + llvm_unreachable("Size is not an integer."); + return ret; + } +}; + +static const ArchiveMemberHeader *ToHeader(const char *base) { + return reinterpret_cast<const ArchiveMemberHeader *>(base); +} class Archive : public Binary { virtual void anchor(); public: class Child { const Archive *Parent; + /// \brief Includes header but not padding byte. StringRef Data; + /// \brief Offset from Data to the start of the file. + uint16_t StartOfFile; public: - Child(const Archive *p, StringRef d) : Parent(p), Data(d) {} + Child(const Archive *p, StringRef d) : Parent(p), Data(d) { + if (!p || d.empty()) + return; + // Setup StartOfFile and PaddingBytes. + StartOfFile = sizeof(ArchiveMemberHeader); + // Don't include attached name. + StringRef Name = ToHeader(Data.data())->getName(); + if (Name.startswith("#1/")) { + uint64_t NameSize; + if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize)) + llvm_unreachable("Long name length is not an integer"); + StartOfFile += NameSize; + } + } bool operator ==(const Child &other) const { return (Parent == other.Parent) && (Data.begin() == other.Data.begin()); @@ -39,16 +95,48 @@ public: return Data.begin() < other.Data.begin(); } - Child getNext() const; + Child getNext() const { + size_t SpaceToSkip = Data.size(); + // If it's odd, add 1 to make it even. + if (SpaceToSkip & 1) + ++SpaceToSkip; + + const char *NextLoc = Data.data() + SpaceToSkip; + + // Check to see if this is past the end of the archive. + if (NextLoc >= Parent->Data->getBufferEnd()) + return Child(Parent, StringRef(0, 0)); + + size_t NextSize = + sizeof(ArchiveMemberHeader) + ToHeader(NextLoc)->getSize(); + + return Child(Parent, StringRef(NextLoc, NextSize)); + } + error_code getName(StringRef &Result) const; int getLastModified() const; int getUID() const; int getGID() const; int getAccessMode() const; - ///! Return the size of the archive member without the header or padding. - uint64_t getSize() const; + /// \return the size of the archive member without the header or padding. + uint64_t getSize() const { return Data.size() - StartOfFile; } + + StringRef getBuffer() const { + return StringRef(Data.data() + StartOfFile, getSize()); + } + + error_code getMemoryBuffer(OwningPtr<MemoryBuffer> &Result, + bool FullPath = false) const { + StringRef Name; + if (error_code ec = getName(Name)) + return ec; + SmallString<128> Path; + Result.reset(MemoryBuffer::getMemBuffer( + getBuffer(), FullPath ? (Twine(Parent->getFileName()) + "(" + Name + + ")").toStringRef(Path) : Name, false)); + return error_code::success(); + } - MemoryBuffer *getBuffer() const; error_code getAsBinary(OwningPtr<Binary> &Result) const; }; diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index d555de3..8bbcd8b 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -49,8 +49,8 @@ protected: ID_EndObjects }; - static inline unsigned int getELFType(bool isLittleEndian, bool is64Bits) { - if (isLittleEndian) + static inline unsigned int getELFType(bool isLE, bool is64Bits) { + if (isLE) return is64Bits ? ID_ELF64L : ID_ELF32L; else return is64Bits ? ID_ELF64B : ID_ELF32B; @@ -85,6 +85,10 @@ public: bool isCOFF() const { return TypeID == ID_COFF; } + + bool isLittleEndian() const { + return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B); + } }; /// @brief Create a Binary from Source, autodetecting the file type. diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index aa26d17..d5ff6f9 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -37,6 +37,13 @@ namespace object { using support::endianness; +template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +struct ELFType { + static const endianness TargetEndianness = target_endianness; + static const std::size_t MaxAlignment = max_alignment; + static const bool Is64Bits = is64Bits; +}; + template<typename T, int max_align> struct MaximumAlignment { enum {value = AlignOf<T>::Alignment > max_align ? max_align @@ -72,59 +79,59 @@ struct ELFDataTypeTypedefHelperCommon { MaximumAlignment<int64_t, max_alignment>::value> Elf_Sxword; }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct ELFDataTypeTypedefHelper; /// ELF 32bit types. -template<endianness target_endianness, std::size_t max_alignment> -struct ELFDataTypeTypedefHelper<target_endianness, max_alignment, false> - : ELFDataTypeTypedefHelperCommon<target_endianness, max_alignment> { +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct ELFDataTypeTypedefHelper<ELFT<TargetEndianness, MaxAlign, false> > + : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { typedef uint32_t value_type; typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, - MaximumAlignment<value_type, max_alignment>::value> Elf_Addr; + <value_type, TargetEndianness, + MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr; typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, - MaximumAlignment<value_type, max_alignment>::value> Elf_Off; + <value_type, TargetEndianness, + MaximumAlignment<value_type, MaxAlign>::value> Elf_Off; }; /// ELF 64bit types. -template<endianness target_endianness, std::size_t max_alignment> -struct ELFDataTypeTypedefHelper<target_endianness, max_alignment, true> - : ELFDataTypeTypedefHelperCommon<target_endianness, max_alignment>{ +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct ELFDataTypeTypedefHelper<ELFT<TargetEndianness, MaxAlign, true> > + : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { typedef uint64_t value_type; typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, - MaximumAlignment<value_type, max_alignment>::value> Elf_Addr; + <value_type, TargetEndianness, + MaximumAlignment<value_type, MaxAlign>::value> Elf_Addr; typedef support::detail::packed_endian_specific_integral - <value_type, target_endianness, - MaximumAlignment<value_type, max_alignment>::value> Elf_Off; + <value_type, TargetEndianness, + MaximumAlignment<value_type, MaxAlign>::value> Elf_Off; }; // I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Addr Elf_Addr; \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Off Elf_Off; \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Half Elf_Half; \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Word Elf_Word; \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Sword Elf_Sword; \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Xword Elf_Xword; \ -typedef typename ELFDataTypeTypedefHelper \ - <target_endianness, max_alignment, is64Bits>::Elf_Sxword Elf_Sxword; +#define LLVM_ELF_IMPORT_TYPES(ELFT) \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Addr Elf_Addr; \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Off Elf_Off; \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Half Elf_Half; \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Word Elf_Word; \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Sword Elf_Sword; \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Xword Elf_Xword; \ +typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Sxword Elf_Sxword; + +// This is required to get template types into a macro :( +#define LLVM_ELF_COMMA , // Section header. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Shdr_Base; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Shdr_Base<target_endianness, max_alignment, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Shdr_Base<ELFT<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Word sh_flags; // Section flags (SHF_*) @@ -137,9 +144,11 @@ struct Elf_Shdr_Base<target_endianness, max_alignment, false> { Elf_Word sh_entsize; // Size of records contained within the section }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Shdr_Base<target_endianness, max_alignment, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Shdr_Base<ELFT<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Xword sh_flags; // Section flags (SHF_*) @@ -152,11 +161,10 @@ struct Elf_Shdr_Base<target_endianness, max_alignment, true> { Elf_Xword sh_entsize; // Size of records contained within the section }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -struct Elf_Shdr_Impl - : Elf_Shdr_Base<target_endianness, max_alignment, is64Bits> { - using Elf_Shdr_Base<target_endianness, max_alignment, is64Bits>::sh_entsize; - using Elf_Shdr_Base<target_endianness, max_alignment, is64Bits>::sh_size; +template<class ELFT> +struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> { + using Elf_Shdr_Base<ELFT>::sh_entsize; + using Elf_Shdr_Base<ELFT>::sh_size; /// @brief Get the number of entities this section contains if it has any. unsigned getEntityCount() const { @@ -166,14 +174,14 @@ struct Elf_Shdr_Impl } }; -template< endianness target_endianness - , std::size_t max_alignment - , bool is64Bits> +template<class ELFT> struct Elf_Sym_Base; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Sym_Base<target_endianness, max_alignment, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Sym_Base<ELFT<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) Elf_Word st_name; // Symbol name (index into string table) Elf_Addr st_value; // Value or address associated with the symbol Elf_Word st_size; // Size of the symbol @@ -182,9 +190,11 @@ struct Elf_Sym_Base<target_endianness, max_alignment, false> { Elf_Half st_shndx; // Which section (header table index) it's defined in }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Sym_Base<target_endianness, max_alignment, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Sym_Base<ELFT<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) Elf_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes unsigned char st_other; // Must be zero; reserved @@ -193,10 +203,9 @@ struct Elf_Sym_Base<target_endianness, max_alignment, true> { Elf_Xword st_size; // Size of the symbol }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -struct Elf_Sym_Impl - : Elf_Sym_Base<target_endianness, max_alignment, is64Bits> { - using Elf_Sym_Base<target_endianness, max_alignment, is64Bits>::st_info; +template<class ELFT> +struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { + using Elf_Sym_Base<ELFT>::st_info; // These accessors and mutators correspond to the ELF32_ST_BIND, // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: @@ -211,22 +220,21 @@ struct Elf_Sym_Impl /// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section /// (.gnu.version). This structure is identical for ELF32 and ELF64. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Versym_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES(ELFT) Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Verdaux_Impl; /// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section /// (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Verdef_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) - typedef - Elf_Verdaux_Impl<target_endianness, max_alignment, is64Bits> Elf_Verdaux; + LLVM_ELF_IMPORT_TYPES(ELFT) + typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux; Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) Elf_Half vd_ndx; // Version index, used in .gnu.version entries @@ -243,18 +251,18 @@ struct Elf_Verdef_Impl { /// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef /// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Verdaux_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES(ELFT) Elf_Word vda_name; // Version name (offset in string table) Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) }; /// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Verneed_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES(ELFT) Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) Elf_Half vn_cnt; // Number of associated Vernaux entries Elf_Word vn_file; // Library name (string table offset) @@ -264,9 +272,9 @@ struct Elf_Verneed_Impl { /// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Vernaux_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES(ELFT) Elf_Word vna_hash; // Hash of dependency name Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) Elf_Half vna_other; // Version index, used in .gnu.version entries @@ -276,12 +284,14 @@ struct Elf_Vernaux_Impl { /// Elf_Dyn_Base: This structure matches the form of entries in the dynamic /// table section (.dynamic) look like. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Dyn_Base; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Dyn_Base<target_endianness, max_alignment, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Dyn_Base<ELFT<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) Elf_Sword d_tag; union { Elf_Word d_val; @@ -289,9 +299,11 @@ struct Elf_Dyn_Base<target_endianness, max_alignment, false> { } d_un; }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Dyn_Base<target_endianness, max_alignment, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Dyn_Base<ELFT<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) Elf_Sxword d_tag; union { Elf_Xword d_val; @@ -300,92 +312,67 @@ struct Elf_Dyn_Base<target_endianness, max_alignment, true> { }; /// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters and setters. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -struct Elf_Dyn_Impl : Elf_Dyn_Base<target_endianness, max_alignment, is64Bits> { - using Elf_Dyn_Base<target_endianness, max_alignment, is64Bits>::d_tag; - using Elf_Dyn_Base<target_endianness, max_alignment, is64Bits>::d_un; +template<class ELFT> +struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> { + using Elf_Dyn_Base<ELFT>::d_tag; + using Elf_Dyn_Base<ELFT>::d_un; int64_t getTag() const { return d_tag; } uint64_t getVal() const { return d_un.d_val; } uint64_t getPtr() const { return d_un.ptr; } }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -class ELFObjectFile; - -// DynRefImpl: Reference to an entry in the dynamic table -// This is an ELF-specific interface. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -class DynRefImpl { - typedef Elf_Dyn_Impl<target_endianness, max_alignment, is64Bits> Elf_Dyn; - typedef ELFObjectFile<target_endianness, max_alignment, is64Bits> OwningType; - - DataRefImpl DynPimpl; - const OwningType *OwningObject; - -public: - DynRefImpl() : OwningObject(NULL) { } - - DynRefImpl(DataRefImpl DynP, const OwningType *Owner); - - bool operator==(const DynRefImpl &Other) const; - bool operator <(const DynRefImpl &Other) const; - - error_code getNext(DynRefImpl &Result) const; - int64_t getTag() const; - uint64_t getVal() const; - uint64_t getPtr() const; - - DataRefImpl getRawDataRefImpl() const; -}; - // Elf_Rel: Elf Relocation -template< endianness target_endianness - , std::size_t max_alignment - , bool is64Bits - , bool isRela> +template<class ELFT, bool isRela> struct Elf_Rel_Base; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Rel_Base<target_endianness, max_alignment, false, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, false> { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Word r_info; // Symbol table index and type of relocation to apply }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Rel_Base<target_endianness, max_alignment, true, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, false> { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Xword r_info; // Symbol table index and type of relocation to apply }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Rel_Base<target_endianness, max_alignment, false, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, true> { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Word r_info; // Symbol table index and type of relocation to apply Elf_Sword r_addend; // Compute value for relocatable field by adding this }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Rel_Base<target_endianness, max_alignment, true, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, true> { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Xword r_info; // Symbol table index and type of relocation to apply Elf_Sxword r_addend; // Compute value for relocatable field by adding this. }; -template< endianness target_endianness - , std::size_t max_alignment - , bool is64Bits - , bool isRela> +template<class ELFT, bool isRela> struct Elf_Rel_Impl; -template<endianness target_endianness, std::size_t max_alignment, bool isRela> -struct Elf_Rel_Impl<target_endianness, max_alignment, true, isRela> - : Elf_Rel_Base<target_endianness, max_alignment, true, isRela> { - using Elf_Rel_Base<target_endianness, max_alignment, true, isRela>::r_info; - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign, bool isRela> +struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, true>, isRela> + : Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, isRela> { + using Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, isRela>::r_info; + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: @@ -400,11 +387,13 @@ struct Elf_Rel_Impl<target_endianness, max_alignment, true, isRela> } }; -template<endianness target_endianness, std::size_t max_alignment, bool isRela> -struct Elf_Rel_Impl<target_endianness, max_alignment, false, isRela> - : Elf_Rel_Base<target_endianness, max_alignment, false, isRela> { - using Elf_Rel_Base<target_endianness, max_alignment, false, isRela>::r_info; - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign, bool isRela> +struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, false>, isRela> + : Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, isRela> { + using Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, isRela>::r_info; + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, // and ELF32_R_INFO macros defined in the ELF specification: @@ -417,9 +406,9 @@ struct Elf_Rel_Impl<target_endianness, max_alignment, false, isRela> } }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Ehdr_Impl { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) + LLVM_ELF_IMPORT_TYPES(ELFT) unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes Elf_Half e_type; // Type of file (see ET_*) Elf_Half e_machine; // Required architecture for this file (see EM_*) @@ -442,12 +431,14 @@ struct Elf_Ehdr_Impl { unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> struct Elf_Phdr_Impl; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Phdr_Impl<target_endianness, max_alignment, false> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, false) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Phdr_Impl<ELFT<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA false>) Elf_Word p_type; // Type of segment Elf_Off p_offset; // FileOffset where segment is located, in bytes Elf_Addr p_vaddr; // Virtual Address of beginning of segment @@ -458,9 +449,11 @@ struct Elf_Phdr_Impl<target_endianness, max_alignment, false> { Elf_Word p_align; // Segment alignment constraint }; -template<endianness target_endianness, std::size_t max_alignment> -struct Elf_Phdr_Impl<target_endianness, max_alignment, true> { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, true) +template<template<endianness, std::size_t, bool> class ELFT, + endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Phdr_Impl<ELFT<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA + MaxAlign LLVM_ELF_COMMA true>) Elf_Word p_type; // Type of segment Elf_Word p_flags; // Segment flags Elf_Off p_offset; // FileOffset where segment is located, in bytes @@ -471,72 +464,18 @@ struct Elf_Phdr_Impl<target_endianness, max_alignment, true> { Elf_Xword p_align; // Segment alignment constraint }; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> class ELFObjectFile : public ObjectFile { - LLVM_ELF_IMPORT_TYPES(target_endianness, max_alignment, is64Bits) - - typedef Elf_Ehdr_Impl<target_endianness, max_alignment, is64Bits> Elf_Ehdr; - typedef Elf_Shdr_Impl<target_endianness, max_alignment, is64Bits> Elf_Shdr; - typedef Elf_Sym_Impl<target_endianness, max_alignment, is64Bits> Elf_Sym; - typedef Elf_Dyn_Impl<target_endianness, max_alignment, is64Bits> Elf_Dyn; - typedef Elf_Phdr_Impl<target_endianness, max_alignment, is64Bits> Elf_Phdr; - typedef - Elf_Rel_Impl<target_endianness, max_alignment, is64Bits, false> Elf_Rel; - typedef - Elf_Rel_Impl<target_endianness, max_alignment, is64Bits, true> Elf_Rela; - typedef - Elf_Verdef_Impl<target_endianness, max_alignment, is64Bits> Elf_Verdef; - typedef - Elf_Verdaux_Impl<target_endianness, max_alignment, is64Bits> Elf_Verdaux; - typedef - Elf_Verneed_Impl<target_endianness, max_alignment, is64Bits> Elf_Verneed; - typedef - Elf_Vernaux_Impl<target_endianness, max_alignment, is64Bits> Elf_Vernaux; - typedef - Elf_Versym_Impl<target_endianness, max_alignment, is64Bits> Elf_Versym; - typedef DynRefImpl<target_endianness, max_alignment, is64Bits> DynRef; - typedef content_iterator<DynRef> dyn_iterator; - -protected: - // 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. - bool isDyldELFObject; - -private: - typedef SmallVector<const Elf_Shdr*, 1> Sections_t; - typedef DenseMap<unsigned, unsigned> IndexMap_t; - typedef DenseMap<const Elf_Shdr*, SmallVector<uint32_t, 1> > RelocMap_t; - - const Elf_Ehdr *Header; - const Elf_Shdr *SectionHeaderTable; - const Elf_Shdr *dot_shstrtab_sec; // Section header string table. - const Elf_Shdr *dot_strtab_sec; // Symbol header string table. - const Elf_Shdr *dot_dynstr_sec; // Dynamic symbol string table. - - // SymbolTableSections[0] always points to the dynamic string table section - // header, or NULL if there is no dynamic string table. - Sections_t SymbolTableSections; - IndexMap_t SymbolTableSectionsIndexMap; - DenseMap<const Elf_Sym*, ELF::Elf64_Word> ExtendedSymbolTable; - - const Elf_Shdr *dot_dynamic_sec; // .dynamic - const Elf_Shdr *dot_gnu_version_sec; // .gnu.version - const Elf_Shdr *dot_gnu_version_r_sec; // .gnu.version_r - const Elf_Shdr *dot_gnu_version_d_sec; // .gnu.version_d - - // Pointer to SONAME entry in dynamic string table - // This is set the first time getLoadName is called. - mutable const char *dt_soname; + LLVM_ELF_IMPORT_TYPES(ELFT) public: /// \brief Iterate over constant sized entities. template<class EntT> class ELFEntityIterator { public: - typedef void difference_type; + typedef ptrdiff_t difference_type; typedef EntT value_type; - typedef std::forward_iterator_tag iterator_category; + typedef std::random_access_iterator_tag iterator_category; typedef value_type &reference; typedef value_type *pointer; @@ -576,11 +515,74 @@ public: 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 EntitiySize!"); + return (Current - Other.Current) / EntitySize; + } + + const char *get() const { return Current; } + private: - const uint64_t EntitySize; + uint64_t EntitySize; const char *Current; }; + typedef Elf_Ehdr_Impl<ELFT> Elf_Ehdr; + typedef Elf_Shdr_Impl<ELFT> Elf_Shdr; + typedef Elf_Sym_Impl<ELFT> Elf_Sym; + typedef Elf_Dyn_Impl<ELFT> Elf_Dyn; + typedef Elf_Phdr_Impl<ELFT> Elf_Phdr; + typedef Elf_Rel_Impl<ELFT, false> Elf_Rel; + typedef Elf_Rel_Impl<ELFT, true> Elf_Rela; + typedef Elf_Verdef_Impl<ELFT> Elf_Verdef; + typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux; + typedef Elf_Verneed_Impl<ELFT> Elf_Verneed; + typedef Elf_Vernaux_Impl<ELFT> Elf_Vernaux; + typedef Elf_Versym_Impl<ELFT> Elf_Versym; + typedef ELFEntityIterator<const Elf_Dyn> Elf_Dyn_iterator; + typedef ELFEntityIterator<const Elf_Sym> Elf_Sym_iterator; + typedef ELFEntityIterator<const Elf_Rela> Elf_Rela_Iter; + typedef ELFEntityIterator<const Elf_Rel> Elf_Rel_Iter; + +protected: + // 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. + bool isDyldELFObject; + +private: + typedef SmallVector<const Elf_Shdr *, 2> Sections_t; + typedef DenseMap<unsigned, unsigned> IndexMap_t; + typedef DenseMap<const Elf_Shdr*, SmallVector<uint32_t, 1> > RelocMap_t; + + const Elf_Ehdr *Header; + const Elf_Shdr *SectionHeaderTable; + const Elf_Shdr *dot_shstrtab_sec; // Section header string table. + const Elf_Shdr *dot_strtab_sec; // Symbol header string table. + const Elf_Shdr *dot_dynstr_sec; // Dynamic symbol string table. + + // SymbolTableSections[0] always points to the dynamic string table section + // header, or NULL if there is no dynamic string table. + Sections_t SymbolTableSections; + IndexMap_t SymbolTableSectionsIndexMap; + DenseMap<const Elf_Sym*, ELF::Elf64_Word> ExtendedSymbolTable; + + const Elf_Shdr *dot_dynamic_sec; // .dynamic + const Elf_Shdr *dot_gnu_version_sec; // .gnu.version + const Elf_Shdr *dot_gnu_version_r_sec; // .gnu.version_r + const Elf_Shdr *dot_gnu_version_d_sec; // .gnu.version_d + + // Pointer to SONAME entry in dynamic string table + // This is set the first time getLoadName is called. + mutable const char *dt_soname; + private: // Records for each version index the corresponding Verdef or Vernaux entry. // This is filled the first time LoadVersionMap() is called. @@ -617,6 +619,7 @@ private: return getSection(Rel.w.b); } +public: bool isRelocationHasAddend(DataRefImpl Rel) const; template<typename T> const T *getEntry(uint16_t Section, uint32_t Entry) const; @@ -661,9 +664,6 @@ protected: section_iterator &Res) const; virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - friend class DynRefImpl<target_endianness, max_alignment, is64Bits>; - virtual error_code getDynNext(DataRefImpl DynData, DynRef &Result) const; - virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; @@ -717,11 +717,34 @@ public: virtual library_iterator begin_libraries_needed() const; virtual library_iterator end_libraries_needed() const; - virtual dyn_iterator begin_dynamic_table() const; - virtual dyn_iterator end_dynamic_table() const; + const Elf_Shdr *getDynamicSymbolTableSectionHeader() const { + return SymbolTableSections[0]; + } - typedef ELFEntityIterator<const Elf_Rela> Elf_Rela_Iter; - typedef ELFEntityIterator<const Elf_Rel> Elf_Rel_Iter; + const Elf_Shdr *getDynamicStringTableSectionHeader() const { + return dot_dynstr_sec; + } + + Elf_Dyn_iterator begin_dynamic_table() const; + /// \param NULLEnd use one past the first DT_NULL entry as the end instead of + /// the section size. + Elf_Dyn_iterator end_dynamic_table(bool NULLEnd = false) const; + + Elf_Sym_iterator begin_elf_dynamic_symbols() const { + const Elf_Shdr *DynSymtab = SymbolTableSections[0]; + if (DynSymtab) + return Elf_Sym_iterator(DynSymtab->sh_entsize, + (const char *)base() + DynSymtab->sh_offset); + return Elf_Sym_iterator(0, 0); + } + + Elf_Sym_iterator end_elf_dynamic_symbols() const { + const Elf_Shdr *DynSymtab = SymbolTableSections[0]; + if (DynSymtab) + return Elf_Sym_iterator(DynSymtab->sh_entsize, (const char *)base() + + DynSymtab->sh_offset + DynSymtab->sh_size); + return Elf_Sym_iterator(0, 0); + } Elf_Rela_Iter beginELFRela(const Elf_Shdr *sec) const { return Elf_Rela_Iter(sec->sh_entsize, @@ -777,16 +800,15 @@ public: // Methods for type inquiry through isa, cast, and dyn_cast bool isDyldType() const { return isDyldELFObject; } static inline bool classof(const Binary *v) { - return v->getType() == getELFType(target_endianness == support::little, - is64Bits); + return v->getType() == getELFType(ELFT::TargetEndianness == support::little, + ELFT::Is64Bits); } }; // Iterate through the version definitions, and place each Elf_Verdef // in the VersionMap according to its index. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -void ELFObjectFile<target_endianness, max_alignment, is64Bits>:: - LoadVersionDefs(const Elf_Shdr *sec) const { +template<class ELFT> +void ELFObjectFile<ELFT>::LoadVersionDefs(const Elf_Shdr *sec) const { unsigned vd_size = sec->sh_size; // Size of section in bytes unsigned vd_count = sec->sh_info; // Number of Verdef entries const char *sec_start = (const char*)base() + sec->sh_offset; @@ -810,9 +832,8 @@ void ELFObjectFile<target_endianness, max_alignment, is64Bits>:: // Iterate through the versions needed section, and place each Elf_Vernaux // in the VersionMap according to its index. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -void ELFObjectFile<target_endianness, max_alignment, is64Bits>:: - LoadVersionNeeds(const Elf_Shdr *sec) const { +template<class ELFT> +void ELFObjectFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const { unsigned vn_size = sec->sh_size; // Size of section in bytes unsigned vn_count = sec->sh_info; // Number of Verneed entries const char *sec_start = (const char*)base() + sec->sh_offset; @@ -843,9 +864,8 @@ void ELFObjectFile<target_endianness, max_alignment, is64Bits>:: } } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -void ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::LoadVersionMap() const { +template<class ELFT> +void ELFObjectFile<ELFT>::LoadVersionMap() const { // If there is no dynamic symtab or version table, there is nothing to do. if (SymbolTableSections[0] == NULL || dot_gnu_version_sec == NULL) return; @@ -866,9 +886,9 @@ void ELFObjectFile<target_endianness, max_alignment, is64Bits> LoadVersionNeeds(dot_gnu_version_r_sec); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -void ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::validateSymbol(DataRefImpl Symb) const { +template<class ELFT> +void ELFObjectFile<ELFT>::validateSymbol(DataRefImpl Symb) const { +#ifndef NDEBUG const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; // FIXME: We really need to do proper error handling in the case of an invalid @@ -883,12 +903,12 @@ void ELFObjectFile<target_endianness, max_alignment, is64Bits> + SymbolTableSection->sh_size))) // FIXME: Proper error handling. report_fatal_error("Symb must point to a valid symbol!"); +#endif } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolNext(DataRefImpl Symb, - SymbolRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolNext(DataRefImpl Symb, + SymbolRef &Result) const { validateSymbol(Symb); const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; @@ -913,20 +933,18 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolName(DataRefImpl Symb, - StringRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb, + StringRef &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); return getSymbolName(SymbolTableSections[Symb.d.b], symb, Result); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolVersion(SymbolRef SymRef, - StringRef &Version, - bool &IsDefault) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef, + StringRef &Version, + bool &IsDefault) const { DataRefImpl Symb = SymRef.getRawDataRefImpl(); validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); @@ -934,19 +952,17 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> Version, IsDefault); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -ELF::Elf64_Word ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolTableIndex(const Elf_Sym *symb) const { +template<class ELFT> +ELF::Elf64_Word ELFObjectFile<ELFT> + ::getSymbolTableIndex(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return ExtendedSymbolTable.lookup(symb); return symb->st_shndx; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Shdr * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSection(const Elf_Sym *symb) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Shdr * +ELFObjectFile<ELFT>::getSection(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return getSection(ExtendedSymbolTable.lookup(symb)); if (symb->st_shndx >= ELF::SHN_LORESERVE) @@ -954,38 +970,31 @@ ELFObjectFile<target_endianness, max_alignment, is64Bits> return getSection(symb->st_shndx); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Shdr * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getElfSection(section_iterator &It) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Shdr * +ELFObjectFile<ELFT>::getElfSection(section_iterator &It) const { llvm::object::DataRefImpl ShdrRef = It->getRawDataRefImpl(); return reinterpret_cast<const Elf_Shdr *>(ShdrRef.p); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Sym * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getElfSymbol(symbol_iterator &It) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Sym * +ELFObjectFile<ELFT>::getElfSymbol(symbol_iterator &It) const { return getSymbol(It->getRawDataRefImpl()); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Sym * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getElfSymbol(uint32_t index) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Sym * +ELFObjectFile<ELFT>::getElfSymbol(uint32_t index) const { DataRefImpl SymbolData; SymbolData.d.a = index; SymbolData.d.b = 1; return getSymbol(SymbolData); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolFileOffset(DataRefImpl Symb, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolFileOffset(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section; @@ -1003,7 +1012,7 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> switch (symb->getType()) { case ELF::STT_SECTION: - Result = Section ? Section->sh_addr : UnknownAddressOrSize; + Result = Section ? Section->sh_offset : UnknownAddressOrSize; return object_error::success; case ELF::STT_FUNC: case ELF::STT_OBJECT: @@ -1017,10 +1026,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> } } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolAddress(DataRefImpl Symb, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section; @@ -1061,10 +1069,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> } } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolSize(DataRefImpl Symb, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); if (symb->st_size == 0) @@ -1073,10 +1080,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolNMTypeChar(DataRefImpl Symb, - char &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolNMTypeChar(DataRefImpl Symb, + char &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section = getSection(symb); @@ -1138,10 +1144,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); @@ -1170,10 +1175,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolFlags(DataRefImpl Symb, - uint32_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb, + uint32_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); @@ -1205,10 +1209,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *sec = getSection(symb); @@ -1222,19 +1225,18 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolValue(DataRefImpl Symb, + uint64_t &Val) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); Val = symb->st_value; return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionNext(DataRefImpl Sec, + SectionRef &Result) const { const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p); sec += Header->e_shentsize; Sec.p = reinterpret_cast<intptr_t>(sec); @@ -1242,65 +1244,58 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionName(DataRefImpl Sec, - StringRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec, + StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionAddress(DataRefImpl Sec, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); Result = sec->sh_addr; return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionSize(DataRefImpl Sec, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); Result = sec->sh_size; return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionContents(DataRefImpl Sec, - StringRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); const char *start = (const char*)base() + sec->sh_offset; Result = StringRef(start, sec->sh_size); return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionContents(const Elf_Shdr *Sec, - StringRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionContents(const Elf_Shdr *Sec, + StringRef &Result) const { const char *start = (const char*)base() + Sec->sh_offset; Result = StringRef(start, Sec->sh_size); return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionAlignment(DataRefImpl Sec, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec, + uint64_t &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); Result = sec->sh_addralign; return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionText(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); if (sec->sh_flags & ELF::SHF_EXECINSTR) Result = true; @@ -1309,10 +1304,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionData(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && sec->sh_type == ELF::SHT_PROGBITS) @@ -1322,10 +1316,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionBSS(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && sec->sh_type == ELF::SHT_NOBITS) @@ -1335,10 +1328,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionRequiredForExecution(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionRequiredForExecution( + DataRefImpl Sec, bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); if (sec->sh_flags & ELF::SHF_ALLOC) Result = true; @@ -1347,10 +1339,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); if (sec->sh_type == ELF::SHT_NOBITS) Result = true; @@ -1359,10 +1350,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionZeroInit(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionZeroInit(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); // For ELF, all zero-init sections are virtual (that is, they occupy no space // in the object image) and vice versa. @@ -1370,10 +1360,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::isSectionReadOnlyData(DataRefImpl Sec, + bool &Result) const { const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); if (sec->sh_flags & ELF::SHF_WRITE || sec->sh_flags & ELF::SHF_EXECINSTR) Result = false; @@ -1382,19 +1371,18 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -relocation_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionRelBegin(DataRefImpl Sec) const { +template<class ELFT> +relocation_iterator +ELFObjectFile<ELFT>::getSectionRelBegin(DataRefImpl Sec) const { DataRefImpl RelData; const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); @@ -1406,9 +1394,9 @@ relocation_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> return relocation_iterator(RelocationRef(RelData, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -relocation_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionRelEnd(DataRefImpl Sec) const { +template<class ELFT> +relocation_iterator +ELFObjectFile<ELFT>::getSectionRelEnd(DataRefImpl Sec) const { DataRefImpl RelData; const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); @@ -1424,10 +1412,9 @@ relocation_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> } // Relocations -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationNext(DataRefImpl Rel, - RelocationRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationNext(DataRefImpl Rel, + RelocationRef &Result) const { ++Rel.w.c; const Elf_Shdr *relocsec = getSection(Rel.w.b); if (Rel.w.c >= (relocsec->sh_size / relocsec->sh_entsize)) { @@ -1453,10 +1440,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Result) const { uint32_t symbolIdx; const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { @@ -1481,10 +1467,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationAddress(DataRefImpl Rel, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, + uint64_t &Result) const { uint64_t offset; const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { @@ -1504,10 +1489,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationOffset(DataRefImpl Rel, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel, + uint64_t &Result) const { uint64_t offset; const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { @@ -1527,10 +1511,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationType(DataRefImpl Rel, - uint64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel, + uint64_t &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { default : @@ -1550,10 +1533,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> #define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ case ELF::enum: res = #enum; break; -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationTypeName( + DataRefImpl Rel, SmallVectorImpl<char> &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); uint32_t type; StringRef res; @@ -1654,6 +1636,86 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> res = "Unknown"; } break; + case ELF::EM_AARCH64: + switch (type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G3); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD_PREL_LO19); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_LO21); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_PG_HI21); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADD_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST8_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TSTBR14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CONDBR19); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_JUMP26); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CALL26); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST16_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST32_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST64_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST128_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_GOT_PAGE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD64_GOT_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_HI12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_HI12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADR_PAGE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_LD64_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADD_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_CALL); + + default: + res = "Unknown"; + } + break; case ELF::EM_ARM: switch (type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_NONE); @@ -1892,10 +1954,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> #undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationAdditionalInfo( + DataRefImpl Rel, int64_t &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { default : @@ -1911,10 +1972,9 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> } } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationValueString( + DataRefImpl Rel, SmallVectorImpl<char> &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); uint8_t type; StringRef res; @@ -1969,6 +2029,7 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> res = "Unknown"; } break; + case ELF::EM_AARCH64: case ELF::EM_ARM: case ELF::EM_HEXAGON: res = symname; @@ -1982,20 +2043,21 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> } // Verify that the last byte in the string table in a null. -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -void ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::VerifyStrTab(const Elf_Shdr *sh) const { +template<class ELFT> +void ELFObjectFile<ELFT>::VerifyStrTab(const Elf_Shdr *sh) const { const char *strtab = (const char*)base() + sh->sh_offset; if (strtab[sh->sh_size - 1] != 0) // FIXME: Proper error handling. report_fatal_error("String table must end with a null terminator!"); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::ELFObjectFile(MemoryBuffer *Object, error_code &ec) - : ObjectFile(getELFType(target_endianness == support::little, is64Bits), - Object, ec) +template<class ELFT> +ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) + : ObjectFile(getELFType( + static_cast<endianness>(ELFT::TargetEndianness) == support::little, + ELFT::Is64Bits), + Object, + ec) , isDyldELFObject(false) , SectionHeaderTable(0) , dot_shstrtab_sec(0) @@ -2153,9 +2215,8 @@ ELFObjectFile<target_endianness, max_alignment, is64Bits> } // Get the symbol table index in the symtab section given a symbol -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -uint64_t ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolIndex(const Elf_Sym *Sym) const { +template<class ELFT> +uint64_t ELFObjectFile<ELFT>::getSymbolIndex(const Elf_Sym *Sym) const { assert(SymbolTableSections.size() == 1 && "Only one symbol table supported!"); const Elf_Shdr *SymTab = *SymbolTableSections.begin(); uintptr_t SymLoc = uintptr_t(Sym); @@ -2167,9 +2228,8 @@ uint64_t ELFObjectFile<target_endianness, max_alignment, is64Bits> return SymOffset / SymTab->sh_entsize; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::begin_symbols() const { +template<class ELFT> +symbol_iterator ELFObjectFile<ELFT>::begin_symbols() const { DataRefImpl SymbolData; if (SymbolTableSections.size() <= 1) { SymbolData.d.a = std::numeric_limits<uint32_t>::max(); @@ -2181,18 +2241,16 @@ symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> return symbol_iterator(SymbolRef(SymbolData, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::end_symbols() const { +template<class ELFT> +symbol_iterator ELFObjectFile<ELFT>::end_symbols() const { DataRefImpl SymbolData; SymbolData.d.a = std::numeric_limits<uint32_t>::max(); SymbolData.d.b = std::numeric_limits<uint32_t>::max(); return symbol_iterator(SymbolRef(SymbolData, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::begin_dynamic_symbols() const { +template<class ELFT> +symbol_iterator ELFObjectFile<ELFT>::begin_dynamic_symbols() const { DataRefImpl SymbolData; if (SymbolTableSections[0] == NULL) { SymbolData.d.a = std::numeric_limits<uint32_t>::max(); @@ -2204,26 +2262,23 @@ symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> return symbol_iterator(SymbolRef(SymbolData, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -symbol_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::end_dynamic_symbols() const { +template<class ELFT> +symbol_iterator ELFObjectFile<ELFT>::end_dynamic_symbols() const { DataRefImpl SymbolData; SymbolData.d.a = std::numeric_limits<uint32_t>::max(); SymbolData.d.b = std::numeric_limits<uint32_t>::max(); return symbol_iterator(SymbolRef(SymbolData, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -section_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::begin_sections() const { +template<class ELFT> +section_iterator ELFObjectFile<ELFT>::begin_sections() const { DataRefImpl ret; ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff); return section_iterator(SectionRef(ret, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -section_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::end_sections() const { +template<class ELFT> +section_iterator ELFObjectFile<ELFT>::end_sections() const { DataRefImpl ret; ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff @@ -2231,58 +2286,46 @@ section_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> return section_iterator(SectionRef(ret, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -typename ELFObjectFile<target_endianness, max_alignment, is64Bits>::dyn_iterator -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::begin_dynamic_table() const { - DataRefImpl DynData; - if (dot_dynamic_sec == NULL || dot_dynamic_sec->sh_size == 0) { - DynData.d.a = std::numeric_limits<uint32_t>::max(); - } else { - DynData.d.a = 0; - } - return dyn_iterator(DynRef(DynData, this)); -} - -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -typename ELFObjectFile<target_endianness, max_alignment, is64Bits>::dyn_iterator -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::end_dynamic_table() const { - DataRefImpl DynData; - DynData.d.a = std::numeric_limits<uint32_t>::max(); - return dyn_iterator(DynRef(DynData, this)); -} - -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getDynNext(DataRefImpl DynData, - DynRef &Result) const { - ++DynData.d.a; - - // Check to see if we are at the end of .dynamic - if (DynData.d.a >= dot_dynamic_sec->getEntityCount()) { - // We are at the end. Return the terminator. - DynData.d.a = std::numeric_limits<uint32_t>::max(); +template<class ELFT> +typename ELFObjectFile<ELFT>::Elf_Dyn_iterator +ELFObjectFile<ELFT>::begin_dynamic_table() const { + if (dot_dynamic_sec) + return Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, + (const char *)base() + dot_dynamic_sec->sh_offset); + return Elf_Dyn_iterator(0, 0); +} + +template<class ELFT> +typename ELFObjectFile<ELFT>::Elf_Dyn_iterator +ELFObjectFile<ELFT>::end_dynamic_table(bool NULLEnd) const { + if (dot_dynamic_sec) { + Elf_Dyn_iterator Ret(dot_dynamic_sec->sh_entsize, + (const char *)base() + dot_dynamic_sec->sh_offset + + dot_dynamic_sec->sh_size); + + if (NULLEnd) { + Elf_Dyn_iterator Start = begin_dynamic_table(); + for (; Start != Ret && Start->getTag() != ELF::DT_NULL; ++Start) + ; + // Include the DT_NULL. + if (Start != Ret) + ++Start; + Ret = Start; + } + return Ret; } - - Result = DynRef(DynData, this); - return object_error::success; + return Elf_Dyn_iterator(0, 0); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -StringRef -ELFObjectFile<target_endianness, max_alignment, is64Bits>::getLoadName() const { +template<class ELFT> +StringRef ELFObjectFile<ELFT>::getLoadName() const { if (!dt_soname) { // Find the DT_SONAME entry - dyn_iterator it = begin_dynamic_table(); - dyn_iterator ie = end_dynamic_table(); - error_code ec; - while (it != ie) { + Elf_Dyn_iterator it = begin_dynamic_table(); + Elf_Dyn_iterator ie = end_dynamic_table(); + for (; it != ie; ++it) { if (it->getTag() == ELF::DT_SONAME) break; - it.increment(ec); - if (ec) - report_fatal_error("dynamic table iteration failed"); } if (it != ie) { if (dot_dynstr_sec == NULL) @@ -2295,57 +2338,46 @@ ELFObjectFile<target_endianness, max_alignment, is64Bits>::getLoadName() const { return dt_soname; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -library_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::begin_libraries_needed() const { +template<class ELFT> +library_iterator ELFObjectFile<ELFT>::begin_libraries_needed() const { // Find the first DT_NEEDED entry - dyn_iterator i = begin_dynamic_table(); - dyn_iterator e = end_dynamic_table(); - error_code ec; - while (i != e) { + Elf_Dyn_iterator i = begin_dynamic_table(); + Elf_Dyn_iterator e = end_dynamic_table(); + for (; i != e; ++i) { if (i->getTag() == ELF::DT_NEEDED) break; - i.increment(ec); - if (ec) - report_fatal_error("dynamic table iteration failed"); } - // Use the same DataRefImpl format as DynRef. - return library_iterator(LibraryRef(i->getRawDataRefImpl(), this)); + + DataRefImpl DRI; + DRI.p = reinterpret_cast<uintptr_t>(i.get()); + return library_iterator(LibraryRef(DRI, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getLibraryNext(DataRefImpl Data, - LibraryRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const { // Use the same DataRefImpl format as DynRef. - dyn_iterator i = dyn_iterator(DynRef(Data, this)); - dyn_iterator e = end_dynamic_table(); + Elf_Dyn_iterator i = Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, + reinterpret_cast<const char *>(Data.p)); + Elf_Dyn_iterator e = end_dynamic_table(); // Skip the current dynamic table entry. - error_code ec; - if (i != e) { - i.increment(ec); - // TODO: proper error handling - if (ec) - report_fatal_error("dynamic table iteration failed"); - } + ++i; // Find the next DT_NEEDED entry. - while (i != e) { - if (i->getTag() == ELF::DT_NEEDED) - break; - i.increment(ec); - if (ec) - report_fatal_error("dynamic table iteration failed"); - } - Result = LibraryRef(i->getRawDataRefImpl(), this); + for (; i != e && i->getTag() != ELF::DT_NEEDED; ++i); + + DataRefImpl DRI; + DRI.p = reinterpret_cast<uintptr_t>(i.get()); + Result = LibraryRef(DRI, this); return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getLibraryPath(DataRefImpl Data, StringRef &Res) const { - dyn_iterator i = dyn_iterator(DynRef(Data, this)); +template<class ELFT> +error_code ELFObjectFile<ELFT>::getLibraryPath(DataRefImpl Data, + StringRef &Res) const { + Elf_Dyn_iterator i = Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, + reinterpret_cast<const char *>(Data.p)); if (i == end_dynamic_table()) report_fatal_error("getLibraryPath() called on iterator end"); @@ -2363,23 +2395,21 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -library_iterator ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::end_libraries_needed() const { - dyn_iterator e = end_dynamic_table(); - // Use the same DataRefImpl format as DynRef. - return library_iterator(LibraryRef(e->getRawDataRefImpl(), this)); +template<class ELFT> +library_iterator ELFObjectFile<ELFT>::end_libraries_needed() const { + Elf_Dyn_iterator e = end_dynamic_table(); + DataRefImpl DRI; + DRI.p = reinterpret_cast<uintptr_t>(e.get()); + return library_iterator(LibraryRef(DRI, this)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -uint8_t ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getBytesInAddress() const { - return is64Bits ? 8 : 4; +template<class ELFT> +uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const { + return ELFT::Is64Bits ? 8 : 4; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -StringRef ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getFileFormatName() const { +template<class ELFT> +StringRef ELFObjectFile<ELFT>::getFileFormatName() const { switch(Header->e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: switch(Header->e_machine) { @@ -2391,6 +2421,8 @@ StringRef ELFObjectFile<target_endianness, max_alignment, is64Bits> return "ELF32-arm"; case ELF::EM_HEXAGON: return "ELF32-hexagon"; + case ELF::EM_MIPS: + return "ELF32-mips"; default: return "ELF32-unknown"; } @@ -2400,6 +2432,8 @@ StringRef ELFObjectFile<target_endianness, max_alignment, is64Bits> return "ELF64-i386"; case ELF::EM_X86_64: return "ELF64-x86-64"; + case ELF::EM_AARCH64: + return "ELF64-aarch64"; case ELF::EM_PPC64: return "ELF64-ppc64"; default: @@ -2411,20 +2445,21 @@ StringRef ELFObjectFile<target_endianness, max_alignment, is64Bits> } } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -unsigned ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getArch() const { +template<class ELFT> +unsigned ELFObjectFile<ELFT>::getArch() const { switch(Header->e_machine) { case ELF::EM_386: return Triple::x86; case ELF::EM_X86_64: return Triple::x86_64; + case ELF::EM_AARCH64: + return Triple::aarch64; case ELF::EM_ARM: return Triple::arm; case ELF::EM_HEXAGON: return Triple::hexagon; case ELF::EM_MIPS: - return (target_endianness == support::little) ? + return (ELFT::TargetEndianness == support::little) ? Triple::mipsel : Triple::mips; case ELF::EM_PPC64: return Triple::ppc64; @@ -2433,9 +2468,8 @@ unsigned ELFObjectFile<target_endianness, max_alignment, is64Bits> } } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -uint64_t ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getNumSections() const { +template<class ELFT> +uint64_t ELFObjectFile<ELFT>::getNumSections() const { assert(Header && "Header not initialized!"); if (Header->e_shnum == ELF::SHN_UNDEF) { assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); @@ -2444,10 +2478,9 @@ uint64_t ELFObjectFile<target_endianness, max_alignment, is64Bits> return Header->e_shnum; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> uint64_t -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getStringTableIndex() const { +ELFObjectFile<ELFT>::getStringTableIndex() const { if (Header->e_shnum == ELF::SHN_UNDEF) { if (Header->e_shstrndx == ELF::SHN_HIRESERVE) return SectionHeaderTable->sh_link; @@ -2457,62 +2490,44 @@ ELFObjectFile<target_endianness, max_alignment, is64Bits> return Header->e_shstrndx; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> template<typename T> inline const T * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getEntry(uint16_t Section, uint32_t Entry) const { +ELFObjectFile<ELFT>::getEntry(uint16_t Section, uint32_t Entry) const { return getEntry<T>(getSection(Section), Entry); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> +template<class ELFT> template<typename T> inline const T * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getEntry(const Elf_Shdr * Section, uint32_t Entry) const { +ELFObjectFile<ELFT>::getEntry(const Elf_Shdr * Section, uint32_t Entry) const { return reinterpret_cast<const T *>( base() + Section->sh_offset + (Entry * Section->sh_entsize)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Sym * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbol(DataRefImpl Symb) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Sym * +ELFObjectFile<ELFT>::getSymbol(DataRefImpl Symb) const { return getEntry<Elf_Sym>(SymbolTableSections[Symb.d.b], Symb.d.a); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Dyn * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getDyn(DataRefImpl DynData) const { - return getEntry<Elf_Dyn>(dot_dynamic_sec, DynData.d.a); -} - -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Rel * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRel(DataRefImpl Rel) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Rel * +ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const { return getEntry<Elf_Rel>(Rel.w.b, Rel.w.c); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Rela * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getRela(DataRefImpl Rela) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Rela * +ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { return getEntry<Elf_Rela>(Rela.w.b, Rela.w.c); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Shdr * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSection(DataRefImpl Symb) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Shdr * +ELFObjectFile<ELFT>::getSection(DataRefImpl Symb) const { const Elf_Shdr *sec = getSection(Symb.d.b); if (sec->sh_type != ELF::SHT_SYMTAB || sec->sh_type != ELF::SHT_DYNSYM) // FIXME: Proper error handling. @@ -2520,11 +2535,9 @@ ELFObjectFile<target_endianness, max_alignment, is64Bits> return sec; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const typename ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::Elf_Shdr * -ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSection(uint32_t index) const { +template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Shdr * +ELFObjectFile<ELFT>::getSection(uint32_t index) const { if (index == 0) return 0; if (!SectionHeaderTable || index >= getNumSections()) @@ -2536,17 +2549,15 @@ ELFObjectFile<target_endianness, max_alignment, is64Bits> + (index * Header->e_shentsize)); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const char *ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getString(uint32_t section, - ELF::Elf32_Word offset) const { +template<class ELFT> +const char *ELFObjectFile<ELFT>::getString(uint32_t section, + ELF::Elf32_Word offset) const { return getString(getSection(section), offset); } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -const char *ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getString(const Elf_Shdr *section, - ELF::Elf32_Word offset) const { +template<class ELFT> +const char *ELFObjectFile<ELFT>::getString(const Elf_Shdr *section, + ELF::Elf32_Word offset) const { assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); if (offset >= section->sh_size) // FIXME: Proper error handling. @@ -2554,11 +2565,10 @@ const char *ELFObjectFile<target_endianness, max_alignment, is64Bits> return (const char *)base() + section->sh_offset + offset; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolName(const Elf_Shdr *section, - const Elf_Sym *symb, - StringRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolName(const Elf_Shdr *section, + const Elf_Sym *symb, + StringRef &Result) const { if (symb->st_name == 0) { const Elf_Shdr *section = getSection(symb); if (!section) @@ -2578,20 +2588,18 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSectionName(const Elf_Shdr *section, - StringRef &Result) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSectionName(const Elf_Shdr *section, + StringRef &Result) const { Result = StringRef(getString(dot_shstrtab_sec, section->sh_name)); return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> - ::getSymbolVersion(const Elf_Shdr *section, - const Elf_Sym *symb, - StringRef &Version, - bool &IsDefault) const { +template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, + const Elf_Sym *symb, + StringRef &Version, + bool &IsDefault) const { // Handle non-dynamic symbols. if (section != SymbolTableSections[0]) { // Non-dynamic symbols can have versions in their names @@ -2669,54 +2677,6 @@ error_code ELFObjectFile<target_endianness, max_alignment, is64Bits> return object_error::success; } -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline DynRefImpl<target_endianness, max_alignment, is64Bits> - ::DynRefImpl(DataRefImpl DynP, const OwningType *Owner) - : DynPimpl(DynP) - , OwningObject(Owner) {} - -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline bool DynRefImpl<target_endianness, max_alignment, is64Bits> - ::operator==(const DynRefImpl &Other) const { - return DynPimpl == Other.DynPimpl; -} - -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline bool DynRefImpl<target_endianness, max_alignment, is64Bits> - ::operator <(const DynRefImpl &Other) const { - return DynPimpl < Other.DynPimpl; -} - -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline error_code DynRefImpl<target_endianness, max_alignment, is64Bits> - ::getNext(DynRefImpl &Result) const { - return OwningObject->getDynNext(DynPimpl, Result); -} - -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline int64_t DynRefImpl<target_endianness, max_alignment, is64Bits> - ::getTag() const { - return OwningObject->getDyn(DynPimpl)->d_tag; -} - -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline uint64_t DynRefImpl<target_endianness, max_alignment, is64Bits> - ::getVal() const { - return OwningObject->getDyn(DynPimpl)->d_un.d_val; -} - -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline uint64_t DynRefImpl<target_endianness, max_alignment, is64Bits> - ::getPtr() const { - return OwningObject->getDyn(DynPimpl)->d_un.d_ptr; -} - -template<endianness target_endianness, std::size_t max_alignment, bool is64Bits> -inline DataRefImpl DynRefImpl<target_endianness, max_alignment, is64Bits> - ::getRawDataRefImpl() const { - return DynPimpl; -} - /// This is a generic interface for retrieving GNU symbol version /// information from an ELFObjectFile. static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, @@ -2724,23 +2684,23 @@ static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, StringRef &Version, bool &IsDefault) { // Little-endian 32-bit - if (const ELFObjectFile<support::little, 4, false> *ELFObj = - dyn_cast<ELFObjectFile<support::little, 4, false> >(Obj)) + if (const ELFObjectFile<ELFType<support::little, 4, false> > *ELFObj = + dyn_cast<ELFObjectFile<ELFType<support::little, 4, false> > >(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 32-bit - if (const ELFObjectFile<support::big, 4, false> *ELFObj = - dyn_cast<ELFObjectFile<support::big, 4, false> >(Obj)) + if (const ELFObjectFile<ELFType<support::big, 4, false> > *ELFObj = + dyn_cast<ELFObjectFile<ELFType<support::big, 4, false> > >(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Little-endian 64-bit - if (const ELFObjectFile<support::little, 8, true> *ELFObj = - dyn_cast<ELFObjectFile<support::little, 8, true> >(Obj)) + if (const ELFObjectFile<ELFType<support::little, 8, true> > *ELFObj = + dyn_cast<ELFObjectFile<ELFType<support::little, 8, true> > >(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); // Big-endian 64-bit - if (const ELFObjectFile<support::big, 8, true> *ELFObj = - dyn_cast<ELFObjectFile<support::big, 8, true> >(Obj)) + if (const ELFObjectFile<ELFType<support::big, 8, true> > *ELFObj = + dyn_cast<ELFObjectFile<ELFType<support::big, 8, true> > >(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h index a17d58d..ffca391 100644 --- a/include/llvm/Object/MachOFormat.h +++ b/include/llvm/Object/MachOFormat.h @@ -64,7 +64,10 @@ namespace mach { CSARM_V7 = 9, CSARM_V7F = 10, CSARM_V7S = 11, - CSARM_V7K = 12 + CSARM_V7K = 12, + CSARM_V6M = 14, + CSARM_V7M = 15, + CSARM_V7EM = 16 }; /// \brief PowerPC Machine Subtypes. @@ -145,7 +148,8 @@ namespace macho { LCT_CodeSignature = 0x1d, LCT_SegmentSplitInfo = 0x1e, LCT_FunctionStarts = 0x26, - LCT_DataInCode = 0x29 + LCT_DataInCode = 0x29, + LCT_LinkerOptions = 0x2D }; /// \brief Load command structure. @@ -233,6 +237,14 @@ namespace macho { uint32_t DataSize; }; + struct LinkerOptionsLoadCommand { + uint32_t Type; + uint32_t Size; + uint32_t Count; + // Load command is followed by Count number of zero-terminated UTF8 strings, + // and then zero-filled to be 4-byte aligned. + }; + /// @} /// @name Section Data /// @{ diff --git a/include/llvm/Object/MachOObject.h b/include/llvm/Object/MachOObject.h index e32a85d..9e4ab19 100644 --- a/include/llvm/Object/MachOObject.h +++ b/include/llvm/Object/MachOObject.h @@ -153,6 +153,9 @@ public: void ReadLinkeditDataLoadCommand( const LoadCommandInfo &LCI, InMemoryStruct<macho::LinkeditDataLoadCommand> &Res) const; + void ReadLinkerOptionsLoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct<macho::LinkerOptionsLoadCommand> &Res) const; void ReadIndirectSymbolTableEntry( const macho::DysymtabLoadCommand &DLC, unsigned Index, diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index e63f554..6a66653 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_OBJECT_OBJECT_FILE_H -#define LLVM_OBJECT_OBJECT_FILE_H +#ifndef LLVM_OBJECT_OBJECTFILE_H +#define LLVM_OBJECT_OBJECTFILE_H #include "llvm/ADT/StringRef.h" #include "llvm/Object/Binary.h" diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 2c2dd03..2dcbdf9 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -13,13 +13,13 @@ // //===----------------------------------------------------------------------===// -#ifndef _LLVM_OBJECT_RELOCVISITOR -#define _LLVM_OBJECT_RELOCVISITOR +#ifndef LLVM_OBJECT_RELOCVISITOR_H +#define LLVM_OBJECT_RELOCVISITOR_H #include "llvm/ADT/StringRef.h" -#include "llvm/Object/ELF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ELF.h" #include "llvm/Support/raw_ostream.h" namespace llvm { @@ -40,7 +40,7 @@ struct RelocToApply { /// @brief Base class for object file relocation visitors. class RelocVisitor { public: - explicit RelocVisitor(llvm::StringRef FileFormat) + explicit RelocVisitor(StringRef FileFormat) : FileFormat(FileFormat), HasError(false) {} // TODO: Should handle multiple applied relocations via either passing in the @@ -76,14 +76,41 @@ public: HasError = true; return RelocToApply(); } + } else if (FileFormat == "ELF64-ppc64") { + switch (RelocType) { + case llvm::ELF::R_PPC64_ADDR32: + return visitELF_PPC64_ADDR32(R, Value); + default: + HasError = true; + return RelocToApply(); + } + } else if (FileFormat == "ELF32-mips") { + switch (RelocType) { + case llvm::ELF::R_MIPS_32: + return visitELF_MIPS_32(R, Value); + default: + HasError = true; + return RelocToApply(); + } + } else if (FileFormat == "ELF64-aarch64") { + switch (RelocType) { + case llvm::ELF::R_AARCH64_ABS32: + return visitELF_AARCH64_ABS32(R, Value); + case llvm::ELF::R_AARCH64_ABS64: + return visitELF_AARCH64_ABS64(R, Value); + default: + HasError = true; + return RelocToApply(); + } } + HasError = true; return RelocToApply(); } bool error() { return HasError; } private: - llvm::StringRef FileFormat; + StringRef FileFormat; bool HasError; /// Operations @@ -139,6 +166,42 @@ private: int32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } + + /// PPC64 ELF + RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) { + int64_t Addend; + R.getAdditionalInfo(Addend); + uint32_t Res = (Value + Addend) & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } + + /// MIPS ELF + RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) { + int64_t Addend; + R.getAdditionalInfo(Addend); + uint32_t Res = (Value + Addend) & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } + + // AArch64 ELF + RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) { + int64_t Addend; + R.getAdditionalInfo(Addend); + int64_t Res = Value + Addend; + + // Overflow check allows for both signed and unsigned interpretation. + if (Res < INT32_MIN || Res > UINT32_MAX) + HasError = true; + + return RelocToApply(static_cast<uint32_t>(Res), 4); + } + + RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) { + int64_t Addend; + R.getAdditionalInfo(Addend); + return RelocToApply(Value + Addend, 8); + } + }; } diff --git a/include/llvm/Option/Arg.h b/include/llvm/Option/Arg.h index baa4b6a..6b8ed3f 100644 --- a/include/llvm/Option/Arg.h +++ b/include/llvm/Option/Arg.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_ARG_H_ -#define LLVM_SUPPORT_ARG_H_ +#ifndef LLVM_OPTION_ARG_H +#define LLVM_OPTION_ARG_H #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index 378b58a..d3accfe 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_ARGLIST_H_ -#define LLVM_SUPPORT_ARGLIST_H_ +#ifndef LLVM_OPTION_ARGLIST_H +#define LLVM_OPTION_ARGLIST_H #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" diff --git a/include/llvm/Option/OptSpecifier.h b/include/llvm/Option/OptSpecifier.h index 3bc9bb2..02bc6b1 100644 --- a/include/llvm/Option/OptSpecifier.h +++ b/include/llvm/Option/OptSpecifier.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_OPTSPECIFIER_H -#define LLVM_SUPPORT_OPTSPECIFIER_H +#ifndef LLVM_OPTION_OPTSPECIFIER_H +#define LLVM_OPTION_OPTSPECIFIER_H namespace llvm { namespace opt { @@ -19,7 +19,7 @@ namespace opt { unsigned ID; private: - explicit OptSpecifier(bool); // DO NOT IMPLEMENT + explicit OptSpecifier(bool) LLVM_DELETED_FUNCTION; public: OptSpecifier() : ID(0) {} diff --git a/include/llvm/Option/OptTable.h b/include/llvm/Option/OptTable.h index 930549f..a93acbf 100644 --- a/include/llvm/Option/OptTable.h +++ b/include/llvm/Option/OptTable.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_OPTTABLE_H -#define LLVM_SUPPORT_OPTTABLE_H +#ifndef LLVM_OPTION_OPTTABLE_H +#define LLVM_OPTION_OPTTABLE_H #include "llvm/ADT/StringSet.h" #include "llvm/Option/OptSpecifier.h" diff --git a/include/llvm/Option/Option.h b/include/llvm/Option/Option.h index ee5eec4..541aa8d 100644 --- a/include/llvm/Option/Option.h +++ b/include/llvm/Option/Option.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_OPTION_H_ -#define LLVM_SUPPORT_OPTION_H_ +#ifndef LLVM_OPTION_OPTION_H +#define LLVM_OPTION_OPTION_H #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" diff --git a/include/llvm/PassAnalysisSupport.h b/include/llvm/PassAnalysisSupport.h index 1cc5741..a581802 100644 --- a/include/llvm/PassAnalysisSupport.h +++ b/include/llvm/PassAnalysisSupport.h @@ -16,8 +16,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PASS_ANALYSIS_SUPPORT_H -#define LLVM_PASS_ANALYSIS_SUPPORT_H +#ifndef LLVM_PASSANALYSISSUPPORT_H +#define LLVM_PASSANALYSISSUPPORT_H #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" diff --git a/include/llvm/PassManagers.h b/include/llvm/PassManagers.h index fac7928..7afb0a0 100644 --- a/include/llvm/PassManagers.h +++ b/include/llvm/PassManagers.h @@ -352,7 +352,7 @@ public: return PMT_Unknown; } - std::map<AnalysisID, Pass*> *getAvailableAnalysis() { + DenseMap<AnalysisID, Pass*> *getAvailableAnalysis() { return &AvailableAnalysis; } @@ -375,8 +375,7 @@ protected: // Collection of Analysis provided by Parent pass manager and // used by current pass manager. At at time there can not be more // then PMT_Last active pass mangers. - std::map<AnalysisID, Pass *> *InheritedAnalysis[PMT_Last]; - + DenseMap<AnalysisID, Pass *> *InheritedAnalysis[PMT_Last]; /// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions /// or higher is specified. @@ -390,7 +389,7 @@ private: // pass. If a pass requires an analysis which is not available then // the required analysis pass is scheduled to run before the pass itself is // scheduled to run. - std::map<AnalysisID, Pass*> AvailableAnalysis; + DenseMap<AnalysisID, Pass*> AvailableAnalysis; // Collection of higher level analysis used by the pass managed by // this manager. diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h index 3633f47..ccc7934 100644 --- a/include/llvm/PassSupport.h +++ b/include/llvm/PassSupport.h @@ -18,8 +18,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PASS_SUPPORT_H -#define LLVM_PASS_SUPPORT_H +#ifndef LLVM_PASSSUPPORT_H +#define LLVM_PASSSUPPORT_H #include "Pass.h" #include "llvm/InitializePasses.h" diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index 0894316..bba3424 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -169,17 +169,20 @@ LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) namespace detail { template <typename T1, - typename T2 = char, typename T3 = char, typename T4 = char> + typename T2 = char, typename T3 = char, typename T4 = char, + typename T5 = char, typename T6 = char, typename T7 = char> class AlignerImpl { - T1 t1; T2 t2; T3 t3; T4 t4; + T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; AlignerImpl(); // Never defined or instantiated. }; template <typename T1, - typename T2 = char, typename T3 = char, typename T4 = char> + typename T2 = char, typename T3 = char, typename T4 = char, + typename T5 = char, typename T6 = char, typename T7 = char> union SizerImpl { - char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)]; + char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)], + arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)]; }; } // end namespace detail @@ -188,14 +191,14 @@ union SizerImpl { /// /// 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 four types can +/// a placement new of any of these types. Support for more than seven types can /// be added at the cost of more boiler plate. template <typename T1, - typename T2 = char, typename T3 = char, typename T4 = char> -struct AlignedCharArrayUnion : - llvm::AlignedCharArray<AlignOf<detail::AlignerImpl<T1, T2, T3, T4> > - ::Alignment, - sizeof(detail::SizerImpl<T1, T2, T3, T4>)> { + typename T2 = char, typename T3 = char, typename T4 = char, + typename T5 = char, typename T6 = char, typename T7 = char> +struct AlignedCharArrayUnion : llvm::AlignedCharArray< + AlignOf<detail::AlignerImpl<T1, T2, T3, T4, T5, T6, T7> >::Alignment, + sizeof(detail::SizerImpl<T1, T2, T3, T4, T5, T6, T7>)> { }; } // end namespace llvm #endif diff --git a/include/llvm/Support/ArrayRecycler.h b/include/llvm/Support/ArrayRecycler.h index 0fbe79c..c7e0cba 100644 --- a/include/llvm/Support/ArrayRecycler.h +++ b/include/llvm/Support/ArrayRecycler.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_ARRAY_RECYCLER_H -#define LLVM_SUPPORT_ARRAY_RECYCLER_H +#ifndef LLVM_SUPPORT_ARRAYRECYCLER_H +#define LLVM_SUPPORT_ARRAYRECYCLER_H #include "llvm/ADT/SmallVector.h" #include "llvm/Support/MathExtras.h" diff --git a/include/llvm/Support/Atomic.h b/include/llvm/Support/Atomic.h index 1a6c606..9ec23e8 100644 --- a/include/llvm/Support/Atomic.h +++ b/include/llvm/Support/Atomic.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_ATOMIC_H -#define LLVM_SYSTEM_ATOMIC_H +#ifndef LLVM_SUPPORT_ATOMIC_H +#define LLVM_SUPPORT_ATOMIC_H #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index ba8adb0..02c44cd 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -20,8 +20,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_WIN_COFF_H -#define LLVM_SUPPORT_WIN_COFF_H +#ifndef LLVM_SUPPORT_COFF_H +#define LLVM_SUPPORT_COFF_H #include "llvm/Support/DataTypes.h" #include <cassert> diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index 0c71882..80f09db 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -55,8 +55,8 @@ struct isa_impl { /// \brief Always allow upcasts, and perform no dynamic check for them. template <typename To, typename From> struct isa_impl<To, From, - typename llvm::enable_if_c< - llvm::is_base_of<To, From>::value + typename enable_if< + llvm::is_base_of<To, From> >::type > { static inline bool doit(const From &) { return true; } @@ -204,12 +204,35 @@ template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { // cast<Instruction>(myVal)->getParent() // template <class X, class Y> -inline typename cast_retty<X, Y>::ret_type cast(const Y &Val) { +inline typename enable_if_c< + !is_same<Y, typename simplify_type<Y>::SimpleType>::value, + typename cast_retty<X, Y>::ret_type +>::type cast(const Y &Val) { assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); return cast_convert_val<X, Y, typename simplify_type<Y>::SimpleType>::doit(Val); } +template <class X, class Y> +inline typename enable_if< + is_same<Y, typename simplify_type<Y>::SimpleType>, + typename cast_retty<X, Y>::ret_type +>::type cast(Y &Val) { + assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); + return cast_convert_val<X, Y, + typename simplify_type<Y>::SimpleType>::doit(Val); +} + +template <class X, class Y> +inline typename enable_if< + is_same<Y, typename simplify_type<Y>::SimpleType>, + typename cast_retty<X, Y*>::ret_type +>::type cast(Y *Val) { + assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); + return cast_convert_val<X, Y*, + typename simplify_type<Y*>::SimpleType>::doit(Val); +} + // cast_or_null<X> - Functionally identical to cast, except that a null value is // accepted. // @@ -230,8 +253,27 @@ inline typename cast_retty<X, Y*>::ret_type cast_or_null(Y *Val) { // template <class X, class Y> -inline typename cast_retty<X, Y>::ret_type dyn_cast(const Y &Val) { - return isa<X>(Val) ? cast<X, Y>(Val) : 0; +inline typename enable_if_c< + !is_same<Y, typename simplify_type<Y>::SimpleType>::value, + typename cast_retty<X, Y>::ret_type +>::type dyn_cast(const Y &Val) { + return isa<X>(Val) ? cast<X>(Val) : 0; +} + +template <class X, class Y> +inline typename enable_if< + is_same<Y, typename simplify_type<Y>::SimpleType>, + typename cast_retty<X, Y>::ret_type +>::type dyn_cast(Y &Val) { + return isa<X>(Val) ? cast<X>(Val) : 0; +} + +template <class X, class Y> +inline typename enable_if< + is_same<Y, typename simplify_type<Y>::SimpleType>, + typename cast_retty<X, Y*>::ret_type +>::type dyn_cast(Y *Val) { + return isa<X>(Val) ? cast<X>(Val) : 0; } // dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 0ab39fc..bf7823e 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -469,8 +469,7 @@ public: template<class Opt> void apply(Opt &O) const { - for (unsigned i = 0, e = static_cast<unsigned>(Values.size()); - i != e; ++i) + for (size_t i = 0, e = Values.size(); i != e; ++i) O.getParser().addLiteralOption(Values[i].first, Values[i].second.first, Values[i].second.second); } @@ -629,8 +628,7 @@ public: else ArgVal = ArgName; - for (unsigned i = 0, e = static_cast<unsigned>(Values.size()); - i != e; ++i) + for (size_t i = 0, e = Values.size(); i != e; ++i) if (Values[i].Name == ArgVal) { V = Values[i].V.getValue(); return false; diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index b32939e..25f42a9 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -15,6 +15,8 @@ #ifndef LLVM_SUPPORT_COMPILER_H #define LLVM_SUPPORT_COMPILER_H +#include "llvm/Config/llvm-config.h" + #ifndef __has_feature # define __has_feature(x) 0 #endif @@ -42,6 +44,43 @@ #define LLVM_HAS_RVALUE_REFERENCE_THIS 0 #endif +/// \macro LLVM_HAS_CXX11_TYPETRAITS +/// \brief Does the compiler have the C++11 type traits. +/// +/// #include <type_traits> +/// +/// * enable_if +/// * {true,false}_type +/// * is_constructible +/// * etc... +#if defined(__GXX_EXPERIMENTAL_CXX0X__) \ + || (defined(_MSC_VER) && _MSC_VER >= 1700) +#define LLVM_HAS_CXX11_TYPETRAITS 1 +#else +#define LLVM_HAS_CXX11_TYPETRAITS 0 +#endif + +/// \macro LLVM_HAS_CXX11_STDLIB +/// \brief Does the compiler have the C++11 standard library. +/// +/// Implies LLVM_HAS_RVALUE_REFERENCES, LLVM_HAS_CXX11_TYPETRAITS +#if defined(__GXX_EXPERIMENTAL_CXX0X__) \ + || (defined(_MSC_VER) && _MSC_VER >= 1700) +#define LLVM_HAS_CXX11_STDLIB 1 +#else +#define LLVM_HAS_CXX11_STDLIB 0 +#endif + +/// \macro LLVM_HAS_VARIADIC_TEMPLATES +/// \brief Does this compiler support variadic templates. +/// +/// Implies LLVM_HAS_RVALUE_REFERENCES and the existence of std::forward. +#if __has_feature(cxx_variadic_templates) +# define LLVM_HAS_VARIADIC_TEMPLATES 1 +#else +# define LLVM_HAS_VARIADIC_TEMPLATES 0 +#endif + /// llvm_move - Expands to ::std::move if the compiler supports /// r-value references; otherwise, expands to the argument. #if LLVM_HAS_RVALUE_REFERENCES @@ -81,7 +120,8 @@ /// LLVM_FINAL - Expands to 'final' if the compiler supports it. /// Use to mark classes or virtual methods as final. -#if (__has_feature(cxx_override_control)) +#if __has_feature(cxx_override_control) \ + || (defined(_MSC_VER) && _MSC_VER >= 1700) #define LLVM_FINAL final #else #define LLVM_FINAL @@ -89,12 +129,19 @@ /// LLVM_OVERRIDE - Expands to 'override' if the compiler supports it. /// Use to mark virtual methods as overriding a base class method. -#if (__has_feature(cxx_override_control)) +#if __has_feature(cxx_override_control) \ + || (defined(_MSC_VER) && _MSC_VER >= 1700) #define LLVM_OVERRIDE override #else #define LLVM_OVERRIDE #endif +#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) +# define LLVM_CONSTEXPR constexpr +#else +# define LLVM_CONSTEXPR +#endif + /// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked /// into a shared library, then the class should be private to the library and /// not accessible from outside it. Can also be used to mark variables and @@ -249,4 +296,59 @@ # define LLVM_ASSUME_ALIGNED(p, a) (p) #endif +/// \macro LLVM_FUNCTION_NAME +/// \brief Expands to __func__ on compilers which support it. Otherwise, +/// expands to a compiler-dependent replacement. +#if defined(_MSC_VER) +# define LLVM_FUNCTION_NAME __FUNCTION__ +#else +# define LLVM_FUNCTION_NAME __func__ +#endif + +#if defined(HAVE_SANITIZER_MSAN_INTERFACE_H) +# include <sanitizer/msan_interface.h> +#else +# define __msan_allocated_memory(p, size) +# define __msan_unpoison(p, size) +#endif + +/// \macro LLVM_MEMORY_SANITIZER_BUILD +/// \brief Whether LLVM itself is built with MemorySanitizer instrumentation. +#if __has_feature(memory_sanitizer) +# define LLVM_MEMORY_SANITIZER_BUILD 1 +#else +# define LLVM_MEMORY_SANITIZER_BUILD 0 +#endif + +/// \macro LLVM_ADDRESS_SANITIZER_BUILD +/// \brief Whether LLVM itself is built with AddressSanitizer instrumentation. +#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) +# define LLVM_ADDRESS_SANITIZER_BUILD 1 +#else +# define LLVM_ADDRESS_SANITIZER_BUILD 0 +#endif + +/// \macro LLVM_IS_UNALIGNED_ACCESS_FAST +/// \brief Is unaligned memory access fast on the host machine. +/// +/// Don't specialize on alignment for platforms where unaligned memory accesses +/// generates the same code as aligned memory accesses for common types. +#if defined(_M_AMD64) || defined(_M_IX86) || defined(__amd64) || \ + defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || \ + defined(_X86_) || defined(__i386) || defined(__i386__) +# define LLVM_IS_UNALIGNED_ACCESS_FAST 1 +#else +# 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__)) +#define LLVM_EXPLICIT explicit +#else +#define LLVM_EXPLICIT +#endif + #endif diff --git a/include/llvm/Support/ConstantRange.h b/include/llvm/Support/ConstantRange.h index 90dd69f..0f29256 100644 --- a/include/llvm/Support/ConstantRange.h +++ b/include/llvm/Support/ConstantRange.h @@ -29,8 +29,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_CONSTANT_RANGE_H -#define LLVM_SUPPORT_CONSTANT_RANGE_H +#ifndef LLVM_SUPPORT_CONSTANTRANGE_H +#define LLVM_SUPPORT_CONSTANTRANGE_H #include "llvm/ADT/APInt.h" #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/Support/ConvertUTF.h b/include/llvm/Support/ConvertUTF.h new file mode 100644 index 0000000..1eae6d6 --- /dev/null +++ b/include/llvm/Support/ConvertUTF.h @@ -0,0 +1,228 @@ +/*===--- ConvertUTF.h - Universal Character Names conversions ---------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *==------------------------------------------------------------------------==*/ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Header file. + + Several funtions are included here, forming a complete set of + conversions between the three formats. UTF-7 is not included + here, but is handled in a separate source file. + + Each of these routines takes pointers to input buffers and output + buffers. The input buffers are const. + + Each routine converts the text between *sourceStart and sourceEnd, + putting the result into the buffer between *targetStart and + targetEnd. Note: the end pointers are *after* the last item: e.g. + *(sourceEnd - 1) is the last item. + + The return result indicates whether the conversion was successful, + and if not, whether the problem was in the source or target buffers. + (Only the first encountered problem is indicated.) + + After the conversion, *sourceStart and *targetStart are both + updated to point to the end of last text successfully converted in + the respective buffers. + + Input parameters: + sourceStart - pointer to a pointer to the source buffer. + The contents of this are modified on return so that + it points at the next thing to be converted. + targetStart - similarly, pointer to pointer to the target buffer. + sourceEnd, targetEnd - respectively pointers to the ends of the + two buffers, for overflow checking only. + + These conversion functions take a ConversionFlags argument. When this + flag is set to strict, both irregular sequences and isolated surrogates + will cause an error. When the flag is set to lenient, both irregular + sequences and isolated surrogates are converted. + + Whether the flag is strict or lenient, all illegal sequences will cause + an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>, + or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code + must check for illegal sequences. + + When the flag is set to lenient, characters over 0x10FFFF are converted + to the replacement character; otherwise (when the flag is set to strict) + they constitute an error. + + Output parameters: + The value "sourceIllegal" is returned from some routines if the input + sequence is malformed. When "sourceIllegal" is returned, the source + value will point to the illegal value that caused the problem. E.g., + in UTF-8 when a sequence is malformed, it points to the start of the + malformed sequence. + + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Fixes & updates, Sept 2001. + +------------------------------------------------------------------------ */ + +#ifndef CLANG_BASIC_CONVERTUTF_H +#define CLANG_BASIC_CONVERTUTF_H + +/* --------------------------------------------------------------------- + The following 4 definitions are compiler-specific. + The C standard does not guarantee that wchar_t has at least + 16 bits, so wchar_t is no less portable than unsigned short! + All should be unsigned values to avoid sign extension during + bit mask & shift operations. +------------------------------------------------------------------------ */ + +typedef unsigned int UTF32; /* at least 32 bits */ +typedef unsigned short UTF16; /* at least 16 bits */ +typedef unsigned char UTF8; /* typically 8 bits */ +typedef unsigned char Boolean; /* 0 or 1 */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF + +#define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4 + +typedef enum { + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +/* This is for C++ and does no harm in C */ +#ifdef __cplusplus +extern "C" { +#endif + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF8toUTF32 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF8 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF8 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF32 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF16 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); + +Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd); + +unsigned getNumBytesForUTF8(UTF8 firstByte); + +#ifdef __cplusplus +} + +/*************************************************************************/ +/* Below are LLVM-specific wrappers of the functions above. */ + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +/** + * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on + * WideCharWidth. The converted data is written to ResultPtr, which needs to + * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success, + * ResultPtr will point one after the end of the copied string. On failure, + * ResultPtr will not be changed, and ErrorPtr will be set to the location of + * the first character which could not be converted. + * \return true on success. + */ +bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source, + char *&ResultPtr, const UTF8 *&ErrorPtr); + +/** + * Convert an Unicode code point to UTF8 sequence. + * + * \param Source a Unicode code point. + * \param [in,out] ResultPtr pointer to the output buffer, needs to be at least + * \c UNI_MAX_UTF8_BYTES_PER_CODE_POINT bytes. On success \c ResultPtr is + * updated one past end of the converted sequence. + * + * \returns true on success. + */ +bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr); + +/** + * Convert the first UTF8 sequence in the given source buffer to a UTF32 + * code point. + * + * \param [in,out] source A pointer to the source buffer. If the conversion + * succeeds, this pointer will be updated to point to the byte just past the + * end of the converted sequence. + * \param sourceEnd A pointer just past the end of the source buffer. + * \param [out] target The converted code + * \param flags Whether the conversion is strict or lenient. + * + * \returns conversionOK on success + * + * \sa ConvertUTF8toUTF32 + */ +static inline ConversionResult convertUTF8Sequence(const UTF8 **source, + const UTF8 *sourceEnd, + UTF32 *target, + ConversionFlags flags) { + if (*source == sourceEnd) + return sourceExhausted; + unsigned size = getNumBytesForUTF8(**source); + if ((ptrdiff_t)size > sourceEnd - *source) + return sourceExhausted; + return ConvertUTF8toUTF32(source, *source + size, &target, target + 1, flags); +} +} /* end namespace llvm */ + +#endif + +/* --------------------------------------------------------------------- */ + +#endif diff --git a/include/llvm/Support/DOTGraphTraits.h b/include/llvm/Support/DOTGraphTraits.h index 483f267..95e37c0 100644 --- a/include/llvm/Support/DOTGraphTraits.h +++ b/include/llvm/Support/DOTGraphTraits.h @@ -79,6 +79,11 @@ public: return false; } + template<typename GraphType> + static std::string getNodeDescription(const void *, const GraphType &) { + return ""; + } + /// If you want to specify custom node attributes, this is the place to do so /// template<typename GraphType> diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h index a3ae782..e8a19cd 100644 --- a/include/llvm/Support/DataExtractor.h +++ b/include/llvm/Support/DataExtractor.h @@ -18,22 +18,24 @@ namespace llvm { class DataExtractor { StringRef Data; uint8_t IsLittleEndian; - uint8_t PointerSize; + uint8_t AddressSize; public: /// Construct with a buffer that is owned by the caller. /// /// This constructor allows us to use data that is owned by the /// caller. The data must stay around as long as this object is /// valid. - DataExtractor(StringRef Data, bool IsLittleEndian, uint8_t PointerSize) - : Data(Data), IsLittleEndian(IsLittleEndian), PointerSize(PointerSize) {} + DataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize) + : Data(Data), IsLittleEndian(IsLittleEndian), AddressSize(AddressSize) {} - /// getData - Get the data pointed to by this extractor. + /// \brief Get the data pointed to by this extractor. StringRef getData() const { return Data; } - /// isLittleEndian - Get the endianess for this extractor. + /// \brief Get the endianess for this extractor. bool isLittleEndian() const { return IsLittleEndian; } - /// getAddressSize - Get the address size for this extractor. - uint8_t getAddressSize() const { return PointerSize; } + /// \brief Get the address size for this extractor. + uint8_t getAddressSize() const { return AddressSize; } + /// \brief Set the address size for this extractor. + void setAddressSize(uint8_t Size) { AddressSize = Size; } /// Extract a C string from \a *offset_ptr. /// @@ -113,7 +115,7 @@ public: /// /// Extract a single pointer from the data and update the offset /// pointed to by \a offset_ptr. The size of the extracted pointer - /// comes from the \a m_addr_size member variable and should be + /// is \a getAddressSize(), so the address size has to be /// set correctly prior to extracting any pointer values. /// /// @param[in,out] offset_ptr @@ -126,7 +128,7 @@ public: /// @return /// The extracted pointer value as a 64 integer. uint64_t getAddress(uint32_t *offset_ptr) const { - return getUnsigned(offset_ptr, PointerSize); + return getUnsigned(offset_ptr, AddressSize); } /// Extract a uint8_t value from \a *offset_ptr. diff --git a/include/llvm/Support/DataStream.h b/include/llvm/Support/DataStream.h index fedb0c9..8bc4133 100644 --- a/include/llvm/Support/DataStream.h +++ b/include/llvm/Support/DataStream.h @@ -14,8 +14,8 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_DATASTREAM_H_ -#define LLVM_SUPPORT_DATASTREAM_H_ +#ifndef LLVM_SUPPORT_DATASTREAM_H +#define LLVM_SUPPORT_DATASTREAM_H #include <string> diff --git a/include/llvm/Support/DebugLoc.h b/include/llvm/Support/DebugLoc.h index 0498075..3596be8 100644 --- a/include/llvm/Support/DebugLoc.h +++ b/include/llvm/Support/DebugLoc.h @@ -109,4 +109,4 @@ namespace llvm { }; } // end namespace llvm -#endif /* LLVM_DEBUGLOC_H */ +#endif /* LLVM_SUPPORT_DEBUGLOC_H */ diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index c703da5..b52914f 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -16,6 +16,9 @@ #ifndef LLVM_SUPPORT_DWARF_H #define LLVM_SUPPORT_DWARF_H +#include "llvm/Support/DataTypes.h" + + namespace llvm { //===----------------------------------------------------------------------===// @@ -53,10 +56,16 @@ enum llvm_dwarf_constants { DW_TAG_user_base = 0x1000, // Recommended base for user tags. - DW_CIE_VERSION = 1, // Common frame information version. - DW_CIE_ID = 0xffffffff // Common frame information mark. + DW_CIE_VERSION = 1 // Common frame information version. }; + +// Special ID values that distinguish a CIE from a FDE in DWARF CFI. +// Not inside an enum because a 64-bit value is needed. +const uint32_t DW_CIE_ID = UINT32_MAX; +const uint64_t DW64_CIE_ID = UINT64_MAX; + + enum dwarf_constants { DWARF_VERSION = 2, diff --git a/include/llvm/Support/DynamicLibrary.h b/include/llvm/Support/DynamicLibrary.h index 0f59cbf..1e2d16c 100644 --- a/include/llvm/Support/DynamicLibrary.h +++ b/include/llvm/Support/DynamicLibrary.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_DYNAMIC_LIBRARY_H -#define LLVM_SYSTEM_DYNAMIC_LIBRARY_H +#ifndef LLVM_SYSTEM_DYNAMICLIBRARY_H +#define LLVM_SYSTEM_DYNAMICLIBRARY_H #include <string> diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index d6e54be..8e6b91e 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -271,6 +271,7 @@ enum { EM_SLE9X = 179, // Infineon Technologies SLE9X core EM_L10M = 180, // Intel L10M EM_K10M = 181, // Intel K10M + EM_AARCH64 = 183, // ARM AArch64 EM_AVR32 = 185, // Atmel Corporation 32-bit microprocessor family EM_STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller EM_TILE64 = 187, // Tilera TILE64 multicore architecture family @@ -366,7 +367,8 @@ enum { R_X86_64_SIZE64 = 33, R_X86_64_GOTPC32_TLSDESC = 34, R_X86_64_TLSDESC_CALL = 35, - R_X86_64_TLSDESC = 36 + R_X86_64_TLSDESC = 36, + R_X86_64_IRELATIVE = 37 }; // i386 relocations. @@ -469,6 +471,7 @@ enum { R_PPC64_ADDR16_HI = 5, R_PPC64_ADDR14 = 7, R_PPC64_REL24 = 10, + R_PPC64_REL32 = 26, R_PPC64_ADDR64 = 38, R_PPC64_ADDR16_HIGHER = 39, R_PPC64_ADDR16_HIGHEST = 41, @@ -480,6 +483,7 @@ enum { R_PPC64_TOC16_DS = 63, R_PPC64_TOC16_LO_DS = 64, R_PPC64_TLS = 67, + R_PPC64_TPREL16_LO = 70, R_PPC64_DTPREL16_LO = 75, R_PPC64_DTPREL16_HA = 77, R_PPC64_GOT_TLSGD16_LO = 80, @@ -492,8 +496,106 @@ enum { R_PPC64_TLSLD = 108 }; +// ELF Relocation types for AArch64 + +enum { + R_AARCH64_NONE = 0x100, + + R_AARCH64_ABS64 = 0x101, + R_AARCH64_ABS32 = 0x102, + R_AARCH64_ABS16 = 0x103, + R_AARCH64_PREL64 = 0x104, + R_AARCH64_PREL32 = 0x105, + R_AARCH64_PREL16 = 0x106, + + R_AARCH64_MOVW_UABS_G0 = 0x107, + R_AARCH64_MOVW_UABS_G0_NC = 0x108, + R_AARCH64_MOVW_UABS_G1 = 0x109, + R_AARCH64_MOVW_UABS_G1_NC = 0x10a, + R_AARCH64_MOVW_UABS_G2 = 0x10b, + R_AARCH64_MOVW_UABS_G2_NC = 0x10c, + R_AARCH64_MOVW_UABS_G3 = 0x10d, + R_AARCH64_MOVW_SABS_G0 = 0x10e, + R_AARCH64_MOVW_SABS_G1 = 0x10f, + R_AARCH64_MOVW_SABS_G2 = 0x110, + + R_AARCH64_LD_PREL_LO19 = 0x111, + R_AARCH64_ADR_PREL_LO21 = 0x112, + R_AARCH64_ADR_PREL_PG_HI21 = 0x113, + R_AARCH64_ADD_ABS_LO12_NC = 0x115, + R_AARCH64_LDST8_ABS_LO12_NC = 0x116, + + R_AARCH64_TSTBR14 = 0x117, + R_AARCH64_CONDBR19 = 0x118, + R_AARCH64_JUMP26 = 0x11a, + R_AARCH64_CALL26 = 0x11b, + + R_AARCH64_LDST16_ABS_LO12_NC = 0x11c, + R_AARCH64_LDST32_ABS_LO12_NC = 0x11d, + R_AARCH64_LDST64_ABS_LO12_NC = 0x11e, + + R_AARCH64_LDST128_ABS_LO12_NC = 0x12b, + + R_AARCH64_ADR_GOT_PAGE = 0x137, + R_AARCH64_LD64_GOT_LO12_NC = 0x138, + + R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 0x20b, + R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 0x20c, + R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 0x20d, + R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 0x20e, + R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 0x20f, + R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 0x210, + R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 0x211, + R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 0x212, + R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 0x213, + R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 0x214, + R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 0x215, + R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 0x216, + R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 0x217, + R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 0x218, + R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 0x219, + R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 0x21a, + + R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 0x21b, + R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 0x21c, + R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 0x21d, + R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 0x21e, + R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 0x21f, + + R_AARCH64_TLSLE_MOVW_TPREL_G2 = 0x220, + R_AARCH64_TLSLE_MOVW_TPREL_G1 = 0x221, + R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 0x222, + R_AARCH64_TLSLE_MOVW_TPREL_G0 = 0x223, + R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 0x224, + R_AARCH64_TLSLE_ADD_TPREL_HI12 = 0x225, + R_AARCH64_TLSLE_ADD_TPREL_LO12 = 0x226, + R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 0x227, + R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 0x228, + R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 0x229, + R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 0x22a, + R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC = 0x22b, + R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 0x22c, + R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 0x22d, + R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 0x22e, + R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 0x22f, + + R_AARCH64_TLSDESC_ADR_PAGE = 0x232, + R_AARCH64_TLSDESC_LD64_LO12_NC = 0x233, + R_AARCH64_TLSDESC_ADD_LO12_NC = 0x234, + + R_AARCH64_TLSDESC_CALL = 0x239 +}; + // ARM Specific e_flags -enum { EF_ARM_EABIMASK = 0xFF000000U }; +enum { + EF_ARM_EABI_UNKNOWN = 0x00000000U, + EF_ARM_EABI_VER1 = 0x01000000U, + EF_ARM_EABI_VER2 = 0x02000000U, + EF_ARM_EABI_VER3 = 0x03000000U, + EF_ARM_EABI_VER4 = 0x04000000U, + EF_ARM_EABI_VER5 = 0x05000000U, + EF_ARM_EABIMASK = 0xFF000000U +}; // ELF Relocation types for ARM // Meets 2.08 ABI Specs. @@ -637,6 +739,13 @@ enum { 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_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI + + //ARCH_ASE + EF_MIPS_MICROMIPS = 0x02000000, // microMIPS + EF_MIPS_ARCH_ASE_M16 = + 0x04000000, // Has Mips-16 ISA extensions + //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 @@ -707,6 +816,11 @@ enum { R_MIPS_NUM = 218 }; +// Special values for the st_other field in the symbol table entry for MIPS. +enum { + STO_MIPS_MICROMIPS = 0x80 // MIPS Specific ISA for MicroMips +}; + // Hexagon Specific e_flags // Release 5 ABI enum { @@ -726,14 +840,14 @@ enum { }; // Hexagon specific Section indexes for common small data -// Release 5 ABI +// Release 5 ABI enum { SHN_HEXAGON_SCOMMON = 0xff00, // Other access sizes SHN_HEXAGON_SCOMMON_1 = 0xff01, // Byte-sized access SHN_HEXAGON_SCOMMON_2 = 0xff02, // Half-word-sized access SHN_HEXAGON_SCOMMON_4 = 0xff03, // Word-sized access SHN_HEXAGON_SCOMMON_8 = 0xff04 // Double-word-size access -}; +}; // ELF Relocation types for Hexagon // Release 5 ABI @@ -894,8 +1008,7 @@ enum { SHT_GNU_verneed = 0x6ffffffe, // GNU version references. SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table. SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. - SHT_LOPROC = 0x70000000, // Lowest processor architecture-specific type. - + SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type. // Fixme: All this is duplicated in MCSectionELF. Why?? // Exception Index table SHT_ARM_EXIDX = 0x70000001U, @@ -905,10 +1018,14 @@ enum { SHT_ARM_ATTRIBUTES = 0x70000003U, SHT_ARM_DEBUGOVERLAY = 0x70000004U, SHT_ARM_OVERLAYSECTION = 0x70000005U, - + SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in + // this section based on their sizes SHT_X86_64_UNWIND = 0x70000001, // Unwind information - SHT_HIPROC = 0x7fffffff, // Highest processor architecture-specific type. + SHT_MIPS_REGINFO = 0x70000006, // Register usage information + SHT_MIPS_OPTIONS = 0x7000000d, // General options + + SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. SHT_HIUSER = 0xffffffff // Highest type reserved for applications. }; @@ -970,7 +1087,14 @@ enum { // sets this flag besides being able to refer to data in a section that does // not set it; likewise, a small code model object can refer only to code in a // section that does not set this flag. - SHF_X86_64_LARGE = 0x10000000 + SHF_X86_64_LARGE = 0x10000000, + + // All sections with the GPREL flag are grouped into a global data area + // for faster accesses + SHF_HEX_GPREL = 0x10000000, + + // Do not strip this section. FIXME: We need target specific SHF_ enums. + SHF_MIPS_NOSTRIP = 0x8000000 }; // Section Group Flags @@ -1005,7 +1129,7 @@ struct Elf64_Sym { Elf64_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes unsigned char st_other; // Must be zero; reserved - Elf64_Half st_shndx; // Which section (header table index) it's defined in + Elf64_Half st_shndx; // Which section (header tbl index) it's defined in Elf64_Addr st_value; // Value or address associated with the symbol Elf64_Xword st_size; // Size of the symbol @@ -1060,6 +1184,11 @@ enum { STV_PROTECTED = 3 // Visible in other components but not preemptable }; +// Symbol number. +enum { + STN_UNDEF = 0 +}; + // Relocation entry, without explicit addend. struct Elf32_Rel { Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) @@ -1100,14 +1229,14 @@ struct Elf64_Rel { // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: - Elf64_Xword getSymbol() const { return (r_info >> 32); } - unsigned char getType() const { - return (unsigned char) (r_info & 0xffffffffL); + Elf64_Word getSymbol() const { return (r_info >> 32); } + Elf64_Word getType() const { + return (Elf64_Word) (r_info & 0xffffffffL); } - void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); } - void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(Elf64_Xword s, unsigned char t) { - r_info = (s << 32) + (t&0xffffffffL); + void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); } + void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf64_Word s, Elf64_Word t) { + r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL); } }; @@ -1119,14 +1248,14 @@ struct Elf64_Rela { // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: - Elf64_Xword getSymbol() const { return (r_info >> 32); } - unsigned char getType() const { - return (unsigned char) (r_info & 0xffffffffL); + Elf64_Word getSymbol() const { return (r_info >> 32); } + Elf64_Word getType() const { + return (Elf64_Word) (r_info & 0xffffffffL); } - void setSymbol(Elf64_Xword s) { setSymbolAndType(s, getType()); } - void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(Elf64_Xword s, unsigned char t) { - r_info = (s << 32) + (t&0xffffffffL); + void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); } + void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf64_Word s, Elf64_Word t) { + r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL); } }; @@ -1148,7 +1277,7 @@ struct Elf64_Phdr { Elf64_Word p_flags; // Segment flags Elf64_Off p_offset; // File offset where segment is located, in bytes Elf64_Addr p_vaddr; // Virtual address of beginning of segment - Elf64_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf64_Addr p_paddr; // Physical addr of beginning of segment (OS-specific) Elf64_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) Elf64_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) Elf64_Xword p_align; // Segment alignment constraint @@ -1179,7 +1308,7 @@ enum { PT_GNU_RELRO = 0x6474e552, // Read-only after relocation. // ARM program header types. - PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility information + PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility info // These all contain stack unwind tables. PT_ARM_EXIDX = 0x70000001, PT_ARM_UNWIND = 0x70000001 diff --git a/include/llvm/Support/Errno.h b/include/llvm/Support/Errno.h index 150bdb7..8e145c7 100644 --- a/include/llvm/Support/Errno.h +++ b/include/llvm/Support/Errno.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_ERRNO_H -#define LLVM_SYSTEM_ERRNO_H +#ifndef LLVM_SUPPORT_ERRNO_H +#define LLVM_SUPPORT_ERRNO_H #include <string> diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h new file mode 100644 index 0000000..ceec33d --- /dev/null +++ b/include/llvm/Support/ErrorOr.h @@ -0,0 +1,488 @@ +//===- llvm/Support/ErrorOr.h - Error Smart Pointer -----------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// +/// Provides ErrorOr<T> smart pointer. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERROR_OR_H +#define LLVM_SUPPORT_ERROR_OR_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/system_error.h" +#include "llvm/Support/type_traits.h" + +#include <cassert> +#if LLVM_HAS_CXX11_TYPETRAITS +#include <type_traits> +#endif + +namespace llvm { +struct ErrorHolderBase { + error_code Error; + uint16_t RefCount; + bool HasUserData; + + ErrorHolderBase() : RefCount(1) {} + + void aquire() { + ++RefCount; + } + + void release() { + if (--RefCount == 0) + delete this; + } + +protected: + virtual ~ErrorHolderBase() {} +}; + +template<class T> +struct ErrorHolder : ErrorHolderBase { +#if LLVM_HAS_RVALUE_REFERENCES + ErrorHolder(T &&UD) : UserData(llvm_move(UD)) {} +#else + ErrorHolder(T &UD) : UserData(UD) {} +#endif + T UserData; +}; + +template<class Tp> struct ErrorOrUserDataTraits : llvm::false_type {}; + +#if LLVM_HAS_CXX11_TYPETRAITS && LLVM_HAS_RVALUE_REFERENCES +template<class T, class V> +typename std::enable_if< std::is_constructible<T, V>::value + , typename std::remove_reference<V>::type>::type && + moveIfMoveConstructible(V &Val) { + return std::move(Val); +} + +template<class T, class V> +typename std::enable_if< !std::is_constructible<T, V>::value + , typename std::remove_reference<V>::type>::type & +moveIfMoveConstructible(V &Val) { + return Val; +} +#else +template<class T, class V> +V &moveIfMoveConstructible(V &Val) { + return Val; +} +#endif + +/// \brief Stores a reference that can be changed. +template <typename T> +class ReferenceStorage { + T *Storage; + +public: + ReferenceStorage(T &Ref) : Storage(&Ref) {} + + operator T &() const { return *Storage; } + T &get() const { return *Storage; } +}; + +/// \brief Represents either an error or a value T. +/// +/// ErrorOr<T> is a pointer-like class that represents the result of an +/// operation. The result is either an error, or a value of type T. This is +/// designed to emulate the usage of returning a pointer where nullptr indicates +/// failure. However instead of just knowing that the operation failed, we also +/// have an error_code and optional user data that describes why it failed. +/// +/// It is used like the following. +/// \code +/// ErrorOr<Buffer> getBuffer(); +/// void handleError(error_code ec); +/// +/// auto buffer = getBuffer(); +/// if (!buffer) +/// handleError(buffer); +/// buffer->write("adena"); +/// \endcode +/// +/// ErrorOr<T> also supports user defined data for specific error_codes. To use +/// this feature you must first add a template specialization of +/// ErrorOrUserDataTraits derived from std::true_type for your type in the lld +/// namespace. This specialization must have a static error_code error() +/// function that returns the error_code this data is used with. +/// +/// getError<UserData>() may be called to get either the stored user data, or +/// a default constructed UserData if none was stored. +/// +/// Example: +/// \code +/// struct InvalidArgError { +/// InvalidArgError() {} +/// InvalidArgError(std::string S) : ArgName(S) {} +/// std::string ArgName; +/// }; +/// +/// namespace llvm { +/// template<> +/// struct ErrorOrUserDataTraits<InvalidArgError> : std::true_type { +/// static error_code error() { +/// return make_error_code(errc::invalid_argument); +/// } +/// }; +/// } // end namespace llvm +/// +/// using namespace llvm; +/// +/// ErrorOr<int> foo() { +/// return InvalidArgError("adena"); +/// } +/// +/// int main() { +/// auto a = foo(); +/// if (!a && error_code(a) == errc::invalid_argument) +/// llvm::errs() << a.getError<InvalidArgError>().ArgName << "\n"; +/// } +/// \endcode +/// +/// An implicit conversion to bool provides a way to check if there was an +/// error. The unary * and -> operators provide pointer like access to the +/// value. Accessing the value when there is an error has undefined behavior. +/// +/// When T is a reference type the behaivor is slightly different. The reference +/// is held in a std::reference_wrapper<std::remove_reference<T>::type>, and +/// there is special handling to make operator -> work as if T was not a +/// reference. +/// +/// T cannot be a rvalue reference. +template<class T> +class ErrorOr { + template <class OtherT> friend class ErrorOr; + static const bool isRef = is_reference<T>::value; + typedef ReferenceStorage<typename remove_reference<T>::type> wrap; + +public: + typedef typename + conditional< isRef + , wrap + , T + >::type storage_type; + +private: + typedef typename remove_reference<T>::type &reference; + typedef typename remove_reference<T>::type *pointer; + +public: + ErrorOr() : IsValid(false) {} + + ErrorOr(llvm::error_code EC) : HasError(true), IsValid(true) { + Error = new ErrorHolderBase; + Error->Error = EC; + Error->HasUserData = false; + } + + template<class UserDataT> + ErrorOr(UserDataT UD, typename + enable_if_c<ErrorOrUserDataTraits<UserDataT>::value>::type* = 0) + : HasError(true), IsValid(true) { + Error = new ErrorHolder<UserDataT>(llvm_move(UD)); + Error->Error = ErrorOrUserDataTraits<UserDataT>::error(); + Error->HasUserData = true; + } + + ErrorOr(T Val) : HasError(false), IsValid(true) { + new (get()) storage_type(moveIfMoveConstructible<storage_type>(Val)); + } + + ErrorOr(const ErrorOr &Other) : IsValid(false) { + copyConstruct(Other); + } + + template <class OtherT> + ErrorOr(const ErrorOr<OtherT> &Other) : IsValid(false) { + copyConstruct(Other); + } + + ErrorOr &operator =(const ErrorOr &Other) { + copyAssign(Other); + return *this; + } + + template <class OtherT> + ErrorOr &operator =(const ErrorOr<OtherT> &Other) { + copyAssign(Other); + return *this; + } + +#if LLVM_HAS_RVALUE_REFERENCES + ErrorOr(ErrorOr &&Other) : IsValid(false) { + moveConstruct(std::move(Other)); + } + + template <class OtherT> + ErrorOr(ErrorOr<OtherT> &&Other) : IsValid(false) { + moveConstruct(std::move(Other)); + } + + ErrorOr &operator =(ErrorOr &&Other) { + moveAssign(std::move(Other)); + return *this; + } + + template <class OtherT> + ErrorOr &operator =(ErrorOr<OtherT> &&Other) { + moveAssign(std::move(Other)); + return *this; + } +#endif + + ~ErrorOr() { + if (!IsValid) + return; + if (HasError) + Error->release(); + else + get()->~storage_type(); + } + + template<class ET> + ET getError() const { + assert(IsValid && "Cannot get the error of a default constructed ErrorOr!"); + assert(HasError && "Cannot get an error if none exists!"); + assert(ErrorOrUserDataTraits<ET>::error() == Error->Error && + "Incorrect user error data type for error!"); + if (!Error->HasUserData) + return ET(); + return reinterpret_cast<const ErrorHolder<ET>*>(Error)->UserData; + } + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + /// \brief Return false if there is an error. + operator unspecified_bool_type() const { + assert(IsValid && "Can't do anything on a default constructed ErrorOr!"); + return HasError ? 0 : unspecified_bool_true; + } + + operator llvm::error_code() const { + assert(IsValid && "Can't do anything on a default constructed ErrorOr!"); + return HasError ? Error->Error : llvm::error_code::success(); + } + + pointer operator ->() { + return toPointer(get()); + } + + reference operator *() { + return *get(); + } + +private: + template <class OtherT> + void copyConstruct(const ErrorOr<OtherT> &Other) { + // Construct an invalid ErrorOr if other is invalid. + if (!Other.IsValid) + return; + IsValid = true; + if (!Other.HasError) { + // Get the other value. + HasError = false; + new (get()) storage_type(*Other.get()); + } else { + // Get other's error. + Error = Other.Error; + HasError = true; + Error->aquire(); + } + } + + template <class T1> + static bool compareThisIfSameType(const T1 &a, const T1 &b) { + return &a == &b; + } + + template <class T1, class T2> + static bool compareThisIfSameType(const T1 &a, const T2 &b) { + return false; + } + + template <class OtherT> + void copyAssign(const ErrorOr<OtherT> &Other) { + if (compareThisIfSameType(*this, Other)) + return; + + this->~ErrorOr(); + new (this) ErrorOr(Other); + } + +#if LLVM_HAS_RVALUE_REFERENCES + template <class OtherT> + void moveConstruct(ErrorOr<OtherT> &&Other) { + // Construct an invalid ErrorOr if other is invalid. + if (!Other.IsValid) + return; + IsValid = true; + if (!Other.HasError) { + // Get the other value. + HasError = false; + new (get()) storage_type(std::move(*Other.get())); + // Tell other not to do any destruction. + Other.IsValid = false; + } else { + // Get other's error. + Error = Other.Error; + HasError = true; + // Tell other not to do any destruction. + Other.IsValid = false; + } + } + + template <class OtherT> + void moveAssign(ErrorOr<OtherT> &&Other) { + if (compareThisIfSameType(*this, Other)) + return; + + this->~ErrorOr(); + new (this) ErrorOr(std::move(Other)); + } +#endif + + pointer toPointer(pointer Val) { + return Val; + } + + pointer toPointer(wrap *Val) { + return &Val->get(); + } + + storage_type *get() { + assert(IsValid && "Can't do anything on a default constructed ErrorOr!"); + assert(!HasError && "Cannot get value when an error exists!"); + return reinterpret_cast<storage_type*>(TStorage.buffer); + } + + const storage_type *get() const { + assert(IsValid && "Can't do anything on a default constructed ErrorOr!"); + assert(!HasError && "Cannot get value when an error exists!"); + return reinterpret_cast<const storage_type*>(TStorage.buffer); + } + + union { + AlignedCharArrayUnion<storage_type> TStorage; + ErrorHolderBase *Error; + }; + bool HasError : 1; + bool IsValid : 1; +}; + +// ErrorOr specialization for void. +template <> +class ErrorOr<void> { +public: + ErrorOr() : Error(0, 0) {} + + ErrorOr(llvm::error_code EC) : Error(0, 0) { + if (EC == errc::success) { + Error.setInt(1); + return; + } + ErrorHolderBase *E = new ErrorHolderBase; + E->Error = EC; + E->HasUserData = false; + Error.setPointer(E); + } + + template<class UserDataT> + ErrorOr(UserDataT UD, typename + enable_if_c<ErrorOrUserDataTraits<UserDataT>::value>::type* = 0) + : Error(0, 0) { + ErrorHolderBase *E = new ErrorHolder<UserDataT>(llvm_move(UD)); + E->Error = ErrorOrUserDataTraits<UserDataT>::error(); + E->HasUserData = true; + Error.setPointer(E); + } + + ErrorOr(const ErrorOr &Other) : Error(0, 0) { + Error = Other.Error; + if (Other.Error.getPointer()->Error) { + Error.getPointer()->aquire(); + } + } + + ErrorOr &operator =(const ErrorOr &Other) { + if (this == &Other) + return *this; + + this->~ErrorOr(); + new (this) ErrorOr(Other); + + return *this; + } + +#if LLVM_HAS_RVALUE_REFERENCES + ErrorOr(ErrorOr &&Other) : Error(0) { + // Get other's error. + Error = Other.Error; + // Tell other not to do any destruction. + Other.Error.setPointer(0); + } + + ErrorOr &operator =(ErrorOr &&Other) { + if (this == &Other) + return *this; + + this->~ErrorOr(); + new (this) ErrorOr(std::move(Other)); + + return *this; + } +#endif + + ~ErrorOr() { + if (Error.getPointer()) + Error.getPointer()->release(); + } + + template<class ET> + ET getError() const { + assert(ErrorOrUserDataTraits<ET>::error() == *this && + "Incorrect user error data type for error!"); + if (!Error.getPointer()->HasUserData) + return ET(); + return reinterpret_cast<const ErrorHolder<ET> *>( + Error.getPointer())->UserData; + } + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + /// \brief Return false if there is an error. + operator unspecified_bool_type() const { + return Error.getInt() ? unspecified_bool_true : 0; + } + + operator llvm::error_code() const { + return Error.getInt() ? make_error_code(errc::success) + : Error.getPointer()->Error; + } + +private: + // If the bit is 1, the error is success. + llvm::PointerIntPair<ErrorHolderBase *, 1> Error; +}; + +template<class T, class E> +typename enable_if_c<is_error_code_enum<E>::value || + is_error_condition_enum<E>::value, bool>::type +operator ==(ErrorOr<T> &Err, E Code) { + return error_code(Err) == Code; +} +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/FEnv.h b/include/llvm/Support/FEnv.h index f6f4333..d9cf724 100644 --- a/include/llvm/Support/FEnv.h +++ b/include/llvm/Support/FEnv.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_FENV_H -#define LLVM_SYSTEM_FENV_H +#ifndef LLVM_SUPPORT_FENV_H +#define LLVM_SUPPORT_FENV_H #include "llvm/Config/config.h" #include <cerrno> diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index f1cbe97..bae3a5a 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -24,8 +24,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_FILE_SYSTEM_H -#define LLVM_SUPPORT_FILE_SYSTEM_H +#ifndef LLVM_SUPPORT_FILESYSTEM_H +#define LLVM_SUPPORT_FILESYSTEM_H #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h index e552315..f1040f5 100644 --- a/include/llvm/Support/GCOV.h +++ b/include/llvm/Support/GCOV.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_GCOV_H -#define LLVM_GCOV_H +#ifndef LLVM_SUPPORT_GCOV_H +#define LLVM_SUPPORT_GCOV_H #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" diff --git a/include/llvm/Support/GetElementPtrTypeIterator.h b/include/llvm/Support/GetElementPtrTypeIterator.h index 52b06ad..5a90553 100644 --- a/include/llvm/Support/GetElementPtrTypeIterator.h +++ b/include/llvm/Support/GetElementPtrTypeIterator.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_GETELEMENTPTRTYPE_H -#define LLVM_SUPPORT_GETELEMENTPTRTYPE_H +#ifndef LLVM_SUPPORT_GETELEMENTPTRTYPEITERATOR_H +#define LLVM_SUPPORT_GETELEMENTPTRTYPEITERATOR_H #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/User.h" diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index 30cfe61..22181d4 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -34,6 +34,10 @@ namespace llvm { namespace DOT { // Private functions... std::string EscapeString(const std::string &Label); + + /// \brief Get a color string for this node number. Simply round-robin selects + /// from a reasonable number of colors. + StringRef getColorString(unsigned NodeNumber); } namespace GraphProgram { @@ -173,6 +177,10 @@ public: // If we should include the address of the node in the label, do so now. if (DTraits.hasNodeAddressLabel(Node, G)) O << "|" << static_cast<const void*>(Node); + + std::string NodeDesc = DTraits.getNodeDescription(Node, G); + if (!NodeDesc.empty()) + O << "|" << DOT::EscapeString(NodeDesc); } std::string edgeSourceLabels; @@ -193,6 +201,10 @@ public: // If we should include the address of the node in the label, do so now. if (DTraits.hasNodeAddressLabel(Node, G)) O << "|" << static_cast<const void*>(Node); + + std::string NodeDesc = DTraits.getNodeDescription(Node, G); + if (!NodeDesc.empty()) + O << "|" << DOT::EscapeString(NodeDesc); } if (DTraits.hasEdgeDestLabels()) { diff --git a/include/llvm/Support/Host.h b/include/llvm/Support/Host.h index b331016..3a44405 100644 --- a/include/llvm/Support/Host.h +++ b/include/llvm/Support/Host.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_HOST_H -#define LLVM_SYSTEM_HOST_H +#ifndef LLVM_SUPPORT_HOST_H +#define LLVM_SUPPORT_HOST_H #include "llvm/ADT/StringMap.h" #include <string> @@ -42,6 +42,10 @@ namespace sys { /// CPU_TYPE-VENDOR-KERNEL-OPERATING_SYSTEM std::string getDefaultTargetTriple(); + /// getProcessTriple() - Return an appropriate target triple for generating + /// code to be loaded into the current process, e.g. when using the JIT. + std::string getProcessTriple(); + /// getHostCPUName - Get the LLVM name for the host CPU. The particular format /// of the name is target dependent, and suitable for passing as -mcpu to the /// target which matches the host. diff --git a/include/llvm/Support/IncludeFile.h b/include/llvm/Support/IncludeFile.h index a931972..2067e34 100644 --- a/include/llvm/Support/IncludeFile.h +++ b/include/llvm/Support/IncludeFile.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_INCLUDEFILE_H -#define LLVM_SYSTEM_INCLUDEFILE_H +#ifndef LLVM_SUPPORT_INCLUDEFILE_H +#define LLVM_SUPPORT_INCLUDEFILE_H /// This macro is the public interface that IncludeFile.h exports. This gives /// us the option to implement the "link the definition" capability in any diff --git a/include/llvm/Support/IntegersSubset.h b/include/llvm/Support/IntegersSubset.h index 9e5361c..ce34d78 100644 --- a/include/llvm/Support/IntegersSubset.h +++ b/include/llvm/Support/IntegersSubset.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CONSTANTRANGESSET_H_ -#define CONSTANTRANGESSET_H_ +#ifndef LLVM_SUPPORT_INTEGERSSUBSET_H +#define LLVM_SUPPORT_INTEGERSSUBSET_H #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" @@ -537,4 +537,4 @@ public: } -#endif /* CONSTANTRANGESSET_H_ */ +#endif /* CLLVM_SUPPORT_INTEGERSSUBSET_H */ diff --git a/include/llvm/Support/IntegersSubsetMapping.h b/include/llvm/Support/IntegersSubsetMapping.h index 7635d5e..641ce78 100644 --- a/include/llvm/Support/IntegersSubsetMapping.h +++ b/include/llvm/Support/IntegersSubsetMapping.h @@ -17,8 +17,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CRSBUILDER_H_ -#define CRSBUILDER_H_ +#ifndef LLVM_SUPPORT_INTEGERSSUBSETMAPPING_H +#define LLVM_SUPPORT_INTEGERSSUBSETMAPPING_H #include "llvm/Support/IntegersSubset.h" #include <list> @@ -585,4 +585,4 @@ typedef IntegersSubsetMapping<BasicBlock> IntegersSubsetToBB; } -#endif /* CRSBUILDER_H_ */ +#endif /* LLVM_SUPPORT_INTEGERSSUBSETMAPPING_CRSBUILDER_H */ diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h index b52e5bc..802b4f3 100644 --- a/include/llvm/Support/LEB128.h +++ b/include/llvm/Support/LEB128.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_LEB128_H -#define LLVM_SYSTEM_LEB128_H +#ifndef LLVM_SUPPORT_LEB128_H +#define LLVM_SUPPORT_LEB128_H #include "llvm/Support/raw_ostream.h" diff --git a/include/llvm/Support/Locale.h b/include/llvm/Support/Locale.h index b0f1295..b384d58 100644 --- a/include/llvm/Support/Locale.h +++ b/include/llvm/Support/Locale.h @@ -1,5 +1,5 @@ -#ifndef LLVM_SUPPORT_LOCALE -#define LLVM_SUPPORT_LOCALE +#ifndef LLVM_SUPPORT_LOCALE_H +#define LLVM_SUPPORT_LOCALE_H #include "llvm/ADT/StringRef.h" @@ -14,4 +14,4 @@ bool isPrint(int c); } } -#endif // LLVM_SUPPORT_LOCALE +#endif // LLVM_SUPPORT_LOCALE_H diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h index 8c4a760..9df8675 100644 --- a/include/llvm/Support/LockFileManager.h +++ b/include/llvm/Support/LockFileManager.h @@ -41,6 +41,7 @@ public: }; private: + SmallString<128> FileName; SmallString<128> LockFileName; SmallString<128> UniqueLockFileName; diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index 11f9e63..214bb6c 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -16,6 +16,10 @@ #include "llvm/Support/SwapByteOrder.h" +#ifdef _MSC_VER +# include <intrin.h> +#endif + namespace llvm { // NOTE: The following support functions use the _32/_64 extensions instead of @@ -61,7 +65,7 @@ inline bool isShiftedInt(int64_t x) { /// isUInt - Checks if an unsigned integer fits into the given bit width. template<unsigned N> inline bool isUInt(uint64_t x) { - return N >= 64 || x < (UINT64_C(1)<<N); + return N >= 64 || x < (UINT64_C(1)<<(N)); } // Template specializations to get better code for common cases. template<> diff --git a/include/llvm/Support/Memory.h b/include/llvm/Support/Memory.h index 025eee7..a08c796 100644 --- a/include/llvm/Support/Memory.h +++ b/include/llvm/Support/Memory.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_MEMORY_H -#define LLVM_SYSTEM_MEMORY_H +#ifndef LLVM_SUPPORT_MEMORY_H +#define LLVM_SUPPORT_MEMORY_H #include "llvm/Support/DataTypes.h" #include "llvm/Support/system_error.h" diff --git a/include/llvm/Support/MemoryObject.h b/include/llvm/Support/MemoryObject.h index b778b08..732b0f0 100644 --- a/include/llvm/Support/MemoryObject.h +++ b/include/llvm/Support/MemoryObject.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MEMORYOBJECT_H -#define MEMORYOBJECT_H +#ifndef LLVM_SUPPORT_MEMORYOBJECT_H +#define LLVM_SUPPORT_MEMORYOBJECT_H #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/Support/Mutex.h b/include/llvm/Support/Mutex.h index 6abc533..496a438 100644 --- a/include/llvm/Support/Mutex.h +++ b/include/llvm/Support/Mutex.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_MUTEX_H -#define LLVM_SYSTEM_MUTEX_H +#ifndef LLVM_SUPPORT_MUTEX_H +#define LLVM_SUPPORT_MUTEX_H #include "llvm/Support/Compiler.h" #include "llvm/Support/Threading.h" diff --git a/include/llvm/Support/PassNameParser.h b/include/llvm/Support/PassNameParser.h index bdfab39..317416c 100644 --- a/include/llvm/Support/PassNameParser.h +++ b/include/llvm/Support/PassNameParser.h @@ -20,8 +20,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_PASS_NAME_PARSER_H -#define LLVM_SUPPORT_PASS_NAME_PARSER_H +#ifndef LLVM_SUPPORT_PASSNAMEPARSER_H +#define LLVM_SUPPORT_PASSNAMEPARSER_H #include "llvm/ADT/STLExtras.h" #include "llvm/Pass.h" diff --git a/include/llvm/Support/PathV1.h b/include/llvm/Support/PathV1.h index 643ee8c..86328f0 100644 --- a/include/llvm/Support/PathV1.h +++ b/include/llvm/Support/PathV1.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_PATH_H -#define LLVM_SYSTEM_PATH_H +#ifndef LLVM_SUPPORT_PATHV1_H +#define LLVM_SUPPORT_PATHV1_H #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h index ea8da6d..4256d4a 100644 --- a/include/llvm/Support/Process.h +++ b/include/llvm/Support/Process.h @@ -22,8 +22,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_PROCESS_H -#define LLVM_SYSTEM_PROCESS_H +#ifndef LLVM_SUPPORT_PROCESS_H +#define LLVM_SUPPORT_PROCESS_H #include "llvm/Config/llvm-config.h" #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index 028565d..a0cc27c 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_PROGRAM_H -#define LLVM_SYSTEM_PROGRAM_H +#ifndef LLVM_SUPPORT_PROGRAM_H +#define LLVM_SUPPORT_PROGRAM_H #include "llvm/Support/Path.h" diff --git a/include/llvm/Support/RegistryParser.h b/include/llvm/Support/RegistryParser.h index 2cc5783..a6997b6 100644 --- a/include/llvm/Support/RegistryParser.h +++ b/include/llvm/Support/RegistryParser.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_REGISTRY_PARSER_H -#define LLVM_SUPPORT_REGISTRY_PARSER_H +#ifndef LLVM_SUPPORT_REGISTRYPARSER_H +#define LLVM_SUPPORT_REGISTRYPARSER_H #include "llvm/Support/CommandLine.h" #include "llvm/Support/Registry.h" @@ -52,4 +52,4 @@ namespace llvm { } -#endif // LLVM_SUPPORT_REGISTRY_PARSER_H +#endif // LLVM_SUPPORT_REGISTRYPARSER_H diff --git a/include/llvm/Support/SMLoc.h b/include/llvm/Support/SMLoc.h index 2b0e9df..0906471 100644 --- a/include/llvm/Support/SMLoc.h +++ b/include/llvm/Support/SMLoc.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef SUPPORT_SMLOC_H -#define SUPPORT_SMLOC_H +#ifndef LLVM_SUPPORT_SMLOC_H +#define LLVM_SUPPORT_SMLOC_H #include <cassert> diff --git a/include/llvm/Support/SaveAndRestore.h b/include/llvm/Support/SaveAndRestore.h index ffa99b9..6330bec 100644 --- a/include/llvm/Support/SaveAndRestore.h +++ b/include/llvm/Support/SaveAndRestore.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_SAVERESTORE -#define LLVM_ADT_SAVERESTORE +#ifndef LLVM_SUPPORT_SAVEANDRESTORE_H +#define LLVM_SUPPORT_SAVEANDRESTORE_H namespace llvm { diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h index 634f4cf..465656b 100644 --- a/include/llvm/Support/Signals.h +++ b/include/llvm/Support/Signals.h @@ -12,10 +12,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_SIGNALS_H -#define LLVM_SYSTEM_SIGNALS_H +#ifndef LLVM_SUPPORT_SIGNALS_H +#define LLVM_SUPPORT_SIGNALS_H #include "llvm/Support/Path.h" +#include <cstdio> namespace llvm { namespace sys { @@ -38,6 +39,9 @@ namespace sys { /// @brief Print a stack trace if a fatal signal occurs. void PrintStackTraceOnErrorSignal(); + /// \brief Print the stack trace using the given \c FILE object. + void PrintStackTrace(FILE *); + /// 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 /// to identify what instance of the handler it is. diff --git a/include/llvm/Support/Solaris.h b/include/llvm/Support/Solaris.h index 57eee2c..6228c4b 100644 --- a/include/llvm/Support/Solaris.h +++ b/include/llvm/Support/Solaris.h @@ -11,8 +11,8 @@ * *===----------------------------------------------------------------------===*/ -#ifndef LLVM_SYSTEM_SOLARIS_H -#define LLVM_SYSTEM_SOLARIS_H +#ifndef LLVM_SUPPORT_SOLARIS_H +#define LLVM_SUPPORT_SOLARIS_H #include <sys/types.h> #include <sys/regset.h> diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index aaee344..02abf92 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -13,10 +13,12 @@ // //===----------------------------------------------------------------------===// -#ifndef SUPPORT_SOURCEMGR_H -#define SUPPORT_SOURCEMGR_H +#ifndef LLVM_SUPPORT_SOURCEMGR_H +#define LLVM_SUPPORT_SOURCEMGR_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/SMLoc.h" #include <string> @@ -24,6 +26,7 @@ namespace llvm { class MemoryBuffer; class SourceMgr; class SMDiagnostic; + class SMFixIt; class Twine; class raw_ostream; @@ -143,6 +146,7 @@ public: /// the default error handler is used. void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef<SMRange> Ranges = ArrayRef<SMRange>(), + ArrayRef<SMFixIt> FixIts = ArrayRef<SMFixIt>(), bool ShowColors = true) const; @@ -152,7 +156,8 @@ public: /// @param Msg If non-null, the kind of message (e.g., "error") which is /// prefixed to the message. SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, - ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) const; + ArrayRef<SMRange> Ranges = ArrayRef<SMRange>(), + ArrayRef<SMFixIt> FixIts = ArrayRef<SMFixIt>()) const; /// PrintIncludeStack - Prints the names of included files and the line of the /// file they were included from. A diagnostic handler can use this before @@ -164,6 +169,38 @@ public: }; +/// Represents a single fixit, a replacement of one range of text with another. +class SMFixIt { + SMRange Range; + + std::string Text; + +public: + // FIXME: Twine.str() is not very efficient. + SMFixIt(SMLoc Loc, const Twine &Insertion) + : Range(Loc, Loc), Text(Insertion.str()) { + assert(Loc.isValid()); + } + + // FIXME: Twine.str() is not very efficient. + SMFixIt(SMRange R, const Twine &Replacement) + : Range(R), Text(Replacement.str()) { + assert(R.isValid()); + } + + StringRef getText() const { return Text; } + SMRange getRange() const { return Range; } + + bool operator<(const SMFixIt &Other) const { + if (Range.Start.getPointer() != Other.Range.Start.getPointer()) + return Range.Start.getPointer() < Other.Range.Start.getPointer(); + if (Range.End.getPointer() != Other.Range.End.getPointer()) + return Range.End.getPointer() < Other.Range.End.getPointer(); + return Text < Other.Text; + } +}; + + /// SMDiagnostic - Instances of this class encapsulate one diagnostic report, /// allowing printing to a raw_ostream as a caret diagnostic. class SMDiagnostic { @@ -174,35 +211,46 @@ class SMDiagnostic { SourceMgr::DiagKind Kind; std::string Message, LineContents; std::vector<std::pair<unsigned, unsigned> > Ranges; + SmallVector<SMFixIt, 4> FixIts; public: // Null diagnostic. SMDiagnostic() : SM(0), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {} // Diagnostic with no location (e.g. file not found, command line arg error). - SMDiagnostic(const std::string &filename, SourceMgr::DiagKind Knd, - const std::string &Msg) + SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg) : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {} // Diagnostic with a location. - SMDiagnostic(const SourceMgr &sm, SMLoc L, const std::string &FN, + SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN, int Line, int Col, SourceMgr::DiagKind Kind, - const std::string &Msg, const std::string &LineStr, - ArrayRef<std::pair<unsigned,unsigned> > Ranges); + StringRef Msg, StringRef LineStr, + ArrayRef<std::pair<unsigned,unsigned> > Ranges, + ArrayRef<SMFixIt> FixIts = ArrayRef<SMFixIt>()); const SourceMgr *getSourceMgr() const { return SM; } SMLoc getLoc() const { return Loc; } - const std::string &getFilename() const { return Filename; } + StringRef getFilename() const { return Filename; } int getLineNo() const { return LineNo; } int getColumnNo() const { return ColumnNo; } SourceMgr::DiagKind getKind() const { return Kind; } - const std::string &getMessage() const { return Message; } - const std::string &getLineContents() const { return LineContents; } - const std::vector<std::pair<unsigned, unsigned> > &getRanges() const { + StringRef getMessage() const { return Message; } + StringRef getLineContents() const { return LineContents; } + ArrayRef<std::pair<unsigned, unsigned> > getRanges() const { return Ranges; } - void print(const char *ProgName, raw_ostream &S, bool ShowColors = true) const; + + void addFixIt(const SMFixIt &Hint) { + FixIts.push_back(Hint); + } + + ArrayRef<SMFixIt> getFixIts() const { + return FixIts; + } + + void print(const char *ProgName, raw_ostream &S, + bool ShowColors = true) const; }; } // end llvm namespace diff --git a/include/llvm/Support/StreamableMemoryObject.h b/include/llvm/Support/StreamableMemoryObject.h index 2e1163f..3855485 100644 --- a/include/llvm/Support/StreamableMemoryObject.h +++ b/include/llvm/Support/StreamableMemoryObject.h @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// -#ifndef STREAMABLEMEMORYOBJECT_H_ -#define STREAMABLEMEMORYOBJECT_H_ +#ifndef LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H +#define LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/Compiler.h" diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h index 6c0592c..e65f9cc 100644 --- a/include/llvm/Support/SwapByteOrder.h +++ b/include/llvm/Support/SwapByteOrder.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_SWAP_BYTE_ORDER_H -#define LLVM_SYSTEM_SWAP_BYTE_ORDER_H +#ifndef LLVM_SUPPORT_SWAPBYTEORDER_H +#define LLVM_SUPPORT_SWAPBYTEORDER_H #include "llvm/Support/DataTypes.h" #include <cstddef> diff --git a/include/llvm/Support/ThreadLocal.h b/include/llvm/Support/ThreadLocal.h index 01f735c..7518626 100644 --- a/include/llvm/Support/ThreadLocal.h +++ b/include/llvm/Support/ThreadLocal.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_THREAD_LOCAL_H -#define LLVM_SYSTEM_THREAD_LOCAL_H +#ifndef LLVM_SUPPORT_THREADLOCAL_H +#define LLVM_SUPPORT_THREADLOCAL_H #include "llvm/Support/DataTypes.h" #include "llvm/Support/Threading.h" diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h index 9017afb..a7e8774 100644 --- a/include/llvm/Support/Threading.h +++ b/include/llvm/Support/Threading.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_THREADING_H -#define LLVM_SYSTEM_THREADING_H +#ifndef LLVM_SUPPORT_THREADING_H +#define LLVM_SUPPORT_THREADING_H namespace llvm { /// llvm_start_multithreaded - Allocate and initialize structures needed to diff --git a/include/llvm/Support/TimeValue.h b/include/llvm/Support/TimeValue.h index ab7401a..4b48b84 100644 --- a/include/llvm/Support/TimeValue.h +++ b/include/llvm/Support/TimeValue.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_TIMEVALUE_H -#define LLVM_SYSTEM_TIMEVALUE_H +#ifndef LLVM_SUPPORT_TIMEVALUE_H +#define LLVM_SUPPORT_TIMEVALUE_H #include "llvm/Support/DataTypes.h" #include <string> @@ -240,7 +240,7 @@ namespace sys { /// Posix, correcting for the difference in Posix zero time. /// @brief Convert to unix time (100 nanoseconds since 12:00:00a Jan 1,1970) uint64_t toPosixTime() const { - uint64_t result = seconds_ - PosixZeroTime.seconds_; + uint64_t result = seconds_ - PosixZeroTimeSeconds; result += nanos_ / NANOSECONDS_PER_POSIX_TICK; return result; } @@ -248,14 +248,14 @@ namespace sys { /// Converts the TimeValue into the corresponding number of seconds /// since the epoch (00:00:00 Jan 1,1970). uint64_t toEpochTime() const { - return seconds_ - PosixZeroTime.seconds_; + return seconds_ - PosixZeroTimeSeconds; } /// Converts the TimeValue into the corresponding number of "ticks" for /// Win32 platforms, correcting for the difference in Win32 zero time. /// @brief Convert to windows time (seconds since 12:00:00a Jan 1, 1601) uint64_t toWin32Time() const { - uint64_t result = seconds_ - Win32ZeroTime.seconds_; + uint64_t result = seconds_ - Win32ZeroTimeSeconds; result += nanos_ / NANOSECONDS_PER_WIN32_TICK; return result; } @@ -264,7 +264,7 @@ namespace sys { /// correction for the Posix zero time. /// @brief Convert to timespec time (ala POSIX.1b) void getTimespecTime( uint64_t& seconds, uint32_t& nanos ) const { - seconds = seconds_ - PosixZeroTime.seconds_; + seconds = seconds_ - PosixZeroTimeSeconds; nanos = nanos_; } @@ -331,7 +331,7 @@ namespace sys { /// TimeValue and assigns that value to \p this. /// @brief Convert seconds form PosixTime to TimeValue void fromEpochTime( SecondsType seconds ) { - seconds_ = seconds + PosixZeroTime.seconds_; + seconds_ = seconds + PosixZeroTimeSeconds; nanos_ = 0; this->normalize(); } @@ -340,7 +340,7 @@ namespace sys { /// corresponding TimeValue and assigns that value to \p this. /// @brief Convert seconds form Windows FILETIME to TimeValue void fromWin32Time( uint64_t win32Time ) { - this->seconds_ = win32Time / 10000000 + Win32ZeroTime.seconds_; + this->seconds_ = win32Time / 10000000 + Win32ZeroTimeSeconds; this->nanos_ = NanoSecondsType(win32Time % 10000000) * 100; } @@ -360,6 +360,9 @@ namespace sys { /// Store the values as a <timeval>. SecondsType seconds_;///< Stores the seconds part of the TimeVal NanoSecondsType nanos_; ///< Stores the nanoseconds part of the TimeVal + + static const SecondsType PosixZeroTimeSeconds; + static const SecondsType Win32ZeroTimeSeconds; /// @} }; diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h index 789c05f..d009d7f 100644 --- a/include/llvm/Support/Timer.h +++ b/include/llvm/Support/Timer.h @@ -6,11 +6,6 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines three classes: Timer, TimeRegion, and TimerGroup, -// documented below. -// -//===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_TIMER_H #define LLVM_SUPPORT_TIMER_H @@ -78,7 +73,7 @@ public: /// invocations of its startTimer()/stopTimer() methods. Given appropriate OS /// support it can also keep track of the RSS of the program at various points. /// By default, the Timer will print the amount of time it has captured to -/// standard error when the laster timer is destroyed, otherwise it is printed +/// standard error when the last timer is destroyed, otherwise it is printed /// when its TimerGroup is destroyed. Timers do not print their information /// if they are never started. /// @@ -126,7 +121,7 @@ private: /// The TimeRegion class is used as a helper class to call the startTimer() and /// stopTimer() methods of the Timer class. When the object is constructed, it -/// starts the timer specified as it's argument. When it is destroyed, it stops +/// starts the timer specified as its argument. When it is destroyed, it stops /// the relevant timer. This makes it easy to time a region of code. /// class TimeRegion { diff --git a/include/llvm/Support/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h index 65b182a..b3b7c57 100644 --- a/include/llvm/Support/ToolOutputFile.h +++ b/include/llvm/Support/ToolOutputFile.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_TOOL_OUTPUT_FILE_H -#define LLVM_SUPPORT_TOOL_OUTPUT_FILE_H +#ifndef LLVM_SUPPORT_TOOLOUTPUTFILE_H +#define LLVM_SUPPORT_TOOLOUTPUTFILE_H #include "llvm/Support/raw_ostream.h" diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h index 5b728bc..6e4f57f 100644 --- a/include/llvm/Support/YAMLParser.h +++ b/include/llvm/Support/YAMLParser.h @@ -35,8 +35,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_YAML_PARSER_H -#define LLVM_SUPPORT_YAML_PARSER_H +#ifndef LLVM_SUPPORT_YAMLPARSER_H +#define LLVM_SUPPORT_YAMLPARSER_H #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index 1862286..801868f 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_YAML_TRAITS_H_ -#define LLVM_YAML_TRAITS_H_ +#ifndef LLVM_SUPPORT_YAMLTRAITS_H +#define LLVM_SUPPORT_YAMLTRAITS_H #include "llvm/ADT/DenseMap.h" @@ -195,7 +195,7 @@ public: template <class T> struct has_ScalarTraits { - typedef llvm::StringRef (*Signature_input)(llvm::StringRef, void*, T&); + typedef StringRef (*Signature_input)(StringRef, void*, T&); typedef void (*Signature_output)(const T&, void*, llvm::raw_ostream&); template <typename U> @@ -528,73 +528,73 @@ yamlize(IO &io, T &Seq, bool) { template<> struct ScalarTraits<bool> { static void output(const bool &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, bool &); + static StringRef input(StringRef, void*, bool &); }; template<> struct ScalarTraits<StringRef> { static void output(const StringRef &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, StringRef &); + static StringRef input(StringRef, void*, StringRef &); }; template<> struct ScalarTraits<uint8_t> { static void output(const uint8_t &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, uint8_t &); + static StringRef input(StringRef, void*, uint8_t &); }; template<> struct ScalarTraits<uint16_t> { static void output(const uint16_t &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, uint16_t &); + static StringRef input(StringRef, void*, uint16_t &); }; template<> struct ScalarTraits<uint32_t> { static void output(const uint32_t &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, uint32_t &); + static StringRef input(StringRef, void*, uint32_t &); }; template<> struct ScalarTraits<uint64_t> { static void output(const uint64_t &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, uint64_t &); + static StringRef input(StringRef, void*, uint64_t &); }; template<> struct ScalarTraits<int8_t> { static void output(const int8_t &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, int8_t &); + static StringRef input(StringRef, void*, int8_t &); }; template<> struct ScalarTraits<int16_t> { static void output(const int16_t &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, int16_t &); + static StringRef input(StringRef, void*, int16_t &); }; template<> struct ScalarTraits<int32_t> { static void output(const int32_t &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, int32_t &); + static StringRef input(StringRef, void*, int32_t &); }; template<> struct ScalarTraits<int64_t> { static void output(const int64_t &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, int64_t &); + static StringRef input(StringRef, void*, int64_t &); }; template<> struct ScalarTraits<float> { static void output(const float &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, float &); + static StringRef input(StringRef, void*, float &); }; template<> struct ScalarTraits<double> { static void output(const double &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, double &); + static StringRef input(StringRef, void*, double &); }; @@ -913,25 +913,25 @@ LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64) template<> struct ScalarTraits<Hex8> { static void output(const Hex8 &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, Hex8 &); + static StringRef input(StringRef, void*, Hex8 &); }; template<> struct ScalarTraits<Hex16> { static void output(const Hex16 &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, Hex16 &); + static StringRef input(StringRef, void*, Hex16 &); }; template<> struct ScalarTraits<Hex32> { static void output(const Hex32 &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, Hex32 &); + static StringRef input(StringRef, void*, Hex32 &); }; template<> struct ScalarTraits<Hex64> { static void output(const Hex64 &, void*, llvm::raw_ostream &); - static llvm::StringRef input(llvm::StringRef , void*, Hex64 &); + static StringRef input(StringRef, void*, Hex64 &); }; @@ -1101,4 +1101,4 @@ operator<<(Output &yout, T &seq) { -#endif // LLVM_YAML_TRAITS_H_ +#endif // LLVM_SUPPORT_YAMLTRAITS_H diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index eab0f2d..d2b4a2a 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -29,7 +29,6 @@ namespace llvm { /// a chunk at a time. class raw_ostream { private: - // Do not implement. raw_ostream is noncopyable. void operator=(const raw_ostream &) LLVM_DELETED_FUNCTION; raw_ostream(const raw_ostream &) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/Support/system_error.h b/include/llvm/Support/system_error.h index 0d164f6..43dace6 100644 --- a/include/llvm/Support/system_error.h +++ b/include/llvm/Support/system_error.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_SYSTEM_ERROR_H -#define LLVM_SYSTEM_SYSTEM_ERROR_H +#ifndef LLVM_SUPPORT_SYSTEM_ERROR_H +#define LLVM_SUPPORT_SYSTEM_ERROR_H #include "llvm/Support/Compiler.h" diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index f930639..db43ccf 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -145,6 +145,10 @@ template <typename T> struct is_pointer<T* const> : true_type {}; template <typename T> struct is_pointer<T* volatile> : true_type {}; template <typename T> struct is_pointer<T* const volatile> : true_type {}; +/// \brief Metafunction that determines wheather the given type is a reference. +template <typename T> struct is_reference : false_type {}; +template <typename T> struct is_reference<T&> : true_type {}; + /// \brief Metafunction that determines whether the given type is either an /// integral type or an enumeration type. /// diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 8968534..3cf4f1f 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -175,8 +175,7 @@ public: }; -// BitsRecTy - 'bits<n>' - Represent a fixed number of bits -/// BitsRecTy - 'bits<n>' - Represent a fixed number of bits +/// BitsRecTy - 'bits<n>' - Represent a fixed number of bits /// class BitsRecTy : public RecTy { unsigned Size; @@ -288,10 +287,8 @@ public: } }; -// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of -// the specified type. -/// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must -/// be of the specified type. +/// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of +/// the specified type. /// class ListRecTy : public RecTy { RecTy *Ty; @@ -930,7 +927,7 @@ public: /// class BinOpInit : public OpInit { public: - enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, EQ }; + enum BinaryOp { ADD, SHL, SRA, SRL, STRCONCAT, CONCAT, EQ }; private: BinaryOp Opc; Init *LHS, *RHS; @@ -1387,12 +1384,14 @@ class Record { SmallVector<SMLoc, 4> Locs; std::vector<Init *> TemplateArgs; std::vector<RecordVal> Values; - std::vector<Record*> SuperClasses; + std::vector<Record *> SuperClasses; + std::vector<SMRange> SuperClassRanges; // Tracks Record instances. Not owned by Record. RecordKeeper &TrackedRecords; DefInit *TheInit; + bool IsAnonymous; void init(); void checkName(); @@ -1401,14 +1400,15 @@ public: // Constructs a record. explicit Record(const std::string &N, ArrayRef<SMLoc> locs, - RecordKeeper &records) : + RecordKeeper &records, bool Anonymous = false) : ID(LastID++), Name(StringInit::get(N)), Locs(locs.begin(), locs.end()), - TrackedRecords(records), TheInit(0) { + TrackedRecords(records), TheInit(0), IsAnonymous(Anonymous) { init(); } - explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records) : + explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records, + bool Anonymous = false) : ID(LastID++), Name(N), Locs(locs.begin(), locs.end()), - TrackedRecords(records), TheInit(0) { + TrackedRecords(records), TheInit(0), IsAnonymous(Anonymous) { init(); } @@ -1417,7 +1417,8 @@ public: Record(const Record &O) : ID(LastID++), Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs), Values(O.Values), SuperClasses(O.SuperClasses), - TrackedRecords(O.TrackedRecords), TheInit(O.TheInit) { } + SuperClassRanges(O.SuperClassRanges), TrackedRecords(O.TrackedRecords), + TheInit(O.TheInit), IsAnonymous(O.IsAnonymous) { } ~Record() {} @@ -1448,6 +1449,7 @@ public: } const std::vector<RecordVal> &getValues() const { return Values; } const std::vector<Record*> &getSuperClasses() const { return SuperClasses; } + ArrayRef<SMRange> getSuperClassRanges() const { return SuperClassRanges; } bool isTemplateArg(Init *Name) const { for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i) @@ -1522,9 +1524,10 @@ public: return false; } - void addSuperClass(Record *R) { + void addSuperClass(Record *R, SMRange Range) { assert(!isSubClassOf(R) && "Already subclassing record!"); SuperClasses.push_back(R); + SuperClassRanges.push_back(Range); } /// resolveReferences - If there are any field references that refer to fields @@ -1541,6 +1544,10 @@ public: return TrackedRecords; } + bool isAnonymous() const { + return IsAnonymous; + } + void dump() const; //===--------------------------------------------------------------------===// diff --git a/include/llvm/TableGen/StringMatcher.h b/include/llvm/TableGen/StringMatcher.h index 1b0572f..99cbcad 100644 --- a/include/llvm/TableGen/StringMatcher.h +++ b/include/llvm/TableGen/StringMatcher.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef STRINGMATCHER_H -#define STRINGMATCHER_H +#ifndef LLVM_TABLEGEN_STRINGMATCHER_H +#define LLVM_TABLEGEN_STRINGMATCHER_H #include "llvm/ADT/StringRef.h" #include <string> diff --git a/include/llvm/Target/CostTable.h b/include/llvm/Target/CostTable.h new file mode 100644 index 0000000..a974b56 --- /dev/null +++ b/include/llvm/Target/CostTable.h @@ -0,0 +1,64 @@ +//===-- CostTable.h - Instruction Cost Table handling -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Cost tables and simple lookup functions +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_COSTTABLE_H_ +#define LLVM_TARGET_COSTTABLE_H_ + +namespace llvm { + +/// Cost Table Entry +template <class TypeTy> +struct CostTblEntry { + int ISD; + TypeTy Type; + unsigned Cost; +}; + +/// Find in cost table, TypeTy must be comparable by == +template <class TypeTy> +int CostTableLookup(const CostTblEntry<TypeTy> *Tbl, + unsigned len, int ISD, TypeTy Ty) { + for (unsigned int i = 0; i < len; ++i) + if (Tbl[i].ISD == ISD && Tbl[i].Type == Ty) + return i; + + // Could not find an entry. + return -1; +} + +/// Type Conversion Cost Table +template <class TypeTy> +struct TypeConversionCostTblEntry { + int ISD; + TypeTy Dst; + TypeTy Src; + unsigned Cost; +}; + +/// Find in type conversion cost table, TypeTy must be comparable by == +template <class TypeTy> +int ConvertCostTableLookup(const TypeConversionCostTblEntry<TypeTy> *Tbl, + unsigned len, int ISD, TypeTy Dst, TypeTy Src) { + for (unsigned int i = 0; i < len; ++i) + if (Tbl[i].ISD == ISD && Tbl[i].Src == Src && Tbl[i].Dst == Dst) + return i; + + // Could not find an entry. + return -1; +} + +} // namespace llvm + + +#endif /* LLVM_TARGET_COSTTABLE_H_ */ diff --git a/include/llvm/Target/Mangler.h b/include/llvm/Target/Mangler.h index a50f54a..9500f1c 100644 --- a/include/llvm/Target/Mangler.h +++ b/include/llvm/Target/Mangler.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_MANGLER_H -#define LLVM_SUPPORT_MANGLER_H +#ifndef LLVM_TARGET_MANGLER_H +#define LLVM_TARGET_MANGLER_H #include "llvm/ADT/DenseMap.h" @@ -69,4 +69,4 @@ public: } // End llvm namespace -#endif // LLVM_SUPPORT_MANGLER_H +#endif // LLVM_TARGET_MANGLER_H diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 1781e47..876479b 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -367,8 +367,9 @@ class Instruction { // hasSideEffects - The instruction has side effects that are not // captured by any operands of the instruction or other flags. // - // neverHasSideEffects - Set on an instruction with no pattern if it has no - // side effects. + // neverHasSideEffects (deprecated) - Set on an instruction with no pattern + // if it has no side effects. This is now equivalent to setting + // "hasSideEffects = 0". bit hasSideEffects = ?; bit neverHasSideEffects = 0; diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h index 1958f90..58bfcec 100644 --- a/include/llvm/Target/TargetFrameLowering.h +++ b/include/llvm/Target/TargetFrameLowering.h @@ -120,6 +120,10 @@ public: /// by adding a check even before the "normal" function prologue. virtual void adjustForSegmentedStacks(MachineFunction &MF) 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 { } + /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee /// saved registers and returns true if it isn't possible / profitable to do /// so by issuing a series of store instructions via @@ -192,6 +196,21 @@ public: /// virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const { } + + /// eliminateCallFramePseudoInstr - This method is called during prolog/epilog + /// code insertion to eliminate call frame setup and destroy pseudo + /// instructions (but only if the Target is using them). It is responsible + /// for eliminating these instructions, replacing them with concrete + /// instructions. This method need only be implemented if using call frame + /// setup/destroy pseudo instructions. + /// + virtual void + eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const { + llvm_unreachable("Call Frame Pseudo Instructions do not exist on this " + "target!"); + } }; } // End llvm namespace diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index eee25c9..a28d63a 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -68,17 +68,12 @@ namespace llvm { }; } -//===----------------------------------------------------------------------===// -/// TargetLowering - This class defines information used to lower LLVM code to -/// legal SelectionDAG operators that the target instruction selector can accept -/// natively. -/// -/// This class also defines callbacks that targets must implement to lower -/// target-specific constructs to SelectionDAG operators. -/// -class TargetLowering { - TargetLowering(const TargetLowering&) LLVM_DELETED_FUNCTION; - void operator=(const TargetLowering&) LLVM_DELETED_FUNCTION; +/// TargetLoweringBase - 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; + public: /// LegalizeAction - This enum indicates whether operations are valid for a /// target, and if not, what action should be used to make them valid. @@ -136,9 +131,9 @@ public: } /// NOTE: The constructor takes ownership of TLOF. - explicit TargetLowering(const TargetMachine &TM, - const TargetLoweringObjectFile *TLOF); - virtual ~TargetLowering(); + explicit TargetLoweringBase(const TargetMachine &TM, + const TargetLoweringObjectFile *TLOF); + virtual ~TargetLoweringBase(); const TargetMachine &getTargetMachine() const { return TM; } const DataLayout *getDataLayout() const { return TD; } @@ -188,7 +183,7 @@ public: /// isPredictableSelectExpensive - Return true if selects are only cheaper /// than branches if the branch is unlikely to be predicted right. bool isPredictableSelectExpensive() const { - return predictableSelectIsExpensive; + return PredictableSelectIsExpensive; } /// getSetCCResultType - Return the ValueType of the result of SETCC @@ -664,7 +659,7 @@ public: /// return the limit for functions that have OptSize attribute. /// @brief Get maximum # of store operations permitted for llvm.memset unsigned getMaxStoresPerMemset(bool OptSize) const { - return OptSize ? maxStoresPerMemsetOptSize : maxStoresPerMemset; + return OptSize ? MaxStoresPerMemsetOptSize : MaxStoresPerMemset; } /// This function returns the maximum number of store operations permitted @@ -673,7 +668,7 @@ public: /// return the limit for functions that have OptSize attribute. /// @brief Get maximum # of store operations permitted for llvm.memcpy unsigned getMaxStoresPerMemcpy(bool OptSize) const { - return OptSize ? maxStoresPerMemcpyOptSize : maxStoresPerMemcpy; + return OptSize ? MaxStoresPerMemcpyOptSize : MaxStoresPerMemcpy; } /// This function returns the maximum number of store operations permitted @@ -682,7 +677,7 @@ public: /// return the limit for functions that have OptSize attribute. /// @brief Get maximum # of store operations permitted for llvm.memmove unsigned getMaxStoresPerMemmove(bool OptSize) const { - return OptSize ? maxStoresPerMemmoveOptSize : maxStoresPerMemmove; + return OptSize ? MaxStoresPerMemmoveOptSize : MaxStoresPerMemmove; } /// This function returns true if the target allows unaligned memory accesses. @@ -701,7 +696,7 @@ public: /// optimization. /// @brief Determine if the target should perform code placement optimization. bool shouldOptimizeCodePlacement() const { - return benefitFromCodePlacementOpt; + return BenefitFromCodePlacementOpt; } /// getOptimalMemOpType - Returns the target specific optimal type for load @@ -829,55 +824,6 @@ public: return InsertFencesForAtomic; } - /// getPreIndexedAddressParts - returns true by value, base pointer and - /// offset pointer and addressing mode by reference if the node's address - /// can be legally represented as pre-indexed load / store address. - virtual bool getPreIndexedAddressParts(SDNode * /*N*/, SDValue &/*Base*/, - SDValue &/*Offset*/, - ISD::MemIndexedMode &/*AM*/, - SelectionDAG &/*DAG*/) const { - return false; - } - - /// getPostIndexedAddressParts - returns true by value, base pointer and - /// offset pointer and addressing mode by reference if this node can be - /// combined with a load / store to form a post-indexed load / store. - virtual bool getPostIndexedAddressParts(SDNode * /*N*/, SDNode * /*Op*/, - SDValue &/*Base*/, SDValue &/*Offset*/, - ISD::MemIndexedMode &/*AM*/, - SelectionDAG &/*DAG*/) const { - return false; - } - - /// getJumpTableEncoding - Return the entry encoding for a jump table in the - /// current function. The returned value is a member of the - /// MachineJumpTableInfo::JTEntryKind enum. - virtual unsigned getJumpTableEncoding() const; - - virtual const MCExpr * - LowerCustomJumpTableEntry(const MachineJumpTableInfo * /*MJTI*/, - const MachineBasicBlock * /*MBB*/, unsigned /*uid*/, - MCContext &/*Ctx*/) const { - llvm_unreachable("Need to implement this hook if target has custom JTIs"); - } - - /// getPICJumpTableRelocaBase - Returns relocation base for the given PIC - /// jumptable. - virtual SDValue getPICJumpTableRelocBase(SDValue Table, - SelectionDAG &DAG) const; - - /// getPICJumpTableRelocBaseExpr - This returns the relocation base for the - /// given PIC jumptable, the same as getPICJumpTableRelocBase, but as an - /// MCExpr. - virtual const MCExpr * - getPICJumpTableRelocBaseExpr(const MachineFunction *MF, - unsigned JTI, MCContext &Ctx) const; - - /// isOffsetFoldingLegal - Return true if folding a constant offset - /// with the given GlobalAddress is legal. It is frequently not legal in - /// PIC relocation models. - virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; - /// getStackCookieLocation - Return true if the target stores stack /// protector cookies at a fixed offset in some non-standard address /// space, and populates the address space and offset as @@ -906,152 +852,6 @@ public: /// @} //===--------------------------------------------------------------------===// - // TargetLowering Optimization Methods - // - - /// TargetLoweringOpt - A convenience struct that encapsulates a DAG, and two - /// SDValues for returning information from TargetLowering to its clients - /// that want to combine - struct TargetLoweringOpt { - SelectionDAG &DAG; - bool LegalTys; - bool LegalOps; - SDValue Old; - SDValue New; - - explicit TargetLoweringOpt(SelectionDAG &InDAG, - bool LT, bool LO) : - DAG(InDAG), LegalTys(LT), LegalOps(LO) {} - - bool LegalTypes() const { return LegalTys; } - bool LegalOperations() const { return LegalOps; } - - bool CombineTo(SDValue O, SDValue N) { - Old = O; - New = N; - return true; - } - - /// ShrinkDemandedConstant - Check to see if the specified operand of the - /// specified instruction is a constant integer. If so, check to see if - /// there are any bits set in the constant that are not demanded. If so, - /// shrink the constant and return true. - bool ShrinkDemandedConstant(SDValue Op, const APInt &Demanded); - - /// ShrinkDemandedOp - Convert x+y to (VT)((SmallVT)x+(SmallVT)y) if the - /// casts are free. This uses isZExtFree and ZERO_EXTEND for the widening - /// cast, but it could be generalized for targets with other types of - /// implicit widening casts. - bool ShrinkDemandedOp(SDValue Op, unsigned BitWidth, const APInt &Demanded, - DebugLoc dl); - }; - - /// SimplifyDemandedBits - Look at Op. At this point, we know that only the - /// DemandedMask bits of the result of Op are ever used downstream. If we can - /// use this information to simplify Op, create a new simplified DAG node and - /// return true, returning the original and new nodes in Old and New. - /// Otherwise, analyze the expression and return a mask of KnownOne and - /// KnownZero bits for the expression (used to simplify the caller). - /// The KnownZero/One bits may only be accurate for those bits in the - /// DemandedMask. - bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedMask, - APInt &KnownZero, APInt &KnownOne, - TargetLoweringOpt &TLO, unsigned Depth = 0) const; - - /// computeMaskedBitsForTargetNode - Determine which of the bits specified in - /// Mask are known to be either zero or one and return them in the - /// KnownZero/KnownOne bitsets. - virtual void computeMaskedBitsForTargetNode(const SDValue Op, - APInt &KnownZero, - APInt &KnownOne, - const SelectionDAG &DAG, - unsigned Depth = 0) const; - - /// ComputeNumSignBitsForTargetNode - This method can be implemented by - /// targets that want to expose additional information about sign bits to the - /// DAG Combiner. - virtual unsigned ComputeNumSignBitsForTargetNode(SDValue Op, - unsigned Depth = 0) const; - - struct DAGCombinerInfo { - void *DC; // The DAG Combiner object. - CombineLevel Level; - bool CalledByLegalizer; - public: - SelectionDAG &DAG; - - DAGCombinerInfo(SelectionDAG &dag, CombineLevel level, bool cl, void *dc) - : DC(dc), Level(level), CalledByLegalizer(cl), DAG(dag) {} - - bool isBeforeLegalize() const { return Level == BeforeLegalizeTypes; } - bool isBeforeLegalizeOps() const { return Level < AfterLegalizeVectorOps; } - bool isAfterLegalizeVectorOps() const { - return Level == AfterLegalizeDAG; - } - CombineLevel getDAGCombineLevel() { return Level; } - bool isCalledByLegalizer() const { return CalledByLegalizer; } - - void AddToWorklist(SDNode *N); - void RemoveFromWorklist(SDNode *N); - SDValue CombineTo(SDNode *N, const std::vector<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); - - void CommitTargetLoweringOpt(const TargetLoweringOpt &TLO); - }; - - /// SimplifySetCC - Try to simplify a setcc built with the specified operands - /// and cc. If it is unable to simplify it, return a null SDValue. - SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1, - ISD::CondCode Cond, bool foldBooleans, - DAGCombinerInfo &DCI, DebugLoc dl) const; - - /// isGAPlusOffset - Returns true (and the GlobalValue and the offset) if the - /// node is a GlobalAddress + offset. - virtual bool - isGAPlusOffset(SDNode *N, const GlobalValue* &GA, int64_t &Offset) const; - - /// PerformDAGCombine - This method will be invoked for all target nodes and - /// for any target-independent nodes that the target has registered with - /// invoke it for. - /// - /// The semantics are as follows: - /// Return Value: - /// SDValue.Val == 0 - No change was made - /// SDValue.Val == N - N was replaced, is dead, and is already handled. - /// otherwise - N should be replaced by the returned Operand. - /// - /// In addition, methods provided by DAGCombinerInfo may be used to perform - /// more complex transformations. - /// - virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; - - /// isTypeDesirableForOp - Return true if the target has native support for - /// the specified value type and it is 'desirable' to use the type for the - /// given node type. e.g. On x86 i16 is legal, but undesirable since i16 - /// instruction encodings are longer and some i16 instructions are slow. - virtual bool isTypeDesirableForOp(unsigned /*Opc*/, EVT VT) const { - // By default, assume all legal types are desirable. - return isTypeLegal(VT); - } - - /// isDesirableToPromoteOp - Return true if it is profitable for dag combiner - /// to transform a floating point op of specified opcode to a equivalent op of - /// an integer type. e.g. f32 load -> i32 load can be profitable on ARM. - virtual bool isDesirableToTransformToIntegerOp(unsigned /*Opc*/, - EVT /*VT*/) const { - return false; - } - - /// IsDesirableToPromoteOp - This method query the target whether it is - /// beneficial for dag combiner to promote the specified node. If true, it - /// should return the desired promotion type by reference. - virtual bool IsDesirableToPromoteOp(SDValue /*Op*/, EVT &/*PVT*/) const { - return false; - } - - //===--------------------------------------------------------------------===// // TargetLowering Configuration Methods - These methods should be invoked by // the derived class constructor to configure this object for the target. // @@ -1302,387 +1102,6 @@ protected: public: //===--------------------------------------------------------------------===// - // Lowering methods - These methods must be implemented by targets so that - // the SelectionDAGBuilder code knows how to lower these. - // - - /// LowerFormalArguments - This hook must be implemented to lower the - /// incoming (formal) arguments, described by the Ins array, into the - /// specified DAG. The implementation should fill in the InVals array - /// with legal-type argument values, and return the resulting token - /// chain value. - /// - virtual SDValue - LowerFormalArguments(SDValue /*Chain*/, CallingConv::ID /*CallConv*/, - bool /*isVarArg*/, - const SmallVectorImpl<ISD::InputArg> &/*Ins*/, - DebugLoc /*dl*/, SelectionDAG &/*DAG*/, - SmallVectorImpl<SDValue> &/*InVals*/) const { - llvm_unreachable("Not Implemented"); - } - - struct ArgListEntry { - SDValue Node; - Type* Ty; - bool isSExt : 1; - bool isZExt : 1; - bool isInReg : 1; - bool isSRet : 1; - bool isNest : 1; - bool isByVal : 1; - uint16_t Alignment; - - ArgListEntry() : isSExt(false), isZExt(false), isInReg(false), - isSRet(false), isNest(false), isByVal(false), Alignment(0) { } - }; - typedef std::vector<ArgListEntry> ArgListTy; - - /// CallLoweringInfo - This structure contains all information that is - /// necessary for lowering calls. It is passed to TLI::LowerCallTo when the - /// SelectionDAG builder needs to lower a call, and targets will see this - /// struct in their LowerCall implementation. - struct CallLoweringInfo { - SDValue Chain; - Type *RetTy; - bool RetSExt : 1; - bool RetZExt : 1; - bool IsVarArg : 1; - bool IsInReg : 1; - bool DoesNotReturn : 1; - bool IsReturnValueUsed : 1; - - // IsTailCall should be modified by implementations of - // TargetLowering::LowerCall that perform tail call conversions. - bool IsTailCall; - - unsigned NumFixedArgs; - CallingConv::ID CallConv; - SDValue Callee; - ArgListTy &Args; - SelectionDAG &DAG; - DebugLoc DL; - ImmutableCallSite *CS; - SmallVector<ISD::OutputArg, 32> Outs; - SmallVector<SDValue, 32> OutVals; - SmallVector<ISD::InputArg, 32> Ins; - - - /// CallLoweringInfo - Constructs a call lowering context based on the - /// ImmutableCallSite \p cs. - CallLoweringInfo(SDValue chain, Type *retTy, - FunctionType *FTy, bool isTailCall, SDValue callee, - ArgListTy &args, SelectionDAG &dag, DebugLoc dl, - ImmutableCallSite &cs) - : Chain(chain), RetTy(retTy), RetSExt(cs.paramHasAttr(0, Attribute::SExt)), - RetZExt(cs.paramHasAttr(0, Attribute::ZExt)), IsVarArg(FTy->isVarArg()), - IsInReg(cs.paramHasAttr(0, Attribute::InReg)), - DoesNotReturn(cs.doesNotReturn()), - IsReturnValueUsed(!cs.getInstruction()->use_empty()), - IsTailCall(isTailCall), NumFixedArgs(FTy->getNumParams()), - CallConv(cs.getCallingConv()), Callee(callee), Args(args), DAG(dag), - DL(dl), CS(&cs) {} - - /// CallLoweringInfo - Constructs a call lowering context based on the - /// provided call information. - CallLoweringInfo(SDValue chain, Type *retTy, bool retSExt, bool retZExt, - bool isVarArg, bool isInReg, unsigned numFixedArgs, - CallingConv::ID callConv, bool isTailCall, - bool doesNotReturn, bool isReturnValueUsed, SDValue callee, - ArgListTy &args, SelectionDAG &dag, DebugLoc dl) - : Chain(chain), RetTy(retTy), RetSExt(retSExt), RetZExt(retZExt), - IsVarArg(isVarArg), IsInReg(isInReg), DoesNotReturn(doesNotReturn), - IsReturnValueUsed(isReturnValueUsed), IsTailCall(isTailCall), - NumFixedArgs(numFixedArgs), CallConv(callConv), Callee(callee), - Args(args), DAG(dag), DL(dl), CS(NULL) {} - }; - - /// LowerCallTo - This function lowers an abstract call to a function into an - /// actual call. This returns a pair of operands. The first element is the - /// return value for the function (if RetTy is not VoidTy). The second - /// element is the outgoing token chain. It calls LowerCall to do the actual - /// lowering. - std::pair<SDValue, SDValue> LowerCallTo(CallLoweringInfo &CLI) const; - - /// LowerCall - This hook must be implemented to lower calls into the - /// the specified DAG. The outgoing arguments to the call are described - /// by the Outs array, and the values to be returned by the call are - /// described by the Ins array. The implementation should fill in the - /// InVals array with legal-type return values from the call, and return - /// the resulting token chain value. - virtual SDValue - LowerCall(CallLoweringInfo &/*CLI*/, - SmallVectorImpl<SDValue> &/*InVals*/) const { - llvm_unreachable("Not Implemented"); - } - - /// HandleByVal - Target-specific cleanup for formal ByVal parameters. - virtual void HandleByVal(CCState *, unsigned &, unsigned) const {} - - /// CanLowerReturn - This hook should be implemented to check whether the - /// return values described by the Outs array can fit into the return - /// registers. If false is returned, an sret-demotion is performed. - /// - virtual bool CanLowerReturn(CallingConv::ID /*CallConv*/, - MachineFunction &/*MF*/, bool /*isVarArg*/, - const SmallVectorImpl<ISD::OutputArg> &/*Outs*/, - LLVMContext &/*Context*/) const - { - // Return true by default to get preexisting behavior. - return true; - } - - /// LowerReturn - This hook must be implemented to lower outgoing - /// return values, described by the Outs array, into the specified - /// DAG. The implementation should return the resulting token chain - /// value. - /// - virtual SDValue - LowerReturn(SDValue /*Chain*/, CallingConv::ID /*CallConv*/, - bool /*isVarArg*/, - const SmallVectorImpl<ISD::OutputArg> &/*Outs*/, - const SmallVectorImpl<SDValue> &/*OutVals*/, - DebugLoc /*dl*/, SelectionDAG &/*DAG*/) const { - llvm_unreachable("Not Implemented"); - } - - /// isUsedByReturnOnly - Return true if result of the specified node is used - /// by a return node only. It also compute and return the input chain for the - /// tail call. - /// This is used to determine whether it is possible - /// to codegen a libcall as tail call at legalization time. - virtual bool isUsedByReturnOnly(SDNode *, SDValue &Chain) const { - return false; - } - - /// mayBeEmittedAsTailCall - Return true if the target may be able emit the - /// call instruction as a tail call. This is used by optimization passes to - /// determine if it's profitable to duplicate return instructions to enable - /// tailcall optimization. - virtual bool mayBeEmittedAsTailCall(CallInst *) const { - return false; - } - - /// getTypeForExtArgOrReturn - Return the type that should be used to zero or - /// sign extend a zeroext/signext integer argument or return value. - /// FIXME: Most C calling convention requires the return type to be promoted, - /// but this is not true all the time, e.g. i1 on x86-64. It is also not - /// necessary for non-C calling conventions. The frontend should handle this - /// and include all of the necessary information. - virtual MVT getTypeForExtArgOrReturn(MVT VT, - ISD::NodeType /*ExtendKind*/) const { - MVT MinVT = getRegisterType(MVT::i32); - return VT.bitsLT(MinVT) ? MinVT : VT; - } - - /// LowerOperationWrapper - This callback is invoked by the type legalizer - /// to legalize nodes with an illegal operand type but legal result types. - /// It replaces the LowerOperation callback in the type Legalizer. - /// The reason we can not do away with LowerOperation entirely is that - /// LegalizeDAG isn't yet ready to use this callback. - /// TODO: Consider merging with ReplaceNodeResults. - - /// The target places new result values for the node in Results (their number - /// and types must exactly match those of the original return values of - /// the node), or leaves Results empty, which indicates that the node is not - /// to be custom lowered after all. - /// The default implementation calls LowerOperation. - virtual void LowerOperationWrapper(SDNode *N, - SmallVectorImpl<SDValue> &Results, - SelectionDAG &DAG) const; - - /// LowerOperation - This callback is invoked for operations that are - /// unsupported by the target, which are registered to use 'custom' lowering, - /// and whose defined values are all legal. - /// If the target has no operations that require custom lowering, it need not - /// implement this. The default implementation of this aborts. - virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; - - /// ReplaceNodeResults - This callback is invoked when a node result type is - /// illegal for the target, and the operation was registered to use 'custom' - /// lowering for that result type. The target places new result values for - /// the node in Results (their number and types must exactly match those of - /// the original return values of the node), or leaves Results empty, which - /// indicates that the node is not to be custom lowered after all. - /// - /// If the target has no operations that require custom lowering, it need not - /// implement this. The default implementation aborts. - virtual void ReplaceNodeResults(SDNode * /*N*/, - SmallVectorImpl<SDValue> &/*Results*/, - SelectionDAG &/*DAG*/) const { - llvm_unreachable("ReplaceNodeResults not implemented for this target!"); - } - - /// getTargetNodeName() - This method returns the name of a target specific - /// DAG node. - virtual const char *getTargetNodeName(unsigned Opcode) const; - - /// createFastISel - This method returns a target specific FastISel object, - /// or null if the target does not support "fast" ISel. - virtual FastISel *createFastISel(FunctionLoweringInfo &, - const TargetLibraryInfo *) const { - return 0; - } - - //===--------------------------------------------------------------------===// - // Inline Asm Support hooks - // - - /// ExpandInlineAsm - This hook allows the target to expand an inline asm - /// call to be explicit llvm code if it wants to. This is useful for - /// turning simple inline asms into LLVM intrinsics, which gives the - /// compiler more information about the behavior of the code. - virtual bool ExpandInlineAsm(CallInst *) const { - return false; - } - - enum ConstraintType { - C_Register, // Constraint represents specific register(s). - C_RegisterClass, // Constraint represents any of register(s) in class. - C_Memory, // Memory constraint. - C_Other, // Something else. - C_Unknown // Unsupported constraint. - }; - - enum ConstraintWeight { - // Generic weights. - CW_Invalid = -1, // No match. - CW_Okay = 0, // Acceptable. - CW_Good = 1, // Good weight. - CW_Better = 2, // Better weight. - CW_Best = 3, // Best weight. - - // Well-known weights. - CW_SpecificReg = CW_Okay, // Specific register operands. - CW_Register = CW_Good, // Register operands. - CW_Memory = CW_Better, // Memory operands. - CW_Constant = CW_Best, // Constant operand. - CW_Default = CW_Okay // Default or don't know type. - }; - - /// AsmOperandInfo - This contains information for each constraint that we are - /// lowering. - struct AsmOperandInfo : public InlineAsm::ConstraintInfo { - /// ConstraintCode - This contains the actual string for the code, like "m". - /// TargetLowering picks the 'best' code from ConstraintInfo::Codes that - /// most closely matches the operand. - std::string ConstraintCode; - - /// ConstraintType - Information about the constraint code, e.g. Register, - /// RegisterClass, Memory, Other, Unknown. - TargetLowering::ConstraintType ConstraintType; - - /// CallOperandval - If this is the result output operand or a - /// clobber, this is null, otherwise it is the incoming operand to the - /// CallInst. This gets modified as the asm is processed. - Value *CallOperandVal; - - /// ConstraintVT - The ValueType for the operand value. - MVT ConstraintVT; - - /// isMatchingInputConstraint - Return true of this is an input operand that - /// is a matching constraint like "4". - bool isMatchingInputConstraint() const; - - /// getMatchedOperand - If this is an input matching constraint, this method - /// returns the output operand it matches. - unsigned getMatchedOperand() const; - - /// Copy constructor for copying from an AsmOperandInfo. - AsmOperandInfo(const AsmOperandInfo &info) - : InlineAsm::ConstraintInfo(info), - ConstraintCode(info.ConstraintCode), - ConstraintType(info.ConstraintType), - CallOperandVal(info.CallOperandVal), - ConstraintVT(info.ConstraintVT) { - } - - /// Copy constructor for copying from a ConstraintInfo. - AsmOperandInfo(const InlineAsm::ConstraintInfo &info) - : InlineAsm::ConstraintInfo(info), - ConstraintType(TargetLowering::C_Unknown), - CallOperandVal(0), ConstraintVT(MVT::Other) { - } - }; - - typedef std::vector<AsmOperandInfo> AsmOperandInfoVector; - - /// ParseConstraints - Split up the constraint string from the inline - /// assembly value into the specific constraints and their prefixes, - /// and also tie in the associated operand values. - /// If this returns an empty vector, and if the constraint string itself - /// isn't empty, there was an error parsing. - virtual AsmOperandInfoVector ParseConstraints(ImmutableCallSite CS) const; - - /// Examine constraint type and operand type and determine a weight value. - /// The operand object must already have been set up with the operand type. - virtual ConstraintWeight getMultipleConstraintMatchWeight( - AsmOperandInfo &info, int maIndex) const; - - /// Examine constraint string and operand type and determine a weight value. - /// The operand object must already have been set up with the operand type. - virtual ConstraintWeight getSingleConstraintMatchWeight( - AsmOperandInfo &info, const char *constraint) const; - - /// ComputeConstraintToUse - Determines the constraint code and constraint - /// type to use for the specific AsmOperandInfo, setting - /// OpInfo.ConstraintCode and OpInfo.ConstraintType. If the actual operand - /// being passed in is available, it can be passed in as Op, otherwise an - /// empty SDValue can be passed. - virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, - SDValue Op, - SelectionDAG *DAG = 0) const; - - /// getConstraintType - Given a constraint, return the type of constraint it - /// is for this target. - virtual ConstraintType getConstraintType(const std::string &Constraint) const; - - /// getRegForInlineAsmConstraint - Given a physical register constraint (e.g. - /// {edx}), return the register number and the register class for the - /// register. - /// - /// Given a register class constraint, like 'r', if this corresponds directly - /// to an LLVM register class, return a register of 0 and the register class - /// 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, - EVT VT) const; - - /// LowerXConstraint - try to replace an X constraint, which matches anything, - /// with another that has more specific requirements based on the type of the - /// corresponding operand. This returns null if there is no replacement to - /// make. - virtual const char *LowerXConstraint(EVT ConstraintVT) const; - - /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops - /// vector. If it is invalid, don't add anything to Ops. - virtual void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, - std::vector<SDValue> &Ops, - SelectionDAG &DAG) const; - - //===--------------------------------------------------------------------===// - // Instruction Emitting Hooks - // - - // EmitInstrWithCustomInserter - This method should be implemented by targets - // that mark instructions with the 'usesCustomInserter' flag. These - // instructions are special in various ways, which require special support to - // insert. The specified MachineInstr 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. - virtual MachineBasicBlock * - EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; - - /// AdjustInstrPostInstrSelection - This method should be implemented by - /// targets that mark instructions with the 'hasPostISelHook' flag. These - /// instructions must be adjusted after instruction selection by target hooks. - /// e.g. To fill in optional defs for ARM 's' setting instructions. - virtual void - AdjustInstrPostInstrSelection(MachineInstr *MI, SDNode *Node) const; - - //===--------------------------------------------------------------------===// // Addressing mode description hooks (used by LSR etc). // @@ -1798,17 +1217,6 @@ public: } //===--------------------------------------------------------------------===// - // Div utility functions - // - SDValue BuildExactSDIV(SDValue Op1, SDValue Op2, DebugLoc dl, - SelectionDAG &DAG) const; - SDValue BuildSDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, - std::vector<SDNode*> *Created) const; - SDValue BuildUDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, - std::vector<SDNode*> *Created) const; - - - //===--------------------------------------------------------------------===// // Runtime Library hooks // @@ -2190,11 +1598,11 @@ protected: /// with 16-bit alignment would result in four 2-byte stores and one 1-byte /// store. This only applies to setting a constant array of a constant size. /// @brief Specify maximum number of store instructions per memset call. - unsigned maxStoresPerMemset; + unsigned MaxStoresPerMemset; /// Maximum number of stores operations that may be substituted for the call /// to memset, used for functions with OptSize attribute. - unsigned maxStoresPerMemsetOptSize; + unsigned MaxStoresPerMemsetOptSize; /// When lowering \@llvm.memcpy this field specifies the maximum number of /// store operations that may be substituted for a call to memcpy. Targets @@ -2206,11 +1614,11 @@ protected: /// and one 1-byte store. This only applies to copying a constant array of /// constant size. /// @brief Specify maximum bytes of store instructions per memcpy call. - unsigned maxStoresPerMemcpy; + unsigned MaxStoresPerMemcpy; /// Maximum number of store operations that may be substituted for a call /// to memcpy, used for functions with OptSize attribute. - unsigned maxStoresPerMemcpyOptSize; + unsigned MaxStoresPerMemcpyOptSize; /// When lowering \@llvm.memmove this field specifies the maximum number of /// store instructions that may be substituted for a call to memmove. Targets @@ -2221,26 +1629,641 @@ protected: /// with 8-bit alignment would result in nine 1-byte stores. This only /// applies to copying a constant array of constant size. /// @brief Specify maximum bytes of store instructions per memmove call. - unsigned maxStoresPerMemmove; + unsigned MaxStoresPerMemmove; /// Maximum number of store instructions that may be substituted for a call /// to memmove, used for functions with OpSize attribute. - unsigned maxStoresPerMemmoveOptSize; + unsigned MaxStoresPerMemmoveOptSize; /// This field specifies whether the target can benefit from code placement /// optimization. - bool benefitFromCodePlacementOpt; + bool BenefitFromCodePlacementOpt; - /// predictableSelectIsExpensive - Tells the code generator that select is + /// PredictableSelectIsExpensive - Tells the code generator that select is /// more expensive than a branch if the branch is usually predicted right. - bool predictableSelectIsExpensive; + bool PredictableSelectIsExpensive; -private: +protected: /// isLegalRC - Return true if the value types that can be represented by the /// specified register class are all legal. bool isLegalRC(const TargetRegisterClass *RC) const; }; +//===----------------------------------------------------------------------===// +/// TargetLowering - This class defines information used to lower LLVM code to +/// legal SelectionDAG operators that the target instruction selector can accept +/// natively. +/// +/// 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; + +public: + /// NOTE: The constructor takes ownership of TLOF. + explicit TargetLowering(const TargetMachine &TM, + const TargetLoweringObjectFile *TLOF); + + /// getPreIndexedAddressParts - returns true by value, base pointer and + /// offset pointer and addressing mode by reference if the node's address + /// can be legally represented as pre-indexed load / store address. + virtual bool getPreIndexedAddressParts(SDNode * /*N*/, SDValue &/*Base*/, + SDValue &/*Offset*/, + ISD::MemIndexedMode &/*AM*/, + SelectionDAG &/*DAG*/) const { + return false; + } + + /// getPostIndexedAddressParts - returns true by value, base pointer and + /// offset pointer and addressing mode by reference if this node can be + /// combined with a load / store to form a post-indexed load / store. + virtual bool getPostIndexedAddressParts(SDNode * /*N*/, SDNode * /*Op*/, + SDValue &/*Base*/, SDValue &/*Offset*/, + ISD::MemIndexedMode &/*AM*/, + SelectionDAG &/*DAG*/) const { + return false; + } + + /// getJumpTableEncoding - Return the entry encoding for a jump table in the + /// current function. The returned value is a member of the + /// MachineJumpTableInfo::JTEntryKind enum. + virtual unsigned getJumpTableEncoding() const; + + virtual const MCExpr * + LowerCustomJumpTableEntry(const MachineJumpTableInfo * /*MJTI*/, + const MachineBasicBlock * /*MBB*/, unsigned /*uid*/, + MCContext &/*Ctx*/) const { + llvm_unreachable("Need to implement this hook if target has custom JTIs"); + } + + /// getPICJumpTableRelocaBase - Returns relocation base for the given PIC + /// jumptable. + virtual SDValue getPICJumpTableRelocBase(SDValue Table, + SelectionDAG &DAG) const; + + /// getPICJumpTableRelocBaseExpr - This returns the relocation base for the + /// given PIC jumptable, the same as getPICJumpTableRelocBase, but as an + /// MCExpr. + virtual const MCExpr * + getPICJumpTableRelocBaseExpr(const MachineFunction *MF, + unsigned JTI, MCContext &Ctx) const; + + /// isOffsetFoldingLegal - Return true if folding a constant offset + /// with the given GlobalAddress is legal. It is frequently not legal in + /// PIC relocation models. + virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; + + bool isInTailCallPosition(SelectionDAG &DAG, SDNode *Node, + SDValue &Chain) const; + + void softenSetCCOperands(SelectionDAG &DAG, EVT VT, + SDValue &NewLHS, SDValue &NewRHS, + ISD::CondCode &CCCode, DebugLoc DL) const; + + SDValue makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, + const SDValue *Ops, unsigned NumOps, + bool isSigned, DebugLoc dl) const; + + //===--------------------------------------------------------------------===// + // TargetLowering Optimization Methods + // + + /// TargetLoweringOpt - A convenience struct that encapsulates a DAG, and two + /// SDValues for returning information from TargetLowering to its clients + /// that want to combine + struct TargetLoweringOpt { + SelectionDAG &DAG; + bool LegalTys; + bool LegalOps; + SDValue Old; + SDValue New; + + explicit TargetLoweringOpt(SelectionDAG &InDAG, + bool LT, bool LO) : + DAG(InDAG), LegalTys(LT), LegalOps(LO) {} + + bool LegalTypes() const { return LegalTys; } + bool LegalOperations() const { return LegalOps; } + + bool CombineTo(SDValue O, SDValue N) { + Old = O; + New = N; + return true; + } + + /// ShrinkDemandedConstant - Check to see if the specified operand of the + /// specified instruction is a constant integer. If so, check to see if + /// there are any bits set in the constant that are not demanded. If so, + /// shrink the constant and return true. + bool ShrinkDemandedConstant(SDValue Op, const APInt &Demanded); + + /// ShrinkDemandedOp - Convert x+y to (VT)((SmallVT)x+(SmallVT)y) if the + /// casts are free. This uses isZExtFree and ZERO_EXTEND for the widening + /// cast, but it could be generalized for targets with other types of + /// implicit widening casts. + bool ShrinkDemandedOp(SDValue Op, unsigned BitWidth, const APInt &Demanded, + DebugLoc dl); + }; + + /// SimplifyDemandedBits - Look at Op. At this point, we know that only the + /// DemandedMask bits of the result of Op are ever used downstream. If we can + /// use this information to simplify Op, create a new simplified DAG node and + /// return true, returning the original and new nodes in Old and New. + /// Otherwise, analyze the expression and return a mask of KnownOne and + /// KnownZero bits for the expression (used to simplify the caller). + /// The KnownZero/One bits may only be accurate for those bits in the + /// DemandedMask. + bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedMask, + APInt &KnownZero, APInt &KnownOne, + TargetLoweringOpt &TLO, unsigned Depth = 0) const; + + /// computeMaskedBitsForTargetNode - Determine which of the bits specified in + /// Mask are known to be either zero or one and return them in the + /// KnownZero/KnownOne bitsets. + virtual void computeMaskedBitsForTargetNode(const SDValue Op, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth = 0) const; + + /// ComputeNumSignBitsForTargetNode - This method can be implemented by + /// targets that want to expose additional information about sign bits to the + /// DAG Combiner. + virtual unsigned ComputeNumSignBitsForTargetNode(SDValue Op, + unsigned Depth = 0) const; + + struct DAGCombinerInfo { + void *DC; // The DAG Combiner object. + CombineLevel Level; + bool CalledByLegalizer; + public: + SelectionDAG &DAG; + + DAGCombinerInfo(SelectionDAG &dag, CombineLevel level, bool cl, void *dc) + : DC(dc), Level(level), CalledByLegalizer(cl), DAG(dag) {} + + bool isBeforeLegalize() const { return Level == BeforeLegalizeTypes; } + bool isBeforeLegalizeOps() const { return Level < AfterLegalizeVectorOps; } + bool isAfterLegalizeVectorOps() const { + return Level == AfterLegalizeDAG; + } + CombineLevel getDAGCombineLevel() { return Level; } + bool isCalledByLegalizer() const { return CalledByLegalizer; } + + void AddToWorklist(SDNode *N); + void RemoveFromWorklist(SDNode *N); + SDValue CombineTo(SDNode *N, const std::vector<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); + + void CommitTargetLoweringOpt(const TargetLoweringOpt &TLO); + }; + + /// SimplifySetCC - Try to simplify a setcc built with the specified operands + /// and cc. If it is unable to simplify it, return a null SDValue. + SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1, + ISD::CondCode Cond, bool foldBooleans, + DAGCombinerInfo &DCI, DebugLoc dl) const; + + /// isGAPlusOffset - Returns true (and the GlobalValue and the offset) if the + /// node is a GlobalAddress + offset. + virtual bool + isGAPlusOffset(SDNode *N, const GlobalValue* &GA, int64_t &Offset) const; + + /// PerformDAGCombine - This method will be invoked for all target nodes and + /// for any target-independent nodes that the target has registered with + /// invoke it for. + /// + /// The semantics are as follows: + /// Return Value: + /// SDValue.Val == 0 - No change was made + /// SDValue.Val == N - N was replaced, is dead, and is already handled. + /// otherwise - N should be replaced by the returned Operand. + /// + /// In addition, methods provided by DAGCombinerInfo may be used to perform + /// more complex transformations. + /// + virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + + /// isTypeDesirableForOp - Return true if the target has native support for + /// the specified value type and it is 'desirable' to use the type for the + /// given node type. e.g. On x86 i16 is legal, but undesirable since i16 + /// instruction encodings are longer and some i16 instructions are slow. + virtual bool isTypeDesirableForOp(unsigned /*Opc*/, EVT VT) const { + // By default, assume all legal types are desirable. + return isTypeLegal(VT); + } + + /// isDesirableToPromoteOp - Return true if it is profitable for dag combiner + /// to transform a floating point op of specified opcode to a equivalent op of + /// an integer type. e.g. f32 load -> i32 load can be profitable on ARM. + virtual bool isDesirableToTransformToIntegerOp(unsigned /*Opc*/, + EVT /*VT*/) const { + return false; + } + + /// IsDesirableToPromoteOp - This method query the target whether it is + /// beneficial for dag combiner to promote the specified node. If true, it + /// should return the desired promotion type by reference. + virtual bool IsDesirableToPromoteOp(SDValue /*Op*/, EVT &/*PVT*/) const { + return false; + } + + //===--------------------------------------------------------------------===// + // Lowering methods - These methods must be implemented by targets so that + // the SelectionDAGBuilder code knows how to lower these. + // + + /// LowerFormalArguments - This hook must be implemented to lower the + /// incoming (formal) arguments, described by the Ins array, into the + /// specified DAG. The implementation should fill in the InVals array + /// with legal-type argument values, and return the resulting token + /// chain value. + /// + virtual SDValue + LowerFormalArguments(SDValue /*Chain*/, CallingConv::ID /*CallConv*/, + bool /*isVarArg*/, + const SmallVectorImpl<ISD::InputArg> &/*Ins*/, + DebugLoc /*dl*/, SelectionDAG &/*DAG*/, + SmallVectorImpl<SDValue> &/*InVals*/) const { + llvm_unreachable("Not Implemented"); + } + + struct ArgListEntry { + SDValue Node; + Type* Ty; + bool isSExt : 1; + bool isZExt : 1; + bool isInReg : 1; + bool isSRet : 1; + bool isNest : 1; + bool isByVal : 1; + uint16_t Alignment; + + ArgListEntry() : isSExt(false), isZExt(false), isInReg(false), + isSRet(false), isNest(false), isByVal(false), Alignment(0) { } + }; + typedef std::vector<ArgListEntry> ArgListTy; + + /// CallLoweringInfo - This structure contains all information that is + /// necessary for lowering calls. It is passed to TLI::LowerCallTo when the + /// SelectionDAG builder needs to lower a call, and targets will see this + /// struct in their LowerCall implementation. + struct CallLoweringInfo { + SDValue Chain; + Type *RetTy; + bool RetSExt : 1; + bool RetZExt : 1; + bool IsVarArg : 1; + bool IsInReg : 1; + bool DoesNotReturn : 1; + bool IsReturnValueUsed : 1; + + // IsTailCall should be modified by implementations of + // TargetLowering::LowerCall that perform tail call conversions. + bool IsTailCall; + + unsigned NumFixedArgs; + CallingConv::ID CallConv; + SDValue Callee; + ArgListTy &Args; + SelectionDAG &DAG; + DebugLoc DL; + ImmutableCallSite *CS; + SmallVector<ISD::OutputArg, 32> Outs; + SmallVector<SDValue, 32> OutVals; + SmallVector<ISD::InputArg, 32> Ins; + + + /// CallLoweringInfo - Constructs a call lowering context based on the + /// ImmutableCallSite \p cs. + CallLoweringInfo(SDValue chain, Type *retTy, + FunctionType *FTy, bool isTailCall, SDValue callee, + ArgListTy &args, SelectionDAG &dag, DebugLoc dl, + ImmutableCallSite &cs) + : Chain(chain), RetTy(retTy), RetSExt(cs.paramHasAttr(0, Attribute::SExt)), + RetZExt(cs.paramHasAttr(0, Attribute::ZExt)), IsVarArg(FTy->isVarArg()), + IsInReg(cs.paramHasAttr(0, Attribute::InReg)), + DoesNotReturn(cs.doesNotReturn()), + IsReturnValueUsed(!cs.getInstruction()->use_empty()), + IsTailCall(isTailCall), NumFixedArgs(FTy->getNumParams()), + CallConv(cs.getCallingConv()), Callee(callee), Args(args), DAG(dag), + DL(dl), CS(&cs) {} + + /// CallLoweringInfo - Constructs a call lowering context based on the + /// provided call information. + CallLoweringInfo(SDValue chain, Type *retTy, bool retSExt, bool retZExt, + bool isVarArg, bool isInReg, unsigned numFixedArgs, + CallingConv::ID callConv, bool isTailCall, + bool doesNotReturn, bool isReturnValueUsed, SDValue callee, + ArgListTy &args, SelectionDAG &dag, DebugLoc dl) + : Chain(chain), RetTy(retTy), RetSExt(retSExt), RetZExt(retZExt), + IsVarArg(isVarArg), IsInReg(isInReg), DoesNotReturn(doesNotReturn), + IsReturnValueUsed(isReturnValueUsed), IsTailCall(isTailCall), + NumFixedArgs(numFixedArgs), CallConv(callConv), Callee(callee), + Args(args), DAG(dag), DL(dl), CS(NULL) {} + }; + + /// LowerCallTo - This function lowers an abstract call to a function into an + /// actual call. This returns a pair of operands. The first element is the + /// return value for the function (if RetTy is not VoidTy). The second + /// element is the outgoing token chain. It calls LowerCall to do the actual + /// lowering. + std::pair<SDValue, SDValue> LowerCallTo(CallLoweringInfo &CLI) const; + + /// LowerCall - This hook must be implemented to lower calls into the + /// the specified DAG. The outgoing arguments to the call are described + /// by the Outs array, and the values to be returned by the call are + /// described by the Ins array. The implementation should fill in the + /// InVals array with legal-type return values from the call, and return + /// the resulting token chain value. + virtual SDValue + LowerCall(CallLoweringInfo &/*CLI*/, + SmallVectorImpl<SDValue> &/*InVals*/) const { + llvm_unreachable("Not Implemented"); + } + + /// HandleByVal - Target-specific cleanup for formal ByVal parameters. + virtual void HandleByVal(CCState *, unsigned &, unsigned) const {} + + /// CanLowerReturn - This hook should be implemented to check whether the + /// return values described by the Outs array can fit into the return + /// registers. If false is returned, an sret-demotion is performed. + /// + virtual bool CanLowerReturn(CallingConv::ID /*CallConv*/, + MachineFunction &/*MF*/, bool /*isVarArg*/, + const SmallVectorImpl<ISD::OutputArg> &/*Outs*/, + LLVMContext &/*Context*/) const + { + // Return true by default to get preexisting behavior. + return true; + } + + /// LowerReturn - This hook must be implemented to lower outgoing + /// return values, described by the Outs array, into the specified + /// DAG. The implementation should return the resulting token chain + /// value. + /// + virtual SDValue + LowerReturn(SDValue /*Chain*/, CallingConv::ID /*CallConv*/, + bool /*isVarArg*/, + const SmallVectorImpl<ISD::OutputArg> &/*Outs*/, + const SmallVectorImpl<SDValue> &/*OutVals*/, + DebugLoc /*dl*/, SelectionDAG &/*DAG*/) const { + llvm_unreachable("Not Implemented"); + } + + /// isUsedByReturnOnly - Return true if result of the specified node is used + /// by a return node only. It also compute and return the input chain for the + /// tail call. + /// This is used to determine whether it is possible + /// to codegen a libcall as tail call at legalization time. + virtual bool isUsedByReturnOnly(SDNode *, SDValue &Chain) const { + return false; + } + + /// mayBeEmittedAsTailCall - Return true if the target may be able emit the + /// call instruction as a tail call. This is used by optimization passes to + /// determine if it's profitable to duplicate return instructions to enable + /// tailcall optimization. + virtual bool mayBeEmittedAsTailCall(CallInst *) const { + return false; + } + + /// getTypeForExtArgOrReturn - Return the type that should be used to zero or + /// sign extend a zeroext/signext integer argument or return value. + /// FIXME: Most C calling convention requires the return type to be promoted, + /// but this is not true all the time, e.g. i1 on x86-64. It is also not + /// necessary for non-C calling conventions. The frontend should handle this + /// and include all of the necessary information. + virtual MVT getTypeForExtArgOrReturn(MVT VT, + ISD::NodeType /*ExtendKind*/) const { + MVT MinVT = getRegisterType(MVT::i32); + return VT.bitsLT(MinVT) ? MinVT : VT; + } + + /// LowerOperationWrapper - This callback is invoked by the type legalizer + /// to legalize nodes with an illegal operand type but legal result types. + /// It replaces the LowerOperation callback in the type Legalizer. + /// The reason we can not do away with LowerOperation entirely is that + /// LegalizeDAG isn't yet ready to use this callback. + /// TODO: Consider merging with ReplaceNodeResults. + + /// The target places new result values for the node in Results (their number + /// and types must exactly match those of the original return values of + /// the node), or leaves Results empty, which indicates that the node is not + /// to be custom lowered after all. + /// The default implementation calls LowerOperation. + virtual void LowerOperationWrapper(SDNode *N, + SmallVectorImpl<SDValue> &Results, + SelectionDAG &DAG) const; + + /// LowerOperation - This callback is invoked for operations that are + /// unsupported by the target, which are registered to use 'custom' lowering, + /// and whose defined values are all legal. + /// If the target has no operations that require custom lowering, it need not + /// implement this. The default implementation of this aborts. + virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; + + /// ReplaceNodeResults - This callback is invoked when a node result type is + /// illegal for the target, and the operation was registered to use 'custom' + /// lowering for that result type. The target places new result values for + /// the node in Results (their number and types must exactly match those of + /// the original return values of the node), or leaves Results empty, which + /// indicates that the node is not to be custom lowered after all. + /// + /// If the target has no operations that require custom lowering, it need not + /// implement this. The default implementation aborts. + virtual void ReplaceNodeResults(SDNode * /*N*/, + SmallVectorImpl<SDValue> &/*Results*/, + SelectionDAG &/*DAG*/) const { + llvm_unreachable("ReplaceNodeResults not implemented for this target!"); + } + + /// getTargetNodeName() - This method returns the name of a target specific + /// DAG node. + virtual const char *getTargetNodeName(unsigned Opcode) const; + + /// createFastISel - This method returns a target specific FastISel object, + /// or null if the target does not support "fast" ISel. + virtual FastISel *createFastISel(FunctionLoweringInfo &, + const TargetLibraryInfo *) const { + return 0; + } + + //===--------------------------------------------------------------------===// + // Inline Asm Support hooks + // + + /// ExpandInlineAsm - This hook allows the target to expand an inline asm + /// call to be explicit llvm code if it wants to. This is useful for + /// turning simple inline asms into LLVM intrinsics, which gives the + /// compiler more information about the behavior of the code. + virtual bool ExpandInlineAsm(CallInst *) const { + return false; + } + + enum ConstraintType { + C_Register, // Constraint represents specific register(s). + C_RegisterClass, // Constraint represents any of register(s) in class. + C_Memory, // Memory constraint. + C_Other, // Something else. + C_Unknown // Unsupported constraint. + }; + + enum ConstraintWeight { + // Generic weights. + CW_Invalid = -1, // No match. + CW_Okay = 0, // Acceptable. + CW_Good = 1, // Good weight. + CW_Better = 2, // Better weight. + CW_Best = 3, // Best weight. + + // Well-known weights. + CW_SpecificReg = CW_Okay, // Specific register operands. + CW_Register = CW_Good, // Register operands. + CW_Memory = CW_Better, // Memory operands. + CW_Constant = CW_Best, // Constant operand. + CW_Default = CW_Okay // Default or don't know type. + }; + + /// AsmOperandInfo - This contains information for each constraint that we are + /// lowering. + struct AsmOperandInfo : public InlineAsm::ConstraintInfo { + /// ConstraintCode - This contains the actual string for the code, like "m". + /// TargetLowering picks the 'best' code from ConstraintInfo::Codes that + /// most closely matches the operand. + std::string ConstraintCode; + + /// ConstraintType - Information about the constraint code, e.g. Register, + /// RegisterClass, Memory, Other, Unknown. + TargetLowering::ConstraintType ConstraintType; + + /// CallOperandval - If this is the result output operand or a + /// clobber, this is null, otherwise it is the incoming operand to the + /// CallInst. This gets modified as the asm is processed. + Value *CallOperandVal; + + /// ConstraintVT - The ValueType for the operand value. + MVT ConstraintVT; + + /// isMatchingInputConstraint - Return true of this is an input operand that + /// is a matching constraint like "4". + bool isMatchingInputConstraint() const; + + /// getMatchedOperand - If this is an input matching constraint, this method + /// returns the output operand it matches. + unsigned getMatchedOperand() const; + + /// Copy constructor for copying from an AsmOperandInfo. + AsmOperandInfo(const AsmOperandInfo &info) + : InlineAsm::ConstraintInfo(info), + ConstraintCode(info.ConstraintCode), + ConstraintType(info.ConstraintType), + CallOperandVal(info.CallOperandVal), + ConstraintVT(info.ConstraintVT) { + } + + /// Copy constructor for copying from a ConstraintInfo. + AsmOperandInfo(const InlineAsm::ConstraintInfo &info) + : InlineAsm::ConstraintInfo(info), + ConstraintType(TargetLowering::C_Unknown), + CallOperandVal(0), ConstraintVT(MVT::Other) { + } + }; + + typedef std::vector<AsmOperandInfo> AsmOperandInfoVector; + + /// ParseConstraints - Split up the constraint string from the inline + /// assembly value into the specific constraints and their prefixes, + /// and also tie in the associated operand values. + /// If this returns an empty vector, and if the constraint string itself + /// isn't empty, there was an error parsing. + virtual AsmOperandInfoVector ParseConstraints(ImmutableCallSite CS) const; + + /// Examine constraint type and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + virtual ConstraintWeight getMultipleConstraintMatchWeight( + AsmOperandInfo &info, int maIndex) const; + + /// Examine constraint string and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + virtual ConstraintWeight getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const; + + /// ComputeConstraintToUse - Determines the constraint code and constraint + /// type to use for the specific AsmOperandInfo, setting + /// OpInfo.ConstraintCode and OpInfo.ConstraintType. If the actual operand + /// being passed in is available, it can be passed in as Op, otherwise an + /// empty SDValue can be passed. + virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, + SDValue Op, + SelectionDAG *DAG = 0) const; + + /// getConstraintType - Given a constraint, return the type of constraint it + /// is for this target. + virtual ConstraintType getConstraintType(const std::string &Constraint) const; + + /// getRegForInlineAsmConstraint - Given a physical register constraint (e.g. + /// {edx}), return the register number and the register class for the + /// register. + /// + /// Given a register class constraint, like 'r', if this corresponds directly + /// to an LLVM register class, return a register of 0 and the register class + /// 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, + EVT VT) const; + + /// LowerXConstraint - try to replace an X constraint, which matches anything, + /// with another that has more specific requirements based on the type of the + /// corresponding operand. This returns null if there is no replacement to + /// make. + virtual const char *LowerXConstraint(EVT ConstraintVT) const; + + /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops + /// vector. If it is invalid, don't add anything to Ops. + virtual void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, + std::vector<SDValue> &Ops, + SelectionDAG &DAG) const; + + //===--------------------------------------------------------------------===// + // Div utility functions + // + SDValue BuildExactSDIV(SDValue Op1, SDValue Op2, DebugLoc dl, + SelectionDAG &DAG) const; + SDValue BuildSDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, + std::vector<SDNode*> *Created) const; + SDValue BuildUDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, + std::vector<SDNode*> *Created) const; + + //===--------------------------------------------------------------------===// + // Instruction Emitting Hooks + // + + // EmitInstrWithCustomInserter - This method should be implemented by targets + // that mark instructions with the 'usesCustomInserter' flag. These + // instructions are special in various ways, which require special support to + // insert. The specified MachineInstr 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. + virtual MachineBasicBlock * + EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; + + /// AdjustInstrPostInstrSelection - This method should be implemented by + /// targets that mark instructions with the 'hasPostISelHook' flag. These + /// instructions must be adjusted after instruction selection by target hooks. + /// e.g. To fill in optional defs for ARM 's' setting instructions. + virtual void + AdjustInstrPostInstrSelection(MachineInstr *MI, SDNode *Node) const; +}; + /// GetReturnInfo - Given an LLVM IR type and return type attributes, /// compute the return value EVTs and flags, and optionally also /// the offsets, if the return value is being lowered to memory. diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index aa049f0..35cf20a 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -59,10 +59,6 @@ protected: // Can only create subclasses. TargetMachine(const Target &T, StringRef TargetTriple, StringRef CPU, StringRef FS, const TargetOptions &Options); - /// getSubtargetImpl - virtual method implemented by subclasses that returns - /// a reference to that target's TargetSubtargetInfo-derived member variable. - virtual const TargetSubtargetInfo *getSubtargetImpl() const { return 0; } - /// TheTarget - The Target that this machine was created for. const Target &TheTarget; @@ -95,6 +91,10 @@ public: const StringRef getTargetCPU() const { return TargetCPU; } const 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 0; } + TargetOptions Options; // Interfaces to the major aspects of target machine information: diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index 8fc566e..c31db24 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -48,10 +48,10 @@ namespace llvm { UseSoftFloat(false), NoZerosInBSS(false), JITExceptionHandling(false), JITEmitDebugInfo(false), JITEmitDebugInfoToDisk(false), GuaranteedTailCallOpt(false), DisableTailCalls(false), - StackAlignmentOverride(0), RealignStack(true), EnableFastISel(false), - PositionIndependentExecutable(false), EnableSegmentedStacks(false), - UseInitArray(false), TrapFuncName(""),FloatABIType(FloatABI::Default), - AllowFPOpFusion(FPOpFusion::Standard) + StackAlignmentOverride(0), RealignStack(true), SSPBufferSize(0), + EnableFastISel(false), PositionIndependentExecutable(false), + EnableSegmentedStacks(false), UseInitArray(false), TrapFuncName(""), + FloatABIType(FloatABI::Default), AllowFPOpFusion(FPOpFusion::Standard) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 2a8ef98..6b1e70b 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -733,21 +733,6 @@ public: llvm_unreachable("isFrameOffsetLegal does not exist on this target"); } - /// eliminateCallFramePseudoInstr - This method is called during prolog/epilog - /// code insertion to eliminate call frame setup and destroy pseudo - /// instructions (but only if the Target is using them). It is responsible - /// for eliminating these instructions, replacing them with concrete - /// instructions. This method need only be implemented if using call frame - /// setup/destroy pseudo instructions. - /// - virtual void - eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI) const { - llvm_unreachable("Call Frame Pseudo Instructions do not exist on this " - "target!"); - } - /// saveScavengerRegister - Spill the register so it can be used by the /// register scavenger. Return true if the register was spilled, false @@ -767,10 +752,11 @@ public: /// referenced by the iterator contains an MO_FrameIndex operand which must be /// eliminated by this method. This method may modify or replace the /// specified instruction, as long as it keeps the iterator pointing at the - /// finished product. SPAdj is the SP adjustment due to call frame setup - /// instruction. + /// finished product. SPAdj is the SP adjustment due to call frame setup + /// instruction. FIOperandNum is the FI operand number. virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI, - int SPAdj, RegScavenger *RS=NULL) const = 0; + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS = NULL) const = 0; //===--------------------------------------------------------------------===// /// Debug information queries. diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td index 0da82fd..b7920ba 100644 --- a/include/llvm/Target/TargetSchedule.td +++ b/include/llvm/Target/TargetSchedule.td @@ -76,6 +76,7 @@ class SchedMachineModel { int IssueWidth = -1; // Max micro-ops that may be scheduled per cycle. int MinLatency = -1; // Determines which instrucions are allowed in a group. // (-1) inorder (0) ooo, (1): inorder +var latencies. + int ILPWindow = -1; // Cycles of latency likely hidden by hardware buffers. int LoadLatency = -1; // Cycles for loads to access the cache. int HighLatency = -1; // Approximation of cycles for "high latency" ops. int MispredictPenalty = -1; // Extra cycles for a mispredicted branch. diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h index 3f22f47..b2d405d 100644 --- a/include/llvm/Target/TargetSubtargetInfo.h +++ b/include/llvm/Target/TargetSubtargetInfo.h @@ -19,6 +19,7 @@ namespace llvm { +class MachineFunction; class MachineInstr; class SDep; class SUnit; @@ -73,6 +74,9 @@ public: // the latency of a schedule dependency. virtual void adjustSchedDependency(SUnit *def, SUnit *use, SDep& dep) const { } + + /// \brief Reset the features for the subtarget. + virtual void resetSubtargetFeatures(const MachineFunction *MF) { } }; } // End llvm namespace diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h index 3ea0a42..209f68d 100644 --- a/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_PASSMANAGERBUILDER_H -#define LLVM_SUPPORT_PASSMANAGERBUILDER_H +#ifndef LLVM_TRANSFORMS_IPO_PASSMANAGERBUILDER_H +#define LLVM_TRANSFORMS_IPO_PASSMANAGERBUILDER_H #include <vector> diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index 5504dc9..fed92c8 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -39,9 +39,11 @@ ModulePass *createGCOVProfilerPass(bool EmitNotes = true, bool EmitData = true, // Insert AddressSanitizer (address sanity checking) instrumentation FunctionPass *createAddressSanitizerFunctionPass( bool CheckInitOrder = false, bool CheckUseAfterReturn = false, - bool CheckLifetime = false, StringRef BlacklistFile = StringRef()); + bool CheckLifetime = false, StringRef BlacklistFile = StringRef(), + bool ZeroBaseShadow = false); ModulePass *createAddressSanitizerModulePass( - bool CheckInitOrder = false, StringRef BlacklistFile = StringRef()); + bool CheckInitOrder = false, StringRef BlacklistFile = StringRef(), + bool ZeroBaseShadow = false); // Insert MemorySanitizer instrumentation (detection of uninitialized reads) FunctionPass *createMemorySanitizerPass(bool TrackOrigins = false, diff --git a/include/llvm/Transforms/ObjCARC.h b/include/llvm/Transforms/ObjCARC.h new file mode 100644 index 0000000..b3c19c0 --- /dev/null +++ b/include/llvm/Transforms/ObjCARC.h @@ -0,0 +1,49 @@ +//===-- ObjCARC.h - ObjCARC Scalar Transformations --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines prototypes for accessor functions that expose passes +// in the ObjCARC Scalar Transformations library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_OBJCARC_H +#define LLVM_TRANSFORMS_OBJCARC_H + +namespace llvm { + +class Pass; + +//===----------------------------------------------------------------------===// +// +// ObjCARCAPElim - ObjC ARC autorelease pool elimination. +// +Pass *createObjCARCAPElimPass(); + +//===----------------------------------------------------------------------===// +// +// ObjCARCExpand - ObjC ARC preliminary simplifications. +// +Pass *createObjCARCExpandPass(); + +//===----------------------------------------------------------------------===// +// +// ObjCARCContract - Late ObjC ARC cleanups. +// +Pass *createObjCARCContractPass(); + +//===----------------------------------------------------------------------===// +// +// ObjCARCOpt - ObjC ARC optimization. +// +Pass *createObjCARCOptPass(); + +} // End llvm namespace + +#endif + diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index d465127..e89759a 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -334,30 +334,6 @@ Pass *createCorrelatedValuePropagationPass(); //===----------------------------------------------------------------------===// // -// ObjCARCAPElim - ObjC ARC autorelease pool elimination. -// -Pass *createObjCARCAPElimPass(); - -//===----------------------------------------------------------------------===// -// -// ObjCARCExpand - ObjC ARC preliminary simplifications. -// -Pass *createObjCARCExpandPass(); - -//===----------------------------------------------------------------------===// -// -// ObjCARCContract - Late ObjC ARC cleanups. -// -Pass *createObjCARCContractPass(); - -//===----------------------------------------------------------------------===// -// -// ObjCARCOpt - ObjC ARC optimization. -// -Pass *createObjCARCOptPass(); - -//===----------------------------------------------------------------------===// -// // InstructionSimplifier - Remove redundant instructions. // FunctionPass *createInstructionSimplifierPass(); diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index d08f75e..8f1a6e2 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -12,14 +12,13 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TRANSFORMS_UTILS_BASICBLOCK_H -#define LLVM_TRANSFORMS_UTILS_BASICBLOCK_H +#ifndef LLVM_TRANSFORMS_UTILS_BASICBLOCKUTILS_H +#define LLVM_TRANSFORMS_UTILS_BASICBLOCKUTILS_H // FIXME: Move to this file: BasicBlock::removePredecessor, BB::splitBasicBlock #include "llvm/IR/BasicBlock.h" #include "llvm/Support/CFG.h" -#include "llvm/Support/DebugLoc.h" namespace llvm { diff --git a/include/llvm/Transforms/Utils/BlackList.h b/include/llvm/Transforms/Utils/BlackList.h new file mode 100644 index 0000000..f19470e --- /dev/null +++ b/include/llvm/Transforms/Utils/BlackList.h @@ -0,0 +1,58 @@ +//===-- BlackList.h - blacklist for sanitizers ------------------*- 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 utility class for instrumentation passes (like AddressSanitizer +// or ThreadSanitizer) to avoid instrumenting some functions or global +// variables based on a user-supplied blacklist. +// +// The blacklist disables instrumentation of various functions and global +// variables. Each line contains a prefix, followed by a wild card expression. +// Empty lines and lines starting with "#" are ignored. +// --- +// # Blacklisted items: +// fun:*_ZN4base6subtle* +// global:*global_with_bad_access_or_initialization* +// global-init:*global_with_initialization_issues* +// global-init-type:*Namespace::ClassName* +// src:file_with_tricky_code.cc +// --- +// Note that the wild card is in fact an llvm::Regex, but * is automatically +// replaced with .* +// This is similar to the "ignore" feature of ThreadSanitizer. +// http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores +// +//===----------------------------------------------------------------------===// +// + +#include "llvm/ADT/StringMap.h" + +namespace llvm { +class Function; +class GlobalVariable; +class Module; +class Regex; +class StringRef; + +class BlackList { + public: + BlackList(const StringRef Path); + // Returns whether either this function or it's source file are blacklisted. + bool isIn(const Function &F) const; + // Returns whether either this global or it's source file are blacklisted. + bool isIn(const GlobalVariable &G) const; + // Returns whether this module is blacklisted by filename. + bool isIn(const Module &M) const; + // Returns whether a global should be excluded from initialization checking. + bool isInInit(const GlobalVariable &G) const; + private: + StringMap<Regex*> Entries; + + bool inSection(const StringRef Section, const StringRef Query) const; +}; + +} // namespace llvm diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h index ca2d8f6..181ed07 100644 --- a/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TRANSFORMS_UTILS_BUILDLIBCALLS_H -#define TRANSFORMS_UTILS_BUILDLIBCALLS_H +#ifndef LLVM_TRANSFORMS_UTILS_BUILDLIBCALLS_H +#define LLVM_TRANSFORMS_UTILS_BUILDLIBCALLS_H #include "llvm/IR/IRBuilder.h" diff --git a/include/llvm/Transforms/Utils/BypassSlowDivision.h b/include/llvm/Transforms/Utils/BypassSlowDivision.h index b11be05..0d081c0 100644 --- a/include/llvm/Transforms/Utils/BypassSlowDivision.h +++ b/include/llvm/Transforms/Utils/BypassSlowDivision.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TRANSFORMS_UTILS_BYPASSSLOWDIVISION_H -#define TRANSFORMS_UTILS_BYPASSSLOWDIVISION_H +#ifndef LLVM_TRANSFORMS_UTILS_BYPASSSLOWDIVISION_H +#define LLVM_TRANSFORMS_UTILS_BYPASSSLOWDIVISION_H #include "llvm/ADT/DenseMap.h" #include "llvm/IR/Function.h" diff --git a/include/llvm/Transforms/Utils/IntegerDivision.h b/include/llvm/Transforms/Utils/IntegerDivision.h index cecc807..27d3c58 100644 --- a/include/llvm/Transforms/Utils/IntegerDivision.h +++ b/include/llvm/Transforms/Utils/IntegerDivision.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TRANSFORMS_UTILS_INTEGERDIVISION_H -#define TRANSFORMS_UTILS_INTEGERDIVISION_H +#ifndef LLVM_TRANSFORMS_UTILS_INTEGERDIVISION_H +#define LLVM_TRANSFORMS_UTILS_INTEGERDIVISION_H namespace llvm { class BinaryOperator; @@ -43,6 +43,20 @@ namespace llvm { /// @brief Replace Div with generated code. bool expandDivision(BinaryOperator* Div); + /// Generate code to calculate the remainder of two integers, replacing Rem + /// with the generated code. Uses the above 32bit routine, therefore adequate + /// for targets with little or no support for less than 32 bit arithmetic. + /// + /// @brief Replace Rem with generated code. + bool expandRemainderUpTo32Bits(BinaryOperator *Rem); + + /// Generate code to divide two integers, replacing Div with the generated + /// code. Uses the above 32bit routine, therefore adequate for targets with + /// little or no support for less than 32 bit arithmetic. + /// + /// @brief Replace Rem with generated code. + bool expandDivisionUpTo32Bits(BinaryOperator *Div); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h index 2c0ec9b..bb7fc06 100644 --- a/include/llvm/Transforms/Utils/ModuleUtils.h +++ b/include/llvm/Transforms/Utils/ModuleUtils.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TRANSFORMS_UTILS_MODULE_UTILS_H -#define LLVM_TRANSFORMS_UTILS_MODULE_UTILS_H +#ifndef LLVM_TRANSFORMS_UTILS_MODULEUTILS_H +#define LLVM_TRANSFORMS_UTILS_MODULEUTILS_H namespace llvm { @@ -30,4 +30,4 @@ void appendToGlobalDtors(Module &M, Function *F, int Priority); } // End llvm namespace -#endif // LLVM_TRANSFORMS_UTILS_MODULE_UTILS_H +#endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h index 0bb6ec6..52a6157 100644 --- a/include/llvm/Transforms/Utils/PromoteMemToReg.h +++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TRANSFORMS_UTILS_PROMOTEMEMTOREG_H -#define TRANSFORMS_UTILS_PROMOTEMEMTOREG_H +#ifndef LLVM_TRANSFORMS_UTILS_PROMOTEMEMTOREG_H +#define LLVM_TRANSFORMS_UTILS_PROMOTEMEMTOREG_H #include <vector> diff --git a/include/llvm/Transforms/Vectorize.h b/include/llvm/Transforms/Vectorize.h index 1ba4d22..d205dbd 100644 --- a/include/llvm/Transforms/Vectorize.h +++ b/include/llvm/Transforms/Vectorize.h @@ -84,6 +84,9 @@ struct VectorizeConfig { /// @brief The maximum number of pairable instructions per group. unsigned MaxInsts; + /// @brief The maximum number of candidate instruction pairs per group. + unsigned MaxPairs; + /// @brief The maximum number of pairing iterations. unsigned MaxIter; |