diff options
Diffstat (limited to 'contrib/llvm/include')
319 files changed, 17629 insertions, 5368 deletions
diff --git a/contrib/llvm/include/llvm-c/Core.h b/contrib/llvm/include/llvm-c/Core.h index 75cee7d..39c3cb4 100644 --- a/contrib/llvm/include/llvm-c/Core.h +++ b/contrib/llvm/include/llvm-c/Core.h @@ -33,13 +33,14 @@ #ifndef LLVM_C_CORE_H #define LLVM_C_CORE_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #ifdef __cplusplus /* Need these includes to support the LLVM 'cast' template for the C++ 'wrap' and 'unwrap' conversion functions. */ #include "llvm/Module.h" +#include "llvm/PassRegistry.h" #include "llvm/Support/IRBuilder.h" extern "C" { @@ -92,6 +93,9 @@ typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef; /** See the llvm::PassManagerBase class. */ typedef struct LLVMOpaquePassManager *LLVMPassManagerRef; +/** See the llvm::PassRegistry class. */ +typedef struct LLVMOpaquePassRegistry *LLVMPassRegistryRef; + /** Used to get the users and usees of a Value. See the llvm::Use class. */ typedef struct LLVMOpaqueUse *LLVMUseRef; @@ -204,7 +208,8 @@ typedef enum { LLVMPointerTypeKind, /**< Pointers */ LLVMOpaqueTypeKind, /**< Opaque: type with unknown structure */ LLVMVectorTypeKind, /**< SIMD 'packed' format, or other vector type */ - LLVMMetadataTypeKind /**< Metadata */ + LLVMMetadataTypeKind, /**< Metadata */ + LLVMX86_MMXTypeKind /**< X86 MMX */ } LLVMTypeKind; typedef enum { @@ -317,6 +322,7 @@ void LLVMSetTarget(LLVMModuleRef M, const char *Triple); LLVMBool LLVMAddTypeName(LLVMModuleRef M, const char *Name, LLVMTypeRef Ty); void LLVMDeleteTypeName(LLVMModuleRef M, const char *Name); LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name); +const char *LLVMGetTypeName(LLVMModuleRef M, LLVMTypeRef Ty); /** See Module::dump. */ void LLVMDumpModule(LLVMModuleRef M); @@ -324,6 +330,9 @@ void LLVMDumpModule(LLVMModuleRef M); /** See Module::setModuleInlineAsm. */ void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm); +/** See Module::getContext. */ +LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M); + /*===-- Types -------------------------------------------------------------===*/ /* LLVM types conform to the following hierarchy: @@ -408,10 +417,12 @@ unsigned LLVMGetVectorSize(LLVMTypeRef VectorTy); LLVMTypeRef LLVMVoidTypeInContext(LLVMContextRef C); LLVMTypeRef LLVMLabelTypeInContext(LLVMContextRef C); LLVMTypeRef LLVMOpaqueTypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMX86MMXTypeInContext(LLVMContextRef C); LLVMTypeRef LLVMVoidType(void); LLVMTypeRef LLVMLabelType(void); LLVMTypeRef LLVMOpaqueType(void); +LLVMTypeRef LLVMX86MMXType(void); /* Operations on type handles */ LLVMTypeHandleRef LLVMCreateTypeHandle(LLVMTypeRef PotentiallyAbstractTy); @@ -540,6 +551,9 @@ LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count); /* Operations on scalar constants */ LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N, LLVMBool SignExtend); +LLVMValueRef LLVMConstIntOfArbitraryPrecision(LLVMTypeRef IntTy, + unsigned NumWords, + const uint64_t Words[]); LLVMValueRef LLVMConstIntOfString(LLVMTypeRef IntTy, const char *Text, uint8_t Radix); LLVMValueRef LLVMConstIntOfStringAndSize(LLVMTypeRef IntTy, const char *Text, @@ -1013,6 +1027,11 @@ LLVMBool LLVMCreateMemoryBufferWithSTDIN(LLVMMemoryBufferRef *OutMemBuf, char **OutMessage); void LLVMDisposeMemoryBuffer(LLVMMemoryBufferRef MemBuf); +/*===-- Pass Registry -----------------------------------------------------===*/ + +/** Return the global pass registry, for use with initialization functions. + See llvm::PassRegistry::getPassRegistry. */ +LLVMPassRegistryRef LLVMGetGlobalPassRegistry(void); /*===-- Pass Managers -----------------------------------------------------===*/ @@ -1101,6 +1120,7 @@ namespace llvm { DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef ) DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Use, LLVMUseRef ) DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBase, LLVMPassManagerRef ) + DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassRegistry, LLVMPassRegistryRef ) /* LLVMModuleProviderRef exists for historical reasons, but now just holds a * Module. */ diff --git a/contrib/llvm/include/llvm-c/EnhancedDisassembly.h b/contrib/llvm/include/llvm-c/EnhancedDisassembly.h index d177381..28ac0ed 100644 --- a/contrib/llvm/include/llvm-c/EnhancedDisassembly.h +++ b/contrib/llvm/include/llvm-c/EnhancedDisassembly.h @@ -19,7 +19,7 @@ #ifndef LLVM_C_ENHANCEDDISASSEMBLY_H #define LLVM_C_ENHANCEDDISASSEMBLY_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #ifdef __cplusplus extern "C" { diff --git a/contrib/llvm/include/llvm-c/Initialization.h b/contrib/llvm/include/llvm-c/Initialization.h new file mode 100644 index 0000000..3b59abb --- /dev/null +++ b/contrib/llvm/include/llvm-c/Initialization.h @@ -0,0 +1,40 @@ +/*===-- llvm-c/Initialization.h - Initialization C Interface ------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to LLVM initialization routines, *| +|* which must be called before you can use the functionality provided by *| +|* the corresponding LLVM library. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_INITIALIZEPASSES_H +#define LLVM_C_INITIALIZEPASSES_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void LLVMInitializeCore(LLVMPassRegistryRef R); +void LLVMInitializeTransformUtils(LLVMPassRegistryRef R); +void LLVMInitializeScalarOpts(LLVMPassRegistryRef R); +void LLVMInitializeInstCombine(LLVMPassRegistryRef R); +void LLVMInitializeIPO(LLVMPassRegistryRef R); +void LLVMInitializeInstrumentation(LLVMPassRegistryRef R); +void LLVMInitializeAnalysis(LLVMPassRegistryRef R); +void LLVMInitializeIPA(LLVMPassRegistryRef R); +void LLVMInitializeCodeGen(LLVMPassRegistryRef R); +void LLVMInitializeTarget(LLVMPassRegistryRef R); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/contrib/llvm/include/llvm-c/LinkTimeOptimizer.h b/contrib/llvm/include/llvm-c/LinkTimeOptimizer.h index ccfdcee..fca3946 100644 --- a/contrib/llvm/include/llvm-c/LinkTimeOptimizer.h +++ b/contrib/llvm/include/llvm-c/LinkTimeOptimizer.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This header provides a C API to use the LLVM link time optimization -// library. This is inteded to be used by linkers which are C-only in +// library. This is intended to be used by linkers which are C-only in // their implementation for performing LTO. // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm-c/Transforms/Scalar.h b/contrib/llvm/include/llvm-c/Transforms/Scalar.h index c94019a..2ddfb38 100644 --- a/contrib/llvm/include/llvm-c/Transforms/Scalar.h +++ b/contrib/llvm/include/llvm-c/Transforms/Scalar.h @@ -52,9 +52,6 @@ void LLVMAddLICMPass(LLVMPassManagerRef PM); /** See llvm::createLoopDeletionPass function. */ void LLVMAddLoopDeletionPass(LLVMPassManagerRef PM); -/** See llvm::createLoopIndexSplitPass function. */ -void LLVMAddLoopIndexSplitPass(LLVMPassManagerRef PM); - /** See llvm::createLoopRotatePass function. */ void LLVMAddLoopRotatePass(LLVMPassManagerRef PM); diff --git a/contrib/llvm/include/llvm-c/lto.h b/contrib/llvm/include/llvm-c/lto.h index e6f69af..1c42ce0 100644 --- a/contrib/llvm/include/llvm-c/lto.h +++ b/contrib/llvm/include/llvm-c/lto.h @@ -18,27 +18,28 @@ #include <stdbool.h> #include <stddef.h> -#include "llvm/System/DataTypes.h" +#include <unistd.h> -#define LTO_API_VERSION 3 +#define LTO_API_VERSION 4 typedef enum { - LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */ - LTO_SYMBOL_PERMISSIONS_MASK = 0x000000E0, - LTO_SYMBOL_PERMISSIONS_CODE = 0x000000A0, - LTO_SYMBOL_PERMISSIONS_DATA = 0x000000C0, - LTO_SYMBOL_PERMISSIONS_RODATA = 0x00000080, - LTO_SYMBOL_DEFINITION_MASK = 0x00000700, - LTO_SYMBOL_DEFINITION_REGULAR = 0x00000100, - LTO_SYMBOL_DEFINITION_TENTATIVE = 0x00000200, - LTO_SYMBOL_DEFINITION_WEAK = 0x00000300, - LTO_SYMBOL_DEFINITION_UNDEFINED = 0x00000400, - LTO_SYMBOL_DEFINITION_WEAKUNDEF = 0x00000500, - LTO_SYMBOL_SCOPE_MASK = 0x00003800, - LTO_SYMBOL_SCOPE_INTERNAL = 0x00000800, - LTO_SYMBOL_SCOPE_HIDDEN = 0x00001000, - LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000, - LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800 + LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */ + LTO_SYMBOL_PERMISSIONS_MASK = 0x000000E0, + LTO_SYMBOL_PERMISSIONS_CODE = 0x000000A0, + LTO_SYMBOL_PERMISSIONS_DATA = 0x000000C0, + LTO_SYMBOL_PERMISSIONS_RODATA = 0x00000080, + LTO_SYMBOL_DEFINITION_MASK = 0x00000700, + LTO_SYMBOL_DEFINITION_REGULAR = 0x00000100, + LTO_SYMBOL_DEFINITION_TENTATIVE = 0x00000200, + LTO_SYMBOL_DEFINITION_WEAK = 0x00000300, + LTO_SYMBOL_DEFINITION_UNDEFINED = 0x00000400, + LTO_SYMBOL_DEFINITION_WEAKUNDEF = 0x00000500, + LTO_SYMBOL_SCOPE_MASK = 0x00003800, + LTO_SYMBOL_SCOPE_INTERNAL = 0x00000800, + LTO_SYMBOL_SCOPE_HIDDEN = 0x00001000, + LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000, + LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800, + LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800 } lto_symbol_attributes; typedef enum { @@ -121,6 +122,13 @@ lto_module_create(const char* path); extern lto_module_t lto_module_create_from_memory(const void* mem, size_t length); +/** + * Loads an object file from disk. The seek point of fd is not preserved. + * Returns NULL on error (check lto_get_error_message() for details). + */ +extern lto_module_t +lto_module_create_from_fd(int fd, const char *path, off_t size); + /** * Frees all memory internally allocated by the module. @@ -146,7 +154,7 @@ lto_module_set_target_triple(lto_module_t mod, const char *triple); /** * Returns the number of symbols in the object module. */ -extern uint32_t +extern unsigned int lto_module_get_num_symbols(lto_module_t mod); @@ -154,14 +162,14 @@ lto_module_get_num_symbols(lto_module_t mod); * Returns the name of the ith symbol in the object module. */ extern const char* -lto_module_get_symbol_name(lto_module_t mod, uint32_t index); +lto_module_get_symbol_name(lto_module_t mod, unsigned int index); /** * Returns the attributes of the ith symbol in the object module. */ extern lto_symbol_attributes -lto_module_get_symbol_attribute(lto_module_t mod, uint32_t index); +lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index); /** diff --git a/contrib/llvm/include/llvm/ADT/APFloat.h b/contrib/llvm/include/llvm/ADT/APFloat.h index dfe4e0f..ca4138b 100644 --- a/contrib/llvm/include/llvm/ADT/APFloat.h +++ b/contrib/llvm/include/llvm/ADT/APFloat.h @@ -246,6 +246,13 @@ namespace llvm { static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative = false); + /// getAllOnesValue - Returns a float which is bitcasted from + /// an all one value int. + /// + /// \param BitWidth - Select float type + /// \param isIEEE - If 128 bit number, select between PPC and IEEE + static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false); + /// Profile - Used to insert APFloat objects, or objects that contain /// APFloat objects, into FoldingSets. void Profile(FoldingSetNodeID& NID) const; diff --git a/contrib/llvm/include/llvm/ADT/APInt.h b/contrib/llvm/include/llvm/ADT/APInt.h index 8004cb4..b91d5dc 100644 --- a/contrib/llvm/include/llvm/ADT/APInt.h +++ b/contrib/llvm/include/llvm/ADT/APInt.h @@ -275,12 +275,6 @@ public: /// objects, into FoldingSets. void Profile(FoldingSetNodeID& id) const; - /// @brief Used by the Bitcode serializer to emit APInts to Bitcode. - void Emit(Serializer& S) const; - - /// @brief Used by the Bitcode deserializer to deserialize APInts. - void Read(Deserializer& D); - /// @} /// @name Value Tests /// @{ @@ -302,7 +296,7 @@ public: /// @returns true if this APInt is positive. /// @brief Determine if this APInt Value is positive. bool isStrictlyPositive() const { - return isNonNegative() && (*this) != 0; + return isNonNegative() && !!*this; } /// This checks to see if the value has all bits of the APInt are set or not. @@ -330,15 +324,14 @@ public: /// value for the APInt's bit width. /// @brief Determine if this is the smallest unsigned value. bool isMinValue() const { - return countPopulation() == 0; + return !*this; } /// This checks to see if the value of this APInt is the minimum signed /// value for the APInt's bit width. /// @brief Determine if this is the smallest signed value. bool isMinSignedValue() const { - return BitWidth == 1 ? VAL == 1 : - isNegative() && countPopulation() == 1; + return BitWidth == 1 ? VAL == 1 : isNegative() && isPowerOf2(); } /// @brief Check if this APInt has an N-bits unsigned integer value. @@ -348,10 +341,8 @@ public: return true; if (isSingleWord()) - return VAL == (VAL & (~0ULL >> (64 - N))); - APInt Tmp(N, getNumWords(), pVal); - Tmp.zext(getBitWidth()); - return Tmp == (*this); + return isUIntN(N, VAL); + return APInt(N, getNumWords(), pVal).zext(getBitWidth()) == (*this); } /// @brief Check if this APInt has an N-bits signed integer value. @@ -361,7 +352,11 @@ public: } /// @returns true if the argument APInt value is a power of two > 0. - bool isPowerOf2() const; + bool isPowerOf2() const { + if (isSingleWord()) + return isPowerOf2_64(VAL); + return countPopulationSlowCase() == 1; + } /// isSignBit - Return true if this is the value returned by getSignBit. bool isSignBit() const { return isMinSignedValue(); } @@ -369,7 +364,7 @@ public: /// This converts the APInt to a boolean value as a test against zero. /// @brief Boolean conversion function. bool getBoolValue() const { - return *this != 0; + return !!*this; } /// getLimitedValue - If this value is smaller than the specified limit, @@ -385,12 +380,14 @@ public: /// @{ /// @brief Gets maximum unsigned value of APInt for specific bit width. static APInt getMaxValue(unsigned numBits) { - return APInt(numBits, 0).set(); + return getAllOnesValue(numBits); } /// @brief Gets maximum signed value of APInt for a specific bit width. static APInt getSignedMaxValue(unsigned numBits) { - return APInt(numBits, 0).set().clear(numBits - 1); + APInt API = getAllOnesValue(numBits); + API.clearBit(numBits - 1); + return API; } /// @brief Gets minimum unsigned value of APInt for a specific bit width. @@ -400,7 +397,9 @@ public: /// @brief Gets minimum signed value of APInt for a specific bit width. static APInt getSignedMinValue(unsigned numBits) { - return APInt(numBits, 0).set(numBits - 1); + APInt API(numBits, 0); + API.setBit(numBits - 1); + return API; } /// getSignBit - This is just a wrapper function of getSignedMinValue(), and @@ -413,7 +412,7 @@ public: /// @returns the all-ones value for an APInt of the specified bit-width. /// @brief Get the all-ones value. static APInt getAllOnesValue(unsigned numBits) { - return APInt(numBits, 0).set(); + return APInt(numBits, -1ULL, true); } /// @returns the '0' value for an APInt of the specified bit-width. @@ -432,6 +431,13 @@ public: /// @returns the low "numBits" bits of this APInt. APInt getLoBits(unsigned numBits) const; + /// getOneBitSet - Return an APInt with exactly one bit set in the result. + static APInt getOneBitSet(unsigned numBits, unsigned BitNo) { + APInt Res(numBits, 0); + Res.setBit(BitNo); + return Res; + } + /// Constructs an APInt value that has a contiguous range of bits set. The /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other /// bits will be zero. For example, with parameters(32, 0, 16) you would get @@ -530,7 +536,7 @@ public: /// @brief Unary bitwise complement operator. APInt operator~() const { APInt Result(*this); - Result.flip(); + Result.flipAllBits(); return Result; } @@ -741,11 +747,11 @@ public: /// RHS are treated as unsigned quantities for purposes of this division. /// @returns a new APInt value containing the division result /// @brief Unsigned division operation. - APInt udiv(const APInt& RHS) const; + APInt udiv(const APInt &RHS) const; /// Signed divide this APInt by APInt RHS. /// @brief Signed division function for APInt. - APInt sdiv(const APInt& RHS) const { + APInt sdiv(const APInt &RHS) const { if (isNegative()) if (RHS.isNegative()) return (-(*this)).udiv(-RHS); @@ -763,11 +769,11 @@ public: /// which is *this. /// @returns a new APInt value containing the remainder result /// @brief Unsigned remainder operation. - APInt urem(const APInt& RHS) const; + APInt urem(const APInt &RHS) const; /// Signed remainder operation on APInt. /// @brief Function for signed remainder operation. - APInt srem(const APInt& RHS) const { + APInt srem(const APInt &RHS) const { if (isNegative()) if (RHS.isNegative()) return -((-(*this)).urem(-RHS)); @@ -788,8 +794,7 @@ public: APInt &Quotient, APInt &Remainder); static void sdivrem(const APInt &LHS, const APInt &RHS, - APInt &Quotient, APInt &Remainder) - { + APInt &Quotient, APInt &Remainder) { if (LHS.isNegative()) { if (RHS.isNegative()) APInt::udivrem(-LHS, -RHS, Quotient, Remainder); @@ -804,6 +809,16 @@ public: APInt::udivrem(LHS, RHS, Quotient, Remainder); } } + + + // Operations that return overflow indicators. + APInt sadd_ov(const APInt &RHS, bool &Overflow) const; + APInt uadd_ov(const APInt &RHS, bool &Overflow) const; + APInt ssub_ov(const APInt &RHS, bool &Overflow) const; + APInt usub_ov(const APInt &RHS, bool &Overflow) const; + APInt sdiv_ov(const APInt &RHS, bool &Overflow) const; + APInt smul_ov(const APInt &RHS, bool &Overflow) const; + APInt sshl_ov(unsigned Amt, bool &Overflow) const; /// @returns the bit value at bitPosition /// @brief Array-indexing support. @@ -868,7 +883,7 @@ public: /// the validity of the less-than relationship. /// @returns true if *this < RHS when both are considered unsigned. /// @brief Unsigned less than comparison - bool ult(const APInt& RHS) const; + bool ult(const APInt &RHS) const; /// Regards both *this as an unsigned quantity and compares it with RHS for /// the validity of the less-than relationship. @@ -988,6 +1003,9 @@ public: return sge(APInt(getBitWidth(), RHS)); } + + + /// This operation tests if there are any pairs of corresponding bits /// between this APInt and RHS that are both set. bool intersects(const APInt &RHS) const { @@ -1000,80 +1018,78 @@ public: /// Truncate the APInt to a specified width. It is an error to specify a width /// that is greater than or equal to the current width. /// @brief Truncate to new width. - APInt &trunc(unsigned width); + APInt trunc(unsigned width) const; /// This operation sign extends the APInt to a new width. If the high order /// bit is set, the fill on the left will be done with 1 bits, otherwise zero. /// It is an error to specify a width that is less than or equal to the /// current width. /// @brief Sign extend to a new width. - APInt &sext(unsigned width); + APInt sext(unsigned width) const; /// This operation zero extends the APInt to a new width. The high order bits /// are filled with 0 bits. It is an error to specify a width that is less /// than or equal to the current width. /// @brief Zero extend to a new width. - APInt &zext(unsigned width); + APInt zext(unsigned width) const; /// Make this APInt have the bit width given by \p width. The value is sign /// extended, truncated, or left alone to make it that width. /// @brief Sign extend or truncate to width - APInt &sextOrTrunc(unsigned width); + APInt sextOrTrunc(unsigned width) const; /// Make this APInt have the bit width given by \p width. The value is zero /// extended, truncated, or left alone to make it that width. /// @brief Zero extend or truncate to width - APInt &zextOrTrunc(unsigned width); + APInt zextOrTrunc(unsigned width) const; /// @} /// @name Bit Manipulation Operators /// @{ /// @brief Set every bit to 1. - APInt& set() { - if (isSingleWord()) { + void setAllBits() { + if (isSingleWord()) VAL = -1ULL; - return clearUnusedBits(); + else { + // Set all the bits in all the words. + for (unsigned i = 0; i < getNumWords(); ++i) + pVal[i] = -1ULL; } - - // Set all the bits in all the words. - for (unsigned i = 0; i < getNumWords(); ++i) - pVal[i] = -1ULL; // Clear the unused ones - return clearUnusedBits(); + clearUnusedBits(); } /// Set the given bit to 1 whose position is given as "bitPosition". /// @brief Set a given bit to 1. - APInt& set(unsigned bitPosition); + void setBit(unsigned bitPosition); /// @brief Set every bit to 0. - APInt& clear() { + void clearAllBits() { if (isSingleWord()) VAL = 0; else memset(pVal, 0, getNumWords() * APINT_WORD_SIZE); - return *this; } /// Set the given bit to 0 whose position is given as "bitPosition". /// @brief Set a given bit to 0. - APInt& clear(unsigned bitPosition); + void clearBit(unsigned bitPosition); /// @brief Toggle every bit to its opposite value. - APInt& flip() { - if (isSingleWord()) { + void flipAllBits() { + if (isSingleWord()) VAL ^= -1ULL; - return clearUnusedBits(); + else { + for (unsigned i = 0; i < getNumWords(); ++i) + pVal[i] ^= -1ULL; } - for (unsigned i = 0; i < getNumWords(); ++i) - pVal[i] ^= -1ULL; - return clearUnusedBits(); + clearUnusedBits(); } /// Toggle a given bit to its opposite value whose position is given /// as "bitPosition". /// @brief Toggles a given bit to its opposite value. - APInt& flip(unsigned bitPosition); + void flipBit(unsigned bitPosition); /// @} /// @name Value Characterization Functions @@ -1281,37 +1297,27 @@ public: } /// The conversion does not do a translation from double to integer, it just - /// re-interprets the bits of the double. Note that it is valid to do this on - /// any bit width but bits from V may get truncated. + /// re-interprets the bits of the double. /// @brief Converts a double to APInt bits. - APInt& doubleToBits(double V) { + static APInt doubleToBits(double V) { union { uint64_t I; double D; } T; T.D = V; - if (isSingleWord()) - VAL = T.I; - else - pVal[0] = T.I; - return clearUnusedBits(); + return APInt(sizeof T * CHAR_BIT, T.I); } /// The conversion does not do a translation from float to integer, it just - /// re-interprets the bits of the float. Note that it is valid to do this on - /// any bit width but bits from V may get truncated. + /// re-interprets the bits of the float. /// @brief Converts a float to APInt bits. - APInt& floatToBits(float V) { + static APInt floatToBits(float V) { union { unsigned I; float F; } T; T.F = V; - if (isSingleWord()) - VAL = T.I; - else - pVal[0] = T.I; - return clearUnusedBits(); + return APInt(sizeof T * CHAR_BIT, T.I); } /// @} diff --git a/contrib/llvm/include/llvm/ADT/APSInt.h b/contrib/llvm/include/llvm/ADT/APSInt.h index 1c9931c..54a7b60 100644 --- a/contrib/llvm/include/llvm/ADT/APSInt.h +++ b/contrib/llvm/include/llvm/ADT/APSInt.h @@ -68,20 +68,22 @@ public: } using APInt::toString; - APSInt& extend(uint32_t width) { + APSInt trunc(uint32_t width) const { + return APSInt(APInt::trunc(width), IsUnsigned); + } + + APSInt extend(uint32_t width) const { if (IsUnsigned) - zext(width); + return APSInt(zext(width), IsUnsigned); else - sext(width); - return *this; + return APSInt(sext(width), IsUnsigned); } - APSInt& extOrTrunc(uint32_t width) { + APSInt extOrTrunc(uint32_t width) const { if (IsUnsigned) - zextOrTrunc(width); + return APSInt(zextOrTrunc(width), IsUnsigned); else - sextOrTrunc(width); - return *this; + return APSInt(sextOrTrunc(width), IsUnsigned); } const APSInt &operator%=(const APSInt &RHS) { diff --git a/contrib/llvm/include/llvm/ADT/ArrayRef.h b/contrib/llvm/include/llvm/ADT/ArrayRef.h new file mode 100644 index 0000000..1c5470d --- /dev/null +++ b/contrib/llvm/include/llvm/ADT/ArrayRef.h @@ -0,0 +1,121 @@ +//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ARRAYREF_H +#define LLVM_ADT_ARRAYREF_H + +#include "llvm/ADT/SmallVector.h" +#include <vector> + +namespace llvm { + class APInt; + + /// ArrayRef - Represent a constant reference to an array (0 or more elements + /// consecutively in memory), i.e. a start pointer and a length. It allows + /// various APIs to take consecutive elements easily and conveniently. + /// + /// This class does not own the underlying data, it is expected to be used in + /// situations where the data resides in some other buffer, whose lifetime + /// extends past that of the StringRef. For this reason, it is not in general + /// safe to store a ArrayRef. + /// + /// This is intended to be trivially copyable, so it should be passed by + /// value. + template<typename T> + class ArrayRef { + public: + typedef const T *iterator; + typedef const T *const_iterator; + typedef size_t size_type; + + private: + /// The start of the array, in an external buffer. + const T *Data; + + /// The number of elements. + size_t Length; + + public: + /// @name Constructors + /// @{ + + /// Construct an empty ArrayRef. + /*implicit*/ ArrayRef() : Data(0), Length(0) {} + + /// Construct an ArrayRef from a single element. + /*implicit*/ ArrayRef(const T &OneElt) + : Data(&OneElt), Length(1) {} + + /// Construct an ArrayRef from a pointer and length. + /*implicit*/ ArrayRef(const T *data, size_t length) + : Data(data), Length(length) {} + + /// Construct an ArrayRef from a SmallVector. + /*implicit*/ ArrayRef(const SmallVectorImpl<T> &Vec) + : Data(Vec.data()), Length(Vec.size()) {} + + /// Construct an ArrayRef from a std::vector. + /*implicit*/ ArrayRef(const std::vector<T> &Vec) + : Data(Vec.empty() ? (T*)0 : &Vec[0]), Length(Vec.size()) {} + + // TODO: C arrays. + + /// @} + /// @name Simple Operations + /// @{ + + iterator begin() const { return Data; } + iterator end() const { return Data + Length; } + + /// empty - Check if the array is empty. + bool empty() const { return Length == 0; } + + /// size - Get the array size. + size_t size() const { return Length; } + + /// front - Get the first element. + const T &front() const { + assert(!empty()); + return Data[0]; + } + + /// back - Get the last element. + const T &back() const { + assert(!empty()); + return Data[Length-1]; + } + + /// @} + /// @name Operator Overloads + /// @{ + + const T &operator[](size_t Index) const { + assert(Index < Length && "Invalid index!"); + return Data[Index]; + } + + /// @} + /// @name Expensive Operations + /// @{ + + std::vector<T> vec() const { + return std::vector<T>(Data, Data+Length); + } + + /// @} + }; + + // ArrayRefs can be treated like a POD type. + template <typename T> struct isPodLike; + template <typename T> struct isPodLike<ArrayRef<T> > { + static const bool value = true; + }; +} + +#endif diff --git a/contrib/llvm/include/llvm/ADT/BitVector.h b/contrib/llvm/include/llvm/ADT/BitVector.h index 9dcb9e1..ac1cf0c 100644 --- a/contrib/llvm/include/llvm/ADT/BitVector.h +++ b/contrib/llvm/include/llvm/ADT/BitVector.h @@ -18,6 +18,7 @@ #include <algorithm> #include <cassert> #include <climits> +#include <cstdlib> #include <cstring> namespace llvm { @@ -77,7 +78,7 @@ public: /// bits are initialized to the specified value. explicit BitVector(unsigned s, bool t = false) : Size(s) { Capacity = NumBitWords(s); - Bits = new BitWord[Capacity]; + Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); init_words(Bits, Capacity, t); if (t) clear_unused_bits(); @@ -92,12 +93,12 @@ public: } Capacity = NumBitWords(RHS.size()); - Bits = new BitWord[Capacity]; - std::copy(RHS.Bits, &RHS.Bits[Capacity], Bits); + Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); + std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord)); } ~BitVector() { - delete[] Bits; + std::free(Bits); } /// empty - Tests whether there are no bits in this bitvector. @@ -127,6 +128,12 @@ public: return false; } + /// all - Returns true if all bits are set. + bool all() const { + // TODO: Optimize this. + return count() == size(); + } + /// none - Returns true if none of the bits are set. bool none() const { return !any(); @@ -335,18 +342,18 @@ public: unsigned RHSWords = NumBitWords(Size); if (Size <= Capacity * BITWORD_SIZE) { if (Size) - std::copy(RHS.Bits, &RHS.Bits[RHSWords], Bits); + std::memcpy(Bits, RHS.Bits, RHSWords * sizeof(BitWord)); clear_unused_bits(); return *this; } // Grow the bitvector to have enough elements. Capacity = RHSWords; - BitWord *NewBits = new BitWord[Capacity]; - std::copy(RHS.Bits, &RHS.Bits[RHSWords], NewBits); + BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); + std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord)); // Destroy the old bits. - delete[] Bits; + std::free(Bits); Bits = NewBits; return *this; @@ -384,17 +391,8 @@ private: } void grow(unsigned NewSize) { - unsigned OldCapacity = Capacity; - Capacity = NumBitWords(NewSize); - BitWord *NewBits = new BitWord[Capacity]; - - // Copy the old bits over. - if (OldCapacity != 0) - std::copy(Bits, &Bits[OldCapacity], NewBits); - - // Destroy the old bits. - delete[] Bits; - Bits = NewBits; + Capacity = std::max(NumBitWords(NewSize), Capacity * 2); + Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord)); clear_unused_bits(); } diff --git a/contrib/llvm/include/llvm/ADT/DenseMap.h b/contrib/llvm/include/llvm/ADT/DenseMap.h index 06a1575..61d6ae7 100644 --- a/contrib/llvm/include/llvm/ADT/DenseMap.h +++ b/contrib/llvm/include/llvm/ADT/DenseMap.h @@ -18,6 +18,7 @@ #include "llvm/Support/PointerLikeTypeTraits.h" #include "llvm/Support/type_traits.h" #include "llvm/ADT/DenseMapInfo.h" +#include <algorithm> #include <iterator> #include <new> #include <utility> @@ -385,7 +386,7 @@ private: // Insert the key/value into the new table. BucketT *DestBucket; bool FoundVal = LookupBucketFor(B->first, DestBucket); - FoundVal = FoundVal; // silence warning. + (void)FoundVal; // silence warning. assert(!FoundVal && "Key already in new map?"); DestBucket->first = B->first; new (&DestBucket->second) ValueT(B->second); diff --git a/contrib/llvm/include/llvm/ADT/DenseMapInfo.h b/contrib/llvm/include/llvm/ADT/DenseMapInfo.h index 5299386..25e341b 100644 --- a/contrib/llvm/include/llvm/ADT/DenseMapInfo.h +++ b/contrib/llvm/include/llvm/ADT/DenseMapInfo.h @@ -102,6 +102,20 @@ template<> struct DenseMapInfo<int> { } }; +// Provide DenseMapInfo for longs. +template<> struct DenseMapInfo<long> { + static inline long getEmptyKey() { + return (1UL << (sizeof(long) * 8 - 1)) - 1L; + } + static inline long getTombstoneKey() { return getEmptyKey() - 1L; } + static unsigned getHashValue(const long& Val) { + return (unsigned)(Val * 37L); + } + static bool isEqual(const long& LHS, const long& RHS) { + return LHS == RHS; + } +}; + // Provide DenseMapInfo for long longs. template<> struct DenseMapInfo<long long> { static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; } diff --git a/contrib/llvm/include/llvm/ADT/DenseSet.h b/contrib/llvm/include/llvm/ADT/DenseSet.h index 00bcf64..67321f5 100644 --- a/contrib/llvm/include/llvm/ADT/DenseSet.h +++ b/contrib/llvm/include/llvm/ADT/DenseSet.h @@ -33,6 +33,9 @@ public: bool empty() const { return TheMap.empty(); } unsigned size() const { return TheMap.size(); } + /// Grow the denseset so that it has at least Size buckets. Does not shrink + void resize(size_t Size) { TheMap.resize(Size); } + void clear() { TheMap.clear(); } diff --git a/contrib/llvm/include/llvm/ADT/EquivalenceClasses.h b/contrib/llvm/include/llvm/ADT/EquivalenceClasses.h index 07a5edf..771476c 100644 --- a/contrib/llvm/include/llvm/ADT/EquivalenceClasses.h +++ b/contrib/llvm/include/llvm/ADT/EquivalenceClasses.h @@ -15,7 +15,7 @@ #ifndef LLVM_ADT_EQUIVALENCECLASSES_H #define LLVM_ADT_EQUIVALENCECLASSES_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> #include <set> diff --git a/contrib/llvm/include/llvm/ADT/FoldingSet.h b/contrib/llvm/include/llvm/ADT/FoldingSet.h index 662b5e2..879dbd0 100644 --- a/contrib/llvm/include/llvm/ADT/FoldingSet.h +++ b/contrib/llvm/include/llvm/ADT/FoldingSet.h @@ -16,7 +16,7 @@ #ifndef LLVM_ADT_FOLDINGSET_H #define LLVM_ADT_FOLDINGSET_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" diff --git a/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h b/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h index 968ce15..d3196ca 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h @@ -94,7 +94,7 @@ public: : ImutAVLFactory<ImutInfo>(Alloc) {} TreeTy *Add(TreeTy *T, value_type_ref V) { - T = Add_internal(V,T); + T = add_internal(V,T); this->MarkImmutable(T); return T; } @@ -103,20 +103,20 @@ public: if (!T) return NULL; - key_type_ref CurrentKey = ImutInfo::KeyOfValue(this->Value(T)); + key_type_ref CurrentKey = ImutInfo::KeyOfValue(this->getValue(T)); if (ImutInfo::isContainedIn(K, CurrentKey)) return T; else if (ImutInfo::isLess(K, CurrentKey)) - return Find(this->Left(T), K); + return Find(this->getLeft(T), K); else - return Find(this->Right(T), K); + return Find(this->getRight(T), K); } private: - TreeTy *Add_internal(value_type_ref V, TreeTy *T) { + TreeTy *add_internal(value_type_ref V, TreeTy *T) { key_type_ref K = ImutInfo::KeyOfValue(V); - T = RemoveAllOverlaps(T, K); + T = removeAllOverlaps(T, K); if (this->isEmpty(T)) return this->CreateNode(NULL, V, NULL); @@ -125,38 +125,38 @@ private: key_type_ref KCurrent = ImutInfo::KeyOfValue(this->Value(T)); if (ImutInfo::isLess(K, KCurrent)) - return this->Balance(Add_internal(V, this->Left(T)), this->Value(T), + return this->Balance(add_internal(V, this->Left(T)), this->Value(T), this->Right(T)); else return this->Balance(this->Left(T), this->Value(T), - Add_internal(V, this->Right(T))); + add_internal(V, this->Right(T))); } // Remove all overlaps from T. - TreeTy *RemoveAllOverlaps(TreeTy *T, key_type_ref K) { + TreeTy *removeAllOverlaps(TreeTy *T, key_type_ref K) { bool Changed; do { Changed = false; - T = RemoveOverlap(T, K, Changed); - this->MarkImmutable(T); + T = removeOverlap(T, K, Changed); + this->markImmutable(T); } while (Changed); return T; } // Remove one overlap from T. - TreeTy *RemoveOverlap(TreeTy *T, key_type_ref K, bool &Changed) { + TreeTy *removeOverlap(TreeTy *T, key_type_ref K, bool &Changed) { if (!T) return NULL; Interval CurrentK = ImutInfo::KeyOfValue(this->Value(T)); // If current key does not overlap the inserted key. if (CurrentK.getStart() > K.getEnd()) - return this->Balance(RemoveOverlap(this->Left(T), K, Changed), + return this->Balance(removeOverlap(this->Left(T), K, Changed), this->Value(T), this->Right(T)); else if (CurrentK.getEnd() < K.getStart()) return this->Balance(this->Left(T), this->Value(T), - RemoveOverlap(this->Right(T), K, Changed)); + removeOverlap(this->Right(T), K, Changed)); // Current key overlaps with the inserted key. // Remove the current key. @@ -167,18 +167,18 @@ private: if (CurrentK.getStart() < K.getStart()) { if (CurrentK.getEnd() <= K.getEnd()) { Interval NewK(CurrentK.getStart(), K.getStart()-1); - return Add_internal(std::make_pair(NewK, OldData), T); + return add_internal(std::make_pair(NewK, OldData), T); } else { Interval NewK1(CurrentK.getStart(), K.getStart()-1); - T = Add_internal(std::make_pair(NewK1, OldData), T); + T = add_internal(std::make_pair(NewK1, OldData), T); Interval NewK2(K.getEnd()+1, CurrentK.getEnd()); - return Add_internal(std::make_pair(NewK2, OldData), T); + return add_internal(std::make_pair(NewK2, OldData), T); } } else { if (CurrentK.getEnd() > K.getEnd()) { Interval NewK(K.getEnd()+1, CurrentK.getEnd()); - return Add_internal(std::make_pair(NewK, OldData), T); + return add_internal(std::make_pair(NewK, OldData), T); } else return T; } @@ -209,22 +209,22 @@ public: public: Factory(BumpPtrAllocator& Alloc) : F(Alloc) {} - ImmutableIntervalMap GetEmptyMap() { - return ImmutableIntervalMap(F.GetEmptyTree()); + ImmutableIntervalMap getEmptyMap() { + return ImmutableIntervalMap(F.getEmptyTree()); } - ImmutableIntervalMap Add(ImmutableIntervalMap Old, + ImmutableIntervalMap add(ImmutableIntervalMap Old, key_type_ref K, data_type_ref D) { - TreeTy *T = F.Add(Old.Root, std::make_pair<key_type, data_type>(K, D)); - return ImmutableIntervalMap(F.GetCanonicalTree(T)); + TreeTy *T = F.add(Old.Root, std::make_pair<key_type, data_type>(K, D)); + return ImmutableIntervalMap(F.getCanonicalTree(T)); } - ImmutableIntervalMap Remove(ImmutableIntervalMap Old, key_type_ref K) { - TreeTy *T = F.Remove(Old.Root, K); - return ImmutableIntervalMap(F.GetCanonicalTree(T)); + ImmutableIntervalMap remove(ImmutableIntervalMap Old, key_type_ref K) { + TreeTy *T = F.remove(Old.Root, K); + return ImmutableIntervalMap(F.getCanonicalTree(T)); } - data_type *Lookup(ImmutableIntervalMap M, key_type_ref K) { + data_type *lookup(ImmutableIntervalMap M, key_type_ref K) { TreeTy *T = F.Find(M.getRoot(), K); if (T) return &T->getValue().second; diff --git a/contrib/llvm/include/llvm/ADT/ImmutableList.h b/contrib/llvm/include/llvm/ADT/ImmutableList.h index 7757c08..714355b 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableList.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableList.h @@ -16,7 +16,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { @@ -156,7 +156,7 @@ public: if (ownsAllocator()) delete &getAllocator(); } - ImmutableList<T> Concat(const T& Head, ImmutableList<T> Tail) { + ImmutableList<T> concat(const T& Head, ImmutableList<T> Tail) { // Profile the new list to see if it already exists in our cache. FoldingSetNodeID ID; void* InsertPos; @@ -178,16 +178,16 @@ public: return L; } - ImmutableList<T> Add(const T& D, ImmutableList<T> L) { - return Concat(D, L); + ImmutableList<T> add(const T& D, ImmutableList<T> L) { + return concat(D, L); } - ImmutableList<T> GetEmptyList() const { + ImmutableList<T> getEmptyList() const { return ImmutableList<T>(0); } - ImmutableList<T> Create(const T& X) { - return Concat(X, GetEmptyList()); + ImmutableList<T> create(const T& X) { + return Concat(X, getEmptyList()); } }; diff --git a/contrib/llvm/include/llvm/ADT/ImmutableMap.h b/contrib/llvm/include/llvm/ADT/ImmutableMap.h index 8af128e..e439a09 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableMap.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableMap.h @@ -76,7 +76,23 @@ public: /// should use a Factory object to create maps instead of directly /// invoking the constructor, but there are cases where make this /// constructor public is useful. - explicit ImmutableMap(const TreeTy* R) : Root(const_cast<TreeTy*>(R)) {} + explicit ImmutableMap(const TreeTy* R) : Root(const_cast<TreeTy*>(R)) { + if (Root) { Root->retain(); } + } + ImmutableMap(const ImmutableMap &X) : Root(X.Root) { + if (Root) { Root->retain(); } + } + ImmutableMap &operator=(const ImmutableMap &X) { + if (Root != X.Root) { + if (X.Root) { X.Root->retain(); } + if (Root) { Root->release(); } + Root = X.Root; + } + return *this; + } + ~ImmutableMap() { + if (Root) { Root->release(); } + } class Factory { typename TreeTy::Factory F; @@ -89,16 +105,16 @@ public: Factory(BumpPtrAllocator& Alloc, bool canonicalize = true) : F(Alloc), Canonicalize(canonicalize) {} - ImmutableMap GetEmptyMap() { return ImmutableMap(F.GetEmptyTree()); } + ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); } - ImmutableMap Add(ImmutableMap Old, key_type_ref K, data_type_ref D) { - TreeTy *T = F.Add(Old.Root, std::make_pair<key_type,data_type>(K,D)); - return ImmutableMap(Canonicalize ? F.GetCanonicalTree(T): T); + ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D) { + TreeTy *T = F.add(Old.Root, std::make_pair<key_type,data_type>(K,D)); + return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); } - ImmutableMap Remove(ImmutableMap Old, key_type_ref K) { - TreeTy *T = F.Remove(Old.Root,K); - return ImmutableMap(Canonicalize ? F.GetCanonicalTree(T): T); + ImmutableMap remove(ImmutableMap Old, key_type_ref K) { + TreeTy *T = F.remove(Old.Root,K); + return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); } private: @@ -110,15 +126,30 @@ public: return Root ? Root->contains(K) : false; } - bool operator==(ImmutableMap RHS) const { + bool operator==(const ImmutableMap &RHS) const { return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; } - bool operator!=(ImmutableMap RHS) const { + bool operator!=(const ImmutableMap &RHS) const { return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; } - TreeTy* getRoot() const { return Root; } + TreeTy *getRoot() const { + if (Root) { Root->retain(); } + return Root; + } + + TreeTy *getRootWithoutRetain() const { + return Root; + } + + void manualRetain() { + if (Root) Root->retain(); + } + + void manualRelease() { + if (Root) Root->release(); + } bool isEmpty() const { return !Root; } diff --git a/contrib/llvm/include/llvm/ADT/ImmutableSet.h b/contrib/llvm/include/llvm/ADT/ImmutableSet.h index 70c3caf..3ca910c 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableSet.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableSet.h @@ -15,10 +15,13 @@ #define LLVM_ADT_IMSET_H #include "llvm/Support/Allocator.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> #include <functional> +#include <vector> +#include <stdio.h> namespace llvm { @@ -32,7 +35,7 @@ template <typename ImutInfo> class ImutAVLTreeInOrderIterator; template <typename ImutInfo> class ImutAVLTreeGenericIterator; template <typename ImutInfo > -class ImutAVLTree : public FoldingSetNode { +class ImutAVLTree { public: typedef typename ImutInfo::key_type_ref key_type_ref; typedef typename ImutInfo::value_type value_type; @@ -43,7 +46,6 @@ public: friend class ImutIntervalAVLFactory<ImutInfo>; friend class ImutAVLTreeGenericIterator<ImutInfo>; - friend class FoldingSet<ImutAVLTree>; typedef ImutAVLTreeInOrderIterator<ImutInfo> iterator; @@ -51,29 +53,27 @@ public: // Public Interface. //===----------------------------------------------------===// - /// getLeft - Returns a pointer to the left subtree. This value + /// Return a pointer to the left subtree. This value /// is NULL if there is no left subtree. - ImutAVLTree *getLeft() const { return Left; } + ImutAVLTree *getLeft() const { return left; } - /// getRight - Returns a pointer to the right subtree. This value is + /// Return a pointer to the right subtree. This value is /// NULL if there is no right subtree. - ImutAVLTree *getRight() const { return Right; } + ImutAVLTree *getRight() const { return right; } /// getHeight - Returns the height of the tree. A tree with no subtrees /// has a height of 1. - unsigned getHeight() const { return Height; } + unsigned getHeight() const { return height; } /// getValue - Returns the data value associated with the tree node. - const value_type& getValue() const { return Value; } + const value_type& getValue() const { return value; } /// find - Finds the subtree associated with the specified key value. /// This method returns NULL if no matching subtree is found. ImutAVLTree* find(key_type_ref K) { ImutAVLTree *T = this; - while (T) { key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue()); - if (ImutInfo::isEqual(K,CurrentKey)) return T; else if (ImutInfo::isLess(K,CurrentKey)) @@ -81,7 +81,6 @@ public: else T = T->getRight(); } - return NULL; } @@ -90,7 +89,7 @@ public: ImutAVLTree* getMaxElement() { ImutAVLTree *T = this; ImutAVLTree *Right = T->getRight(); - while (Right) { T = Right; Right = T->getRight(); } + while (Right) { T = right; right = T->getRight(); } return T; } @@ -98,10 +97,10 @@ public: /// both leaves and non-leaf nodes. unsigned size() const { unsigned n = 1; - - if (const ImutAVLTree* L = getLeft()) n += L->size(); - if (const ImutAVLTree* R = getRight()) n += R->size(); - + if (const ImutAVLTree* L = getLeft()) + n += L->size(); + if (const ImutAVLTree* R = getRight()) + n += R->size(); return n; } @@ -114,7 +113,7 @@ public: /// inorder traversal. iterator end() const { return iterator(); } - bool ElementEqual(value_type_ref V) const { + bool isElementEqual(value_type_ref V) const { // Compare the keys. if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()), ImutInfo::KeyOfValue(V))) @@ -128,8 +127,8 @@ public: return true; } - bool ElementEqual(const ImutAVLTree* RHS) const { - return ElementEqual(RHS->getValue()); + bool isElementEqual(const ImutAVLTree* RHS) const { + return isElementEqual(RHS->getValue()); } /// isEqual - Compares two trees for structural equality and returns true @@ -144,12 +143,12 @@ public: while (LItr != LEnd && RItr != REnd) { if (*LItr == *RItr) { - LItr.SkipSubTree(); - RItr.SkipSubTree(); + LItr.skipSubTree(); + RItr.skipSubTree(); continue; } - if (!LItr->ElementEqual(*RItr)) + if (!LItr->isElementEqual(*RItr)) return false; ++LItr; @@ -173,22 +172,24 @@ public: /// Nodes are visited using an inorder traversal. template <typename Callback> void foreach(Callback& C) { - if (ImutAVLTree* L = getLeft()) L->foreach(C); + if (ImutAVLTree* L = getLeft()) + L->foreach(C); - C(Value); + C(value); - if (ImutAVLTree* R = getRight()) R->foreach(C); + if (ImutAVLTree* R = getRight()) + R->foreach(C); } - /// verify - A utility method that checks that the balancing and + /// validateTree - A utility method that checks that the balancing and /// ordering invariants of the tree are satisifed. It is a recursive /// method that returns the height of the tree, which is then consumed - /// by the enclosing verify call. External callers should ignore the + /// by the enclosing validateTree call. External callers should ignore the /// return value. An invalid tree will cause an assertion to fire in /// a debug build. - unsigned verify() const { - unsigned HL = getLeft() ? getLeft()->verify() : 0; - unsigned HR = getRight() ? getRight()->verify() : 0; + unsigned validateTree() const { + unsigned HL = getLeft() ? getLeft()->validateTree() : 0; + unsigned HR = getRight() ? getRight()->validateTree() : 0; (void) HL; (void) HR; @@ -198,37 +199,39 @@ public: assert((HL > HR ? HL-HR : HR-HL) <= 2 && "Balancing invariant violated"); - assert(!getLeft() - || ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()), - ImutInfo::KeyOfValue(getValue())) - && "Value in left child is not less that current value"); + assert((!getLeft() || + ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()), + ImutInfo::KeyOfValue(getValue()))) && + "Value in left child is not less that current value"); - assert(!getRight() - || ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()), - ImutInfo::KeyOfValue(getRight()->getValue())) - && "Current value is not less that value of right child"); + assert(!(getRight() || + ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()), + ImutInfo::KeyOfValue(getRight()->getValue()))) && + "Current value is not less that value of right child"); return getHeight(); } - /// Profile - Profiling for ImutAVLTree. - void Profile(llvm::FoldingSetNodeID& ID) { - ID.AddInteger(ComputeDigest()); - } - //===----------------------------------------------------===// - // Internal Values. + // Internal values. //===----------------------------------------------------===// private: - ImutAVLTree* Left; - ImutAVLTree* Right; - unsigned Height : 28; - unsigned Mutable : 1; - unsigned CachedDigest : 1; - value_type Value; - uint32_t Digest; + Factory *factory; + ImutAVLTree *left; + ImutAVLTree *right; + ImutAVLTree *prev; + ImutAVLTree *next; + + unsigned height : 28; + unsigned IsMutable : 1; + unsigned IsDigestCached : 1; + unsigned IsCanonicalized : 1; + + value_type value; + uint32_t digest; + uint32_t refCount; //===----------------------------------------------------===// // Internal methods (node manipulation; used by Factory). @@ -237,10 +240,15 @@ private: private: /// ImutAVLTree - Internal constructor that is only called by /// ImutAVLFactory. - ImutAVLTree(ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, + ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, unsigned height) - : Left(l), Right(r), Height(height), Mutable(true), CachedDigest(false), - Value(v), Digest(0) {} + : factory(f), left(l), right(r), prev(0), next(0), height(height), + IsMutable(true), IsDigestCached(false), IsCanonicalized(0), + value(v), digest(0), refCount(0) + { + if (left) left->retain(); + if (right) right->retain(); + } /// isMutable - Returns true if the left and right subtree references /// (as well as height) can be changed. If this method returns false, @@ -248,11 +256,11 @@ private: /// object should always have this method return true. Further, if this /// method returns false for an instance of ImutAVLTree, all subtrees /// will also have this method return false. The converse is not true. - bool isMutable() const { return Mutable; } + bool isMutable() const { return IsMutable; } /// hasCachedDigest - Returns true if the digest for this tree is cached. /// This can only be true if the tree is immutable. - bool hasCachedDigest() const { return CachedDigest; } + bool hasCachedDigest() const { return IsDigestCached; } //===----------------------------------------------------===// // Mutating operations. A tree root can be manipulated as @@ -265,51 +273,32 @@ private: // immutable. //===----------------------------------------------------===// - /// MarkImmutable - Clears the mutable flag for a tree. After this happens, + /// markImmutable - Clears the mutable flag for a tree. After this happens, /// it is an error to call setLeft(), setRight(), and setHeight(). - void MarkImmutable() { + void markImmutable() { assert(isMutable() && "Mutable flag already removed."); - Mutable = false; + IsMutable = false; } - /// MarkedCachedDigest - Clears the NoCachedDigest flag for a tree. - void MarkedCachedDigest() { + /// markedCachedDigest - Clears the NoCachedDigest flag for a tree. + void markedCachedDigest() { assert(!hasCachedDigest() && "NoCachedDigest flag already removed."); - CachedDigest = true; - } - - /// setLeft - Changes the reference of the left subtree. Used internally - /// by ImutAVLFactory. - void setLeft(ImutAVLTree* NewLeft) { - assert(isMutable() && - "Only a mutable tree can have its left subtree changed."); - Left = NewLeft; - CachedDigest = false; - } - - /// setRight - Changes the reference of the right subtree. Used internally - /// by ImutAVLFactory. - void setRight(ImutAVLTree* NewRight) { - assert(isMutable() && - "Only a mutable tree can have its right subtree changed."); - - Right = NewRight; - CachedDigest = false; + IsDigestCached = true; } /// setHeight - Changes the height of the tree. Used internally by /// ImutAVLFactory. void setHeight(unsigned h) { assert(isMutable() && "Only a mutable tree can have its height changed."); - Height = h; + height = h; } static inline - uint32_t ComputeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) { + uint32_t computeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) { uint32_t digest = 0; if (L) - digest += L->ComputeDigest(); + digest += L->computeDigest(); // Compute digest of stored data. FoldingSetNodeID ID; @@ -317,22 +306,54 @@ private: digest += ID.ComputeHash(); if (R) - digest += R->ComputeDigest(); + digest += R->computeDigest(); return digest; } - inline uint32_t ComputeDigest() { + inline uint32_t computeDigest() { // Check the lowest bit to determine if digest has actually been // pre-computed. if (hasCachedDigest()) - return Digest; + return digest; - uint32_t X = ComputeDigest(getLeft(), getRight(), getValue()); - Digest = X; - MarkedCachedDigest(); + uint32_t X = computeDigest(getLeft(), getRight(), getValue()); + digest = X; + markedCachedDigest(); return X; } + + //===----------------------------------------------------===// + // Reference count operations. + //===----------------------------------------------------===// + +public: + void retain() { ++refCount; } + void release() { + assert(refCount > 0); + if (--refCount == 0) + destroy(); + } + void destroy() { + if (left) + left->release(); + if (right) + right->release(); + if (IsCanonicalized) { + if (next) + next->prev = prev; + + if (prev) + prev->next = next; + else + factory->Cache[computeDigest()] = next; + } + + // We need to clear the mutability bit in case we are + // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes(). + IsMutable = false; + factory->freeNodes.push_back(this); + } }; //===----------------------------------------------------------------------===// @@ -341,14 +362,17 @@ private: template <typename ImutInfo > class ImutAVLFactory { + friend class ImutAVLTree<ImutInfo>; typedef ImutAVLTree<ImutInfo> TreeTy; typedef typename TreeTy::value_type_ref value_type_ref; typedef typename TreeTy::key_type_ref key_type_ref; - typedef FoldingSet<TreeTy> CacheTy; + typedef DenseMap<unsigned, TreeTy*> CacheTy; CacheTy Cache; uintptr_t Allocator; + std::vector<TreeTy*> createdNodes; + std::vector<TreeTy*> freeNodes; bool ownsAllocator() const { return Allocator & 0x1 ? false : true; @@ -373,55 +397,56 @@ public: if (ownsAllocator()) delete &getAllocator(); } - TreeTy* Add(TreeTy* T, value_type_ref V) { - T = Add_internal(V,T); - MarkImmutable(T); + TreeTy* add(TreeTy* T, value_type_ref V) { + T = add_internal(V,T); + markImmutable(T); + recoverNodes(); return T; } - TreeTy* Remove(TreeTy* T, key_type_ref V) { - T = Remove_internal(V,T); - MarkImmutable(T); + TreeTy* remove(TreeTy* T, key_type_ref V) { + T = remove_internal(V,T); + markImmutable(T); + recoverNodes(); return T; } - TreeTy* GetEmptyTree() const { return NULL; } + TreeTy* getEmptyTree() const { return NULL; } +protected: + //===--------------------------------------------------===// // A bunch of quick helper functions used for reasoning // about the properties of trees and their children. // These have succinct names so that the balancing code // is as terse (and readable) as possible. //===--------------------------------------------------===// -protected: - bool isEmpty(TreeTy* T) const { return !T; } - unsigned Height(TreeTy* T) const { return T ? T->getHeight() : 0; } - TreeTy* Left(TreeTy* T) const { return T->getLeft(); } - TreeTy* Right(TreeTy* T) const { return T->getRight(); } - value_type_ref Value(TreeTy* T) const { return T->Value; } + bool isEmpty(TreeTy* T) const { return !T; } + unsigned getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; } + TreeTy* getLeft(TreeTy* T) const { return T->getLeft(); } + TreeTy* getRight(TreeTy* T) const { return T->getRight(); } + value_type_ref getValue(TreeTy* T) const { return T->value; } - unsigned IncrementHeight(TreeTy* L, TreeTy* R) const { - unsigned hl = Height(L); - unsigned hr = Height(R); + unsigned incrementHeight(TreeTy* L, TreeTy* R) const { + unsigned hl = getHeight(L); + unsigned hr = getHeight(R); return (hl > hr ? hl : hr) + 1; } - static bool CompareTreeWithSection(TreeTy* T, + static bool compareTreeWithSection(TreeTy* T, typename TreeTy::iterator& TI, typename TreeTy::iterator& TE) { - typename TreeTy::iterator I = T->begin(), E = T->end(); - - for ( ; I!=E ; ++I, ++TI) - if (TI == TE || !I->ElementEqual(*TI)) + for ( ; I!=E ; ++I, ++TI) { + if (TI == TE || !I->isElementEqual(*TI)) return false; - + } return true; } //===--------------------------------------------------===// - // "CreateNode" is used to generate new tree roots that link + // "createNode" is used to generate new tree roots that link // to other trees. The functon may also simply move links // in an existing root if that root is still marked mutable. // This is necessary because otherwise our balancing code @@ -430,181 +455,188 @@ protected: // returned to the caller. //===--------------------------------------------------===// - TreeTy* CreateNode(TreeTy* L, value_type_ref V, TreeTy* R) { + TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) { BumpPtrAllocator& A = getAllocator(); - TreeTy* T = (TreeTy*) A.Allocate<TreeTy>(); - new (T) TreeTy(L, R, V, IncrementHeight(L,R)); + TreeTy* T; + if (!freeNodes.empty()) { + T = freeNodes.back(); + freeNodes.pop_back(); + assert(T != L); + assert(T != R); + } + else { + T = (TreeTy*) A.Allocate<TreeTy>(); + } + new (T) TreeTy(this, L, R, V, incrementHeight(L,R)); + createdNodes.push_back(T); return T; } - TreeTy* CreateNode(TreeTy* L, TreeTy* OldTree, TreeTy* R) { - assert(!isEmpty(OldTree)); + TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) { + return createNode(newLeft, getValue(oldTree), newRight); + } - if (OldTree->isMutable()) { - OldTree->setLeft(L); - OldTree->setRight(R); - OldTree->setHeight(IncrementHeight(L, R)); - return OldTree; + void recoverNodes() { + for (unsigned i = 0, n = createdNodes.size(); i < n; ++i) { + TreeTy *N = createdNodes[i]; + if (N->isMutable() && N->refCount == 0) + N->destroy(); } - else - return CreateNode(L, Value(OldTree), R); + createdNodes.clear(); } - /// Balance - Used by Add_internal and Remove_internal to + /// balanceTree - Used by add_internal and remove_internal to /// balance a newly created tree. - TreeTy* Balance(TreeTy* L, value_type_ref V, TreeTy* R) { - - unsigned hl = Height(L); - unsigned hr = Height(R); + TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) { + unsigned hl = getHeight(L); + unsigned hr = getHeight(R); if (hl > hr + 2) { assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2"); - TreeTy* LL = Left(L); - TreeTy* LR = Right(L); + TreeTy *LL = getLeft(L); + TreeTy *LR = getRight(L); - if (Height(LL) >= Height(LR)) - return CreateNode(LL, L, CreateNode(LR,V,R)); + if (getHeight(LL) >= getHeight(LR)) + return createNode(LL, L, createNode(LR,V,R)); assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1"); - TreeTy* LRL = Left(LR); - TreeTy* LRR = Right(LR); + TreeTy *LRL = getLeft(LR); + TreeTy *LRR = getRight(LR); - return CreateNode(CreateNode(LL,L,LRL), LR, CreateNode(LRR,V,R)); + return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R)); } else if (hr > hl + 2) { assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2"); - TreeTy* RL = Left(R); - TreeTy* RR = Right(R); + TreeTy *RL = getLeft(R); + TreeTy *RR = getRight(R); - if (Height(RR) >= Height(RL)) - return CreateNode(CreateNode(L,V,RL), R, RR); + if (getHeight(RR) >= getHeight(RL)) + return createNode(createNode(L,V,RL), R, RR); assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1"); - TreeTy* RLL = Left(RL); - TreeTy* RLR = Right(RL); + TreeTy *RLL = getLeft(RL); + TreeTy *RLR = getRight(RL); - return CreateNode(CreateNode(L,V,RLL), RL, CreateNode(RLR,R,RR)); + return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR)); } else - return CreateNode(L,V,R); + return createNode(L,V,R); } - /// Add_internal - Creates a new tree that includes the specified + /// add_internal - Creates a new tree that includes the specified /// data and the data from the original tree. If the original tree /// already contained the data item, the original tree is returned. - TreeTy* Add_internal(value_type_ref V, TreeTy* T) { + TreeTy* add_internal(value_type_ref V, TreeTy* T) { if (isEmpty(T)) - return CreateNode(T, V, T); - + return createNode(T, V, T); assert(!T->isMutable()); key_type_ref K = ImutInfo::KeyOfValue(V); - key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T)); + key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T)); if (ImutInfo::isEqual(K,KCurrent)) - return CreateNode(Left(T), V, Right(T)); + return createNode(getLeft(T), V, getRight(T)); else if (ImutInfo::isLess(K,KCurrent)) - return Balance(Add_internal(V,Left(T)), Value(T), Right(T)); + return balanceTree(add_internal(V, getLeft(T)), getValue(T), getRight(T)); else - return Balance(Left(T), Value(T), Add_internal(V,Right(T))); + return balanceTree(getLeft(T), getValue(T), add_internal(V, getRight(T))); } - /// Remove_internal - Creates a new tree that includes all the data + /// remove_internal - Creates a new tree that includes all the data /// from the original tree except the specified data. If the /// specified data did not exist in the original tree, the original /// tree is returned. - TreeTy* Remove_internal(key_type_ref K, TreeTy* T) { + TreeTy* remove_internal(key_type_ref K, TreeTy* T) { if (isEmpty(T)) return T; assert(!T->isMutable()); - key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T)); + key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T)); - if (ImutInfo::isEqual(K,KCurrent)) - return CombineLeftRightTrees(Left(T),Right(T)); - else if (ImutInfo::isLess(K,KCurrent)) - return Balance(Remove_internal(K,Left(T)), Value(T), Right(T)); - else - return Balance(Left(T), Value(T), Remove_internal(K,Right(T))); + if (ImutInfo::isEqual(K,KCurrent)) { + return combineTrees(getLeft(T), getRight(T)); + } else if (ImutInfo::isLess(K,KCurrent)) { + return balanceTree(remove_internal(K, getLeft(T)), + getValue(T), getRight(T)); + } else { + return balanceTree(getLeft(T), getValue(T), + remove_internal(K, getRight(T))); + } } - TreeTy* CombineLeftRightTrees(TreeTy* L, TreeTy* R) { - if (isEmpty(L)) return R; - if (isEmpty(R)) return L; - + TreeTy* combineTrees(TreeTy* L, TreeTy* R) { + if (isEmpty(L)) + return R; + if (isEmpty(R)) + return L; TreeTy* OldNode; - TreeTy* NewRight = RemoveMinBinding(R,OldNode); - return Balance(L,Value(OldNode),NewRight); + TreeTy* newRight = removeMinBinding(R,OldNode); + return balanceTree(L, getValue(OldNode), newRight); } - TreeTy* RemoveMinBinding(TreeTy* T, TreeTy*& NodeRemoved) { + TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) { assert(!isEmpty(T)); - - if (isEmpty(Left(T))) { - NodeRemoved = T; - return Right(T); + if (isEmpty(getLeft(T))) { + Noderemoved = T; + return getRight(T); } - - return Balance(RemoveMinBinding(Left(T),NodeRemoved),Value(T),Right(T)); + return balanceTree(removeMinBinding(getLeft(T), Noderemoved), + getValue(T), getRight(T)); } - /// MarkImmutable - Clears the mutable bits of a root and all of its + /// markImmutable - Clears the mutable bits of a root and all of its /// descendants. - void MarkImmutable(TreeTy* T) { + void markImmutable(TreeTy* T) { if (!T || !T->isMutable()) return; - - T->MarkImmutable(); - MarkImmutable(Left(T)); - MarkImmutable(Right(T)); + T->markImmutable(); + markImmutable(getLeft(T)); + markImmutable(getRight(T)); } public: - TreeTy *GetCanonicalTree(TreeTy *TNew) { + TreeTy *getCanonicalTree(TreeTy *TNew) { if (!TNew) - return NULL; - - // Search the FoldingSet bucket for a Tree with the same digest. - FoldingSetNodeID ID; - unsigned digest = TNew->ComputeDigest(); - ID.AddInteger(digest); - unsigned hash = ID.ComputeHash(); - - typename CacheTy::bucket_iterator I = Cache.bucket_begin(hash); - typename CacheTy::bucket_iterator E = Cache.bucket_end(hash); - - for (; I != E; ++I) { - TreeTy *T = &*I; - - if (T->ComputeDigest() != digest) - continue; - - // We found a collision. Perform a comparison of Contents('T') - // with Contents('TNew') - typename TreeTy::iterator TI = T->begin(), TE = T->end(); - - if (!CompareTreeWithSection(TNew, TI, TE)) - continue; - - if (TI != TE) - continue; // T has more contents than TNew. - - // Trees did match! Return 'T'. - return T; + return 0; + + if (TNew->IsCanonicalized) + return TNew; + + // Search the hashtable for another tree with the same digest, and + // if find a collision compare those trees by their contents. + unsigned digest = TNew->computeDigest(); + TreeTy *&entry = Cache[digest]; + do { + if (!entry) + break; + for (TreeTy *T = entry ; T != 0; T = T->next) { + // Compare the Contents('T') with Contents('TNew') + typename TreeTy::iterator TI = T->begin(), TE = T->end(); + if (!compareTreeWithSection(TNew, TI, TE)) + continue; + if (TI != TE) + continue; // T has more contents than TNew. + // Trees did match! Return 'T'. + if (TNew->refCount == 0) + TNew->destroy(); + return T; + } + entry->prev = TNew; + TNew->next = entry; } + while (false); - // 'TNew' is the only tree of its kind. Return it. - Cache.InsertNode(TNew, (void*) &*Cache.bucket_end(hash)); + entry = TNew; + TNew->IsCanonicalized = true; return TNew; } }; - //===----------------------------------------------------------------------===// // Immutable AVL-Tree Iterators. //===----------------------------------------------------------------------===// @@ -635,19 +667,17 @@ public: } - bool AtEnd() const { return stack.empty(); } + bool atEnd() const { return stack.empty(); } - bool AtBeginning() const { + bool atBeginning() const { return stack.size() == 1 && getVisitState() == VisitedNone; } - void SkipToParent() { + void skipToParent() { assert(!stack.empty()); stack.pop_back(); - if (stack.empty()) return; - switch (getVisitState()) { case VisitedNone: stack.back() |= VisitedLeft; @@ -663,11 +693,9 @@ public: inline bool operator==(const _Self& x) const { if (stack.size() != x.stack.size()) return false; - for (unsigned i = 0 ; i < stack.size(); i++) if (stack[i] != x.stack[i]) return false; - return true; } @@ -675,70 +703,52 @@ public: _Self& operator++() { assert(!stack.empty()); - TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); assert(Current); - switch (getVisitState()) { case VisitedNone: if (TreeTy* L = Current->getLeft()) stack.push_back(reinterpret_cast<uintptr_t>(L)); else stack.back() |= VisitedLeft; - break; - case VisitedLeft: if (TreeTy* R = Current->getRight()) stack.push_back(reinterpret_cast<uintptr_t>(R)); else stack.back() |= VisitedRight; - break; - case VisitedRight: - SkipToParent(); + skipToParent(); break; - default: assert(false && "Unreachable."); } - return *this; } _Self& operator--() { assert(!stack.empty()); - TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); assert(Current); - switch (getVisitState()) { case VisitedNone: stack.pop_back(); break; - case VisitedLeft: stack.back() &= ~Flags; // Set state to "VisitedNone." - if (TreeTy* L = Current->getLeft()) stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight); - break; - case VisitedRight: stack.back() &= ~Flags; stack.back() |= VisitedLeft; - if (TreeTy* R = Current->getRight()) stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight); - break; - default: assert(false && "Unreachable."); } - return *this; } }; @@ -769,7 +779,7 @@ public: inline _Self& operator++() { do ++InternalItr; - while (!InternalItr.AtEnd() && + while (!InternalItr.atEnd() && InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); return *this; @@ -777,16 +787,16 @@ public: inline _Self& operator--() { do --InternalItr; - while (!InternalItr.AtBeginning() && + while (!InternalItr.atBeginning() && InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); return *this; } - inline void SkipSubTree() { - InternalItr.SkipToParent(); + inline void skipSubTree() { + InternalItr.skipToParent(); - while (!InternalItr.AtEnd() && + while (!InternalItr.atEnd() && InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft) ++InternalItr; } @@ -927,7 +937,23 @@ public: /// should use a Factory object to create sets instead of directly /// invoking the constructor, but there are cases where make this /// constructor public is useful. - explicit ImmutableSet(TreeTy* R) : Root(R) {} + explicit ImmutableSet(TreeTy* R) : Root(R) { + if (Root) { Root->retain(); } + } + ImmutableSet(const ImmutableSet &X) : Root(X.Root) { + if (Root) { Root->retain(); } + } + ImmutableSet &operator=(const ImmutableSet &X) { + if (Root != X.Root) { + if (X.Root) { X.Root->retain(); } + if (Root) { Root->release(); } + Root = X.Root; + } + return *this; + } + ~ImmutableSet() { + if (Root) { Root->release(); } + } class Factory { typename TreeTy::Factory F; @@ -940,33 +966,33 @@ public: Factory(BumpPtrAllocator& Alloc, bool canonicalize = true) : F(Alloc), Canonicalize(canonicalize) {} - /// GetEmptySet - Returns an immutable set that contains no elements. - ImmutableSet GetEmptySet() { - return ImmutableSet(F.GetEmptyTree()); + /// getEmptySet - Returns an immutable set that contains no elements. + ImmutableSet getEmptySet() { + return ImmutableSet(F.getEmptyTree()); } - /// Add - Creates a new immutable set that contains all of the values + /// add - Creates a new immutable set that contains all of the values /// of the original set with the addition of the specified value. If /// the original set already included the value, then the original set is /// returned and no memory is allocated. The time and space complexity /// of this operation is logarithmic in the size of the original set. /// The memory allocated to represent the set is released when the /// factory object that created the set is destroyed. - ImmutableSet Add(ImmutableSet Old, value_type_ref V) { - TreeTy *NewT = F.Add(Old.Root, V); - return ImmutableSet(Canonicalize ? F.GetCanonicalTree(NewT) : NewT); + ImmutableSet add(ImmutableSet Old, value_type_ref V) { + TreeTy *NewT = F.add(Old.Root, V); + return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT); } - /// Remove - Creates a new immutable set that contains all of the values + /// remove - Creates a new immutable set that contains all of the values /// of the original set with the exception of the specified value. If /// the original set did not contain the value, the original set is /// returned and no memory is allocated. The time and space complexity /// of this operation is logarithmic in the size of the original set. /// The memory allocated to represent the set is released when the /// factory object that created the set is destroyed. - ImmutableSet Remove(ImmutableSet Old, value_type_ref V) { - TreeTy *NewT = F.Remove(Old.Root, V); - return ImmutableSet(Canonicalize ? F.GetCanonicalTree(NewT) : NewT); + ImmutableSet remove(ImmutableSet Old, value_type_ref V) { + TreeTy *NewT = F.remove(Old.Root, V); + return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT); } BumpPtrAllocator& getAllocator() { return F.getAllocator(); } @@ -978,20 +1004,21 @@ public: friend class Factory; - /// contains - Returns true if the set contains the specified value. + /// Returns true if the set contains the specified value. bool contains(value_type_ref V) const { return Root ? Root->contains(V) : false; } - bool operator==(ImmutableSet RHS) const { + bool operator==(const ImmutableSet &RHS) const { return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; } - bool operator!=(ImmutableSet RHS) const { + bool operator!=(const ImmutableSet &RHS) const { return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; } TreeTy *getRoot() { + if (Root) { Root->retain(); } return Root; } @@ -1049,7 +1076,7 @@ public: // For testing. //===--------------------------------------------------===// - void verify() const { if (Root) Root->verify(); } + void validateTree() const { if (Root) Root->validateTree(); } }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/ADT/InMemoryStruct.h b/contrib/llvm/include/llvm/ADT/InMemoryStruct.h new file mode 100644 index 0000000..a560845 --- /dev/null +++ b/contrib/llvm/include/llvm/ADT/InMemoryStruct.h @@ -0,0 +1,77 @@ +//===- InMemoryStruct.h - Indirect Struct Access Smart Pointer --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INMEMORYSTRUCT_H +#define LLVM_ADT_INMEMORYSTRUCT_H + +#include <cassert> + +namespace llvm { + +/// \brief Helper object for abstracting access to an in-memory structure which +/// may require some kind of temporary storage. +/// +/// This class is designed to be used for accessing file data structures which +/// in the common case can be accessed from a direct pointer to a memory mapped +/// object, but which in some cases may require indirect access to a temporary +/// structure (which, for example, may have undergone endianness translation). +template<typename T> +class InMemoryStruct { + typedef T value_type; + typedef value_type &reference; + typedef value_type *pointer; + typedef const value_type &const_reference; + typedef const value_type *const_pointer; + + /// \brief The smart pointer target. + value_type *Target; + + /// \brief A temporary object which can be used as a target of the smart + /// pointer. + value_type Contents; + +private: + +public: + InMemoryStruct() : Target(0) {} + InMemoryStruct(reference Value) : Target(&Contents), Contents(Value) {} + InMemoryStruct(pointer Value) : Target(Value) {} + InMemoryStruct(const InMemoryStruct<T> &Value) { *this = Value; } + + void operator=(const InMemoryStruct<T> &Value) { + if (Value.Target != &Value.Contents) { + Target = Value.Target; + } else { + Target = &Contents; + Contents = Value.Contents; + } + } + + const_reference operator*() const { + assert(Target && "Cannot dereference null pointer"); + return *Target; + } + reference operator*() { + assert(Target && "Cannot dereference null pointer"); + return *Target; + } + + const_pointer operator->() const { + return Target; + } + pointer operator->() { + return Target; + } + + operator bool() const { return Target != 0; } +}; + +} + +#endif diff --git a/contrib/llvm/include/llvm/ADT/IndexedMap.h b/contrib/llvm/include/llvm/ADT/IndexedMap.h index 89f0dfa..87126ea 100644 --- a/contrib/llvm/include/llvm/ADT/IndexedMap.h +++ b/contrib/llvm/include/llvm/ADT/IndexedMap.h @@ -55,6 +55,14 @@ namespace llvm { return storage_[toIndex_(n)]; } + void reserve(typename StorageT::size_type s) { + storage_.reserve(s); + } + + void resize(typename StorageT::size_type s) { + storage_.resize(s, nullVal_); + } + void clear() { storage_.clear(); } @@ -62,7 +70,11 @@ namespace llvm { void grow(IndexT n) { unsigned NewSize = toIndex_(n) + 1; if (NewSize > storage_.size()) - storage_.resize(NewSize, nullVal_); + resize(NewSize); + } + + bool inBounds(IndexT n) const { + return toIndex_(n) < storage_.size(); } typename StorageT::size_type size() const { diff --git a/contrib/llvm/include/llvm/ADT/IntEqClasses.h b/contrib/llvm/include/llvm/ADT/IntEqClasses.h new file mode 100644 index 0000000..8e75c48 --- /dev/null +++ b/contrib/llvm/include/llvm/ADT/IntEqClasses.h @@ -0,0 +1,88 @@ +//===-- llvm/ADT/IntEqClasses.h - Equiv. Classes of Integers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Equivalence classes for small integers. This is a mapping of the integers +// 0 .. N-1 into M equivalence classes numbered 0 .. M-1. +// +// Initially each integer has its own equivalence class. Classes are joined by +// passing a representative member of each class to join(). +// +// Once the classes are built, compress() will number them 0 .. M-1 and prevent +// further changes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTEQCLASSES_H +#define LLVM_ADT_INTEQCLASSES_H + +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class IntEqClasses { + /// EC - When uncompressed, map each integer to a smaller member of its + /// equivalence class. The class leader is the smallest member and maps to + /// itself. + /// + /// When compressed, EC[i] is the equivalence class of i. + SmallVector<unsigned, 8> EC; + + /// NumClasses - The number of equivalence classes when compressed, or 0 when + /// uncompressed. + unsigned NumClasses; + +public: + /// IntEqClasses - Create an equivalence class mapping for 0 .. N-1. + IntEqClasses(unsigned N = 0) : NumClasses(0) { grow(N); } + + /// grow - Increase capacity to hold 0 .. N-1, putting new integers in unique + /// equivalence classes. + /// This requires an uncompressed map. + void grow(unsigned N); + + /// clear - Clear all classes so that grow() will assign a unique class to + /// every integer. + void clear() { + EC.clear(); + NumClasses = 0; + } + + /// join - Join the equivalence classes of a and b. After joining classes, + /// findLeader(a) == findLeader(b). + /// This requires an uncompressed map. + void join(unsigned a, unsigned b); + + /// findLeader - Compute the leader of a's equivalence class. This is the + /// smallest member of the class. + /// This requires an uncompressed map. + unsigned findLeader(unsigned a) const; + + /// compress - Compress equivalence classes by numbering them 0 .. M. + /// This makes the equivalence class map immutable. + void compress(); + + /// getNumClasses - Return the number of equivalence classes after compress() + /// was called. + unsigned getNumClasses() const { return NumClasses; } + + /// operator[] - Return a's equivalence class number, 0 .. getNumClasses()-1. + /// This requires a compressed map. + unsigned operator[](unsigned a) const { + assert(NumClasses && "operator[] called before compress()"); + return EC[a]; + } + + /// uncompress - Change back to the uncompressed representation that allows + /// editing. + void uncompress(); +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/ADT/IntervalMap.h b/contrib/llvm/include/llvm/ADT/IntervalMap.h new file mode 100644 index 0000000..79f24d3 --- /dev/null +++ b/contrib/llvm/include/llvm/ADT/IntervalMap.h @@ -0,0 +1,2139 @@ +//===- llvm/ADT/IntervalMap.h - A sorted interval map -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a coalescing interval map for small objects. +// +// KeyT objects are mapped to ValT objects. Intervals of keys that map to the +// same value are represented in a compressed form. +// +// Iterators provide ordered access to the compressed intervals rather than the +// individual keys, and insert and erase operations use key intervals as well. +// +// Like SmallVector, IntervalMap will store the first N intervals in the map +// object itself without any allocations. When space is exhausted it switches to +// a B+-tree representation with very small overhead for small key and value +// objects. +// +// A Traits class specifies how keys are compared. It also allows IntervalMap to +// work with both closed and half-open intervals. +// +// Keys and values are not stored next to each other in a std::pair, so we don't +// provide such a value_type. Dereferencing iterators only returns the mapped +// value. The interval bounds are accessible through the start() and stop() +// iterator methods. +// +// IntervalMap is optimized for small key and value objects, 4 or 8 bytes each +// is the optimal size. For large objects use std::map instead. +// +//===----------------------------------------------------------------------===// +// +// Synopsis: +// +// template <typename KeyT, typename ValT, unsigned N, typename Traits> +// class IntervalMap { +// public: +// typedef KeyT key_type; +// typedef ValT mapped_type; +// typedef RecyclingAllocator<...> Allocator; +// class iterator; +// class const_iterator; +// +// explicit IntervalMap(Allocator&); +// ~IntervalMap(): +// +// bool empty() const; +// KeyT start() const; +// KeyT stop() const; +// ValT lookup(KeyT x, Value NotFound = Value()) const; +// +// const_iterator begin() const; +// const_iterator end() const; +// iterator begin(); +// iterator end(); +// const_iterator find(KeyT x) const; +// iterator find(KeyT x); +// +// void insert(KeyT a, KeyT b, ValT y); +// void clear(); +// }; +// +// template <typename KeyT, typename ValT, unsigned N, typename Traits> +// class IntervalMap::const_iterator : +// public std::iterator<std::bidirectional_iterator_tag, ValT> { +// public: +// bool operator==(const const_iterator &) const; +// bool operator!=(const const_iterator &) const; +// bool valid() const; +// +// const KeyT &start() const; +// const KeyT &stop() const; +// const ValT &value() const; +// const ValT &operator*() const; +// const ValT *operator->() const; +// +// const_iterator &operator++(); +// const_iterator &operator++(int); +// const_iterator &operator--(); +// const_iterator &operator--(int); +// void goToBegin(); +// void goToEnd(); +// void find(KeyT x); +// void advanceTo(KeyT x); +// }; +// +// template <typename KeyT, typename ValT, unsigned N, typename Traits> +// class IntervalMap::iterator : public const_iterator { +// public: +// void insert(KeyT a, KeyT b, Value y); +// void erase(); +// }; +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTERVALMAP_H +#define LLVM_ADT_INTERVALMAP_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/RecyclingAllocator.h" +#include <iterator> + +namespace llvm { + + +//===----------------------------------------------------------------------===// +//--- Key traits ---// +//===----------------------------------------------------------------------===// +// +// The IntervalMap works with closed or half-open intervals. +// Adjacent intervals that map to the same value are coalesced. +// +// The IntervalMapInfo traits class is used to determine if a key is contained +// in an interval, and if two intervals are adjacent so they can be coalesced. +// The provided implementation works for closed integer intervals, other keys +// probably need a specialized version. +// +// The point x is contained in [a;b] when !startLess(x, a) && !stopLess(b, x). +// +// It is assumed that (a;b] half-open intervals are not used, only [a;b) is +// allowed. This is so that stopLess(a, b) can be used to determine if two +// intervals overlap. +// +//===----------------------------------------------------------------------===// + +template <typename T> +struct IntervalMapInfo { + + /// startLess - Return true if x is not in [a;b]. + /// This is x < a both for closed intervals and for [a;b) half-open intervals. + static inline bool startLess(const T &x, const T &a) { + return x < a; + } + + /// stopLess - Return true if x is not in [a;b]. + /// This is b < x for a closed interval, b <= x for [a;b) half-open intervals. + static inline bool stopLess(const T &b, const T &x) { + return b < x; + } + + /// adjacent - Return true when the intervals [x;a] and [b;y] can coalesce. + /// This is a+1 == b for closed intervals, a == b for half-open intervals. + static inline bool adjacent(const T &a, const T &b) { + return a+1 == b; + } + +}; + +/// IntervalMapImpl - Namespace used for IntervalMap implementation details. +/// It should be considered private to the implementation. +namespace IntervalMapImpl { + +// Forward declarations. +template <typename, typename, unsigned, typename> class LeafNode; +template <typename, typename, unsigned, typename> class BranchNode; + +typedef std::pair<unsigned,unsigned> IdxPair; + + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::NodeBase ---// +//===----------------------------------------------------------------------===// +// +// Both leaf and branch nodes store vectors of pairs. +// Leaves store ((KeyT, KeyT), ValT) pairs, branches use (NodeRef, KeyT). +// +// Keys and values are stored in separate arrays to avoid padding caused by +// different object alignments. This also helps improve locality of reference +// when searching the keys. +// +// The nodes don't know how many elements they contain - that information is +// stored elsewhere. Omitting the size field prevents padding and allows a node +// to fill the allocated cache lines completely. +// +// These are typical key and value sizes, the node branching factor (N), and +// wasted space when nodes are sized to fit in three cache lines (192 bytes): +// +// T1 T2 N Waste Used by +// 4 4 24 0 Branch<4> (32-bit pointers) +// 8 4 16 0 Leaf<4,4>, Branch<4> +// 8 8 12 0 Leaf<4,8>, Branch<8> +// 16 4 9 12 Leaf<8,4> +// 16 8 8 0 Leaf<8,8> +// +//===----------------------------------------------------------------------===// + +template <typename T1, typename T2, unsigned N> +class NodeBase { +public: + enum { Capacity = N }; + + T1 first[N]; + T2 second[N]; + + /// copy - Copy elements from another node. + /// @param Other Node elements are copied from. + /// @param i Beginning of the source range in other. + /// @param j Beginning of the destination range in this. + /// @param Count Number of elements to copy. + template <unsigned M> + void copy(const NodeBase<T1, T2, M> &Other, unsigned i, + unsigned j, unsigned Count) { + assert(i + Count <= M && "Invalid source range"); + assert(j + Count <= N && "Invalid dest range"); + for (unsigned e = i + Count; i != e; ++i, ++j) { + first[j] = Other.first[i]; + second[j] = Other.second[i]; + } + } + + /// moveLeft - Move elements to the left. + /// @param i Beginning of the source range. + /// @param j Beginning of the destination range. + /// @param Count Number of elements to copy. + void moveLeft(unsigned i, unsigned j, unsigned Count) { + assert(j <= i && "Use moveRight shift elements right"); + copy(*this, i, j, Count); + } + + /// moveRight - Move elements to the right. + /// @param i Beginning of the source range. + /// @param j Beginning of the destination range. + /// @param Count Number of elements to copy. + void moveRight(unsigned i, unsigned j, unsigned Count) { + assert(i <= j && "Use moveLeft shift elements left"); + assert(j + Count <= N && "Invalid range"); + while (Count--) { + first[j + Count] = first[i + Count]; + second[j + Count] = second[i + Count]; + } + } + + /// erase - Erase elements [i;j). + /// @param i Beginning of the range to erase. + /// @param j End of the range. (Exclusive). + /// @param Size Number of elements in node. + void erase(unsigned i, unsigned j, unsigned Size) { + moveLeft(j, i, Size - j); + } + + /// erase - Erase element at i. + /// @param i Index of element to erase. + /// @param Size Number of elements in node. + void erase(unsigned i, unsigned Size) { + erase(i, i+1, Size); + } + + /// shift - Shift elements [i;size) 1 position to the right. + /// @param i Beginning of the range to move. + /// @param Size Number of elements in node. + void shift(unsigned i, unsigned Size) { + moveRight(i, i + 1, Size - i); + } + + /// transferToLeftSib - Transfer elements to a left sibling node. + /// @param Size Number of elements in this. + /// @param Sib Left sibling node. + /// @param SSize Number of elements in sib. + /// @param Count Number of elements to transfer. + void transferToLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize, + unsigned Count) { + Sib.copy(*this, 0, SSize, Count); + erase(0, Count, Size); + } + + /// transferToRightSib - Transfer elements to a right sibling node. + /// @param Size Number of elements in this. + /// @param Sib Right sibling node. + /// @param SSize Number of elements in sib. + /// @param Count Number of elements to transfer. + void transferToRightSib(unsigned Size, NodeBase &Sib, unsigned SSize, + unsigned Count) { + Sib.moveRight(0, Count, SSize); + Sib.copy(*this, Size-Count, 0, Count); + } + + /// adjustFromLeftSib - Adjust the number if elements in this node by moving + /// elements to or from a left sibling node. + /// @param Size Number of elements in this. + /// @param Sib Right sibling node. + /// @param SSize Number of elements in sib. + /// @param Add The number of elements to add to this node, possibly < 0. + /// @return Number of elements added to this node, possibly negative. + int adjustFromLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize, int Add) { + if (Add > 0) { + // We want to grow, copy from sib. + unsigned Count = std::min(std::min(unsigned(Add), SSize), N - Size); + Sib.transferToRightSib(SSize, *this, Size, Count); + return Count; + } else { + // We want to shrink, copy to sib. + unsigned Count = std::min(std::min(unsigned(-Add), Size), N - SSize); + transferToLeftSib(Size, Sib, SSize, Count); + return -Count; + } + } +}; + +/// IntervalMapImpl::adjustSiblingSizes - Move elements between sibling nodes. +/// @param Node Array of pointers to sibling nodes. +/// @param Nodes Number of nodes. +/// @param CurSize Array of current node sizes, will be overwritten. +/// @param NewSize Array of desired node sizes. +template <typename NodeT> +void adjustSiblingSizes(NodeT *Node[], unsigned Nodes, + unsigned CurSize[], const unsigned NewSize[]) { + // Move elements right. + for (int n = Nodes - 1; n; --n) { + if (CurSize[n] == NewSize[n]) + continue; + for (int m = n - 1; m != -1; --m) { + int d = Node[n]->adjustFromLeftSib(CurSize[n], *Node[m], CurSize[m], + NewSize[n] - CurSize[n]); + CurSize[m] -= d; + CurSize[n] += d; + // Keep going if the current node was exhausted. + if (CurSize[n] >= NewSize[n]) + break; + } + } + + if (Nodes == 0) + return; + + // Move elements left. + for (unsigned n = 0; n != Nodes - 1; ++n) { + if (CurSize[n] == NewSize[n]) + continue; + for (unsigned m = n + 1; m != Nodes; ++m) { + int d = Node[m]->adjustFromLeftSib(CurSize[m], *Node[n], CurSize[n], + CurSize[n] - NewSize[n]); + CurSize[m] += d; + CurSize[n] -= d; + // Keep going if the current node was exhausted. + if (CurSize[n] >= NewSize[n]) + break; + } + } + +#ifndef NDEBUG + for (unsigned n = 0; n != Nodes; n++) + assert(CurSize[n] == NewSize[n] && "Insufficient element shuffle"); +#endif +} + +/// IntervalMapImpl::distribute - Compute a new distribution of node elements +/// after an overflow or underflow. Reserve space for a new element at Position, +/// and compute the node that will hold Position after redistributing node +/// elements. +/// +/// It is required that +/// +/// Elements == sum(CurSize), and +/// Elements + Grow <= Nodes * Capacity. +/// +/// NewSize[] will be filled in such that: +/// +/// sum(NewSize) == Elements, and +/// NewSize[i] <= Capacity. +/// +/// The returned index is the node where Position will go, so: +/// +/// sum(NewSize[0..idx-1]) <= Position +/// sum(NewSize[0..idx]) >= Position +/// +/// The last equality, sum(NewSize[0..idx]) == Position, can only happen when +/// Grow is set and NewSize[idx] == Capacity-1. The index points to the node +/// before the one holding the Position'th element where there is room for an +/// insertion. +/// +/// @param Nodes The number of nodes. +/// @param Elements Total elements in all nodes. +/// @param Capacity The capacity of each node. +/// @param CurSize Array[Nodes] of current node sizes, or NULL. +/// @param NewSize Array[Nodes] to receive the new node sizes. +/// @param Position Insert position. +/// @param Grow Reserve space for a new element at Position. +/// @return (node, offset) for Position. +IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity, + const unsigned *CurSize, unsigned NewSize[], + unsigned Position, bool Grow); + + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::NodeSizer ---// +//===----------------------------------------------------------------------===// +// +// Compute node sizes from key and value types. +// +// The branching factors are chosen to make nodes fit in three cache lines. +// This may not be possible if keys or values are very large. Such large objects +// are handled correctly, but a std::map would probably give better performance. +// +//===----------------------------------------------------------------------===// + +enum { + // Cache line size. Most architectures have 32 or 64 byte cache lines. + // We use 64 bytes here because it provides good branching factors. + Log2CacheLine = 6, + CacheLineBytes = 1 << Log2CacheLine, + DesiredNodeBytes = 3 * CacheLineBytes +}; + +template <typename KeyT, typename ValT> +struct NodeSizer { + enum { + // Compute the leaf node branching factor that makes a node fit in three + // cache lines. The branching factor must be at least 3, or some B+-tree + // balancing algorithms won't work. + // LeafSize can't be larger than CacheLineBytes. This is required by the + // PointerIntPair used by NodeRef. + DesiredLeafSize = DesiredNodeBytes / + static_cast<unsigned>(2*sizeof(KeyT)+sizeof(ValT)), + MinLeafSize = 3, + LeafSize = DesiredLeafSize > MinLeafSize ? DesiredLeafSize : MinLeafSize + }; + + typedef NodeBase<std::pair<KeyT, KeyT>, ValT, LeafSize> LeafBase; + + enum { + // Now that we have the leaf branching factor, compute the actual allocation + // unit size by rounding up to a whole number of cache lines. + AllocBytes = (sizeof(LeafBase) + CacheLineBytes-1) & ~(CacheLineBytes-1), + + // Determine the branching factor for branch nodes. + BranchSize = AllocBytes / + static_cast<unsigned>(sizeof(KeyT) + sizeof(void*)) + }; + + /// Allocator - The recycling allocator used for both branch and leaf nodes. + /// This typedef is very likely to be identical for all IntervalMaps with + /// reasonably sized entries, so the same allocator can be shared among + /// different kinds of maps. + typedef RecyclingAllocator<BumpPtrAllocator, char, + AllocBytes, CacheLineBytes> Allocator; + +}; + + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::NodeRef ---// +//===----------------------------------------------------------------------===// +// +// B+-tree nodes can be leaves or branches, so we need a polymorphic node +// pointer that can point to both kinds. +// +// All nodes are cache line aligned and the low 6 bits of a node pointer are +// always 0. These bits are used to store the number of elements in the +// referenced node. Besides saving space, placing node sizes in the parents +// allow tree balancing algorithms to run without faulting cache lines for nodes +// that may not need to be modified. +// +// A NodeRef doesn't know whether it references a leaf node or a branch node. +// It is the responsibility of the caller to use the correct types. +// +// Nodes are never supposed to be empty, and it is invalid to store a node size +// of 0 in a NodeRef. The valid range of sizes is 1-64. +// +//===----------------------------------------------------------------------===// + +class NodeRef { + struct CacheAlignedPointerTraits { + static inline void *getAsVoidPointer(void *P) { return P; } + static inline void *getFromVoidPointer(void *P) { return P; } + enum { NumLowBitsAvailable = Log2CacheLine }; + }; + PointerIntPair<void*, Log2CacheLine, unsigned, CacheAlignedPointerTraits> pip; + +public: + /// NodeRef - Create a null ref. + NodeRef() {} + + /// operator bool - Detect a null ref. + operator bool() const { return pip.getOpaqueValue(); } + + /// NodeRef - Create a reference to the node p with n elements. + template <typename NodeT> + NodeRef(NodeT *p, unsigned n) : pip(p, n - 1) { + assert(n <= NodeT::Capacity && "Size too big for node"); + } + + /// size - Return the number of elements in the referenced node. + unsigned size() const { return pip.getInt() + 1; } + + /// setSize - Update the node size. + void setSize(unsigned n) { pip.setInt(n - 1); } + + /// subtree - Access the i'th subtree reference in a branch node. + /// This depends on branch nodes storing the NodeRef array as their first + /// member. + NodeRef &subtree(unsigned i) const { + return reinterpret_cast<NodeRef*>(pip.getPointer())[i]; + } + + /// get - Dereference as a NodeT reference. + template <typename NodeT> + NodeT &get() const { + return *reinterpret_cast<NodeT*>(pip.getPointer()); + } + + bool operator==(const NodeRef &RHS) const { + if (pip == RHS.pip) + return true; + assert(pip.getPointer() != RHS.pip.getPointer() && "Inconsistent NodeRefs"); + return false; + } + + bool operator!=(const NodeRef &RHS) const { + return !operator==(RHS); + } +}; + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::LeafNode ---// +//===----------------------------------------------------------------------===// +// +// Leaf nodes store up to N disjoint intervals with corresponding values. +// +// The intervals are kept sorted and fully coalesced so there are no adjacent +// intervals mapping to the same value. +// +// These constraints are always satisfied: +// +// - Traits::stopLess(start(i), stop(i)) - Non-empty, sane intervals. +// +// - Traits::stopLess(stop(i), start(i + 1) - Sorted. +// +// - value(i) != value(i + 1) || !Traits::adjacent(stop(i), start(i + 1)) +// - Fully coalesced. +// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +class LeafNode : public NodeBase<std::pair<KeyT, KeyT>, ValT, N> { +public: + const KeyT &start(unsigned i) const { return this->first[i].first; } + const KeyT &stop(unsigned i) const { return this->first[i].second; } + const ValT &value(unsigned i) const { return this->second[i]; } + + KeyT &start(unsigned i) { return this->first[i].first; } + KeyT &stop(unsigned i) { return this->first[i].second; } + ValT &value(unsigned i) { return this->second[i]; } + + /// findFrom - Find the first interval after i that may contain x. + /// @param i Starting index for the search. + /// @param Size Number of elements in node. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i].stop, x), or size. + /// This is the first interval that can possibly contain x. + unsigned findFrom(unsigned i, unsigned Size, KeyT x) const { + assert(i <= Size && Size <= N && "Bad indices"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index is past the needed point"); + while (i != Size && Traits::stopLess(stop(i), x)) ++i; + return i; + } + + /// safeFind - Find an interval that is known to exist. This is the same as + /// findFrom except is it assumed that x is at least within range of the last + /// interval. + /// @param i Starting index for the search. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i].stop, x), never size. + /// This is the first interval that can possibly contain x. + unsigned safeFind(unsigned i, KeyT x) const { + assert(i < N && "Bad index"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index is past the needed point"); + while (Traits::stopLess(stop(i), x)) ++i; + assert(i < N && "Unsafe intervals"); + return i; + } + + /// safeLookup - Lookup mapped value for a safe key. + /// It is assumed that x is within range of the last entry. + /// @param x Key to search for. + /// @param NotFound Value to return if x is not in any interval. + /// @return The mapped value at x or NotFound. + ValT safeLookup(KeyT x, ValT NotFound) const { + unsigned i = safeFind(0, x); + return Traits::startLess(x, start(i)) ? NotFound : value(i); + } + + unsigned insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y); +}; + +/// insertFrom - Add mapping of [a;b] to y if possible, coalescing as much as +/// possible. This may cause the node to grow by 1, or it may cause the node +/// to shrink because of coalescing. +/// @param i Starting index = insertFrom(0, size, a) +/// @param Size Number of elements in node. +/// @param a Interval start. +/// @param b Interval stop. +/// @param y Value be mapped. +/// @return (insert position, new size), or (i, Capacity+1) on overflow. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +unsigned LeafNode<KeyT, ValT, N, Traits>:: +insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y) { + unsigned i = Pos; + assert(i <= Size && Size <= N && "Invalid index"); + assert(!Traits::stopLess(b, a) && "Invalid interval"); + + // Verify the findFrom invariant. + assert((i == 0 || Traits::stopLess(stop(i - 1), a))); + assert((i == Size || !Traits::stopLess(stop(i), a))); + assert((i == Size || Traits::stopLess(b, start(i))) && "Overlapping insert"); + + // Coalesce with previous interval. + if (i && value(i - 1) == y && Traits::adjacent(stop(i - 1), a)) { + Pos = i - 1; + // Also coalesce with next interval? + if (i != Size && value(i) == y && Traits::adjacent(b, start(i))) { + stop(i - 1) = stop(i); + this->erase(i, Size); + return Size - 1; + } + stop(i - 1) = b; + return Size; + } + + // Detect overflow. + if (i == N) + return N + 1; + + // Add new interval at end. + if (i == Size) { + start(i) = a; + stop(i) = b; + value(i) = y; + return Size + 1; + } + + // Try to coalesce with following interval. + if (value(i) == y && Traits::adjacent(b, start(i))) { + start(i) = a; + return Size; + } + + // We must insert before i. Detect overflow. + if (Size == N) + return N + 1; + + // Insert before i. + this->shift(i, Size); + start(i) = a; + stop(i) = b; + value(i) = y; + return Size + 1; +} + + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::BranchNode ---// +//===----------------------------------------------------------------------===// +// +// A branch node stores references to 1--N subtrees all of the same height. +// +// The key array in a branch node holds the rightmost stop key of each subtree. +// It is redundant to store the last stop key since it can be found in the +// parent node, but doing so makes tree balancing a lot simpler. +// +// It is unusual for a branch node to only have one subtree, but it can happen +// in the root node if it is smaller than the normal nodes. +// +// When all of the leaf nodes from all the subtrees are concatenated, they must +// satisfy the same constraints as a single leaf node. They must be sorted, +// sane, and fully coalesced. +// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +class BranchNode : public NodeBase<NodeRef, KeyT, N> { +public: + const KeyT &stop(unsigned i) const { return this->second[i]; } + const NodeRef &subtree(unsigned i) const { return this->first[i]; } + + KeyT &stop(unsigned i) { return this->second[i]; } + NodeRef &subtree(unsigned i) { return this->first[i]; } + + /// findFrom - Find the first subtree after i that may contain x. + /// @param i Starting index for the search. + /// @param Size Number of elements in node. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i], x), or size. + /// This is the first subtree that can possibly contain x. + unsigned findFrom(unsigned i, unsigned Size, KeyT x) const { + assert(i <= Size && Size <= N && "Bad indices"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index to findFrom is past the needed point"); + while (i != Size && Traits::stopLess(stop(i), x)) ++i; + return i; + } + + /// safeFind - Find a subtree that is known to exist. This is the same as + /// findFrom except is it assumed that x is in range. + /// @param i Starting index for the search. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i], x), never size. + /// This is the first subtree that can possibly contain x. + unsigned safeFind(unsigned i, KeyT x) const { + assert(i < N && "Bad index"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index is past the needed point"); + while (Traits::stopLess(stop(i), x)) ++i; + assert(i < N && "Unsafe intervals"); + return i; + } + + /// safeLookup - Get the subtree containing x, Assuming that x is in range. + /// @param x Key to search for. + /// @return Subtree containing x + NodeRef safeLookup(KeyT x) const { + return subtree(safeFind(0, x)); + } + + /// insert - Insert a new (subtree, stop) pair. + /// @param i Insert position, following entries will be shifted. + /// @param Size Number of elements in node. + /// @param Node Subtree to insert. + /// @param Stop Last key in subtree. + void insert(unsigned i, unsigned Size, NodeRef Node, KeyT Stop) { + assert(Size < N && "branch node overflow"); + assert(i <= Size && "Bad insert position"); + this->shift(i, Size); + subtree(i) = Node; + stop(i) = Stop; + } +}; + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::Path ---// +//===----------------------------------------------------------------------===// +// +// A Path is used by iterators to represent a position in a B+-tree, and the +// path to get there from the root. +// +// The Path class also constains the tree navigation code that doesn't have to +// be templatized. +// +//===----------------------------------------------------------------------===// + +class Path { + /// Entry - Each step in the path is a node pointer and an offset into that + /// node. + struct Entry { + void *node; + unsigned size; + unsigned offset; + + Entry(void *Node, unsigned Size, unsigned Offset) + : node(Node), size(Size), offset(Offset) {} + + Entry(NodeRef Node, unsigned Offset) + : node(&Node.subtree(0)), size(Node.size()), offset(Offset) {} + + NodeRef &subtree(unsigned i) const { + return reinterpret_cast<NodeRef*>(node)[i]; + } + }; + + /// path - The path entries, path[0] is the root node, path.back() is a leaf. + SmallVector<Entry, 4> path; + +public: + // Node accessors. + template <typename NodeT> NodeT &node(unsigned Level) const { + return *reinterpret_cast<NodeT*>(path[Level].node); + } + unsigned size(unsigned Level) const { return path[Level].size; } + unsigned offset(unsigned Level) const { return path[Level].offset; } + unsigned &offset(unsigned Level) { return path[Level].offset; } + + // Leaf accessors. + template <typename NodeT> NodeT &leaf() const { + return *reinterpret_cast<NodeT*>(path.back().node); + } + unsigned leafSize() const { return path.back().size; } + unsigned leafOffset() const { return path.back().offset; } + unsigned &leafOffset() { return path.back().offset; } + + /// valid - Return true if path is at a valid node, not at end(). + bool valid() const { + return !path.empty() && path.front().offset < path.front().size; + } + + /// height - Return the height of the tree corresponding to this path. + /// This matches map->height in a full path. + unsigned height() const { return path.size() - 1; } + + /// subtree - Get the subtree referenced from Level. When the path is + /// consistent, node(Level + 1) == subtree(Level). + /// @param Level 0..height-1. The leaves have no subtrees. + NodeRef &subtree(unsigned Level) const { + return path[Level].subtree(path[Level].offset); + } + + /// reset - Reset cached information about node(Level) from subtree(Level -1). + /// @param Level 1..height. THe node to update after parent node changed. + void reset(unsigned Level) { + path[Level] = Entry(subtree(Level - 1), offset(Level)); + } + + /// push - Add entry to path. + /// @param Node Node to add, should be subtree(path.size()-1). + /// @param Offset Offset into Node. + void push(NodeRef Node, unsigned Offset) { + path.push_back(Entry(Node, Offset)); + } + + /// pop - Remove the last path entry. + void pop() { + path.pop_back(); + } + + /// setSize - Set the size of a node both in the path and in the tree. + /// @param Level 0..height. Note that setting the root size won't change + /// map->rootSize. + /// @param Size New node size. + void setSize(unsigned Level, unsigned Size) { + path[Level].size = Size; + if (Level) + subtree(Level - 1).setSize(Size); + } + + /// setRoot - Clear the path and set a new root node. + /// @param Node New root node. + /// @param Size New root size. + /// @param Offset Offset into root node. + void setRoot(void *Node, unsigned Size, unsigned Offset) { + path.clear(); + path.push_back(Entry(Node, Size, Offset)); + } + + /// replaceRoot - Replace the current root node with two new entries after the + /// tree height has increased. + /// @param Root The new root node. + /// @param Size Number of entries in the new root. + /// @param Offsets Offsets into the root and first branch nodes. + void replaceRoot(void *Root, unsigned Size, IdxPair Offsets); + + /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef. + /// @param Level Get the sibling to node(Level). + /// @return Left sibling, or NodeRef(). + NodeRef getLeftSibling(unsigned Level) const; + + /// moveLeft - Move path to the left sibling at Level. Leave nodes below Level + /// unaltered. + /// @param Level Move node(Level). + void moveLeft(unsigned Level); + + /// fillLeft - Grow path to Height by taking leftmost branches. + /// @param Height The target height. + void fillLeft(unsigned Height) { + while (height() < Height) + push(subtree(height()), 0); + } + + /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef. + /// @param Level Get the sinbling to node(Level). + /// @return Left sibling, or NodeRef(). + NodeRef getRightSibling(unsigned Level) const; + + /// moveRight - Move path to the left sibling at Level. Leave nodes below + /// Level unaltered. + /// @param Level Move node(Level). + void moveRight(unsigned Level); + + /// atBegin - Return true if path is at begin(). + bool atBegin() const { + for (unsigned i = 0, e = path.size(); i != e; ++i) + if (path[i].offset != 0) + return false; + return true; + } + + /// atLastEntry - Return true if the path is at the last entry of the node at + /// Level. + /// @param Level Node to examine. + bool atLastEntry(unsigned Level) const { + return path[Level].offset == path[Level].size - 1; + } + + /// legalizeForInsert - Prepare the path for an insertion at Level. When the + /// path is at end(), node(Level) may not be a legal node. legalizeForInsert + /// ensures that node(Level) is real by moving back to the last node at Level, + /// and setting offset(Level) to size(Level) if required. + /// @param Level The level where an insertion is about to take place. + void legalizeForInsert(unsigned Level) { + if (valid()) + return; + moveLeft(Level); + ++path[Level].offset; + } +}; + +} // namespace IntervalMapImpl + + +//===----------------------------------------------------------------------===// +//--- IntervalMap ----// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, + unsigned N = IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize, + typename Traits = IntervalMapInfo<KeyT> > +class IntervalMap { + typedef IntervalMapImpl::NodeSizer<KeyT, ValT> Sizer; + typedef IntervalMapImpl::LeafNode<KeyT, ValT, Sizer::LeafSize, Traits> Leaf; + typedef IntervalMapImpl::BranchNode<KeyT, ValT, Sizer::BranchSize, Traits> + Branch; + typedef IntervalMapImpl::LeafNode<KeyT, ValT, N, Traits> RootLeaf; + typedef IntervalMapImpl::IdxPair IdxPair; + + // The RootLeaf capacity is given as a template parameter. We must compute the + // corresponding RootBranch capacity. + enum { + DesiredRootBranchCap = (sizeof(RootLeaf) - sizeof(KeyT)) / + (sizeof(KeyT) + sizeof(IntervalMapImpl::NodeRef)), + RootBranchCap = DesiredRootBranchCap ? DesiredRootBranchCap : 1 + }; + + typedef IntervalMapImpl::BranchNode<KeyT, ValT, RootBranchCap, Traits> + RootBranch; + + // When branched, we store a global start key as well as the branch node. + struct RootBranchData { + KeyT start; + RootBranch node; + }; + + enum { + RootDataSize = sizeof(RootBranchData) > sizeof(RootLeaf) ? + sizeof(RootBranchData) : sizeof(RootLeaf) + }; + +public: + typedef typename Sizer::Allocator Allocator; + typedef KeyT KeyType; + typedef ValT ValueType; + typedef Traits KeyTraits; + +private: + // The root data is either a RootLeaf or a RootBranchData instance. + // We can't put them in a union since C++03 doesn't allow non-trivial + // constructors in unions. + // Instead, we use a char array with pointer alignment. The alignment is + // ensured by the allocator member in the class, but still verified in the + // constructor. We don't support keys or values that are more aligned than a + // pointer. + char data[RootDataSize]; + + // Tree height. + // 0: Leaves in root. + // 1: Root points to leaf. + // 2: root->branch->leaf ... + unsigned height; + + // Number of entries in the root node. + unsigned rootSize; + + // Allocator used for creating external nodes. + Allocator &allocator; + + /// dataAs - Represent data as a node type without breaking aliasing rules. + template <typename T> + T &dataAs() const { + union { + const char *d; + T *t; + } u; + u.d = data; + return *u.t; + } + + const RootLeaf &rootLeaf() const { + assert(!branched() && "Cannot acces leaf data in branched root"); + return dataAs<RootLeaf>(); + } + RootLeaf &rootLeaf() { + assert(!branched() && "Cannot acces leaf data in branched root"); + return dataAs<RootLeaf>(); + } + RootBranchData &rootBranchData() const { + assert(branched() && "Cannot access branch data in non-branched root"); + return dataAs<RootBranchData>(); + } + RootBranchData &rootBranchData() { + assert(branched() && "Cannot access branch data in non-branched root"); + return dataAs<RootBranchData>(); + } + const RootBranch &rootBranch() const { return rootBranchData().node; } + RootBranch &rootBranch() { return rootBranchData().node; } + KeyT rootBranchStart() const { return rootBranchData().start; } + KeyT &rootBranchStart() { return rootBranchData().start; } + + template <typename NodeT> NodeT *newNode() { + return new(allocator.template Allocate<NodeT>()) NodeT(); + } + + template <typename NodeT> void deleteNode(NodeT *P) { + P->~NodeT(); + allocator.Deallocate(P); + } + + IdxPair branchRoot(unsigned Position); + IdxPair splitRoot(unsigned Position); + + void switchRootToBranch() { + rootLeaf().~RootLeaf(); + height = 1; + new (&rootBranchData()) RootBranchData(); + } + + void switchRootToLeaf() { + rootBranchData().~RootBranchData(); + height = 0; + new(&rootLeaf()) RootLeaf(); + } + + bool branched() const { return height > 0; } + + ValT treeSafeLookup(KeyT x, ValT NotFound) const; + void visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef, + unsigned Level)); + void deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level); + +public: + explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) { + assert((uintptr_t(data) & (alignOf<RootLeaf>() - 1)) == 0 && + "Insufficient alignment"); + new(&rootLeaf()) RootLeaf(); + } + + ~IntervalMap() { + clear(); + rootLeaf().~RootLeaf(); + } + + /// empty - Return true when no intervals are mapped. + bool empty() const { + return rootSize == 0; + } + + /// start - Return the smallest mapped key in a non-empty map. + KeyT start() const { + assert(!empty() && "Empty IntervalMap has no start"); + return !branched() ? rootLeaf().start(0) : rootBranchStart(); + } + + /// stop - Return the largest mapped key in a non-empty map. + KeyT stop() const { + assert(!empty() && "Empty IntervalMap has no stop"); + return !branched() ? rootLeaf().stop(rootSize - 1) : + rootBranch().stop(rootSize - 1); + } + + /// lookup - Return the mapped value at x or NotFound. + ValT lookup(KeyT x, ValT NotFound = ValT()) const { + if (empty() || Traits::startLess(x, start()) || Traits::stopLess(stop(), x)) + return NotFound; + return branched() ? treeSafeLookup(x, NotFound) : + rootLeaf().safeLookup(x, NotFound); + } + + /// insert - Add a mapping of [a;b] to y, coalesce with adjacent intervals. + /// It is assumed that no key in the interval is mapped to another value, but + /// overlapping intervals already mapped to y will be coalesced. + void insert(KeyT a, KeyT b, ValT y) { + if (branched() || rootSize == RootLeaf::Capacity) + return find(a).insert(a, b, y); + + // Easy insert into root leaf. + unsigned p = rootLeaf().findFrom(0, rootSize, a); + rootSize = rootLeaf().insertFrom(p, rootSize, a, b, y); + } + + /// clear - Remove all entries. + void clear(); + + class const_iterator; + class iterator; + friend class const_iterator; + friend class iterator; + + const_iterator begin() const { + const_iterator I(*this); + I.goToBegin(); + return I; + } + + iterator begin() { + iterator I(*this); + I.goToBegin(); + return I; + } + + const_iterator end() const { + const_iterator I(*this); + I.goToEnd(); + return I; + } + + iterator end() { + iterator I(*this); + I.goToEnd(); + return I; + } + + /// find - Return an iterator pointing to the first interval ending at or + /// after x, or end(). + const_iterator find(KeyT x) const { + const_iterator I(*this); + I.find(x); + return I; + } + + iterator find(KeyT x) { + iterator I(*this); + I.find(x); + return I; + } +}; + +/// treeSafeLookup - Return the mapped value at x or NotFound, assuming a +/// branched root. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +ValT IntervalMap<KeyT, ValT, N, Traits>:: +treeSafeLookup(KeyT x, ValT NotFound) const { + assert(branched() && "treeLookup assumes a branched root"); + + IntervalMapImpl::NodeRef NR = rootBranch().safeLookup(x); + for (unsigned h = height-1; h; --h) + NR = NR.get<Branch>().safeLookup(x); + return NR.get<Leaf>().safeLookup(x, NotFound); +} + + +// branchRoot - Switch from a leaf root to a branched root. +// Return the new (root offset, node offset) corresponding to Position. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>:: +branchRoot(unsigned Position) { + using namespace IntervalMapImpl; + // How many external leaf nodes to hold RootLeaf+1? + const unsigned Nodes = RootLeaf::Capacity / Leaf::Capacity + 1; + + // Compute element distribution among new nodes. + unsigned size[Nodes]; + IdxPair NewOffset(0, Position); + + // Is is very common for the root node to be smaller than external nodes. + if (Nodes == 1) + size[0] = rootSize; + else + NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, NULL, size, + Position, true); + + // Allocate new nodes. + unsigned pos = 0; + NodeRef node[Nodes]; + for (unsigned n = 0; n != Nodes; ++n) { + Leaf *L = newNode<Leaf>(); + L->copy(rootLeaf(), pos, 0, size[n]); + node[n] = NodeRef(L, size[n]); + pos += size[n]; + } + + // Destroy the old leaf node, construct branch node instead. + switchRootToBranch(); + for (unsigned n = 0; n != Nodes; ++n) { + rootBranch().stop(n) = node[n].template get<Leaf>().stop(size[n]-1); + rootBranch().subtree(n) = node[n]; + } + rootBranchStart() = node[0].template get<Leaf>().start(0); + rootSize = Nodes; + return NewOffset; +} + +// splitRoot - Split the current BranchRoot into multiple Branch nodes. +// Return the new (root offset, node offset) corresponding to Position. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>:: +splitRoot(unsigned Position) { + using namespace IntervalMapImpl; + // How many external leaf nodes to hold RootBranch+1? + const unsigned Nodes = RootBranch::Capacity / Branch::Capacity + 1; + + // Compute element distribution among new nodes. + unsigned Size[Nodes]; + IdxPair NewOffset(0, Position); + + // Is is very common for the root node to be smaller than external nodes. + if (Nodes == 1) + Size[0] = rootSize; + else + NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, NULL, Size, + Position, true); + + // Allocate new nodes. + unsigned Pos = 0; + NodeRef Node[Nodes]; + for (unsigned n = 0; n != Nodes; ++n) { + Branch *B = newNode<Branch>(); + B->copy(rootBranch(), Pos, 0, Size[n]); + Node[n] = NodeRef(B, Size[n]); + Pos += Size[n]; + } + + for (unsigned n = 0; n != Nodes; ++n) { + rootBranch().stop(n) = Node[n].template get<Branch>().stop(Size[n]-1); + rootBranch().subtree(n) = Node[n]; + } + rootSize = Nodes; + ++height; + return NewOffset; +} + +/// visitNodes - Visit each external node. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef, unsigned Height)) { + if (!branched()) + return; + SmallVector<IntervalMapImpl::NodeRef, 4> Refs, NextRefs; + + // Collect level 0 nodes from the root. + for (unsigned i = 0; i != rootSize; ++i) + Refs.push_back(rootBranch().subtree(i)); + + // Visit all branch nodes. + for (unsigned h = height - 1; h; --h) { + for (unsigned i = 0, e = Refs.size(); i != e; ++i) { + for (unsigned j = 0, s = Refs[i].size(); j != s; ++j) + NextRefs.push_back(Refs[i].subtree(j)); + (this->*f)(Refs[i], h); + } + Refs.clear(); + Refs.swap(NextRefs); + } + + // Visit all leaf nodes. + for (unsigned i = 0, e = Refs.size(); i != e; ++i) + (this->*f)(Refs[i], 0); +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level) { + if (Level) + deleteNode(&Node.get<Branch>()); + else + deleteNode(&Node.get<Leaf>()); +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +clear() { + if (branched()) { + visitNodes(&IntervalMap::deleteNode); + switchRootToLeaf(); + } + rootSize = 0; +} + +//===----------------------------------------------------------------------===// +//--- IntervalMap::const_iterator ----// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +class IntervalMap<KeyT, ValT, N, Traits>::const_iterator : + public std::iterator<std::bidirectional_iterator_tag, ValT> { +protected: + friend class IntervalMap; + + // The map referred to. + IntervalMap *map; + + // We store a full path from the root to the current position. + // The path may be partially filled, but never between iterator calls. + IntervalMapImpl::Path path; + + explicit const_iterator(const IntervalMap &map) : + map(const_cast<IntervalMap*>(&map)) {} + + bool branched() const { + assert(map && "Invalid iterator"); + return map->branched(); + } + + void setRoot(unsigned Offset) { + if (branched()) + path.setRoot(&map->rootBranch(), map->rootSize, Offset); + else + path.setRoot(&map->rootLeaf(), map->rootSize, Offset); + } + + void pathFillFind(KeyT x); + void treeFind(KeyT x); + void treeAdvanceTo(KeyT x); + + /// unsafeStart - Writable access to start() for iterator. + KeyT &unsafeStart() const { + assert(valid() && "Cannot access invalid iterator"); + return branched() ? path.leaf<Leaf>().start(path.leafOffset()) : + path.leaf<RootLeaf>().start(path.leafOffset()); + } + + /// unsafeStop - Writable access to stop() for iterator. + KeyT &unsafeStop() const { + assert(valid() && "Cannot access invalid iterator"); + return branched() ? path.leaf<Leaf>().stop(path.leafOffset()) : + path.leaf<RootLeaf>().stop(path.leafOffset()); + } + + /// unsafeValue - Writable access to value() for iterator. + ValT &unsafeValue() const { + assert(valid() && "Cannot access invalid iterator"); + return branched() ? path.leaf<Leaf>().value(path.leafOffset()) : + path.leaf<RootLeaf>().value(path.leafOffset()); + } + +public: + /// const_iterator - Create an iterator that isn't pointing anywhere. + const_iterator() : map(0) {} + + /// valid - Return true if the current position is valid, false for end(). + bool valid() const { return path.valid(); } + + /// start - Return the beginning of the current interval. + const KeyT &start() const { return unsafeStart(); } + + /// stop - Return the end of the current interval. + const KeyT &stop() const { return unsafeStop(); } + + /// value - Return the mapped value at the current interval. + const ValT &value() const { return unsafeValue(); } + + const ValT &operator*() const { return value(); } + + bool operator==(const const_iterator &RHS) const { + assert(map == RHS.map && "Cannot compare iterators from different maps"); + if (!valid()) + return !RHS.valid(); + if (path.leafOffset() != RHS.path.leafOffset()) + return false; + return &path.template leaf<Leaf>() == &RHS.path.template leaf<Leaf>(); + } + + bool operator!=(const const_iterator &RHS) const { + return !operator==(RHS); + } + + /// goToBegin - Move to the first interval in map. + void goToBegin() { + setRoot(0); + if (branched()) + path.fillLeft(map->height); + } + + /// goToEnd - Move beyond the last interval in map. + void goToEnd() { + setRoot(map->rootSize); + } + + /// preincrement - move to the next interval. + const_iterator &operator++() { + assert(valid() && "Cannot increment end()"); + if (++path.leafOffset() == path.leafSize() && branched()) + path.moveRight(map->height); + return *this; + } + + /// postincrement - Dont do that! + const_iterator operator++(int) { + const_iterator tmp = *this; + operator++(); + return tmp; + } + + /// predecrement - move to the previous interval. + const_iterator &operator--() { + if (path.leafOffset() && (valid() || !branched())) + --path.leafOffset(); + else + path.moveLeft(map->height); + return *this; + } + + /// postdecrement - Dont do that! + const_iterator operator--(int) { + const_iterator tmp = *this; + operator--(); + return tmp; + } + + /// find - Move to the first interval with stop >= x, or end(). + /// This is a full search from the root, the current position is ignored. + void find(KeyT x) { + if (branched()) + treeFind(x); + else + setRoot(map->rootLeaf().findFrom(0, map->rootSize, x)); + } + + /// advanceTo - Move to the first interval with stop >= x, or end(). + /// The search is started from the current position, and no earlier positions + /// can be found. This is much faster than find() for small moves. + void advanceTo(KeyT x) { + if (!valid()) + return; + if (branched()) + treeAdvanceTo(x); + else + path.leafOffset() = + map->rootLeaf().findFrom(path.leafOffset(), map->rootSize, x); + } + +}; + +/// pathFillFind - Complete path by searching for x. +/// @param x Key to search for. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +const_iterator::pathFillFind(KeyT x) { + IntervalMapImpl::NodeRef NR = path.subtree(path.height()); + for (unsigned i = map->height - path.height() - 1; i; --i) { + unsigned p = NR.get<Branch>().safeFind(0, x); + path.push(NR, p); + NR = NR.subtree(p); + } + path.push(NR, NR.get<Leaf>().safeFind(0, x)); +} + +/// treeFind - Find in a branched tree. +/// @param x Key to search for. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +const_iterator::treeFind(KeyT x) { + setRoot(map->rootBranch().findFrom(0, map->rootSize, x)); + if (valid()) + pathFillFind(x); +} + +/// treeAdvanceTo - Find position after the current one. +/// @param x Key to search for. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +const_iterator::treeAdvanceTo(KeyT x) { + // Can we stay on the same leaf node? + if (!Traits::stopLess(path.leaf<Leaf>().stop(path.leafSize() - 1), x)) { + path.leafOffset() = path.leaf<Leaf>().safeFind(path.leafOffset(), x); + return; + } + + // Drop the current leaf. + path.pop(); + + // Search towards the root for a usable subtree. + if (path.height()) { + for (unsigned l = path.height() - 1; l; --l) { + if (!Traits::stopLess(path.node<Branch>(l).stop(path.offset(l)), x)) { + // The branch node at l+1 is usable + path.offset(l + 1) = + path.node<Branch>(l + 1).safeFind(path.offset(l + 1), x); + return pathFillFind(x); + } + path.pop(); + } + // Is the level-1 Branch usable? + if (!Traits::stopLess(map->rootBranch().stop(path.offset(0)), x)) { + path.offset(1) = path.node<Branch>(1).safeFind(path.offset(1), x); + return pathFillFind(x); + } + } + + // We reached the root. + setRoot(map->rootBranch().findFrom(path.offset(0), map->rootSize, x)); + if (valid()) + pathFillFind(x); +} + +//===----------------------------------------------------------------------===// +//--- IntervalMap::iterator ----// +//===----------------------------------------------------------------------===// + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +class IntervalMap<KeyT, ValT, N, Traits>::iterator : public const_iterator { + friend class IntervalMap; + typedef IntervalMapImpl::IdxPair IdxPair; + + explicit iterator(IntervalMap &map) : const_iterator(map) {} + + void setNodeStop(unsigned Level, KeyT Stop); + bool insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop); + template <typename NodeT> bool overflow(unsigned Level); + void treeInsert(KeyT a, KeyT b, ValT y); + void eraseNode(unsigned Level); + void treeErase(bool UpdateRoot = true); + bool canCoalesceLeft(KeyT Start, ValT x); + bool canCoalesceRight(KeyT Stop, ValT x); + +public: + /// iterator - Create null iterator. + iterator() {} + + /// setStart - Move the start of the current interval. + /// This may cause coalescing with the previous interval. + /// @param a New start key, must not overlap the previous interval. + void setStart(KeyT a); + + /// setStop - Move the end of the current interval. + /// This may cause coalescing with the following interval. + /// @param b New stop key, must not overlap the following interval. + void setStop(KeyT b); + + /// setValue - Change the mapped value of the current interval. + /// This may cause coalescing with the previous and following intervals. + /// @param x New value. + void setValue(ValT x); + + /// setStartUnchecked - Move the start of the current interval without + /// checking for coalescing or overlaps. + /// This should only be used when it is known that coalescing is not required. + /// @param a New start key. + void setStartUnchecked(KeyT a) { this->unsafeStart() = a; } + + /// setStopUnchecked - Move the end of the current interval without checking + /// for coalescing or overlaps. + /// This should only be used when it is known that coalescing is not required. + /// @param b New stop key. + void setStopUnchecked(KeyT b) { + this->unsafeStop() = b; + // Update keys in branch nodes as well. + if (this->path.atLastEntry(this->path.height())) + setNodeStop(this->path.height(), b); + } + + /// setValueUnchecked - Change the mapped value of the current interval + /// without checking for coalescing. + /// @param x New value. + void setValueUnchecked(ValT x) { this->unsafeValue() = x; } + + /// insert - Insert mapping [a;b] -> y before the current position. + void insert(KeyT a, KeyT b, ValT y); + + /// erase - Erase the current interval. + void erase(); + + iterator &operator++() { + const_iterator::operator++(); + return *this; + } + + iterator operator++(int) { + iterator tmp = *this; + operator++(); + return tmp; + } + + iterator &operator--() { + const_iterator::operator--(); + return *this; + } + + iterator operator--(int) { + iterator tmp = *this; + operator--(); + return tmp; + } + +}; + +/// canCoalesceLeft - Can the current interval coalesce to the left after +/// changing start or value? +/// @param Start New start of current interval. +/// @param Value New value for current interval. +/// @return True when updating the current interval would enable coalescing. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +bool IntervalMap<KeyT, ValT, N, Traits>:: +iterator::canCoalesceLeft(KeyT Start, ValT Value) { + using namespace IntervalMapImpl; + Path &P = this->path; + if (!this->branched()) { + unsigned i = P.leafOffset(); + RootLeaf &Node = P.leaf<RootLeaf>(); + return i && Node.value(i-1) == Value && + Traits::adjacent(Node.stop(i-1), Start); + } + // Branched. + if (unsigned i = P.leafOffset()) { + Leaf &Node = P.leaf<Leaf>(); + return Node.value(i-1) == Value && Traits::adjacent(Node.stop(i-1), Start); + } else if (NodeRef NR = P.getLeftSibling(P.height())) { + unsigned i = NR.size() - 1; + Leaf &Node = NR.get<Leaf>(); + return Node.value(i) == Value && Traits::adjacent(Node.stop(i), Start); + } + return false; +} + +/// canCoalesceRight - Can the current interval coalesce to the right after +/// changing stop or value? +/// @param Stop New stop of current interval. +/// @param Value New value for current interval. +/// @return True when updating the current interval would enable coalescing. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +bool IntervalMap<KeyT, ValT, N, Traits>:: +iterator::canCoalesceRight(KeyT Stop, ValT Value) { + using namespace IntervalMapImpl; + Path &P = this->path; + unsigned i = P.leafOffset() + 1; + if (!this->branched()) { + if (i >= P.leafSize()) + return false; + RootLeaf &Node = P.leaf<RootLeaf>(); + return Node.value(i) == Value && Traits::adjacent(Stop, Node.start(i)); + } + // Branched. + if (i < P.leafSize()) { + Leaf &Node = P.leaf<Leaf>(); + return Node.value(i) == Value && Traits::adjacent(Stop, Node.start(i)); + } else if (NodeRef NR = P.getRightSibling(P.height())) { + Leaf &Node = NR.get<Leaf>(); + return Node.value(0) == Value && Traits::adjacent(Stop, Node.start(0)); + } + return false; +} + +/// setNodeStop - Update the stop key of the current node at level and above. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::setNodeStop(unsigned Level, KeyT Stop) { + // There are no references to the root node, so nothing to update. + if (!Level) + return; + IntervalMapImpl::Path &P = this->path; + // Update nodes pointing to the current node. + while (--Level) { + P.node<Branch>(Level).stop(P.offset(Level)) = Stop; + if (!P.atLastEntry(Level)) + return; + } + // Update root separately since it has a different layout. + P.node<RootBranch>(Level).stop(P.offset(Level)) = Stop; +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::setStart(KeyT a) { + assert(Traits::stopLess(a, this->stop()) && "Cannot move start beyond stop"); + KeyT &CurStart = this->unsafeStart(); + if (!Traits::startLess(a, CurStart) || !canCoalesceLeft(a, this->value())) { + CurStart = a; + return; + } + // Coalesce with the interval to the left. + --*this; + a = this->start(); + erase(); + setStartUnchecked(a); +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::setStop(KeyT b) { + assert(Traits::stopLess(this->start(), b) && "Cannot move stop beyond start"); + if (Traits::startLess(b, this->stop()) || + !canCoalesceRight(b, this->value())) { + setStopUnchecked(b); + return; + } + // Coalesce with interval to the right. + KeyT a = this->start(); + erase(); + setStartUnchecked(a); +} + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::setValue(ValT x) { + setValueUnchecked(x); + if (canCoalesceRight(this->stop(), x)) { + KeyT a = this->start(); + erase(); + setStartUnchecked(a); + } + if (canCoalesceLeft(this->start(), x)) { + --*this; + KeyT a = this->start(); + erase(); + setStartUnchecked(a); + } +} + +/// insertNode - insert a node before the current path at level. +/// Leave the current path pointing at the new node. +/// @param Level path index of the node to be inserted. +/// @param Node The node to be inserted. +/// @param Stop The last index in the new node. +/// @return True if the tree height was increased. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +bool IntervalMap<KeyT, ValT, N, Traits>:: +iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) { + assert(Level && "Cannot insert next to the root"); + bool SplitRoot = false; + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + + if (Level == 1) { + // Insert into the root branch node. + if (IM.rootSize < RootBranch::Capacity) { + IM.rootBranch().insert(P.offset(0), IM.rootSize, Node, Stop); + P.setSize(0, ++IM.rootSize); + P.reset(Level); + return SplitRoot; + } + + // We need to split the root while keeping our position. + SplitRoot = true; + IdxPair Offset = IM.splitRoot(P.offset(0)); + P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset); + + // Fall through to insert at the new higher level. + ++Level; + } + + // When inserting before end(), make sure we have a valid path. + P.legalizeForInsert(--Level); + + // Insert into the branch node at Level-1. + if (P.size(Level) == Branch::Capacity) { + // Branch node is full, handle handle the overflow. + assert(!SplitRoot && "Cannot overflow after splitting the root"); + SplitRoot = overflow<Branch>(Level); + Level += SplitRoot; + } + P.node<Branch>(Level).insert(P.offset(Level), P.size(Level), Node, Stop); + P.setSize(Level, P.size(Level) + 1); + if (P.atLastEntry(Level)) + setNodeStop(Level, Stop); + P.reset(Level + 1); + return SplitRoot; +} + +// insert +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::insert(KeyT a, KeyT b, ValT y) { + if (this->branched()) + return treeInsert(a, b, y); + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + + // Try simple root leaf insert. + unsigned Size = IM.rootLeaf().insertFrom(P.leafOffset(), IM.rootSize, a, b, y); + + // Was the root node insert successful? + if (Size <= RootLeaf::Capacity) { + P.setSize(0, IM.rootSize = Size); + return; + } + + // Root leaf node is full, we must branch. + IdxPair Offset = IM.branchRoot(P.leafOffset()); + P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset); + + // Now it fits in the new leaf. + treeInsert(a, b, y); +} + + +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::treeInsert(KeyT a, KeyT b, ValT y) { + using namespace IntervalMapImpl; + Path &P = this->path; + + if (!P.valid()) + P.legalizeForInsert(this->map->height); + + // Check if this insertion will extend the node to the left. + if (P.leafOffset() == 0 && Traits::startLess(a, P.leaf<Leaf>().start(0))) { + // Node is growing to the left, will it affect a left sibling node? + if (NodeRef Sib = P.getLeftSibling(P.height())) { + Leaf &SibLeaf = Sib.get<Leaf>(); + unsigned SibOfs = Sib.size() - 1; + if (SibLeaf.value(SibOfs) == y && + Traits::adjacent(SibLeaf.stop(SibOfs), a)) { + // This insertion will coalesce with the last entry in SibLeaf. We can + // handle it in two ways: + // 1. Extend SibLeaf.stop to b and be done, or + // 2. Extend a to SibLeaf, erase the SibLeaf entry and continue. + // We prefer 1., but need 2 when coalescing to the right as well. + Leaf &CurLeaf = P.leaf<Leaf>(); + P.moveLeft(P.height()); + if (Traits::stopLess(b, CurLeaf.start(0)) && + (y != CurLeaf.value(0) || !Traits::adjacent(b, CurLeaf.start(0)))) { + // Easy, just extend SibLeaf and we're done. + setNodeStop(P.height(), SibLeaf.stop(SibOfs) = b); + return; + } else { + // We have both left and right coalescing. Erase the old SibLeaf entry + // and continue inserting the larger interval. + a = SibLeaf.start(SibOfs); + treeErase(/* UpdateRoot= */false); + } + } + } else { + // No left sibling means we are at begin(). Update cached bound. + this->map->rootBranchStart() = a; + } + } + + // When we are inserting at the end of a leaf node, we must update stops. + unsigned Size = P.leafSize(); + bool Grow = P.leafOffset() == Size; + Size = P.leaf<Leaf>().insertFrom(P.leafOffset(), Size, a, b, y); + + // Leaf insertion unsuccessful? Overflow and try again. + if (Size > Leaf::Capacity) { + overflow<Leaf>(P.height()); + Grow = P.leafOffset() == P.leafSize(); + Size = P.leaf<Leaf>().insertFrom(P.leafOffset(), P.leafSize(), a, b, y); + assert(Size <= Leaf::Capacity && "overflow() didn't make room"); + } + + // Inserted, update offset and leaf size. + P.setSize(P.height(), Size); + + // Insert was the last node entry, update stops. + if (Grow) + setNodeStop(P.height(), b); +} + +/// erase - erase the current interval and move to the next position. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::erase() { + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + assert(P.valid() && "Cannot erase end()"); + if (this->branched()) + return treeErase(); + IM.rootLeaf().erase(P.leafOffset(), IM.rootSize); + P.setSize(0, --IM.rootSize); +} + +/// treeErase - erase() for a branched tree. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::treeErase(bool UpdateRoot) { + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + Leaf &Node = P.leaf<Leaf>(); + + // Nodes are not allowed to become empty. + if (P.leafSize() == 1) { + IM.deleteNode(&Node); + eraseNode(IM.height); + // Update rootBranchStart if we erased begin(). + if (UpdateRoot && IM.branched() && P.valid() && P.atBegin()) + IM.rootBranchStart() = P.leaf<Leaf>().start(0); + return; + } + + // Erase current entry. + Node.erase(P.leafOffset(), P.leafSize()); + unsigned NewSize = P.leafSize() - 1; + P.setSize(IM.height, NewSize); + // When we erase the last entry, update stop and move to a legal position. + if (P.leafOffset() == NewSize) { + setNodeStop(IM.height, Node.stop(NewSize - 1)); + P.moveRight(IM.height); + } else if (UpdateRoot && P.atBegin()) + IM.rootBranchStart() = P.leaf<Leaf>().start(0); +} + +/// eraseNode - Erase the current node at Level from its parent and move path to +/// the first entry of the next sibling node. +/// The node must be deallocated by the caller. +/// @param Level 1..height, the root node cannot be erased. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +void IntervalMap<KeyT, ValT, N, Traits>:: +iterator::eraseNode(unsigned Level) { + assert(Level && "Cannot erase root node"); + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + + if (--Level == 0) { + IM.rootBranch().erase(P.offset(0), IM.rootSize); + P.setSize(0, --IM.rootSize); + // If this cleared the root, switch to height=0. + if (IM.empty()) { + IM.switchRootToLeaf(); + this->setRoot(0); + return; + } + } else { + // Remove node ref from branch node at Level. + Branch &Parent = P.node<Branch>(Level); + if (P.size(Level) == 1) { + // Branch node became empty, remove it recursively. + IM.deleteNode(&Parent); + eraseNode(Level); + } else { + // Branch node won't become empty. + Parent.erase(P.offset(Level), P.size(Level)); + unsigned NewSize = P.size(Level) - 1; + P.setSize(Level, NewSize); + // If we removed the last branch, update stop and move to a legal pos. + if (P.offset(Level) == NewSize) { + setNodeStop(Level, Parent.stop(NewSize - 1)); + P.moveRight(Level); + } + } + } + // Update path cache for the new right sibling position. + if (P.valid()) { + P.reset(Level + 1); + P.offset(Level + 1) = 0; + } +} + +/// overflow - Distribute entries of the current node evenly among +/// its siblings and ensure that the current node is not full. +/// This may require allocating a new node. +/// @param NodeT The type of node at Level (Leaf or Branch). +/// @param Level path index of the overflowing node. +/// @return True when the tree height was changed. +template <typename KeyT, typename ValT, unsigned N, typename Traits> +template <typename NodeT> +bool IntervalMap<KeyT, ValT, N, Traits>:: +iterator::overflow(unsigned Level) { + using namespace IntervalMapImpl; + Path &P = this->path; + unsigned CurSize[4]; + NodeT *Node[4]; + unsigned Nodes = 0; + unsigned Elements = 0; + unsigned Offset = P.offset(Level); + + // Do we have a left sibling? + NodeRef LeftSib = P.getLeftSibling(Level); + if (LeftSib) { + Offset += Elements = CurSize[Nodes] = LeftSib.size(); + Node[Nodes++] = &LeftSib.get<NodeT>(); + } + + // Current node. + Elements += CurSize[Nodes] = P.size(Level); + Node[Nodes++] = &P.node<NodeT>(Level); + + // Do we have a right sibling? + NodeRef RightSib = P.getRightSibling(Level); + if (RightSib) { + Elements += CurSize[Nodes] = RightSib.size(); + Node[Nodes++] = &RightSib.get<NodeT>(); + } + + // Do we need to allocate a new node? + unsigned NewNode = 0; + if (Elements + 1 > Nodes * NodeT::Capacity) { + // Insert NewNode at the penultimate position, or after a single node. + NewNode = Nodes == 1 ? 1 : Nodes - 1; + CurSize[Nodes] = CurSize[NewNode]; + Node[Nodes] = Node[NewNode]; + CurSize[NewNode] = 0; + Node[NewNode] = this->map->newNode<NodeT>(); + ++Nodes; + } + + // Compute the new element distribution. + unsigned NewSize[4]; + IdxPair NewOffset = distribute(Nodes, Elements, NodeT::Capacity, + CurSize, NewSize, Offset, true); + adjustSiblingSizes(Node, Nodes, CurSize, NewSize); + + // Move current location to the leftmost node. + if (LeftSib) + P.moveLeft(Level); + + // Elements have been rearranged, now update node sizes and stops. + bool SplitRoot = false; + unsigned Pos = 0; + for (;;) { + KeyT Stop = Node[Pos]->stop(NewSize[Pos]-1); + if (NewNode && Pos == NewNode) { + SplitRoot = insertNode(Level, NodeRef(Node[Pos], NewSize[Pos]), Stop); + Level += SplitRoot; + } else { + P.setSize(Level, NewSize[Pos]); + setNodeStop(Level, Stop); + } + if (Pos + 1 == Nodes) + break; + P.moveRight(Level); + ++Pos; + } + + // Where was I? Find NewOffset. + while(Pos != NewOffset.first) { + P.moveLeft(Level); + --Pos; + } + P.offset(Level) = NewOffset.second; + return SplitRoot; +} + +//===----------------------------------------------------------------------===// +//--- IntervalMapOverlaps ----// +//===----------------------------------------------------------------------===// + +/// IntervalMapOverlaps - Iterate over the overlaps of mapped intervals in two +/// IntervalMaps. The maps may be different, but the KeyT and Traits types +/// should be the same. +/// +/// Typical uses: +/// +/// 1. Test for overlap: +/// bool overlap = IntervalMapOverlaps(a, b).valid(); +/// +/// 2. Enumerate overlaps: +/// for (IntervalMapOverlaps I(a, b); I.valid() ; ++I) { ... } +/// +template <typename MapA, typename MapB> +class IntervalMapOverlaps { + typedef typename MapA::KeyType KeyType; + typedef typename MapA::KeyTraits Traits; + typename MapA::const_iterator posA; + typename MapB::const_iterator posB; + + /// advance - Move posA and posB forward until reaching an overlap, or until + /// either meets end. + /// Don't move the iterators if they are already overlapping. + void advance() { + if (!valid()) + return; + + if (Traits::stopLess(posA.stop(), posB.start())) { + // A ends before B begins. Catch up. + posA.advanceTo(posB.start()); + if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start())) + return; + } else if (Traits::stopLess(posB.stop(), posA.start())) { + // B ends before A begins. Catch up. + posB.advanceTo(posA.start()); + if (!posB.valid() || !Traits::stopLess(posA.stop(), posB.start())) + return; + } else + // Already overlapping. + return; + + for (;;) { + // Make a.end > b.start. + posA.advanceTo(posB.start()); + if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start())) + return; + // Make b.end > a.start. + posB.advanceTo(posA.start()); + if (!posB.valid() || !Traits::stopLess(posA.stop(), posB.start())) + return; + } + } + +public: + /// IntervalMapOverlaps - Create an iterator for the overlaps of a and b. + IntervalMapOverlaps(const MapA &a, const MapB &b) + : posA(b.empty() ? a.end() : a.find(b.start())), + posB(posA.valid() ? b.find(posA.start()) : b.end()) { advance(); } + + /// valid - Return true if iterator is at an overlap. + bool valid() const { + return posA.valid() && posB.valid(); + } + + /// a - access the left hand side in the overlap. + const typename MapA::const_iterator &a() const { return posA; } + + /// b - access the right hand side in the overlap. + const typename MapB::const_iterator &b() const { return posB; } + + /// start - Beginning of the overlapping interval. + KeyType start() const { + KeyType ak = a().start(); + KeyType bk = b().start(); + return Traits::startLess(ak, bk) ? bk : ak; + } + + /// stop - End of the overlapping interval. + KeyType stop() const { + KeyType ak = a().stop(); + KeyType bk = b().stop(); + return Traits::startLess(ak, bk) ? ak : bk; + } + + /// skipA - Move to the next overlap that doesn't involve a(). + void skipA() { + ++posA; + advance(); + } + + /// skipB - Move to the next overlap that doesn't involve b(). + void skipB() { + ++posB; + advance(); + } + + /// Preincrement - Move to the next overlap. + IntervalMapOverlaps &operator++() { + // Bump the iterator that ends first. The other one may have more overlaps. + if (Traits::startLess(posB.stop(), posA.stop())) + skipB(); + else + skipA(); + return *this; + } + + /// advanceTo - Move to the first overlapping interval with + /// stopLess(x, stop()). + void advanceTo(KeyType x) { + if (!valid()) + return; + // Make sure advanceTo sees monotonic keys. + if (Traits::stopLess(posA.stop(), x)) + posA.advanceTo(x); + if (Traits::stopLess(posB.stop(), x)) + posB.advanceTo(x); + advance(); + } +}; + +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/ADT/Optional.h b/contrib/llvm/include/llvm/ADT/Optional.h index 34e54a0..ee8b69f 100644 --- a/contrib/llvm/include/llvm/ADT/Optional.h +++ b/contrib/llvm/include/llvm/ADT/Optional.h @@ -61,6 +61,60 @@ template <typename T> struct simplify_type<Optional<T> > : public simplify_type<const Optional<T> > {}; +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template<typename T, typename U> +void operator==(const Optional<T> &X, const Optional<U> &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template<typename T, typename U> +void operator!=(const Optional<T> &X, const Optional<U> &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template<typename T, typename U> +void operator<(const Optional<T> &X, const Optional<U> &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template<typename T, typename U> +void operator<=(const Optional<T> &X, const Optional<U> &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template<typename T, typename U> +void operator>=(const Optional<T> &X, const Optional<U> &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template<typename T, typename U> +void operator>(const Optional<T> &X, const Optional<U> &Y); + } // end llvm namespace #endif diff --git a/contrib/llvm/include/llvm/ADT/PointerIntPair.h b/contrib/llvm/include/llvm/ADT/PointerIntPair.h index 64f4a7c..85dbba2 100644 --- a/contrib/llvm/include/llvm/ADT/PointerIntPair.h +++ b/contrib/llvm/include/llvm/ADT/PointerIntPair.h @@ -91,6 +91,13 @@ public: Value |= IntVal << IntShift; // Set new integer. } + PointerTy const *getAddrOfPointer() const { + assert(Value == reinterpret_cast<intptr_t>(getPointer()) && + "Can only return the address if IntBits is cleared and " + "PtrTraits doesn't change the pointer"); + return reinterpret_cast<PointerTy const *>(&Value); + } + void *getOpaqueValue() const { return reinterpret_cast<void*>(Value); } void setFromOpaqueValue(void *Val) { Value = reinterpret_cast<intptr_t>(Val);} diff --git a/contrib/llvm/include/llvm/ADT/PointerUnion.h b/contrib/llvm/include/llvm/ADT/PointerUnion.h index 3a514b5..61de042 100644 --- a/contrib/llvm/include/llvm/ADT/PointerUnion.h +++ b/contrib/llvm/include/llvm/ADT/PointerUnion.h @@ -107,6 +107,18 @@ namespace llvm { if (is<T>()) return get<T>(); return T(); } + + /// \brief If the union is set to the first pointer type we can get an + /// address pointing to it. + template <typename T> + PT1 const *getAddrOf() const { + assert(is<PT1>() && "Val is not the first pointer"); + assert(get<PT1>() == Val.getPointer() && + "Can't get the address because PointerLikeTypeTraits changes the ptr"); + T const *can_only_get_address_of_first_pointer_type + = reinterpret_cast<PT1 const *>(Val.getAddrOfPointer()); + return can_only_get_address_of_first_pointer_type; + } /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. diff --git a/contrib/llvm/include/llvm/ADT/PostOrderIterator.h b/contrib/llvm/include/llvm/ADT/PostOrderIterator.h index 47e5b2b..e3b4994 100644 --- a/contrib/llvm/include/llvm/ADT/PostOrderIterator.h +++ b/contrib/llvm/include/llvm/ADT/PostOrderIterator.h @@ -56,8 +56,7 @@ class po_iterator : public std::iterator<std::forward_iterator_tag, void traverseChild() { while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) { NodeType *BB = *VisitStack.back().second++; - if (!this->Visited.count(BB)) { // If the block is not visited... - this->Visited.insert(BB); + if (this->Visited.insert(BB)) { // If the block is not visited... VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); } } @@ -72,8 +71,7 @@ class po_iterator : public std::iterator<std::forward_iterator_tag, inline po_iterator(NodeType *BB, SetType &S) : po_iterator_storage<SetType, ExtStorage>(S) { - if(!S.count(BB)) { - this->Visited.insert(BB); + if (this->Visited.insert(BB)) { VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); traverseChild(); } diff --git a/contrib/llvm/include/llvm/ADT/SCCIterator.h b/contrib/llvm/include/llvm/ADT/SCCIterator.h index c49d599..3e93cfe 100644 --- a/contrib/llvm/include/llvm/ADT/SCCIterator.h +++ b/contrib/llvm/include/llvm/ADT/SCCIterator.h @@ -60,7 +60,7 @@ class scc_iterator // First element is basic block pointer, second is the 'next child' to visit std::vector<std::pair<NodeType *, ChildItTy> > VisitStack; - // MinVistNumStack - Stack holding the "min" values for each node in the DFS. + // MinVisitNumStack - Stack holding the "min" values for each node in the DFS. // This is used to track the minimum uplink values for all children of // the corresponding node on the VisitStack. std::vector<unsigned> MinVisitNumStack; diff --git a/contrib/llvm/include/llvm/ADT/ScopedHashTable.h b/contrib/llvm/include/llvm/ADT/ScopedHashTable.h index c96ad19..af3c482 100644 --- a/contrib/llvm/include/llvm/ADT/ScopedHashTable.h +++ b/contrib/llvm/include/llvm/ADT/ScopedHashTable.h @@ -31,25 +31,23 @@ #ifndef LLVM_ADT_SCOPEDHASHTABLE_H #define LLVM_ADT_SCOPEDHASHTABLE_H -#include <cassert> #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Allocator.h" namespace llvm { -template <typename K, typename V, typename KInfo = DenseMapInfo<K> > +template <typename K, typename V, typename KInfo = DenseMapInfo<K>, + typename AllocatorTy = MallocAllocator> class ScopedHashTable; -template <typename K, typename V, typename KInfo = DenseMapInfo<K> > +template <typename K, typename V> class ScopedHashTableVal { ScopedHashTableVal *NextInScope; ScopedHashTableVal *NextForKey; K Key; V Val; + ScopedHashTableVal(const K &key, const V &val) : Key(key), Val(val) {} public: - ScopedHashTableVal(ScopedHashTableVal *nextInScope, - ScopedHashTableVal *nextForKey, const K &key, const V &val) - : NextInScope(nextInScope), NextForKey(nextForKey), Key(key), Val(val) { - } const K &getKey() const { return Key; } const V &getValue() const { return Val; } @@ -57,33 +55,53 @@ public: ScopedHashTableVal *getNextForKey() { return NextForKey; } const ScopedHashTableVal *getNextForKey() const { return NextForKey; } -public: ScopedHashTableVal *getNextInScope() { return NextInScope; } + + template <typename AllocatorTy> + static ScopedHashTableVal *Create(ScopedHashTableVal *nextInScope, + ScopedHashTableVal *nextForKey, + const K &key, const V &val, + AllocatorTy &Allocator) { + ScopedHashTableVal *New = Allocator.template Allocate<ScopedHashTableVal>(); + // Set up the value. + new (New) ScopedHashTableVal(key, val); + New->NextInScope = nextInScope; + New->NextForKey = nextForKey; + return New; + } + + template <typename AllocatorTy> + void Destroy(AllocatorTy &Allocator) { + // Free memory referenced by the item. + this->~ScopedHashTableVal(); + Allocator.Deallocate(this); + } }; -template <typename K, typename V, typename KInfo = DenseMapInfo<K> > +template <typename K, typename V, typename KInfo = DenseMapInfo<K>, + typename AllocatorTy = MallocAllocator> class ScopedHashTableScope { /// HT - The hashtable that we are active for. - ScopedHashTable<K, V, KInfo> &HT; + ScopedHashTable<K, V, KInfo, AllocatorTy> &HT; /// PrevScope - This is the scope that we are shadowing in HT. ScopedHashTableScope *PrevScope; /// LastValInScope - This is the last value that was inserted for this scope /// or null if none have been inserted yet. - ScopedHashTableVal<K, V, KInfo> *LastValInScope; + ScopedHashTableVal<K, V> *LastValInScope; void operator=(ScopedHashTableScope&); // DO NOT IMPLEMENT ScopedHashTableScope(ScopedHashTableScope&); // DO NOT IMPLEMENT public: - ScopedHashTableScope(ScopedHashTable<K, V, KInfo> &HT); + ScopedHashTableScope(ScopedHashTable<K, V, KInfo, AllocatorTy> &HT); ~ScopedHashTableScope(); private: - friend class ScopedHashTable<K, V, KInfo>; - ScopedHashTableVal<K, V, KInfo> *getLastValInScope() { + friend class ScopedHashTable<K, V, KInfo, AllocatorTy>; + ScopedHashTableVal<K, V> *getLastValInScope() { return LastValInScope; } - void setLastValInScope(ScopedHashTableVal<K, V, KInfo> *Val) { + void setLastValInScope(ScopedHashTableVal<K, V> *Val) { LastValInScope = Val; } }; @@ -91,9 +109,9 @@ private: template <typename K, typename V, typename KInfo = DenseMapInfo<K> > class ScopedHashTableIterator { - ScopedHashTableVal<K, V, KInfo> *Node; + ScopedHashTableVal<K, V> *Node; public: - ScopedHashTableIterator(ScopedHashTableVal<K, V, KInfo> *node) : Node(node) {} + ScopedHashTableIterator(ScopedHashTableVal<K, V> *node) : Node(node) {} V &operator*() const { assert(Node && "Dereference end()"); @@ -121,26 +139,40 @@ public: }; -template <typename K, typename V, typename KInfo> +template <typename K, typename V, typename KInfo, typename AllocatorTy> class ScopedHashTable { - DenseMap<K, ScopedHashTableVal<K, V, KInfo>*, KInfo> TopLevelMap; - ScopedHashTableScope<K, V, KInfo> *CurScope; + typedef ScopedHashTableVal<K, V> ValTy; + DenseMap<K, ValTy*, KInfo> TopLevelMap; + ScopedHashTableScope<K, V, KInfo, AllocatorTy> *CurScope; + + AllocatorTy Allocator; + ScopedHashTable(const ScopedHashTable&); // NOT YET IMPLEMENTED void operator=(const ScopedHashTable&); // NOT YET IMPLEMENTED - friend class ScopedHashTableScope<K, V, KInfo>; + friend class ScopedHashTableScope<K, V, KInfo, AllocatorTy>; public: ScopedHashTable() : CurScope(0) {} + ScopedHashTable(AllocatorTy A) : CurScope(0), Allocator(A) {} ~ScopedHashTable() { assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!"); } + + /// ScopeTy - This is a helpful typedef that allows clients to get easy access + /// to the name of the scope for this hash table. + typedef ScopedHashTableScope<K, V, KInfo, AllocatorTy> ScopeTy; + + /// Access to the allocator. + typedef typename ReferenceAdder<AllocatorTy>::result AllocatorRefTy; + typedef typename ReferenceAdder<const AllocatorTy>::result AllocatorCRefTy; + AllocatorRefTy getAllocator() { return Allocator; } + AllocatorCRefTy getAllocator() const { return Allocator; } bool count(const K &Key) const { return TopLevelMap.count(Key); } V lookup(const K &Key) { - typename DenseMap<K, ScopedHashTableVal<K, V, KInfo>*, KInfo>::iterator - I = TopLevelMap.find(Key); + typename DenseMap<K, ValTy*, KInfo>::iterator I = TopLevelMap.find(Key); if (I != TopLevelMap.end()) return I->second->getValue(); @@ -150,10 +182,10 @@ public: void insert(const K &Key, const V &Val) { assert(CurScope && "No scope active!"); - ScopedHashTableVal<K, V, KInfo> *&KeyEntry = TopLevelMap[Key]; + ScopedHashTableVal<K, V> *&KeyEntry = TopLevelMap[Key]; - KeyEntry= new ScopedHashTableVal<K, V, KInfo>(CurScope->getLastValInScope(), - KeyEntry, Key, Val); + KeyEntry = ValTy::Create(CurScope->getLastValInScope(), KeyEntry, Key, Val, + Allocator); CurScope->setLastValInScope(KeyEntry); } @@ -162,7 +194,7 @@ public: iterator end() { return iterator(0); } iterator begin(const K &Key) { - typename DenseMap<K, ScopedHashTableVal<K, V, KInfo>*, KInfo>::iterator I = + typename DenseMap<K, ValTy*, KInfo>::iterator I = TopLevelMap.find(Key); if (I == TopLevelMap.end()) return end(); return iterator(I->second); @@ -171,29 +203,28 @@ public: /// ScopedHashTableScope ctor - Install this as the current scope for the hash /// table. -template <typename K, typename V, typename KInfo> -ScopedHashTableScope<K, V, KInfo>:: - ScopedHashTableScope(ScopedHashTable<K, V, KInfo> &ht) : HT(ht) { +template <typename K, typename V, typename KInfo, typename Allocator> +ScopedHashTableScope<K, V, KInfo, Allocator>:: + ScopedHashTableScope(ScopedHashTable<K, V, KInfo, Allocator> &ht) : HT(ht) { PrevScope = HT.CurScope; HT.CurScope = this; LastValInScope = 0; } -template <typename K, typename V, typename KInfo> -ScopedHashTableScope<K, V, KInfo>::~ScopedHashTableScope() { +template <typename K, typename V, typename KInfo, typename Allocator> +ScopedHashTableScope<K, V, KInfo, Allocator>::~ScopedHashTableScope() { assert(HT.CurScope == this && "Scope imbalance!"); HT.CurScope = PrevScope; // Pop and delete all values corresponding to this scope. - while (ScopedHashTableVal<K, V, KInfo> *ThisEntry = LastValInScope) { + while (ScopedHashTableVal<K, V> *ThisEntry = LastValInScope) { // Pop this value out of the TopLevelMap. if (ThisEntry->getNextForKey() == 0) { assert(HT.TopLevelMap[ThisEntry->getKey()] == ThisEntry && "Scope imbalance!"); HT.TopLevelMap.erase(ThisEntry->getKey()); } else { - ScopedHashTableVal<K, V, KInfo> *&KeyEntry = - HT.TopLevelMap[ThisEntry->getKey()]; + ScopedHashTableVal<K, V> *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()]; assert(KeyEntry == ThisEntry && "Scope imbalance!"); KeyEntry = ThisEntry->getNextForKey(); } @@ -202,7 +233,7 @@ ScopedHashTableScope<K, V, KInfo>::~ScopedHashTableScope() { LastValInScope = ThisEntry->getNextInScope(); // Delete this entry. - delete ThisEntry; + ThisEntry->Destroy(HT.getAllocator()); } } diff --git a/contrib/llvm/include/llvm/ADT/SetVector.h b/contrib/llvm/include/llvm/ADT/SetVector.h index bf8286c..abe2067 100644 --- a/contrib/llvm/include/llvm/ADT/SetVector.h +++ b/contrib/llvm/include/llvm/ADT/SetVector.h @@ -114,13 +114,15 @@ public: } /// @brief Remove an item from the set vector. - void remove(const value_type& X) { + bool remove(const value_type& X) { if (set_.erase(X)) { typename vector_type::iterator I = std::find(vector_.begin(), vector_.end(), X); assert(I != vector_.end() && "Corrupted SetVector instances!"); vector_.erase(I); + return true; } + return false; } diff --git a/contrib/llvm/include/llvm/ADT/SmallBitVector.h b/contrib/llvm/include/llvm/ADT/SmallBitVector.h index 3441d0a..b15b3ee 100644 --- a/contrib/llvm/include/llvm/ADT/SmallBitVector.h +++ b/contrib/llvm/include/llvm/ADT/SmallBitVector.h @@ -187,6 +187,13 @@ public: return getPointer()->any(); } + /// all - Returns true if all bits are set. + bool all() const { + if (isSmall()) + return getSmallBits() == (uintptr_t(1) << getSmallSize()) - 1; + return getPointer()->all(); + } + /// none - Returns true if none of the bits are set. bool none() const { if (isSmall()) diff --git a/contrib/llvm/include/llvm/ADT/SmallPtrSet.h b/contrib/llvm/include/llvm/ADT/SmallPtrSet.h index 424bdba..ff32ba8 100644 --- a/contrib/llvm/include/llvm/ADT/SmallPtrSet.h +++ b/contrib/llvm/include/llvm/ADT/SmallPtrSet.h @@ -16,9 +16,10 @@ #define LLVM_ADT_SMALLPTRSET_H #include <cassert> +#include <cstddef> #include <cstring> #include <iterator> -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/PointerLikeTypeTraits.h" namespace llvm { @@ -56,7 +57,7 @@ protected: /// it, so that the end iterator actually points to valid memory. unsigned CurArraySize; - // If small, this is # elts allocated consequtively + // If small, this is # elts allocated consecutively unsigned NumElements; unsigned NumTombstones; diff --git a/contrib/llvm/include/llvm/ADT/SmallString.h b/contrib/llvm/include/llvm/ADT/SmallString.h index 05bd8a4..da26416 100644 --- a/contrib/llvm/include/llvm/ADT/SmallString.h +++ b/contrib/llvm/include/llvm/ADT/SmallString.h @@ -27,6 +27,9 @@ public: // Default ctor - Initialize to empty. SmallString() {} + // Initialize from a StringRef. + SmallString(StringRef S) : SmallVector<char, InternalLen>(S.begin(), S.end()) {} + // Initialize with a range. template<typename ItTy> SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {} @@ -38,15 +41,16 @@ public: // Extra methods. StringRef str() const { return StringRef(this->begin(), this->size()); } - // Implicit conversion to StringRef. - operator StringRef() const { return str(); } - - const char *c_str() { + // TODO: Make this const, if it's safe... + const char* c_str() { this->push_back(0); this->pop_back(); return this->data(); } + // Implicit conversion to StringRef. + operator StringRef() const { return str(); } + // Extra operators. const SmallString &operator=(StringRef RHS) { this->clear(); diff --git a/contrib/llvm/include/llvm/ADT/SmallVector.h b/contrib/llvm/include/llvm/ADT/SmallVector.h index fec6bcd..8b0a13d 100644 --- a/contrib/llvm/include/llvm/ADT/SmallVector.h +++ b/contrib/llvm/include/llvm/ADT/SmallVector.h @@ -20,6 +20,7 @@ #include <cstddef> #include <cstdlib> #include <cstring> +#include <iterator> #include <memory> #ifdef _MSC_VER @@ -57,19 +58,13 @@ protected: // Allocate raw space for N elements of type T. If T has a ctor or dtor, we // don't want it to be automatically run, so we need to represent the space as // something else. An array of char would work great, but might not be - // aligned sufficiently. Instead, we either use GCC extensions, or some - // number of union instances for the space, which guarantee maximal alignment. - struct U { -#ifdef __GNUC__ - char X __attribute__((aligned)); -#else - union { - double D; - long double LD; - long long L; - void *P; - } X; -#endif + // aligned sufficiently. Instead we use some number of union instances for + // the space, which guarantee maximal alignment. + union U { + double D; + long double LD; + long long L; + void *P; } FirstEl; // Space after 'FirstEl' is clobbered, do not add any instance vars after it. @@ -94,7 +89,7 @@ protected: } /// grow_pod - This is an implementation of the grow() method which only works - /// on POD-like datatypes and is out of line to reduce code duplication. + /// on POD-like data types and is out of line to reduce code duplication. void grow_pod(size_t MinSizeInBytes, size_t TSize); public: @@ -269,7 +264,7 @@ public: template <typename T> class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> { typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass; - + SmallVectorImpl(const SmallVectorImpl&); // DISABLED. public: typedef typename SuperClass::iterator iterator; @@ -346,7 +341,6 @@ public: return Result; } - void swap(SmallVectorImpl &RHS); /// append - Add the specified range to the end of the SmallVector. diff --git a/contrib/llvm/include/llvm/ADT/SparseBitVector.h b/contrib/llvm/include/llvm/ADT/SparseBitVector.h index 0862981..d977136 100644 --- a/contrib/llvm/include/llvm/ADT/SparseBitVector.h +++ b/contrib/llvm/include/llvm/ADT/SparseBitVector.h @@ -17,7 +17,7 @@ #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include <cassert> diff --git a/contrib/llvm/include/llvm/ADT/Statistic.h b/contrib/llvm/include/llvm/ADT/Statistic.h index 3a1319f..f137ea2 100644 --- a/contrib/llvm/include/llvm/ADT/Statistic.h +++ b/contrib/llvm/include/llvm/ADT/Statistic.h @@ -26,7 +26,7 @@ #ifndef LLVM_ADT_STATISTIC_H #define LLVM_ADT_STATISTIC_H -#include "llvm/System/Atomic.h" +#include "llvm/Support/Atomic.h" namespace llvm { class raw_ostream; diff --git a/contrib/llvm/include/llvm/ADT/StringExtras.h b/contrib/llvm/include/llvm/ADT/StringExtras.h index 3c53ade..acbed66 100644 --- a/contrib/llvm/include/llvm/ADT/StringExtras.h +++ b/contrib/llvm/include/llvm/ADT/StringExtras.h @@ -14,7 +14,7 @@ #ifndef LLVM_ADT_STRINGEXTRAS_H #define LLVM_ADT_STRINGEXTRAS_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/StringRef.h" #include <cctype> @@ -25,10 +25,11 @@ namespace llvm { template<typename T> class SmallVectorImpl; -/// hexdigit - Return the (uppercase) hexadecimal character for the +/// hexdigit - Return the hexadecimal character for the /// given number \arg X (which should be less than 16). -static inline char hexdigit(unsigned X) { - return X < 10 ? '0' + X : 'A' + X - 10; +static inline char hexdigit(unsigned X, bool LowerCase = false) { + const char HexChar = LowerCase ? 'a' : 'A'; + return X < 10 ? '0' + X : HexChar + X - 10; } /// utohex_buffer - Emit the specified number into the buffer specified by diff --git a/contrib/llvm/include/llvm/ADT/StringMap.h b/contrib/llvm/include/llvm/ADT/StringMap.h index 59ff6aa..bad0e6f 100644 --- a/contrib/llvm/include/llvm/ADT/StringMap.h +++ b/contrib/llvm/include/llvm/ADT/StringMap.h @@ -137,8 +137,8 @@ public: StringMapEntry(unsigned strLen, const ValueTy &V) : StringMapEntryBase(strLen), second(V) {} - StringRef getKey() const { - return StringRef(getKeyData(), getKeyLength()); + StringRef getKey() const { + return StringRef(getKeyData(), getKeyLength()); } const ValueTy &getValue() const { return second; } @@ -167,7 +167,7 @@ public: unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+ KeyLength+1; - unsigned Alignment = alignof<StringMapEntry>(); + unsigned Alignment = alignOf<StringMapEntry>(); StringMapEntry *NewItem = static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment)); @@ -216,14 +216,14 @@ public: static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) { return GetStringMapEntryFromValue(const_cast<ValueTy&>(V)); } - + /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded /// into a StringMapEntry, return the StringMapEntry itself. static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>); return *reinterpret_cast<StringMapEntry*>(Ptr); } - + /// Destroy - Destroy this StringMapEntry, releasing memory back to the /// specified allocator. @@ -254,7 +254,7 @@ public: StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {} explicit StringMap(unsigned InitialSize) : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {} - + explicit StringMap(AllocatorTy A) : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {} @@ -262,16 +262,19 @@ public: : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) { assert(RHS.empty() && "Copy ctor from non-empty stringmap not implemented yet!"); + (void)RHS; } void operator=(const StringMap &RHS) { assert(RHS.empty() && "assignment from non-empty stringmap not implemented yet!"); + (void)RHS; clear(); } - - AllocatorTy &getAllocator() { return Allocator; } - const AllocatorTy &getAllocator() const { return Allocator; } + typedef typename ReferenceAdder<AllocatorTy>::result AllocatorRefTy; + typedef typename ReferenceAdder<const AllocatorTy>::result AllocatorCRefTy; + AllocatorRefTy getAllocator() { return Allocator; } + AllocatorCRefTy getAllocator() const { return Allocator; } typedef const char* key_type; typedef ValueTy mapped_type; diff --git a/contrib/llvm/include/llvm/ADT/StringRef.h b/contrib/llvm/include/llvm/ADT/StringRef.h index 8386d3e..1766d2b 100644 --- a/contrib/llvm/include/llvm/ADT/StringRef.h +++ b/contrib/llvm/include/llvm/ADT/StringRef.h @@ -132,7 +132,7 @@ namespace llvm { /// numbers. int compare_numeric(StringRef RHS) const; - /// \brief Determine the edit distance between this string and another + /// \brief Determine the edit distance between this string and another /// string. /// /// \param Other the string to compare this string against. @@ -142,11 +142,16 @@ namespace llvm { /// operation, rather than as two operations (an insertion and a /// removal). /// + /// \param MaxEditDistance If non-zero, the maximum edit distance that + /// this routine is allowed to compute. If the edit distance will exceed + /// that maximum, returns \c MaxEditDistance+1. + /// /// \returns the minimum number of character insertions, removals, /// or (if \p AllowReplacements is \c true) replacements needed to /// transform one of the given strings into the other. If zero, /// the strings are identical. - unsigned edit_distance(StringRef Other, bool AllowReplacements = true); + unsigned edit_distance(StringRef Other, bool AllowReplacements = true, + unsigned MaxEditDistance = 0); /// str - Get the contents as an std::string. std::string str() const { @@ -251,6 +256,18 @@ namespace llvm { /// Note: O(size() + Chars.size()) size_type find_first_not_of(StringRef Chars, size_t From = 0) const; + /// find_last_of - Find the last character in the string that is \arg C, or + /// npos if not found. + size_type find_last_of(char C, size_t From = npos) const { + return rfind(C, From); + } + + /// find_last_of - Find the last character in the string that is in \arg C, + /// or npos if not found. + /// + /// Note: O(size() + Chars.size()) + size_type find_last_of(StringRef Chars, size_t From = npos) const; + /// @} /// @name Helpful Algorithms /// @{ @@ -432,6 +449,10 @@ namespace llvm { /// @} + // StringRefs can be treated like a POD type. + template <typename T> struct isPodLike; + template <> struct isPodLike<StringRef> { static const bool value = true; }; + } #endif diff --git a/contrib/llvm/include/llvm/ADT/Triple.h b/contrib/llvm/include/llvm/ADT/Triple.h index 8dca3c1..e6dcc23 100644 --- a/contrib/llvm/include/llvm/ADT/Triple.h +++ b/contrib/llvm/include/llvm/ADT/Triple.h @@ -45,7 +45,7 @@ class Triple { public: enum ArchType { UnknownArch, - + alpha, // Alpha: alpha arm, // ARM; arm, armv.*, xscale bfin, // Blackfin: bfin @@ -53,7 +53,6 @@ public: mips, // MIPS: mips, mipsallegrex mipsel, // MIPSEL: mipsel, mipsallegrexel, psp msp430, // MSP430: msp430 - pic16, // PIC16: pic16 ppc, // PPC: powerpc ppc64, // PPC64: powerpc64, ppu sparc, // Sparc: sparc @@ -65,13 +64,14 @@ public: x86_64, // X86-64: amd64, x86_64 xcore, // XCore: xcore mblaze, // MBlaze: mblaze + ptx, // PTX: ptx InvalidArch }; enum VendorType { UnknownVendor, - Apple, + Apple, PC }; enum OSType { @@ -84,8 +84,7 @@ public: FreeBSD, Linux, Lv2, // PS3 - MinGW32, - MinGW64, + MinGW32, // i*86-pc-mingw32, *-w64-mingw32 NetBSD, OpenBSD, Psp, @@ -94,7 +93,15 @@ public: Haiku, Minix }; - + enum EnvironmentType { + UnknownEnvironment, + + GNU, + GNUEABI, + EABI, + MachO + }; + private: std::string Data; @@ -107,16 +114,20 @@ private: /// The parsed OS type. mutable OSType OS; + /// The parsed Environment type. + mutable EnvironmentType Environment; + bool isInitialized() const { return Arch != InvalidArch; } static ArchType ParseArch(StringRef ArchName); static VendorType ParseVendor(StringRef VendorName); static OSType ParseOS(StringRef OSName); + static EnvironmentType ParseEnvironment(StringRef EnvironmentName); void Parse() const; public: /// @name Constructors /// @{ - + Triple() : Data(), Arch(InvalidArch) {} explicit Triple(StringRef Str) : Data(Str), Arch(InvalidArch) {} explicit Triple(StringRef ArchStr, StringRef VendorStr, StringRef OSStr) @@ -127,6 +138,17 @@ public: Data += OSStr; } + explicit Triple(StringRef ArchStr, StringRef VendorStr, StringRef OSStr, + StringRef EnvironmentStr) + : Data(ArchStr), Arch(InvalidArch) { + Data += '-'; + Data += VendorStr; + Data += '-'; + Data += OSStr; + Data += '-'; + Data += EnvironmentStr; + } + /// @} /// @name Normalization /// @{ @@ -140,22 +162,22 @@ public: /// @} /// @name Typed Component Access /// @{ - + /// getArch - Get the parsed architecture type of this triple. - ArchType getArch() const { - if (!isInitialized()) Parse(); + ArchType getArch() const { + if (!isInitialized()) Parse(); return Arch; } - + /// getVendor - Get the parsed vendor type of this triple. - VendorType getVendor() const { - if (!isInitialized()) Parse(); + VendorType getVendor() const { + if (!isInitialized()) Parse(); return Vendor; } - + /// getOS - Get the parsed operating system type of this triple. - OSType getOS() const { - if (!isInitialized()) Parse(); + OSType getOS() const { + if (!isInitialized()) Parse(); return OS; } @@ -165,6 +187,12 @@ public: return getEnvironmentName() != ""; } + /// getEnvironment - Get the parsed environment type of this triple. + EnvironmentType getEnvironment() const { + if (!isInitialized()) Parse(); + return Environment; + } + /// @} /// @name Direct Component Access /// @{ @@ -193,13 +221,13 @@ public: /// if the environment component is present). StringRef getOSAndEnvironmentName() const; - + /// getDarwinNumber - Parse the 'darwin number' out of the specific target /// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is /// not defined, return 0's. This requires that the triple have an OSType of /// darwin before it is called. void getDarwinNumber(unsigned &Maj, unsigned &Min, unsigned &Revision) const; - + /// getDarwinMajorNumber - Return just the major version number, this is /// specialized because it is a common query. unsigned getDarwinMajorNumber() const { @@ -207,7 +235,7 @@ public: getDarwinNumber(Maj, Min, Rev); return Maj; } - + /// @} /// @name Mutators /// @{ @@ -224,6 +252,10 @@ public: /// to a known type. void setOS(OSType Kind); + /// setEnvironment - Set the environment (fourth) component of the triple + /// to a known type. + void setEnvironment(EnvironmentType Kind); + /// setTriple - Set all components to the new triple \arg Str. void setTriple(const Twine &Str); @@ -271,9 +303,14 @@ public: /// vendor. static const char *getVendorTypeName(VendorType Kind); - /// getOSTypeName - Get the canonical name for the \arg Kind vendor. + /// getOSTypeName - Get the canonical name for the \arg Kind operating + /// system. static const char *getOSTypeName(OSType Kind); + /// getEnvironmentTypeName - Get the canonical name for the \arg Kind + /// environment. + static const char *getEnvironmentTypeName(EnvironmentType Kind); + /// @} /// @name Static helpers for converting alternate architecture names. /// @{ diff --git a/contrib/llvm/include/llvm/ADT/Twine.h b/contrib/llvm/include/llvm/ADT/Twine.h index b519a3e..ab8d365 100644 --- a/contrib/llvm/include/llvm/ADT/Twine.h +++ b/contrib/llvm/include/llvm/ADT/Twine.h @@ -11,7 +11,7 @@ #define LLVM_ADT_TWINE_H #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> #include <string> @@ -42,7 +42,7 @@ namespace llvm { /// Twines support a special 'null' value, which always concatenates to form /// itself, and renders as an empty string. This can be returned from APIs to /// effectively nullify any concatenations performed on the result. - /// + /// /// \b Implementation \n /// /// Given the nature of a Twine, it is not possible for the Twine's @@ -99,7 +99,7 @@ namespace llvm { /// A pointer to a StringRef instance. StringRefKind, - /// An unsigned int value reinterpreted as a pointer, to render as an + /// An unsigned int value reinterpreted as a pointer, to render as an /// unsigned decimal integer. DecUIKind, @@ -260,32 +260,32 @@ namespace llvm { } /// Construct a twine to print \arg Val as an unsigned decimal integer. - explicit Twine(unsigned Val) + explicit Twine(unsigned Val) : LHS((void*)(intptr_t)Val), LHSKind(DecUIKind), RHSKind(EmptyKind) { } /// Construct a twine to print \arg Val as a signed decimal integer. - explicit Twine(int Val) + explicit Twine(int Val) : LHS((void*)(intptr_t)Val), LHSKind(DecIKind), RHSKind(EmptyKind) { } /// Construct a twine to print \arg Val as an unsigned decimal integer. - explicit Twine(const unsigned long &Val) + explicit Twine(const unsigned long &Val) : LHS(&Val), LHSKind(DecULKind), RHSKind(EmptyKind) { } /// Construct a twine to print \arg Val as a signed decimal integer. - explicit Twine(const long &Val) + explicit Twine(const long &Val) : LHS(&Val), LHSKind(DecLKind), RHSKind(EmptyKind) { } /// Construct a twine to print \arg Val as an unsigned decimal integer. - explicit Twine(const unsigned long long &Val) + explicit Twine(const unsigned long long &Val) : LHS(&Val), LHSKind(DecULLKind), RHSKind(EmptyKind) { } /// Construct a twine to print \arg Val as a signed decimal integer. - explicit Twine(const long long &Val) + explicit Twine(const long long &Val) : LHS(&Val), LHSKind(DecLLKind), RHSKind(EmptyKind) { } @@ -330,12 +330,12 @@ namespace llvm { bool isTriviallyEmpty() const { return isNullary(); } - + /// isSingleStringRef - Return true if this twine can be dynamically /// accessed as a single StringRef value with getSingleStringRef(). bool isSingleStringRef() const { if (getRHSKind() != EmptyKind) return false; - + switch (getLHSKind()) { case EmptyKind: case CStringKind: @@ -382,6 +382,14 @@ namespace llvm { /// SmallVector and a StringRef to the SmallVector's data is returned. StringRef toStringRef(SmallVectorImpl<char> &Out) const; + /// toNullTerminatedStringRef - This returns the twine as a single null + /// terminated StringRef if it can be represented as such. Otherwise the + /// twine is written into the given SmallVector and a StringRef to the + /// SmallVector's data is returned. + /// + /// The returned StringRef's size does not include the null terminator. + StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const; + /// print - Write the concatenated string represented by this twine to the /// stream \arg OS. void print(raw_ostream &OS) const; diff --git a/contrib/llvm/include/llvm/ADT/ValueMap.h b/contrib/llvm/include/llvm/ADT/ValueMap.h index ded17fc..d1f4e5a 100644 --- a/contrib/llvm/include/llvm/ADT/ValueMap.h +++ b/contrib/llvm/include/llvm/ADT/ValueMap.h @@ -29,7 +29,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/Support/ValueHandle.h" #include "llvm/Support/type_traits.h" -#include "llvm/System/Mutex.h" +#include "llvm/Support/Mutex.h" #include <iterator> diff --git a/contrib/llvm/include/llvm/ADT/ilist.h b/contrib/llvm/include/llvm/ADT/ilist.h index 4e3afe1..865fcb3 100644 --- a/contrib/llvm/include/llvm/ADT/ilist.h +++ b/contrib/llvm/include/llvm/ADT/ilist.h @@ -38,6 +38,7 @@ #ifndef LLVM_ADT_ILIST_H #define LLVM_ADT_ILIST_H +#include <algorithm> #include <cassert> #include <cstddef> #include <iterator> diff --git a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h index ad68d48..71a5982 100644 --- a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h @@ -16,11 +16,21 @@ // which automatically provides functionality for the entire suite of client // APIs. // -// This API represents memory as a (Pointer, Size) pair. The Pointer component -// specifies the base memory address of the region, the Size specifies how large -// of an area is being queried, or UnknownSize if the size is not known. -// Pointers that point to two completely different objects in memory never -// alias, regardless of the value of the Size component. +// This API identifies memory regions with the Location class. The pointer +// component specifies the base memory address of the region. The Size specifies +// the maximum size (in address units) of the memory region, or UnknownSize if +// the size is not known. The TBAA tag identifies the "type" of the memory +// reference; see the TypeBasedAliasAnalysis class for details. +// +// Some non-obvious details include: +// - Pointers that point to two completely different objects in memory never +// alias, regardless of the value of the Size component. +// - NoAlias doesn't imply inequal pointers. The most obvious example of this +// is two pointers to constant memory. Even if they are equal, constant +// memory is never stored to, so there will never be any dependencies. +// In this and other situations, the pointers may be both NoAlias and +// MustAlias at the same time. The current API can only return one result, +// though this is rarely a problem in practice. // //===----------------------------------------------------------------------===// @@ -28,7 +38,6 @@ #define LLVM_ANALYSIS_ALIAS_ANALYSIS_H #include "llvm/Support/CallSite.h" -#include "llvm/System/IncludeFile.h" #include <vector> namespace llvm { @@ -39,6 +48,8 @@ class VAArgInst; class TargetData; class Pass; class AnalysisUsage; +class MemTransferInst; +class MemIntrinsic; class AliasAnalysis { protected: @@ -67,7 +78,7 @@ public: /// UnknownSize - This is a special value which can be used with the /// size arguments in alias queries to indicate that the caller does not /// know the sizes of the potential memory references. - static unsigned const UnknownSize = ~0u; + static uint64_t const UnknownSize = ~UINT64_C(0); /// getTargetData - Return a pointer to the current TargetData object, or /// null if no TargetData object is available. @@ -77,12 +88,57 @@ public: /// getTypeStoreSize - Return the TargetData store size for the given type, /// if known, or a conservative value otherwise. /// - unsigned getTypeStoreSize(const Type *Ty); + uint64_t getTypeStoreSize(const Type *Ty); //===--------------------------------------------------------------------===// /// Alias Queries... /// + /// Location - A description of a memory location. + struct Location { + /// Ptr - The address of the start of the location. + const Value *Ptr; + /// Size - The maximum size of the location, in address-units, or + /// UnknownSize if the size is not known. Note that an unknown size does + /// not mean the pointer aliases the entire virtual address space, because + /// there are restrictions on stepping out of one object and into another. + /// See http://llvm.org/docs/LangRef.html#pointeraliasing + uint64_t Size; + /// TBAATag - The metadata node which describes the TBAA type of + /// the location, or null if there is no known unique tag. + const MDNode *TBAATag; + + explicit Location(const Value *P = 0, uint64_t S = UnknownSize, + const MDNode *N = 0) + : Ptr(P), Size(S), TBAATag(N) {} + + Location getWithNewPtr(const Value *NewPtr) const { + Location Copy(*this); + Copy.Ptr = NewPtr; + return Copy; + } + + Location getWithNewSize(uint64_t NewSize) const { + Location Copy(*this); + Copy.Size = NewSize; + return Copy; + } + + Location getWithoutTBAATag() const { + Location Copy(*this); + Copy.TBAATag = 0; + return Copy; + } + }; + + /// getLocation - Fill in Loc with information about the memory reference by + /// the given instruction. + Location getLocation(const LoadInst *LI); + Location getLocation(const StoreInst *SI); + Location getLocation(const VAArgInst *VI); + static Location getLocationForSource(const MemTransferInst *MTI); + static Location getLocationForDest(const MemIntrinsic *MI); + /// Alias analysis result - Either we know for sure that it does not alias, we /// know for sure it must alias, or we don't know anything: The two pointers /// _might_ alias. This enum is designed so you can do things like: @@ -92,33 +148,63 @@ public: /// See docs/AliasAnalysis.html for more information on the specific meanings /// of these values. /// - enum AliasResult { NoAlias = 0, MayAlias = 1, MustAlias = 2 }; + enum AliasResult { + NoAlias = 0, ///< No dependencies. + MayAlias, ///< Anything goes. + PartialAlias, ///< Pointers differ, but pointees overlap. + MustAlias ///< Pointers are equal. + }; /// alias - The main low level interface to the alias analysis implementation. - /// Returns a Result indicating whether the two pointers are aliased to each - /// other. This is the interface that must be implemented by specific alias - /// analysis implementations. - /// - virtual AliasResult alias(const Value *V1, unsigned V1Size, - const Value *V2, unsigned V2Size); + /// Returns an AliasResult indicating whether the two pointers are aliased to + /// each other. This is the interface that must be implemented by specific + /// alias analysis implementations. + virtual AliasResult alias(const Location &LocA, const Location &LocB); + + /// alias - A convenience wrapper. + AliasResult alias(const Value *V1, uint64_t V1Size, + const Value *V2, uint64_t V2Size) { + return alias(Location(V1, V1Size), Location(V2, V2Size)); + } - /// alias - A convenience wrapper for the case where the sizes are unknown. + /// alias - A convenience wrapper. AliasResult alias(const Value *V1, const Value *V2) { return alias(V1, UnknownSize, V2, UnknownSize); } /// isNoAlias - A trivial helper function to check to see if the specified /// pointers are no-alias. - bool isNoAlias(const Value *V1, unsigned V1Size, - const Value *V2, unsigned V2Size) { - return alias(V1, V1Size, V2, V2Size) == NoAlias; + bool isNoAlias(const Location &LocA, const Location &LocB) { + return alias(LocA, LocB) == NoAlias; } - /// pointsToConstantMemory - If the specified pointer is known to point into - /// constant global memory, return true. This allows disambiguation of store - /// instructions from constant pointers. - /// - virtual bool pointsToConstantMemory(const Value *P); + /// isNoAlias - A convenience wrapper. + bool isNoAlias(const Value *V1, uint64_t V1Size, + const Value *V2, uint64_t V2Size) { + return isNoAlias(Location(V1, V1Size), Location(V2, V2Size)); + } + + /// isMustAlias - A convenience wrapper. + bool isMustAlias(const Location &LocA, const Location &LocB) { + return alias(LocA, LocB) == MustAlias; + } + + /// isMustAlias - A convenience wrapper. + bool isMustAlias(const Value *V1, const Value *V2) { + return alias(V1, 1, V2, 1) == MustAlias; + } + + /// pointsToConstantMemory - If the specified memory location is + /// known to be constant, return true. If OrLocal is true and the + /// specified memory location is known to be "local" (derived from + /// an alloca), return true. Otherwise return false. + virtual bool pointsToConstantMemory(const Location &Loc, + bool OrLocal = false); + + /// pointsToConstantMemory - A convenient wrapper. + bool pointsToConstantMemory(const Value *P, bool OrLocal = false) { + return pointsToConstantMemory(Location(P), OrLocal); + } //===--------------------------------------------------------------------===// /// Simple mod/ref information... @@ -129,36 +215,48 @@ public: /// enum ModRefResult { NoModRef = 0, Ref = 1, Mod = 2, ModRef = 3 }; + /// These values define additional bits used to define the + /// ModRefBehavior values. + enum { Nowhere = 0, ArgumentPointees = 4, Anywhere = 8 | ArgumentPointees }; /// ModRefBehavior - Summary of how a function affects memory in the program. /// Loads from constant globals are not considered memory accesses for this /// interface. Also, functions may freely modify stack space local to their /// invocation without having to report it through these interfaces. enum ModRefBehavior { - // DoesNotAccessMemory - This function does not perform any non-local loads - // or stores to memory. - // - // This property corresponds to the GCC 'const' attribute. - DoesNotAccessMemory, - - // AccessesArguments - This function accesses function arguments in well - // known (possibly volatile) ways, but does not access any other memory. - AccessesArguments, - - // AccessesArgumentsAndGlobals - This function has accesses function - // arguments and global variables well known (possibly volatile) ways, but - // does not access any other memory. - AccessesArgumentsAndGlobals, - - // OnlyReadsMemory - This function does not perform any non-local stores or - // volatile loads, but may read from any memory location. - // - // This property corresponds to the GCC 'pure' attribute. - OnlyReadsMemory, - - // UnknownModRefBehavior - This indicates that the function could not be - // classified into one of the behaviors above. - UnknownModRefBehavior + /// DoesNotAccessMemory - This function does not perform any non-local loads + /// or stores to memory. + /// + /// This property corresponds to the GCC 'const' attribute. + /// This property corresponds to the LLVM IR 'readnone' attribute. + /// This property corresponds to the IntrNoMem LLVM intrinsic flag. + DoesNotAccessMemory = Nowhere | NoModRef, + + /// OnlyReadsArgumentPointees - The only memory references in this function + /// (if it has any) are non-volatile loads from objects pointed to by its + /// pointer-typed arguments, with arbitrary offsets. + /// + /// This property corresponds to the IntrReadArgMem LLVM intrinsic flag. + OnlyReadsArgumentPointees = ArgumentPointees | Ref, + + /// OnlyAccessesArgumentPointees - The only memory references in this + /// function (if it has any) are non-volatile loads and stores from objects + /// pointed to by its pointer-typed arguments, with arbitrary offsets. + /// + /// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag. + OnlyAccessesArgumentPointees = ArgumentPointees | ModRef, + + /// OnlyReadsMemory - This function does not perform any non-local stores or + /// volatile loads, but may read from any memory location. + /// + /// This property corresponds to the GCC 'pure' attribute. + /// This property corresponds to the LLVM IR 'readonly' attribute. + /// This property corresponds to the IntrReadMem LLVM intrinsic flag. + OnlyReadsMemory = Anywhere | Ref, + + /// UnknownModRefBehavior - This indicates that the function could not be + /// classified into one of the behaviors above. + UnknownModRefBehavior = Anywhere | ModRef }; /// getModRefBehavior - Return the behavior when calling the given call site. @@ -168,11 +266,6 @@ public: /// For use when the call site is not known. virtual ModRefBehavior getModRefBehavior(const Function *F); - /// getIntrinsicModRefBehavior - Return the modref behavior of the intrinsic - /// with the given id. Most clients won't need this, because the regular - /// getModRefBehavior incorporates this information. - static ModRefBehavior getIntrinsicModRefBehavior(unsigned iid); - /// doesNotAccessMemory - If the specified call is known to never read or /// write memory, return true. If the call only reads from known-constant /// memory, it is also legal to return true. Calls that unwind the stack @@ -205,8 +298,7 @@ public: /// This property corresponds to the GCC 'pure' attribute. /// bool onlyReadsMemory(ImmutableCallSite CS) { - ModRefBehavior MRB = getModRefBehavior(CS); - return MRB == DoesNotAccessMemory || MRB == OnlyReadsMemory; + return onlyReadsMemory(getModRefBehavior(CS)); } /// onlyReadsMemory - If the specified function is known to only read from @@ -214,21 +306,114 @@ public: /// when the call site is not known. /// bool onlyReadsMemory(const Function *F) { - ModRefBehavior MRB = getModRefBehavior(F); - return MRB == DoesNotAccessMemory || MRB == OnlyReadsMemory; + return onlyReadsMemory(getModRefBehavior(F)); } + /// onlyReadsMemory - Return true if functions with the specified behavior are + /// known to only read from non-volatile memory (or not access memory at all). + /// + static bool onlyReadsMemory(ModRefBehavior MRB) { + return !(MRB & Mod); + } + + /// onlyAccessesArgPointees - Return true if functions with the specified + /// behavior are known to read and write at most from objects pointed to by + /// their pointer-typed arguments (with arbitrary offsets). + /// + static bool onlyAccessesArgPointees(ModRefBehavior MRB) { + return !(MRB & Anywhere & ~ArgumentPointees); + } + + /// doesAccessArgPointees - Return true if functions with the specified + /// behavior are known to potentially read or write from objects pointed + /// to be their pointer-typed arguments (with arbitrary offsets). + /// + static bool doesAccessArgPointees(ModRefBehavior MRB) { + return (MRB & ModRef) && (MRB & ArgumentPointees); + } /// getModRefInfo - Return information about whether or not an instruction may - /// read or write memory specified by the pointer operand. An instruction + /// read or write the specified memory location. An instruction /// that doesn't read or write memory may be trivially LICM'd for example. + ModRefResult getModRefInfo(const Instruction *I, + const Location &Loc) { + switch (I->getOpcode()) { + case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc); + case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc); + case Instruction::Store: return getModRefInfo((const StoreInst*)I, Loc); + case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc); + case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc); + default: return NoModRef; + } + } + + /// getModRefInfo - A convenience wrapper. + ModRefResult getModRefInfo(const Instruction *I, + const Value *P, uint64_t Size) { + return getModRefInfo(I, Location(P, Size)); + } /// getModRefInfo (for call sites) - Return whether information about whether - /// a particular call site modifies or reads the memory specified by the - /// pointer. - /// + /// a particular call site modifies or reads the specified memory location. virtual ModRefResult getModRefInfo(ImmutableCallSite CS, - const Value *P, unsigned Size); + const Location &Loc); + + /// getModRefInfo (for call sites) - A convenience wrapper. + ModRefResult getModRefInfo(ImmutableCallSite CS, + const Value *P, uint64_t Size) { + return getModRefInfo(CS, Location(P, Size)); + } + + /// getModRefInfo (for calls) - Return whether information about whether + /// a particular call modifies or reads the specified memory location. + ModRefResult getModRefInfo(const CallInst *C, const Location &Loc) { + return getModRefInfo(ImmutableCallSite(C), Loc); + } + + /// getModRefInfo (for calls) - A convenience wrapper. + ModRefResult getModRefInfo(const CallInst *C, const Value *P, uint64_t Size) { + return getModRefInfo(C, Location(P, Size)); + } + + /// getModRefInfo (for invokes) - Return whether information about whether + /// a particular invoke modifies or reads the specified memory location. + ModRefResult getModRefInfo(const InvokeInst *I, + const Location &Loc) { + return getModRefInfo(ImmutableCallSite(I), Loc); + } + + /// getModRefInfo (for invokes) - A convenience wrapper. + ModRefResult getModRefInfo(const InvokeInst *I, + const Value *P, uint64_t Size) { + return getModRefInfo(I, Location(P, Size)); + } + + /// getModRefInfo (for loads) - Return whether information about whether + /// a particular load modifies or reads the specified memory location. + ModRefResult getModRefInfo(const LoadInst *L, const Location &Loc); + + /// getModRefInfo (for loads) - A convenience wrapper. + ModRefResult getModRefInfo(const LoadInst *L, const Value *P, uint64_t Size) { + return getModRefInfo(L, Location(P, Size)); + } + + /// getModRefInfo (for stores) - Return whether information about whether + /// a particular store modifies or reads the specified memory location. + ModRefResult getModRefInfo(const StoreInst *S, const Location &Loc); + + /// getModRefInfo (for stores) - A convenience wrapper. + ModRefResult getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size){ + return getModRefInfo(S, Location(P, Size)); + } + + /// getModRefInfo (for va_args) - Return whether information about whether + /// a particular va_arg modifies or reads the specified memory location. + ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc); + + /// getModRefInfo (for va_args) - A convenience wrapper. + ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){ + return getModRefInfo(I, Location(P, Size)); + } /// getModRefInfo - Return information about whether two call sites may refer /// to the same set of memory locations. See @@ -237,46 +422,31 @@ public: virtual ModRefResult getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2); -public: - /// Convenience functions... - ModRefResult getModRefInfo(const LoadInst *L, const Value *P, unsigned Size); - ModRefResult getModRefInfo(const StoreInst *S, const Value *P, unsigned Size); - ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, unsigned Size); - ModRefResult getModRefInfo(const CallInst *C, const Value *P, unsigned Size) { - return getModRefInfo(ImmutableCallSite(C), P, Size); - } - ModRefResult getModRefInfo(const InvokeInst *I, - const Value *P, unsigned Size) { - return getModRefInfo(ImmutableCallSite(I), P, Size); - } - ModRefResult getModRefInfo(const Instruction *I, - const Value *P, unsigned Size) { - switch (I->getOpcode()) { - case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, P,Size); - case Instruction::Load: return getModRefInfo((const LoadInst*)I, P, Size); - case Instruction::Store: return getModRefInfo((const StoreInst*)I, P,Size); - case Instruction::Call: return getModRefInfo((const CallInst*)I, P, Size); - case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,P,Size); - default: return NoModRef; - } - } - //===--------------------------------------------------------------------===// /// Higher level methods for querying mod/ref information. /// /// canBasicBlockModify - Return true if it is possible for execution of the /// specified basic block to modify the value pointed to by Ptr. - /// - bool canBasicBlockModify(const BasicBlock &BB, const Value *P, unsigned Size); + bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc); + + /// canBasicBlockModify - A convenience wrapper. + bool canBasicBlockModify(const BasicBlock &BB, const Value *P, uint64_t Size){ + return canBasicBlockModify(BB, Location(P, Size)); + } /// canInstructionRangeModify - Return true if it is possible for the /// execution of the specified instructions to modify the value pointed to by /// Ptr. The instructions to consider are all of the instructions in the /// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block. - /// bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, - const Value *Ptr, unsigned Size); + const Location &Loc); + + /// canInstructionRangeModify - A convenience wrapper. + bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, + const Value *Ptr, uint64_t Size) { + return canInstructionRangeModify(I1, I2, Location(Ptr, Size)); + } //===--------------------------------------------------------------------===// /// Methods that clients should call when they transform the program to allow @@ -299,6 +469,17 @@ public: /// virtual void copyValue(Value *From, Value *To); + /// addEscapingUse - This method should be used whenever an escaping use is + /// added to a pointer value. Analysis implementations may either return + /// conservative responses for that value in the future, or may recompute + /// some or all internal state to continue providing precise responses. + /// + /// Escaping uses are considered by anything _except_ the following: + /// - GEPs or bitcasts of the pointer + /// - Loads through the pointer + /// - Stores through (but not of) the pointer + virtual void addEscapingUse(Use &U); + /// replaceWithNewValue - This method is the obvious combination of the two /// above, and it provided as a helper to simplify client code. /// @@ -323,11 +504,4 @@ bool isIdentifiedObject(const Value *V); } // End llvm namespace -// Because of the way .a files work, we must force the BasicAA implementation to -// be pulled in if the AliasAnalysis header is included. Otherwise we run -// the risk of AliasAnalysis being used, but the default implementation not -// being linked into the tool that uses it. -FORCE_DEFINING_FILE_TO_BE_LINKED(AliasAnalysis) -FORCE_DEFINING_FILE_TO_BE_LINKED(BasicAliasAnalysis) - #endif diff --git a/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h b/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h index 8e2f7fd..e844d10 100644 --- a/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h +++ b/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h @@ -40,10 +40,12 @@ class AliasSet : public ilist_node<AliasSet> { Value *Val; // The pointer this record corresponds to. PointerRec **PrevInList, *NextInList; AliasSet *AS; - unsigned Size; + uint64_t Size; + const MDNode *TBAAInfo; public: PointerRec(Value *V) - : Val(V), PrevInList(0), NextInList(0), AS(0), Size(0) {} + : Val(V), PrevInList(0), NextInList(0), AS(0), Size(0), + TBAAInfo(DenseMapInfo<const MDNode *>::getEmptyKey()) {} Value *getValue() const { return Val; } @@ -55,11 +57,28 @@ class AliasSet : public ilist_node<AliasSet> { return &NextInList; } - void updateSize(unsigned NewSize) { + void updateSizeAndTBAAInfo(uint64_t NewSize, const MDNode *NewTBAAInfo) { if (NewSize > Size) Size = NewSize; + + if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey()) + // We don't have a TBAAInfo yet. Set it to NewTBAAInfo. + TBAAInfo = NewTBAAInfo; + else if (TBAAInfo != NewTBAAInfo) + // NewTBAAInfo conflicts with TBAAInfo. + TBAAInfo = DenseMapInfo<const MDNode *>::getTombstoneKey(); } - unsigned getSize() const { return Size; } + uint64_t getSize() const { return Size; } + + /// getTBAAInfo - Return the TBAAInfo, or null if there is no + /// information or conflicting information. + const MDNode *getTBAAInfo() const { + // If we have missing or conflicting TBAAInfo, return null. + if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey() || + TBAAInfo == DenseMapInfo<const MDNode *>::getTombstoneKey()) + return 0; + return TBAAInfo; + } AliasSet *getAliasSet(AliasSetTracker &AST) { assert(AS && "No AliasSet yet!"); @@ -186,7 +205,8 @@ public: value_type *operator->() const { return &operator*(); } Value *getPointer() const { return CurNode->getValue(); } - unsigned getSize() const { return CurNode->getSize(); } + uint64_t getSize() const { return CurNode->getSize(); } + const MDNode *getTBAAInfo() const { return CurNode->getTBAAInfo(); } iterator& operator++() { // Preincrement assert(CurNode && "Advancing past AliasSet.end()!"); @@ -230,7 +250,8 @@ private: void removeFromTracker(AliasSetTracker &AST); - void addPointer(AliasSetTracker &AST, PointerRec &Entry, unsigned Size, + void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size, + const MDNode *TBAAInfo, bool KnownMustAlias = false); void addCallSite(CallSite CS, AliasAnalysis &AA); void removeCallSite(CallSite CS) { @@ -245,7 +266,8 @@ private: /// aliasesPointer - Return true if the specified pointer "may" (or must) /// alias one of the members in the set. /// - bool aliasesPointer(const Value *Ptr, unsigned Size, AliasAnalysis &AA) const; + bool aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo, + AliasAnalysis &AA) const; bool aliasesCallSite(CallSite CS, AliasAnalysis &AA) const; }; @@ -298,7 +320,7 @@ public: /// These methods return true if inserting the instruction resulted in the /// addition of a new alias set (i.e., the pointer did not alias anything). /// - bool add(Value *Ptr, unsigned Size); // Add a location + bool add(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); // Add a location bool add(LoadInst *LI); bool add(StoreInst *SI); bool add(VAArgInst *VAAI); @@ -312,7 +334,8 @@ public: /// remove methods - These methods are used to remove all entries that might /// be aliased by the specified instruction. These methods return true if any /// alias sets were eliminated. - bool remove(Value *Ptr, unsigned Size); // Remove a location + // Remove a location + bool remove(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); bool remove(LoadInst *LI); bool remove(StoreInst *SI); bool remove(VAArgInst *VAAI); @@ -332,18 +355,21 @@ public: /// lives in. If the New argument is non-null, this method sets the value to /// true if a new alias set is created to contain the pointer (because the /// pointer didn't alias anything). - AliasSet &getAliasSetForPointer(Value *P, unsigned Size, bool *New = 0); + AliasSet &getAliasSetForPointer(Value *P, uint64_t Size, + const MDNode *TBAAInfo, + bool *New = 0); /// getAliasSetForPointerIfExists - Return the alias set containing the /// location specified if one exists, otherwise return null. - AliasSet *getAliasSetForPointerIfExists(Value *P, unsigned Size) { - return findAliasSetForPointer(P, Size); + AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size, + const MDNode *TBAAInfo) { + return findAliasSetForPointer(P, Size, TBAAInfo); } /// containsPointer - Return true if the specified location is represented by /// this alias set, false otherwise. This does not modify the AST object or /// alias sets. - bool containsPointer(Value *P, unsigned Size) const; + bool containsPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo) const; /// getAliasAnalysis - Return the underlying alias analysis object used by /// this tracker. @@ -390,14 +416,16 @@ private: return *Entry; } - AliasSet &addPointer(Value *P, unsigned Size, AliasSet::AccessType E, + AliasSet &addPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo, + AliasSet::AccessType E, bool &NewSet) { NewSet = false; - AliasSet &AS = getAliasSetForPointer(P, Size, &NewSet); + AliasSet &AS = getAliasSetForPointer(P, Size, TBAAInfo, &NewSet); AS.AccessTy |= E; return AS; } - AliasSet *findAliasSetForPointer(const Value *Ptr, unsigned Size); + AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size, + const MDNode *TBAAInfo); AliasSet *findAliasSetForCallSite(CallSite CS); }; diff --git a/contrib/llvm/include/llvm/Analysis/CallGraph.h b/contrib/llvm/include/llvm/Analysis/CallGraph.h index a4884ed..089f322 100644 --- a/contrib/llvm/include/llvm/Analysis/CallGraph.h +++ b/contrib/llvm/include/llvm/Analysis/CallGraph.h @@ -57,7 +57,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/ValueHandle.h" -#include "llvm/System/IncludeFile.h" +#include "llvm/Support/IncludeFile.h" #include <map> namespace llvm { @@ -138,6 +138,13 @@ public: /// not already exist. CallGraphNode *getOrInsertFunction(const Function *F); + /// spliceFunction - Replace the function represented by this node by another. + /// This does not rescan the body of the function, so it is suitable when + /// splicing the body of one function to another while also updating all + /// callers from the old function to the new. + /// + void spliceFunction(const Function *From, const Function *To); + //===--------------------------------------------------------------------- // Pass infrastructure interface glue code. // @@ -163,8 +170,10 @@ protected: // CallGraphNode class definition. // class CallGraphNode { - AssertingVH<Function> F; + friend class CallGraph; + AssertingVH<Function> F; + // CallRecord - This is a pair of the calling instruction (a call or invoke) // and the callgraph node being called. public: diff --git a/contrib/llvm/include/llvm/Analysis/CodeMetrics.h b/contrib/llvm/include/llvm/Analysis/CodeMetrics.h index 58096f1..75edfbb 100644 --- a/contrib/llvm/include/llvm/Analysis/CodeMetrics.h +++ b/contrib/llvm/include/llvm/Analysis/CodeMetrics.h @@ -7,15 +7,16 @@ // //===----------------------------------------------------------------------===// // -// This file implements various weight measurements for a function, helping -// the Inliner and PartialSpecialization decide whether to duplicate its -// contents. +// This file implements various weight measurements for code, helping +// the Inliner and other passes decide whether to duplicate its contents. // //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_CODEMETRICS_H #define LLVM_ANALYSIS_CODEMETRICS_H +#include "llvm/ADT/DenseMap.h" + namespace llvm { // CodeMetrics - Calculate size and a few similar metrics for a set of // basic blocks. @@ -45,6 +46,11 @@ namespace llvm { /// NumCalls - Keep track of the number of calls to 'big' functions. unsigned NumCalls; + + /// NumInlineCandidates - Keep track of the number of calls to internal + /// functions with only a single caller. These are likely targets for + /// future inlining, likely exposed by interleaved devirtualization. + unsigned NumInlineCandidates; /// NumVectorInsts - Keep track of how many instructions produce vector /// values. The inliner is being more aggressive with inlining vector @@ -56,7 +62,8 @@ namespace llvm { CodeMetrics() : callsSetJmp(false), isRecursive(false), containsIndirectBr(false), usesDynamicAlloca(false), - NumInsts(0), NumBlocks(0), NumCalls(0), NumVectorInsts(0), + NumInsts(0), NumBlocks(0), NumCalls(0), + NumInlineCandidates(0), NumVectorInsts(0), NumRets(0) {} /// analyzeBasicBlock - Add information about the specified basic block @@ -66,6 +73,22 @@ namespace llvm { /// analyzeFunction - Add information about the specified function /// to the current structure. void analyzeFunction(Function *F); + + /// CountCodeReductionForConstant - Figure out an approximation for how + /// many instructions will be constant folded if the specified value is + /// constant. + unsigned CountCodeReductionForConstant(Value *V); + + /// CountBonusForConstant - Figure out an approximation for how much + /// per-call performance boost we can expect if the specified value is + /// constant. + unsigned CountBonusForConstant(Value *V); + + /// CountCodeReductionForAlloca - Figure out an approximation of how much + /// smaller the function will be if it is inlined into a context where an + /// argument becomes an alloca. + /// + unsigned CountCodeReductionForAlloca(Value *V); }; } diff --git a/contrib/llvm/include/llvm/Analysis/ConstantFolding.h b/contrib/llvm/include/llvm/Analysis/ConstantFolding.h index e2675eb..f6b1f5a 100644 --- a/contrib/llvm/include/llvm/Analysis/ConstantFolding.h +++ b/contrib/llvm/include/llvm/Analysis/ConstantFolding.h @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file declares routines for folding instructions into constants. +// This file declares routines for folding instructions into constants when all +// operands are constants, for example "sub i32 1, 0" -> "1". // // Also, to supplement the basic VMCore ConstantExpr simplifications, // this file declares some additional folding routines that can make use of @@ -27,11 +28,11 @@ namespace llvm { class Function; class Type; -/// ConstantFoldInstruction - Attempt to constant fold the specified -/// instruction. If successful, the constant result is returned, if not, null -/// is returned. Note that this function can only fail when attempting to fold -/// instructions like loads and stores, which have no constant expression form. -/// +/// ConstantFoldInstruction - Try to constant fold the specified instruction. +/// If successful, the constant result is returned, if not, null is returned. +/// Note that this fails if not all of the operands are constant. Otherwise, +/// this function can only fail when attempting to fold instructions like loads +/// and stores, which have no constant expression form. Constant *ConstantFoldInstruction(Instruction *I, const TargetData *TD = 0); /// ConstantFoldConstantExpression - Attempt to fold the constant expression diff --git a/contrib/llvm/include/llvm/Analysis/DIBuilder.h b/contrib/llvm/include/llvm/Analysis/DIBuilder.h new file mode 100644 index 0000000..bd22134 --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/DIBuilder.h @@ -0,0 +1,459 @@ +//===--- llvm/Analysis/DIBuilder.h - Debug Information Builder --*- 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 a DIBuilder that is useful for creating debugging +// information entries in LLVM IR form. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DIBUILDER_H +#define LLVM_ANALYSIS_DIBUILDER_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/StringRef.h" + +namespace llvm { + class BasicBlock; + class Instruction; + class Function; + class Module; + class Value; + class LLVMContext; + class MDNode; + class StringRef; + class DIDescriptor; + class DIFile; + class DIEnumerator; + class DIType; + class DIArray; + class DIGlobalVariable; + class DINameSpace; + class DIVariable; + class DISubrange; + class DILexicalBlock; + class DISubprogram; + class DITemplateTypeParameter; + class DITemplateValueParameter; + + class DIBuilder { + private: + Module &M; + LLVMContext & VMContext; + MDNode *TheCU; + + Function *DeclareFn; // llvm.dbg.declare + Function *ValueFn; // llvm.dbg.value + + DIBuilder(const DIBuilder &); // DO NOT IMPLEMENT + void operator=(const DIBuilder &); // DO NOT IMPLEMENT + + public: + explicit DIBuilder(Module &M); + const MDNode *getCU() { return TheCU; } + enum ComplexAddrKind { OpPlus=1, OpDeref }; + + /// CreateCompileUnit - A CompileUnit provides an anchor for all debugging + /// information generated during this instance of compilation. + /// @param Lang Source programming language, eg. dwarf::DW_LANG_C99 + /// @param File File name + /// @param Dir Directory + /// @param Producer String identify producer of debugging information. + /// Usuall this is a compiler version string. + /// @param isOptimized A boolean flag which indicates whether optimization + /// is ON or not. + /// @param Flags This string lists command line options. This string is + /// directly embedded in debug info output which may be used + /// by a tool analyzing generated debugging information. + /// @param RV This indicates runtime version for languages like + /// Objective-C. + void CreateCompileUnit(unsigned Lang, StringRef File, StringRef Dir, + StringRef Producer, + bool isOptimized, StringRef Flags, unsigned RV); + + /// CreateFile - Create a file descriptor to hold debugging information + /// for a file. + DIFile CreateFile(StringRef Filename, StringRef Directory); + + /// CreateEnumerator - Create a single enumerator value. + DIEnumerator CreateEnumerator(StringRef Name, uint64_t Val); + + /// CreateBasicType - Create debugging information entry for a basic + /// type. + /// @param Name Type name. + /// @param SizeInBits Size of the type. + /// @param AlignInBits Type alignment. + /// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. + DIType CreateBasicType(StringRef Name, uint64_t SizeInBits, + 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); + + /// CreatePointerType - Create debugging information entry for a pointer. + /// @param PointeeTy Type pointed by this pointer. + /// @param SizeInBits Size. + /// @param AlignInBits Alignment. (optional) + /// @param Name Pointer type name. (optional) + DIType CreatePointerType(DIType PointeeTy, uint64_t SizeInBits, + uint64_t AlignInBits = 0, + StringRef Name = StringRef()); + + /// CreateReferenceType - Create debugging information entry for a c++ + /// style reference. + DIType CreateReferenceType(DIType RTy); + + /// CreateTypedef - Create debugging information entry for a typedef. + /// @param Ty Original type. + /// @param Name Typedef name. + /// @param File File where this type is defined. + /// @param LineNo Line number. + DIType CreateTypedef(DIType Ty, StringRef Name, DIFile File, + unsigned LineNo); + + /// CreateFriend - Create debugging information entry for a 'friend'. + DIType CreateFriend(DIType Ty, DIType FriendTy); + + /// CreateInheritance - Create debugging information entry to establish + /// inheritance relationship between two types. + /// @param Ty Original type. + /// @param BaseTy Base type. Ty is inherits from base. + /// @param BaseOffset Base offset. + /// @param Flags Flags to describe inheritance attribute, + /// e.g. private + DIType CreateInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset, + unsigned Flags); + + /// CreateMemberType - Create debugging information entry for a member. + /// @param Name Member name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param OffsetInBits Member offset. + /// @param Flags Flags to encode member attribute, e.g. private + /// @param Ty Parent type. + DIType CreateMemberType(StringRef Name, DIFile File, + unsigned LineNo, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DIType Ty); + + /// CreateClassType - Create debugging information entry for a class. + /// @param Scope Scope in which this class is defined. + /// @param Name class name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param OffsetInBits Member offset. + /// @param Flags Flags to encode member attribute, e.g. private + /// @param Elements class members. + /// @param VTableHolder Debug info of the base class that contains vtable + /// for this type. This is used in + /// DW_AT_containing_type. See DWARF documentation + /// for more info. + /// @param TemplateParms Template type parameters. + DIType CreateClassType(DIDescriptor Scope, StringRef Name, DIFile File, + unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DIType DerivedFrom, + DIArray Elements, MDNode *VTableHolder = 0, + MDNode *TemplateParms = 0); + + /// CreateStructType - Create debugging information entry for a struct. + /// @param Scope Scope in which this struct is defined. + /// @param Name Struct name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param Flags Flags to encode member attribute, e.g. private + /// @param Elements Struct elements. + /// @param RunTimeLang Optional parameter, Objective-C runtime version. + DIType CreateStructType(DIDescriptor Scope, StringRef Name, DIFile File, + unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Flags, + DIArray Elements, unsigned RunTimeLang = 0); + + /// CreateUnionType - Create debugging information entry for an union. + /// @param Scope Scope in which this union is defined. + /// @param Name Union name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param Flags Flags to encode member attribute, e.g. private + /// @param Elements Union elements. + /// @param RunTimeLang Optional parameter, Objective-C runtime version. + DIType CreateUnionType(DIDescriptor Scope, StringRef Name, DIFile File, + unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Flags, + DIArray Elements, unsigned RunTimeLang = 0); + + /// CreateTemplateTypeParameter - Create debugging information for template + /// type parameter. + /// @param Scope Scope in which this type is defined. + /// @param Name Type parameter name. + /// @param Ty Parameter type. + /// @param File File where this type parameter is defined. + /// @param LineNo Line number. + /// @param ColumnNo Column Number. + DITemplateTypeParameter + CreateTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty, + MDNode *File = 0, unsigned LineNo = 0, + unsigned ColumnNo = 0); + + /// CreateTemplateValueParameter - Create debugging information for template + /// value parameter. + /// @param Scope Scope in which this type is defined. + /// @param Name Value parameter name. + /// @param Ty Parameter type. + /// @param Value Constant parameter value. + /// @param File File where this type parameter is defined. + /// @param LineNo Line number. + /// @param ColumnNo Column Number. + DITemplateValueParameter + CreateTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty, + uint64_t Value, + MDNode *File = 0, unsigned LineNo = 0, + unsigned ColumnNo = 0); + + /// CreateArrayType - Create debugging information entry for an array. + /// @param Size Array size. + /// @param AlignInBits Alignment. + /// @param Ty Element type. + /// @param Subscripts Subscripts. + DIType CreateArrayType(uint64_t Size, uint64_t AlignInBits, + DIType Ty, DIArray Subscripts); + + /// CreateVectorType - Create debugging information entry for a vector type. + /// @param Size Array size. + /// @param AlignInBits Alignment. + /// @param Ty Element type. + /// @param Subscripts Subscripts. + DIType CreateVectorType(uint64_t Size, uint64_t AlignInBits, + DIType Ty, DIArray Subscripts); + + /// CreateEnumerationType - Create debugging information entry for an + /// enumeration. + /// @param Scope Scope in which this enumeration is defined. + /// @param Name Union name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param Elements Enumeration elements. + DIType CreateEnumerationType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, DIArray Elements); + + /// CreateSubroutineType - Create subroutine type. + /// @param File File in which this subroutine is defined. + /// @param ParamterTypes An array of subroutine parameter types. This + /// includes return type at 0th index. + DIType CreateSubroutineType(DIFile File, DIArray ParameterTypes); + + /// CreateArtificialType - Create a new DIType with "artificial" flag set. + DIType CreateArtificialType(DIType Ty); + + /// CreateTemporaryType - Create a temporary forward-declared type. + DIType CreateTemporaryType(); + DIType CreateTemporaryType(DIFile F); + + /// RetainType - Retain DIType in a module even if it is not referenced + /// through debug info anchors. + void RetainType(DIType T); + + /// CreateUnspecifiedParameter - Create unspeicified type descriptor + /// for a subroutine type. + DIDescriptor CreateUnspecifiedParameter(); + + /// GetOrCreateArray - Get a DIArray, create one if required. + DIArray GetOrCreateArray(Value *const *Elements, unsigned NumElements); + + /// GetOrCreateSubrange - Create a descriptor for a value range. This + /// implicitly uniques the values returned. + DISubrange GetOrCreateSubrange(int64_t Lo, int64_t Hi); + + /// CreateGlobalVariable - Create a new descriptor for the specified global. + /// @param Name Name of the variable. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Variable Type. + /// @param isLocalToUnit Boolean flag indicate whether this variable is + /// externally visible or not. + /// @param Val llvm::Value of the variable. + DIGlobalVariable + CreateGlobalVariable(StringRef Name, DIFile File, unsigned LineNo, + DIType Ty, bool isLocalToUnit, llvm::Value *Val); + + + /// CreateStaticVariable - Create a new descriptor for the specified + /// variable. + /// @param Conext Variable scope. + /// @param Name Name of the variable. + /// @param LinakgeName Mangled name of the variable. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Variable Type. + /// @param isLocalToUnit Boolean flag indicate whether this variable is + /// externally visible or not. + /// @param Val llvm::Value of the variable. + DIGlobalVariable + CreateStaticVariable(DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile File, unsigned LineNo, + DIType Ty, bool isLocalToUnit, llvm::Value *Val); + + + /// CreateLocalVariable - Create a new descriptor for the specified + /// local variable. + /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or + /// DW_TAG_arg_variable. + /// @param Scope Variable scope. + /// @param Name Variable name. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Variable Type + /// @param AlwaysPreserve Boolean. Set to true if debug info for this + /// variable should be preserved in optimized build. + /// @param Flags Flags, e.g. artificial variable. + DIVariable CreateLocalVariable(unsigned Tag, DIDescriptor Scope, + StringRef Name, + DIFile File, unsigned LineNo, + DIType Ty, bool AlwaysPreserve = false, + unsigned Flags = 0); + + + /// CreateComplexVariable - Create a new descriptor for the specified + /// variable which has a complex address expression for its address. + /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or + /// DW_TAG_arg_variable. + /// @param Scope Variable scope. + /// @param Name Variable name. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Variable Type + /// @param Addr A pointer to a vector of complex address operations. + /// @param NumAddr Num of address operations in the vector. + DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Scope, + StringRef Name, DIFile F, unsigned LineNo, + DIType Ty, Value *const *Addr, + unsigned NumAddr); + + /// CreateFunction - Create a new descriptor for the specified subprogram. + /// See comments in DISubprogram for descriptions of these fields. + /// @param Scope Function scope. + /// @param Name Function name. + /// @param LinkageName Mangled function name. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Function type. + /// @param isLocalToUnit True if this function is not externally visible.. + /// @param isDefinition True if this is a function definition. + /// @param Flags e.g. is this function prototyped or not. + /// This flags are used to emit dwarf attributes. + /// @param isOptimized True if optimization is ON. + /// @param Fn llvm::Function pointer. + DISubprogram CreateFunction(DIDescriptor Scope, StringRef Name, + StringRef LinkageName, + DIFile File, unsigned LineNo, + DIType Ty, bool isLocalToUnit, + bool isDefinition, + unsigned Flags = 0, + bool isOptimized = false, + Function *Fn = 0); + + /// CreateMethod - Create a new descriptor for the specified C++ method. + /// See comments in DISubprogram for descriptions of these fields. + /// @param Scope Function scope. + /// @param Name Function name. + /// @param LinkageName Mangled function name. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Function type. + /// @param isLocalToUnit True if this function is not externally visible.. + /// @param isDefinition True if this is a function definition. + /// @param Virtuality Attributes describing virutallness. e.g. pure + /// virtual function. + /// @param VTableIndex Index no of this method in virtual table. + /// @param VTableHolder Type that holds vtable. + /// @param Flags e.g. is this function prototyped or not. + /// This flags are used to emit dwarf attributes. + /// @param isOptimized True if optimization is ON. + /// @param Fn llvm::Function pointer. + DISubprogram CreateMethod(DIDescriptor Scope, StringRef Name, + StringRef LinkageName, + DIFile File, unsigned LineNo, + DIType Ty, bool isLocalToUnit, + bool isDefinition, + unsigned Virtuality = 0, unsigned VTableIndex = 0, + MDNode *VTableHolder = 0, + unsigned Flags = 0, + bool isOptimized = false, + Function *Fn = 0); + + /// CreateNameSpace - This creates new descriptor for a namespace + /// with the specified parent scope. + /// @param Scope Namespace scope + /// @param Name Name of this namespace + /// @param File Source file + /// @param LineNo Line number + DINameSpace CreateNameSpace(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNo); + + + /// CreateLexicalBlock - This creates a descriptor for a lexical block + /// with the specified parent context. + /// @param Scope Parent lexical scope. + /// @param File Source file + /// @param Line Line number + /// @param Col Column number + DILexicalBlock CreateLexicalBlock(DIDescriptor Scope, DIFile File, + unsigned Line, unsigned Col); + + /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. + /// @param Storage llvm::Value of the variable + /// @param VarInfo Variable's debug info descriptor. + /// @param InsertAtEnd Location for the new intrinsic. + Instruction *InsertDeclare(llvm::Value *Storage, DIVariable VarInfo, + BasicBlock *InsertAtEnd); + + /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. + /// @param Storage llvm::Value of the variable + /// @param VarInfo Variable's debug info descriptor. + /// @param InsertBefore Location for the new intrinsic. + Instruction *InsertDeclare(llvm::Value *Storage, DIVariable VarInfo, + Instruction *InsertBefore); + + + /// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. + /// @param Val llvm::Value of the variable + /// @param Offset Offset + /// @param VarInfo Variable's debug info descriptor. + /// @param InsertAtEnd Location for the new intrinsic. + Instruction *InsertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, + DIVariable VarInfo, + BasicBlock *InsertAtEnd); + + /// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. + /// @param Val llvm::Value of the variable + /// @param Offset Offset + /// @param VarInfo Variable's debug info descriptor. + /// @param InsertBefore Location for the new intrinsic. + Instruction *InsertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, + DIVariable VarInfo, + Instruction *InsertBefore); + + }; +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h b/contrib/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h index d8daf51..30741c4 100644 --- a/contrib/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h +++ b/contrib/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h @@ -67,7 +67,7 @@ struct DOTGraphTraitsPrinter : public FunctionPass { Title = GraphName + " for '" + F.getNameStr() + "' function"; if (ErrorInfo.empty()) - WriteGraph(File, Graph, Simple, Name, Title); + WriteGraph(File, Graph, Simple, Title); else errs() << " error opening file for writing!"; errs() << "\n"; diff --git a/contrib/llvm/include/llvm/Analysis/DebugInfo.h b/contrib/llvm/include/llvm/Analysis/DebugInfo.h index 2d1418d..aa69088 100644 --- a/contrib/llvm/include/llvm/Analysis/DebugInfo.h +++ b/contrib/llvm/include/llvm/Analysis/DebugInfo.h @@ -33,6 +33,7 @@ namespace llvm { class DbgDeclareInst; class Instruction; class MDNode; + class NamedMDNode; class LLVMContext; class raw_ostream; @@ -46,6 +47,18 @@ namespace llvm { /// This should not be stored in a container, because underly MDNode may /// change in certain situations. class DIDescriptor { + public: + enum { + FlagPrivate = 1 << 0, + FlagProtected = 1 << 1, + FlagFwdDecl = 1 << 2, + FlagAppleBlock = 1 << 3, + FlagBlockByrefStruct = 1 << 4, + FlagVirtual = 1 << 5, + FlagArtificial = 1 << 6, + FlagExplicit = 1 << 7, + FlagPrototyped = 1 << 8 + }; protected: const MDNode *DbgNode; @@ -108,6 +121,9 @@ namespace llvm { bool isEnumerator() const; bool isType() const; bool isGlobal() const; + bool isUnspecifiedParameter() const; + bool isTemplateTypeParameter() const; + bool isTemplateValueParameter() const; }; /// DISubrange - This is used to represent ranges, for array bounds. @@ -160,8 +176,8 @@ namespace llvm { /// module does not contain any main compile unit then the code generator /// will emit multiple compile units in the output object file. - bool isMain() const { return getUnsignedField(6); } - bool isOptimized() const { return getUnsignedField(7); } + bool isMain() const { return getUnsignedField(6) != 0; } + bool isOptimized() const { return getUnsignedField(7) != 0; } StringRef getFlags() const { return getStringField(8); } unsigned getRunTimeVersion() const { return getUnsignedField(9); } @@ -203,17 +219,6 @@ namespace llvm { /// others do not require a huge and empty descriptor full of zeros. class DIType : public DIScope { public: - enum { - FlagPrivate = 1 << 0, - FlagProtected = 1 << 1, - FlagFwdDecl = 1 << 2, - FlagAppleBlock = 1 << 3, - FlagBlockByrefStruct = 1 << 4, - FlagVirtual = 1 << 5, - FlagArtificial = 1 << 6 // To identify artificial arguments in - // a subroutine type. e.g. "this" in c++. - }; - protected: // This ctor is used when the Tag has already been validated by a derived // ctor. @@ -231,12 +236,12 @@ namespace llvm { DIScope getContext() const { return getFieldAs<DIScope>(1); } StringRef getName() const { return getStringField(2); } DICompileUnit getCompileUnit() const{ - if (getVersion() == llvm::LLVMDebugVersion7) - return getFieldAs<DICompileUnit>(3); - - DIFile F = getFieldAs<DIFile>(3); - return F.getCompileUnit(); + if (getVersion() == llvm::LLVMDebugVersion7) + return getFieldAs<DICompileUnit>(3); + + return getFieldAs<DIFile>(3).getCompileUnit(); } + DIFile getFile() const { return getFieldAs<DIFile>(3); } unsigned getLineNumber() const { return getUnsignedField(4); } uint64_t getSizeInBits() const { return getUInt64Field(5); } uint64_t getAlignInBits() const { return getUInt64Field(6); } @@ -269,12 +274,23 @@ namespace llvm { bool isValid() const { return DbgNode && (isBasicType() || isDerivedType() || isCompositeType()); } - StringRef getFilename() const { return getCompileUnit().getFilename();} - StringRef getDirectory() const { return getCompileUnit().getDirectory();} + StringRef getDirectory() const { + if (getVersion() == llvm::LLVMDebugVersion7) + return getCompileUnit().getDirectory(); + + return getFieldAs<DIFile>(3).getDirectory(); + } + StringRef getFilename() const { + if (getVersion() == llvm::LLVMDebugVersion7) + return getCompileUnit().getFilename(); + + return getFieldAs<DIFile>(3).getFilename(); + } /// replaceAllUsesWith - Replace all uses of debug info referenced by /// this descriptor. void replaceAllUsesWith(DIDescriptor &D); + void replaceAllUsesWith(MDNode *D); /// print - print type. void print(raw_ostream &OS) const; @@ -342,6 +358,7 @@ namespace llvm { DICompositeType getContainingType() const { return getFieldAs<DICompositeType>(12); } + DIArray getTemplateParams() const { return getFieldAs<DIArray>(13); } /// Verify - Verify that a composite type descriptor is well formed. bool Verify() const; @@ -353,6 +370,43 @@ namespace llvm { void dump() const; }; + /// DITemplateTypeParameter - This is a wrapper for template type parameter. + class DITemplateTypeParameter : public DIDescriptor { + public: + explicit DITemplateTypeParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs<DIScope>(1); } + StringRef getName() const { return getStringField(2); } + DIType getType() const { return getFieldAs<DIType>(3); } + StringRef getFilename() const { + return getFieldAs<DIFile>(4).getFilename(); + } + StringRef getDirectory() const { + return getFieldAs<DIFile>(4).getDirectory(); + } + unsigned getLineNumber() const { return getUnsignedField(5); } + unsigned getColumnNumber() const { return getUnsignedField(6); } + }; + + /// DITemplateValueParameter - This is a wrapper for template value parameter. + class DITemplateValueParameter : public DIDescriptor { + public: + explicit DITemplateValueParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs<DIScope>(1); } + StringRef getName() const { return getStringField(2); } + DIType getType() const { return getFieldAs<DIType>(3); } + uint64_t getValue() const { return getUInt64Field(4); } + StringRef getFilename() const { + return getFieldAs<DIFile>(5).getFilename(); + } + StringRef getDirectory() const { + return getFieldAs<DIFile>(5).getDirectory(); + } + unsigned getLineNumber() const { return getUnsignedField(6); } + unsigned getColumnNumber() const { return getUnsignedField(7); } + }; + /// DISubprogram - This is a wrapper for a subprogram (e.g. a function). class DISubprogram : public DIScope { public: @@ -366,8 +420,7 @@ namespace llvm { if (getVersion() == llvm::LLVMDebugVersion7) return getFieldAs<DICompileUnit>(6); - DIFile F = getFieldAs<DIFile>(6); - return F.getCompileUnit(); + return getFieldAs<DIFile>(6).getCompileUnit(); } unsigned getLineNumber() const { return getUnsignedField(7); } DICompositeType getType() const { return getFieldAs<DICompositeType>(8); } @@ -396,23 +449,52 @@ namespace llvm { DICompositeType getContainingType() const { return getFieldAs<DICompositeType>(13); } - unsigned isArtificial() const { return getUnsignedField(14); } + unsigned isArtificial() const { + if (getVersion() <= llvm::LLVMDebugVersion8) + return getUnsignedField(14); + return (getUnsignedField(14) & FlagArtificial) != 0; + } + /// isPrivate - Return true if this subprogram has "private" + /// access specifier. + bool isPrivate() const { + if (getVersion() <= llvm::LLVMDebugVersion8) + return false; + return (getUnsignedField(14) & FlagPrivate) != 0; + } + /// isProtected - Return true if this subprogram has "protected" + /// access specifier. + bool isProtected() const { + if (getVersion() <= llvm::LLVMDebugVersion8) + return false; + return (getUnsignedField(14) & FlagProtected) != 0; + } + /// isExplicit - Return true if this subprogram is marked as explicit. + bool isExplicit() const { + if (getVersion() <= llvm::LLVMDebugVersion8) + return false; + return (getUnsignedField(14) & FlagExplicit) != 0; + } + /// isPrototyped - Return true if this subprogram is prototyped. + bool isPrototyped() const { + if (getVersion() <= llvm::LLVMDebugVersion8) + return false; + return (getUnsignedField(14) & FlagPrototyped) != 0; + } + unsigned isOptimized() const; StringRef getFilename() const { if (getVersion() == llvm::LLVMDebugVersion7) return getCompileUnit().getFilename(); - DIFile F = getFieldAs<DIFile>(6); - return F.getFilename(); + return getFieldAs<DIFile>(6).getFilename(); } StringRef getDirectory() const { if (getVersion() == llvm::LLVMDebugVersion7) return getCompileUnit().getFilename(); - DIFile F = getFieldAs<DIFile>(6); - return F.getDirectory(); + return getFieldAs<DIFile>(6).getDirectory(); } /// Verify - Verify that a subprogram descriptor is well formed. @@ -484,6 +566,13 @@ namespace llvm { } unsigned getLineNumber() const { return getUnsignedField(4); } DIType getType() const { return getFieldAs<DIType>(5); } + + /// isArtificial - Return true if this variable is marked as "artificial". + bool isArtificial() const { + if (getVersion() <= llvm::LLVMDebugVersion8) + return false; + return (getUnsignedField(6) & FlagArtificial) != 0; + } /// Verify - Verify that a variable descriptor is well formed. @@ -525,13 +614,11 @@ namespace llvm { unsigned getLineNumber() const { return getUnsignedField(2); } unsigned getColumnNumber() const { return getUnsignedField(3); } StringRef getDirectory() const { - DIFile F = getFieldAs<DIFile>(4); - StringRef dir = F.getDirectory(); + StringRef dir = getFieldAs<DIFile>(4).getDirectory(); return !dir.empty() ? dir : getContext().getDirectory(); } StringRef getFilename() const { - DIFile F = getFieldAs<DIFile>(4); - StringRef filename = F.getFilename(); + StringRef filename = getFieldAs<DIFile>(4).getFilename(); return !filename.empty() ? filename : getContext().getFilename(); } }; @@ -542,14 +629,17 @@ namespace llvm { explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} DIScope getContext() const { return getFieldAs<DIScope>(1); } StringRef getName() const { return getStringField(2); } - StringRef getDirectory() const { return getContext().getDirectory(); } - StringRef getFilename() const { return getContext().getFilename(); } + StringRef getDirectory() const { + return getFieldAs<DIFile>(3).getDirectory(); + } + StringRef getFilename() const { + return getFieldAs<DIFile>(3).getFilename(); + } DICompileUnit getCompileUnit() const{ if (getVersion() == llvm::LLVMDebugVersion7) return getFieldAs<DICompileUnit>(3); - DIFile F = getFieldAs<DIFile>(3); - return F.getCompileUnit(); + return getFieldAs<DIFile>(3).getCompileUnit(); } unsigned getLineNumber() const { return getUnsignedField(4); } bool Verify() const; @@ -594,6 +684,10 @@ namespace llvm { /// implicitly uniques the values returned. DISubrange GetOrCreateSubrange(int64_t Lo, int64_t Hi); + /// CreateUnspecifiedParameter - Create unspeicified type descriptor + /// for a subroutine type. + DIDescriptor CreateUnspecifiedParameter(); + /// CreateCompileUnit - Create a new descriptor for the specified compile /// unit. DICompileUnit CreateCompileUnit(unsigned LangID, @@ -662,6 +756,7 @@ namespace llvm { /// CreateTemporaryType - Create a temporary forward-declared type. DIType CreateTemporaryType(); + DIType CreateTemporaryType(DIFile F); /// CreateArtificialType - Create a new DIType with "artificial" flag set. DIType CreateArtificialType(DIType Ty); @@ -690,8 +785,8 @@ namespace llvm { bool isDefinition, unsigned VK = 0, unsigned VIndex = 0, - DIType = DIType(), - bool isArtificial = 0, + DIType ContainingType = DIType(), + unsigned Flags = 0, bool isOptimized = false, Function *Fn = 0); @@ -721,15 +816,15 @@ namespace llvm { DIVariable CreateVariable(unsigned Tag, DIDescriptor Context, StringRef Name, DIFile F, unsigned LineNo, - DIType Ty, bool AlwaysPreserve = false); + DIType Ty, bool AlwaysPreserve = false, + unsigned Flags = 0); /// CreateComplexVariable - Create a new descriptor for the specified /// variable which has a complex address expression for its address. DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Context, - const std::string &Name, - DIFile F, unsigned LineNo, - DIType Ty, - SmallVector<Value *, 9> &addr); + StringRef Name, DIFile F, unsigned LineNo, + DIType Ty, Value *const *Addr, + unsigned NumAddr); /// CreateLexicalBlock - This creates a descriptor for a lexical block /// with the specified parent context. @@ -764,20 +859,29 @@ namespace llvm { /// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. Instruction *InsertDbgValueIntrinsic(llvm::Value *V, uint64_t Offset, DIVariable D, Instruction *InsertBefore); + + // RecordType - Record DIType in a module such that it is not lost even if + // it is not referenced through debug info anchors. + void RecordType(DIType T); + private: Constant *GetTagConstant(unsigned TAG); }; - bool getLocationInfo(const Value *V, std::string &DisplayName, - std::string &Type, unsigned &LineNo, std::string &File, - std::string &Dir); - /// getDISubprogram - Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); /// getDICompositeType - Find underlying composite type. DICompositeType getDICompositeType(DIType T); + /// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable + /// to hold function specific information. + NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, StringRef Name); + + /// getFnSpecificMDNode - Return a NameMDNode, if available, that is + /// suitable to hold function specific information. + NamedMDNode *getFnSpecificMDNode(const Module &M, StringRef Name); + class DebugInfoFinder { public: /// processModule - Process entire module and collect debug info diff --git a/contrib/llvm/include/llvm/Analysis/DominanceFrontier.h b/contrib/llvm/include/llvm/Analysis/DominanceFrontier.h new file mode 100644 index 0000000..d7f74af --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/DominanceFrontier.h @@ -0,0 +1,189 @@ +//===- llvm/Analysis/DominanceFrontier.h - Dominator Frontiers --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DominanceFrontier class, which calculate and holds the +// dominance frontier for a function. +// +// This should be considered deprecated, don't add any more uses of this data +// structure. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_H +#define LLVM_ANALYSIS_DOMINANCEFRONTIER_H + +#include "llvm/Analysis/Dominators.h" +#include <map> +#include <set> + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// DominanceFrontierBase - Common base class for computing forward and inverse +/// dominance frontiers for a function. +/// +class DominanceFrontierBase : public FunctionPass { +public: + typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb + typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map +protected: + DomSetMapType Frontiers; + std::vector<BasicBlock*> Roots; + const bool IsPostDominators; + +public: + DominanceFrontierBase(char &ID, bool isPostDom) + : FunctionPass(ID), IsPostDominators(isPostDom) {} + + /// getRoots - Return the root blocks of the current CFG. This may include + /// multiple blocks if we are computing post dominators. For forward + /// dominators, this will always be a single block (the entry node). + /// + inline const std::vector<BasicBlock*> &getRoots() const { return Roots; } + + /// isPostDominator - Returns true if analysis based of postdoms + /// + bool isPostDominator() const { return IsPostDominators; } + + virtual void releaseMemory() { Frontiers.clear(); } + + // Accessor interface: + typedef DomSetMapType::iterator iterator; + typedef DomSetMapType::const_iterator const_iterator; + iterator begin() { return Frontiers.begin(); } + const_iterator begin() const { return Frontiers.begin(); } + iterator end() { return Frontiers.end(); } + const_iterator end() const { return Frontiers.end(); } + iterator find(BasicBlock *B) { return Frontiers.find(B); } + const_iterator find(BasicBlock *B) const { return Frontiers.find(B); } + + iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) { + assert(find(BB) == end() && "Block already in DominanceFrontier!"); + return Frontiers.insert(std::make_pair(BB, frontier)).first; + } + + /// removeBlock - Remove basic block BB's frontier. + void removeBlock(BasicBlock *BB) { + assert(find(BB) != end() && "Block is not in DominanceFrontier!"); + for (iterator I = begin(), E = end(); I != E; ++I) + I->second.erase(BB); + Frontiers.erase(BB); + } + + void addToFrontier(iterator I, BasicBlock *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + I->second.insert(Node); + } + + void removeFromFrontier(iterator I, BasicBlock *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); + I->second.erase(Node); + } + + /// compareDomSet - Return false if two domsets match. Otherwise + /// return true; + bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const { + std::set<BasicBlock *> tmpSet; + for (DomSetType::const_iterator I = DS2.begin(), + E = DS2.end(); I != E; ++I) + tmpSet.insert(*I); + + for (DomSetType::const_iterator I = DS1.begin(), + E = DS1.end(); I != E; ) { + BasicBlock *Node = *I++; + + if (tmpSet.erase(Node) == 0) + // Node is in DS1 but not in DS2. + return true; + } + + if (!tmpSet.empty()) + // There are nodes that are in DS2 but not in DS1. + return true; + + // DS1 and DS2 matches. + return false; + } + + /// compare - Return true if the other dominance frontier base matches + /// this dominance frontier base. Otherwise return false. + bool compare(DominanceFrontierBase &Other) const { + DomSetMapType tmpFrontiers; + for (DomSetMapType::const_iterator I = Other.begin(), + E = Other.end(); I != E; ++I) + tmpFrontiers.insert(std::make_pair(I->first, I->second)); + + for (DomSetMapType::iterator I = tmpFrontiers.begin(), + E = tmpFrontiers.end(); I != E; ) { + BasicBlock *Node = I->first; + const_iterator DFI = find(Node); + if (DFI == end()) + return true; + + if (compareDomSet(I->second, DFI->second)) + return true; + + ++I; + tmpFrontiers.erase(Node); + } + + if (!tmpFrontiers.empty()) + return true; + + return false; + } + + /// print - Convert to human readable form + /// + virtual void print(raw_ostream &OS, const Module* = 0) const; + + /// dump - Dump the dominance frontier to dbgs(). + void dump() const; +}; + + +//===------------------------------------- +/// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is +/// used to compute a forward dominator frontiers. +/// +class DominanceFrontier : public DominanceFrontierBase { +public: + static char ID; // Pass ID, replacement for typeid + DominanceFrontier() : + DominanceFrontierBase(ID, false) { + initializeDominanceFrontierPass(*PassRegistry::getPassRegistry()); + } + + BasicBlock *getRoot() const { + assert(Roots.size() == 1 && "Should always have entry node!"); + return Roots[0]; + } + + virtual bool runOnFunction(Function &) { + Frontiers.clear(); + DominatorTree &DT = getAnalysis<DominatorTree>(); + Roots = DT.getRoots(); + assert(Roots.size() == 1 && "Only one entry block for forward domfronts!"); + calculate(DT, DT[Roots[0]]); + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired<DominatorTree>(); + } + + const DomSetType &calculate(const DominatorTree &DT, + const DomTreeNode *Node); +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/Analysis/DominatorInternals.h b/contrib/llvm/include/llvm/Analysis/DominatorInternals.h index 0419688..ae552b0 100644 --- a/contrib/llvm/include/llvm/Analysis/DominatorInternals.h +++ b/contrib/llvm/include/llvm/Analysis/DominatorInternals.h @@ -22,13 +22,9 @@ // A Fast Algorithm for Finding Dominators in a Flowgraph // T. Lengauer & R. Tarjan, ACM TOPLAS July 1979, pgs 121-141. // -// This implements both the O(n*ack(n)) and the O(n*log(n)) versions of EVAL and -// LINK, but it turns out that the theoretically slower O(n*log(n)) -// implementation is actually faster than the "efficient" algorithm (even for -// large CFGs) because the constant overheads are substantially smaller. The -// lower-complexity version can be enabled with the following #define: -// -#define BALANCE_IDOM_TREE 0 +// This implements the O(n*log(n)) versions of EVAL and LINK, because it turns +// out that the theoretically slower O(n*log(n)) implementation is actually +// faster than the almost-linear O(n*alpha(n)) version, even for large CFGs. // //===----------------------------------------------------------------------===// @@ -46,9 +42,6 @@ unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT, VInfo.Label = V; Vertex.push_back(V); // Vertex[n] = V; - //Info[V].Ancestor = 0; // Ancestor[n] = 0 - //Info[V].Child = 0; // Child[v] = 0 - VInfo.Size = 1; // Size[v] = 1 for (succ_iterator SI = succ_begin(V), E = succ_end(V); SI != E; ++SI) { InfoRec &SuccVInfo = DT.Info[*SI]; @@ -58,10 +51,10 @@ unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT, } } #else - bool IsChilOfArtificialExit = (N != 0); + bool IsChildOfArtificialExit = (N != 0); - std::vector<std::pair<typename GraphT::NodeType*, - typename GraphT::ChildIteratorType> > Worklist; + SmallVector<std::pair<typename GraphT::NodeType*, + typename GraphT::ChildIteratorType>, 32> Worklist; Worklist.push_back(std::make_pair(V, GraphT::child_begin(V))); while (!Worklist.empty()) { typename GraphT::NodeType* BB = Worklist.back().first; @@ -76,14 +69,11 @@ unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT, BBInfo.Label = BB; DT.Vertex.push_back(BB); // Vertex[n] = V; - //BBInfo[V].Ancestor = 0; // Ancestor[n] = 0 - //BBInfo[V].Child = 0; // Child[v] = 0 - BBInfo.Size = 1; // Size[v] = 1 - if (IsChilOfArtificialExit) + if (IsChildOfArtificialExit) BBInfo.Parent = 1; - IsChilOfArtificialExit = false; + IsChildOfArtificialExit = false; } // store the DFS number of the current BB - the reference to BBInfo might @@ -114,118 +104,47 @@ unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT, } template<class GraphT> -void Compress(DominatorTreeBase<typename GraphT::NodeType>& DT, - typename GraphT::NodeType *VIn) { - std::vector<typename GraphT::NodeType*> Work; +typename GraphT::NodeType* +Eval(DominatorTreeBase<typename GraphT::NodeType>& DT, + typename GraphT::NodeType *VIn, unsigned LastLinked) { + typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInInfo = + DT.Info[VIn]; + if (VInInfo.DFSNum < LastLinked) + return VIn; + + SmallVector<typename GraphT::NodeType*, 32> Work; SmallPtrSet<typename GraphT::NodeType*, 32> Visited; - typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInVAInfo = - DT.Info[DT.Vertex[DT.Info[VIn].Ancestor]]; - if (VInVAInfo.Ancestor != 0) + if (VInInfo.Parent >= LastLinked) Work.push_back(VIn); while (!Work.empty()) { typename GraphT::NodeType* V = Work.back(); typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInfo = DT.Info[V]; - typename GraphT::NodeType* VAncestor = DT.Vertex[VInfo.Ancestor]; - typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VAInfo = - DT.Info[VAncestor]; + typename GraphT::NodeType* VAncestor = DT.Vertex[VInfo.Parent]; // Process Ancestor first - if (Visited.insert(VAncestor) && - VAInfo.Ancestor != 0) { + if (Visited.insert(VAncestor) && VInfo.Parent >= LastLinked) { Work.push_back(VAncestor); continue; } Work.pop_back(); // Update VInfo based on Ancestor info - if (VAInfo.Ancestor == 0) + if (VInfo.Parent < LastLinked) continue; + + typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VAInfo = + DT.Info[VAncestor]; typename GraphT::NodeType* VAncestorLabel = VAInfo.Label; typename GraphT::NodeType* VLabel = VInfo.Label; if (DT.Info[VAncestorLabel].Semi < DT.Info[VLabel].Semi) VInfo.Label = VAncestorLabel; - VInfo.Ancestor = VAInfo.Ancestor; - } -} - -template<class GraphT> -typename GraphT::NodeType* -Eval(DominatorTreeBase<typename GraphT::NodeType>& DT, - typename GraphT::NodeType *V) { - typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInfo = - DT.Info[V]; -#if !BALANCE_IDOM_TREE - // Higher-complexity but faster implementation - if (VInfo.Ancestor == 0) - return V; - Compress<GraphT>(DT, V); - return VInfo.Label; -#else - // Lower-complexity but slower implementation - if (VInfo.Ancestor == 0) - return VInfo.Label; - Compress<GraphT>(DT, V); - GraphT::NodeType* VLabel = VInfo.Label; - - GraphT::NodeType* VAncestorLabel = DT.Info[VInfo.Ancestor].Label; - if (DT.Info[VAncestorLabel].Semi >= DT.Info[VLabel].Semi) - return VLabel; - else - return VAncestorLabel; -#endif -} - -template<class GraphT> -void Link(DominatorTreeBase<typename GraphT::NodeType>& DT, - unsigned DFSNumV, typename GraphT::NodeType* W, - typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo) { -#if !BALANCE_IDOM_TREE - // Higher-complexity but faster implementation - WInfo.Ancestor = DFSNumV; -#else - // Lower-complexity but slower implementation - GraphT::NodeType* WLabel = WInfo.Label; - unsigned WLabelSemi = DT.Info[WLabel].Semi; - GraphT::NodeType* S = W; - InfoRec *SInfo = &DT.Info[S]; - - GraphT::NodeType* SChild = SInfo->Child; - InfoRec *SChildInfo = &DT.Info[SChild]; - - while (WLabelSemi < DT.Info[SChildInfo->Label].Semi) { - GraphT::NodeType* SChildChild = SChildInfo->Child; - if (SInfo->Size+DT.Info[SChildChild].Size >= 2*SChildInfo->Size) { - SChildInfo->Ancestor = S; - SInfo->Child = SChild = SChildChild; - SChildInfo = &DT.Info[SChild]; - } else { - SChildInfo->Size = SInfo->Size; - S = SInfo->Ancestor = SChild; - SInfo = SChildInfo; - SChild = SChildChild; - SChildInfo = &DT.Info[SChild]; - } + VInfo.Parent = VAInfo.Parent; } - DominatorTreeBase::InfoRec &VInfo = DT.Info[V]; - SInfo->Label = WLabel; - - assert(V != W && "The optimization here will not work in this case!"); - unsigned WSize = WInfo.Size; - unsigned VSize = (VInfo.Size += WSize); - - if (VSize < 2*WSize) - std::swap(S, VInfo.Child); - - while (S) { - SInfo = &DT.Info[S]; - SInfo->Ancestor = V; - S = SInfo->Child; - } -#endif + return VInInfo.Label; } template<class FuncT, class NodeT> @@ -242,9 +161,6 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, BBInfo.Label = NULL; DT.Vertex.push_back(NULL); // Vertex[n] = V; - //BBInfo[V].Ancestor = 0; // Ancestor[n] = 0 - //BBInfo[V].Child = 0; // Child[v] = 0 - BBInfo.Size = 1; // Size[v] = 1 } // Step #1: Number blocks in depth-first order and initialize variables used @@ -257,12 +173,34 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, // infinite loops). In these cases an artificial exit node is required. MultipleRoots |= (DT.isPostDominator() && N != F.size()); + // When naively implemented, the Lengauer-Tarjan algorithm requires a separate + // bucket for each vertex. However, this is unnecessary, because each vertex + // is only placed into a single bucket (that of its semidominator), and each + // vertex's bucket is processed before it is added to any bucket itself. + // + // Instead of using a bucket per vertex, we use a single array Buckets that + // has two purposes. Before the vertex V with preorder number i is processed, + // Buckets[i] stores the index of the first element in V's bucket. After V's + // bucket is processed, Buckets[i] stores the index of the next element in the + // bucket containing V, if any. + SmallVector<unsigned, 32> Buckets; + Buckets.resize(N + 1); + for (unsigned i = 1; i <= N; ++i) + Buckets[i] = i; + for (unsigned i = N; i >= 2; --i) { typename GraphT::NodeType* W = DT.Vertex[i]; typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo = DT.Info[W]; - // Step #2: Calculate the semidominators of all vertices + // Step #2: Implicitly define the immediate dominator of vertices + for (unsigned j = i; Buckets[j] != i; j = Buckets[j]) { + typename GraphT::NodeType* V = DT.Vertex[Buckets[j]]; + typename GraphT::NodeType* U = Eval<GraphT>(DT, V, i + 1); + DT.IDoms[V] = DT.Info[U].Semi < i ? U : W; + } + + // Step #3: Calculate the semidominators of all vertices // initialize the semi dominator to point to the parent node WInfo.Semi = WInfo.Parent; @@ -272,25 +210,28 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, E = InvTraits::child_end(W); CI != E; ++CI) { typename InvTraits::NodeType *N = *CI; if (DT.Info.count(N)) { // Only if this predecessor is reachable! - unsigned SemiU = DT.Info[Eval<GraphT>(DT, N)].Semi; + unsigned SemiU = DT.Info[Eval<GraphT>(DT, N, i + 1)].Semi; if (SemiU < WInfo.Semi) WInfo.Semi = SemiU; } } - DT.Info[DT.Vertex[WInfo.Semi]].Bucket.push_back(W); - - typename GraphT::NodeType* WParent = DT.Vertex[WInfo.Parent]; - Link<GraphT>(DT, WInfo.Parent, W, WInfo); + // If V is a non-root vertex and sdom(V) = parent(V), then idom(V) is + // necessarily parent(V). In this case, set idom(V) here and avoid placing + // V into a bucket. + if (WInfo.Semi == WInfo.Parent) { + DT.IDoms[W] = DT.Vertex[WInfo.Parent]; + } else { + Buckets[i] = Buckets[WInfo.Semi]; + Buckets[WInfo.Semi] = i; + } + } - // Step #3: Implicitly define the immediate dominator of vertices - std::vector<typename GraphT::NodeType*> &WParentBucket = - DT.Info[WParent].Bucket; - while (!WParentBucket.empty()) { - typename GraphT::NodeType* V = WParentBucket.back(); - WParentBucket.pop_back(); - typename GraphT::NodeType* U = Eval<GraphT>(DT, V); - DT.IDoms[V] = DT.Info[U].Semi < DT.Info[V].Semi ? U : WParent; + if (N >= 1) { + typename GraphT::NodeType* Root = DT.Vertex[1]; + for (unsigned j = 1; Buckets[j] != 1; j = Buckets[j]) { + typename GraphT::NodeType* V = DT.Vertex[Buckets[j]]; + DT.IDoms[V] = Root; } } diff --git a/contrib/llvm/include/llvm/Analysis/Dominators.h b/contrib/llvm/include/llvm/Analysis/Dominators.h index 73c6e62..230e83d 100644 --- a/contrib/llvm/include/llvm/Analysis/Dominators.h +++ b/contrib/llvm/include/llvm/Analysis/Dominators.h @@ -7,14 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file defines the following classes: -// 1. DominatorTree: Represent dominators as an explicit tree structure. -// 2. DominanceFrontier: Calculate and hold the dominance frontier for a -// function. -// -// These data structures are listed in increasing order of complexity. It -// takes longer to calculate the dominator frontier, for example, than the -// DominatorTree mapping. +// This file defines the DominatorTree class, which provides fast and efficient +// dominance queries. // //===----------------------------------------------------------------------===// @@ -23,19 +17,15 @@ #include "llvm/Pass.h" #include "llvm/Function.h" -#include "llvm/Instructions.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Assembly/Writer.h" #include "llvm/Support/CFG.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> -#include <map> -#include <set> namespace llvm { @@ -205,15 +195,11 @@ protected: // Information record used during immediate dominators computation. struct InfoRec { unsigned DFSNum; + unsigned Parent; unsigned Semi; - unsigned Size; - NodeT *Label, *Child; - unsigned Parent, Ancestor; - - std::vector<NodeT*> Bucket; + NodeT *Label; - InfoRec() : DFSNum(0), Semi(0), Size(0), Label(0), Child(0), Parent(0), - Ancestor(0) {} + InfoRec() : DFSNum(0), Parent(0), Semi(0), Label(0) {} }; DenseMap<NodeT*, NodeT*> IDoms; @@ -303,9 +289,6 @@ public: : DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {} virtual ~DominatorTreeBase() { reset(); } - // FIXME: Should remove this - virtual bool runOnFunction(Function &F) { return false; } - /// compare - Return false if the other dominator tree base matches this /// dominator tree base. Otherwise return true. bool compare(DominatorTreeBase &Other) const { @@ -361,8 +344,15 @@ public: return dominatedBySlowTreeWalk(A, B); } - inline bool properlyDominates(NodeT *A, NodeT *B) { - return properlyDominates(getNode(A), getNode(B)); + inline bool properlyDominates(const NodeT *A, const NodeT *B) { + if (A == B) + return false; + + // Cast away the const qualifiers here. This is ok since + // this function doesn't actually return the values returned + // from getNode. + return properlyDominates(getNode(const_cast<NodeT *>(A)), + getNode(const_cast<NodeT *>(B))); } bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A, @@ -377,7 +367,7 @@ public: /// isReachableFromEntry - Return true if A is dominated by the entry /// block of the function containing it. - bool isReachableFromEntry(NodeT* A) { + bool isReachableFromEntry(const NodeT* A) { assert(!this->isPostDominator() && "This is not implemented for post dominators"); return dominates(&A->getParent()->front(), A); @@ -478,6 +468,13 @@ public: return NULL; } + const NodeT *findNearestCommonDominator(const NodeT *A, const NodeT *B) { + // Cast away the const qualifiers here. This is ok since + // const is re-introduced on the return type. + return findNearestCommonDominator(const_cast<NodeT *>(A), + const_cast<NodeT *>(B)); + } + //===--------------------------------------------------------------------===// // API to update (Post)DominatorTree information based on modifications to // the CFG... @@ -509,7 +506,7 @@ public: } /// eraseNode - Removes a node from the dominator tree. Block must not - /// domiante any other blocks. Removes node from its immediate dominator's + /// dominate any other blocks. Removes node from its immediate dominator's /// children list. Deletes dominator node associated with basic block BB. void eraseNode(NodeT *BB) { DomTreeNodeBase<NodeT> *Node = getNode(BB); @@ -556,7 +553,7 @@ public: o << "Inorder PostDominator Tree: "; else o << "Inorder Dominator Tree: "; - if (this->DFSInfoValid) + if (!this->DFSInfoValid) o << "DFSNumbers invalid: " << SlowQueries << " slow queries."; o << "\n"; @@ -567,18 +564,10 @@ public: protected: template<class GraphT> - friend void Compress(DominatorTreeBase<typename GraphT::NodeType>& DT, - typename GraphT::NodeType* VIn); - - template<class GraphT> friend typename GraphT::NodeType* Eval( DominatorTreeBase<typename GraphT::NodeType>& DT, - typename GraphT::NodeType* V); - - template<class GraphT> - friend void Link(DominatorTreeBase<typename GraphT::NodeType>& DT, - unsigned DFSNumV, typename GraphT::NodeType* W, - typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo); + typename GraphT::NodeType* V, + unsigned LastLinked); template<class GraphT> friend unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT, @@ -703,6 +692,7 @@ public: DominatorTreeBase<BasicBlock>* DT; DominatorTree() : FunctionPass(ID) { + initializeDominatorTreePass(*PassRegistry::getPassRegistry()); DT = new DominatorTreeBase<BasicBlock>(false); } @@ -751,7 +741,7 @@ public: AU.setPreservesAll(); } - inline bool dominates(DomTreeNode* A, DomTreeNode* B) const { + inline bool dominates(const DomTreeNode* A, const DomTreeNode* B) const { return DT->dominates(A, B); } @@ -767,7 +757,7 @@ public: return DT->properlyDominates(A, B); } - bool properlyDominates(BasicBlock *A, BasicBlock *B) const { + bool properlyDominates(const BasicBlock *A, const BasicBlock *B) const { return DT->properlyDominates(A, B); } @@ -777,6 +767,11 @@ public: return DT->findNearestCommonDominator(A, B); } + inline const BasicBlock *findNearestCommonDominator(const BasicBlock *A, + const BasicBlock *B) { + return DT->findNearestCommonDominator(A, B); + } + inline DomTreeNode *operator[](BasicBlock *BB) const { return DT->getNode(BB); } @@ -807,7 +802,7 @@ public: } /// eraseNode - Removes a node from the dominator tree. Block must not - /// domiante any other blocks. Removes node from its immediate dominator's + /// dominate any other blocks. Removes node from its immediate dominator's /// children list. Deletes dominator node associated with basic block BB. inline void eraseNode(BasicBlock *BB) { DT->eraseNode(BB); @@ -819,7 +814,7 @@ public: DT->splitBlock(NewBB); } - bool isReachableFromEntry(BasicBlock* A) { + bool isReachableFromEntry(const BasicBlock* A) { return DT->isReachableFromEntry(A); } @@ -876,194 +871,6 @@ template <> struct GraphTraits<DominatorTree*> }; -//===----------------------------------------------------------------------===// -/// DominanceFrontierBase - Common base class for computing forward and inverse -/// dominance frontiers for a function. -/// -class DominanceFrontierBase : public FunctionPass { -public: - typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb - typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map -protected: - DomSetMapType Frontiers; - std::vector<BasicBlock*> Roots; - const bool IsPostDominators; - -public: - DominanceFrontierBase(char &ID, bool isPostDom) - : FunctionPass(ID), IsPostDominators(isPostDom) {} - - /// getRoots - Return the root blocks of the current CFG. This may include - /// multiple blocks if we are computing post dominators. For forward - /// dominators, this will always be a single block (the entry node). - /// - inline const std::vector<BasicBlock*> &getRoots() const { return Roots; } - - /// isPostDominator - Returns true if analysis based of postdoms - /// - bool isPostDominator() const { return IsPostDominators; } - - virtual void releaseMemory() { Frontiers.clear(); } - - // Accessor interface: - typedef DomSetMapType::iterator iterator; - typedef DomSetMapType::const_iterator const_iterator; - iterator begin() { return Frontiers.begin(); } - const_iterator begin() const { return Frontiers.begin(); } - iterator end() { return Frontiers.end(); } - const_iterator end() const { return Frontiers.end(); } - iterator find(BasicBlock *B) { return Frontiers.find(B); } - const_iterator find(BasicBlock *B) const { return Frontiers.find(B); } - - iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) { - assert(find(BB) == end() && "Block already in DominanceFrontier!"); - return Frontiers.insert(std::make_pair(BB, frontier)).first; - } - - /// removeBlock - Remove basic block BB's frontier. - void removeBlock(BasicBlock *BB) { - assert(find(BB) != end() && "Block is not in DominanceFrontier!"); - for (iterator I = begin(), E = end(); I != E; ++I) - I->second.erase(BB); - Frontiers.erase(BB); - } - - void addToFrontier(iterator I, BasicBlock *Node) { - assert(I != end() && "BB is not in DominanceFrontier!"); - I->second.insert(Node); - } - - void removeFromFrontier(iterator I, BasicBlock *Node) { - assert(I != end() && "BB is not in DominanceFrontier!"); - assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); - I->second.erase(Node); - } - - /// compareDomSet - Return false if two domsets match. Otherwise - /// return true; - bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const { - std::set<BasicBlock *> tmpSet; - for (DomSetType::const_iterator I = DS2.begin(), - E = DS2.end(); I != E; ++I) - tmpSet.insert(*I); - - for (DomSetType::const_iterator I = DS1.begin(), - E = DS1.end(); I != E; ) { - BasicBlock *Node = *I++; - - if (tmpSet.erase(Node) == 0) - // Node is in DS1 but not in DS2. - return true; - } - - if (!tmpSet.empty()) - // There are nodes that are in DS2 but not in DS1. - return true; - - // DS1 and DS2 matches. - return false; - } - - /// compare - Return true if the other dominance frontier base matches - /// this dominance frontier base. Otherwise return false. - bool compare(DominanceFrontierBase &Other) const { - DomSetMapType tmpFrontiers; - for (DomSetMapType::const_iterator I = Other.begin(), - E = Other.end(); I != E; ++I) - tmpFrontiers.insert(std::make_pair(I->first, I->second)); - - for (DomSetMapType::iterator I = tmpFrontiers.begin(), - E = tmpFrontiers.end(); I != E; ) { - BasicBlock *Node = I->first; - const_iterator DFI = find(Node); - if (DFI == end()) - return true; - - if (compareDomSet(I->second, DFI->second)) - return true; - - ++I; - tmpFrontiers.erase(Node); - } - - if (!tmpFrontiers.empty()) - return true; - - return false; - } - - /// print - Convert to human readable form - /// - virtual void print(raw_ostream &OS, const Module* = 0) const; - - /// dump - Dump the dominance frontier to dbgs(). - void dump() const; -}; - - -//===------------------------------------- -/// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is -/// used to compute a forward dominator frontiers. -/// -class DominanceFrontier : public DominanceFrontierBase { -public: - static char ID; // Pass ID, replacement for typeid - DominanceFrontier() : - DominanceFrontierBase(ID, false) {} - - BasicBlock *getRoot() const { - assert(Roots.size() == 1 && "Should always have entry node!"); - return Roots[0]; - } - - virtual bool runOnFunction(Function &) { - Frontiers.clear(); - DominatorTree &DT = getAnalysis<DominatorTree>(); - Roots = DT.getRoots(); - assert(Roots.size() == 1 && "Only one entry block for forward domfronts!"); - calculate(DT, DT[Roots[0]]); - return false; - } - - virtual void verifyAnalysis() const; - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired<DominatorTree>(); - } - - /// splitBlock - BB is split and now it has one successor. Update dominance - /// frontier to reflect this change. - void splitBlock(BasicBlock *BB); - - /// BasicBlock BB's new dominator is NewBB. Update BB's dominance frontier - /// to reflect this change. - void changeImmediateDominator(BasicBlock *BB, BasicBlock *NewBB, - DominatorTree *DT) { - // NewBB is now dominating BB. Which means BB's dominance - // frontier is now part of NewBB's dominance frontier. However, BB - // itself is not member of NewBB's dominance frontier. - DominanceFrontier::iterator NewDFI = find(NewBB); - DominanceFrontier::iterator DFI = find(BB); - // If BB was an entry block then its frontier is empty. - if (DFI == end()) - return; - DominanceFrontier::DomSetType BBSet = DFI->second; - for (DominanceFrontier::DomSetType::iterator BBSetI = BBSet.begin(), - BBSetE = BBSet.end(); BBSetI != BBSetE; ++BBSetI) { - BasicBlock *DFMember = *BBSetI; - // Insert only if NewBB dominates DFMember. - if (!DT->dominates(NewBB, DFMember)) - NewDFI->second.insert(DFMember); - } - NewDFI->second.erase(BB); - } - - const DomSetType &calculate(const DominatorTree &DT, - const DomTreeNode *Node); -}; - - } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Analysis/FindUsedTypes.h b/contrib/llvm/include/llvm/Analysis/FindUsedTypes.h index 8a78eb6..fc57e1a 100644 --- a/contrib/llvm/include/llvm/Analysis/FindUsedTypes.h +++ b/contrib/llvm/include/llvm/Analysis/FindUsedTypes.h @@ -26,7 +26,9 @@ class FindUsedTypes : public ModulePass { std::set<const Type *> UsedTypes; public: static char ID; // Pass identification, replacement for typeid - FindUsedTypes() : ModulePass(ID) {} + FindUsedTypes() : ModulePass(ID) { + initializeFindUsedTypesPass(*PassRegistry::getPassRegistry()); + } /// getTypes - After the pass has been run, return the set containing all of /// the types used in the module. diff --git a/contrib/llvm/include/llvm/Analysis/InlineCost.h b/contrib/llvm/include/llvm/Analysis/InlineCost.h index 462bddd..b08bf57 100644 --- a/contrib/llvm/include/llvm/Analysis/InlineCost.h +++ b/contrib/llvm/include/llvm/Analysis/InlineCost.h @@ -33,7 +33,7 @@ namespace llvm { namespace InlineConstants { // Various magic constants used to adjust heuristics. const int InstrCost = 5; - const int IndirectCallBonus = 500; + const int IndirectCallBonus = -100; const int CallPenalty = 25; const int LastCallToStaticBonus = -15000; const int ColdccPenalty = 2000; @@ -98,7 +98,8 @@ namespace llvm { unsigned AllocaWeight; ArgInfo(unsigned CWeight, unsigned AWeight) - : ConstantWeight(CWeight), AllocaWeight(AWeight) {} + : ConstantWeight(CWeight), AllocaWeight(AWeight) + {} }; struct FunctionInfo { @@ -110,17 +111,6 @@ namespace llvm { /// entry here. std::vector<ArgInfo> ArgumentWeights; - /// CountCodeReductionForConstant - Figure out an approximation for how - /// many instructions will be constant folded if the specified value is - /// constant. - unsigned CountCodeReductionForConstant(Value *V); - - /// CountCodeReductionForAlloca - Figure out an approximation of how much - /// smaller the function will be if it is inlined into a context where an - /// argument becomes an alloca. - /// - unsigned CountCodeReductionForAlloca(Value *V); - /// analyzeFunction - Add information about the specified function /// to the current structure. void analyzeFunction(Function *F); @@ -134,6 +124,10 @@ namespace llvm { // the ValueMap will update itself when this happens. ValueMap<const Function *, FunctionInfo> CachedFunctionInfo; + int CountBonusForConstant(Value *V, Constant *C = NULL); + int ConstantFunctionBonus(CallSite CS, Constant *C); + int getInlineSize(CallSite CS, Function *Callee); + int getInlineBonuses(CallSite CS, Function *Callee); public: /// getInlineCost - The heuristic used to determine if we should inline the @@ -150,6 +144,18 @@ namespace llvm { Function *Callee, SmallPtrSet<const Function *, 16> &NeverInline); + /// getSpecializationBonus - The heuristic used to determine the per-call + /// performance boost for using a specialization of Callee with argument + /// SpecializedArgNos replaced by a constant. + int getSpecializationBonus(Function *Callee, + SmallVectorImpl<unsigned> &SpecializedArgNo); + + /// getSpecializationCost - The heuristic used to determine the code-size + /// impact of creating a specialized version of Callee with argument + /// SpecializedArgNo replaced by a constant. + InlineCost getSpecializationCost(Function *Callee, + SmallVectorImpl<unsigned> &SpecializedArgNo); + /// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a /// higher threshold to determine if the function call should be inlined. float getInlineFudgeFactor(CallSite CS); diff --git a/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h b/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h index f47e740..dff1ba2 100644 --- a/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h +++ b/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h @@ -7,9 +7,12 @@ // //===----------------------------------------------------------------------===// // -// This file declares routines for folding instructions into simpler forms that -// do not require creating new instructions. For example, this does constant -// folding, and can handle identities like (X&0)->0. +// This file declares routines for folding instructions into simpler forms +// that do not require creating new instructions. This does constant folding +// ("add i32 1, 1" -> "2") but can also handle non-constant operands, either +// returning a constant ("and i32 %x, 0" -> "0") or an already existing value +// ("and i32 %x, %x" -> "%x"). If the simplification is also an instruction +// then it dominates the original instruction. // //===----------------------------------------------------------------------===// @@ -17,6 +20,7 @@ #define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H namespace llvm { + class DominatorTree; class Instruction; class Value; class TargetData; @@ -24,56 +28,106 @@ namespace llvm { /// SimplifyAddInst - Given operands for an Add, see if we can /// fold the result. If not, this returns null. Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, - const TargetData *TD = 0); - + const TargetData *TD = 0, const DominatorTree *DT = 0); + + /// SimplifySubInst - Given operands for a Sub, see if we can + /// fold the result. If not, this returns null. + Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, + const TargetData *TD = 0, const DominatorTree *DT = 0); + + /// SimplifyMulInst - Given operands for a Mul, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyMulInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifySDivInst - Given operands for an SDiv, see if we can + /// fold the result. If not, this returns null. + Value *SimplifySDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyUDivInst - Given operands for a UDiv, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyUDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyFDivInst - Given operands for an FDiv, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyFDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyShlInst - Given operands for a Shl, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, + const TargetData *TD = 0, const DominatorTree *DT = 0); + + /// SimplifyLShrInst - Given operands for a LShr, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, + const TargetData *TD = 0, const DominatorTree *DT=0); + + /// SimplifyAShrInst - Given operands for a AShr, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, + const TargetData *TD = 0, + const DominatorTree *DT = 0); + /// SimplifyAndInst - Given operands for an And, see if we can /// fold the result. If not, this returns null. - Value *SimplifyAndInst(Value *LHS, Value *RHS, - const TargetData *TD = 0); + Value *SimplifyAndInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); /// SimplifyOrInst - Given operands for an Or, see if we can /// fold the result. If not, this returns null. - Value *SimplifyOrInst(Value *LHS, Value *RHS, - const TargetData *TD = 0); - + Value *SimplifyOrInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyXorInst - Given operands for a Xor, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyXorInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const TargetData *TD = 0); - + const TargetData *TD = 0, + const DominatorTree *DT = 0); + /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const TargetData *TD = 0); - + const TargetData *TD = 0, + const DominatorTree *DT = 0); + /// SimplifySelectInst - Given operands for a SelectInst, see if we can fold /// the result. If not, this returns null. Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, - const TargetData *TD = 0); + const TargetData *TD = 0, + const DominatorTree *DT = 0); /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyGEPInst(Value * const *Ops, unsigned NumOps, - const TargetData *TD = 0); - + const TargetData *TD = 0, const DominatorTree *DT = 0); + //=== Helper functions for higher up the class hierarchy. - - + + /// SimplifyCmpInst - Given operands for a CmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const TargetData *TD = 0); - + const TargetData *TD = 0, const DominatorTree *DT = 0); + /// SimplifyBinOp - Given operands for a BinaryOperator, see if we can /// fold the result. If not, this returns null. - Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, - const TargetData *TD = 0); - + Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, + const TargetData *TD = 0, const DominatorTree *DT = 0); + /// SimplifyInstruction - See if we can compute a simplified version of this /// instruction. If not, this returns null. - Value *SimplifyInstruction(Instruction *I, const TargetData *TD = 0); - - + Value *SimplifyInstruction(Instruction *I, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// ReplaceAndSimplifyAllUses - Perform From->replaceAllUsesWith(To) and then /// delete the From instruction. In addition to a basic RAUW, this does a /// recursive simplification of the updated instructions. This catches @@ -81,7 +135,8 @@ namespace llvm { /// simplifies and deletes scalar operations, it does not change the CFG. /// void ReplaceAndSimplifyAllUses(Instruction *From, Value *To, - const TargetData *TD = 0); + const TargetData *TD = 0, + const DominatorTree *DT = 0); } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/Analysis/IntervalPartition.h b/contrib/llvm/include/llvm/Analysis/IntervalPartition.h index 75a5cdf..df7313f 100644 --- a/contrib/llvm/include/llvm/Analysis/IntervalPartition.h +++ b/contrib/llvm/include/llvm/Analysis/IntervalPartition.h @@ -48,7 +48,9 @@ class IntervalPartition : public FunctionPass { public: static char ID; // Pass identification, replacement for typeid - IntervalPartition() : FunctionPass(ID), RootInterval(0) {} + IntervalPartition() : FunctionPass(ID), RootInterval(0) { + initializeIntervalPartitionPass(*PassRegistry::getPassRegistry()); + } // run - Calculate the interval partition for this function virtual bool runOnFunction(Function &F); diff --git a/contrib/llvm/include/llvm/Analysis/LazyValueInfo.h b/contrib/llvm/include/llvm/Analysis/LazyValueInfo.h index b2a3afb..fc4d0af 100644 --- a/contrib/llvm/include/llvm/Analysis/LazyValueInfo.h +++ b/contrib/llvm/include/llvm/Analysis/LazyValueInfo.h @@ -31,7 +31,9 @@ class LazyValueInfo : public FunctionPass { void operator=(const LazyValueInfo&); // DO NOT IMPLEMENT. public: static char ID; - LazyValueInfo() : FunctionPass(ID), PImpl(0) {} + LazyValueInfo() : FunctionPass(ID), PImpl(0) { + initializeLazyValueInfoPass(*PassRegistry::getPassRegistry()); + } ~LazyValueInfo() { assert(PImpl == 0 && "releaseMemory not called"); } /// Tristate - This is used to return true/false/dunno results. diff --git a/contrib/llvm/include/llvm/Analysis/LibCallAliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/LibCallAliasAnalysis.h index c9adf3f..243234b 100644 --- a/contrib/llvm/include/llvm/Analysis/LibCallAliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/LibCallAliasAnalysis.h @@ -28,15 +28,17 @@ namespace llvm { LibCallInfo *LCI; explicit LibCallAliasAnalysis(LibCallInfo *LC = 0) - : FunctionPass(ID), LCI(LC) { + : FunctionPass(ID), LCI(LC) { + initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry()); } explicit LibCallAliasAnalysis(char &ID, LibCallInfo *LC) - : FunctionPass(ID), LCI(LC) { + : FunctionPass(ID), LCI(LC) { + initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry()); } ~LibCallAliasAnalysis(); ModRefResult getModRefInfo(ImmutableCallSite CS, - const Value *P, unsigned Size); + const Location &Loc); ModRefResult getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) { @@ -64,7 +66,7 @@ namespace llvm { private: ModRefResult AnalyzeLibCallDetails(const LibCallFunctionInfo *FI, ImmutableCallSite CS, - const Value *P, unsigned Size); + const Location &Loc); }; } // End of llvm namespace diff --git a/contrib/llvm/include/llvm/Analysis/LibCallSemantics.h b/contrib/llvm/include/llvm/Analysis/LibCallSemantics.h index 31d7cc5..f5a9e96 100644 --- a/contrib/llvm/include/llvm/Analysis/LibCallSemantics.h +++ b/contrib/llvm/include/llvm/Analysis/LibCallSemantics.h @@ -48,7 +48,7 @@ namespace llvm { Yes, No, Unknown }; LocResult (*isLocation)(ImmutableCallSite CS, - const Value *Ptr, unsigned Size); + const AliasAnalysis::Location &Loc); }; /// LibCallFunctionInfo - Each record in the array of FunctionInfo structs diff --git a/contrib/llvm/include/llvm/Analysis/LoopDependenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/LoopDependenceAnalysis.h index 94fd990..f195d27 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopDependenceAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/LoopDependenceAnalysis.h @@ -91,7 +91,9 @@ class LoopDependenceAnalysis : public LoopPass { public: static char ID; // Class identification, replacement for typeinfo - LoopDependenceAnalysis() : LoopPass(ID) {} + LoopDependenceAnalysis() : LoopPass(ID) { + initializeLoopDependenceAnalysisPass(*PassRegistry::getPassRegistry()); + } /// isDependencePair - Check whether two values can possibly give rise to /// a data dependence: that is the case if both are instructions accessing diff --git a/contrib/llvm/include/llvm/Analysis/LoopInfo.h b/contrib/llvm/include/llvm/Analysis/LoopInfo.h index 462620f..392bdad 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopInfo.h +++ b/contrib/llvm/include/llvm/Analysis/LoopInfo.h @@ -32,6 +32,7 @@ #define LLVM_ANALYSIS_LOOP_INFO_H #include "llvm/Pass.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SmallVector.h" @@ -40,6 +41,7 @@ #include "llvm/Support/CFG.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <map> namespace llvm { @@ -53,6 +55,7 @@ static void RemoveFromVector(std::vector<T*> &V, T *N) { class DominatorTree; class LoopInfo; class Loop; +class PHINode; template<class N, class M> class LoopInfoBase; template<class N, class M> class LoopBase; @@ -523,10 +526,9 @@ public: /// bool isLoopInvariant(Value *V) const; - /// isLoopInvariant - Return true if the specified instruction is - /// loop-invariant. - /// - bool isLoopInvariant(Instruction *I) const; + /// hasLoopInvariantOperands - Return true if all the operands of the + /// specified instruction are loop invariant. + bool hasLoopInvariantOperands(Instruction *I) const; /// makeLoopInvariant - If the given value is an instruction inside of the /// loop and it can be hoisted, do so to make it trivially loop-invariant. @@ -630,7 +632,7 @@ private: template<class BlockT, class LoopT> class LoopInfoBase { // BBMap - Mapping of basic blocks to the inner most loop they occur in - std::map<BlockT *, LoopT *> BBMap; + DenseMap<BlockT *, LoopT *> BBMap; std::vector<LoopT *> TopLevelLoops; friend class LoopBase<BlockT, LoopT>; @@ -661,7 +663,7 @@ public: /// block is in no loop (for example the entry node), null is returned. /// LoopT *getLoopFor(const BlockT *BB) const { - typename std::map<BlockT *, LoopT *>::const_iterator I= + typename DenseMap<BlockT *, LoopT *>::const_iterator I= BBMap.find(const_cast<BlockT*>(BB)); return I != BBMap.end() ? I->second : 0; } @@ -729,7 +731,7 @@ public: /// including all of the Loop objects it is nested in and our mapping from /// BasicBlocks to loops. void removeBlock(BlockT *BB) { - typename std::map<BlockT *, LoopT *>::iterator I = BBMap.find(BB); + typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB); if (I != BBMap.end()) { for (LoopT *L = I->second; L; L = L->getParentLoop()) L->removeBlockFromLoop(BB); @@ -923,7 +925,7 @@ public: for (unsigned i = 0; i < TopLevelLoops.size(); ++i) TopLevelLoops[i]->print(OS); #if 0 - for (std::map<BasicBlock*, LoopT*>::const_iterator I = BBMap.begin(), + for (DenseMap<BasicBlock*, LoopT*>::const_iterator I = BBMap.begin(), E = BBMap.end(); I != E; ++I) OS << "BB '" << I->first->getName() << "' level = " << I->second->getLoopDepth() << "\n"; @@ -940,7 +942,9 @@ class LoopInfo : public FunctionPass { public: static char ID; // Pass identification, replacement for typeid - LoopInfo() : FunctionPass(ID) {} + LoopInfo() : FunctionPass(ID) { + initializeLoopInfoPass(*PassRegistry::getPassRegistry()); + } LoopInfoBase<BasicBlock, Loop>& getBase() { return LI; } @@ -1019,6 +1023,27 @@ public: void removeBlock(BasicBlock *BB) { LI.removeBlock(BB); } + + /// replacementPreservesLCSSAForm - Returns true if replacing From with To + /// everywhere is guaranteed to preserve LCSSA form. + bool replacementPreservesLCSSAForm(Instruction *From, Value *To) { + // Preserving LCSSA form is only problematic if the replacing value is an + // instruction. + Instruction *I = dyn_cast<Instruction>(To); + if (!I) return true; + // If both instructions are defined in the same basic block then replacement + // cannot break LCSSA form. + if (I->getParent() == From->getParent()) + return true; + // If the instruction is not defined in a loop then it can safely replace + // anything. + Loop *ToLoop = getLoopFor(I->getParent()); + if (!ToLoop) return true; + // If the replacing instruction is defined in the same loop as the original + // instruction, or in a loop that contains it as an inner loop, then using + // it as a replacement will not break LCSSA form. + return ToLoop->contains(getLoopFor(From->getParent())); + } }; diff --git a/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h b/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h index a4f9162..22493f6 100644 --- a/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -74,6 +74,10 @@ Value *getMallocArraySize(CallInst *CI, const TargetData *TD, /// isFreeCall - Returns non-null if the value is a call to the builtin free() const CallInst *isFreeCall(const Value *I); + +static inline CallInst *isFreeCall(Value *I) { + return const_cast<CallInst*>(isFreeCall((const Value*)I)); +} } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h index f6aab03..4d5dd19 100644 --- a/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -17,6 +17,7 @@ #include "llvm/BasicBlock.h" #include "llvm/Pass.h" #include "llvm/Support/ValueHandle.h" +#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" @@ -46,6 +47,9 @@ namespace llvm { /// pair holds the instruction that clobbers the memory. For example, /// this occurs when we see a may-aliased store to the memory location we /// care about. + /// + /// A dependence query on the first instruction of the entry block will + /// return a clobber(self) result. Clobber, /// Def - This is a dependence on the specified instruction which @@ -132,26 +136,49 @@ namespace llvm { } }; + /// NonLocalDepEntry - This is an entry in the NonLocalDepInfo cache. For + /// each BasicBlock (the BB entry) it keeps a MemDepResult. + class NonLocalDepEntry { + BasicBlock *BB; + MemDepResult Result; + public: + NonLocalDepEntry(BasicBlock *bb, MemDepResult result) + : BB(bb), Result(result) {} + + // This is used for searches. + NonLocalDepEntry(BasicBlock *bb) : BB(bb) {} + + // 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. class NonLocalDepResult { - BasicBlock *BB; - MemDepResult Result; + NonLocalDepEntry Entry; Value *Address; public: NonLocalDepResult(BasicBlock *bb, MemDepResult result, Value *address) - : BB(bb), Result(result), Address(address) {} + : Entry(bb, result), Address(address) {} // BB is the sort key, it can't be changed. - BasicBlock *getBB() const { return BB; } + BasicBlock *getBB() const { return Entry.getBB(); } void setResult(const MemDepResult &R, Value *Addr) { - Result = R; + Entry.setResult(R); Address = Addr; } - const MemDepResult &getResult() const { return Result; } + 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 @@ -163,30 +190,6 @@ namespace llvm { Value *getAddress() const { return Address; } }; - /// NonLocalDepEntry - This is an entry in the NonLocalDepInfo cache. For - /// each BasicBlock (the BB entry) it keeps a MemDepResult. - class NonLocalDepEntry { - BasicBlock *BB; - MemDepResult Result; - public: - NonLocalDepEntry(BasicBlock *bb, MemDepResult result) - : BB(bb), Result(result) {} - - // This is used for searches. - NonLocalDepEntry(BasicBlock *bb) : BB(bb) {} - - // 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; - } - }; - /// 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, @@ -212,7 +215,7 @@ namespace llvm { private: /// ValueIsLoadPair - This is a pair<Value*, bool> where the bool is true if /// the dependence is a read only dependence, false if read/write. - typedef PointerIntPair<Value*, 1, bool> ValueIsLoadPair; + typedef PointerIntPair<const Value*, 1, bool> ValueIsLoadPair; /// BBSkipFirstBlockPair - This pair is used when caching information for a /// block. If the pointer is null, the cache value is not a full query that @@ -220,11 +223,28 @@ namespace llvm { /// or not the contents of the block was skipped. typedef PointerIntPair<BasicBlock*, 1, bool> BBSkipFirstBlockPair; + /// NonLocalPointerInfo - This record is the information kept for each + /// (value, is load) pair. + struct NonLocalPointerInfo { + /// Pair - The pair of the block and the skip-first-block flag. + BBSkipFirstBlockPair Pair; + /// NonLocalDeps - The results of the query for each relevant block. + NonLocalDepInfo NonLocalDeps; + /// Size - The maximum size of the dereferences of the + /// pointer. May be UnknownSize if the sizes are unknown. + uint64_t Size; + /// TBAATag - The TBAA tag associated with dereferences of the + /// pointer. May be null if there are no tags or conflicting tags. + const MDNode *TBAATag; + + NonLocalPointerInfo() : Size(AliasAnalysis::UnknownSize), TBAATag(0) {} + }; + /// CachedNonLocalPointerInfo - This map stores the cached results of doing /// a pointer lookup at the bottom of a block. The key of this map is the /// pointer+isload bit, the value is a list of <bb->result> mappings. - typedef DenseMap<ValueIsLoadPair, std::pair<BBSkipFirstBlockPair, - NonLocalDepInfo> > CachedNonLocalPointerInfo; + typedef DenseMap<ValueIsLoadPair, + NonLocalPointerInfo> CachedNonLocalPointerInfo; CachedNonLocalPointerInfo NonLocalPointerDeps; // A map from instructions to their non-local pointer dependencies. @@ -297,10 +317,10 @@ namespace llvm { /// set of instructions that either define or clobber the value. /// /// This method assumes the pointer has a "NonLocal" dependency within BB. - void getNonLocalPointerDependency(Value *Pointer, bool isLoad, - BasicBlock *BB, + void getNonLocalPointerDependency(const AliasAnalysis::Location &Loc, + bool isLoad, BasicBlock *BB, SmallVectorImpl<NonLocalDepResult> &Result); - + /// removeInstruction - Remove an instruction from the dependence analysis, /// updating the dependence of instructions that previously depended on it. void removeInstruction(Instruction *InstToRemove); @@ -318,20 +338,29 @@ namespace llvm { /// critical edges. void invalidateCachedPredecessors(); - private: - MemDepResult getPointerDependencyFrom(Value *Pointer, uint64_t MemSize, + /// getPointerDependencyFrom - Return the instruction on which a memory + /// location depends. If isLoad is true, this routine ignores may-aliases + /// with read-only operations. If isLoad is false, this routine ignores + /// may-aliases with reads from read-only locations. + /// + /// Note that this is an uncached query, and thus may be inefficient. + /// + MemDepResult getPointerDependencyFrom(const AliasAnalysis::Location &Loc, bool isLoad, BasicBlock::iterator ScanIt, BasicBlock *BB); + + private: MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, BasicBlock::iterator ScanIt, BasicBlock *BB); - bool getNonLocalPointerDepFromBB(const PHITransAddr &Pointer, uint64_t Size, + bool getNonLocalPointerDepFromBB(const PHITransAddr &Pointer, + const AliasAnalysis::Location &Loc, bool isLoad, BasicBlock *BB, SmallVectorImpl<NonLocalDepResult> &Result, DenseMap<BasicBlock*, Value*> &Visited, bool SkipFirstBlock = false); - MemDepResult GetNonLocalInfoForBlock(Value *Pointer, uint64_t PointeeSize, + MemDepResult GetNonLocalInfoForBlock(const AliasAnalysis::Location &Loc, bool isLoad, BasicBlock *BB, NonLocalDepInfo *Cache, unsigned NumSortedEntries); diff --git a/contrib/llvm/include/llvm/Analysis/Passes.h b/contrib/llvm/include/llvm/Analysis/Passes.h index 37425eb..5b0c5b1 100644 --- a/contrib/llvm/include/llvm/Analysis/Passes.h +++ b/contrib/llvm/include/llvm/Analysis/Passes.h @@ -59,7 +59,7 @@ namespace llvm { //===--------------------------------------------------------------------===// // - // createBasicAliasAnalysisPass - This pass implements the default alias + // createBasicAliasAnalysisPass - This pass implements the stateless alias // analysis. // ImmutablePass *createBasicAliasAnalysisPass(); @@ -116,6 +116,28 @@ namespace llvm { //===--------------------------------------------------------------------===// // + // createPathProfileLoaderPass - This pass loads information from a path + // profile dump file. + // + ModulePass *createPathProfileLoaderPass(); + extern char &PathProfileLoaderPassID; + + //===--------------------------------------------------------------------===// + // + // createNoPathProfileInfoPass - This pass implements the default + // "no path profile". + // + ImmutablePass *createNoPathProfileInfoPass(); + + //===--------------------------------------------------------------------===// + // + // createPathProfileVerifierPass - This pass verifies path profiling + // information. + // + ModulePass *createPathProfileVerifierPass(); + + //===--------------------------------------------------------------------===// + // // createDSAAPass - This pass implements simple context sensitive alias // analysis. // @@ -140,7 +162,7 @@ namespace llvm { // createLiveValuesPass - This creates an instance of the LiveValues pass. // FunctionPass *createLiveValuesPass(); - + //===--------------------------------------------------------------------===// // /// createLazyValueInfoPass - This creates an instance of the LazyValueInfo @@ -153,7 +175,7 @@ namespace llvm { // LoopDependenceAnalysis pass. // LoopPass *createLoopDependenceAnalysisPass(); - + // Minor pass prototypes, allowing us to expose them through bugpoint and // analyze. FunctionPass *createInstCountPass(); @@ -170,6 +192,13 @@ namespace llvm { // Print module-level debug info metadata in human-readable form. ModulePass *createModuleDebugInfoPrinterPass(); + + //===--------------------------------------------------------------------===// + // + // createMemDepPrinter - This pass exhaustively collects all memdep + // information and prints it with -analyze. + // + FunctionPass *createMemDepPrinter(); } #endif diff --git a/contrib/llvm/include/llvm/Analysis/PathNumbering.h b/contrib/llvm/include/llvm/Analysis/PathNumbering.h new file mode 100644 index 0000000..7025e28 --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/PathNumbering.h @@ -0,0 +1,304 @@ +//===- PathNumbering.h ----------------------------------------*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Ball-Larus path numbers uniquely identify paths through a directed acyclic +// graph (DAG) [Ball96]. For a CFG backedges are removed and replaced by phony +// edges to obtain a DAG, and thus the unique path numbers [Ball96]. +// +// The purpose of this analysis is to enumerate the edges in a CFG in order +// to obtain paths from path numbers in a convenient manner. As described in +// [Ball96] edges can be enumerated such that given a path number by following +// the CFG and updating the path number, the path is obtained. +// +// [Ball96] +// T. Ball and J. R. Larus. "Efficient Path Profiling." +// International Symposium on Microarchitecture, pages 46-57, 1996. +// http://portal.acm.org/citation.cfm?id=243857 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PATH_NUMBERING_H +#define LLVM_PATH_NUMBERING_H + +#include "llvm/BasicBlock.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Support/CFG.h" +#include "llvm/Analysis/ProfileInfoTypes.h" +#include <map> +#include <stack> +#include <vector> + +namespace llvm { +class BallLarusNode; +class BallLarusEdge; +class BallLarusDag; + +// typedefs for storage/ interators of various DAG components +typedef std::vector<BallLarusNode*> BLNodeVector; +typedef std::vector<BallLarusNode*>::iterator BLNodeIterator; +typedef std::vector<BallLarusEdge*> BLEdgeVector; +typedef std::vector<BallLarusEdge*>::iterator BLEdgeIterator; +typedef std::map<BasicBlock*, BallLarusNode*> BLBlockNodeMap; +typedef std::stack<BallLarusNode*> BLNodeStack; + +// Represents a basic block with information necessary for the BallLarus +// algorithms. +class BallLarusNode { +public: + enum NodeColor { WHITE, GRAY, BLACK }; + + // Constructor: Initializes a new Node for the given BasicBlock + BallLarusNode(BasicBlock* BB) : + _basicBlock(BB), _numberPaths(0), _color(WHITE) { + static unsigned nextUID = 0; + _uid = nextUID++; + } + + // Returns the basic block for the BallLarusNode + BasicBlock* getBlock(); + + // Get/set the number of paths to the exit starting at the node. + unsigned getNumberPaths(); + void setNumberPaths(unsigned numberPaths); + + // Get/set the NodeColor used in graph algorithms. + NodeColor getColor(); + void setColor(NodeColor color); + + // Iterator information for predecessor edges. Includes phony and + // backedges. + BLEdgeIterator predBegin(); + BLEdgeIterator predEnd(); + unsigned getNumberPredEdges(); + + // Iterator information for successor edges. Includes phony and + // backedges. + BLEdgeIterator succBegin(); + BLEdgeIterator succEnd(); + unsigned getNumberSuccEdges(); + + // Add an edge to the predecessor list. + void addPredEdge(BallLarusEdge* edge); + + // Remove an edge from the predecessor list. + void removePredEdge(BallLarusEdge* edge); + + // Add an edge to the successor list. + void addSuccEdge(BallLarusEdge* edge); + + // Remove an edge from the successor list. + void removeSuccEdge(BallLarusEdge* edge); + + // Returns the name of the BasicBlock being represented. If BasicBlock + // is null then returns "<null>". If BasicBlock has no name, then + // "<unnamed>" is returned. Intended for use with debug output. + std::string getName(); + +private: + // The corresponding underlying BB. + BasicBlock* _basicBlock; + + // Holds the predecessor edges of this node. + BLEdgeVector _predEdges; + + // Holds the successor edges of this node. + BLEdgeVector _succEdges; + + // The number of paths from the node to the exit. + unsigned _numberPaths; + + // 'Color' used by graph algorithms to mark the node. + NodeColor _color; + + // Unique ID to ensure naming difference with dotgraphs + unsigned _uid; + + // Removes an edge from an edgeVector. Used by removePredEdge and + // removeSuccEdge. + void removeEdge(BLEdgeVector& v, BallLarusEdge* e); +}; + +// Represents an edge in the Dag. For an edge, v -> w, v is the source, and +// w is the target. +class BallLarusEdge { +public: + enum EdgeType { NORMAL, BACKEDGE, SPLITEDGE, + BACKEDGE_PHONY, SPLITEDGE_PHONY, CALLEDGE_PHONY }; + + // Constructor: Initializes an BallLarusEdge with a source and target. + BallLarusEdge(BallLarusNode* source, BallLarusNode* target, + unsigned duplicateNumber) + : _source(source), _target(target), _weight(0), _edgeType(NORMAL), + _realEdge(NULL), _duplicateNumber(duplicateNumber) {} + + // Returns the source/ target node of this edge. + BallLarusNode* getSource() const; + BallLarusNode* getTarget() const; + + // Sets the type of the edge. + EdgeType getType() const; + + // Gets the type of the edge. + void setType(EdgeType type); + + // Returns the weight of this edge. Used to decode path numbers to + // sequences of basic blocks. + unsigned getWeight(); + + // Sets the weight of the edge. Used during path numbering. + void setWeight(unsigned weight); + + // Gets/sets the phony edge originating at the root. + BallLarusEdge* getPhonyRoot(); + void setPhonyRoot(BallLarusEdge* phonyRoot); + + // Gets/sets the phony edge terminating at the exit. + BallLarusEdge* getPhonyExit(); + void setPhonyExit(BallLarusEdge* phonyExit); + + // Gets/sets the associated real edge if this is a phony edge. + BallLarusEdge* getRealEdge(); + void setRealEdge(BallLarusEdge* realEdge); + + // Returns the duplicate number of the edge. + unsigned getDuplicateNumber(); + +protected: + // Source node for this edge. + BallLarusNode* _source; + + // Target node for this edge. + BallLarusNode* _target; + +private: + // Edge weight cooresponding to path number increments before removing + // increments along a spanning tree. The sum over the edge weights gives + // the path number. + unsigned _weight; + + // Type to represent for what this edge is intended + EdgeType _edgeType; + + // For backedges and split-edges, the phony edge which is linked to the + // root node of the DAG. This contains a path number initialization. + BallLarusEdge* _phonyRoot; + + // For backedges and split-edges, the phony edge which is linked to the + // exit node of the DAG. This contains a path counter increment, and + // potentially a path number increment. + BallLarusEdge* _phonyExit; + + // If this is a phony edge, _realEdge is a link to the back or split + // edge. Otherwise, this is null. + BallLarusEdge* _realEdge; + + // An ID to differentiate between those edges which have the same source + // and destination blocks. + unsigned _duplicateNumber; +}; + +// Represents the Ball Larus DAG for a given Function. Can calculate +// various properties required for instrumentation or analysis. E.g. the +// edge weights that determine the path number. +class BallLarusDag { +public: + // Initializes a BallLarusDag from the CFG of a given function. Must + // call init() after creation, since some initialization requires + // virtual functions. + BallLarusDag(Function &F) + : _root(NULL), _exit(NULL), _function(F) {} + + // Initialization that requires virtual functions which are not fully + // functional in the constructor. + void init(); + + // Frees all memory associated with the DAG. + virtual ~BallLarusDag(); + + // Calculate the path numbers by assigning edge increments as prescribed + // in Ball-Larus path profiling. + void calculatePathNumbers(); + + // Returns the number of paths for the DAG. + unsigned getNumberOfPaths(); + + // Returns the root (i.e. entry) node for the DAG. + BallLarusNode* getRoot(); + + // Returns the exit node for the DAG. + BallLarusNode* getExit(); + + // Returns the function for the DAG. + Function& getFunction(); + + // Clears the node colors. + void clearColors(BallLarusNode::NodeColor color); + +protected: + // All nodes in the DAG. + BLNodeVector _nodes; + + // All edges in the DAG. + BLEdgeVector _edges; + + // All backedges in the DAG. + BLEdgeVector _backEdges; + + // Allows subclasses to determine which type of Node is created. + // Override this method to produce subclasses of BallLarusNode if + // necessary. The destructor of BallLarusDag will call free on each pointer + // created. + virtual BallLarusNode* createNode(BasicBlock* BB); + + // Allows subclasses to determine which type of Edge is created. + // Override this method to produce subclasses of BallLarusEdge if + // necessary. Parameters source and target will have been created by + // createNode and can be cast to the subclass of BallLarusNode* + // returned by createNode. The destructor of BallLarusDag will call free + // on each pointer created. + virtual BallLarusEdge* createEdge(BallLarusNode* source, BallLarusNode* + target, unsigned duplicateNumber); + + // Proxy to node's constructor. Updates the DAG state. + BallLarusNode* addNode(BasicBlock* BB); + + // Proxy to edge's constructor. Updates the DAG state. + BallLarusEdge* addEdge(BallLarusNode* source, BallLarusNode* target, + unsigned duplicateNumber); + +private: + // The root (i.e. entry) node for this DAG. + BallLarusNode* _root; + + // The exit node for this DAG. + BallLarusNode* _exit; + + // The function represented by this DAG. + Function& _function; + + // Processes one node and its imediate edges for building the DAG. + void buildNode(BLBlockNodeMap& inDag, std::stack<BallLarusNode*>& dfsStack); + + // Process an edge in the CFG for DAG building. + void buildEdge(BLBlockNodeMap& inDag, std::stack<BallLarusNode*>& dfsStack, + BallLarusNode* currentNode, BasicBlock* succBB, + unsigned duplicateNumber); + + // The weight on each edge is the increment required along any path that + // contains that edge. + void calculatePathNumbersFrom(BallLarusNode* node); + + // Adds a backedge with its phony edges. Updates the DAG state. + void addBackedge(BallLarusNode* source, BallLarusNode* target, + unsigned duplicateCount); +}; +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Analysis/PathProfileInfo.h b/contrib/llvm/include/llvm/Analysis/PathProfileInfo.h new file mode 100644 index 0000000..263763f --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/PathProfileInfo.h @@ -0,0 +1,113 @@ +//===- PathProfileInfo.h --------------------------------------*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file outlines the interface used by optimizers to load path profiles. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PATHPROFILEINFO_H +#define LLVM_PATHPROFILEINFO_H + +#include "llvm/BasicBlock.h" +#include "llvm/Analysis/PathNumbering.h" +#include <stack> + +namespace llvm { + +class ProfilePath; +class ProfilePathEdge; +class PathProfileInfo; + +typedef std::vector<ProfilePathEdge> ProfilePathEdgeVector; +typedef std::vector<ProfilePathEdge>::iterator ProfilePathEdgeIterator; + +typedef std::vector<BasicBlock*> ProfilePathBlockVector; +typedef std::vector<BasicBlock*>::iterator ProfilePathBlockIterator; + +typedef std::map<unsigned int,ProfilePath*> ProfilePathMap; +typedef std::map<unsigned int,ProfilePath*>::iterator ProfilePathIterator; + +typedef std::map<Function*,unsigned int> FunctionPathCountMap; +typedef std::map<Function*,ProfilePathMap> FunctionPathMap; +typedef std::map<Function*,ProfilePathMap>::iterator FunctionPathIterator; + +class ProfilePathEdge { +public: + ProfilePathEdge(BasicBlock* source, BasicBlock* target, + unsigned duplicateNumber); + + inline unsigned getDuplicateNumber() { return _duplicateNumber; } + inline BasicBlock* getSource() { return _source; } + inline BasicBlock* getTarget() { return _target; } + +protected: + BasicBlock* _source; + BasicBlock* _target; + unsigned _duplicateNumber; +}; + +class ProfilePath { +public: + ProfilePath(unsigned int number, unsigned int count, + double countStdDev, PathProfileInfo* ppi); + + double getFrequency() const; + + inline unsigned int getNumber() const { return _number; } + inline unsigned int getCount() const { return _count; } + inline double getCountStdDev() const { return _countStdDev; } + + ProfilePathEdgeVector* getPathEdges() const; + ProfilePathBlockVector* getPathBlocks() const; + + BasicBlock* getFirstBlockInPath() const; + +private: + unsigned int _number; + unsigned int _count; + double _countStdDev; + + // double pointer back to the profiling info + PathProfileInfo* _ppi; +}; + +// TODO: overload [] operator for getting path +// Add: getFunctionCallCount() +class PathProfileInfo { + public: + PathProfileInfo(); + ~PathProfileInfo(); + + void setCurrentFunction(Function* F); + Function* getCurrentFunction() const; + BasicBlock* getCurrentFunctionEntry(); + + ProfilePath* getPath(unsigned int number); + unsigned int getPotentialPathCount(); + + ProfilePathIterator pathBegin(); + ProfilePathIterator pathEnd(); + unsigned int pathsRun(); + + static char ID; // Pass identification + std::string argList; + +protected: + FunctionPathMap _functionPaths; + FunctionPathCountMap _functionPathCounts; + +private: + BallLarusDag* _currentDag; + Function* _currentFunction; + + friend class ProfilePath; +}; +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Analysis/PointerTracking.h b/contrib/llvm/include/llvm/Analysis/PointerTracking.h deleted file mode 100644 index 6b49e18..0000000 --- a/contrib/llvm/include/llvm/Analysis/PointerTracking.h +++ /dev/null @@ -1,132 +0,0 @@ -//===- PointerTracking.h - Pointer Bounds Tracking --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements tracking of pointer bounds. -// It knows that the libc functions "calloc" and "realloc" allocate memory, thus -// you should avoid using this pass if they mean something else for your -// language. -// -// All methods assume that the pointer is not NULL, if it is then the returned -// allocation size is wrong, and the result from checkLimits is wrong too. -// It also assumes that pointers are valid, and that it is not analyzing a -// use-after-free scenario. -// Due to these limitations the "size" returned by these methods should be -// considered as either 0 or the returned size. -// -// Another analysis pass should be used to find use-after-free/NULL dereference -// bugs. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_POINTERTRACKING_H -#define LLVM_ANALYSIS_POINTERTRACKING_H - -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Analysis/Dominators.h" -#include "llvm/Instructions.h" -#include "llvm/Pass.h" -#include "llvm/Support/PredIteratorCache.h" - -namespace llvm { - class DominatorTree; - class ScalarEvolution; - class SCEV; - class Loop; - class LoopInfo; - class TargetData; - - // Result from solver, assuming pointer is not NULL, - // and it is not a use-after-free situation. - enum SolverResult { - AlwaysFalse,// always false with above constraints - AlwaysTrue,// always true with above constraints - Unknown // it can sometimes be true, sometimes false, or it is undecided - }; - - class PointerTracking : public FunctionPass { - public: - typedef ICmpInst::Predicate Predicate; - static char ID; - PointerTracking(); - - virtual bool doInitialization(Module &M); - - // If this pointer directly points to an allocation, return - // the number of elements of type Ty allocated. - // Otherwise return CouldNotCompute. - // Since allocations can fail by returning NULL, the real element count - // for every allocation is either 0 or the value returned by this function. - const SCEV *getAllocationElementCount(Value *P) const; - - // Same as getAllocationSize() but returns size in bytes. - // We consider one byte as 8 bits. - const SCEV *getAllocationSizeInBytes(Value *V) const; - - // Given a Pointer, determine a base pointer of known size, and an offset - // therefrom. - // When unable to determine, sets Base to NULL, and Limit/Offset to - // CouldNotCompute. - // BaseSize, and Offset are in bytes: Pointer == Base + Offset - void getPointerOffset(Value *Pointer, Value *&Base, const SCEV *& BaseSize, - const SCEV *&Offset) const; - - // Compares the 2 scalar evolution expressions according to predicate, - // and if it can prove that the result is always true or always false - // return AlwaysTrue/AlwaysFalse. Otherwise it returns Unknown. - enum SolverResult compareSCEV(const SCEV *A, Predicate Pred, const SCEV *B, - const Loop *L); - - // Determines whether the condition LHS <Pred> RHS is sufficient - // for the condition A <Pred> B to hold. - // Currently only ULT/ULE is supported. - // This errs on the side of returning false. - bool conditionSufficient(const SCEV *LHS, Predicate Pred1, const SCEV *RHS, - const SCEV *A, Predicate Pred2, const SCEV *B, - const Loop *L); - - // Determines whether Offset is known to be always in [0, Limit) bounds. - // This errs on the side of returning Unknown. - enum SolverResult checkLimits(const SCEV *Offset, const SCEV *Limit, - BasicBlock *BB); - - virtual bool runOnFunction(Function &F); - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - void print(raw_ostream &OS, const Module* = 0) const; - Value *computeAllocationCountValue(Value *P, const Type *&Ty) const; - private: - Function *FF; - TargetData *TD; - ScalarEvolution *SE; - LoopInfo *LI; - DominatorTree *DT; - - Function *callocFunc; - Function *reallocFunc; - PredIteratorCache predCache; - - SmallPtrSet<const SCEV*, 1> analyzing; - - enum SolverResult isLoopGuardedBy(const Loop *L, Predicate Pred, - const SCEV *A, const SCEV *B) const; - static bool isMonotonic(const SCEV *S); - bool scevPositive(const SCEV *A, const Loop *L, bool strict=true) const; - bool conditionSufficient(Value *Cond, bool negated, - const SCEV *A, Predicate Pred, const SCEV *B); - Value *getConditionToReach(BasicBlock *A, - DomTreeNodeBase<BasicBlock> *B, - bool &negated); - Value *getConditionToReach(BasicBlock *A, - BasicBlock *B, - bool &negated); - const SCEV *computeAllocationCount(Value *P, const Type *&Ty) const; - const SCEV *computeAllocationCountForType(Value *P, const Type *Ty) const; - }; -} -#endif - diff --git a/contrib/llvm/include/llvm/Analysis/PostDominators.h b/contrib/llvm/include/llvm/Analysis/PostDominators.h index 46ce820..2cd6ae3 100644 --- a/contrib/llvm/include/llvm/Analysis/PostDominators.h +++ b/contrib/llvm/include/llvm/Analysis/PostDominators.h @@ -14,7 +14,7 @@ #ifndef LLVM_ANALYSIS_POST_DOMINATORS_H #define LLVM_ANALYSIS_POST_DOMINATORS_H -#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/DominanceFrontier.h" namespace llvm { @@ -26,6 +26,7 @@ struct PostDominatorTree : public FunctionPass { DominatorTreeBase<BasicBlock>* DT; PostDominatorTree() : FunctionPass(ID) { + initializePostDominatorTreePass(*PassRegistry::getPassRegistry()); DT = new DominatorTreeBase<BasicBlock>(true); } @@ -106,7 +107,9 @@ template <> struct GraphTraits<PostDominatorTree*> struct PostDominanceFrontier : public DominanceFrontierBase { static char ID; PostDominanceFrontier() - : DominanceFrontierBase(ID, true) {} + : DominanceFrontierBase(ID, true) { + initializePostDominanceFrontierPass(*PassRegistry::getPassRegistry()); + } virtual bool runOnFunction(Function &) { Frontiers.clear(); diff --git a/contrib/llvm/include/llvm/Analysis/ProfileInfoTypes.h b/contrib/llvm/include/llvm/Analysis/ProfileInfoTypes.h index 0d531d5..6b4ac85 100644 --- a/contrib/llvm/include/llvm/Analysis/ProfileInfoTypes.h +++ b/contrib/llvm/include/llvm/Analysis/ProfileInfoTypes.h @@ -1,4 +1,4 @@ -/*===-- ProfileInfoTypes.h - Profiling info shared constants ------*- C -*-===*\ +/*===-- ProfileInfoTypes.h - Profiling info shared constants --------------===*\ |* |* The LLVM Compiler Infrastructure |* @@ -16,6 +16,17 @@ #ifndef LLVM_ANALYSIS_PROFILEINFOTYPES_H #define LLVM_ANALYSIS_PROFILEINFOTYPES_H +/* Included by libprofile. */ +#if defined(__cplusplus) +extern "C" { +#endif + +/* IDs to distinguish between those path counters stored in hashses vs arrays */ +enum ProfilingStorageType { + ProfilingArray = 1, + ProfilingHash = 2 +}; + enum ProfilingType { ArgumentInfo = 1, /* The command line argument block */ FunctionInfo = 2, /* Function profiling information */ @@ -26,4 +37,24 @@ enum ProfilingType { OptEdgeInfo = 7 /* Edge profiling information, optimal version */ }; +/* + * The header for tables that map path numbers to path counters. + */ +typedef struct { + unsigned fnNumber; /* function number for these counters */ + unsigned numEntries; /* number of entries stored */ +} PathProfileHeader; + +/* + * Describes an entry in a tagged table for path counters. + */ +typedef struct { + unsigned pathNumber; + unsigned pathCounter; +} PathProfileTableEntry; + +#if defined(__cplusplus) +} +#endif + #endif /* LLVM_ANALYSIS_PROFILEINFOTYPES_H */ diff --git a/contrib/llvm/include/llvm/Analysis/RegionInfo.h b/contrib/llvm/include/llvm/Analysis/RegionInfo.h index 7a2670f..a36ca11 100644 --- a/contrib/llvm/include/llvm/Analysis/RegionInfo.h +++ b/contrib/llvm/include/llvm/Analysis/RegionInfo.h @@ -58,6 +58,7 @@ class RegionNode { // DO NOT IMPLEMENT const RegionNode &operator=(const RegionNode &); +protected: /// This is the entry basic block that starts this region node. If this is a /// BasicBlock RegionNode, then entry is just the basic block, that this /// RegionNode represents. Otherwise it is the entry of this (Sub)RegionNode. @@ -70,7 +71,6 @@ class RegionNode { /// RegionNode. PointerIntPair<BasicBlock*, 1, bool> entry; -protected: /// @brief The parent Region of this RegionNode. /// @see getParent() Region* parent; @@ -257,6 +257,18 @@ public: /// @return The entry BasicBlock of the region. BasicBlock *getEntry() const { return RegionNode::getEntry(); } + /// @brief Replace the entry basic block of the region with the new basic + /// block. + /// + /// @param BB The new entry basic block of the region. + void replaceEntry(BasicBlock *BB); + + /// @brief Replace the exit basic block of the region with the new basic + /// block. + /// + /// @param BB The new exit basic block of the region. + void replaceExit(BasicBlock *BB); + /// @brief Get the exit BasicBlock of the Region. /// @return The exit BasicBlock of the Region, NULL if this is the TopLevel /// Region. @@ -280,6 +292,33 @@ public: /// @return The depth of the region. unsigned getDepth() const; + /// @brief Check if a Region is the TopLevel region. + /// + /// The toplevel region represents the whole function. + bool isTopLevelRegion() const { return exit == NULL; } + + /// @brief Return a new (non canonical) region, that is obtained by joining + /// this region with its predecessors. + /// + /// @return A region also starting at getEntry(), but reaching to the next + /// basic block that forms with getEntry() a (non canonical) region. + /// NULL if such a basic block does not exist. + Region *getExpandedRegion() const; + + /// @brief Return the first block of this region's single entry edge, + /// if existing. + /// + /// @return The BasicBlock starting this region's single entry edge, + /// else NULL. + BasicBlock *getEnteringBlock() const; + + /// @brief Return the first block of this region's single exit edge, + /// if existing. + /// + /// @return The BasicBlock starting this region's single exit edge, + /// else NULL. + BasicBlock *getExitingBlock() const; + /// @brief Is this a simple region? /// /// A region is simple if it has exactly one exit and one entry edge. @@ -386,7 +425,9 @@ public: /// @brief Add a new subregion to this Region. /// /// @param SubRegion The new subregion that will be added. - void addSubRegion(Region *SubRegion); + /// @param moveChildren Move the children of this region, that are also + /// contained in SubRegion into SubRegion. + void addSubRegion(Region *SubRegion, bool moveChildren = false); /// @brief Remove a subregion from this Region. /// @@ -565,6 +606,12 @@ public: /// region containing BB. Region *getRegionFor(BasicBlock *BB) const; + /// @brief Set the smallest region that surrounds a basic block. + /// + /// @param BB The basic block surrounded by a region. + /// @param R The smallest region that surrounds BB. + void setRegionFor(BasicBlock *BB, Region *R); + /// @brief A shortcut for getRegionFor(). /// /// @param BB The basic block. @@ -610,6 +657,12 @@ public: return TopLevelRegion; } + /// @brief Update RegionInfo after a basic block was split. + /// + /// @param NewBB The basic block that was created before OldBB. + /// @param OldBB The old basic block. + void splitBlock(BasicBlock* NewBB, BasicBlock *OldBB); + /// @brief Clear the Node Cache for all Regions. /// /// @see Region::clearNodeCache() diff --git a/contrib/llvm/include/llvm/Analysis/RegionPass.h b/contrib/llvm/include/llvm/Analysis/RegionPass.h new file mode 100644 index 0000000..aedc06a --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/RegionPass.h @@ -0,0 +1,126 @@ +//===- RegionPass.h - RegionPass class ------------------------------------===// +// +// 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 RegionPass class. All region based analysis, +// optimization and transformation passes are derived from RegionPass. +// This class is implemented following the some ideas of the LoopPass.h class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_REGION_PASS_H +#define LLVM_REGION_PASS_H + +#include "llvm/Analysis/RegionInfo.h" + +#include "llvm/Pass.h" +#include "llvm/PassManagers.h" +#include "llvm/Function.h" + +#include <deque> + +namespace llvm { + +class RGPassManager; +class Function; + +//===----------------------------------------------------------------------===// +/// @brief A pass that runs on each Region in a function. +/// +/// RegionPass is managed by RGPassManager. +class RegionPass : public Pass { +public: + explicit RegionPass(char &pid) : Pass(PT_Region, pid) {} + + //===--------------------------------------------------------------------===// + /// @name To be implemented by every RegionPass + /// + //@{ + /// @brief Run the pass on a specific Region + /// + /// Accessing regions not contained in the current region is not allowed. + /// + /// @param R The region this pass is run on. + /// @param RGM The RegionPassManager that manages this Pass. + /// + /// @return True if the pass modifies this Region. + virtual bool runOnRegion(Region *R, RGPassManager &RGM) = 0; + + /// @brief Get a pass to print the LLVM IR in the region. + /// + /// @param O The ouput stream to print the Region. + /// @param Banner The banner to seperate different printed passes. + /// + /// @return The pass to print the LLVM IR in the region. + Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + + virtual bool doInitialization(Region *R, RGPassManager &RGM) { return false; } + virtual bool doFinalization() { return false; } + //@} + + //===--------------------------------------------------------------------===// + /// @name PassManager API + /// + //@{ + void preparePassManager(PMStack &PMS); + + virtual void assignPassManager(PMStack &PMS, + PassManagerType PMT = PMT_RegionPassManager); + + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_RegionPassManager; + } + //@} +}; + +/// @brief The pass manager to schedule RegionPasses. +class RGPassManager : public FunctionPass, public PMDataManager { + std::deque<Region*> RQ; + bool skipThisRegion; + bool redoThisRegion; + RegionInfo *RI; + Region *CurrentRegion; + +public: + static char ID; + explicit RGPassManager(int Depth); + + /// @brief Execute all of the passes scheduled for execution. + /// + /// @return True if any of the passes modifies the function. + bool runOnFunction(Function &F); + + /// Pass Manager itself does not invalidate any analysis info. + /// RGPassManager needs RegionInfo. + void getAnalysisUsage(AnalysisUsage &Info) const; + + virtual const char *getPassName() const { + return "Region Pass Manager"; + } + + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + + /// @brief Print passes managed by this manager. + void dumpPassStructure(unsigned Offset); + + /// @brief Print passes contained by this manager. + Pass *getContainedPass(unsigned N) { + assert(N < PassVector.size() && "Pass number out of range!"); + Pass *FP = static_cast<Pass *>(PassVector[N]); + return FP; + } + + virtual PassManagerType getPassManagerType() const { + return PMT_RegionPassManager; + } +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h index 1fa94e9..d193806 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -24,7 +24,7 @@ #include "llvm/Pass.h" #include "llvm/Instructions.h" #include "llvm/Function.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/ValueHandle.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ConstantRange.h" @@ -70,27 +70,16 @@ namespace llvm { private: SCEV(const SCEV &); // DO NOT IMPLEMENT void operator=(const SCEV &); // DO NOT IMPLEMENT - protected: - virtual ~SCEV(); + public: explicit SCEV(const FoldingSetNodeIDRef ID, unsigned SCEVTy) : FastID(ID), SCEVType(SCEVTy), SubclassData(0) {} unsigned getSCEVType() const { return SCEVType; } - /// isLoopInvariant - Return true if the value of this SCEV is unchanging in - /// the specified loop. - virtual bool isLoopInvariant(const Loop *L) const = 0; - - /// hasComputableLoopEvolution - Return true if this SCEV changes value in a - /// known way in the specified loop. This property being true implies that - /// the value is variant in the loop AND that we can emit an expression to - /// compute the value of the expression at any particular loop iteration. - virtual bool hasComputableLoopEvolution(const Loop *L) const = 0; - /// getType - Return the LLVM type of this SCEV expression. /// - virtual const Type *getType() const = 0; + const Type *getType() const; /// isZero - Return true if the expression is a constant zero. /// @@ -105,22 +94,10 @@ namespace llvm { /// bool isAllOnesValue() const; - /// hasOperand - Test whether this SCEV has Op as a direct or - /// indirect operand. - virtual bool hasOperand(const SCEV *Op) const = 0; - - /// dominates - Return true if elements that makes up this SCEV dominates - /// the specified basic block. - virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const = 0; - - /// properlyDominates - Return true if elements that makes up this SCEV - /// properly dominate the specified basic block. - virtual bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const = 0; - /// print - Print out the internal representation of this scalar to the /// specified stream. This should really only be used for debugging /// purposes. - virtual void print(raw_ostream &OS) const = 0; + void print(raw_ostream &OS) const; /// dump - This method is used for debugging. /// @@ -155,21 +132,6 @@ namespace llvm { struct SCEVCouldNotCompute : public SCEV { SCEVCouldNotCompute(); - // None of these methods are valid for this object. - virtual bool isLoopInvariant(const Loop *L) const; - virtual const Type *getType() const; - virtual bool hasComputableLoopEvolution(const Loop *L) const; - virtual void print(raw_ostream &OS) const; - virtual bool hasOperand(const SCEV *Op) const; - - virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const { - return true; - } - - virtual bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const { - return true; - } - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVCouldNotCompute *S) { return true; } static bool classof(const SCEV *S); @@ -180,6 +142,24 @@ namespace llvm { /// they must ask this class for services. /// class ScalarEvolution : public FunctionPass { + public: + /// LoopDisposition - An enum describing the relationship between a + /// SCEV and a loop. + enum LoopDisposition { + LoopVariant, ///< The SCEV is loop-variant (unknown). + LoopInvariant, ///< The SCEV is loop-invariant. + LoopComputable ///< The SCEV varies predictably with the loop. + }; + + /// BlockDisposition - An enum describing the relationship between a + /// SCEV and a basic block. + enum BlockDisposition { + DoesNotDominateBlock, ///< The SCEV does not dominate the block. + DominatesBlock, ///< The SCEV dominates the block. + ProperlyDominatesBlock ///< The SCEV properly dominates the block. + }; + + private: /// SCEVCallbackVH - A CallbackVH to arrange for ScalarEvolution to be /// notified whenever a Value is deleted. class SCEVCallbackVH : public CallbackVH { @@ -267,6 +247,46 @@ namespace llvm { std::map<const SCEV *, std::map<const Loop *, const SCEV *> > ValuesAtScopes; + /// LoopDispositions - Memoized computeLoopDisposition results. + std::map<const SCEV *, + std::map<const Loop *, LoopDisposition> > LoopDispositions; + + /// computeLoopDisposition - Compute a LoopDisposition value. + LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L); + + /// BlockDispositions - Memoized computeBlockDisposition results. + std::map<const SCEV *, + std::map<const BasicBlock *, BlockDisposition> > BlockDispositions; + + /// computeBlockDisposition - Compute a BlockDisposition value. + BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB); + + /// UnsignedRanges - Memoized results from getUnsignedRange + DenseMap<const SCEV *, ConstantRange> UnsignedRanges; + + /// SignedRanges - Memoized results from getSignedRange + DenseMap<const SCEV *, ConstantRange> SignedRanges; + + /// setUnsignedRange - Set the memoized unsigned range for the given SCEV. + const ConstantRange &setUnsignedRange(const SCEV *S, + const ConstantRange &CR) { + std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair = + UnsignedRanges.insert(std::make_pair(S, CR)); + if (!Pair.second) + Pair.first->second = CR; + return Pair.first->second; + } + + /// setUnsignedRange - Set the memoized signed range for the given SCEV. + const ConstantRange &setSignedRange(const SCEV *S, + const ConstantRange &CR) { + std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair = + SignedRanges.insert(std::make_pair(S, CR)); + if (!Pair.second) + Pair.first->second = CR; + return Pair.first->second; + } + /// createSCEV - We know that there is no SCEV for the specified value. /// Analyze the expression. const SCEV *createSCEV(Value *V); @@ -408,6 +428,9 @@ namespace llvm { bool isKnownPredicateWithRanges(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS); + /// forgetMemoizedResults - Drop memoized information computed for S. + void forgetMemoizedResults(const SCEV *S); + public: static char ID; // Pass identification, replacement for typeid ScalarEvolution(); @@ -514,10 +537,11 @@ namespace llvm { /// const SCEV *getNotSCEV(const SCEV *V); - /// getMinusSCEV - Return LHS-RHS. - /// - const SCEV *getMinusSCEV(const SCEV *LHS, - const SCEV *RHS); + /// getMinusSCEV - Return LHS-RHS. Minus is represented in SCEV as A+B*-1, + /// and thus the HasNUW and HasNSW bits apply to the resultant add, not + /// whether the sub would have overflowed. + const SCEV *getMinusSCEV(const SCEV *LHS, const SCEV *RHS, + bool HasNUW = false, bool HasNSW = false); /// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion /// of the input value to the specified type. If the type must be @@ -675,6 +699,36 @@ namespace llvm { const SCEV *&LHS, const SCEV *&RHS); + /// getLoopDisposition - Return the "disposition" of the given SCEV with + /// respect to the given loop. + LoopDisposition getLoopDisposition(const SCEV *S, const Loop *L); + + /// isLoopInvariant - Return true if the value of the given SCEV is + /// unchanging in the specified loop. + bool isLoopInvariant(const SCEV *S, const Loop *L); + + /// hasComputableLoopEvolution - Return true if the given SCEV changes value + /// in a known way in the specified loop. This property being true implies + /// that the value is variant in the loop AND that we can emit an expression + /// to compute the value of the expression at any particular loop iteration. + bool hasComputableLoopEvolution(const SCEV *S, const Loop *L); + + /// getLoopDisposition - Return the "disposition" of the given SCEV with + /// respect to the given block. + BlockDisposition getBlockDisposition(const SCEV *S, const BasicBlock *BB); + + /// dominates - Return true if elements that makes up the given SCEV + /// dominate the specified basic block. + bool dominates(const SCEV *S, const BasicBlock *BB); + + /// properlyDominates - Return true if elements that makes up the given SCEV + /// properly dominate the specified basic block. + bool properlyDominates(const SCEV *S, const BasicBlock *BB); + + /// hasOperand - Test whether the given SCEV has Op as a direct or + /// indirect operand. + bool hasOperand(const SCEV *S, const SCEV *Op) const; + virtual bool runOnFunction(Function &F); virtual void releaseMemory(); virtual void getAnalysisUsage(AnalysisUsage &AU) const; diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h index 4b02f82..39d378e 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -35,6 +35,9 @@ namespace llvm { std::set<AssertingVH<Value> > InsertedValues; std::set<AssertingVH<Value> > InsertedPostIncValues; + /// RelevantLoops - A memoization of the "relevant" loop for a given SCEV. + DenseMap<const SCEV *, const Loop *> RelevantLoops; + /// PostIncLoops - Addrecs referring to any of the given loops are expanded /// in post-inc mode. For example, expanding {1,+,1}<L> in post-inc mode /// returns the add instruction that adds one to the phi for {0,+,1}<L>, @@ -168,6 +171,9 @@ namespace llvm { return InsertedValues.count(I) || InsertedPostIncValues.count(I); } + /// getRelevantLoop - Determine the most "relevant" loop for the given SCEV. + const Loop *getRelevantLoop(const SCEV *); + Value *visitConstant(const SCEVConstant *S) { return S->getValue(); } diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h index 4213a28..db432c8 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -42,29 +42,7 @@ namespace llvm { public: ConstantInt *getValue() const { return V; } - virtual bool isLoopInvariant(const Loop *L) const { - return true; - } - - virtual bool hasComputableLoopEvolution(const Loop *L) const { - return false; // Not loop variant - } - - virtual const Type *getType() const; - - virtual bool hasOperand(const SCEV *) const { - return false; - } - - bool dominates(BasicBlock *BB, DominatorTree *DT) const { - return true; - } - - bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const { - return true; - } - - virtual void print(raw_ostream &OS) const; + const Type *getType() const { return V->getType(); } /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVConstant *S) { return true; } @@ -86,23 +64,7 @@ namespace llvm { public: const SCEV *getOperand() const { return Op; } - virtual const Type *getType() const { return Ty; } - - virtual bool isLoopInvariant(const Loop *L) const { - return Op->isLoopInvariant(L); - } - - virtual bool hasComputableLoopEvolution(const Loop *L) const { - return Op->hasComputableLoopEvolution(L); - } - - virtual bool hasOperand(const SCEV *O) const { - return Op == O || Op->hasOperand(O); - } - - virtual bool dominates(BasicBlock *BB, DominatorTree *DT) const; - - virtual bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; + const Type *getType() const { return Ty; } /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVCastExpr *S) { return true; } @@ -124,8 +86,6 @@ namespace llvm { const SCEV *op, const Type *ty); public: - virtual void print(raw_ostream &OS) const; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVTruncateExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -144,8 +104,6 @@ namespace llvm { const SCEV *op, const Type *ty); public: - virtual void print(raw_ostream &OS) const; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVZeroExtendExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -164,8 +122,6 @@ namespace llvm { const SCEV *op, const Type *ty); public: - virtual void print(raw_ostream &OS) const; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVSignExtendExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -202,20 +158,7 @@ namespace llvm { op_iterator op_begin() const { return Operands; } op_iterator op_end() const { return Operands + NumOperands; } - virtual bool isLoopInvariant(const Loop *L) const; - - // hasComputableLoopEvolution - N-ary expressions have computable loop - // evolutions iff they have at least one operand that varies with the loop, - // but that all varying operands are computable. - virtual bool hasComputableLoopEvolution(const Loop *L) const; - - virtual bool hasOperand(const SCEV *O) const; - - bool dominates(BasicBlock *BB, DominatorTree *DT) const; - - bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; - - virtual const Type *getType() const { return getOperand(0)->getType(); } + const Type *getType() const { return getOperand(0)->getType(); } bool hasNoUnsignedWrap() const { return SubclassData & (1 << 0); } void setHasNoUnsignedWrap(bool B) { @@ -248,10 +191,6 @@ namespace llvm { : SCEVNAryExpr(ID, T, O, N) {} public: - virtual const char *getOperationStr() const = 0; - - virtual void print(raw_ostream &OS) const; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVCommutativeExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -275,9 +214,7 @@ namespace llvm { } public: - virtual const char *getOperationStr() const { return " + "; } - - virtual const Type *getType() const { + const Type *getType() const { // Use the type of the last operand, which is likely to be a pointer // type, if there is one. This doesn't usually matter, but it can help // reduce casts when the expressions are expanded. @@ -303,8 +240,6 @@ namespace llvm { } public: - virtual const char *getOperationStr() const { return " * "; } - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVMulExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -328,27 +263,15 @@ namespace llvm { const SCEV *getLHS() const { return LHS; } const SCEV *getRHS() const { return RHS; } - virtual bool isLoopInvariant(const Loop *L) const { - return LHS->isLoopInvariant(L) && RHS->isLoopInvariant(L); - } - - virtual bool hasComputableLoopEvolution(const Loop *L) const { - return LHS->hasComputableLoopEvolution(L) && - RHS->hasComputableLoopEvolution(L); - } - - virtual bool hasOperand(const SCEV *O) const { - return O == LHS || O == RHS || LHS->hasOperand(O) || RHS->hasOperand(O); + const Type *getType() const { + // In most cases the types of LHS and RHS will be the same, but in some + // crazy cases one or the other may be a pointer. ScalarEvolution doesn't + // depend on the type for correctness, but handling types carefully can + // avoid extra casts in the SCEVExpander. The LHS is more likely to be + // a pointer type than the RHS, so use the RHS' type here. + return getRHS()->getType(); } - bool dominates(BasicBlock *BB, DominatorTree *DT) const; - - bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; - - virtual const Type *getType() const; - - void print(raw_ostream &OS) const; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVUDivExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -373,11 +296,7 @@ namespace llvm { SCEVAddRecExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N, const Loop *l) - : SCEVNAryExpr(ID, scAddRecExpr, O, N), L(l) { - for (size_t i = 0, e = NumOperands; i != e; ++i) - assert(Operands[i]->isLoopInvariant(l) && - "Operands of AddRec must be loop-invariant!"); - } + : SCEVNAryExpr(ID, scAddRecExpr, O, N), L(l) {} public: const SCEV *getStart() const { return Operands[0]; } @@ -393,16 +312,6 @@ namespace llvm { getLoop()); } - virtual bool hasComputableLoopEvolution(const Loop *QL) const { - return L == QL; - } - - virtual bool isLoopInvariant(const Loop *QueryLoop) const; - - bool dominates(BasicBlock *BB, DominatorTree *DT) const; - - bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; - /// isAffine - Return true if this is an affine AddRec (i.e., it represents /// an expressions A+B*x where A and B are loop invariant values. bool isAffine() const { @@ -437,8 +346,6 @@ namespace llvm { return cast<SCEVAddRecExpr>(SE.getAddExpr(this, getStepRecurrence(SE))); } - virtual void print(raw_ostream &OS) const; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVAddRecExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -462,8 +369,6 @@ namespace llvm { } public: - virtual const char *getOperationStr() const { return " smax "; } - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVSMaxExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -487,8 +392,6 @@ namespace llvm { } public: - virtual const char *getOperationStr() const { return " umax "; } - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVUMaxExpr *S) { return true; } static inline bool classof(const SCEV *S) { @@ -534,22 +437,7 @@ namespace llvm { bool isAlignOf(const Type *&AllocTy) const; bool isOffsetOf(const Type *&STy, Constant *&FieldNo) const; - virtual bool isLoopInvariant(const Loop *L) const; - virtual bool hasComputableLoopEvolution(const Loop *QL) const { - return false; // not computable - } - - virtual bool hasOperand(const SCEV *) const { - return false; - } - - bool dominates(BasicBlock *BB, DominatorTree *DT) const; - - bool properlyDominates(BasicBlock *BB, DominatorTree *DT) const; - - virtual const Type *getType() const; - - virtual void print(raw_ostream &OS) const; + const Type *getType() const { return getValPtr()->getType(); } /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVUnknown *S) { return true; } diff --git a/contrib/llvm/include/llvm/Analysis/ValueTracking.h b/contrib/llvm/include/llvm/Analysis/ValueTracking.h index 7b6026f..6df1693 100644 --- a/contrib/llvm/include/llvm/Analysis/ValueTracking.h +++ b/contrib/llvm/include/llvm/Analysis/ValueTracking.h @@ -15,7 +15,7 @@ #ifndef LLVM_ANALYSIS_VALUETRACKING_H #define LLVM_ANALYSIS_VALUETRACKING_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> namespace llvm { @@ -39,6 +39,23 @@ namespace llvm { APInt &KnownOne, const TargetData *TD = 0, unsigned Depth = 0); + /// ComputeSignBit - Determine whether the sign bit is known to be zero or + /// one. Convenience wrapper around ComputeMaskedBits. + void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne, + const TargetData *TD = 0, unsigned Depth = 0); + + /// isPowerOfTwo - Return true if the given value is known to have exactly one + /// bit set when defined. For vectors return true if every element is known to + /// be a power of two when defined. Supports values with integer or pointer + /// type and vectors of integers. + bool isPowerOfTwo(Value *V, const TargetData *TD = 0, unsigned Depth = 0); + + /// isKnownNonZero - Return true if the given value is known to be non-zero + /// when defined. For vectors return true if every element is known to be + /// non-zero when defined. Supports values with integer or pointer type and + /// vectors of integers. + bool isKnownNonZero(Value *V, const TargetData *TD = 0, unsigned Depth = 0); + /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use /// this predicate to simplify operations downstream. Mask is known to be /// zero for bits that V cannot have. @@ -77,7 +94,13 @@ namespace llvm { /// bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0); - + /// isBytewiseValue - If the specified value can be set by repeating the same + /// byte in memory, return the i8 value that it is represented with. This is + /// true for all i8 values obviously, but is also true for i32 0, i32 -1, + /// i16 0xF0F0, double 0.0 etc. If the value can't be handled with a repeated + /// byte store (e.g. i16 0x1234), return null. + Value *isBytewiseValue(Value *V); + /// FindInsertedValue - Given an aggregrate and an sequence of indices, see if /// the scalar value indexed is already around as a register, for example if /// it were inserted directly into the aggregrate. @@ -97,6 +120,17 @@ namespace llvm { return FindInsertedValue(V, &Idxs[0], &Idxs[1], InsertBefore); } + /// GetPointerBaseWithConstantOffset - Analyze the specified pointer to see if + /// it can be expressed as a base pointer plus a constant offset. Return the + /// base and offset to the caller. + Value *GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, + const TargetData &TD); + static inline const Value * + GetPointerBaseWithConstantOffset(const Value *Ptr, int64_t &Offset, + const TargetData &TD) { + return GetPointerBaseWithConstantOffset(const_cast<Value*>(Ptr), Offset,TD); + } + /// GetConstantStringInfo - This function computes the length of a /// null-terminated C string pointed to by V. If successful, it returns true /// and returns the string in Str. If unsuccessful, it returns false. If @@ -110,6 +144,20 @@ namespace llvm { /// GetStringLength - If we can compute the length of the string pointed to by /// the specified pointer, return 'len+1'. If we can't, return 0. uint64_t GetStringLength(Value *V); + + /// GetUnderlyingObject - This method strips off any GEP address adjustments + /// and pointer casts from the specified value, returning the original object + /// being addressed. Note that the returned value has pointer type if the + /// specified value does. If the MaxLookup value is non-zero, it limits the + /// number of instructions to be stripped off. + Value *GetUnderlyingObject(Value *V, const TargetData *TD = 0, + unsigned MaxLookup = 6); + static inline const Value * + GetUnderlyingObject(const Value *V, const TargetData *TD = 0, + unsigned MaxLookup = 6) { + return GetUnderlyingObject(const_cast<Value *>(V), TD, MaxLookup); + } + } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/Attributes.h b/contrib/llvm/include/llvm/Attributes.h index 1296d67..da6188b 100644 --- a/contrib/llvm/include/llvm/Attributes.h +++ b/contrib/llvm/include/llvm/Attributes.h @@ -65,6 +65,8 @@ const Attributes StackAlignment = 7<<26; ///< Alignment of stack for ///of alignment with +1 bias ///0 means unaligned (different from ///alignstack(1)) +const Attributes Hotpatch = 1<<29; ///< Function should have special + ///'hotpatch' sequence in prologue /// @brief Attributes that only apply to function parameters. const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture; @@ -73,7 +75,8 @@ const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture; /// be used on return values or function parameters. const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly | NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq | - NoRedZone | NoImplicitFloat | Naked | InlineHint | StackAlignment; + NoRedZone | NoImplicitFloat | Naked | InlineHint | StackAlignment | + Hotpatch; /// @brief Parameter attributes that do not apply to vararg call arguments. const Attributes VarArgsIncompatible = StructRet; @@ -223,7 +226,7 @@ public: /// paramHasAttr - Return true if the specified parameter index has the /// specified attribute set. bool paramHasAttr(unsigned Idx, Attributes Attr) const { - return getAttributes(Idx) & Attr; + return (getAttributes(Idx) & Attr) != 0; } /// getParamAlignment - Return the alignment for the specified function diff --git a/contrib/llvm/include/llvm/BasicBlock.h b/contrib/llvm/include/llvm/BasicBlock.h index bf5874f..7e7c9e7 100644 --- a/contrib/llvm/include/llvm/BasicBlock.h +++ b/contrib/llvm/include/llvm/BasicBlock.h @@ -18,7 +18,7 @@ #include "llvm/SymbolTableListTraits.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/Twine.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { @@ -58,9 +58,9 @@ private: /// tables. The type of a BasicBlock is "Type::LabelTy" because the basic block /// represents a label to which a branch can jump. /// -/// A well formed basic block is formed of a list of non-terminating -/// instructions followed by a single TerminatorInst instruction. -/// TerminatorInst's may not occur in the middle of basic blocks, and must +/// A well formed basic block is formed of a list of non-terminating +/// instructions followed by a single TerminatorInst instruction. +/// TerminatorInst's may not occur in the middle of basic blocks, and must /// terminate the blocks. The BasicBlock class allows malformed basic blocks to /// occur because it may be useful in the intermediate stage of constructing or /// modifying a program. However, the verifier will ensure that basic blocks @@ -90,7 +90,7 @@ private: public: /// getContext - Get the context in which this basic block lives. LLVMContext &getContext() const; - + /// Instruction iterators... typedef InstListType::iterator iterator; typedef InstListType::const_iterator const_iterator; @@ -98,7 +98,7 @@ public: /// Create - Creates a new BasicBlock. If the Parent parameter is specified, /// the basic block is automatically inserted at either the end of the /// function (if InsertBefore is 0), or before the specified basic block. - static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "", + static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "", Function *Parent = 0,BasicBlock *InsertBefore = 0) { return new BasicBlock(Context, Name, Parent, InsertBefore); } @@ -114,15 +114,15 @@ public: /// and BlockAddress's). User *use_back() { return cast<User>(*use_begin());} const User *use_back() const { return cast<User>(*use_begin());} - + /// getTerminator() - If this is a well formed basic block, then this returns /// a pointer to the terminator instruction. If it is not, then you get a /// null pointer back. /// TerminatorInst *getTerminator(); const TerminatorInst *getTerminator() const; - - /// Returns a pointer to the first instructon in this block that is not a + + /// Returns a pointer to the first instructon in this block that is not a /// PHINode instruction. When adding instruction to the beginning of the /// basic block, they should be added before the returned value, not before /// the first instruction, which might be PHI. @@ -137,7 +137,7 @@ public: const Instruction* getFirstNonPHIOrDbg() const { return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbg(); } - + /// removeFromParent - This method unlinks 'this' from the containing /// function, but does not delete it. /// @@ -147,15 +147,15 @@ public: /// and deletes it. /// void eraseFromParent(); - + /// moveBefore - Unlink this basic block from its current function and /// insert it into the function that MovePos lives in, right before MovePos. void moveBefore(BasicBlock *MovePos); - + /// moveAfter - Unlink this basic block from its current function and /// insert it into the function that MovePos lives in, right after MovePos. void moveAfter(BasicBlock *MovePos); - + /// getSinglePredecessor - If this basic block has a single predecessor block, /// return the block, otherwise return a null pointer. @@ -166,8 +166,8 @@ public: /// getUniquePredecessor - If this basic block has a unique predecessor block, /// return the block, otherwise return a null pointer. - /// Note that unique predecessor doesn't mean single edge, there can be - /// multiple edges from the unique predecessor to this block (for example + /// Note that unique predecessor doesn't mean single edge, there can be + /// multiple edges from the unique predecessor to this block (for example /// a switch statement with multiple cases having the same destination). BasicBlock *getUniquePredecessor(); const BasicBlock *getUniquePredecessor() const { @@ -247,7 +247,7 @@ public: /// hasAddressTaken - returns true if there are any uses of this basic block /// other than direct branches, switches, etc. to it. bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; } - + private: /// AdjustBlockAddressRefCount - BasicBlock stores the number of BlockAddress /// objects using it. This is almost always 0, sometimes one, possibly but diff --git a/contrib/llvm/include/llvm/Bitcode/Archive.h b/contrib/llvm/include/llvm/Bitcode/Archive.h index 934e764..c3c07d8 100644 --- a/contrib/llvm/include/llvm/Bitcode/Archive.h +++ b/contrib/llvm/include/llvm/Bitcode/Archive.h @@ -19,12 +19,13 @@ #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" #include <map> #include <set> namespace llvm { class MemoryBuffer; + class raw_ostream; // Forward declare classes class Module; // From VMCore @@ -82,7 +83,7 @@ class ArchiveMember : public ilist_node<ArchiveMember> { unsigned getGroup() const { return info.getGroup(); } /// The "mode" specifies the access permissions for the file per Unix - /// security. This may not have any applicabiity on non-Unix systems but is + /// security. This may not have any applicability on non-Unix systems but is /// a required component of the "ar" file format. /// @brief Get the permission mode associated with this archive member. unsigned getMode() const { return info.getMode(); } @@ -144,7 +145,7 @@ class ArchiveMember : public ilist_node<ArchiveMember> { /// allowed that doesn't have this restriction. This method determines if /// that "long format" is used for this member. /// @returns true iff the file name uses the long form - /// @brief Determin if the member has a long file name + /// @brief Determine if the member has a long file name bool hasLongFilename() const { return flags&HasLongFilenameFlag; } /// This method returns the status info (like Unix stat(2)) for the archive @@ -402,7 +403,7 @@ class Archive { /// bitcode archive. It first makes sure the symbol table has been loaded /// and has a non-zero size. If it does, then it is an archive. If not, /// then it tries to load all the bitcode modules of the archive. Finally, - /// it returns whether it was successfull. + /// it returns whether it was successful. /// @returns true if the archive is a proper llvm bitcode archive /// @brief Determine whether the archive is a proper llvm bitcode archive. bool isBitcodeArchive(); @@ -482,7 +483,7 @@ class Archive { bool loadSymbolTable(std::string* ErrMessage); /// @brief Write the symbol table to an ofstream. - void writeSymbolTable(std::ofstream& ARFile); + void writeSymbolTable(raw_ostream& ARFile); /// Writes one ArchiveMember to an ofstream. If an error occurs, returns /// false, otherwise true. If an error occurs and error is non-null then @@ -491,7 +492,7 @@ class Archive { /// @returns true Writing member failed, \p error set to error message bool writeMember( const ArchiveMember& member, ///< The member to be written - std::ofstream& ARFile, ///< The file to write member onto + raw_ostream& ARFile, ///< The file to write member onto bool CreateSymbolTable, ///< Should symbol table be created? bool TruncateNames, ///< Should names be truncated to 11 chars? bool ShouldCompress, ///< Should the member be compressed? diff --git a/contrib/llvm/include/llvm/Bitcode/BitCodes.h b/contrib/llvm/include/llvm/Bitcode/BitCodes.h index ada2e65..449dc35 100644 --- a/contrib/llvm/include/llvm/Bitcode/BitCodes.h +++ b/contrib/llvm/include/llvm/Bitcode/BitCodes.h @@ -19,7 +19,7 @@ #define LLVM_BITCODE_BITCODES_H #include "llvm/ADT/SmallVector.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { diff --git a/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 4f9b783..7692bd2 100644 --- a/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -94,7 +94,9 @@ namespace bitc { TYPE_CODE_FP128 = 14, // LONG DOUBLE (112 bit mantissa) TYPE_CODE_PPC_FP128= 15, // PPC LONG DOUBLE (2 doubles) - TYPE_CODE_METADATA = 16 // METADATA + TYPE_CODE_METADATA = 16, // METADATA + + TYPE_CODE_X86_MMX = 17 // X86 MMX }; // The type symbol table only has one code (TST_ENTRY_CODE). @@ -197,10 +199,10 @@ namespace bitc { OBO_NO_SIGNED_WRAP = 1 }; - /// SDivOperatorOptionalFlags - Flags for serializing SDivOperator's - /// SubclassOptionalData contents. - enum SDivOperatorOptionalFlags { - SDIV_EXACT = 0 + /// PossiblyExactOperatorOptionalFlags - Flags for serializing + /// PossiblyExactOperator's SubclassOptionalData contents. + enum PossiblyExactOperatorOptionalFlags { + PEO_EXACT = 0 }; // The function body block (FUNCTION_BLOCK_ID) describes function bodies. It diff --git a/contrib/llvm/include/llvm/Bitcode/ReaderWriter.h b/contrib/llvm/include/llvm/Bitcode/ReaderWriter.h index a186964..fa754c0 100644 --- a/contrib/llvm/include/llvm/Bitcode/ReaderWriter.h +++ b/contrib/llvm/include/llvm/Bitcode/ReaderWriter.h @@ -33,6 +33,15 @@ namespace llvm { LLVMContext& Context, std::string *ErrMsg = 0); + /// getBitcodeTargetTriple - Read the header of the specified bitcode + /// buffer and extract just the triple information. If successful, + /// this returns a string and *does not* take ownership + /// of 'buffer'. On error, this returns "", and fills in *ErrMsg + /// if ErrMsg is non-null. + std::string getBitcodeTargetTriple(MemoryBuffer *Buffer, + LLVMContext& Context, + std::string *ErrMsg = 0); + /// ParseBitcodeFile - Read the specified bitcode file, returning the module. /// If an error occurs, this returns null and fills in *ErrMsg if it is /// non-null. This method *never* takes ownership of Buffer. diff --git a/contrib/llvm/include/llvm/CallingConv.h b/contrib/llvm/include/llvm/CallingConv.h index b0481b9..4c5ee62 100644 --- a/contrib/llvm/include/llvm/CallingConv.h +++ b/contrib/llvm/include/llvm/CallingConv.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines LLVM's set of calling conventions. +// This file defines LLVM's set of calling conventions. // //===----------------------------------------------------------------------===// @@ -20,21 +20,21 @@ namespace llvm { /// the well-known calling conventions. /// namespace CallingConv { - /// A set of enums which specify the assigned numeric values for known llvm + /// A set of enums which specify the assigned numeric values for known llvm /// calling conventions. /// @brief LLVM Calling Convention Representation enum ID { /// C - The default llvm calling convention, compatible with C. This /// convention is the only calling convention that supports varargs calls. - /// As with typical C calling conventions, the callee/caller have to + /// As with typical C calling conventions, the callee/caller have to /// tolerate certain amounts of prototype mismatch. C = 0, - + // Generic LLVM calling conventions. None of these calling conventions // support varargs calls, and all assume that the caller and callee // prototype exactly match. - /// Fast - This calling convention attempts to make calls as fast as + /// Fast - This calling convention attempts to make calls as fast as /// possible (e.g. by passing things in registers). Fast = 8, @@ -79,7 +79,22 @@ namespace CallingConv { /// X86_ThisCall - Similar to X86_StdCall. Passes first argument in ECX, /// others via stack. Callee is responsible for stack cleaning. MSVC uses /// this by default for methods in its ABI. - X86_ThisCall = 70 + X86_ThisCall = 70, + + /// PTX_Kernel - Call to a PTX kernel. + /// Passes all arguments in parameter space. + PTX_Kernel = 71, + + /// PTX_Device - Call to a PTX device function. + /// Passes all arguments in register or parameter space. + PTX_Device = 72, + + /// MBLAZE_INTR - Calling convention used for MBlaze interrupt routines. + MBLAZE_INTR = 73, + + /// MBLAZE_INTR - Calling convention used for MBlaze interrupt support + /// routines (i.e. GCC's save_volatiles attribute). + MBLAZE_SVOL = 74 }; } // End CallingConv namespace diff --git a/contrib/llvm/include/llvm/CodeGen/Analysis.h b/contrib/llvm/include/llvm/CodeGen/Analysis.h index f33a9db..78bf9fc 100644 --- a/contrib/llvm/include/llvm/CodeGen/Analysis.h +++ b/contrib/llvm/include/llvm/CodeGen/Analysis.h @@ -23,14 +23,16 @@ namespace llvm { -class TargetLowering; class GlobalVariable; +class TargetLowering; +class SDNode; +class SelectionDAG; /// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence /// of insertvalue or extractvalue indices that identify a member, return /// the linearized index of the start of the member. /// -unsigned ComputeLinearIndex(const TargetLowering &TLI, const Type *Ty, +unsigned ComputeLinearIndex(const Type *Ty, const unsigned *Indices, const unsigned *IndicesEnd, unsigned CurIndex = 0); @@ -52,7 +54,7 @@ GlobalVariable *ExtractTypeInfo(Value *V); /// hasInlineAsmMemConstraint - Return true if the inline asm instruction being /// processed uses a memory 'm' constraint. -bool hasInlineAsmMemConstraint(std::vector<InlineAsm::ConstraintInfo> &CInfos, +bool hasInlineAsmMemConstraint(InlineAsm::ConstraintInfoVector &CInfos, const TargetLowering &TLI); /// getFCmpCondCode - Return the ISD condition code corresponding to @@ -75,6 +77,9 @@ ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred); bool isInTailCallPosition(ImmutableCallSite CS, Attributes CalleeRetAttr, const TargetLowering &TLI); +bool isInTailCallPosition(SelectionDAG &DAG, SDNode *Node, + const TargetLowering &TLI); + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h index b018603..357b933 100644 --- a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -17,7 +17,7 @@ #define LLVM_CODEGEN_ASMPRINTER_H #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/Support/DebugLoc.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class BlockAddress; @@ -49,6 +49,7 @@ namespace llvm { class MCSection; class MCStreamer; class MCSymbol; + class MDNode; class DwarfDebug; class DwarfException; class Mangler; @@ -388,7 +389,7 @@ namespace llvm { /// frame. void EmitFrameMoves(const std::vector<MachineMove> &Moves, MCSymbol *BaseLabel, bool isEH) const; - + void EmitCFIFrameMoves(const std::vector<MachineMove> &Moves) const; //===------------------------------------------------------------------===// // Inline Asm Support @@ -432,7 +433,7 @@ namespace llvm { mutable unsigned SetCounter; /// EmitInlineAsm - Emit a blob of inline asm to the output streamer. - void EmitInlineAsm(StringRef Str, unsigned LocCookie) const; + void EmitInlineAsm(StringRef Str, const MDNode *LocMDNode = 0) const; /// EmitInlineAsm - This method formats and emits the specified machine /// instruction that is an inline asm. diff --git a/contrib/llvm/include/llvm/CodeGen/BinaryObject.h b/contrib/llvm/include/llvm/CodeGen/BinaryObject.h index 3ade7c9..8c1431f 100644 --- a/contrib/llvm/include/llvm/CodeGen/BinaryObject.h +++ b/contrib/llvm/include/llvm/CodeGen/BinaryObject.h @@ -16,7 +16,7 @@ #define LLVM_CODEGEN_BINARYOBJECT_H #include "llvm/CodeGen/MachineRelocation.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> #include <vector> diff --git a/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h b/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h index 240734f..853ebf9 100644 --- a/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h +++ b/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h @@ -20,6 +20,26 @@ namespace llvm { class LiveIntervals; class MachineLoopInfo; + /// normalizeSpillWeight - The spill weight of a live interval is computed as: + /// + /// (sum(use freq) + sum(def freq)) / (K + size) + /// + /// @param UseDefFreq Expected number of executed use and def instructions + /// per function call. Derived from block frequencies. + /// @param Size Size of live interval as returnexd by getSize() + /// + static inline float normalizeSpillWeight(float UseDefFreq, unsigned Size) { + // The magic constant 200 corresponds to approx. 25 instructions since + // SlotIndexes allocate 8 slots per instruction. + // + // The constant is added to avoid depending too much on accidental SlotIndex + // gaps for small intervals. The effect is that small intervals have a spill + // weight that is mostly proportional to the number of uses, while large + // intervals get a spill weight that is closer to a use density. + // + return UseDefFreq / (Size + 200); + } + /// VirtRegAuxInfo - Calculate auxiliary information for a virtual /// register such as its spill weight and allocation hint. class VirtRegAuxInfo { @@ -48,7 +68,9 @@ namespace llvm { public: static char ID; - CalculateSpillWeights() : MachineFunctionPass(ID) {} + CalculateSpillWeights() : MachineFunctionPass(ID) { + initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); + } virtual void getAnalysisUsage(AnalysisUsage &au) const; diff --git a/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h b/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h index 6fb8436..2a9bbdf 100644 --- a/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h +++ b/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h @@ -57,14 +57,14 @@ private: LocInfo HTP : 6; /// ValVT - The type of the value being assigned. - EVT ValVT; + MVT ValVT; /// LocVT - The type of the location being assigned to. - EVT LocVT; + MVT LocVT; public: - static CCValAssign getReg(unsigned ValNo, EVT ValVT, - unsigned RegNo, EVT LocVT, + static CCValAssign getReg(unsigned ValNo, MVT ValVT, + unsigned RegNo, MVT LocVT, LocInfo HTP) { CCValAssign Ret; Ret.ValNo = ValNo; @@ -77,8 +77,8 @@ public: return Ret; } - static CCValAssign getCustomReg(unsigned ValNo, EVT ValVT, - unsigned RegNo, EVT LocVT, + static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, + unsigned RegNo, MVT LocVT, LocInfo HTP) { CCValAssign Ret; Ret = getReg(ValNo, ValVT, RegNo, LocVT, HTP); @@ -86,8 +86,8 @@ public: return Ret; } - static CCValAssign getMem(unsigned ValNo, EVT ValVT, - unsigned Offset, EVT LocVT, + static CCValAssign getMem(unsigned ValNo, MVT ValVT, + unsigned Offset, MVT LocVT, LocInfo HTP) { CCValAssign Ret; Ret.ValNo = ValNo; @@ -100,8 +100,8 @@ public: return Ret; } - static CCValAssign getCustomMem(unsigned ValNo, EVT ValVT, - unsigned Offset, EVT LocVT, + static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, + unsigned Offset, MVT LocVT, LocInfo HTP) { CCValAssign Ret; Ret = getMem(ValNo, ValVT, Offset, LocVT, HTP); @@ -110,7 +110,7 @@ public: } unsigned getValNo() const { return ValNo; } - EVT getValVT() const { return ValVT; } + MVT getValVT() const { return ValVT; } bool isRegLoc() const { return !isMem; } bool isMemLoc() const { return isMem; } @@ -119,7 +119,7 @@ public: unsigned getLocReg() const { assert(isRegLoc()); return Loc; } unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; } - EVT getLocVT() const { return LocVT; } + MVT getLocVT() const { return LocVT; } LocInfo getLocInfo() const { return HTP; } bool isExtInLoc() const { @@ -129,16 +129,16 @@ public: }; /// CCAssignFn - This function assigns a location for Val, updating State to -/// reflect the change. -typedef bool CCAssignFn(unsigned ValNo, EVT ValVT, - EVT LocVT, CCValAssign::LocInfo LocInfo, +/// reflect the change. It returns 'true' if it failed to handle Val. +typedef bool CCAssignFn(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State); /// CCCustomFn - This function assigns a location for Val, possibly updating /// all args to reflect changes and indicates if it handled it. It must set /// isCustom if it handles the arg and returns true. -typedef bool CCCustomFn(unsigned &ValNo, EVT &ValVT, - EVT &LocVT, CCValAssign::LocInfo &LocInfo, +typedef bool CCCustomFn(unsigned &ValNo, MVT &ValVT, + MVT &LocVT, CCValAssign::LocInfo &LocInfo, ISD::ArgFlagsTy &ArgFlags, CCState &State); /// CCState - This class holds information needed while lowering arguments and @@ -198,7 +198,7 @@ public: /// AnalyzeCallOperands - Same as above except it takes vectors of types /// and argument flags. - void AnalyzeCallOperands(SmallVectorImpl<EVT> &ArgVTs, + void AnalyzeCallOperands(SmallVectorImpl<MVT> &ArgVTs, SmallVectorImpl<ISD::ArgFlagsTy> &Flags, CCAssignFn Fn); @@ -209,7 +209,7 @@ public: /// AnalyzeCallResult - Same as above except it's specialized for calls which /// produce a single value. - void AnalyzeCallResult(EVT VT, CCAssignFn Fn); + void AnalyzeCallResult(MVT VT, CCAssignFn Fn); /// getFirstUnallocated - Return the first unallocated register in the set, or /// NumRegs if they are all allocated. @@ -284,8 +284,8 @@ public: // HandleByVal - Allocate a stack slot large enough to pass an argument by // value. The size and alignment information of the argument is encoded in its // parameter attribute. - void HandleByVal(unsigned ValNo, EVT ValVT, - EVT LocVT, CCValAssign::LocInfo LocInfo, + void HandleByVal(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, int MinSize, int MinAlign, ISD::ArgFlagsTy ArgFlags); private: diff --git a/contrib/llvm/include/llvm/CodeGen/EdgeBundles.h b/contrib/llvm/include/llvm/CodeGen/EdgeBundles.h new file mode 100644 index 0000000..2c5215a --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/EdgeBundles.h @@ -0,0 +1,61 @@ +//===-------- EdgeBundles.h - Bundles of CFG edges --------------*- c++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The EdgeBundles analysis forms equivalence classes of CFG edges such that all +// edges leaving a machine basic block are in the same bundle, and all edges +// leaving a basic block are in the same bundle. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_EDGEBUNDLES_H +#define LLVM_CODEGEN_EDGEBUNDLES_H + +#include "llvm/ADT/IntEqClasses.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { + +class EdgeBundles : public MachineFunctionPass { + const MachineFunction *MF; + + /// EC - Each edge bundle is an equivalence class. The keys are: + /// 2*BB->getNumber() -> Ingoing bundle. + /// 2*BB->getNumber()+1 -> Outgoing bundle. + IntEqClasses EC; + +public: + static char ID; + EdgeBundles() : MachineFunctionPass(ID) {} + + /// getBundle - Return the ingoing (Out = false) or outgoing (Out = true) + /// bundle number for basic block #N + unsigned getBundle(unsigned N, bool Out) const { return EC[2 * N + Out]; } + + /// getNumBundles - Return the total number of bundles in the CFG. + unsigned getNumBundles() const { return EC.getNumClasses(); } + + /// getMachineFunction - Return the last machine function computed. + const MachineFunction *getMachineFunction() const { return MF; } + + /// view - Visualize the annotated bipartite CFG with Graphviz. + void view() const; + +private: + virtual bool runOnMachineFunction(MachineFunction&); + virtual void getAnalysisUsage(AnalysisUsage&) const; +}; + +/// Specialize WriteGraph, the standard implementation won't work. +raw_ostream &WriteGraph(raw_ostream &O, const EdgeBundles &G, + bool ShortNames = false, + const std::string &Title = ""); + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/CodeGen/FastISel.h b/contrib/llvm/include/llvm/CodeGen/FastISel.h index 79b1554..fbb1200 100644 --- a/contrib/llvm/include/llvm/CodeGen/FastISel.h +++ b/contrib/llvm/include/llvm/CodeGen/FastISel.h @@ -15,9 +15,6 @@ #define LLVM_CODEGEN_FASTISEL_H #include "llvm/ADT/DenseMap.h" -#ifndef NDEBUG -#include "llvm/ADT/SmallSet.h" -#endif #include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/MachineBasicBlock.h" @@ -39,6 +36,7 @@ class TargetLowering; class TargetMachine; class TargetRegisterClass; class TargetRegisterInfo; +class LoadInst; /// FastISel - This is a fast-path instruction selection class that /// generates poor code and doesn't support illegal types or non-trivial @@ -102,7 +100,16 @@ public: /// index value. std::pair<unsigned, bool> getRegForGEPIndex(const Value *V); - /// recomputeInsertPt - Reset InsertPt to prepare for insterting instructions + /// TryToFoldLoad - The specified machine instr operand is a vreg, and that + /// vreg is being provided by the specified load instruction. If possible, + /// try to fold the load as an operand to the instruction, returning true if + /// possible. + virtual bool TryToFoldLoad(MachineInstr * /*MI*/, unsigned /*OpNo*/, + const LoadInst * /*LI*/) { + return false; + } + + /// recomputeInsertPt - Reset InsertPt to prepare for inserting instructions /// into the current block. void recomputeInsertPt(); diff --git a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h index f17fe5a..27631b7 100644 --- a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -19,6 +19,7 @@ #include "llvm/Instructions.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallVector.h" #ifndef NDEBUG #include "llvm/ADT/SmallSet.h" @@ -27,6 +28,7 @@ #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/Support/CallSite.h" +#include "llvm/Target/TargetRegisterInfo.h" #include <vector> namespace llvm { @@ -104,9 +106,8 @@ public: LiveOutInfo() : NumSignBits(0), KnownOne(1, 0), KnownZero(1, 0) {} }; - /// LiveOutRegInfo - Information about live out vregs, indexed by their - /// register number offset by 'FirstVirtualRegister'. - std::vector<LiveOutInfo> LiveOutRegInfo; + /// LiveOutRegInfo - Information about live out vregs. + IndexedMap<LiveOutInfo, VirtReg2IndexFunctor> LiveOutRegInfo; /// PHINodesToUpdate - A list of phi instructions whose operand list will /// be updated after processing the current basic block. diff --git a/contrib/llvm/include/llvm/CodeGen/GCMetadata.h b/contrib/llvm/include/llvm/CodeGen/GCMetadata.h index b401068..45469ed 100644 --- a/contrib/llvm/include/llvm/CodeGen/GCMetadata.h +++ b/contrib/llvm/include/llvm/CodeGen/GCMetadata.h @@ -36,6 +36,7 @@ #include "llvm/Pass.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/DebugLoc.h" namespace llvm { class AsmPrinter; @@ -59,8 +60,10 @@ namespace llvm { struct GCPoint { GC::PointKind Kind; //< The kind of the safe point. MCSymbol *Label; //< A label. + DebugLoc Loc; - GCPoint(GC::PointKind K, MCSymbol *L) : Kind(K), Label(L) {} + GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL) + : Kind(K), Label(L), Loc(DL) {} }; /// GCRoot - Metadata for a pointer to an object managed by the garbage @@ -121,8 +124,8 @@ namespace llvm { /// addSafePoint - Notes the existence of a safe point. Num is the ID of the /// label just prior to the safe point (if the code generator is using /// MachineModuleInfo). - void addSafePoint(GC::PointKind Kind, MCSymbol *Label) { - SafePoints.push_back(GCPoint(Kind, Label)); + void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) { + SafePoints.push_back(GCPoint(Kind, Label, DL)); } /// getFrameSize/setFrameSize - Records the function's frame size. diff --git a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h index 2e23f4e..3da11c4 100644 --- a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h +++ b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -107,6 +107,13 @@ namespace ISD { // and returns an outchain. EH_SJLJ_LONGJMP, + // OUTCHAIN = EH_SJLJ_DISPATCHSETUP(INCHAIN, context) + // This corresponds to the eh.sjlj.dispatchsetup intrinsic. It takes an + // input chain and a pointer to the sjlj function context as inputs and + // returns an outchain. By default, this does nothing. Targets can lower + // this to unwind setup code if needed. + EH_SJLJ_DISPATCHSETUP, + // TargetConstant* - Like Constant*, but the DAG does not do any folding, // simplification, or lowering of the constant. They are used for constants // which are known to fit in the immediate fields of their users, or for @@ -262,16 +269,24 @@ namespace ISD { /// lengths of the input vectors. CONCAT_VECTORS, + /// INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector + /// with VECTOR2 inserted into VECTOR1 at the (potentially + /// variable) element number IDX, which must be a multiple of the + /// VECTOR2 vector length. The elements of VECTOR1 starting at + /// IDX are overwritten with VECTOR2. Elements IDX through + /// vector_length(VECTOR2) must be valid VECTOR1 indices. + INSERT_SUBVECTOR, + /// EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR (an - /// vector value) starting with the (potentially variable) element number - /// IDX, which must be a multiple of the result vector length. + /// vector value) starting with the element number IDX, which must be a + /// constant multiple of the result vector length. EXTRACT_SUBVECTOR, - /// VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as + /// VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as /// VEC1/VEC2. A VECTOR_SHUFFLE node also contains an array of constant int /// values that indicate which value (or undef) each result element will - /// get. These constant ints are accessible through the - /// ShuffleVectorSDNode class. This is quite similar to the Altivec + /// get. These constant ints are accessible through the + /// ShuffleVectorSDNode class. This is quite similar to the Altivec /// 'vperm' instruction, except that the indices must be constants and are /// in terms of the element size of VEC1/VEC2, not in terms of bytes. VECTOR_SHUFFLE, @@ -288,13 +303,21 @@ namespace ISD { // an unsigned/signed value of type i[2*N], then return the top part. MULHU, MULHS, - // Bitwise operators - logical and, logical or, logical xor, shift left, - // shift right algebraic (shift in sign bits), shift right logical (shift in - // zeroes), rotate left, rotate right, and byteswap. - AND, OR, XOR, SHL, SRA, SRL, ROTL, ROTR, BSWAP, + /// Bitwise operators - logical and, logical or, logical xor. + AND, OR, XOR, + + /// Shift and rotation operations. After legalization, the type of the + /// shift amount is known to be TLI.getShiftAmountTy(). Before legalization + /// the shift amount can be any type, but care must be taken to ensure it is + /// large enough. TLI.getShiftAmountTy() is i8 on some targets, but before + /// legalization, types like i1024 can occur and i8 doesn't have enough bits + /// to represent the shift amount. By convention, DAGCombine and + /// SelectionDAGBuilder forces these shift amounts to i32 for simplicity. + /// + SHL, SRA, SRL, ROTL, ROTR, - // Counting operators - CTTZ, CTLZ, CTPOP, + /// Byte Swap and Counting operators. + BSWAP, CTTZ, CTLZ, CTPOP, // Select(COND, TRUEVAL, FALSEVAL). If the type of the boolean COND is not // i1 then the high bits must conform to getBooleanContents. @@ -392,14 +415,14 @@ namespace ISD { /// X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type. FP_EXTEND, - // BIT_CONVERT - This operator converts between integer, vector and FP + // BITCAST - This operator converts between integer, vector and FP // values, as if the value was stored to memory with one type and loaded // from the same address with the other type (or equivalently for vector // format conversions, etc). The source and result are required to have // the same bit size (e.g. f32 <-> i32). This can also be used for // int-to-int or fp-to-fp conversions, but that is a noop, deleted by // getNode(). - BIT_CONVERT, + BITCAST, // CONVERT_RNDSAT - This operator is used to support various conversions // between various types (float, signed, unsigned and vectors of those @@ -475,6 +498,7 @@ namespace ISD { // Operand #0 : Input chain. // Operand #1 : a ExternalSymbolSDNode with a pointer to the asm string. // Operand #2 : a MDNodeSDNode with the !srcloc metadata. + // Operand #3 : HasSideEffect, IsAlignStack bits. // After this, it is followed by a list of operands with this format: // ConstantSDNode: Flags that encode whether it is a mem or not, the // of operands that follow, etc. See InlineAsm.h. @@ -525,7 +549,7 @@ namespace ISD { // SRCVALUE - This is a node type that holds a Value* that is used to // make reference to a value in the LLVM IR. SRCVALUE, - + // MDNODE_SDNODE - This is a node that holdes an MDNode*, which is used to // reference metadata in the IR. MDNODE_SDNODE, diff --git a/contrib/llvm/include/llvm/CodeGen/IntrinsicLowering.h b/contrib/llvm/include/llvm/CodeGen/IntrinsicLowering.h index eefbc45..767b666 100644 --- a/contrib/llvm/include/llvm/CodeGen/IntrinsicLowering.h +++ b/contrib/llvm/include/llvm/CodeGen/IntrinsicLowering.h @@ -48,6 +48,11 @@ namespace llvm { /// be capable of handling this kind of change. /// void LowerIntrinsicCall(CallInst *CI); + + /// LowerToByteSwap - Replace a call instruction into a call to bswap + /// intrinsic. Return false if it has determined the call is not a + /// simple integer bswap. + static bool LowerToByteSwap(CallInst *CI); }; } diff --git a/contrib/llvm/include/llvm/CodeGen/JITCodeEmitter.h b/contrib/llvm/include/llvm/CodeGen/JITCodeEmitter.h index eb373fb..fea8523 100644 --- a/contrib/llvm/include/llvm/CodeGen/JITCodeEmitter.h +++ b/contrib/llvm/include/llvm/CodeGen/JITCodeEmitter.h @@ -18,7 +18,7 @@ #define LLVM_CODEGEN_JITCODEEMITTER_H #include <string> -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/ADT/DenseMap.h" diff --git a/contrib/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h b/contrib/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h index 13cebea..1ed2547 100644 --- a/contrib/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h +++ b/contrib/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h @@ -20,25 +20,25 @@ namespace llvm { class LatencyPriorityQueue; - + /// Sorting functions for the Available queue. struct latency_sort : public std::binary_function<SUnit*, SUnit*, bool> { LatencyPriorityQueue *PQ; explicit latency_sort(LatencyPriorityQueue *pq) : PQ(pq) {} - + bool operator()(const SUnit* left, const SUnit* right) const; }; class LatencyPriorityQueue : public SchedulingPriorityQueue { // SUnits - The SUnits for the current graph. std::vector<SUnit> *SUnits; - + /// NumNodesSolelyBlocking - This vector contains, for every node in the /// Queue, the number of nodes that the node is the sole unscheduled /// predecessor for. This is used as a tie-breaker heuristic for better /// mobility. std::vector<unsigned> NumNodesSolelyBlocking; - + /// Queue - The queue. std::vector<SUnit*> Queue; latency_sort Picker; @@ -47,6 +47,8 @@ namespace llvm { LatencyPriorityQueue() : Picker(this) { } + bool isBottomUp() const { return false; } + void initNodes(std::vector<SUnit> &sunits) { SUnits = &sunits; NumNodesSolelyBlocking.resize(SUnits->size(), 0); @@ -62,25 +64,27 @@ namespace llvm { void releaseState() { SUnits = 0; } - + unsigned getLatency(unsigned NodeNum) const { assert(NodeNum < (*SUnits).size()); return (*SUnits)[NodeNum].getHeight(); } - + unsigned getNumSolelyBlockNodes(unsigned NodeNum) const { assert(NodeNum < NumNodesSolelyBlocking.size()); return NumNodesSolelyBlocking[NodeNum]; } - + bool empty() const { return Queue.empty(); } - + virtual void push(SUnit *U); - + virtual SUnit *pop(); virtual void remove(SUnit *SU); + virtual void dump(ScheduleDAG* DAG) const; + // ScheduledNode - As nodes are scheduled, we look to see if there are any // successor nodes that have a single unscheduled predecessor. If so, that // single predecessor has a higher priority, since scheduling it will make diff --git a/contrib/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h b/contrib/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h index cd8293d..c931261 100644 --- a/contrib/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/contrib/llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -34,8 +34,10 @@ namespace { (void) llvm::createDeadMachineInstructionElimPass(); (void) llvm::createFastRegisterAllocator(); + (void) llvm::createBasicRegisterAllocator(); (void) llvm::createLinearScanRegisterAllocator(); - (void) llvm::createPBQPRegisterAllocator(); + (void) llvm::createGreedyRegisterAllocator(); + (void) llvm::createDefaultPBQPRegisterAllocator(); (void) llvm::createSimpleRegisterCoalescer(); diff --git a/contrib/llvm/include/llvm/CodeGen/LiveInterval.h b/contrib/llvm/include/llvm/CodeGen/LiveInterval.h index 29e689a..88131fb 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveInterval.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveInterval.h @@ -21,7 +21,7 @@ #ifndef LLVM_CODEGEN_LIVEINTERVAL_H #define LLVM_CODEGEN_LIVEINTERVAL_H -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/IntEqClasses.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/AlignOf.h" #include "llvm/CodeGen/SlotIndexes.h" @@ -39,32 +39,17 @@ namespace llvm { /// This class holds information about a machine level values, including /// definition and use points. /// - /// Care must be taken in interpreting the def index of the value. The - /// following rules apply: - /// - /// If the isDefAccurate() method returns false then def does not contain the - /// index of the defining MachineInstr, or even (necessarily) to a - /// MachineInstr at all. In general such a def index is not meaningful - /// and should not be used. The exception is that, for values originally - /// defined by PHI instructions, after PHI elimination def will contain the - /// index of the MBB in which the PHI originally existed. This can be used - /// to insert code (spills or copies) which deals with the value, which will - /// be live in to the block. class VNInfo { private: enum { HAS_PHI_KILL = 1, REDEF_BY_EC = 1 << 1, IS_PHI_DEF = 1 << 2, - IS_UNUSED = 1 << 3, - IS_DEF_ACCURATE = 1 << 4 + IS_UNUSED = 1 << 3 }; + MachineInstr *copy; unsigned char flags; - union { - MachineInstr *copy; - unsigned reg; - } cr; public: typedef BumpPtrAllocator Allocator; @@ -76,20 +61,19 @@ namespace llvm { SlotIndex def; /// VNInfo constructor. - /// d is presumed to point to the actual defining instr. If it doesn't - /// setIsDefAccurate(false) should be called after construction. VNInfo(unsigned i, SlotIndex d, MachineInstr *c) - : flags(IS_DEF_ACCURATE), id(i), def(d) { cr.copy = c; } + : copy(c), flags(0), id(i), def(d) + { } /// VNInfo construtor, copies values from orig, except for the value number. VNInfo(unsigned i, const VNInfo &orig) - : flags(orig.flags), cr(orig.cr), id(i), def(orig.def) + : copy(orig.copy), flags(orig.flags), id(i), def(orig.def) { } /// Copy from the parameter into this VNInfo. void copyFrom(VNInfo &src) { flags = src.flags; - cr = src.cr; + copy = src.copy; def = src.def; } @@ -97,23 +81,23 @@ namespace llvm { unsigned getFlags() const { return flags; } void setFlags(unsigned flags) { this->flags = flags; } + /// Merge flags from another VNInfo + void mergeFlags(const VNInfo *VNI) { + flags = (flags | VNI->flags) & ~IS_UNUSED; + } + /// For a register interval, if this VN was definied by a copy instr /// getCopy() returns a pointer to it, otherwise returns 0. /// For a stack interval the behaviour of this method is undefined. - MachineInstr* getCopy() const { return cr.copy; } + MachineInstr* getCopy() const { return copy; } /// For a register interval, set the copy member. /// This method should not be called on stack intervals as it may lead to /// undefined behavior. - void setCopy(MachineInstr *c) { cr.copy = c; } + void setCopy(MachineInstr *c) { copy = c; } - /// For a stack interval, returns the reg which this stack interval was - /// defined from. - /// For a register interval the behaviour of this method is undefined. - unsigned getReg() const { return cr.reg; } - /// For a stack interval, set the defining register. - /// This method should not be called on register intervals as it may lead - /// to undefined behaviour. - void setReg(unsigned reg) { cr.reg = reg; } + /// isDefByCopy - Return true when this value was defined by a copy-like + /// instruction as determined by MachineInstr::isCopyLike. + bool isDefByCopy() const { return copy != 0; } /// Returns true if one or more kills are PHI nodes. bool hasPHIKill() const { return flags & HAS_PHI_KILL; } @@ -156,16 +140,6 @@ namespace llvm { else flags &= ~IS_UNUSED; } - - /// Returns true if the def is accurate. - bool isDefAccurate() const { return flags & IS_DEF_ACCURATE; } - /// Set the "is def accurate" flag on this value. - void setIsDefAccurate(bool defAccurate) { - if (defAccurate) - flags |= IS_DEF_ACCURATE; - else - flags &= ~IS_DEF_ACCURATE; - } }; /// LiveRange structure - This represents a simple register range in the @@ -231,8 +205,7 @@ namespace llvm { typedef SmallVector<LiveRange,4> Ranges; typedef SmallVector<VNInfo*,4> VNInfoList; - unsigned reg; // the register or stack slot of this interval - // if the top bits is set, it represents a stack slot. + const unsigned reg; // the register or stack slot of this interval. float weight; // weight of this interval Ranges ranges; // the ranges in which this register is live VNInfoList valnos; // value#'s @@ -248,11 +221,8 @@ namespace llvm { }; - LiveInterval(unsigned Reg, float Weight, bool IsSS = false) - : reg(Reg), weight(Weight) { - if (IsSS) - reg = reg | (1U << (sizeof(unsigned)*CHAR_BIT-1)); - } + LiveInterval(unsigned Reg, float Weight) + : reg(Reg), weight(Weight) {} typedef Ranges::iterator iterator; iterator begin() { return ranges.begin(); } @@ -276,28 +246,29 @@ namespace llvm { /// position is in a hole, this method returns an iterator pointing to the /// LiveRange immediately after the hole. iterator advanceTo(iterator I, SlotIndex Pos) { + assert(I != end()); if (Pos >= endIndex()) return end(); while (I->end <= Pos) ++I; return I; } - void clear() { - valnos.clear(); - ranges.clear(); - } - - /// isStackSlot - Return true if this is a stack slot interval. + /// find - Return an iterator pointing to the first range that ends after + /// Pos, or end(). This is the same as advanceTo(begin(), Pos), but faster + /// when searching large intervals. /// - bool isStackSlot() const { - return reg & (1U << (sizeof(unsigned)*CHAR_BIT-1)); + /// If Pos is contained in a LiveRange, that range is returned. + /// If Pos is in a hole, the following LiveRange is returned. + /// If Pos is beyond endIndex, end() is returned. + iterator find(SlotIndex Pos); + + const_iterator find(SlotIndex Pos) const { + return const_cast<LiveInterval*>(this)->find(Pos); } - /// getStackSlotIndex - Return stack slot index if this is a stack slot - /// interval. - int getStackSlotIndex() const { - assert(isStackSlot() && "Interval is not a stack slot interval!"); - return reg & ~(1U << (sizeof(unsigned)*CHAR_BIT-1)); + void clear() { + valnos.clear(); + ranges.clear(); } bool hasAtLeastOneValue() const { return !valnos.empty(); } @@ -318,10 +289,9 @@ namespace llvm { /// getNextValue - Create a new value number and return it. MIIdx specifies /// the instruction that defines the value number. VNInfo *getNextValue(SlotIndex def, MachineInstr *CopyMI, - bool isDefAccurate, VNInfo::Allocator &VNInfoAllocator) { + VNInfo::Allocator &VNInfoAllocator) { VNInfo *VNI = new (VNInfoAllocator) VNInfo((unsigned)valnos.size(), def, CopyMI); - VNI->setIsDefAccurate(isDefAccurate); valnos.push_back(VNI); return VNI; } @@ -358,21 +328,6 @@ namespace llvm { /// cause merging of V1/V2 values numbers and compaction of the value space. VNInfo* MergeValueNumberInto(VNInfo *V1, VNInfo *V2); - /// MergeInClobberRanges - For any live ranges that are not defined in the - /// current interval, but are defined in the Clobbers interval, mark them - /// used with an unknown definition value. Caller must pass in reference to - /// VNInfoAllocator since it will create a new val#. - void MergeInClobberRanges(LiveIntervals &li_, - const LiveInterval &Clobbers, - VNInfo::Allocator &VNInfoAllocator); - - /// MergeInClobberRange - Same as MergeInClobberRanges except it merge in a - /// single LiveRange only. - void MergeInClobberRange(LiveIntervals &li_, - SlotIndex Start, - SlotIndex End, - VNInfo::Allocator &VNInfoAllocator); - /// MergeValueInAsValue - Merge all of the live ranges of a specific val# /// in RHS into this live interval as the specified value number. /// The LiveRanges in RHS are allowed to overlap with LiveRanges in the @@ -412,17 +367,18 @@ namespace llvm { return index >= endIndex(); } - bool liveAt(SlotIndex index) const; - - // liveBeforeAndAt - Check if the interval is live at the index and the - // index just before it. If index is liveAt, check if it starts a new live - // range.If it does, then check if the previous live range ends at index-1. - bool liveBeforeAndAt(SlotIndex index) const; + bool liveAt(SlotIndex index) const { + const_iterator r = find(index); + return r != end() && r->start <= index; + } /// killedAt - Return true if a live range ends at index. Note that the kill /// point is not contained in the half-open live range. It is usually the /// getDefIndex() slot following its last use. - bool killedAt(SlotIndex index) const; + bool killedAt(SlotIndex index) const { + const_iterator r = find(index.getUseIndex()); + return r != end() && r->end == index; + } /// killedInRange - Return true if the interval has kills in [Start,End). /// Note that the kill point is considered the end of a live range, so it is @@ -452,20 +408,20 @@ namespace llvm { /// FindLiveRangeContaining - Return an iterator to the live range that /// contains the specified index, or end() if there is none. - const_iterator FindLiveRangeContaining(SlotIndex Idx) const; + iterator FindLiveRangeContaining(SlotIndex Idx) { + iterator I = find(Idx); + return I != end() && I->start <= Idx ? I : end(); + } - /// FindLiveRangeContaining - Return an iterator to the live range that - /// contains the specified index, or end() if there is none. - iterator FindLiveRangeContaining(SlotIndex Idx); + const_iterator FindLiveRangeContaining(SlotIndex Idx) const { + const_iterator I = find(Idx); + return I != end() && I->start <= Idx ? I : end(); + } /// findDefinedVNInfo - Find the by the specified /// index (register interval) or defined VNInfo *findDefinedVNInfoForRegInt(SlotIndex Idx) const; - /// findDefinedVNInfo - Find the VNInfo that's defined by the specified - /// register (stack inteval only). - VNInfo *findDefinedVNInfoForStackInt(unsigned Reg) const; - /// overlaps - Return true if the intersection of the two live intervals is /// not empty. @@ -502,7 +458,10 @@ namespace llvm { /// isInOneLiveRange - Return true if the range specified is entirely in the /// a single LiveRange of the live interval. - bool isInOneLiveRange(SlotIndex Start, SlotIndex End); + bool isInOneLiveRange(SlotIndex Start, SlotIndex End) const { + const_iterator r = find(Start); + return r != end() && r->containsRange(Start, End); + } /// removeRange - Remove the specified range from this interval. Note that /// the range must be a single LiveRange in its entirety. @@ -569,6 +528,46 @@ namespace llvm { LI.print(OS); return OS; } -} + /// ConnectedVNInfoEqClasses - Helper class that can divide VNInfos in a + /// LiveInterval into equivalence clases of connected components. A + /// LiveInterval that has multiple connected components can be broken into + /// multiple LiveIntervals. + /// + /// Given a LiveInterval that may have multiple connected components, run: + /// + /// unsigned numComps = ConEQ.Classify(LI); + /// if (numComps > 1) { + /// // allocate numComps-1 new LiveIntervals into LIS[1..] + /// ConEQ.Distribute(LIS); + /// } + + class ConnectedVNInfoEqClasses { + LiveIntervals &lis_; + IntEqClasses eqClass_; + + // Note that values a and b are connected. + void Connect(unsigned a, unsigned b); + + unsigned Renumber(); + + public: + explicit ConnectedVNInfoEqClasses(LiveIntervals &lis) : lis_(lis) {} + + /// Classify - Classify the values in LI into connected components. + /// Return the number of connected components. + unsigned Classify(const LiveInterval *LI); + + /// getEqClass - Classify creates equivalence classes numbered 0..N. Return + /// the equivalence class assigned the VNI. + unsigned getEqClass(const VNInfo *VNI) const { return eqClass_[VNI->id]; } + + /// Distribute - Distribute values in LIV[0] into a separate LiveInterval + /// for each connected component. LIV must have a LiveInterval for each + /// connected component. The LiveIntervals in Liv[1..] must be empty. + void Distribute(LiveInterval *LIV[]); + + }; + +} #endif diff --git a/contrib/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h b/contrib/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h index 2918c3c2a..b09f8d1 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -68,19 +68,13 @@ namespace llvm { public: static char ID; // Pass identification, replacement for typeid - LiveIntervals() : MachineFunctionPass(ID) {} + LiveIntervals() : MachineFunctionPass(ID) { + initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); + } // Calculate the spill weight to assign to a single instruction. static float getSpillWeight(bool isDef, bool isUse, unsigned loopDepth); - // After summing the spill weights of all defs and uses, the final weight - // should be normalized, dividing the weight of the interval by its size. - // This encourages spilling of intervals that are large and have few uses, - // and discourages spilling of small intervals with many uses. - void normalizeSpillWeight(LiveInterval &li) { - li.weight /= getApproximateInstructionCount(li) + 25; - } - typedef Reg2IntervalMap::iterator iterator; typedef Reg2IntervalMap::const_iterator const_iterator; const_iterator begin() const { return r2iMap_.begin(); } @@ -161,6 +155,12 @@ namespace llvm { LiveRange addLiveRangeToEndOfBlock(unsigned reg, MachineInstr* startInst); + /// shrinkToUses - After removing some uses of a register, shrink its live + /// range to just the remaining uses. This method does not compute reaching + /// defs for new uses, and it doesn't remove dead defs. + /// Dead PHIDef values are marked as unused. + void shrinkToUses(LiveInterval *li); + // Interval removal void removeInterval(unsigned Reg) { @@ -169,6 +169,10 @@ namespace llvm { r2iMap_.erase(I); } + SlotIndexes *getSlotIndexes() const { + return indexes_; + } + SlotIndex getZeroIndex() const { return indexes_->getZeroIndex(); } @@ -227,10 +231,6 @@ namespace llvm { return indexes_->getMBBFromIndex(index); } - SlotIndex getMBBTerminatorGap(const MachineBasicBlock *mbb) { - return indexes_->getTerminatorGap(mbb); - } - SlotIndex InsertMachineInstrInMaps(MachineInstr *MI) { return indexes_->insertMachineInstrInMaps(MI); } @@ -272,7 +272,7 @@ namespace llvm { /// (if any is created) by reference. This is temporary. std::vector<LiveInterval*> addIntervalsForSpills(const LiveInterval& i, - SmallVectorImpl<LiveInterval*> &SpillIs, + const SmallVectorImpl<LiveInterval*> &SpillIs, const MachineLoopInfo *loopInfo, VirtRegMap& vrm); /// spillPhysRegAroundRegDefsUses - Spill the specified physical register @@ -285,7 +285,7 @@ namespace llvm { /// val# of the specified interval is re-materializable. Also returns true /// by reference if all of the defs are load instructions. bool isReMaterializable(const LiveInterval &li, - SmallVectorImpl<LiveInterval*> &SpillIs, + const SmallVectorImpl<LiveInterval*> &SpillIs, bool &isLoad); /// isReMaterializable - Returns true if the definition MI of the specified @@ -306,6 +306,16 @@ namespace llvm { /// within a single basic block. bool intervalIsInOneMBB(const LiveInterval &li) const; + /// getLastSplitPoint - Return the last possible insertion point in mbb for + /// spilling and splitting code. This is the first terminator, or the call + /// instruction if li is live into a landing pad successor. + MachineBasicBlock::iterator getLastSplitPoint(const LiveInterval &li, + MachineBasicBlock *mbb) const; + + /// addKillFlags - Add kill flags to any instruction that kills a virtual + /// register. + void addKillFlags(); + private: /// computeIntervals - Compute live intervals. void computeIntervals(); @@ -362,7 +372,7 @@ namespace llvm { /// by reference if the def is a load. bool isReMaterializable(const LiveInterval &li, const VNInfo *ValNo, MachineInstr *MI, - SmallVectorImpl<LiveInterval*> &SpillIs, + const SmallVectorImpl<LiveInterval*> &SpillIs, bool &isLoad); /// tryFoldMemoryOperand - Attempts to fold either a spill / restore from @@ -443,9 +453,6 @@ namespace llvm { DenseMap<unsigned,unsigned> &MBBVRegsMap, std::vector<LiveInterval*> &NewLIs); - // Normalize the spill weight of all the intervals in NewLIs. - void normalizeSpillWeights(std::vector<LiveInterval*> &NewLIs); - static LiveInterval* createInterval(unsigned Reg); void printInstrs(raw_ostream &O) const; diff --git a/contrib/llvm/include/llvm/CodeGen/LiveStackAnalysis.h b/contrib/llvm/include/llvm/CodeGen/LiveStackAnalysis.h index ad984db..8a8dcaf 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveStackAnalysis.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveStackAnalysis.h @@ -39,7 +39,9 @@ namespace llvm { public: static char ID; // Pass identification, replacement for typeid - LiveStacks() : MachineFunctionPass(ID) {} + LiveStacks() : MachineFunctionPass(ID) { + initializeLiveStacksPass(*PassRegistry::getPassRegistry()); + } typedef SS2IntervalMap::iterator iterator; typedef SS2IntervalMap::const_iterator const_iterator; @@ -50,19 +52,7 @@ namespace llvm { unsigned getNumIntervals() const { return (unsigned)S2IMap.size(); } - LiveInterval &getOrCreateInterval(int Slot, const TargetRegisterClass *RC) { - assert(Slot >= 0 && "Spill slot indice must be >= 0"); - SS2IntervalMap::iterator I = S2IMap.find(Slot); - if (I == S2IMap.end()) { - I = S2IMap.insert(I,std::make_pair(Slot, LiveInterval(Slot,0.0F,true))); - S2RCMap.insert(std::make_pair(Slot, RC)); - } else { - // Use the largest common subclass register class. - const TargetRegisterClass *OldRC = S2RCMap[Slot]; - S2RCMap[Slot] = getCommonSubClass(OldRC, RC); - } - return I->second; - } + LiveInterval &getOrCreateInterval(int Slot, const TargetRegisterClass *RC); LiveInterval &getInterval(int Slot) { assert(Slot >= 0 && "Spill slot indice must be >= 0"); diff --git a/contrib/llvm/include/llvm/CodeGen/LiveVariables.h b/contrib/llvm/include/llvm/CodeGen/LiveVariables.h index c8182e0..f9b81b1 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveVariables.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveVariables.h @@ -32,8 +32,10 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SparseBitVector.h" @@ -46,7 +48,9 @@ class TargetRegisterInfo; class LiveVariables : public MachineFunctionPass { public: static char ID; // Pass identification, replacement for typeid - LiveVariables() : MachineFunctionPass(ID) {} + LiveVariables() : MachineFunctionPass(ID) { + initializeLiveVariablesPass(*PassRegistry::getPassRegistry()); + } /// VarInfo - This represents the regions where a virtual register is live in /// the program. We represent this with three different pieces of @@ -119,10 +123,9 @@ public: private: /// VirtRegInfo - This list is a mapping from virtual register number to - /// variable information. FirstVirtualRegister is subtracted from the virtual - /// register number before indexing into this list. + /// variable information. /// - std::vector<VarInfo> VirtRegInfo; + IndexedMap<VarInfo, VirtReg2IndexFunctor> VirtRegInfo; /// PHIJoins - list of virtual registers that are PHI joins. These registers /// may have multiple definitions, and they require special handling when diff --git a/contrib/llvm/include/llvm/CodeGen/MachORelocation.h b/contrib/llvm/include/llvm/CodeGen/MachORelocation.h index 27306c6..21fe74f 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachORelocation.h +++ b/contrib/llvm/include/llvm/CodeGen/MachORelocation.h @@ -15,7 +15,7 @@ #ifndef LLVM_CODEGEN_MACHO_RELOCATION_H #define LLVM_CODEGEN_MACHO_RELOCATION_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h index 3cfc47a..1785451 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -23,6 +23,7 @@ class Pass; class BasicBlock; class MachineFunction; class MCSymbol; +class SlotIndexes; class StringRef; class raw_ostream; @@ -223,6 +224,10 @@ public: /// this basic block is entered via an exception handler. void setIsLandingPad() { IsLandingPad = true; } + /// getLandingPadSuccessor - If this block has a successor that is a landing + /// pad, return it. Otherwise return NULL. + const MachineBasicBlock *getLandingPadSuccessor() const; + // Code Layout methods. /// moveBefore/moveAfter - move 'this' block before or after the specified @@ -289,11 +294,20 @@ public: /// Returns end() is there's no non-PHI instruction. iterator getFirstNonPHI(); + /// SkipPHIsAndLabels - Return the first instruction in MBB after I that is + /// not a PHI or a label. This is the correct point to insert copies at the + /// beginning of a basic block. + iterator SkipPHIsAndLabels(iterator I); + /// getFirstTerminator - returns an iterator to the first terminator /// instruction of this basic block. If a terminator does not exist, /// it returns end() iterator getFirstTerminator(); + /// getLastNonDebugInstr - returns an iterator to the last non-debug + /// instruction in the basic block, or end() + iterator getLastNonDebugInstr(); + /// SplitCriticalEdge - Split the critical edge from this block to the /// given successor block, and return the newly created block, or null /// if splitting is not possible. @@ -308,6 +322,9 @@ public: template<typename IT> void insert(iterator I, IT S, IT E) { Insts.insert(I, S, E); } iterator insert(iterator I, MachineInstr *M) { return Insts.insert(I, M); } + iterator insertAfter(iterator I, MachineInstr *M) { + return Insts.insertAfter(I, M); + } // erase - Remove the specified element or range from the instruction list. // These functions delete any instructions removed. @@ -358,7 +375,7 @@ public: // Debugging methods. void dump() const; - void print(raw_ostream &OS) const; + void print(raw_ostream &OS, SlotIndexes* = 0) const; /// getNumber - MachineBasicBlocks are uniquely numbered at the function /// level, unless they're not in a MachineFunction yet, in which case this diff --git a/contrib/llvm/include/llvm/CodeGen/MachineCodeEmitter.h b/contrib/llvm/include/llvm/CodeGen/MachineCodeEmitter.h index 7abb49a..8fc80ad 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineCodeEmitter.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineCodeEmitter.h @@ -17,7 +17,7 @@ #ifndef LLVM_CODEGEN_MACHINECODEEMITTER_H #define LLVM_CODEGEN_MACHINECODEEMITTER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/DebugLoc.h" namespace llvm { diff --git a/contrib/llvm/include/llvm/CodeGen/MachineCodeInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineCodeInfo.h index a75c02a..c5c0c44 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineCodeInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineCodeInfo.h @@ -17,7 +17,7 @@ #ifndef EE_MACHINE_CODE_INFO_H #define EE_MACHINE_CODE_INFO_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/contrib/llvm/include/llvm/CodeGen/MachineDominators.h b/contrib/llvm/include/llvm/CodeGen/MachineDominators.h index 48695d5..ab944a2 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineDominators.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineDominators.h @@ -145,7 +145,7 @@ public: } /// eraseNode - Removes a node from the dominator tree. Block must not - /// domiante any other blocks. Removes node from its immediate dominator's + /// 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); diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h index dca65ef..22a82a9 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -16,7 +16,7 @@ #include "llvm/ADT/SmallVector.h" //#include "llvm/ADT/IndexedMap.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> #include <vector> @@ -27,7 +27,7 @@ class TargetRegisterClass; class Type; class MachineFunction; class MachineBasicBlock; -class TargetFrameInfo; +class TargetFrameLowering; class BitVector; /// The CalleeSavedInfo class tracks the information need to locate where a @@ -192,13 +192,9 @@ class MachineFrameInfo { /// CSIValid - Has CSInfo been set yet? bool CSIValid; - /// SpillObjects - A vector indicating which frame indices refer to - /// spill slots. - SmallVector<bool, 8> SpillObjects; - - /// TargetFrameInfo - Target information about frame layout. + /// TargetFrameLowering - Target information about frame layout. /// - const TargetFrameInfo &TFI; + const TargetFrameLowering &TFI; /// LocalFrameObjects - References to frame indices which are mapped /// into the local frame allocation block. <FrameIdx, LocalOffset> @@ -217,7 +213,7 @@ class MachineFrameInfo { bool UseLocalStackAllocationBlock; public: - explicit MachineFrameInfo(const TargetFrameInfo &tfi) : TFI(tfi) { + explicit MachineFrameInfo(const TargetFrameLowering &tfi) : TFI(tfi) { StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0; HasVarSizedObjects = false; FrameAddressTaken = false; diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFunction.h b/contrib/llvm/include/llvm/CodeGen/MachineFunction.h index 5bb453d..abeaa4f 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineFunction.h @@ -28,6 +28,7 @@ namespace llvm { class Value; class Function; +class GCModuleInfo; class MachineRegisterInfo; class MachineFrameInfo; class MachineConstantPool; @@ -37,6 +38,7 @@ class MCContext; class Pass; class TargetMachine; class TargetRegisterClass; +struct MachinePointerInfo; template <> struct ilist_traits<MachineBasicBlock> @@ -74,6 +76,7 @@ class MachineFunction { const TargetMachine &Target; MCContext &Ctx; MachineModuleInfo &MMI; + GCModuleInfo *GMI; // RegInfo - Information about each register in use in the function. MachineRegisterInfo *RegInfo; @@ -126,10 +129,12 @@ class MachineFunction { void operator=(const MachineFunction&); // DO NOT IMPLEMENT public: MachineFunction(const Function *Fn, const TargetMachine &TM, - unsigned FunctionNum, MachineModuleInfo &MMI); + unsigned FunctionNum, MachineModuleInfo &MMI, + GCModuleInfo* GMI); ~MachineFunction(); MachineModuleInfo &getMMI() const { return MMI; } + GCModuleInfo *getGMI() const { return GMI; } MCContext &getContext() const { return Ctx; } /// getFunction - Return the LLVM function that this machine code represents @@ -243,7 +248,7 @@ public: /// print - Print out the MachineFunction in a format suitable for debugging /// to the specified stream. /// - void print(raw_ostream &OS) const; + void print(raw_ostream &OS, SlotIndexes* = 0) const; /// viewCFG - This function is meant for use from the debugger. You can just /// say 'call F->viewCFG()' and a ghostview window should pop up from the @@ -266,7 +271,7 @@ public: /// verify - Run the current MachineFunction through the machine code /// verifier, useful for debugger use. - void verify(Pass *p=NULL) const; + void verify(Pass *p = NULL, const char *Banner = NULL) const; // Provide accessors for the MachineBasicBlock list... typedef BasicBlockListType::iterator iterator; @@ -276,7 +281,7 @@ public: /// addLiveIn - Add the specified physical register as a live-in value and /// create a corresponding virtual register for it. - unsigned addLiveIn(unsigned PReg, const TargetRegisterClass *RC); + unsigned addLiveIn(unsigned PReg, const TargetRegisterClass *RC, DebugLoc DL); //===--------------------------------------------------------------------===// // BasicBlock accessor functions. @@ -368,10 +373,11 @@ public: /// getMachineMemOperand - Allocate a new MachineMemOperand. /// MachineMemOperands are owned by the MachineFunction and need not be /// explicitly deallocated. - MachineMemOperand *getMachineMemOperand(const Value *v, unsigned f, - int64_t o, uint64_t s, - unsigned base_alignment); - + MachineMemOperand *getMachineMemOperand(MachinePointerInfo PtrInfo, + unsigned f, uint64_t s, + unsigned base_alignment, + const MDNode *TBAAInfo = 0); + /// getMachineMemOperand - Allocate a new MachineMemOperand by copying /// an existing one, adjusting by an offset and using the given size. /// MachineMemOperands are owned by the MachineFunction and need not be @@ -406,6 +412,10 @@ public: /// normal 'L' label is returned. MCSymbol *getJTISymbol(unsigned JTI, MCContext &Ctx, bool isLinkerPrivate = false) const; + + /// getPICBaseSymbol - Return a function-local symbol to represent the PIC + /// base. + MCSymbol *getPICBaseSymbol() const; }; //===--------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFunctionAnalysis.h b/contrib/llvm/include/llvm/CodeGen/MachineFunctionAnalysis.h index 75dbaab..50676ad 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineFunctionAnalysis.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineFunctionAnalysis.h @@ -37,6 +37,10 @@ public: MachineFunction &getMF() const { return *MF; } CodeGenOpt::Level getOptLevel() const { return OptLevel; } + + virtual const char* getPassName() const { + return "Machine Function Analysis"; + } private: virtual bool doInitialization(Module &M); diff --git a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h index f843196..82c5332 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h @@ -127,6 +127,10 @@ public: /// unsigned short getAsmPrinterFlags() const { return AsmPrinterFlags; } + /// clearAsmPrinterFlags - clear the AsmPrinter bitvector + /// + void clearAsmPrinterFlags() { AsmPrinterFlags = 0; } + /// getAsmPrinterFlag - Return whether an AsmPrinter flag is set. /// bool getAsmPrinterFlag(CommentFlag Flag) const { @@ -138,6 +142,12 @@ public: void setAsmPrinterFlag(CommentFlag Flag) { AsmPrinterFlags |= (unsigned short)Flag; } + + /// clearAsmPrinterFlag - clear specific AsmPrinter flags + /// + void clearAsmPrinterFlag(CommentFlag Flag) { + AsmPrinterFlags &= ~Flag; + } /// getDebugLoc - Returns the debug location id of this MachineInstr. /// @@ -167,7 +177,17 @@ public: /// getNumExplicitOperands - Returns the number of non-implicit operands. /// unsigned getNumExplicitOperands() const; - + + /// iterator/begin/end - Iterate over all operands of a machine instruction. + typedef std::vector<MachineOperand>::iterator mop_iterator; + typedef std::vector<MachineOperand>::const_iterator const_mop_iterator; + + mop_iterator operands_begin() { return Operands.begin(); } + mop_iterator operands_end() { return Operands.end(); } + + const_mop_iterator operands_begin() const { return Operands.begin(); } + const_mop_iterator operands_end() const { return Operands.end(); } + /// Access to memory operands of the instruction mmo_iterator memoperands_begin() const { return MemRefs; } mmo_iterator memoperands_end() const { return MemRefsEnd; } @@ -217,6 +237,7 @@ public: bool isKill() const { return getOpcode() == TargetOpcode::KILL; } bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; } bool isInlineAsm() const { return getOpcode() == TargetOpcode::INLINEASM; } + bool isStackAligningInlineAsm() const; bool isInsertSubreg() const { return getOpcode() == TargetOpcode::INSERT_SUBREG; } @@ -412,10 +433,23 @@ public: /// return 0. unsigned isConstantValuePHI() const; + /// hasUnmodeledSideEffects - Return true if this instruction has side + /// effects that are not modeled by mayLoad / mayStore, etc. + /// For all instructions, the property is encoded in TargetInstrDesc::Flags + /// (see TargetInstrDesc::hasUnmodeledSideEffects(). The only exception is + /// INLINEASM instruction, in which case the side effect property is encoded + /// in one of its operands (see InlineAsm::Extra_HasSideEffect). + /// + bool hasUnmodeledSideEffects() const; + /// allDefsAreDead - Return true if all the defs of this instruction are dead. /// bool allDefsAreDead() const; + /// copyImplicitOps - Copy implicit register operands from specified + /// instruction to this instruction. + void copyImplicitOps(const MachineInstr *MI); + // // Debugging support // diff --git a/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h index 37ac24c..1eb9735 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -18,6 +18,7 @@ #define LLVM_CODEGEN_MACHINEINSTRBUILDER_H #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Support/ErrorHandling.h" namespace llvm { @@ -122,6 +123,13 @@ public: return *this; } + const MachineInstrBuilder &setMemRefs(MachineInstr::mmo_iterator b, + MachineInstr::mmo_iterator e) const { + MI->setMemRefs(b, e); + return *this; + } + + const MachineInstrBuilder &addOperand(const MachineOperand &MO) const { MI->addOperand(MO); return *this; @@ -136,6 +144,19 @@ public: MI->addOperand(MachineOperand::CreateMCSymbol(Sym)); return *this; } + + // Add a displacement from an existing MachineOperand with an added offset. + const MachineInstrBuilder &addDisp(const MachineOperand &Disp, + int64_t off) const { + switch (Disp.getType()) { + default: + llvm_unreachable("Unhandled operand type in addDisp()"); + case MachineOperand::MO_Immediate: + return addImm(Disp.getImm() + off); + case MachineOperand::MO_GlobalAddress: + return addGlobalAddress(Disp.getGlobal(), Disp.getOffset() + off); + } + } }; /// BuildMI - Builder interface. Specify how to create the initial instruction diff --git a/contrib/llvm/include/llvm/CodeGen/MachineLocation.h b/contrib/llvm/include/llvm/CodeGen/MachineLocation.h index a1fcb9f..21951b6 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineLocation.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineLocation.h @@ -32,7 +32,7 @@ private: public: enum { // The target register number for an abstract frame pointer. The value is - // an arbitrary value greater than TargetRegisterInfo::FirstVirtualRegister. + // an arbitrary value that doesn't collide with any real target register. VirtualFP = ~0U }; MachineLocation() @@ -41,6 +41,11 @@ public: : IsRegister(true), Register(R), Offset(0) {} MachineLocation(unsigned R, int O) : IsRegister(false), Register(R), Offset(O) {} + + bool operator==(const MachineLocation &Other) const { + return IsRegister == Other.IsRegister && Register == Other.Register && + Offset == Other.Offset; + } // Accessors bool isReg() const { return IsRegister; } diff --git a/contrib/llvm/include/llvm/CodeGen/MachineLoopInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineLoopInfo.h index 9760eba..6dd9440 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineLoopInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineLoopInfo.h @@ -67,7 +67,9 @@ class MachineLoopInfo : public MachineFunctionPass { public: static char ID; // Pass identification, replacement for typeid - MachineLoopInfo() : MachineFunctionPass(ID) {} + MachineLoopInfo() : MachineFunctionPass(ID) { + initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry()); + } LoopInfoBase<MachineBasicBlock, MachineLoop>& getBase() { return LI; } diff --git a/contrib/llvm/include/llvm/CodeGen/MachineLoopRanges.h b/contrib/llvm/include/llvm/CodeGen/MachineLoopRanges.h new file mode 100644 index 0000000..6a30e8b --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/MachineLoopRanges.h @@ -0,0 +1,112 @@ +//===- MachineLoopRanges.h - Ranges of machine loops -----------*- c++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the interface to the MachineLoopRanges analysis. +// +// Provide on-demand information about the ranges of machine instructions +// covered by a loop. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINELOOPRANGES_H +#define LLVM_CODEGEN_MACHINELOOPRANGES_H + +#include "llvm/ADT/IntervalMap.h" +#include "llvm/CodeGen/SlotIndexes.h" + +namespace llvm { + +class MachineLoop; +class MachineLoopInfo; +class raw_ostream; + +/// MachineLoopRange - Range information for a single loop. +class MachineLoopRange { + friend class MachineLoopRanges; + +public: + typedef IntervalMap<SlotIndex, unsigned, 4> Map; + typedef Map::Allocator Allocator; + +private: + /// The mapped loop. + const MachineLoop *const Loop; + + /// Map intervals to a bit mask. + /// Bit 0 = inside loop block. + Map Intervals; + + /// Loop area as measured by SlotIndex::distance. + unsigned Area; + + /// Create a MachineLoopRange, only accessible to MachineLoopRanges. + MachineLoopRange(const MachineLoop*, Allocator&, SlotIndexes&); + +public: + /// getLoop - Return the mapped machine loop. + const MachineLoop *getLoop() const { return Loop; } + + /// overlaps - Return true if this loop overlaps the given range of machine + /// inteructions. + bool overlaps(SlotIndex Start, SlotIndex Stop); + + /// getNumber - Return the loop number. This is the same as the number of the + /// header block. + unsigned getNumber() const; + + /// getArea - Return the loop area. This number is approximately proportional + /// to the number of instructions in the loop. + unsigned getArea() const { return Area; } + + /// getMap - Allow public read-only access for IntervalMapOverlaps. + const Map &getMap() { return Intervals; } + + /// print - Print loop ranges on OS. + void print(raw_ostream&) const; + + /// byNumber - Comparator for array_pod_sort that sorts a list of + /// MachineLoopRange pointers by number. + static int byNumber(const void*, const void*); + + /// byAreaDesc - Comparator for array_pod_sort that sorts a list of + /// MachineLoopRange pointers by descending area, then by number. + static int byAreaDesc(const void*, const void*); +}; + +raw_ostream &operator<<(raw_ostream&, const MachineLoopRange&); + +/// MachineLoopRanges - Analysis pass that provides on-demand per-loop range +/// information. +class MachineLoopRanges : public MachineFunctionPass { + typedef DenseMap<const MachineLoop*, MachineLoopRange*> CacheMap; + typedef MachineLoopRange::Allocator MapAllocator; + + MapAllocator Allocator; + SlotIndexes *Indexes; + CacheMap Cache; + +public: + static char ID; // Pass identification, replacement for typeid + + MachineLoopRanges() : MachineFunctionPass(ID), Indexes(0) {} + ~MachineLoopRanges() { releaseMemory(); } + + /// getLoopRange - Return the range of loop. + MachineLoopRange *getLoopRange(const MachineLoop *Loop); + +private: + virtual bool runOnMachineFunction(MachineFunction&); + virtual void releaseMemory(); + virtual void getAnalysisUsage(AnalysisUsage&) const; +}; + + +} // end namespace llvm + +#endif // LLVM_CODEGEN_MACHINELOOPRANGES_H diff --git a/contrib/llvm/include/llvm/CodeGen/MachineMemOperand.h b/contrib/llvm/include/llvm/CodeGen/MachineMemOperand.h index 7272aa5..768ce47 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineMemOperand.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineMemOperand.h @@ -16,7 +16,7 @@ #ifndef LLVM_CODEGEN_MACHINEMEMOPERAND_H #define LLVM_CODEGEN_MACHINEMEMOPERAND_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { @@ -24,6 +24,52 @@ class Value; class FoldingSetNodeID; class raw_ostream; +/// MachinePointerInfo - This class contains a discriminated union of +/// information about pointers in memory operands, relating them back to LLVM IR +/// or to virtual locations (such as frame indices) that are exposed during +/// codegen. +struct MachinePointerInfo { + /// V - This is the IR pointer value for the access, or it is null if unknown. + /// If this is null, then the access is to a pointer in the default address + /// space. + const Value *V; + + /// Offset - This is an offset from the base Value*. + int64_t Offset; + + explicit MachinePointerInfo(const Value *v = 0, int64_t offset = 0) + : V(v), Offset(offset) {} + + MachinePointerInfo getWithOffset(int64_t O) const { + if (V == 0) return MachinePointerInfo(0, 0); + return MachinePointerInfo(V, Offset+O); + } + + /// getAddrSpace - Return the LLVM IR address space number that this pointer + /// points into. + unsigned getAddrSpace() const; + + /// getConstantPool - Return a MachinePointerInfo record that refers to the + /// constant pool. + static MachinePointerInfo getConstantPool(); + + /// getFixedStack - Return a MachinePointerInfo record that refers to the + /// the specified FrameIndex. + static MachinePointerInfo getFixedStack(int FI, int64_t offset = 0); + + /// getJumpTable - Return a MachinePointerInfo record that refers to a + /// jump table entry. + static MachinePointerInfo getJumpTable(); + + /// getGOT - Return a MachinePointerInfo record that refers to a + /// GOT entry. + static MachinePointerInfo getGOT(); + + /// getStack - stack pointer relative access. + static MachinePointerInfo getStack(int64_t Offset); +}; + + //===----------------------------------------------------------------------===// /// MachineMemOperand - A description of a memory reference used in the backend. /// Instead of holding a StoreInst or LoadInst, this class holds the address @@ -33,10 +79,10 @@ class raw_ostream; /// that aren't explicit in the regular LLVM IR. /// class MachineMemOperand { - int64_t Offset; + MachinePointerInfo PtrInfo; uint64_t Size; - const Value *V; - unsigned int Flags; + unsigned Flags; + const MDNode *TBAAInfo; public: /// Flags values. These may be or'd together. @@ -54,10 +100,12 @@ public: }; /// MachineMemOperand - Construct an MachineMemOperand object with the - /// specified address Value, flags, offset, size, and base alignment. - MachineMemOperand(const Value *v, unsigned int f, int64_t o, uint64_t s, - unsigned int base_alignment); + /// specified PtrInfo, flags, size, and base alignment. + MachineMemOperand(MachinePointerInfo PtrInfo, unsigned flags, uint64_t s, + unsigned base_alignment, const MDNode *TBAAInfo = 0); + const MachinePointerInfo &getPointerInfo() const { return PtrInfo; } + /// getValue - Return the base address of the memory access. This may either /// be a normal LLVM IR Value, or one of the special values used in CodeGen. /// Special values are those obtained via @@ -65,7 +113,7 @@ public: /// other PseudoSourceValue member functions which return objects which stand /// for frame/stack pointer relative references and other special references /// which are not representable in the high-level IR. - const Value *getValue() const { return V; } + const Value *getValue() const { return PtrInfo.V; } /// getFlags - Return the raw flags of the source value, \see MemOperandFlags. unsigned int getFlags() const { return Flags & ((1 << MOMaxBits) - 1); } @@ -73,7 +121,7 @@ public: /// getOffset - For normal values, this is a byte offset added to the base /// address. For PseudoSourceValue::FPRel values, this is the FrameIndex /// number. - int64_t getOffset() const { return Offset; } + int64_t getOffset() const { return PtrInfo.Offset; } /// getSize - Return the size in bytes of the memory reference. uint64_t getSize() const { return Size; } @@ -86,6 +134,9 @@ public: /// base address, without the offset. uint64_t getBaseAlignment() const { return (1u << (Flags >> MOMaxBits)) >> 1; } + /// getTBAAInfo - Return the TBAA tag for the memory reference. + const MDNode *getTBAAInfo() const { return TBAAInfo; } + bool isLoad() const { return Flags & MOLoad; } bool isStore() const { return Flags & MOStore; } bool isVolatile() const { return Flags & MOVolatile; } @@ -99,7 +150,8 @@ public: /// setValue - Change the SourceValue for this MachineMemOperand. This /// should only be used when an object is being relocated and all references /// to it are being updated. - void setValue(const Value *NewSV) { V = NewSV; } + void setValue(const Value *NewSV) { PtrInfo.V = NewSV; } + void setOffset(int64_t NewOffset) { PtrInfo.Offset = NewOffset; } /// Profile - Gather unique data for the object. /// diff --git a/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h index 0e719c8..6bc80b0 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h @@ -39,7 +39,7 @@ #include "llvm/Support/Dwarf.h" #include "llvm/Support/DebugLoc.h" #include "llvm/Support/ValueHandle.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" @@ -57,7 +57,7 @@ class MachineFunction; class Module; class PointerType; class StructType; - + /// MachineModuleInfoImpl - This class can be derived from and used by targets /// to hold private target-specific information for each Module. Objects of /// type are accessed/created with MMI::getInfo and destroyed when the @@ -70,8 +70,8 @@ public: protected: static SymbolListTy GetSortedStubs(const DenseMap<MCSymbol*, StubValueTy>&); }; - - + + //===----------------------------------------------------------------------===// /// LandingPadInfo - This structure is used to retain landing pad info for @@ -90,19 +90,19 @@ struct LandingPadInfo { }; class MMIAddrLabelMap; - + //===----------------------------------------------------------------------===// /// MachineModuleInfo - This class contains meta information specific to a -/// module. Queries can be made by different debugging and exception handling +/// module. Queries can be made by different debugging and exception handling /// schemes and reformated for specific use. /// class MachineModuleInfo : public ImmutablePass { /// Context - This is the MCContext used for the entire code generator. MCContext Context; - + /// TheModule - This is the LLVM Module being worked on. const Module *TheModule; - + /// ObjFileMMI - This is the object-file-format-specific implementation of /// MachineModuleInfoImpl, which lets targets accumulate whatever info they /// want. @@ -111,7 +111,7 @@ class MachineModuleInfo : public ImmutablePass { // FrameMoves - List of moves done by a function's prolog. Used to construct // frame maps by debug and exception handling consumers. std::vector<MachineMove> FrameMoves; - + // LandingPads - List of LandingPadInfo describing the landing pad information // in the current function. std::vector<LandingPadInfo> LandingPads; @@ -145,18 +145,22 @@ class MachineModuleInfo : public ImmutablePass { /// llvm.compiler.used. SmallPtrSet<const Function *, 32> UsedFunctions; - + /// AddrLabelSymbols - This map keeps track of which symbol is being used for /// the specified basic block's address of label. MMIAddrLabelMap *AddrLabelSymbols; - + bool CallsEHReturn; bool CallsUnwindInit; - + /// DbgInfoAvailable - True if debugging information is available /// in this module. bool DbgInfoAvailable; + /// True if this module calls VarArg function with floating point arguments. + /// This is used to emit an undefined reference to fltused on Windows targets. + bool CallsExternalVAFunctionWithFloatingPointArguments; + public: static char ID; // Pass identification, replacement for typeid @@ -166,22 +170,23 @@ public: VariableDbgInfoMapTy VariableDbgInfo; MachineModuleInfo(); // DUMMY CONSTRUCTOR, DO NOT CALL. - MachineModuleInfo(const MCAsmInfo &MAI); // Real constructor. + // Real constructor. + MachineModuleInfo(const MCAsmInfo &MAI, const TargetAsmInfo *TAI); ~MachineModuleInfo(); - + bool doInitialization(); bool doFinalization(); /// EndFunction - Discard function meta information. /// void EndFunction(); - + const MCContext &getContext() const { return Context; } MCContext &getContext() { return Context; } void setModule(const Module *M) { TheModule = M; } const Module *getModule() const { return TheModule; } - + /// getInfo - Keep track of various per-function pieces of information for /// backends that would like to do so. /// @@ -191,32 +196,40 @@ public: ObjFileMMI = new Ty(*this); return *static_cast<Ty*>(ObjFileMMI); } - + template<typename Ty> const Ty &getObjFileInfo() const { return const_cast<MachineModuleInfo*>(this)->getObjFileInfo<Ty>(); } - + /// AnalyzeModule - Scan the module for global debug information. /// void AnalyzeModule(const Module &M); - + /// hasDebugInfo - Returns true if valid debug info is present. /// bool hasDebugInfo() const { return DbgInfoAvailable; } - void setDebugInfoAvailability(bool avail) { DbgInfoAvailable = true; } + void setDebugInfoAvailability(bool avail) { DbgInfoAvailable = avail; } bool callsEHReturn() const { return CallsEHReturn; } void setCallsEHReturn(bool b) { CallsEHReturn = b; } bool callsUnwindInit() const { return CallsUnwindInit; } void setCallsUnwindInit(bool b) { CallsUnwindInit = b; } - + + bool callsExternalVAFunctionWithFloatingPointArguments() const { + return CallsExternalVAFunctionWithFloatingPointArguments; + } + + void setCallsExternalVAFunctionWithFloatingPointArguments(bool b) { + CallsExternalVAFunctionWithFloatingPointArguments = b; + } + /// getFrameMoves - Returns a reference to a list of moves done in the current /// function's prologue. Used to construct frame maps for debug and exception /// handling comsumers. std::vector<MachineMove> &getFrameMoves() { return FrameMoves; } - + /// getAddrLabelSymbol - Return the symbol to be used for the specified basic /// block when its address is taken. This cannot be its normal LBB label /// because the block may be accessed outside its containing function. @@ -226,15 +239,15 @@ public: /// basic block when its address is taken. If other blocks were RAUW'd to /// this one, we may have to emit them as well, return the whole set. std::vector<MCSymbol*> getAddrLabelSymbolToEmit(const BasicBlock *BB); - + /// takeDeletedSymbolsForFunction - If the specified function has had any /// references to address-taken blocks generated, but the block got deleted, /// return the symbol now so we can emit it. This prevents emitting a /// reference to a symbol that has no definition. - void takeDeletedSymbolsForFunction(const Function *F, + void takeDeletedSymbolsForFunction(const Function *F, std::vector<MCSymbol*> &Result); - + //===- EH ---------------------------------------------------------------===// /// getOrCreateLandingPadInfo - Find or create an LandingPadInfo for the @@ -245,11 +258,11 @@ public: /// associate it with a try landing pad block. void addInvoke(MachineBasicBlock *LandingPad, MCSymbol *BeginLabel, MCSymbol *EndLabel); - - /// addLandingPad - Add a new panding pad. Returns the label ID for the + + /// addLandingPad - Add a new panding pad. Returns the label ID for the /// landing pad entry. MCSymbol *addLandingPad(MachineBasicBlock *LandingPad); - + /// addPersonality - Provide the personality function for the exception /// information. void addPersonality(MachineBasicBlock *LandingPad, @@ -285,7 +298,7 @@ public: /// void addCleanup(MachineBasicBlock *LandingPad); - /// getTypeIDFor - Return the type id for the specified typeinfo. This is + /// getTypeIDFor - Return the type id for the specified typeinfo. This is /// function wide. unsigned getTypeIDFor(const GlobalVariable *TI); @@ -296,7 +309,7 @@ public: /// TidyLandingPads - Remap landing pad labels and remove any deleted landing /// pads. void TidyLandingPads(DenseMap<MCSymbol*, uintptr_t> *LPMap = 0); - + /// getLandingPads - Return a reference to the landing pad info for the /// current function. const std::vector<LandingPadInfo> &getLandingPads() const { diff --git a/contrib/llvm/include/llvm/CodeGen/MachineOperand.h b/contrib/llvm/include/llvm/CodeGen/MachineOperand.h index afa2c29..8acc949 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineOperand.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineOperand.h @@ -14,11 +14,11 @@ #ifndef LLVM_CODEGEN_MACHINEOPERAND_H #define LLVM_CODEGEN_MACHINEOPERAND_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { - + class BlockAddress; class ConstantFP; class GlobalValue; @@ -30,7 +30,7 @@ class TargetMachine; class TargetRegisterInfo; class raw_ostream; class MCSymbol; - + /// MachineOperand class - Representation of each machine instruction operand. /// class MachineOperand { @@ -54,21 +54,21 @@ private: /// OpKind - Specify what kind of operand this is. This discriminates the /// union. unsigned char OpKind; // MachineOperandType - + /// SubReg - Subregister number, only valid for MO_Register. A value of 0 /// indicates the MO_Register has no subReg. unsigned char SubReg; - + /// TargetFlags - This is a set of target-specific operand flags. unsigned char TargetFlags; - + /// IsDef/IsImp/IsKill/IsDead flags - These are only valid for MO_Register /// operands. - + /// IsDef - True if this is a def, false if this is a use of the register. /// bool IsDef : 1; - + /// IsImp - True if this is an implicit def or use, false if it is explicit. /// bool IsImp : 1; @@ -94,7 +94,16 @@ private: /// not a real instruction. Such uses should be ignored during codegen. bool IsDebug : 1; - /// ParentMI - This is the instruction that this operand is embedded into. + /// SmallContents - Thisreally should be part of the Contents union, but lives + /// out here so we can get a better packed struct. + /// MO_Register: Register number. + /// OffsetedInfo: Low bits of offset. + union { + unsigned RegNo; // For MO_Register. + unsigned OffsetLo; // Matches Contents.OffsetedInfo.OffsetHi. + } SmallContents; + + /// ParentMI - This is the instruction that this operand is embedded into. /// This is valid for all operand types, when the operand is in an instr. MachineInstr *ParentMI; @@ -107,11 +116,11 @@ private: MCSymbol *Sym; // For MO_MCSymbol struct { // For MO_Register. - unsigned RegNo; + // Register number is in SmallContents.RegNo. MachineOperand **Prev; // Access list for register. MachineOperand *Next; } Reg; - + /// OffsetedInfo - This struct contains the offset and an object identifier. /// this represent the object as with an optional offset from it. struct { @@ -121,10 +130,11 @@ private: const GlobalValue *GV; // For MO_GlobalAddress. const BlockAddress *BA; // For MO_BlockAddress. } Val; - int64_t Offset; // An offset from the object. + // Low bits of offset are in SmallContents.OffsetLo. + int OffsetHi; // An offset from the object, high 32 bits. } OffsetedInfo; } Contents; - + explicit MachineOperand(MachineOperandType K) : OpKind(K), ParentMI(0) { TargetFlags = 0; } @@ -132,17 +142,27 @@ public: /// getType - Returns the MachineOperandType for this operand. /// MachineOperandType getType() const { return (MachineOperandType)OpKind; } - + unsigned char getTargetFlags() const { return TargetFlags; } void setTargetFlags(unsigned char F) { TargetFlags = F; } void addTargetFlag(unsigned char F) { TargetFlags |= F; } - + /// getParent - Return the instruction that this operand belongs to. /// MachineInstr *getParent() { return ParentMI; } const MachineInstr *getParent() const { return ParentMI; } - + + /// clearParent - Reset the parent pointer. + /// + /// The MachineOperand copy constructor also copies ParentMI, expecting the + /// original to be deleted. If a MachineOperand is ever stored outside a + /// MachineInstr, the parent pointer must be cleared. + /// + /// Never call clearParent() on an operand in a MachineInstr. + /// + void clearParent() { ParentMI = 0; } + void print(raw_ostream &os, const TargetMachine *TM = 0) const; //===--------------------------------------------------------------------===// @@ -180,44 +200,44 @@ public: /// getReg - Returns the register number. unsigned getReg() const { assert(isReg() && "This is not a register operand!"); - return Contents.Reg.RegNo; + return SmallContents.RegNo; } - + unsigned getSubReg() const { assert(isReg() && "Wrong MachineOperand accessor"); return (unsigned)SubReg; } - - bool isUse() const { + + bool isUse() const { assert(isReg() && "Wrong MachineOperand accessor"); return !IsDef; } - + bool isDef() const { assert(isReg() && "Wrong MachineOperand accessor"); return IsDef; } - - bool isImplicit() const { + + bool isImplicit() const { assert(isReg() && "Wrong MachineOperand accessor"); return IsImp; } - + bool isDead() const { assert(isReg() && "Wrong MachineOperand accessor"); return IsDead; } - + bool isKill() const { assert(isReg() && "Wrong MachineOperand accessor"); return IsKill; } - + bool isUndef() const { assert(isReg() && "Wrong MachineOperand accessor"); return IsUndef; } - + bool isEarlyClobber() const { assert(isReg() && "Wrong MachineOperand accessor"); return IsEarlyClobber; @@ -238,11 +258,11 @@ public: //===--------------------------------------------------------------------===// // Mutators for Register Operands //===--------------------------------------------------------------------===// - + /// Change the register this operand corresponds to. /// void setReg(unsigned Reg); - + void setSubReg(unsigned subReg) { assert(isReg() && "Wrong MachineOperand accessor"); SubReg = (unsigned char)subReg; @@ -266,14 +286,14 @@ public: assert((Val || !isDebug()) && "Marking a debug operation as def"); IsDef = !Val; } - + void setIsDef(bool Val = true) { assert(isReg() && "Wrong MachineOperand accessor"); assert((!Val || !isDebug()) && "Marking a debug operation as def"); IsDef = Val; } - void setImplicit(bool Val = true) { + void setImplicit(bool Val = true) { assert(isReg() && "Wrong MachineOperand accessor"); IsImp = Val; } @@ -283,7 +303,7 @@ public: assert((!Val || !isDebug()) && "Marking a debug operation as kill"); IsKill = Val; } - + void setIsDead(bool Val = true) { assert(isReg() && IsDef && "Wrong MachineOperand accessor"); IsDead = Val; @@ -293,7 +313,7 @@ public: assert(isReg() && "Wrong MachineOperand accessor"); IsUndef = Val; } - + void setIsEarlyClobber(bool Val = true) { assert(isReg() && IsDef && "Wrong MachineOperand accessor"); IsEarlyClobber = Val; @@ -307,17 +327,17 @@ public: //===--------------------------------------------------------------------===// // Accessors for various operand types. //===--------------------------------------------------------------------===// - + int64_t getImm() const { assert(isImm() && "Wrong MachineOperand accessor"); return Contents.ImmVal; } - + const ConstantFP *getFPImm() const { assert(isFPImm() && "Wrong MachineOperand accessor"); return Contents.CFP; } - + MachineBasicBlock *getMBB() const { assert(isMBB() && "Wrong MachineOperand accessor"); return Contents.MBB; @@ -328,7 +348,7 @@ public: "Wrong MachineOperand accessor"); return Contents.OffsetedInfo.Val.Index; } - + const GlobalValue *getGlobal() const { assert(isGlobal() && "Wrong MachineOperand accessor"); return Contents.OffsetedInfo.Val.GV; @@ -343,15 +363,16 @@ public: assert(isMCSymbol() && "Wrong MachineOperand accessor"); return Contents.Sym; } - + /// getOffset - Return the offset from the symbol in this operand. This always /// returns 0 for ExternalSymbol operands. int64_t getOffset() const { assert((isGlobal() || isSymbol() || isCPI() || isBlockAddress()) && "Wrong MachineOperand accessor"); - return Contents.OffsetedInfo.Offset; + return (int64_t(Contents.OffsetedInfo.OffsetHi) << 32) | + SmallContents.OffsetLo; } - + const char *getSymbolName() const { assert(isSymbol() && "Wrong MachineOperand accessor"); return Contents.OffsetedInfo.Val.SymbolName; @@ -361,11 +382,11 @@ public: assert(isMetadata() && "Wrong MachineOperand accessor"); return Contents.MD; } - + //===--------------------------------------------------------------------===// // Mutators for various operand types. //===--------------------------------------------------------------------===// - + void setImm(int64_t immVal) { assert(isImm() && "Wrong MachineOperand mutator"); Contents.ImmVal = immVal; @@ -374,56 +395,57 @@ public: void setOffset(int64_t Offset) { assert((isGlobal() || isSymbol() || isCPI() || isBlockAddress()) && "Wrong MachineOperand accessor"); - Contents.OffsetedInfo.Offset = Offset; + SmallContents.OffsetLo = unsigned(Offset); + Contents.OffsetedInfo.OffsetHi = int(Offset >> 32); } - + void setIndex(int Idx) { assert((isFI() || isCPI() || isJTI()) && "Wrong MachineOperand accessor"); Contents.OffsetedInfo.Val.Index = Idx; } - + void setMBB(MachineBasicBlock *MBB) { assert(isMBB() && "Wrong MachineOperand accessor"); Contents.MBB = MBB; } - + //===--------------------------------------------------------------------===// // Other methods. //===--------------------------------------------------------------------===// - + /// isIdenticalTo - Return true if this operand is identical to the specified /// operand. Note: This method ignores isKill and isDead properties. bool isIdenticalTo(const MachineOperand &Other) const; - + /// ChangeToImmediate - Replace this operand with a new immediate operand of /// the specified value. If an operand is known to be an immediate already, /// the setImm method should be used. void ChangeToImmediate(int64_t ImmVal); - + /// ChangeToRegister - Replace this operand with a new register operand of /// the specified value. If an operand is known to be an register already, /// the setReg method should be used. void ChangeToRegister(unsigned Reg, bool isDef, bool isImp = false, bool isKill = false, bool isDead = false, bool isUndef = false, bool isDebug = false); - + //===--------------------------------------------------------------------===// // Construction methods. //===--------------------------------------------------------------------===// - + static MachineOperand CreateImm(int64_t Val) { MachineOperand Op(MachineOperand::MO_Immediate); Op.setImm(Val); return Op; } - + static MachineOperand CreateFPImm(const ConstantFP *CFP) { MachineOperand Op(MachineOperand::MO_FPImmediate); Op.Contents.CFP = CFP; return Op; } - + static MachineOperand CreateReg(unsigned Reg, bool isDef, bool isImp = false, bool isKill = false, bool isDead = false, bool isUndef = false, @@ -438,7 +460,7 @@ public: Op.IsUndef = isUndef; Op.IsEarlyClobber = isEarlyClobber; Op.IsDebug = isDebug; - Op.Contents.Reg.RegNo = Reg; + Op.SmallContents.RegNo = Reg; Op.Contents.Reg.Prev = 0; Op.Contents.Reg.Next = 0; Op.SubReg = SubReg; @@ -506,7 +528,7 @@ public: Op.Contents.Sym = Sym; return Op; } - + friend class MachineInstr; friend class MachineRegisterInfo; private: @@ -521,7 +543,7 @@ private: assert(isReg() && "Can only add reg operand to use lists"); return Contents.Reg.Prev != 0; } - + /// AddRegOperandToRegInfo - Add this register operand to the specified /// MachineRegisterInfo. If it is null, then the next/prev fields should be /// explicitly nulled out. diff --git a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h index 066c91b..79ff714 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -16,6 +16,9 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/DebugLoc.h" #include <vector> namespace llvm { @@ -24,13 +27,12 @@ namespace llvm { /// registers, including vreg register classes, use/def chains for registers, /// etc. class MachineRegisterInfo { - /// VRegInfo - Information we keep for each virtual register. The entries in - /// this vector are actually converted to vreg numbers by adding the - /// TargetRegisterInfo::FirstVirtualRegister delta to their index. + /// VRegInfo - Information we keep for each virtual register. /// /// Each element in this list contains the register class of the vreg and the /// start of the use/def list for the register. - std::vector<std::pair<const TargetRegisterClass*, MachineOperand*> > VRegInfo; + IndexedMap<std::pair<const TargetRegisterClass*, MachineOperand*>, + VirtReg2IndexFunctor> VRegInfo; /// RegClassVRegMap - This vector acts as a map from TargetRegisterClass to /// virtual registers. For each target register class, it keeps a list of @@ -44,7 +46,7 @@ class MachineRegisterInfo { /// register for allocation. For example, if the hint is <0, 1024>, it means /// the allocator should prefer the physical register allocated to the virtual /// register of the hint. - std::vector<std::pair<unsigned, unsigned> > RegAllocHints; + IndexedMap<std::pair<unsigned, unsigned>, VirtReg2IndexFunctor> RegAllocHints; /// PhysRegUseDefLists - This is an array of the head of the use/def list for /// physical registers. @@ -64,7 +66,10 @@ class MachineRegisterInfo { /// stored in the second element. std::vector<std::pair<unsigned, unsigned> > LiveIns; std::vector<unsigned> LiveOuts; - + + /// LiveInLocs - Keep track of location livein registers. + DenseMap<unsigned, DebugLoc> LiveInLocs; + MachineRegisterInfo(const MachineRegisterInfo&); // DO NOT IMPLEMENT void operator=(const MachineRegisterInfo&); // DO NOT IMPLEMENT public: @@ -159,17 +164,15 @@ public: /// getRegUseDefListHead - Return the head pointer for the register use/def /// list for the specified virtual or physical register. MachineOperand *&getRegUseDefListHead(unsigned RegNo) { - if (RegNo < TargetRegisterInfo::FirstVirtualRegister) - return PhysRegUseDefLists[RegNo]; - RegNo -= TargetRegisterInfo::FirstVirtualRegister; - return VRegInfo[RegNo].second; + if (TargetRegisterInfo::isVirtualRegister(RegNo)) + return VRegInfo[RegNo].second; + return PhysRegUseDefLists[RegNo]; } MachineOperand *getRegUseDefListHead(unsigned RegNo) const { - if (RegNo < TargetRegisterInfo::FirstVirtualRegister) - return PhysRegUseDefLists[RegNo]; - RegNo -= TargetRegisterInfo::FirstVirtualRegister; - return VRegInfo[RegNo].second; + if (TargetRegisterInfo::isVirtualRegister(RegNo)) + return VRegInfo[RegNo].second; + return PhysRegUseDefLists[RegNo]; } /// getVRegDef - Return the machine instr that defines the specified virtual @@ -194,8 +197,6 @@ public: /// getRegClass - Return the register class of the specified virtual register. /// const TargetRegisterClass *getRegClass(unsigned Reg) const { - Reg -= TargetRegisterInfo::FirstVirtualRegister; - assert(Reg < VRegInfo.size() && "Invalid vreg!"); return VRegInfo[Reg].first; } @@ -203,16 +204,22 @@ public: /// void setRegClass(unsigned Reg, const TargetRegisterClass *RC); + /// constrainRegClass - Constrain the register class of the specified virtual + /// register to be a common subclass of RC and the current register class. + /// Return the new register class, or NULL if no such class exists. + /// This should only be used when the constraint is known to be trivial, like + /// GR32 -> GR32_NOSP. Beware of increasing register pressure. + const TargetRegisterClass *constrainRegClass(unsigned Reg, + const TargetRegisterClass *RC); + /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. /// unsigned createVirtualRegister(const TargetRegisterClass *RegClass); - /// getLastVirtReg - Return the highest currently assigned virtual register. + /// getNumVirtRegs - Return the number of virtual registers created. /// - unsigned getLastVirtReg() const { - return (unsigned)VRegInfo.size()+TargetRegisterInfo::FirstVirtualRegister-1; - } + unsigned getNumVirtRegs() const { return VRegInfo.size(); } /// getRegClassVirtRegs - Return the list of virtual registers of the given /// target register class. @@ -224,8 +231,6 @@ public: /// setRegAllocationHint - Specify a register allocation hint for the /// specified virtual register. void setRegAllocationHint(unsigned Reg, unsigned Type, unsigned PrefReg) { - Reg -= TargetRegisterInfo::FirstVirtualRegister; - assert(Reg < VRegInfo.size() && "Invalid vreg!"); RegAllocHints[Reg].first = Type; RegAllocHints[Reg].second = PrefReg; } @@ -234,8 +239,6 @@ public: /// specified virtual register. std::pair<unsigned, unsigned> getRegAllocationHint(unsigned Reg) const { - Reg -= TargetRegisterInfo::FirstVirtualRegister; - assert(Reg < VRegInfo.size() && "Invalid vreg!"); return RegAllocHints[Reg]; } @@ -273,7 +276,12 @@ public: LiveIns.push_back(std::make_pair(Reg, vreg)); } void addLiveOut(unsigned Reg) { LiveOuts.push_back(Reg); } - + + /// addLiveInLoc - Keep track of location info for live in reg. + void addLiveInLoc(unsigned VReg, DebugLoc DL) { + LiveInLocs[VReg] = DL; + } + // Iteration support for live in/out sets. These sets are kept in sorted // order by their register number. typedef std::vector<std::pair<unsigned,unsigned> >::const_iterator diff --git a/contrib/llvm/include/llvm/CodeGen/MachineRelocation.h b/contrib/llvm/include/llvm/CodeGen/MachineRelocation.h index c316785..244b466 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineRelocation.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineRelocation.h @@ -14,7 +14,7 @@ #ifndef LLVM_CODEGEN_MACHINERELOCATION_H #define LLVM_CODEGEN_MACHINERELOCATION_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h new file mode 100644 index 0000000..b2224cb --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h @@ -0,0 +1,425 @@ +//===-------------------- Graph.h - PBQP Graph ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// PBQP Graph class. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_PBQP_GRAPH_H +#define LLVM_CODEGEN_PBQP_GRAPH_H + +#include "Math.h" + +#include <list> +#include <vector> +#include <map> + +namespace PBQP { + + /// PBQP Graph class. + /// Instances of this class describe PBQP problems. + class Graph { + private: + + // ----- TYPEDEFS ----- + class NodeEntry; + class EdgeEntry; + + typedef std::list<NodeEntry> NodeList; + typedef std::list<EdgeEntry> EdgeList; + + public: + + typedef NodeList::iterator NodeItr; + typedef NodeList::const_iterator ConstNodeItr; + + typedef EdgeList::iterator EdgeItr; + typedef EdgeList::const_iterator ConstEdgeItr; + + private: + + typedef std::list<EdgeItr> AdjEdgeList; + + public: + + typedef AdjEdgeList::iterator AdjEdgeItr; + + private: + + class NodeEntry { + private: + Vector costs; + AdjEdgeList adjEdges; + unsigned degree; + void *data; + public: + NodeEntry(const Vector &costs) : costs(costs), degree(0) {} + Vector& getCosts() { return costs; } + const Vector& getCosts() const { return costs; } + unsigned getDegree() const { return degree; } + AdjEdgeItr edgesBegin() { return adjEdges.begin(); } + AdjEdgeItr edgesEnd() { return adjEdges.end(); } + AdjEdgeItr addEdge(EdgeItr e) { + ++degree; + return adjEdges.insert(adjEdges.end(), e); + } + void removeEdge(AdjEdgeItr ae) { + --degree; + adjEdges.erase(ae); + } + void setData(void *data) { this->data = data; } + void* getData() { return data; } + }; + + class EdgeEntry { + private: + NodeItr node1, node2; + Matrix costs; + AdjEdgeItr node1AEItr, node2AEItr; + void *data; + public: + EdgeEntry(NodeItr node1, NodeItr node2, const Matrix &costs) + : node1(node1), node2(node2), costs(costs) {} + NodeItr getNode1() const { return node1; } + NodeItr getNode2() const { return node2; } + Matrix& getCosts() { return costs; } + const Matrix& getCosts() const { return costs; } + void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; } + AdjEdgeItr getNode1AEItr() { return node1AEItr; } + void setNode2AEItr(AdjEdgeItr ae) { node2AEItr = ae; } + AdjEdgeItr getNode2AEItr() { return node2AEItr; } + void setData(void *data) { this->data = data; } + void *getData() { return data; } + }; + + // ----- MEMBERS ----- + + NodeList nodes; + unsigned numNodes; + + EdgeList edges; + unsigned numEdges; + + // ----- INTERNAL METHODS ----- + + NodeEntry& getNode(NodeItr nItr) { return *nItr; } + const NodeEntry& getNode(ConstNodeItr nItr) const { return *nItr; } + + EdgeEntry& getEdge(EdgeItr eItr) { return *eItr; } + const EdgeEntry& getEdge(ConstEdgeItr eItr) const { return *eItr; } + + NodeItr addConstructedNode(const NodeEntry &n) { + ++numNodes; + return nodes.insert(nodes.end(), n); + } + + EdgeItr addConstructedEdge(const EdgeEntry &e) { + assert(findEdge(e.getNode1(), e.getNode2()) == edges.end() && + "Attempt to add duplicate edge."); + ++numEdges; + EdgeItr edgeItr = edges.insert(edges.end(), e); + EdgeEntry &ne = getEdge(edgeItr); + NodeEntry &n1 = getNode(ne.getNode1()); + NodeEntry &n2 = getNode(ne.getNode2()); + // Sanity check on matrix dimensions: + assert((n1.getCosts().getLength() == ne.getCosts().getRows()) && + (n2.getCosts().getLength() == ne.getCosts().getCols()) && + "Edge cost dimensions do not match node costs dimensions."); + ne.setNode1AEItr(n1.addEdge(edgeItr)); + ne.setNode2AEItr(n2.addEdge(edgeItr)); + return edgeItr; + } + + inline void copyFrom(const Graph &other); + public: + + /// \brief Construct an empty PBQP graph. + Graph() : numNodes(0), numEdges(0) {} + + /// \brief Copy construct this graph from "other". Note: Does not copy node + /// and edge data, only graph structure and costs. + /// @param other Source graph to copy from. + Graph(const Graph &other) : numNodes(0), numEdges(0) { + copyFrom(other); + } + + /// \brief Make this graph a copy of "other". Note: Does not copy node and + /// edge data, only graph structure and costs. + /// @param other The graph to copy from. + /// @return A reference to this graph. + /// + /// This will clear the current graph, erasing any nodes and edges added, + /// before copying from other. + Graph& operator=(const Graph &other) { + clear(); + copyFrom(other); + return *this; + } + + /// \brief Add a node with the given costs. + /// @param costs Cost vector for the new node. + /// @return Node iterator for the added node. + NodeItr addNode(const Vector &costs) { + return addConstructedNode(NodeEntry(costs)); + } + + /// \brief Add an edge between the given nodes with the given costs. + /// @param n1Itr First node. + /// @param n2Itr Second node. + /// @return Edge iterator for the added edge. + EdgeItr addEdge(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr, + const Matrix &costs) { + assert(getNodeCosts(n1Itr).getLength() == costs.getRows() && + getNodeCosts(n2Itr).getLength() == costs.getCols() && + "Matrix dimensions mismatch."); + return addConstructedEdge(EdgeEntry(n1Itr, n2Itr, costs)); + } + + /// \brief Get the number of nodes in the graph. + /// @return Number of nodes in the graph. + unsigned getNumNodes() const { return numNodes; } + + /// \brief Get the number of edges in the graph. + /// @return Number of edges in the graph. + unsigned getNumEdges() const { return numEdges; } + + /// \brief Get a node's cost vector. + /// @param nItr Node iterator. + /// @return Node cost vector. + Vector& getNodeCosts(NodeItr nItr) { return getNode(nItr).getCosts(); } + + /// \brief Get a node's cost vector (const version). + /// @param nItr Node iterator. + /// @return Node cost vector. + const Vector& getNodeCosts(ConstNodeItr nItr) const { + return getNode(nItr).getCosts(); + } + + /// \brief Set a node's data pointer. + /// @param nItr Node iterator. + /// @param data Pointer to node data. + /// + /// Typically used by a PBQP solver to attach data to aid in solution. + void setNodeData(NodeItr nItr, void *data) { getNode(nItr).setData(data); } + + /// \brief Get the node's data pointer. + /// @param nItr Node iterator. + /// @return Pointer to node data. + void* getNodeData(NodeItr nItr) { return getNode(nItr).getData(); } + + /// \brief Get an edge's cost matrix. + /// @param eItr Edge iterator. + /// @return Edge cost matrix. + Matrix& getEdgeCosts(EdgeItr eItr) { return getEdge(eItr).getCosts(); } + + /// \brief Get an edge's cost matrix (const version). + /// @param eItr Edge iterator. + /// @return Edge cost matrix. + const Matrix& getEdgeCosts(ConstEdgeItr eItr) const { + return getEdge(eItr).getCosts(); + } + + /// \brief Set an edge's data pointer. + /// @param eItr Edge iterator. + /// @param data Pointer to edge data. + /// + /// Typically used by a PBQP solver to attach data to aid in solution. + void setEdgeData(EdgeItr eItr, void *data) { getEdge(eItr).setData(data); } + + /// \brief Get an edge's data pointer. + /// @param eItr Edge iterator. + /// @return Pointer to edge data. + void* getEdgeData(EdgeItr eItr) { return getEdge(eItr).getData(); } + + /// \brief Get a node's degree. + /// @param nItr Node iterator. + /// @return The degree of the node. + unsigned getNodeDegree(NodeItr nItr) const { + return getNode(nItr).getDegree(); + } + + /// \brief Begin iterator for node set. + NodeItr nodesBegin() { return nodes.begin(); } + + /// \brief Begin const iterator for node set. + ConstNodeItr nodesBegin() const { return nodes.begin(); } + + /// \brief End iterator for node set. + NodeItr nodesEnd() { return nodes.end(); } + + /// \brief End const iterator for node set. + ConstNodeItr nodesEnd() const { return nodes.end(); } + + /// \brief Begin iterator for edge set. + EdgeItr edgesBegin() { return edges.begin(); } + + /// \brief End iterator for edge set. + EdgeItr edgesEnd() { return edges.end(); } + + /// \brief Get begin iterator for adjacent edge set. + /// @param nItr Node iterator. + /// @return Begin iterator for the set of edges connected to the given node. + AdjEdgeItr adjEdgesBegin(NodeItr nItr) { + return getNode(nItr).edgesBegin(); + } + + /// \brief Get end iterator for adjacent edge set. + /// @param nItr Node iterator. + /// @return End iterator for the set of edges connected to the given node. + AdjEdgeItr adjEdgesEnd(NodeItr nItr) { + return getNode(nItr).edgesEnd(); + } + + /// \brief Get the first node connected to this edge. + /// @param eItr Edge iterator. + /// @return The first node connected to the given edge. + NodeItr getEdgeNode1(EdgeItr eItr) { + return getEdge(eItr).getNode1(); + } + + /// \brief Get the second node connected to this edge. + /// @param eItr Edge iterator. + /// @return The second node connected to the given edge. + NodeItr getEdgeNode2(EdgeItr eItr) { + return getEdge(eItr).getNode2(); + } + + /// \brief Get the "other" node connected to this edge. + /// @param eItr Edge iterator. + /// @param nItr Node iterator for the "given" node. + /// @return The iterator for the "other" node connected to this edge. + NodeItr getEdgeOtherNode(EdgeItr eItr, NodeItr nItr) { + EdgeEntry &e = getEdge(eItr); + if (e.getNode1() == nItr) { + return e.getNode2(); + } // else + return e.getNode1(); + } + + /// \brief Get the edge connecting two nodes. + /// @param n1Itr First node iterator. + /// @param n2Itr Second node iterator. + /// @return An iterator for edge (n1Itr, n2Itr) if such an edge exists, + /// otherwise returns edgesEnd(). + EdgeItr findEdge(NodeItr n1Itr, NodeItr n2Itr) { + for (AdjEdgeItr aeItr = adjEdgesBegin(n1Itr), aeEnd = adjEdgesEnd(n1Itr); + aeItr != aeEnd; ++aeItr) { + if ((getEdgeNode1(*aeItr) == n2Itr) || + (getEdgeNode2(*aeItr) == n2Itr)) { + return *aeItr; + } + } + return edges.end(); + } + + /// \brief Remove a node from the graph. + /// @param nItr Node iterator. + void removeNode(NodeItr nItr) { + NodeEntry &n = getNode(nItr); + for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end;) { + EdgeItr eItr = *itr; + ++itr; + removeEdge(eItr); + } + nodes.erase(nItr); + --numNodes; + } + + /// \brief Remove an edge from the graph. + /// @param eItr Edge iterator. + void removeEdge(EdgeItr eItr) { + EdgeEntry &e = getEdge(eItr); + NodeEntry &n1 = getNode(e.getNode1()); + NodeEntry &n2 = getNode(e.getNode2()); + n1.removeEdge(e.getNode1AEItr()); + n2.removeEdge(e.getNode2AEItr()); + edges.erase(eItr); + --numEdges; + } + + /// \brief Remove all nodes and edges from the graph. + void clear() { + nodes.clear(); + edges.clear(); + numNodes = numEdges = 0; + } + + /// \brief Print a representation of this graph in DOT format. + /// @param os Output stream to print on. + template <typename OStream> + void printDot(OStream &os) { + + os << "graph {\n"; + + for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd(); + nodeItr != nodeEnd; ++nodeItr) { + + os << " node" << nodeItr << " [ label=\"" + << nodeItr << ": " << getNodeCosts(nodeItr) << "\" ]\n"; + } + + os << " edge [ len=" << getNumNodes() << " ]\n"; + + for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd(); + edgeItr != edgeEnd; ++edgeItr) { + + os << " node" << getEdgeNode1(edgeItr) + << " -- node" << getEdgeNode2(edgeItr) + << " [ label=\""; + + const Matrix &edgeCosts = getEdgeCosts(edgeItr); + + for (unsigned i = 0; i < edgeCosts.getRows(); ++i) { + os << edgeCosts.getRowAsVector(i) << "\\n"; + } + os << "\" ]\n"; + } + os << "}\n"; + } + + }; + + class NodeItrComparator { + public: + bool operator()(Graph::NodeItr n1, Graph::NodeItr n2) const { + return &*n1 < &*n2; + } + + bool operator()(Graph::ConstNodeItr n1, Graph::ConstNodeItr n2) const { + return &*n1 < &*n2; + } + }; + + class EdgeItrCompartor { + public: + bool operator()(Graph::EdgeItr e1, Graph::EdgeItr e2) const { + return &*e1 < &*e2; + } + + bool operator()(Graph::ConstEdgeItr e1, Graph::ConstEdgeItr e2) const { + return &*e1 < &*e2; + } + }; + + void Graph::copyFrom(const Graph &other) { + std::map<Graph::ConstNodeItr, Graph::NodeItr, + NodeItrComparator> nodeMap; + + for (Graph::ConstNodeItr nItr = other.nodesBegin(), + nEnd = other.nodesEnd(); + nItr != nEnd; ++nItr) { + nodeMap[nItr] = addNode(other.getNodeCosts(nItr)); + } + + } + +} + +#endif // LLVM_CODEGEN_PBQP_GRAPH_HPP diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicBase.h b/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicBase.h new file mode 100644 index 0000000..791c227 --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicBase.h @@ -0,0 +1,246 @@ +//===-- HeuristcBase.h --- Heuristic base class for PBQP --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_HEURISTICBASE_H +#define LLVM_CODEGEN_PBQP_HEURISTICBASE_H + +#include "HeuristicSolver.h" + +namespace PBQP { + + /// \brief Abstract base class for heuristic implementations. + /// + /// This class provides a handy base for heuristic implementations with common + /// solver behaviour implemented for a number of methods. + /// + /// To implement your own heuristic using this class as a base you'll have to + /// implement, as a minimum, the following methods: + /// <ul> + /// <li> void addToHeuristicList(Graph::NodeItr) : Add a node to the + /// heuristic reduction list. + /// <li> void heuristicReduce() : Perform a single heuristic reduction. + /// <li> void preUpdateEdgeCosts(Graph::EdgeItr) : Handle the (imminent) + /// change to the cost matrix on the given edge (by R2). + /// <li> void postUpdateEdgeCostts(Graph::EdgeItr) : Handle the new + /// costs on the given edge. + /// <li> void handleAddEdge(Graph::EdgeItr) : Handle the addition of a new + /// edge into the PBQP graph (by R2). + /// <li> void handleRemoveEdge(Graph::EdgeItr, Graph::NodeItr) : Handle the + /// disconnection of the given edge from the given node. + /// <li> A constructor for your derived class : to pass back a reference to + /// the solver which is using this heuristic. + /// </ul> + /// + /// These methods are implemented in this class for documentation purposes, + /// but will assert if called. + /// + /// Note that this class uses the curiously recursive template idiom to + /// forward calls to the derived class. These methods need not be made + /// virtual, and indeed probably shouldn't for performance reasons. + /// + /// You'll also need to provide NodeData and EdgeData structs in your class. + /// These can be used to attach data relevant to your heuristic to each + /// node/edge in the PBQP graph. + + template <typename HImpl> + class HeuristicBase { + private: + + typedef std::list<Graph::NodeItr> OptimalList; + + HeuristicSolverImpl<HImpl> &s; + Graph &g; + OptimalList optimalList; + + // Return a reference to the derived heuristic. + HImpl& impl() { return static_cast<HImpl&>(*this); } + + // Add the given node to the optimal reductions list. Keep an iterator to + // its location for fast removal. + void addToOptimalReductionList(Graph::NodeItr nItr) { + optimalList.insert(optimalList.end(), nItr); + } + + public: + + /// \brief Construct an instance with a reference to the given solver. + /// @param solver The solver which is using this heuristic instance. + HeuristicBase(HeuristicSolverImpl<HImpl> &solver) + : s(solver), g(s.getGraph()) { } + + /// \brief Get the solver which is using this heuristic instance. + /// @return The solver which is using this heuristic instance. + /// + /// You can use this method to get access to the solver in your derived + /// heuristic implementation. + HeuristicSolverImpl<HImpl>& getSolver() { return s; } + + /// \brief Get the graph representing the problem to be solved. + /// @return The graph representing the problem to be solved. + Graph& getGraph() { return g; } + + /// \brief Tell the solver to simplify the graph before the reduction phase. + /// @return Whether or not the solver should run a simplification phase + /// prior to the main setup and reduction. + /// + /// HeuristicBase returns true from this method as it's a sensible default, + /// however you can over-ride it in your derived class if you want different + /// behaviour. + bool solverRunSimplify() const { return true; } + + /// \brief Decide whether a node should be optimally or heuristically + /// reduced. + /// @return Whether or not the given node should be listed for optimal + /// reduction (via R0, R1 or R2). + /// + /// HeuristicBase returns true for any node with degree less than 3. This is + /// sane and sensible for many situations, but not all. You can over-ride + /// this method in your derived class if you want a different selection + /// criteria. Note however that your criteria for selecting optimal nodes + /// should be <i>at least</i> as strong as this. I.e. Nodes of degree 3 or + /// higher should not be selected under any circumstances. + bool shouldOptimallyReduce(Graph::NodeItr nItr) { + if (g.getNodeDegree(nItr) < 3) + return true; + // else + return false; + } + + /// \brief Add the given node to the list of nodes to be optimally reduced. + /// @return nItr Node iterator to be added. + /// + /// You probably don't want to over-ride this, except perhaps to record + /// statistics before calling this implementation. HeuristicBase relies on + /// its behaviour. + void addToOptimalReduceList(Graph::NodeItr nItr) { + optimalList.push_back(nItr); + } + + /// \brief Initialise the heuristic. + /// + /// HeuristicBase iterates over all nodes in the problem and adds them to + /// the appropriate list using addToOptimalReduceList or + /// addToHeuristicReduceList based on the result of shouldOptimallyReduce. + /// + /// This behaviour should be fine for most situations. + void setup() { + for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); + nItr != nEnd; ++nItr) { + if (impl().shouldOptimallyReduce(nItr)) { + addToOptimalReduceList(nItr); + } else { + impl().addToHeuristicReduceList(nItr); + } + } + } + + /// \brief Optimally reduce one of the nodes in the optimal reduce list. + /// @return True if a reduction takes place, false if the optimal reduce + /// list is empty. + /// + /// Selects a node from the optimal reduce list and removes it, applying + /// R0, R1 or R2 as appropriate based on the selected node's degree. + bool optimalReduce() { + if (optimalList.empty()) + return false; + + Graph::NodeItr nItr = optimalList.front(); + optimalList.pop_front(); + + switch (s.getSolverDegree(nItr)) { + case 0: s.applyR0(nItr); break; + case 1: s.applyR1(nItr); break; + case 2: s.applyR2(nItr); break; + default: assert(false && + "Optimal reductions of degree > 2 nodes is invalid."); + } + + return true; + } + + /// \brief Perform the PBQP reduction process. + /// + /// Reduces the problem to the empty graph by repeated application of the + /// reduction rules R0, R1, R2 and RN. + /// R0, R1 or R2 are always applied if possible before RN is used. + void reduce() { + bool finished = false; + + while (!finished) { + if (!optimalReduce()) { + if (impl().heuristicReduce()) { + getSolver().recordRN(); + } else { + finished = true; + } + } + } + } + + /// \brief Add a node to the heuristic reduce list. + /// @param nItr Node iterator to add to the heuristic reduce list. + void addToHeuristicList(Graph::NodeItr nItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Heuristically reduce one of the nodes in the heuristic + /// reduce list. + /// @return True if a reduction takes place, false if the heuristic reduce + /// list is empty. + void heuristicReduce() { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Prepare a change in the costs on the given edge. + /// @param eItr Edge iterator. + void preUpdateEdgeCosts(Graph::EdgeItr eItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Handle the change in the costs on the given edge. + /// @param eItr Edge iterator. + void postUpdateEdgeCostts(Graph::EdgeItr eItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Handle the addition of a new edge into the PBQP graph. + /// @param eItr Edge iterator for the added edge. + void handleAddEdge(Graph::EdgeItr eItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Handle disconnection of an edge from a node. + /// @param eItr Edge iterator for edge being disconnected. + /// @param nItr Node iterator for the node being disconnected from. + /// + /// Edges are frequently removed due to the removal of a node. This + /// method allows for the effect to be computed only for the remaining + /// node in the graph. + void handleRemoveEdge(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Clean up any structures used by HeuristicBase. + /// + /// At present this just performs a sanity check: that the optimal reduce + /// list is empty now that reduction has completed. + /// + /// If your derived class has more complex structures which need tearing + /// down you should over-ride this method but include a call back to this + /// implementation. + void cleanup() { + assert(optimalList.empty() && "Nodes left over in optimal reduce list?"); + } + + }; + +} + + +#endif // LLVM_CODEGEN_PBQP_HEURISTICBASE_H diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicSolver.h b/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicSolver.h new file mode 100644 index 0000000..35514f9 --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicSolver.h @@ -0,0 +1,616 @@ +//===-- HeuristicSolver.h - Heuristic PBQP Solver --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Heuristic PBQP solver. This solver is able to perform optimal reductions for +// nodes of degree 0, 1 or 2. For nodes of degree >2 a plugable heuristic is +// used to select a node for reduction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H +#define LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H + +#include "Graph.h" +#include "Solution.h" +#include <vector> +#include <limits> + +namespace PBQP { + + /// \brief Heuristic PBQP solver implementation. + /// + /// This class should usually be created (and destroyed) indirectly via a call + /// to HeuristicSolver<HImpl>::solve(Graph&). + /// See the comments for HeuristicSolver. + /// + /// HeuristicSolverImpl provides the R0, R1 and R2 reduction rules, + /// backpropagation phase, and maintains the internal copy of the graph on + /// which the reduction is carried out (the original being kept to facilitate + /// backpropagation). + template <typename HImpl> + class HeuristicSolverImpl { + private: + + typedef typename HImpl::NodeData HeuristicNodeData; + typedef typename HImpl::EdgeData HeuristicEdgeData; + + typedef std::list<Graph::EdgeItr> SolverEdges; + + public: + + /// \brief Iterator type for edges in the solver graph. + typedef SolverEdges::iterator SolverEdgeItr; + + private: + + class NodeData { + public: + NodeData() : solverDegree(0) {} + + HeuristicNodeData& getHeuristicData() { return hData; } + + SolverEdgeItr addSolverEdge(Graph::EdgeItr eItr) { + ++solverDegree; + return solverEdges.insert(solverEdges.end(), eItr); + } + + void removeSolverEdge(SolverEdgeItr seItr) { + --solverDegree; + solverEdges.erase(seItr); + } + + SolverEdgeItr solverEdgesBegin() { return solverEdges.begin(); } + SolverEdgeItr solverEdgesEnd() { return solverEdges.end(); } + unsigned getSolverDegree() const { return solverDegree; } + void clearSolverEdges() { + solverDegree = 0; + solverEdges.clear(); + } + + private: + HeuristicNodeData hData; + unsigned solverDegree; + SolverEdges solverEdges; + }; + + class EdgeData { + public: + HeuristicEdgeData& getHeuristicData() { return hData; } + + void setN1SolverEdgeItr(SolverEdgeItr n1SolverEdgeItr) { + this->n1SolverEdgeItr = n1SolverEdgeItr; + } + + SolverEdgeItr getN1SolverEdgeItr() { return n1SolverEdgeItr; } + + void setN2SolverEdgeItr(SolverEdgeItr n2SolverEdgeItr){ + this->n2SolverEdgeItr = n2SolverEdgeItr; + } + + SolverEdgeItr getN2SolverEdgeItr() { return n2SolverEdgeItr; } + + private: + + HeuristicEdgeData hData; + SolverEdgeItr n1SolverEdgeItr, n2SolverEdgeItr; + }; + + Graph &g; + HImpl h; + Solution s; + std::vector<Graph::NodeItr> stack; + + typedef std::list<NodeData> NodeDataList; + NodeDataList nodeDataList; + + typedef std::list<EdgeData> EdgeDataList; + EdgeDataList edgeDataList; + + public: + + /// \brief Construct a heuristic solver implementation to solve the given + /// graph. + /// @param g The graph representing the problem instance to be solved. + HeuristicSolverImpl(Graph &g) : g(g), h(*this) {} + + /// \brief Get the graph being solved by this solver. + /// @return The graph representing the problem instance being solved by this + /// solver. + Graph& getGraph() { return g; } + + /// \brief Get the heuristic data attached to the given node. + /// @param nItr Node iterator. + /// @return The heuristic data attached to the given node. + HeuristicNodeData& getHeuristicNodeData(Graph::NodeItr nItr) { + return getSolverNodeData(nItr).getHeuristicData(); + } + + /// \brief Get the heuristic data attached to the given edge. + /// @param eItr Edge iterator. + /// @return The heuristic data attached to the given node. + HeuristicEdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) { + return getSolverEdgeData(eItr).getHeuristicData(); + } + + /// \brief Begin iterator for the set of edges adjacent to the given node in + /// the solver graph. + /// @param nItr Node iterator. + /// @return Begin iterator for the set of edges adjacent to the given node + /// in the solver graph. + SolverEdgeItr solverEdgesBegin(Graph::NodeItr nItr) { + return getSolverNodeData(nItr).solverEdgesBegin(); + } + + /// \brief End iterator for the set of edges adjacent to the given node in + /// the solver graph. + /// @param nItr Node iterator. + /// @return End iterator for the set of edges adjacent to the given node in + /// the solver graph. + SolverEdgeItr solverEdgesEnd(Graph::NodeItr nItr) { + return getSolverNodeData(nItr).solverEdgesEnd(); + } + + /// \brief Remove a node from the solver graph. + /// @param eItr Edge iterator for edge to be removed. + /// + /// Does <i>not</i> notify the heuristic of the removal. That should be + /// done manually if necessary. + void removeSolverEdge(Graph::EdgeItr eItr) { + EdgeData &eData = getSolverEdgeData(eItr); + NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)), + &n2Data = getSolverNodeData(g.getEdgeNode2(eItr)); + + n1Data.removeSolverEdge(eData.getN1SolverEdgeItr()); + n2Data.removeSolverEdge(eData.getN2SolverEdgeItr()); + } + + /// \brief Compute a solution to the PBQP problem instance with which this + /// heuristic solver was constructed. + /// @return A solution to the PBQP problem. + /// + /// Performs the full PBQP heuristic solver algorithm, including setup, + /// calls to the heuristic (which will call back to the reduction rules in + /// this class), and cleanup. + Solution computeSolution() { + setup(); + h.setup(); + h.reduce(); + backpropagate(); + h.cleanup(); + cleanup(); + return s; + } + + /// \brief Add to the end of the stack. + /// @param nItr Node iterator to add to the reduction stack. + void pushToStack(Graph::NodeItr nItr) { + getSolverNodeData(nItr).clearSolverEdges(); + stack.push_back(nItr); + } + + /// \brief Returns the solver degree of the given node. + /// @param nItr Node iterator for which degree is requested. + /// @return Node degree in the <i>solver</i> graph (not the original graph). + unsigned getSolverDegree(Graph::NodeItr nItr) { + return getSolverNodeData(nItr).getSolverDegree(); + } + + /// \brief Set the solution of the given node. + /// @param nItr Node iterator to set solution for. + /// @param selection Selection for node. + void setSolution(const Graph::NodeItr &nItr, unsigned selection) { + s.setSelection(nItr, selection); + + for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr), + aeEnd = g.adjEdgesEnd(nItr); + aeItr != aeEnd; ++aeItr) { + Graph::EdgeItr eItr(*aeItr); + Graph::NodeItr anItr(g.getEdgeOtherNode(eItr, nItr)); + getSolverNodeData(anItr).addSolverEdge(eItr); + } + } + + /// \brief Apply rule R0. + /// @param nItr Node iterator for node to apply R0 to. + /// + /// Node will be automatically pushed to the solver stack. + void applyR0(Graph::NodeItr nItr) { + assert(getSolverNodeData(nItr).getSolverDegree() == 0 && + "R0 applied to node with degree != 0."); + + // Nothing to do. Just push the node onto the reduction stack. + pushToStack(nItr); + + s.recordR0(); + } + + /// \brief Apply rule R1. + /// @param xnItr Node iterator for node to apply R1 to. + /// + /// Node will be automatically pushed to the solver stack. + void applyR1(Graph::NodeItr xnItr) { + NodeData &nd = getSolverNodeData(xnItr); + assert(nd.getSolverDegree() == 1 && + "R1 applied to node with degree != 1."); + + Graph::EdgeItr eItr = *nd.solverEdgesBegin(); + + const Matrix &eCosts = g.getEdgeCosts(eItr); + const Vector &xCosts = g.getNodeCosts(xnItr); + + // Duplicate a little to avoid transposing matrices. + if (xnItr == g.getEdgeNode1(eItr)) { + Graph::NodeItr ynItr = g.getEdgeNode2(eItr); + Vector &yCosts = g.getNodeCosts(ynItr); + for (unsigned j = 0; j < yCosts.getLength(); ++j) { + PBQPNum min = eCosts[0][j] + xCosts[0]; + for (unsigned i = 1; i < xCosts.getLength(); ++i) { + PBQPNum c = eCosts[i][j] + xCosts[i]; + if (c < min) + min = c; + } + yCosts[j] += min; + } + h.handleRemoveEdge(eItr, ynItr); + } else { + Graph::NodeItr ynItr = g.getEdgeNode1(eItr); + Vector &yCosts = g.getNodeCosts(ynItr); + for (unsigned i = 0; i < yCosts.getLength(); ++i) { + PBQPNum min = eCosts[i][0] + xCosts[0]; + for (unsigned j = 1; j < xCosts.getLength(); ++j) { + PBQPNum c = eCosts[i][j] + xCosts[j]; + if (c < min) + min = c; + } + yCosts[i] += min; + } + h.handleRemoveEdge(eItr, ynItr); + } + removeSolverEdge(eItr); + assert(nd.getSolverDegree() == 0 && + "Degree 1 with edge removed should be 0."); + pushToStack(xnItr); + s.recordR1(); + } + + /// \brief Apply rule R2. + /// @param xnItr Node iterator for node to apply R2 to. + /// + /// Node will be automatically pushed to the solver stack. + void applyR2(Graph::NodeItr xnItr) { + assert(getSolverNodeData(xnItr).getSolverDegree() == 2 && + "R2 applied to node with degree != 2."); + + NodeData &nd = getSolverNodeData(xnItr); + const Vector &xCosts = g.getNodeCosts(xnItr); + + SolverEdgeItr aeItr = nd.solverEdgesBegin(); + Graph::EdgeItr yxeItr = *aeItr, + zxeItr = *(++aeItr); + + Graph::NodeItr ynItr = g.getEdgeOtherNode(yxeItr, xnItr), + znItr = g.getEdgeOtherNode(zxeItr, xnItr); + + bool flipEdge1 = (g.getEdgeNode1(yxeItr) == xnItr), + flipEdge2 = (g.getEdgeNode1(zxeItr) == xnItr); + + const Matrix *yxeCosts = flipEdge1 ? + new Matrix(g.getEdgeCosts(yxeItr).transpose()) : + &g.getEdgeCosts(yxeItr); + + const Matrix *zxeCosts = flipEdge2 ? + new Matrix(g.getEdgeCosts(zxeItr).transpose()) : + &g.getEdgeCosts(zxeItr); + + unsigned xLen = xCosts.getLength(), + yLen = yxeCosts->getRows(), + zLen = zxeCosts->getRows(); + + Matrix delta(yLen, zLen); + + for (unsigned i = 0; i < yLen; ++i) { + for (unsigned j = 0; j < zLen; ++j) { + PBQPNum min = (*yxeCosts)[i][0] + (*zxeCosts)[j][0] + xCosts[0]; + for (unsigned k = 1; k < xLen; ++k) { + PBQPNum c = (*yxeCosts)[i][k] + (*zxeCosts)[j][k] + xCosts[k]; + if (c < min) { + min = c; + } + } + delta[i][j] = min; + } + } + + if (flipEdge1) + delete yxeCosts; + + if (flipEdge2) + delete zxeCosts; + + Graph::EdgeItr yzeItr = g.findEdge(ynItr, znItr); + bool addedEdge = false; + + if (yzeItr == g.edgesEnd()) { + yzeItr = g.addEdge(ynItr, znItr, delta); + addedEdge = true; + } else { + Matrix &yzeCosts = g.getEdgeCosts(yzeItr); + h.preUpdateEdgeCosts(yzeItr); + if (ynItr == g.getEdgeNode1(yzeItr)) { + yzeCosts += delta; + } else { + yzeCosts += delta.transpose(); + } + } + + bool nullCostEdge = tryNormaliseEdgeMatrix(yzeItr); + + if (!addedEdge) { + // If we modified the edge costs let the heuristic know. + h.postUpdateEdgeCosts(yzeItr); + } + + if (nullCostEdge) { + // If this edge ended up null remove it. + if (!addedEdge) { + // We didn't just add it, so we need to notify the heuristic + // and remove it from the solver. + h.handleRemoveEdge(yzeItr, ynItr); + h.handleRemoveEdge(yzeItr, znItr); + removeSolverEdge(yzeItr); + } + g.removeEdge(yzeItr); + } else if (addedEdge) { + // If the edge was added, and non-null, finish setting it up, add it to + // the solver & notify heuristic. + edgeDataList.push_back(EdgeData()); + g.setEdgeData(yzeItr, &edgeDataList.back()); + addSolverEdge(yzeItr); + h.handleAddEdge(yzeItr); + } + + h.handleRemoveEdge(yxeItr, ynItr); + removeSolverEdge(yxeItr); + h.handleRemoveEdge(zxeItr, znItr); + removeSolverEdge(zxeItr); + + pushToStack(xnItr); + s.recordR2(); + } + + /// \brief Record an application of the RN rule. + /// + /// For use by the HeuristicBase. + void recordRN() { s.recordRN(); } + + private: + + NodeData& getSolverNodeData(Graph::NodeItr nItr) { + return *static_cast<NodeData*>(g.getNodeData(nItr)); + } + + EdgeData& getSolverEdgeData(Graph::EdgeItr eItr) { + return *static_cast<EdgeData*>(g.getEdgeData(eItr)); + } + + void addSolverEdge(Graph::EdgeItr eItr) { + EdgeData &eData = getSolverEdgeData(eItr); + NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)), + &n2Data = getSolverNodeData(g.getEdgeNode2(eItr)); + + eData.setN1SolverEdgeItr(n1Data.addSolverEdge(eItr)); + eData.setN2SolverEdgeItr(n2Data.addSolverEdge(eItr)); + } + + void setup() { + if (h.solverRunSimplify()) { + simplify(); + } + + // Create node data objects. + for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); + nItr != nEnd; ++nItr) { + nodeDataList.push_back(NodeData()); + g.setNodeData(nItr, &nodeDataList.back()); + } + + // Create edge data objects. + for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd(); + eItr != eEnd; ++eItr) { + edgeDataList.push_back(EdgeData()); + g.setEdgeData(eItr, &edgeDataList.back()); + addSolverEdge(eItr); + } + } + + void simplify() { + disconnectTrivialNodes(); + eliminateIndependentEdges(); + } + + // Eliminate trivial nodes. + void disconnectTrivialNodes() { + unsigned numDisconnected = 0; + + for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); + nItr != nEnd; ++nItr) { + + if (g.getNodeCosts(nItr).getLength() == 1) { + + std::vector<Graph::EdgeItr> edgesToRemove; + + for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr), + aeEnd = g.adjEdgesEnd(nItr); + aeItr != aeEnd; ++aeItr) { + + Graph::EdgeItr eItr = *aeItr; + + if (g.getEdgeNode1(eItr) == nItr) { + Graph::NodeItr otherNodeItr = g.getEdgeNode2(eItr); + g.getNodeCosts(otherNodeItr) += + g.getEdgeCosts(eItr).getRowAsVector(0); + } + else { + Graph::NodeItr otherNodeItr = g.getEdgeNode1(eItr); + g.getNodeCosts(otherNodeItr) += + g.getEdgeCosts(eItr).getColAsVector(0); + } + + edgesToRemove.push_back(eItr); + } + + if (!edgesToRemove.empty()) + ++numDisconnected; + + while (!edgesToRemove.empty()) { + g.removeEdge(edgesToRemove.back()); + edgesToRemove.pop_back(); + } + } + } + } + + void eliminateIndependentEdges() { + std::vector<Graph::EdgeItr> edgesToProcess; + unsigned numEliminated = 0; + + for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd(); + eItr != eEnd; ++eItr) { + edgesToProcess.push_back(eItr); + } + + while (!edgesToProcess.empty()) { + if (tryToEliminateEdge(edgesToProcess.back())) + ++numEliminated; + edgesToProcess.pop_back(); + } + } + + bool tryToEliminateEdge(Graph::EdgeItr eItr) { + if (tryNormaliseEdgeMatrix(eItr)) { + g.removeEdge(eItr); + return true; + } + return false; + } + + bool tryNormaliseEdgeMatrix(Graph::EdgeItr &eItr) { + + const PBQPNum infinity = std::numeric_limits<PBQPNum>::infinity(); + + Matrix &edgeCosts = g.getEdgeCosts(eItr); + Vector &uCosts = g.getNodeCosts(g.getEdgeNode1(eItr)), + &vCosts = g.getNodeCosts(g.getEdgeNode2(eItr)); + + for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { + PBQPNum rowMin = infinity; + + for (unsigned c = 0; c < edgeCosts.getCols(); ++c) { + if (vCosts[c] != infinity && edgeCosts[r][c] < rowMin) + rowMin = edgeCosts[r][c]; + } + + uCosts[r] += rowMin; + + if (rowMin != infinity) { + edgeCosts.subFromRow(r, rowMin); + } + else { + edgeCosts.setRow(r, 0); + } + } + + for (unsigned c = 0; c < edgeCosts.getCols(); ++c) { + PBQPNum colMin = infinity; + + for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { + if (uCosts[r] != infinity && edgeCosts[r][c] < colMin) + colMin = edgeCosts[r][c]; + } + + vCosts[c] += colMin; + + if (colMin != infinity) { + edgeCosts.subFromCol(c, colMin); + } + else { + edgeCosts.setCol(c, 0); + } + } + + return edgeCosts.isZero(); + } + + void backpropagate() { + while (!stack.empty()) { + computeSolution(stack.back()); + stack.pop_back(); + } + } + + void computeSolution(Graph::NodeItr nItr) { + + NodeData &nodeData = getSolverNodeData(nItr); + + Vector v(g.getNodeCosts(nItr)); + + // Solve based on existing solved edges. + for (SolverEdgeItr solvedEdgeItr = nodeData.solverEdgesBegin(), + solvedEdgeEnd = nodeData.solverEdgesEnd(); + solvedEdgeItr != solvedEdgeEnd; ++solvedEdgeItr) { + + Graph::EdgeItr eItr(*solvedEdgeItr); + Matrix &edgeCosts = g.getEdgeCosts(eItr); + + if (nItr == g.getEdgeNode1(eItr)) { + Graph::NodeItr adjNode(g.getEdgeNode2(eItr)); + unsigned adjSolution = s.getSelection(adjNode); + v += edgeCosts.getColAsVector(adjSolution); + } + else { + Graph::NodeItr adjNode(g.getEdgeNode1(eItr)); + unsigned adjSolution = s.getSelection(adjNode); + v += edgeCosts.getRowAsVector(adjSolution); + } + + } + + setSolution(nItr, v.minIndex()); + } + + void cleanup() { + h.cleanup(); + nodeDataList.clear(); + edgeDataList.clear(); + } + }; + + /// \brief PBQP heuristic solver class. + /// + /// Given a PBQP Graph g representing a PBQP problem, you can find a solution + /// by calling + /// <tt>Solution s = HeuristicSolver<H>::solve(g);</tt> + /// + /// The choice of heuristic for the H parameter will affect both the solver + /// speed and solution quality. The heuristic should be chosen based on the + /// nature of the problem being solved. + /// Currently the only solver included with LLVM is the Briggs heuristic for + /// register allocation. + template <typename HImpl> + class HeuristicSolver { + public: + static Solution solve(Graph &g) { + HeuristicSolverImpl<HImpl> hs(g); + return hs.computeSolution(); + } + }; + +} + +#endif // LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h new file mode 100644 index 0000000..47a287c --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h @@ -0,0 +1,464 @@ +//===-- Briggs.h --- Briggs Heuristic for PBQP ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements the Briggs test for "allocability" of nodes in a +// PBQP graph representing a register allocation problem. Nodes which can be +// proven allocable (by a safe and relatively accurate test) are removed from +// the PBQP graph first. If no provably allocable node is present in the graph +// then the node with the minimal spill-cost to degree ratio is removed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H +#define LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H + +#include "../HeuristicSolver.h" +#include "../HeuristicBase.h" + +#include <set> +#include <limits> + +namespace PBQP { + namespace Heuristics { + + /// \brief PBQP Heuristic which applies an allocability test based on + /// Briggs. + /// + /// This heuristic assumes that the elements of cost vectors in the PBQP + /// problem represent storage options, with the first being the spill + /// option and subsequent elements representing legal registers for the + /// corresponding node. Edge cost matrices are likewise assumed to represent + /// register constraints. + /// If one or more nodes can be proven allocable by this heuristic (by + /// inspection of their constraint matrices) then the allocable node of + /// highest degree is selected for the next reduction and pushed to the + /// solver stack. If no nodes can be proven allocable then the node with + /// the lowest estimated spill cost is selected and push to the solver stack + /// instead. + /// + /// This implementation is built on top of HeuristicBase. + class Briggs : public HeuristicBase<Briggs> { + private: + + class LinkDegreeComparator { + public: + LinkDegreeComparator(HeuristicSolverImpl<Briggs> &s) : s(&s) {} + bool operator()(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr) const { + if (s->getSolverDegree(n1Itr) > s->getSolverDegree(n2Itr)) + return true; + return false; + } + private: + HeuristicSolverImpl<Briggs> *s; + }; + + class SpillCostComparator { + public: + SpillCostComparator(HeuristicSolverImpl<Briggs> &s) + : s(&s), g(&s.getGraph()) {} + bool operator()(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr) const { + const PBQP::Vector &cv1 = g->getNodeCosts(n1Itr); + const PBQP::Vector &cv2 = g->getNodeCosts(n2Itr); + + PBQPNum cost1 = cv1[0] / s->getSolverDegree(n1Itr); + PBQPNum cost2 = cv2[0] / s->getSolverDegree(n2Itr); + + if (cost1 < cost2) + return true; + return false; + } + + private: + HeuristicSolverImpl<Briggs> *s; + Graph *g; + }; + + typedef std::list<Graph::NodeItr> RNAllocableList; + typedef RNAllocableList::iterator RNAllocableListItr; + + typedef std::list<Graph::NodeItr> RNUnallocableList; + typedef RNUnallocableList::iterator RNUnallocableListItr; + + public: + + struct NodeData { + typedef std::vector<unsigned> UnsafeDegreesArray; + bool isHeuristic, isAllocable, isInitialized; + unsigned numDenied, numSafe; + UnsafeDegreesArray unsafeDegrees; + RNAllocableListItr rnaItr; + RNUnallocableListItr rnuItr; + + NodeData() + : isHeuristic(false), isAllocable(false), isInitialized(false), + numDenied(0), numSafe(0) { } + }; + + struct EdgeData { + typedef std::vector<unsigned> UnsafeArray; + unsigned worst, reverseWorst; + UnsafeArray unsafe, reverseUnsafe; + bool isUpToDate; + + EdgeData() : worst(0), reverseWorst(0), isUpToDate(false) {} + }; + + /// \brief Construct an instance of the Briggs heuristic. + /// @param solver A reference to the solver which is using this heuristic. + Briggs(HeuristicSolverImpl<Briggs> &solver) : + HeuristicBase<Briggs>(solver) {} + + /// \brief Determine whether a node should be reduced using optimal + /// reduction. + /// @param nItr Node iterator to be considered. + /// @return True if the given node should be optimally reduced, false + /// otherwise. + /// + /// Selects nodes of degree 0, 1 or 2 for optimal reduction, with one + /// exception. Nodes whose spill cost (element 0 of their cost vector) is + /// infinite are checked for allocability first. Allocable nodes may be + /// optimally reduced, but nodes whose allocability cannot be proven are + /// selected for heuristic reduction instead. + bool shouldOptimallyReduce(Graph::NodeItr nItr) { + if (getSolver().getSolverDegree(nItr) < 3) { + return true; + } + // else + return false; + } + + /// \brief Add a node to the heuristic reduce list. + /// @param nItr Node iterator to add to the heuristic reduce list. + void addToHeuristicReduceList(Graph::NodeItr nItr) { + NodeData &nd = getHeuristicNodeData(nItr); + initializeNode(nItr); + nd.isHeuristic = true; + if (nd.isAllocable) { + nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr); + } else { + nd.rnuItr = rnUnallocableList.insert(rnUnallocableList.end(), nItr); + } + } + + /// \brief Heuristically reduce one of the nodes in the heuristic + /// reduce list. + /// @return True if a reduction takes place, false if the heuristic reduce + /// list is empty. + /// + /// If the list of allocable nodes is non-empty a node is selected + /// from it and pushed to the stack. Otherwise if the non-allocable list + /// is non-empty a node is selected from it and pushed to the stack. + /// If both lists are empty the method simply returns false with no action + /// taken. + bool heuristicReduce() { + if (!rnAllocableList.empty()) { + RNAllocableListItr rnaItr = + min_element(rnAllocableList.begin(), rnAllocableList.end(), + LinkDegreeComparator(getSolver())); + Graph::NodeItr nItr = *rnaItr; + rnAllocableList.erase(rnaItr); + handleRemoveNode(nItr); + getSolver().pushToStack(nItr); + return true; + } else if (!rnUnallocableList.empty()) { + RNUnallocableListItr rnuItr = + min_element(rnUnallocableList.begin(), rnUnallocableList.end(), + SpillCostComparator(getSolver())); + Graph::NodeItr nItr = *rnuItr; + rnUnallocableList.erase(rnuItr); + handleRemoveNode(nItr); + getSolver().pushToStack(nItr); + return true; + } + // else + return false; + } + + /// \brief Prepare a change in the costs on the given edge. + /// @param eItr Edge iterator. + void preUpdateEdgeCosts(Graph::EdgeItr eItr) { + Graph &g = getGraph(); + Graph::NodeItr n1Itr = g.getEdgeNode1(eItr), + n2Itr = g.getEdgeNode2(eItr); + NodeData &n1 = getHeuristicNodeData(n1Itr), + &n2 = getHeuristicNodeData(n2Itr); + + if (n1.isHeuristic) + subtractEdgeContributions(eItr, getGraph().getEdgeNode1(eItr)); + if (n2.isHeuristic) + subtractEdgeContributions(eItr, getGraph().getEdgeNode2(eItr)); + + EdgeData &ed = getHeuristicEdgeData(eItr); + ed.isUpToDate = false; + } + + /// \brief Handle the change in the costs on the given edge. + /// @param eItr Edge iterator. + void postUpdateEdgeCosts(Graph::EdgeItr eItr) { + // This is effectively the same as adding a new edge now, since + // we've factored out the costs of the old one. + handleAddEdge(eItr); + } + + /// \brief Handle the addition of a new edge into the PBQP graph. + /// @param eItr Edge iterator for the added edge. + /// + /// Updates allocability of any nodes connected by this edge which are + /// being managed by the heuristic. If allocability changes they are + /// moved to the appropriate list. + void handleAddEdge(Graph::EdgeItr eItr) { + Graph &g = getGraph(); + Graph::NodeItr n1Itr = g.getEdgeNode1(eItr), + n2Itr = g.getEdgeNode2(eItr); + NodeData &n1 = getHeuristicNodeData(n1Itr), + &n2 = getHeuristicNodeData(n2Itr); + + // If neither node is managed by the heuristic there's nothing to be + // done. + if (!n1.isHeuristic && !n2.isHeuristic) + return; + + // Ok - we need to update at least one node. + computeEdgeContributions(eItr); + + // Update node 1 if it's managed by the heuristic. + if (n1.isHeuristic) { + bool n1WasAllocable = n1.isAllocable; + addEdgeContributions(eItr, n1Itr); + updateAllocability(n1Itr); + if (n1WasAllocable && !n1.isAllocable) { + rnAllocableList.erase(n1.rnaItr); + n1.rnuItr = + rnUnallocableList.insert(rnUnallocableList.end(), n1Itr); + } + } + + // Likewise for node 2. + if (n2.isHeuristic) { + bool n2WasAllocable = n2.isAllocable; + addEdgeContributions(eItr, n2Itr); + updateAllocability(n2Itr); + if (n2WasAllocable && !n2.isAllocable) { + rnAllocableList.erase(n2.rnaItr); + n2.rnuItr = + rnUnallocableList.insert(rnUnallocableList.end(), n2Itr); + } + } + } + + /// \brief Handle disconnection of an edge from a node. + /// @param eItr Edge iterator for edge being disconnected. + /// @param nItr Node iterator for the node being disconnected from. + /// + /// Updates allocability of the given node and, if appropriate, moves the + /// node to a new list. + void handleRemoveEdge(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + NodeData &nd = getHeuristicNodeData(nItr); + + // If the node is not managed by the heuristic there's nothing to be + // done. + if (!nd.isHeuristic) + return; + + EdgeData &ed = getHeuristicEdgeData(eItr); + (void)ed; + assert(ed.isUpToDate && "Edge data is not up to date."); + + // Update node. + bool ndWasAllocable = nd.isAllocable; + subtractEdgeContributions(eItr, nItr); + updateAllocability(nItr); + + // If the node has gone optimal... + if (shouldOptimallyReduce(nItr)) { + nd.isHeuristic = false; + addToOptimalReduceList(nItr); + if (ndWasAllocable) { + rnAllocableList.erase(nd.rnaItr); + } else { + rnUnallocableList.erase(nd.rnuItr); + } + } else { + // Node didn't go optimal, but we might have to move it + // from "unallocable" to "allocable". + if (!ndWasAllocable && nd.isAllocable) { + rnUnallocableList.erase(nd.rnuItr); + nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr); + } + } + } + + private: + + NodeData& getHeuristicNodeData(Graph::NodeItr nItr) { + return getSolver().getHeuristicNodeData(nItr); + } + + EdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) { + return getSolver().getHeuristicEdgeData(eItr); + } + + // Work out what this edge will contribute to the allocability of the + // nodes connected to it. + void computeEdgeContributions(Graph::EdgeItr eItr) { + EdgeData &ed = getHeuristicEdgeData(eItr); + + if (ed.isUpToDate) + return; // Edge data is already up to date. + + Matrix &eCosts = getGraph().getEdgeCosts(eItr); + + unsigned numRegs = eCosts.getRows() - 1, + numReverseRegs = eCosts.getCols() - 1; + + std::vector<unsigned> rowInfCounts(numRegs, 0), + colInfCounts(numReverseRegs, 0); + + ed.worst = 0; + ed.reverseWorst = 0; + ed.unsafe.clear(); + ed.unsafe.resize(numRegs, 0); + ed.reverseUnsafe.clear(); + ed.reverseUnsafe.resize(numReverseRegs, 0); + + for (unsigned i = 0; i < numRegs; ++i) { + for (unsigned j = 0; j < numReverseRegs; ++j) { + if (eCosts[i + 1][j + 1] == + std::numeric_limits<PBQPNum>::infinity()) { + ed.unsafe[i] = 1; + ed.reverseUnsafe[j] = 1; + ++rowInfCounts[i]; + ++colInfCounts[j]; + + if (colInfCounts[j] > ed.worst) { + ed.worst = colInfCounts[j]; + } + + if (rowInfCounts[i] > ed.reverseWorst) { + ed.reverseWorst = rowInfCounts[i]; + } + } + } + } + + ed.isUpToDate = true; + } + + // Add the contributions of the given edge to the given node's + // numDenied and safe members. No action is taken other than to update + // these member values. Once updated these numbers can be used by clients + // to update the node's allocability. + void addEdgeContributions(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + EdgeData &ed = getHeuristicEdgeData(eItr); + + assert(ed.isUpToDate && "Using out-of-date edge numbers."); + + NodeData &nd = getHeuristicNodeData(nItr); + unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + + bool nIsNode1 = nItr == getGraph().getEdgeNode1(eItr); + EdgeData::UnsafeArray &unsafe = + nIsNode1 ? ed.unsafe : ed.reverseUnsafe; + nd.numDenied += nIsNode1 ? ed.worst : ed.reverseWorst; + + for (unsigned r = 0; r < numRegs; ++r) { + if (unsafe[r]) { + if (nd.unsafeDegrees[r]==0) { + --nd.numSafe; + } + ++nd.unsafeDegrees[r]; + } + } + } + + // Subtract the contributions of the given edge to the given node's + // numDenied and safe members. No action is taken other than to update + // these member values. Once updated these numbers can be used by clients + // to update the node's allocability. + void subtractEdgeContributions(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + EdgeData &ed = getHeuristicEdgeData(eItr); + + assert(ed.isUpToDate && "Using out-of-date edge numbers."); + + NodeData &nd = getHeuristicNodeData(nItr); + unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + + bool nIsNode1 = nItr == getGraph().getEdgeNode1(eItr); + EdgeData::UnsafeArray &unsafe = + nIsNode1 ? ed.unsafe : ed.reverseUnsafe; + nd.numDenied -= nIsNode1 ? ed.worst : ed.reverseWorst; + + for (unsigned r = 0; r < numRegs; ++r) { + if (unsafe[r]) { + if (nd.unsafeDegrees[r] == 1) { + ++nd.numSafe; + } + --nd.unsafeDegrees[r]; + } + } + } + + void updateAllocability(Graph::NodeItr nItr) { + NodeData &nd = getHeuristicNodeData(nItr); + unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + nd.isAllocable = nd.numDenied < numRegs || nd.numSafe > 0; + } + + void initializeNode(Graph::NodeItr nItr) { + NodeData &nd = getHeuristicNodeData(nItr); + + if (nd.isInitialized) + return; // Node data is already up to date. + + unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + + nd.numDenied = 0; + nd.numSafe = numRegs; + nd.unsafeDegrees.resize(numRegs, 0); + + typedef HeuristicSolverImpl<Briggs>::SolverEdgeItr SolverEdgeItr; + + for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(nItr), + aeEnd = getSolver().solverEdgesEnd(nItr); + aeItr != aeEnd; ++aeItr) { + + Graph::EdgeItr eItr = *aeItr; + computeEdgeContributions(eItr); + addEdgeContributions(eItr, nItr); + } + + updateAllocability(nItr); + nd.isInitialized = true; + } + + void handleRemoveNode(Graph::NodeItr xnItr) { + typedef HeuristicSolverImpl<Briggs>::SolverEdgeItr SolverEdgeItr; + std::vector<Graph::EdgeItr> edgesToRemove; + for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(xnItr), + aeEnd = getSolver().solverEdgesEnd(xnItr); + aeItr != aeEnd; ++aeItr) { + Graph::NodeItr ynItr = getGraph().getEdgeOtherNode(*aeItr, xnItr); + handleRemoveEdge(*aeItr, ynItr); + edgesToRemove.push_back(*aeItr); + } + while (!edgesToRemove.empty()) { + getSolver().removeSolverEdge(edgesToRemove.back()); + edgesToRemove.pop_back(); + } + } + + RNAllocableList rnAllocableList; + RNUnallocableList rnUnallocableList; + }; + + } +} + + +#endif // LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h new file mode 100644 index 0000000..e7598bf --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h @@ -0,0 +1,288 @@ +//===------ Math.h - PBQP Vector and Matrix classes -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_MATH_H +#define LLVM_CODEGEN_PBQP_MATH_H + +#include <cassert> +#include <algorithm> +#include <functional> + +namespace PBQP { + +typedef float PBQPNum; + +/// \brief PBQP Vector class. +class Vector { + public: + + /// \brief Construct a PBQP vector of the given size. + explicit Vector(unsigned length) : + length(length), data(new PBQPNum[length]) { + } + + /// \brief Construct a PBQP vector with initializer. + Vector(unsigned length, PBQPNum initVal) : + length(length), data(new PBQPNum[length]) { + std::fill(data, data + length, initVal); + } + + /// \brief Copy construct a PBQP vector. + Vector(const Vector &v) : + length(v.length), data(new PBQPNum[length]) { + std::copy(v.data, v.data + length, data); + } + + /// \brief Destroy this vector, return its memory. + ~Vector() { delete[] data; } + + /// \brief Assignment operator. + Vector& operator=(const Vector &v) { + delete[] data; + length = v.length; + data = new PBQPNum[length]; + std::copy(v.data, v.data + length, data); + return *this; + } + + /// \brief Return the length of the vector + unsigned getLength() const { + return length; + } + + /// \brief Element access. + PBQPNum& operator[](unsigned index) { + assert(index < length && "Vector element access out of bounds."); + return data[index]; + } + + /// \brief Const element access. + const PBQPNum& operator[](unsigned index) const { + assert(index < length && "Vector element access out of bounds."); + return data[index]; + } + + /// \brief Add another vector to this one. + Vector& operator+=(const Vector &v) { + assert(length == v.length && "Vector length mismatch."); + std::transform(data, data + length, v.data, data, std::plus<PBQPNum>()); + return *this; + } + + /// \brief Subtract another vector from this one. + Vector& operator-=(const Vector &v) { + assert(length == v.length && "Vector length mismatch."); + std::transform(data, data + length, v.data, data, std::minus<PBQPNum>()); + return *this; + } + + /// \brief Returns the index of the minimum value in this vector + unsigned minIndex() const { + return std::min_element(data, data + length) - data; + } + + private: + unsigned length; + PBQPNum *data; +}; + +/// \brief Output a textual representation of the given vector on the given +/// output stream. +template <typename OStream> +OStream& operator<<(OStream &os, const Vector &v) { + assert((v.getLength() != 0) && "Zero-length vector badness."); + + os << "[ " << v[0]; + for (unsigned i = 1; i < v.getLength(); ++i) { + os << ", " << v[i]; + } + os << " ]"; + + return os; +} + + +/// \brief PBQP Matrix class +class Matrix { + public: + + /// \brief Construct a PBQP Matrix with the given dimensions. + Matrix(unsigned rows, unsigned cols) : + rows(rows), cols(cols), data(new PBQPNum[rows * cols]) { + } + + /// \brief Construct a PBQP Matrix with the given dimensions and initial + /// value. + Matrix(unsigned rows, unsigned cols, PBQPNum initVal) : + rows(rows), cols(cols), data(new PBQPNum[rows * cols]) { + std::fill(data, data + (rows * cols), initVal); + } + + /// \brief Copy construct a PBQP matrix. + Matrix(const Matrix &m) : + rows(m.rows), cols(m.cols), data(new PBQPNum[rows * cols]) { + std::copy(m.data, m.data + (rows * cols), data); + } + + /// \brief Destroy this matrix, return its memory. + ~Matrix() { delete[] data; } + + /// \brief Assignment operator. + Matrix& operator=(const Matrix &m) { + delete[] data; + rows = m.rows; cols = m.cols; + data = new PBQPNum[rows * cols]; + std::copy(m.data, m.data + (rows * cols), data); + return *this; + } + + /// \brief Return the number of rows in this matrix. + unsigned getRows() const { return rows; } + + /// \brief Return the number of cols in this matrix. + unsigned getCols() const { return cols; } + + /// \brief Matrix element access. + PBQPNum* operator[](unsigned r) { + assert(r < rows && "Row out of bounds."); + return data + (r * cols); + } + + /// \brief Matrix element access. + const PBQPNum* operator[](unsigned r) const { + assert(r < rows && "Row out of bounds."); + return data + (r * cols); + } + + /// \brief Returns the given row as a vector. + Vector getRowAsVector(unsigned r) const { + Vector v(cols); + for (unsigned c = 0; c < cols; ++c) + v[c] = (*this)[r][c]; + return v; + } + + /// \brief Returns the given column as a vector. + Vector getColAsVector(unsigned c) const { + Vector v(rows); + for (unsigned r = 0; r < rows; ++r) + v[r] = (*this)[r][c]; + return v; + } + + /// \brief Reset the matrix to the given value. + Matrix& reset(PBQPNum val = 0) { + std::fill(data, data + (rows * cols), val); + return *this; + } + + /// \brief Set a single row of this matrix to the given value. + Matrix& setRow(unsigned r, PBQPNum val) { + assert(r < rows && "Row out of bounds."); + std::fill(data + (r * cols), data + ((r + 1) * cols), val); + return *this; + } + + /// \brief Set a single column of this matrix to the given value. + Matrix& setCol(unsigned c, PBQPNum val) { + assert(c < cols && "Column out of bounds."); + for (unsigned r = 0; r < rows; ++r) + (*this)[r][c] = val; + return *this; + } + + /// \brief Matrix transpose. + Matrix transpose() const { + Matrix m(cols, rows); + for (unsigned r = 0; r < rows; ++r) + for (unsigned c = 0; c < cols; ++c) + m[c][r] = (*this)[r][c]; + return m; + } + + /// \brief Returns the diagonal of the matrix as a vector. + /// + /// Matrix must be square. + Vector diagonalize() const { + assert(rows == cols && "Attempt to diagonalize non-square matrix."); + + Vector v(rows); + for (unsigned r = 0; r < rows; ++r) + v[r] = (*this)[r][r]; + return v; + } + + /// \brief Add the given matrix to this one. + Matrix& operator+=(const Matrix &m) { + assert(rows == m.rows && cols == m.cols && + "Matrix dimensions mismatch."); + std::transform(data, data + (rows * cols), m.data, data, + std::plus<PBQPNum>()); + return *this; + } + + /// \brief Returns the minimum of the given row + PBQPNum getRowMin(unsigned r) const { + assert(r < rows && "Row out of bounds"); + return *std::min_element(data + (r * cols), data + ((r + 1) * cols)); + } + + /// \brief Returns the minimum of the given column + PBQPNum getColMin(unsigned c) const { + PBQPNum minElem = (*this)[0][c]; + for (unsigned r = 1; r < rows; ++r) + if ((*this)[r][c] < minElem) minElem = (*this)[r][c]; + return minElem; + } + + /// \brief Subtracts the given scalar from the elements of the given row. + Matrix& subFromRow(unsigned r, PBQPNum val) { + assert(r < rows && "Row out of bounds"); + std::transform(data + (r * cols), data + ((r + 1) * cols), + data + (r * cols), + std::bind2nd(std::minus<PBQPNum>(), val)); + return *this; + } + + /// \brief Subtracts the given scalar from the elements of the given column. + Matrix& subFromCol(unsigned c, PBQPNum val) { + for (unsigned r = 0; r < rows; ++r) + (*this)[r][c] -= val; + return *this; + } + + /// \brief Returns true if this is a zero matrix. + bool isZero() const { + return find_if(data, data + (rows * cols), + std::bind2nd(std::not_equal_to<PBQPNum>(), 0)) == + data + (rows * cols); + } + + private: + unsigned rows, cols; + PBQPNum *data; +}; + +/// \brief Output a textual representation of the given matrix on the given +/// output stream. +template <typename OStream> +OStream& operator<<(OStream &os, const Matrix &m) { + + assert((m.getRows() != 0) && "Zero-row matrix badness."); + + for (unsigned i = 0; i < m.getRows(); ++i) { + os << m.getRowAsVector(i); + } + + return os; +} + +} + +#endif // LLVM_CODEGEN_PBQP_MATH_H diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h new file mode 100644 index 0000000..57d9b95 --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h @@ -0,0 +1,94 @@ +//===-- Solution.h ------- PBQP Solution ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// PBQP Solution class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_SOLUTION_H +#define LLVM_CODEGEN_PBQP_SOLUTION_H + +#include "Math.h" +#include "Graph.h" + +#include <map> + +namespace PBQP { + + /// \brief Represents a solution to a PBQP problem. + /// + /// To get the selection for each node in the problem use the getSelection method. + class Solution { + private: + + typedef std::map<Graph::ConstNodeItr, unsigned, + NodeItrComparator> SelectionsMap; + SelectionsMap selections; + + unsigned r0Reductions, r1Reductions, r2Reductions, rNReductions; + + public: + + /// \brief Initialise an empty solution. + Solution() + : r0Reductions(0), r1Reductions(0), r2Reductions(0), rNReductions(0) {} + + /// \brief Number of nodes for which selections have been made. + /// @return Number of nodes for which selections have been made. + unsigned numNodes() const { return selections.size(); } + + /// \brief Records a reduction via the R0 rule. Should be called from the + /// solver only. + void recordR0() { ++r0Reductions; } + + /// \brief Returns the number of R0 reductions applied to solve the problem. + unsigned numR0Reductions() const { return r0Reductions; } + + /// \brief Records a reduction via the R1 rule. Should be called from the + /// solver only. + void recordR1() { ++r1Reductions; } + + /// \brief Returns the number of R1 reductions applied to solve the problem. + unsigned numR1Reductions() const { return r1Reductions; } + + /// \brief Records a reduction via the R2 rule. Should be called from the + /// solver only. + void recordR2() { ++r2Reductions; } + + /// \brief Returns the number of R2 reductions applied to solve the problem. + unsigned numR2Reductions() const { return r2Reductions; } + + /// \brief Records a reduction via the RN rule. Should be called from the + /// solver only. + void recordRN() { ++ rNReductions; } + + /// \brief Returns the number of RN reductions applied to solve the problem. + unsigned numRNReductions() const { return rNReductions; } + + /// \brief Set the selection for a given node. + /// @param nItr Node iterator. + /// @param selection Selection for nItr. + void setSelection(Graph::NodeItr nItr, unsigned selection) { + selections[nItr] = selection; + } + + /// \brief Get a node's selection. + /// @param nItr Node iterator. + /// @return The selection for nItr; + unsigned getSelection(Graph::ConstNodeItr nItr) const { + SelectionsMap::const_iterator sItr = selections.find(nItr); + assert(sItr != selections.end() && "No selection for node."); + return sItr->second; + } + + }; + +} + +#endif // LLVM_CODEGEN_PBQP_SOLUTION_H diff --git a/contrib/llvm/include/llvm/CodeGen/Passes.h b/contrib/llvm/include/llvm/CodeGen/Passes.h index 4762a39..53aee7a 100644 --- a/contrib/llvm/include/llvm/CodeGen/Passes.h +++ b/contrib/llvm/include/llvm/CodeGen/Passes.h @@ -45,10 +45,19 @@ namespace llvm { /// extern char &MachineLoopInfoID; + /// MachineLoopRanges pass - This pass is an on-demand loop coverage + /// analysis pass. + /// + extern char &MachineLoopRangesID; + /// MachineDominators pass - This pass is a machine dominators analysis pass. /// extern char &MachineDominatorsID; + /// EdgeBundles analysis - Bundle machine CFG edges. + /// + extern char &EdgeBundlesID; + /// PHIElimination pass - This pass eliminates machine instruction PHI nodes /// by inserting copy instructions. This destroys SSA information, but is the /// desired input for some register allocators. This pass is "required" by @@ -66,6 +75,9 @@ namespace llvm { extern char &PreAllocSplittingID; + /// LiveStacks pass. An analysis keeping track of the liveness of stack slots. + extern char &LiveStacksID; + /// SimpleRegisterCoalescing pass. Aggressively coalesces every register /// copy it can. /// @@ -76,6 +88,11 @@ namespace llvm { /// register allocators. extern char &TwoAddressInstructionPassID; + /// SpillPlacement analysis. Suggest optimal placement of spill code between + /// basic blocks. + /// + extern char &SpillPlacementID; + /// UnreachableMachineBlockElimination pass - This pass removes unreachable /// machine basic blocks. extern char &UnreachableMachineBlockElimID; @@ -95,6 +112,16 @@ namespace llvm { /// FunctionPass *createFastRegisterAllocator(); + /// BasicRegisterAllocation Pass - This pass implements a degenerate global + /// register allocator using the basic regalloc framework. + /// + FunctionPass *createBasicRegisterAllocator(); + + /// Greedy register allocation pass - This pass implements a global register + /// allocator for optimized builds. + /// + FunctionPass *createGreedyRegisterAllocator(); + /// LinearScanRegisterAllocation Pass - This pass implements the linear scan /// register allocation algorithm, a global register allocator. /// @@ -103,7 +130,7 @@ namespace llvm { /// PBQPRegisterAllocation Pass - This pass implements the Partitioned Boolean /// Quadratic Prograaming (PBQP) based register allocator. /// - FunctionPass *createPBQPRegisterAllocator(); + FunctionPass *createDefaultPBQPRegisterAllocator(); /// SimpleRegisterCoalescing Pass - Coalesce all copies possible. Can run /// independently of the register allocator. @@ -188,7 +215,7 @@ namespace llvm { /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. - FunctionPass *createMachineVerifierPass(); + FunctionPass *createMachineVerifierPass(const char *Banner = 0); /// createDwarfEHPass - This pass mulches exception handling code into a form /// adapted to code generation. Required if using dwarf exception handling. @@ -205,6 +232,10 @@ namespace llvm { /// addressing. FunctionPass *createLocalStackSlotAllocationPass(); + /// createExpandISelPseudosPass - This pass expands pseudo-instructions. + /// + FunctionPass *createExpandISelPseudosPass(); + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/CodeGen/PostRAHazardRecognizer.h b/contrib/llvm/include/llvm/CodeGen/PostRAHazardRecognizer.h deleted file mode 100644 index 24d73cb..0000000 --- a/contrib/llvm/include/llvm/CodeGen/PostRAHazardRecognizer.h +++ /dev/null @@ -1,94 +0,0 @@ -//=- llvm/CodeGen/PostRAHazardRecognizer.h - Scheduling Support -*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the PostRAHazardRecognizer class, which -// implements hazard-avoidance heuristics for scheduling, based on the -// scheduling itineraries specified for the target. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H -#define LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H - -#include "llvm/CodeGen/ScheduleHazardRecognizer.h" -#include "llvm/System/DataTypes.h" - -#include <cassert> -#include <cstring> -#include <string> - -namespace llvm { - -class InstrItineraryData; -class SUnit; - -class PostRAHazardRecognizer : public ScheduleHazardRecognizer { - // ScoreBoard to track function unit usage. ScoreBoard[0] is a - // mask of the FUs in use in the cycle currently being - // schedule. ScoreBoard[1] is a mask for the next cycle. The - // ScoreBoard is used as a circular buffer with the current cycle - // indicated by Head. - class ScoreBoard { - unsigned *Data; - - // The maximum number of cycles monitored by the Scoreboard. This - // value is determined based on the target itineraries to ensure - // that all hazards can be tracked. - size_t Depth; - // Indices into the Scoreboard that represent the current cycle. - size_t Head; - public: - ScoreBoard():Data(NULL), Depth(0), Head(0) { } - ~ScoreBoard() { - delete[] Data; - } - - size_t getDepth() const { return Depth; } - unsigned& operator[](size_t idx) const { - assert(Depth && "ScoreBoard was not initialized properly!"); - - return Data[(Head + idx) % Depth]; - } - - void reset(size_t d = 1) { - if (Data == NULL) { - Depth = d; - Data = new unsigned[Depth]; - } - - memset(Data, 0, Depth * sizeof(Data[0])); - Head = 0; - } - - void advance() { - Head = (Head + 1) % Depth; - } - - // Print the scoreboard. - void dump() const; - }; - - // Itinerary data for the target. - const InstrItineraryData &ItinData; - - ScoreBoard ReservedScoreboard; - ScoreBoard RequiredScoreboard; - -public: - PostRAHazardRecognizer(const InstrItineraryData &ItinData); - - virtual HazardType getHazardType(SUnit *SU); - virtual void Reset(); - virtual void EmitInstruction(SUnit *SU); - virtual void AdvanceCycle(); -}; - -} - -#endif diff --git a/contrib/llvm/include/llvm/CodeGen/ProcessImplicitDefs.h b/contrib/llvm/include/llvm/CodeGen/ProcessImplicitDefs.h index 1d743c1..e2ab899 100644 --- a/contrib/llvm/include/llvm/CodeGen/ProcessImplicitDefs.h +++ b/contrib/llvm/include/llvm/CodeGen/ProcessImplicitDefs.h @@ -31,7 +31,9 @@ namespace llvm { public: static char ID; - ProcessImplicitDefs() : MachineFunctionPass(ID) {} + ProcessImplicitDefs() : MachineFunctionPass(ID) { + initializeProcessImplicitDefsPass(*PassRegistry::getPassRegistry()); + } virtual void getAnalysisUsage(AnalysisUsage &au) const; diff --git a/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h b/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h new file mode 100644 index 0000000..7e8745e --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h @@ -0,0 +1,167 @@ +//===-- RegAllocPBQP.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PBQPBuilder interface, for classes which build PBQP +// instances to represent register allocation problems, and the RegAllocPBQP +// interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REGALLOCPBQP_H +#define LLVM_CODEGEN_REGALLOCPBQP_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/PBQP/Graph.h" +#include "llvm/CodeGen/PBQP/Solution.h" + +#include <map> +#include <set> + +namespace llvm { + + class LiveIntervals; + class MachineFunction; + class MachineLoopInfo; + + /// This class wraps up a PBQP instance representing a register allocation + /// problem, plus the structures necessary to map back from the PBQP solution + /// to a register allocation solution. (i.e. The PBQP-node <--> vreg map, + /// and the PBQP option <--> storage location map). + + class PBQPRAProblem { + public: + + typedef SmallVector<unsigned, 16> AllowedSet; + + PBQP::Graph& getGraph() { return graph; } + + const PBQP::Graph& getGraph() const { return graph; } + + /// Record the mapping between the given virtual register and PBQP node, + /// and the set of allowed pregs for the vreg. + /// + /// If you are extending + /// PBQPBuilder you are unlikely to need this: Nodes and options for all + /// vregs will already have been set up for you by the base class. + template <typename AllowedRegsItr> + void recordVReg(unsigned vreg, PBQP::Graph::NodeItr node, + AllowedRegsItr arBegin, AllowedRegsItr arEnd) { + assert(node2VReg.find(node) == node2VReg.end() && "Re-mapping node."); + assert(vreg2Node.find(vreg) == vreg2Node.end() && "Re-mapping vreg."); + assert(allowedSets[vreg].empty() && "vreg already has pregs."); + + node2VReg[node] = vreg; + vreg2Node[vreg] = node; + std::copy(arBegin, arEnd, std::back_inserter(allowedSets[vreg])); + } + + /// Get the virtual register corresponding to the given PBQP node. + unsigned getVRegForNode(PBQP::Graph::ConstNodeItr node) const; + + /// Get the PBQP node corresponding to the given virtual register. + PBQP::Graph::NodeItr getNodeForVReg(unsigned vreg) const; + + /// Returns true if the given PBQP option represents a physical register, + /// false otherwise. + bool isPRegOption(unsigned vreg, unsigned option) const { + // At present we only have spills or pregs, so anything that's not a + // spill is a preg. (This might be extended one day to support remat). + return !isSpillOption(vreg, option); + } + + /// Returns true if the given PBQP option represents spilling, false + /// otherwise. + bool isSpillOption(unsigned vreg, unsigned option) const { + // We hardcode option zero as the spill option. + return option == 0; + } + + /// Returns the allowed set for the given virtual register. + const AllowedSet& getAllowedSet(unsigned vreg) const; + + /// Get PReg for option. + unsigned getPRegForOption(unsigned vreg, unsigned option) const; + + private: + + typedef std::map<PBQP::Graph::ConstNodeItr, unsigned, + PBQP::NodeItrComparator> Node2VReg; + typedef DenseMap<unsigned, PBQP::Graph::NodeItr> VReg2Node; + typedef std::map<unsigned, AllowedSet> AllowedSetMap; + + PBQP::Graph graph; + Node2VReg node2VReg; + VReg2Node vreg2Node; + + AllowedSetMap allowedSets; + + }; + + /// Builds PBQP instances to represent register allocation problems. Includes + /// spill, interference and coalescing costs by default. You can extend this + /// class to support additional constraints for your architecture. + class PBQPBuilder { + private: + PBQPBuilder(const PBQPBuilder&) {} + void operator=(const PBQPBuilder&) {} + public: + + typedef std::set<unsigned> RegSet; + + /// Default constructor. + PBQPBuilder() {} + + /// Clean up a PBQPBuilder. + virtual ~PBQPBuilder() {} + + /// Build a PBQP instance to represent the register allocation problem for + /// the given MachineFunction. + virtual std::auto_ptr<PBQPRAProblem> build( + MachineFunction *mf, + const LiveIntervals *lis, + const MachineLoopInfo *loopInfo, + const RegSet &vregs); + private: + + void addSpillCosts(PBQP::Vector &costVec, PBQP::PBQPNum spillCost); + + void addInterferenceCosts(PBQP::Matrix &costMat, + const PBQPRAProblem::AllowedSet &vr1Allowed, + const PBQPRAProblem::AllowedSet &vr2Allowed, + const TargetRegisterInfo *tri); + }; + + /// Extended builder which adds coalescing constraints to a problem. + class PBQPBuilderWithCoalescing : public PBQPBuilder { + public: + + /// Build a PBQP instance to represent the register allocation problem for + /// the given MachineFunction. + virtual std::auto_ptr<PBQPRAProblem> build( + MachineFunction *mf, + const LiveIntervals *lis, + const MachineLoopInfo *loopInfo, + const RegSet &vregs); + + private: + + void addPhysRegCoalesce(PBQP::Vector &costVec, unsigned pregOption, + PBQP::PBQPNum benefit); + + void addVirtRegCoalesce(PBQP::Matrix &costMat, + const PBQPRAProblem::AllowedSet &vr1Allowed, + const PBQPRAProblem::AllowedSet &vr2Allowed, + PBQP::PBQPNum benefit); + }; + + FunctionPass* createPBQPRegisterAllocator(std::auto_ptr<PBQPBuilder> builder); +} + +#endif /* LLVM_CODEGEN_REGALLOCPBQP_H */ diff --git a/contrib/llvm/include/llvm/CodeGen/RegisterCoalescer.h b/contrib/llvm/include/llvm/CodeGen/RegisterCoalescer.h index 7644433..af0b394 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegisterCoalescer.h +++ b/contrib/llvm/include/llvm/CodeGen/RegisterCoalescer.h @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/System/IncludeFile.h" +#include "llvm/Support/IncludeFile.h" #include "llvm/CodeGen/LiveInterval.h" #include "llvm/ADT/SmallPtrSet.h" diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h b/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h index 076268b..3864ffd 100644 --- a/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h +++ b/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h @@ -221,6 +221,9 @@ namespace llvm { } }; + template <> + struct isPodLike<SDep> { static const bool value = true; }; + /// SUnit - Scheduling unit. This is a node in the scheduling DAG. class SUnit { private: @@ -229,9 +232,8 @@ namespace llvm { public: SUnit *OrigNode; // If not this, the node from which // this node was cloned. - - // Preds/Succs - The SUnits before/after us in the graph. The boolean value - // is true if the edge is a token chain edge, false if it is a value edge. + + // Preds/Succs - The SUnits before/after us in the graph. SmallVector<SDep, 4> Preds; // All sunit predecessors. SmallVector<SDep, 4> Succs; // All sunit successors. @@ -242,11 +244,13 @@ namespace llvm { unsigned NodeNum; // Entry # of node in the node vector. unsigned NodeQueueId; // Queue id of node. - unsigned short Latency; // Node latency. unsigned NumPreds; // # of SDep::Data preds. unsigned NumSuccs; // # of SDep::Data sucss. unsigned NumPredsLeft; // # of preds not scheduled. unsigned NumSuccsLeft; // # of succs not scheduled. + unsigned short NumRegDefsLeft; // # of reg defs with no scheduled use. + unsigned short Latency; // Node latency. + bool isCall : 1; // Is a function call. bool isTwoAddress : 1; // Is a two-address instruction. bool isCommutable : 1; // Is a commutable instruction. bool hasPhysRegDefs : 1; // Has physreg defs that are being used. @@ -267,13 +271,14 @@ namespace llvm { public: const TargetRegisterClass *CopyDstRC; // Is a special copy node if not null. const TargetRegisterClass *CopySrcRC; - + /// SUnit - Construct an SUnit for pre-regalloc scheduling to represent /// an SDNode and any nodes flagged to it. SUnit(SDNode *node, unsigned nodenum) : Node(node), Instr(0), OrigNode(0), NodeNum(nodenum), - NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), - NumSuccsLeft(0), isTwoAddress(false), isCommutable(false), + NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), + NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), + isCall(false), isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), isScheduleHigh(false), isCloned(false), @@ -285,8 +290,9 @@ namespace llvm { /// a MachineInstr. SUnit(MachineInstr *instr, unsigned nodenum) : Node(0), Instr(instr), OrigNode(0), NodeNum(nodenum), - NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), - NumSuccsLeft(0), isTwoAddress(false), isCommutable(false), + NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), + NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), + isCall(false), isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), isScheduleHigh(false), isCloned(false), @@ -297,8 +303,9 @@ namespace llvm { /// SUnit - Construct a placeholder SUnit. SUnit() : Node(0), Instr(0), OrigNode(0), NodeNum(~0u), - NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), - NumSuccsLeft(0), isTwoAddress(false), isCommutable(false), + NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), + NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), + isCall(false), isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), isScheduleHigh(false), isCloned(false), @@ -320,6 +327,10 @@ namespace llvm { return Node; } + /// isInstr - Return true if this SUnit refers to a machine instruction as + /// opposed to an SDNode. + bool isInstr() const { return Instr; } + /// setInstr - Assign the instruction for the SUnit. /// This may be used during post-regalloc scheduling. void setInstr(MachineInstr *MI) { @@ -337,7 +348,7 @@ namespace llvm { /// addPred - This adds the specified edge as a pred of the current node if /// not already. It also adds the current node as a successor of the /// specified node. - void addPred(const SDep &D); + bool addPred(const SDep &D); /// removePred - This removes the specified edge as a pred of the current /// node if it exists. It also removes the current node as a successor of @@ -347,7 +358,7 @@ namespace llvm { /// getDepth - Return the depth of this node, which is the length of the /// maximum path up to any node with has no predecessors. unsigned getDepth() const { - if (!isDepthCurrent) + if (!isDepthCurrent) const_cast<SUnit *>(this)->ComputeDepth(); return Depth; } @@ -355,7 +366,7 @@ namespace llvm { /// getHeight - Return the height of this node, which is the length of the /// maximum path down to any node with has no successors. unsigned getHeight() const { - if (!isHeightCurrent) + if (!isHeightCurrent) const_cast<SUnit *>(this)->ComputeHeight(); return Height; } @@ -387,7 +398,7 @@ namespace llvm { return true; return false; } - + /// isSucc - Test if node N is a successor of this node. bool isSucc(SUnit *N) { for (unsigned i = 0, e = (unsigned)Succs.size(); i != e; ++i) @@ -408,25 +419,38 @@ namespace llvm { //===--------------------------------------------------------------------===// /// SchedulingPriorityQueue - This interface is used to plug different /// priorities computation algorithms into the list scheduler. It implements - /// the interface of a standard priority queue, where nodes are inserted in + /// the interface of a standard priority queue, where nodes are inserted in /// arbitrary order and returned in priority order. The computation of the /// priority and the representation of the queue are totally up to the /// implementation to decide. - /// + /// class SchedulingPriorityQueue { unsigned CurCycle; + bool HasReadyFilter; public: - SchedulingPriorityQueue() : CurCycle(0) {} + SchedulingPriorityQueue(bool rf = false): + CurCycle(0), HasReadyFilter(rf) {} virtual ~SchedulingPriorityQueue() {} - + + virtual bool isBottomUp() const = 0; + virtual void initNodes(std::vector<SUnit> &SUnits) = 0; virtual void addNode(const SUnit *SU) = 0; virtual void updateNode(const SUnit *SU) = 0; virtual void releaseState() = 0; virtual bool empty() const = 0; + + bool hasReadyFilter() const { return HasReadyFilter; } + + virtual bool tracksRegPressure() const { return false; } + + virtual bool isReady(SUnit *) const { + assert(!HasReadyFilter && "The ready filter must override isReady()"); + return true; + } virtual void push(SUnit *U) = 0; - + void push_all(const std::vector<SUnit *> &Nodes) { for (std::vector<SUnit *>::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) @@ -437,6 +461,8 @@ namespace llvm { virtual void remove(SUnit *SU) = 0; + virtual void dump(ScheduleDAG *) const {} + /// ScheduledNode - As each node is scheduled, this method is invoked. This /// allows the priority function to adjust the priority of related /// unscheduled nodes, for example. @@ -451,7 +477,7 @@ namespace llvm { unsigned getCurCycle() const { return CurCycle; - } + } }; class ScheduleDAG { @@ -473,11 +499,18 @@ namespace llvm { virtual ~ScheduleDAG(); + /// getInstrDesc - Return the TargetInstrDesc of this SUnit. + /// Return NULL for SDNodes without a machine opcode. + const TargetInstrDesc *getInstrDesc(const SUnit *SU) const { + if (SU->isInstr()) return &SU->getInstr()->getDesc(); + return getNodeDesc(SU->getNode()); + } + /// viewGraph - Pop up a GraphViz/gv window with the ScheduleDAG rendered /// using 'dot'. /// void viewGraph(); - + /// EmitSchedule - Insert MachineInstrs into the MachineBasicBlock /// according to the order specified in Sequence. /// @@ -536,6 +569,10 @@ namespace llvm { void EmitNoop(); void EmitPhysRegCopy(SUnit *SU, DenseMap<SUnit*, unsigned> &VRBaseMap); + + private: + // Return the TargetInstrDesc of this SDNode or NULL. + const TargetInstrDesc *getNodeDesc(const SDNode *Node) const; }; class SUnitIterator : public std::iterator<std::forward_iterator_tag, @@ -627,7 +664,7 @@ namespace llvm { /// Visited - a set of nodes visited during a DFS traversal. BitVector Visited; - /// DFS - make a DFS traversal and mark all nodes affected by the + /// DFS - make a DFS traversal and mark all nodes affected by the /// edge insertion. These nodes will later get new topological indexes /// by means of the Shift method. void DFS(const SUnit *SU, int UpperBound, bool& HasLoop); @@ -642,7 +679,7 @@ namespace llvm { public: explicit ScheduleDAGTopologicalSort(std::vector<SUnit> &SUnits); - /// InitDAGTopologicalSorting - create the initial topological + /// InitDAGTopologicalSorting - create the initial topological /// ordering from the DAG to be scheduled. void InitDAGTopologicalSorting(); diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/contrib/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h index 09e3e88..2f53baa 100644 --- a/contrib/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h +++ b/contrib/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h @@ -23,7 +23,15 @@ class SUnit; /// issued this cycle, and whether or not a noop needs to be inserted to handle /// the hazard. class ScheduleHazardRecognizer { +protected: + /// MaxLookAhead - Indicate the number of cycles in the scoreboard + /// state. Important to restore the state after backtracking. Additionally, + /// MaxLookAhead=0 identifies a fake recognizer, allowing the client to + /// bypass virtual calls. Currently the PostRA scheduler ignores it. + unsigned MaxLookAhead; + public: + ScheduleHazardRecognizer(): MaxLookAhead(0) {} virtual ~ScheduleHazardRecognizer(); enum HazardType { @@ -32,6 +40,14 @@ public: NoopHazard // This instruction can't be emitted, and needs noops. }; + unsigned getMaxLookAhead() const { return MaxLookAhead; } + + bool isEnabled() const { return MaxLookAhead != 0; } + + /// atIssueLimit - Return true if no more instructions may be issued in this + /// cycle. + virtual bool atIssueLimit() const { return false; } + /// getHazardType - Return the hazard type of emitting this node. There are /// three possible results. Either: /// * NoHazard: it is legal to issue this instruction on this cycle. @@ -39,7 +55,7 @@ public: /// other instruction is available, issue it first. /// * NoopHazard: issuing this instruction would break the program. If /// some other instruction can be issued, do so, otherwise issue a noop. - virtual HazardType getHazardType(SUnit *) { + virtual HazardType getHazardType(SUnit *m, int Stalls) { return NoHazard; } @@ -52,12 +68,18 @@ public: /// emitted, to advance the hazard state. virtual void EmitInstruction(SUnit *) {} - /// AdvanceCycle - This callback is invoked when no instructions can be - /// issued on this cycle without a hazard. This should increment the + /// AdvanceCycle - This callback is invoked whenever the next top-down + /// instruction to be scheduled cannot issue in the current cycle, either + /// because of latency or resource conflicts. This should increment the /// internal state of the hazard recognizer so that previously "Hazard" /// instructions will now not be hazards. virtual void AdvanceCycle() {} + /// RecedeCycle - This callback is invoked whenever the next bottom-up + /// instruction to be scheduled cannot issue in the current cycle, either + /// because of latency or resource conflicts. + virtual void RecedeCycle() {} + /// EmitNoop - This callback is invoked when a noop was added to the /// instruction stream. virtual void EmitNoop() { diff --git a/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h new file mode 100644 index 0000000..8850006 --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h @@ -0,0 +1,129 @@ +//=- llvm/CodeGen/ScoreboardHazardRecognizer.h - Schedule Support -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ScoreboardHazardRecognizer class, which +// encapsulates hazard-avoidance heuristics for scheduling, based on the +// scheduling itineraries specified for the target. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H +#define LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H + +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/Support/DataTypes.h" + +#include <cassert> +#include <cstring> +#include <string> + +namespace llvm { + +class InstrItineraryData; +class TargetInstrDesc; +class ScheduleDAG; +class SUnit; + +class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer { + // Scoreboard to track function unit usage. Scoreboard[0] is a + // mask of the FUs in use in the cycle currently being + // schedule. Scoreboard[1] is a mask for the next cycle. The + // Scoreboard is used as a circular buffer with the current cycle + // indicated by Head. + // + // Scoreboard always counts cycles in forward execution order. If used by a + // bottom-up scheduler, then the scoreboard cycles are the inverse of the + // scheduler's cycles. + class Scoreboard { + unsigned *Data; + + // The maximum number of cycles monitored by the Scoreboard. This + // value is determined based on the target itineraries to ensure + // that all hazards can be tracked. + size_t Depth; + // Indices into the Scoreboard that represent the current cycle. + size_t Head; + public: + Scoreboard():Data(NULL), Depth(0), Head(0) { } + ~Scoreboard() { + delete[] Data; + } + + size_t getDepth() const { return Depth; } + unsigned& operator[](size_t idx) const { + // Depth is expected to be a power-of-2. + assert(Depth && !(Depth & (Depth - 1)) && + "Scoreboard was not initialized properly!"); + + return Data[(Head + idx) & (Depth-1)]; + } + + void reset(size_t d = 1) { + if (Data == NULL) { + Depth = d; + Data = new unsigned[Depth]; + } + + memset(Data, 0, Depth * sizeof(Data[0])); + Head = 0; + } + + void advance() { + Head = (Head + 1) & (Depth-1); + } + + void recede() { + Head = (Head - 1) & (Depth-1); + } + + // Print the scoreboard. + void dump() const; + }; + +#ifndef NDEBUG + // Support for tracing ScoreboardHazardRecognizer as a component within + // another module. Follows the current thread-unsafe model of tracing. + static const char *DebugType; +#endif + + // Itinerary data for the target. + const InstrItineraryData *ItinData; + + const ScheduleDAG *DAG; + + /// IssueWidth - Max issue per cycle. 0=Unknown. + unsigned IssueWidth; + + /// IssueCount - Count instructions issued in this cycle. + unsigned IssueCount; + + Scoreboard ReservedScoreboard; + Scoreboard RequiredScoreboard; + +public: + ScoreboardHazardRecognizer(const InstrItineraryData *ItinData, + const ScheduleDAG *DAG, + const char *ParentDebugType = ""); + + /// atIssueLimit - Return true if no more instructions may be issued in this + /// cycle. + virtual bool atIssueLimit() const; + + // Stalls provides an cycle offset at which SU will be scheduled. It will be + // negative for bottom-up scheduling. + virtual HazardType getHazardType(SUnit *SU, int Stalls); + virtual void Reset(); + virtual void EmitInstruction(SUnit *SU); + virtual void AdvanceCycle(); + virtual void RecedeCycle(); +}; + +} + +#endif //!LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h index 7723fa0..c9de95b 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -171,9 +171,6 @@ class SelectionDAG { /// DbgInfo - Tracks dbg_value information through SDISel. SDDbgInfo *DbgInfo; - /// VerifyNode - Sanity check the given node. Aborts if it is invalid. - void VerifyNode(SDNode *N); - /// setGraphColorHelper - Implementation of setSubgraphColor. /// Return whether we had to truncate the search. /// @@ -401,21 +398,21 @@ public: } // This version of the getCopyToReg method takes an extra operand, which - // indicates that there is potentially an incoming flag value (if Flag is not - // null) and that there should be a flag result. + // indicates that there is potentially an incoming glue value (if Glue is not + // null) and that there should be a glue result. SDValue getCopyToReg(SDValue Chain, DebugLoc dl, unsigned Reg, SDValue N, - SDValue Flag) { - SDVTList VTs = getVTList(MVT::Other, MVT::Flag); - SDValue Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Flag }; - return getNode(ISD::CopyToReg, dl, VTs, Ops, Flag.getNode() ? 4 : 3); + SDValue Glue) { + SDVTList VTs = getVTList(MVT::Other, MVT::Glue); + SDValue Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Glue }; + return getNode(ISD::CopyToReg, dl, VTs, Ops, Glue.getNode() ? 4 : 3); } // Similar to last getCopyToReg() except parameter Reg is a SDValue SDValue getCopyToReg(SDValue Chain, DebugLoc dl, SDValue Reg, SDValue N, - SDValue Flag) { - SDVTList VTs = getVTList(MVT::Other, MVT::Flag); - SDValue Ops[] = { Chain, Reg, N, Flag }; - return getNode(ISD::CopyToReg, dl, VTs, Ops, Flag.getNode() ? 4 : 3); + SDValue Glue) { + SDVTList VTs = getVTList(MVT::Other, MVT::Glue); + SDValue Ops[] = { Chain, Reg, N, Glue }; + return getNode(ISD::CopyToReg, dl, VTs, Ops, Glue.getNode() ? 4 : 3); } SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, EVT VT) { @@ -425,13 +422,13 @@ public: } // This version of the getCopyFromReg method takes an extra operand, which - // indicates that there is potentially an incoming flag value (if Flag is not - // null) and that there should be a flag result. + // indicates that there is potentially an incoming glue value (if Glue is not + // null) and that there should be a glue result. SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, EVT VT, - SDValue Flag) { - SDVTList VTs = getVTList(VT, MVT::Other, MVT::Flag); - SDValue Ops[] = { Chain, getRegister(Reg, VT), Flag }; - return getNode(ISD::CopyFromReg, dl, VTs, Ops, Flag.getNode() ? 3 : 2); + SDValue Glue) { + SDVTList VTs = getVTList(VT, MVT::Other, MVT::Glue); + SDValue Ops[] = { Chain, getRegister(Reg, VT), Glue }; + return getNode(ISD::CopyFromReg, dl, VTs, Ops, Glue.getNode() ? 3 : 2); } SDValue getCondCode(ISD::CondCode Cond); @@ -465,27 +462,27 @@ public: SDValue getNOT(DebugLoc DL, SDValue Val, EVT VT); /// getCALLSEQ_START - Return a new CALLSEQ_START node, which always must have - /// a flag result (to ensure it's not CSE'd). CALLSEQ_START does not have a + /// a glue result (to ensure it's not CSE'd). CALLSEQ_START does not have a /// useful DebugLoc. SDValue getCALLSEQ_START(SDValue Chain, SDValue Op) { - SDVTList VTs = getVTList(MVT::Other, MVT::Flag); + SDVTList VTs = getVTList(MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, Op }; return getNode(ISD::CALLSEQ_START, DebugLoc(), VTs, Ops, 2); } /// getCALLSEQ_END - Return a new CALLSEQ_END node, which always must have a - /// flag result (to ensure it's not CSE'd). CALLSEQ_END does not have + /// glue result (to ensure it's not CSE'd). CALLSEQ_END does not have /// a useful DebugLoc. SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, - SDValue InFlag) { - SDVTList NodeTys = getVTList(MVT::Other, MVT::Flag); + SDValue InGlue) { + SDVTList NodeTys = getVTList(MVT::Other, MVT::Glue); SmallVector<SDValue, 4> Ops; Ops.push_back(Chain); Ops.push_back(Op1); Ops.push_back(Op2); - Ops.push_back(InFlag); + Ops.push_back(InGlue); return getNode(ISD::CALLSEQ_END, DebugLoc(), NodeTys, &Ops[0], - (unsigned)Ops.size() - (InFlag.getNode() == 0 ? 1 : 0)); + (unsigned)Ops.size() - (InGlue.getNode() == 0 ? 1 : 0)); } /// getUNDEF - Return an UNDEF node. UNDEF does not have a useful DebugLoc. @@ -542,17 +539,17 @@ public: SDValue getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, bool AlwaysInline, - const Value *DstSV, uint64_t DstSVOff, - const Value *SrcSV, uint64_t SrcSVOff); + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo); SDValue getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, - const Value *DstSV, uint64_t DstOSVff, - const Value *SrcSV, uint64_t SrcSVOff); + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo); SDValue getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, - const Value *DstSV, uint64_t DstSVOff); + MachinePointerInfo DstPtrInfo); /// getSetCC - Helper function to make it easier to build SetCC's if you just /// have an ISD::CondCode instead of an SDValue. @@ -587,8 +584,8 @@ public: /// getAtomic - Gets a node for an atomic op, produces result and chain and /// takes 3 operands SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, - SDValue Ptr, SDValue Cmp, SDValue Swp, const Value* PtrVal, - unsigned Alignment=0); + SDValue Ptr, SDValue Cmp, SDValue Swp, + MachinePointerInfo PtrInfo, unsigned Alignment=0); SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, MachineMemOperand *MMO); @@ -609,13 +606,13 @@ public: SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, const EVT *VTs, unsigned NumVTs, const SDValue *Ops, unsigned NumOps, - EVT MemVT, const Value *srcValue, int SVOff, + EVT MemVT, MachinePointerInfo PtrInfo, unsigned Align = 0, bool Vol = false, bool ReadMem = true, bool WriteMem = true); SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, const SDValue *Ops, unsigned NumOps, - EVT MemVT, const Value *srcValue, int SVOff, + EVT MemVT, MachinePointerInfo PtrInfo, unsigned Align = 0, bool Vol = false, bool ReadMem = true, bool WriteMem = true); @@ -630,19 +627,22 @@ public: /// determined by their operands, and they produce a value AND a token chain. /// SDValue getLoad(EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, - const Value *SV, int SVOffset, bool isVolatile, - bool isNonTemporal, unsigned Alignment); - SDValue getExtLoad(ISD::LoadExtType ExtType, EVT VT, DebugLoc dl, - SDValue Chain, SDValue Ptr, const Value *SV, - int SVOffset, EVT MemVT, bool isVolatile, - bool isNonTemporal, unsigned Alignment); + MachinePointerInfo PtrInfo, bool isVolatile, + bool isNonTemporal, unsigned Alignment, + const MDNode *TBAAInfo = 0); + SDValue getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, EVT VT, + SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, + EVT MemVT, bool isVolatile, + bool isNonTemporal, unsigned Alignment, + const MDNode *TBAAInfo = 0); SDValue getIndexedLoad(SDValue OrigLoad, DebugLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, SDValue Offset, - const Value *SV, int SVOffset, EVT MemVT, - bool isVolatile, bool isNonTemporal, unsigned Alignment); + MachinePointerInfo PtrInfo, EVT MemVT, + bool isVolatile, bool isNonTemporal, unsigned Alignment, + const MDNode *TBAAInfo = 0); SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, SDValue Offset, @@ -651,14 +651,16 @@ public: /// getStore - Helper function to build ISD::STORE nodes. /// SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, - const Value *SV, int SVOffset, bool isVolatile, - bool isNonTemporal, unsigned Alignment); + MachinePointerInfo PtrInfo, bool isVolatile, + bool isNonTemporal, unsigned Alignment, + const MDNode *TBAAInfo = 0); SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, MachineMemOperand *MMO); SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, - const Value *SV, int SVOffset, EVT TVT, + MachinePointerInfo PtrInfo, EVT TVT, bool isNonTemporal, bool isVolatile, - unsigned Alignment); + unsigned Alignment, + const MDNode *TBAAInfo = 0); SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, EVT TVT, MachineMemOperand *MMO); SDValue getIndexedStore(SDValue OrigStoe, DebugLoc dl, SDValue Base, @@ -899,6 +901,9 @@ public: SmallVector<SDDbgValue*,2> &GetDbgValues(const SDNode* SD) { return DbgInfo->getSDDbgValues(SD); } + + /// TransferDbgValues - Transfer SDDbgValues. + void TransferDbgValues(SDValue From, SDValue To); /// hasDebugValues - Return true if there are any SDDbgValue nodes associated /// with this SelectionDAG. @@ -961,6 +966,13 @@ public: /// class to allow target nodes to be understood. unsigned ComputeNumSignBits(SDValue Op, unsigned Depth = 0) const; + /// isBaseWithConstantOffset - Return true if the specified operand is an + /// ISD::ADD with a ConstantSDNode on the right-hand side, or if it is an + /// ISD::OR with a ConstantSDNode that is guaranteed to have the same + /// semantics as an ADD. This handles the equivalence: + /// X|Cst == X+Cst iff X&Cst = 0. + bool isBaseWithConstantOffset(SDValue Op) const; + /// isKnownNeverNan - Test whether the given SDValue is known to never be NaN. bool isKnownNeverNaN(SDValue Op) const; diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h index 01d05dd..62358e7 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h @@ -34,7 +34,8 @@ namespace llvm { class ScheduleHazardRecognizer; class GCFunctionInfo; class ScheduleDAGSDNodes; - + class LoadInst; + /// SelectionDAGISel - This is the common base class used for SelectionDAG-based /// pattern-matching instruction selectors. class SelectionDAGISel : public MachineFunctionPass { @@ -54,7 +55,7 @@ public: explicit SelectionDAGISel(const TargetMachine &tm, CodeGenOpt::Level OL = CodeGenOpt::Default); virtual ~SelectionDAGISel(); - + const TargetLowering &getTargetLowering() { return TLI; } virtual void getAnalysisUsage(AnalysisUsage &AU) const; @@ -62,18 +63,18 @@ public: virtual bool runOnMachineFunction(MachineFunction &MF); virtual void EmitFunctionEntryCode() {} - + /// PreprocessISelDAG - This hook allows targets to hack on the graph before /// instruction selection starts. virtual void PreprocessISelDAG() {} - + /// PostprocessISelDAG() - This hook allows the target to hack on the graph /// right after selection. virtual void PostprocessISelDAG() {} - + /// Select - Main hook targets implement to select a node. virtual SDNode *Select(SDNode *N) = 0; - + /// SelectInlineAsmMemoryOperand - Select the specified address as a target /// addressing mode, according to the specified constraint code. If this does /// not match or is not implemented, return true. The resultant operands @@ -91,25 +92,20 @@ public: /// IsLegalToFold - Returns true if the specific operand node N of /// U can be folded during instruction selection that starts at Root. - /// FIXME: This is a static member function because the PIC16 target, - /// which uses it during lowering. + /// FIXME: This is a static member function because the MSP430/SystemZ/X86 + /// targets, which uses it during isel. This could become a proper member. static bool IsLegalToFold(SDValue N, SDNode *U, SDNode *Root, CodeGenOpt::Level OptLevel, bool IgnoreChains = false); - /// CreateTargetHazardRecognizer - Return a newly allocated hazard recognizer - /// to use for this target when scheduling the DAG. - virtual ScheduleHazardRecognizer *CreateTargetHazardRecognizer(); - - // Opcodes used by the DAG state machine: enum BuiltinOpcodes { OPC_Scope, OPC_RecordNode, - OPC_RecordChild0, OPC_RecordChild1, OPC_RecordChild2, OPC_RecordChild3, + OPC_RecordChild0, OPC_RecordChild1, OPC_RecordChild2, OPC_RecordChild3, OPC_RecordChild4, OPC_RecordChild5, OPC_RecordChild6, OPC_RecordChild7, OPC_RecordMemRef, - OPC_CaptureFlagInput, + OPC_CaptureGlueInput, OPC_MoveChild, OPC_MoveParent, OPC_CheckSame, @@ -128,7 +124,7 @@ public: OPC_CheckComplexPat, OPC_CheckAndImm, OPC_CheckOrImm, OPC_CheckFoldableChainNode, - + OPC_EmitInteger, OPC_EmitRegister, OPC_EmitConvertToTarget, @@ -139,15 +135,15 @@ public: OPC_EmitNodeXForm, OPC_EmitNode, OPC_MorphNodeTo, - OPC_MarkFlagResults, + OPC_MarkGlueResults, OPC_CompleteMatch }; - + enum { - OPFL_None = 0, // Node has no chain or flag input and isn't variadic. + OPFL_None = 0, // Node has no chain or glue input and isn't variadic. OPFL_Chain = 1, // Node has a chain input. - OPFL_FlagInput = 2, // Node has a flag input. - OPFL_FlagOutput = 4, // Node has a flag output. + OPFL_GlueInput = 2, // Node has a glue input. + OPFL_GlueOutput = 4, // Node has a glue output. OPFL_MemRefs = 8, // Node gets accumulated MemRefs. OPFL_Variadic0 = 1<<4, // Node is variadic, root has 0 fixed inputs. OPFL_Variadic1 = 2<<4, // Node is variadic, root has 1 fixed inputs. @@ -156,37 +152,37 @@ public: OPFL_Variadic4 = 5<<4, // Node is variadic, root has 4 fixed inputs. OPFL_Variadic5 = 6<<4, // Node is variadic, root has 5 fixed inputs. OPFL_Variadic6 = 7<<4, // Node is variadic, root has 6 fixed inputs. - + OPFL_VariadicInfo = OPFL_Variadic6 }; - + /// getNumFixedFromVariadicInfo - Transform an EmitNode flags word into the /// number of fixed arity values that should be skipped when copying from the /// root. static inline int getNumFixedFromVariadicInfo(unsigned Flags) { return ((Flags&OPFL_VariadicInfo) >> 4)-1; } - - + + protected: /// DAGSize - Size of DAG being instruction selected. /// unsigned DAGSize; - + /// ISelPosition - Node iterator marking the current position of /// instruction selection as it procedes through the topologically-sorted /// node list. SelectionDAG::allnodes_iterator ISelPosition; - - /// ISelUpdater - helper class to handle updates of the + + /// ISelUpdater - helper class to handle updates of the /// instruction selection graph. class ISelUpdater : public SelectionDAG::DAGUpdateListener { SelectionDAG::allnodes_iterator &ISelPosition; public: explicit ISelUpdater(SelectionDAG::allnodes_iterator &isp) : ISelPosition(isp) {} - + /// NodeDeleted - Handle nodes deleted from the graph. If the /// node being deleted is the current ISelPosition node, update /// ISelPosition. @@ -195,46 +191,46 @@ protected: if (ISelPosition == SelectionDAG::allnodes_iterator(N)) ++ISelPosition; } - + /// NodeUpdated - Ignore updates for now. virtual void NodeUpdated(SDNode *N) {} }; - + /// ReplaceUses - replace all uses of the old node F with the use /// of the new node T. void ReplaceUses(SDValue F, SDValue T) { ISelUpdater ISU(ISelPosition); CurDAG->ReplaceAllUsesOfValueWith(F, T, &ISU); } - + /// ReplaceUses - replace all uses of the old nodes F with the use /// of the new nodes T. void ReplaceUses(const SDValue *F, const SDValue *T, unsigned Num) { ISelUpdater ISU(ISelPosition); CurDAG->ReplaceAllUsesOfValuesWith(F, T, Num, &ISU); } - + /// ReplaceUses - replace all uses of the old node F with the use /// of the new node T. void ReplaceUses(SDNode *F, SDNode *T) { ISelUpdater ISU(ISelPosition); CurDAG->ReplaceAllUsesWith(F, T, &ISU); } - + /// SelectInlineAsmMemoryOperands - Calls to this are automatically generated /// by tblgen. Others should not call it. void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops); - + public: // Calls to these predicates are generated by tblgen. bool CheckAndMask(SDValue LHS, ConstantSDNode *RHS, int64_t DesiredMaskS) const; bool CheckOrMask(SDValue LHS, ConstantSDNode *RHS, int64_t DesiredMaskS) const; - - + + /// CheckPatternPredicate - This function is generated by tblgen in the /// target. It runs the specified pattern predicate and returns true if it /// succeeds or false if it fails. The number is a private implementation @@ -252,13 +248,14 @@ public: assert(0 && "Tblgen should generate the implementation of this!"); return 0; } - - virtual bool CheckComplexPattern(SDNode *Root, SDValue N, unsigned PatternNo, - SmallVectorImpl<SDValue> &Result) { + + virtual bool CheckComplexPattern(SDNode *Root, SDNode *Parent, SDValue N, + unsigned PatternNo, + SmallVectorImpl<std::pair<SDValue, SDNode*> > &Result) { assert(0 && "Tblgen should generate the implementation of this!"); return false; } - + virtual SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) { assert(0 && "Tblgen shoudl generate this!"); return SDValue(); @@ -267,9 +264,9 @@ public: SDNode *SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, unsigned TableSize); - + private: - + // Calls to these functions are generated by tblgen. SDNode *Select_INLINEASM(SDNode *N); SDNode *Select_UNDEF(SDNode *N); @@ -279,9 +276,10 @@ private: void DoInstructionSelection(); SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTs, const SDValue *Ops, unsigned NumOps, unsigned EmitNodeInfo); - + void PrepareEHLandingPad(); void SelectAllBasicBlocks(const Function &Fn); + bool TryToFoldFastISelLoad(const LoadInst *LI, FastISel *FastIS); void FinishBasicBlock(); void SelectBasicBlock(BasicBlock::const_iterator Begin, @@ -289,7 +287,7 @@ private: bool &HadTailCall); void CodeGenAndEmitDAG(); void LowerArguments(const BasicBlock *BB); - + void ComputeLiveOutVRegInfo(); /// Create the scheduler. If a specific scheduler was specified @@ -297,16 +295,16 @@ private: /// one preferred by the target. /// ScheduleDAGSDNodes *CreateScheduler(); - + /// OpcodeOffset - This is a cache used to dispatch efficiently into isel /// state machines that start with a OPC_SwitchOpcode node. std::vector<unsigned> OpcodeOffset; - - void UpdateChainsAndFlags(SDNode *NodeToMatch, SDValue InputChain, - const SmallVectorImpl<SDNode*> &ChainNodesMatched, - SDValue InputFlag,const SmallVectorImpl<SDNode*> &F, - bool isMorphNodeTo); - + + void UpdateChainsAndGlue(SDNode *NodeToMatch, SDValue InputChain, + const SmallVectorImpl<SDNode*> &ChainNodesMatched, + SDValue InputGlue, const SmallVectorImpl<SDNode*> &F, + bool isMorphNodeTo); + }; } diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index 4cf6f36..6454639 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -29,7 +29,7 @@ #include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/Support/MathExtras.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/DebugLoc.h" #include <cassert> @@ -524,24 +524,24 @@ public: return X; } - /// getFlaggedNode - If this node has a flag operand, return the node - /// to which the flag operand points. Otherwise return NULL. - SDNode *getFlaggedNode() const { + /// getGluedNode - If this node has a glue operand, return the node + /// to which the glue operand points. Otherwise return NULL. + SDNode *getGluedNode() const { if (getNumOperands() != 0 && - getOperand(getNumOperands()-1).getValueType().getSimpleVT() == MVT::Flag) + getOperand(getNumOperands()-1).getValueType() == MVT::Glue) return getOperand(getNumOperands()-1).getNode(); return 0; } // If this is a pseudo op, like copyfromreg, look to see if there is a - // real target node flagged to it. If so, return the target node. - const SDNode *getFlaggedMachineNode() const { + // real target node glued to it. If so, return the target node. + const SDNode *getGluedMachineNode() const { const SDNode *FoundNode = this; - // Climb up flag edges until a machine-opcode node is found, or the + // Climb up glue edges until a machine-opcode node is found, or the // end of the chain is reached. while (!FoundNode->isMachineOpcode()) { - const SDNode *N = FoundNode->getFlaggedNode(); + const SDNode *N = FoundNode->getGluedNode(); if (!N) break; FoundNode = N; } @@ -549,11 +549,11 @@ public: return FoundNode; } - /// getFlaggedUser - If this node has a flag value with a user, return + /// getGluedUser - If this node has a glue value with a user, return /// the user (there is at most one). Otherwise return NULL. - SDNode *getFlaggedUser() const { + SDNode *getGluedUser() const { for (use_iterator UI = use_begin(), UE = use_end(); UI != UE; ++UI) - if (UI.getUse().get().getValueType() == MVT::Flag) + if (UI.getUse().get().getValueType() == MVT::Glue) return *UI; return 0; } @@ -902,6 +902,9 @@ public: const Value *getSrcValue() const { return MMO->getValue(); } int64_t getSrcValueOffset() const { return MMO->getOffset(); } + /// Returns the TBAAInfo that describes the dereference. + const MDNode *getTBAAInfo() const { return MMO->getTBAAInfo(); } + /// getMemoryVT - Return the type of the in-memory value. EVT getMemoryVT() const { return MemoryVT; } @@ -909,6 +912,10 @@ public: /// reference performed by operation. MachineMemOperand *getMemOperand() const { return MMO; } + const MachinePointerInfo &getPointerInfo() const { + return MMO->getPointerInfo(); + } + /// refineAlignment - Update this MemSDNode's MachineMemOperand information /// to reflect the alignment of NewMMO, if it has a greater alignment. /// This must only be used when the new alignment applies to all users of @@ -929,6 +936,7 @@ public: // with either an intrinsic or a target opcode. return N->getOpcode() == ISD::LOAD || N->getOpcode() == ISD::STORE || + N->getOpcode() == ISD::PREFETCH || N->getOpcode() == ISD::ATOMIC_CMP_SWAP || N->getOpcode() == ISD::ATOMIC_SWAP || N->getOpcode() == ISD::ATOMIC_LOAD_ADD || @@ -1004,8 +1012,8 @@ public: /// MemIntrinsicSDNode - This SDNode is used for target intrinsics that touch /// memory and need an associated MachineMemOperand. Its opcode may be -/// INTRINSIC_VOID, INTRINSIC_W_CHAIN, or a target-specific opcode with a -/// value not less than FIRST_TARGET_MEMORY_OPCODE. +/// INTRINSIC_VOID, INTRINSIC_W_CHAIN, PREFETCH, or a target-specific opcode +/// with a value not less than FIRST_TARGET_MEMORY_OPCODE. class MemIntrinsicSDNode : public MemSDNode { public: MemIntrinsicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, @@ -1021,6 +1029,7 @@ public: // early a node with a target opcode can be of this class return N->getOpcode() == ISD::INTRINSIC_W_CHAIN || N->getOpcode() == ISD::INTRINSIC_VOID || + N->getOpcode() == ISD::PREFETCH || N->isTargetMemoryOpcode(); } }; diff --git a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h index 88044c7..1da1e91be 100644 --- a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h +++ b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h @@ -13,10 +13,7 @@ // // SlotIndex is mostly a proxy for entries of the SlotIndexList, a class which // is held is LiveIntervals and provides the real numbering. This allows -// LiveIntervals to perform largely transparent renumbering. The SlotIndex -// class does hold a PHI bit, which determines whether the index relates to a -// PHI use or def point, or an actual instruction. See the SlotIndex class -// description for futher information. +// LiveIntervals to perform largely transparent renumbering. //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_SLOTINDEXES_H @@ -130,12 +127,10 @@ namespace llvm { enum Slot { LOAD, USE, DEF, STORE, NUM }; - static const unsigned PHI_BIT = 1 << 2; + PointerIntPair<IndexListEntry*, 2, unsigned> lie; - PointerIntPair<IndexListEntry*, 3, unsigned> lie; - - SlotIndex(IndexListEntry *entry, unsigned phiAndSlot) - : lie(entry, phiAndSlot) { + SlotIndex(IndexListEntry *entry, unsigned slot) + : lie(entry, slot) { assert(entry != 0 && "Attempt to construct index with 0 pointer."); } @@ -149,7 +144,7 @@ namespace llvm { /// Returns the slot for this SlotIndex. Slot getSlot() const { - return static_cast<Slot>(lie.getInt() & ~PHI_BIT); + return static_cast<Slot>(lie.getInt()); } static inline unsigned getHashValue(const SlotIndex &v) { @@ -166,22 +161,13 @@ namespace llvm { static inline SlotIndex getTombstoneKey() { return SlotIndex(IndexListEntry::getTombstoneKeyEntry(), 0); } - + /// Construct an invalid index. SlotIndex() : lie(IndexListEntry::getEmptyKeyEntry(), 0) {} - // Construct a new slot index from the given one, set the phi flag on the - // new index to the value of the phi parameter. - SlotIndex(const SlotIndex &li, bool phi) - : lie(&li.entry(), phi ? PHI_BIT | li.getSlot() : (unsigned)li.getSlot()){ - assert(lie.getPointer() != 0 && - "Attempt to construct index with 0 pointer."); - } - - // Construct a new slot index from the given one, set the phi flag on the - // new index to the value of the phi parameter, and the slot to the new slot. - SlotIndex(const SlotIndex &li, bool phi, Slot s) - : lie(&li.entry(), phi ? PHI_BIT | s : (unsigned)s) { + // Construct a new slot index from the given one, and set the slot. + SlotIndex(const SlotIndex &li, Slot s) + : lie(&li.entry(), unsigned(s)) { assert(lie.getPointer() != 0 && "Attempt to construct index with 0 pointer."); } @@ -236,11 +222,6 @@ namespace llvm { return other.getIndex() - getIndex(); } - /// Returns the state of the PHI bit. - bool isPHI() const { - return lie.getInt() & PHI_BIT; - } - /// isLoad - Return true if this is a LOAD slot. bool isLoad() const { return getSlot() == LOAD; @@ -405,9 +386,6 @@ namespace llvm { /// and MBB id. std::vector<IdxMBBPair> idx2MBBMap; - typedef DenseMap<const MachineBasicBlock*, SlotIndex> TerminatorGapsMap; - TerminatorGapsMap terminatorGaps; - // IndexListEntry allocator. BumpPtrAllocator ileAllocator; @@ -415,7 +393,7 @@ namespace llvm { IndexListEntry *entry = static_cast<IndexListEntry*>( ileAllocator.Allocate(sizeof(IndexListEntry), - alignof<IndexListEntry>())); + alignOf<IndexListEntry>())); new (entry) IndexListEntry(mi, index); @@ -491,7 +469,9 @@ namespace llvm { public: static char ID; - SlotIndexes() : MachineFunctionPass(ID), indexListHead(0) {} + SlotIndexes() : MachineFunctionPass(ID), indexListHead(0) { + initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); + } virtual void getAnalysisUsage(AnalysisUsage &au) const; virtual void releaseMemory(); @@ -565,26 +545,22 @@ namespace llvm { return nextNonNull; } - /// Returns the first index in the given basic block. - SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const { + /// Return the (start,end) range of the given basic block. + const std::pair<SlotIndex, SlotIndex> & + getMBBRange(const MachineBasicBlock *mbb) const { MBB2IdxMap::const_iterator itr = mbb2IdxMap.find(mbb); assert(itr != mbb2IdxMap.end() && "MBB not found in maps."); - return itr->second.first; + return itr->second; } - /// Returns the last index in the given basic block. - SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const { - MBB2IdxMap::const_iterator itr = mbb2IdxMap.find(mbb); - assert(itr != mbb2IdxMap.end() && "MBB not found in maps."); - return itr->second.second; + /// Returns the first index in the given basic block. + SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const { + return getMBBRange(mbb).first; } - /// Returns the terminator gap for the given index. - SlotIndex getTerminatorGap(const MachineBasicBlock *mbb) { - TerminatorGapsMap::iterator itr = terminatorGaps.find(mbb); - assert(itr != terminatorGaps.end() && - "All MBBs should have terminator gaps in their indexes."); - return itr->second; + /// Returns the last index in the given basic block. + SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const { + return getMBBRange(mbb).second; } /// Returns the basic block which the given index falls in. @@ -618,29 +594,6 @@ namespace llvm { return resVal; } - /// Return a list of MBBs that can be reach via any branches or - /// fall-throughs. - bool findReachableMBBs(SlotIndex start, SlotIndex end, - SmallVectorImpl<MachineBasicBlock*> &mbbs) const { - std::vector<IdxMBBPair>::const_iterator itr = - std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), start); - - bool resVal = false; - while (itr != idx2MBBMap.end()) { - if (itr->first > end) - break; - MachineBasicBlock *mbb = itr->second; - if (getMBBEndIdx(mbb) > end) - break; - for (MachineBasicBlock::succ_iterator si = mbb->succ_begin(), - se = mbb->succ_end(); si != se; ++si) - mbbs.push_back(*si); - resVal = true; - ++itr; - } - return resVal; - } - /// Returns the MBB covering the given range, or null if the range covers /// more than one basic block. MachineBasicBlock* getMBBCoveringRange(SlotIndex start, SlotIndex end) const { @@ -672,6 +625,9 @@ namespace llvm { SlotIndex insertMachineInstrInMaps(MachineInstr *mi, bool *deferredRenumber = 0) { assert(mi2iMap.find(mi) == mi2iMap.end() && "Instr already indexed."); + // Numbering DBG_VALUE instructions could cause code generation to be + // affected by debug information. + assert(!mi->isDebugValue() && "Cannot number DBG_VALUE instructions."); MachineBasicBlock *mbb = mi->getParent(); @@ -789,7 +745,7 @@ namespace llvm { MachineFunction::iterator nextMBB = llvm::next(MachineFunction::iterator(mbb)); IndexListEntry *startEntry = createEntry(0, 0); - IndexListEntry *terminatorEntry = createEntry(0, 0); + IndexListEntry *stopEntry = createEntry(0, 0); IndexListEntry *nextEntry = 0; if (nextMBB == mbb->getParent()->end()) { @@ -799,15 +755,11 @@ namespace llvm { } insert(nextEntry, startEntry); - insert(nextEntry, terminatorEntry); + insert(nextEntry, stopEntry); SlotIndex startIdx(startEntry, SlotIndex::LOAD); - SlotIndex terminatorIdx(terminatorEntry, SlotIndex::PHI_BIT); SlotIndex endIdx(nextEntry, SlotIndex::LOAD); - terminatorGaps.insert( - std::make_pair(mbb, terminatorIdx)); - mbb2IdxMap.insert( std::make_pair(mbb, std::make_pair(startIdx, endIdx))); @@ -828,6 +780,20 @@ namespace llvm { }; + // Specialize IntervalMapInfo for half-open slot index intervals. + template <typename> struct IntervalMapInfo; + template <> struct IntervalMapInfo<SlotIndex> { + static inline bool startLess(const SlotIndex &x, const SlotIndex &a) { + return x < a; + } + static inline bool stopLess(const SlotIndex &b, const SlotIndex &x) { + return b <= x; + } + static inline bool adjacent(const SlotIndex &a, const SlotIndex &b) { + return a == b; + } + }; + } #endif // LLVM_CODEGEN_LIVEINDEX_H diff --git a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index d8f0373..fba3e48 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -57,6 +57,8 @@ public: virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + virtual const MCSection *getEHFrameSection() const; + const MCSection *getDataRelSection() const { return DataRelSection; } /// getSectionForConstant - Given a constant with the SectionKind, return a @@ -121,6 +123,8 @@ public: virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + virtual const MCSection *getEHFrameSection() const; + virtual const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const; @@ -184,6 +188,8 @@ public: virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + virtual const MCSection *getEHFrameSection() const; + virtual const MCSection *getDrectveSection() const { return DrectveSection; } virtual const MCSection * diff --git a/contrib/llvm/include/llvm/CodeGen/ValueTypes.h b/contrib/llvm/include/llvm/CodeGen/ValueTypes.h index 51f324c..22d1622 100644 --- a/contrib/llvm/include/llvm/CodeGen/ValueTypes.h +++ b/contrib/llvm/include/llvm/CodeGen/ValueTypes.h @@ -18,7 +18,7 @@ #include <cassert> #include <string> -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" namespace llvm { @@ -26,7 +26,10 @@ namespace llvm { class LLVMContext; struct EVT; - class MVT { // MVT = Machine Value Type + /// MVT - Machine Value Type. Every type that is supported natively by some + /// processor targeted by LLVM occurs here. This means that any legal value + /// type can be represented by a MVT. + class MVT { public: enum SimpleValueType { // If you change this numbering, you must change the values in @@ -74,14 +77,16 @@ namespace llvm { FIRST_VECTOR_VALUETYPE = v2i8, LAST_VECTOR_VALUETYPE = v4f64, - Flag = 33, // This glues nodes together during pre-RA sched + x86mmx = 33, // This is an X86 MMX value - isVoid = 34, // This has no value + Glue = 34, // This glues nodes together during pre-RA sched - LAST_VALUETYPE = 35, // This always remains at the end of the list. + isVoid = 35, // This has no value + + LAST_VALUETYPE = 36, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. - // EVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors + // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors // This value must be a multiple of 32. MAX_ALLOWED_VALUETYPE = 64, @@ -124,13 +129,14 @@ namespace llvm { MVT() : SimpleTy((SimpleValueType)(INVALID_SIMPLE_VALUE_TYPE)) {} MVT(SimpleValueType SVT) : SimpleTy(SVT) { } - + bool operator>(const MVT& S) const { return SimpleTy > S.SimpleTy; } bool operator<(const MVT& S) const { return SimpleTy < S.SimpleTy; } bool operator==(const MVT& S) const { return SimpleTy == S.SimpleTy; } + bool operator!=(const MVT& S) const { return SimpleTy != S.SimpleTy; } bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; } bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; } - + /// isFloatingPoint - Return true if this is a FP, or a vector FP type. bool isFloatingPoint() const { return ((SimpleTy >= MVT::f32 && SimpleTy <= MVT::ppcf128) || @@ -149,14 +155,14 @@ namespace llvm { return (SimpleTy >= MVT::FIRST_VECTOR_VALUETYPE && SimpleTy <= MVT::LAST_VECTOR_VALUETYPE); } - + /// isPow2VectorType - Returns true if the given vector is a power of 2. bool isPow2VectorType() const { unsigned NElts = getVectorNumElements(); return !(NElts & (NElts - 1)); } - /// getPow2VectorType - Widens the length of the given vector EVT up to + /// getPow2VectorType - Widens the length of the given vector MVT up to /// the nearest power of 2 and returns that type. MVT getPow2VectorType() const { if (isPow2VectorType()) @@ -172,7 +178,7 @@ namespace llvm { MVT getScalarType() const { return isVector() ? getVectorElementType() : *this; } - + MVT getVectorElementType() const { switch (SimpleTy) { default: @@ -200,7 +206,7 @@ namespace llvm { case v4f64: return f64; } } - + unsigned getVectorNumElements() const { switch (SimpleTy) { default: @@ -228,7 +234,7 @@ namespace llvm { case v1i64: return 1; } } - + unsigned getSizeInBits() const { switch (SimpleTy) { case iPTR: @@ -247,6 +253,7 @@ namespace llvm { case i32 : case v4i8: case v2i16: return 32; + case x86mmx: case f64 : case i64 : case v8i8: @@ -273,7 +280,19 @@ namespace llvm { case v8i64: return 512; } } - + + /// getStoreSize - Return the number of bytes overwritten by a store + /// of the specified value type. + unsigned getStoreSize() const { + return (getSizeInBits() + 7) / 8; + } + + /// getStoreSizeInBits - Return the number of bits overwritten by a store + /// of the specified value type. + unsigned getStoreSizeInBits() const { + return getStoreSize() * 8; + } + static MVT getFloatingPointVT(unsigned BitWidth) { switch (BitWidth) { default: @@ -288,7 +307,7 @@ namespace llvm { return MVT::f128; } } - + static MVT getIntegerVT(unsigned BitWidth) { switch (BitWidth) { default: @@ -307,7 +326,7 @@ namespace llvm { return MVT::i128; } } - + static MVT getVectorVT(MVT VT, unsigned NumElements) { switch (VT.SimpleTy) { default: @@ -350,7 +369,11 @@ namespace llvm { } }; - struct EVT { // EVT = Extended Value Type + + /// EVT - Extended Value Type. Capable of holding value types which are not + /// native for any processor (such as the i12345 type), as well as the types + /// a MVT can represent. + struct EVT { private: MVT V; const Type *LLVMTy; @@ -527,7 +550,7 @@ namespace llvm { EVT getScalarType() const { return isVector() ? getVectorElementType() : *this; } - + /// getVectorElementType - Given a vector type, return the type of /// each element. EVT getVectorElementType() const { diff --git a/contrib/llvm/include/llvm/CodeGen/ValueTypes.td b/contrib/llvm/include/llvm/CodeGen/ValueTypes.td index 8151c0b..a1163f7 100644 --- a/contrib/llvm/include/llvm/CodeGen/ValueTypes.td +++ b/contrib/llvm/include/llvm/CodeGen/ValueTypes.td @@ -46,17 +46,18 @@ def v4i32 : ValueType<128, 22>; // 4 x i32 vector value def v8i32 : ValueType<256, 23>; // 8 x i32 vector value def v1i64 : ValueType<64 , 24>; // 1 x i64 vector value def v2i64 : ValueType<128, 25>; // 2 x i64 vector value -def v4i64 : ValueType<256, 26>; // 4 x f64 vector value -def v8i64 : ValueType<512, 27>; // 4 x f64 vector value +def v4i64 : ValueType<256, 26>; // 4 x i64 vector value +def v8i64 : ValueType<512, 27>; // 8 x i64 vector value -def v2f32 : ValueType<64, 28>; // 2 x f32 vector value +def v2f32 : ValueType<64 , 28>; // 2 x f32 vector value def v4f32 : ValueType<128, 29>; // 4 x f32 vector value def v8f32 : ValueType<256, 30>; // 8 x f32 vector value def v2f64 : ValueType<128, 31>; // 2 x f64 vector value def v4f64 : ValueType<256, 32>; // 4 x f64 vector value -def FlagVT : ValueType<0 , 33>; // Pre-RA sched glue -def isVoid : ValueType<0 , 34>; // Produces no value +def x86mmx : ValueType<64 , 33>; // X86 MMX value +def FlagVT : ValueType<0 , 34>; // Pre-RA sched glue +def isVoid : ValueType<0 , 35>; // Produces no value def MetadataVT: ValueType<0, 250>; // Metadata diff --git a/contrib/llvm/include/llvm/CompilerDriver/CompilationGraph.h b/contrib/llvm/include/llvm/CompilerDriver/CompilationGraph.h index 619c904..e1eea32 100644 --- a/contrib/llvm/include/llvm/CompilerDriver/CompilationGraph.h +++ b/contrib/llvm/include/llvm/CompilerDriver/CompilationGraph.h @@ -21,7 +21,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" #include <cassert> #include <string> diff --git a/contrib/llvm/include/llvm/CompilerDriver/Tool.h b/contrib/llvm/include/llvm/CompilerDriver/Tool.h index 45ef50d..d0926ba 100644 --- a/contrib/llvm/include/llvm/CompilerDriver/Tool.h +++ b/contrib/llvm/include/llvm/CompilerDriver/Tool.h @@ -18,7 +18,7 @@ #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringSet.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" #include <string> #include <vector> @@ -58,7 +58,7 @@ namespace llvmc { virtual const char* Name() const = 0; virtual const char** InputLanguages() const = 0; - virtual const char* OutputLanguage() const = 0; + virtual const char** OutputLanguages() const = 0; virtual bool IsJoin() const = 0; virtual bool WorksOnEmpty() const = 0; diff --git a/contrib/llvm/include/llvm/Constant.h b/contrib/llvm/include/llvm/Constant.h index 8647299..38045fc 100644 --- a/contrib/llvm/include/llvm/Constant.h +++ b/contrib/llvm/include/llvm/Constant.h @@ -20,7 +20,6 @@ namespace llvm { class APInt; template<typename T> class SmallVectorImpl; - class LLVMContext; /// This is an important base class in LLVM. It provides the common facilities /// of all constant values in an LLVM program. A constant is a value that is @@ -142,16 +141,22 @@ public: assert(0 && "Constants that do not have operands cannot be using 'From'!"); } - static Constant* getNullValue(const Type* Ty); + static Constant *getNullValue(const Type* Ty); /// @returns the value for an integer constant of the given type that has all /// its bits set to true. /// @brief Get the all ones value - static Constant* getAllOnesValue(const Type* Ty); + static Constant *getAllOnesValue(const Type* Ty); /// getIntegerValue - Return the value for an integer or pointer constant, /// or a vector thereof, with the given scalar value. - static Constant* getIntegerValue(const Type* Ty, const APInt &V); + static Constant *getIntegerValue(const Type* Ty, const APInt &V); + + /// removeDeadConstantUsers - If there are any dead constant users dangling + /// off of this constant, remove them. This method is useful for clients + /// that want to check to see if a global is unused, but don't want to deal + /// with potentially dead constants hanging off of the globals. + void removeDeadConstantUsers() const; }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Constants.h b/contrib/llvm/include/llvm/Constants.h index a7deae0..c4768f8 100644 --- a/contrib/llvm/include/llvm/Constants.h +++ b/contrib/llvm/include/llvm/Constants.h @@ -25,8 +25,7 @@ #include "llvm/OperandTraits.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APFloat.h" -#include "llvm/ADT/SmallVector.h" -#include <vector> +#include "llvm/ADT/ArrayRef.h" namespace llvm { @@ -265,8 +264,8 @@ public: inline const APFloat& getValueAPF() const { return Val; } /// isNullValue - Return true if this is the value that would be returned by - /// getNullValue. Don't depend on == for doubles to tell us it's zero, it - /// considers -0.0 to be null as well as 0.0. :( + /// getNullValue. For ConstantFP, this is +0.0, but not -0.0. To handle the + /// two the same, use isZero(). virtual bool isNullValue() const; /// isNegativeZeroValue - Return true if the value is what would be returned @@ -404,7 +403,8 @@ public: }; template <> -struct OperandTraits<ConstantArray> : public VariadicOperandTraits<> { +struct OperandTraits<ConstantArray> : + public VariadicOperandTraits<ConstantArray> { }; DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantArray, Constant) @@ -453,7 +453,8 @@ public: }; template <> -struct OperandTraits<ConstantStruct> : public VariadicOperandTraits<> { +struct OperandTraits<ConstantStruct> : + public VariadicOperandTraits<ConstantStruct> { }; DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantStruct, Constant) @@ -470,9 +471,9 @@ protected: ConstantVector(const VectorType *T, const std::vector<Constant*> &Val); public: // ConstantVector accessors + static Constant *get(ArrayRef<Constant*> V); + // FIXME: Eliminate this constructor form. static Constant *get(const VectorType *T, const std::vector<Constant*> &V); - static Constant *get(const std::vector<Constant*> &V); - static Constant *get(Constant *const *Vals, unsigned NumVals); /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -497,7 +498,7 @@ public: /// getSplatValue - If this is a splat constant, meaning that all of the /// elements have the same value, return that value. Otherwise return NULL. - Constant *getSplatValue(); + Constant *getSplatValue() const; virtual void destroyConstant(); virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); @@ -510,7 +511,8 @@ public: }; template <> -struct OperandTraits<ConstantVector> : public VariadicOperandTraits<> { +struct OperandTraits<ConstantVector> : + public VariadicOperandTraits<ConstantVector> { }; DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantVector, Constant) @@ -591,7 +593,8 @@ public: }; template <> -struct OperandTraits<BlockAddress> : public FixedNumOperandTraits<2> { +struct OperandTraits<BlockAddress> : + public FixedNumOperandTraits<BlockAddress, 2> { }; DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(BlockAddress, Value) @@ -624,11 +627,10 @@ protected: Constant *C2); static Constant *getSelectTy(const Type *Ty, Constant *C1, Constant *C2, Constant *C3); + template<typename IndexTy> static Constant *getGetElementPtrTy(const Type *Ty, Constant *C, - Value* const *Idxs, unsigned NumIdxs); - static Constant *getInBoundsGetElementPtrTy(const Type *Ty, Constant *C, - Value* const *Idxs, - unsigned NumIdxs); + IndexTy const *Idxs, unsigned NumIdxs, + bool InBounds); static Constant *getExtractElementTy(const Type *Ty, Constant *Val, Constant *Idx); static Constant *getInsertElementTy(const Type *Ty, Constant *Val, @@ -640,6 +642,10 @@ protected: static Constant *getInsertValueTy(const Type *Ty, Constant *Agg, Constant *Val, const unsigned *Idxs, unsigned NumIdxs); + template<typename IndexTy> + static Constant *getGetElementPtrImpl(Constant *C, + IndexTy const *IdxList, + unsigned NumIdx, bool InBounds); public: // Static methods to construct a ConstantExpr of different kinds. Note that @@ -649,35 +655,38 @@ public: /// getAlignOf constant expr - computes the alignment of a type in a target /// independent way (Note: the return type is an i64). - static Constant *getAlignOf(const Type* Ty); + static Constant *getAlignOf(const Type *Ty); /// getSizeOf constant expr - computes the (alloc) size of a type (in /// address-units, not bits) in a target independent way (Note: the return /// type is an i64). /// - static Constant *getSizeOf(const Type* Ty); + static Constant *getSizeOf(const Type *Ty); /// getOffsetOf constant expr - computes the offset of a struct field in a /// target independent way (Note: the return type is an i64). /// - static Constant *getOffsetOf(const StructType* STy, unsigned FieldNo); + static Constant *getOffsetOf(const StructType *STy, unsigned FieldNo); /// getOffsetOf constant expr - This is a generalized form of getOffsetOf, /// which supports any aggregate type, and any Constant index. /// - static Constant *getOffsetOf(const Type* Ty, Constant *FieldNo); + static Constant *getOffsetOf(const Type *Ty, Constant *FieldNo); - static Constant *getNeg(Constant *C); + static Constant *getNeg(Constant *C, bool HasNUW = false, bool HasNSW =false); static Constant *getFNeg(Constant *C); static Constant *getNot(Constant *C); - static Constant *getAdd(Constant *C1, Constant *C2); + static Constant *getAdd(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); static Constant *getFAdd(Constant *C1, Constant *C2); - static Constant *getSub(Constant *C1, Constant *C2); + static Constant *getSub(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); static Constant *getFSub(Constant *C1, Constant *C2); - static Constant *getMul(Constant *C1, Constant *C2); + static Constant *getMul(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); static Constant *getFMul(Constant *C1, Constant *C2); - static Constant *getUDiv(Constant *C1, Constant *C2); - static Constant *getSDiv(Constant *C1, Constant *C2); + static Constant *getUDiv(Constant *C1, Constant *C2, bool isExact = false); + static Constant *getSDiv(Constant *C1, Constant *C2, bool isExact = false); static Constant *getFDiv(Constant *C1, Constant *C2); static Constant *getURem(Constant *C1, Constant *C2); static Constant *getSRem(Constant *C1, Constant *C2); @@ -685,9 +694,10 @@ public: static Constant *getAnd(Constant *C1, Constant *C2); static Constant *getOr(Constant *C1, Constant *C2); static Constant *getXor(Constant *C1, Constant *C2); - static Constant *getShl(Constant *C1, Constant *C2); - static Constant *getLShr(Constant *C1, Constant *C2); - static Constant *getAShr(Constant *C1, Constant *C2); + static Constant *getShl(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); + static Constant *getLShr(Constant *C1, Constant *C2, bool isExact = false); + static Constant *getAShr(Constant *C1, Constant *C2, bool isExact = false); static Constant *getTrunc (Constant *C, const Type *Ty); static Constant *getSExt (Constant *C, const Type *Ty); static Constant *getZExt (Constant *C, const Type *Ty); @@ -701,15 +711,44 @@ public: static Constant *getIntToPtr(Constant *C, const Type *Ty); static Constant *getBitCast (Constant *C, const Type *Ty); - static Constant *getNSWNeg(Constant *C); - static Constant *getNUWNeg(Constant *C); - static Constant *getNSWAdd(Constant *C1, Constant *C2); - static Constant *getNUWAdd(Constant *C1, Constant *C2); - static Constant *getNSWSub(Constant *C1, Constant *C2); - static Constant *getNUWSub(Constant *C1, Constant *C2); - static Constant *getNSWMul(Constant *C1, Constant *C2); - static Constant *getNUWMul(Constant *C1, Constant *C2); - static Constant *getExactSDiv(Constant *C1, Constant *C2); + static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); } + static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); } + static Constant *getNSWAdd(Constant *C1, Constant *C2) { + return getAdd(C1, C2, false, true); + } + static Constant *getNUWAdd(Constant *C1, Constant *C2) { + return getAdd(C1, C2, true, false); + } + static Constant *getNSWSub(Constant *C1, Constant *C2) { + return getSub(C1, C2, false, true); + } + static Constant *getNUWSub(Constant *C1, Constant *C2) { + return getSub(C1, C2, true, false); + } + static Constant *getNSWMul(Constant *C1, Constant *C2) { + return getMul(C1, C2, false, true); + } + static Constant *getNUWMul(Constant *C1, Constant *C2) { + return getMul(C1, C2, true, false); + } + static Constant *getNSWShl(Constant *C1, Constant *C2) { + return getShl(C1, C2, false, true); + } + static Constant *getNUWShl(Constant *C1, Constant *C2) { + return getShl(C1, C2, true, false); + } + static Constant *getExactSDiv(Constant *C1, Constant *C2) { + return getSDiv(C1, C2, true); + } + static Constant *getExactUDiv(Constant *C1, Constant *C2) { + return getUDiv(C1, C2, true); + } + static Constant *getExactAShr(Constant *C1, Constant *C2) { + return getAShr(C1, C2, true); + } + static Constant *getExactLShr(Constant *C1, Constant *C2) { + return getLShr(C1, C2, true); + } /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -801,18 +840,24 @@ public: /// all elements must be Constant's. /// static Constant *getGetElementPtr(Constant *C, - Constant *const *IdxList, unsigned NumIdx); + Constant *const *IdxList, unsigned NumIdx, + bool InBounds = false); static Constant *getGetElementPtr(Constant *C, - Value* const *IdxList, unsigned NumIdx); + Value *const *IdxList, unsigned NumIdx, + bool InBounds = false); /// Create an "inbounds" getelementptr. See the documentation for the /// "inbounds" flag in LangRef.html for details. static Constant *getInBoundsGetElementPtr(Constant *C, Constant *const *IdxList, - unsigned NumIdx); + unsigned NumIdx) { + return getGetElementPtr(C, IdxList, NumIdx, true); + } static Constant *getInBoundsGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx); + unsigned NumIdx) { + return getGetElementPtr(C, IdxList, NumIdx, true); + } static Constant *getExtractElement(Constant *Vec, Constant *Idx); static Constant *getInsertElement(Constant *Vec, Constant *Elt,Constant *Idx); @@ -870,7 +915,8 @@ private: }; template <> -struct OperandTraits<ConstantExpr> : public VariadicOperandTraits<1> { +struct OperandTraits<ConstantExpr> : + public VariadicOperandTraits<ConstantExpr, 1> { }; DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantExpr, Constant) diff --git a/contrib/llvm/include/llvm/DerivedTypes.h b/contrib/llvm/include/llvm/DerivedTypes.h index 9b6b19f..56d1e3e 100644 --- a/contrib/llvm/include/llvm/DerivedTypes.h +++ b/contrib/llvm/include/llvm/DerivedTypes.h @@ -9,7 +9,7 @@ // // This file contains the declarations of classes that represent "derived // types". These are things like "arrays of x" or "structure of x, y, z" or -// "method returning x taking (y,z) as parameters", etc... +// "function returning x taking (y,z) as parameters", etc... // // The implementations of these classes live in the Type.cpp file. // @@ -19,6 +19,7 @@ #define LLVM_DERIVED_TYPES_H #include "llvm/Type.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h b/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h index 3287b39..71698fa 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -22,7 +22,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/ValueMap.h" #include "llvm/Support/ValueHandle.h" -#include "llvm/System/Mutex.h" +#include "llvm/Support/Mutex.h" #include "llvm/Target/TargetMachine.h" namespace llvm { @@ -41,6 +41,8 @@ class MutexGuard; class TargetData; class Type; +/// \brief Helper class for helping synchronize access to the global address map +/// table. class ExecutionEngineState { public: struct AddressMapConfig : public ValueMapConfig<const GlobalValue*> { @@ -70,8 +72,7 @@ private: public: ExecutionEngineState(ExecutionEngine &EE); - GlobalAddressMapTy & - getGlobalAddressMap(const MutexGuard &) { + GlobalAddressMapTy &getGlobalAddressMap(const MutexGuard &) { return GlobalAddressMap; } @@ -80,23 +81,41 @@ public: return GlobalAddressReverseMap; } - // Returns the address ToUnmap was mapped to. + /// \brief Erase an entry from the mapping table. + /// + /// \returns The address that \arg ToUnmap was happed to. void *RemoveMapping(const MutexGuard &, const GlobalValue *ToUnmap); }; - +/// \brief Abstract interface for implementation execution of LLVM modules, +/// designed to support both interpreter and just-in-time (JIT) compiler +/// implementations. class ExecutionEngine { - const TargetData *TD; + /// The state object holding the global address mapping, which must be + /// accessed synchronously. + // + // FIXME: There is no particular need the entire map needs to be + // synchronized. Wouldn't a reader-writer design be better here? ExecutionEngineState EEState; + + /// The target data for the platform for which execution is being performed. + const TargetData *TD; + + /// Whether lazy JIT compilation is enabled. bool CompilingLazily; + + /// Whether JIT compilation of external global variables is allowed. bool GVCompilationDisabled; + + /// Whether the JIT should perform lookups of external symbols (e.g., + /// using dlsym). bool SymbolSearchingDisabled; friend class EngineBuilder; // To allow access to JITCtor and InterpCtor. protected: - /// Modules - This is a list of Modules that we are JIT'ing from. We use a - /// smallvector to optimize for the case where there is only one module. + /// The list of Modules that we are JIT'ing from. We use a SmallVector to + /// optimize for the case where there is only one module. SmallVector<Module*, 1> Modules; void setTargetData(const TargetData *td) { @@ -104,11 +123,11 @@ protected: } /// getMemoryforGV - Allocate memory for a global variable. - virtual char* getMemoryForGV(const GlobalVariable* GV); + virtual char *getMemoryForGV(const GlobalVariable *GV); // To avoid having libexecutionengine depend on the JIT and interpreter - // libraries, the JIT and Interpreter set these functions to ctor pointers - // at startup time if they are linked in. + // libraries, the execution engine implementations set these functions to ctor + // pointers at startup time if they are linked in. static ExecutionEngine *(*JITCtor)( Module *M, std::string *ErrorStr, @@ -119,23 +138,36 @@ protected: StringRef MArch, StringRef MCPU, const SmallVectorImpl<std::string>& MAttrs); + static ExecutionEngine *(*MCJITCtor)( + Module *M, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl<std::string>& MAttrs); static ExecutionEngine *(*InterpCtor)(Module *M, std::string *ErrorStr); /// LazyFunctionCreator - If an unknown function is needed, this function - /// pointer is invoked to create it. If this returns null, the JIT will abort. - void* (*LazyFunctionCreator)(const std::string &); + /// pointer is invoked to create it. If this returns null, the JIT will + /// abort. + void *(*LazyFunctionCreator)(const std::string &); - /// ExceptionTableRegister - If Exception Handling is set, the JIT will - /// register dwarf tables with this function + /// ExceptionTableRegister - If Exception Handling is set, the JIT will + /// register dwarf tables with this function. typedef void (*EERegisterFn)(void*); - static EERegisterFn ExceptionTableRegister; + EERegisterFn ExceptionTableRegister; + EERegisterFn ExceptionTableDeregister; + std::vector<void*> AllExceptionTables; public: - /// lock - This lock is protects the ExecutionEngine, JIT, JITResolver and + /// lock - This lock protects the ExecutionEngine, JIT, JITResolver and /// JITEmitter classes. It must be held while changing the internal state of /// any of those classes. - sys::Mutex lock; // Used to make this class and subclasses thread-safe + sys::Mutex lock; //===--------------------------------------------------------------------===// // ExecutionEngine Startup @@ -146,20 +178,18 @@ public: /// create - This is the factory method for creating an execution engine which /// is appropriate for the current machine. This takes ownership of the /// module. + /// + /// \param GVsWithCode - Allocating globals with code breaks + /// freeMachineCodeForFunction and is probably unsafe and bad for performance. + /// However, we have clients who depend on this behavior, so we must support + /// it. Eventually, when we're willing to break some backwards compatability, + /// this flag should be flipped to false, so that by default + /// freeMachineCodeForFunction works. static ExecutionEngine *create(Module *M, bool ForceInterpreter = false, std::string *ErrorStr = 0, CodeGenOpt::Level OptLevel = CodeGenOpt::Default, - // Allocating globals with code breaks - // freeMachineCodeForFunction and is probably - // unsafe and bad for performance. However, - // we have clients who depend on this - // behavior, so we must support it. - // Eventually, when we're willing to break - // some backwards compatability, this flag - // should be flipped to false, so that by - // default freeMachineCodeForFunction works. bool GVsWithCode = true); /// createJIT - This is the factory method for creating a JIT for the current @@ -184,11 +214,10 @@ public: Modules.push_back(M); } - //===----------------------------------------------------------------------===// + //===--------------------------------------------------------------------===// const TargetData *getTargetData() const { return TD; } - /// removeModule - Remove a Module from the list of modules. Returns true if /// M is found. virtual bool removeModule(Module *M); @@ -200,17 +229,19 @@ public: /// runFunction - Execute the specified function with the specified arguments, /// and return the result. - /// virtual GenericValue runFunction(Function *F, const std::vector<GenericValue> &ArgValues) = 0; /// runStaticConstructorsDestructors - This method is used to execute all of - /// the static constructors or destructors for a program, depending on the - /// value of isDtors. + /// the static constructors or destructors for a program. + /// + /// \param isDtors - Run the destructors instead of constructors. void runStaticConstructorsDestructors(bool isDtors); + /// runStaticConstructorsDestructors - This method is used to execute all of - /// the static constructors or destructors for a module, depending on the - /// value of isDtors. + /// the static constructors or destructors for a particular module. + /// + /// \param isDtors - Run the destructors instead of constructors. void runStaticConstructorsDestructors(Module *module, bool isDtors); @@ -229,8 +260,8 @@ public: /// GlobalValue is destroyed. void addGlobalMapping(const GlobalValue *GV, void *Addr); - /// clearAllGlobalMappings - Clear all global mappings and start over again - /// use in dynamic compilation scenarios when you want to move globals + /// clearAllGlobalMappings - Clear all global mappings and start over again, + /// for use in dynamic compilation scenarios to move globals. void clearAllGlobalMappings(); /// clearGlobalMappingsFromModule - Clear all global mappings that came from a @@ -246,12 +277,10 @@ public: /// getPointerToGlobalIfAvailable - This returns the address of the specified /// global value if it is has already been codegen'd, otherwise it returns /// null. - /// void *getPointerToGlobalIfAvailable(const GlobalValue *GV); /// getPointerToGlobal - This returns the address of the specified global - /// value. This may involve code generation if it's a function. - /// + /// value. This may involve code generation if it's a function. void *getPointerToGlobal(const GlobalValue *GV); /// getPointerToFunction - The different EE's represent function bodies in @@ -259,20 +288,17 @@ public: /// pointer should look like. When F is destroyed, the ExecutionEngine will /// remove its global mapping and free any machine code. Be sure no threads /// are running inside F when that happens. - /// virtual void *getPointerToFunction(Function *F) = 0; /// getPointerToBasicBlock - The different EE's represent basic blocks in /// different ways. Return the representation for a blockaddress of the /// specified block. - /// virtual void *getPointerToBasicBlock(BasicBlock *BB) = 0; /// getPointerToFunctionOrStub - If the specified function has been /// code-gen'd, return a pointer to the function. If not, compile it, or use /// a stub to implement lazy compilation if available. See /// getPointerToFunction for the requirements on destroying F. - /// virtual void *getPointerToFunctionOrStub(Function *F) { // Default implementation, just codegen the function. return getPointerToFunction(F); @@ -286,23 +312,25 @@ public: /// const GlobalValue *getGlobalValueAtAddress(void *Addr); - + /// StoreValueToMemory - Stores the data in Val of type Ty at address Ptr. + /// Ptr is the address of the memory at which to store Val, cast to + /// GenericValue *. It is not a pointer to a GenericValue containing the + /// address at which to store Val. void StoreValueToMemory(const GenericValue &Val, GenericValue *Ptr, const Type *Ty); + void InitializeMemory(const Constant *Init, void *Addr); - /// recompileAndRelinkFunction - This method is used to force a function - /// which has already been compiled to be compiled again, possibly - /// after it has been modified. Then the entry to the old copy is overwritten - /// with a branch to the new copy. If there was no old copy, this acts - /// just like VM::getPointerToFunction(). - /// + /// recompileAndRelinkFunction - This method is used to force a function which + /// has already been compiled to be compiled again, possibly after it has been + /// modified. Then the entry to the old copy is overwritten with a branch to + /// the new copy. If there was no old copy, this acts just like + /// VM::getPointerToFunction(). virtual void *recompileAndRelinkFunction(Function *F) = 0; /// freeMachineCodeForFunction - Release memory in the ExecutionEngine /// corresponding to the machine code emitted to execute this function, useful /// for garbage-collecting generated code. - /// virtual void freeMachineCodeForFunction(Function *F) = 0; /// getOrEmitGlobalVariable - Return the address of the specified global @@ -373,25 +401,31 @@ public: /// InstallExceptionTableRegister - The JIT will use the given function /// to register the exception tables it generates. - static void InstallExceptionTableRegister(void (*F)(void*)) { + void InstallExceptionTableRegister(EERegisterFn F) { ExceptionTableRegister = F; } + void InstallExceptionTableDeregister(EERegisterFn F) { + ExceptionTableDeregister = F; + } - /// RegisterTable - Registers the given pointer as an exception table. It uses - /// the ExceptionTableRegister function. - static void RegisterTable(void* res) { - if (ExceptionTableRegister) + /// RegisterTable - Registers the given pointer as an exception table. It + /// uses the ExceptionTableRegister function. + void RegisterTable(void* res) { + if (ExceptionTableRegister) { ExceptionTableRegister(res); + AllExceptionTables.push_back(res); + } } + /// DeregisterAllTables - Deregisters all previously registered pointers to an + /// exception tables. It uses the ExceptionTableoDeregister function. + void DeregisterAllTables(); + protected: explicit ExecutionEngine(Module *M); void emitGlobals(); - // EmitGlobalVariable - This method emits the specified global variable to the - // address specified in GlobalAddresses, or allocates new memory if it's not - // already in the map. void EmitGlobalVariable(const GlobalVariable *GV); GenericValue getConstantValue(const Constant *C); @@ -412,8 +446,7 @@ namespace EngineKind { /// stack-allocating a builder, chaining the various set* methods, and /// terminating it with a .create() call. class EngineBuilder { - - private: +private: Module *M; EngineKind::Kind WhichEngine; std::string *ErrorStr; @@ -424,9 +457,9 @@ class EngineBuilder { std::string MArch; std::string MCPU; SmallVector<std::string, 4> MAttrs; + bool UseMCJIT; /// InitEngine - Does the common initialization of default options. - /// void InitEngine() { WhichEngine = EngineKind::Either; ErrorStr = NULL; @@ -434,9 +467,10 @@ class EngineBuilder { JMM = NULL; AllocateGVsWithCode = false; CMModel = CodeModel::Default; + UseMCJIT = false; } - public: +public: /// EngineBuilder - Constructor for EngineBuilder. If create() is called and /// is successful, the created engine takes ownership of the module. EngineBuilder(Module *m) : M(m) { @@ -504,6 +538,12 @@ class EngineBuilder { return *this; } + /// setUseMCJIT - Set whether the MC-JIT implementation should be used + /// (experimental). + void setUseMCJIT(bool Value) { + UseMCJIT = Value; + } + /// setMAttrs - Set cpu-specific attributes. template<typename StringSequence> EngineBuilder &setMAttrs(const StringSequence &mattrs) { diff --git a/contrib/llvm/include/llvm/ExecutionEngine/GenericValue.h b/contrib/llvm/include/llvm/ExecutionEngine/GenericValue.h index 1301320..a2fed98 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/GenericValue.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/GenericValue.h @@ -16,7 +16,7 @@ #define GENERIC_VALUE_H #include "llvm/ADT/APInt.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/contrib/llvm/include/llvm/ExecutionEngine/JITEventListener.h b/contrib/llvm/include/llvm/ExecutionEngine/JITEventListener.h index dcc66b2..abc063b 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/JITEventListener.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/JITEventListener.h @@ -15,7 +15,7 @@ #ifndef LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H #define LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/DebugLoc.h" #include <vector> @@ -24,35 +24,38 @@ namespace llvm { class Function; class MachineFunction; -/// Empty for now, but this object will contain all details about the -/// generated machine code that a Listener might care about. +/// JITEvent_EmittedFunctionDetails - Helper struct for containing information +/// about a generated machine code function. struct JITEvent_EmittedFunctionDetails { - const MachineFunction *MF; - struct LineStart { - // The address at which the current line changes. + /// The address at which the current line changes. uintptr_t Address; - // The new location information. These can be translated to - // DebugLocTuples using MF->getDebugLocTuple(). + + /// The new location information. These can be translated to DebugLocTuples + /// using MF->getDebugLocTuple(). DebugLoc Loc; }; - // This holds line boundary information sorted by address. + + /// The machine function the struct contains information for. + const MachineFunction *MF; + + /// The list of line boundary information, sorted by address. std::vector<LineStart> LineStarts; }; -/// JITEventListener - This interface is used by the JIT to notify clients about -/// significant events during compilation. For example, we could have -/// implementations for profilers and debuggers that need to know where -/// functions have been emitted. +/// JITEventListener - Abstract interface for use by the JIT to notify clients +/// about significant events during compilation. For example, to notify +/// profilers and debuggers that need to know where functions have been emitted. /// -/// Each method defaults to doing nothing, so you only need to override the ones -/// you care about. +/// The default implementation of each method does nothing. class JITEventListener { public: + typedef JITEvent_EmittedFunctionDetails EmittedFunctionDetails; + +public: JITEventListener() {} - virtual ~JITEventListener(); // Defined in JIT.cpp. + virtual ~JITEventListener(); - typedef JITEvent_EmittedFunctionDetails EmittedFunctionDetails; /// NotifyFunctionEmitted - Called after a function has been successfully /// emitted to memory. The function still has its MachineFunction attached, /// if you should happen to need that. @@ -60,13 +63,14 @@ public: void *Code, size_t Size, const EmittedFunctionDetails &Details) {} - /// NotifyFreeingMachineCode - This is called inside of - /// freeMachineCodeForFunction(), after the global mapping is removed, but - /// before the machine code is returned to the allocator. OldPtr is the - /// address of the machine code and will be the same as the Code parameter to - /// a previous NotifyFunctionEmitted call. The Function passed to - /// NotifyFunctionEmitted may have been destroyed by the time of the matching - /// NotifyFreeingMachineCode call. + /// NotifyFreeingMachineCode - Called from freeMachineCodeForFunction(), after + /// the global mapping is removed, but before the machine code is returned to + /// the allocator. + /// + /// OldPtr is the address of the machine code and will be the same as the Code + /// parameter to a previous NotifyFunctionEmitted call. The Function passed + /// to NotifyFunctionEmitted may have been destroyed by the time of the + /// matching NotifyFreeingMachineCode call. virtual void NotifyFreeingMachineCode(void *OldPtr) {} }; diff --git a/contrib/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h b/contrib/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h index e015930..3841418 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -6,15 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the JITMemoryManagerInterface -// -//===----------------------------------------------------------------------===// #ifndef LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H #define LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> namespace llvm { @@ -29,8 +25,8 @@ namespace llvm { class JITMemoryManager { protected: bool HasGOT; -public: +public: JITMemoryManager() : HasGOT(false) {} virtual ~JITMemoryManager(); @@ -48,7 +44,7 @@ public: /// setPoisonMemory - Setting this flag to true makes the memory manager /// garbage values over freed memory. This is useful for testing and - /// debugging, and is be turned on by default in debug mode. + /// debugging, and may be turned on by default in debug mode. virtual void setPoisonMemory(bool poison) = 0; //===--------------------------------------------------------------------===// @@ -61,7 +57,6 @@ public: virtual void AllocateGOT() = 0; /// isManagingGOT - Return true if the AllocateGOT method is called. - /// bool isManagingGOT() const { return HasGOT; } @@ -111,7 +106,6 @@ public: virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) = 0; /// allocateGlobal - Allocate memory for a global. - /// virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0; /// deallocateFunctionBody - Free the specified function body. The argument diff --git a/contrib/llvm/include/llvm/ExecutionEngine/MCJIT.h b/contrib/llvm/include/llvm/ExecutionEngine/MCJIT.h new file mode 100644 index 0000000..f956a50 --- /dev/null +++ b/contrib/llvm/include/llvm/ExecutionEngine/MCJIT.h @@ -0,0 +1,38 @@ +//===-- MCJIT.h - MC-Based Just-In-Time Execution Engine --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file forces the MCJIT to link in on certain operating systems. +// (Windows). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_MCJIT_H +#define LLVM_EXECUTION_ENGINE_MCJIT_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include <cstdlib> + +extern "C" void LLVMLinkInMCJIT(); + +namespace { + struct ForceMCJITLinking { + ForceMCJITLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + LLVMLinkInMCJIT(); + } + } ForceMCJITLinking; +} + +#endif diff --git a/contrib/llvm/include/llvm/Function.h b/contrib/llvm/include/llvm/Function.h index 2b19fa5..9a0825a 100644 --- a/contrib/llvm/include/llvm/Function.h +++ b/contrib/llvm/include/llvm/Function.h @@ -152,7 +152,7 @@ public: /// The particular intrinsic functions which correspond to this value are /// defined in llvm/Intrinsics.h. /// - unsigned getIntrinsicID() const ATTRIBUTE_READONLY; + unsigned getIntrinsicID() const LLVM_ATTRIBUTE_READONLY; bool isIntrinsic() const { return getIntrinsicID() != 0; } /// getCallingConv()/setCallingConv(CC) - These method get and set the diff --git a/contrib/llvm/include/llvm/GlobalAlias.h b/contrib/llvm/include/llvm/GlobalAlias.h index 9867c51..f4af5b1 100644 --- a/contrib/llvm/include/llvm/GlobalAlias.h +++ b/contrib/llvm/include/llvm/GlobalAlias.h @@ -89,7 +89,8 @@ public: }; template <> -struct OperandTraits<GlobalAlias> : public FixedNumOperandTraits<1> { +struct OperandTraits<GlobalAlias> : + public FixedNumOperandTraits<GlobalAlias, 1> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Value) diff --git a/contrib/llvm/include/llvm/GlobalValue.h b/contrib/llvm/include/llvm/GlobalValue.h index 62e84f8..b184b8e 100644 --- a/contrib/llvm/include/llvm/GlobalValue.h +++ b/contrib/llvm/include/llvm/GlobalValue.h @@ -60,7 +60,8 @@ protected: GlobalValue(const Type *ty, ValueTy vty, Use *Ops, unsigned NumOps, LinkageTypes linkage, const Twine &Name) : Constant(ty, vty, Ops, NumOps), Parent(0), - Linkage(linkage), Visibility(DefaultVisibility), Alignment(0) { + Linkage(linkage), Visibility(DefaultVisibility), Alignment(0), + UnnamedAddr(0) { setName(Name); } @@ -70,6 +71,7 @@ protected: LinkageTypes Linkage : 5; // The linkage of this global unsigned Visibility : 2; // The visibility style of this global unsigned Alignment : 16; // Alignment of this symbol, must be power of two + unsigned UnnamedAddr : 1; // This value's address is not significant std::string Section; // Section to emit this into, empty mean default public: ~GlobalValue() { @@ -81,6 +83,9 @@ public: } void setAlignment(unsigned Align); + bool hasUnnamedAddr() const { return UnnamedAddr; } + void setUnnamedAddr(bool Val) { UnnamedAddr = Val; } + VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); } bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; } bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; } @@ -173,7 +178,9 @@ public: } /// isWeakForLinker - Whether the definition of this global may be replaced at - /// link time. + /// link time. NB: Using this method outside of the code generators is almost + /// always a mistake: when working at the IR level use mayBeOverridden instead + /// as it knows about ODR semantics. static bool isWeakForLinker(LinkageTypes Linkage) { return Linkage == AvailableExternallyLinkage || Linkage == WeakAnyLinkage || @@ -275,12 +282,6 @@ public: inline Module *getParent() { return Parent; } inline const Module *getParent() const { return Parent; } - /// removeDeadConstantUsers - If there are any dead constant users dangling - /// off of this global value, remove them. This method is useful for clients - /// that want to check to see if a global is unused, but don't want to deal - /// with potentially dead constants hanging off of the globals. - void removeDeadConstantUsers() const; - // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const GlobalValue *) { return true; } static inline bool classof(const Value *V) { diff --git a/contrib/llvm/include/llvm/GlobalVariable.h b/contrib/llvm/include/llvm/GlobalVariable.h index 633e8b4..1769c66 100644 --- a/contrib/llvm/include/llvm/GlobalVariable.h +++ b/contrib/llvm/include/llvm/GlobalVariable.h @@ -68,7 +68,7 @@ public: /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - /// isDeclaration - Is this global variable lacking an initializer? If so, + /// isDeclaration - Is this global variable lacking an initializer? If so, /// the global variable is defined in some other translation unit, and is thus /// only a declaration here. virtual bool isDeclaration() const { return getNumOperands() == 0; } @@ -80,7 +80,21 @@ public: inline bool hasInitializer() const { return !isDeclaration(); } /// hasDefinitiveInitializer - Whether the global variable has an initializer, - /// and this is the initializer that will be used in the final executable. + /// and any other instances of the global (this can happen due to weak + /// linkage) are guaranteed to have the same initializer. + /// + /// Note that if you want to transform a global, you must use + /// hasUniqueInitializer() instead, because of the *_odr linkage type. + /// + /// Example: + /// + /// @a = global SomeType* null - Initializer is both definitive and unique. + /// + /// @b = global weak SomeType* null - Initializer is neither definitive nor + /// unique. + /// + /// @c = global weak_odr SomeType* null - Initializer is definitive, but not + /// unique. inline bool hasDefinitiveInitializer() const { return hasInitializer() && // The initializer of a global variable with weak linkage may change at @@ -88,6 +102,19 @@ public: !mayBeOverridden(); } + /// hasUniqueInitializer - Whether the global variable has an initializer, and + /// any changes made to the initializer will turn up in the final executable. + inline bool hasUniqueInitializer() const { + return hasInitializer() && + // It's not safe to modify initializers of global variables with weak + // linkage, because the linker might choose to discard the initializer and + // use the initializer from another instance of the global variable + // 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(); + } + /// getInitializer - Return the initializer for this global variable. It is /// illegal to call this method if the global is external, because we cannot /// tell what the value is initialized to! @@ -142,7 +169,8 @@ public: }; template <> -struct OperandTraits<GlobalVariable> : public OptionalOperandTraits<> { +struct OperandTraits<GlobalVariable> : + public OptionalOperandTraits<GlobalVariable> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalVariable, Value) diff --git a/contrib/llvm/include/llvm/InitializePasses.h b/contrib/llvm/include/llvm/InitializePasses.h new file mode 100644 index 0000000..02dbfbd --- /dev/null +++ b/contrib/llvm/include/llvm/InitializePasses.h @@ -0,0 +1,235 @@ +//===- llvm/InitializePasses.h -------- Initialize All Passes ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations for the pass initialization routines +// for the entire LLVM project. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INITIALIZEPASSES_H +#define LLVM_INITIALIZEPASSES_H + +namespace llvm { + +class PassRegistry; + +/// initializeCore - Initialize all passes linked into the +/// TransformUtils library. +void initializeCore(PassRegistry&); + +/// initializeTransformUtils - Initialize all passes linked into the +/// TransformUtils library. +void initializeTransformUtils(PassRegistry&); + +/// initializeScalarOpts - Initialize all passes linked into the +/// ScalarOpts library. +void initializeScalarOpts(PassRegistry&); + +/// initializeInstCombine - Initialize all passes linked into the +/// ScalarOpts library. +void initializeInstCombine(PassRegistry&); + +/// initializeIPO - Initialize all passes linked into the IPO library. +void initializeIPO(PassRegistry&); + +/// initializeInstrumentation - Initialize all passes linked into the +/// Instrumentation library. +void initializeInstrumentation(PassRegistry&); + +/// initializeAnalysis - Initialize all passes linked into the Analysis library. +void initializeAnalysis(PassRegistry&); + +/// initializeIPA - Initialize all passes linked into the IPA library. +void initializeIPA(PassRegistry&); + +/// initializeCodeGen - Initialize all passes linked into the CodeGen library. +void initializeCodeGen(PassRegistry&); + +/// initializeCodeGen - Initialize all passes linked into the CodeGen library. +void initializeTarget(PassRegistry&); + +void initializeAAEvalPass(PassRegistry&); +void initializeADCEPass(PassRegistry&); +void initializeAliasAnalysisAnalysisGroup(PassRegistry&); +void initializeAliasAnalysisCounterPass(PassRegistry&); +void initializeAliasDebuggerPass(PassRegistry&); +void initializeAliasSetPrinterPass(PassRegistry&); +void initializeAlwaysInlinerPass(PassRegistry&); +void initializeArgPromotionPass(PassRegistry&); +void initializeBasicAliasAnalysisPass(PassRegistry&); +void initializeBasicCallGraphPass(PassRegistry&); +void initializeBlockExtractorPassPass(PassRegistry&); +void initializeBlockPlacementPass(PassRegistry&); +void initializeBreakCriticalEdgesPass(PassRegistry&); +void initializeCFGOnlyPrinterPass(PassRegistry&); +void initializeCFGOnlyViewerPass(PassRegistry&); +void initializeCFGPrinterPass(PassRegistry&); +void initializeCFGSimplifyPassPass(PassRegistry&); +void initializeCFGViewerPass(PassRegistry&); +void initializeCalculateSpillWeightsPass(PassRegistry&); +void initializeCallGraphAnalysisGroup(PassRegistry&); +void initializeCodeGenPreparePass(PassRegistry&); +void initializeConstantMergePass(PassRegistry&); +void initializeConstantPropagationPass(PassRegistry&); +void initializeCorrelatedValuePropagationPass(PassRegistry&); +void initializeDAEPass(PassRegistry&); +void initializeDAHPass(PassRegistry&); +void initializeDCEPass(PassRegistry&); +void initializeDSEPass(PassRegistry&); +void initializeDTEPass(PassRegistry&); +void initializeDeadInstEliminationPass(PassRegistry&); +void initializeDeadMachineInstructionElimPass(PassRegistry&); +void initializeDomOnlyPrinterPass(PassRegistry&); +void initializeDomOnlyViewerPass(PassRegistry&); +void initializeDomPrinterPass(PassRegistry&); +void initializeDomViewerPass(PassRegistry&); +void initializeDominanceFrontierPass(PassRegistry&); +void initializeDominatorTreePass(PassRegistry&); +void initializeEdgeBundlesPass(PassRegistry&); +void initializeEdgeProfilerPass(PassRegistry&); +void initializePathProfilerPass(PassRegistry&); +void initializeEarlyCSEPass(PassRegistry&); +void initializeExpandISelPseudosPass(PassRegistry&); +void initializeFindUsedTypesPass(PassRegistry&); +void initializeFunctionAttrsPass(PassRegistry&); +void initializeGCModuleInfoPass(PassRegistry&); +void initializeGEPSplitterPass(PassRegistry&); +void initializeGVNPass(PassRegistry&); +void initializeGlobalDCEPass(PassRegistry&); +void initializeGlobalOptPass(PassRegistry&); +void initializeGlobalsModRefPass(PassRegistry&); +void initializeIPCPPass(PassRegistry&); +void initializeIPSCCPPass(PassRegistry&); +void initializeIVUsersPass(PassRegistry&); +void initializeIfConverterPass(PassRegistry&); +void initializeIndVarSimplifyPass(PassRegistry&); +void initializeInstCombinerPass(PassRegistry&); +void initializeInstCountPass(PassRegistry&); +void initializeInstNamerPass(PassRegistry&); +void initializeInternalizePassPass(PassRegistry&); +void initializeIntervalPartitionPass(PassRegistry&); +void initializeJumpThreadingPass(PassRegistry&); +void initializeLCSSAPass(PassRegistry&); +void initializeLICMPass(PassRegistry&); +void initializeLazyValueInfoPass(PassRegistry&); +void initializeLibCallAliasAnalysisPass(PassRegistry&); +void initializeLintPass(PassRegistry&); +void initializeLiveDebugVariablesPass(PassRegistry&); +void initializeLiveIntervalsPass(PassRegistry&); +void initializeLiveStacksPass(PassRegistry&); +void initializeLiveValuesPass(PassRegistry&); +void initializeLiveVariablesPass(PassRegistry&); +void initializeLoaderPassPass(PassRegistry&); +void initializePathProfileLoaderPassPass(PassRegistry&); +void initializeLoopDeletionPass(PassRegistry&); +void initializeLoopDependenceAnalysisPass(PassRegistry&); +void initializeLoopExtractorPass(PassRegistry&); +void initializeLoopInfoPass(PassRegistry&); +void initializeLoopInstSimplifyPass(PassRegistry&); +void initializeLoopRotatePass(PassRegistry&); +void initializeLoopSimplifyPass(PassRegistry&); +void initializeLoopSplitterPass(PassRegistry&); +void initializeLoopStrengthReducePass(PassRegistry&); +void initializeLoopUnrollPass(PassRegistry&); +void initializeLoopUnswitchPass(PassRegistry&); +void initializeLoopIdiomRecognizePass(PassRegistry&); +void initializeLowerAtomicPass(PassRegistry&); +void initializeLowerIntrinsicsPass(PassRegistry&); +void initializeLowerInvokePass(PassRegistry&); +void initializeLowerSetJmpPass(PassRegistry&); +void initializeLowerSwitchPass(PassRegistry&); +void initializeMachineCSEPass(PassRegistry&); +void initializeMachineDominatorTreePass(PassRegistry&); +void initializeMachineLICMPass(PassRegistry&); +void initializeMachineLoopInfoPass(PassRegistry&); +void initializeMachineLoopRangesPass(PassRegistry&); +void initializeMachineModuleInfoPass(PassRegistry&); +void initializeMachineSinkingPass(PassRegistry&); +void initializeMachineVerifierPassPass(PassRegistry&); +void initializeMemCpyOptPass(PassRegistry&); +void initializeMemDepPrinterPass(PassRegistry&); +void initializeMemoryDependenceAnalysisPass(PassRegistry&); +void initializeMergeFunctionsPass(PassRegistry&); +void initializeModuleDebugInfoPrinterPass(PassRegistry&); +void initializeNoAAPass(PassRegistry&); +void initializeNoProfileInfoPass(PassRegistry&); +void initializeNoPathProfileInfoPass(PassRegistry&); +void initializeOptimalEdgeProfilerPass(PassRegistry&); +void initializeOptimizePHIsPass(PassRegistry&); +void initializePEIPass(PassRegistry&); +void initializePHIEliminationPass(PassRegistry&); +void initializePartialInlinerPass(PassRegistry&); +void initializePeepholeOptimizerPass(PassRegistry&); +void initializePostDomOnlyPrinterPass(PassRegistry&); +void initializePostDomOnlyViewerPass(PassRegistry&); +void initializePostDomPrinterPass(PassRegistry&); +void initializePostDomViewerPass(PassRegistry&); +void initializePostDominanceFrontierPass(PassRegistry&); +void initializePostDominatorTreePass(PassRegistry&); +void initializePreAllocSplittingPass(PassRegistry&); +void initializePreVerifierPass(PassRegistry&); +void initializePrintDbgInfoPass(PassRegistry&); +void initializePrintFunctionPassPass(PassRegistry&); +void initializePrintModulePassPass(PassRegistry&); +void initializeProcessImplicitDefsPass(PassRegistry&); +void initializeProfileEstimatorPassPass(PassRegistry&); +void initializeProfileInfoAnalysisGroup(PassRegistry&); +void initializePathProfileInfoAnalysisGroup(PassRegistry&); +void initializePathProfileVerifierPass(PassRegistry&); +void initializeProfileVerifierPassPass(PassRegistry&); +void initializePromotePassPass(PassRegistry&); +void initializePruneEHPass(PassRegistry&); +void initializeRALinScanPass(PassRegistry&); +void initializeReassociatePass(PassRegistry&); +void initializeRegToMemPass(PassRegistry&); +void initializeRegionInfoPass(PassRegistry&); +void initializeRegionOnlyPrinterPass(PassRegistry&); +void initializeRegionOnlyViewerPass(PassRegistry&); +void initializeRegionPrinterPass(PassRegistry&); +void initializeRegionViewerPass(PassRegistry&); +void initializeRegisterCoalescerAnalysisGroup(PassRegistry&); +void initializeRenderMachineFunctionPass(PassRegistry&); +void initializeSCCPPass(PassRegistry&); +void initializeSRETPromotionPass(PassRegistry&); +void initializeSROA_DTPass(PassRegistry&); +void initializeSROA_SSAUpPass(PassRegistry&); +void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); +void initializeScalarEvolutionPass(PassRegistry&); +void initializeSimpleInlinerPass(PassRegistry&); +void initializeSimpleRegisterCoalescingPass(PassRegistry&); +void initializeSimplifyHalfPowrLibCallsPass(PassRegistry&); +void initializeSimplifyLibCallsPass(PassRegistry&); +void initializeSingleLoopExtractorPass(PassRegistry&); +void initializeSinkingPass(PassRegistry&); +void initializeSlotIndexesPass(PassRegistry&); +void initializeSpillPlacementPass(PassRegistry&); +void initializeStackProtectorPass(PassRegistry&); +void initializeStackSlotColoringPass(PassRegistry&); +void initializeStripDeadDebugInfoPass(PassRegistry&); +void initializeStripDeadPrototypesPassPass(PassRegistry&); +void initializeStripDebugDeclarePass(PassRegistry&); +void initializeStripNonDebugSymbolsPass(PassRegistry&); +void initializeStripSymbolsPass(PassRegistry&); +void initializeStrongPHIEliminationPass(PassRegistry&); +void initializeTailCallElimPass(PassRegistry&); +void initializeTailDupPass(PassRegistry&); +void initializeTargetDataPass(PassRegistry&); +void initializeTargetLibraryInfoPass(PassRegistry&); +void initializeTwoAddressInstructionPassPass(PassRegistry&); +void initializeTypeBasedAliasAnalysisPass(PassRegistry&); +void initializeUnifyFunctionExitNodesPass(PassRegistry&); +void initializeUnreachableBlockElimPass(PassRegistry&); +void initializeUnreachableMachineBlockElimPass(PassRegistry&); +void initializeVerifierPass(PassRegistry&); +void initializeVirtRegMapPass(PassRegistry&); +void initializeInstSimplifierPass(PassRegistry&); + +} + +#endif diff --git a/contrib/llvm/include/llvm/InlineAsm.h b/contrib/llvm/include/llvm/InlineAsm.h index 105b1bc..ed8f0f7 100644 --- a/contrib/llvm/include/llvm/InlineAsm.h +++ b/contrib/llvm/include/llvm/InlineAsm.h @@ -87,6 +87,25 @@ public: isClobber // '~x' }; + typedef std::vector<std::string> ConstraintCodeVector; + + struct SubConstraintInfo { + /// MatchingInput - If this is not -1, this is an output constraint where an + /// input constraint is required to match it (e.g. "0"). The value is the + /// constraint number that matches this one (for example, if this is + /// constraint #0 and constraint #4 has the value "0", this will be 4). + signed char MatchingInput; + /// Code - The constraint code, either the register name (in braces) or the + /// constraint letter/number. + ConstraintCodeVector Codes; + /// Default constructor. + SubConstraintInfo() : MatchingInput(-1) {} + }; + + typedef std::vector<SubConstraintInfo> SubConstraintInfoVector; + struct ConstraintInfo; + typedef std::vector<ConstraintInfo> ConstraintInfoVector; + struct ConstraintInfo { /// Type - The basic type of the constraint: input/output/clobber /// @@ -118,25 +137,42 @@ public: /// Code - The constraint code, either the register name (in braces) or the /// constraint letter/number. - std::vector<std::string> Codes; + ConstraintCodeVector Codes; + + /// isMultipleAlternative - '|': has multiple-alternative constraints. + bool isMultipleAlternative; + + /// multipleAlternatives - If there are multiple alternative constraints, + /// this array will contain them. Otherwise it will be empty. + SubConstraintInfoVector multipleAlternatives; + + /// The currently selected alternative constraint index. + unsigned currentAlternativeIndex; + + ///Default constructor. + ConstraintInfo(); + + /// Copy constructor. + ConstraintInfo(const ConstraintInfo &other); /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the /// fields in this structure. If the constraint string is not understood, /// return true, otherwise return false. - bool Parse(StringRef Str, - std::vector<InlineAsm::ConstraintInfo> &ConstraintsSoFar); + bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar); + + /// selectAlternative - Point this constraint to the alternative constraint + /// indicated by the index. + void selectAlternative(unsigned index); }; /// ParseConstraints - Split up the constraint string into the specific /// constraints and their prefixes. If this returns an empty vector, and if /// the constraint string itself isn't empty, there was an error parsing. - static std::vector<ConstraintInfo> - ParseConstraints(StringRef ConstraintString); + static ConstraintInfoVector ParseConstraints(StringRef ConstraintString); /// ParseConstraints - Parse the constraints of this inlineasm object, /// returning them the same way that ParseConstraints(str) does. - std::vector<ConstraintInfo> - ParseConstraints() const { + ConstraintInfoVector ParseConstraints() const { return ParseConstraints(Constraints); } @@ -154,8 +190,15 @@ public: Op_InputChain = 0, Op_AsmString = 1, Op_MDNode = 2, - Op_IsAlignStack = 3, + Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack Op_FirstOperand = 4, + + MIOp_AsmString = 0, + MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack + MIOp_FirstOperand = 2, + + Extra_HasSideEffects = 1, + Extra_IsAlignStack = 2, Kind_RegUse = 1, Kind_RegDef = 2, diff --git a/contrib/llvm/include/llvm/InstrTypes.h b/contrib/llvm/include/llvm/InstrTypes.h index 6715416..a166956 100644 --- a/contrib/llvm/include/llvm/InstrTypes.h +++ b/contrib/llvm/include/llvm/InstrTypes.h @@ -128,7 +128,8 @@ public: }; template <> -struct OperandTraits<UnaryInstruction> : public FixedNumOperandTraits<1> { +struct OperandTraits<UnaryInstruction> : + public FixedNumOperandTraits<UnaryInstruction, 1> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value) @@ -193,154 +194,93 @@ public: } #include "llvm/Instruction.def" - - /// CreateNSWAdd - Create an Add operator with the NSW flag set. - /// - static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateAdd(V1, V2, Name); + static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = Create(Opc, V1, V2, Name); BO->setHasNoSignedWrap(true); return BO; } - static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateAdd(V1, V2, Name, BB); + static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); BO->setHasNoSignedWrap(true); return BO; } - static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateAdd(V1, V2, Name, I); + static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, I); BO->setHasNoSignedWrap(true); return BO; } - - /// CreateNUWAdd - Create an Add operator with the NUW flag set. - /// - static BinaryOperator *CreateNUWAdd(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateAdd(V1, V2, Name); - BO->setHasNoUnsignedWrap(true); - return BO; - } - static BinaryOperator *CreateNUWAdd(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateAdd(V1, V2, Name, BB); - BO->setHasNoUnsignedWrap(true); - return BO; - } - static BinaryOperator *CreateNUWAdd(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateAdd(V1, V2, Name, I); - BO->setHasNoUnsignedWrap(true); - return BO; - } - - /// CreateNSWSub - Create an Sub operator with the NSW flag set. - /// - static BinaryOperator *CreateNSWSub(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateSub(V1, V2, Name); - BO->setHasNoSignedWrap(true); - return BO; - } - static BinaryOperator *CreateNSWSub(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateSub(V1, V2, Name, BB); - BO->setHasNoSignedWrap(true); - return BO; - } - static BinaryOperator *CreateNSWSub(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateSub(V1, V2, Name, I); - BO->setHasNoSignedWrap(true); - return BO; - } - - /// CreateNUWSub - Create an Sub operator with the NUW flag set. - /// - static BinaryOperator *CreateNUWSub(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateSub(V1, V2, Name); - BO->setHasNoUnsignedWrap(true); - return BO; - } - static BinaryOperator *CreateNUWSub(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateSub(V1, V2, Name, BB); - BO->setHasNoUnsignedWrap(true); - return BO; - } - static BinaryOperator *CreateNUWSub(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateSub(V1, V2, Name, I); - BO->setHasNoUnsignedWrap(true); - return BO; - } - - /// CreateNSWMul - Create a Mul operator with the NSW flag set. - /// - static BinaryOperator *CreateNSWMul(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateMul(V1, V2, Name); - BO->setHasNoSignedWrap(true); - return BO; - } - static BinaryOperator *CreateNSWMul(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateMul(V1, V2, Name, BB); - BO->setHasNoSignedWrap(true); - return BO; - } - static BinaryOperator *CreateNSWMul(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateMul(V1, V2, Name, I); - BO->setHasNoSignedWrap(true); - return BO; - } - - /// CreateNUWMul - Create a Mul operator with the NUW flag set. - /// - static BinaryOperator *CreateNUWMul(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateMul(V1, V2, Name); + + static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = Create(Opc, V1, V2, Name); BO->setHasNoUnsignedWrap(true); return BO; } - static BinaryOperator *CreateNUWMul(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateMul(V1, V2, Name, BB); + static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); BO->setHasNoUnsignedWrap(true); return BO; } - static BinaryOperator *CreateNUWMul(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateMul(V1, V2, Name, I); + static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, I); BO->setHasNoUnsignedWrap(true); return BO; } - - /// CreateExactSDiv - Create an SDiv operator with the exact flag set. - /// - static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2, - const Twine &Name = "") { - BinaryOperator *BO = CreateSDiv(V1, V2, Name); + + static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = Create(Opc, V1, V2, Name); BO->setIsExact(true); return BO; } - static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2, - const Twine &Name, BasicBlock *BB) { - BinaryOperator *BO = CreateSDiv(V1, V2, Name, BB); + static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); BO->setIsExact(true); return BO; } - static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2, - const Twine &Name, Instruction *I) { - BinaryOperator *BO = CreateSDiv(V1, V2, Name, I); + static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, I); BO->setIsExact(true); return BO; } - + +#define DEFINE_HELPERS(OPC, NUWNSWEXACT) \ + static BinaryOperator *Create ## NUWNSWEXACT ## OPC \ + (Value *V1, Value *V2, const Twine &Name = "") { \ + return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name); \ + } \ + static BinaryOperator *Create ## NUWNSWEXACT ## OPC \ + (Value *V1, Value *V2, const Twine &Name, BasicBlock *BB) { \ + return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name, BB); \ + } \ + static BinaryOperator *Create ## NUWNSWEXACT ## OPC \ + (Value *V1, Value *V2, const Twine &Name, Instruction *I) { \ + return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name, I); \ + } + + DEFINE_HELPERS(Add, NSW) // CreateNSWAdd + DEFINE_HELPERS(Add, NUW) // CreateNUWAdd + DEFINE_HELPERS(Sub, NSW) // CreateNSWSub + DEFINE_HELPERS(Sub, NUW) // CreateNUWSub + DEFINE_HELPERS(Mul, NSW) // CreateNSWMul + DEFINE_HELPERS(Mul, NUW) // CreateNUWMul + DEFINE_HELPERS(Shl, NSW) // CreateNSWShl + DEFINE_HELPERS(Shl, NUW) // CreateNUWShl + + DEFINE_HELPERS(SDiv, Exact) // CreateExactSDiv + DEFINE_HELPERS(UDiv, Exact) // CreateExactUDiv + DEFINE_HELPERS(AShr, Exact) // CreateExactAShr + DEFINE_HELPERS(LShr, Exact) // CreateExactLShr + +#undef DEFINE_HELPERS + /// Helper functions to construct and inspect unary operations (NEG and NOT) /// via binary operators SUB and XOR: /// @@ -432,7 +372,8 @@ public: }; template <> -struct OperandTraits<BinaryOperator> : public FixedNumOperandTraits<2> { +struct OperandTraits<BinaryOperator> : + public FixedNumOperandTraits<BinaryOperator, 2> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value) @@ -824,11 +765,11 @@ public: /// This is just a convenience that dispatches to the subclasses. /// @brief Determine if this CmpInst is commutative. - bool isCommutative(); + bool isCommutative() const; /// This is just a convenience that dispatches to the subclasses. /// @brief Determine if this is an equals/not equals predicate. - bool isEquality(); + bool isEquality() const; /// @returns true if the comparison is signed, false otherwise. /// @brief Determine if this instruction is using a signed comparison. @@ -903,7 +844,7 @@ private: // FIXME: these are redundant if CmpInst < BinaryOperator template <> -struct OperandTraits<CmpInst> : public FixedNumOperandTraits<2> { +struct OperandTraits<CmpInst> : public FixedNumOperandTraits<CmpInst, 2> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CmpInst, Value) diff --git a/contrib/llvm/include/llvm/Instruction.h b/contrib/llvm/include/llvm/Instruction.h index 88f5ce1..89bb9fd 100644 --- a/contrib/llvm/include/llvm/Instruction.h +++ b/contrib/llvm/include/llvm/Instruction.h @@ -200,11 +200,10 @@ public: /// /// Associative operators satisfy: x op (y op z) === (x op y) op z /// - /// In LLVM, the Add, Mul, And, Or, and Xor operators are associative, when - /// not applied to floating point types. + /// In LLVM, the Add, Mul, And, Or, and Xor operators are associative. /// - bool isAssociative() const { return isAssociative(getOpcode(), getType()); } - static bool isAssociative(unsigned op, const Type *Ty); + bool isAssociative() const { return isAssociative(getOpcode()); } + static bool isAssociative(unsigned op); /// isCommutative - Return true if the instruction is commutative: /// diff --git a/contrib/llvm/include/llvm/Instructions.h b/contrib/llvm/include/llvm/Instructions.h index bd1e889..17ff763 100644 --- a/contrib/llvm/include/llvm/Instructions.h +++ b/contrib/llvm/include/llvm/Instructions.h @@ -29,7 +29,6 @@ class ConstantInt; class ConstantRange; class APInt; class LLVMContext; -class DominatorTree; //===----------------------------------------------------------------------===// // AllocaInst Class @@ -43,7 +42,7 @@ protected: public: explicit AllocaInst(const Type *Ty, Value *ArraySize = 0, const Twine &Name = "", Instruction *InsertBefore = 0); - AllocaInst(const Type *Ty, Value *ArraySize, + AllocaInst(const Type *Ty, Value *ArraySize, const Twine &Name, BasicBlock *InsertAtEnd); AllocaInst(const Type *Ty, const Twine &Name, Instruction *InsertBefore = 0); @@ -166,8 +165,8 @@ public: unsigned getPointerAddressSpace() const { return cast<PointerType>(getPointerOperand()->getType())->getAddressSpace(); } - - + + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const LoadInst *) { return true; } static inline bool classof(const Instruction *I) { @@ -237,7 +236,7 @@ public: Value *getValueOperand() { return getOperand(0); } const Value *getValueOperand() const { return getOperand(0); } - + Value *getPointerOperand() { return getOperand(1); } const Value *getPointerOperand() const { return getOperand(1); } static unsigned getPointerOperandIndex() { return 1U; } @@ -245,7 +244,7 @@ public: unsigned getPointerAddressSpace() const { return cast<PointerType>(getPointerOperand()->getType())->getAddressSpace(); } - + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const StoreInst *) { return true; } static inline bool classof(const Instruction *I) { @@ -263,7 +262,7 @@ private: }; template <> -struct OperandTraits<StoreInst> : public FixedNumOperandTraits<2> { +struct OperandTraits<StoreInst> : public FixedNumOperandTraits<StoreInst, 2> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) @@ -289,8 +288,10 @@ class GetElementPtrInst : public Instruction { const Twine &NameStr); void init(Value *Ptr, Value *Idx, const Twine &NameStr); - template<typename InputIterator> - void init(Value *Ptr, InputIterator IdxBegin, InputIterator IdxEnd, + template<typename RandomAccessIterator> + void init(Value *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, // This argument ensures that we have an iterator we can // do arithmetic on in constant time @@ -313,10 +314,10 @@ class GetElementPtrInst : public Instruction { /// Null is returned if the indices are invalid for the specified /// pointer type. /// - template<typename InputIterator> + template<typename RandomAccessIterator> static const Type *getIndexedType(const Type *Ptr, - InputIterator IdxBegin, - InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, // This argument ensures that we // have an iterator we can do // arithmetic on in constant time @@ -331,18 +332,19 @@ class GetElementPtrInst : public Instruction { } /// Constructors - Create a getelementptr instruction with a base pointer an - /// list of indices. The first ctor can optionally insert before an existing + /// list of indices. The first ctor can optionally insert before an existing /// instruction, the second appends the new instruction to the specified /// BasicBlock. - template<typename InputIterator> - inline GetElementPtrInst(Value *Ptr, InputIterator IdxBegin, - InputIterator IdxEnd, + template<typename RandomAccessIterator> + inline GetElementPtrInst(Value *Ptr, RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, unsigned Values, const Twine &NameStr, Instruction *InsertBefore); - template<typename InputIterator> + template<typename RandomAccessIterator> inline GetElementPtrInst(Value *Ptr, - InputIterator IdxBegin, InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd); @@ -355,23 +357,24 @@ class GetElementPtrInst : public Instruction { protected: virtual GetElementPtrInst *clone_impl() const; public: - template<typename InputIterator> - static GetElementPtrInst *Create(Value *Ptr, InputIterator IdxBegin, - InputIterator IdxEnd, + template<typename RandomAccessIterator> + static GetElementPtrInst *Create(Value *Ptr, RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr = "", Instruction *InsertBefore = 0) { - typename std::iterator_traits<InputIterator>::difference_type Values = - 1 + std::distance(IdxBegin, IdxEnd); + typename std::iterator_traits<RandomAccessIterator>::difference_type + Values = 1 + std::distance(IdxBegin, IdxEnd); return new(Values) GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Values, NameStr, InsertBefore); } - template<typename InputIterator> + template<typename RandomAccessIterator> static GetElementPtrInst *Create(Value *Ptr, - InputIterator IdxBegin, InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, BasicBlock *InsertAtEnd) { - typename std::iterator_traits<InputIterator>::difference_type Values = - 1 + std::distance(IdxBegin, IdxEnd); + typename std::iterator_traits<RandomAccessIterator>::difference_type + Values = 1 + std::distance(IdxBegin, IdxEnd); return new(Values) GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Values, NameStr, InsertAtEnd); } @@ -391,9 +394,10 @@ public: /// Create an "inbounds" getelementptr. See the documentation for the /// "inbounds" flag in LangRef.html for details. - template<typename InputIterator> - static GetElementPtrInst *CreateInBounds(Value *Ptr, InputIterator IdxBegin, - InputIterator IdxEnd, + template<typename RandomAccessIterator> + static GetElementPtrInst *CreateInBounds(Value *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr = "", Instruction *InsertBefore = 0) { GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd, @@ -401,10 +405,10 @@ public: GEP->setIsInBounds(true); return GEP; } - template<typename InputIterator> + template<typename RandomAccessIterator> static GetElementPtrInst *CreateInBounds(Value *Ptr, - InputIterator IdxBegin, - InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, BasicBlock *InsertAtEnd) { GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd, @@ -441,12 +445,12 @@ public: /// Null is returned if the indices are invalid for the specified /// pointer type. /// - template<typename InputIterator> + template<typename RandomAccessIterator> static const Type *getIndexedType(const Type *Ptr, - InputIterator IdxBegin, - InputIterator IdxEnd) { + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd) { return getIndexedType(Ptr, IdxBegin, IdxEnd, - typename std::iterator_traits<InputIterator>:: + typename std::iterator_traits<RandomAccessIterator>:: iterator_category()); } @@ -454,6 +458,9 @@ public: Value* const *Idx, unsigned NumIdx); static const Type *getIndexedType(const Type *Ptr, + Constant* const *Idx, unsigned NumIdx); + + static const Type *getIndexedType(const Type *Ptr, uint64_t const *Idx, unsigned NumIdx); static const Type *getIndexedType(const Type *Ptr, Value *Idx); @@ -472,7 +479,7 @@ public: static unsigned getPointerOperandIndex() { return 0U; // get index for modifying correct operand } - + unsigned getPointerAddressSpace() const { return cast<PointerType>(getType())->getAddressSpace(); } @@ -520,13 +527,14 @@ public: }; template <> -struct OperandTraits<GetElementPtrInst> : public VariadicOperandTraits<1> { +struct OperandTraits<GetElementPtrInst> : + public VariadicOperandTraits<GetElementPtrInst, 1> { }; -template<typename InputIterator> +template<typename RandomAccessIterator> GetElementPtrInst::GetElementPtrInst(Value *Ptr, - InputIterator IdxBegin, - InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, unsigned Values, const Twine &NameStr, Instruction *InsertBefore) @@ -539,12 +547,13 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr, OperandTraits<GetElementPtrInst>::op_end(this) - Values, Values, InsertBefore) { init(Ptr, IdxBegin, IdxEnd, NameStr, - typename std::iterator_traits<InputIterator>::iterator_category()); + typename std::iterator_traits<RandomAccessIterator> + ::iterator_category()); } -template<typename InputIterator> +template<typename RandomAccessIterator> GetElementPtrInst::GetElementPtrInst(Value *Ptr, - InputIterator IdxBegin, - InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd) @@ -557,7 +566,8 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr, OperandTraits<GetElementPtrInst>::op_end(this) - Values, Values, InsertAtEnd) { init(Ptr, IdxBegin, IdxEnd, NameStr, - typename std::iterator_traits<InputIterator>::iterator_category()); + typename std::iterator_traits<RandomAccessIterator> + ::iterator_category()); } @@ -575,7 +585,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) class ICmpInst: public CmpInst { protected: /// @brief Clone an indentical ICmpInst - virtual ICmpInst *clone_impl() const; + virtual ICmpInst *clone_impl() const; public: /// @brief Constructor with insert-before-instruction semantics. ICmpInst( @@ -746,7 +756,7 @@ public: assert(getOperand(0)->getType()->isFPOrFPVectorTy() && "Invalid operand types for FCmp instruction"); } - + /// @brief Constructor with insert-at-end semantics. FCmpInst( BasicBlock &InsertAtEnd, ///< Block to insert into. @@ -838,8 +848,10 @@ class CallInst : public Instruction { void init(Value *Func, Value *Actual); void init(Value *Func); - template<typename InputIterator> - void init(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, + template<typename RandomAccessIterator> + void init(Value *Func, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, const Twine &NameStr, // This argument ensures that we have an iterator we can // do arithmetic on in constant time @@ -851,24 +863,26 @@ class CallInst : public Instruction { setName(NameStr); } - /// Construct a CallInst given a range of arguments. InputIterator + /// Construct a CallInst given a range of arguments. RandomAccessIterator /// must be a random-access iterator pointing to contiguous storage - /// (e.g. a std::vector<>::iterator). Checks are made for + /// (e.g. a std::vector<>::iterator). Checks are made for /// random-accessness but not for contiguous storage as that would /// incur runtime overhead. /// @brief Construct a CallInst from a range of arguments - template<typename InputIterator> - CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, + template<typename RandomAccessIterator> + CallInst(Value *Func, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, const Twine &NameStr, Instruction *InsertBefore); - /// Construct a CallInst given a range of arguments. InputIterator + /// Construct a CallInst given a range of arguments. RandomAccessIterator /// must be a random-access iterator pointing to contiguous storage /// (e.g. a std::vector<>::iterator). Checks are made for /// random-accessness but not for contiguous storage as that would /// incur runtime overhead. /// @brief Construct a CallInst from a range of arguments - template<typename InputIterator> - inline CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, + template<typename RandomAccessIterator> + inline CallInst(Value *Func, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, const Twine &NameStr, BasicBlock *InsertAtEnd); CallInst(Value *F, Value *Actual, const Twine &NameStr, @@ -881,17 +895,19 @@ class CallInst : public Instruction { protected: virtual CallInst *clone_impl() const; public: - template<typename InputIterator> + template<typename RandomAccessIterator> static CallInst *Create(Value *Func, - InputIterator ArgBegin, InputIterator ArgEnd, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, const Twine &NameStr = "", Instruction *InsertBefore = 0) { return new(unsigned(ArgEnd - ArgBegin + 1)) CallInst(Func, ArgBegin, ArgEnd, NameStr, InsertBefore); } - template<typename InputIterator> + template<typename RandomAccessIterator> static CallInst *Create(Value *Func, - InputIterator ArgBegin, InputIterator ArgEnd, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, const Twine &NameStr, BasicBlock *InsertAtEnd) { return new(unsigned(ArgEnd - ArgBegin + 1)) CallInst(Func, ArgBegin, ArgEnd, NameStr, InsertAtEnd); @@ -984,7 +1000,7 @@ public: unsigned getParamAlignment(unsigned i) const { return AttributeList.getParamAlignment(i); } - + /// @brief Return true if the call should not be inlined. bool isNoInline() const { return paramHasAttr(~0, Attribute::NoInline); } void setIsNoInline(bool Value = true) { @@ -1052,7 +1068,7 @@ public: void setCalledFunction(Value* Fn) { Op<-1>() = Fn; } - + /// isInlineAsm - Check if this call is an inline asm statement. bool isInlineAsm() const { return isa<InlineAsm>(Op<-1>()); @@ -1075,11 +1091,12 @@ private: }; template <> -struct OperandTraits<CallInst> : public VariadicOperandTraits<1> { +struct OperandTraits<CallInst> : public VariadicOperandTraits<CallInst, 1> { }; -template<typename InputIterator> -CallInst::CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, +template<typename RandomAccessIterator> +CallInst::CallInst(Value *Func, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, const Twine &NameStr, BasicBlock *InsertAtEnd) : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) ->getElementType())->getReturnType(), @@ -1087,11 +1104,13 @@ CallInst::CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, OperandTraits<CallInst>::op_end(this) - (ArgEnd - ArgBegin + 1), unsigned(ArgEnd - ArgBegin + 1), InsertAtEnd) { init(Func, ArgBegin, ArgEnd, NameStr, - typename std::iterator_traits<InputIterator>::iterator_category()); + typename std::iterator_traits<RandomAccessIterator> + ::iterator_category()); } -template<typename InputIterator> -CallInst::CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, +template<typename RandomAccessIterator> +CallInst::CallInst(Value *Func, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, const Twine &NameStr, Instruction *InsertBefore) : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType()) ->getElementType())->getReturnType(), @@ -1099,7 +1118,8 @@ CallInst::CallInst(Value *Func, InputIterator ArgBegin, InputIterator ArgEnd, OperandTraits<CallInst>::op_end(this) - (ArgEnd - ArgBegin + 1), unsigned(ArgEnd - ArgBegin + 1), InsertBefore) { init(Func, ArgBegin, ArgEnd, NameStr, - typename std::iterator_traits<InputIterator>::iterator_category()); + typename std::iterator_traits<RandomAccessIterator> + ::iterator_category()); } @@ -1156,7 +1176,7 @@ public: Value *getCondition() { return Op<0>(); } Value *getTrueValue() { return Op<1>(); } Value *getFalseValue() { return Op<2>(); } - + /// areInvalidOperands - Return a string if the specified operands are invalid /// for a select operation, otherwise return null. static const char *areInvalidOperands(Value *Cond, Value *True, Value *False); @@ -1179,7 +1199,7 @@ public: }; template <> -struct OperandTraits<SelectInst> : public FixedNumOperandTraits<3> { +struct OperandTraits<SelectInst> : public FixedNumOperandTraits<SelectInst, 3> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectInst, Value) @@ -1207,6 +1227,10 @@ public: setName(NameStr); } + Value *getPointerOperand() { return getOperand(0); } + const Value *getPointerOperand() const { return getOperand(0); } + static unsigned getPointerOperandIndex() { return 0U; } + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const VAArgInst *) { return true; } static inline bool classof(const Instruction *I) { @@ -1252,12 +1276,12 @@ public: Value *getIndexOperand() { return Op<1>(); } const Value *getVectorOperand() const { return Op<0>(); } const Value *getIndexOperand() const { return Op<1>(); } - + const VectorType *getVectorOperandType() const { return reinterpret_cast<const VectorType*>(getVectorOperand()->getType()); } - - + + /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -1272,7 +1296,8 @@ public: }; template <> -struct OperandTraits<ExtractElementInst> : public FixedNumOperandTraits<2> { +struct OperandTraits<ExtractElementInst> : + public FixedNumOperandTraits<ExtractElementInst, 2> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementInst, Value) @@ -1330,7 +1355,8 @@ public: }; template <> -struct OperandTraits<InsertElementInst> : public FixedNumOperandTraits<3> { +struct OperandTraits<InsertElementInst> : + public FixedNumOperandTraits<InsertElementInst, 3> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementInst, Value) @@ -1387,7 +1413,8 @@ public: }; template <> -struct OperandTraits<ShuffleVectorInst> : public FixedNumOperandTraits<3> { +struct OperandTraits<ShuffleVectorInst> : + public FixedNumOperandTraits<ShuffleVectorInst, 3> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorInst, Value) @@ -1407,8 +1434,9 @@ class ExtractValueInst : public UnaryInstruction { const Twine &NameStr); void init(unsigned Idx, const Twine &NameStr); - template<typename InputIterator> - void init(InputIterator IdxBegin, InputIterator IdxEnd, + template<typename RandomAccessIterator> + void init(RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, // This argument ensures that we have an iterator we can // do arithmetic on in constant time @@ -1429,16 +1457,15 @@ class ExtractValueInst : public UnaryInstruction { /// getIndexedType - Returns the type of the element that would be extracted /// with an extractvalue instruction with the specified parameters. /// - /// Null is returned if the indices are invalid for the specified - /// pointer type. + /// Null is returned if the indices are invalid for the specified type. /// static const Type *getIndexedType(const Type *Agg, const unsigned *Idx, unsigned NumIdx); - template<typename InputIterator> + template<typename RandomAccessIterator> static const Type *getIndexedType(const Type *Ptr, - InputIterator IdxBegin, - InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, // This argument ensures that we // have an iterator we can do // arithmetic on in constant time @@ -1456,14 +1483,16 @@ class ExtractValueInst : public UnaryInstruction { /// value and a list of indices. The first ctor can optionally insert before /// an existing instruction, the second appends the new instruction to the /// specified BasicBlock. - template<typename InputIterator> - inline ExtractValueInst(Value *Agg, InputIterator IdxBegin, - InputIterator IdxEnd, + template<typename RandomAccessIterator> + inline ExtractValueInst(Value *Agg, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, Instruction *InsertBefore); - template<typename InputIterator> + template<typename RandomAccessIterator> inline ExtractValueInst(Value *Agg, - InputIterator IdxBegin, InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, BasicBlock *InsertAtEnd); // allocate space for exactly one operand @@ -1474,17 +1503,19 @@ protected: virtual ExtractValueInst *clone_impl() const; public: - template<typename InputIterator> - static ExtractValueInst *Create(Value *Agg, InputIterator IdxBegin, - InputIterator IdxEnd, + template<typename RandomAccessIterator> + static ExtractValueInst *Create(Value *Agg, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr = "", Instruction *InsertBefore = 0) { return new ExtractValueInst(Agg, IdxBegin, IdxEnd, NameStr, InsertBefore); } - template<typename InputIterator> + template<typename RandomAccessIterator> static ExtractValueInst *Create(Value *Agg, - InputIterator IdxBegin, InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, BasicBlock *InsertAtEnd) { return new ExtractValueInst(Agg, IdxBegin, IdxEnd, NameStr, InsertAtEnd); @@ -1509,15 +1540,14 @@ public: /// getIndexedType - Returns the type of the element that would be extracted /// with an extractvalue instruction with the specified parameters. /// - /// Null is returned if the indices are invalid for the specified - /// pointer type. + /// Null is returned if the indices are invalid for the specified type. /// - template<typename InputIterator> + template<typename RandomAccessIterator> static const Type *getIndexedType(const Type *Ptr, - InputIterator IdxBegin, - InputIterator IdxEnd) { + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd) { return getIndexedType(Ptr, IdxBegin, IdxEnd, - typename std::iterator_traits<InputIterator>:: + typename std::iterator_traits<RandomAccessIterator>:: iterator_category()); } static const Type *getIndexedType(const Type *Ptr, unsigned Idx); @@ -1554,29 +1584,31 @@ public: } }; -template<typename InputIterator> +template<typename RandomAccessIterator> ExtractValueInst::ExtractValueInst(Value *Agg, - InputIterator IdxBegin, - InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, Instruction *InsertBefore) : UnaryInstruction(checkType(getIndexedType(Agg->getType(), IdxBegin, IdxEnd)), ExtractValue, Agg, InsertBefore) { init(IdxBegin, IdxEnd, NameStr, - typename std::iterator_traits<InputIterator>::iterator_category()); + typename std::iterator_traits<RandomAccessIterator> + ::iterator_category()); } -template<typename InputIterator> +template<typename RandomAccessIterator> ExtractValueInst::ExtractValueInst(Value *Agg, - InputIterator IdxBegin, - InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, BasicBlock *InsertAtEnd) : UnaryInstruction(checkType(getIndexedType(Agg->getType(), IdxBegin, IdxEnd)), ExtractValue, Agg, InsertAtEnd) { init(IdxBegin, IdxEnd, NameStr, - typename std::iterator_traits<InputIterator>::iterator_category()); + typename std::iterator_traits<RandomAccessIterator> + ::iterator_category()); } @@ -1596,9 +1628,9 @@ class InsertValueInst : public Instruction { const Twine &NameStr); void init(Value *Agg, Value *Val, unsigned Idx, const Twine &NameStr); - template<typename InputIterator> + template<typename RandomAccessIterator> void init(Value *Agg, Value *Val, - InputIterator IdxBegin, InputIterator IdxEnd, + RandomAccessIterator IdxBegin, RandomAccessIterator IdxEnd, const Twine &NameStr, // This argument ensures that we have an iterator we can // do arithmetic on in constant time @@ -1620,14 +1652,16 @@ class InsertValueInst : public Instruction { /// value, a value to insert, and a list of indices. The first ctor can /// optionally insert before an existing instruction, the second appends /// the new instruction to the specified BasicBlock. - template<typename InputIterator> - inline InsertValueInst(Value *Agg, Value *Val, InputIterator IdxBegin, - InputIterator IdxEnd, + template<typename RandomAccessIterator> + inline InsertValueInst(Value *Agg, Value *Val, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, Instruction *InsertBefore); - template<typename InputIterator> + template<typename RandomAccessIterator> inline InsertValueInst(Value *Agg, Value *Val, - InputIterator IdxBegin, InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, BasicBlock *InsertAtEnd); /// Constructors - These two constructors are convenience methods because one @@ -1645,17 +1679,19 @@ public: return User::operator new(s, 2); } - template<typename InputIterator> - static InsertValueInst *Create(Value *Agg, Value *Val, InputIterator IdxBegin, - InputIterator IdxEnd, + template<typename RandomAccessIterator> + static InsertValueInst *Create(Value *Agg, Value *Val, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr = "", Instruction *InsertBefore = 0) { return new InsertValueInst(Agg, Val, IdxBegin, IdxEnd, NameStr, InsertBefore); } - template<typename InputIterator> + template<typename RandomAccessIterator> static InsertValueInst *Create(Value *Agg, Value *Val, - InputIterator IdxBegin, InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, BasicBlock *InsertAtEnd) { return new InsertValueInst(Agg, Val, IdxBegin, IdxEnd, @@ -1722,34 +1758,37 @@ public: }; template <> -struct OperandTraits<InsertValueInst> : public FixedNumOperandTraits<2> { +struct OperandTraits<InsertValueInst> : + public FixedNumOperandTraits<InsertValueInst, 2> { }; -template<typename InputIterator> +template<typename RandomAccessIterator> InsertValueInst::InsertValueInst(Value *Agg, Value *Val, - InputIterator IdxBegin, - InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, Instruction *InsertBefore) : Instruction(Agg->getType(), InsertValue, OperandTraits<InsertValueInst>::op_begin(this), 2, InsertBefore) { init(Agg, Val, IdxBegin, IdxEnd, NameStr, - typename std::iterator_traits<InputIterator>::iterator_category()); + typename std::iterator_traits<RandomAccessIterator> + ::iterator_category()); } -template<typename InputIterator> +template<typename RandomAccessIterator> InsertValueInst::InsertValueInst(Value *Agg, Value *Val, - InputIterator IdxBegin, - InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &NameStr, BasicBlock *InsertAtEnd) : Instruction(Agg->getType(), InsertValue, OperandTraits<InsertValueInst>::op_begin(this), 2, InsertAtEnd) { init(Agg, Val, IdxBegin, IdxEnd, NameStr, - typename std::iterator_traits<InputIterator>::iterator_category()); + typename std::iterator_traits<RandomAccessIterator> + ::iterator_category()); } DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value) @@ -1835,7 +1874,7 @@ public: BasicBlock *getIncomingBlock(unsigned i) const { return cast<BasicBlock>(getOperand(i*2+1)); } - + /// getIncomingBlock - Return incoming basic block corresponding /// to an operand of the PHI. /// @@ -1843,7 +1882,7 @@ public: assert(this == U.getUser() && "Iterator doesn't point to PHI's Uses?"); return cast<BasicBlock>((&U + 1)->get()); } - + /// getIncomingBlock - Return incoming basic block corresponding /// to value use iterator. /// @@ -1851,8 +1890,8 @@ public: BasicBlock *getIncomingBlock(value_use_iterator<U> I) const { return getIncomingBlock(I.getUse()); } - - + + void setIncomingBlock(unsigned i, BasicBlock *BB) { setOperand(i*2+1, (Value*)BB); } @@ -1912,13 +1951,7 @@ public: /// hasConstantValue - If the specified PHI node always merges together the /// same value, return the value, otherwise return null. - /// - /// If the PHI has undef operands, but all the rest of the operands are - /// some unique value, return that value if it can be proved that the - /// value dominates the PHI. If DT is null, use a conservative check, - /// otherwise use DT to test for dominance. - /// - Value *hasConstantValue(DominatorTree *DT = 0) const; + Value *hasConstantValue() const; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const PHINode *) { return true; } @@ -1985,11 +2018,9 @@ public: /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - /// Convenience accessor - Value *getReturnValue(unsigned n = 0) const { - return n < getNumOperands() - ? getOperand(n) - : 0; + /// Convenience accessor. Returns null if there is no return value. + Value *getReturnValue() const { + return getNumOperands() != 0 ? getOperand(0) : 0; } unsigned getNumSuccessors() const { return 0; } @@ -2009,7 +2040,7 @@ public: }; template <> -struct OperandTraits<ReturnInst> : public VariadicOperandTraits<> { +struct OperandTraits<ReturnInst> : public VariadicOperandTraits<ReturnInst> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ReturnInst, Value) @@ -2045,22 +2076,20 @@ protected: virtual BranchInst *clone_impl() const; public: static BranchInst *Create(BasicBlock *IfTrue, Instruction *InsertBefore = 0) { - return new(1, true) BranchInst(IfTrue, InsertBefore); + return new(1) BranchInst(IfTrue, InsertBefore); } static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, Instruction *InsertBefore = 0) { return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertBefore); } static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *InsertAtEnd) { - return new(1, true) BranchInst(IfTrue, InsertAtEnd); + return new(1) BranchInst(IfTrue, InsertAtEnd); } static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, BasicBlock *InsertAtEnd) { return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertAtEnd); } - ~BranchInst(); - /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2077,19 +2106,6 @@ public: Op<-3>() = V; } - // setUnconditionalDest - Change the current branch to an unconditional branch - // targeting the specified block. - // FIXME: Eliminate this ugly method. - void setUnconditionalDest(BasicBlock *Dest) { - Op<-1>() = (Value*)Dest; - if (isConditional()) { // Convert this to an uncond branch. - Op<-2>() = 0; - Op<-3>() = 0; - NumOperands = 1; - OperandList = op_begin(); - } - } - unsigned getNumSuccessors() const { return 1+isConditional(); } BasicBlock *getSuccessor(unsigned i) const { @@ -2117,7 +2133,8 @@ private: }; template <> -struct OperandTraits<BranchInst> : public VariadicOperandTraits<1> {}; +struct OperandTraits<BranchInst> : public VariadicOperandTraits<BranchInst, 1> { +}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) @@ -2136,7 +2153,7 @@ class SwitchInst : public TerminatorInst { // Operand[2n ] = Value to match // Operand[2n+1] = BasicBlock to go to on match SwitchInst(const SwitchInst &SI); - void init(Value *Value, BasicBlock *Default, unsigned NumCases); + void init(Value *Value, BasicBlock *Default, unsigned NumReserved); void resizeOperands(unsigned No); // allocate space for exactly zero operands void *operator new(size_t s) { @@ -2230,7 +2247,8 @@ public: /// removeCase - This method removes the specified successor from the switch /// instruction. Note that this cannot be used to remove the default - /// destination (successor #0). + /// destination (successor #0). Also note that this operation may reorder the + /// remaining cases at index idx and above. /// void removeCase(unsigned idx); @@ -2298,7 +2316,7 @@ class IndirectBrInst : public TerminatorInst { /// here to make memory allocation more efficient. This constructor can also /// autoinsert before another instruction. IndirectBrInst(Value *Address, unsigned NumDests, Instruction *InsertBefore); - + /// IndirectBrInst ctor - Create a new indirectbr instruction, specifying an /// Address to jump to. The number of expected destinations can be specified /// here to make memory allocation more efficient. This constructor also @@ -2316,32 +2334,32 @@ public: return new IndirectBrInst(Address, NumDests, InsertAtEnd); } ~IndirectBrInst(); - + /// Provide fast operand accessors. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - + // Accessor Methods for IndirectBrInst instruction. Value *getAddress() { return getOperand(0); } const Value *getAddress() const { return getOperand(0); } void setAddress(Value *V) { setOperand(0, V); } - - + + /// getNumDestinations - return the number of possible destinations in this /// indirectbr instruction. unsigned getNumDestinations() const { return getNumOperands()-1; } - + /// getDestination - Return the specified destination. BasicBlock *getDestination(unsigned i) { return getSuccessor(i); } const BasicBlock *getDestination(unsigned i) const { return getSuccessor(i); } - + /// addDestination - Add a destination. /// void addDestination(BasicBlock *Dest); - + /// removeDestination - This method removes the specified successor from the /// indirectbr instruction. void removeDestination(unsigned i); - + unsigned getNumSuccessors() const { return getNumOperands()-1; } BasicBlock *getSuccessor(unsigned i) const { return cast<BasicBlock>(getOperand(i+1)); @@ -2349,7 +2367,7 @@ public: void setSuccessor(unsigned i, BasicBlock *NewSucc) { setOperand(i+1, (Value*)NewSucc); } - + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const IndirectBrInst *) { return true; } static inline bool classof(const Instruction *I) { @@ -2369,8 +2387,8 @@ struct OperandTraits<IndirectBrInst> : public HungoffOperandTraits<1> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value) - - + + //===----------------------------------------------------------------------===// // InvokeInst Class //===----------------------------------------------------------------------===// @@ -2384,9 +2402,9 @@ class InvokeInst : public TerminatorInst { void init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, Value* const *Args, unsigned NumArgs); - template<typename InputIterator> + template<typename RandomAccessIterator> void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - InputIterator ArgBegin, InputIterator ArgEnd, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, const Twine &NameStr, // This argument ensures that we have an iterator we can // do arithmetic on in constant time @@ -2399,47 +2417,49 @@ class InvokeInst : public TerminatorInst { } /// Construct an InvokeInst given a range of arguments. - /// InputIterator must be a random-access iterator pointing to + /// RandomAccessIterator must be a random-access iterator pointing to /// contiguous storage (e.g. a std::vector<>::iterator). Checks are /// made for random-accessness but not for contiguous storage as /// that would incur runtime overhead. /// /// @brief Construct an InvokeInst from a range of arguments - template<typename InputIterator> + template<typename RandomAccessIterator> inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - InputIterator ArgBegin, InputIterator ArgEnd, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, unsigned Values, const Twine &NameStr, Instruction *InsertBefore); /// Construct an InvokeInst given a range of arguments. - /// InputIterator must be a random-access iterator pointing to + /// RandomAccessIterator must be a random-access iterator pointing to /// contiguous storage (e.g. a std::vector<>::iterator). Checks are /// made for random-accessness but not for contiguous storage as /// that would incur runtime overhead. /// /// @brief Construct an InvokeInst from a range of arguments - template<typename InputIterator> + template<typename RandomAccessIterator> inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - InputIterator ArgBegin, InputIterator ArgEnd, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: virtual InvokeInst *clone_impl() const; public: - template<typename InputIterator> + template<typename RandomAccessIterator> static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - InputIterator ArgBegin, InputIterator ArgEnd, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, const Twine &NameStr = "", Instruction *InsertBefore = 0) { unsigned Values(ArgEnd - ArgBegin + 3); return new(Values) InvokeInst(Func, IfNormal, IfException, ArgBegin, ArgEnd, Values, NameStr, InsertBefore); } - template<typename InputIterator> + template<typename RandomAccessIterator> static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - InputIterator ArgBegin, InputIterator ArgEnd, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, const Twine &NameStr, BasicBlock *InsertAtEnd) { unsigned Values(ArgEnd - ArgBegin + 3); @@ -2606,13 +2626,14 @@ private: }; template <> -struct OperandTraits<InvokeInst> : public VariadicOperandTraits<3> { +struct OperandTraits<InvokeInst> : public VariadicOperandTraits<InvokeInst, 3> { }; -template<typename InputIterator> +template<typename RandomAccessIterator> InvokeInst::InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - InputIterator ArgBegin, InputIterator ArgEnd, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, unsigned Values, const Twine &NameStr, Instruction *InsertBefore) : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType()) @@ -2621,12 +2642,14 @@ InvokeInst::InvokeInst(Value *Func, OperandTraits<InvokeInst>::op_end(this) - Values, Values, InsertBefore) { init(Func, IfNormal, IfException, ArgBegin, ArgEnd, NameStr, - typename std::iterator_traits<InputIterator>::iterator_category()); + typename std::iterator_traits<RandomAccessIterator> + ::iterator_category()); } -template<typename InputIterator> +template<typename RandomAccessIterator> InvokeInst::InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - InputIterator ArgBegin, InputIterator ArgEnd, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd) : TerminatorInst(cast<FunctionType>(cast<PointerType>(Func->getType()) @@ -2635,7 +2658,8 @@ InvokeInst::InvokeInst(Value *Func, OperandTraits<InvokeInst>::op_end(this) - Values, Values, InsertAtEnd) { init(Func, IfNormal, IfException, ArgBegin, ArgEnd, NameStr, - typename std::iterator_traits<InputIterator>::iterator_category()); + typename std::iterator_traits<RandomAccessIterator> + ::iterator_category()); } DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InvokeInst, Value) diff --git a/contrib/llvm/include/llvm/IntrinsicInst.h b/contrib/llvm/include/llvm/IntrinsicInst.h index a17fa9c..74c30fb 100644 --- a/contrib/llvm/include/llvm/IntrinsicInst.h +++ b/contrib/llvm/include/llvm/IntrinsicInst.h @@ -55,7 +55,7 @@ namespace llvm { return isa<CallInst>(V) && classof(cast<CallInst>(V)); } }; - + /// DbgInfoIntrinsic - This is the common base class for debug info intrinsics /// class DbgInfoIntrinsic : public IntrinsicInst { @@ -139,6 +139,10 @@ namespace llvm { return !getVolatileCst()->isZero(); } + unsigned getAddressSpace() const { + return cast<PointerType>(getRawDest()->getType())->getAddressSpace(); + } + /// getDest - This is just like getRawDest, but it strips off any cast /// instructions that feed it, giving the original input. The returned /// value is guaranteed to be a pointer. @@ -297,29 +301,6 @@ namespace llvm { } }; - /// MemoryUseIntrinsic - This is the common base class for the memory use - /// marker intrinsics. - /// - class MemoryUseIntrinsic : public IntrinsicInst { - public: - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const MemoryUseIntrinsic *) { return true; } - static inline bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::lifetime_start: - case Intrinsic::lifetime_end: - case Intrinsic::invariant_start: - case Intrinsic::invariant_end: - return true; - default: return false; - } - } - static inline bool classof(const Value *V) { - return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); - } - }; - } #endif diff --git a/contrib/llvm/include/llvm/Intrinsics.td b/contrib/llvm/include/llvm/Intrinsics.td index fb4f750..0c9be78 100644 --- a/contrib/llvm/include/llvm/Intrinsics.td +++ b/contrib/llvm/include/llvm/Intrinsics.td @@ -109,6 +109,9 @@ def llvm_empty_ty : LLVMType<OtherVT>; // { } def llvm_descriptor_ty : LLVMPointerType<llvm_empty_ty>; // { }* def llvm_metadata_ty : LLVMType<MetadataVT>; // !{...} +def llvm_x86mmx_ty : LLVMType<x86mmx>; +def llvm_ptrx86mmx_ty : LLVMPointerType<llvm_x86mmx_ty>; // <1 x i64>* + def llvm_v2i8_ty : LLVMType<v2i8>; // 2 x i8 def llvm_v4i8_ty : LLVMType<v4i8>; // 4 x i8 def llvm_v8i8_ty : LLVMType<v8i8>; // 8 x i8 @@ -256,7 +259,7 @@ def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty]>; // Internal interface for object size checking def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_ptr_ty, llvm_i1_ty], - [IntrReadArgMem]>, + [IntrNoMem]>, GCCBuiltin<"__builtin_object_size">; //===-------------------- Bit Manipulation Intrinsics ---------------------===// @@ -304,6 +307,7 @@ let Properties = [IntrNoMem] in { def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty]>; def int_eh_sjlj_callsite: Intrinsic<[], [llvm_i32_ty]>; } +def int_eh_sjlj_dispatch_setup : Intrinsic<[], [llvm_ptr_ty]>; def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty]>; @@ -432,7 +436,7 @@ def int_lifetime_end : Intrinsic<[], [IntrReadWriteArgMem, NoCapture<1>]>; def int_invariant_start : Intrinsic<[llvm_descriptor_ty], [llvm_i64_ty, llvm_ptr_ty], - [IntrReadArgMem, NoCapture<1>]>; + [IntrReadWriteArgMem, NoCapture<1>]>; def int_invariant_end : Intrinsic<[], [llvm_descriptor_ty, llvm_i64_ty, llvm_ptr_ty], diff --git a/contrib/llvm/include/llvm/IntrinsicsARM.td b/contrib/llvm/include/llvm/IntrinsicsARM.td index 6c04771..546538a 100644 --- a/contrib/llvm/include/llvm/IntrinsicsARM.td +++ b/contrib/llvm/include/llvm/IntrinsicsARM.td @@ -286,6 +286,12 @@ def int_arm_neon_vcvtfp2fxu : Neon_CvtFPToFx_Intrinsic; def int_arm_neon_vcvtfxs2fp : Neon_CvtFxToFP_Intrinsic; def int_arm_neon_vcvtfxu2fp : Neon_CvtFxToFP_Intrinsic; +// Vector Conversions Between Half-Precision and Single-Precision. +def int_arm_neon_vcvtfp2hf + : Intrinsic<[llvm_v4i16_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_arm_neon_vcvthf2fp + : Intrinsic<[llvm_v4f32_ty], [llvm_v4i16_ty], [IntrNoMem]>; + // Narrowing Saturating Vector Moves. def int_arm_neon_vqmovns : Neon_1Arg_Narrow_Intrinsic; def int_arm_neon_vqmovnu : Neon_1Arg_Narrow_Intrinsic; diff --git a/contrib/llvm/include/llvm/IntrinsicsX86.td b/contrib/llvm/include/llvm/IntrinsicsX86.td index 06ea3ae..4946220 100644 --- a/contrib/llvm/include/llvm/IntrinsicsX86.td +++ b/contrib/llvm/include/llvm/IntrinsicsX86.td @@ -130,12 +130,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i64_ty], [IntrNoMem]>; def int_x86_sse_cvtps2pi : GCCBuiltin<"__builtin_ia32_cvtps2pi">, - Intrinsic<[llvm_v2i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_v4f32_ty], [IntrNoMem]>; def int_x86_sse_cvttps2pi: GCCBuiltin<"__builtin_ia32_cvttps2pi">, - Intrinsic<[llvm_v2i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_v4f32_ty], [IntrNoMem]>; def int_x86_sse_cvtpi2ps : GCCBuiltin<"__builtin_ia32_cvtpi2ps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v2i32_ty], [IntrNoMem]>; + llvm_x86mmx_ty], [IntrNoMem]>; } // SIMD load ops @@ -445,11 +445,11 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v4f32_ty], [IntrNoMem]>; def int_x86_sse_cvtpd2pi : GCCBuiltin<"__builtin_ia32_cvtpd2pi">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_v2f64_ty], [IntrNoMem]>; def int_x86_sse_cvttpd2pi: GCCBuiltin<"__builtin_ia32_cvttpd2pi">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_v2f64_ty], [IntrNoMem]>; def int_x86_sse_cvtpi2pd : GCCBuiltin<"__builtin_ia32_cvtpi2pd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2f64_ty], [llvm_x86mmx_ty], [IntrNoMem]>; } // SIMD load ops @@ -563,50 +563,50 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Horizontal arithmetic ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_ssse3_phadd_w : GCCBuiltin<"__builtin_ia32_phaddw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_phadd_w_128 : GCCBuiltin<"__builtin_ia32_phaddw128">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; def int_x86_ssse3_phadd_d : GCCBuiltin<"__builtin_ia32_phaddd">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, - llvm_v2i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_phadd_d_128 : GCCBuiltin<"__builtin_ia32_phaddd128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; def int_x86_ssse3_phadd_sw : GCCBuiltin<"__builtin_ia32_phaddsw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_phadd_sw_128 : GCCBuiltin<"__builtin_ia32_phaddsw128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; def int_x86_ssse3_phsub_w : GCCBuiltin<"__builtin_ia32_phsubw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_phsub_w_128 : GCCBuiltin<"__builtin_ia32_phsubw128">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; def int_x86_ssse3_phsub_d : GCCBuiltin<"__builtin_ia32_phsubd">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, - llvm_v2i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_phsub_d_128 : GCCBuiltin<"__builtin_ia32_phsubd128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; def int_x86_ssse3_phsub_sw : GCCBuiltin<"__builtin_ia32_phsubsw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_phsub_sw_128 : GCCBuiltin<"__builtin_ia32_phsubsw128">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; def int_x86_ssse3_pmadd_ub_sw : GCCBuiltin<"__builtin_ia32_pmaddubsw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_pmadd_ub_sw_128 : GCCBuiltin<"__builtin_ia32_pmaddubsw128">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; @@ -615,8 +615,8 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Packed multiply high with round and scale let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_ssse3_pmul_hr_sw : GCCBuiltin<"__builtin_ia32_pmulhrsw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; def int_x86_ssse3_pmul_hr_sw_128 : GCCBuiltin<"__builtin_ia32_pmulhrsw128">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem, Commutative]>; @@ -625,35 +625,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Shuffle ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_ssse3_pshuf_b : GCCBuiltin<"__builtin_ia32_pshufb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_pshuf_b_128 : GCCBuiltin<"__builtin_ia32_pshufb128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_ssse3_pshuf_w : GCCBuiltin<"__builtin_ia32_pshufw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, llvm_i32_ty], + def int_x86_sse_pshuf_w : GCCBuiltin<"__builtin_ia32_pshufw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i8_ty], [IntrNoMem]>; } // Sign ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_ssse3_psign_b : GCCBuiltin<"__builtin_ia32_psignb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_psign_b_128 : GCCBuiltin<"__builtin_ia32_psignb128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; def int_x86_ssse3_psign_w : GCCBuiltin<"__builtin_ia32_psignw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_psign_w_128 : GCCBuiltin<"__builtin_ia32_psignw128">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; def int_x86_ssse3_psign_d : GCCBuiltin<"__builtin_ia32_psignd">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, - llvm_v2i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_psign_d_128 : GCCBuiltin<"__builtin_ia32_psignd128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; @@ -662,17 +662,17 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Absolute value ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_ssse3_pabs_b : GCCBuiltin<"__builtin_ia32_pabsb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_pabs_b_128 : GCCBuiltin<"__builtin_ia32_pabsb128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; def int_x86_ssse3_pabs_w : GCCBuiltin<"__builtin_ia32_pabsw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_pabs_w_128 : GCCBuiltin<"__builtin_ia32_pabsw128">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; def int_x86_ssse3_pabs_d : GCCBuiltin<"__builtin_ia32_pabsd">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_ssse3_pabs_d_128 : GCCBuiltin<"__builtin_ia32_pabsd128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; } @@ -1328,281 +1328,257 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Addition def int_x86_mmx_padd_b : GCCBuiltin<"__builtin_ia32_paddb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, llvm_v8i8_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_padd_w : GCCBuiltin<"__builtin_ia32_paddw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, llvm_v4i16_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_padd_d : GCCBuiltin<"__builtin_ia32_paddd">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, llvm_v2i32_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_padd_q : GCCBuiltin<"__builtin_ia32_paddq">, - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_padds_b : GCCBuiltin<"__builtin_ia32_paddsb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_padds_w : GCCBuiltin<"__builtin_ia32_paddsw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_paddus_b : GCCBuiltin<"__builtin_ia32_paddusb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_paddus_w : GCCBuiltin<"__builtin_ia32_paddusw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; // Subtraction def int_x86_mmx_psub_b : GCCBuiltin<"__builtin_ia32_psubb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, llvm_v8i8_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psub_w : GCCBuiltin<"__builtin_ia32_psubw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, llvm_v4i16_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psub_d : GCCBuiltin<"__builtin_ia32_psubd">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, llvm_v2i32_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psub_q : GCCBuiltin<"__builtin_ia32_psubq">, - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psubs_b : GCCBuiltin<"__builtin_ia32_psubsb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psubs_w : GCCBuiltin<"__builtin_ia32_psubsw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psubus_b : GCCBuiltin<"__builtin_ia32_psubusb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psubus_w : GCCBuiltin<"__builtin_ia32_psubusw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; // Multiplication def int_x86_mmx_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_pmull_w : GCCBuiltin<"__builtin_ia32_pmullw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, - llvm_v2i32_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd">, - Intrinsic<[llvm_v2i32_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; // Bitwise operations def int_x86_mmx_pand : GCCBuiltin<"__builtin_ia32_pand">, - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_pandn : GCCBuiltin<"__builtin_ia32_pandn">, - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_por : GCCBuiltin<"__builtin_ia32_por">, - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_pxor : GCCBuiltin<"__builtin_ia32_pxor">, - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; // Averages def int_x86_mmx_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; // Maximum def int_x86_mmx_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; // Minimum def int_x86_mmx_pminu_b : GCCBuiltin<"__builtin_ia32_pminub">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; // Packed sum of absolute differences def int_x86_mmx_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem, Commutative]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; } // Integer shift ops. let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Shift left logical def int_x86_mmx_psll_w : GCCBuiltin<"__builtin_ia32_psllw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v1i64_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psll_d : GCCBuiltin<"__builtin_ia32_pslld">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, - llvm_v1i64_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psll_q : GCCBuiltin<"__builtin_ia32_psllq">, - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, - llvm_v1i64_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psrl_w : GCCBuiltin<"__builtin_ia32_psrlw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v1i64_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psrl_d : GCCBuiltin<"__builtin_ia32_psrld">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, - llvm_v1i64_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq">, - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, - llvm_v1i64_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psra_w : GCCBuiltin<"__builtin_ia32_psraw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v1i64_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_psra_d : GCCBuiltin<"__builtin_ia32_psrad">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, - llvm_v1i64_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_mmx_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_mmx_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi">, - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_mmx_psrli_w : GCCBuiltin<"__builtin_ia32_psrlwi">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_mmx_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_mmx_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi">, - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_mmx_psrai_w : GCCBuiltin<"__builtin_ia32_psrawi">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_mmx_psrai_d : GCCBuiltin<"__builtin_ia32_psradi">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i32_ty], [IntrNoMem]>; } // Pack ops. let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_mmx_packsswb : GCCBuiltin<"__builtin_ia32_packsswb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_packssdw : GCCBuiltin<"__builtin_ia32_packssdw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v2i32_ty, - llvm_v2i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_packuswb : GCCBuiltin<"__builtin_ia32_packuswb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; } // Unpacking ops. let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_mmx_punpckhbw : GCCBuiltin<"__builtin_ia32_punpckhbw">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, llvm_v8i8_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_punpckhwd : GCCBuiltin<"__builtin_ia32_punpckhwd">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, llvm_v4i16_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_punpckhdq : GCCBuiltin<"__builtin_ia32_punpckhdq">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, llvm_v2i32_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_punpcklbw : GCCBuiltin<"__builtin_ia32_punpcklbw">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, llvm_v8i8_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_punpcklwd : GCCBuiltin<"__builtin_ia32_punpcklwd">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, llvm_v4i16_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_punpckldq : GCCBuiltin<"__builtin_ia32_punpckldq">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, llvm_v2i32_ty], + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; } // Integer comparison ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_mmx_pcmpeq_b : GCCBuiltin<"__builtin_ia32_pcmpeqb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_pcmpeq_w : GCCBuiltin<"__builtin_ia32_pcmpeqw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_pcmpeq_d : GCCBuiltin<"__builtin_ia32_pcmpeqd">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, - llvm_v2i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_pcmpgt_b : GCCBuiltin<"__builtin_ia32_pcmpgtb">, - Intrinsic<[llvm_v8i8_ty], [llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_pcmpgt_w : GCCBuiltin<"__builtin_ia32_pcmpgtw">, - Intrinsic<[llvm_v4i16_ty], [llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_pcmpgt_d : GCCBuiltin<"__builtin_ia32_pcmpgtd">, - Intrinsic<[llvm_v2i32_ty], [llvm_v2i32_ty, - llvm_v2i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; } // Misc. let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_mmx_maskmovq : GCCBuiltin<"__builtin_ia32_maskmovq">, - Intrinsic<[], [llvm_v8i8_ty, llvm_v8i8_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_x86mmx_ty, llvm_x86mmx_ty, llvm_ptr_ty], []>; def int_x86_mmx_pmovmskb : GCCBuiltin<"__builtin_ia32_pmovmskb">, - Intrinsic<[llvm_i32_ty], [llvm_v8i8_ty], [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], [llvm_x86mmx_ty], [IntrNoMem]>; def int_x86_mmx_movnt_dq : GCCBuiltin<"__builtin_ia32_movntq">, - Intrinsic<[], [llvm_ptr_ty, llvm_v1i64_ty], []>; + Intrinsic<[], [llvm_ptrx86mmx_ty, llvm_x86mmx_ty], []>; -// def int_x86_mmx_palignr_b : GCCBuiltin<"__builtin_ia32_palignr">, -// Intrinsic<[llvm_v1i64_ty], [llvm_1i64_ty, -// llvm_v1i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_mmx_palignr_b : GCCBuiltin<"__builtin_ia32_palignr">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_mmx_pextr_w : - Intrinsic<[llvm_i32_ty], [llvm_v1i64_ty, llvm_i32_ty], + def int_x86_mmx_pextr_w : GCCBuiltin<"__builtin_ia32_vec_ext_v4hi">, + Intrinsic<[llvm_i32_ty], [llvm_x86mmx_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_mmx_pinsr_w : - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, + def int_x86_mmx_pinsr_w : GCCBuiltin<"__builtin_ia32_vec_set_v4hi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - - def int_x86_mmx_cvtsi32_si64 : - Intrinsic<[llvm_v1i64_ty], [llvm_i32_ty], [IntrNoMem]>; - def int_x86_mmx_cvtsi64_si32 : - Intrinsic<[llvm_i32_ty], [llvm_v1i64_ty], [IntrNoMem]>; - - def int_x86_mmx_vec_init_b : GCCBuiltin<"__builtin_ia32_vec_init_v8qi">, - Intrinsic<[llvm_v8i8_ty], - [llvm_i8_ty, llvm_i8_ty, llvm_i8_ty, llvm_i8_ty, - llvm_i8_ty, llvm_i8_ty, llvm_i8_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_mmx_vec_init_w : GCCBuiltin<"__builtin_ia32_vec_init_v4hi">, - Intrinsic<[llvm_v4i16_ty], - [llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_mmx_vec_init_d : GCCBuiltin<"__builtin_ia32_vec_init_v2si">, - Intrinsic<[llvm_v2i32_ty], - [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - - def int_x86_mmx_vec_ext_d : GCCBuiltin<"__builtin_ia32_vec_ext_v2si">, - Intrinsic<[llvm_v2i32_ty], - [llvm_v2i32_ty, llvm_i32_ty], - [IntrNoMem]>; } diff --git a/contrib/llvm/include/llvm/IntrinsicsXCore.td b/contrib/llvm/include/llvm/IntrinsicsXCore.td index a86cda2..97bac1d 100644 --- a/contrib/llvm/include/llvm/IntrinsicsXCore.td +++ b/contrib/llvm/include/llvm/IntrinsicsXCore.td @@ -11,4 +11,26 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". def int_xcore_bitrev : Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem]>; def int_xcore_getid : Intrinsic<[llvm_i32_ty],[],[IntrNoMem]>; + + // Resource instructions. + def int_xcore_getr : Intrinsic<[llvm_anyptr_ty],[llvm_i32_ty]>; + def int_xcore_freer : Intrinsic<[],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_in : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty],[NoCapture<0>]>; + def int_xcore_int : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_inct : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_out : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_outt : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_outct : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_chkct : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setd : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setc : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; } diff --git a/contrib/llvm/include/llvm/LLVMContext.h b/contrib/llvm/include/llvm/LLVMContext.h index 7cb6579..3502ff7 100644 --- a/contrib/llvm/include/llvm/LLVMContext.h +++ b/contrib/llvm/include/llvm/LLVMContext.h @@ -20,6 +20,8 @@ namespace llvm { class LLVMContextImpl; class StringRef; class Instruction; +class Module; +class SMDiagnostic; template <typename T> class SmallVectorImpl; /// This is an important class for using LLVM in a threaded context. It @@ -28,10 +30,6 @@ template <typename T> class SmallVectorImpl; /// LLVMContext itself provides no locking guarantees, so you should be careful /// to have one context per thread. class LLVMContext { - // DO NOT IMPLEMENT - LLVMContext(LLVMContext&); - void operator=(LLVMContext&); - public: LLVMContextImpl *const pImpl; LLVMContext(); @@ -40,7 +38,8 @@ public: // Pinned metadata names, which always have the same value. This is a // compile-time performance optimization, not a correctness optimization. enum { - MD_dbg = 0 // "dbg" + MD_dbg = 0, // "dbg" + MD_tbaa = 1 // "tbaa" }; /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. @@ -51,18 +50,23 @@ public: /// custom metadata IDs registered in this LLVMContext. void getMDKindNames(SmallVectorImpl<StringRef> &Result) const; + + typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context, + unsigned LocCookie); + /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked /// when problems with inline asm are detected by the backend. The first - /// argument is a function pointer (of type SourceMgr::DiagHandlerTy) and the - /// second is a context pointer that gets passed into the DiagHandler. + /// argument is a function pointer and the second is a context pointer that + /// gets passed into the DiagHandler. /// - /// LLVMContext doesn't take ownership or interpreter either of these + /// LLVMContext doesn't take ownership or interpret either of these /// pointers. - void setInlineAsmDiagnosticHandler(void *DiagHandler, void *DiagContext = 0); + void setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, + void *DiagContext = 0); /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by /// setInlineAsmDiagnosticHandler. - void *getInlineAsmDiagnosticHandler() const; + InlineAsmDiagHandlerTy getInlineAsmDiagnosticHandler() const; /// getInlineAsmDiagnosticContext - Return the diagnostic context set by /// setInlineAsmDiagnosticHandler. @@ -77,6 +81,21 @@ public: void emitError(unsigned LocCookie, StringRef ErrorStr); void emitError(const Instruction *I, StringRef ErrorStr); void emitError(StringRef ErrorStr); + +private: + // DO NOT IMPLEMENT + LLVMContext(LLVMContext&); + void operator=(LLVMContext&); + + /// addModule - Register a module as being instantiated in this context. If + /// the context is deleted, the module will be deleted as well. + void addModule(Module*); + + /// removeModule - Unregister a module from this context. + void removeModule(Module*); + + // Module needs access to the add/removeModule methods. + friend class Module; }; /// getGlobalContext - Returns a global context. This is for LLVM clients that diff --git a/contrib/llvm/include/llvm/LinkAllPasses.h b/contrib/llvm/include/llvm/LinkAllPasses.h index 35dab62..69e1bd9 100644 --- a/contrib/llvm/include/llvm/LinkAllPasses.h +++ b/contrib/llvm/include/llvm/LinkAllPasses.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This header file pulls in all transformation and analysis passes for tools +// This header file pulls in all transformation and analysis passes for tools // like opt and bugpoint that need this functionality. // //===----------------------------------------------------------------------===// @@ -20,8 +20,8 @@ #include "llvm/Analysis/FindUsedTypes.h" #include "llvm/Analysis/IntervalPartition.h" #include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/PointerTracking.h" #include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/RegionPass.h" #include "llvm/Analysis/RegionPrinter.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/Lint.h" @@ -70,6 +70,7 @@ namespace { (void) llvm::createDomViewerPass(); (void) llvm::createEdgeProfilerPass(); (void) llvm::createOptimalEdgeProfilerPass(); + (void) llvm::createPathProfilerPass(); (void) llvm::createFunctionInliningPass(); (void) llvm::createAlwaysInlinerPass(); (void) llvm::createGlobalDCEPass(); @@ -90,8 +91,8 @@ namespace { (void) llvm::createLoopStrengthReducePass(); (void) llvm::createLoopUnrollPass(); (void) llvm::createLoopUnswitchPass(); + (void) llvm::createLoopIdiomPass(); (void) llvm::createLoopRotatePass(); - (void) llvm::createLoopIndexSplitPass(); (void) llvm::createLowerInvokePass(); (void) llvm::createLowerSetJmpPass(); (void) llvm::createLowerSwitchPass(); @@ -99,7 +100,9 @@ namespace { (void) llvm::createNoProfileInfoPass(); (void) llvm::createProfileEstimatorPass(); (void) llvm::createProfileVerifierPass(); + (void) llvm::createPathProfileVerifierPass(); (void) llvm::createProfileLoaderPass(); + (void) llvm::createPathProfileLoaderPass(); (void) llvm::createPromoteMemoryToRegisterPass(); (void) llvm::createDemoteRegisterToMemoryPass(); (void) llvm::createPruneEHPass(); @@ -128,13 +131,13 @@ namespace { (void) llvm::createUnifyFunctionExitNodesPass(); (void) llvm::createInstCountPass(); (void) llvm::createCodeGenPreparePass(); + (void) llvm::createEarlyCSEPass(); (void) llvm::createGVNPass(); (void) llvm::createMemCpyOptPass(); (void) llvm::createLoopDeletionPass(); (void) llvm::createPostDomTree(); (void) llvm::createPostDomFrontier(); (void) llvm::createInstructionNamerPass(); - (void) llvm::createPartialSpecializationPass(); (void) llvm::createFunctionAttrsPass(); (void) llvm::createMergeFunctionsPass(); (void) llvm::createPrintModulePass(0); @@ -147,14 +150,17 @@ namespace { (void) llvm::createSinkingPass(); (void) llvm::createLowerAtomicPass(); (void) llvm::createCorrelatedValuePropagationPass(); + (void) llvm::createMemDepPrinter(); + (void) llvm::createInstructionSimplifierPass(); (void)new llvm::IntervalPartition(); (void)new llvm::FindUsedTypes(); (void)new llvm::ScalarEvolution(); - (void)new llvm::PointerTracking(); ((llvm::Function*)0)->viewCFGOnly(); + llvm::RGPassManager RGM(0); + ((llvm::RegionPass*)0)->runOnRegion((llvm::Region*)0, RGM); llvm::AliasSetTracker X(*(llvm::AliasAnalysis*)0); - X.add((llvm::Value*)0, 0); // for -print-alias-sets + X.add((llvm::Value*)0, 0, 0); // for -print-alias-sets } } ForcePassLinking; // Force link by creating a global definition. } diff --git a/contrib/llvm/include/llvm/LinkAllVMCore.h b/contrib/llvm/include/llvm/LinkAllVMCore.h index 6959cb6..83684c0 100644 --- a/contrib/llvm/include/llvm/LinkAllVMCore.h +++ b/contrib/llvm/include/llvm/LinkAllVMCore.h @@ -22,15 +22,14 @@ #include "llvm/IntrinsicInst.h" #include "llvm/InlineAsm.h" #include "llvm/Analysis/Verifier.h" -#include "llvm/System/Alarm.h" -#include "llvm/System/DynamicLibrary.h" -#include "llvm/System/Memory.h" -#include "llvm/System/Mutex.h" -#include "llvm/System/Path.h" -#include "llvm/System/Process.h" -#include "llvm/System/Program.h" -#include "llvm/System/Signals.h" -#include "llvm/System/TimeValue.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Memory.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/TimeValue.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/MathExtras.h" #include <cstdlib> diff --git a/contrib/llvm/include/llvm/MC/EDInstInfo.h b/contrib/llvm/include/llvm/MC/EDInstInfo.h index dded255..83d9e78 100644 --- a/contrib/llvm/include/llvm/MC/EDInstInfo.h +++ b/contrib/llvm/include/llvm/MC/EDInstInfo.h @@ -9,7 +9,7 @@ #ifndef EDINSTINFO_H #define EDINSTINFO_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/contrib/llvm/include/llvm/MC/ELFObjectWriter.h b/contrib/llvm/include/llvm/MC/ELFObjectWriter.h deleted file mode 100644 index 3b9951f..0000000 --- a/contrib/llvm/include/llvm/MC/ELFObjectWriter.h +++ /dev/null @@ -1,46 +0,0 @@ -//===-- llvm/MC/ELFObjectWriter.h - ELF File Writer ---------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_ELFOBJECTWRITER_H -#define LLVM_MC_ELFOBJECTWRITER_H - -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> - -namespace llvm { -class MCAsmFixup; -class MCAssembler; -class MCFragment; -class MCValue; -class raw_ostream; - -class ELFObjectWriter : public MCObjectWriter { - void *Impl; - -public: - ELFObjectWriter(raw_ostream &OS, bool Is64Bit, bool IsLittleEndian = true, - bool HasRelocationAddend = true); - - virtual ~ELFObjectWriter(); - - virtual void ExecutePostLayoutBinding(MCAssembler &Asm); - - virtual void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - uint64_t &FixedValue); - - virtual void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout); -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/MC/MCAsmInfo.h b/contrib/llvm/include/llvm/MC/MCAsmInfo.h index 43952e0..9cfd004 100644 --- a/contrib/llvm/include/llvm/MC/MCAsmInfo.h +++ b/contrib/llvm/include/llvm/MC/MCAsmInfo.h @@ -22,10 +22,12 @@ namespace llvm { class MCSection; class MCContext; - + /// MCAsmInfo - This class is intended to be used as a base class for asm /// properties and features specific to the target. - namespace ExceptionHandling { enum ExceptionsType { None, Dwarf, SjLj }; } + namespace ExceptionHandling { + enum ExceptionsType { None, DwarfTable, DwarfCFI, SjLj }; + } class MCAsmInfo { protected: @@ -36,25 +38,30 @@ namespace llvm { /// HasSubsectionsViaSymbols - True if this target has the MachO /// .subsections_via_symbols directive. bool HasSubsectionsViaSymbols; // Default is false. - + /// HasMachoZeroFillDirective - True if this is a MachO target that supports /// the macho-specific .zerofill directive for emitting BSS Symbols. bool HasMachoZeroFillDirective; // Default is false. - + /// HasMachoTBSSDirective - True if this is a MachO target that supports /// the macho-specific .tbss directive for emitting thread local BSS Symbols bool HasMachoTBSSDirective; // Default is false. - + /// HasStaticCtorDtorReferenceInStaticMode - True if the compiler should /// emit a ".reference .constructors_used" or ".reference .destructors_used" /// directive after the a static ctor/dtor list. This directive is only /// emitted in Static relocation model. bool HasStaticCtorDtorReferenceInStaticMode; // Default is false. - + + /// LinkerRequiresNonEmptyDwarfLines - True if the linker has a bug and + /// requires that the debug_line section be of a minimum size. In practice + /// such a linker requires a non empty line sequence if a file is present. + bool LinkerRequiresNonEmptyDwarfLines; // Default to false. + /// MaxInstLength - This is the maximum possible length of an instruction, /// which is needed to compute the size of an inline asm. unsigned MaxInstLength; // Defaults to 4. - + /// PCSymbol - The symbol used to represent the current PC. Used in PC /// relative expressions. const char *PCSymbol; // Defaults to "$". @@ -72,6 +79,9 @@ namespace llvm { /// assembler. const char *CommentString; // Defaults to "#" + /// LabelSuffix - This is appended to emitted labels. + const char *LabelSuffix; // Defaults to ":" + /// GlobalPrefix - If this is set to a non-empty string, it is prepended /// onto all global symbols. This is often used for "_" or ".". const char *GlobalPrefix; // Defaults to "" @@ -80,12 +90,12 @@ namespace llvm { /// pool entries that are completely private to the .s file and should not /// have names in the .o file. This is often "." or "L". const char *PrivateGlobalPrefix; // Defaults to "." - + /// LinkerPrivateGlobalPrefix - This prefix is used for symbols that should /// be passed through the assembler but be removed by the linker. This /// is "l" on Darwin, currently used for some ObjC metadata. const char *LinkerPrivateGlobalPrefix; // Defaults to "" - + /// InlineAsmStart/End - If these are nonempty, they contain a directive to /// emit before and after an inline assembly statement. const char *InlineAsmStart; // Defaults to "#APP\n" @@ -117,7 +127,7 @@ namespace llvm { /// AsciiDirective - This directive allows emission of an ascii string with /// the standard C escape characters embedded into it. const char *AsciiDirective; // Defaults to "\t.ascii\t" - + /// AscizDirective - If not null, this allows for special handling of /// zero terminated strings on this target. This is commonly supported as /// ".asciz". If a target doesn't support this, it can be set to null. @@ -135,7 +145,7 @@ namespace llvm { /// which should be relocated as a 32-bit GP-relative offset, e.g. .gpword /// on Mips or .gprel32 on Alpha. const char *GPRel32Directive; // Defaults to NULL. - + /// getDataASDirective - Return the directive that should be used to emit /// data of the specified size to the specified numeric address space. virtual const char *getDataASDirective(unsigned Size, unsigned AS) const { @@ -149,15 +159,15 @@ namespace llvm { bool SunStyleELFSectionSwitchSyntax; // Defaults to false. /// UsesELFSectionDirectiveForBSS - This is true if this target uses ELF - /// '.section' directive before the '.bss' one. It's used for PPC/Linux + /// '.section' directive before the '.bss' one. It's used for PPC/Linux /// which doesn't support the '.bss' directive only. bool UsesELFSectionDirectiveForBSS; // Defaults to false. - + /// HasMicrosoftFastStdCallMangling - True if this target uses microsoft /// style mangling for functions with X86_StdCall/X86_FastCall calling /// convention. bool HasMicrosoftFastStdCallMangling; // Defaults to false. - + //===--- Alignment Information ----------------------------------------===// /// AlignDirective - The directive used to emit round up to an alignment @@ -176,27 +186,34 @@ namespace llvm { unsigned TextAlignFillValue; // Defaults to 0 //===--- Global Variable Emission Directives --------------------------===// - + /// GlobalDirective - This is the directive used to declare a global entity. /// const char *GlobalDirective; // Defaults to NULL. - /// ExternDirective - This is the directive used to declare external + /// ExternDirective - This is the directive used to declare external /// globals. /// const char *ExternDirective; // Defaults to NULL. - + /// HasSetDirective - True if the assembler supports the .set directive. bool HasSetDirective; // Defaults to true. - + + /// HasAggressiveSymbolFolding - False if the assembler requires that we use + /// Lc = a - b + /// .long Lc + /// instead of + /// .long a - b + bool HasAggressiveSymbolFolding; // Defaults to true. + /// HasLCOMMDirective - This is true if the target supports the .lcomm /// directive. bool HasLCOMMDirective; // Defaults to false. - + /// COMMDirectiveAlignmentIsInBytes - True is COMMDirective's optional /// alignment is to be specified in bytes instead of log2(n). bool COMMDirectiveAlignmentIsInBytes; // Defaults to true; - + /// HasDotTypeDotSizeDirective - True if the target has .type and .size /// directives, this is true for most ELF targets. bool HasDotTypeDotSizeDirective; // Defaults to true. @@ -209,10 +226,14 @@ namespace llvm { /// directive. bool HasNoDeadStrip; // Defaults to false. + /// HasSymbolResolver - True if this target supports the MachO + /// .symbol_resolver directive. + bool HasSymbolResolver; // Defaults to false. + /// WeakRefDirective - This directive, if non-null, is used to declare a /// global as being a weak undefined symbol. const char *WeakRefDirective; // Defaults to NULL. - + /// WeakDefDirective - This directive, if non-null, is used to declare a /// global as being a weak defined symbol. const char *WeakDefDirective; // Defaults to NULL. @@ -220,7 +241,7 @@ namespace llvm { /// LinkOnceDirective - This directive, if non-null is used to declare a /// global as being a weak defined symbol. This is used on cygwin/mingw. const char *LinkOnceDirective; // Defaults to NULL. - + /// HiddenVisibilityAttr - This attribute, if not MCSA_Invalid, is used to /// declare a symbol as having hidden visibility. MCSymbolAttr HiddenVisibilityAttr; // Defaults to MCSA_Hidden. @@ -234,10 +255,6 @@ namespace llvm { /// HasLEB128 - True if target asm supports leb128 directives. bool HasLEB128; // Defaults to false. - /// hasDotLocAndDotFile - True if target asm supports .loc and .file - /// directives for emitting debugging information. - bool HasDotLocAndDotFile; // Defaults to false. - /// SupportsDebugInformation - True if target supports emission of debugging /// information. bool SupportsDebugInformation; // Defaults to false. @@ -254,8 +271,8 @@ namespace llvm { /// DwarfSectionOffsetDirective - Special section offset directive. const char* DwarfSectionOffsetDirective; // Defaults to NULL - - /// DwarfUsesAbsoluteLabelForStmtList - True if DW_AT_stmt_list needs + + /// DwarfUsesAbsoluteLabelForStmtList - True if DW_AT_stmt_list needs /// absolute label instead of offset. bool DwarfUsesAbsoluteLabelForStmtList; // Defaults to true; @@ -276,7 +293,7 @@ namespace llvm { static unsigned getULEB128Size(unsigned Value); bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } - + // Data directive accessors. // const char *getData8bitsDirective(unsigned AS = 0) const { @@ -299,11 +316,11 @@ namespace llvm { virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const{ return 0; } - + bool usesSunStyleELFSectionSwitchSyntax() const { return SunStyleELFSectionSwitchSyntax; } - + bool usesELFSectionDirectiveForBSS() const { return UsesELFSectionDirectiveForBSS; } @@ -311,7 +328,7 @@ namespace llvm { bool hasMicrosoftFastStdCallMangling() const { return HasMicrosoftFastStdCallMangling; } - + // Accessors. // bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; } @@ -319,6 +336,9 @@ namespace llvm { bool hasStaticCtorDtorReferenceInStaticMode() const { return HasStaticCtorDtorReferenceInStaticMode; } + bool getLinkerRequiresNonEmptyDwarfLines() const { + return LinkerRequiresNonEmptyDwarfLines; + } unsigned getMaxInstLength() const { return MaxInstLength; } @@ -334,6 +354,9 @@ namespace llvm { const char *getCommentString() const { return CommentString; } + const char *getLabelSuffix() const { + return LabelSuffix; + } const char *getGlobalPrefix() const { return GlobalPrefix; } @@ -386,6 +409,9 @@ namespace llvm { return ExternDirective; } bool hasSetDirective() const { return HasSetDirective; } + bool hasAggressiveSymbolFolding() const { + return HasAggressiveSymbolFolding; + } bool hasLCOMMDirective() const { return HasLCOMMDirective; } bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} bool getCOMMDirectiveAlignmentIsInBytes() const { @@ -393,10 +419,11 @@ namespace llvm { } bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } bool hasNoDeadStrip() const { return HasNoDeadStrip; } + bool hasSymbolResolver() const { return HasSymbolResolver; } const char *getWeakRefDirective() const { return WeakRefDirective; } const char *getWeakDefDirective() const { return WeakDefDirective; } const char *getLinkOnceDirective() const { return LinkOnceDirective; } - + MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr;} MCSymbolAttr getProtectedVisibilityAttr() const { return ProtectedVisibilityAttr; @@ -404,9 +431,6 @@ namespace llvm { bool hasLEB128() const { return HasLEB128; } - bool hasDotLocAndDotFile() const { - return HasDotLocAndDotFile; - } bool doesSupportDebugInformation() const { return SupportsDebugInformation; } @@ -416,6 +440,12 @@ namespace llvm { ExceptionHandling::ExceptionsType getExceptionHandlingType() const { return ExceptionsType; } + bool isExceptionHandlingDwarf() const { + return + (ExceptionsType == ExceptionHandling::DwarfTable || + ExceptionsType == ExceptionHandling::DwarfCFI); + } + bool doesDwarfRequireFrameSection() const { return DwarfRequiresFrameSection; } diff --git a/contrib/llvm/include/llvm/MC/MCAsmLayout.h b/contrib/llvm/include/llvm/MC/MCAsmLayout.h index b9565ba..01cb000 100644 --- a/contrib/llvm/include/llvm/MC/MCAsmLayout.h +++ b/contrib/llvm/include/llvm/MC/MCAsmLayout.h @@ -39,13 +39,12 @@ private: /// The last fragment which was layed out, or 0 if nothing has been layed /// out. Fragments are always layed out in order, so all fragments with a /// lower ordinal will be up to date. - mutable MCFragment *LastValidFragment; + mutable DenseMap<const MCSectionData*, MCFragment *> LastValidFragment; /// \brief Make sure that the layout for the given fragment is valid, lazily /// computing it if necessary. void EnsureValid(const MCFragment *F) const; - bool isSectionUpToDate(const MCSectionData *SD) const; bool isFragmentUpToDate(const MCFragment *F) const; public: @@ -54,27 +53,15 @@ public: /// Get the assembler object this is a layout for. MCAssembler &getAssembler() const { return Assembler; } - /// \brief Update the layout because a fragment has been resized. The - /// fragments size should have already been updated, the \arg SlideAmount is - /// the delta from the old size. - void UpdateForSlide(MCFragment *F, int SlideAmount); - - /// \brief Update the layout because a fragment has been replaced. - void FragmentReplaced(MCFragment *Src, MCFragment *Dst); - - /// \brief Perform a full layout. - void LayoutFile(); + /// \brief Invalidate all following fragments because a fragment has been + /// resized. The fragments size should have already been updated. + void Invalidate(MCFragment *F); /// \brief Perform layout for a single fragment, assuming that the previous /// fragment has already been layed out correctly, and the parent section has /// been initialized. void LayoutFragment(MCFragment *Fragment); - /// \brief Performs initial layout for a single section, assuming that the - /// previous section (including its fragments) has already been layed out - /// correctly. - void LayoutSection(MCSectionData *SD); - /// @name Section Access (in layout order) /// @{ @@ -89,28 +76,13 @@ public: /// @name Fragment Layout Data /// @{ - /// \brief Get the effective size of the given fragment, as computed in the - /// current layout. - uint64_t getFragmentEffectiveSize(const MCFragment *F) const; - /// \brief Get the offset of the given fragment inside its containing section. uint64_t getFragmentOffset(const MCFragment *F) const; /// @} - /// @name Section Layout Data - /// @{ - - /// \brief Get the computed address of the given section. - uint64_t getSectionAddress(const MCSectionData *SD) const; - - /// @} /// @name Utility Functions /// @{ - /// \brief Get the address of the given fragment, as computed in the current - /// layout. - uint64_t getFragmentAddress(const MCFragment *F) const; - /// \brief Get the address space size of the given section, as it effects /// layout. This may differ from the size reported by \see getSectionSize() by /// not including section tail padding. @@ -120,12 +92,9 @@ public: /// file. This may include additional padding, or be 0 for virtual sections. uint64_t getSectionFileSize(const MCSectionData *SD) const; - /// \brief Get the logical data size of the given section. - uint64_t getSectionSize(const MCSectionData *SD) const; - - /// \brief Get the address of the given symbol, as computed in the current + /// \brief Get the offset of the given symbol, as computed in the current /// layout. - uint64_t getSymbolAddress(const MCSymbolData *SD) const; + uint64_t getSymbolOffset(const MCSymbolData *SD) const; /// @} }; diff --git a/contrib/llvm/include/llvm/MC/MCAssembler.h b/contrib/llvm/include/llvm/MC/MCAssembler.h index d193b98..30971c6 100644 --- a/contrib/llvm/include/llvm/MC/MCAssembler.h +++ b/contrib/llvm/include/llvm/MC/MCAssembler.h @@ -11,13 +11,14 @@ #define LLVM_MC_MCASSEMBLER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" #include "llvm/Support/Casting.h" #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCInst.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <vector> // FIXME: Shouldn't be needed. namespace llvm { @@ -49,7 +50,10 @@ public: FT_Data, FT_Fill, FT_Inst, - FT_Org + FT_Org, + FT_Dwarf, + FT_DwarfFrame, + FT_LEB }; private: @@ -72,12 +76,7 @@ private: /// initialized. uint64_t Offset; - /// EffectiveSize - The compute size of this section. This is ~0 until - /// initialized. - uint64_t EffectiveSize; - - /// LayoutOrder - The global layout order of this fragment. This is the index - /// across all fragments in the file, not just within the section. + /// LayoutOrder - The layout order of this fragment. unsigned LayoutOrder; /// @} @@ -234,19 +233,12 @@ class MCAlignFragment : public MCFragment { /// target dependent. bool EmitNops : 1; - /// OnlyAlignAddress - Flag to indicate that this align is only used to adjust - /// the address space size of a section and that it should not be included as - /// part of the section size. This flag can only be used on the last fragment - /// in a section. - bool OnlyAlignAddress : 1; - public: MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, unsigned _MaxBytesToEmit, MCSectionData *SD = 0) : MCFragment(FT_Align, SD), Alignment(_Alignment), Value(_Value),ValueSize(_ValueSize), - MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false), - OnlyAlignAddress(false) {} + MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {} /// @name Accessors /// @{ @@ -262,9 +254,6 @@ public: bool hasEmitNops() const { return EmitNops; } void setEmitNops(bool Value) { EmitNops = Value; } - bool hasOnlyAlignAddress() const { return OnlyAlignAddress; } - void setOnlyAlignAddress(bool Value) { OnlyAlignAddress = Value; } - /// @} static bool classof(const MCFragment *F) { @@ -337,6 +326,100 @@ public: static bool classof(const MCOrgFragment *) { return true; } }; +class MCLEBFragment : public MCFragment { + /// Value - The value this fragment should contain. + const MCExpr *Value; + + /// IsSigned - True if this is a sleb128, false if uleb128. + bool IsSigned; + + SmallString<8> Contents; +public: + MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSectionData *SD) + : MCFragment(FT_LEB, SD), + Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); } + + /// @name Accessors + /// @{ + + const MCExpr &getValue() const { return *Value; } + + bool isSigned() const { return IsSigned; } + + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_LEB; + } + static bool classof(const MCLEBFragment *) { return true; } +}; + +class MCDwarfLineAddrFragment : public MCFragment { + /// LineDelta - the value of the difference between the two line numbers + /// between two .loc dwarf directives. + int64_t LineDelta; + + /// AddrDelta - The expression for the difference of the two symbols that + /// make up the address delta between two .loc dwarf directives. + const MCExpr *AddrDelta; + + SmallString<8> Contents; + +public: + MCDwarfLineAddrFragment(int64_t _LineDelta, const MCExpr &_AddrDelta, + MCSectionData *SD) + : MCFragment(FT_Dwarf, SD), + LineDelta(_LineDelta), AddrDelta(&_AddrDelta) { Contents.push_back(0); } + + /// @name Accessors + /// @{ + + int64_t getLineDelta() const { return LineDelta; } + + const MCExpr &getAddrDelta() const { return *AddrDelta; } + + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Dwarf; + } + static bool classof(const MCDwarfLineAddrFragment *) { return true; } +}; + +class MCDwarfCallFrameFragment : public MCFragment { + /// AddrDelta - The expression for the difference of the two symbols that + /// make up the address delta between two .cfi_* dwarf directives. + const MCExpr *AddrDelta; + + SmallString<8> Contents; + +public: + MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, MCSectionData *SD) + : MCFragment(FT_DwarfFrame, SD), + AddrDelta(&_AddrDelta) { Contents.push_back(0); } + + /// @name Accessors + /// @{ + + const MCExpr &getAddrDelta() const { return *AddrDelta; } + + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_DwarfFrame; + } + static bool classof(const MCDwarfCallFrameFragment *) { return true; } +}; + // FIXME: Should this be a separate class, or just merged into MCSection? Since // we anticipate the fast path being through an MCAssembler, the only reason to // keep it out is for API abstraction. @@ -373,10 +456,6 @@ private: // // FIXME: This could all be kept private to the assembler implementation. - /// Address - The computed address of this section. This is ~0 until - /// initialized. - uint64_t Address; - /// HasInstructions - Whether this section has had instructions emitted into /// it. unsigned HasInstructions : 1; @@ -585,6 +664,8 @@ private: MCCodeEmitter &Emitter; + MCObjectWriter &Writer; + raw_ostream &OS; iplist<MCSectionData> Sections; @@ -603,7 +684,17 @@ private: std::vector<IndirectSymbolData> IndirectSymbols; + /// The set of function symbols for which a .thumb_func directive has + /// been seen. + // + // FIXME: We really would like this in target specific code rather than + // here. Maybe when the relocation stuff moves to target specific, + // this can go with it? The streamer would need some target specific + // refactoring too. + SmallPtrSet<const MCSymbol*, 64> ThumbFuncs; + unsigned RelaxAll : 1; + unsigned NoExecStack : 1; unsigned SubsectionsViaSymbols : 1; private: @@ -633,24 +724,34 @@ private: bool FragmentNeedsRelaxation(const MCInstFragment *IF, const MCAsmLayout &Layout) const; - /// Compute the effective fragment size assuming it is layed out at the given - /// \arg SectionAddress and \arg FragmentOffset. - uint64_t ComputeFragmentSize(MCAsmLayout &Layout, const MCFragment &F, - uint64_t SectionAddress, - uint64_t FragmentOffset) const; - /// LayoutOnce - Perform one layout iteration and return true if any offsets /// were adjusted. bool LayoutOnce(MCAsmLayout &Layout); + bool LayoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD); + + bool RelaxInstruction(MCAsmLayout &Layout, MCInstFragment &IF); + + bool RelaxLEB(MCAsmLayout &Layout, MCLEBFragment &IF); + + bool RelaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF); + bool RelaxDwarfCallFrameFragment(MCAsmLayout &Layout, + MCDwarfCallFrameFragment &DF); + /// FinishLayout - Finalize a layout, including fragment lowering. void FinishLayout(MCAsmLayout &Layout); + uint64_t HandleFixup(const MCAsmLayout &Layout, + MCFragment &F, const MCFixup &Fixup); + public: + /// Compute the effective fragment size assuming it is layed out at the given + /// \arg SectionAddress and \arg FragmentOffset. + uint64_t ComputeFragmentSize(const MCAsmLayout &Layout, const MCFragment &F) const; + /// Find the symbol which defines the atom containing the given symbol, or /// null if there is no such symbol. - const MCSymbolData *getAtom(const MCAsmLayout &Layout, - const MCSymbolData *Symbol) const; + const MCSymbolData *getAtom(const MCSymbolData *Symbol) const; /// Check whether a particular symbol is visible to the linker and is required /// in the symbol table, or whether it can be discarded by the assembler. This @@ -659,12 +760,16 @@ public: bool isSymbolLinkerVisible(const MCSymbol &SD) const; /// Emit the section contents using the given object writer. - // - // FIXME: Should MCAssembler always have a reference to the object writer? - void WriteSectionData(const MCSectionData *Section, const MCAsmLayout &Layout, - MCObjectWriter *OW) const; + void WriteSectionData(const MCSectionData *Section, + const MCAsmLayout &Layout) const; - void AddSectionToTheEnd(MCSectionData &SD, MCAsmLayout &Layout); + /// Check whether a given symbol has been flagged with .thumb_func. + bool isThumbFunc(const MCSymbol *Func) const { + return ThumbFuncs.count(Func); + } + + /// Flag a function symbol as the target of a .thumb_func directive. + void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); } public: /// Construct a new assembler instance. @@ -675,8 +780,9 @@ public: // concrete and require clients to pass in a target like object. The other // option is to make this abstract, and have targets provide concrete // implementations as we do with AsmParser. - MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, - MCCodeEmitter &_Emitter, raw_ostream &OS); + MCAssembler(MCContext &Context_, TargetAsmBackend &Backend_, + MCCodeEmitter &Emitter_, MCObjectWriter &Writer_, + raw_ostream &OS); ~MCAssembler(); MCContext &getContext() const { return Context; } @@ -685,10 +791,12 @@ public: MCCodeEmitter &getEmitter() const { return Emitter; } + MCObjectWriter &getWriter() const { return Writer; } + /// Finish - Do final processing and write the object to the output stream. /// \arg Writer is used for custom object writer (as the MCJIT does), /// if not specified it is automatically created from backend. - void Finish(MCObjectWriter *Writer = 0); + void Finish(); // FIXME: This does not belong here. bool getSubsectionsViaSymbols() const { @@ -701,6 +809,9 @@ public: bool getRelaxAll() const { return RelaxAll; } void setRelaxAll(bool Value) { RelaxAll = Value; } + bool getNoExecStack() const { return NoExecStack; } + void setNoExecStack(bool Value) { NoExecStack = Value; } + /// @name Section List Access /// @{ diff --git a/contrib/llvm/include/llvm/MC/MCCodeEmitter.h b/contrib/llvm/include/llvm/MC/MCCodeEmitter.h index 010a2e5..bc63241 100644 --- a/contrib/llvm/include/llvm/MC/MCCodeEmitter.h +++ b/contrib/llvm/include/llvm/MC/MCCodeEmitter.h @@ -20,33 +20,6 @@ class MCInst; class raw_ostream; template<typename T> class SmallVectorImpl; -/// MCFixupKindInfo - Target independent information on a fixup kind. -struct MCFixupKindInfo { - enum FixupKindFlags { - /// Is this fixup kind PCrelative. This is used by the assembler backend to - /// evaluate fixup values in a target independent manner when possible. - FKF_IsPCRel = (1 << 0) - }; - - /// A target specific name for the fixup kind. The names will be unique for - /// distinct kinds on any given target. - const char *Name; - - /// The bit offset to write the relocation into. - // - // FIXME: These two fields are under-specified and not general enough, but it - // is covers many things, and is enough to let the AsmStreamer pretty-print - // the encoding. - unsigned TargetOffset; - - /// The number of bits written by this fixup. The bits are assumed to be - /// contiguous. - unsigned TargetSize; - - /// Flags describing additional information on this fixup kind. - unsigned Flags; -}; - /// MCCodeEmitter - Generic instruction encoding interface. class MCCodeEmitter { private: @@ -58,17 +31,6 @@ protected: // Can only create subclasses. public: virtual ~MCCodeEmitter(); - /// @name Target Independent Fixup Information - /// @{ - - /// getNumFixupKinds - Get the number of target specific fixup kinds. - virtual unsigned getNumFixupKinds() const = 0; - - /// getFixupKindInfo - Get information on a fixup kind. - virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const; - - /// @} - /// EncodeInstruction - Encode the given \arg Inst to bytes on the output /// stream \arg OS. virtual void EncodeInstruction(const MCInst &Inst, raw_ostream &OS, diff --git a/contrib/llvm/include/llvm/MC/MCContext.h b/contrib/llvm/include/llvm/MC/MCContext.h index d22868c..7b26d54 100644 --- a/contrib/llvm/include/llvm/MC/MCContext.h +++ b/contrib/llvm/include/llvm/MC/MCContext.h @@ -29,7 +29,9 @@ namespace llvm { class MCLineSection; class StringRef; class Twine; + class TargetAsmInfo; class MCSectionMachO; + class MCSectionELF; /// MCContext - Context object for machine code objects. This class owns all /// of the sections that it creates. @@ -41,9 +43,15 @@ namespace llvm { /// The MCAsmInfo for this target. const MCAsmInfo &MAI; + const TargetAsmInfo *TAI; + /// Symbols - Bindings of names to symbols. StringMap<MCSymbol*> Symbols; + /// UsedNames - Keeps tracks of names that were used both for used declared + /// and artificial symbols. + StringMap<bool> UsedNames; + /// NextUniqueID - The next ID to dole out to an unnamed assembler temporary /// symbol. unsigned NextUniqueID; @@ -56,8 +64,8 @@ namespace llvm { /// GetInstance() gets the current instance of the directional local label /// for the LocalLabelVal and adds it to the map if needed. unsigned GetInstance(int64_t LocalLabelVal); - - /// The file name of the log file from the enviromment variable + + /// The file name of the log file from the environment variable /// AS_SECURE_LOG_FILE. Which must be set before the .secure_log_unique /// directive is used or it is an error. char *SecureLogFile; @@ -79,29 +87,37 @@ namespace llvm { /// The dwarf line information from the .loc directives for the sections /// with assembled machine instructions have after seeing .loc directives. DenseMap<const MCSection *, MCLineSection *> MCLineSections; + /// We need a deterministic iteration order, so we remember the order + /// the elements were added. + std::vector<const MCSection *> MCLineSectionOrder; /// Allocator - Allocator object used for creating machine code objects. /// /// We use a bump pointer allocator to avoid the need to track all allocated /// objects. BumpPtrAllocator Allocator; - + void *MachOUniquingMap, *ELFUniquingMap, *COFFUniquingMap; + + MCSymbol *CreateSymbol(StringRef Name); + public: - explicit MCContext(const MCAsmInfo &MAI); + explicit MCContext(const MCAsmInfo &MAI, const TargetAsmInfo *TAI); ~MCContext(); - + const MCAsmInfo &getAsmInfo() const { return MAI; } - /// @name Symbol Managment + const TargetAsmInfo &getTargetAsmInfo() const { return *TAI; } + + /// @name Symbol Management /// @{ - + /// CreateTempSymbol - Create and return a new assembler temporary symbol /// with a unique but unspecified name. MCSymbol *CreateTempSymbol(); - /// CreateDirectionalLocalSymbol - Create the defintion of a directional - /// local symbol for numbered label (used for "1:" defintions). + /// CreateDirectionalLocalSymbol - Create the definition of a directional + /// local symbol for numbered label (used for "1:" definitions). MCSymbol *CreateDirectionalLocalSymbol(int64_t LocalLabelVal); /// GetDirectionalLocalSymbol - Create and return a directional local @@ -120,8 +136,8 @@ namespace llvm { MCSymbol *LookupSymbol(StringRef Name) const; /// @} - - /// @name Section Managment + + /// @name Section Management /// @{ /// getMachOSection - Return the MCSection for the specified mach-o section. @@ -137,11 +153,15 @@ namespace llvm { SectionKind K) { return getMachOSection(Segment, Section, TypeAndAttributes, 0, K); } - - const MCSection *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind, - bool IsExplicit = false, - unsigned EntrySize = 0); + + const MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, SectionKind Kind); + + const MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, SectionKind Kind, + unsigned EntrySize, StringRef Group); + + const MCSectionELF *CreateELFGroupSection(); const MCSection *getCOFFSection(StringRef Section, unsigned Characteristics, int Selection, SectionKind Kind); @@ -151,16 +171,20 @@ namespace llvm { return getCOFFSection (Section, Characteristics, 0, Kind); } - + /// @} - /// @name Dwarf Managment + /// @name Dwarf Management /// @{ /// GetDwarfFile - creates an entry in the dwarf file and directory tables. unsigned GetDwarfFile(StringRef FileName, unsigned FileNumber); - bool ValidateDwarfFileNumber(unsigned FileNumber); + bool isValidDwarfFileNumber(unsigned FileNumber); + + bool hasDwarfFiles() const { + return !MCDwarfFiles.empty(); + } const std::vector<MCDwarfFile *> &getMCDwarfFiles() { return MCDwarfFiles; @@ -168,23 +192,35 @@ namespace llvm { const std::vector<StringRef> &getMCDwarfDirs() { return MCDwarfDirs; } - DenseMap<const MCSection *, MCLineSection *> &getMCLineSections() { + + const DenseMap<const MCSection *, MCLineSection *> + &getMCLineSections() const { return MCLineSections; } + const std::vector<const MCSection *> &getMCLineSectionOrder() const { + return MCLineSectionOrder; + } + void addMCLineSection(const MCSection *Sec, MCLineSection *Line) { + MCLineSections[Sec] = Line; + MCLineSectionOrder.push_back(Sec); + } /// setCurrentDwarfLoc - saves the information from the currently parsed - /// dwarf .loc directive and sets DwarfLocSeen. When the next instruction /// is assembled an entry in the line number table with this information and + /// dwarf .loc directive and sets DwarfLocSeen. When the next instruction + /// is assembled an entry in the line number table with this information and /// the address of the instruction will be created. void setCurrentDwarfLoc(unsigned FileNum, unsigned Line, unsigned Column, - unsigned Flags, unsigned Isa) { + unsigned Flags, unsigned Isa, + unsigned Discriminator) { CurrentDwarfLoc.setFileNum(FileNum); CurrentDwarfLoc.setLine(Line); CurrentDwarfLoc.setColumn(Column); CurrentDwarfLoc.setFlags(Flags); CurrentDwarfLoc.setIsa(Isa); + CurrentDwarfLoc.setDiscriminator(Discriminator); DwarfLocSeen = true; } - void clearDwarfLocSeen() { DwarfLocSeen = false; } + void ClearDwarfLocSeen() { DwarfLocSeen = false; } bool getDwarfLocSeen() { return DwarfLocSeen; } const MCDwarfLoc &getCurrentDwarfLoc() { return CurrentDwarfLoc; } diff --git a/contrib/llvm/include/llvm/MC/MCDirectives.h b/contrib/llvm/include/llvm/MC/MCDirectives.h index 223b09e..1df55dc 100644 --- a/contrib/llvm/include/llvm/MC/MCDirectives.h +++ b/contrib/llvm/include/llvm/MC/MCDirectives.h @@ -26,6 +26,7 @@ enum MCSymbolAttr { MCSA_ELF_TypeTLS, ///< .type _foo, STT_TLS # aka @tls_object MCSA_ELF_TypeCommon, ///< .type _foo, STT_COMMON # aka @common MCSA_ELF_TypeNoType, ///< .type _foo, STT_NOTYPE # aka @notype + MCSA_ELF_TypeGnuUniqueObject, /// .type _foo, @gnu_unique_object MCSA_Global, ///< .globl MCSA_Hidden, ///< .hidden (ELF) MCSA_IndirectSymbol, ///< .indirect_symbol (MachO) @@ -33,6 +34,7 @@ enum MCSymbolAttr { MCSA_LazyReference, ///< .lazy_reference (MachO) MCSA_Local, ///< .local (ELF) MCSA_NoDeadStrip, ///< .no_dead_strip (MachO) + MCSA_SymbolResolver, ///< .symbol_resolver (MachO) MCSA_PrivateExtern, ///< .private_extern (MachO) MCSA_Protected, ///< .protected (ELF) MCSA_Reference, ///< .reference (MachO) @@ -43,9 +45,12 @@ enum MCSymbolAttr { }; enum MCAssemblerFlag { - MCAF_SubsectionsViaSymbols ///< .subsections_via_symbols (MachO) + MCAF_SyntaxUnified, ///< .syntax (ARM/ELF) + MCAF_SubsectionsViaSymbols, ///< .subsections_via_symbols (MachO) + MCAF_Code16, ///< .code 16 + MCAF_Code32 ///< .code 32 }; - + } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/MC/MCDisassembler.h b/contrib/llvm/include/llvm/MC/MCDisassembler.h index dfb8ed5..c9e42eb 100644 --- a/contrib/llvm/include/llvm/MC/MCDisassembler.h +++ b/contrib/llvm/include/llvm/MC/MCDisassembler.h @@ -9,7 +9,7 @@ #ifndef MCDISASSEMBLER_H #define MCDISASSEMBLER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/contrib/llvm/include/llvm/MC/MCDwarf.h b/contrib/llvm/include/llvm/MC/MCDwarf.h index dac875c..07a7bad 100644 --- a/contrib/llvm/include/llvm/MC/MCDwarf.h +++ b/contrib/llvm/include/llvm/MC/MCDwarf.h @@ -8,8 +8,7 @@ //===----------------------------------------------------------------------===// // // This file contains the declaration of the MCDwarfFile to support the dwarf -// .file directive. -// TODO: add the support needed for the .loc directive. +// .file directive and the .loc directive. // //===----------------------------------------------------------------------===// @@ -17,12 +16,21 @@ #define LLVM_MC_MCDWARF_H #include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/MachineLocation.h" // FIXME +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Dwarf.h" #include <vector> namespace llvm { + class MachineMove; class MCContext; + class MCExpr; class MCSection; + class MCSectionData; + class MCStreamer; class MCSymbol; + class MCObjectStreamer; class raw_ostream; /// MCDwarfFile - Instances of this class represent the name of the dwarf @@ -78,6 +86,11 @@ namespace llvm { unsigned Flags; // Isa unsigned Isa; + // Discriminator + unsigned Discriminator; + +// Flag that indicates the initial value of the is_stmt_start flag. +#define DWARF2_LINE_DEFAULT_IS_STMT 1 #define DWARF2_FLAG_IS_STMT (1 << 0) #define DWARF2_FLAG_BASIC_BLOCK (1 << 1) @@ -88,13 +101,32 @@ namespace llvm { friend class MCContext; friend class MCLineEntry; MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, - unsigned isa) - : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa) {} + unsigned isa, unsigned discriminator) + : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa), + Discriminator(discriminator) {} // Allow the default copy constructor and assignment operator to be used // for an MCDwarfLoc object. public: + /// getFileNum - Get the FileNum of this MCDwarfLoc. + unsigned getFileNum() const { return FileNum; } + + /// getLine - Get the Line of this MCDwarfLoc. + unsigned getLine() const { return Line; } + + /// getColumn - Get the Column of this MCDwarfLoc. + unsigned getColumn() const { return Column; } + + /// getFlags - Get the Flags of this MCDwarfLoc. + unsigned getFlags() const { return Flags; } + + /// getIsa - Get the Isa of this MCDwarfLoc. + unsigned getIsa() const { return Isa; } + + /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. + unsigned getDiscriminator() const { return Discriminator; } + /// setFileNum - Set the FileNum of this MCDwarfLoc. void setFileNum(unsigned fileNum) { FileNum = fileNum; } @@ -109,6 +141,11 @@ namespace llvm { /// setIsa - Set the Isa of this MCDwarfLoc. void setIsa(unsigned isa) { Isa = isa; } + + /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. + void setDiscriminator(unsigned discriminator) { + Discriminator = discriminator; + } }; /// MCLineEntry - Instances of this class represent the line information for @@ -127,6 +164,13 @@ namespace llvm { // Constructor to create an MCLineEntry given a symbol and the dwarf loc. MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) : MCDwarfLoc(loc), Label(label) {} + + MCSymbol *getLabel() const { return Label; } + + // This is called when an instruction is assembled into the specified + // section and if there is information from the last .loc directive that + // has yet to have a line entry made for it is made. + static void Make(MCStreamer *MCOS, const MCSection *Section); }; /// MCLineSection - Instances of this class represent the line information @@ -134,7 +178,6 @@ namespace llvm { /// .loc directives. This is the information used to build the dwarf line /// table for a section. class MCLineSection { - std::vector<MCLineEntry> MCLineEntries; private: MCLineSection(const MCLineSection&); // DO NOT IMPLEMENT @@ -149,8 +192,88 @@ namespace llvm { void addLineEntry(const MCLineEntry &LineEntry) { MCLineEntries.push_back(LineEntry); } + + typedef std::vector<MCLineEntry> MCLineEntryCollection; + typedef MCLineEntryCollection::iterator iterator; + typedef MCLineEntryCollection::const_iterator const_iterator; + + private: + MCLineEntryCollection MCLineEntries; + + public: + const MCLineEntryCollection *getMCLineEntries() const { + return &MCLineEntries; + } }; + class MCDwarfFileTable { + public: + // + // This emits the Dwarf file and the line tables. + // + static void Emit(MCStreamer *MCOS); + }; + + class MCDwarfLineAddr { + public: + /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. + static void Encode(int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS); + + /// Utility function to emit the encoding to a streamer. + static void Emit(MCStreamer *MCOS, + int64_t LineDelta,uint64_t AddrDelta); + + /// Utility function to write the encoding to an object writer. + static void Write(MCObjectWriter *OW, + int64_t LineDelta, uint64_t AddrDelta); + }; + + class MCCFIInstruction { + public: + enum OpType { Remember, Restore, Move }; + private: + OpType Operation; + MCSymbol *Label; + // Move to & from location. + MachineLocation Destination; + MachineLocation Source; + public: + MCCFIInstruction(OpType Op, MCSymbol *L) + : Operation(Op), Label(L) { + assert(Op == Remember || Op == Restore); + } + MCCFIInstruction(MCSymbol *L, const MachineLocation &D, + const MachineLocation &S) + : Operation(Move), Label(L), Destination(D), Source(S) { + } + OpType getOperation() const { return Operation; } + MCSymbol *getLabel() const { return Label; } + const MachineLocation &getDestination() const { return Destination; } + const MachineLocation &getSource() const { return Source; } + }; + + struct MCDwarfFrameInfo { + MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), + Instructions(), PersonalityEncoding(0), + LsdaEncoding(0) {} + MCSymbol *Begin; + MCSymbol *End; + const MCSymbol *Personality; + const MCSymbol *Lsda; + std::vector<MCCFIInstruction> Instructions; + unsigned PersonalityEncoding; + unsigned LsdaEncoding; + }; + + class MCDwarfFrameEmitter { + public: + // + // This emits the frame info section. + // + static void Emit(MCStreamer &streamer); + static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); + static void EncodeAdvanceLoc(uint64_t AddrDelta, raw_ostream &OS); + }; } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h b/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h new file mode 100644 index 0000000..3c150dc --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h @@ -0,0 +1,47 @@ +//===-- llvm/MC/MCELFObjectWriter.h - ELF Object Writer ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCELFOBJECTWRITER_H +#define LLVM_MC_MCELFOBJECTWRITER_H + +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { +class MCELFObjectTargetWriter { + const Triple::OSType OSType; + const uint16_t EMachine; + const unsigned HasRelocationAddend : 1; + const unsigned Is64Bit : 1; +protected: + MCELFObjectTargetWriter(bool Is64Bit_, Triple::OSType OSType_, + uint16_t EMachine_, bool HasRelocationAddend_); + +public: + virtual ~MCELFObjectTargetWriter(); + + /// @name Accessors + /// @{ + Triple::OSType getOSType() { return OSType; } + uint16_t getEMachine() { return EMachine; } + bool hasRelocationAddend() { return HasRelocationAddend; } + bool is64Bit() { return Is64Bit; } + /// @} +}; + +/// \brief Construct a new ELF writer instance. +/// +/// \param MOTW - The target specific ELF writer subclass. +/// \param OS - The stream to write to. +/// \returns The constructed object writer. +MCObjectWriter *createELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &OS, bool IsLittleEndian); +} // End llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/MC/MCELFSymbolFlags.h b/contrib/llvm/include/llvm/MC/MCELFSymbolFlags.h index eb7978b..d798fb0 100644 --- a/contrib/llvm/include/llvm/MC/MCELFSymbolFlags.h +++ b/contrib/llvm/include/llvm/MC/MCELFSymbolFlags.h @@ -21,9 +21,10 @@ namespace llvm { enum { - ELF_STT_Shift = 0, // Shift value for STT_* flags. - ELF_STB_Shift = 4, // Shift value for STB_* flags. - ELF_STV_Shift = 8 // Shift value ofr STV_* flags. + ELF_STT_Shift = 0, // Shift value for STT_* flags. + ELF_STB_Shift = 4, // Shift value for STB_* flags. + ELF_STV_Shift = 8, // Shift value for STV_* flags. + ELF_Other_Shift = 10 // Shift value for other flags. }; enum SymbolFlags { @@ -46,7 +47,9 @@ namespace llvm { ELF_STV_Default = (ELF::STV_DEFAULT << ELF_STV_Shift), ELF_STV_Internal = (ELF::STV_INTERNAL << ELF_STV_Shift), ELF_STV_Hidden = (ELF::STV_HIDDEN << ELF_STV_Shift), - ELF_STV_Protected = (ELF::STV_PROTECTED << ELF_STV_Shift) + ELF_STV_Protected = (ELF::STV_PROTECTED << ELF_STV_Shift), + + ELF_Other_Weakref = (1 << ELF_Other_Shift) }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCExpr.h b/contrib/llvm/include/llvm/MC/MCExpr.h index 1f9b8f2..fea5249 100644 --- a/contrib/llvm/include/llvm/MC/MCExpr.h +++ b/contrib/llvm/include/llvm/MC/MCExpr.h @@ -10,17 +10,21 @@ #ifndef LLVM_MC_MCEXPR_H #define LLVM_MC_MCEXPR_H +#include "llvm/ADT/DenseMap.h" #include "llvm/Support/Casting.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class MCAsmInfo; class MCAsmLayout; +class MCAssembler; class MCContext; +class MCSectionData; class MCSymbol; class MCValue; class raw_ostream; class StringRef; +typedef DenseMap<const MCSectionData*, uint64_t> SectionAddrMap; /// MCExpr - Base class for the full range of assembler expressions which are /// needed for parsing. @@ -40,9 +44,16 @@ private: MCExpr(const MCExpr&); // DO NOT IMPLEMENT void operator=(const MCExpr&); // DO NOT IMPLEMENT + bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs) const; protected: explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {} + bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, + bool InSet) const; public: /// @name Accessors /// @{ @@ -67,7 +78,11 @@ public: /// values. If not given, then only non-symbolic expressions will be /// evaluated. /// @result - True on success. - bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout = 0) const; + bool EvaluateAsAbsolute(int64_t &Res) const; + bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; + bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; + bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout, + const SectionAddrMap &Addrs) const; /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable /// value, i.e. an expression of the fixed form (a - b + constant). @@ -75,7 +90,7 @@ public: /// @param Res - The relocatable value, if evaluation succeeds. /// @param Layout - The assembler layout object to use for evaluating values. /// @result - True on success. - bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout = 0) const; + bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout &Layout) const; /// @} @@ -132,12 +147,25 @@ public: VK_GOTTPOFF, VK_INDNTPOFF, VK_NTPOFF, + VK_GOTNTPOFF, VK_PLT, VK_TLSGD, + VK_TLSLD, + VK_TLSLDM, VK_TPOFF, - VK_ARM_HI16, // The R_ARM_MOVT_ABS relocation (:upper16: in the asm file) - VK_ARM_LO16, // The R_ARM_MOVW_ABS_NC relocation (:lower16: in the asm file) - VK_TLVP // Mach-O thread local variable relocation + VK_DTPOFF, + VK_TLVP, // Mach-O thread local variable relocation + // FIXME: We'd really like to use the generic Kinds listed above for these. + VK_ARM_PLT, // ARM-style PLT references. i.e., (PLT) instead of @PLT + VK_ARM_TLSGD, // ditto for TLSGD, GOT, GOTOFF, TPOFF and GOTTPOFF + VK_ARM_GOT, + VK_ARM_GOTOFF, + VK_ARM_TPOFF, + VK_ARM_GOTTPOFF, + + VK_PPC_TOC, + VK_PPC_HA16, // ha16(symbol) + VK_PPC_LO16 // lo16(symbol) }; private: @@ -162,7 +190,7 @@ public: MCContext &Ctx); static const MCSymbolRefExpr *Create(StringRef Name, VariantKind Kind, MCContext &Ctx); - + /// @} /// @name Accessors /// @{ @@ -391,7 +419,7 @@ public: virtual void PrintImpl(raw_ostream &OS) const = 0; virtual bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout) const = 0; - + virtual void AddValueSymbols(MCAssembler *) const = 0; static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Target; diff --git a/contrib/llvm/include/llvm/MC/MCFixup.h b/contrib/llvm/include/llvm/MC/MCFixup.h index eed4c34..6fde797 100644 --- a/contrib/llvm/include/llvm/MC/MCFixup.h +++ b/contrib/llvm/include/llvm/MC/MCFixup.h @@ -10,7 +10,7 @@ #ifndef LLVM_MC_MCFIXUP_H #define LLVM_MC_MCFIXUP_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { @@ -22,6 +22,10 @@ enum MCFixupKind { FK_Data_2, ///< A two-byte fixup. FK_Data_4, ///< A four-byte fixup. FK_Data_8, ///< A eight-byte fixup. + FK_PCRel_1, ///< A one-byte pc relative fixup. + FK_PCRel_2, ///< A two-byte pc relative fixup. + FK_PCRel_4, ///< A four-byte pc relative fixup. + FK_PCRel_8, ///< A eight-byte pc relative fixup. FirstTargetFixupKind = 128, @@ -77,13 +81,13 @@ public: /// getKindForSize - Return the generic fixup kind for a value with the given /// size. It is an error to pass an unsupported size. - static MCFixupKind getKindForSize(unsigned Size) { + static MCFixupKind getKindForSize(unsigned Size, bool isPCRel) { switch (Size) { default: assert(0 && "Invalid generic fixup size!"); - case 1: return FK_Data_1; - case 2: return FK_Data_2; - case 4: return FK_Data_4; - case 8: return FK_Data_8; + case 1: return isPCRel ? FK_PCRel_1 : FK_Data_1; + case 2: return isPCRel ? FK_PCRel_2 : FK_Data_2; + case 4: return isPCRel ? FK_PCRel_4 : FK_Data_4; + case 8: return isPCRel ? FK_PCRel_8 : FK_Data_8; } } }; diff --git a/contrib/llvm/include/llvm/MC/MCFixupKindInfo.h b/contrib/llvm/include/llvm/MC/MCFixupKindInfo.h new file mode 100644 index 0000000..1961687 --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCFixupKindInfo.h @@ -0,0 +1,43 @@ +//===-- llvm/MC/MCFixupKindInfo.h - Fixup Descriptors -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCFIXUPKINDINFO_H +#define LLVM_MC_MCFIXUPKINDINFO_H + +namespace llvm { + +/// MCFixupKindInfo - Target independent information on a fixup kind. +struct MCFixupKindInfo { + enum FixupKindFlags { + /// Is this fixup kind PCrelative? This is used by the assembler backend to + /// evaluate fixup values in a target independent manner when possible. + FKF_IsPCRel = (1 << 0), + + /// Should this fixup kind force a 4-byte aligned effective PC value? + FKF_IsAlignedDownTo32Bits = (1 << 1) + }; + + /// A target specific name for the fixup kind. The names will be unique for + /// distinct kinds on any given target. + const char *Name; + + /// The bit offset to write the relocation into. + unsigned TargetOffset; + + /// The number of bits written by this fixup. The bits are assumed to be + /// contiguous. + unsigned TargetSize; + + /// Flags describing additional information on this fixup kind. + unsigned Flags; +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/MC/MCInst.h b/contrib/llvm/include/llvm/MC/MCInst.h index dc630fe..d6ef7b4 100644 --- a/contrib/llvm/include/llvm/MC/MCInst.h +++ b/contrib/llvm/include/llvm/MC/MCInst.h @@ -18,7 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class raw_ostream; @@ -33,24 +33,27 @@ class MCOperand { kInvalid, ///< Uninitialized. kRegister, ///< Register operand. kImmediate, ///< Immediate operand. + kFPImmediate, ///< Floating-point immediate operand. kExpr ///< Relocatable immediate operand. }; unsigned char Kind; - + union { unsigned RegVal; int64_t ImmVal; + double FPImmVal; const MCExpr *ExprVal; }; public: - - MCOperand() : Kind(kInvalid) {} + + MCOperand() : Kind(kInvalid), FPImmVal(0.0) {} bool isValid() const { return Kind != kInvalid; } bool isReg() const { return Kind == kRegister; } bool isImm() const { return Kind == kImmediate; } + bool isFPImm() const { return Kind == kFPImmediate; } bool isExpr() const { return Kind == kExpr; } - + /// getReg - Returns the register number. unsigned getReg() const { assert(isReg() && "This is not a register operand!"); @@ -62,7 +65,7 @@ public: assert(isReg() && "This is not a register operand!"); RegVal = Reg; } - + int64_t getImm() const { assert(isImm() && "This is not an immediate"); return ImmVal; @@ -71,7 +74,17 @@ public: assert(isImm() && "This is not an immediate"); ImmVal = Val; } - + + double getFPImm() const { + assert(isFPImm() && "This is not an FP immediate"); + return FPImmVal; + } + + void setFPImm(double Val) { + assert(isFPImm() && "This is not an FP immediate"); + FPImmVal = Val; + } + const MCExpr *getExpr() const { assert(isExpr() && "This is not an expression"); return ExprVal; @@ -80,7 +93,7 @@ public: assert(isExpr() && "This is not an expression"); ExprVal = Val; } - + static MCOperand CreateReg(unsigned Reg) { MCOperand Op; Op.Kind = kRegister; @@ -93,6 +106,12 @@ public: Op.ImmVal = Val; return Op; } + static MCOperand CreateFPImm(double Val) { + MCOperand Op; + Op.Kind = kFPImmediate; + Op.FPImmVal = Val; + return Op; + } static MCOperand CreateExpr(const MCExpr *Val) { MCOperand Op; Op.Kind = kExpr; @@ -104,23 +123,23 @@ public: void dump() const; }; - + /// MCInst - Instances of this class represent a single low-level machine -/// instruction. +/// instruction. class MCInst { unsigned Opcode; SmallVector<MCOperand, 8> Operands; public: MCInst() : Opcode(0) {} - + void setOpcode(unsigned Op) { Opcode = Op; } - + unsigned getOpcode() const { return Opcode; } const MCOperand &getOperand(unsigned i) const { return Operands[i]; } MCOperand &getOperand(unsigned i) { return Operands[i]; } unsigned getNumOperands() const { return Operands.size(); } - + void addOperand(const MCOperand &Op) { Operands.push_back(Op); } @@ -136,6 +155,15 @@ public: StringRef Separator = " ") const; }; +inline raw_ostream& operator<<(raw_ostream &OS, const MCOperand &MO) { + MO.print(OS, 0); + return OS; +} + +inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) { + MI.print(OS, 0); + return OS; +} } // end namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCInstPrinter.h b/contrib/llvm/include/llvm/MC/MCInstPrinter.h index 4839a83..96716c7 100644 --- a/contrib/llvm/include/llvm/MC/MCInstPrinter.h +++ b/contrib/llvm/include/llvm/MC/MCInstPrinter.h @@ -28,21 +28,21 @@ protected: public: MCInstPrinter(const MCAsmInfo &mai) : CommentStream(0), MAI(mai) {} - + virtual ~MCInstPrinter(); /// setCommentStream - Specify a stream to emit comments to. void setCommentStream(raw_ostream &OS) { CommentStream = &OS; } - + /// printInst - Print the specified MCInst to the specified raw_ostream. /// virtual void printInst(const MCInst *MI, raw_ostream &OS) = 0; - + /// getOpcodeName - Return the name of the specified opcode enum (e.g. /// "MOV32ri") or empty if we can't resolve it. virtual StringRef getOpcodeName(unsigned Opcode) const; }; - + } // namespace llvm #endif diff --git a/contrib/llvm/include/llvm/MC/MCMachOSymbolFlags.h b/contrib/llvm/include/llvm/MC/MCMachOSymbolFlags.h index c938c81..696436d 100644 --- a/contrib/llvm/include/llvm/MC/MCMachOSymbolFlags.h +++ b/contrib/llvm/include/llvm/MC/MCMachOSymbolFlags.h @@ -34,9 +34,11 @@ namespace llvm { SF_ReferenceTypePrivateUndefinedLazy = 0x0005, // Other 'desc' flags. + SF_ThumbFunc = 0x0008, SF_NoDeadStrip = 0x0020, SF_WeakReference = 0x0040, - SF_WeakDefinition = 0x0080 + SF_WeakDefinition = 0x0080, + SF_SymbolResolver = 0x0100 }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h b/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h new file mode 100644 index 0000000..ec51031 --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h @@ -0,0 +1,65 @@ +//===-- llvm/MC/MCMachObjectWriter.h - Mach Object Writer -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCMACHOBJECTWRITER_H +#define LLVM_MC_MCMACHOBJECTWRITER_H + +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class MCMachObjectTargetWriter { + const unsigned Is64Bit : 1; + const uint32_t CPUType; + const uint32_t CPUSubtype; + // FIXME: Remove this, we should just always use it once we no longer care + // about Darwin 'as' compatibility. + const unsigned UseAggressiveSymbolFolding : 1; + unsigned LocalDifference_RIT; + +protected: + MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_, + uint32_t CPUSubtype_, + bool UseAggressiveSymbolFolding_ = false); + + void setLocalDifferenceRelocationType(unsigned Type) { + LocalDifference_RIT = Type; + } + +public: + virtual ~MCMachObjectTargetWriter(); + + /// @name Accessors + /// @{ + + bool is64Bit() const { return Is64Bit; } + bool useAggressiveSymbolFolding() const { return UseAggressiveSymbolFolding; } + uint32_t getCPUType() const { return CPUType; } + uint32_t getCPUSubtype() const { return CPUSubtype; } + unsigned getLocalDifferenceRelocationType() const { + return LocalDifference_RIT; + } + + /// @} +}; + +/// \brief Construct a new Mach-O writer instance. +/// +/// This routine takes ownership of the target writer subclass. +/// +/// \param MOTW - The target specific Mach-O writer subclass. +/// \param OS - The stream to write to. +/// \returns The constructed object writer. +MCObjectWriter *createMachObjectWriter(MCMachObjectTargetWriter *MOTW, + raw_ostream &OS, bool IsLittleEndian); + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/MC/MCObjectStreamer.h b/contrib/llvm/include/llvm/MC/MCObjectStreamer.h index ea6d9c1..833341e 100644 --- a/contrib/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCObjectStreamer.h @@ -33,6 +33,8 @@ class MCObjectStreamer : public MCStreamer { MCAssembler *Assembler; MCSectionData *CurSectionData; + virtual void EmitInstToData(const MCInst &Inst) = 0; + protected: MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter); @@ -56,7 +58,21 @@ public: /// @name MCStreamer Interface /// @{ - virtual void SwitchSection(const MCSection *Section); + virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace); + virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); + virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); + virtual void ChangeSection(const MCSection *Section); + virtual void EmitInstruction(const MCInst &Inst); + virtual void EmitInstToFragment(const MCInst &Inst); + virtual void EmitValueToOffset(const MCExpr *Offset, unsigned char Value); + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label); + virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label); virtual void Finish(); /// @} diff --git a/contrib/llvm/include/llvm/MC/MCObjectWriter.h b/contrib/llvm/include/llvm/MC/MCObjectWriter.h index f1c1cb8..782d844 100644 --- a/contrib/llvm/include/llvm/MC/MCObjectWriter.h +++ b/contrib/llvm/include/llvm/MC/MCObjectWriter.h @@ -10,8 +10,9 @@ #ifndef LLVM_MC_MCOBJECTWRITER_H #define LLVM_MC_MCOBJECTWRITER_H +#include "llvm/ADT/Triple.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { @@ -19,6 +20,9 @@ class MCAsmLayout; class MCAssembler; class MCFixup; class MCFragment; +class MCSymbol; +class MCSymbolData; +class MCSymbolRefExpr; class MCValue; class raw_ostream; @@ -61,7 +65,8 @@ public: /// /// This routine is called by the assembler after layout and relaxation is /// complete. - virtual void ExecutePostLayoutBinding(MCAssembler &Asm) = 0; + virtual void ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) = 0; /// Record a relocation entry. /// @@ -75,12 +80,31 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) = 0; + /// \brief Check whether the difference (A - B) between two symbol + /// references is fully resolved. + /// + /// Clients are not required to answer precisely and may conservatively return + /// false, even when a difference is fully resolved. + bool + IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, + const MCSymbolRefExpr *A, + const MCSymbolRefExpr *B, + bool InSet) const; + + virtual bool + IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const; + + /// 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 /// generated. - virtual void WriteObject(const MCAssembler &Asm, + virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) = 0; /// @} @@ -160,6 +184,11 @@ public: } /// @} + + /// Utility function to encode a SLEB128 value. + static void EncodeSLEB128(int64_t Value, raw_ostream &OS); + /// Utility function to encode a ULEB128 value. + static void EncodeULEB128(uint64_t Value, raw_ostream &OS); }; MCObjectWriter *createWinCOFFObjectWriter(raw_ostream &OS, bool is64Bit); diff --git a/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h b/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h index 2187889..252696b 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h +++ b/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h @@ -17,7 +17,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> #include <cassert> @@ -29,10 +29,10 @@ class MCAsmInfo; /// AsmLexer - Lexer class for assembly files. class AsmLexer : public MCAsmLexer { const MCAsmInfo &MAI; - + const char *CurPtr; const MemoryBuffer *CurBuf; - + void operator=(const AsmLexer&); // DO NOT IMPLEMENT AsmLexer(const AsmLexer&); // DO NOT IMPLEMENT @@ -43,13 +43,13 @@ protected: public: AsmLexer(const MCAsmInfo &MAI); ~AsmLexer(); - + void setBuffer(const MemoryBuffer *buf, const char *ptr = NULL); - + virtual StringRef LexUntilEndOfStatement(); bool isAtStartOfComment(char Char); - + const MCAsmInfo &getMAI() const { return MAI; } private: @@ -60,9 +60,11 @@ private: AsmToken LexSlash(); AsmToken LexLineComment(); AsmToken LexDigit(); + AsmToken LexSingleQuote(); AsmToken LexQuote(); + AsmToken LexFloatLiteral(); }; - + } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h index d690e81..606725a 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h @@ -11,7 +11,7 @@ #define LLVM_MC_MCASMLEXER_H #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/SMLoc.h" namespace llvm { @@ -29,13 +29,16 @@ public: // String values. Identifier, String, - + // Integer values. Integer, - + + // Real values. + Real, + // Register values (stored in IntVal). Only used by TargetAsmLexer. Register, - + // No-value. EndOfStatement, Colon, @@ -43,8 +46,8 @@ public: Slash, // '/' LParen, RParen, LBrac, RBrac, LCurly, RCurly, Star, Dot, Comma, Dollar, Equal, EqualEqual, - - Pipe, PipePipe, Caret, + + Pipe, PipePipe, Caret, Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash, Less, LessEqual, LessLess, LessGreater, Greater, GreaterEqual, GreaterGreater, At @@ -70,7 +73,7 @@ public: SMLoc getLoc() const; /// getStringContents - Get the contents of a string token (without quotes). - StringRef getStringContents() const { + StringRef getStringContents() const { assert(Kind == String && "This token isn't a string!"); return Str.slice(1, Str.size() - 1); } @@ -95,11 +98,11 @@ public: // FIXME: Don't compute this in advance, it makes every token larger, and is // also not generally what we want (it is nicer for recovery etc. to lex 123br // as a single token, then diagnose as an invalid number). - int64_t getIntVal() const { + int64_t getIntVal() const { assert(Kind == Integer && "This token isn't an integer!"); - return IntVal; + return IntVal; } - + /// getRegVal - Get the register number for the current token, which should /// be a register. unsigned getRegVal() const { @@ -113,7 +116,7 @@ public: class MCAsmLexer { /// The current token, stored in the base class for faster access. AsmToken CurTok; - + /// The location and description of the current error SMLoc ErrLoc; std::string Err; @@ -126,12 +129,12 @@ protected: // Can only create subclasses. MCAsmLexer(); virtual AsmToken LexToken() = 0; - + void SetError(const SMLoc &errLoc, const std::string &err) { ErrLoc = errLoc; Err = err; } - + public: virtual ~MCAsmLexer(); @@ -152,12 +155,12 @@ public: const AsmToken &getTok() { return CurTok; } - + /// getErrLoc - Get the current error location const SMLoc &getErrLoc() { return ErrLoc; } - + /// getErr - Get the current error string const std::string &getErr() { return Err; diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h index b37d46c..54979d9 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h +++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h @@ -10,7 +10,7 @@ #ifndef LLVM_MC_MCASMPARSER_H #define LLVM_MC_MCASMPARSER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class AsmToken; @@ -99,6 +99,10 @@ public: /// will be either the EndOfStatement or EOF. virtual StringRef ParseStringToEndOfStatement() = 0; + /// EatToEndOfStatement - Skip to the end of the current statement, for error + /// recovery. + virtual void EatToEndOfStatement() = 0; + /// ParseExpression - Parse an arbitrary expression. /// /// @param Res - The value of the expression. The result is undefined diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/contrib/llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h index 99fa5ad..91f5773 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/contrib/llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -19,10 +19,10 @@ class raw_ostream; /// base class is used by target-independent clients and is the interface /// between parsing an asm instruction and recognizing it. class MCParsedAsmOperand { -public: +public: MCParsedAsmOperand() {} virtual ~MCParsedAsmOperand() {} - + /// getStartLoc - Get the location of the first token of this operand. virtual SMLoc getStartLoc() const = 0; /// getEndLoc - Get the location of the last token of this operand. diff --git a/contrib/llvm/include/llvm/MC/MCSection.h b/contrib/llvm/include/llvm/MC/MCSection.h index 5c99735..1c01b2f 100644 --- a/contrib/llvm/include/llvm/MC/MCSection.h +++ b/contrib/llvm/include/llvm/MC/MCSection.h @@ -32,8 +32,7 @@ namespace llvm { enum SectionVariant { SV_COFF = 0, SV_ELF, - SV_MachO, - SV_PIC16 + SV_MachO }; private: @@ -61,6 +60,14 @@ namespace llvm { return false; } + // UseCodeAlign - Return true if a .align directive should use + // "optimized nops" to fill instead of 0s. + virtual bool UseCodeAlign() const = 0; + + /// isVirtualSection - Check whether this section is "virtual", that is + /// has no actual object file contents. + virtual bool isVirtualSection() const = 0; + static bool classof(const MCSection *) { return true; } }; diff --git a/contrib/llvm/include/llvm/MC/MCSectionCOFF.h b/contrib/llvm/include/llvm/MC/MCSectionCOFF.h index f828e10..b154cf5 100644 --- a/contrib/llvm/include/llvm/MC/MCSectionCOFF.h +++ b/contrib/llvm/include/llvm/MC/MCSectionCOFF.h @@ -19,12 +19,12 @@ #include "llvm/Support/COFF.h" namespace llvm { - + /// MCSectionCOFF - This represents a section on Windows class MCSectionCOFF : public MCSection { // The memory for this string is stored in the same MCContext as *this. StringRef SectionName; - + /// Characteristics - This is the Characteristics field of a section, // drawn from the enums below. unsigned Characteristics; @@ -52,9 +52,11 @@ namespace llvm { StringRef getSectionName() const { return SectionName; } unsigned getCharacteristics() const { return Characteristics; } int getSelection () const { return Selection; } - + virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS) const; + virtual bool UseCodeAlign() const; + virtual bool isVirtualSection() const; static bool classof(const MCSection *S) { return S->getVariant() == SV_COFF; diff --git a/contrib/llvm/include/llvm/MC/MCSectionELF.h b/contrib/llvm/include/llvm/MC/MCSectionELF.h index 5de0bf5..c82de71 100644 --- a/contrib/llvm/include/llvm/MC/MCSectionELF.h +++ b/contrib/llvm/include/llvm/MC/MCSectionELF.h @@ -15,38 +15,39 @@ #define LLVM_MC_MCSECTIONELF_H #include "llvm/MC/MCSection.h" +#include "llvm/Support/ELF.h" namespace llvm { - + +class MCSymbol; + /// MCSectionELF - This represents a section on linux, lots of unix variants /// and some bare metal systems. class MCSectionELF : public MCSection { /// SectionName - This is the name of the section. The referenced memory is /// owned by TargetLoweringObjectFileELF's ELFUniqueMap. StringRef SectionName; - + /// Type - This is the sh_type field of a section, drawn from the enums below. unsigned Type; - + /// Flags - This is the sh_flags field of a section, drawn from the enums. /// below. unsigned Flags; - /// IsExplicit - Indicates that this section comes from globals with an - /// explicit section specified. - bool IsExplicit; - /// EntrySize - The size of each entry in this section. This size only /// makes sense for sections that contain fixed-sized entries. If a /// section does not contain fixed-sized entries 'EntrySize' will be 0. unsigned EntrySize; - + + const MCSymbol *Group; + private: friend class MCContext; MCSectionELF(StringRef Section, unsigned type, unsigned flags, - SectionKind K, bool isExplicit, unsigned entrySize) + SectionKind K, unsigned entrySize, const MCSymbol *group) : MCSection(SV_ELF, K), SectionName(Section), Type(type), Flags(flags), - IsExplicit(isExplicit), EntrySize(entrySize) {} + EntrySize(entrySize), Group(group) {} ~MCSectionELF(); public: @@ -54,141 +55,31 @@ public: /// should be printed before the section name bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; - /// ShouldPrintSectionType - Only prints the section type if supported - bool ShouldPrintSectionType(unsigned Ty) const; - - /// HasCommonSymbols - True if this section holds common symbols, this is - /// indicated on the ELF object file by a symbol with SHN_COMMON section - /// header index. - bool HasCommonSymbols() const; - - /// These are the section type and flags fields. An ELF section can have - /// only one Type, but can have more than one of the flags specified. - /// - /// Valid section types. - enum { - // This value marks the section header as inactive. - SHT_NULL = 0x00U, - - // Holds information defined by the program, with custom format and meaning. - SHT_PROGBITS = 0x01U, - - // This section holds a symbol table. - SHT_SYMTAB = 0x02U, - - // The section holds a string table. - SHT_STRTAB = 0x03U, - - // The section holds relocation entries with explicit addends. - SHT_RELA = 0x04U, - - // The section holds a symbol hash table. - SHT_HASH = 0x05U, - - // Information for dynamic linking. - SHT_DYNAMIC = 0x06U, - - // The section holds information that marks the file in some way. - SHT_NOTE = 0x07U, - - // A section of this type occupies no space in the file. - SHT_NOBITS = 0x08U, - - // The section holds relocation entries without explicit addends. - SHT_REL = 0x09U, - - // This section type is reserved but has unspecified semantics. - SHT_SHLIB = 0x0AU, - - // This section holds a symbol table. - SHT_DYNSYM = 0x0BU, - - // This section contains an array of pointers to initialization functions. - SHT_INIT_ARRAY = 0x0EU, - - // This section contains an array of pointers to termination functions. - SHT_FINI_ARRAY = 0x0FU, - - // This section contains an array of pointers to functions that are invoked - // before all other initialization functions. - SHT_PREINIT_ARRAY = 0x10U, - - // A section group is a set of sections that are related and that must be - // treated specially by the linker. - SHT_GROUP = 0x11U, - - // This section is associated with a section of type SHT_SYMTAB, when the - // referenced symbol table contain the escape value SHN_XINDEX - SHT_SYMTAB_SHNDX = 0x12U, - - LAST_KNOWN_SECTION_TYPE = SHT_SYMTAB_SHNDX - }; - - /// Valid section flags. - enum { - // The section contains data that should be writable. - SHF_WRITE = 0x1U, - - // The section occupies memory during execution. - SHF_ALLOC = 0x2U, - - // The section contains executable machine instructions. - SHF_EXECINSTR = 0x4U, - - // The data in the section may be merged to eliminate duplication. - SHF_MERGE = 0x10U, - - // Elements in the section consist of null-terminated character strings. - SHF_STRINGS = 0x20U, - - // A field in this section holds a section header table index. - SHF_INFO_LINK = 0x40U, - - // Adds special ordering requirements for link editors. - SHF_LINK_ORDER = 0x80U, - - // This section requires special OS-specific processing to avoid incorrect - // behavior. - SHF_OS_NONCONFORMING = 0x100U, - - // This section is a member of a section group. - SHF_GROUP = 0x200U, - - // This section holds Thread-Local Storage. - SHF_TLS = 0x400U, - - - // Start of target-specific flags. - - /// XCORE_SHF_CP_SECTION - All sections with the "c" flag are grouped - /// together by the linker to form the constant pool and the cp register is - /// set to the start of the constant pool by the boot code. - XCORE_SHF_CP_SECTION = 0x800U, - - /// XCORE_SHF_DP_SECTION - All sections with the "d" flag are grouped - /// together by the linker to form the data section and the dp register is - /// set to the start of the section by the boot code. - XCORE_SHF_DP_SECTION = 0x1000U - }; - StringRef getSectionName() const { return SectionName; } unsigned getType() const { return Type; } unsigned getFlags() const { return Flags; } unsigned getEntrySize() const { return EntrySize; } - + const MCSymbol *getGroup() const { return Group; } + void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS) const; - + virtual bool UseCodeAlign() const; + virtual bool isVirtualSection() const; + /// isBaseAddressKnownZero - We know that non-allocatable sections (like /// debug info) have a base of zero. virtual bool isBaseAddressKnownZero() const { - return (getFlags() & SHF_ALLOC) == 0; + return (getFlags() & ELF::SHF_ALLOC) == 0; } static bool classof(const MCSection *S) { return S->getVariant() == SV_ELF; } static bool classof(const MCSectionELF *) { return true; } + + // Return the entry size for sections with fixed-width data. + static unsigned DetermineEntrySize(SectionKind Kind); + }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCSectionMachO.h b/contrib/llvm/include/llvm/MC/MCSectionMachO.h index 2d9d133..7633515 100644 --- a/contrib/llvm/include/llvm/MC/MCSectionMachO.h +++ b/contrib/llvm/include/llvm/MC/MCSectionMachO.h @@ -17,36 +17,36 @@ #include "llvm/MC/MCSection.h" namespace llvm { - + /// MCSectionMachO - This represents a section on a Mach-O system (used by /// Mac OS X). On a Mac system, these are also described in /// /usr/include/mach-o/loader.h. class MCSectionMachO : public MCSection { char SegmentName[16]; // Not necessarily null terminated! char SectionName[16]; // Not necessarily null terminated! - + /// TypeAndAttributes - This is the SECTION_TYPE and SECTION_ATTRIBUTES /// field of a section, drawn from the enums below. unsigned TypeAndAttributes; - + /// Reserved2 - The 'reserved2' field of a section, used to represent the /// size of stubs, for example. unsigned Reserved2; - + MCSectionMachO(StringRef Segment, StringRef Section, - unsigned TAA, unsigned reserved2, SectionKind K); + unsigned TAA, unsigned reserved2, SectionKind K); friend class MCContext; public: - + /// These are the section type and attributes fields. A MachO section can /// have only one Type, but can have any of the attributes specified. enum { // TypeAndAttributes bitmasks. SECTION_TYPE = 0x000000FFU, SECTION_ATTRIBUTES = 0xFFFFFF00U, - + // Valid section types. - + /// S_REGULAR - Regular section. S_REGULAR = 0x00U, /// S_ZEROFILL - Zero fill on demand section. @@ -101,10 +101,10 @@ public: S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15U, LAST_KNOWN_SECTION_TYPE = S_THREAD_LOCAL_INIT_FUNCTION_POINTERS, - + // Valid section attributes. - + /// S_ATTR_PURE_INSTRUCTIONS - Section contains only true machine /// instructions. S_ATTR_PURE_INSTRUCTIONS = 1U << 31, @@ -165,6 +165,8 @@ public: virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS) const; + virtual bool UseCodeAlign() const; + virtual bool isVirtualSection() const; static bool classof(const MCSection *S) { return S->getVariant() == SV_MachO; diff --git a/contrib/llvm/include/llvm/MC/MCStreamer.h b/contrib/llvm/include/llvm/MC/MCStreamer.h index 1ce1b0e..fc2451f 100644 --- a/contrib/llvm/include/llvm/MC/MCStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCStreamer.h @@ -14,8 +14,10 @@ #ifndef LLVM_MC_MCSTREAMER_H #define LLVM_MC_MCSTREAMER_H -#include "llvm/System/DataTypes.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" #include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" namespace llvm { class MCAsmInfo; @@ -28,6 +30,7 @@ namespace llvm { class MCSymbol; class StringRef; class TargetAsmBackend; + class TargetLoweringObjectFile; class Twine; class raw_ostream; class formatted_raw_ostream; @@ -47,29 +50,44 @@ namespace llvm { MCStreamer(const MCStreamer&); // DO NOT IMPLEMENT MCStreamer &operator=(const MCStreamer&); // DO NOT IMPLEMENT - protected: - MCStreamer(MCContext &Ctx); + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + bool isPCRel, unsigned AddrSpace); + + std::vector<MCDwarfFrameInfo> FrameInfos; + MCDwarfFrameInfo *getCurrentFrameInfo(); + void EnsureValidFrame(); + + /// CurSectionStack - This is stack of CurSection values saved by + /// PushSection. + SmallVector<const MCSection *, 4> CurSectionStack; - /// CurSection - This is the current section code is being emitted to, it is - /// kept up to date by SwitchSection. - const MCSection *CurSection; + /// PrevSectionStack - This is stack of PrevSection values saved by + /// PushSection. + SmallVector<const MCSection *, 4> PrevSectionStack; - /// PrevSection - This is the previous section code is being emitted to, it is - /// kept up to date by SwitchSection. - const MCSection *PrevSection; + protected: + MCStreamer(MCContext &Ctx); public: virtual ~MCStreamer(); MCContext &getContext() const { return Context; } + unsigned getNumFrameInfos() { + return FrameInfos.size(); + } + + const MCDwarfFrameInfo &getFrameInfo(unsigned i) { + return FrameInfos[i]; + } + /// @name Assembly File Formatting. /// @{ - + /// isVerboseAsm - Return true if this streamer supports verbose assembly /// and if it is enabled. virtual bool isVerboseAsm() const { return false; } - + /// hasRawTextSupport - Return true if this asm streamer supports emitting /// unformatted text to the .s file with EmitRawText. virtual bool hasRawTextSupport() const { return false; } @@ -82,34 +100,83 @@ namespace llvm { /// If the comment includes embedded \n's, they will each get the comment /// prefix as appropriate. The added comment should not end with a \n. virtual void AddComment(const Twine &T) {} - + /// GetCommentOS - Return a raw_ostream that comments can be written to. /// Unlike AddComment, you are required to terminate comments with \n if you /// use this method. virtual raw_ostream &GetCommentOS(); - + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. virtual void AddBlankLine() {} - + /// @} - + /// @name Symbol & Section Management /// @{ - + /// getCurrentSection - Return the current section that the streamer is /// emitting code to. - const MCSection *getCurrentSection() const { return CurSection; } + const MCSection *getCurrentSection() const { + if (!CurSectionStack.empty()) + return CurSectionStack.back(); + return NULL; + } /// getPreviousSection - Return the previous section that the streamer is /// emitting code to. - const MCSection *getPreviousSection() const { return PrevSection; } + const MCSection *getPreviousSection() const { + if (!PrevSectionStack.empty()) + return PrevSectionStack.back(); + return NULL; + } + + /// ChangeSection - Update streamer for a new active section. + /// + /// This is called by PopSection and SwitchSection, if the current + /// section changes. + virtual void ChangeSection(const MCSection *) = 0; + + /// pushSection - Save the current and previous section on the + /// section stack. + void PushSection() { + PrevSectionStack.push_back(getPreviousSection()); + CurSectionStack.push_back(getCurrentSection()); + } + + /// popSection - Restore the current and previous section from + /// the section stack. Calls ChangeSection as needed. + /// + /// Returns false if the stack was empty. + bool PopSection() { + if (PrevSectionStack.size() <= 1) + return false; + assert(CurSectionStack.size() > 1); + PrevSectionStack.pop_back(); + const MCSection *oldSection = CurSectionStack.pop_back_val(); + const MCSection *curSection = CurSectionStack.back(); + + if (oldSection != curSection) + ChangeSection(curSection); + return true; + } /// SwitchSection - Set the current section where code is being emitted to /// @p Section. This is required to update CurSection. /// /// This corresponds to assembler directives like .section, .text, etc. - virtual void SwitchSection(const MCSection *Section) = 0; - + void SwitchSection(const MCSection *Section) { + assert(Section && "Cannot switch to a null section!"); + const MCSection *curSection = CurSectionStack.back(); + PrevSectionStack.back() = curSection; + if (Section != curSection) { + CurSectionStack.back() = Section; + ChangeSection(Section); + } + } + + /// InitSections - Create the default sections and set the initial one. + virtual void InitSections() = 0; + /// EmitLabel - Emit a label for @p Symbol into the current section. /// /// This corresponds to an assembler statement such as: @@ -123,6 +190,10 @@ namespace llvm { /// EmitAssemblerFlag - Note in the output the specified @p Flag virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; + /// EmitThumbFunc - Note in the output that the specified @p Func is + /// a Thumb mode function (ARM target only). + virtual void EmitThumbFunc(MCSymbol *Func) = 0; + /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. /// /// This corresponds to an assembler statement such as: @@ -136,6 +207,15 @@ namespace llvm { /// @param Value - The value for the symbol. virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) = 0; + /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol. + /// + /// This corresponds to an assembler statement such as: + /// .weakref alias, symbol + /// + /// @param Alias - The alias that is being created. + /// @param Symbol - The symbol being aliased. + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) = 0; + /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) = 0; @@ -170,7 +250,7 @@ namespace llvm { /// .size symbol, expression /// virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) = 0; - + /// EmitCommonSymbol - Emit a common symbol. /// /// @param Symbol - The common symbol to emit. @@ -185,7 +265,7 @@ namespace llvm { /// @param Symbol - The common symbol to emit. /// @param Size - The size of the common symbol. virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) = 0; - + /// EmitZerofill - Emit the zerofill section and an optional symbol. /// /// @param Section - The zerofill section to create and or to put the symbol @@ -204,7 +284,7 @@ namespace llvm { /// @param ByteAlignment - The alignment of the thread local common symbol /// if non-zero. This must be a power of 2 on some targets. virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0) = 0; + uint64_t Size, unsigned ByteAlignment = 0) = 0; /// @} /// @name Generating Data /// @{ @@ -224,38 +304,67 @@ namespace llvm { /// @param Value - The value to emit. /// @param Size - The size of the integer (in bytes) to emit. This must /// match a native machine width. - virtual void EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace = 0) = 0; + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace) = 0; + + void EmitValue(const MCExpr *Value, unsigned Size, unsigned AddrSpace = 0); + + void EmitPCRelValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace = 0); /// EmitIntValue - Special case of EmitValue that avoids the client having /// to pass in a MCExpr for constant integers. virtual void EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace = 0); - + + /// EmitAbsValue - Emit the Value, but try to avoid relocations. On MachO + /// this is done by producing + /// foo = value + /// .long foo + void EmitAbsValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace = 0); + + virtual void EmitULEB128Value(const MCExpr *Value, + unsigned AddrSpace = 0) = 0; + + virtual void EmitSLEB128Value(const MCExpr *Value, + unsigned AddrSpace = 0) = 0; + + /// 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); + + /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the + /// client having to pass in a MCExpr for constant integers. + void EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace = 0); + /// EmitSymbolValue - Special case of EmitValue that avoids the client /// having to pass in a MCExpr for MCSymbols. - virtual void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, - unsigned AddrSpace); - + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + unsigned AddrSpace = 0); + + void EmitPCRelSymbolValue(const MCSymbol *Sym, unsigned Size, + unsigned AddrSpace = 0); + /// EmitGPRel32Value - Emit the expression @p Value into the output as a /// gprel32 (32-bit GP relative) value. /// /// This is used to implement assembler directives such as .gprel32 on /// targets that support them. - virtual void EmitGPRel32Value(const MCExpr *Value) = 0; - + virtual void EmitGPRel32Value(const MCExpr *Value); + /// EmitFill - Emit NumBytes bytes worth of the value specified by /// FillValue. This implements directives such as '.space'. virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, unsigned AddrSpace); - + /// EmitZeros - Emit NumBytes worth of zeros. This is a convenience /// function that just wraps EmitFill. void EmitZeros(uint64_t NumBytes, unsigned AddrSpace) { EmitFill(NumBytes, 0, AddrSpace); } - + /// EmitValueToAlignment - Emit some number of copies of @p Value until /// the byte alignment @p ByteAlignment is reached. /// @@ -301,17 +410,47 @@ namespace llvm { /// @param Value - The value to use when filling bytes. virtual void EmitValueToOffset(const MCExpr *Offset, unsigned char Value = 0) = 0; - + /// @} - + /// EmitFileDirective - Switch to a new logical file. This is used to /// implement the '.file "foo.c"' assembler directive. virtual void EmitFileDirective(StringRef Filename) = 0; - + /// EmitDwarfFileDirective - Associate a filename with a specified logical /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler /// directive. - virtual void EmitDwarfFileDirective(unsigned FileNo,StringRef Filename) = 0; + virtual bool EmitDwarfFileDirective(unsigned FileNo,StringRef Filename); + + /// EmitDwarfLocDirective - This implements the DWARF2 + // '.loc fileno lineno ...' assembler directive. + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, + unsigned Discriminator); + + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label) = 0; + + virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label) { + } + + void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, + int PointerSize); + + virtual bool EmitCFIStartProc(); + virtual bool EmitCFIEndProc(); + virtual bool EmitCFIDefCfa(int64_t Register, int64_t Offset); + virtual bool EmitCFIDefCfaOffset(int64_t Offset); + virtual bool EmitCFIDefCfaRegister(int64_t Register); + virtual bool EmitCFIOffset(int64_t Register, int64_t Offset); + virtual bool EmitCFIPersonality(const MCSymbol *Sym, + unsigned Encoding); + virtual bool EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + virtual bool EmitCFIRememberState(); + virtual bool EmitCFIRestoreState(); /// EmitInstruction - Emit the given @p Instruction into the current /// section. @@ -322,7 +461,7 @@ namespace llvm { /// indicated by the hasRawTextSupport() predicate. By default this aborts. virtual void EmitRawText(StringRef String); void EmitRawText(const Twine &String); - + /// Finish - Finish emission of machine code. virtual void Finish() = 0; }; @@ -342,12 +481,18 @@ namespace llvm { /// \param CE - If given, a code emitter to use to show the instruction /// encoding inline with the assembly. This method takes ownership of \arg CE. /// + /// \param TAB - If given, a target asm backend to use to show the fixup + /// information in conjunction with encoding information. This method takes + /// ownership of \arg TAB. + /// /// \param ShowInst - Whether to show the MCInst representation inline with /// the assembly. MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isLittleEndian, bool isVerboseAsm, + bool isVerboseAsm, + bool useLoc, MCInstPrinter *InstPrint = 0, MCCodeEmitter *CE = 0, + TargetAsmBackend *TAB = 0, bool ShowInst = false); /// createMachOStreamer - Create a machine code streamer which will generate @@ -371,7 +516,7 @@ namespace llvm { /// ELF format object files. MCStreamer *createELFStreamer(MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll = false); + bool RelaxAll, bool NoExecStack); /// createLoggingStreamer - Create a machine code streamer which just logs the /// API calls and then dispatches to another streamer. @@ -379,6 +524,13 @@ namespace llvm { /// The new streamer takes ownership of the \arg Child. MCStreamer *createLoggingStreamer(MCStreamer *Child, raw_ostream &OS); + /// createPureStreamer - Create a machine code streamer which will generate + /// "pure" MC object files, for use with MC-JIT and testing tools. + /// + /// Takes ownership of \arg TAB and \arg CE. + MCStreamer *createPureStreamer(MCContext &Ctx, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE); + } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/MC/MCSymbol.h b/contrib/llvm/include/llvm/MC/MCSymbol.h index 1b432c2..7da4d7c 100644 --- a/contrib/llvm/include/llvm/MC/MCSymbol.h +++ b/contrib/llvm/include/llvm/MC/MCSymbol.h @@ -52,15 +52,14 @@ namespace llvm { /// "Lfoo" or ".foo". unsigned IsTemporary : 1; - /// IsUsedInExpr - True if this symbol has been used in an expression and - /// cannot be redefined. - unsigned IsUsedInExpr : 1; + /// IsUsed - True if this symbol has been used. + mutable unsigned IsUsed : 1; private: // MCContext creates and uniques these. friend class MCContext; MCSymbol(StringRef name, bool isTemporary) : Name(name), Section(0), Value(0), - IsTemporary(isTemporary), IsUsedInExpr(false) {} + IsTemporary(isTemporary), IsUsed(false) {} MCSymbol(const MCSymbol&); // DO NOT IMPLEMENT void operator=(const MCSymbol&); // DO NOT IMPLEMENT @@ -74,9 +73,9 @@ namespace llvm { /// isTemporary - Check if this is an assembler temporary symbol. bool isTemporary() const { return IsTemporary; } - /// isUsedInExpr - Check if this is an assembler temporary symbol. - bool isUsedInExpr() const { return IsUsedInExpr; } - void setUsedInExpr(bool Value) { IsUsedInExpr = Value; } + /// isUsed - Check if this is used. + bool isUsed() const { return IsUsed; } + void setUsed(bool Value) const { IsUsed = Value; } /// @} /// @name Associated Sections @@ -135,9 +134,15 @@ namespace llvm { /// getValue() - Get the value for variable symbols. const MCExpr *getVariableValue() const { assert(isVariable() && "Invalid accessor!"); + IsUsed = true; return Value; } + // AliasedSymbol() - If this is an alias (a = b), return the symbol + // we ultimately point to. For a non alias, this just returns the symbol + // itself. + const MCSymbol &AliasedSymbol() const; + void setVariableValue(const MCExpr *Value); /// @} diff --git a/contrib/llvm/include/llvm/MC/MCValue.h b/contrib/llvm/include/llvm/MC/MCValue.h index 11b6c2a..df8dbd9 100644 --- a/contrib/llvm/include/llvm/MC/MCValue.h +++ b/contrib/llvm/include/llvm/MC/MCValue.h @@ -14,7 +14,7 @@ #ifndef LLVM_MC_MCVALUE_H #define LLVM_MC_MCVALUE_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/MC/MCSymbol.h" #include <cassert> diff --git a/contrib/llvm/include/llvm/MC/MachObjectWriter.h b/contrib/llvm/include/llvm/MC/MachObjectWriter.h deleted file mode 100644 index 9b1ff1d..0000000 --- a/contrib/llvm/include/llvm/MC/MachObjectWriter.h +++ /dev/null @@ -1,44 +0,0 @@ -//===-- llvm/MC/MachObjectWriter.h - Mach-O File Writer ---------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MACHOBJECTWRITER_H -#define LLVM_MC_MACHOBJECTWRITER_H - -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> - -namespace llvm { -class MCAssembler; -class MCFragment; -class MCFixup; -class MCValue; -class raw_ostream; - -class MachObjectWriter : public MCObjectWriter { - void *Impl; - -public: - MachObjectWriter(raw_ostream &OS, bool Is64Bit, bool IsLittleEndian = true); - virtual ~MachObjectWriter(); - - virtual void ExecutePostLayoutBinding(MCAssembler &Asm); - - virtual void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, MCValue Target, - uint64_t &FixedValue); - - virtual void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout); -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Metadata.h b/contrib/llvm/include/llvm/Metadata.h index f5a80a3..a6c3f03 100644 --- a/contrib/llvm/include/llvm/Metadata.h +++ b/contrib/llvm/include/llvm/Metadata.h @@ -144,9 +144,6 @@ public: unsigned getNumOperands() const { return NumOperands; } /// isFunctionLocal - Return whether MDNode is local to a function. - /// Note: MDNodes are designated as function-local when created, and keep - /// that designation even if their operands are modified to no longer - /// refer to function-local IR. bool isFunctionLocal() const { return (getSubclassDataFromValue() & FunctionLocalBit) != 0; } diff --git a/contrib/llvm/include/llvm/Module.h b/contrib/llvm/include/llvm/Module.h index b7880ca..f95895e 100644 --- a/contrib/llvm/include/llvm/Module.h +++ b/contrib/llvm/include/llvm/Module.h @@ -20,7 +20,7 @@ #include "llvm/GlobalAlias.h" #include "llvm/Metadata.h" #include "llvm/ADT/OwningPtr.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <vector> namespace llvm { diff --git a/contrib/llvm/include/llvm/Object/MachOFormat.h b/contrib/llvm/include/llvm/Object/MachOFormat.h new file mode 100644 index 0000000..31cd523 --- /dev/null +++ b/contrib/llvm/include/llvm/Object/MachOFormat.h @@ -0,0 +1,367 @@ +//===- MachOFormat.h - Mach-O Format Structures And Constants ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares various structures and constants which are platform +// independent and can be shared by any client which wishes to interact with +// Mach object files. +// +// The definitions here are purposely chosen to match the LLVM style as opposed +// to following the platform specific definition of the format. +// +// On a Mach system, see the <mach-o/...> includes for more information, in +// particular <mach-o/loader.h>. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MACHOFORMAT_H +#define LLVM_OBJECT_MACHOFORMAT_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { +namespace object { + +/// General Mach platform information. +namespace mach { + /// @name CPU Type and Subtype Information + /// { + + /// \brief Capability bits used in CPU type encoding. + enum CPUTypeFlagsMask { + CTFM_ArchMask = 0xFF000000, + CTFM_ArchABI64 = 0x01000000 + }; + + /// \brief Machine type IDs used in CPU type encoding. + enum CPUTypeMachine { + CTM_i386 = 7, + CTM_x86_64 = CTM_i386 | CTFM_ArchABI64, + CTM_ARM = 12, + CTM_SPARC = 14, + CTM_PowerPC = 18, + CTM_PowerPC64 = CTM_PowerPC | CTFM_ArchABI64 + }; + + /// \brief Capability bits used in CPU subtype encoding. + enum CPUSubtypeFlagsMask { + CSFM_SubtypeMask = 0xFF000000, + CSFM_SubtypeLib64 = 0x80000000 + }; + + /// \brief ARM Machine Subtypes. + enum CPUSubtypeARM { + CSARM_ALL = 0, + CSARM_V4T = 5, + CSARM_V6 = 6, + CSARM_V5TEJ = 7, + CSARM_XSCALE = 8, + CSARM_V7 = 9 + }; + + /// \brief PowerPC Machine Subtypes. + enum CPUSubtypePowerPC { + CSPPC_ALL = 0 + }; + + /// \brief SPARC Machine Subtypes. + enum CPUSubtypeSPARC { + CSSPARC_ALL = 0 + }; + + /// \brief x86 Machine Subtypes. + enum CPUSubtypeX86 { + CSX86_ALL = 3 + }; + + /// @} + +} // end namespace mach + +/// Format information for Mach object files. +namespace macho { + /// \brief Constants for structure sizes. + enum StructureSizes { + Header32Size = 28, + Header64Size = 32, + SegmentLoadCommand32Size = 56, + SegmentLoadCommand64Size = 72, + Section32Size = 68, + Section64Size = 80, + SymtabLoadCommandSize = 24, + DysymtabLoadCommandSize = 80, + Nlist32Size = 12, + Nlist64Size = 16, + RelocationInfoSize = 8 + }; + + /// \brief Constants for header magic field. + enum HeaderMagic { + HM_Object32 = 0xFEEDFACE, ///< 32-bit mach object file + HM_Object64 = 0xFEEDFACF, ///< 64-bit mach object file + HM_Universal = 0xCAFEBABE ///< Universal object file + }; + + /// \brief Header common to all Mach object files. + struct Header { + uint32_t Magic; + uint32_t CPUType; + uint32_t CPUSubtype; + uint32_t FileType; + uint32_t NumLoadCommands; + uint32_t SizeOfLoadCommands; + uint32_t Flags; + }; + + /// \brief Extended header for 64-bit object files. + struct Header64Ext { + uint32_t Reserved; + }; + + // See <mach-o/loader.h>. + enum HeaderFileType { + HFT_Object = 0x1 + }; + + enum HeaderFlags { + HF_SubsectionsViaSymbols = 0x2000 + }; + + enum LoadCommandType { + LCT_Segment = 0x1, + LCT_Symtab = 0x2, + LCT_Dysymtab = 0xb, + LCT_Segment64 = 0x19, + LCT_UUID = 0x1b + }; + + /// \brief Load command structure. + struct LoadCommand { + uint32_t Type; + uint32_t Size; + }; + + /// @name Load Command Structures + /// @{ + + struct SegmentLoadCommand { + uint32_t Type; + uint32_t Size; + char Name[16]; + uint32_t VMAddress; + uint32_t VMSize; + uint32_t FileOffset; + uint32_t FileSize; + uint32_t MaxVMProtection; + uint32_t InitialVMProtection; + uint32_t NumSections; + uint32_t Flags; + }; + + struct Segment64LoadCommand { + uint32_t Type; + uint32_t Size; + char Name[16]; + uint64_t VMAddress; + uint64_t VMSize; + uint64_t FileOffset; + uint64_t FileSize; + uint32_t MaxVMProtection; + uint32_t InitialVMProtection; + uint32_t NumSections; + uint32_t Flags; + }; + + struct SymtabLoadCommand { + uint32_t Type; + uint32_t Size; + uint32_t SymbolTableOffset; + uint32_t NumSymbolTableEntries; + uint32_t StringTableOffset; + uint32_t StringTableSize; + }; + + struct DysymtabLoadCommand { + uint32_t Type; + uint32_t Size; + + uint32_t LocalSymbolsIndex; + uint32_t NumLocalSymbols; + + uint32_t ExternalSymbolsIndex; + uint32_t NumExternalSymbols; + + uint32_t UndefinedSymbolsIndex; + uint32_t NumUndefinedSymbols; + + uint32_t TOCOffset; + uint32_t NumTOCEntries; + + uint32_t ModuleTableOffset; + uint32_t NumModuleTableEntries; + + uint32_t ReferenceSymbolTableOffset; + uint32_t NumReferencedSymbolTableEntries; + + uint32_t IndirectSymbolTableOffset; + uint32_t NumIndirectSymbolTableEntries; + + uint32_t ExternalRelocationTableOffset; + uint32_t NumExternalRelocationTableEntries; + + uint32_t LocalRelocationTableOffset; + uint32_t NumLocalRelocationTableEntries; + }; + + /// @} + /// @name Section Data + /// @{ + + struct Section { + char Name[16]; + char SegmentName[16]; + uint32_t Address; + uint32_t Size; + uint32_t Offset; + uint32_t Align; + uint32_t RelocationTableOffset; + uint32_t NumRelocationTableEntries; + uint32_t Flags; + uint32_t Reserved1; + uint32_t Reserved2; + }; + struct Section64 { + char Name[16]; + char SegmentName[16]; + uint64_t Address; + uint64_t Size; + uint32_t Offset; + uint32_t Align; + uint32_t RelocationTableOffset; + uint32_t NumRelocationTableEntries; + uint32_t Flags; + uint32_t Reserved1; + uint32_t Reserved2; + uint32_t Reserved3; + }; + + /// @} + /// @name Symbol Table Entries + /// @{ + + struct SymbolTableEntry { + uint32_t StringIndex; + uint8_t Type; + uint8_t SectionIndex; + uint16_t Flags; + uint32_t Value; + }; + struct Symbol64TableEntry { + uint32_t StringIndex; + uint8_t Type; + uint8_t SectionIndex; + uint16_t Flags; + uint64_t Value; + }; + + /// @} + /// @name Indirect Symbol Table + /// @{ + + struct IndirectSymbolTableEntry { + uint32_t Index; + }; + + /// @} + /// @name Relocation Data + /// @{ + + struct RelocationEntry { + uint32_t Word0; + uint32_t Word1; + }; + + /// @} + + // See <mach-o/nlist.h>. + enum SymbolTypeType { + STT_Undefined = 0x00, + STT_Absolute = 0x02, + STT_Section = 0x0e + }; + + enum SymbolTypeFlags { + // If any of these bits are set, then the entry is a stab entry number (see + // <mach-o/stab.h>. Otherwise the other masks apply. + STF_StabsEntryMask = 0xe0, + + STF_TypeMask = 0x0e, + STF_External = 0x01, + STF_PrivateExtern = 0x10 + }; + + /// IndirectSymbolFlags - Flags for encoding special values in the indirect + /// symbol entry. + enum IndirectSymbolFlags { + ISF_Local = 0x80000000, + ISF_Absolute = 0x40000000 + }; + + /// RelocationFlags - Special flags for addresses. + enum RelocationFlags { + RF_Scattered = 0x80000000 + }; + + /// Common relocation info types. + enum RelocationInfoType { + RIT_Vanilla = 0, + RIT_Pair = 1, + RIT_Difference = 2 + }; + + /// Generic relocation info types, which are shared by some (but not all) + /// platforms. + enum RelocationInfoType_Generic { + RIT_Generic_PreboundLazyPointer = 3, + RIT_Generic_LocalDifference = 4, + RIT_Generic_TLV = 5 + }; + + /// X86_64 uses its own relocation types. + enum RelocationInfoTypeX86_64 { + // Note that x86_64 doesn't even share the common relocation types. + RIT_X86_64_Unsigned = 0, + RIT_X86_64_Signed = 1, + RIT_X86_64_Branch = 2, + RIT_X86_64_GOTLoad = 3, + RIT_X86_64_GOT = 4, + RIT_X86_64_Subtractor = 5, + RIT_X86_64_Signed1 = 6, + RIT_X86_64_Signed2 = 7, + RIT_X86_64_Signed4 = 8, + RIT_X86_64_TLV = 9 + }; + + /// ARM uses its own relocation types. + enum RelocationInfoTypeARM { + RIT_ARM_LocalDifference = 3, + RIT_ARM_PreboundLazyPointer = 4, + RIT_ARM_Branch24Bit = 5, + RIT_ARM_ThumbBranch22Bit = 6, + RIT_ARM_ThumbBranch32Bit = 7, + RIT_ARM_Half = 8, + RIT_ARM_HalfDifference = 9 + + }; + +} // end namespace macho + +} // end namespace object +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Object/MachOObject.h b/contrib/llvm/include/llvm/Object/MachOObject.h new file mode 100644 index 0000000..03d9c14 --- /dev/null +++ b/contrib/llvm/include/llvm/Object/MachOObject.h @@ -0,0 +1,180 @@ +//===- MachOObject.h - Mach-O Object File Wrapper ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MACHOOBJECT_H +#define LLVM_OBJECT_MACHOOBJECT_H + +#include <string> +#include "llvm/ADT/InMemoryStruct.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Object/MachOFormat.h" + +namespace llvm { + +class MemoryBuffer; + +namespace object { + +/// \brief Wrapper object for manipulating Mach-O object files. +/// +/// This class is designed to implement a full-featured, efficient, portable, +/// and robust Mach-O interface to Mach-O object files. It does not attempt to +/// smooth over rough edges in the Mach-O format or generalize access to object +/// independent features. +/// +/// The class is designed around accessing the Mach-O object which is expected +/// to be fully loaded into memory. +/// +/// This class is *not* suitable for concurrent use. For efficient operation, +/// the class uses APIs which rely on the ability to cache the results of +/// certain calls in internal objects which are not safe for concurrent +/// access. This allows the API to be zero-copy on the common paths. +// +// FIXME: It would be cool if we supported a "paged" MemoryBuffer +// implementation. This would allow us to implement a more sensible version of +// MemoryObject which can work like a MemoryBuffer, but be more efficient for +// objects which are in the current address space. +class MachOObject { +public: + struct LoadCommandInfo { + /// The load command information. + macho::LoadCommand Command; + + /// The offset to the start of the load command in memory. + uint64_t Offset; + }; + +private: + OwningPtr<MemoryBuffer> Buffer; + + /// Whether the object is little endian. + bool IsLittleEndian; + /// Whether the object is 64-bit. + bool Is64Bit; + /// Whether the object is swapped endianness from the host. + bool IsSwappedEndian; + /// Whether the string table has been registered. + bool HasStringTable; + + /// The cached information on the load commands. + LoadCommandInfo *LoadCommands; + mutable unsigned NumLoadedCommands; + + /// The cached copy of the header. + macho::Header Header; + macho::Header64Ext Header64Ext; + + /// Cache string table information. + StringRef StringTable; + +private: + MachOObject(MemoryBuffer *Buffer, bool IsLittleEndian, bool Is64Bit); + +public: + ~MachOObject(); + + /// \brief Load a Mach-O object from a MemoryBuffer object. + /// + /// \param Buffer - The buffer to load the object from. This routine takes + /// exclusive ownership of the buffer (which is passed to the returned object + /// on success). + /// \param ErrorStr [out] - If given, will be set to a user readable error + /// message on failure. + /// \returns The loaded object, or null on error. + static MachOObject *LoadFromBuffer(MemoryBuffer *Buffer, + std::string *ErrorStr = 0); + + /// @name File Information + /// @{ + + bool isLittleEndian() const { return IsLittleEndian; } + bool isSwappedEndian() const { return IsSwappedEndian; } + bool is64Bit() const { return Is64Bit; } + + unsigned getHeaderSize() const { + return Is64Bit ? macho::Header64Size : macho::Header32Size; + } + + StringRef getData(size_t Offset, size_t Size) const; + + /// @} + /// @name String Table Data + /// @{ + + StringRef getStringTableData() const { + assert(HasStringTable && "String table has not been registered!"); + return StringTable; + } + + StringRef getStringAtIndex(unsigned Index) const { + size_t End = getStringTableData().find('\0', Index); + return getStringTableData().slice(Index, End); + } + + void RegisterStringTable(macho::SymtabLoadCommand &SLC); + + /// @} + /// @name Object Header Access + /// @{ + + const macho::Header &getHeader() const { return Header; } + const macho::Header64Ext &getHeader64Ext() const { + assert(is64Bit() && "Invalid access!"); + return Header64Ext; + } + + /// @} + /// @name Object Structure Access + /// @{ + + /// \brief Retrieve the information for the given load command. + const LoadCommandInfo &getLoadCommandInfo(unsigned Index) const; + + void ReadSegmentLoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct<macho::SegmentLoadCommand> &Res) const; + void ReadSegment64LoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct<macho::Segment64LoadCommand> &Res) const; + void ReadSymtabLoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct<macho::SymtabLoadCommand> &Res) const; + void ReadDysymtabLoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct<macho::DysymtabLoadCommand> &Res) const; + void ReadIndirectSymbolTableEntry( + const macho::DysymtabLoadCommand &DLC, + unsigned Index, + InMemoryStruct<macho::IndirectSymbolTableEntry> &Res) const; + void ReadSection( + const LoadCommandInfo &LCI, + unsigned Index, + InMemoryStruct<macho::Section> &Res) const; + void ReadSection64( + const LoadCommandInfo &LCI, + unsigned Index, + InMemoryStruct<macho::Section64> &Res) const; + void ReadRelocationEntry( + uint64_t RelocationTableOffset, unsigned Index, + InMemoryStruct<macho::RelocationEntry> &Res) const; + void ReadSymbolTableEntry( + uint64_t SymbolTableOffset, unsigned Index, + InMemoryStruct<macho::SymbolTableEntry> &Res) const; + void ReadSymbol64TableEntry( + uint64_t SymbolTableOffset, unsigned Index, + InMemoryStruct<macho::Symbol64TableEntry> &Res) const; + + /// @} +}; + +} // end namespace object +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Object/ObjectFile.h b/contrib/llvm/include/llvm/Object/ObjectFile.h new file mode 100644 index 0000000..eee9d44 --- /dev/null +++ b/contrib/llvm/include/llvm/Object/ObjectFile.h @@ -0,0 +1,262 @@ +//===- ObjectFile.h - File format independent object file -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares a file format independent ObjectFile class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_OBJECT_FILE_H +#define LLVM_OBJECT_OBJECT_FILE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include <cstring> + +namespace llvm { + +class MemoryBuffer; +class StringRef; + +namespace object { + +class ObjectFile; + +union DataRefImpl { + struct { + uint32_t a, b; + } d; + intptr_t p; +}; + +static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; +} + +/// SymbolRef - This is a value type class that represents a single symbol in +/// the list of symbols in the object file. +class SymbolRef { + DataRefImpl SymbolPimpl; + const ObjectFile *OwningObject; + +public: + SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); + + bool operator==(const SymbolRef &Other) const; + + SymbolRef getNext() const; + + StringRef getName() const; + uint64_t getAddress() const; + uint64_t getSize() const; + + /// Returns the ascii char that should be displayed in a symbol table dump via + /// nm for this symbol. + char getNMTypeChar() const; + + /// Returns true for symbols that are internal to the object file format such + /// as section symbols. + bool isInternal() const; +}; + +/// SectionRef - This is a value type class that represents a single section in +/// the list of sections in the object file. +class SectionRef { + DataRefImpl SectionPimpl; + const ObjectFile *OwningObject; + +public: + SectionRef(DataRefImpl SectionP, const ObjectFile *Owner); + + bool operator==(const SectionRef &Other) const; + + SectionRef getNext() const; + + StringRef getName() const; + uint64_t getAddress() const; + uint64_t getSize() const; + StringRef getContents() const; + + // FIXME: Move to the normalization layer when it's created. + bool isText() const; +}; + +const uint64_t UnknownAddressOrSize = ~0ULL; + +/// ObjectFile - This class is the base class for all object file types. +/// Concrete instances of this object are created by createObjectFile, which +/// figure out which type to create. +class ObjectFile { +private: + ObjectFile(); // = delete + ObjectFile(const ObjectFile &other); // = delete + +protected: + MemoryBuffer *MapFile; + const uint8_t *base; + + ObjectFile(MemoryBuffer *Object); + + // These functions are for SymbolRef to call internally. The main goal of + // this is to allow SymbolRef::SymbolPimpl to point directly to the symbol + // entry in the memory mapped object file. SymbolPimpl cannot contain any + // virtual functions because then it could not point into the memory mapped + // file. + friend class SymbolRef; + virtual SymbolRef getSymbolNext(DataRefImpl Symb) const = 0; + virtual StringRef getSymbolName(DataRefImpl Symb) const = 0; + virtual uint64_t getSymbolAddress(DataRefImpl Symb) const = 0; + virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; + virtual char getSymbolNMTypeChar(DataRefImpl Symb) const = 0; + virtual bool isSymbolInternal(DataRefImpl Symb) const = 0; + + // Same as above for SectionRef. + friend class SectionRef; + virtual SectionRef getSectionNext(DataRefImpl Sec) const = 0; + virtual StringRef getSectionName(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0; + virtual StringRef getSectionContents(DataRefImpl Sec) const = 0; + virtual bool isSectionText(DataRefImpl Sec) const = 0; + + +public: + template<class content_type> + class content_iterator { + content_type Current; + public: + content_iterator(content_type symb) + : Current(symb) {} + + const content_type* operator->() const { + return &Current; + } + + bool operator==(const content_iterator &other) const { + return Current == other.Current; + } + + bool operator!=(const content_iterator &other) const { + return !(*this == other); + } + + content_iterator& operator++() { // Preincrement + Current = Current.getNext(); + return *this; + } + }; + + typedef content_iterator<SymbolRef> symbol_iterator; + typedef content_iterator<SectionRef> section_iterator; + + virtual ~ObjectFile(); + + virtual symbol_iterator begin_symbols() const = 0; + virtual symbol_iterator end_symbols() const = 0; + + virtual section_iterator begin_sections() const = 0; + virtual section_iterator end_sections() const = 0; + + /// @brief The number of bytes used to represent an address in this object + /// file format. + virtual uint8_t getBytesInAddress() const = 0; + + virtual StringRef getFileFormatName() const = 0; + virtual /* Triple::ArchType */ unsigned getArch() const = 0; + + StringRef getFilename() const; + + /// @returns Pointer to ObjectFile subclass to handle this type of object. + /// @param ObjectPath The path to the object file. ObjectPath.isObject must + /// return true. + /// @brief Create ObjectFile from path. + static ObjectFile *createObjectFile(StringRef ObjectPath); + static ObjectFile *createObjectFile(MemoryBuffer *Object); + +private: + static ObjectFile *createCOFFObjectFile(MemoryBuffer *Object); + static ObjectFile *createELFObjectFile(MemoryBuffer *Object); + static ObjectFile *createMachOObjectFile(MemoryBuffer *Object); + static ObjectFile *createArchiveObjectFile(MemoryBuffer *Object); + static ObjectFile *createLibObjectFile(MemoryBuffer *Object); +}; + +// Inline function definitions. +inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner) + : SymbolPimpl(SymbolP) + , OwningObject(Owner) {} + +inline bool SymbolRef::operator==(const SymbolRef &Other) const { + return SymbolPimpl == Other.SymbolPimpl; +} + +inline SymbolRef SymbolRef::getNext() const { + return OwningObject->getSymbolNext(SymbolPimpl); +} + +inline StringRef SymbolRef::getName() const { + return OwningObject->getSymbolName(SymbolPimpl); +} + +inline uint64_t SymbolRef::getAddress() const { + return OwningObject->getSymbolAddress(SymbolPimpl); +} + +inline uint64_t SymbolRef::getSize() const { + return OwningObject->getSymbolSize(SymbolPimpl); +} + +inline char SymbolRef::getNMTypeChar() const { + return OwningObject->getSymbolNMTypeChar(SymbolPimpl); +} + +inline bool SymbolRef::isInternal() const { + return OwningObject->isSymbolInternal(SymbolPimpl); +} + + +/// SectionRef +inline SectionRef::SectionRef(DataRefImpl SectionP, + const ObjectFile *Owner) + : SectionPimpl(SectionP) + , OwningObject(Owner) {} + +inline bool SectionRef::operator==(const SectionRef &Other) const { + return SectionPimpl == Other.SectionPimpl; +} + +inline SectionRef SectionRef::getNext() const { + return OwningObject->getSectionNext(SectionPimpl); +} + +inline StringRef SectionRef::getName() const { + return OwningObject->getSectionName(SectionPimpl); +} + +inline uint64_t SectionRef::getAddress() const { + return OwningObject->getSectionAddress(SectionPimpl); +} + +inline uint64_t SectionRef::getSize() const { + return OwningObject->getSectionSize(SectionPimpl); +} + +inline StringRef SectionRef::getContents() const { + return OwningObject->getSectionContents(SectionPimpl); +} + +inline bool SectionRef::isText() const { + return OwningObject->isSectionText(SectionPimpl); +} + +} // end namespace object +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/OperandTraits.h b/contrib/llvm/include/llvm/OperandTraits.h index b614ccb..f0df5fa 100644 --- a/contrib/llvm/include/llvm/OperandTraits.h +++ b/contrib/llvm/include/llvm/OperandTraits.h @@ -27,27 +27,17 @@ namespace llvm { /// when it is a prefix to the User object, and the number of Use objects is /// known at compile time. -template <unsigned ARITY> +template <typename SubClass, unsigned ARITY> struct FixedNumOperandTraits { - static Use *op_begin(User* U) { + static Use *op_begin(SubClass* U) { return reinterpret_cast<Use*>(U) - ARITY; } - static Use *op_end(User* U) { + static Use *op_end(SubClass* U) { return reinterpret_cast<Use*>(U); } static unsigned operands(const User*) { return ARITY; } - struct prefix { - Use Ops[ARITY]; - prefix(); // DO NOT IMPLEMENT - }; - template <class U> - struct Layout { - struct overlay : public prefix, public U { - overlay(); // DO NOT IMPLEMENT - }; - }; }; //===----------------------------------------------------------------------===// @@ -57,8 +47,8 @@ struct FixedNumOperandTraits { /// OptionalOperandTraits - when the number of operands may change at runtime. /// Naturally it may only decrease, because the allocations may not change. -template <unsigned ARITY = 1> -struct OptionalOperandTraits : public FixedNumOperandTraits<ARITY> { +template <typename SubClass, unsigned ARITY = 1> +struct OptionalOperandTraits : public FixedNumOperandTraits<SubClass, ARITY> { static unsigned operands(const User *U) { return U->getNumOperands(); } @@ -72,12 +62,12 @@ struct OptionalOperandTraits : public FixedNumOperandTraits<ARITY> { /// when it is a prefix to the User object, and the number of Use objects is /// only known at allocation time. -template <unsigned MINARITY = 0> +template <typename SubClass, unsigned MINARITY = 0> struct VariadicOperandTraits { - static Use *op_begin(User* U) { - return reinterpret_cast<Use*>(U) - U->getNumOperands(); + static Use *op_begin(SubClass* U) { + return reinterpret_cast<Use*>(U) - static_cast<User*>(U)->getNumOperands(); } - static Use *op_end(User* U) { + static Use *op_end(SubClass* U) { return reinterpret_cast<Use*>(U); } static unsigned operands(const User *U) { diff --git a/contrib/llvm/include/llvm/Operator.h b/contrib/llvm/include/llvm/Operator.h index 60865aa..ff2a0ad 100644 --- a/contrib/llvm/include/llvm/Operator.h +++ b/contrib/llvm/include/llvm/Operator.h @@ -99,19 +99,21 @@ public: /// hasNoSignedWrap - Test whether this operation is known to never /// undergo signed overflow, aka the nsw property. bool hasNoSignedWrap() const { - return SubclassOptionalData & NoSignedWrap; + return (SubclassOptionalData & NoSignedWrap) != 0; } static inline bool classof(const OverflowingBinaryOperator *) { return true; } static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Add || I->getOpcode() == Instruction::Sub || - I->getOpcode() == Instruction::Mul; + I->getOpcode() == Instruction::Mul || + I->getOpcode() == Instruction::Shl; } static inline bool classof(const ConstantExpr *CE) { return CE->getOpcode() == Instruction::Add || CE->getOpcode() == Instruction::Sub || - CE->getOpcode() == Instruction::Mul; + CE->getOpcode() == Instruction::Mul || + CE->getOpcode() == Instruction::Shl; } static inline bool classof(const Value *V) { return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || @@ -119,105 +121,97 @@ public: } }; -/// AddOperator - Utility class for integer addition operators. -/// -class AddOperator : public OverflowingBinaryOperator { - ~AddOperator(); // do not implement -public: - static inline bool classof(const AddOperator *) { return true; } - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Add; - } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::Add; - } - static inline bool classof(const Value *V) { - return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || - (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); - } -}; - -/// SubOperator - Utility class for integer subtraction operators. -/// -class SubOperator : public OverflowingBinaryOperator { - ~SubOperator(); // do not implement -public: - static inline bool classof(const SubOperator *) { return true; } - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Sub; - } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::Sub; - } - static inline bool classof(const Value *V) { - return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || - (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); - } -}; - -/// MulOperator - Utility class for integer multiplication operators. -/// -class MulOperator : public OverflowingBinaryOperator { - ~MulOperator(); // do not implement -public: - static inline bool classof(const MulOperator *) { return true; } - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Mul; - } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::Mul; - } - static inline bool classof(const Value *V) { - return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || - (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); - } -}; - -/// SDivOperator - An Operator with opcode Instruction::SDiv. -/// -class SDivOperator : public Operator { +/// PossiblyExactOperator - A udiv or sdiv instruction, which can be marked as +/// "exact", indicating that no bits are destroyed. +class PossiblyExactOperator : public Operator { public: enum { IsExact = (1 << 0) }; - -private: - ~SDivOperator(); // do not implement - + friend class BinaryOperator; friend class ConstantExpr; void setIsExact(bool B) { SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); } - + +private: + ~PossiblyExactOperator(); // do not implement public: /// isExact - Test whether this division is known to be exact, with /// zero remainder. bool isExact() const { return SubclassOptionalData & IsExact; } - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SDivOperator *) { return true; } + + static bool isPossiblyExactOpcode(unsigned OpC) { + return OpC == Instruction::SDiv || + OpC == Instruction::UDiv || + OpC == Instruction::AShr || + OpC == Instruction::LShr; + } static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::SDiv; + return isPossiblyExactOpcode(CE->getOpcode()); } static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::SDiv; + return isPossiblyExactOpcode(I->getOpcode()); } static inline bool classof(const Value *V) { return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); } }; + -class GEPOperator : public Operator { + +/// ConcreteOperator - A helper template for defining operators for individual +/// opcodes. +template<typename SuperClass, unsigned Opc> +class ConcreteOperator : public SuperClass { + ~ConcreteOperator(); // DO NOT IMPLEMENT +public: + static inline bool classof(const ConcreteOperator<SuperClass, Opc> *) { + return true; + } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Opc; + } + static inline bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Opc; + } + static inline bool classof(const Value *V) { + return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || + (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); + } +}; + +class AddOperator + : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> {}; +class SubOperator + : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> {}; +class MulOperator + : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> {}; +class ShlOperator + : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> {}; + + +class SDivOperator + : public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> {}; +class UDivOperator + : public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> {}; +class AShrOperator + : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> {}; +class LShrOperator + : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> {}; + + + +class GEPOperator + : public ConcreteOperator<Operator, Instruction::GetElementPtr> { enum { IsInBounds = (1 << 0) }; - ~GEPOperator(); // do not implement - friend class GetElementPtrInst; friend class ConstantExpr; void setIsInBounds(bool B) { @@ -266,8 +260,8 @@ public: /// value, just potentially different types. bool hasAllZeroIndices() const { for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { - if (Constant *C = dyn_cast<Constant>(I)) - if (C->isNullValue()) + if (ConstantInt *C = dyn_cast<ConstantInt>(I)) + if (C->isZero()) continue; return false; } @@ -284,21 +278,6 @@ public: } return true; } - - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const GEPOperator *) { return true; } - static inline bool classof(const GetElementPtrInst *) { return true; } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::GetElementPtr; - } - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::GetElementPtr; - } - static inline bool classof(const Value *V) { - return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || - (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); - } }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Pass.h b/contrib/llvm/include/llvm/Pass.h index f4c6eed..ed0fb39 100644 --- a/contrib/llvm/include/llvm/Pass.h +++ b/contrib/llvm/include/llvm/Pass.h @@ -57,6 +57,7 @@ enum PassManagerType { PMT_CallGraphPassManager, ///< CGPassManager PMT_FunctionPassManager, ///< FPPassManager PMT_LoopPassManager, ///< LPPassManager + PMT_RegionPassManager, ///< RGPassManager PMT_BasicBlockPassManager, ///< BBPassManager PMT_Last }; @@ -64,13 +65,14 @@ enum PassManagerType { // Different types of passes. enum PassKind { PT_BasicBlock, + PT_Region, PT_Loop, PT_Function, PT_CallGraphSCC, PT_Module, PT_PassManager }; - + //===----------------------------------------------------------------------===// /// Pass interface - Implemented by all 'passes'. Subclass this if you are an /// interprocedural optimization or you do not fit into any of the more diff --git a/contrib/llvm/include/llvm/PassManagers.h b/contrib/llvm/include/llvm/PassManagers.h index 17f4a05..c4f409e 100644 --- a/contrib/llvm/include/llvm/PassManagers.h +++ b/contrib/llvm/include/llvm/PassManagers.h @@ -106,6 +106,7 @@ enum PassDebuggingString { ON_BASICBLOCK_MSG, // "' on BasicBlock '" + PassName + "'...\n" ON_FUNCTION_MSG, // "' on Function '" + FunctionName + "'...\n" ON_MODULE_MSG, // "' on Module '" + ModuleName + "'...\n" + ON_REGION_MSG, // " 'on Region ...\n'" ON_LOOP_MSG, // " 'on Loop ...\n'" ON_CG_MSG // "' on Call Graph ...\n'" }; @@ -184,10 +185,10 @@ public: void schedulePass(Pass *P); /// Set pass P as the last user of the given analysis passes. - void setLastUser(SmallVector<Pass *, 12> &AnalysisPasses, Pass *P); + void setLastUser(const SmallVectorImpl<Pass *> &AnalysisPasses, Pass *P); /// Collect passes whose last user is P - void collectLastUses(SmallVector<Pass *, 12> &LastUses, Pass *P); + void collectLastUses(SmallVectorImpl<Pass *> &LastUses, Pass *P); /// Find the pass that implements Analysis AID. Search immutable /// passes and all pass managers. If desired pass is not found @@ -205,7 +206,7 @@ public: ImmutablePasses.push_back(P); } - inline SmallVector<ImmutablePass *, 8>& getImmutablePasses() { + inline SmallVectorImpl<ImmutablePass *>& getImmutablePasses() { return ImmutablePasses; } @@ -313,8 +314,8 @@ public: /// Populate RequiredPasses with analysis pass that are required by /// pass P and are available. Populate ReqPassNotAvailable with analysis /// pass that are required by pass P but are not available. - void collectRequiredAnalysis(SmallVector<Pass *, 8> &RequiredPasses, - SmallVector<AnalysisID, 8> &ReqPassNotAvailable, + void collectRequiredAnalysis(SmallVectorImpl<Pass *> &RequiredPasses, + SmallVectorImpl<AnalysisID> &ReqPassNotAvailable, Pass *P); /// All Required analyses should be available to the pass as it runs! Here diff --git a/contrib/llvm/include/llvm/PassRegistry.h b/contrib/llvm/include/llvm/PassRegistry.h index 5907139..5d89c49 100644 --- a/contrib/llvm/include/llvm/PassRegistry.h +++ b/contrib/llvm/include/llvm/PassRegistry.h @@ -8,61 +8,74 @@ //===----------------------------------------------------------------------===// // // This file defines PassRegistry, a class that is used in the initialization -// and registration of passes. At initialization, passes are registered with -// the PassRegistry, which is later provided to the PassManager for dependency -// resolution and similar tasks. +// and registration of passes. At application startup, passes are registered +// with the PassRegistry, which is later provided to the PassManager for +// dependency resolution and similar tasks. // //===----------------------------------------------------------------------===// #ifndef LLVM_PASSREGISTRY_H #define LLVM_PASSREGISTRY_H -#include "llvm/ADT/StringMap.h" -#include "llvm/System/DataTypes.h" -#include "llvm/System/Mutex.h" -#include <map> -#include <set> -#include <vector> +#include "llvm/ADT/StringRef.h" namespace llvm { class PassInfo; struct PassRegistrationListener; +/// PassRegistry - This class manages the registration and intitialization of +/// the pass subsystem as application startup, and assists the PassManager +/// in resolving pass dependencies. +/// NOTE: PassRegistry is NOT thread-safe. If you want to use LLVM on multiple +/// threads simultaneously, you will need to use a separate PassRegistry on +/// each thread. class PassRegistry { - /// Guards the contents of this class. - mutable sys::SmartMutex<true> Lock; - - /// PassInfoMap - Keep track of the PassInfo object for each registered pass. - typedef std::map<const void*, const PassInfo*> MapType; - MapType PassInfoMap; - - typedef StringMap<const PassInfo*> StringMapType; - StringMapType PassInfoStringMap; - - /// AnalysisGroupInfo - Keep track of information for each analysis group. - struct AnalysisGroupInfo { - std::set<const PassInfo *> Implementations; - }; - std::map<const PassInfo*, AnalysisGroupInfo> AnalysisGroupInfoMap; - - std::vector<PassRegistrationListener*> Listeners; - + mutable void *pImpl; + void *getImpl() const; + public: + PassRegistry() : pImpl(0) { } + ~PassRegistry(); + + /// getPassRegistry - Access the global registry object, which is + /// automatically initialized at application launch and destroyed by + /// llvm_shutdown. static PassRegistry *getPassRegistry(); + /// getPassInfo - Look up a pass' corresponding PassInfo, indexed by the pass' + /// type identifier (&MyPass::ID). const PassInfo *getPassInfo(const void *TI) const; + + /// getPassInfo - Look up a pass' corresponding PassInfo, indexed by the pass' + /// argument string. const PassInfo *getPassInfo(StringRef Arg) const; - void registerPass(const PassInfo &PI); + /// registerPass - Register a pass (by means of its PassInfo) with the + /// registry. Required in order to use the pass with a PassManager. + void registerPass(const PassInfo &PI, bool ShouldFree = false); + + /// registerPass - Unregister a pass (by means of its PassInfo) with the + /// registry. void unregisterPass(const PassInfo &PI); - /// Analysis Group Mechanisms. + /// registerAnalysisGroup - Register an analysis group (or a pass implementing + // an analysis group) with the registry. Like registerPass, this is required + // in order for a PassManager to be able to use this group/pass. void registerAnalysisGroup(const void *InterfaceID, const void *PassID, - PassInfo& Registeree, bool isDefault); + PassInfo& Registeree, bool isDefault, + bool ShouldFree = false); + /// enumerateWith - Enumerate the registered passes, calling the provided + /// PassRegistrationListener's passEnumerate() callback on each of them. void enumerateWith(PassRegistrationListener *L); - void addRegistrationListener(PassRegistrationListener* L); + + /// addRegistrationListener - Register the given PassRegistrationListener + /// to receive passRegistered() callbacks whenever a new pass is registered. + void addRegistrationListener(PassRegistrationListener *L); + + /// removeRegistrationListener - Unregister a PassRegistrationListener so that + /// it no longer receives passRegistered() callbacks. void removeRegistrationListener(PassRegistrationListener *L); }; diff --git a/contrib/llvm/include/llvm/PassSupport.h b/contrib/llvm/include/llvm/PassSupport.h index 0f559d6..0827909 100644 --- a/contrib/llvm/include/llvm/PassSupport.h +++ b/contrib/llvm/include/llvm/PassSupport.h @@ -23,6 +23,9 @@ #include "Pass.h" #include "llvm/PassRegistry.h" +#include "llvm/InitializePasses.h" +#include "llvm/Support/Atomic.h" +#include <vector> namespace llvm { @@ -54,17 +57,14 @@ public: NormalCtor_t normal, bool isCFGOnly, bool is_analysis) : PassName(name), PassArgument(arg), PassID(pi), IsCFGOnlyPass(isCFGOnly), - IsAnalysis(is_analysis), IsAnalysisGroup(false), NormalCtor(normal) { - PassRegistry::getPassRegistry()->registerPass(*this); - } + IsAnalysis(is_analysis), IsAnalysisGroup(false), NormalCtor(normal) { } /// PassInfo ctor - Do not call this directly, this should only be invoked /// through RegisterPass. This version is for use by analysis groups; it /// does not auto-register the pass. PassInfo(const char *name, const void *pi) : PassName(name), PassArgument(""), PassID(pi), IsCFGOnlyPass(false), - IsAnalysis(false), IsAnalysisGroup(true), NormalCtor(0) { - } + IsAnalysis(false), IsAnalysisGroup(true), NormalCtor(0) { } /// getPassName - Return the friendly name for the pass, never returns null /// @@ -129,8 +129,50 @@ private: PassInfo(const PassInfo &); // do not implement }; +#define CALL_ONCE_INITIALIZATION(function) \ + static volatile sys::cas_flag initialized = 0; \ + sys::cas_flag old_val = sys::CompareAndSwap(&initialized, 1, 0); \ + if (old_val == 0) { \ + function(Registry); \ + sys::MemoryFence(); \ + initialized = 2; \ + } else { \ + sys::cas_flag tmp = initialized; \ + sys::MemoryFence(); \ + while (tmp != 2) { \ + tmp = initialized; \ + sys::MemoryFence(); \ + } \ + } + #define INITIALIZE_PASS(passName, arg, name, cfg, analysis) \ - static RegisterPass<passName> passName ## _info(arg, name, cfg, analysis) + static void* initialize##passName##PassOnce(PassRegistry &Registry) { \ + PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \ + PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis); \ + Registry.registerPass(*PI, true); \ + return PI; \ + } \ + void llvm::initialize##passName##Pass(PassRegistry &Registry) { \ + CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ + } + +#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis) \ + static void* initialize##passName##PassOnce(PassRegistry &Registry) { + +#define INITIALIZE_PASS_DEPENDENCY(depName) \ + initialize##depName##Pass(Registry); +#define INITIALIZE_AG_DEPENDENCY(depName) \ + initialize##depName##AnalysisGroup(Registry); + +#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis) \ + PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \ + PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis); \ + Registry.registerPass(*PI, true); \ + return PI; \ + } \ + void llvm::initialize##passName##Pass(PassRegistry &Registry) { \ + CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ + } template<typename PassName> Pass *callDefaultCtor() { return new PassName(); } @@ -161,7 +203,7 @@ struct RegisterPass : public PassInfo { : PassInfo(Name, PassArg, &passName::ID, PassInfo::NormalCtor_t(callDefaultCtor<passName>), CFGOnly, is_analysis) { - + PassRegistry::getPassRegistry()->registerPass(*this); } }; @@ -186,7 +228,7 @@ struct RegisterPass : public PassInfo { /// a nice name with the interface. /// class RegisterAGBase : public PassInfo { -protected: +public: RegisterAGBase(const char *Name, const void *InterfaceID, const void *PassID = 0, @@ -206,9 +248,52 @@ struct RegisterAnalysisGroup : public RegisterAGBase { } }; +#define INITIALIZE_ANALYSIS_GROUP(agName, name, defaultPass) \ + static void* initialize##agName##AnalysisGroupOnce(PassRegistry &Registry) { \ + initialize##defaultPass##Pass(Registry); \ + PassInfo *AI = new PassInfo(name, & agName :: ID); \ + Registry.registerAnalysisGroup(& agName ::ID, 0, *AI, false, true); \ + return AI; \ + } \ + void llvm::initialize##agName##AnalysisGroup(PassRegistry &Registry) { \ + CALL_ONCE_INITIALIZATION(initialize##agName##AnalysisGroupOnce) \ + } + + #define INITIALIZE_AG_PASS(passName, agName, arg, name, cfg, analysis, def) \ - static RegisterPass<passName> passName ## _info(arg, name, cfg, analysis); \ - static RegisterAnalysisGroup<agName, def> passName ## _ag(passName ## _info) + static void* initialize##passName##PassOnce(PassRegistry &Registry) { \ + if (!def) initialize##agName##AnalysisGroup(Registry); \ + PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \ + PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis); \ + Registry.registerPass(*PI, true); \ + \ + PassInfo *AI = new PassInfo(name, & agName :: ID); \ + Registry.registerAnalysisGroup(& agName ::ID, & passName ::ID, \ + *AI, def, true); \ + return AI; \ + } \ + void llvm::initialize##passName##Pass(PassRegistry &Registry) { \ + CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ + } + + +#define INITIALIZE_AG_PASS_BEGIN(passName, agName, arg, n, cfg, analysis, def) \ + static void* initialize##passName##PassOnce(PassRegistry &Registry) { \ + if (!def) initialize##agName##AnalysisGroup(Registry); + +#define INITIALIZE_AG_PASS_END(passName, agName, arg, n, cfg, analysis, def) \ + PassInfo *PI = new PassInfo(n, arg, & passName ::ID, \ + PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis); \ + Registry.registerPass(*PI, true); \ + \ + PassInfo *AI = new PassInfo(n, & agName :: ID); \ + Registry.registerAnalysisGroup(& agName ::ID, & passName ::ID, \ + *AI, def, true); \ + return AI; \ + } \ + void llvm::initialize##passName##Pass(PassRegistry &Registry) { \ + CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ + } //===--------------------------------------------------------------------------- /// PassRegistrationListener class - This class is meant to be derived from by diff --git a/contrib/llvm/include/llvm/System/AIXDataTypesFix.h b/contrib/llvm/include/llvm/Support/AIXDataTypesFix.h index 8dbf02f..a9a9147 100644 --- a/contrib/llvm/include/llvm/System/AIXDataTypesFix.h +++ b/contrib/llvm/include/llvm/Support/AIXDataTypesFix.h @@ -1,4 +1,4 @@ -//===-- llvm/System/AIXDataTypesFix.h - Fix datatype defs ------*- C++ -*-===// +//===-- llvm/Support/AIXDataTypesFix.h - Fix datatype defs ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/include/llvm/Support/AlignOf.h b/contrib/llvm/include/llvm/Support/AlignOf.h index 6a7a1a6..cebfa79 100644 --- a/contrib/llvm/include/llvm/Support/AlignOf.h +++ b/contrib/llvm/include/llvm/Support/AlignOf.h @@ -49,12 +49,12 @@ struct AlignOf { }; -/// alignof - A templated function that returns the mininum alignment of +/// alignOf - A templated function that returns the minimum alignment of /// of a type. This provides no extra functionality beyond the AlignOf /// class besides some cosmetic cleanliness. Example usage: -/// alignof<int>() returns the alignment of an int. +/// alignOf<int>() returns the alignment of an int. template <typename T> -static inline unsigned alignof() { return AlignOf<T>::Alignment; } +static inline unsigned alignOf() { return AlignOf<T>::Alignment; } } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/Support/Allocator.h b/contrib/llvm/include/llvm/Support/Allocator.h index 4a7251f..c680709 100644 --- a/contrib/llvm/include/llvm/Support/Allocator.h +++ b/contrib/llvm/include/llvm/Support/Allocator.h @@ -16,13 +16,15 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/MathExtras.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <algorithm> #include <cassert> #include <cstdlib> #include <cstddef> namespace llvm { +template <typename T> struct ReferenceAdder { typedef T& result; }; +template <typename T> struct ReferenceAdder<T&> { typedef T result; }; class MallocAllocator { public: @@ -201,7 +203,7 @@ public: char *End = Slab == Allocator.CurSlab ? Allocator.CurPtr : (char *)Slab + Slab->Size; for (char *Ptr = (char*)(Slab+1); Ptr < End; Ptr += sizeof(T)) { - Ptr = Allocator.AlignPtr(Ptr, alignof<T>()); + Ptr = Allocator.AlignPtr(Ptr, alignOf<T>()); if (Ptr + sizeof(T) <= End) reinterpret_cast<T*>(Ptr)->~T(); } @@ -221,16 +223,12 @@ public: inline void *operator new(size_t Size, llvm::BumpPtrAllocator &Allocator) { struct S { char c; -#ifdef __GNUC__ - char x __attribute__((aligned)); -#else union { double D; long double LD; long long L; void *P; } x; -#endif }; return Allocator.Allocate(Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x))); diff --git a/contrib/llvm/include/llvm/System/Atomic.h b/contrib/llvm/include/llvm/Support/Atomic.h index fc19369..1a6c606 100644 --- a/contrib/llvm/include/llvm/System/Atomic.h +++ b/contrib/llvm/include/llvm/Support/Atomic.h @@ -1,4 +1,4 @@ -//===- llvm/System/Atomic.h - Atomic Operations -----------------*- C++ -*-===// +//===- llvm/Support/Atomic.h - Atomic Operations -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_ATOMIC_H #define LLVM_SYSTEM_ATOMIC_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { namespace sys { diff --git a/contrib/llvm/include/llvm/Support/COFF.h b/contrib/llvm/include/llvm/Support/COFF.h index 78254ae..6739255 100644 --- a/contrib/llvm/include/llvm/Support/COFF.h +++ b/contrib/llvm/include/llvm/Support/COFF.h @@ -11,7 +11,7 @@ // // Structures and enums defined within this file where created using // information from Microsoft's publicly available PE/COFF format document: -// +// // Microsoft Portable Executable and Common Object File Format Specification // Revision 8.1 - February 15, 2008 // @@ -23,7 +23,7 @@ #ifndef LLVM_SUPPORT_WIN_COFF_H #define LLVM_SUPPORT_WIN_COFF_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cstring> namespace llvm { @@ -69,7 +69,7 @@ namespace COFF { SF_ClassMask = 0x00FF0000, SF_ClassShift = 16, - SF_WeakReference = 0x01000000 + SF_WeakExternal = 0x01000000 }; enum SymbolSectionNumber { @@ -133,13 +133,13 @@ namespace COFF { }; enum SymbolComplexType { - IMAGE_SYM_DTYPE_NULL = 0, ///< No complex type; simple scalar variable. + IMAGE_SYM_DTYPE_NULL = 0, ///< No complex type; simple scalar variable. IMAGE_SYM_DTYPE_POINTER = 1, ///< A pointer to base type. IMAGE_SYM_DTYPE_FUNCTION = 2, ///< A function that returns a base type. IMAGE_SYM_DTYPE_ARRAY = 3, ///< An array of base type. - + /// Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT)) - SCT_COMPLEX_TYPE_SHIFT = 8 + SCT_COMPLEX_TYPE_SHIFT = 4 }; struct section { diff --git a/contrib/llvm/include/llvm/Support/CallSite.h b/contrib/llvm/include/llvm/Support/CallSite.h index 9b6a409..8a998a8 100644 --- a/contrib/llvm/include/llvm/Support/CallSite.h +++ b/contrib/llvm/include/llvm/Support/CallSite.h @@ -52,12 +52,7 @@ public: CallSiteBase(CallTy *CI) : I(CI, true) { assert(CI); } CallSiteBase(InvokeTy *II) : I(II, false) { assert(II); } CallSiteBase(ValTy *II) { *this = get(II); } - CallSiteBase(InstrTy *II) { - assert(II && "Null instruction given?"); - *this = get(II); - assert(I.getPointer() && "Not a call?"); - } - +protected: /// CallSiteBase::get - This static method is sort of like a constructor. It /// will create an appropriate call site for a Call or Invoke instruction, but /// it can also create a null initialized CallSiteBase object for something @@ -72,7 +67,7 @@ public: } return CallSiteBase(); } - +public: /// isCall - true if a CallInst is enclosed. /// Note that !isCall() does not mean it is an InvokeInst enclosed, /// it also could signify a NULL Instruction pointer. @@ -282,16 +277,6 @@ public: bool operator==(const CallSite &CS) const { return I == CS.I; } bool operator!=(const CallSite &CS) const { return I != CS.I; } - - /// CallSite::get - This static method is sort of like a constructor. It will - /// create an appropriate call site for a Call or Invoke instruction, but it - /// can also create a null initialized CallSite object for something which is - /// NOT a call site. - /// - static CallSite get(Value *V) { - return Base::get(V); - } - bool operator<(const CallSite &CS) const { return getInstruction() < CS.getInstruction(); } diff --git a/contrib/llvm/include/llvm/Support/Casting.h b/contrib/llvm/include/llvm/Support/Casting.h index c589171..6bb9806 100644 --- a/contrib/llvm/include/llvm/Support/Casting.h +++ b/contrib/llvm/include/llvm/Support/Casting.h @@ -232,8 +232,8 @@ inline typename cast_retty<X, Y>::ret_type dyn_cast(const Y &Val) { // value is accepted. // template <class X, class Y> -inline typename cast_retty<X, Y>::ret_type dyn_cast_or_null(const Y &Val) { - return (Val && isa<X>(Val)) ? cast<X, Y>(Val) : 0; +inline typename cast_retty<X, Y*>::ret_type dyn_cast_or_null(Y *Val) { + return (Val && isa<X>(Val)) ? cast<X>(Val) : 0; } } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Support/Compiler.h b/contrib/llvm/include/llvm/Support/Compiler.h index 14b36f8..67f0fd7 100644 --- a/contrib/llvm/include/llvm/Support/Compiler.h +++ b/contrib/llvm/include/llvm/Support/Compiler.h @@ -15,48 +15,50 @@ #ifndef LLVM_SUPPORT_COMPILER_H #define LLVM_SUPPORT_COMPILER_H +#ifndef __has_feature +# define __has_feature(x) 0 +#endif + /// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked /// into a shared library, then the class should be private to the library and /// not accessible from outside it. Can also be used to mark variables and /// functions, making them private to any shared library they are linked into. - -/// LLVM_GLOBAL_VISIBILITY - If a class marked with this attribute is linked -/// into a shared library, then the class will be accessible from outside the -/// the library. Can also be used to mark variables and functions, making them -/// accessible from outside any shared library they are linked into. -#if defined(__MINGW32__) || defined(__CYGWIN__) -#define LLVM_LIBRARY_VISIBILITY -#define LLVM_GLOBAL_VISIBILITY __declspec(dllexport) -#elif (__GNUC__ >= 4) +#if (__GNUC__ >= 4) && !defined(__MINGW32__) && !defined(__CYGWIN__) #define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) -#define LLVM_GLOBAL_VISIBILITY __attribute__ ((visibility("default"))) #else #define LLVM_LIBRARY_VISIBILITY -#define LLVM_GLOBAL_VISIBILITY #endif #if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -#define ATTRIBUTE_USED __attribute__((__used__)) +#define LLVM_ATTRIBUTE_USED __attribute__((__used__)) #else -#define ATTRIBUTE_USED +#define LLVM_ATTRIBUTE_USED #endif +// Some compilers warn about unused functions. When a function is sometimes +// used or not depending on build settings (e.g. a function only called from +// within "assert"), this attribute can be used to suppress such warnings. +// +// However, it shouldn't be used for unused *variables*, as those have a much +// more portable solution: +// (void)unused_var_name; +// Prefer cast-to-void wherever it is sufficient. #if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -#define ATTRIBUTE_UNUSED __attribute__((__unused__)) +#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__)) #else -#define ATTRIBUTE_UNUSED +#define LLVM_ATTRIBUTE_UNUSED #endif #ifdef __GNUC__ // aka 'ATTRIBUTE_CONST' but following LLVM Conventions. -#define ATTRIBUTE_READNONE __attribute__((__const__)) +#define LLVM_ATTRIBUTE_READNONE __attribute__((__const__)) #else -#define ATTRIBUTE_READNONE +#define LLVM_ATTRIBUTE_READNONE #endif #ifdef __GNUC__ // aka 'ATTRIBUTE_PURE' but following LLVM Conventions. -#define ATTRIBUTE_READONLY __attribute__((__pure__)) +#define LLVM_ATTRIBUTE_READONLY __attribute__((__pure__)) #else -#define ATTRIBUTE_READONLY +#define LLVM_ATTRIBUTE_READONLY #endif #if (__GNUC__ >= 4) @@ -78,34 +80,50 @@ #define TEMPLATE_INSTANTIATION(X) #endif -// DISABLE_INLINE - On compilers where we have a directive to do so, mark a -// method "not for inlining". +// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, +// mark a method "not for inlining". #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -#define DISABLE_INLINE __attribute__((noinline)) +#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) #elif defined(_MSC_VER) -#define DISABLE_INLINE __declspec(noinline) +#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) #else -#define DISABLE_INLINE +#define LLVM_ATTRIBUTE_NOINLINE #endif -// ALWAYS_INLINE - On compilers where we have a directive to do so, mark a -// method "always inline" because it is performance sensitive. -// GCC 3.4 supported this but is buggy in various cases and produces -// unimplemented errors, just use it in GCC 4.0 and later. +// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do +// so, mark a method "always inline" because it is performance sensitive. GCC +// 3.4 supported this but is buggy in various cases and produces unimplemented +// errors, just use it in GCC 4.0 and later. #if __GNUC__ > 3 -#define ALWAYS_INLINE __attribute__((always_inline)) +#define LLVM_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline #else -// TODO: No idea how to do this with MSVC. -#define ALWAYS_INLINE +#define LLVM_ATTRIBUTE_ALWAYS_INLINE #endif #ifdef __GNUC__ -#define NORETURN __attribute__((noreturn)) +#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn) +#else +#define LLVM_ATTRIBUTE_NORETURN +#endif + +// LLVM_ATTRIBUTE_DEPRECATED(decl, "message") +#if __has_feature(attribute_deprecated_with_message) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl __attribute__((deprecated(message))) +#elif defined(__GNUC__) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl __attribute__((deprecated)) #elif defined(_MSC_VER) -#define NORETURN __declspec(noreturn) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + __declspec(deprecated(message)) decl #else -#define NORETURN +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl #endif #endif diff --git a/contrib/llvm/include/llvm/Support/ConstantFolder.h b/contrib/llvm/include/llvm/Support/ConstantFolder.h index ea6c5fd..bd3765d 100644 --- a/contrib/llvm/include/llvm/Support/ConstantFolder.h +++ b/contrib/llvm/include/llvm/Support/ConstantFolder.h @@ -33,50 +33,34 @@ public: // Binary Operators //===--------------------------------------------------------------------===// - Constant *CreateAdd(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getAdd(LHS, RHS); - } - Constant *CreateNSWAdd(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNSWAdd(LHS, RHS); - } - Constant *CreateNUWAdd(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNUWAdd(LHS, RHS); + Constant *CreateAdd(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW); } Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFAdd(LHS, RHS); } - Constant *CreateSub(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getSub(LHS, RHS); - } - Constant *CreateNSWSub(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNSWSub(LHS, RHS); - } - Constant *CreateNUWSub(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNUWSub(LHS, RHS); + Constant *CreateSub(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW); } Constant *CreateFSub(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFSub(LHS, RHS); } - Constant *CreateMul(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getMul(LHS, RHS); - } - Constant *CreateNSWMul(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNSWMul(LHS, RHS); - } - Constant *CreateNUWMul(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNUWMul(LHS, RHS); + Constant *CreateMul(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW); } Constant *CreateFMul(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFMul(LHS, RHS); } - Constant *CreateUDiv(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getUDiv(LHS, RHS); - } - Constant *CreateSDiv(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getSDiv(LHS, RHS); + Constant *CreateUDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getUDiv(LHS, RHS, isExact); } - Constant *CreateExactSDiv(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getExactSDiv(LHS, RHS); + Constant *CreateSDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getSDiv(LHS, RHS, isExact); } Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFDiv(LHS, RHS); @@ -90,14 +74,17 @@ public: Constant *CreateFRem(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFRem(LHS, RHS); } - Constant *CreateShl(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getShl(LHS, RHS); + Constant *CreateShl(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW); } - Constant *CreateLShr(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getLShr(LHS, RHS); + Constant *CreateLShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getLShr(LHS, RHS, isExact); } - Constant *CreateAShr(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getAShr(LHS, RHS); + Constant *CreateAShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getAShr(LHS, RHS, isExact); } Constant *CreateAnd(Constant *LHS, Constant *RHS) const { return ConstantExpr::getAnd(LHS, RHS); @@ -118,14 +105,9 @@ public: // Unary Operators //===--------------------------------------------------------------------===// - Constant *CreateNeg(Constant *C) const { - return ConstantExpr::getNeg(C); - } - Constant *CreateNSWNeg(Constant *C) const { - return ConstantExpr::getNSWNeg(C); - } - Constant *CreateNUWNeg(Constant *C) const { - return ConstantExpr::getNUWNeg(C); + Constant *CreateNeg(Constant *C, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getNeg(C, HasNUW, HasNSW); } Constant *CreateFNeg(Constant *C) const { return ConstantExpr::getFNeg(C); diff --git a/contrib/llvm/include/llvm/Support/ConstantRange.h b/contrib/llvm/include/llvm/Support/ConstantRange.h index 29086b2..ced3a2c 100644 --- a/contrib/llvm/include/llvm/Support/ConstantRange.h +++ b/contrib/llvm/include/llvm/Support/ConstantRange.h @@ -33,7 +33,7 @@ #define LLVM_SUPPORT_CONSTANT_RANGE_H #include "llvm/ADT/APInt.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { @@ -54,7 +54,7 @@ public: /// @brief Initialize a range of values explicitly. This will assert out if /// Lower==Upper and Lower != Min or Max value for its type. It will also /// assert out if the two APInt's are not the same bit width. - ConstantRange(const APInt& Lower, const APInt& Upper); + ConstantRange(const APInt &Lower, const APInt &Upper); /// makeICmpRegion - Produce the smallest range that contains all values that /// might satisfy the comparison specified by Pred when compared to any value @@ -92,6 +92,11 @@ public: /// bool isWrappedSet() const; + /// isSignWrappedSet - Return true if this set wraps around the INT_MIN of + /// its bitwidth, for example: i8 [120, 140). + /// + bool isSignWrappedSet() const; + /// contains - Return true if the specified value is in the set. /// bool contains(const APInt &Val) const; @@ -219,6 +224,14 @@ public: /// \p Other. ConstantRange udiv(const ConstantRange &Other) const; + /// binaryAnd - return a new range representing the possible values resulting + /// from a binary-and of a value in this range by a value in \p Other. + ConstantRange binaryAnd(const ConstantRange &Other) const; + + /// binaryOr - return a new range representing the possible values resulting + /// from a binary-or of a value in this range by a value in \p Other. + ConstantRange binaryOr(const ConstantRange &Other) const; + /// shl - Return a new range representing the possible values resulting /// from a left shift of a value in this range by a value in \p Other. /// TODO: This isn't fully implemented yet. diff --git a/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h b/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h index d66609f..2e9b5d4 100644 --- a/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h +++ b/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h @@ -67,6 +67,14 @@ public: /// the backtrace of the crash on failures. bool RunSafely(void (*Fn)(void*), void *UserData); + /// \brief Execute the provide callback function (with the given arguments) in + /// a protected context which is run in another thread (optionally with a + /// requested stack size). + /// + /// See RunSafely() and llvm_execute_on_thread(). + bool RunSafelyOnThread(void (*Fn)(void*), void *UserData, + unsigned RequestedStackSize = 0); + /// \brief Explicitly trigger a crash recovery in the current process, and /// return failure from RunSafely(). This function does not return. void HandleCrash(); diff --git a/contrib/llvm/include/llvm/Support/DataTypes.h.in b/contrib/llvm/include/llvm/Support/DataTypes.h.in new file mode 100644 index 0000000..5965e8c --- /dev/null +++ b/contrib/llvm/include/llvm/Support/DataTypes.h.in @@ -0,0 +1,111 @@ +/*===-- include/System/DataTypes.h - Define fixed size types -----*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file contains definitions to figure out the size of _HOST_ data types.*| +|* This file is important because different host OS's define different macros,*| +|* which makes portability tough. This file exports the following *| +|* definitions: *| +|* *| +|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*| +|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *| +|* *| +|* No library is required when using these functions. *| +|* *| +|*===----------------------------------------------------------------------===*/ + +/* Please leave this file C-compatible. */ + +#ifndef SUPPORT_DATATYPES_H +#define SUPPORT_DATATYPES_H + +#undef HAVE_SYS_TYPES_H +#undef HAVE_INTTYPES_H +#undef HAVE_STDINT_H +#undef HAVE_UINT64_T +#undef HAVE_U_INT64_T + +#ifdef __cplusplus +#include <cmath> +#else +#include <math.h> +#endif + +/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS + being defined. We would define it here, but in order to prevent Bad Things + happening when system headers or C++ STL headers include stdint.h before we + define it here, we define it on the g++ command line (in Makefile.rules). */ +#if !defined(__STDC_LIMIT_MACROS) +# error "Must #define __STDC_LIMIT_MACROS before #including System/DataTypes.h" +#endif + +#if !defined(__STDC_CONSTANT_MACROS) +# error "Must #define __STDC_CONSTANT_MACROS before " \ + "#including System/DataTypes.h" +#endif + +/* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +#ifdef _AIX +#include "llvm/Support/AIXDataTypesFix.h" +#endif + +/* Handle incorrect definition of uint64_t as u_int64_t */ +#ifndef HAVE_UINT64_T +#ifdef HAVE_U_INT64_T +typedef u_int64_t uint64_t; +#else +# error "Don't have a definition for uint64_t on this platform" +#endif +#endif + +#ifdef _OpenBSD_ +#define INT8_MAX 127 +#define INT8_MIN -128 +#define UINT8_MAX 255 +#define INT16_MAX 32767 +#define INT16_MIN -32768 +#define UINT16_MAX 65535 +#define INT32_MAX 2147483647 +#define INT32_MIN -2147483648 +#define UINT32_MAX 4294967295U +#endif + +/* Set defaults for constants which we cannot find. */ +#if !defined(INT64_MAX) +# define INT64_MAX 9223372036854775807LL +#endif +#if !defined(INT64_MIN) +# define INT64_MIN ((-INT64_MAX)-1) +#endif +#if !defined(UINT64_MAX) +# define UINT64_MAX 0xffffffffffffffffULL +#endif + +#if __GNUC__ > 3 +#define END_WITH_NULL __attribute__((sentinel)) +#else +#define END_WITH_NULL +#endif + +#ifndef HUGE_VALF +#define HUGE_VALF (float)HUGE_VAL +#endif + +#endif /* SUPPORT_DATATYPES_H */ diff --git a/contrib/llvm/include/llvm/System/Disassembler.h b/contrib/llvm/include/llvm/Support/Disassembler.h index e11e792..6d1cc0f 100644 --- a/contrib/llvm/include/llvm/System/Disassembler.h +++ b/contrib/llvm/include/llvm/Support/Disassembler.h @@ -15,7 +15,7 @@ #ifndef LLVM_SYSTEM_DISASSEMBLER_H #define LLVM_SYSTEM_DISASSEMBLER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> namespace llvm { diff --git a/contrib/llvm/include/llvm/Support/Dwarf.h b/contrib/llvm/include/llvm/Support/Dwarf.h index 3ca8d96..5d0b5a9 100644 --- a/contrib/llvm/include/llvm/Support/Dwarf.h +++ b/contrib/llvm/include/llvm/Support/Dwarf.h @@ -22,7 +22,8 @@ namespace llvm { // Debug info constants. enum { - LLVMDebugVersion = (8 << 16), // Current version of debug information. + LLVMDebugVersion = (9 << 16), // Current version of debug information. + LLVMDebugVersion8 = (8 << 16), // Cconstant for version 8. LLVMDebugVersion7 = (7 << 16), // Constant for version 7. LLVMDebugVersion6 = (6 << 16), // Constant for version 6. LLVMDebugVersion5 = (5 << 16), // Constant for version 5. @@ -44,11 +45,9 @@ enum llvm_dwarf_constants { // llvm mock tags DW_TAG_invalid = ~0U, // Tag for invalid results. - DW_TAG_anchor = 0, // Tag for descriptor anchors. DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables. DW_TAG_arg_variable = 0x101, // Tag for argument variables. DW_TAG_return_variable = 0x102, // Tag for return variables. - DW_TAG_vector_type = 0x103, // Tag for vector types. DW_TAG_user_base = 0x1000, // Recommended base for user tags. @@ -118,6 +117,7 @@ enum dwarf_constants { DW_TAG_imported_unit = 0x3d, DW_TAG_condition = 0x3f, DW_TAG_shared_type = 0x40, + DW_TAG_rvalue_reference_type = 0x41, DW_TAG_lo_user = 0x4080, DW_TAG_hi_user = 0xffff, @@ -509,6 +509,7 @@ enum dwarf_constants { DW_DSC_range = 0x01, // Line Number Standard Opcode Encodings + DW_LNS_extended_op = 0x00, DW_LNS_copy = 0x01, DW_LNS_advance_pc = 0x02, DW_LNS_advance_line = 0x03, diff --git a/contrib/llvm/include/llvm/System/DynamicLibrary.h b/contrib/llvm/include/llvm/Support/DynamicLibrary.h index 745b8f8..e6d9ff5 100644 --- a/contrib/llvm/include/llvm/System/DynamicLibrary.h +++ b/contrib/llvm/include/llvm/Support/DynamicLibrary.h @@ -1,4 +1,4 @@ -//===-- llvm/System/DynamicLibrary.h - Portable Dynamic Library -*- C++ -*-===// +//===-- llvm/Support/DynamicLibrary.h - Portable Dynamic Library -*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/include/llvm/Support/DynamicLinker.h b/contrib/llvm/include/llvm/Support/DynamicLinker.h deleted file mode 100644 index b60ffa8..0000000 --- a/contrib/llvm/include/llvm/Support/DynamicLinker.h +++ /dev/null @@ -1,40 +0,0 @@ -//===-- llvm/Support/DynamicLinker.h - Portable Dynamic Linker --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Lightweight interface to dynamic library linking and loading, and dynamic -// symbol lookup functionality, in whatever form the operating system -// provides it. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_DYNAMICLINKER_H -#define LLVM_SUPPORT_DYNAMICLINKER_H - -#include <string> - -namespace llvm { - -/// LinkDynamicObject - Load the named file as a dynamic library -/// and link it with the currently running process. Returns false -/// on success, true if there is an error (and sets ErrorMessage -/// if it is not NULL). Analogous to dlopen(). -/// -bool LinkDynamicObject (const char *filename, std::string *ErrorMessage); - -/// GetAddressOfSymbol - Returns the address of the named symbol in -/// the currently running process, as reported by the dynamic linker, -/// or NULL if the symbol does not exist or some other error has -/// occurred. -/// -void *GetAddressOfSymbol (const char *symbolName); -void *GetAddressOfSymbol (const std::string &symbolName); - -} // End llvm namespace - -#endif // SUPPORT_DYNAMICLINKER_H diff --git a/contrib/llvm/include/llvm/Support/ELF.h b/contrib/llvm/include/llvm/Support/ELF.h index 83478b7..cc72bd5 100644 --- a/contrib/llvm/include/llvm/Support/ELF.h +++ b/contrib/llvm/include/llvm/Support/ELF.h @@ -20,7 +20,7 @@ #ifndef LLVM_SUPPORT_ELF_H #define LLVM_SUPPORT_ELF_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cstring> namespace llvm { @@ -126,25 +126,27 @@ enum { // Machine architectures enum { - EM_NONE = 0, // No machine - EM_M32 = 1, // AT&T WE 32100 - EM_SPARC = 2, // SPARC - EM_386 = 3, // Intel 386 - EM_68K = 4, // Motorola 68000 - EM_88K = 5, // Motorola 88000 - EM_486 = 6, // Intel 486 (deprecated) - EM_860 = 7, // Intel 80860 - EM_MIPS = 8, // MIPS R3000 - EM_PPC = 20, // PowerPC - EM_PPC64 = 21, // PowerPC64 - EM_ARM = 40, // ARM - EM_ALPHA = 41, // DEC Alpha - EM_SPARCV9 = 43, // SPARC V9 - EM_X86_64 = 62 // AMD64 + EM_NONE = 0, // No machine + EM_M32 = 1, // AT&T WE 32100 + EM_SPARC = 2, // SPARC + EM_386 = 3, // Intel 386 + EM_68K = 4, // Motorola 68000 + EM_88K = 5, // Motorola 88000 + EM_486 = 6, // Intel 486 (deprecated) + EM_860 = 7, // Intel 80860 + EM_MIPS = 8, // MIPS R3000 + EM_PPC = 20, // PowerPC + EM_PPC64 = 21, // PowerPC64 + EM_ARM = 40, // ARM + EM_ALPHA = 41, // DEC Alpha + EM_SPARCV9 = 43, // SPARC V9 + EM_X86_64 = 62, // AMD64 + EM_MBLAZE = 47787 // Xilinx MicroBlaze }; // Object file classes. enum { + ELFCLASSNONE = 0, ELFCLASS32 = 1, // 32-bit object file ELFCLASS64 = 2 // 64-bit object file }; @@ -231,12 +233,206 @@ enum { R_386_GOTOFF = 9, R_386_GOTPC = 10, R_386_32PLT = 11, + R_386_TLS_TPOFF = 14, + R_386_TLS_IE = 15, + R_386_TLS_GOTIE = 16, + R_386_TLS_LE = 17, + R_386_TLS_GD = 18, + R_386_TLS_LDM = 19, R_386_16 = 20, R_386_PC16 = 21, R_386_8 = 22, - R_386_PC8 = 23 + R_386_PC8 = 23, + R_386_TLS_GD_32 = 24, + R_386_TLS_GD_PUSH = 25, + R_386_TLS_GD_CALL = 26, + R_386_TLS_GD_POP = 27, + R_386_TLS_LDM_32 = 28, + R_386_TLS_LDM_PUSH = 29, + R_386_TLS_LDM_CALL = 30, + R_386_TLS_LDM_POP = 31, + R_386_TLS_LDO_32 = 32, + R_386_TLS_IE_32 = 33, + R_386_TLS_LE_32 = 34, + R_386_TLS_DTPMOD32 = 35, + R_386_TLS_DTPOFF32 = 36, + R_386_TLS_TPOFF32 = 37, + R_386_TLS_GOTDESC = 39, + R_386_TLS_DESC_CALL = 40, + R_386_TLS_DESC = 41, + R_386_IRELATIVE = 42, + R_386_NUM = 43 +}; + +// MBlaze relocations. +enum { + R_MICROBLAZE_NONE = 0, + R_MICROBLAZE_32 = 1, + R_MICROBLAZE_32_PCREL = 2, + R_MICROBLAZE_64_PCREL = 3, + R_MICROBLAZE_32_PCREL_LO = 4, + R_MICROBLAZE_64 = 5, + R_MICROBLAZE_32_LO = 6, + R_MICROBLAZE_SRO32 = 7, + R_MICROBLAZE_SRW32 = 8, + R_MICROBLAZE_64_NONE = 9, + R_MICROBLAZE_32_SYM_OP_SYM = 10, + R_MICROBLAZE_GNU_VTINHERIT = 11, + R_MICROBLAZE_GNU_VTENTRY = 12, + R_MICROBLAZE_GOTPC_64 = 13, + R_MICROBLAZE_GOT_64 = 14, + R_MICROBLAZE_PLT_64 = 15, + R_MICROBLAZE_REL = 16, + R_MICROBLAZE_JUMP_SLOT = 17, + R_MICROBLAZE_GLOB_DAT = 18, + R_MICROBLAZE_GOTOFF_64 = 19, + R_MICROBLAZE_GOTOFF_32 = 20, + R_MICROBLAZE_COPY = 21 +}; + + +// ARM Specific e_flags +enum { EF_ARM_EABIMASK = 0xFF000000U }; + +// ELF Relocation types for ARM +// Meets 2.08 ABI Specs. + +enum { + R_ARM_NONE = 0x00, + R_ARM_PC24 = 0x01, + R_ARM_ABS32 = 0x02, + R_ARM_REL32 = 0x03, + R_ARM_LDR_PC_G0 = 0x04, + R_ARM_ABS16 = 0x05, + R_ARM_ABS12 = 0x06, + R_ARM_THM_ABS5 = 0x07, + R_ARM_ABS8 = 0x08, + R_ARM_SBREL32 = 0x09, + R_ARM_THM_CALL = 0x0a, + R_ARM_THM_PC8 = 0x0b, + R_ARM_BREL_ADJ = 0x0c, + R_ARM_TLS_DESC = 0x0d, + R_ARM_THM_SWI8 = 0x0e, + R_ARM_XPC25 = 0x0f, + R_ARM_THM_XPC22 = 0x10, + R_ARM_TLS_DTPMOD32 = 0x11, + R_ARM_TLS_DTPOFF32 = 0x12, + R_ARM_TLS_TPOFF32 = 0x13, + R_ARM_COPY = 0x14, + R_ARM_GLOB_DAT = 0x15, + R_ARM_JUMP_SLOT = 0x16, + R_ARM_RELATIVE = 0x17, + R_ARM_GOTOFF32 = 0x18, + R_ARM_BASE_PREL = 0x19, + R_ARM_GOT_BREL = 0x1a, + R_ARM_PLT32 = 0x1b, + R_ARM_CALL = 0x1c, + R_ARM_JUMP24 = 0x1d, + R_ARM_THM_JUMP24 = 0x1e, + R_ARM_BASE_ABS = 0x1f, + R_ARM_ALU_PCREL_7_0 = 0x20, + R_ARM_ALU_PCREL_15_8 = 0x21, + R_ARM_ALU_PCREL_23_15 = 0x22, + R_ARM_LDR_SBREL_11_0_NC = 0x23, + R_ARM_ALU_SBREL_19_12_NC = 0x24, + R_ARM_ALU_SBREL_27_20_CK = 0x25, + R_ARM_TARGET1 = 0x26, + R_ARM_SBREL31 = 0x27, + R_ARM_V4BX = 0x28, + R_ARM_TARGET2 = 0x29, + R_ARM_PREL31 = 0x2a, + R_ARM_MOVW_ABS_NC = 0x2b, + R_ARM_MOVT_ABS = 0x2c, + R_ARM_MOVW_PREL_NC = 0x2d, + R_ARM_MOVT_PREL = 0x2e, + R_ARM_THM_MOVW_ABS_NC = 0x2f, + R_ARM_THM_MOVT_ABS = 0x30, + R_ARM_THM_MOVW_PREL_NC = 0x31, + R_ARM_THM_MOVT_PREL = 0x32, + R_ARM_THM_JUMP19 = 0x33, + R_ARM_THM_JUMP6 = 0x34, + R_ARM_THM_ALU_PREL_11_0 = 0x35, + R_ARM_THM_PC12 = 0x36, + R_ARM_ABS32_NOI = 0x37, + R_ARM_REL32_NOI = 0x38, + R_ARM_ALU_PC_G0_NC = 0x39, + R_ARM_ALU_PC_G0 = 0x3a, + R_ARM_ALU_PC_G1_NC = 0x3b, + R_ARM_ALU_PC_G1 = 0x3c, + R_ARM_ALU_PC_G2 = 0x3d, + R_ARM_LDR_PC_G1 = 0x3e, + R_ARM_LDR_PC_G2 = 0x3f, + R_ARM_LDRS_PC_G0 = 0x40, + R_ARM_LDRS_PC_G1 = 0x41, + R_ARM_LDRS_PC_G2 = 0x42, + R_ARM_LDC_PC_G0 = 0x43, + R_ARM_LDC_PC_G1 = 0x44, + R_ARM_LDC_PC_G2 = 0x45, + R_ARM_ALU_SB_G0_NC = 0x46, + R_ARM_ALU_SB_G0 = 0x47, + R_ARM_ALU_SB_G1_NC = 0x48, + R_ARM_ALU_SB_G1 = 0x49, + R_ARM_ALU_SB_G2 = 0x4a, + R_ARM_LDR_SB_G0 = 0x4b, + R_ARM_LDR_SB_G1 = 0x4c, + R_ARM_LDR_SB_G2 = 0x4d, + R_ARM_LDRS_SB_G0 = 0x4e, + R_ARM_LDRS_SB_G1 = 0x4f, + R_ARM_LDRS_SB_G2 = 0x50, + R_ARM_LDC_SB_G0 = 0x51, + R_ARM_LDC_SB_G1 = 0x52, + R_ARM_LDC_SB_G2 = 0x53, + R_ARM_MOVW_BREL_NC = 0x54, + R_ARM_MOVT_BREL = 0x55, + R_ARM_MOVW_BREL = 0x56, + R_ARM_THM_MOVW_BREL_NC = 0x57, + R_ARM_THM_MOVT_BREL = 0x58, + R_ARM_THM_MOVW_BREL = 0x59, + R_ARM_TLS_GOTDESC = 0x5a, + R_ARM_TLS_CALL = 0x5b, + R_ARM_TLS_DESCSEQ = 0x5c, + R_ARM_THM_TLS_CALL = 0x5d, + R_ARM_PLT32_ABS = 0x5e, + R_ARM_GOT_ABS = 0x5f, + R_ARM_GOT_PREL = 0x60, + R_ARM_GOT_BREL12 = 0x61, + R_ARM_GOTOFF12 = 0x62, + R_ARM_GOTRELAX = 0x63, + R_ARM_GNU_VTENTRY = 0x64, + R_ARM_GNU_VTINHERIT = 0x65, + R_ARM_THM_JUMP11 = 0x66, + R_ARM_THM_JUMP8 = 0x67, + R_ARM_TLS_GD32 = 0x68, + R_ARM_TLS_LDM32 = 0x69, + R_ARM_TLS_LDO32 = 0x6a, + R_ARM_TLS_IE32 = 0x6b, + R_ARM_TLS_LE32 = 0x6c, + R_ARM_TLS_LDO12 = 0x6d, + R_ARM_TLS_LE12 = 0x6e, + R_ARM_TLS_IE12GP = 0x6f, + R_ARM_PRIVATE_0 = 0x70, + R_ARM_PRIVATE_1 = 0x71, + R_ARM_PRIVATE_2 = 0x72, + R_ARM_PRIVATE_3 = 0x73, + R_ARM_PRIVATE_4 = 0x74, + R_ARM_PRIVATE_5 = 0x75, + R_ARM_PRIVATE_6 = 0x76, + R_ARM_PRIVATE_7 = 0x77, + R_ARM_PRIVATE_8 = 0x78, + R_ARM_PRIVATE_9 = 0x79, + R_ARM_PRIVATE_10 = 0x7a, + R_ARM_PRIVATE_11 = 0x7b, + R_ARM_PRIVATE_12 = 0x7c, + R_ARM_PRIVATE_13 = 0x7d, + R_ARM_PRIVATE_14 = 0x7e, + R_ARM_PRIVATE_15 = 0x7f, + R_ARM_ME_TOO = 0x80, + R_ARM_THM_TLS_DESCSEQ16 = 0x81, + R_ARM_THM_TLS_DESCSEQ32 = 0x82 }; + + // Section header. struct Elf32_Shdr { Elf32_Word sh_name; // Section name (index into string table) @@ -273,6 +469,7 @@ enum { SHN_HIPROC = 0xff1f, // Highest processor-specific index SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables + SHN_XINDEX = 0xffff, // Mark that the index is >= SHN_LORESERVE SHN_HIRESERVE = 0xffff // Highest reserved index }; @@ -298,6 +495,18 @@ enum { SHT_LOOS = 0x60000000, // Lowest operating system-specific type. SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. SHT_LOPROC = 0x70000000, // Lowest processor architecture-specific type. + // Fixme: All this is duplicated in MCSectionELF. Why?? + // Exception Index table + SHT_ARM_EXIDX = 0x70000001U, + // BPABI DLL dynamic linking pre-emption map + SHT_ARM_PREEMPTMAP = 0x70000002U, + // Object file compatibility attributes + SHT_ARM_ATTRIBUTES = 0x70000003U, + SHT_ARM_DEBUGOVERLAY = 0x70000004U, + SHT_ARM_OVERLAYSECTION = 0x70000005U, + + SHT_X86_64_UNWIND = 0x70000001, // Unwind information + SHT_HIPROC = 0x7fffffff, // Highest processor architecture-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. SHT_HIUSER = 0xffffffff // Highest type reserved for applications. @@ -305,10 +514,58 @@ enum { // Section flags. enum { - SHF_WRITE = 0x1, // Section data should be writable during execution. - SHF_ALLOC = 0x2, // Section occupies memory during program execution. - SHF_EXECINSTR = 0x4, // Section contains executable machine instructions. - SHF_MASKPROC = 0xf0000000 // Bits indicating processor-specific flags. + // Section data should be writable during execution. + SHF_WRITE = 0x1, + + // Section occupies memory during program execution. + SHF_ALLOC = 0x2, + + // Section contains executable machine instructions. + SHF_EXECINSTR = 0x4, + + // The data in this section may be merged. + SHF_MERGE = 0x10, + + // The data in this section is null-terminated strings. + SHF_STRINGS = 0x20, + + // A field in this section holds a section header table index. + SHF_INFO_LINK = 0x40U, + + // Adds special ordering requirements for link editors. + SHF_LINK_ORDER = 0x80U, + + // This section requires special OS-specific processing to avoid incorrect + // behavior. + SHF_OS_NONCONFORMING = 0x100U, + + // This section is a member of a section group. + SHF_GROUP = 0x200U, + + // This section holds Thread-Local Storage. + SHF_TLS = 0x400U, + + // Start of target-specific flags. + + /// XCORE_SHF_CP_SECTION - All sections with the "c" flag are grouped + /// together by the linker to form the constant pool and the cp register is + /// set to the start of the constant pool by the boot code. + XCORE_SHF_CP_SECTION = 0x800U, + + /// XCORE_SHF_DP_SECTION - All sections with the "d" flag are grouped + /// together by the linker to form the data section and the dp register is + /// set to the start of the section by the boot code. + XCORE_SHF_DP_SECTION = 0x1000U, + + // Bits indicating processor-specific flags. + SHF_MASKPROC = 0xf0000000 +}; + +// Section Group Flags +enum { + GRP_COMDAT = 0x1, + GRP_MASKOS = 0x0ff00000, + GRP_MASKPROC = 0xf0000000 }; // Symbol table entries for ELF32. diff --git a/contrib/llvm/include/llvm/Support/Endian.h b/contrib/llvm/include/llvm/Support/Endian.h new file mode 100644 index 0000000..f62eab0 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/Endian.h @@ -0,0 +1,213 @@ +//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares generic functions to read and write endian specific data. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ENDIAN_H +#define LLVM_SUPPORT_ENDIAN_H + +#include "llvm/Config/config.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/SwapByteOrder.h" +#include "llvm/Support/type_traits.h" + +namespace llvm { +namespace support { + +enum endianness {big, little}; +enum alignment {unaligned, aligned}; + +namespace detail { + +template<typename value_type, alignment align> +struct alignment_access_helper; + +template<typename value_type> +struct alignment_access_helper<value_type, aligned> +{ + value_type val; +}; + +// Provides unaligned loads and stores. +#pragma pack(push) +#pragma pack(1) +template<typename value_type> +struct alignment_access_helper<value_type, unaligned> +{ + value_type val; +}; +#pragma pack(pop) + +} // end namespace detail + +namespace endian { + template<typename value_type, alignment align> + static value_type read_le(const void *memory) { + value_type t = + reinterpret_cast<const detail::alignment_access_helper + <value_type, align> *>(memory)->val; + if (sys::isBigEndianHost()) + return sys::SwapByteOrder(t); + return t; + } + + template<typename value_type, alignment align> + static void write_le(void *memory, value_type value) { + if (sys::isBigEndianHost()) + value = sys::SwapByteOrder(value); + reinterpret_cast<detail::alignment_access_helper<value_type, align> *> + (memory)->val = value; + } + + template<typename value_type, alignment align> + static value_type read_be(const void *memory) { + value_type t = + reinterpret_cast<const detail::alignment_access_helper + <value_type, align> *>(memory)->val; + if (sys::isLittleEndianHost()) + return sys::SwapByteOrder(t); + return t; + } + + template<typename value_type, alignment align> + static void write_be(void *memory, value_type value) { + if (sys::isLittleEndianHost()) + value = sys::SwapByteOrder(value); + reinterpret_cast<detail::alignment_access_helper<value_type, align> *> + (memory)->val = value; + } +} + +namespace detail { + +template<typename value_type, + endianness endian, + alignment align> +class packed_endian_specific_integral; + +template<typename value_type> +class packed_endian_specific_integral<value_type, little, unaligned> { +public: + operator value_type() const { + return endian::read_le<value_type, unaligned>(Value); + } +private: + uint8_t Value[sizeof(value_type)]; +}; + +template<typename value_type> +class packed_endian_specific_integral<value_type, big, unaligned> { +public: + operator value_type() const { + return endian::read_be<value_type, unaligned>(Value); + } +private: + uint8_t Value[sizeof(value_type)]; +}; + +template<typename value_type> +class packed_endian_specific_integral<value_type, little, aligned> { +public: + operator value_type() const { + return endian::read_le<value_type, aligned>(&Value); + } +private: + value_type Value; +}; + +template<typename value_type> +class packed_endian_specific_integral<value_type, big, aligned> { +public: + operator value_type() const { + return endian::read_be<value_type, aligned>(&Value); + } +private: + value_type Value; +}; + +} // end namespace detail + +typedef detail::packed_endian_specific_integral + <uint8_t, little, unaligned> ulittle8_t; +typedef detail::packed_endian_specific_integral + <uint16_t, little, unaligned> ulittle16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, little, unaligned> ulittle32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, little, unaligned> ulittle64_t; + +typedef detail::packed_endian_specific_integral + <int8_t, little, unaligned> little8_t; +typedef detail::packed_endian_specific_integral + <int16_t, little, unaligned> little16_t; +typedef detail::packed_endian_specific_integral + <int32_t, little, unaligned> little32_t; +typedef detail::packed_endian_specific_integral + <int64_t, little, unaligned> little64_t; + +typedef detail::packed_endian_specific_integral + <uint8_t, little, aligned> aligned_ulittle8_t; +typedef detail::packed_endian_specific_integral + <uint16_t, little, aligned> aligned_ulittle16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, little, aligned> aligned_ulittle32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, little, aligned> aligned_ulittle64_t; + +typedef detail::packed_endian_specific_integral + <int8_t, little, aligned> aligned_little8_t; +typedef detail::packed_endian_specific_integral + <int16_t, little, aligned> aligned_little16_t; +typedef detail::packed_endian_specific_integral + <int32_t, little, aligned> aligned_little32_t; +typedef detail::packed_endian_specific_integral + <int64_t, little, aligned> aligned_little64_t; + +typedef detail::packed_endian_specific_integral + <uint8_t, big, unaligned> ubig8_t; +typedef detail::packed_endian_specific_integral + <uint16_t, big, unaligned> ubig16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, big, unaligned> ubig32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, big, unaligned> ubig64_t; + +typedef detail::packed_endian_specific_integral + <int8_t, big, unaligned> big8_t; +typedef detail::packed_endian_specific_integral + <int16_t, big, unaligned> big16_t; +typedef detail::packed_endian_specific_integral + <int32_t, big, unaligned> big32_t; +typedef detail::packed_endian_specific_integral + <int64_t, big, unaligned> big64_t; + +typedef detail::packed_endian_specific_integral + <uint8_t, big, aligned> aligned_ubig8_t; +typedef detail::packed_endian_specific_integral + <uint16_t, big, aligned> aligned_ubig16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, big, aligned> aligned_ubig32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, big, aligned> aligned_ubig64_t; + +typedef detail::packed_endian_specific_integral + <int8_t, big, aligned> aligned_big8_t; +typedef detail::packed_endian_specific_integral + <int16_t, big, aligned> aligned_big16_t; +typedef detail::packed_endian_specific_integral + <int32_t, big, aligned> aligned_big32_t; +typedef detail::packed_endian_specific_integral + <int64_t, big, aligned> aligned_big64_t; + +} // end namespace llvm +} // end namespace support + +#endif diff --git a/contrib/llvm/include/llvm/System/Errno.h b/contrib/llvm/include/llvm/Support/Errno.h index 6e292ba..150bdb7 100644 --- a/contrib/llvm/include/llvm/System/Errno.h +++ b/contrib/llvm/include/llvm/Support/Errno.h @@ -1,4 +1,4 @@ -//===- llvm/System/Errno.h - Portable+convenient errno handling -*- C++ -*-===// +//===- llvm/Support/Errno.h - Portable+convenient errno handling -*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/include/llvm/Support/ErrorHandling.h b/contrib/llvm/include/llvm/Support/ErrorHandling.h index 9854657..5eca438 100644 --- a/contrib/llvm/include/llvm/Support/ErrorHandling.h +++ b/contrib/llvm/include/llvm/Support/ErrorHandling.h @@ -16,6 +16,7 @@ #define LLVM_SUPPORT_ERRORHANDLING_H #include "llvm/Support/Compiler.h" +#include "llvm/ADT/StringRef.h" #include <string> namespace llvm { @@ -72,15 +73,17 @@ namespace llvm { /// standard error, followed by a newline. /// After the error handler is called this function will call exit(1), it /// does not return. - NORETURN void report_fatal_error(const char *reason); - NORETURN void report_fatal_error(const std::string &reason); - NORETURN void report_fatal_error(const Twine &reason); + LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason); + LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason); + LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason); + LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason); /// This function calls abort(), and prints the optional message to stderr. /// Use the llvm_unreachable macro (that adds location info), instead of /// calling this function directly. - NORETURN void llvm_unreachable_internal(const char *msg=0, - const char *file=0, unsigned line=0); + LLVM_ATTRIBUTE_NORETURN void llvm_unreachable_internal(const char *msg=0, + const char *file=0, + unsigned line=0); } /// Prints the message and location info to stderr in !NDEBUG builds. diff --git a/contrib/llvm/include/llvm/Support/FEnv.h b/contrib/llvm/include/llvm/Support/FEnv.h new file mode 100644 index 0000000..f6f4333 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/FEnv.h @@ -0,0 +1,56 @@ +//===- llvm/Support/FEnv.h - Host floating-point exceptions ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides an operating system independent interface to +// floating-point exception interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_FENV_H +#define LLVM_SYSTEM_FENV_H + +#include "llvm/Config/config.h" +#include <cerrno> +#ifdef HAVE_FENV_H +#include <fenv.h> +#endif + +// FIXME: Clang's #include handling apparently doesn't work for libstdc++'s +// fenv.h; see PR6907 for details. +#if defined(__clang__) && defined(_GLIBCXX_FENV_H) +#undef HAVE_FENV_H +#endif + +namespace llvm { +namespace sys { + +/// llvm_fenv_clearexcept - Clear the floating-point exception state. +static inline void llvm_fenv_clearexcept() { +#ifdef HAVE_FENV_H + feclearexcept(FE_ALL_EXCEPT); +#endif + errno = 0; +} + +/// llvm_fenv_testexcept - Test if a floating-point exception was raised. +static inline bool llvm_fenv_testexcept() { + int errno_val = errno; + if (errno_val == ERANGE || errno_val == EDOM) + return true; +#ifdef HAVE_FENV_H + if (fetestexcept(FE_ALL_EXCEPT & ~FE_INEXACT)) + return true; +#endif + return false; +} + +} // End sys namespace +} // End llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/Support/FileSystem.h b/contrib/llvm/include/llvm/Support/FileSystem.h new file mode 100644 index 0000000..4001bf0 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/FileSystem.h @@ -0,0 +1,690 @@ +//===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::fs namespace. It is designed after +// TR2/boost filesystem (v3), but modified to remove exception handling and the +// path class. +// +// All functions return an error_code and their actual work via the last out +// argument. The out argument is defined if and only if errc::success is +// returned. A function may return any error code in the generic or system +// category. However, they shall be equivalent to any error conditions listed +// in each functions respective documentation if the condition applies. [ note: +// this does not guarantee that error_code will be in the set of explicitly +// listed codes, but it does guarantee that if any of the explicitly listed +// errors occur, the correct error_code will be used ]. All functions may +// return errc::not_enough_memory if there is not enough memory to complete the +// operation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FILE_SYSTEM_H +#define LLVM_SUPPORT_FILE_SYSTEM_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/PathV1.h" +#include "llvm/Support/system_error.h" +#include <ctime> +#include <iterator> +#include <string> + +namespace llvm { +namespace sys { +namespace fs { + +/// file_type - An "enum class" enumeration for the file system's view of the +/// type. +struct file_type { + enum _ { + status_error, + file_not_found, + regular_file, + directory_file, + symlink_file, + block_file, + character_file, + fifo_file, + socket_file, + type_unknown + }; + + file_type(_ v) : v_(v) {} + explicit file_type(int v) : v_(_(v)) {} + operator int() const {return v_;} + +private: + int v_; +}; + +/// copy_option - An "enum class" enumeration of copy semantics for copy +/// operations. +struct copy_option { + enum _ { + fail_if_exists, + overwrite_if_exists + }; + + copy_option(_ v) : v_(v) {} + explicit copy_option(int v) : v_(_(v)) {} + operator int() const {return v_;} + +private: + int v_; +}; + +/// space_info - Self explanatory. +struct space_info { + uint64_t capacity; + uint64_t free; + uint64_t available; +}; + +/// file_status - Represents the result of a call to stat and friends. It has +/// a platform specific member to store the result. +class file_status +{ + // implementation defined status field. + file_type Type; +public: + explicit file_status(file_type v=file_type::status_error) + : Type(v) {} + + file_type type() const { return Type; } + void type(file_type v) { Type = v; } +}; + +/// @} +/// @name Physical Operators +/// @{ + +/// @brief Make \a path an absolute path. +/// +/// Makes \a path absolute using the current directory if it is not already. An +/// empty \a path will result in the current directory. +/// +/// /absolute/path => /absolute/path +/// relative/../path => <current-directory>/relative/../path +/// +/// @param path A path that is modified to be an absolute path. +/// @returns errc::success if \a path has been made absolute, otherwise a +/// platform specific error_code. +error_code make_absolute(SmallVectorImpl<char> &path); + +/// @brief Copy the file at \a from to the path \a to. +/// +/// @param from The path to copy the file from. +/// @param to The path to copy the file to. +/// @param copt Behavior if \a to already exists. +/// @returns errc::success if the file has been successfully copied. +/// errc::file_exists if \a to already exists and \a copt == +/// copy_option::fail_if_exists. Otherwise a platform specific +/// error_code. +error_code copy_file(const Twine &from, const Twine &to, + copy_option copt = copy_option::fail_if_exists); + +/// @brief Create all the non-existent directories in path. +/// +/// @param path Directories to create. +/// @param existed Set to true if \a path already existed, false otherwise. +/// @returns errc::success if is_directory(path) and existed have been set, +/// otherwise a platform specific error_code. +error_code create_directories(const Twine &path, bool &existed); + +/// @brief Create the directory in path. +/// +/// @param path Directory to create. +/// @param existed Set to true if \a path already existed, false otherwise. +/// @returns errc::success if is_directory(path) and existed have been set, +/// otherwise a platform specific error_code. +error_code create_directory(const Twine &path, bool &existed); + +/// @brief Create a hard link from \a from to \a to. +/// +/// @param to The path to hard link to. +/// @param from The path to hard link from. This is created. +/// @returns errc::success if exists(to) && exists(from) && equivalent(to, from) +/// , otherwise a platform specific error_code. +error_code create_hard_link(const Twine &to, const Twine &from); + +/// @brief Create a symbolic link from \a from to \a to. +/// +/// @param to The path to symbolically link to. +/// @param from The path to symbolically link from. This is created. +/// @returns errc::success if exists(to) && exists(from) && is_symlink(from), +/// otherwise a platform specific error_code. +error_code create_symlink(const Twine &to, const Twine &from); + +/// @brief Get the current path. +/// +/// @param result Holds the current path on return. +/// @results errc::success if the current path has been stored in result, +/// otherwise a platform specific error_code. +error_code current_path(SmallVectorImpl<char> &result); + +/// @brief Remove path. Equivalent to POSIX remove(). +/// +/// @param path Input path. +/// @param existed Set to true if \a path existed, false if it did not. +/// undefined otherwise. +/// @results errc::success if path has been removed and existed has been +/// successfully set, otherwise a platform specific error_code. +error_code remove(const Twine &path, bool &existed); + +/// @brief Recursively remove all files below \a path, then \a path. Files are +/// removed as if by POSIX remove(). +/// +/// @param path Input path. +/// @param num_removed Number of files removed. +/// @results errc::success if path has been removed and num_removed has been +/// successfully set, otherwise a platform specific error_code. +error_code remove_all(const Twine &path, uint32_t &num_removed); + +/// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). +/// +/// @param from The path to rename from. +/// @param to The path to rename to. This is created. +error_code rename(const Twine &from, const Twine &to); + +/// @brief Resize path to size. File is resized as if by POSIX truncate(). +/// +/// @param path Input path. +/// @param size Size to resize to. +/// @returns errc::success if \a path has been resized to \a size, otherwise a +/// platform specific error_code. +error_code resize_file(const Twine &path, uint64_t size); + +/// @brief Make file readable. +/// +/// @param path Input path. +/// @param value If true, make readable, else, make unreadable. +/// @results errc::success if readability has been successfully set, otherwise a +/// platform specific error_code. +error_code set_read(const Twine &path, bool value); + +/// @brief Make file writeable. +/// +/// @param path Input path. +/// @param value If true, make writeable, else, make unwriteable. +/// @results errc::success if writeability has been successfully set, otherwise +/// a platform specific error_code. +error_code set_write(const Twine &path, bool value); + +/// @brief Make file executable. +/// +/// @param path Input path. +/// @param value If true, make executable, else, make unexecutable. +/// @results errc::success if executability has been successfully set, otherwise +/// a platform specific error_code. +error_code set_execute(const Twine &path, bool value); + +/// @} +/// @name Physical Observers +/// @{ + +/// @brief Does file exist? +/// +/// @param status A file_status previously returned from stat. +/// @results True if the file represented by status exists, false if it does +/// not. +bool exists(file_status status); + +/// @brief Does file exist? +/// +/// @param path Input path. +/// @param result Set to true if the file represented by status exists, false if +/// it does not. Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code exists(const Twine &path, bool &result); + +/// @brief Do file_status's represent the same thing? +/// +/// @param A Input file_status. +/// @param B Input file_status. +/// +/// assert(status_known(A) || status_known(B)); +/// +/// @results True if A and B both represent the same file system entity, false +/// otherwise. +bool equivalent(file_status A, file_status B); + +/// @brief Do paths represent the same thing? +/// +/// @param A Input path A. +/// @param B Input path B. +/// @param result Set to true if stat(A) and stat(B) have the same device and +/// inode (or equivalent). +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code equivalent(const Twine &A, const Twine &B, bool &result); + +/// @brief Get file size. +/// +/// @param path Input path. +/// @param result Set to the size of the file in \a path. +/// @returns errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code file_size(const Twine &path, uint64_t &result); + +/// @brief Does status represent a directory? +/// +/// @param status A file_status previously returned from status. +/// @results status.type() == file_type::directory_file. +bool is_directory(file_status status); + +/// @brief Is path a directory? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a directory, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_directory(const Twine &path, bool &result); + +/// @brief Is path an empty file? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a an empty file, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_empty(const Twine &path, bool &result); + +/// @brief Does status represent a regular file? +/// +/// @param status A file_status previously returned from status. +/// @results status_known(status) && status.type() == file_type::regular_file. +bool is_regular_file(file_status status); + +/// @brief Is path a regular file? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a regular file, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_regular_file(const Twine &path, bool &result); + +/// @brief Does this status represent something that exists but is not a +/// directory, regular file, or symlink? +/// +/// @param status A file_status previously returned from status. +/// @results exists(s) && !is_regular_file(s) && !is_directory(s) && +/// !is_symlink(s) +bool is_other(file_status status); + +/// @brief Is path something that exists but is not a directory, +/// regular file, or symlink? +/// +/// @param path Input path. +/// @param result Set to true if \a path exists, but is not a directory, regular +/// file, or a symlink, false if it does not. Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_other(const Twine &path, bool &result); + +/// @brief Does status represent a symlink? +/// +/// @param status A file_status previously returned from stat. +/// @param result status.type() == symlink_file. +bool is_symlink(file_status status); + +/// @brief Is path a symlink? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a symlink, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_symlink(const Twine &path, bool &result); + +/// @brief Get last write time without changing it. +/// +/// @param path Input path. +/// @param result Set to the last write time (UNIX time) of \a path if it +/// exists. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code last_write_time(const Twine &path, std::time_t &result); + +/// @brief Set last write time. +/// +/// @param path Input path. +/// @param value Time to set (UNIX time) \a path's last write time to. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code set_last_write_time(const Twine &path, std::time_t value); + +/// @brief Read a symlink's value. +/// +/// @param path Input path. +/// @param result Set to the value of the symbolic link \a path. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code read_symlink(const Twine &path, SmallVectorImpl<char> &result); + +/// @brief Get disk space usage information. +/// +/// @param path Input path. +/// @param result Set to the capacity, free, and available space on the device +/// \a path is on. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code disk_space(const Twine &path, space_info &result); + +/// @brief Get file status as if by POSIX stat(). +/// +/// @param path Input path. +/// @param result Set to the file status. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code status(const Twine &path, file_status &result); + +/// @brief Is status available? +/// +/// @param path Input path. +/// @results True if status() != status_error. +bool status_known(file_status s); + +/// @brief Is status available? +/// +/// @param path Input path. +/// @param result Set to true if status() != status_error. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code status_known(const Twine &path, bool &result); + +/// @brief Get file status as if by POSIX lstat(). +/// +/// Does not resolve symlinks. +/// +/// @param path Input path. +/// @param result Set to the file status. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code symlink_status(const Twine &path, file_status &result); + +/// @brief Generate a unique path and open it as a file. +/// +/// Generates a unique path suitable for a temporary file and then opens it as a +/// file. The name is based on \a model with '%' replaced by a random char in +/// [0-9a-f]. If \a model is not an absolute path, a suitable temporary +/// directory will be prepended. +/// +/// This is an atomic operation. Either the file is created and opened, or the +/// file system is left untouched. +/// +/// clang-%%-%%-%%-%%-%%.s => /tmp/clang-a0-b1-c2-d3-e4.s +/// +/// @param model Name to base unique path off of. +/// @param result_fs Set to the opened file's file descriptor. +/// @param result_path Set to the opened file's absolute path. +/// @results errc::success if result_{fd,path} have been successfully set, +/// otherwise a platform specific error_code. +error_code unique_file(const Twine &model, int &result_fd, + SmallVectorImpl<char> &result_path); + +/// @brief Canonicalize path. +/// +/// Sets result to the file system's idea of what path is. The result is always +/// absolute and has the same capitalization as the file system. +/// +/// @param path Input path. +/// @param result Set to the canonicalized version of \a path. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code canonicalize(const Twine &path, SmallVectorImpl<char> &result); + +/// @brief Are \a path's first bytes \a magic? +/// +/// @param path Input path. +/// @param magic Byte sequence to compare \a path's first len(magic) bytes to. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code has_magic(const Twine &path, const Twine &magic, bool &result); + +/// @brief Get \a path's first \a len bytes. +/// +/// @param path Input path. +/// @param len Number of magic bytes to get. +/// @param result Set to the first \a len bytes in the file pointed to by +/// \a path. Or the entire file if file_size(path) < len, in which +/// case result.size() returns the size of the file. +/// @results errc::success if result has been successfully set, +/// errc::value_too_large if len is larger then the file pointed to by +/// \a path, otherwise a platform specific error_code. +error_code get_magic(const Twine &path, uint32_t len, + SmallVectorImpl<char> &result); + +/// @brief Get and identify \a path's type based on its content. +/// +/// @param path Input path. +/// @param result Set to the type of file, or LLVMFileType::Unknown_FileType. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code identify_magic(const Twine &path, LLVMFileType &result); + +/// @brief Is file bitcode? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a bitcode file, false if it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_bitcode(const Twine &path, bool &result); + +/// @brief Is file a dynamic library? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a dynamic library, false if it is +/// not, undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_dynamic_library(const Twine &path, bool &result); + +/// @brief Is an object file? +/// +/// @param path Input path. +/// @param result Set to true if \a path is an object file, false if it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_object_file(const Twine &path, bool &result); + +/// @brief Can file be read? +/// +/// @param path Input path. +/// @param result Set to true if \a path is readable, false it it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code can_read(const Twine &path, bool &result); + +/// @brief Can file be written? +/// +/// @param path Input path. +/// @param result Set to true if \a path is writeable, false it it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code can_write(const Twine &path, bool &result); + +/// @brief Can file be executed? +/// +/// @param path Input path. +/// @param result Set to true if \a path is executable, false it it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code can_execute(const Twine &path, bool &result); + +/// @brief Get library paths the system linker uses. +/// +/// @param result Set to the list of system library paths. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code GetSystemLibraryPaths(SmallVectorImpl<std::string> &result); + +/// @brief Get bitcode library paths the system linker uses +/// + LLVM_LIB_SEARCH_PATH + LLVM_LIBDIR. +/// +/// @param result Set to the list of bitcode library paths. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code GetBitcodeLibraryPaths(SmallVectorImpl<std::string> &result); + +/// @brief Find a library. +/// +/// Find the path to a library using its short name. Use the system +/// dependent library paths to locate the library. +/// +/// c => /usr/lib/libc.so +/// +/// @param short_name Library name one would give to the system linker. +/// @param result Set to the absolute path \a short_name represents. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code FindLibrary(const Twine &short_name, SmallVectorImpl<char> &result); + +/// @brief Get absolute path of main executable. +/// +/// @param argv0 The program name as it was spelled on the command line. +/// @param MainAddr Address of some symbol in the executable (not in a library). +/// @param result Set to the absolute path of the current executable. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code GetMainExecutable(const char *argv0, void *MainAddr, + SmallVectorImpl<char> &result); + +/// @} +/// @name Iterators +/// @{ + +/// directory_entry - A single entry in a directory. Caches the status either +/// from the result of the iteration syscall, or the first time status or +/// symlink_status is called. +class directory_entry { + std::string Path; + mutable file_status Status; + mutable file_status SymlinkStatus; + +public: + explicit directory_entry(const Twine &path, file_status st = file_status(), + file_status symlink_st = file_status()) + : Path(path.str()) + , Status(st) + , SymlinkStatus(symlink_st) {} + + directory_entry() {} + + void assign(const Twine &path, file_status st = file_status(), + file_status symlink_st = file_status()) { + Path = path.str(); + Status = st; + SymlinkStatus = symlink_st; + } + + void replace_filename(const Twine &filename, file_status st = file_status(), + file_status symlink_st = file_status()); + + StringRef path() const { return Path; } + error_code status(file_status &result) const; + error_code symlink_status(file_status &result) const; + + bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } + bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } + bool operator< (const directory_entry& rhs) const; + bool operator<=(const directory_entry& rhs) const; + bool operator> (const directory_entry& rhs) const; + bool operator>=(const directory_entry& rhs) const; +}; + +/// directory_iterator - Iterates through the entries in path. There is no +/// operator++ because we need an error_code. If it's really needed we can make +/// it call report_fatal_error on error. +class directory_iterator { + intptr_t IterationHandle; + directory_entry CurrentEntry; + + // Platform implementations implement these functions to handle iteration. + friend error_code directory_iterator_construct(directory_iterator &it, + StringRef path); + friend error_code directory_iterator_increment(directory_iterator &it); + friend error_code directory_iterator_destruct(directory_iterator &it); + +public: + explicit directory_iterator(const Twine &path, error_code &ec) + : IterationHandle(0) { + SmallString<128> path_storage; + ec = directory_iterator_construct(*this, path.toStringRef(path_storage)); + } + + /// Construct end iterator. + directory_iterator() : IterationHandle(0) {} + + ~directory_iterator() { + directory_iterator_destruct(*this); + } + + // No operator++ because we need error_code. + directory_iterator &increment(error_code &ec) { + ec = directory_iterator_increment(*this); + return *this; + } + + const directory_entry &operator*() const { return CurrentEntry; } + const directory_entry *operator->() const { return &CurrentEntry; } + + bool operator!=(const directory_iterator &RHS) const { + return CurrentEntry != RHS.CurrentEntry; + } + // Other members as required by + // C++ Std, 24.1.1 Input iterators [input.iterators] +}; + +/// recursive_directory_iterator - Same as directory_iterator except for it +/// recurses down into child directories. +class recursive_directory_iterator { + uint16_t Level; + bool HasNoPushRequest; + // implementation directory iterator status + +public: + explicit recursive_directory_iterator(const Twine &path, error_code &ec); + // No operator++ because we need error_code. + directory_iterator &increment(error_code &ec); + + const directory_entry &operator*() const; + const directory_entry *operator->() const; + + // observers + /// Gets the current level. path is at level 0. + int level() const; + /// Returns true if no_push has been called for this directory_entry. + bool no_push_request() const; + + // modifiers + /// Goes up one level if Level > 0. + void pop(); + /// Does not go down into the current directory_entry. + void no_push(); + + // Other members as required by + // C++ Std, 24.1.1 Input iterators [input.iterators] +}; + +/// @} + +} // end namespace fs +} // end namespace sys +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Support/FileUtilities.h b/contrib/llvm/include/llvm/Support/FileUtilities.h index d0dd4a7..748ce7c 100644 --- a/contrib/llvm/include/llvm/Support/FileUtilities.h +++ b/contrib/llvm/include/llvm/Support/FileUtilities.h @@ -15,7 +15,7 @@ #ifndef LLVM_SUPPORT_FILEUTILITIES_H #define LLVM_SUPPORT_FILEUTILITIES_H -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" namespace llvm { diff --git a/contrib/llvm/include/llvm/Support/GraphWriter.h b/contrib/llvm/include/llvm/Support/GraphWriter.h index 287c5ba..7573ef0 100644 --- a/contrib/llvm/include/llvm/Support/GraphWriter.h +++ b/contrib/llvm/include/llvm/Support/GraphWriter.h @@ -26,7 +26,7 @@ #include "llvm/Support/DOTGraphTraits.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" #include <vector> #include <cassert> @@ -89,14 +89,28 @@ class GraphWriter { public: GraphWriter(raw_ostream &o, const GraphType &g, bool SN) : O(o), G(g) { - DTraits = DOTTraits(SN); -} + DTraits = DOTTraits(SN); + } + + void writeGraph(const std::string &Title = "") { + // Output the header for the graph... + writeHeader(Title); + + // Emit all of the nodes in the graph... + writeNodes(); + + // Output any customizations on the graph + DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, *this); - void writeHeader(const std::string &Name) { + // Output the end of the graph + writeFooter(); + } + + void writeHeader(const std::string &Title) { std::string GraphName = DTraits.getGraphName(G); - if (!Name.empty()) - O << "digraph \"" << DOT::EscapeString(Name) << "\" {\n"; + if (!Title.empty()) + O << "digraph \"" << DOT::EscapeString(Title) << "\" {\n"; else if (!GraphName.empty()) O << "digraph \"" << DOT::EscapeString(GraphName) << "\" {\n"; else @@ -105,8 +119,8 @@ public: if (DTraits.renderGraphFromBottomUp()) O << "\trankdir=\"BT\";\n"; - if (!Name.empty()) - O << "\tlabel=\"" << DOT::EscapeString(Name) << "\";\n"; + if (!Title.empty()) + O << "\tlabel=\"" << DOT::EscapeString(Title) << "\";\n"; else if (!GraphName.empty()) O << "\tlabel=\"" << DOT::EscapeString(GraphName) << "\";\n"; O << DTraits.getGraphProperties(G); @@ -282,22 +296,13 @@ public: template<typename GraphType> raw_ostream &WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames = false, - const std::string &Name = "", const std::string &Title = "") { // Start the graph emission process... GraphWriter<GraphType> W(O, G, ShortNames); - // Output the header for the graph... - W.writeHeader(Title); - - // Emit all of the nodes in the graph... - W.writeNodes(); - - // Output any customizations on the graph - DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, W); + // Emit the graph. + W.writeGraph(Title); - // Output the end of the graph - W.writeFooter(); return O; } @@ -322,7 +327,7 @@ sys::Path WriteGraph(const GraphType &G, const std::string &Name, raw_fd_ostream O(Filename.c_str(), ErrorInfo); if (ErrorInfo.empty()) { - llvm::WriteGraph(O, G, ShortNames, Name, Title); + llvm::WriteGraph(O, G, ShortNames, Title); errs() << " done. \n"; } else { errs() << "error opening file '" << Filename.str() << "' for writing!\n"; diff --git a/contrib/llvm/include/llvm/System/Host.h b/contrib/llvm/include/llvm/Support/Host.h index 4fbf5c1..f77d4c1 100644 --- a/contrib/llvm/include/llvm/System/Host.h +++ b/contrib/llvm/include/llvm/Support/Host.h @@ -1,4 +1,4 @@ -//===- llvm/System/Host.h - Host machine characteristics --------*- C++ -*-===// +//===- llvm/Support/Host.h - Host machine characteristics --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/include/llvm/Support/IRBuilder.h b/contrib/llvm/include/llvm/Support/IRBuilder.h index c827cce..2394a59 100644 --- a/contrib/llvm/include/llvm/Support/IRBuilder.h +++ b/contrib/llvm/include/llvm/Support/IRBuilder.h @@ -46,32 +46,39 @@ protected: BasicBlock::iterator InsertPt; LLVMContext &Context; public: - + IRBuilderBase(LLVMContext &context) : Context(context) { ClearInsertionPoint(); } - + //===--------------------------------------------------------------------===// // Builder configuration methods //===--------------------------------------------------------------------===// - + /// ClearInsertionPoint - Clear the insertion point: created instructions will /// not be inserted into a block. void ClearInsertionPoint() { BB = 0; } - + BasicBlock *GetInsertBlock() const { return BB; } 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. void SetInsertPoint(BasicBlock *TheBB) { BB = TheBB; InsertPt = BB->end(); } + + /// SetInsertPoint - This specifies that created instructions should be + /// inserted before the specified instruction. + void SetInsertPoint(Instruction *I) { + BB = I->getParent(); + InsertPt = I; + } /// SetInsertPoint - This specifies that created instructions should be /// inserted at the specified point. @@ -79,17 +86,17 @@ public: BB = TheBB; InsertPt = IP; } - + /// SetCurrentDebugLocation - Set location information used by debugging /// information. void SetCurrentDebugLocation(const DebugLoc &L) { CurDbgLocation = L; } - + /// getCurrentDebugLocation - Get location information used by debugging /// information. const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; } - + /// SetInstDebugLocation - If this builder has a current debug location, set /// it on the specified instruction. void SetInstDebugLocation(Instruction *I) const { @@ -142,7 +149,7 @@ 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. If Name is specified, it is the name of the global variable @@ -178,65 +185,100 @@ public: ConstantInt *getInt32(uint32_t C) { return ConstantInt::get(getInt32Ty(), C); } - + /// getInt64 - Get a constant 64-bit value. ConstantInt *getInt64(uint64_t C) { return ConstantInt::get(getInt64Ty(), C); } - + //===--------------------------------------------------------------------===// // Type creation methods //===--------------------------------------------------------------------===// - + /// getInt1Ty - Fetch the type representing a single bit const IntegerType *getInt1Ty() { return Type::getInt1Ty(Context); } - + /// getInt8Ty - Fetch the type representing an 8-bit integer. const IntegerType *getInt8Ty() { return Type::getInt8Ty(Context); } - + /// getInt16Ty - Fetch the type representing a 16-bit integer. const IntegerType *getInt16Ty() { return Type::getInt16Ty(Context); } - + /// getInt32Ty - Fetch the type resepresenting a 32-bit integer. const IntegerType *getInt32Ty() { return Type::getInt32Ty(Context); } - + /// getInt64Ty - Fetch the type representing a 64-bit integer. const IntegerType *getInt64Ty() { return Type::getInt64Ty(Context); } - + /// getFloatTy - Fetch the type representing a 32-bit floating point value. const Type *getFloatTy() { return Type::getFloatTy(Context); } - + /// getDoubleTy - Fetch the type representing a 64-bit floating point value. const Type *getDoubleTy() { return Type::getDoubleTy(Context); } - + /// getVoidTy - Fetch the type representing void. const Type *getVoidTy() { return Type::getVoidTy(Context); } - - const PointerType *getInt8PtrTy() { - return Type::getInt8PtrTy(Context); + + const PointerType *getInt8PtrTy(unsigned AddrSpace = 0) { + return Type::getInt8PtrTy(Context, AddrSpace); } - + /// getCurrentFunctionReturnType - Get the return type of the current function /// that we're emitting into. const Type *getCurrentFunctionReturnType() const; -}; + /// CreateMemSet - Create and insert a memset to the specified pointer and the + /// specified value. If the pointer isn't an i8*, it will be converted. If a + /// TBAA tag is specified, it will be added to the instruction. + CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); + + /// CreateMemCpy - Create and insert a memcpy between the specified pointers. + /// If the pointers aren't i8*, they will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. + CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); + + /// CreateMemMove - Create and insert a memmove between the specified + /// pointers. If the pointers aren't i8*, they will be converted. If a TBAA + /// tag is specified, it will be added to the instruction. + CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); +private: + Value *getCastedInt8PtrValue(Value *Ptr); +}; + /// IRBuilder - This provides a uniform API for creating instructions and /// inserting them into a basic block: either at the end of a BasicBlock, or /// at a specific iterator location in a block. @@ -258,25 +300,30 @@ public: IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter()) : IRBuilderBase(C), Inserter(I), Folder(F) { } - + explicit IRBuilder(LLVMContext &C) : IRBuilderBase(C), Folder(C) { } - + explicit IRBuilder(BasicBlock *TheBB, const T &F) : IRBuilderBase(TheBB->getContext()), Folder(F) { SetInsertPoint(TheBB); } - + explicit IRBuilder(BasicBlock *TheBB) : IRBuilderBase(TheBB->getContext()), Folder(Context) { SetInsertPoint(TheBB); } + + explicit IRBuilder(Instruction *IP) + : IRBuilderBase(IP->getContext()), Folder(Context) { + SetInsertPoint(IP); + } IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F) : IRBuilderBase(TheBB->getContext()), Folder(F) { SetInsertPoint(TheBB, IP); } - + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP) : IRBuilderBase(TheBB->getContext()), Folder(Context) { SetInsertPoint(TheBB, IP); @@ -288,7 +335,7 @@ public: /// isNamePreserving - 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. template<typename InstTy> InstTy *Insert(InstTy *I, const Twine &Name = "") const { @@ -298,6 +345,11 @@ public: return I; } + /// Insert - No-op overload to handle constants. + Constant *Insert(Constant *C, const Twine& = "") const { + return C; + } + //===--------------------------------------------------------------------===// // Instruction creation methods: Terminators //===--------------------------------------------------------------------===// @@ -313,7 +365,7 @@ public: ReturnInst *CreateRet(Value *V) { return Insert(ReturnInst::Create(Context, V)); } - + /// CreateAggregateRet - 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 @@ -375,10 +427,12 @@ public: Args+3), Name); } /// CreateInvoke - Create an invoke instruction. - template<typename InputIterator> + template<typename RandomAccessIterator> InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, - BasicBlock *UnwindDest, InputIterator ArgBegin, - InputIterator ArgEnd, const Twine &Name = "") { + BasicBlock *UnwindDest, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, + const Twine &Name = "") { return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, ArgBegin, ArgEnd), Name); } @@ -394,177 +448,179 @@ public: //===--------------------------------------------------------------------===// // Instruction creation methods: Binary Operators //===--------------------------------------------------------------------===// - - Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "") { +private: + BinaryOperator *CreateInsertNUWNSWBinOp(BinaryOperator::BinaryOps Opc, + Value *LHS, Value *RHS, + const Twine &Name, + bool HasNUW, bool HasNSW) { + BinaryOperator *BO = Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } +public: + Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateAdd(LC, RC); - return Insert(BinaryOperator::CreateAdd(LHS, RHS), Name); + return Insert(Folder.CreateAdd(LC, RC, HasNUW, HasNSW), Name); + return CreateInsertNUWNSWBinOp(Instruction::Add, LHS, RHS, Name, + HasNUW, HasNSW); } Value *CreateNSWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNSWAdd(LC, RC); - return Insert(BinaryOperator::CreateNSWAdd(LHS, RHS), Name); + return CreateAdd(LHS, RHS, Name, false, true); } Value *CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNUWAdd(LC, RC); - return Insert(BinaryOperator::CreateNUWAdd(LHS, RHS), Name); + return CreateAdd(LHS, RHS, Name, true, false); } Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFAdd(LC, RC); + return Insert(Folder.CreateFAdd(LC, RC), Name); return Insert(BinaryOperator::CreateFAdd(LHS, RHS), Name); } - Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateSub(LC, RC); - return Insert(BinaryOperator::CreateSub(LHS, RHS), Name); + return Insert(Folder.CreateSub(LC, RC), Name); + return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name, + HasNUW, HasNSW); } Value *CreateNSWSub(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNSWSub(LC, RC); - return Insert(BinaryOperator::CreateNSWSub(LHS, RHS), Name); + return CreateSub(LHS, RHS, Name, false, true); } Value *CreateNUWSub(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNUWSub(LC, RC); - return Insert(BinaryOperator::CreateNUWSub(LHS, RHS), Name); + return CreateSub(LHS, RHS, Name, true, false); } Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFSub(LC, RC); + return Insert(Folder.CreateFSub(LC, RC), Name); return Insert(BinaryOperator::CreateFSub(LHS, RHS), Name); } - Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateMul(LC, RC); - return Insert(BinaryOperator::CreateMul(LHS, RHS), Name); + return Insert(Folder.CreateMul(LC, RC), Name); + return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name, + HasNUW, HasNSW); } Value *CreateNSWMul(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNSWMul(LC, RC); - return Insert(BinaryOperator::CreateNSWMul(LHS, RHS), Name); + return CreateMul(LHS, RHS, Name, false, true); } Value *CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNUWMul(LC, RC); - return Insert(BinaryOperator::CreateNUWMul(LHS, RHS), Name); + return CreateMul(LHS, RHS, Name, true, false); } Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFMul(LC, RC); + return Insert(Folder.CreateFMul(LC, RC), Name); return Insert(BinaryOperator::CreateFMul(LHS, RHS), Name); } - Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateUDiv(LC, RC); - return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name); + return Insert(Folder.CreateUDiv(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactUDiv(LHS, RHS), Name); } - Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateSDiv(LC, RC); - return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name); + Value *CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateUDiv(LHS, RHS, Name, true); } - Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateExactSDiv(LC, RC); + return Insert(Folder.CreateSDiv(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name); return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name); } + Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateSDiv(LHS, RHS, Name, true); + } Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFDiv(LC, RC); + return Insert(Folder.CreateFDiv(LC, RC), Name); return Insert(BinaryOperator::CreateFDiv(LHS, RHS), Name); } Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateURem(LC, RC); + return Insert(Folder.CreateURem(LC, RC), Name); return Insert(BinaryOperator::CreateURem(LHS, RHS), Name); } Value *CreateSRem(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateSRem(LC, RC); + return Insert(Folder.CreateSRem(LC, RC), Name); return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name); } Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFRem(LC, RC); + return Insert(Folder.CreateFRem(LC, RC), Name); return Insert(BinaryOperator::CreateFRem(LHS, RHS), Name); } - Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateShl(LC, RC); - return Insert(BinaryOperator::CreateShl(LHS, RHS), Name); + return Insert(Folder.CreateShl(LC, RC, HasNUW, HasNSW), Name); + return CreateInsertNUWNSWBinOp(Instruction::Shl, LHS, RHS, Name, + HasNUW, HasNSW); } - Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateShl(LC, RHSC); - return Insert(BinaryOperator::CreateShl(LHS, RHSC), Name); + Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, + HasNUW, HasNSW); } - Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateShl(LC, RHSC); - return Insert(BinaryOperator::CreateShl(LHS, RHSC), Name); + Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, + HasNUW, HasNSW); } - Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateLShr(LC, RC); - return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name); + return Insert(Folder.CreateLShr(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactLShr(LHS, RHS), Name); } - Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateLShr(LC, RHSC); - return Insert(BinaryOperator::CreateLShr(LHS, RHSC), Name); + Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool isExact = false) { + return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } - Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateLShr(LC, RHSC); - return Insert(BinaryOperator::CreateLShr(LHS, RHSC), Name); + Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool isExact = false) { + return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } - Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateAShr(LC, RC); - return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name); + return Insert(Folder.CreateAShr(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactAShr(LHS, RHS), Name); } - Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAShr(LC, RHSC); - return Insert(BinaryOperator::CreateAShr(LHS, RHSC), Name); + Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool isExact = false) { + return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } - Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAShr(LC, RHSC); - return Insert(BinaryOperator::CreateAShr(LHS, RHSC), Name); + Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool isExact = false) { + return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") { @@ -572,21 +628,15 @@ public: if (isa<ConstantInt>(RC) && cast<ConstantInt>(RC)->isAllOnesValue()) return LHS; // LHS & -1 -> LHS if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAnd(LC, RC); + return Insert(Folder.CreateAnd(LC, RC), Name); } return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name); } Value *CreateAnd(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAnd(LC, RHSC); - return Insert(BinaryOperator::CreateAnd(LHS, RHSC), Name); + return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateAnd(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAnd(LC, RHSC); - return Insert(BinaryOperator::CreateAnd(LHS, RHSC), Name); + return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") { @@ -594,73 +644,61 @@ public: if (RC->isNullValue()) return LHS; // LHS | 0 -> LHS if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateOr(LC, RC); + return Insert(Folder.CreateOr(LC, RC), Name); } return Insert(BinaryOperator::CreateOr(LHS, RHS), Name); } Value *CreateOr(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateOr(LC, RHSC); - return Insert(BinaryOperator::CreateOr(LHS, RHSC), Name); + return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateOr(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateOr(LC, RHSC); - return Insert(BinaryOperator::CreateOr(LHS, RHSC), Name); + return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateXor(LC, RC); + return Insert(Folder.CreateXor(LC, RC), Name); return Insert(BinaryOperator::CreateXor(LHS, RHS), Name); } Value *CreateXor(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateXor(LC, RHSC); - return Insert(BinaryOperator::CreateXor(LHS, RHSC), Name); + return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateXor(LC, RHSC); - return Insert(BinaryOperator::CreateXor(LHS, RHSC), Name); + return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateBinOp(Opc, LC, RC); + return Insert(Folder.CreateBinOp(Opc, LC, RC), Name); return Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); } - Value *CreateNeg(Value *V, const Twine &Name = "") { + Value *CreateNeg(Value *V, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateNeg(VC); - return Insert(BinaryOperator::CreateNeg(V), Name); + return Insert(Folder.CreateNeg(VC, HasNUW, HasNSW), Name); + BinaryOperator *BO = Insert(BinaryOperator::CreateNeg(V), Name); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; } Value *CreateNSWNeg(Value *V, const Twine &Name = "") { - if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateNSWNeg(VC); - return Insert(BinaryOperator::CreateNSWNeg(V), Name); + return CreateNeg(V, Name, false, true); } Value *CreateNUWNeg(Value *V, const Twine &Name = "") { - if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateNUWNeg(VC); - return Insert(BinaryOperator::CreateNUWNeg(V), Name); + return CreateNeg(V, Name, true, false); } Value *CreateFNeg(Value *V, const Twine &Name = "") { if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateFNeg(VC); + return Insert(Folder.CreateFNeg(VC), Name); return Insert(BinaryOperator::CreateFNeg(V), Name); } Value *CreateNot(Value *V, const Twine &Name = "") { if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateNot(VC); + return Insert(Folder.CreateNot(VC), Name); return Insert(BinaryOperator::CreateNot(V), Name); } @@ -686,33 +724,39 @@ public: StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { return Insert(new StoreInst(Val, Ptr, isVolatile)); } - template<typename InputIterator> - Value *CreateGEP(Value *Ptr, InputIterator IdxBegin, InputIterator IdxEnd, + template<typename RandomAccessIterator> + Value *CreateGEP(Value *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) { // Every index must be constant. - InputIterator i; + RandomAccessIterator i; for (i = IdxBegin; i < IdxEnd; ++i) if (!isa<Constant>(*i)) break; if (i == IdxEnd) - return Folder.CreateGetElementPtr(PC, &IdxBegin[0], IdxEnd - IdxBegin); + return Insert(Folder.CreateGetElementPtr(PC, &IdxBegin[0], + IdxEnd - IdxBegin), + Name); } return Insert(GetElementPtrInst::Create(Ptr, IdxBegin, IdxEnd), Name); } - template<typename InputIterator> - Value *CreateInBoundsGEP(Value *Ptr, InputIterator IdxBegin, - InputIterator IdxEnd, const Twine &Name = "") { + template<typename RandomAccessIterator> + Value *CreateInBoundsGEP(Value *Ptr, RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) { // Every index must be constant. - InputIterator i; + RandomAccessIterator i; for (i = IdxBegin; i < IdxEnd; ++i) if (!isa<Constant>(*i)) break; if (i == IdxEnd) - return Folder.CreateInBoundsGetElementPtr(PC, - &IdxBegin[0], - IdxEnd - IdxBegin); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, + &IdxBegin[0], + IdxEnd - IdxBegin), + Name); } return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxBegin, IdxEnd), Name); @@ -720,33 +764,33 @@ public: Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Folder.CreateGetElementPtr(PC, &IC, 1); + return Insert(Folder.CreateGetElementPtr(PC, &IC, 1), Name); return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); } Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Folder.CreateInBoundsGetElementPtr(PC, &IC, 1); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, &IC, 1), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); } Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateGetElementPtr(PC, &Idx, 1); + return Insert(Folder.CreateGetElementPtr(PC, &Idx, 1), Name); - return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); + return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); } Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); } - Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, + Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name = "") { Value *Idxs[] = { ConstantInt::get(Type::getInt32Ty(Context), Idx0), @@ -754,9 +798,9 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateGetElementPtr(PC, Idxs, 2); + return Insert(Folder.CreateGetElementPtr(PC, Idxs, 2), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); + return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); } Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name = "") { @@ -766,7 +810,7 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); } @@ -774,16 +818,16 @@ public: Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateGetElementPtr(PC, &Idx, 1); + return Insert(Folder.CreateGetElementPtr(PC, &Idx, 1), Name); - return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); + return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); } Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); } @@ -795,9 +839,9 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateGetElementPtr(PC, Idxs, 2); + return Insert(Folder.CreateGetElementPtr(PC, Idxs, 2), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); + return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); } Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { @@ -807,14 +851,14 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); } Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { 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. Value *CreateGlobalStringPtr(const char *Str = "", const Twine &Name = "") { @@ -823,7 +867,7 @@ public: Value *Args[] = { zero, zero }; return CreateInBoundsGEP(gv, Args, Args+2, Name); } - + //===--------------------------------------------------------------------===// // Instruction creation methods: Cast/Conversion Operators //===--------------------------------------------------------------------===// @@ -873,7 +917,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateZExtOrBitCast(VC, DestTy); + return Insert(Folder.CreateZExtOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateZExtOrBitCast(V, DestTy), Name); } Value *CreateSExtOrBitCast(Value *V, const Type *DestTy, @@ -881,7 +925,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateSExtOrBitCast(VC, DestTy); + return Insert(Folder.CreateSExtOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateSExtOrBitCast(V, DestTy), Name); } Value *CreateTruncOrBitCast(Value *V, const Type *DestTy, @@ -889,7 +933,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateTruncOrBitCast(VC, DestTy); + return Insert(Folder.CreateTruncOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateTruncOrBitCast(V, DestTy), Name); } Value *CreateCast(Instruction::CastOps Op, Value *V, const Type *DestTy, @@ -897,7 +941,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateCast(Op, VC, DestTy); + return Insert(Folder.CreateCast(Op, VC, DestTy), Name); return Insert(CastInst::Create(Op, V, DestTy), Name); } Value *CreatePointerCast(Value *V, const Type *DestTy, @@ -905,7 +949,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreatePointerCast(VC, DestTy); + return Insert(Folder.CreatePointerCast(VC, DestTy), Name); return Insert(CastInst::CreatePointerCast(V, DestTy), Name); } Value *CreateIntCast(Value *V, const Type *DestTy, bool isSigned, @@ -913,7 +957,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateIntCast(VC, DestTy, isSigned); + return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); } private: @@ -925,7 +969,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateFPCast(VC, DestTy); + return Insert(Folder.CreateFPCast(VC, DestTy), Name); return Insert(CastInst::CreateFPCast(V, DestTy), Name); } @@ -1011,14 +1055,14 @@ public: const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateICmp(P, LC, RC); + return Insert(Folder.CreateICmp(P, LC, RC), Name); return Insert(new ICmpInst(P, LHS, RHS), Name); } Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFCmp(P, LC, RC); + return Insert(Folder.CreateFCmp(P, LC, RC), Name); return Insert(new FCmpInst(P, LHS, RHS), Name); } @@ -1057,9 +1101,9 @@ public: return Insert(CallInst::Create(Callee, Args, Args+5), Name); } - template<typename InputIterator> - CallInst *CreateCall(Value *Callee, InputIterator ArgBegin, - InputIterator ArgEnd, const Twine &Name = "") { + template<typename RandomAccessIterator> + CallInst *CreateCall(Value *Callee, RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, const Twine &Name = "") { return Insert(CallInst::Create(Callee, ArgBegin, ArgEnd), Name); } @@ -1068,7 +1112,7 @@ public: if (Constant *CC = dyn_cast<Constant>(C)) if (Constant *TC = dyn_cast<Constant>(True)) if (Constant *FC = dyn_cast<Constant>(False)) - return Folder.CreateSelect(CC, TC, FC); + return Insert(Folder.CreateSelect(CC, TC, FC), Name); return Insert(SelectInst::Create(C, True, False), Name); } @@ -1080,7 +1124,7 @@ public: const Twine &Name = "") { if (Constant *VC = dyn_cast<Constant>(Vec)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Folder.CreateExtractElement(VC, IC); + return Insert(Folder.CreateExtractElement(VC, IC), Name); return Insert(ExtractElementInst::Create(Vec, Idx), Name); } @@ -1089,7 +1133,7 @@ public: if (Constant *VC = dyn_cast<Constant>(Vec)) if (Constant *NC = dyn_cast<Constant>(NewElt)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Folder.CreateInsertElement(VC, NC, IC); + return Insert(Folder.CreateInsertElement(VC, NC, IC), Name); return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name); } @@ -1098,24 +1142,25 @@ public: if (Constant *V1C = dyn_cast<Constant>(V1)) if (Constant *V2C = dyn_cast<Constant>(V2)) if (Constant *MC = dyn_cast<Constant>(Mask)) - return Folder.CreateShuffleVector(V1C, V2C, MC); + return Insert(Folder.CreateShuffleVector(V1C, V2C, MC), Name); return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); } Value *CreateExtractValue(Value *Agg, unsigned Idx, const Twine &Name = "") { if (Constant *AggC = dyn_cast<Constant>(Agg)) - return Folder.CreateExtractValue(AggC, &Idx, 1); + return Insert(Folder.CreateExtractValue(AggC, &Idx, 1), Name); return Insert(ExtractValueInst::Create(Agg, Idx), Name); } - template<typename InputIterator> + template<typename RandomAccessIterator> Value *CreateExtractValue(Value *Agg, - InputIterator IdxBegin, - InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &Name = "") { if (Constant *AggC = dyn_cast<Constant>(Agg)) - return Folder.CreateExtractValue(AggC, IdxBegin, IdxEnd - IdxBegin); + return Insert(Folder.CreateExtractValue(AggC, IdxBegin, IdxEnd-IdxBegin), + Name); return Insert(ExtractValueInst::Create(Agg, IdxBegin, IdxEnd), Name); } @@ -1123,18 +1168,20 @@ public: const Twine &Name = "") { if (Constant *AggC = dyn_cast<Constant>(Agg)) if (Constant *ValC = dyn_cast<Constant>(Val)) - return Folder.CreateInsertValue(AggC, ValC, &Idx, 1); + return Insert(Folder.CreateInsertValue(AggC, ValC, &Idx, 1), Name); return Insert(InsertValueInst::Create(Agg, Val, Idx), Name); } - template<typename InputIterator> + template<typename RandomAccessIterator> Value *CreateInsertValue(Value *Agg, Value *Val, - InputIterator IdxBegin, - InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &Name = "") { if (Constant *AggC = dyn_cast<Constant>(Agg)) if (Constant *ValC = dyn_cast<Constant>(Val)) - return Folder.CreateInsertValue(AggC, ValC, IdxBegin, IdxEnd-IdxBegin); + return Insert(Folder.CreateInsertValue(AggC, ValC, IdxBegin, + IdxEnd - IdxBegin), + Name); return Insert(InsertValueInst::Create(Agg, Val, IdxBegin, IdxEnd), Name); } diff --git a/contrib/llvm/include/llvm/Support/IRReader.h b/contrib/llvm/include/llvm/Support/IRReader.h index a44da52..292c001 100644 --- a/contrib/llvm/include/llvm/Support/IRReader.h +++ b/contrib/llvm/include/llvm/Support/IRReader.h @@ -19,10 +19,12 @@ #ifndef LLVM_SUPPORT_IRREADER_H #define LLVM_SUPPORT_IRREADER_H +#include "llvm/ADT/OwningPtr.h" #include "llvm/Assembly/Parser.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/system_error.h" namespace llvm { @@ -56,15 +58,14 @@ namespace llvm { inline Module *getLazyIRFileModule(const std::string &Filename, SMDiagnostic &Err, LLVMContext &Context) { - std::string ErrMsg; - MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrMsg); - if (F == 0) { - Err = SMDiagnostic(Filename, - "Could not open input file: " + ErrMsg); + OwningPtr<MemoryBuffer> File; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { + Err = SMDiagnostic(Filename, + "Could not open input file: " + ec.message()); return 0; } - return getLazyIRModule(F, Err, Context); + return getLazyIRModule(File.take(), Err, Context); } /// If the given MemoryBuffer holds a bitcode image, return a Module @@ -94,15 +95,14 @@ namespace llvm { inline Module *ParseIRFile(const std::string &Filename, SMDiagnostic &Err, LLVMContext &Context) { - std::string ErrMsg; - MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrMsg); - if (F == 0) { - Err = SMDiagnostic(Filename, - "Could not open input file: " + ErrMsg); + OwningPtr<MemoryBuffer> File; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { + Err = SMDiagnostic(Filename, + "Could not open input file: " + ec.message()); return 0; } - return ParseIR(F, Err, Context); + return ParseIR(File.take(), Err, Context); } } diff --git a/contrib/llvm/include/llvm/System/IncludeFile.h b/contrib/llvm/include/llvm/Support/IncludeFile.h index 3268ea2..a931972 100644 --- a/contrib/llvm/include/llvm/System/IncludeFile.h +++ b/contrib/llvm/include/llvm/Support/IncludeFile.h @@ -1,4 +1,4 @@ -//===- llvm/System/IncludeFile.h - Ensure Linking Of Library ---*- C++ -*-===// +//===- llvm/Support/IncludeFile.h - Ensure Linking Of Library ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,14 +16,14 @@ #define LLVM_SYSTEM_INCLUDEFILE_H /// This macro is the public interface that IncludeFile.h exports. This gives -/// us the option to implement the "link the definition" capability in any +/// us the option to implement the "link the definition" capability in any /// manner that we choose. All header files that depend on a specific .cpp /// file being linked at run time should use this macro instead of the -/// IncludeFile class directly. -/// +/// IncludeFile class directly. +/// /// For example, foo.h would use:<br/> /// <tt>FORCE_DEFINING_FILE_TO_BE_LINKED(foo)</tt><br/> -/// +/// /// And, foo.cp would use:<br/> /// <tt>DEFINING_FILE_FOR(foo)</tt><br/> #ifdef __GNUC__ @@ -34,14 +34,14 @@ extern const char name ## LinkVar; \ __attribute__((used)) static const char *const name ## LinkObj = \ &name ## LinkVar; \ - } + } #else // Otherwise use a constructor call. #define FORCE_DEFINING_FILE_TO_BE_LINKED(name) \ namespace llvm { \ extern const char name ## LinkVar; \ static const IncludeFile name ## LinkObj ( &name ## LinkVar ); \ - } + } #endif /// This macro is the counterpart to FORCE_DEFINING_FILE_TO_BE_LINKED. It should @@ -53,9 +53,9 @@ namespace llvm { /// This class is used in the implementation of FORCE_DEFINING_FILE_TO_BE_LINKED -/// macro to make sure that the implementation of a header file is included -/// into a tool that uses the header. This is solely -/// to overcome problems linking .a files and not getting the implementation +/// macro to make sure that the implementation of a header file is included +/// into a tool that uses the header. This is solely +/// to overcome problems linking .a files and not getting the implementation /// of compilation units we need. This is commonly an issue with the various /// Passes but also occurs elsewhere in LLVM. We like to use .a files because /// they link faster and provide the smallest executables. However, sometimes diff --git a/contrib/llvm/include/llvm/Support/MachO.h b/contrib/llvm/include/llvm/Support/MachO.h index 4c13177..6841a0f 100644 --- a/contrib/llvm/include/llvm/Support/MachO.h +++ b/contrib/llvm/include/llvm/Support/MachO.h @@ -14,7 +14,7 @@ #ifndef LLVM_SUPPORT_MACHO_H #define LLVM_SUPPORT_MACHO_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" // NOTE: The enums in this file are intentially named to be different than those // in the headers in /usr/include/mach (on darwin systems) to avoid conflicts @@ -23,7 +23,7 @@ namespace llvm { namespace MachO { // Enums from <mach-o/loader.h> enum { - // Constants for the "magic" field in llvm::MachO::mach_header and + // Constants for the "magic" field in llvm::MachO::mach_header and // llvm::MachO::mach_header_64 HeaderMagic32 = 0xFEEDFACEu, // MH_MAGIC HeaderMagic32Swapped = 0xCEFAEDFEu, // MH_CIGAM @@ -71,7 +71,7 @@ namespace llvm { HeaderFlagBitNoReexportedDylibs = 0x00100000u, // MH_NO_REEXPORTED_DYLIBS HeaderFlagBitPIE = 0x00200000u, // MH_PIE HeaderFlagBitDeadStrippableDylib = 0x00400000u, // MH_DEAD_STRIPPABLE_DYLIB - + // Constants for the "cmd" field in llvm::MachO::load_command LoadCommandDynamicLinkerRequired = 0x80000000u, // LC_REQ_DYLD LoadCommandSegment32 = 0x00000001u, // LC_SEGMENT @@ -110,7 +110,7 @@ namespace llvm { LoadCommandDynamicLinkerInfo = 0x00000022u, // LC_DYLD_INFO LoadCommandDynamicLinkerInfoOnly = 0x80000022u, // LC_DYLD_INFO_ONLY LoadCommandDylibLoadUpward = 0x80000023u, // LC_LOAD_UPWARD_DYLIB - + // Constant bits for the "flags" field in llvm::MachO::segment_command SegmentCommandFlagBitHighVM = 0x1u, // SG_HIGHVM SegmentCommandFlagBitFixedVMLibrary = 0x2u, // SG_FVMLIB @@ -243,20 +243,20 @@ namespace llvm { StabFunction = 0x24u, // N_FUN StabStaticSymbol = 0x26u, // N_STSYM StabLocalCommon = 0x28u, // N_LCSYM - StabBeginSymbol = 0x2Eu, // N_BNSYM + StabBeginSymbol = 0x2Eu, // N_BNSYM StabSourceFileOptions = 0x3Cu, // N_OPT StabRegisterSymbol = 0x40u, // N_RSYM StabSourceLine = 0x44u, // N_SLINE - StabEndSymbol = 0x4Eu, // N_ENSYM + StabEndSymbol = 0x4Eu, // N_ENSYM StabStructureType = 0x60u, // N_SSYM StabSourceFileName = 0x64u, // N_SO StabObjectFileName = 0x66u, // N_OSO StabLocalSymbol = 0x80u, // N_LSYM StabBeginIncludeFileName = 0x82u, // N_BINCL StabIncludeFileName = 0x84u, // N_SOL - StabCompilerParameters = 0x86u, // N_PARAMS - StabCompilerVersion = 0x88u, // N_VERSION - StabCompilerOptLevel = 0x8Au, // N_OLEVEL + StabCompilerParameters = 0x86u, // N_PARAMS + StabCompilerVersion = 0x88u, // N_VERSION + StabCompilerOptLevel = 0x8Au, // N_OLEVEL StabParameter = 0xA0u, // N_PSYM StabEndIncludeFile = 0xA2u, // N_EINCL StabAlternateEntry = 0xA4u, // N_ENTRY @@ -269,9 +269,9 @@ namespace llvm { StabLength = 0xFEu // N_LENG }; - + // Structs from <mach-o/loader.h> - + struct mach_header { uint32_t magic; uint32_t cputype; @@ -636,12 +636,12 @@ namespace llvm { }; // Get/Set functions from <mach-o/nlist.h> - + static inline uint16_t GET_LIBRARY_ORDINAL(uint16_t n_desc) { return (((n_desc) >> 8u) & 0xffu); } - + static inline void SET_LIBRARY_ORDINAL(uint16_t &n_desc, uint8_t ordinal) { n_desc = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8)); @@ -651,7 +651,7 @@ namespace llvm { { return (n_desc >> 8u) & 0x0fu; } - + static inline void SET_COMM_ALIGN (uint16_t &n_desc, uint8_t align) { n_desc = ((n_desc & 0xf0ffu) | ((align & 0x0fu) << 8u)); @@ -662,7 +662,7 @@ namespace llvm { // Capability bits used in the definition of cpu_type. CPUArchMask = 0xff000000, // Mask for architecture bits CPUArchABI64 = 0x01000000, // 64 bit ABI - + // Constants for the cputype field. CPUTypeI386 = 7, CPUTypeX86_64 = CPUTypeI386 | CPUArchABI64, @@ -673,19 +673,21 @@ namespace llvm { // Constants for the cpusubtype field. - + // X86 CPUSubType_I386_ALL = 3, CPUSubType_X86_64_ALL = 3, - + // ARM CPUSubType_ARM_ALL = 0, CPUSubType_ARM_V4T = 5, + CPUSubType_ARM_V5 = 7, CPUSubType_ARM_V6 = 6, + CPUSubType_ARM_V7 = 9, // PowerPC CPUSubType_POWERPC_ALL = 0, - + CPUSubType_SPARC_ALL = 0 }; } // end namespace MachO diff --git a/contrib/llvm/include/llvm/Support/ManagedStatic.h b/contrib/llvm/include/llvm/Support/ManagedStatic.h index b8e2235..53e73ad 100644 --- a/contrib/llvm/include/llvm/Support/ManagedStatic.h +++ b/contrib/llvm/include/llvm/Support/ManagedStatic.h @@ -14,8 +14,8 @@ #ifndef LLVM_SUPPORT_MANAGED_STATIC_H #define LLVM_SUPPORT_MANAGED_STATIC_H -#include "llvm/System/Atomic.h" -#include "llvm/System/Threading.h" +#include "llvm/Support/Atomic.h" +#include "llvm/Support/Threading.h" namespace llvm { @@ -91,12 +91,6 @@ public: } }; -template<void (*CleanupFn)(void*)> -class ManagedCleanup : public ManagedStaticBase { -public: - void Register() { RegisterManagedStatic(0, CleanupFn); } -}; - /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. void llvm_shutdown(); diff --git a/contrib/llvm/include/llvm/Support/MathExtras.h b/contrib/llvm/include/llvm/Support/MathExtras.h index 982813f..4627557 100644 --- a/contrib/llvm/include/llvm/Support/MathExtras.h +++ b/contrib/llvm/include/llvm/Support/MathExtras.h @@ -14,7 +14,7 @@ #ifndef LLVM_SUPPORT_MATHEXTRAS_H #define LLVM_SUPPORT_MATHEXTRAS_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/SwapByteOrder.h" namespace llvm { @@ -70,6 +70,18 @@ inline bool isUInt<32>(uint64_t x) { return static_cast<uint32_t>(x) == x; } +/// isUIntN - Checks if an unsigned integer fits into the given (dynamic) +/// bit width. +inline bool isUIntN(unsigned N, uint64_t x) { + return x == (x & (~0ULL >> (64 - N))); +} + +/// isIntN - Checks if an signed integer fits into the given (dynamic) +/// bit width. +inline bool isIntN(unsigned N, int64_t x) { + return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); +} + /// isMask_32 - This function returns true if the argument is a sequence of ones /// starting at the least significant bit with the remainder zero (32 bit /// version). Ex. isMask_32(0x0000FFFFU) == true. @@ -112,47 +124,19 @@ inline bool isPowerOf2_64(uint64_t Value) { /// ByteSwap_16 - This function returns a byte-swapped representation of the /// 16-bit argument, Value. inline uint16_t ByteSwap_16(uint16_t Value) { -#if defined(_MSC_VER) && !defined(_DEBUG) - // The DLL version of the runtime lacks these functions (bug!?), but in a - // release build they're replaced with BSWAP instructions anyway. - return _byteswap_ushort(Value); -#else - uint16_t Hi = Value << 8; - uint16_t Lo = Value >> 8; - return Hi | Lo; -#endif + return sys::SwapByteOrder_16(Value); } /// ByteSwap_32 - This function returns a byte-swapped representation of the /// 32-bit argument, Value. inline uint32_t ByteSwap_32(uint32_t Value) { -#if defined(__llvm__) || \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) - return __builtin_bswap32(Value); -#elif defined(_MSC_VER) && !defined(_DEBUG) - return _byteswap_ulong(Value); -#else - uint32_t Byte0 = Value & 0x000000FF; - uint32_t Byte1 = Value & 0x0000FF00; - uint32_t Byte2 = Value & 0x00FF0000; - uint32_t Byte3 = Value & 0xFF000000; - return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); -#endif + return sys::SwapByteOrder_32(Value); } /// ByteSwap_64 - This function returns a byte-swapped representation of the /// 64-bit argument, Value. inline uint64_t ByteSwap_64(uint64_t Value) { -#if defined(__llvm__) || \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) - return __builtin_bswap64(Value); -#elif defined(_MSC_VER) && !defined(_DEBUG) - return _byteswap_uint64(Value); -#else - uint64_t Hi = ByteSwap_32(uint32_t(Value)); - uint32_t Lo = ByteSwap_32(uint32_t(Value >> 32)); - return (Hi << 32) | Lo; -#endif + return sys::SwapByteOrder_64(Value); } /// CountLeadingZeros_32 - this function performs the platform optimal form of diff --git a/contrib/llvm/include/llvm/System/Memory.h b/contrib/llvm/include/llvm/Support/Memory.h index 2dd36e8..9c3f85b 100644 --- a/contrib/llvm/include/llvm/System/Memory.h +++ b/contrib/llvm/include/llvm/Support/Memory.h @@ -1,4 +1,4 @@ -//===- llvm/System/Memory.h - Memory Support --------------------*- C++ -*-===// +//===- llvm/Support/Memory.h - Memory Support --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_MEMORY_H #define LLVM_SYSTEM_MEMORY_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> namespace llvm { @@ -51,7 +51,7 @@ namespace sys { /// /// On success, this returns a non-null memory block, otherwise it returns /// a null memory block and fills in *ErrMsg. - /// + /// /// @brief Allocate Read/Write/Execute memory. static MemoryBlock AllocateRWX(size_t NumBytes, const MemoryBlock *NearBlock, @@ -65,8 +65,8 @@ namespace sys { /// in *ErrMsg. /// @brief Release Read/Write/Execute memory. static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = 0); - - + + /// InvalidateInstructionCache - Before the JIT can run a block of code /// that has been emitted it must invalidate the instruction cache on some /// platforms. @@ -82,11 +82,11 @@ namespace sys { /// boundaries, and the JIT internal allocations are not page aligned. static bool setWritable (MemoryBlock &M, std::string *ErrMsg = 0); - /// setRangeExecutable - Mark the page containing a range of addresses + /// setRangeExecutable - Mark the page containing a range of addresses /// as executable. static bool setRangeExecutable(const void *Addr, size_t Size); - /// setRangeWritable - Mark the page containing a range of addresses + /// setRangeWritable - Mark the page containing a range of addresses /// as writable. static bool setRangeWritable(const void *Addr, size_t Size); }; diff --git a/contrib/llvm/include/llvm/Support/MemoryBuffer.h b/contrib/llvm/include/llvm/Support/MemoryBuffer.h index 8a41aa5..b6243b7 100644 --- a/contrib/llvm/include/llvm/Support/MemoryBuffer.h +++ b/contrib/llvm/include/llvm/Support/MemoryBuffer.h @@ -15,12 +15,13 @@ #define LLVM_SUPPORT_MEMORYBUFFER_H #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" -#include <string> -#include <sys/stat.h> +#include "llvm/Support/DataTypes.h" namespace llvm { +class error_code; +template<class T> class OwningPtr; + /// MemoryBuffer - This interface provides simple read-only access to a block /// of memory, and provides simple methods for reading files and standard input /// into a memory buffer. In addition to basic access to the characters in the @@ -47,8 +48,8 @@ public: const char *getBufferEnd() const { return BufferEnd; } size_t getBufferSize() const { return BufferEnd-BufferStart; } - StringRef getBuffer() const { - return StringRef(BufferStart, getBufferSize()); + StringRef getBuffer() const { + return StringRef(BufferStart, getBufferSize()); } /// getBufferIdentifier - Return an identifier for this buffer, typically the @@ -61,23 +62,26 @@ public: /// MemoryBuffer if successful, otherwise returning null. If FileSize is /// specified, this means that the client knows that the file exists and that /// it has the specified size. - static MemoryBuffer *getFile(StringRef Filename, - std::string *ErrStr = 0, - int64_t FileSize = -1, - struct stat *FileInfo = 0); - static MemoryBuffer *getFile(const char *Filename, - std::string *ErrStr = 0, - int64_t FileSize = -1, - struct stat *FileInfo = 0); + static error_code getFile(StringRef Filename, OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); + static error_code getFile(const char *Filename, + OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); + + /// getOpenFile - Given an already-open file descriptor, read the file and + /// return a MemoryBuffer. + static error_code getOpenFile(int FD, const char *Filename, + OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note - /// that EndPtr[0] must be a null byte and be accessible! + /// that InputData must be null terminated. static MemoryBuffer *getMemBuffer(StringRef InputData, StringRef BufferName = ""); /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, - /// copying the contents and taking ownership of it. This has no requirements - /// on EndPtr[0]. + /// copying the contents and taking ownership of it. InputData does not + /// have to be null terminated. static MemoryBuffer *getMemBufferCopy(StringRef InputData, StringRef BufferName = ""); @@ -95,21 +99,19 @@ public: StringRef BufferName = ""); /// getSTDIN - Read all of stdin into a file buffer, and return it. - /// If an error occurs, this returns null and fills in *ErrStr with a reason. - static MemoryBuffer *getSTDIN(std::string *ErrStr = 0); + /// If an error occurs, this returns null and sets ec. + static error_code getSTDIN(OwningPtr<MemoryBuffer> &result); /// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin - /// if the Filename is "-". If an error occurs, this returns null and fills - /// in *ErrStr with a reason. - static MemoryBuffer *getFileOrSTDIN(StringRef Filename, - std::string *ErrStr = 0, - int64_t FileSize = -1, - struct stat *FileInfo = 0); - static MemoryBuffer *getFileOrSTDIN(const char *Filename, - std::string *ErrStr = 0, - int64_t FileSize = -1, - struct stat *FileInfo = 0); + /// if the Filename is "-". If an error occurs, this returns null and sets + /// ec. + static error_code getFileOrSTDIN(StringRef Filename, + OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); + static error_code getFileOrSTDIN(const char *Filename, + OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Support/MemoryObject.h b/contrib/llvm/include/llvm/Support/MemoryObject.h index e193ca2..dec0f13 100644 --- a/contrib/llvm/include/llvm/Support/MemoryObject.h +++ b/contrib/llvm/include/llvm/Support/MemoryObject.h @@ -10,7 +10,7 @@ #ifndef MEMORYOBJECT_H #define MEMORYOBJECT_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/contrib/llvm/include/llvm/System/Mutex.h b/contrib/llvm/include/llvm/Support/Mutex.h index 71d1006..42ea630 100644 --- a/contrib/llvm/include/llvm/System/Mutex.h +++ b/contrib/llvm/include/llvm/Support/Mutex.h @@ -1,4 +1,4 @@ -//===- llvm/System/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===// +//===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_MUTEX_H #define LLVM_SYSTEM_MUTEX_H -#include "llvm/System/Threading.h" +#include "llvm/Support/Threading.h" #include <cassert> namespace llvm @@ -79,9 +79,9 @@ namespace llvm void operator=(const MutexImpl &); /// @} }; - - - /// SmartMutex - A mutex with a compile time constant parameter that + + + /// SmartMutex - A mutex with a compile time constant parameter that /// indicates whether this mutex should become a no-op when we're not /// running in multithreaded mode. template<bool mt_only> @@ -91,7 +91,7 @@ namespace llvm public: explicit SmartMutex(bool rec = true) : MutexImpl(rec), acquired(0), recursive(rec) { } - + bool acquire() { if (!mt_only || llvm_is_multithreaded()) { return MutexImpl::acquire(); @@ -124,29 +124,29 @@ namespace llvm return MutexImpl::tryacquire(); else return true; } - + private: SmartMutex(const SmartMutex<mt_only> & original); void operator=(const SmartMutex<mt_only> &); }; - + /// Mutex - A standard, always enforced mutex. typedef SmartMutex<false> Mutex; - + template<bool mt_only> class SmartScopedLock { SmartMutex<mt_only>& mtx; - + public: SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { mtx.acquire(); } - + ~SmartScopedLock() { mtx.release(); } }; - + typedef SmartScopedLock<false> ScopedLock; } } diff --git a/contrib/llvm/include/llvm/Support/MutexGuard.h b/contrib/llvm/include/llvm/Support/MutexGuard.h index 9958b97..cd13bfe 100644 --- a/contrib/llvm/include/llvm/Support/MutexGuard.h +++ b/contrib/llvm/include/llvm/Support/MutexGuard.h @@ -15,7 +15,7 @@ #ifndef LLVM_SUPPORT_MUTEXGUARD_H #define LLVM_SUPPORT_MUTEXGUARD_H -#include "llvm/System/Mutex.h" +#include "llvm/Support/Mutex.h" namespace llvm { /// Instances of this class acquire a given Mutex Lock when constructed and diff --git a/contrib/llvm/include/llvm/Support/NoFolder.h b/contrib/llvm/include/llvm/Support/NoFolder.h index 01256e1..d7b5b42 100644 --- a/contrib/llvm/include/llvm/Support/NoFolder.h +++ b/contrib/llvm/include/llvm/Support/NoFolder.h @@ -15,8 +15,7 @@ // llvm/Analysis/ConstantFolding.h. // // Note: since it is not actually possible to create unfolded constants, this -// class returns values rather than constants. The values do not have names, -// even if names were provided to IRBuilder, which may be confusing. +// class returns instructions rather than constants. // //===----------------------------------------------------------------------===// @@ -30,7 +29,7 @@ namespace llvm { class LLVMContext; -/// NoFolder - Create "constants" (actually, values) with no folding. +/// NoFolder - Create "constants" (actually, instructions) with no folding. class NoFolder { public: explicit NoFolder(LLVMContext &) {} @@ -39,84 +38,87 @@ public: // Binary Operators //===--------------------------------------------------------------------===// - Value *CreateAdd(Constant *LHS, Constant *RHS) const { + Instruction *CreateAdd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateAdd(LHS, RHS); } - Value *CreateNSWAdd(Constant *LHS, Constant *RHS) const { + Instruction *CreateNSWAdd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNSWAdd(LHS, RHS); } - Value *CreateNUWAdd(Constant *LHS, Constant *RHS) const { + Instruction *CreateNUWAdd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNUWAdd(LHS, RHS); } - Value *CreateFAdd(Constant *LHS, Constant *RHS) const { + Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFAdd(LHS, RHS); } - Value *CreateSub(Constant *LHS, Constant *RHS) const { + Instruction *CreateSub(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateSub(LHS, RHS); } - Value *CreateNSWSub(Constant *LHS, Constant *RHS) const { + Instruction *CreateNSWSub(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNSWSub(LHS, RHS); } - Value *CreateNUWSub(Constant *LHS, Constant *RHS) const { + Instruction *CreateNUWSub(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNUWSub(LHS, RHS); } - Value *CreateFSub(Constant *LHS, Constant *RHS) const { + Instruction *CreateFSub(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFSub(LHS, RHS); } - Value *CreateMul(Constant *LHS, Constant *RHS) const { + Instruction *CreateMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateMul(LHS, RHS); } - Value *CreateNSWMul(Constant *LHS, Constant *RHS) const { + Instruction *CreateNSWMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNSWMul(LHS, RHS); } - Value *CreateNUWMul(Constant *LHS, Constant *RHS) const { + Instruction *CreateNUWMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNUWMul(LHS, RHS); } - Value *CreateFMul(Constant *LHS, Constant *RHS) const { + Instruction *CreateFMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFMul(LHS, RHS); } - Value *CreateUDiv(Constant *LHS, Constant *RHS) const { + Instruction *CreateUDiv(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateUDiv(LHS, RHS); } - Value *CreateSDiv(Constant *LHS, Constant *RHS) const { + Instruction *CreateExactUDiv(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateExactUDiv(LHS, RHS); + } + Instruction *CreateSDiv(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateSDiv(LHS, RHS); } - Value *CreateExactSDiv(Constant *LHS, Constant *RHS) const { + Instruction *CreateExactSDiv(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateExactSDiv(LHS, RHS); } - Value *CreateFDiv(Constant *LHS, Constant *RHS) const { + Instruction *CreateFDiv(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFDiv(LHS, RHS); } - Value *CreateURem(Constant *LHS, Constant *RHS) const { + Instruction *CreateURem(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateURem(LHS, RHS); } - Value *CreateSRem(Constant *LHS, Constant *RHS) const { + Instruction *CreateSRem(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateSRem(LHS, RHS); } - Value *CreateFRem(Constant *LHS, Constant *RHS) const { + Instruction *CreateFRem(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFRem(LHS, RHS); } - Value *CreateShl(Constant *LHS, Constant *RHS) const { + Instruction *CreateShl(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateShl(LHS, RHS); } - Value *CreateLShr(Constant *LHS, Constant *RHS) const { + Instruction *CreateLShr(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateLShr(LHS, RHS); } - Value *CreateAShr(Constant *LHS, Constant *RHS) const { + Instruction *CreateAShr(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateAShr(LHS, RHS); } - Value *CreateAnd(Constant *LHS, Constant *RHS) const { + Instruction *CreateAnd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateAnd(LHS, RHS); } - Value *CreateOr(Constant *LHS, Constant *RHS) const { + Instruction *CreateOr(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateOr(LHS, RHS); } - Value *CreateXor(Constant *LHS, Constant *RHS) const { + Instruction *CreateXor(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateXor(LHS, RHS); } - Value *CreateBinOp(Instruction::BinaryOps Opc, - Constant *LHS, Constant *RHS) const { + Instruction *CreateBinOp(Instruction::BinaryOps Opc, + Constant *LHS, Constant *RHS) const { return BinaryOperator::Create(Opc, LHS, RHS); } @@ -124,16 +126,19 @@ public: // Unary Operators //===--------------------------------------------------------------------===// - Value *CreateNeg(Constant *C) const { + Instruction *CreateNeg(Constant *C) const { return BinaryOperator::CreateNeg(C); } - Value *CreateNSWNeg(Constant *C) const { + Instruction *CreateNSWNeg(Constant *C) const { return BinaryOperator::CreateNSWNeg(C); } - Value *CreateNUWNeg(Constant *C) const { + Instruction *CreateNUWNeg(Constant *C) const { return BinaryOperator::CreateNUWNeg(C); } - Value *CreateNot(Constant *C) const { + Instruction *CreateFNeg(Constant *C) const { + return BinaryOperator::CreateFNeg(C); + } + Instruction *CreateNot(Constant *C) const { return BinaryOperator::CreateNot(C); } @@ -145,8 +150,8 @@ public: unsigned NumIdx) const { return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); } - Value *CreateGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx) const { + Instruction *CreateGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { return GetElementPtrInst::Create(C, IdxList, IdxList+NumIdx); } @@ -154,8 +159,8 @@ public: unsigned NumIdx) const { return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); } - Value *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx) const { + Instruction *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { return GetElementPtrInst::CreateInBounds(C, IdxList, IdxList+NumIdx); } @@ -163,23 +168,51 @@ public: // Cast/Conversion Operators //===--------------------------------------------------------------------===// - Value *CreateCast(Instruction::CastOps Op, Constant *C, + Instruction *CreateCast(Instruction::CastOps Op, Constant *C, const Type *DestTy) const { return CastInst::Create(Op, C, DestTy); } - Value *CreateIntCast(Constant *C, const Type *DestTy, + Instruction *CreatePointerCast(Constant *C, const Type *DestTy) const { + return CastInst::CreatePointerCast(C, DestTy); + } + Instruction *CreateIntCast(Constant *C, const Type *DestTy, bool isSigned) const { return CastInst::CreateIntegerCast(C, DestTy, isSigned); } + Instruction *CreateFPCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateFPCast(C, DestTy); + } + + Instruction *CreateBitCast(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::BitCast, C, DestTy); + } + Instruction *CreateIntToPtr(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::IntToPtr, C, DestTy); + } + Instruction *CreatePtrToInt(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::PtrToInt, C, DestTy); + } + Instruction *CreateZExtOrBitCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateZExtOrBitCast(C, DestTy); + } + Instruction *CreateSExtOrBitCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateSExtOrBitCast(C, DestTy); + } + + Instruction *CreateTruncOrBitCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateTruncOrBitCast(C, DestTy); + } //===--------------------------------------------------------------------===// // Compare Instructions //===--------------------------------------------------------------------===// - Value *CreateICmp(CmpInst::Predicate P, Constant *LHS, Constant *RHS) const { + Instruction *CreateICmp(CmpInst::Predicate P, + Constant *LHS, Constant *RHS) const { return new ICmpInst(P, LHS, RHS); } - Value *CreateFCmp(CmpInst::Predicate P, Constant *LHS, Constant *RHS) const { + Instruction *CreateFCmp(CmpInst::Predicate P, + Constant *LHS, Constant *RHS) const { return new FCmpInst(P, LHS, RHS); } @@ -187,30 +220,33 @@ public: // Other Instructions //===--------------------------------------------------------------------===// - Value *CreateSelect(Constant *C, Constant *True, Constant *False) const { + Instruction *CreateSelect(Constant *C, + Constant *True, Constant *False) const { return SelectInst::Create(C, True, False); } - Value *CreateExtractElement(Constant *Vec, Constant *Idx) const { + Instruction *CreateExtractElement(Constant *Vec, Constant *Idx) const { return ExtractElementInst::Create(Vec, Idx); } - Value *CreateInsertElement(Constant *Vec, Constant *NewElt, - Constant *Idx) const { + Instruction *CreateInsertElement(Constant *Vec, Constant *NewElt, + Constant *Idx) const { return InsertElementInst::Create(Vec, NewElt, Idx); } - Value *CreateShuffleVector(Constant *V1, Constant *V2, Constant *Mask) const { + Instruction *CreateShuffleVector(Constant *V1, Constant *V2, + Constant *Mask) const { return new ShuffleVectorInst(V1, V2, Mask); } - Value *CreateExtractValue(Constant *Agg, const unsigned *IdxList, - unsigned NumIdx) const { + Instruction *CreateExtractValue(Constant *Agg, const unsigned *IdxList, + unsigned NumIdx) const { return ExtractValueInst::Create(Agg, IdxList, IdxList+NumIdx); } - Value *CreateInsertValue(Constant *Agg, Constant *Val, - const unsigned *IdxList, unsigned NumIdx) const { + Instruction *CreateInsertValue(Constant *Agg, Constant *Val, + const unsigned *IdxList, + unsigned NumIdx) const { return InsertValueInst::Create(Agg, Val, IdxList, IdxList+NumIdx); } }; diff --git a/contrib/llvm/include/llvm/Support/Path.h b/contrib/llvm/include/llvm/Support/Path.h new file mode 100644 index 0000000..196eecc --- /dev/null +++ b/contrib/llvm/include/llvm/Support/Path.h @@ -0,0 +1,16 @@ +//===- llvm/Support/Path.h - Path Operating System Concept ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file currently includes both PathV1 and PathV2 to facilitate moving +// clients over to the new interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/PathV1.h" +#include "llvm/Support/PathV2.h" diff --git a/contrib/llvm/include/llvm/System/Path.h b/contrib/llvm/include/llvm/Support/PathV1.h index 23b18d4..a1c3f6a 100644 --- a/contrib/llvm/include/llvm/System/Path.h +++ b/contrib/llvm/include/llvm/Support/PathV1.h @@ -1,4 +1,4 @@ -//===- llvm/System/Path.h - Path Operating System Concept -------*- C++ -*-===// +//===- llvm/Support/PathV1.h - Path Operating System Concept ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,11 +15,17 @@ #define LLVM_SYSTEM_PATH_H #include "llvm/ADT/StringRef.h" -#include "llvm/System/TimeValue.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/TimeValue.h" #include <set> #include <string> #include <vector> +#define LLVM_PATH_DEPRECATED_MSG(replacement) \ + "PathV1 has been deprecated and will be removed as soon as all LLVM and" \ + " Clang clients have been moved over to PathV2. Please use `" #replacement \ + "` from PathV2 instead." + namespace llvm { namespace sys { @@ -89,10 +95,11 @@ namespace sys { /// Construct a path to the root directory of the file system. The root /// directory is a top level directory above which there are no more /// directories. For example, on UNIX, the root directory is /. On Windows - /// it is C:\. Other operating systems may have different notions of + /// it is file:///. Other operating systems may have different notions of /// what the root directory is or none at all. In that case, a consistent /// default root directory will be used. - static Path GetRootDirectory(); + LLVM_ATTRIBUTE_DEPRECATED(static Path GetRootDirectory(), + LLVM_PATH_DEPRECATED_MSG(NOTHING)); /// Construct a path to a unique temporary directory that is created in /// a "standard" place for the operating system. The directory is @@ -100,14 +107,12 @@ namespace sys { /// cannot be created, the function will throw an exception. /// @returns an invalid path (empty) on error /// @param ErrMsg Optional place for an error message if an error occurs - /// @brief Constrct a path to an new, unique, existing temporary + /// @brief Construct a path to an new, unique, existing temporary /// directory. static Path GetTemporaryDirectory(std::string* ErrMsg = 0); /// Construct a vector of sys::Path that contains the "standard" system - /// library paths suitable for linking into programs. This function *must* - /// return the value of LLVM_LIB_SEARCH_PATH as the first item in \p Paths - /// if that environment variable is set and it references a directory. + /// library paths suitable for linking into programs. /// @brief Construct a path to the system library directory static void GetSystemLibraryPaths(std::vector<sys::Path>& Paths); @@ -154,6 +159,12 @@ namespace sys { /// @brief Returns the current working directory. static Path GetCurrentDirectory(); + /// Return the suffix commonly used on file names that contain an + /// executable. + /// @returns The executable file suffix for the current platform. + /// @brief Return the executable file suffix. + static StringRef GetEXESuffix(); + /// Return the suffix commonly used on file names that contain a shared /// object, shared archive, or dynamic link library. Such files are /// linked at runtime into a process and their code images are shared @@ -250,23 +261,27 @@ namespace sys { bool isEmpty() const { return path.empty(); } /// This function returns the last component of the path name. The last - /// component is the file or directory name occuring after the last + /// component is the file or directory name occurring after the last /// directory separator. If no directory separator is present, the entire /// path name is returned (i.e. same as toString). /// @returns StringRef containing the last component of the path name. /// @brief Returns the last component of the path name. - StringRef getLast() const; + LLVM_ATTRIBUTE_DEPRECATED( + StringRef getLast() const, + LLVM_PATH_DEPRECATED_MSG(path::filename)); /// This function strips off the path and suffix of the file or directory /// name and returns just the basename. For example /a/foo.bar would cause /// this function to return "foo". /// @returns StringRef containing the basename of the path /// @brief Get the base name of the path - StringRef getBasename() const; + LLVM_ATTRIBUTE_DEPRECATED(StringRef getBasename() const, + LLVM_PATH_DEPRECATED_MSG(path::stem)); /// This function strips off the suffix of the path beginning with the /// path separator ('/' on Unix, '\' on Windows) and returns the result. - StringRef getDirname() const; + LLVM_ATTRIBUTE_DEPRECATED(StringRef getDirname() const, + LLVM_PATH_DEPRECATED_MSG(path::parent_path)); /// This function strips off the path and basename(up to and /// including the last dot) of the file or directory name and @@ -274,7 +289,8 @@ namespace sys { /// this function to return "bar". /// @returns StringRef containing the suffix of the path /// @brief Get the suffix of the path - StringRef getSuffix() const; + LLVM_ATTRIBUTE_DEPRECATED(StringRef getSuffix() const, + LLVM_PATH_DEPRECATED_MSG(path::extension)); /// Obtain a 'C' string for the path name. /// @returns a 'C' string containing the path name. @@ -296,12 +312,16 @@ namespace sys { /// This function determines if the path name is absolute, as opposed to /// relative. /// @brief Determine if the path is absolute. +//FIXME: LLVM_ATTRIBUTE_DEPRECATED( bool isAbsolute() const; +//FIXME: LLVMV_PATH_DEPRECATED_MSG(path::is_absolute)); /// This function determines if the path name is absolute, as opposed to /// relative. /// @brief Determine if the path is absolute. - static bool isAbsolute(const char *NameStart, unsigned NameLen); + LLVM_ATTRIBUTE_DEPRECATED( + static bool isAbsolute(const char *NameStart, unsigned NameLen), + LLVM_PATH_DEPRECATED_MSG(path::is_absolute)); /// This function opens the file associated with the path name provided by /// the Path object and reads its magic number. If the magic number at the @@ -309,7 +329,8 @@ namespace sys { /// cases (file not found, file not accessible, etc.) it returns false. /// @returns true if the magic number of the file matches \p magic. /// @brief Determine if file has a specific magic number - bool hasMagicNumber(StringRef magic) const; + LLVM_ATTRIBUTE_DEPRECATED(bool hasMagicNumber(StringRef magic) const, + LLVM_PATH_DEPRECATED_MSG(fs::has_magic)); /// This function retrieves the first \p len bytes of the file associated /// with \p this. These bytes are returned as the "magic number" in the @@ -342,19 +363,39 @@ namespace sys { /// @brief Determine if the path references a dynamic library. bool isDynamicLibrary() const; + /// This function determines if the path name in the object references a + /// native object file by looking at it's magic number. The term object + /// file is defined as "an organized collection of separate, named + /// sequences of binary data." This covers the obvious file formats such + /// as COFF and ELF, but it also includes llvm ir bitcode, archives, + /// libraries, etc... + /// @returns true if the file starts with the magic number for an object + /// file. + /// @brief Determine if the path references an object file. + bool isObjectFile() const; + /// This function determines if the path name references an existing file /// or directory in the file system. /// @returns true if the pathname references an existing file or /// directory. /// @brief Determines if the path is a file or directory in /// the file system. - bool exists() const; + LLVM_ATTRIBUTE_DEPRECATED(bool exists() const, + LLVM_PATH_DEPRECATED_MSG(fs::exists)); - /// This function determines if the path name refences an + /// This function determines if the path name references an /// existing directory. /// @returns true if the pathname references an existing directory. - /// @brief Determins if the path is a directory in the file system. - bool isDirectory() const; + /// @brief Determines if the path is a directory in the file system. + LLVM_ATTRIBUTE_DEPRECATED(bool isDirectory() const, + LLVM_PATH_DEPRECATED_MSG(fs::is_directory)); + + /// This function determines if the path name references an + /// existing symbolic link. + /// @returns true if the pathname references an existing symlink. + /// @brief Determines if the path is a symlink in the file system. + LLVM_ATTRIBUTE_DEPRECATED(bool isSymLink() const, + LLVM_PATH_DEPRECATED_MSG(fs::is_symlink)); /// This function determines if the path name references a readable file /// or directory in the file system. This function checks for @@ -374,9 +415,9 @@ namespace sys { /// in the file system. bool canWrite() const; - /// This function checks that what we're trying to work only on a regular file. - /// Check for things like /dev/null, any block special file, - /// or other things that aren't "regular" regular files. + /// This function checks that what we're trying to work only on a regular + /// file. Check for things like /dev/null, any block special file, or + /// other things that aren't "regular" regular files. /// @returns true if the file is S_ISREG. /// @brief Determines if the file is a regular file bool isRegularFile() const; @@ -434,13 +475,9 @@ namespace sys { bool appendComponent(StringRef component); /// A period and the \p suffix are appended to the end of the pathname. - /// The precondition for this function is that the Path reference a file - /// name (i.e. isFile() returns true). If the Path is not a file, no - /// action is taken and the function returns false. If the path would - /// become invalid for the host operating system, false is returned. - /// @returns false if the suffix could not be added, true if it was. + /// When the \p suffix is empty, no action is performed. /// @brief Adds a period and the \p suffix to the end of the pathname. - bool appendSuffix(StringRef suffix); + void appendSuffix(StringRef suffix); /// The suffix of the filename is erased. The suffix begins with and /// includes the last . character in the filename after the last directory @@ -462,7 +499,9 @@ namespace sys { /// The current Path name is made absolute by prepending the /// current working directory if necessary. - void makeAbsolute(); + LLVM_ATTRIBUTE_DEPRECATED( + void makeAbsolute(), + LLVM_PATH_DEPRECATED_MSG(fs::make_absolute)); /// @} /// @name Disk Mutators @@ -594,7 +633,7 @@ namespace sys { /// efficiency. First, the file status requires additional space and the space /// is incorporated directly into PathWithStatus without an additional malloc. /// Second, obtaining status information is an expensive operation on most - /// operating systems so we want to be careful and explicity about where we + /// operating systems so we want to be careful and explicit about where we /// allow this operation in LLVM. /// @brief Path with file status class. class PathWithStatus : public Path { @@ -688,7 +727,7 @@ namespace sys { Mach_O_Executable_FileType, ///< Mach-O Executable Mach_O_FixedVirtualMemorySharedLib_FileType, ///< Mach-O Shared Lib, FVM Mach_O_Core_FileType, ///< Mach-O Core File - Mach_O_PreloadExectuable_FileType, ///< Mach-O Preloaded Executable + Mach_O_PreloadExecutable_FileType, ///< Mach-O Preloaded Executable Mach_O_DynamicallyLinkedSharedLib_FileType, ///< Mach-O dynlinked shared lib Mach_O_DynamicLinker_FileType, ///< The Mach-O dynamic linker Mach_O_Bundle_FileType, ///< Mach-O Bundle file diff --git a/contrib/llvm/include/llvm/Support/PathV2.h b/contrib/llvm/include/llvm/Support/PathV2.h new file mode 100644 index 0000000..2515633 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/PathV2.h @@ -0,0 +1,347 @@ +//===- llvm/Support/PathV2.h - Path Operating System Concept ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::path namespace. It is designed after +// TR2/boost filesystem (v3), but modified to remove exception handling and the +// path class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PATHV2_H +#define LLVM_SUPPORT_PATHV2_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/DataTypes.h" +#include <iterator> + +namespace llvm { +namespace sys { +namespace path { + +/// @name Lexical Component Iterator +/// @{ + +/// @brief Path iterator. +/// +/// This is a bidirectional iterator that iterates over the individual +/// components in \a path. The forward traversal order is as follows: +/// * The root-name element, if present. +/// * The root-directory element, if present. +/// * Each successive filename element, if present. +/// * Dot, if one or more trailing non-root slash characters are present. +/// The backwards traversal order is the reverse of forward traversal. +/// +/// Iteration examples. Each component is separated by ',': +/// / => / +/// /foo => /,foo +/// foo/ => foo,. +/// /foo/bar => /,foo,bar +/// ../ => ..,. +/// C:\foo\bar => C:,/,foo,bar +/// +class const_iterator { + StringRef Path; //< The entire path. + StringRef Component; //< The current component. Not necessarily in Path. + size_t Position; //< The iterators current position within Path. + + // An end iterator has Position = Path.size() + 1. + friend const_iterator begin(StringRef path); + friend const_iterator end(StringRef path); + +public: + typedef const StringRef value_type; + typedef ptrdiff_t difference_type; + typedef value_type &reference; + typedef value_type *pointer; + typedef std::bidirectional_iterator_tag iterator_category; + + reference operator*() const { return Component; } + pointer operator->() const { return &Component; } + const_iterator &operator++(); // preincrement + const_iterator &operator++(int); // postincrement + const_iterator &operator--(); // predecrement + const_iterator &operator--(int); // postdecrement + bool operator==(const const_iterator &RHS) const; + bool operator!=(const const_iterator &RHS) const; + + /// @brief Difference in bytes between this and RHS. + ptrdiff_t operator-(const const_iterator &RHS) const; +}; + +typedef std::reverse_iterator<const_iterator> reverse_iterator; + +/// @brief Get begin iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized with the first component of \a path. +const_iterator begin(StringRef path); + +/// @brief Get end iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized to the end of \a path. +const_iterator end(StringRef path); + +/// @brief Get reverse begin iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized with the first reverse component of \a path. +inline reverse_iterator rbegin(StringRef path) { + return reverse_iterator(end(path)); +} + +/// @brief Get reverse end iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized to the reverse end of \a path. +inline reverse_iterator rend(StringRef path) { + return reverse_iterator(begin(path)); +} + +/// @} +/// @name Lexical Modifiers +/// @{ + +/// @brief Remove the last component from \a path unless it is the root dir. +/// +/// directory/filename.cpp => directory/ +/// directory/ => directory +/// / => / +/// +/// @param path A path that is modified to not have a file component. +void remove_filename(SmallVectorImpl<char> &path); + +/// @brief Replace the file extension of \a path with \a extension. +/// +/// ./filename.cpp => ./filename.extension +/// ./filename => ./filename.extension +/// ./ => ./.extension +/// +/// @param path A path that has its extension replaced with \a extension. +/// @param extension The extension to be added. It may be empty. It may also +/// optionally start with a '.', if it does not, one will be +/// prepended. +void replace_extension(SmallVectorImpl<char> &path, const Twine &extension); + +/// @brief Append to path. +/// +/// /foo + bar/f => /foo/bar/f +/// /foo/ + bar/f => /foo/bar/f +/// foo + bar/f => foo/bar/f +/// +/// @param path Set to \a path + \a component. +/// @param component The component to be appended to \a path. +void append(SmallVectorImpl<char> &path, const Twine &a, + const Twine &b = "", + const Twine &c = "", + const Twine &d = ""); + +/// @brief Append to path. +/// +/// /foo + [bar,f] => /foo/bar/f +/// /foo/ + [bar,f] => /foo/bar/f +/// foo + [bar,f] => foo/bar/f +/// +/// @param path Set to \a path + [\a begin, \a end). +/// @param begin Start of components to append. +/// @param end One past the end of components to append. +void append(SmallVectorImpl<char> &path, + const_iterator begin, const_iterator end); + +/// @} +/// @name Transforms (or some other better name) +/// @{ + +/// Convert path to the native form. This is used to give paths to users and +/// operating system calls in the platform's normal way. For example, on Windows +/// all '/' are converted to '\'. +/// +/// @param path A path that is transformed to native format. +/// @param result Holds the result of the transformation. +void native(const Twine &path, SmallVectorImpl<char> &result); + +/// @} +/// @name Lexical Observers +/// @{ + +/// @brief Get root name. +/// +/// //net/hello => //net +/// c:/hello => c: (on Windows, on other platforms nothing) +/// /hello => <empty> +/// +/// @param path Input path. +/// @result The root name of \a path if it has one, otherwise "". +const StringRef root_name(StringRef path); + +/// @brief Get root directory. +/// +/// /goo/hello => / +/// c:/hello => / +/// d/file.txt => <empty> +/// +/// @param path Input path. +/// @result The root directory of \a path if it has one, otherwise +/// "". +const StringRef root_directory(StringRef path); + +/// @brief Get root path. +/// +/// Equivalent to root_name + root_directory. +/// +/// @param path Input path. +/// @result The root path of \a path if it has one, otherwise "". +const StringRef root_path(StringRef path); + +/// @brief Get relative path. +/// +/// C:\hello\world => hello\world +/// foo/bar => foo/bar +/// /foo/bar => foo/bar +/// +/// @param path Input path. +/// @result The path starting after root_path if one exists, otherwise "". +const StringRef relative_path(StringRef path); + +/// @brief Get parent path. +/// +/// / => <empty> +/// /foo => / +/// foo/../bar => foo/.. +/// +/// @param path Input path. +/// @result The parent path of \a path if one exists, otherwise "". +const StringRef parent_path(StringRef path); + +/// @brief Get filename. +/// +/// /foo.txt => foo.txt +/// . => . +/// .. => .. +/// / => / +/// +/// @param path Input path. +/// @result The filename part of \a path. This is defined as the last component +/// of \a path. +const StringRef filename(StringRef path); + +/// @brief Get stem. +/// +/// If filename contains a dot but not solely one or two dots, result is the +/// substring of filename ending at (but not including) the last dot. Otherwise +/// it is filename. +/// +/// /foo/bar.txt => bar +/// /foo/bar => bar +/// /foo/.txt => <empty> +/// /foo/. => . +/// /foo/.. => .. +/// +/// @param path Input path. +/// @result The stem of \a path. +const StringRef stem(StringRef path); + +/// @brief Get extension. +/// +/// If filename contains a dot but not solely one or two dots, result is the +/// substring of filename starting at (and including) the last dot, and ending +/// at the end of \a path. Otherwise "". +/// +/// /foo/bar.txt => .txt +/// /foo/bar => <empty> +/// /foo/.txt => .txt +/// +/// @param path Input path. +/// @result The extension of \a path. +const StringRef extension(StringRef path); + +/// @brief Check whether the given char is a path separator on the host OS. +/// +/// @param value a character +/// @result true if \a value is a path separator character on the host OS +bool is_separator(char value); + +/// @brief Has root name? +/// +/// root_name != "" +/// +/// @param path Input path. +/// @result True if the path has a root name, false otherwise. +bool has_root_name(const Twine &path); + +/// @brief Has root directory? +/// +/// root_directory != "" +/// +/// @param path Input path. +/// @result True if the path has a root directory, false otherwise. +bool has_root_directory(const Twine &path); + +/// @brief Has root path? +/// +/// root_path != "" +/// +/// @param path Input path. +/// @result True if the path has a root path, false otherwise. +bool has_root_path(const Twine &path); + +/// @brief Has relative path? +/// +/// relative_path != "" +/// +/// @param path Input path. +/// @result True if the path has a relative path, false otherwise. +bool has_relative_path(const Twine &path); + +/// @brief Has parent path? +/// +/// parent_path != "" +/// +/// @param path Input path. +/// @result True if the path has a parent path, false otherwise. +bool has_parent_path(const Twine &path); + +/// @brief Has filename? +/// +/// filename != "" +/// +/// @param path Input path. +/// @result True if the path has a filename, false otherwise. +bool has_filename(const Twine &path); + +/// @brief Has stem? +/// +/// stem != "" +/// +/// @param path Input path. +/// @result True if the path has a stem, false otherwise. +bool has_stem(const Twine &path); + +/// @brief Has extension? +/// +/// extension != "" +/// +/// @param path Input path. +/// @result True if the path has a extension, false otherwise. +bool has_extension(const Twine &path); + +/// @brief Is path absolute? +/// +/// @param path Input path. +/// @result True if the path is absolute, false if it is not. +bool is_absolute(const Twine &path); + +/// @brief Is path relative? +/// +/// @param path Input path. +/// @result True if the path is relative, false if it is not. +bool is_relative(const Twine &path); + +} // end namespace path +} // end namespace sys +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Support/PatternMatch.h b/contrib/llvm/include/llvm/Support/PatternMatch.h index bee6768..948ae51 100644 --- a/contrib/llvm/include/llvm/Support/PatternMatch.h +++ b/contrib/llvm/include/llvm/Support/PatternMatch.h @@ -41,18 +41,62 @@ bool match(Val *V, const Pattern &P) { } template<typename Class> -struct leaf_ty { +struct class_match { template<typename ITy> bool match(ITy *V) { return isa<Class>(V); } }; /// m_Value() - Match an arbitrary value and ignore it. -inline leaf_ty<Value> m_Value() { return leaf_ty<Value>(); } +inline class_match<Value> m_Value() { return class_match<Value>(); } /// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it. -inline leaf_ty<ConstantInt> m_ConstantInt() { return leaf_ty<ConstantInt>(); } +inline class_match<ConstantInt> m_ConstantInt() { + return class_match<ConstantInt>(); +} +/// m_Undef() - Match an arbitrary undef constant. +inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); } +inline class_match<Constant> m_Constant() { return class_match<Constant>(); } + +struct match_zero { + template<typename ITy> + bool match(ITy *V) { + if (const Constant *C = dyn_cast<Constant>(V)) + return C->isNullValue(); + return false; + } +}; + +/// m_Zero() - Match an arbitrary zero/null constant. This includes +/// zero_initializer for vectors and ConstantPointerNull for pointers. +inline match_zero m_Zero() { return match_zero(); } + + +struct apint_match { + const APInt *&Res; + apint_match(const APInt *&R) : Res(R) {} + template<typename ITy> + bool match(ITy *V) { + if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) { + Res = &CI->getValue(); + return true; + } + if (ConstantVector *CV = dyn_cast<ConstantVector>(V)) + if (ConstantInt *CI = + dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) { + Res = &CI->getValue(); + return true; + } + return false; + } +}; + +/// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the +/// specified pointer to the contained APInt. +inline apint_match m_APInt(const APInt *&Res) { return Res; } + + template<int64_t Val> -struct constantint_ty { +struct constantint_match { template<typename ITy> bool match(ITy *V) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) { @@ -68,37 +112,82 @@ struct constantint_ty { } }; -/// m_ConstantInt(int64_t) - Match a ConstantInt with a specific value -/// and ignore it. +/// m_ConstantInt<int64_t> - Match a ConstantInt with a specific value. template<int64_t Val> -inline constantint_ty<Val> m_ConstantInt() { - return constantint_ty<Val>(); +inline constantint_match<Val> m_ConstantInt() { + return constantint_match<Val>(); } -struct zero_ty { +/// cst_pred_ty - This helper class is used to match scalar and vector constants +/// that satisfy a specified predicate. +template<typename Predicate> +struct cst_pred_ty : public Predicate { template<typename ITy> bool match(ITy *V) { - if (const Constant *C = dyn_cast<Constant>(V)) - return C->isNullValue(); + if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) + return this->isValue(CI->getValue()); + if (const ConstantVector *CV = dyn_cast<ConstantVector>(V)) + if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) + return this->isValue(CI->getValue()); return false; } }; - -/// m_Zero() - Match an arbitrary zero/null constant. -inline zero_ty m_Zero() { return zero_ty(); } - -struct one_ty { + +/// api_pred_ty - This helper class is used to match scalar and vector constants +/// that satisfy a specified predicate, and bind them to an APInt. +template<typename Predicate> +struct api_pred_ty : public Predicate { + const APInt *&Res; + api_pred_ty(const APInt *&R) : Res(R) {} template<typename ITy> bool match(ITy *V) { - if (const ConstantInt *C = dyn_cast<ConstantInt>(V)) - return C->isOne(); + if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) + if (this->isValue(CI->getValue())) { + Res = &CI->getValue(); + return true; + } + if (const ConstantVector *CV = dyn_cast<ConstantVector>(V)) + if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) + if (this->isValue(CI->getValue())) { + Res = &CI->getValue(); + return true; + } return false; } }; + + +struct is_one { + bool isValue(const APInt &C) { return C == 1; } +}; -/// m_One() - Match a an integer 1. -inline one_ty m_One() { return one_ty(); } +/// m_One() - Match an integer 1 or a vector with all elements equal to 1. +inline cst_pred_ty<is_one> m_One() { return cst_pred_ty<is_one>(); } +inline api_pred_ty<is_one> m_One(const APInt *&V) { return V; } + +struct is_all_ones { + bool isValue(const APInt &C) { return C.isAllOnesValue(); } +}; +/// m_AllOnes() - Match an integer or vector with all bits set to true. +inline cst_pred_ty<is_all_ones> m_AllOnes() {return cst_pred_ty<is_all_ones>();} +inline api_pred_ty<is_all_ones> m_AllOnes(const APInt *&V) { return V; } + +struct is_sign_bit { + bool isValue(const APInt &C) { return C.isSignBit(); } +}; + +/// m_SignBit() - Match an integer or vector with only the sign bit(s) set. +inline cst_pred_ty<is_sign_bit> m_SignBit() {return cst_pred_ty<is_sign_bit>();} +inline api_pred_ty<is_sign_bit> m_SignBit(const APInt *&V) { return V; } + +struct is_power2 { + bool isValue(const APInt &C) { return C.isPowerOf2(); } +}; + +/// m_Power2() - Match an integer or vector power of 2. +inline cst_pred_ty<is_power2> m_Power2() { return cst_pred_ty<is_power2>(); } +inline api_pred_ty<is_power2> m_Power2(const APInt *&V) { return V; } template<typename Class> struct bind_ty { @@ -121,6 +210,9 @@ inline bind_ty<Value> m_Value(Value *&V) { return V; } /// m_ConstantInt - Match a ConstantInt, capturing the value if we match. inline bind_ty<ConstantInt> m_ConstantInt(ConstantInt *&CI) { return CI; } +/// m_Constant - Match a Constant, capturing the value if we match. +inline bind_ty<Constant> m_Constant(Constant *&C) { return C; } + /// specificval_ty - Match a specified Value*. struct specificval_ty { const Value *Val; @@ -140,8 +232,7 @@ inline specificval_ty m_Specific(const Value *V) { return V; } // Matchers for specific binary operators. // -template<typename LHS_t, typename RHS_t, - unsigned Opcode, typename ConcreteTy = BinaryOperator> +template<typename LHS_t, typename RHS_t, unsigned Opcode> struct BinaryOp_match { LHS_t L; RHS_t R; @@ -151,9 +242,8 @@ struct BinaryOp_match { template<typename OpTy> bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opcode) { - ConcreteTy *I = cast<ConcreteTy>(V); - return I->getOpcode() == Opcode && L.match(I->getOperand(0)) && - R.match(I->getOperand(1)); + BinaryOperator *I = cast<BinaryOperator>(V); + return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && @@ -163,193 +253,156 @@ struct BinaryOp_match { }; template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Add> m_Add(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Add> +m_Add(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Add>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FAdd> m_FAdd(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FAdd> +m_FAdd(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FAdd>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Sub> m_Sub(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Sub> +m_Sub(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Sub>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FSub> m_FSub(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FSub> +m_FSub(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Mul> +m_Mul(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Mul>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FMul> m_FMul(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FMul> +m_FMul(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FMul>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::UDiv> m_UDiv(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::UDiv> +m_UDiv(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::UDiv>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::SDiv> m_SDiv(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::SDiv> +m_SDiv(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::SDiv>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FDiv> m_FDiv(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FDiv> +m_FDiv(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FDiv>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::URem> m_URem(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::URem> +m_URem(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::URem>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::SRem> m_SRem(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::SRem> +m_SRem(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::SRem>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FRem> m_FRem(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FRem> +m_FRem(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FRem>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::And> m_And(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::And> +m_And(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::And>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Or> m_Or(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Or> +m_Or(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Or>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Xor> m_Xor(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Xor> +m_Xor(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Xor>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Shl> m_Shl(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Shl> +m_Shl(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Shl>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::LShr> m_LShr(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::LShr> +m_LShr(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::LShr>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::AShr> m_AShr(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::AShr> +m_AShr(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, R); } //===----------------------------------------------------------------------===// -// Matchers for either AShr or LShr .. for convenience +// Class that matches two different binary ops. // -template<typename LHS_t, typename RHS_t, typename ConcreteTy = BinaryOperator> -struct Shr_match { +template<typename LHS_t, typename RHS_t, unsigned Opc1, unsigned Opc2> +struct BinOp2_match { LHS_t L; RHS_t R; - Shr_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} template<typename OpTy> bool match(OpTy *V) { - if (V->getValueID() == Value::InstructionVal + Instruction::LShr || - V->getValueID() == Value::InstructionVal + Instruction::AShr) { - ConcreteTy *I = cast<ConcreteTy>(V); - return (I->getOpcode() == Instruction::AShr || - I->getOpcode() == Instruction::LShr) && - L.match(I->getOperand(0)) && - R.match(I->getOperand(1)); + if (V->getValueID() == Value::InstructionVal + Opc1 || + V->getValueID() == Value::InstructionVal + Opc2) { + BinaryOperator *I = cast<BinaryOperator>(V); + return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) - return (CE->getOpcode() == Instruction::LShr || - CE->getOpcode() == Instruction::AShr) && - L.match(CE->getOperand(0)) && - R.match(CE->getOperand(1)); + return (CE->getOpcode() == Opc1 || CE->getOpcode() == Opc2) && + L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; +/// m_Shr - Matches LShr or AShr. template<typename LHS, typename RHS> -inline Shr_match<LHS, RHS> m_Shr(const LHS &L, const RHS &R) { - return Shr_match<LHS, RHS>(L, R); +inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr> +m_Shr(const LHS &L, const RHS &R) { + return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr>(L, R); } -//===----------------------------------------------------------------------===// -// Matchers for binary classes -// - -template<typename LHS_t, typename RHS_t, typename Class, typename OpcType> -struct BinaryOpClass_match { - OpcType *Opcode; - LHS_t L; - RHS_t R; - - BinaryOpClass_match(OpcType &Op, const LHS_t &LHS, - const RHS_t &RHS) - : Opcode(&Op), L(LHS), R(RHS) {} - BinaryOpClass_match(const LHS_t &LHS, const RHS_t &RHS) - : Opcode(0), L(LHS), R(RHS) {} - - template<typename OpTy> - bool match(OpTy *V) { - if (Class *I = dyn_cast<Class>(V)) - if (L.match(I->getOperand(0)) && - R.match(I->getOperand(1))) { - if (Opcode) - *Opcode = I->getOpcode(); - return true; - } -#if 0 // Doesn't handle constantexprs yet! - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) - return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && - R.match(CE->getOperand(1)); -#endif - return false; - } -}; - +/// m_LogicalShift - Matches LShr or Shl. template<typename LHS, typename RHS> -inline BinaryOpClass_match<LHS, RHS, BinaryOperator, Instruction::BinaryOps> -m_Shift(Instruction::BinaryOps &Op, const LHS &L, const RHS &R) { - return BinaryOpClass_match<LHS, RHS, - BinaryOperator, Instruction::BinaryOps>(Op, L, R); +inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl> +m_LogicalShift(const LHS &L, const RHS &R) { + return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl>(L, R); } +/// m_IDiv - Matches UDiv and SDiv. template<typename LHS, typename RHS> -inline BinaryOpClass_match<LHS, RHS, BinaryOperator, Instruction::BinaryOps> -m_Shift(const LHS &L, const RHS &R) { - return BinaryOpClass_match<LHS, RHS, - BinaryOperator, Instruction::BinaryOps>(L, R); +inline BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv> +m_IDiv(const LHS &L, const RHS &R) { + return BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv>(L, R); } //===----------------------------------------------------------------------===// @@ -362,15 +415,13 @@ struct CmpClass_match { LHS_t L; RHS_t R; - CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, - const RHS_t &RHS) + CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS) : Predicate(Pred), L(LHS), R(RHS) {} template<typename OpTy> bool match(OpTy *V) { if (Class *I = dyn_cast<Class>(V)) - if (L.match(I->getOperand(0)) && - R.match(I->getOperand(1))) { + if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { Predicate = I->getPredicate(); return true; } @@ -425,11 +476,9 @@ m_Select(const Cond &C, const LHS &L, const RHS &R) { /// m_SelectCst - This matches a select of two constants, e.g.: /// m_SelectCst<-1, 0>(m_Value(V)) template<int64_t L, int64_t R, typename Cond> -inline SelectClass_match<Cond, constantint_ty<L>, constantint_ty<R> > +inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R> > m_SelectCst(const Cond &C) { - return SelectClass_match<Cond, constantint_ty<L>, - constantint_ty<R> >(C, m_ConstantInt<L>(), - m_ConstantInt<R>()); + return m_Select(C, m_ConstantInt<L>(), m_ConstantInt<R>()); } @@ -507,20 +556,14 @@ struct not_match { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (CE->getOpcode() == Instruction::Xor) return matchIfNot(CE->getOperand(0), CE->getOperand(1)); - if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) - return L.match(ConstantExpr::getNot(CI)); return false; } private: bool matchIfNot(Value *LHS, Value *RHS) { if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) return CI->isAllOnesValue() && L.match(LHS); - if (ConstantInt *CI = dyn_cast<ConstantInt>(LHS)) - return CI->isAllOnesValue() && L.match(RHS); if (ConstantVector *CV = dyn_cast<ConstantVector>(RHS)) return CV->isAllOnesValue() && L.match(LHS); - if (ConstantVector *CV = dyn_cast<ConstantVector>(LHS)) - return CV->isAllOnesValue() && L.match(RHS); return false; } }; @@ -543,17 +586,17 @@ struct neg_match { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (CE->getOpcode() == Instruction::Sub) return matchIfNeg(CE->getOperand(0), CE->getOperand(1)); - if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) - return L.match(ConstantExpr::getNeg(CI)); return false; } private: bool matchIfNeg(Value *LHS, Value *RHS) { - return LHS == ConstantFP::getZeroValueForNegation(LHS->getType()) && - L.match(RHS); + if (ConstantInt *C = dyn_cast<ConstantInt>(LHS)) + return C->isZero() && L.match(RHS); + return false; } }; +/// m_Neg - Match an integer negate. template<typename LHS> inline neg_match<LHS> m_Neg(const LHS &L) { return L; } @@ -572,23 +615,23 @@ struct fneg_match { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (CE->getOpcode() == Instruction::FSub) return matchIfFNeg(CE->getOperand(0), CE->getOperand(1)); - if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) - return L.match(ConstantExpr::getFNeg(CF)); return false; } private: bool matchIfFNeg(Value *LHS, Value *RHS) { - return LHS == ConstantFP::getZeroValueForNegation(LHS->getType()) && - L.match(RHS); + if (ConstantFP *C = dyn_cast<ConstantFP>(LHS)) + return C->isNegativeZeroValue() && L.match(RHS); + return false; } }; +/// m_FNeg - Match a floating point negate. template<typename LHS> inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; } //===----------------------------------------------------------------------===// -// Matchers for control flow +// Matchers for control flow. // template<typename Cond_t> @@ -602,12 +645,10 @@ struct brc_match { template<typename OpTy> bool match(OpTy *V) { if (BranchInst *BI = dyn_cast<BranchInst>(V)) - if (BI->isConditional()) { - if (Cond.match(BI->getCondition())) { - T = BI->getSuccessor(0); - F = BI->getSuccessor(1); - return true; - } + if (BI->isConditional() && Cond.match(BI->getCondition())) { + T = BI->getSuccessor(0); + F = BI->getSuccessor(1); + return true; } return false; } diff --git a/contrib/llvm/include/llvm/Support/PointerLikeTypeTraits.h b/contrib/llvm/include/llvm/Support/PointerLikeTypeTraits.h index b851404..8370821 100644 --- a/contrib/llvm/include/llvm/Support/PointerLikeTypeTraits.h +++ b/contrib/llvm/include/llvm/Support/PointerLikeTypeTraits.h @@ -15,7 +15,7 @@ #ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H #define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/contrib/llvm/include/llvm/System/Process.h b/contrib/llvm/include/llvm/Support/Process.h index 41bcd69..3379922 100644 --- a/contrib/llvm/include/llvm/System/Process.h +++ b/contrib/llvm/include/llvm/Support/Process.h @@ -1,4 +1,4 @@ -//===- llvm/System/Process.h ------------------------------------*- C++ -*-===// +//===- llvm/Support/Process.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_PROCESS_H #define LLVM_SYSTEM_PROCESS_H -#include "llvm/System/TimeValue.h" +#include "llvm/Support/TimeValue.h" namespace llvm { namespace sys { diff --git a/contrib/llvm/include/llvm/System/Program.h b/contrib/llvm/include/llvm/Support/Program.h index 7017305..78a495e 100644 --- a/contrib/llvm/include/llvm/System/Program.h +++ b/contrib/llvm/include/llvm/Support/Program.h @@ -1,4 +1,4 @@ -//===- llvm/System/Program.h ------------------------------------*- C++ -*-===// +//===- llvm/Support/Program.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_PROGRAM_H #define LLVM_SYSTEM_PROGRAM_H -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" namespace llvm { namespace sys { @@ -90,12 +90,13 @@ namespace sys { /// @see Execute /// @brief Waits for the program to exit. int Wait - ( unsigned secondsToWait = 0, ///< If non-zero, this specifies the amount + ( const Path& path, ///< The path to the child process executable. + unsigned secondsToWait, ///< If non-zero, this specifies the amount ///< of time to wait for the child process to exit. If the time ///< expires, the child is killed and this call returns. If zero, ///< this function will wait until the child finishes or forever if ///< it doesn't. - std::string* ErrMsg = 0 ///< If non-zero, provides a pointer to a string + std::string* ErrMsg ///< If non-zero, provides a pointer to a string ///< instance in which error messages will be returned. If the string ///< is non-empty upon return an error occurred while waiting. ); @@ -113,7 +114,8 @@ namespace sys { /// This static constructor (factory) will attempt to locate a program in /// the operating system's file system using some pre-determined set of - /// locations to search (e.g. the PATH on Unix). + /// locations to search (e.g. the PATH on Unix). Paths with slashes are + /// returned unmodified. /// @returns A Path object initialized to the path of the program or a /// Path object that is empty (invalid) if the program could not be found. /// @brief Construct a Program by finding it by name. diff --git a/contrib/llvm/include/llvm/System/RWMutex.h b/contrib/llvm/include/llvm/Support/RWMutex.h index 3a28818..0d4cb81 100644 --- a/contrib/llvm/include/llvm/System/RWMutex.h +++ b/contrib/llvm/include/llvm/Support/RWMutex.h @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_RWMUTEX_H #define LLVM_SYSTEM_RWMUTEX_H -#include "llvm/System/Threading.h" +#include "llvm/Support/Threading.h" #include <cassert> namespace llvm @@ -43,7 +43,7 @@ namespace llvm /// Attempts to unconditionally acquire the lock in reader mode. If the /// lock is held by a writer, this method will wait until it can acquire - /// the lock. + /// the lock. /// @returns false if any kind of error occurs, true otherwise. /// @brief Unconditionally acquire the lock in reader mode. bool reader_acquire(); @@ -55,7 +55,7 @@ namespace llvm /// Attempts to unconditionally acquire the lock in reader mode. If the /// lock is held by any readers, this method will wait until it can - /// acquire the lock. + /// acquire the lock. /// @returns false if any kind of error occurs, true otherwise. /// @brief Unconditionally acquire the lock in writer mode. bool writer_acquire(); @@ -79,8 +79,8 @@ namespace llvm void operator=(const RWMutexImpl &); /// @} }; - - /// SmartMutex - An R/W mutex with a compile time constant parameter that + + /// SmartMutex - An R/W mutex with a compile time constant parameter that /// indicates whether this mutex should become a no-op when we're not /// running in multithreaded mode. template<bool mt_only> @@ -88,80 +88,80 @@ namespace llvm unsigned readers, writers; public: explicit SmartRWMutex() : RWMutexImpl(), readers(0), writers(0) { } - + bool reader_acquire() { if (!mt_only || llvm_is_multithreaded()) return RWMutexImpl::reader_acquire(); - + // Single-threaded debugging code. This would be racy in multithreaded // mode, but provides not sanity checks in single threaded mode. ++readers; return true; } - + bool reader_release() { if (!mt_only || llvm_is_multithreaded()) return RWMutexImpl::reader_release(); - + // Single-threaded debugging code. This would be racy in multithreaded // mode, but provides not sanity checks in single threaded mode. assert(readers > 0 && "Reader lock not acquired before release!"); --readers; return true; } - + bool writer_acquire() { if (!mt_only || llvm_is_multithreaded()) return RWMutexImpl::writer_acquire(); - + // Single-threaded debugging code. This would be racy in multithreaded // mode, but provides not sanity checks in single threaded mode. assert(writers == 0 && "Writer lock already acquired!"); ++writers; return true; } - + bool writer_release() { if (!mt_only || llvm_is_multithreaded()) return RWMutexImpl::writer_release(); - + // Single-threaded debugging code. This would be racy in multithreaded // mode, but provides not sanity checks in single threaded mode. assert(writers == 1 && "Writer lock not acquired before release!"); --writers; return true; } - + private: SmartRWMutex(const SmartRWMutex<mt_only> & original); void operator=(const SmartRWMutex<mt_only> &); }; typedef SmartRWMutex<false> RWMutex; - + /// ScopedReader - RAII acquisition of a reader lock template<bool mt_only> struct SmartScopedReader { SmartRWMutex<mt_only>& mutex; - + explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) { mutex.reader_acquire(); } - + ~SmartScopedReader() { mutex.reader_release(); } }; typedef SmartScopedReader<false> ScopedReader; - + /// ScopedWriter - RAII acquisition of a writer lock template<bool mt_only> struct SmartScopedWriter { SmartRWMutex<mt_only>& mutex; - + explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) { mutex.writer_acquire(); } - + ~SmartScopedWriter() { mutex.writer_release(); } diff --git a/contrib/llvm/include/llvm/System/Signals.h b/contrib/llvm/include/llvm/Support/Signals.h index 7f1c87c..9a84df6 100644 --- a/contrib/llvm/include/llvm/System/Signals.h +++ b/contrib/llvm/include/llvm/Support/Signals.h @@ -1,4 +1,4 @@ -//===- llvm/System/Signals.h - Signal Handling support ----------*- C++ -*-===// +//===- llvm/Support/Signals.h - Signal Handling support ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,7 +15,7 @@ #ifndef LLVM_SYSTEM_SIGNALS_H #define LLVM_SYSTEM_SIGNALS_H -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" namespace llvm { namespace sys { diff --git a/contrib/llvm/include/llvm/System/Solaris.h b/contrib/llvm/include/llvm/Support/Solaris.h index 15adb74..57eee2c 100644 --- a/contrib/llvm/include/llvm/System/Solaris.h +++ b/contrib/llvm/include/llvm/Support/Solaris.h @@ -1,4 +1,4 @@ -/*===- llvm/System/Solaris.h ------------------------------------*- C++ -*-===* +/*===- llvm/Support/Solaris.h ------------------------------------*- C++ -*-===* * * The LLVM Compiler Infrastructure * diff --git a/contrib/llvm/include/llvm/Support/SourceMgr.h b/contrib/llvm/include/llvm/Support/SourceMgr.h index 270ab2b..a41a633 100644 --- a/contrib/llvm/include/llvm/Support/SourceMgr.h +++ b/contrib/llvm/include/llvm/Support/SourceMgr.h @@ -26,6 +26,7 @@ namespace llvm { class MemoryBuffer; class SourceMgr; class SMDiagnostic; + class Twine; class raw_ostream; /// SourceMgr - This owns the files read by a parser, handles include stacks, @@ -35,8 +36,7 @@ public: /// DiagHandlerTy - Clients that want to handle their own diagnostics in a /// custom way can register a function pointer+context as a diagnostic /// handler. It gets called each time PrintMessage is invoked. - typedef void (*DiagHandlerTy)(const SMDiagnostic&, void *Context, - unsigned LocCookie); + typedef void (*DiagHandlerTy)(const SMDiagnostic&, void *Context); private: struct SrcBuffer { /// Buffer - The memory buffer for the file. @@ -60,7 +60,6 @@ private: DiagHandlerTy DiagHandler; void *DiagContext; - unsigned DiagLocCookie; SourceMgr(const SourceMgr&); // DO NOT IMPLEMENT void operator=(const SourceMgr&); // DO NOT IMPLEMENT @@ -73,12 +72,10 @@ public: } /// setDiagHandler - Specify a diagnostic handler to be invoked every time - /// PrintMessage is called. Ctx and Cookie are passed into the handler when - /// it is invoked. - void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0, unsigned Cookie = 0) { + /// PrintMessage is called. Ctx is passed into the handler when it is invoked. + void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0) { DiagHandler = DH; DiagContext = Ctx; - DiagLocCookie = Cookie; } const SrcBuffer &getBufferInfo(unsigned i) const { @@ -125,7 +122,7 @@ public: /// @param Type - If non-null, the kind of message (e.g., "error") which is /// prefixed to the message. /// @param ShowLine - Should the diagnostic show the source line. - void PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type, + void PrintMessage(SMLoc Loc, const Twine &Msg, const char *Type, bool ShowLine = true) const; @@ -136,7 +133,7 @@ public: /// prefixed to the message. /// @param ShowLine - Should the diagnostic show the source line. SMDiagnostic GetMessage(SMLoc Loc, - const std::string &Msg, const char *Type, + const Twine &Msg, const char *Type, bool ShowLine = true) const; diff --git a/contrib/llvm/include/llvm/Support/StableBasicBlockNumbering.h b/contrib/llvm/include/llvm/Support/StableBasicBlockNumbering.h deleted file mode 100644 index 5e0f87e..0000000 --- a/contrib/llvm/include/llvm/Support/StableBasicBlockNumbering.h +++ /dev/null @@ -1,59 +0,0 @@ -//===- StableBasicBlockNumbering.h - Provide BB identifiers -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class provides a *stable* numbering of basic blocks that does not depend -// on their address in memory (which is nondeterministic). When requested, this -// class simply provides a unique ID for each basic block in the function -// specified and the inverse mapping. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_STABLEBASICBLOCKNUMBERING_H -#define LLVM_SUPPORT_STABLEBASICBLOCKNUMBERING_H - -#include "llvm/Function.h" -#include "llvm/ADT/UniqueVector.h" - -namespace llvm { - class StableBasicBlockNumbering { - // BBNumbering - Holds the numbering. - UniqueVector<BasicBlock*> BBNumbering; - public: - StableBasicBlockNumbering(Function *F = 0) { - if (F) compute(*F); - } - - /// compute - If we have not computed a numbering for the function yet, do - /// so. - void compute(Function &F) { - if (BBNumbering.empty()) { - for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) - BBNumbering.insert(I); - } - } - - /// getNumber - Return the ID number for the specified BasicBlock. - /// - unsigned getNumber(BasicBlock *BB) const { - unsigned Idx = BBNumbering.idFor(BB); - assert(Idx && "Invalid basic block or numbering not computed!"); - return Idx-1; - } - - /// getBlock - Return the BasicBlock corresponding to a particular ID. - /// - BasicBlock *getBlock(unsigned N) const { - assert(N < BBNumbering.size() && - "Block ID out of range or numbering not computed!"); - return BBNumbering[N+1]; - } - }; -} - -#endif diff --git a/contrib/llvm/include/llvm/Support/StandardPasses.h b/contrib/llvm/include/llvm/Support/StandardPasses.h index bb3bddd..d774faf 100644 --- a/contrib/llvm/include/llvm/Support/StandardPasses.h +++ b/contrib/llvm/include/llvm/Support/StandardPasses.h @@ -20,20 +20,35 @@ #define LLVM_SUPPORT_STANDARDPASSES_H #include "llvm/PassManager.h" -#include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/IPO.h" namespace llvm { + + static inline void createStandardAliasAnalysisPasses(PassManagerBase *PM) { + // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that + // BasicAliasAnalysis wins if they disagree. This is intended to help + // support "obvious" type-punning idioms. + PM->add(createTypeBasedAliasAnalysisPass()); + PM->add(createBasicAliasAnalysisPass()); + } + /// createStandardFunctionPasses - Add the standard list of function passes to /// the provided pass manager. /// /// \arg OptimizationLevel - The optimization level, corresponding to -O0, /// -O1, etc. static inline void createStandardFunctionPasses(PassManagerBase *PM, - unsigned OptimizationLevel); + unsigned OptimizationLevel) { + if (OptimizationLevel > 0) { + createStandardAliasAnalysisPasses(PM); + PM->add(createCFGSimplificationPass()); + PM->add(createScalarReplAggregatesPass()); + PM->add(createEarlyCSEPass()); + } + } /// createStandardModulePasses - Add the standard list of module passes to the /// provided pass manager. @@ -54,43 +69,9 @@ namespace llvm { bool UnrollLoops, bool SimplifyLibCalls, bool HaveExceptions, - Pass *InliningPass); - - /// createStandardLTOPasses - Add the standard list of module passes suitable - /// for link time optimization. - /// - /// Internalize - Run the internalize pass. - /// RunInliner - Use a function inlining pass. - /// VerifyEach - Run the verifier after each pass. - static inline void createStandardLTOPasses(PassManagerBase *PM, - bool Internalize, - bool RunInliner, - bool VerifyEach); - - // Implementations - - static inline void createStandardFunctionPasses(PassManagerBase *PM, - unsigned OptimizationLevel) { - if (OptimizationLevel > 0) { - PM->add(createCFGSimplificationPass()); - if (OptimizationLevel == 1) - PM->add(createPromoteMemoryToRegisterPass()); - else - PM->add(createScalarReplAggregatesPass()); - PM->add(createInstructionCombiningPass()); - } - } - - /// createStandardModulePasses - Add the standard module passes. This is - /// expected to be run after the standard function passes. - static inline void createStandardModulePasses(PassManagerBase *PM, - unsigned OptimizationLevel, - bool OptimizeSize, - bool UnitAtATime, - bool UnrollLoops, - bool SimplifyLibCalls, - bool HaveExceptions, Pass *InliningPass) { + createStandardAliasAnalysisPasses(PM); + if (OptimizationLevel == 0) { if (InliningPass) PM->add(InliningPass); @@ -108,7 +89,7 @@ namespace llvm { // Start of CallGraph SCC passes. if (UnitAtATime && HaveExceptions) - PM->add(createPruneEHPass()); // Remove dead EH info + PM->add(createPruneEHPass()); // Remove dead EH info if (InliningPass) PM->add(InliningPass); if (UnitAtATime) @@ -117,11 +98,13 @@ namespace llvm { PM->add(createArgumentPromotionPass()); // Scalarize uninlined fn args // Start of function pass. - PM->add(createScalarReplAggregatesPass()); // Break up aggregate allocas + // Break up aggregate allocas, using SSAUpdater. + PM->add(createScalarReplAggregatesPass(-1, false)); + PM->add(createEarlyCSEPass()); // Catch trivial redundancies if (SimplifyLibCalls) PM->add(createSimplifyLibCallsPass()); // Library Call Optimizations - PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. PM->add(createJumpThreadingPass()); // Thread jumps. + PM->add(createCorrelatedValuePropagationPass()); // Propagate conditionals PM->add(createCFGSimplificationPass()); // Merge & remove BBs PM->add(createInstructionCombiningPass()); // Combine silly seq's @@ -133,6 +116,7 @@ namespace llvm { PM->add(createLoopUnswitchPass(OptimizeSize || OptimizationLevel < 3)); PM->add(createInstructionCombiningPass()); PM->add(createIndVarSimplifyPass()); // Canonicalize indvars + PM->add(createLoopIdiomPass()); // Recognize idioms like memset. PM->add(createLoopDeletionPass()); // Delete dead loops if (UnrollLoops) PM->add(createLoopUnrollPass()); // Unroll small loops @@ -172,10 +156,19 @@ namespace llvm { PM->add(createVerifierPass()); } + /// createStandardLTOPasses - Add the standard list of module passes suitable + /// for link time optimization. + /// + /// Internalize - Run the internalize pass. + /// RunInliner - Use a function inlining pass. + /// VerifyEach - Run the verifier after each pass. static inline void createStandardLTOPasses(PassManagerBase *PM, bool Internalize, bool RunInliner, bool VerifyEach) { + // Provide AliasAnalysis services for optimizations. + createStandardAliasAnalysisPasses(PM); + // Now that composite has been compiled, scan through the module, looking // for a main function. If main is defined, mark all other functions // internal. diff --git a/contrib/llvm/include/llvm/Support/SwapByteOrder.h b/contrib/llvm/include/llvm/Support/SwapByteOrder.h new file mode 100644 index 0000000..6c0592c --- /dev/null +++ b/contrib/llvm/include/llvm/Support/SwapByteOrder.h @@ -0,0 +1,101 @@ +//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares generic and optimized functions to swap the byte order of +// an integral type. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_SWAP_BYTE_ORDER_H +#define LLVM_SYSTEM_SWAP_BYTE_ORDER_H + +#include "llvm/Support/DataTypes.h" +#include <cstddef> +#include <limits> + +namespace llvm { +namespace sys { + +/// SwapByteOrder_16 - This function returns a byte-swapped representation of +/// the 16-bit argument. +inline uint16_t SwapByteOrder_16(uint16_t value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return _byteswap_ushort(value); +#else + uint16_t Hi = value << 8; + uint16_t Lo = value >> 8; + return Hi | Lo; +#endif +} + +/// SwapByteOrder_32 - This function returns a byte-swapped representation of +/// the 32-bit argument. +inline uint32_t SwapByteOrder_32(uint32_t value) { +#if defined(__llvm__) || \ +(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) + return __builtin_bswap32(value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_ulong(value); +#else + uint32_t Byte0 = value & 0x000000FF; + uint32_t Byte1 = value & 0x0000FF00; + uint32_t Byte2 = value & 0x00FF0000; + uint32_t Byte3 = value & 0xFF000000; + return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); +#endif +} + +/// SwapByteOrder_64 - This function returns a byte-swapped representation of +/// the 64-bit argument. +inline uint64_t SwapByteOrder_64(uint64_t value) { +#if defined(__llvm__) || \ +(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) + return __builtin_bswap64(value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_uint64(value); +#else + uint64_t Hi = SwapByteOrder_32(uint32_t(value)); + uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32)); + return (Hi << 32) | Lo; +#endif +} + +inline unsigned char SwapByteOrder(unsigned char C) { return C; } +inline signed char SwapByteOrder(signed char C) { return C; } +inline char SwapByteOrder(char C) { return C; } + +inline unsigned short SwapByteOrder(unsigned short C) { return SwapByteOrder_16(C); } +inline signed short SwapByteOrder( signed short C) { return SwapByteOrder_16(C); } + +inline unsigned int SwapByteOrder(unsigned int C) { return SwapByteOrder_32(C); } +inline signed int SwapByteOrder( signed int C) { return SwapByteOrder_32(C); } + +#if __LONG_MAX__ == __INT_MAX__ +inline unsigned long SwapByteOrder(unsigned long C) { return SwapByteOrder_32(C); } +inline signed long SwapByteOrder( signed long C) { return SwapByteOrder_32(C); } +#elif __LONG_MAX__ == __LONG_LONG_MAX__ +inline unsigned long SwapByteOrder(unsigned long C) { return SwapByteOrder_64(C); } +inline signed long SwapByteOrder( signed long C) { return SwapByteOrder_64(C); } +#else +#error "Unknown long size!" +#endif + +inline unsigned long long SwapByteOrder(unsigned long long C) { + return SwapByteOrder_64(C); +} +inline signed long long SwapByteOrder(signed long long C) { + return SwapByteOrder_64(C); +} + +} // end namespace sys +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Support/SystemUtils.h b/contrib/llvm/include/llvm/Support/SystemUtils.h index 3c182c1..399aee5 100644 --- a/contrib/llvm/include/llvm/Support/SystemUtils.h +++ b/contrib/llvm/include/llvm/Support/SystemUtils.h @@ -30,13 +30,14 @@ bool CheckBitcodeOutputToConsole( bool print_warning = true ///< Control whether warnings are printed ); -/// FindExecutable - Find a named executable, giving the argv[0] of program -/// being executed. This allows us to find another LLVM tool if it is built in -/// the same directory. If the executable cannot be found, return an -/// empty string. +/// PrependMainExecutablePath - Prepend the path to the program being executed +/// to \p ExeName, given the value of argv[0] and the address of main() +/// itself. This allows us to find another LLVM tool if it is built in the same +/// directory. An empty string is returned on error; note that this function +/// just mainpulates the path and doesn't check for executability. /// @brief Find a named executable. -sys::Path FindExecutable(const std::string &ExeName, - const char *Argv0, void *MainAddr); +sys::Path PrependMainExecutablePath(const std::string &ExeName, + const char *Argv0, void *MainAddr); } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Support/TargetFolder.h b/contrib/llvm/include/llvm/Support/TargetFolder.h index d34f35f..20ca557 100644 --- a/contrib/llvm/include/llvm/Support/TargetFolder.h +++ b/contrib/llvm/include/llvm/Support/TargetFolder.h @@ -46,50 +46,32 @@ public: // Binary Operators //===--------------------------------------------------------------------===// - Constant *CreateAdd(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getAdd(LHS, RHS)); - } - Constant *CreateNSWAdd(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNSWAdd(LHS, RHS)); - } - Constant *CreateNUWAdd(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNUWAdd(LHS, RHS)); + Constant *CreateAdd(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW)); } Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFAdd(LHS, RHS)); } - Constant *CreateSub(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getSub(LHS, RHS)); - } - Constant *CreateNSWSub(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNSWSub(LHS, RHS)); - } - Constant *CreateNUWSub(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNUWSub(LHS, RHS)); + Constant *CreateSub(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW)); } Constant *CreateFSub(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFSub(LHS, RHS)); } - Constant *CreateMul(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getMul(LHS, RHS)); - } - Constant *CreateNSWMul(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNSWMul(LHS, RHS)); - } - Constant *CreateNUWMul(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNUWMul(LHS, RHS)); + Constant *CreateMul(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW)); } Constant *CreateFMul(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFMul(LHS, RHS)); } - Constant *CreateUDiv(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getUDiv(LHS, RHS)); - } - Constant *CreateSDiv(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getSDiv(LHS, RHS)); + Constant *CreateUDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getUDiv(LHS, RHS, isExact)); } - Constant *CreateExactSDiv(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getExactSDiv(LHS, RHS)); + Constant *CreateSDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getSDiv(LHS, RHS, isExact)); } Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFDiv(LHS, RHS)); @@ -103,14 +85,15 @@ public: Constant *CreateFRem(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFRem(LHS, RHS)); } - Constant *CreateShl(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getShl(LHS, RHS)); + Constant *CreateShl(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW)); } - Constant *CreateLShr(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getLShr(LHS, RHS)); + Constant *CreateLShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getLShr(LHS, RHS, isExact)); } - Constant *CreateAShr(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getAShr(LHS, RHS)); + Constant *CreateAShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getAShr(LHS, RHS, isExact)); } Constant *CreateAnd(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getAnd(LHS, RHS)); @@ -131,14 +114,9 @@ public: // Unary Operators //===--------------------------------------------------------------------===// - Constant *CreateNeg(Constant *C) const { - return Fold(ConstantExpr::getNeg(C)); - } - Constant *CreateNSWNeg(Constant *C) const { - return Fold(ConstantExpr::getNSWNeg(C)); - } - Constant *CreateNUWNeg(Constant *C) const { - return Fold(ConstantExpr::getNUWNeg(C)); + Constant *CreateNeg(Constant *C, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getNeg(C, HasNUW, HasNSW)); } Constant *CreateFNeg(Constant *C) const { return Fold(ConstantExpr::getFNeg(C)); diff --git a/contrib/llvm/include/llvm/System/ThreadLocal.h b/contrib/llvm/include/llvm/Support/ThreadLocal.h index e6edd79..15350a7 100644 --- a/contrib/llvm/include/llvm/System/ThreadLocal.h +++ b/contrib/llvm/include/llvm/Support/ThreadLocal.h @@ -1,4 +1,4 @@ -//===- llvm/System/ThreadLocal.h - Thread Local Data ------------*- C++ -*-===// +//===- llvm/Support/ThreadLocal.h - Thread Local Data ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,7 +14,7 @@ #ifndef LLVM_SYSTEM_THREAD_LOCAL_H #define LLVM_SYSTEM_THREAD_LOCAL_H -#include "llvm/System/Threading.h" +#include "llvm/Support/Threading.h" #include <cassert> namespace llvm { @@ -30,21 +30,21 @@ namespace llvm { const void* getInstance(); void removeInstance(); }; - + /// ThreadLocal - A class used to abstract thread-local storage. It holds, /// for each thread, a pointer a single object of type T. template<class T> class ThreadLocal : public ThreadLocalImpl { public: ThreadLocal() : ThreadLocalImpl() { } - + /// get - Fetches a pointer to the object associated with the current /// thread. If no object has yet been associated, it returns NULL; T* get() { return static_cast<T*>(getInstance()); } - + // set - Associates a pointer to an object with the current thread. void set(T* d) { setInstance(d); } - + // erase - Removes the pointer associated with the current thread. void erase() { removeInstance(); } }; diff --git a/contrib/llvm/include/llvm/System/Threading.h b/contrib/llvm/include/llvm/Support/Threading.h index 42d2f89..c0e842c 100644 --- a/contrib/llvm/include/llvm/System/Threading.h +++ b/contrib/llvm/include/llvm/Support/Threading.h @@ -1,4 +1,4 @@ -//===-- llvm/System/Threading.h - Control multithreading mode --*- C++ -*-===// +//===-- llvm/Support/Threading.h - Control multithreading mode --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,28 +18,42 @@ namespace llvm { /// llvm_start_multithreaded - Allocate and initialize structures needed to /// make LLVM safe for multithreading. The return value indicates whether /// multithreaded initialization succeeded. LLVM will still be operational - /// on "failed" return, and will still be safe for hosting threading + /// on "failed" return, and will still be safe for hosting threading /// applications in the JIT, but will not be safe for concurrent calls to the /// LLVM APIs. /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. bool llvm_start_multithreaded(); - + /// llvm_stop_multithreaded - Deallocate structures necessary to make LLVM /// safe for multithreading. /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. void llvm_stop_multithreaded(); - + /// llvm_is_multithreaded - Check whether LLVM is executing in thread-safe /// mode or not. bool llvm_is_multithreaded(); - + /// acquire_global_lock - Acquire the global lock. This is a no-op if called /// before llvm_start_multithreaded(). void llvm_acquire_global_lock(); - + /// release_global_lock - Release the global lock. This is a no-op if called /// before llvm_start_multithreaded(). void llvm_release_global_lock(); + + /// llvm_execute_on_thread - Execute the given \arg UserFn on a separate + /// thread, passing it the provided \arg UserData. + /// + /// This function does not guarantee that the code will actually be executed + /// on a separate thread or honoring the requested stack size, but tries to do + /// so where system support is available. + /// + /// \param UserFn - The callback to execute. + /// \param UserData - An argument to pass to the callback function. + /// \param RequestedStackSize - If non-zero, a requested size (in bytes) for + /// the thread stack. + void llvm_execute_on_thread(void (*UserFn)(void*), void *UserData, + unsigned RequestedStackSize = 0); } #endif diff --git a/contrib/llvm/include/llvm/System/TimeValue.h b/contrib/llvm/include/llvm/Support/TimeValue.h index b82647f..e122711 100644 --- a/contrib/llvm/include/llvm/System/TimeValue.h +++ b/contrib/llvm/include/llvm/Support/TimeValue.h @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <string> #ifndef LLVM_SYSTEM_TIMEVALUE_H diff --git a/contrib/llvm/include/llvm/Support/Timer.h b/contrib/llvm/include/llvm/Support/Timer.h index f959136..404cb6d 100644 --- a/contrib/llvm/include/llvm/Support/Timer.h +++ b/contrib/llvm/include/llvm/Support/Timer.h @@ -15,7 +15,7 @@ #ifndef LLVM_SUPPORT_TIMER_H #define LLVM_SUPPORT_TIMER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/ADT/StringRef.h" #include <cassert> #include <string> diff --git a/contrib/llvm/include/llvm/Support/ToolOutputFile.h b/contrib/llvm/include/llvm/Support/ToolOutputFile.h new file mode 100644 index 0000000..65b182a --- /dev/null +++ b/contrib/llvm/include/llvm/Support/ToolOutputFile.h @@ -0,0 +1,62 @@ +//===- ToolOutputFile.h - Output files for compiler-like tools -----------===// +// +// 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 tool_output_file class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TOOL_OUTPUT_FILE_H +#define LLVM_SUPPORT_TOOL_OUTPUT_FILE_H + +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +/// tool_output_file - This class contains a raw_fd_ostream and adds a +/// few extra features commonly needed for compiler-like tool output files: +/// - The file is automatically deleted if the process is killed. +/// - The file is automatically deleted when the tool_output_file +/// object is destroyed unless the client calls keep(). +class tool_output_file { + /// Installer - This class is declared before the raw_fd_ostream so that + /// it is constructed before the raw_fd_ostream is constructed and + /// destructed after the raw_fd_ostream is destructed. It installs + /// cleanups in its constructor and uninstalls them in its destructor. + class CleanupInstaller { + /// Filename - The name of the file. + std::string Filename; + public: + /// Keep - The flag which indicates whether we should not delete the file. + bool Keep; + + explicit CleanupInstaller(const char *filename); + ~CleanupInstaller(); + } Installer; + + /// OS - The contained stream. This is intentionally declared after + /// Installer. + raw_fd_ostream OS; + +public: + /// tool_output_file - This constructor's arguments are passed to + /// to raw_fd_ostream's constructor. + tool_output_file(const char *filename, std::string &ErrorInfo, + unsigned Flags = 0); + + /// os - Return the contained raw_fd_ostream. + raw_fd_ostream &os() { return OS; } + + /// keep - Indicate that the tool's job wrt this output file has been + /// successful and the file should not be deleted. + void keep() { Installer.Keep = true; } +}; + +} // end llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/Support/TypeBuilder.h b/contrib/llvm/include/llvm/Support/TypeBuilder.h index 81c2747..ea63da0 100644 --- a/contrib/llvm/include/llvm/Support/TypeBuilder.h +++ b/contrib/llvm/include/llvm/Support/TypeBuilder.h @@ -88,6 +88,8 @@ class ieee_double {}; class x86_fp80 {}; class fp128 {}; class ppc_fp128 {}; +// X86 MMX. +class x86_mmx {}; } // namespace types // LLVM doesn't have const or volatile types. @@ -219,6 +221,10 @@ template<bool cross> class TypeBuilder<types::ppc_fp128, cross> { public: static const Type *get(LLVMContext& C) { return Type::getPPC_FP128Ty(C); } }; +template<bool cross> class TypeBuilder<types::x86_mmx, cross> { +public: + static const Type *get(LLVMContext& C) { return Type::getX86_MMXTy(C); } +}; template<bool cross> class TypeBuilder<void, cross> { public: diff --git a/contrib/llvm/include/llvm/System/Valgrind.h b/contrib/llvm/include/llvm/Support/Valgrind.h index 5ec79c3..7662eaa 100644 --- a/contrib/llvm/include/llvm/System/Valgrind.h +++ b/contrib/llvm/include/llvm/Support/Valgrind.h @@ -1,4 +1,4 @@ -//===- llvm/System/Valgrind.h - Communication with Valgrind -----*- C++ -*-===// +//===- llvm/Support/Valgrind.h - Communication with Valgrind -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/include/llvm/Support/raw_ostream.h b/contrib/llvm/include/llvm/Support/raw_ostream.h index 39bdbd8..6bfae5e 100644 --- a/contrib/llvm/include/llvm/Support/raw_ostream.h +++ b/contrib/llvm/include/llvm/Support/raw_ostream.h @@ -15,7 +15,7 @@ #define LLVM_SUPPORT_RAW_OSTREAM_H #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class format_object_base; @@ -165,7 +165,7 @@ public: } raw_ostream &operator<<(const char *Str) { - // Inline fast path, particulary for constant strings where a sufficiently + // Inline fast path, particularly for constant strings where a sufficiently // smart compiler will simplify strlen. return this->operator<<(StringRef(Str)); @@ -196,7 +196,7 @@ public: /// write_escaped - Output \arg Str, turning '\\', '\t', '\n', '"', and /// anything that doesn't satisfy std::isprint into an escape sequence. - raw_ostream &write_escaped(StringRef Str); + raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); raw_ostream &write(unsigned char C); raw_ostream &write(const char *Ptr, size_t Size); @@ -301,6 +301,10 @@ class raw_fd_ostream : public raw_ostream { /// bool Error; + /// Controls whether the stream should attempt to use atomic writes, when + /// possible. + bool UseAtomicWrites; + uint64_t pos; /// write_impl - See raw_ostream::write_impl. @@ -349,10 +353,7 @@ public: /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If /// ShouldClose is true, this closes the file when the stream is destroyed. - raw_fd_ostream(int fd, bool shouldClose, - bool unbuffered=false) : raw_ostream(unbuffered), FD(fd), - ShouldClose(shouldClose), - Error(false) {} + raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false); ~raw_fd_ostream(); @@ -361,9 +362,19 @@ public: void close(); /// seek - Flushes the stream and repositions the underlying file descriptor - /// positition to the offset specified from the beginning of the file. + /// position to the offset specified from the beginning of the file. uint64_t seek(uint64_t off); + /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for + /// individual output routines where possible. + /// + /// Note that because raw_ostream's are typically buffered, this flag is only + /// sensible when used on unbuffered streams which will flush their output + /// immediately. + void SetUseAtomicWrites(bool Value) { + UseAtomicWrites = Value; + } + virtual raw_ostream &changeColor(enum Colors colors, bool bold=false, bool bg=false); virtual raw_ostream &resetColor(); @@ -475,45 +486,6 @@ public: ~raw_null_ostream(); }; -/// tool_output_file - This class contains a raw_fd_ostream and adds a -/// few extra features commonly needed for compiler-like tool output files: -/// - The file is automatically deleted if the process is killed. -/// - The file is automatically deleted when the tool_output_file -/// object is destroyed unless the client calls keep(). -class tool_output_file { - /// Installer - This class is declared before the raw_fd_ostream so that - /// it is constructed before the raw_fd_ostream is constructed and - /// destructed after the raw_fd_ostream is destructed. It installs - /// cleanups in its constructor and uninstalls them in its destructor. - class CleanupInstaller { - /// Filename - The name of the file. - std::string Filename; - public: - /// Keep - The flag which indicates whether we should not delete the file. - bool Keep; - - explicit CleanupInstaller(const char *filename); - ~CleanupInstaller(); - } Installer; - - /// OS - The contained stream. This is intentionally declared after - /// Installer. - raw_fd_ostream OS; - -public: - /// tool_output_file - This constructor's arguments are passed to - /// to raw_fd_ostream's constructor. - tool_output_file(const char *filename, std::string &ErrorInfo, - unsigned Flags = 0); - - /// os - Return the contained raw_fd_ostream. - raw_fd_ostream &os() { return OS; } - - /// keep - Indicate that the tool's job wrt this output file has been - /// successful and the file should not be deleted. - void keep() { Installer.Keep = true; } -}; - } // end llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Support/system_error.h b/contrib/llvm/include/llvm/Support/system_error.h new file mode 100644 index 0000000..e5306ec --- /dev/null +++ b/contrib/llvm/include/llvm/Support/system_error.h @@ -0,0 +1,910 @@ +//===---------------------------- system_error ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This was lifted from libc++ and modified for C++03. This is called +// system_error even though it does not define that class because that's what +// it's called in C++0x. We don't define system_error because it is only used +// for exception handling, which we don't use in LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_SYSTEM_ERROR_H +#define LLVM_SYSTEM_SYSTEM_ERROR_H + +/* + system_error synopsis + +namespace std +{ + +class error_category +{ +public: + virtual ~error_category(); + + error_category(const error_category&) = delete; + error_category& operator=(const error_category&) = delete; + + virtual const char* name() const = 0; + virtual error_condition default_error_condition(int ev) const; + virtual bool equivalent(int code, const error_condition& condition) const; + virtual bool equivalent(const error_code& code, int condition) const; + virtual std::string message(int ev) const = 0; + + bool operator==(const error_category& rhs) const; + bool operator!=(const error_category& rhs) const; + bool operator<(const error_category& rhs) const; +}; + +const error_category& generic_category(); +const error_category& system_category(); + +template <class T> struct is_error_code_enum + : public false_type {}; + +template <class T> struct is_error_condition_enum + : public false_type {}; + +class error_code +{ +public: + // constructors: + error_code(); + error_code(int val, const error_category& cat); + template <class ErrorCodeEnum> + error_code(ErrorCodeEnum e); + + // modifiers: + void assign(int val, const error_category& cat); + template <class ErrorCodeEnum> + error_code& operator=(ErrorCodeEnum e); + void clear(); + + // observers: + int value() const; + const error_category& category() const; + error_condition default_error_condition() const; + std::string message() const; + explicit operator bool() const; +}; + +// non-member functions: +bool operator<(const error_code& lhs, const error_code& rhs); +template <class charT, class traits> + basic_ostream<charT,traits>& + operator<<(basic_ostream<charT,traits>& os, const error_code& ec); + +class error_condition +{ +public: + // constructors: + error_condition(); + error_condition(int val, const error_category& cat); + template <class ErrorConditionEnum> + error_condition(ErrorConditionEnum e); + + // modifiers: + void assign(int val, const error_category& cat); + template <class ErrorConditionEnum> + error_condition& operator=(ErrorConditionEnum e); + void clear(); + + // observers: + int value() const; + const error_category& category() const; + std::string message() const; + explicit operator bool() const; +}; + +bool operator<(const error_condition& lhs, const error_condition& rhs); + +class system_error + : public runtime_error +{ +public: + system_error(error_code ec, const std::string& what_arg); + system_error(error_code ec, const char* what_arg); + system_error(error_code ec); + system_error(int ev, const error_category& ecat, const std::string& what_arg); + system_error(int ev, const error_category& ecat, const char* what_arg); + system_error(int ev, const error_category& ecat); + + const error_code& code() const throw(); + const char* what() const throw(); +}; + +enum class errc +{ + address_family_not_supported, // EAFNOSUPPORT + address_in_use, // EADDRINUSE + address_not_available, // EADDRNOTAVAIL + already_connected, // EISCONN + argument_list_too_long, // E2BIG + argument_out_of_domain, // EDOM + bad_address, // EFAULT + bad_file_descriptor, // EBADF + bad_message, // EBADMSG + broken_pipe, // EPIPE + connection_aborted, // ECONNABORTED + connection_already_in_progress, // EALREADY + connection_refused, // ECONNREFUSED + connection_reset, // ECONNRESET + cross_device_link, // EXDEV + destination_address_required, // EDESTADDRREQ + device_or_resource_busy, // EBUSY + directory_not_empty, // ENOTEMPTY + executable_format_error, // ENOEXEC + file_exists, // EEXIST + file_too_large, // EFBIG + filename_too_long, // ENAMETOOLONG + function_not_supported, // ENOSYS + host_unreachable, // EHOSTUNREACH + identifier_removed, // EIDRM + illegal_byte_sequence, // EILSEQ + inappropriate_io_control_operation, // ENOTTY + interrupted, // EINTR + invalid_argument, // EINVAL + invalid_seek, // ESPIPE + io_error, // EIO + is_a_directory, // EISDIR + message_size, // EMSGSIZE + network_down, // ENETDOWN + network_reset, // ENETRESET + network_unreachable, // ENETUNREACH + no_buffer_space, // ENOBUFS + no_child_process, // ECHILD + no_link, // ENOLINK + no_lock_available, // ENOLCK + no_message_available, // ENODATA + no_message, // ENOMSG + no_protocol_option, // ENOPROTOOPT + no_space_on_device, // ENOSPC + no_stream_resources, // ENOSR + no_such_device_or_address, // ENXIO + no_such_device, // ENODEV + no_such_file_or_directory, // ENOENT + no_such_process, // ESRCH + not_a_directory, // ENOTDIR + not_a_socket, // ENOTSOCK + not_a_stream, // ENOSTR + not_connected, // ENOTCONN + not_enough_memory, // ENOMEM + not_supported, // ENOTSUP + operation_canceled, // ECANCELED + operation_in_progress, // EINPROGRESS + operation_not_permitted, // EPERM + operation_not_supported, // EOPNOTSUPP + operation_would_block, // EWOULDBLOCK + owner_dead, // EOWNERDEAD + permission_denied, // EACCES + protocol_error, // EPROTO + protocol_not_supported, // EPROTONOSUPPORT + read_only_file_system, // EROFS + resource_deadlock_would_occur, // EDEADLK + resource_unavailable_try_again, // EAGAIN + result_out_of_range, // ERANGE + state_not_recoverable, // ENOTRECOVERABLE + stream_timeout, // ETIME + text_file_busy, // ETXTBSY + timed_out, // ETIMEDOUT + too_many_files_open_in_system, // ENFILE + too_many_files_open, // EMFILE + too_many_links, // EMLINK + too_many_symbolic_link_levels, // ELOOP + value_too_large, // EOVERFLOW + wrong_protocol_type // EPROTOTYPE +}; + +template <> struct is_error_condition_enum<errc> : true_type { } + +error_code make_error_code(errc e); +error_condition make_error_condition(errc e); + +// Comparison operators: +bool operator==(const error_code& lhs, const error_code& rhs); +bool operator==(const error_code& lhs, const error_condition& rhs); +bool operator==(const error_condition& lhs, const error_code& rhs); +bool operator==(const error_condition& lhs, const error_condition& rhs); +bool operator!=(const error_code& lhs, const error_code& rhs); +bool operator!=(const error_code& lhs, const error_condition& rhs); +bool operator!=(const error_condition& lhs, const error_code& rhs); +bool operator!=(const error_condition& lhs, const error_condition& rhs); + +template <> struct hash<std::error_code>; + +} // std + +*/ + +#include "llvm/Config/config.h" +#include "llvm/Support/type_traits.h" +#include <cerrno> +#include <string> + +// This must be here instead of a .inc file because it is used in the definition +// of the enum values below. +#ifdef LLVM_ON_WIN32 + + // The following numbers were taken from VS2010. +# ifndef EAFNOSUPPORT +# define EAFNOSUPPORT 102 +# endif +# ifndef EADDRINUSE +# define EADDRINUSE 100 +# endif +# ifndef EADDRNOTAVAIL +# define EADDRNOTAVAIL 101 +# endif +# ifndef EISCONN +# define EISCONN 113 +# endif +# ifndef E2BIG +# define E2BIG 7 +# endif +# ifndef EDOM +# define EDOM 33 +# endif +# ifndef EFAULT +# define EFAULT 14 +# endif +# ifndef EBADF +# define EBADF 9 +# endif +# ifndef EBADMSG +# define EBADMSG 104 +# endif +# ifndef EPIPE +# define EPIPE 32 +# endif +# ifndef ECONNABORTED +# define ECONNABORTED 106 +# endif +# ifndef EALREADY +# define EALREADY 103 +# endif +# ifndef ECONNREFUSED +# define ECONNREFUSED 107 +# endif +# ifndef ECONNRESET +# define ECONNRESET 108 +# endif +# ifndef EXDEV +# define EXDEV 18 +# endif +# ifndef EDESTADDRREQ +# define EDESTADDRREQ 109 +# endif +# ifndef EBUSY +# define EBUSY 16 +# endif +# ifndef ENOTEMPTY +# define ENOTEMPTY 41 +# endif +# ifndef ENOEXEC +# define ENOEXEC 8 +# endif +# ifndef EEXIST +# define EEXIST 17 +# endif +# ifndef EFBIG +# define EFBIG 27 +# endif +# ifndef ENAMETOOLONG +# define ENAMETOOLONG 38 +# endif +# ifndef ENOSYS +# define ENOSYS 40 +# endif +# ifndef EHOSTUNREACH +# define EHOSTUNREACH 110 +# endif +# ifndef EIDRM +# define EIDRM 111 +# endif +# ifndef EILSEQ +# define EILSEQ 42 +# endif +# ifndef ENOTTY +# define ENOTTY 25 +# endif +# ifndef EINTR +# define EINTR 4 +# endif +# ifndef EINVAL +# define EINVAL 22 +# endif +# ifndef ESPIPE +# define ESPIPE 29 +# endif +# ifndef EIO +# define EIO 5 +# endif +# ifndef EISDIR +# define EISDIR 21 +# endif +# ifndef EMSGSIZE +# define EMSGSIZE 115 +# endif +# ifndef ENETDOWN +# define ENETDOWN 116 +# endif +# ifndef ENETRESET +# define ENETRESET 117 +# endif +# ifndef ENETUNREACH +# define ENETUNREACH 118 +# endif +# ifndef ENOBUFS +# define ENOBUFS 119 +# endif +# ifndef ECHILD +# define ECHILD 10 +# endif +# ifndef ENOLINK +# define ENOLINK 121 +# endif +# ifndef ENOLCK +# define ENOLCK 39 +# endif +# ifndef ENODATA +# define ENODATA 120 +# endif +# ifndef ENOMSG +# define ENOMSG 122 +# endif +# ifndef ENOPROTOOPT +# define ENOPROTOOPT 123 +# endif +# ifndef ENOSPC +# define ENOSPC 28 +# endif +# ifndef ENOSR +# define ENOSR 124 +# endif +# ifndef ENXIO +# define ENXIO 6 +# endif +# ifndef ENODEV +# define ENODEV 19 +# endif +# ifndef ENOENT +# define ENOENT 2 +# endif +# ifndef ESRCH +# define ESRCH 3 +# endif +# ifndef ENOTDIR +# define ENOTDIR 20 +# endif +# ifndef ENOTSOCK +# define ENOTSOCK 128 +# endif +# ifndef ENOSTR +# define ENOSTR 125 +# endif +# ifndef ENOTCONN +# define ENOTCONN 126 +# endif +# ifndef ENOMEM +# define ENOMEM 12 +# endif +# ifndef ENOTSUP +# define ENOTSUP 129 +# endif +# ifndef ECANCELED +# define ECANCELED 105 +# endif +# ifndef EINPROGRESS +# define EINPROGRESS 112 +# endif +# ifndef EPERM +# define EPERM 1 +# endif +# ifndef EOPNOTSUPP +# define EOPNOTSUPP 130 +# endif +# ifndef EWOULDBLOCK +# define EWOULDBLOCK 140 +# endif +# ifndef EOWNERDEAD +# define EOWNERDEAD 133 +# endif +# ifndef EACCES +# define EACCES 13 +# endif +# ifndef EPROTO +# define EPROTO 134 +# endif +# ifndef EPROTONOSUPPORT +# define EPROTONOSUPPORT 135 +# endif +# ifndef EROFS +# define EROFS 30 +# endif +# ifndef EDEADLK +# define EDEADLK 36 +# endif +# ifndef EAGAIN +# define EAGAIN 11 +# endif +# ifndef ERANGE +# define ERANGE 34 +# endif +# ifndef ENOTRECOVERABLE +# define ENOTRECOVERABLE 127 +# endif +# ifndef ETIME +# define ETIME 137 +# endif +# ifndef ETXTBSY +# define ETXTBSY 139 +# endif +# ifndef ETIMEDOUT +# define ETIMEDOUT 138 +# endif +# ifndef ENFILE +# define ENFILE 23 +# endif +# ifndef EMFILE +# define EMFILE 24 +# endif +# ifndef EMLINK +# define EMLINK 31 +# endif +# ifndef ELOOP +# define ELOOP 114 +# endif +# ifndef EOVERFLOW +# define EOVERFLOW 132 +# endif +# ifndef EPROTOTYPE +# define EPROTOTYPE 136 +# endif +#endif + +namespace llvm { + +template <class T, T v> +struct integral_constant { + typedef T value_type; + static const value_type value = v; + typedef integral_constant<T,v> type; + operator value_type() { return value; } +}; + +typedef integral_constant<bool, true> true_type; +typedef integral_constant<bool, false> false_type; + +// is_error_code_enum + +template <class Tp> struct is_error_code_enum : public false_type {}; + +// is_error_condition_enum + +template <class Tp> struct is_error_condition_enum : public false_type {}; + +// Some error codes are not present on all platforms, so we provide equivalents +// for them: + +//enum class errc +struct errc { +enum _ { + success = 0, + address_family_not_supported = EAFNOSUPPORT, + address_in_use = EADDRINUSE, + address_not_available = EADDRNOTAVAIL, + already_connected = EISCONN, + argument_list_too_long = E2BIG, + argument_out_of_domain = EDOM, + bad_address = EFAULT, + bad_file_descriptor = EBADF, +#ifdef EBADMSG + bad_message = EBADMSG, +#else + bad_message = EINVAL, +#endif + broken_pipe = EPIPE, + connection_aborted = ECONNABORTED, + connection_already_in_progress = EALREADY, + connection_refused = ECONNREFUSED, + connection_reset = ECONNRESET, + cross_device_link = EXDEV, + destination_address_required = EDESTADDRREQ, + device_or_resource_busy = EBUSY, + directory_not_empty = ENOTEMPTY, + executable_format_error = ENOEXEC, + file_exists = EEXIST, + file_too_large = EFBIG, + filename_too_long = ENAMETOOLONG, + function_not_supported = ENOSYS, + host_unreachable = EHOSTUNREACH, + identifier_removed = EIDRM, + illegal_byte_sequence = EILSEQ, + inappropriate_io_control_operation = ENOTTY, + interrupted = EINTR, + invalid_argument = EINVAL, + invalid_seek = ESPIPE, + io_error = EIO, + is_a_directory = EISDIR, + message_size = EMSGSIZE, + network_down = ENETDOWN, + network_reset = ENETRESET, + network_unreachable = ENETUNREACH, + no_buffer_space = ENOBUFS, + no_child_process = ECHILD, +#ifdef ENOLINK + no_link = ENOLINK, +#else + no_link = EINVAL, +#endif + no_lock_available = ENOLCK, +#ifdef ENODATA + no_message_available = ENODATA, +#else + no_message_available = ENOMSG, +#endif + no_message = ENOMSG, + no_protocol_option = ENOPROTOOPT, + no_space_on_device = ENOSPC, +#ifdef ENOSR + no_stream_resources = ENOSR, +#else + no_stream_resources = ENOMEM, +#endif + no_such_device_or_address = ENXIO, + no_such_device = ENODEV, + no_such_file_or_directory = ENOENT, + no_such_process = ESRCH, + not_a_directory = ENOTDIR, + not_a_socket = ENOTSOCK, +#ifdef ENOSTR + not_a_stream = ENOSTR, +#else + not_a_stream = EINVAL, +#endif + not_connected = ENOTCONN, + not_enough_memory = ENOMEM, + not_supported = ENOTSUP, +#ifdef ECANCELED + operation_canceled = ECANCELED, +#else + operation_canceled = EINVAL, +#endif + operation_in_progress = EINPROGRESS, + operation_not_permitted = EPERM, + operation_not_supported = EOPNOTSUPP, + operation_would_block = EWOULDBLOCK, +#ifdef EOWNERDEAD + owner_dead = EOWNERDEAD, +#else + owner_dead = EINVAL, +#endif + permission_denied = EACCES, +#ifdef EPROTO + protocol_error = EPROTO, +#else + protocol_error = EINVAL, +#endif + protocol_not_supported = EPROTONOSUPPORT, + read_only_file_system = EROFS, + resource_deadlock_would_occur = EDEADLK, + resource_unavailable_try_again = EAGAIN, + result_out_of_range = ERANGE, +#ifdef ENOTRECOVERABLE + state_not_recoverable = ENOTRECOVERABLE, +#else + state_not_recoverable = EINVAL, +#endif +#ifdef ETIME + stream_timeout = ETIME, +#else + stream_timeout = ETIMEDOUT, +#endif + text_file_busy = ETXTBSY, + timed_out = ETIMEDOUT, + too_many_files_open_in_system = ENFILE, + too_many_files_open = EMFILE, + too_many_links = EMLINK, + too_many_symbolic_link_levels = ELOOP, + value_too_large = EOVERFLOW, + wrong_protocol_type = EPROTOTYPE +}; + + _ v_; + + errc(_ v) : v_(v) {} + operator int() const {return v_;} +}; + +template <> struct is_error_condition_enum<errc> : true_type { }; + +template <> struct is_error_condition_enum<errc::_> : true_type { }; + +class error_condition; +class error_code; + +// class error_category + +class _do_message; + +class error_category +{ +public: + virtual ~error_category(); + +private: + error_category(); + error_category(const error_category&);// = delete; + error_category& operator=(const error_category&);// = delete; + +public: + virtual const char* name() const = 0; + virtual error_condition default_error_condition(int _ev) const; + virtual bool equivalent(int _code, const error_condition& _condition) const; + virtual bool equivalent(const error_code& _code, int _condition) const; + virtual std::string message(int _ev) const = 0; + + bool operator==(const error_category& _rhs) const {return this == &_rhs;} + + bool operator!=(const error_category& _rhs) const {return !(*this == _rhs);} + + bool operator< (const error_category& _rhs) const {return this < &_rhs;} + + friend class _do_message; +}; + +class _do_message : public error_category +{ +public: + virtual std::string message(int ev) const; +}; + +const error_category& generic_category(); +const error_category& system_category(); + +/// Get the error_category used for errno values from POSIX functions. This is +/// the same as the system_category on POISIX systems, but is the same as the +/// generic_category on Windows. +const error_category& posix_category(); + +class error_condition +{ + int _val_; + const error_category* _cat_; +public: + error_condition() : _val_(0), _cat_(&generic_category()) {} + + error_condition(int _val, const error_category& _cat) + : _val_(_val), _cat_(&_cat) {} + + template <class E> + error_condition(E _e, typename enable_if_c< + is_error_condition_enum<E>::value + >::type* = 0) + {*this = make_error_condition(_e);} + + void assign(int _val, const error_category& _cat) { + _val_ = _val; + _cat_ = &_cat; + } + + template <class E> + typename enable_if_c + < + is_error_condition_enum<E>::value, + error_condition& + >::type + operator=(E _e) + {*this = make_error_condition(_e); return *this;} + + void clear() { + _val_ = 0; + _cat_ = &generic_category(); + } + + int value() const {return _val_;} + + const error_category& category() const {return *_cat_;} + std::string message() const; + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + operator unspecified_bool_type() const { // true if error + return _val_ == 0 ? 0 : unspecified_bool_true; + } +}; + +inline error_condition make_error_condition(errc _e) { + return error_condition(static_cast<int>(_e), generic_category()); +} + +inline bool operator<(const error_condition& _x, const error_condition& _y) { + return _x.category() < _y.category() + || (_x.category() == _y.category() && _x.value() < _y.value()); +} + +// error_code + +class error_code { + int _val_; + const error_category* _cat_; +public: + error_code() : _val_(0), _cat_(&system_category()) {} + + error_code(int _val, const error_category& _cat) + : _val_(_val), _cat_(&_cat) {} + + template <class E> + error_code(E _e, typename enable_if_c< + is_error_code_enum<E>::value + >::type* = 0) { + *this = make_error_code(_e); + } + + void assign(int _val, const error_category& _cat) { + _val_ = _val; + _cat_ = &_cat; + } + + template <class E> + typename enable_if_c + < + is_error_code_enum<E>::value, + error_code& + >::type + operator=(E _e) + {*this = make_error_code(_e); return *this;} + + void clear() { + _val_ = 0; + _cat_ = &system_category(); + } + + int value() const {return _val_;} + + const error_category& category() const {return *_cat_;} + + error_condition default_error_condition() const + {return _cat_->default_error_condition(_val_);} + + std::string message() const; + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + operator unspecified_bool_type() const { // true if error + return _val_ == 0 ? 0 : unspecified_bool_true; + } +}; + +inline error_code make_error_code(errc _e) { + return error_code(static_cast<int>(_e), generic_category()); +} + +inline bool operator<(const error_code& _x, const error_code& _y) { + return _x.category() < _y.category() + || (_x.category() == _y.category() && _x.value() < _y.value()); +} + +inline bool operator==(const error_code& _x, const error_code& _y) { + return _x.category() == _y.category() && _x.value() == _y.value(); +} + +inline bool operator==(const error_code& _x, const error_condition& _y) { + return _x.category().equivalent(_x.value(), _y) + || _y.category().equivalent(_x, _y.value()); +} + +inline bool operator==(const error_condition& _x, const error_code& _y) { + return _y == _x; +} + +inline bool operator==(const error_condition& _x, const error_condition& _y) { + return _x.category() == _y.category() && _x.value() == _y.value(); +} + +inline bool operator!=(const error_code& _x, const error_code& _y) { + return !(_x == _y); +} + +inline bool operator!=(const error_code& _x, const error_condition& _y) { + return !(_x == _y); +} + +inline bool operator!=(const error_condition& _x, const error_code& _y) { + return !(_x == _y); +} + +inline bool operator!=(const error_condition& _x, const error_condition& _y) { + return !(_x == _y); +} + +// Windows errors. + +// To construct an error_code after an API error: +// +// error_code( ::GetLastError(), system_category() ) +struct windows_error { +enum _ { + success = 0, + // These names and values are based on Windows WinError.h + // This is not a complete list. Add to this list if you need to explicitly + // check for it. + invalid_function = 1, // ERROR_INVALID_FUNCTION, + file_not_found = 2, // ERROR_FILE_NOT_FOUND, + path_not_found = 3, // ERROR_PATH_NOT_FOUND, + too_many_open_files = 4, // ERROR_TOO_MANY_OPEN_FILES, + access_denied = 5, // ERROR_ACCESS_DENIED, + invalid_handle = 6, // ERROR_INVALID_HANDLE, + arena_trashed = 7, // ERROR_ARENA_TRASHED, + not_enough_memory = 8, // ERROR_NOT_ENOUGH_MEMORY, + invalid_block = 9, // ERROR_INVALID_BLOCK, + bad_environment = 10, // ERROR_BAD_ENVIRONMENT, + bad_format = 11, // ERROR_BAD_FORMAT, + invalid_access = 12, // ERROR_INVALID_ACCESS, + outofmemory = 14, // ERROR_OUTOFMEMORY, + invalid_drive = 15, // ERROR_INVALID_DRIVE, + current_directory = 16, // ERROR_CURRENT_DIRECTORY, + not_same_device = 17, // ERROR_NOT_SAME_DEVICE, + no_more_files = 18, // ERROR_NO_MORE_FILES, + write_protect = 19, // ERROR_WRITE_PROTECT, + bad_unit = 20, // ERROR_BAD_UNIT, + not_ready = 21, // ERROR_NOT_READY, + bad_command = 22, // ERROR_BAD_COMMAND, + crc = 23, // ERROR_CRC, + bad_length = 24, // ERROR_BAD_LENGTH, + seek = 25, // ERROR_SEEK, + not_dos_disk = 26, // ERROR_NOT_DOS_DISK, + sector_not_found = 27, // ERROR_SECTOR_NOT_FOUND, + out_of_paper = 28, // ERROR_OUT_OF_PAPER, + write_fault = 29, // ERROR_WRITE_FAULT, + read_fault = 30, // ERROR_READ_FAULT, + gen_failure = 31, // ERROR_GEN_FAILURE, + sharing_violation = 32, // ERROR_SHARING_VIOLATION, + lock_violation = 33, // ERROR_LOCK_VIOLATION, + wrong_disk = 34, // ERROR_WRONG_DISK, + sharing_buffer_exceeded = 36, // ERROR_SHARING_BUFFER_EXCEEDED, + handle_eof = 38, // ERROR_HANDLE_EOF, + handle_disk_full = 39, // ERROR_HANDLE_DISK_FULL, + rem_not_list = 51, // ERROR_REM_NOT_LIST, + dup_name = 52, // ERROR_DUP_NAME, + bad_net_path = 53, // ERROR_BAD_NETPATH, + network_busy = 54, // ERROR_NETWORK_BUSY, + file_exists = 80, // ERROR_FILE_EXISTS, + cannot_make = 82, // ERROR_CANNOT_MAKE, + broken_pipe = 109, // ERROR_BROKEN_PIPE, + open_failed = 110, // ERROR_OPEN_FAILED, + buffer_overflow = 111, // ERROR_BUFFER_OVERFLOW, + disk_full = 112, // ERROR_DISK_FULL, + insufficient_buffer = 122, // ERROR_INSUFFICIENT_BUFFER, + lock_failed = 167, // ERROR_LOCK_FAILED, + busy = 170, // ERROR_BUSY, + cancel_violation = 173, // ERROR_CANCEL_VIOLATION, + already_exists = 183 // ERROR_ALREADY_EXISTS +}; + _ v_; + + windows_error(_ v) : v_(v) {} + explicit windows_error(int v) : v_(_(v)) {} + operator int() const {return v_;} +}; + + +template <> struct is_error_code_enum<windows_error> : true_type { }; + +template <> struct is_error_code_enum<windows_error::_> : true_type { }; + +inline error_code make_error_code(windows_error e) { + return error_code(static_cast<int>(e), system_category()); +} + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/System/Alarm.h b/contrib/llvm/include/llvm/System/Alarm.h deleted file mode 100644 index 7c28416..0000000 --- a/contrib/llvm/include/llvm/System/Alarm.h +++ /dev/null @@ -1,51 +0,0 @@ -//===- llvm/System/Alarm.h - Alarm Generation support ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides an operating system independent interface to alarm(2) -// type functionality. The Alarm class allows a one-shot alarm to be set up -// at some number of seconds in the future. When the alarm triggers, a method -// is called to process the event -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SYSTEM_ALARM_H -#define LLVM_SYSTEM_ALARM_H - -namespace llvm { -namespace sys { - - /// This function registers an alarm to trigger some number of \p seconds in - /// the future. When that time arrives, the AlarmStatus function will begin - /// to return 1 instead of 0. The user must poll the status of the alarm by - /// making occasional calls to AlarmStatus. If the user sends an interrupt - /// signal, AlarmStatus will begin returning -1, even if the alarm event - /// occurred. - /// @returns nothing - void SetupAlarm( - unsigned seconds ///< Number of seconds in future when alarm arrives - ); - - /// This function terminates the alarm previously set up - /// @returns nothing - void TerminateAlarm(); - - /// This function acquires the status of the alarm. - /// @returns -1=cancelled, 0=untriggered, 1=triggered - int AlarmStatus(); - - /// Sleep for n seconds. Warning: mixing calls to Sleep() and other *Alarm - /// calls may be a bad idea on some platforms (source: Linux man page). - /// @returns nothing. - void Sleep(unsigned n); - - -} // End sys namespace -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Target/Mangler.h b/contrib/llvm/include/llvm/Target/Mangler.h index a9f3576..c1c118b 100644 --- a/contrib/llvm/include/llvm/Target/Mangler.h +++ b/contrib/llvm/include/llvm/Target/Mangler.h @@ -15,7 +15,6 @@ #define LLVM_SUPPORT_MANGLER_H #include "llvm/ADT/DenseMap.h" -#include <string> namespace llvm { class StringRef; @@ -69,12 +68,6 @@ public: /// empty. void getNameWithPrefix(SmallVectorImpl<char> &OutName, const Twine &GVName, ManglerPrefixTy PrefixTy = Mangler::Default); - - /// getNameWithPrefix - Return the name of the appropriate prefix - /// and the specified global variable's name. If the global variable doesn't - /// have a name, this fills in a unique name for the global. - std::string getNameWithPrefix(const GlobalValue *GV, - bool isImplicitlyPrivate = false); }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Target/SubtargetFeature.h b/contrib/llvm/include/llvm/Target/SubtargetFeature.h index 4546871..6c21ae9 100644 --- a/contrib/llvm/include/llvm/Target/SubtargetFeature.h +++ b/contrib/llvm/include/llvm/Target/SubtargetFeature.h @@ -22,7 +22,7 @@ #include <vector> #include <cstring> #include "llvm/ADT/Triple.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class raw_ostream; diff --git a/contrib/llvm/include/llvm/Target/Target.td b/contrib/llvm/include/llvm/Target/Target.td index b141a77..0f7e6aa 100644 --- a/contrib/llvm/include/llvm/Target/Target.td +++ b/contrib/llvm/include/llvm/Target/Target.td @@ -1,10 +1,10 @@ //===- Target.td - Target Independent TableGen interface ---*- tablegen -*-===// -// +// // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // // This file defines the target-independent interfaces which should be @@ -47,7 +47,7 @@ class Register<string n> { // modification of this register can potentially read or modify the aliased // registers. list<Register> Aliases = []; - + // SubRegs - A list of registers that are parts of this register. Note these // are "immediate" sub-registers and the registers within the list do not // themselves overlap. e.g. For X86, EAX's SubRegs list contains only [AX], @@ -84,7 +84,7 @@ class Register<string n> { // need to specify sub-registers. // List "subregs" specifies which registers are sub-registers to this one. This // is used to populate the SubRegs and AliasSet fields of TargetRegisterDesc. -// This allows the code generator to be careful not to put two values with +// This allows the code generator to be careful not to put two values with // overlapping live ranges into registers which alias. class RegisterWithSubRegs<string n, list<Register> subregs> : Register<n> { let SubRegs = subregs; @@ -101,7 +101,7 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, // RegType - Specify the list ValueType of the registers in this register // class. Note that all registers in a register class must have the same - // ValueTypes. This is a list because some targets permit storing different + // ValueTypes. This is a list because some targets permit storing different // types in same register, for example vector values with 128-bit total size, // but different count/size of items, like SSE on x86. // @@ -127,13 +127,13 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, // allocation used by the register allocator. // list<Register> MemberList = regList; - + // SubRegClasses - Specify the register class of subregisters as a list of // dags: (RegClass SubRegIndex, SubRegindex, ...) list<dag> SubRegClasses = []; // MethodProtos/MethodBodies - These members can be used to insert arbitrary - // code into a generated register class. The normal usage of this is to + // code into a generated register class. The normal usage of this is to // overload virtual methods. code MethodProtos = [{}]; code MethodBodies = [{}]; @@ -150,8 +150,8 @@ class DwarfRegNum<list<int> Numbers> { // These values can be determined by locating the <target>.h file in the // directory llvmgcc/gcc/config/<target>/ and looking for REGISTER_NAMES. The // order of these names correspond to the enumeration used by gcc. A value of - // -1 indicates that the gcc number is undefined and -2 that register number is - // invalid for this mode/flavour. + // -1 indicates that the gcc number is undefined and -2 that register number + // is invalid for this mode/flavour. list<int> DwarfNumbers = Numbers; } @@ -199,6 +199,7 @@ class Instruction { bit isBranch = 0; // Is this instruction a branch instruction? bit isIndirectBranch = 0; // Is this instruction an indirect branch? bit isCompare = 0; // Is this instruction a comparison instruction? + bit isMoveImm = 0; // Is this instruction a move immediate instruction? bit isBarrier = 0; // Can control flow fall through this instruction? bit isCall = 0; // Is this instruction a call instruction? bit canFoldAsLoad = 0; // Can this be folded as a simple memory operand? @@ -243,14 +244,29 @@ class Instruction { /// be encoded into the output machineinstr. string DisableEncoding = ""; + string PostEncoderMethod = ""; + string DecoderMethod = ""; + /// Target-specific flags. This becomes the TSFlags field in TargetInstrDesc. bits<64> TSFlags = 0; + + ///@name Assembler Parser Support + ///@{ + + string AsmMatchConverter = ""; + + ///@} } /// Predicates - These are extra conditionals which are turned into instruction /// selector matching code. Currently each predicate is just a string. class Predicate<string cond> { string CondString = cond; + + /// AssemblerMatcherPredicate - If this feature can be used by the assembler + /// matcher, this is true. Targets should set this by inheriting their + /// feature from the AssemblerPredicate class in addition to Predicate. + bit AssemblerMatcherPredicate = 0; } /// NoHonorSignDependentRounding - This predicate is true if support for @@ -262,9 +278,9 @@ class Requires<list<Predicate> preds> { list<Predicate> Predicates = preds; } -/// ops definition - This is just a simple marker used to identify the operands -/// list for an instruction. outs and ins are identical both syntatically and -/// semantically, they are used to define def operands and use operands to +/// ops definition - This is just a simple marker used to identify the operand +/// list for an instruction. outs and ins are identical both syntactically and +/// semanticallyr; they are used to define def operands and use operands to /// improve readibility. This should be used like this: /// (outs R32:$dst), (ins R32:$src1, R32:$src2) or something similar. def ops; @@ -326,18 +342,26 @@ class AsmOperandClass { /// signature should be: /// void addFooOperands(MCInst &Inst, unsigned N) const; string RenderMethod = ?; + + /// The name of the method on the target specific operand to call to custom + /// handle the operand parsing. This is useful when the operands do not relate + /// to immediates or registers and are very instruction specific (as flags to + /// set in a processor register, coprocessor number, ...). + string ParserMethod = ?; } def ImmAsmOperand : AsmOperandClass { let Name = "Imm"; } - + /// Operand Types - These provide the built-in operand types that may be used /// by a target. Targets can optionally provide their own operand types as /// needed, though this should not be needed for RISC targets. class Operand<ValueType ty> { ValueType Type = ty; string PrintMethod = "printOperand"; + string EncoderMethod = ""; + string DecoderMethod = ""; string AsmOperandLowerMethod = ?; dag MIOperandInfo = (ops); @@ -409,6 +433,7 @@ def INLINEASM : Instruction { let OutOperandList = (outs); let InOperandList = (ins variable_ops); let AsmString = ""; + let neverHasSideEffects = 1; // Note side effect is encoded in an operand. } def PROLOG_LABEL : Instruction { let OutOperandList = (outs); @@ -475,7 +500,7 @@ def DBG_VALUE : Instruction { let OutOperandList = (outs); let InOperandList = (ins variable_ops); let AsmString = "DBG_VALUE"; - let isAsCheapAsAMove = 1; + let neverHasSideEffects = 1; } def REG_SEQUENCE : Instruction { let OutOperandList = (outs unknown:$dst); @@ -506,9 +531,9 @@ class AsmParser { // name. string AsmParserClassName = "AsmParser"; - // AsmParserInstCleanup - If non-empty, this is the name of a custom function on the - // AsmParser class to call on every matched instruction. This can be used to - // perform target specific instruction post-processing. + // AsmParserInstCleanup - If non-empty, this is the name of a custom member + // function of the AsmParser class to call on every matched instruction. + // This can be used to perform target specific instruction post-processing. string AsmParserInstCleanup = ""; // Variant - AsmParsers can be of multiple different variants. Variants are @@ -529,6 +554,49 @@ class AsmParser { } def DefaultAsmParser : AsmParser; +/// AssemblerPredicate - This is a Predicate that can be used when the assembler +/// matches instructions and aliases. +class AssemblerPredicate { + bit AssemblerMatcherPredicate = 1; +} + + + +/// MnemonicAlias - This class allows targets to define assembler mnemonic +/// aliases. This should be used when all forms of one mnemonic are accepted +/// with a different mnemonic. For example, X86 allows: +/// sal %al, 1 -> shl %al, 1 +/// sal %ax, %cl -> shl %ax, %cl +/// sal %eax, %cl -> shl %eax, %cl +/// etc. Though "sal" is accepted with many forms, all of them are directly +/// translated to a shl, so it can be handled with (in the case of X86, it +/// actually has one for each suffix as well): +/// def : MnemonicAlias<"sal", "shl">; +/// +/// Mnemonic aliases are mapped before any other translation in the match phase, +/// and do allow Requires predicates, e.g.: +/// +/// def : MnemonicAlias<"pushf", "pushfq">, Requires<[In64BitMode]>; +/// def : MnemonicAlias<"pushf", "pushfl">, Requires<[In32BitMode]>; +/// +class MnemonicAlias<string From, string To> { + string FromMnemonic = From; + string ToMnemonic = To; + + // Predicates - Predicates that must be true for this remapping to happen. + list<Predicate> Predicates = []; +} + +/// InstAlias - This defines an alternate assembly syntax that is allowed to +/// match an instruction that has a different (more canonical) assembly +/// representation. +class InstAlias<string Asm, dag Result> { + string AsmString = Asm; // The .s format to match the instruction with. + dag ResultInst = Result; // The MCInst to generate. + + // Predicates - Predicates that must be true for this to match. + list<Predicate> Predicates = []; +} //===----------------------------------------------------------------------===// // AsmWriter - This class can be implemented by targets that need to customize @@ -543,10 +611,6 @@ class AsmWriter { // name. string AsmWriterClassName = "AsmPrinter"; - // InstFormatName - AsmWriters can specify the name of the format string to - // print instructions with. - string InstFormatName = "AsmString"; - // Variant - AsmWriters can be of multiple different variants. Variants are // used to support targets that need to emit assembly code in ways that are // mostly the same for different targets, but have minor differences in @@ -554,17 +618,22 @@ class AsmWriter { // will specify which alternative to use. For example "{x|y|z}" with Variant // == 1, will expand to "y". int Variant = 0; - - + + // FirstOperandColumn/OperandSpacing - If the assembler syntax uses a columnar // layout, the asmwriter can actually generate output in this columns (in // verbose-asm mode). These two values indicate the width of the first column // (the "opcode" area) and the width to reserve for subsequent operands. When // verbose asm mode is enabled, operands will be indented to respect this. int FirstOperandColumn = -1; - + // OperandSpacing - Space between operand columns. int OperandSpacing = -1; + + // isMCAsmWriter - Is this assembly writer for an MC emitter? This controls + // generation of the printInstruction() method. For MC printers, it takes + // an MCInstr* operand, otherwise it takes a MachineInstr*. + bit isMCAsmWriter = 0; } def DefaultAsmWriter : AsmWriter; @@ -592,15 +661,15 @@ class SubtargetFeature<string n, string a, string v, string d, // appropriate target chip. // string Name = n; - + // Attribute - Attribute to be set by feature. // string Attribute = a; - + // Value - Value the attribute to be set to by feature. // string Value = v; - + // Desc - Feature description. Used by command line (-mattr=) to display help // information. // @@ -622,12 +691,12 @@ class Processor<string n, ProcessorItineraries pi, list<SubtargetFeature> f> { // appropriate target chip. // string Name = n; - + // ProcItin - The scheduling information for the target processor. // ProcessorItineraries ProcItin = pi; - - // Features - list of + + // Features - list of list<SubtargetFeature> Features = f; } diff --git a/contrib/llvm/include/llvm/Target/TargetAsmBackend.h b/contrib/llvm/include/llvm/Target/TargetAsmBackend.h index 979595a..7527298 100644 --- a/contrib/llvm/include/llvm/Target/TargetAsmBackend.h +++ b/contrib/llvm/include/llvm/Target/TargetAsmBackend.h @@ -10,17 +10,18 @@ #ifndef LLVM_TARGET_TARGETASMBACKEND_H #define LLVM_TARGET_TARGETASMBACKEND_H -#include "llvm/System/DataTypes.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/Support/DataTypes.h" namespace llvm { -class MCDataFragment; class MCFixup; class MCInst; class MCObjectWriter; class MCSection; template<typename T> class SmallVectorImpl; -class Target; class raw_ostream; /// TargetAsmBackend - Generic interface to target specific assembler backends. @@ -28,37 +29,17 @@ class TargetAsmBackend { TargetAsmBackend(const TargetAsmBackend &); // DO NOT IMPLEMENT void operator=(const TargetAsmBackend &); // DO NOT IMPLEMENT protected: // Can only create subclasses. - TargetAsmBackend(const Target &); + TargetAsmBackend(); - /// TheTarget - The Target that this machine was created for. - const Target &TheTarget; - - unsigned HasAbsolutizedSet : 1; unsigned HasReliableSymbolDifference : 1; - unsigned HasScatteredSymbols : 1; public: virtual ~TargetAsmBackend(); - const Target &getTarget() const { return TheTarget; } - /// createObjectWriter - Create a new MCObjectWriter instance for use by the /// assembler backend to emit the final object file. virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const = 0; - /// hasAbsolutizedSet - Check whether this target "absolutizes" - /// assignments. That is, given code like: - /// a: - /// ... - /// b: - /// tmp = a - b - /// .long tmp - /// will the value of 'tmp' be a relocatable expression, or the assembly time - /// value of L0 - L1. This distinction is only relevant for platforms that - /// support scattered symbols, since in the absence of scattered symbols (a - - /// b) cannot change after assembly. - bool hasAbsolutizedSet() const { return HasAbsolutizedSet; } - /// hasReliableSymbolDifference - Check whether this target implements /// accurate relocations for differences between symbols. If not, differences /// between symbols will always be relocatable expressions and any references @@ -68,21 +49,11 @@ public: /// This should always be true (since it results in fewer relocations with no /// loss of functionality), but is currently supported as a way to maintain /// exact object compatibility with Darwin 'as' (on non-x86_64). It should - /// eventually should be eliminated. See also \see hasAbsolutizedSet. + /// eventually should be eliminated. bool hasReliableSymbolDifference() const { return HasReliableSymbolDifference; } - /// hasScatteredSymbols - Check whether this target supports scattered - /// symbols. If so, the assembler should assume that atoms can be scattered by - /// the linker. In particular, this means that the offsets between symbols - /// which are in distinct atoms is not known at link time, and the assembler - /// must generate fixups and relocations appropriately. - /// - /// Note that the assembler currently does not reason about atoms, instead it - /// assumes all temporary symbols reside in the "current atom". - bool hasScatteredSymbols() const { return HasScatteredSymbols; } - /// doesSectionRequireSymbols - Check whether the given section requires that /// all symbols (even temporaries) have symbol table entries. virtual bool doesSectionRequireSymbols(const MCSection &Section) const { @@ -97,16 +68,28 @@ public: return true; } - /// isVirtualSection - Check whether the given section is "virtual", that is - /// has no actual object file contents. - virtual bool isVirtualSection(const MCSection &Section) const = 0; + /// @name Target Fixup Interfaces + /// @{ + + /// getNumFixupKinds - Get the number of target specific fixup kinds. + virtual unsigned getNumFixupKinds() const = 0; + + /// getFixupKindInfo - Get information on a fixup kind. + virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const; + + /// @} /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided /// data fragment, at the offset specified by the fixup and following the /// fixup kind as appropriate. - virtual void ApplyFixup(const MCFixup &Fixup, MCDataFragment &Fragment, + virtual void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const = 0; + /// @} + + /// @name Target Relaxation Interfaces + /// @{ + /// MayNeedRelaxation - Check whether the given instruction may need /// relaxation. /// @@ -121,12 +104,18 @@ public: /// \parm Res [output] - On return, the relaxed instruction. virtual void RelaxInstruction(const MCInst &Inst, MCInst &Res) const = 0; + /// @} + /// WriteNopData - Write an (optimal) nop sequence of Count bytes to the given /// output. If the target cannot generate such a sequence, it should return an /// error. /// /// \return - True on success. virtual bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const = 0; + + /// HandleAssemblerFlag - Handle any target-specific assembler flags. + /// By default, do nothing. + virtual void HandleAssemblerFlag(MCAssemblerFlag Flag) {} }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Target/TargetAsmInfo.h b/contrib/llvm/include/llvm/Target/TargetAsmInfo.h new file mode 100644 index 0000000..98aab14 --- /dev/null +++ b/contrib/llvm/include/llvm/Target/TargetAsmInfo.h @@ -0,0 +1,75 @@ +//===-- llvm/Target/TargetAsmInfo.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface to provide the information necessary for producing assembly files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETASMINFO_H +#define LLVM_TARGET_TARGETASMINFO_H + +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetRegisterInfo.h" + +namespace llvm { + class MCSection; + class MCContext; + class TargetMachine; + class TargetLoweringObjectFile; + +class TargetAsmInfo { + unsigned PointerSize; + bool IsLittleEndian; + TargetFrameLowering::StackDirection StackDir; + const TargetRegisterInfo *TRI; + std::vector<MachineMove> InitialFrameState; + const TargetLoweringObjectFile *TLOF; + +public: + explicit TargetAsmInfo(const TargetMachine &TM); + + /// getPointerSize - Get the pointer size in bytes. + unsigned getPointerSize() const { + return PointerSize; + } + + /// islittleendian - True if the target is little endian. + bool isLittleEndian() const { + return IsLittleEndian; + } + + TargetFrameLowering::StackDirection getStackGrowthDirection() const { + return StackDir; + } + + const MCSection *getDwarfLineSection() const { + return TLOF->getDwarfLineSection(); + } + + const MCSection *getEHFrameSection() const { + return TLOF->getEHFrameSection(); + } + + unsigned getDwarfRARegNum(bool isEH) const { + return TRI->getDwarfRegNum(TRI->getRARegister(), isEH); + } + + const std::vector<MachineMove> &getInitialFrameState() const { + return InitialFrameState; + } + + int getDwarfRegNum(unsigned RegNum, bool isEH) const { + return TRI->getDwarfRegNum(RegNum, isEH); + } +}; + +} +#endif diff --git a/contrib/llvm/include/llvm/Target/TargetAsmParser.h b/contrib/llvm/include/llvm/Target/TargetAsmParser.h index 5830d1f..9ff50cb 100644 --- a/contrib/llvm/include/llvm/Target/TargetAsmParser.h +++ b/contrib/llvm/include/llvm/Target/TargetAsmParser.h @@ -13,7 +13,7 @@ #include "llvm/MC/MCParser/MCAsmParserExtension.h" namespace llvm { -class MCInst; +class MCStreamer; class StringRef; class Target; class SMLoc; @@ -42,6 +42,8 @@ public: unsigned getAvailableFeatures() const { return AvailableFeatures; } void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } + virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) = 0; + /// ParseInstruction - Parse one assembly instruction. /// /// The parser is positioned following the instruction name. The target @@ -70,16 +72,16 @@ public: /// \param DirectiveID - the identifier token of the directive. virtual bool ParseDirective(AsmToken DirectiveID) = 0; - /// MatchInstruction - Recognize a series of operands of a parsed instruction - /// as an actual MCInst. This returns false and fills in Inst on success and - /// returns true on failure to match. + /// MatchAndEmitInstruction - Recognize a series of operands of a parsed + /// instruction as an actual MCInst and emit it to the specified MCStreamer. + /// This returns false on success and returns true on failure to match. /// /// On failure, the target parser is responsible for emitting a diagnostic /// explaining the match failure. virtual bool - MatchInstruction(SMLoc IDLoc, - const SmallVectorImpl<MCParsedAsmOperand*> &Operands, - MCInst &Inst) = 0; + MatchAndEmitInstruction(SMLoc IDLoc, + SmallVectorImpl<MCParsedAsmOperand*> &Operands, + MCStreamer &Out) = 0; }; diff --git a/contrib/llvm/include/llvm/Target/TargetCallingConv.h b/contrib/llvm/include/llvm/Target/TargetCallingConv.h index f368a2e..275957e 100644 --- a/contrib/llvm/include/llvm/Target/TargetCallingConv.h +++ b/contrib/llvm/include/llvm/Target/TargetCallingConv.h @@ -106,14 +106,13 @@ namespace ISD { /// struct InputArg { ArgFlagsTy Flags; - EVT VT; + MVT VT; bool Used; InputArg() : VT(MVT::Other), Used(false) {} InputArg(ArgFlagsTy flags, EVT vt, bool used) - : Flags(flags), VT(vt), Used(used) { - assert(VT.isSimple() && - "InputArg value type must be Simple!"); + : Flags(flags), Used(used) { + VT = vt.getSimpleVT(); } }; @@ -123,16 +122,15 @@ namespace ISD { /// struct OutputArg { ArgFlagsTy Flags; - EVT VT; + MVT VT; /// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...". bool IsFixed; OutputArg() : IsFixed(false) {} OutputArg(ArgFlagsTy flags, EVT vt, bool isfixed) - : Flags(flags), VT(vt), IsFixed(isfixed) { - assert(VT.isSimple() && - "OutputArg value type must be Simple!"); + : Flags(flags), IsFixed(isfixed) { + VT = vt.getSimpleVT(); } }; } diff --git a/contrib/llvm/include/llvm/Target/TargetData.h b/contrib/llvm/include/llvm/Target/TargetData.h index b89cbe0..25065d3 100644 --- a/contrib/llvm/include/llvm/Target/TargetData.h +++ b/contrib/llvm/include/llvm/Target/TargetData.h @@ -22,6 +22,7 @@ #include "llvm/Pass.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" namespace llvm { @@ -143,7 +144,7 @@ public: std::string getStringRepresentation() const; /// isLegalInteger - This function returns true if the specified type is - /// known tobe a native integer type supported by the CPU. For example, + /// known to be a native integer type supported by the CPU. For example, /// i64 is not native on most 32-bit CPUs and i37 is not native on any known /// one. This returns false if the integer width is not legal. /// diff --git a/contrib/llvm/include/llvm/Target/TargetELFWriterInfo.h b/contrib/llvm/include/llvm/Target/TargetELFWriterInfo.h index 7cb6931..b97f3e2 100644 --- a/contrib/llvm/include/llvm/Target/TargetELFWriterInfo.h +++ b/contrib/llvm/include/llvm/Target/TargetELFWriterInfo.h @@ -28,7 +28,6 @@ namespace llvm { // EMachine - This field is the target specific value to emit as the // e_machine member of the ELF header. unsigned short EMachine; - TargetMachine &TM; bool is64Bit, isLittleEndian; public: @@ -62,7 +61,7 @@ namespace llvm { ELFDATA2MSB = 2 // Big-endian object file }; - explicit TargetELFWriterInfo(TargetMachine &tm); + explicit TargetELFWriterInfo(bool is64Bit_, bool isLittleEndian_); virtual ~TargetELFWriterInfo(); unsigned short getEMachine() const { return EMachine; } diff --git a/contrib/llvm/include/llvm/Target/TargetFrameInfo.h b/contrib/llvm/include/llvm/Target/TargetFrameInfo.h deleted file mode 100644 index 975d156..0000000 --- a/contrib/llvm/include/llvm/Target/TargetFrameInfo.h +++ /dev/null @@ -1,97 +0,0 @@ -//===-- llvm/Target/TargetFrameInfo.h ---------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Interface to describe the layout of a stack frame on the target machine. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETFRAMEINFO_H -#define LLVM_TARGET_TARGETFRAMEINFO_H - -#include <utility> - -namespace llvm { - -/// Information about stack frame layout on the target. It holds the direction -/// of stack growth, the known stack alignment on entry to each function, and -/// the offset to the locals area. -/// -/// The offset to the local area is the offset from the stack pointer on -/// function entry to the first location where function data (local variables, -/// spill locations) can be stored. -class TargetFrameInfo { -public: - enum StackDirection { - StackGrowsUp, // Adding to the stack increases the stack address - StackGrowsDown // Adding to the stack decreases the stack address - }; - - // Maps a callee saved register to a stack slot with a fixed offset. - struct SpillSlot { - unsigned Reg; - int Offset; // Offset relative to stack pointer on function entry. - }; -private: - StackDirection StackDir; - unsigned StackAlignment; - unsigned TransientStackAlignment; - int LocalAreaOffset; -public: - TargetFrameInfo(StackDirection D, unsigned StackAl, int LAO, - unsigned TransAl = 1) - : StackDir(D), StackAlignment(StackAl), TransientStackAlignment(TransAl), - LocalAreaOffset(LAO) {} - - virtual ~TargetFrameInfo(); - - // These methods return information that describes the abstract stack layout - // of the target machine. - - /// getStackGrowthDirection - Return the direction the stack grows - /// - StackDirection getStackGrowthDirection() const { return StackDir; } - - /// getStackAlignment - This method returns the number of bytes to which the - /// stack pointer must be aligned on entry to a function. Typically, this - /// is the largest alignment for any data object in the target. - /// - unsigned getStackAlignment() const { return StackAlignment; } - - /// getTransientStackAlignment - This method returns the number of bytes to - /// which the stack pointer must be aligned at all times, even between - /// calls. - /// - unsigned getTransientStackAlignment() const { - return TransientStackAlignment; - } - - /// getOffsetOfLocalArea - This method returns the offset of the local area - /// from the stack pointer on entrance to a function. - /// - int getOffsetOfLocalArea() const { return LocalAreaOffset; } - - /// getCalleeSavedSpillSlots - This method returns a pointer to an array of - /// pairs, that contains an entry for each callee saved register that must be - /// spilled to a particular stack location if it is spilled. - /// - /// Each entry in this array contains a <register,offset> pair, indicating the - /// fixed offset from the incoming stack pointer that each register should be - /// spilled at. If a register is not listed here, the code generator is - /// allowed to spill it anywhere it chooses. - /// - virtual const SpillSlot * - getCalleeSavedSpillSlots(unsigned &NumEntries) const { - NumEntries = 0; - return 0; - } -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Target/TargetFrameLowering.h b/contrib/llvm/include/llvm/Target/TargetFrameLowering.h new file mode 100644 index 0000000..e104b16 --- /dev/null +++ b/contrib/llvm/include/llvm/Target/TargetFrameLowering.h @@ -0,0 +1,196 @@ +//===-- llvm/Target/TargetFrameLowering.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface to describe the layout of a stack frame on the target machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETFRAMELOWERING_H +#define LLVM_TARGET_TARGETFRAMELOWERING_H + +#include "llvm/CodeGen/MachineBasicBlock.h" + +#include <utility> +#include <vector> + +namespace llvm { + class CalleeSavedInfo; + class MachineFunction; + class MachineBasicBlock; + class MachineMove; + class RegScavenger; + +/// Information about stack frame layout on the target. It holds the direction +/// of stack growth, the known stack alignment on entry to each function, and +/// the offset to the locals area. +/// +/// The offset to the local area is the offset from the stack pointer on +/// function entry to the first location where function data (local variables, +/// spill locations) can be stored. +class TargetFrameLowering { +public: + enum StackDirection { + StackGrowsUp, // Adding to the stack increases the stack address + StackGrowsDown // Adding to the stack decreases the stack address + }; + + // Maps a callee saved register to a stack slot with a fixed offset. + struct SpillSlot { + unsigned Reg; + int Offset; // Offset relative to stack pointer on function entry. + }; +private: + StackDirection StackDir; + unsigned StackAlignment; + unsigned TransientStackAlignment; + int LocalAreaOffset; +public: + TargetFrameLowering(StackDirection D, unsigned StackAl, int LAO, + unsigned TransAl = 1) + : StackDir(D), StackAlignment(StackAl), TransientStackAlignment(TransAl), + LocalAreaOffset(LAO) {} + + virtual ~TargetFrameLowering(); + + // These methods return information that describes the abstract stack layout + // of the target machine. + + /// getStackGrowthDirection - Return the direction the stack grows + /// + StackDirection getStackGrowthDirection() const { return StackDir; } + + /// getStackAlignment - This method returns the number of bytes to which the + /// stack pointer must be aligned on entry to a function. Typically, this + /// is the largest alignment for any data object in the target. + /// + unsigned getStackAlignment() const { return StackAlignment; } + + /// getTransientStackAlignment - This method returns the number of bytes to + /// which the stack pointer must be aligned at all times, even between + /// calls. + /// + unsigned getTransientStackAlignment() const { + return TransientStackAlignment; + } + + /// getOffsetOfLocalArea - This method returns the offset of the local area + /// from the stack pointer on entrance to a function. + /// + int getOffsetOfLocalArea() const { return LocalAreaOffset; } + + /// getCalleeSavedSpillSlots - This method returns a pointer to an array of + /// pairs, that contains an entry for each callee saved register that must be + /// spilled to a particular stack location if it is spilled. + /// + /// Each entry in this array contains a <register,offset> pair, indicating the + /// fixed offset from the incoming stack pointer that each register should be + /// spilled at. If a register is not listed here, the code generator is + /// allowed to spill it anywhere it chooses. + /// + virtual const SpillSlot * + getCalleeSavedSpillSlots(unsigned &NumEntries) const { + NumEntries = 0; + return 0; + } + + /// targetHandlesStackFrameRounding - Returns true if the target is + /// responsible for rounding up the stack frame (probably at emitPrologue + /// time). + virtual bool targetHandlesStackFrameRounding() const { + return false; + } + + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. + virtual void emitPrologue(MachineFunction &MF) const = 0; + virtual void emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const = 0; + + /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee + /// saved registers and returns true if it isn't possible / profitable to do + /// so by issuing a series of store instructions via + /// storeRegToStackSlot(). Returns false otherwise. + virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const { + return false; + } + + /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee + /// saved registers and returns true if it isn't possible / profitable to do + /// so by issuing a series of load instructions via loadRegToStackSlot(). + /// Returns false otherwise. + virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const { + return false; + } + + /// hasFP - Return true if the specified function should have a dedicated + /// frame pointer register. For most targets this is true only if the function + /// has variable sized allocas or if frame pointer elimination is disabled. + virtual bool hasFP(const MachineFunction &MF) const = 0; + + /// hasReservedCallFrame - Under normal circumstances, when a frame pointer is + /// not required, we reserve argument space for call sites in the function + /// immediately on entry to the current function. This eliminates the need for + /// add/sub sp brackets around call sites. Returns true if the call frame is + /// included as part of the stack frame. + virtual bool hasReservedCallFrame(const MachineFunction &MF) const { + return !hasFP(MF); + } + + /// canSimplifyCallFramePseudos - When possible, it's best to simplify the + /// call frame pseudo ops before doing frame index elimination. This is + /// possible only when frame index references between the pseudos won't + /// need adjusting for the call frame adjustments. Normally, that's true + /// if the function has a reserved call frame or a frame pointer. Some + /// targets (Thumb2, for example) may have more complicated criteria, + /// however, and can override this behavior. + virtual bool canSimplifyCallFramePseudos(const MachineFunction &MF) const { + return hasReservedCallFrame(MF) || hasFP(MF); + } + + /// getInitialFrameState - Returns a list of machine moves that are assumed + /// on entry to all functions. Note that LabelID is ignored (assumed to be + /// the beginning of the function.) + virtual void getInitialFrameState(std::vector<MachineMove> &Moves) const; + + /// getFrameIndexOffset - Returns the displacement from the frame register to + /// the stack frame of the specified index. + virtual int getFrameIndexOffset(const MachineFunction &MF, int FI) const; + + /// getFrameIndexReference - This method should return the base register + /// and offset used to reference a frame index location. The offset is + /// returned directly, and the base register is returned via FrameReg. + virtual int getFrameIndexReference(const MachineFunction &MF, int FI, + unsigned &FrameReg) const; + + /// processFunctionBeforeCalleeSavedScan - This method is called immediately + /// before PrologEpilogInserter scans the physical registers used to determine + /// what callee saved registers should be spilled. This method is optional. + virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS = NULL) const { + + } + + /// processFunctionBeforeFrameFinalized - This method is called immediately + /// before the specified function's frame layout (MF.getFrameInfo()) is + /// finalized. Once the frame is finalized, MO_FrameIndex operands are + /// replaced with direct constants. This method is optional. + /// + virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const { + } +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/Target/TargetInstrDesc.h b/contrib/llvm/include/llvm/Target/TargetInstrDesc.h index a127aed..8823d5a 100644 --- a/contrib/llvm/include/llvm/Target/TargetInstrDesc.h +++ b/contrib/llvm/include/llvm/Target/TargetInstrDesc.h @@ -15,7 +15,7 @@ #ifndef LLVM_TARGET_TARGETINSTRDESC_H #define LLVM_TARGET_TARGETINSTRDESC_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { @@ -103,13 +103,14 @@ namespace TID { Terminator, Branch, IndirectBranch, - Predicable, - NotDuplicable, Compare, + MoveImm, DelaySlot, FoldableAsLoad, MayLoad, MayStore, + Predicable, + NotDuplicable, UnmodeledSideEffects, Commutable, ConvertibleTo3Addr, @@ -352,6 +353,12 @@ public: return Flags & (1 << TID::Compare); } + /// isMoveImmediate - Return true if this instruction is a move immediate + /// (including conditional moves) instruction. + bool isMoveImmediate() const { + return Flags & (1 << TID::MoveImm); + } + /// isNotDuplicable - Return true if this instruction cannot be safely /// duplicated. For example, if the instruction has a unique labels attached /// to it, duplicating it would cause multiple definition errors. diff --git a/contrib/llvm/include/llvm/Target/TargetInstrInfo.h b/contrib/llvm/include/llvm/Target/TargetInstrInfo.h index 520c41b..fc7b51e 100644 --- a/contrib/llvm/include/llvm/Target/TargetInstrInfo.h +++ b/contrib/llvm/include/llvm/Target/TargetInstrInfo.h @@ -19,16 +19,17 @@ namespace llvm { -class CalleeSavedInfo; class InstrItineraryData; class LiveVariables; class MCAsmInfo; class MachineMemOperand; +class MachineRegisterInfo; class MDNode; class MCInst; class SDNode; class ScheduleHazardRecognizer; class SelectionDAG; +class ScheduleDAG; class TargetRegisterClass; class TargetRegisterInfo; @@ -134,7 +135,7 @@ public: int &FrameIndex) const { return 0; } - + /// isStoreToStackSlot - If the specified machine instruction is a direct /// store to a stack slot, return the virtual or physical register number of /// the source reg along with the FrameIndex of the loaded stack slot. If @@ -227,9 +228,12 @@ public: /// produceSameValue - Return true if two machine instructions would produce /// identical values. By default, this is only true when the two instructions - /// are deemed identical except for defs. + /// are deemed identical except for defs. If this function is called when the + /// IR is still in SSA form, the caller can pass the MachineRegisterInfo for + /// aggressive checks. virtual bool produceSameValue(const MachineInstr *MI0, - const MachineInstr *MI1) const = 0; + const MachineInstr *MI1, + const MachineRegisterInfo *MRI = 0) const = 0; /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning /// true if it cannot be understood (e.g. it's a switch dispatch or isn't @@ -267,7 +271,7 @@ public: /// This is only invoked in cases where AnalyzeBranch returns success. It /// returns the number of instructions that were removed. virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const { - assert(0 && "Target didn't implement TargetInstrInfo::RemoveBranch!"); + assert(0 && "Target didn't implement TargetInstrInfo::RemoveBranch!"); return 0; } @@ -285,7 +289,7 @@ public: MachineBasicBlock *FBB, const SmallVectorImpl<MachineOperand> &Cond, DebugLoc DL) const { - assert(0 && "Target didn't implement TargetInstrInfo::InsertBranch!"); + assert(0 && "Target didn't implement TargetInstrInfo::InsertBranch!"); return 0; } @@ -303,31 +307,45 @@ public: return true; } - /// isProfitableToIfCvt - Return true if it's profitable to first "NumInstrs" - /// of the specified basic block. + /// isProfitableToIfCvt - Return true if it's profitable to predicate + /// instructions with accumulated instruction latency of "NumCycles" + /// of the specified basic block, where the probability of the instructions + /// being executed is given by Probability, and Confidence is a measure + /// of our confidence that it will be properly predicted. virtual - bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumInstrs) const { + bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCyles, + unsigned ExtraPredCycles, + float Probability, float Confidence) const { return false; } - + /// isProfitableToIfCvt - Second variant of isProfitableToIfCvt, this one /// checks for the case where two basic blocks from true and false path /// of a if-then-else (diamond) are predicated on mutally exclusive - /// predicates. + /// predicates, where the probability of the true path being taken is given + /// by Probability, and Confidence is a measure of our confidence that it + /// will be properly predicted. virtual bool - isProfitableToIfCvt(MachineBasicBlock &TMBB, unsigned NumTInstrs, - MachineBasicBlock &FMBB, unsigned NumFInstrs) const { + isProfitableToIfCvt(MachineBasicBlock &TMBB, + unsigned NumTCycles, unsigned ExtraTCycles, + MachineBasicBlock &FMBB, + unsigned NumFCycles, unsigned ExtraFCycles, + float Probability, float Confidence) const { return false; } /// isProfitableToDupForIfCvt - Return true if it's profitable for - /// if-converter to duplicate a specific number of instructions in the - /// specified MBB to enable if-conversion. + /// if-converter to duplicate instructions of specified accumulated + /// instruction latencies in the specified MBB to enable if-conversion. + /// The probability of the instructions being executed is given by + /// Probability, and Confidence is a measure of our confidence that it + /// will be properly predicted. virtual bool - isProfitableToDupForIfCvt(MachineBasicBlock &MBB,unsigned NumInstrs) const { + isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCyles, + float Probability, float Confidence) const { return false; } - + /// copyPhysReg - Emit instructions to copy a pair of physical registers. virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, DebugLoc DL, @@ -360,29 +378,7 @@ public: const TargetRegisterInfo *TRI) const { assert(0 && "Target didn't implement TargetInstrInfo::loadRegFromStackSlot!"); } - - /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee - /// saved registers and returns true if it isn't possible / profitable to do - /// so by issuing a series of store instructions via - /// storeRegToStackSlot(). Returns false otherwise. - virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const { - return false; - } - /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee - /// saved registers and returns true if it isn't possible / profitable to do - /// so by issuing a series of load instructions via loadRegToStackSlot(). - /// Returns false otherwise. - virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const { - return false; - } - /// emitFrameIndexDebugValue - Emit a target-dependent form of /// DBG_VALUE encoding the address of a frame index. Addresses would /// normally be lowered the same way as other addresses on the target, @@ -493,7 +489,7 @@ public: unsigned NumLoads) const { return false; } - + /// ReverseBranchCondition - Reverses the branch condition of the specified /// condition list, returning false on success and true if it cannot be /// reversed. @@ -501,19 +497,19 @@ public: bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { return true; } - + /// insertNoop - Insert a noop into the instruction stream at the specified /// point. - virtual void insertNoop(MachineBasicBlock &MBB, + virtual void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const; - - + + /// getNoopForMachoTarget - Return the noop instruction to use for a noop. virtual void getNoopForMachoTarget(MCInst &NopInst) const { // Default to just using 'nop' string. } - - + + /// isPredicated - Returns true if the instruction is already predicated. /// virtual bool isPredicated(const MachineInstr *MI) const { @@ -571,26 +567,98 @@ public: virtual unsigned getInlineAsmLength(const char *Str, const MCAsmInfo &MAI) const; - /// CreateTargetHazardRecognizer - Allocate and return a hazard recognizer - /// to use for this target when scheduling the machine instructions after + /// CreateTargetHazardRecognizer - Allocate and return a hazard recognizer to + /// use for this target when scheduling the machine instructions before /// register allocation. virtual ScheduleHazardRecognizer* - CreateTargetPostRAHazardRecognizer(const InstrItineraryData&) const = 0; + CreateTargetHazardRecognizer(const TargetMachine *TM, + const ScheduleDAG *DAG) const = 0; + + /// CreateTargetPostRAHazardRecognizer - Allocate and return a hazard + /// recognizer to use for this target when scheduling the machine instructions + /// after register allocation. + virtual ScheduleHazardRecognizer* + CreateTargetPostRAHazardRecognizer(const InstrItineraryData*, + const ScheduleDAG *DAG) const = 0; /// AnalyzeCompare - For a comparison instruction, return the source register /// in SrcReg and the value it compares against in CmpValue. Return true if /// the comparison instruction can be analyzed. virtual bool AnalyzeCompare(const MachineInstr *MI, - unsigned &SrcReg, int &CmpValue) const { + unsigned &SrcReg, int &Mask, int &Value) const { + return false; + } + + /// OptimizeCompareInstr - See if the comparison instruction can be converted + /// into something more efficient. E.g., on ARM most instructions can set the + /// flags register, obviating the need for a separate CMP. + virtual bool OptimizeCompareInstr(MachineInstr *CmpInstr, + unsigned SrcReg, int Mask, int Value, + const MachineRegisterInfo *MRI) const { return false; } - /// ConvertToSetZeroFlag - Convert the instruction to set the zero flag so - /// that we can remove a "comparison with zero". - virtual bool ConvertToSetZeroFlag(MachineInstr *Instr, - MachineInstr *CmpInstr) const { + /// FoldImmediate - 'Reg' is known to be defined by a move immediate + /// instruction, try to fold the immediate into the use instruction. + virtual bool FoldImmediate(MachineInstr *UseMI, MachineInstr *DefMI, + unsigned Reg, MachineRegisterInfo *MRI) const { return false; } + + /// getNumMicroOps - Return the number of u-operations the given machine + /// instruction will be decoded to on the target cpu. + virtual unsigned getNumMicroOps(const InstrItineraryData *ItinData, + const MachineInstr *MI) const; + + /// isZeroCost - Return true for pseudo instructions that don't consume any + /// machine resources in their current form. These are common cases that the + /// scheduler should consider free, rather than conservatively handling them + /// as instructions with no itinerary. + bool isZeroCost(unsigned Opcode) const { + return Opcode <= TargetOpcode::COPY; + } + + /// getOperandLatency - Compute and return the use operand latency of a given + /// pair of def and use. + /// In most cases, the static scheduling itinerary was enough to determine the + /// operand latency. But it may not be possible for instructions with variable + /// number of defs / uses. + virtual int getOperandLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx, + const MachineInstr *UseMI, unsigned UseIdx) const; + + virtual int getOperandLatency(const InstrItineraryData *ItinData, + SDNode *DefNode, unsigned DefIdx, + SDNode *UseNode, unsigned UseIdx) const; + + /// getInstrLatency - Compute the instruction latency of a given instruction. + /// If the instruction has higher cost when predicated, it's returned via + /// PredCost. + virtual int getInstrLatency(const InstrItineraryData *ItinData, + const MachineInstr *MI, + unsigned *PredCost = 0) const; + + virtual int getInstrLatency(const InstrItineraryData *ItinData, + SDNode *Node) const; + + /// hasHighOperandLatency - Compute operand latency between a def of 'Reg' + /// and an use in the current loop, return true if the target considered + /// it 'high'. This is used by optimization passes such as machine LICM to + /// determine whether it makes sense to hoist an instruction out even in + /// high register pressure situation. + virtual + bool hasHighOperandLatency(const InstrItineraryData *ItinData, + const MachineRegisterInfo *MRI, + const MachineInstr *DefMI, unsigned DefIdx, + const MachineInstr *UseMI, unsigned UseIdx) const { + return false; + } + + /// hasLowDefLatency - Compute operand latency of a def of 'Reg', return true + /// if the target considered it 'low'. + virtual + bool hasLowDefLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx) const; }; /// TargetInstrInfoImpl - This is the default implementation of @@ -620,13 +688,20 @@ public: virtual MachineInstr *duplicate(MachineInstr *Orig, MachineFunction &MF) const; virtual bool produceSameValue(const MachineInstr *MI0, - const MachineInstr *MI1) const; + const MachineInstr *MI1, + const MachineRegisterInfo *MRI) const; virtual bool isSchedulingBoundary(const MachineInstr *MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const; + bool usePreRAHazardRecognizer() const; + + virtual ScheduleHazardRecognizer * + CreateTargetHazardRecognizer(const TargetMachine*, const ScheduleDAG*) const; + virtual ScheduleHazardRecognizer * - CreateTargetPostRAHazardRecognizer(const InstrItineraryData&) const; + CreateTargetPostRAHazardRecognizer(const InstrItineraryData*, + const ScheduleDAG*) const; }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Target/TargetInstrItineraries.h b/contrib/llvm/include/llvm/Target/TargetInstrItineraries.h index 39648c2..a95b70f 100644 --- a/contrib/llvm/include/llvm/Target/TargetInstrItineraries.h +++ b/contrib/llvm/include/llvm/Target/TargetInstrItineraries.h @@ -95,6 +95,7 @@ struct InstrStage { /// operands are read and written. /// struct InstrItinerary { + unsigned NumMicroOps; ///< # of micro-ops, 0 means it's variable unsigned FirstStage; ///< Index of first stage in itinerary unsigned LastStage; ///< Index of last + 1 stage in itinerary unsigned FirstOperandCycle; ///< Index of first operand rd/wr @@ -110,38 +111,42 @@ class InstrItineraryData { public: const InstrStage *Stages; ///< Array of stages selected const unsigned *OperandCycles; ///< Array of operand cycles selected - const InstrItinerary *Itineratries; ///< Array of itineraries selected + const unsigned *Forwardings; ///< Array of pipeline forwarding pathes + const InstrItinerary *Itineraries; ///< Array of itineraries selected + unsigned IssueWidth; ///< Max issue per cycle. 0=Unknown. /// Ctors. /// - InstrItineraryData() : Stages(0), OperandCycles(0), Itineratries(0) {} + InstrItineraryData() : Stages(0), OperandCycles(0), Forwardings(0), + Itineraries(0), IssueWidth(0) {} + InstrItineraryData(const InstrStage *S, const unsigned *OS, - const InstrItinerary *I) - : Stages(S), OperandCycles(OS), Itineratries(I) {} - + const unsigned *F, const InstrItinerary *I) + : Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(I) {} + /// isEmpty - Returns true if there are no itineraries. /// - bool isEmpty() const { return Itineratries == 0; } + bool isEmpty() const { return Itineraries == 0; } /// isEndMarker - Returns true if the index is for the end marker /// itinerary. /// bool isEndMarker(unsigned ItinClassIndx) const { - return ((Itineratries[ItinClassIndx].FirstStage == ~0U) && - (Itineratries[ItinClassIndx].LastStage == ~0U)); + return ((Itineraries[ItinClassIndx].FirstStage == ~0U) && + (Itineraries[ItinClassIndx].LastStage == ~0U)); } /// beginStage - Return the first stage of the itinerary. - /// + /// const InstrStage *beginStage(unsigned ItinClassIndx) const { - unsigned StageIdx = Itineratries[ItinClassIndx].FirstStage; + unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; return Stages + StageIdx; } /// endStage - Return the last+1 stage of the itinerary. - /// + /// const InstrStage *endStage(unsigned ItinClassIndx) const { - unsigned StageIdx = Itineratries[ItinClassIndx].LastStage; + unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; return Stages + StageIdx; } @@ -173,13 +178,68 @@ public: if (isEmpty()) return -1; - unsigned FirstIdx = Itineratries[ItinClassIndx].FirstOperandCycle; - unsigned LastIdx = Itineratries[ItinClassIndx].LastOperandCycle; + unsigned FirstIdx = Itineraries[ItinClassIndx].FirstOperandCycle; + unsigned LastIdx = Itineraries[ItinClassIndx].LastOperandCycle; if ((FirstIdx + OperandIdx) >= LastIdx) return -1; return (int)OperandCycles[FirstIdx + OperandIdx]; } + + /// hasPipelineForwarding - Return true if there is a pipeline forwarding + /// between instructions of itinerary classes DefClass and UseClasses so that + /// value produced by an instruction of itinerary class DefClass, operand + /// index DefIdx can be bypassed when it's read by an instruction of + /// itinerary class UseClass, operand index UseIdx. + bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, + unsigned UseClass, unsigned UseIdx) const { + unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle; + unsigned LastDefIdx = Itineraries[DefClass].LastOperandCycle; + if ((FirstDefIdx + DefIdx) >= LastDefIdx) + return false; + if (Forwardings[FirstDefIdx + DefIdx] == 0) + return false; + + unsigned FirstUseIdx = Itineraries[UseClass].FirstOperandCycle; + unsigned LastUseIdx = Itineraries[UseClass].LastOperandCycle; + if ((FirstUseIdx + UseIdx) >= LastUseIdx) + return false; + + return Forwardings[FirstDefIdx + DefIdx] == + Forwardings[FirstUseIdx + UseIdx]; + } + + /// getOperandLatency - Compute and return the use operand latency of a given + /// itinerary class and operand index if the value is produced by an + /// instruction of the specified itinerary class and def operand index. + int getOperandLatency(unsigned DefClass, unsigned DefIdx, + unsigned UseClass, unsigned UseIdx) const { + if (isEmpty()) + return -1; + + int DefCycle = getOperandCycle(DefClass, DefIdx); + if (DefCycle == -1) + return -1; + + int UseCycle = getOperandCycle(UseClass, UseIdx); + if (UseCycle == -1) + return -1; + + UseCycle = DefCycle - UseCycle + 1; + if (UseCycle > 0 && + hasPipelineForwarding(DefClass, DefIdx, UseClass, UseIdx)) + // FIXME: This assumes one cycle benefit for every pipeline forwarding. + --UseCycle; + return UseCycle; + } + + /// isMicroCoded - Return true if the instructions in the given class decode + /// to more than one micro-ops. + bool isMicroCoded(unsigned ItinClassIndx) const { + if (isEmpty()) + return false; + return Itineraries[ItinClassIndx].NumMicroOps != 1; + } }; diff --git a/contrib/llvm/include/llvm/Target/TargetJITInfo.h b/contrib/llvm/include/llvm/Target/TargetJITInfo.h index 7208a8d..b198eb6 100644 --- a/contrib/llvm/include/llvm/Target/TargetJITInfo.h +++ b/contrib/llvm/include/llvm/Target/TargetJITInfo.h @@ -19,7 +19,7 @@ #include <cassert> #include "llvm/Support/ErrorHandling.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class Function; diff --git a/contrib/llvm/include/llvm/Target/TargetLibraryInfo.h b/contrib/llvm/include/llvm/Target/TargetLibraryInfo.h new file mode 100644 index 0000000..bdd214b --- /dev/null +++ b/contrib/llvm/include/llvm/Target/TargetLibraryInfo.h @@ -0,0 +1,66 @@ +//===-- llvm/Target/TargetLibraryInfo.h - Library information ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETLIBRARYINFO_H +#define LLVM_TARGET_TARGETLIBRARYINFO_H + +#include "llvm/Pass.h" + +namespace llvm { + class Triple; + + namespace LibFunc { + enum Func { + /// void *memset(void *b, int c, size_t len); + memset, + + // void *memcpy(void *s1, const void *s2, size_t n); + memcpy, + + /// void memset_pattern16(void *b, const void *pattern16, size_t len); + memset_pattern16, + + NumLibFuncs + }; + } + +/// TargetLibraryInfo - This immutable pass captures information about what +/// library functions are available for the current target, and allows a +/// frontend to disable optimizations through -fno-builtin etc. +class TargetLibraryInfo : public ImmutablePass { + unsigned char AvailableArray[(LibFunc::NumLibFuncs+7)/8]; +public: + static char ID; + TargetLibraryInfo(); + TargetLibraryInfo(const Triple &T); + + /// has - This function is used by optimizations that want to match on or form + /// a given library function. + bool has(LibFunc::Func F) const { + return (AvailableArray[F/8] & (1 << (F&7))) != 0; + } + + /// setUnavailable - this can be used by whatever sets up TargetLibraryInfo to + /// ban use of specific library functions. + void setUnavailable(LibFunc::Func F) { + AvailableArray[F/8] &= ~(1 << (F&7)); + } + + void setAvailable(LibFunc::Func F) { + AvailableArray[F/8] |= 1 << (F&7); + } + + /// disableAllFunctions - This disables all builtins, which is used for + /// options like -fno-builtin. + void disableAllFunctions(); +}; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Target/TargetLowering.h b/contrib/llvm/include/llvm/Target/TargetLowering.h index 29de994..5141b7b 100644 --- a/contrib/llvm/include/llvm/Target/TargetLowering.h +++ b/contrib/llvm/include/llvm/Target/TargetLowering.h @@ -25,13 +25,9 @@ #include "llvm/CallingConv.h" #include "llvm/InlineAsm.h" #include "llvm/Attributes.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/RuntimeLibcalls.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/Support/DebugLoc.h" #include "llvm/Target/TargetCallingConv.h" #include "llvm/Target/TargetMachine.h" @@ -41,10 +37,12 @@ namespace llvm { class AllocaInst; + class APFloat; class CallInst; class Function; class FastISel; class FunctionLoweringInfo; + class ImmutableCallSite; class MachineBasicBlock; class MachineFunction; class MachineFrameInfo; @@ -55,6 +53,7 @@ namespace llvm { class SDNode; class SDValue; class SelectionDAG; + template<typename T> class SmallVectorImpl; class TargetData; class TargetMachine; class TargetRegisterClass; @@ -126,6 +125,10 @@ public: /// srl/add/sra. bool isPow2DivCheap() const { return Pow2DivIsCheap; } + /// isJumpExpensive() - Return true if Flow Control is an expensive operation + /// that should be avoided. + bool isJumpExpensive() const { return JumpIsExpensive; } + /// getSetCCResultType - Return the ValueType of the result of SETCC /// operations. Also used to obtain the target's preferred type for /// the condition operand of SELECT and BRCOND nodes. In the case of @@ -203,13 +206,6 @@ public: return VT.isSimple() && RegClassForVT[VT.getSimpleVT().SimpleTy] != 0; } - /// isTypeSynthesizable - Return true if it's OK for the compiler to create - /// new operations of this type. All Legal types are synthesizable except - /// MMX vector types on X86. Non-Legal types are not synthesizable. - bool isTypeSynthesizable(EVT VT) const { - return isTypeLegal(VT) && Synthesizable[VT.getSimpleVT().SimpleTy]; - } - class ValueTypeActionImpl { /// ValueTypeActions - For each value type, keep a LegalizeAction enum /// that indicates how instruction selection should deal with the type. @@ -441,7 +437,7 @@ public: /// for it. LegalizeAction getLoadExtAction(unsigned ExtType, EVT VT) const { assert(ExtType < ISD::LAST_LOADEXT_TYPE && - (unsigned)VT.getSimpleVT().SimpleTy < MVT::LAST_VALUETYPE && + VT.getSimpleVT() < MVT::LAST_VALUETYPE && "Table isn't big enough!"); return (LegalizeAction)LoadExtActions[VT.getSimpleVT().SimpleTy][ExtType]; } @@ -459,8 +455,8 @@ public: /// to be expanded to some other code sequence, or the target has a custom /// expander for it. LegalizeAction getTruncStoreAction(EVT ValVT, EVT MemVT) const { - assert((unsigned)ValVT.getSimpleVT().SimpleTy < MVT::LAST_VALUETYPE && - (unsigned)MemVT.getSimpleVT().SimpleTy < MVT::LAST_VALUETYPE && + assert(ValVT.getSimpleVT() < MVT::LAST_VALUETYPE && + MemVT.getSimpleVT() < MVT::LAST_VALUETYPE && "Table isn't big enough!"); return (LegalizeAction)TruncStoreActions[ValVT.getSimpleVT().SimpleTy] [MemVT.getSimpleVT().SimpleTy]; @@ -480,8 +476,8 @@ public: /// for it. LegalizeAction getIndexedLoadAction(unsigned IdxMode, EVT VT) const { - assert( IdxMode < ISD::LAST_INDEXED_MODE && - ((unsigned)VT.getSimpleVT().SimpleTy) < MVT::LAST_VALUETYPE && + assert(IdxMode < ISD::LAST_INDEXED_MODE && + VT.getSimpleVT() < MVT::LAST_VALUETYPE && "Table isn't big enough!"); unsigned Ty = (unsigned)VT.getSimpleVT().SimpleTy; return (LegalizeAction)((IndexedModeActions[Ty][IdxMode] & 0xf0) >> 4); @@ -501,8 +497,8 @@ public: /// for it. LegalizeAction getIndexedStoreAction(unsigned IdxMode, EVT VT) const { - assert( IdxMode < ISD::LAST_INDEXED_MODE && - ((unsigned)VT.getSimpleVT().SimpleTy) < MVT::LAST_VALUETYPE && + assert(IdxMode < ISD::LAST_INDEXED_MODE && + VT.getSimpleVT() < MVT::LAST_VALUETYPE && "Table isn't big enough!"); unsigned Ty = (unsigned)VT.getSimpleVT().SimpleTy; return (LegalizeAction)(IndexedModeActions[Ty][IdxMode] & 0x0f); @@ -646,21 +642,30 @@ public: /// This function returns the maximum number of store operations permitted /// to replace a call to llvm.memset. The value is set by the target at the - /// performance threshold for such a replacement. + /// performance threshold for such a replacement. If OptSize is true, + /// return the limit for functions that have OptSize attribute. /// @brief Get maximum # of store operations permitted for llvm.memset - unsigned getMaxStoresPerMemset() const { return maxStoresPerMemset; } + unsigned getMaxStoresPerMemset(bool OptSize) const { + return OptSize ? maxStoresPerMemsetOptSize : maxStoresPerMemset; + } /// This function returns the maximum number of store operations permitted /// to replace a call to llvm.memcpy. The value is set by the target at the - /// performance threshold for such a replacement. + /// performance threshold for such a replacement. If OptSize is true, + /// return the limit for functions that have OptSize attribute. /// @brief Get maximum # of store operations permitted for llvm.memcpy - unsigned getMaxStoresPerMemcpy() const { return maxStoresPerMemcpy; } + unsigned getMaxStoresPerMemcpy(bool OptSize) const { + return OptSize ? maxStoresPerMemcpyOptSize : maxStoresPerMemcpy; + } /// This function returns the maximum number of store operations permitted /// to replace a call to llvm.memmove. The value is set by the target at the - /// performance threshold for such a replacement. + /// performance threshold for such a replacement. If OptSize is true, + /// return the limit for functions that have OptSize attribute. /// @brief Get maximum # of store operations permitted for llvm.memmove - unsigned getMaxStoresPerMemmove() const { return maxStoresPerMemmove; } + unsigned getMaxStoresPerMemmove(bool OptSize) const { + return OptSize ? maxStoresPerMemmoveOptSize : maxStoresPerMemmove; + } /// This function returns true if the target allows unaligned memory accesses. /// of the specified type. This is used, for example, in situations where an @@ -958,6 +963,13 @@ public: return isTypeLegal(VT); } + /// isDesirableToPromoteOp - Return true if it is profitable for dag combiner + /// to transform a floating point op of specified opcode to a equivalent op of + /// an integer type. e.g. f32 load -> i32 load can be profitable on ARM. + virtual bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const { + return false; + } + /// IsDesirableToPromoteOp - This method query the target whether it is /// beneficial for dag combiner to promote the specified node. If true, it /// should return the desired promotion type by reference. @@ -1021,7 +1033,16 @@ protected: /// SelectIsExpensive - Tells the code generator not to expand operations /// into sequences that use the select operations if possible. - void setSelectIsExpensive() { SelectIsExpensive = true; } + void setSelectIsExpensive(bool isExpensive = true) { + SelectIsExpensive = isExpensive; + } + + /// JumpIsExpensive - Tells the code generator not to expand sequence of + /// operations into a seperate sequences that increases the amount of + /// flow control. + void setJumpIsExpensive(bool isExpensive = true) { + JumpIsExpensive = isExpensive; + } /// setIntDivIsCheap - Tells the code generator that integer divide is /// expensive, and if possible, should be replaced by an alternate sequence @@ -1036,12 +1057,10 @@ protected: /// addRegisterClass - Add the specified register class as an available /// regclass for the specified value type. This indicates the selector can /// handle values of that class natively. - void addRegisterClass(EVT VT, TargetRegisterClass *RC, - bool isSynthesizable = true) { + void addRegisterClass(EVT VT, TargetRegisterClass *RC) { assert((unsigned)VT.getSimpleVT().SimpleTy < array_lengthof(RegClassForVT)); AvailableRegClasses.push_back(std::make_pair(VT, RC)); RegClassForVT[VT.getSimpleVT().SimpleTy] = RC; - Synthesizable[VT.getSimpleVT().SimpleTy] = isSynthesizable; } /// findRepresentativeClass - Return the largest legal super-reg register class @@ -1065,8 +1084,7 @@ protected: /// not work with the specified type and indicate what to do about it. void setLoadExtAction(unsigned ExtType, MVT VT, LegalizeAction Action) { - assert(ExtType < ISD::LAST_LOADEXT_TYPE && - (unsigned)VT.SimpleTy < MVT::LAST_VALUETYPE && + assert(ExtType < ISD::LAST_LOADEXT_TYPE && VT < MVT::LAST_VALUETYPE && "Table isn't big enough!"); LoadExtActions[VT.SimpleTy][ExtType] = (uint8_t)Action; } @@ -1075,8 +1093,7 @@ protected: /// not work with the specified type and indicate what to do about it. void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action) { - assert((unsigned)ValVT.SimpleTy < MVT::LAST_VALUETYPE && - (unsigned)MemVT.SimpleTy < MVT::LAST_VALUETYPE && + assert(ValVT < MVT::LAST_VALUETYPE && MemVT < MVT::LAST_VALUETYPE && "Table isn't big enough!"); TruncStoreActions[ValVT.SimpleTy][MemVT.SimpleTy] = (uint8_t)Action; } @@ -1087,10 +1104,8 @@ protected: /// TargetLowering.cpp void setIndexedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action) { - assert((unsigned)VT.SimpleTy < MVT::LAST_VALUETYPE && - IdxMode < ISD::LAST_INDEXED_MODE && - (unsigned)Action < 0xf && - "Table isn't big enough!"); + assert(VT < MVT::LAST_VALUETYPE && IdxMode < ISD::LAST_INDEXED_MODE && + (unsigned)Action < 0xf && "Table isn't big enough!"); // Load action are kept in the upper half. IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] &= ~0xf0; IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] |= ((uint8_t)Action) <<4; @@ -1102,10 +1117,8 @@ protected: /// TargetLowering.cpp void setIndexedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action) { - assert((unsigned)VT.SimpleTy < MVT::LAST_VALUETYPE && - IdxMode < ISD::LAST_INDEXED_MODE && - (unsigned)Action < 0xf && - "Table isn't big enough!"); + assert(VT < MVT::LAST_VALUETYPE && IdxMode < ISD::LAST_INDEXED_MODE && + (unsigned)Action < 0xf && "Table isn't big enough!"); // Store action are kept in the lower half. IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] &= ~0x0f; IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] |= ((uint8_t)Action); @@ -1115,7 +1128,7 @@ protected: /// supported on the target and indicate what to do about it. void setCondCodeAction(ISD::CondCode CC, MVT VT, LegalizeAction Action) { - assert((unsigned)VT.SimpleTy < MVT::LAST_VALUETYPE && + assert(VT < MVT::LAST_VALUETYPE && (unsigned)CC < array_lengthof(CondCodeActions) && "Table isn't big enough!"); CondCodeActions[(unsigned)CC] &= ~(uint64_t(3UL) << VT.SimpleTy*2); @@ -1261,6 +1274,13 @@ public: return SDValue(); // this is here to silence compiler errors } + /// isUsedByReturnOnly - Return true if result of the specified node is used + /// by a return node only. This is used to determine whether it is possible + /// to codegen a libcall as tail call at legalization time. + virtual bool isUsedByReturnOnly(SDNode *N) const { + return false; + } + /// LowerOperationWrapper - This callback is invoked by the type legalizer /// to legalize nodes with an illegal operand type but legal result types. /// It replaces the LowerOperation callback in the type Legalizer. @@ -1328,6 +1348,22 @@ public: 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 { @@ -1356,12 +1392,41 @@ public: /// 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 @@ -1568,6 +1633,11 @@ private: /// it. bool Pow2DivIsCheap; + /// JumpIsExpensive - Tells the code generator that it shouldn't generate + /// extra flow control instructions and should attempt to combine flow + /// control instructions via predication. + bool JumpIsExpensive; + /// UseUnderscoreSetJmp - This target prefers to use _setjmp to implement /// llvm.setjmp. Defaults to false. bool UseUnderscoreSetJmp; @@ -1643,11 +1713,6 @@ private: /// approximate register pressure. uint8_t RepRegClassCostForVT[MVT::LAST_VALUETYPE]; - /// Synthesizable indicates whether it is OK for the compiler to create new - /// operations using this type. All Legal types are Synthesizable except - /// MMX types on X86. Non-Legal types are not Synthesizable. - bool Synthesizable[MVT::LAST_VALUETYPE]; - /// TransformToType - For any value types we are promoting or expanding, this /// contains the value type that we are changing to. For Expanded types, this /// contains one step of the expand (e.g. i64 -> i32), even if there are @@ -1727,6 +1792,10 @@ protected: /// @brief Specify maximum number of store instructions per memset call. unsigned maxStoresPerMemset; + /// Maximum number of stores operations that may be substituted for the call + /// to memset, used for functions with OptSize attribute. + unsigned maxStoresPerMemsetOptSize; + /// When lowering \@llvm.memcpy this field specifies the maximum number of /// store operations that may be substituted for a call to memcpy. Targets /// must set this value based on the cost threshold for that target. Targets @@ -1739,6 +1808,10 @@ protected: /// @brief Specify maximum bytes of store instructions per memcpy call. unsigned maxStoresPerMemcpy; + /// Maximum number of store operations that may be substituted for a call + /// to memcpy, used for functions with OptSize attribute. + unsigned maxStoresPerMemcpyOptSize; + /// When lowering \@llvm.memmove this field specifies the maximum number of /// store instructions that may be substituted for a call to memmove. Targets /// must set this value based on the cost threshold for that target. Targets @@ -1750,6 +1823,10 @@ protected: /// @brief Specify maximum bytes of store instructions per memmove call. unsigned maxStoresPerMemmove; + /// Maximum number of store instructions that may be substituted for a call + /// to memmove, used for functions with OpSize attribute. + unsigned maxStoresPerMemmoveOptSize; + /// This field specifies whether the target can benefit from code placement /// optimization. bool benefitFromCodePlacementOpt; diff --git a/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h index 819709f..34bf271 100644 --- a/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h +++ b/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h @@ -69,10 +69,6 @@ protected: /// the section the Language Specific Data Area information is emitted to. const MCSection *LSDASection; - /// EHFrameSection - If exception handling is supported by the target, this is - /// the section the EH Frame is emitted to. - const MCSection *EHFrameSection; - // Dwarf sections for debug info. If a target supports debug info, these must // be set. const MCSection *DwarfAbbrevSection; @@ -92,6 +88,11 @@ protected: // information for a TLS variable, it'll go here. const MCSection *TLSExtraDataSection; + /// CommDirectiveSupportsAlignment - True if .comm supports alignment. This + /// is a hack for as long as we support 10.4 Tiger, whose assembler doesn't + /// support alignment on comm. + bool CommDirectiveSupportsAlignment; + /// SupportsWeakEmptyEHFrame - True if target object file supports a /// weak_definition of constant 0 for an omitted EH frame. bool SupportsWeakOmittedEHFrame; @@ -128,13 +129,17 @@ public: return SupportsWeakOmittedEHFrame; } + bool getCommDirectiveSupportsAlignment() const { + return CommDirectiveSupportsAlignment; + } + const MCSection *getTextSection() const { return TextSection; } const MCSection *getDataSection() const { return DataSection; } const MCSection *getBSSSection() const { return BSSSection; } const MCSection *getStaticCtorSection() const { return StaticCtorSection; } const MCSection *getStaticDtorSection() const { return StaticDtorSection; } const MCSection *getLSDASection() const { return LSDASection; } - const MCSection *getEHFrameSection() const { return EHFrameSection; } + virtual const MCSection *getEHFrameSection() const = 0; const MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } const MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } const MCSection *getDwarfLineSection() const { return DwarfLineSection; } diff --git a/contrib/llvm/include/llvm/Target/TargetMachine.h b/contrib/llvm/include/llvm/Target/TargetMachine.h index 42e99e0..030bf5b 100644 --- a/contrib/llvm/include/llvm/Target/TargetMachine.h +++ b/contrib/llvm/include/llvm/Target/TargetMachine.h @@ -29,7 +29,7 @@ class TargetIntrinsicInfo; class TargetJITInfo; class TargetLowering; class TargetSelectionDAGInfo; -class TargetFrameInfo; +class TargetFrameLowering; class JITCodeEmitter; class MCContext; class TargetRegisterInfo; @@ -98,12 +98,14 @@ protected: // Can only create subclasses. /// TheTarget - The Target that this machine was created for. const Target &TheTarget; - + /// AsmInfo - Contains target specific asm information. /// const MCAsmInfo *AsmInfo; unsigned MCRelaxAll : 1; + unsigned MCNoExecStack : 1; + unsigned MCUseLoc : 1; public: virtual ~TargetMachine(); @@ -116,16 +118,16 @@ public: // -- Stack frame information // -- Selection DAG lowering information // - virtual const TargetInstrInfo *getInstrInfo() const { return 0; } - virtual const TargetFrameInfo *getFrameInfo() const { return 0; } + virtual const TargetInstrInfo *getInstrInfo() const { return 0; } + virtual const TargetFrameLowering *getFrameLowering() const { return 0; } virtual const TargetLowering *getTargetLowering() const { return 0; } virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const{ return 0; } - virtual const TargetData *getTargetData() const { return 0; } - + virtual const TargetData *getTargetData() const { return 0; } + /// getMCAsmInfo - Return target specific asm information. /// const MCAsmInfo *getMCAsmInfo() const { return AsmInfo; } - + /// getSubtarget - This method returns a pointer to the specified type of /// TargetSubtarget. In debug builds, it verifies that the object being /// returned is of the correct type. @@ -138,7 +140,7 @@ public: /// details of graph coloring register allocation removed from it. /// virtual const TargetRegisterInfo *getRegisterInfo() const { return 0; } - + /// getIntrinsicInfo - If intrinsic information is available, return it. If /// not, return null. /// @@ -148,17 +150,17 @@ public: /// otherwise return null. /// virtual TargetJITInfo *getJITInfo() { return 0; } - + /// getInstrItineraryData - Returns instruction itinerary data for the target /// or specific subtarget. /// - virtual const InstrItineraryData getInstrItineraryData() const { - return InstrItineraryData(); + virtual const InstrItineraryData *getInstrItineraryData() const { + return 0; } /// getELFWriterInfo - If this target supports an ELF writer, return /// information for it, otherwise return null. - /// + /// virtual const TargetELFWriterInfo *getELFWriterInfo() const { return 0; } /// hasMCRelaxAll - Check whether all machine code instructions should be @@ -169,6 +171,18 @@ public: /// relaxed. void setMCRelaxAll(bool Value) { MCRelaxAll = Value; } + /// hasMCNoExecStack - Check whether an executable stack is not needed. + bool hasMCNoExecStack() const { return MCNoExecStack; } + + /// setMCNoExecStack - Set whether an executabel stack is not needed. + void setMCNoExecStack(bool Value) { MCNoExecStack = Value; } + + /// hasMCUseLoc - Check whether we should use dwarf's .loc directive. + bool hasMCUseLoc() const { return MCUseLoc; } + + /// setMCUseLoc - Set whether all we should use dwarf's .loc directive. + void setMCUseLoc(bool Value) { MCUseLoc = Value; } + /// getRelocationModel - Returns the code generation relocation model. The /// choices are static, PIC, and dynamic-no-pic, and target default. static Reloc::Model getRelocationModel(); @@ -267,7 +281,7 @@ class LLVMTargetMachine : public TargetMachine { protected: // Can only create subclasses. LLVMTargetMachine(const Target &T, const std::string &TargetTriple); - + private: /// addCommonCodeGenPasses - Add standard LLVM codegen passes used for /// both emitting to assembly files or machine code output. @@ -277,9 +291,11 @@ private: virtual void setCodeModelForJIT(); virtual void setCodeModelForStatic(); - + public: - + + const std::string &getTargetTriple() const { return TargetTriple; } + /// addPassesToEmitFile - Add passes to the specified pass manager to get the /// specified file emitted. Typically this will involve several steps of code /// generation. If OptLevel is None, the code generator should emit code as @@ -289,7 +305,7 @@ public: CodeGenFileType FileType, CodeGenOpt::Level, bool DisableVerify = true); - + /// addPassesToEmitMachineCode - Add passes to the specified pass manager to /// get machine code emitted. This uses a JITCodeEmitter object to handle /// actually outputting the machine code and resolving things like the address @@ -310,7 +326,7 @@ public: MCContext *&Ctx, CodeGenOpt::Level OptLevel, bool DisableVerify = true); - + /// Target-Independent Code Generator Pass Configuration Options. /// addPreISelPasses - This method should add any "last minute" LLVM->LLVM @@ -347,15 +363,15 @@ public: virtual bool addPreSched2(PassManagerBase &, CodeGenOpt::Level) { return false; } - + /// addPreEmitPass - This pass may be implemented by targets that want to run /// passes immediately before machine code is emitted. This should return /// true if -print-machineinstrs should print out the code after the passes. virtual bool addPreEmitPass(PassManagerBase &, CodeGenOpt::Level) { return false; } - - + + /// addCodeEmitter - This pass should be overridden by the target to add a /// code emitter, if supported. If this is not supported, 'true' should be /// returned. diff --git a/contrib/llvm/include/llvm/Target/TargetRegisterInfo.h b/contrib/llvm/include/llvm/Target/TargetRegisterInfo.h index 81dec3e..121091c 100644 --- a/contrib/llvm/include/llvm/Target/TargetRegisterInfo.h +++ b/contrib/llvm/include/llvm/Target/TargetRegisterInfo.h @@ -29,21 +29,21 @@ class MachineFunction; class MachineMove; class RegScavenger; template<class T> class SmallVectorImpl; +class raw_ostream; /// TargetRegisterDesc - This record contains all of the information known about -/// a particular register. The AliasSet field (if not null) contains a pointer -/// to a Zero terminated array of registers that this register aliases. This is -/// needed for architectures like X86 which have AL alias AX alias EAX. -/// Registers that this does not apply to simply should set this to null. -/// The SubRegs field is a zero terminated array of registers that are -/// sub-registers of the specific register, e.g. AL, AH are sub-registers of AX. -/// The SuperRegs field is a zero terminated array of registers that are +/// a particular register. The Overlaps field contains a pointer to a zero +/// terminated array of registers that this register aliases, starting with +/// itself. This is needed for architectures like X86 which have AL alias AX +/// alias EAX. The SubRegs field is a zero terminated array of registers that +/// are sub-registers of the specific register, e.g. AL, AH are sub-registers of +/// AX. The SuperRegs field is a zero terminated array of registers that are /// super-registers of the specific register, e.g. RAX, EAX, are super-registers /// of AX. /// struct TargetRegisterDesc { const char *Name; // Printable name for the reg (for debugging) - const unsigned *AliasSet; // Register Alias Set, described above + const unsigned *Overlaps; // Overlapping registers, described above const unsigned *SubRegs; // Sub-register set, described above const unsigned *SuperRegs; // Super-register set, described above }; @@ -123,7 +123,7 @@ public: /// hasType - return true if this TargetRegisterClass has the ValueType vt. /// bool hasType(EVT vt) const { - for(int i = 0; VTs[i].getSimpleVT().SimpleTy != MVT::Other; ++i) + for(int i = 0; VTs[i] != MVT::Other; ++i) if (VTs[i] == vt) return true; return false; @@ -137,7 +137,7 @@ public: vt_iterator vt_end() const { vt_iterator I = VTs; - while (I->getSimpleVT().SimpleTy != MVT::Other) ++I; + while (*I != MVT::Other) ++I; return I; } @@ -227,9 +227,12 @@ public: /// cheaper to allocate caller saved registers. /// /// These methods take a MachineFunction argument, which can be used to tune - /// the allocatable registers based on the characteristics of the function. - /// One simple example is that the frame pointer register can be used if - /// frame-pointer-elimination is performed. + /// the allocatable registers based on the characteristics of the function, + /// subtarget, or other criteria. + /// + /// Register allocators should account for the fact that an allocation + /// order iterator may return a reserved register and always check + /// if the register is allocatable (getAllocatableSet()) before using it. /// /// By default, these methods return all registers in the class. /// @@ -292,30 +295,68 @@ protected: virtual ~TargetRegisterInfo(); public: - enum { // Define some target independent constants - /// NoRegister - This physical register is not a real target register. It - /// is useful as a sentinal. - NoRegister = 0, + // Register numbers can represent physical registers, virtual registers, and + // sometimes stack slots. The unsigned values are divided into these ranges: + // + // 0 Not a register, can be used as a sentinel. + // [1;2^30) Physical registers assigned by TableGen. + // [2^30;2^31) Stack slots. (Rarely used.) + // [2^31;2^32) Virtual registers assigned by MachineRegisterInfo. + // + // Further sentinels can be allocated from the small negative integers. + // DenseMapInfo<unsigned> uses -1u and -2u. - /// FirstVirtualRegister - This is the first register number that is - /// considered to be a 'virtual' register, which is part of the SSA - /// namespace. This must be the same for all targets, which means that each - /// target is limited to this fixed number of registers. - FirstVirtualRegister = 16384 - }; + /// isStackSlot - Sometimes it is useful the be able to store a non-negative + /// frame index in a variable that normally holds a register. isStackSlot() + /// returns true if Reg is in the range used for stack slots. + /// + /// Note that isVirtualRegister() and isPhysicalRegister() cannot handle stack + /// slots, so if a variable may contains a stack slot, always check + /// isStackSlot() first. + /// + static bool isStackSlot(unsigned Reg) { + return int(Reg) >= (1 << 30); + } + + /// stackSlot2Index - Compute the frame index from a register value + /// representing a stack slot. + static int stackSlot2Index(unsigned Reg) { + assert(isStackSlot(Reg) && "Not a stack slot"); + return int(Reg - (1u << 30)); + } + + /// index2StackSlot - Convert a non-negative frame index to a stack slot + /// register value. + static unsigned index2StackSlot(int FI) { + assert(FI >= 0 && "Cannot hold a negative frame index."); + return FI + (1u << 30); + } /// isPhysicalRegister - Return true if the specified register number is in /// the physical register namespace. static bool isPhysicalRegister(unsigned Reg) { - assert(Reg && "this is not a register!"); - return Reg < FirstVirtualRegister; + assert(!isStackSlot(Reg) && "Not a register! Check isStackSlot() first."); + return int(Reg) > 0; } /// isVirtualRegister - Return true if the specified register number is in /// the virtual register namespace. static bool isVirtualRegister(unsigned Reg) { - assert(Reg && "this is not a register!"); - return Reg >= FirstVirtualRegister; + assert(!isStackSlot(Reg) && "Not a register! Check isStackSlot() first."); + return int(Reg) < 0; + } + + /// virtReg2Index - Convert a virtual register number to a 0-based index. + /// The first virtual register in a function will get the index 0. + static unsigned virtReg2Index(unsigned Reg) { + assert(isVirtualRegister(Reg) && "Not a virtual register"); + return Reg - (1u << 31); + } + + /// index2VirtReg - Convert a 0-based index to a virtual register number. + /// This is the inverse operation of VirtReg2IndexFunctor below. + static unsigned index2VirtReg(unsigned Index) { + return Index + (1u << 31); } /// getMinimalPhysRegClass - Returns the Register Class of a physical @@ -348,7 +389,17 @@ public: /// terminated. /// const unsigned *getAliasSet(unsigned RegNo) const { - return get(RegNo).AliasSet; + // The Overlaps set always begins with Reg itself. + return get(RegNo).Overlaps + 1; + } + + /// getOverlaps - Return a list of registers that overlap Reg, including + /// itself. This is the same as the alias set except Reg is included in the + /// list. + /// These are exactly the registers in { x | regsOverlap(x, Reg) }. + /// + const unsigned *getOverlaps(unsigned RegNo) const { + return get(RegNo).Overlaps; } /// getSubRegisters - Return the list of registers that are sub-registers of @@ -574,13 +625,6 @@ public: // Do nothing. } - /// targetHandlesStackFrameRounding - Returns true if the target is - /// responsible for rounding up the stack frame (probably at emitPrologue - /// time). - virtual bool targetHandlesStackFrameRounding() const { - return false; - } - /// requiresRegisterScavenging - returns true if the target requires (and can /// make use of) the register scavenger. virtual bool requiresRegisterScavenging(const MachineFunction &MF) const { @@ -600,31 +644,6 @@ public: return false; } - /// hasFP - Return true if the specified function should have a dedicated - /// frame pointer register. For most targets this is true only if the function - /// has variable sized allocas or if frame pointer elimination is disabled. - virtual bool hasFP(const MachineFunction &MF) const = 0; - - /// hasReservedCallFrame - Under normal circumstances, when a frame pointer is - /// not required, we reserve argument space for call sites in the function - /// immediately on entry to the current function. This eliminates the need for - /// add/sub sp brackets around call sites. Returns true if the call frame is - /// included as part of the stack frame. - virtual bool hasReservedCallFrame(const MachineFunction &MF) const { - return !hasFP(MF); - } - - /// canSimplifyCallFramePseudos - When possible, it's best to simplify the - /// call frame pseudo ops before doing frame index elimination. This is - /// possible only when frame index references between the pseudos won't - /// need adjusting for the call frame adjustments. Normally, that's true - /// if the function has a reserved call frame or a frame pointer. Some - /// targets (Thumb2, for example) may have more complicated criteria, - /// however, and can override this behavior. - virtual bool canSimplifyCallFramePseudos(const MachineFunction &MF) const { - return hasReservedCallFrame(MF) || hasFP(MF); - } - /// hasReservedSpillSlot - Return true if target has reserved a spill slot in /// the stack frame of the given function for the specified register. e.g. On /// x86, if the frame register is required, the first fixed stack object is @@ -644,7 +663,7 @@ public: } /// getFrameIndexInstrOffset - Get the offset from the referenced frame - /// index in the instruction, if the is one. + /// index in the instruction, if there is one. virtual int64_t getFrameIndexInstrOffset(const MachineInstr *MI, int Idx) const { return 0; @@ -660,7 +679,7 @@ public: /// materializeFrameBaseRegister - Insert defining instruction(s) for /// BaseReg to be a pointer to FrameIdx before insertion point I. - virtual void materializeFrameBaseRegister(MachineBasicBlock::iterator I, + virtual void materializeFrameBaseRegister(MachineBasicBlock *MBB, unsigned BaseReg, int FrameIdx, int64_t Offset) const { assert(0 && "materializeFrameBaseRegister does not exist on this target"); @@ -707,21 +726,6 @@ public: assert(0 && "Call Frame Pseudo Instructions do not exist on this target!"); } - /// processFunctionBeforeCalleeSavedScan - This method is called immediately - /// before PrologEpilogInserter scans the physical registers used to determine - /// what callee saved registers should be spilled. This method is optional. - virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, - RegScavenger *RS = NULL) const { - - } - - /// processFunctionBeforeFrameFinalized - This method is called immediately - /// before the specified function's frame layout (MF.getFrameInfo()) is - /// finalized. Once the frame is finalized, MO_FrameIndex operands are - /// replaced with direct constants. This method is optional. - /// - virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const { - } /// saveScavengerRegister - Spill the register so it can be used by the /// register scavenger. Return true if the register was spilled, false @@ -746,12 +750,6 @@ public: virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, RegScavenger *RS=NULL) const = 0; - /// emitProlog/emitEpilog - These methods insert prolog and epilog code into - /// the function. - virtual void emitPrologue(MachineFunction &MF) const = 0; - virtual void emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const = 0; - //===--------------------------------------------------------------------===// /// Debug information queries. @@ -765,37 +763,16 @@ public: /// for values allocated in the current stack frame. virtual unsigned getFrameRegister(const MachineFunction &MF) const = 0; - /// getFrameIndexOffset - Returns the displacement from the frame register to - /// the stack frame of the specified index. - virtual int getFrameIndexOffset(const MachineFunction &MF, int FI) const; - - /// getFrameIndexReference - This method should return the base register - /// and offset used to reference a frame index location. The offset is - /// returned directly, and the base register is returned via FrameReg. - virtual int getFrameIndexReference(const MachineFunction &MF, int FI, - unsigned &FrameReg) const { - // By default, assume all frame indices are referenced via whatever - // getFrameRegister() says. The target can override this if it's doing - // something different. - FrameReg = getFrameRegister(MF); - return getFrameIndexOffset(MF, FI); - } - /// getRARegister - This method should return the register where the return /// address can be found. virtual unsigned getRARegister() const = 0; - - /// getInitialFrameState - Returns a list of machine moves that are assumed - /// on entry to all functions. Note that LabelID is ignored (assumed to be - /// the beginning of the function.) - virtual void getInitialFrameState(std::vector<MachineMove> &Moves) const; }; // This is useful when building IndexedMaps keyed on virtual registers struct VirtReg2IndexFunctor : public std::unary_function<unsigned, unsigned> { unsigned operator()(unsigned Reg) const { - return Reg - TargetRegisterInfo::FirstVirtualRegister; + return TargetRegisterInfo::virtReg2Index(Reg); } }; @@ -804,6 +781,33 @@ struct VirtReg2IndexFunctor : public std::unary_function<unsigned, unsigned> { const TargetRegisterClass *getCommonSubClass(const TargetRegisterClass *A, const TargetRegisterClass *B); +/// PrintReg - Helper class for printing registers on a raw_ostream. +/// Prints virtual and physical registers with or without a TRI instance. +/// +/// The format is: +/// %noreg - NoRegister +/// %vreg5 - a virtual register. +/// %vreg5:sub_8bit - a virtual register with sub-register index (with TRI). +/// %EAX - a physical register +/// %physreg17 - a physical register when no TRI instance given. +/// +/// Usage: OS << PrintReg(Reg, TRI) << '\n'; +/// +class PrintReg { + const TargetRegisterInfo *TRI; + unsigned Reg; + unsigned SubIdx; +public: + PrintReg(unsigned reg, const TargetRegisterInfo *tri = 0, unsigned subidx = 0) + : TRI(tri), Reg(reg), SubIdx(subidx) {} + void print(raw_ostream&) const; +}; + +static inline raw_ostream &operator<<(raw_ostream &OS, const PrintReg &PR) { + PR.print(OS); + return OS; +} + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Target/TargetRegistry.h b/contrib/llvm/include/llvm/Target/TargetRegistry.h index 2817b0c..f851ad0 100644 --- a/contrib/llvm/include/llvm/Target/TargetRegistry.h +++ b/contrib/llvm/include/llvm/Target/TargetRegistry.h @@ -39,6 +39,15 @@ namespace llvm { class TargetAsmParser; class TargetMachine; class raw_ostream; + class formatted_raw_ostream; + + MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + bool isVerboseAsm, + bool useLoc, + MCInstPrinter *InstPrint, + MCCodeEmitter *CE, + TargetAsmBackend *TAB, + bool ShowInst); /// Target - Wrapper for Target specific information. /// @@ -80,7 +89,16 @@ namespace llvm { TargetAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, - bool RelaxAll); + bool RelaxAll, + bool NoExecStack); + typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx, + formatted_raw_ostream &OS, + bool isVerboseAsm, + bool useLoc, + MCInstPrinter *InstPrint, + MCCodeEmitter *CE, + TargetAsmBackend *TAB, + bool ShowInst); private: /// Next - The next registered target in the linked list, maintained by the @@ -138,7 +156,13 @@ namespace llvm { /// ObjectStreamer, if registered. ObjectStreamerCtorTy ObjectStreamerCtorFn; + /// AsmStreamerCtorFn - Construction function for this target's + /// AsmStreamer, if registered (default = llvm::createAsmStreamer). + AsmStreamerCtorTy AsmStreamerCtorFn; + public: + Target() : AsmStreamerCtorFn(llvm::createAsmStreamer) {} + /// @name Target Information /// @{ @@ -185,6 +209,9 @@ namespace llvm { /// hasObjectStreamer - Check if this target supports streaming to files. bool hasObjectStreamer() const { return ObjectStreamerCtorFn != 0; } + /// hasAsmStreamer - Check if this target supports streaming to files. + bool hasAsmStreamer() const { return AsmStreamerCtorFn != 0; } + /// @} /// @name Feature Constructors /// @{ @@ -282,14 +309,31 @@ namespace llvm { /// \arg _OS - The stream object. /// \arg _Emitter - The target independent assembler object.Takes ownership. /// \arg RelaxAll - Relax all fixups? + /// \arg NoExecStack - Mark file as not needing a executable stack. MCStreamer *createObjectStreamer(const std::string &TT, MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, - bool RelaxAll) const { + bool RelaxAll, + bool NoExecStack) const { if (!ObjectStreamerCtorFn) return 0; - return ObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, RelaxAll); + return ObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, RelaxAll, + NoExecStack); + } + + /// createAsmStreamer - Create a target specific MCStreamer. + MCStreamer *createAsmStreamer(MCContext &Ctx, + formatted_raw_ostream &OS, + bool isVerboseAsm, + bool useLoc, + MCInstPrinter *InstPrint, + MCCodeEmitter *CE, + TargetAsmBackend *TAB, + bool ShowInst) const { + // AsmStreamerCtorFn is default to llvm::createAsmStreamer + return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, + InstPrint, CE, TAB, ShowInst); } /// @} @@ -513,7 +557,7 @@ namespace llvm { T.CodeEmitterCtorFn = Fn; } - /// RegisterObjectStreamer - Register an MCStreamer implementation + /// RegisterObjectStreamer - Register a object code MCStreamer implementation /// for the given target. /// /// Clients are responsible for ensuring that registration doesn't occur @@ -527,6 +571,20 @@ namespace llvm { T.ObjectStreamerCtorFn = Fn; } + /// RegisterAsmStreamer - Register an assembly MCStreamer implementation + /// for the given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCStreamer for the target. + static void RegisterAsmStreamer(Target &T, Target::AsmStreamerCtorTy Fn) { + if (T.AsmStreamerCtorFn == createAsmStreamer) + T.AsmStreamerCtorFn = Fn; + } + /// @} }; diff --git a/contrib/llvm/include/llvm/Target/TargetSchedule.td b/contrib/llvm/include/llvm/Target/TargetSchedule.td index 96c8367..97ea82a 100644 --- a/contrib/llvm/include/llvm/Target/TargetSchedule.td +++ b/contrib/llvm/include/llvm/Target/TargetSchedule.td @@ -22,6 +22,13 @@ // class FuncUnit; +//===----------------------------------------------------------------------===// +// Pipeline bypass / forwarding - These values specifies the symbolic names of +// pipeline bypasses which can be used to forward results of instructions +// that are forwarded to uses. +class Bypass; +def NoBypass : Bypass; + class ReservationKind<bits<1> val> { int Value = val; } @@ -66,30 +73,58 @@ class InstrStage<int cycles, list<FuncUnit> units, // across all chip sets. Thus a new chip set can be added without modifying // instruction information. // -class InstrItinClass; +// NumMicroOps represents the number of micro-operations that each instruction +// in the class are decoded to. If the number is zero, then it means the +// instruction can decode into variable number of micro-ops and it must be +// determined dynamically. +// +class InstrItinClass<int ops = 1> { + int NumMicroOps = ops; +} def NoItinerary : InstrItinClass; //===----------------------------------------------------------------------===// // Instruction itinerary data - These values provide a runtime map of an // instruction itinerary class (name) to its itinerary data. // +// OperandCycles are optional "cycle counts". They specify the cycle after +// instruction issue the values which correspond to specific operand indices +// are defined or read. Bypasses are optional "pipeline forwarding pathes", if +// a def by an instruction is available on a specific bypass and the use can +// read from the same bypass, then the operand use latency is reduced by one. +// +// InstrItinData<IIC_iLoad_i , [InstrStage<1, [A9_Pipe1]>, +// InstrStage<1, [A9_AGU]>], +// [3, 1], [A9_LdBypass]>, +// InstrItinData<IIC_iMVNr , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>], +// [1, 1], [NoBypass, A9_LdBypass]>, +// +// In this example, the instruction of IIC_iLoadi reads its input on cycle 1 +// (after issue) and the result of the load is available on cycle 3. The result +// is available via forwarding path A9_LdBypass. If it's used by the first +// source operand of instructions of IIC_iMVNr class, then the operand latency +// is reduced by 1. class InstrItinData<InstrItinClass Class, list<InstrStage> stages, - list<int> operandcycles = []> { + list<int> operandcycles = [], + list<Bypass> bypasses = []> { InstrItinClass TheClass = Class; list<InstrStage> Stages = stages; list<int> OperandCycles = operandcycles; + list<Bypass> Bypasses = bypasses; } //===----------------------------------------------------------------------===// // Processor itineraries - These values represent the set of all itinerary // classes for a given chip set. // -class ProcessorItineraries<list<FuncUnit> fu, list<InstrItinData> iid> { +class ProcessorItineraries<list<FuncUnit> fu, list<Bypass> bp, + list<InstrItinData> iid> { list<FuncUnit> FU = fu; + list<Bypass> BP = bp; list<InstrItinData> IID = iid; } // NoItineraries - A marker that can be used by processors without schedule // info. -def NoItineraries : ProcessorItineraries<[], []>; +def NoItineraries : ProcessorItineraries<[], [], []>; diff --git a/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td b/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td index 58ccfba..c9be40d 100644 --- a/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td +++ b/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td @@ -1,10 +1,10 @@ //===- TargetSelectionDAG.td - Common code for DAG isels ---*- tablegen -*-===// -// +// // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // // This file defines the target-independent interfaces used by SelectionDAG @@ -61,6 +61,13 @@ class SDTCisEltOfVec<int ThisOp, int OtherOp> int OtherOpNum = OtherOp; } +/// SDTCisSubVecOfVec - This indicates that ThisOp is a vector type +/// with length less that of OtherOp, which is a vector type. +class SDTCisSubVecOfVec<int ThisOp, int OtherOp> + : SDTypeConstraint<ThisOp> { + int OtherOpNum = OtherOp; +} + //===----------------------------------------------------------------------===// // Selection DAG Type Profile definitions. // @@ -123,10 +130,10 @@ def SDTFPRoundOp : SDTypeProfile<1, 1, [ // fround def SDTFPExtendOp : SDTypeProfile<1, 1, [ // fextend SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<1, 0> ]>; -def SDTIntToFPOp : SDTypeProfile<1, 1, [ // [su]int_to_fp +def SDTIntToFPOp : SDTypeProfile<1, 1, [ // [su]int_to_fp SDTCisFP<0>, SDTCisInt<1> ]>; -def SDTFPToIntOp : SDTypeProfile<1, 1, [ // fp_to_[su]int +def SDTFPToIntOp : SDTypeProfile<1, 1, [ // fp_to_[su]int SDTCisInt<0>, SDTCisFP<1> ]>; def SDTExtInreg : SDTypeProfile<1, 2, [ // sext_inreg @@ -138,7 +145,7 @@ def SDTSetCC : SDTypeProfile<1, 3, [ // setcc SDTCisInt<0>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT> ]>; -def SDTSelect : SDTypeProfile<1, 3, [ // select +def SDTSelect : SDTypeProfile<1, 3, [ // select SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3> ]>; @@ -162,11 +169,11 @@ def SDTBrind : SDTypeProfile<0, 1, [ // brind def SDTNone : SDTypeProfile<0, 0, []>; // ret, trap def SDTLoad : SDTypeProfile<1, 1, [ // load - SDTCisPtrTy<1> + SDTCisPtrTy<1> ]>; def SDTStore : SDTypeProfile<0, 2, [ // store - SDTCisPtrTy<1> + SDTCisPtrTy<1> ]>; def SDTIStore : SDTypeProfile<1, 3, [ // indexed store @@ -183,18 +190,25 @@ def SDTVecInsert : SDTypeProfile<1, 3, [ // vector insert SDTCisEltOfVec<2, 1>, SDTCisSameAs<0, 1>, SDTCisPtrTy<3> ]>; -def STDPrefetch : SDTypeProfile<0, 3, [ // prefetch +def SDTSubVecExtract : SDTypeProfile<1, 2, [// subvector extract + SDTCisSubVecOfVec<0,1>, SDTCisInt<2> +]>; +def SDTSubVecInsert : SDTypeProfile<1, 3, [ // subvector insert + SDTCisSubVecOfVec<2, 1>, SDTCisSameAs<0,1>, SDTCisInt<3> +]>; + +def SDTPrefetch : SDTypeProfile<0, 3, [ // prefetch SDTCisPtrTy<0>, SDTCisSameAs<1, 2>, SDTCisInt<1> ]>; -def STDMemBarrier : SDTypeProfile<0, 5, [ // memory barier +def SDTMemBarrier : SDTypeProfile<0, 5, [ // memory barier SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisSameAs<0,4>, SDTCisInt<0> ]>; -def STDAtomic3 : SDTypeProfile<1, 3, [ +def SDTAtomic3 : SDTypeProfile<1, 3, [ SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisInt<0>, SDTCisPtrTy<1> ]>; -def STDAtomic2 : SDTypeProfile<1, 2, [ +def SDTAtomic2 : SDTypeProfile<1, 2, [ SDTCisSameAs<0,2>, SDTCisInt<0>, SDTCisPtrTy<1> ]>; @@ -216,20 +230,27 @@ class SDNodeProperty; def SDNPCommutative : SDNodeProperty; // X op Y == Y op X def SDNPAssociative : SDNodeProperty; // (X op Y) op Z == X op (Y op Z) def SDNPHasChain : SDNodeProperty; // R/W chain operand and result -def SDNPOutFlag : SDNodeProperty; // Write a flag result -def SDNPInFlag : SDNodeProperty; // Read a flag operand -def SDNPOptInFlag : SDNodeProperty; // Optionally read a flag operand +def SDNPOutGlue : SDNodeProperty; // Write a flag result +def SDNPInGlue : SDNodeProperty; // Read a flag operand +def SDNPOptInGlue : SDNodeProperty; // Optionally read a flag operand def SDNPMayStore : SDNodeProperty; // May write to memory, sets 'mayStore'. def SDNPMayLoad : SDNodeProperty; // May read memory, sets 'mayLoad'. def SDNPSideEffect : SDNodeProperty; // Sets 'HasUnmodelledSideEffects'. def SDNPMemOperand : SDNodeProperty; // Touches memory, has assoc MemOperand def SDNPVariadic : SDNodeProperty; // Node has variable arguments. +def SDNPWantRoot : SDNodeProperty; // ComplexPattern gets the root of match +def SDNPWantParent : SDNodeProperty; // ComplexPattern gets the parent + +//===----------------------------------------------------------------------===// +// Selection DAG Pattern Operations +class SDPatternOperator; //===----------------------------------------------------------------------===// // Selection DAG Node definitions. // class SDNode<string opcode, SDTypeProfile typeprof, - list<SDNodeProperty> props = [], string sdclass = "SDNode"> { + list<SDNodeProperty> props = [], string sdclass = "SDNode"> + : SDPatternOperator { string Opcode = opcode; string SDClass = sdclass; list<SDNodeProperty> Properties = props; @@ -305,14 +326,14 @@ def or : SDNode<"ISD::OR" , SDTIntBinOp, def xor : SDNode<"ISD::XOR" , SDTIntBinOp, [SDNPCommutative, SDNPAssociative]>; def addc : SDNode<"ISD::ADDC" , SDTIntBinOp, - [SDNPCommutative, SDNPOutFlag]>; + [SDNPCommutative, SDNPOutGlue]>; def adde : SDNode<"ISD::ADDE" , SDTIntBinOp, - [SDNPCommutative, SDNPOutFlag, SDNPInFlag]>; + [SDNPCommutative, SDNPOutGlue, SDNPInGlue]>; def subc : SDNode<"ISD::SUBC" , SDTIntBinOp, - [SDNPOutFlag]>; + [SDNPOutGlue]>; def sube : SDNode<"ISD::SUBE" , SDTIntBinOp, - [SDNPOutFlag, SDNPInFlag]>; - + [SDNPOutGlue, SDNPInGlue]>; + def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>; def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>; def ctlz : SDNode<"ISD::CTLZ" , SDTIntUnaryOp>; @@ -322,11 +343,11 @@ def sext : SDNode<"ISD::SIGN_EXTEND", SDTIntExtendOp>; def zext : SDNode<"ISD::ZERO_EXTEND", SDTIntExtendOp>; def anyext : SDNode<"ISD::ANY_EXTEND" , SDTIntExtendOp>; def trunc : SDNode<"ISD::TRUNCATE" , SDTIntTruncOp>; -def bitconvert : SDNode<"ISD::BIT_CONVERT", SDTUnaryOp>; +def bitconvert : SDNode<"ISD::BITCAST" , SDTUnaryOp>; def extractelt : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTVecExtract>; def insertelt : SDNode<"ISD::INSERT_VECTOR_ELT", SDTVecInsert>; - + def fadd : SDNode<"ISD::FADD" , SDTFPBinOp, [SDNPCommutative]>; def fsub : SDNode<"ISD::FSUB" , SDTFPBinOp>; def fmul : SDNode<"ISD::FMUL" , SDTFPBinOp, [SDNPCommutative]>; @@ -367,35 +388,36 @@ def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>; def trap : SDNode<"ISD::TRAP" , SDTNone, [SDNPHasChain, SDNPSideEffect]>; -def prefetch : SDNode<"ISD::PREFETCH" , STDPrefetch, - [SDNPHasChain, SDNPMayLoad, SDNPMayStore]>; +def prefetch : SDNode<"ISD::PREFETCH" , SDTPrefetch, + [SDNPHasChain, SDNPMayLoad, SDNPMayStore, + SDNPMemOperand]>; -def membarrier : SDNode<"ISD::MEMBARRIER" , STDMemBarrier, +def membarrier : SDNode<"ISD::MEMBARRIER" , SDTMemBarrier, [SDNPHasChain, SDNPSideEffect]>; -def atomic_cmp_swap : SDNode<"ISD::ATOMIC_CMP_SWAP" , STDAtomic3, +def atomic_cmp_swap : SDNode<"ISD::ATOMIC_CMP_SWAP" , SDTAtomic3, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_add : SDNode<"ISD::ATOMIC_LOAD_ADD" , STDAtomic2, +def atomic_load_add : SDNode<"ISD::ATOMIC_LOAD_ADD" , SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_swap : SDNode<"ISD::ATOMIC_SWAP", STDAtomic2, +def atomic_swap : SDNode<"ISD::ATOMIC_SWAP", SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_sub : SDNode<"ISD::ATOMIC_LOAD_SUB" , STDAtomic2, +def atomic_load_sub : SDNode<"ISD::ATOMIC_LOAD_SUB" , SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_and : SDNode<"ISD::ATOMIC_LOAD_AND" , STDAtomic2, +def atomic_load_and : SDNode<"ISD::ATOMIC_LOAD_AND" , SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_or : SDNode<"ISD::ATOMIC_LOAD_OR" , STDAtomic2, +def atomic_load_or : SDNode<"ISD::ATOMIC_LOAD_OR" , SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_xor : SDNode<"ISD::ATOMIC_LOAD_XOR" , STDAtomic2, +def atomic_load_xor : SDNode<"ISD::ATOMIC_LOAD_XOR" , SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_nand: SDNode<"ISD::ATOMIC_LOAD_NAND", STDAtomic2, +def atomic_load_nand: SDNode<"ISD::ATOMIC_LOAD_NAND", SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_min : SDNode<"ISD::ATOMIC_LOAD_MIN", STDAtomic2, +def atomic_load_min : SDNode<"ISD::ATOMIC_LOAD_MIN", SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_max : SDNode<"ISD::ATOMIC_LOAD_MAX", STDAtomic2, +def atomic_load_max : SDNode<"ISD::ATOMIC_LOAD_MAX", SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_umin : SDNode<"ISD::ATOMIC_LOAD_UMIN", STDAtomic2, +def atomic_load_umin : SDNode<"ISD::ATOMIC_LOAD_UMIN", SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; -def atomic_load_umax : SDNode<"ISD::ATOMIC_LOAD_UMAX", STDAtomic2, +def atomic_load_umax : SDNode<"ISD::ATOMIC_LOAD_UMAX", SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; // Do not use ld, st directly. Use load, extload, sextload, zextload, store, @@ -415,16 +437,26 @@ def vector_extract : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTypeProfile<1, 2, [SDTCisPtrTy<2>]>, []>; def vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT", SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisPtrTy<3>]>, []>; - + +// This operator does not do subvector type checking. The ARM +// backend, at least, needs it. +def vector_extract_subvec : SDNode<"ISD::EXTRACT_SUBVECTOR", + SDTypeProfile<1, 2, [SDTCisInt<2>, SDTCisVec<1>, SDTCisVec<0>]>, + []>; + +// This operator does subvector type checking. +def extract_subvector : SDNode<"ISD::EXTRACT_SUBVECTOR", SDTSubVecExtract, []>; +def insert_subvector : SDNode<"ISD::INSERT_SUBVECTOR", SDTSubVecInsert, []>; + // Nodes for intrinsics, you should use the intrinsic itself and let tblgen use // these internally. Don't reference these directly. -def intrinsic_void : SDNode<"ISD::INTRINSIC_VOID", +def intrinsic_void : SDNode<"ISD::INTRINSIC_VOID", SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>, [SDNPHasChain]>; -def intrinsic_w_chain : SDNode<"ISD::INTRINSIC_W_CHAIN", +def intrinsic_w_chain : SDNode<"ISD::INTRINSIC_W_CHAIN", SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, [SDNPHasChain]>; -def intrinsic_wo_chain : SDNode<"ISD::INTRINSIC_WO_CHAIN", +def intrinsic_wo_chain : SDNode<"ISD::INTRINSIC_WO_CHAIN", SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, []>; // Do not use cvt directly. Use cvt forms below @@ -469,10 +501,10 @@ def NOOP_SDNodeXForm : SDNodeXForm<imm, [{}]>; // /// PatFrag - Represents a pattern fragment. This can match something on the -/// DAG, frame a single node to multiply nested other fragments. +/// DAG, from a single node to multiple nested other fragments. /// class PatFrag<dag ops, dag frag, code pred = [{}], - SDNodeXForm xform = NOOP_SDNodeXForm> { + SDNodeXForm xform = NOOP_SDNodeXForm> : SDPatternOperator { dag Operands = ops; dag Fragment = frag; code Predicate = pred; @@ -822,7 +854,7 @@ def cvtfu : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), //===----------------------------------------------------------------------===// // Selection DAG Pattern Support. // -// Patterns are what are actually matched against the target-flavored +// Patterns are what are actually matched against by the target-flavored // instruction selection DAG. Instructions defined by the target implicitly // define patterns in most cases, but patterns can also be explicitly added when // an operation is defined by a sequence of instructions (e.g. loading a large @@ -834,7 +866,7 @@ class Pattern<dag patternToMatch, list<dag> resultInstrs> { dag PatternToMatch = patternToMatch; list<dag> ResultInstrs = resultInstrs; list<Predicate> Predicates = []; // See class Instruction in Target.td. - int AddedComplexity = 0; // See class Instruction in Target.td. + int AddedComplexity = 0; // See class Instruction in Target.td. } // Pat - A simple (but common) form of a pattern, which produces a simple result diff --git a/contrib/llvm/include/llvm/Target/TargetSelectionDAGInfo.h b/contrib/llvm/include/llvm/Target/TargetSelectionDAGInfo.h index 2be1834..c9ca722 100644 --- a/contrib/llvm/include/llvm/Target/TargetSelectionDAGInfo.h +++ b/contrib/llvm/include/llvm/Target/TargetSelectionDAGInfo.h @@ -59,8 +59,8 @@ public: SDValue Op1, SDValue Op2, SDValue Op3, unsigned Align, bool isVolatile, bool AlwaysInline, - const Value *DstSV, uint64_t DstOff, - const Value *SrcSV, uint64_t SrcOff) const { + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo) const { return SDValue(); } @@ -75,8 +75,8 @@ public: SDValue Chain, SDValue Op1, SDValue Op2, SDValue Op3, unsigned Align, bool isVolatile, - const Value *DstSV, uint64_t DstOff, - const Value *SrcSV, uint64_t SrcOff) const { + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo) const { return SDValue(); } @@ -91,7 +91,7 @@ public: SDValue Chain, SDValue Op1, SDValue Op2, SDValue Op3, unsigned Align, bool isVolatile, - const Value *DstSV, uint64_t DstOff) const { + MachinePointerInfo DstPtrInfo) const { return SDValue(); } }; diff --git a/contrib/llvm/include/llvm/Transforms/IPO.h b/contrib/llvm/include/llvm/Transforms/IPO.h index 0de1003..1239881 100644 --- a/contrib/llvm/include/llvm/Transforms/IPO.h +++ b/contrib/llvm/include/llvm/Transforms/IPO.h @@ -99,6 +99,8 @@ ModulePass *createGVExtractionPass(std::vector<GlobalValue*>& GVs, bool /// createFunctionInliningPass - Return a new pass object that uses a heuristic /// to inline direct function calls to small functions. /// +/// The -inline-threshold command line option takes precedence over the +/// threshold given here. Pass *createFunctionInliningPass(); Pass *createFunctionInliningPass(int Threshold); @@ -187,12 +189,6 @@ ModulePass *createBlockExtractorPass(); ModulePass *createStripDeadPrototypesPass(); //===----------------------------------------------------------------------===// -/// createPartialSpecializationPass - This pass specializes functions for -/// constant arguments. -/// -ModulePass *createPartialSpecializationPass(); - -//===----------------------------------------------------------------------===// /// createFunctionAttrsPass - This pass discovers functions that do not access /// memory, or only read memory, and gives them the readnone/readonly attribute. /// It also discovers function arguments that are not captured by the function diff --git a/contrib/llvm/include/llvm/Transforms/Instrumentation.h b/contrib/llvm/include/llvm/Transforms/Instrumentation.h index 9c579ac..aa9873f 100644 --- a/contrib/llvm/include/llvm/Transforms/Instrumentation.h +++ b/contrib/llvm/include/llvm/Transforms/Instrumentation.h @@ -25,6 +25,9 @@ ModulePass *createEdgeProfilerPass(); // Insert optimal edge profiling instrumentation ModulePass *createOptimalEdgeProfilerPass(); +// Insert path profiling instrumentation +ModulePass *createPathProfilerPass(); + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Transforms/RSProfiling.h b/contrib/llvm/include/llvm/Transforms/RSProfiling.h deleted file mode 100644 index 02439e8..0000000 --- a/contrib/llvm/include/llvm/Transforms/RSProfiling.h +++ /dev/null @@ -1,42 +0,0 @@ -//===- RSProfiling.cpp - Various profiling using random sampling ----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the abstract interface that a profiler must implement to -// support the random profiling transform. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_RSPROFILING_H -#define LLVM_TRANSFORMS_RSPROFILING_H - -#include "llvm/Pass.h" - -namespace llvm { - class Value; - - //===--------------------------------------------------------------------===// - /// RSProfilers - The basic Random Sampling Profiler Interface Any profiler - /// that implements this interface can be transformed by the random sampling - /// pass to be sample based rather than always on. - /// - /// The only exposed function can be queried to find out if an instruction - /// was original or if it was inserted by the profiler. Implementations of - /// this interface are expected to chain to other implementations, such that - /// multiple profilers can be support simultaniously. - struct RSProfilers : public ModulePass { - static char ID; // Pass identification, replacement for typeinfo - RSProfilers() : ModulePass(&ID) {} - - /// isProfiling - This method returns true if the value passed it was - /// inserted by the profiler. - virtual bool isProfiling(Value* v) = 0; - }; -} - -#endif diff --git a/contrib/llvm/include/llvm/Transforms/Scalar.h b/contrib/llvm/include/llvm/Transforms/Scalar.h index 0c35d7e..6f2a38e 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar.h @@ -73,7 +73,8 @@ FunctionPass *createAggressiveDCEPass(); // ScalarReplAggregates - Break up alloca's of aggregates into multiple allocas // if possible. // -FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1); +FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1, + bool UseDomTree = true); //===----------------------------------------------------------------------===// // @@ -119,6 +120,12 @@ Pass *createLoopUnswitchPass(bool OptimizeForSize = false); //===----------------------------------------------------------------------===// // +// LoopInstSimplify - This pass simplifies instructions in a loop's body. +// +Pass *createLoopInstSimplifyPass(); + +//===----------------------------------------------------------------------===// +// // LoopUnroll - This pass is a simple loop unrolling pass. // Pass *createLoopUnrollPass(); @@ -131,11 +138,10 @@ Pass *createLoopRotatePass(); //===----------------------------------------------------------------------===// // -// LoopIndexSplit - This pass divides loop's iteration range by spliting loop -// such that each individual loop is executed efficiently. +// LoopIdiom - This pass recognizes and replaces idioms in loops. // -Pass *createLoopIndexSplitPass(); - +Pass *createLoopIdiomPass(); + //===----------------------------------------------------------------------===// // // PromoteMemoryToRegister - This pass is used to promote memory references to @@ -261,6 +267,13 @@ extern char &LCSSAID; //===----------------------------------------------------------------------===// // +// EarlyCSE - This pass performs a simple and fast CSE pass over the dominator +// tree. +// +FunctionPass *createEarlyCSEPass(); + +//===----------------------------------------------------------------------===// +// // GVN - This pass performs global value numbering and redundant load // elimination cotemporaneously. // @@ -329,6 +342,13 @@ Pass *createLowerAtomicPass(); // Pass *createCorrelatedValuePropagationPass(); +//===----------------------------------------------------------------------===// +// +// InstructionSimplifier - Remove redundant instructions. +// +FunctionPass *createInstructionSimplifierPass(); +extern char &InstructionSimplifierID; + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Transforms/Utils/AddrModeMatcher.h b/contrib/llvm/include/llvm/Transforms/Utils/AddrModeMatcher.h index be601e2..0678ecc 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/AddrModeMatcher.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/AddrModeMatcher.h @@ -39,6 +39,12 @@ struct ExtAddrMode : public TargetLowering::AddrMode { ExtAddrMode() : BaseReg(0), ScaledReg(0) {} void print(raw_ostream &OS) const; void dump() const; + + bool operator==(const ExtAddrMode& O) const { + return (BaseReg == O.BaseReg) && (ScaledReg == O.ScaledReg) && + (BaseGV == O.BaseGV) && (BaseOffs == O.BaseOffs) && + (HasBaseReg == O.HasBaseReg) && (Scale == O.Scale); + } }; static inline raw_ostream &operator<<(raw_ostream &OS, const ExtAddrMode &AM) { @@ -84,7 +90,7 @@ public: bool Success = AddressingModeMatcher(AddrModeInsts, TLI, AccessTy, MemoryInst, Result).MatchAddr(V, 0); - Success = Success; assert(Success && "Couldn't select *anything*?"); + (void)Success; assert(Success && "Couldn't select *anything*?"); return Result; } private: diff --git a/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h index 0f54450..5335860 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -22,9 +22,10 @@ namespace llvm { +class AliasAnalysis; class Instruction; class Pass; -class AliasAnalysis; +class ReturnInst; /// DeleteDeadBlock - Delete the specified block, which must have no /// predecessors. @@ -35,7 +36,7 @@ void DeleteDeadBlock(BasicBlock *BB); /// any single-entry PHI nodes in it, fold them away. This handles the case /// when all entries to the PHI nodes in a block are guaranteed equal, such as /// when the block has exactly one predecessor. -void FoldSingleEntryPHINodes(BasicBlock *BB); +void FoldSingleEntryPHINodes(BasicBlock *BB, Pass *P = 0); /// DeleteDeadPHIs - Examine each PHI in the given block and delete it if it /// is dead. Also recursively delete any operands that become dead as @@ -46,7 +47,7 @@ bool DeleteDeadPHIs(BasicBlock *BB); /// MergeBlockIntoPredecessor - Attempts to merge a block into its predecessor, /// if possible. The return value indicates success or failure. -bool MergeBlockIntoPredecessor(BasicBlock* BB, Pass* P = 0); +bool MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P = 0); // ReplaceInstWithValue - Replace all uses of an instruction (specified by BI) // with a value, then remove and delete the original instruction. @@ -75,15 +76,6 @@ void FindFunctionBackedges(const Function &F, SmallVectorImpl<std::pair<const BasicBlock*,const BasicBlock*> > &Result); -// RemoveSuccessor - Change the specified terminator instruction such that its -// successor #SuccNum no longer exists. Because this reduces the outgoing -// degree of the current basic block, the actual terminator instruction itself -// may have to be changed. In the case where the last successor of the block is -// deleted, a return instruction is inserted in its place which can cause a -// suprising change in program behavior if it is not expected. -// -void RemoveSuccessor(TerminatorInst *TI, unsigned SuccNum); - /// GetSuccessorNumber - Search for the specified successor of basic block BB /// and return its position in the terminator instruction's list of /// successors. It is an error to call this with a block that is not a @@ -180,7 +172,15 @@ BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P); BasicBlock *SplitBlockPredecessors(BasicBlock *BB, BasicBlock *const *Preds, unsigned NumPreds, const char *Suffix, Pass *P = 0); - + +/// FoldReturnIntoUncondBranch - This method duplicates the specified return +/// instruction into a predecessor which ends in an unconditional branch. If +/// the return instruction returns a value defined by a PHI, propagate the +/// right value into the return. It returns the new return instruction in the +/// predecessor. +ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, + BasicBlock *Pred); + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h b/contrib/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h index c75c142..e825938 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -47,11 +47,6 @@ namespace llvm { /// specified pointer arguments and length. Value *EmitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, const TargetData *TD, StringRef Name = "strncpy"); - - /// EmitMemCpy - Emit a call to the memcpy function to the builder. This - /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. - Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, unsigned Align, - bool isVolatile, IRBuilder<> &B, const TargetData *TD); /// EmitMemCpyChk - Emit a call to the __memcpy_chk function to the builder. /// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src @@ -59,11 +54,6 @@ namespace llvm { Value *EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, IRBuilder<> &B, const TargetData *TD); - /// EmitMemMove - Emit a call to the memmove function to the builder. This - /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. - Value *EmitMemMove(Value *Dst, Value *Src, Value *Len, unsigned Align, - bool isVolatile, IRBuilder<> &B, const TargetData *TD); - /// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is /// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B, @@ -73,10 +63,6 @@ namespace llvm { Value *EmitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, const TargetData *TD); - /// EmitMemSet - Emit a call to the memset function - Value *EmitMemSet(Value *Dst, Value *Val, Value *Len, bool isVolatile, - IRBuilder<> &B, const TargetData *TD); - /// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' /// (e.g. 'floor'). This function is known to take a single of type matching /// 'Op' and returns one value with the same type. If 'Op' is a long double, diff --git a/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h b/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h index 62bf92a..24ebb10 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h @@ -22,6 +22,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ValueHandle.h" +#include "llvm/Transforms/Utils/ValueMapper.h" namespace llvm { @@ -46,7 +47,7 @@ class AllocaInst; /// CloneModule - Return an exact copy of the specified module /// Module *CloneModule(const Module *M); -Module *CloneModule(const Module *M, ValueMap<const Value*, Value*> &VMap); +Module *CloneModule(const Module *M, ValueToValueMapTy &VMap); /// ClonedCodeInfo - This struct can be used to capture information about code /// being cloned, while it is being cloned. @@ -102,7 +103,7 @@ struct ClonedCodeInfo { /// parameter. /// BasicBlock *CloneBasicBlock(const BasicBlock *BB, - ValueMap<const Value*, Value*> &VMap, + ValueToValueMapTy &VMap, const Twine &NameSuffix = "", Function *F = 0, ClonedCodeInfo *CodeInfo = 0); @@ -110,7 +111,7 @@ BasicBlock *CloneBasicBlock(const BasicBlock *BB, /// CloneLoop - Clone Loop. Clone dominator info for loop insiders. Populate /// VMap using old blocks to new blocks mapping. Loop *CloneLoop(Loop *L, LPPassManager *LPM, LoopInfo *LI, - ValueMap<const Value *, Value *> &VMap, Pass *P); + ValueToValueMapTy &VMap, Pass *P); /// CloneFunction - Return a copy of the specified function, but without /// embedding the function into another module. Also, any references specified @@ -125,14 +126,14 @@ Loop *CloneLoop(Loop *L, LPPassManager *LPM, LoopInfo *LI, /// mappings. /// Function *CloneFunction(const Function *F, - ValueMap<const Value*, Value*> &VMap, + ValueToValueMapTy &VMap, bool ModuleLevelChanges, ClonedCodeInfo *CodeInfo = 0); /// CloneFunction - Version of the function that doesn't need the VMap. /// inline Function *CloneFunction(const Function *F, ClonedCodeInfo *CodeInfo = 0){ - ValueMap<const Value*, Value*> VMap; + ValueToValueMapTy VMap; return CloneFunction(F, VMap, CodeInfo); } @@ -146,7 +147,7 @@ inline Function *CloneFunction(const Function *F, ClonedCodeInfo *CodeInfo = 0){ /// mappings. /// void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, - ValueMap<const Value*, Value*> &VMap, + ValueToValueMapTy &VMap, bool ModuleLevelChanges, SmallVectorImpl<ReturnInst*> &Returns, const char *NameSuffix = "", @@ -164,7 +165,7 @@ void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, /// mappings. /// void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, - ValueMap<const Value*, Value*> &VMap, + ValueToValueMapTy &VMap, bool ModuleLevelChanges, SmallVectorImpl<ReturnInst*> &Returns, const char *NameSuffix = "", diff --git a/contrib/llvm/include/llvm/Transforms/Utils/Local.h b/contrib/llvm/include/llvm/Transforms/Utils/Local.h index caae27f..26b5dd8 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/Local.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/Local.h @@ -69,6 +69,10 @@ bool RecursivelyDeleteDeadPHINode(PHINode *PN); /// /// This returns true if it changed the code, note that it can delete /// instructions in other blocks as well in this block. +/// +/// WARNING: Do not use this function on unreachable blocks, as recursive +/// simplification is not able to handle corner-case scenarios that can +/// arise in them. bool SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData *TD = 0); //===----------------------------------------------------------------------===// @@ -141,6 +145,18 @@ AllocaInst *DemoteRegToStack(Instruction &X, /// The phi node is deleted and it returns the pointer to the alloca inserted. AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = 0); +/// getOrEnforceKnownAlignment - If the specified pointer has an alignment that +/// we can determine, return it, otherwise return 0. If PrefAlign is specified, +/// and it is more than the alignment of the ultimate object, see if we can +/// increase the alignment of the ultimate object, making this check succeed. +unsigned getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign, + const TargetData *TD = 0); + +/// getKnownAlignment - Try to infer an alignment for the specified pointer. +static inline unsigned getKnownAlignment(Value *V, const TargetData *TD = 0) { + return getOrEnforceKnownAlignment(V, 0, TD); +} + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h b/contrib/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h index 35cfadd..98d51a2 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -38,8 +38,7 @@ bool isAllocaPromotable(const AllocaInst *AI); /// made to the IR. /// void PromoteMemToReg(const std::vector<AllocaInst*> &Allocas, - DominatorTree &DT, DominanceFrontier &DF, - AliasSetTracker *AST = 0); + DominatorTree &DT, AliasSetTracker *AST = 0); } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h index e50a6b1..b4048b9 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h @@ -108,6 +108,55 @@ private: void operator=(const SSAUpdater&); // DO NOT IMPLEMENT SSAUpdater(const SSAUpdater&); // DO NOT IMPLEMENT }; + +/// LoadAndStorePromoter - This little helper class provides a convenient way to +/// promote a collection of loads and stores into SSA Form using the SSAUpdater. +/// This handles complexities that SSAUpdater doesn't, such as multiple loads +/// and stores in one block. +/// +/// Clients of this class are expected to subclass this and implement the +/// virtual methods. +/// +class LoadAndStorePromoter { +protected: + SSAUpdater &SSA; +public: + LoadAndStorePromoter(const SmallVectorImpl<Instruction*> &Insts, + SSAUpdater &S, StringRef Name = StringRef()); + virtual ~LoadAndStorePromoter() {} + + /// run - This does the promotion. Insts is a list of loads and stores to + /// promote, and Name is the basename for the PHIs to insert. After this is + /// complete, the loads and stores are removed from the code. + void run(const SmallVectorImpl<Instruction*> &Insts) const; + + + /// Return true if the specified instruction is in the Inst list (which was + /// passed into the run method). Clients should implement this with a more + /// efficient version if possible. + virtual bool isInstInList(Instruction *I, + const SmallVectorImpl<Instruction*> &Insts) const { + for (unsigned i = 0, e = Insts.size(); i != e; ++i) + if (Insts[i] == I) + return true; + return false; + } + + /// doExtraRewritesBeforeFinalDeletion - This hook is invoked after all the + /// stores are found and inserted as available values, but + virtual void doExtraRewritesBeforeFinalDeletion() const { + } + + /// replaceLoadWithValue - Clients can choose to implement this to get + /// notified right before a load is RAUW'd another value. + virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const { + } + + /// This is called before each instruction is deleted. + virtual void instructionDeleted(Instruction *I) const { + } + +}; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/contrib/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h index a5060e6..54506cf 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h @@ -27,7 +27,9 @@ struct UnifyFunctionExitNodes : public FunctionPass { public: static char ID; // Pass identification, replacement for typeid UnifyFunctionExitNodes() : FunctionPass(ID), - ReturnBlock(0), UnwindBlock(0) {} + ReturnBlock(0), UnwindBlock(0) { + initializeUnifyFunctionExitNodesPass(*PassRegistry::getPassRegistry()); + } // We can preserve non-critical-edgeness when we unify function exit nodes virtual void getAnalysisUsage(AnalysisUsage &AU) const; diff --git a/contrib/llvm/include/llvm/Transforms/Utils/ValueMapper.h b/contrib/llvm/include/llvm/Transforms/Utils/ValueMapper.h index 5274112..d612213 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/ValueMapper.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/ValueMapper.h @@ -20,12 +20,31 @@ namespace llvm { class Value; class Instruction; - typedef ValueMap<const Value *, Value *> ValueToValueMapTy; + typedef ValueMap<const Value *, TrackingVH<Value> > ValueToValueMapTy; + /// RemapFlags - These are flags that the value mapping APIs allow. + enum RemapFlags { + RF_None = 0, + + /// RF_NoModuleLevelChanges - If this flag is set, the remapper knows that + /// only local values within a function (such as an instruction or argument) + /// are mapped, not global values like functions and global metadata. + RF_NoModuleLevelChanges = 1, + + /// RF_IgnoreMissingEntries - If this flag is set, the remapper ignores + /// entries that are not in the value map. If it is unset, it aborts if an + /// operand is asked to be remapped which doesn't exist in the mapping. + RF_IgnoreMissingEntries = 2 + }; + + static inline RemapFlags operator|(RemapFlags LHS, RemapFlags RHS) { + return RemapFlags(unsigned(LHS)|unsigned(RHS)); + } + Value *MapValue(const Value *V, ValueToValueMapTy &VM, - bool ModuleLevelChanges); + RemapFlags Flags = RF_None); void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, - bool ModuleLevelChanges); + RemapFlags Flags = RF_None); } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Type.h b/contrib/llvm/include/llvm/Type.h index f7d6fd5..0939d67 100644 --- a/contrib/llvm/include/llvm/Type.h +++ b/contrib/llvm/include/llvm/Type.h @@ -12,7 +12,6 @@ #include "llvm/AbstractTypeUser.h" #include "llvm/Support/Casting.h" -#include "llvm/System/DataTypes.h" #include "llvm/ADT/GraphTraits.h" #include <string> #include <vector> @@ -76,19 +75,20 @@ public: PPC_FP128TyID, ///< 5: 128 bit floating point type (two 64-bits) LabelTyID, ///< 6: Labels MetadataTyID, ///< 7: Metadata + X86_MMXTyID, ///< 8: MMX vectors (64 bits) // Derived types... see DerivedTypes.h file... // Make sure FirstDerivedTyID stays up to date!!! - IntegerTyID, ///< 8: Arbitrary bit width integers - FunctionTyID, ///< 9: Functions - StructTyID, ///< 10: Structures - ArrayTyID, ///< 11: Arrays - PointerTyID, ///< 12: Pointers - OpaqueTyID, ///< 13: Opaque: type with unknown structure - VectorTyID, ///< 14: SIMD 'packed' format, or other vector type + IntegerTyID, ///< 9: Arbitrary bit width integers + FunctionTyID, ///< 10: Functions + StructTyID, ///< 11: Structures + ArrayTyID, ///< 12: Arrays + PointerTyID, ///< 13: Pointers + OpaqueTyID, ///< 14: Opaque: type with unknown structure + VectorTyID, ///< 15: SIMD 'packed' format, or other vector type NumTypeIDs, // Must remain as last defined ID - LastPrimitiveTyID = MetadataTyID, + LastPrimitiveTyID = X86_MMXTyID, FirstDerivedTyID = IntegerTyID }; @@ -212,6 +212,9 @@ public: bool isFloatingPointTy() const { return ID == FloatTyID || ID == DoubleTyID || ID == X86_FP80TyID || ID == FP128TyID || ID == PPC_FP128TyID; } + /// isX86_MMXTy - Return true if this is X86 MMX. + bool isX86_MMXTy() const { return ID == X86_MMXTyID; } + /// isFPOrFPVectorTy - Return true if this is a FP type or a vector of FP. /// bool isFPOrFPVectorTy() const; @@ -310,7 +313,8 @@ public: /// bool isSized() const { // If it's a primitive, it is always sized. - if (ID == IntegerTyID || isFloatingPointTy() || ID == PointerTyID) + if (ID == IntegerTyID || isFloatingPointTy() || ID == PointerTyID || + ID == X86_MMXTyID) return true; // If it is not something that can have a size (e.g. a function or label), // it doesn't have a size. @@ -400,6 +404,7 @@ public: static const Type *getX86_FP80Ty(LLVMContext &C); static const Type *getFP128Ty(LLVMContext &C); static const Type *getPPC_FP128Ty(LLVMContext &C); + static const Type *getX86_MMXTy(LLVMContext &C); static const IntegerType *getIntNTy(LLVMContext &C, unsigned N); static const IntegerType *getInt1Ty(LLVMContext &C); static const IntegerType *getInt8Ty(LLVMContext &C); @@ -416,6 +421,7 @@ public: static const PointerType *getX86_FP80PtrTy(LLVMContext &C, unsigned AS = 0); static const PointerType *getFP128PtrTy(LLVMContext &C, unsigned AS = 0); static const PointerType *getPPC_FP128PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getX86_MMXPtrTy(LLVMContext &C, unsigned AS = 0); static const PointerType *getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS = 0); static const PointerType *getInt1PtrTy(LLVMContext &C, unsigned AS = 0); diff --git a/contrib/llvm/include/llvm/TypeSymbolTable.h b/contrib/llvm/include/llvm/TypeSymbolTable.h index 26b1dbf..9fdcb98 100644 --- a/contrib/llvm/include/llvm/TypeSymbolTable.h +++ b/contrib/llvm/include/llvm/TypeSymbolTable.h @@ -16,12 +16,11 @@ #include "llvm/Type.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" #include <map> namespace llvm { -class StringRef; - /// This class provides a symbol table of name/type pairs with operations to /// support constructing, searching and iterating over the symbol table. The /// class derives from AbstractTypeUser so that the contents of the symbol diff --git a/contrib/llvm/include/llvm/Use.h b/contrib/llvm/include/llvm/Use.h index e1ebc6a..ccbdd7f 100644 --- a/contrib/llvm/include/llvm/Use.h +++ b/contrib/llvm/include/llvm/Use.h @@ -25,7 +25,6 @@ #ifndef LLVM_USE_H #define LLVM_USE_H -#include "llvm/Support/Casting.h" #include "llvm/ADT/PointerIntPair.h" #include <cstddef> #include <iterator> @@ -35,9 +34,8 @@ namespace llvm { class Value; class User; class Use; - -/// Tag - generic tag type for (at least 32 bit) pointers -enum Tag { noTag, tagOne, tagTwo, tagThree }; +template<typename> +struct simplify_type; // Use** is only 4-byte aligned. template<> @@ -67,17 +65,19 @@ private: Use(const Use &U); /// Destructor - Only for zap() - inline ~Use() { + ~Use() { if (Val) removeFromList(); } - /// Default ctor - This leaves the Use completely uninitialized. The only - /// thing that is valid to do with this use is to call the "init" method. - inline Use() {} - enum PrevPtrTag { zeroDigitTag = noTag - , oneDigitTag = tagOne - , stopTag = tagTwo - , fullStopTag = tagThree }; + enum PrevPtrTag { zeroDigitTag + , oneDigitTag + , stopTag + , fullStopTag }; + + /// Constructor + Use(PrevPtrTag tag) : Val(0) { + Prev.setInt(tag); + } public: /// Normally Use will just implicitly convert to a Value* that it holds. @@ -112,11 +112,9 @@ public: /// a User changes. static void zap(Use *Start, const Use *Stop, bool del = false); - /// getPrefix - Return deletable pointer if appropriate - Use *getPrefix(); private: const Use* getImpliedUser() const; - static Use *initTags(Use *Start, Use *Stop, ptrdiff_t Done = 0); + static Use *initTags(Use *Start, Use *Stop); Value *Val; Use *Next; @@ -210,6 +208,15 @@ public: unsigned getOperandNo() const; }; +//===----------------------------------------------------------------------===// +// AugmentedUse layout struct +//===----------------------------------------------------------------------===// + +struct AugmentedUse : public Use { + PointerIntPair<User*, 1, unsigned> ref; + AugmentedUse(); // not implemented +}; + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/User.h b/contrib/llvm/include/llvm/User.h index f827795..1363495 100644 --- a/contrib/llvm/include/llvm/User.h +++ b/contrib/llvm/include/llvm/User.h @@ -29,20 +29,6 @@ namespace llvm { template <class> struct OperandTraits; -class User; - -/// OperandTraits<User> - specialization to User -template <> -struct OperandTraits<User> { - static inline Use *op_begin(User*); - static inline Use *op_end(User*); - static inline unsigned operands(const User*); - template <class U> - struct Layout { - typedef U overlay; - }; -}; - class User : public Value { User(const User &); // Do not implement void *operator new(size_t); // Do not implement @@ -61,21 +47,18 @@ protected: unsigned NumOperands; void *operator new(size_t s, unsigned Us); - void *operator new(size_t s, unsigned Us, bool Prefix); User(const Type *ty, unsigned vty, Use *OpList, unsigned NumOps) : Value(ty, vty), OperandList(OpList), NumOperands(NumOps) {} Use *allocHungoffUses(unsigned) const; - void dropHungoffUses(Use *U) { - if (OperandList == U) { - OperandList = 0; - NumOperands = 0; - } - Use::zap(U, U->getImpliedUser(), true); + void dropHungoffUses() { + Use::zap(OperandList, OperandList + NumOperands, true); + OperandList = 0; + // Reset NumOperands so User::operator delete() does the right thing. + NumOperands = 0; } public: ~User() { - if ((intptr_t(OperandList) & 1) == 0) - Use::zap(OperandList, OperandList + NumOperands); + Use::zap(OperandList, OperandList + NumOperands); } /// operator delete - free memory allocated for User and Use objects void operator delete(void *Usr); @@ -158,18 +141,6 @@ public: } }; -inline Use *OperandTraits<User>::op_begin(User *U) { - return U->op_begin(); -} - -inline Use *OperandTraits<User>::op_end(User *U) { - return U->op_end(); -} - -inline unsigned OperandTraits<User>::operands(const User *U) { - return U->getNumOperands(); -} - template<> struct simplify_type<User::op_iterator> { typedef Value* SimpleType; diff --git a/contrib/llvm/include/llvm/Value.h b/contrib/llvm/include/llvm/Value.h index 8740f35..130e273 100644 --- a/contrib/llvm/include/llvm/Value.h +++ b/contrib/llvm/include/llvm/Value.h @@ -252,6 +252,12 @@ public: return SubclassOptionalData; } + /// clearSubclassOptionalData - Clear the optional flags contained in + /// this value. + void clearSubclassOptionalData() { + SubclassOptionalData = 0; + } + /// hasSameSubclassOptionalData - Test whether the optional flags contained /// in this value are equal to the optional flags in the given value. bool hasSameSubclassOptionalData(const Value *V) const { @@ -285,15 +291,9 @@ public: return const_cast<Value*>(this)->stripPointerCasts(); } - /// getUnderlyingObject - This method strips off any GEP address adjustments - /// and pointer casts from the specified value, returning the original object - /// being addressed. Note that the returned value has pointer type if the - /// specified value does. If the MaxLookup value is non-zero, it limits the - /// number of instructions to be stripped off. - Value *getUnderlyingObject(unsigned MaxLookup = 6); - const Value *getUnderlyingObject(unsigned MaxLookup = 6) const { - return const_cast<Value*>(this)->getUnderlyingObject(MaxLookup); - } + /// isDereferenceablePointer - Test if this value is always a pointer to + /// allocated and suitably aligned memory for a simple load or store. + bool isDereferenceablePointer() const; /// DoPHITranslation - If this value is a PHI node with CurBB as its parent, /// return the value in the PHI node corresponding to PredBB. If not, return diff --git a/contrib/llvm/include/llvm/ValueSymbolTable.h b/contrib/llvm/include/llvm/ValueSymbolTable.h index 35fc97b..1738cc4 100644 --- a/contrib/llvm/include/llvm/ValueSymbolTable.h +++ b/contrib/llvm/include/llvm/ValueSymbolTable.h @@ -16,7 +16,7 @@ #include "llvm/Value.h" #include "llvm/ADT/StringMap.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { template<typename ValueSubClass, typename ItemParentClass> |