diff --git a/contrib/llvm/include/llvm-c/Core.h b/contrib/llvm/include/llvm-c/Core.h index 76f8b31580ac..7f5c05d21e65 100644 --- a/contrib/llvm/include/llvm-c/Core.h +++ b/contrib/llvm/include/llvm-c/Core.h @@ -54,51 +54,6 @@ extern "C" { * @{ */ -typedef enum { - LLVMZExtAttribute = 1<<0, - LLVMSExtAttribute = 1<<1, - LLVMNoReturnAttribute = 1<<2, - LLVMInRegAttribute = 1<<3, - LLVMStructRetAttribute = 1<<4, - LLVMNoUnwindAttribute = 1<<5, - LLVMNoAliasAttribute = 1<<6, - LLVMByValAttribute = 1<<7, - LLVMNestAttribute = 1<<8, - LLVMReadNoneAttribute = 1<<9, - LLVMReadOnlyAttribute = 1<<10, - LLVMNoInlineAttribute = 1<<11, - LLVMAlwaysInlineAttribute = 1<<12, - LLVMOptimizeForSizeAttribute = 1<<13, - LLVMStackProtectAttribute = 1<<14, - LLVMStackProtectReqAttribute = 1<<15, - LLVMAlignment = 31<<16, - LLVMNoCaptureAttribute = 1<<21, - LLVMNoRedZoneAttribute = 1<<22, - LLVMNoImplicitFloatAttribute = 1<<23, - LLVMNakedAttribute = 1<<24, - LLVMInlineHintAttribute = 1<<25, - LLVMStackAlignment = 7<<26, - LLVMReturnsTwice = 1 << 29, - LLVMUWTable = 1 << 30, - LLVMNonLazyBind = 1 << 31 - - /* FIXME: These attributes are currently not included in the C API as - a temporary measure until the API/ABI impact to the C API is understood - and the path forward agreed upon. - LLVMSanitizeAddressAttribute = 1ULL << 32, - LLVMStackProtectStrongAttribute = 1ULL<<35, - LLVMColdAttribute = 1ULL << 40, - LLVMOptimizeNoneAttribute = 1ULL << 42, - LLVMInAllocaAttribute = 1ULL << 43, - LLVMNonNullAttribute = 1ULL << 44, - LLVMJumpTableAttribute = 1ULL << 45, - LLVMConvergentAttribute = 1ULL << 46, - LLVMSafeStackAttribute = 1ULL << 47, - LLVMSwiftSelfAttribute = 1ULL << 48, - LLVMSwiftErrorAttribute = 1ULL << 49, - */ -} LLVMAttribute; - typedef enum { /* Terminator Instructions */ LLVMRet = 1, @@ -1752,6 +1707,7 @@ LLVMValueRef LLVMConstNSWMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant) LLVMValueRef LLVMConstNUWMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); LLVMValueRef LLVMConstFMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); LLVMValueRef LLVMConstUDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstExactUDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); LLVMValueRef LLVMConstSDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); LLVMValueRef LLVMConstExactSDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); LLVMValueRef LLVMConstFDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); @@ -2010,8 +1966,6 @@ void LLVMSetGC(LLVMValueRef Fn, const char *Name); * * @see llvm::Function::addAttribute() */ -void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA); - void LLVMAddAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, LLVMAttributeRef A); unsigned LLVMGetAttributeCountAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx); @@ -2035,18 +1989,6 @@ void LLVMRemoveStringAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, void LLVMAddTargetDependentFunctionAttr(LLVMValueRef Fn, const char *A, const char *V); -/** - * Obtain an attribute from a function. - * - * @see llvm::Function::getAttributes() - */ -LLVMAttribute LLVMGetFunctionAttr(LLVMValueRef Fn); - -/** - * Remove an attribute from a function. - */ -void LLVMRemoveFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA); - /** * @defgroup LLVMCCoreValueFunctionParameters Function Parameters * @@ -2128,25 +2070,6 @@ LLVMValueRef LLVMGetNextParam(LLVMValueRef Arg); */ LLVMValueRef LLVMGetPreviousParam(LLVMValueRef Arg); -/** - * Add an attribute to a function argument. - * - * @see llvm::Argument::addAttr() - */ -void LLVMAddAttribute(LLVMValueRef Arg, LLVMAttribute PA); - -/** - * Remove an attribute from a function argument. - * - * @see llvm::Argument::removeAttr() - */ -void LLVMRemoveAttribute(LLVMValueRef Arg, LLVMAttribute PA); - -/** - * Get an attribute from a function argument. - */ -LLVMAttribute LLVMGetAttribute(LLVMValueRef Arg); - /** * Set the alignment for a function parameter. * @@ -2595,9 +2518,6 @@ void LLVMSetInstructionCallConv(LLVMValueRef Instr, unsigned CC); */ unsigned LLVMGetInstructionCallConv(LLVMValueRef Instr); -void LLVMAddInstrAttribute(LLVMValueRef Instr, unsigned index, LLVMAttribute); -void LLVMRemoveInstrAttribute(LLVMValueRef Instr, unsigned index, - LLVMAttribute); void LLVMSetInstrParamAlignment(LLVMValueRef Instr, unsigned index, unsigned Align); @@ -2962,6 +2882,8 @@ LLVMValueRef LLVMBuildFMul(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name); LLVMValueRef LLVMBuildUDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name); +LLVMValueRef LLVMBuildExactUDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); LLVMValueRef LLVMBuildSDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name); LLVMValueRef LLVMBuildExactSDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, diff --git a/contrib/llvm/include/llvm-c/Transforms/Scalar.h b/contrib/llvm/include/llvm-c/Transforms/Scalar.h index b8a09984aa4d..8991e0904849 100644 --- a/contrib/llvm/include/llvm-c/Transforms/Scalar.h +++ b/contrib/llvm/include/llvm-c/Transforms/Scalar.h @@ -56,6 +56,9 @@ void LLVMAddMergedLoadStoreMotionPass(LLVMPassManagerRef PM); /** See llvm::createGVNPass function. */ void LLVMAddGVNPass(LLVMPassManagerRef PM); +/** See llvm::createGVNPass function. */ +void LLVMAddNewGVNPass(LLVMPassManagerRef PM); + /** See llvm::createIndVarSimplifyPass function. */ void LLVMAddIndVarSimplifyPass(LLVMPassManagerRef PM); @@ -135,6 +138,9 @@ void LLVMAddCorrelatedValuePropagationPass(LLVMPassManagerRef PM); /** See llvm::createEarlyCSEPass function */ void LLVMAddEarlyCSEPass(LLVMPassManagerRef PM); +/** See llvm::createEarlyCSEPass function */ +void LLVMAddEarlyCSEMemSSAPass(LLVMPassManagerRef PM); + /** See llvm::createLowerExpectIntrinsicPass function */ void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM); diff --git a/contrib/llvm/include/llvm-c/lto.h b/contrib/llvm/include/llvm-c/lto.h index b1f5a45d6650..c3af74cdedab 100644 --- a/contrib/llvm/include/llvm-c/lto.h +++ b/contrib/llvm/include/llvm-c/lto.h @@ -44,7 +44,7 @@ typedef bool lto_bool_t; * @{ */ -#define LTO_API_VERSION 20 +#define LTO_API_VERSION 21 /** * \since prior to LTO_API_VERSION=3 @@ -145,10 +145,10 @@ extern lto_bool_t lto_module_has_objc_category(const void *mem, size_t length); /** -* Checks if a buffer is a loadable object file. -* -* \since prior to LTO_API_VERSION=3 -*/ + * Checks if a buffer is a loadable object file. + * + * \since prior to LTO_API_VERSION=3 + */ extern lto_bool_t lto_module_is_object_file_in_memory(const void *mem, size_t length); @@ -636,6 +636,29 @@ extern unsigned int thinlto_module_get_num_objects(thinlto_code_gen_t cg); extern LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t cg, unsigned int index); +/** + * Returns the number of object files produced by the ThinLTO CodeGenerator. + * + * It usually matches the number of input files, but this is not a guarantee of + * the API and may change in future implementation, so the client should not + * assume it. + * + * \since LTO_API_VERSION=21 + */ +unsigned int thinlto_module_get_num_object_files(thinlto_code_gen_t cg); + +/** + * Returns the path to the ith object file produced by the ThinLTO + * CodeGenerator. + * + * Client should use \p thinlto_module_get_num_object_files() to get the number + * of available objects. + * + * \since LTO_API_VERSION=21 + */ +const char *thinlto_module_get_object_file(thinlto_code_gen_t cg, + unsigned int index); + /** * Sets which PIC code model to generate. * Returns true on error (check lto_get_error_message() for details). @@ -724,6 +747,17 @@ extern void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg, extern void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg, const char *save_temps_dir); +/** + * Set the path to a directory where to save generated object files. This + * path can be used by a linker to request on-disk files instead of in-memory + * buffers. When set, results are available through + * thinlto_module_get_object_file() instead of thinlto_module_get_object(). + * + * \since LTO_API_VERSION=21 + */ +void thinlto_set_generated_objects_dir(thinlto_code_gen_t cg, + const char *save_temps_dir); + /** * Sets the cpu to generate code for. * diff --git a/contrib/llvm/include/llvm/ADT/APFloat.h b/contrib/llvm/include/llvm/ADT/APFloat.h index 3f6bd00a779c..00304230a991 100644 --- a/contrib/llvm/include/llvm/ADT/APFloat.h +++ b/contrib/llvm/include/llvm/ADT/APFloat.h @@ -18,12 +18,16 @@ #define LLVM_ADT_APFLOAT_H #include "llvm/ADT/APInt.h" +#include "llvm/Support/ErrorHandling.h" +#include namespace llvm { struct fltSemantics; class APSInt; class StringRef; +class APFloat; +class raw_ostream; template class SmallVectorImpl; @@ -121,33 +125,30 @@ enum lostFraction { // Example of truncated bits: /// /// New operations: sqrt, IEEE remainder, C90 fmod, nexttoward. /// -class APFloat { -public: +// This is the common type definitions shared by APFloat and its internal +// implementation classes. This struct should not define any non-static data +// members. +struct APFloatBase { /// A signed type to represent a floating point numbers unbiased exponent. typedef signed short ExponentType; /// \name Floating Point Semantics. /// @{ - static const fltSemantics IEEEhalf; - static const fltSemantics IEEEsingle; - static const fltSemantics IEEEdouble; - static const fltSemantics IEEEquad; - static const fltSemantics PPCDoubleDouble; - static const fltSemantics x87DoubleExtended; + static const fltSemantics &IEEEhalf(); + static const fltSemantics &IEEEsingle(); + static const fltSemantics &IEEEdouble(); + static const fltSemantics &IEEEquad(); + static const fltSemantics &PPCDoubleDouble(); + static const fltSemantics &x87DoubleExtended(); /// A Pseudo fltsemantic used to construct APFloats that cannot conflict with /// anything real. - static const fltSemantics Bogus; + static const fltSemantics &Bogus(); /// @} - static unsigned int semanticsPrecision(const fltSemantics &); - static ExponentType semanticsMinExponent(const fltSemantics &); - static ExponentType semanticsMaxExponent(const fltSemantics &); - static unsigned int semanticsSizeInBits(const fltSemantics &); - /// IEEE-754R 5.11: Floating Point Comparison Relations. enum cmpResult { cmpLessThan, @@ -190,19 +191,39 @@ public: uninitialized }; + /// \brief Enumeration of \c ilogb error results. + enum IlogbErrorKinds { + IEK_Zero = INT_MIN + 1, + IEK_NaN = INT_MIN, + IEK_Inf = INT_MAX + }; + + static unsigned int semanticsPrecision(const fltSemantics &); + static ExponentType semanticsMinExponent(const fltSemantics &); + static ExponentType semanticsMaxExponent(const fltSemantics &); + static unsigned int semanticsSizeInBits(const fltSemantics &); + + /// Returns the size of the floating point number (in bits) in the given + /// semantics. + static unsigned getSizeInBits(const fltSemantics &Sem); +}; + +namespace detail { + +class IEEEFloat final : public APFloatBase { +public: /// \name Constructors /// @{ - APFloat(const fltSemantics &); // Default construct to 0.0 - APFloat(const fltSemantics &, StringRef); - APFloat(const fltSemantics &, integerPart); - APFloat(const fltSemantics &, uninitializedTag); - APFloat(const fltSemantics &, const APInt &); - explicit APFloat(double d); - explicit APFloat(float f); - APFloat(const APFloat &); - APFloat(APFloat &&); - ~APFloat(); + IEEEFloat(const fltSemantics &); // Default construct to 0.0 + IEEEFloat(const fltSemantics &, integerPart); + IEEEFloat(const fltSemantics &, uninitializedTag); + IEEEFloat(const fltSemantics &, const APInt &); + explicit IEEEFloat(double d); + explicit IEEEFloat(float f); + IEEEFloat(const IEEEFloat &); + IEEEFloat(IEEEFloat &&); + ~IEEEFloat(); /// @} @@ -212,79 +233,6 @@ public: /// \name Convenience "constructors" /// @{ - /// Factory for Positive and Negative Zero. - /// - /// \param Negative True iff the number should be negative. - static APFloat getZero(const fltSemantics &Sem, bool Negative = false) { - APFloat Val(Sem, uninitialized); - Val.makeZero(Negative); - return Val; - } - - /// Factory for Positive and Negative Infinity. - /// - /// \param Negative True iff the number should be negative. - static APFloat getInf(const fltSemantics &Sem, bool Negative = false) { - APFloat Val(Sem, uninitialized); - Val.makeInf(Negative); - return Val; - } - - /// Factory for QNaN values. - /// - /// \param Negative - True iff the NaN generated should be negative. - /// \param type - The unspecified fill bits for creating the NaN, 0 by - /// default. The value is truncated as necessary. - static APFloat getNaN(const fltSemantics &Sem, bool Negative = false, - unsigned type = 0) { - if (type) { - APInt fill(64, type); - return getQNaN(Sem, Negative, &fill); - } else { - return getQNaN(Sem, Negative, nullptr); - } - } - - /// Factory for QNaN values. - static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false, - const APInt *payload = nullptr) { - return makeNaN(Sem, false, Negative, payload); - } - - /// Factory for SNaN values. - static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false, - const APInt *payload = nullptr) { - return makeNaN(Sem, true, Negative, payload); - } - - /// Returns the largest finite number in the given semantics. - /// - /// \param Negative - True iff the number should be negative - static APFloat getLargest(const fltSemantics &Sem, bool Negative = false); - - /// Returns the smallest (by magnitude) finite number in the given semantics. - /// Might be denormalized, which implies a relative loss of precision. - /// - /// \param Negative - True iff the number should be negative - static APFloat getSmallest(const fltSemantics &Sem, bool Negative = false); - - /// Returns the smallest (by magnitude) normalized finite number in the given - /// semantics. - /// - /// \param Negative - True iff the number should be negative - static APFloat getSmallestNormalized(const fltSemantics &Sem, - bool Negative = false); - - /// 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); - - /// Returns the size of the floating point number (in bits) in the given - /// semantics. - static unsigned getSizeInBits(const fltSemantics &Sem); - /// @} /// Used to insert APFloat objects, or objects that contain APFloat objects, @@ -294,47 +242,47 @@ public: /// \name Arithmetic /// @{ - opStatus add(const APFloat &, roundingMode); - opStatus subtract(const APFloat &, roundingMode); - opStatus multiply(const APFloat &, roundingMode); - opStatus divide(const APFloat &, roundingMode); + opStatus add(const IEEEFloat &, roundingMode); + opStatus subtract(const IEEEFloat &, roundingMode); + opStatus multiply(const IEEEFloat &, roundingMode); + opStatus divide(const IEEEFloat &, roundingMode); /// IEEE remainder. - opStatus remainder(const APFloat &); + opStatus remainder(const IEEEFloat &); /// C fmod, or llvm frem. - opStatus mod(const APFloat &); - opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode); + opStatus mod(const IEEEFloat &); + opStatus fusedMultiplyAdd(const IEEEFloat &, const IEEEFloat &, roundingMode); opStatus roundToIntegral(roundingMode); /// IEEE-754R 5.3.1: nextUp/nextDown. opStatus next(bool nextDown); /// \brief Operator+ overload which provides the default /// \c nmNearestTiesToEven rounding mode and *no* error checking. - APFloat operator+(const APFloat &RHS) const { - APFloat Result = *this; + IEEEFloat operator+(const IEEEFloat &RHS) const { + IEEEFloat Result = *this; Result.add(RHS, rmNearestTiesToEven); return Result; } /// \brief Operator- overload which provides the default /// \c nmNearestTiesToEven rounding mode and *no* error checking. - APFloat operator-(const APFloat &RHS) const { - APFloat Result = *this; + IEEEFloat operator-(const IEEEFloat &RHS) const { + IEEEFloat Result = *this; Result.subtract(RHS, rmNearestTiesToEven); return Result; } /// \brief Operator* overload which provides the default /// \c nmNearestTiesToEven rounding mode and *no* error checking. - APFloat operator*(const APFloat &RHS) const { - APFloat Result = *this; + IEEEFloat operator*(const IEEEFloat &RHS) const { + IEEEFloat Result = *this; Result.multiply(RHS, rmNearestTiesToEven); return Result; } /// \brief Operator/ overload which provides the default /// \c nmNearestTiesToEven rounding mode and *no* error checking. - APFloat operator/(const APFloat &RHS) const { - APFloat Result = *this; + IEEEFloat operator/(const IEEEFloat &RHS) const { + IEEEFloat Result = *this; Result.divide(RHS, rmNearestTiesToEven); return Result; } @@ -346,11 +294,11 @@ public: void changeSign(); void clearSign(); - void copySign(const APFloat &); + void copySign(const IEEEFloat &); /// \brief A static helper to produce a copy of an APFloat value with its sign /// copied from some other APFloat. - static APFloat copySign(APFloat Value, const APFloat &Sign) { + static IEEEFloat copySign(IEEEFloat Value, const IEEEFloat &Sign) { Value.copySign(Sign); return Value; } @@ -379,14 +327,14 @@ public: /// The definition of equality is not straightforward for floating point, so /// we won't use operator==. Use one of the following, or write whatever it /// is you really mean. - bool operator==(const APFloat &) const = delete; + bool operator==(const IEEEFloat &) const = delete; /// IEEE comparison with another floating point number (NaNs compare /// unordered, 0==-0). - cmpResult compare(const APFloat &) const; + cmpResult compare(const IEEEFloat &) const; /// Bitwise comparison for equality (QNaNs compare equal, 0!=-0). - bool bitwiseIsEqual(const APFloat &) const; + bool bitwiseIsEqual(const IEEEFloat &) const; /// Write out a hexadecimal representation of the floating point value to DST, /// which must be of sufficient size, in the C99 form [-]0xh.hhhhp[+-]d. @@ -456,8 +404,8 @@ public: /// @} - APFloat &operator=(const APFloat &); - APFloat &operator=(APFloat &&); + IEEEFloat &operator=(const IEEEFloat &); + IEEEFloat &operator=(IEEEFloat &&); /// \brief Overload to compute a hash code for an APFloat value. /// @@ -468,7 +416,7 @@ public: /// emphasizes producing different codes for different inputs in order to /// be used in canonicalization and memoization. As such, equality is /// bitwiseIsEqual, and 0 != -0. - friend hash_code hash_value(const APFloat &Arg); + friend hash_code hash_value(const IEEEFloat &Arg); /// Converts this value into a decimal string. /// @@ -495,14 +443,7 @@ public: /// If this value has an exact multiplicative inverse, store it in inv and /// return true. - bool getExactInverse(APFloat *inv) const; - - /// \brief Enumeration of \c ilogb error results. - enum IlogbErrorKinds { - IEK_Zero = INT_MIN+1, - IEK_NaN = INT_MIN, - IEK_Inf = INT_MAX - }; + bool getExactInverse(IEEEFloat *inv) const; /// \brief Returns the exponent of the internal representation of the APFloat. /// @@ -513,15 +454,35 @@ public: /// 0 -> \c IEK_Zero /// Inf -> \c IEK_Inf /// - friend int ilogb(const APFloat &Arg); + friend int ilogb(const IEEEFloat &Arg); /// \brief Returns: X * 2^Exp for integral exponents. - friend APFloat scalbn(APFloat X, int Exp, roundingMode); + friend IEEEFloat scalbn(IEEEFloat X, int Exp, roundingMode); - friend APFloat frexp(const APFloat &X, int &Exp, roundingMode); + friend IEEEFloat frexp(const IEEEFloat &X, int &Exp, roundingMode); + + /// \name Special value setters. + /// @{ + + void makeLargest(bool Neg = false); + void makeSmallest(bool Neg = false); + void makeNaN(bool SNaN = false, bool Neg = false, + const APInt *fill = nullptr); + void makeInf(bool Neg = false); + void makeZero(bool Neg = false); + void makeQuiet(); + + /// Returns the smallest (by magnitude) normalized finite number in the given + /// semantics. + /// + /// \param Negative - True iff the number should be negative + void makeSmallestNormalized(bool Negative = false); + + /// @} + + cmpResult compareAbsoluteValue(const IEEEFloat &) const; private: - /// \name Simple Queries /// @{ @@ -534,11 +495,11 @@ private: /// \name Significand operations. /// @{ - integerPart addSignificand(const APFloat &); - integerPart subtractSignificand(const APFloat &, integerPart); - lostFraction addOrSubtractSignificand(const APFloat &, bool subtract); - lostFraction multiplySignificand(const APFloat &, const APFloat *); - lostFraction divideSignificand(const APFloat &); + integerPart addSignificand(const IEEEFloat &); + integerPart subtractSignificand(const IEEEFloat &, integerPart); + lostFraction addOrSubtractSignificand(const IEEEFloat &, bool subtract); + lostFraction multiplySignificand(const IEEEFloat &, const IEEEFloat *); + lostFraction divideSignificand(const IEEEFloat &); void incrementSignificand(); void initialize(const fltSemantics *); void shiftSignificandLeft(unsigned int); @@ -556,25 +517,10 @@ private: /// \name Arithmetic on special values. /// @{ - opStatus addOrSubtractSpecials(const APFloat &, bool subtract); - opStatus divideSpecials(const APFloat &); - opStatus multiplySpecials(const APFloat &); - opStatus modSpecials(const APFloat &); - - /// @} - - /// \name Special value setters. - /// @{ - - void makeLargest(bool Neg = false); - void makeSmallest(bool Neg = false); - void makeNaN(bool SNaN = false, bool Neg = false, - const APInt *fill = nullptr); - static APFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, - const APInt *fill); - void makeInf(bool Neg = false); - void makeZero(bool Neg = false); - void makeQuiet(); + opStatus addOrSubtractSpecials(const IEEEFloat &, bool subtract); + opStatus divideSpecials(const IEEEFloat &); + opStatus multiplySpecials(const IEEEFloat &); + opStatus modSpecials(const IEEEFloat &); /// @} @@ -583,8 +529,7 @@ private: bool convertFromStringSpecials(StringRef str); opStatus normalize(roundingMode, lostFraction); - opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract); - cmpResult compareAbsoluteValue(const APFloat &) const; + opStatus addOrSubtract(const IEEEFloat &, roundingMode, bool subtract); opStatus handleOverflow(roundingMode); bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const; opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool, @@ -614,10 +559,11 @@ private: void initFromF80LongDoubleAPInt(const APInt &api); void initFromPPCDoubleDoubleAPInt(const APInt &api); - void assign(const APFloat &); - void copySignificand(const APFloat &); + void assign(const IEEEFloat &); + void copySignificand(const IEEEFloat &); void freeSignificand(); + /// Note: this must be the first data member. /// The semantics that this value obeys. const fltSemantics *semantics; @@ -642,20 +588,513 @@ private: unsigned int sign : 1; }; +hash_code hash_value(const IEEEFloat &Arg); +int ilogb(const IEEEFloat &Arg); +IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode); +IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM); + +// This mode implements more precise float in terms of two APFloats. +// The interface and layout is designed for arbitray underlying semantics, +// though currently only PPCDoubleDouble semantics are supported, whose +// corresponding underlying semantics are IEEEdouble. +class DoubleAPFloat final : public APFloatBase { + // Note: this must be the first data member. + const fltSemantics *Semantics; + std::unique_ptr Floats; + + opStatus addImpl(const APFloat &a, const APFloat &aa, const APFloat &c, + const APFloat &cc, roundingMode RM); + + opStatus addWithSpecial(const DoubleAPFloat &LHS, const DoubleAPFloat &RHS, + DoubleAPFloat &Out, roundingMode RM); + +public: + DoubleAPFloat(const fltSemantics &S); + DoubleAPFloat(const fltSemantics &S, uninitializedTag); + DoubleAPFloat(const fltSemantics &S, integerPart); + DoubleAPFloat(const fltSemantics &S, const APInt &I); + DoubleAPFloat(const fltSemantics &S, APFloat &&First, APFloat &&Second); + DoubleAPFloat(const DoubleAPFloat &RHS); + DoubleAPFloat(DoubleAPFloat &&RHS); + + DoubleAPFloat &operator=(const DoubleAPFloat &RHS); + + DoubleAPFloat &operator=(DoubleAPFloat &&RHS) { + if (this != &RHS) { + this->~DoubleAPFloat(); + new (this) DoubleAPFloat(std::move(RHS)); + } + return *this; + } + + bool needsCleanup() const { return Floats != nullptr; } + + APFloat &getFirst() { return Floats[0]; } + const APFloat &getFirst() const { return Floats[0]; } + APFloat &getSecond() { return Floats[1]; } + const APFloat &getSecond() const { return Floats[1]; } + + opStatus add(const DoubleAPFloat &RHS, roundingMode RM); + opStatus subtract(const DoubleAPFloat &RHS, roundingMode RM); + void changeSign(); + cmpResult compareAbsoluteValue(const DoubleAPFloat &RHS) const; + + fltCategory getCategory() const; + bool isNegative() const; + + void makeInf(bool Neg); + void makeNaN(bool SNaN, bool Neg, const APInt *fill); +}; + +} // End detail namespace + +// This is a interface class that is currently forwarding functionalities from +// detail::IEEEFloat. +class APFloat : public APFloatBase { + typedef detail::IEEEFloat IEEEFloat; + typedef detail::DoubleAPFloat DoubleAPFloat; + + static_assert(std::is_standard_layout::value, ""); + + union Storage { + const fltSemantics *semantics; + IEEEFloat IEEE; + DoubleAPFloat Double; + + explicit Storage(IEEEFloat F, const fltSemantics &S); + explicit Storage(DoubleAPFloat F, const fltSemantics &S) + : Double(std::move(F)) { + assert(&S == &PPCDoubleDouble()); + } + + template + Storage(const fltSemantics &Semantics, ArgTypes &&... Args) { + if (usesLayout(Semantics)) { + new (&IEEE) IEEEFloat(Semantics, std::forward(Args)...); + return; + } + if (usesLayout(Semantics)) { + new (&Double) DoubleAPFloat(Semantics, std::forward(Args)...); + return; + } + llvm_unreachable("Unexpected semantics"); + } + + ~Storage() { + if (usesLayout(*semantics)) { + IEEE.~IEEEFloat(); + return; + } + if (usesLayout(*semantics)) { + Double.~DoubleAPFloat(); + return; + } + llvm_unreachable("Unexpected semantics"); + } + + Storage(const Storage &RHS) { + if (usesLayout(*RHS.semantics)) { + new (this) IEEEFloat(RHS.IEEE); + return; + } + if (usesLayout(*RHS.semantics)) { + new (this) DoubleAPFloat(RHS.Double); + return; + } + llvm_unreachable("Unexpected semantics"); + } + + Storage(Storage &&RHS) { + if (usesLayout(*RHS.semantics)) { + new (this) IEEEFloat(std::move(RHS.IEEE)); + return; + } + if (usesLayout(*RHS.semantics)) { + new (this) DoubleAPFloat(std::move(RHS.Double)); + return; + } + llvm_unreachable("Unexpected semantics"); + } + + Storage &operator=(const Storage &RHS) { + if (usesLayout(*semantics) && + usesLayout(*RHS.semantics)) { + IEEE = RHS.IEEE; + } else if (usesLayout(*semantics) && + usesLayout(*RHS.semantics)) { + Double = RHS.Double; + } else if (this != &RHS) { + this->~Storage(); + new (this) Storage(RHS); + } + return *this; + } + + Storage &operator=(Storage &&RHS) { + if (usesLayout(*semantics) && + usesLayout(*RHS.semantics)) { + IEEE = std::move(RHS.IEEE); + } else if (usesLayout(*semantics) && + usesLayout(*RHS.semantics)) { + Double = std::move(RHS.Double); + } else if (this != &RHS) { + this->~Storage(); + new (this) Storage(std::move(RHS)); + } + return *this; + } + } U; + + template static bool usesLayout(const fltSemantics &Semantics) { + static_assert(std::is_same::value || + std::is_same::value, ""); + if (std::is_same::value) { + return &Semantics == &PPCDoubleDouble(); + } + return &Semantics != &PPCDoubleDouble(); + } + + IEEEFloat &getIEEE() { + if (usesLayout(*U.semantics)) + return U.IEEE; + if (usesLayout(*U.semantics)) + return U.Double.getFirst().U.IEEE; + llvm_unreachable("Unexpected semantics"); + } + + const IEEEFloat &getIEEE() const { + if (usesLayout(*U.semantics)) + return U.IEEE; + if (usesLayout(*U.semantics)) + return U.Double.getFirst().U.IEEE; + llvm_unreachable("Unexpected semantics"); + } + + void makeZero(bool Neg) { getIEEE().makeZero(Neg); } + + void makeInf(bool Neg) { + if (usesLayout(*U.semantics)) + return U.IEEE.makeInf(Neg); + if (usesLayout(*U.semantics)) + return U.Double.makeInf(Neg); + llvm_unreachable("Unexpected semantics"); + } + + void makeNaN(bool SNaN, bool Neg, const APInt *fill) { + getIEEE().makeNaN(SNaN, Neg, fill); + } + + void makeLargest(bool Neg) { getIEEE().makeLargest(Neg); } + + void makeSmallest(bool Neg) { getIEEE().makeSmallest(Neg); } + + void makeSmallestNormalized(bool Neg) { + getIEEE().makeSmallestNormalized(Neg); + } + + // FIXME: This is due to clang 3.3 (or older version) always checks for the + // default constructor in an array aggregate initialization, even if no + // elements in the array is default initialized. + APFloat() : U(IEEEdouble()) { + llvm_unreachable("This is a workaround for old clang."); + } + + explicit APFloat(IEEEFloat F, const fltSemantics &S) : U(std::move(F), S) {} + explicit APFloat(DoubleAPFloat F, const fltSemantics &S) + : U(std::move(F), S) {} + + cmpResult compareAbsoluteValue(const APFloat &RHS) const { + assert(&getSemantics() == &RHS.getSemantics()); + if (usesLayout(getSemantics())) + return U.IEEE.compareAbsoluteValue(RHS.U.IEEE); + if (usesLayout(getSemantics())) + return U.Double.compareAbsoluteValue(RHS.U.Double); + llvm_unreachable("Unexpected semantics"); + } + +public: + APFloat(const fltSemantics &Semantics) : U(Semantics) {} + APFloat(const fltSemantics &Semantics, StringRef S); + APFloat(const fltSemantics &Semantics, integerPart I) : U(Semantics, I) {} + // TODO: Remove this constructor. This isn't faster than the first one. + APFloat(const fltSemantics &Semantics, uninitializedTag) + : U(Semantics, uninitialized) {} + APFloat(const fltSemantics &Semantics, const APInt &I) : U(Semantics, I) {} + explicit APFloat(double d) : U(IEEEFloat(d), IEEEdouble()) {} + explicit APFloat(float f) : U(IEEEFloat(f), IEEEsingle()) {} + APFloat(const APFloat &RHS) = default; + APFloat(APFloat &&RHS) = default; + + ~APFloat() = default; + + bool needsCleanup() const { + if (usesLayout(getSemantics())) + return U.IEEE.needsCleanup(); + if (usesLayout(getSemantics())) + return U.Double.needsCleanup(); + llvm_unreachable("Unexpected semantics"); + } + + /// Factory for Positive and Negative Zero. + /// + /// \param Negative True iff the number should be negative. + static APFloat getZero(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeZero(Negative); + return Val; + } + + /// Factory for Positive and Negative Infinity. + /// + /// \param Negative True iff the number should be negative. + static APFloat getInf(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeInf(Negative); + return Val; + } + + /// Factory for NaN values. + /// + /// \param Negative - True iff the NaN generated should be negative. + /// \param type - The unspecified fill bits for creating the NaN, 0 by + /// default. The value is truncated as necessary. + static APFloat getNaN(const fltSemantics &Sem, bool Negative = false, + unsigned type = 0) { + if (type) { + APInt fill(64, type); + return getQNaN(Sem, Negative, &fill); + } else { + return getQNaN(Sem, Negative, nullptr); + } + } + + /// Factory for QNaN values. + static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false, + const APInt *payload = nullptr) { + APFloat Val(Sem, uninitialized); + Val.makeNaN(false, Negative, payload); + return Val; + } + + /// Factory for SNaN values. + static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false, + const APInt *payload = nullptr) { + APFloat Val(Sem, uninitialized); + Val.makeNaN(true, Negative, payload); + return Val; + } + + /// Returns the largest finite number in the given semantics. + /// + /// \param Negative - True iff the number should be negative + static APFloat getLargest(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeLargest(Negative); + return Val; + } + + /// Returns the smallest (by magnitude) finite number in the given semantics. + /// Might be denormalized, which implies a relative loss of precision. + /// + /// \param Negative - True iff the number should be negative + static APFloat getSmallest(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeSmallest(Negative); + return Val; + } + + /// Returns the smallest (by magnitude) normalized finite number in the given + /// semantics. + /// + /// \param Negative - True iff the number should be negative + static APFloat getSmallestNormalized(const fltSemantics &Sem, + bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeSmallestNormalized(Negative); + return Val; + } + + /// 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); + + void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); } + + opStatus add(const APFloat &RHS, roundingMode RM) { + if (usesLayout(getSemantics())) + return U.IEEE.add(RHS.U.IEEE, RM); + if (usesLayout(getSemantics())) + return U.Double.add(RHS.U.Double, RM); + llvm_unreachable("Unexpected semantics"); + } + opStatus subtract(const APFloat &RHS, roundingMode RM) { + if (usesLayout(getSemantics())) + return U.IEEE.subtract(RHS.U.IEEE, RM); + if (usesLayout(getSemantics())) + return U.Double.subtract(RHS.U.Double, RM); + llvm_unreachable("Unexpected semantics"); + } + opStatus multiply(const APFloat &RHS, roundingMode RM) { + return getIEEE().multiply(RHS.getIEEE(), RM); + } + opStatus divide(const APFloat &RHS, roundingMode RM) { + return getIEEE().divide(RHS.getIEEE(), RM); + } + opStatus remainder(const APFloat &RHS) { + return getIEEE().remainder(RHS.getIEEE()); + } + opStatus mod(const APFloat &RHS) { return getIEEE().mod(RHS.getIEEE()); } + opStatus fusedMultiplyAdd(const APFloat &Multiplicand, const APFloat &Addend, + roundingMode RM) { + return getIEEE().fusedMultiplyAdd(Multiplicand.getIEEE(), Addend.getIEEE(), + RM); + } + opStatus roundToIntegral(roundingMode RM) { + return getIEEE().roundToIntegral(RM); + } + opStatus next(bool nextDown) { return getIEEE().next(nextDown); } + + APFloat operator+(const APFloat &RHS) const { + return APFloat(getIEEE() + RHS.getIEEE(), getSemantics()); + } + + APFloat operator-(const APFloat &RHS) const { + return APFloat(getIEEE() - RHS.getIEEE(), getSemantics()); + } + + APFloat operator*(const APFloat &RHS) const { + return APFloat(getIEEE() * RHS.getIEEE(), getSemantics()); + } + + APFloat operator/(const APFloat &RHS) const { + return APFloat(getIEEE() / RHS.getIEEE(), getSemantics()); + } + + void changeSign() { getIEEE().changeSign(); } + void clearSign() { getIEEE().clearSign(); } + void copySign(const APFloat &RHS) { getIEEE().copySign(RHS.getIEEE()); } + + static APFloat copySign(APFloat Value, const APFloat &Sign) { + return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE()), + Value.getSemantics()); + } + + opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, + bool *losesInfo); + opStatus convertToInteger(integerPart *Input, unsigned int Width, + bool IsSigned, roundingMode RM, + bool *IsExact) const { + return getIEEE().convertToInteger(Input, Width, IsSigned, RM, IsExact); + } + opStatus convertToInteger(APSInt &Result, roundingMode RM, + bool *IsExact) const { + return getIEEE().convertToInteger(Result, RM, IsExact); + } + opStatus convertFromAPInt(const APInt &Input, bool IsSigned, + roundingMode RM) { + return getIEEE().convertFromAPInt(Input, IsSigned, RM); + } + opStatus convertFromSignExtendedInteger(const integerPart *Input, + unsigned int InputSize, bool IsSigned, + roundingMode RM) { + return getIEEE().convertFromSignExtendedInteger(Input, InputSize, IsSigned, + RM); + } + opStatus convertFromZeroExtendedInteger(const integerPart *Input, + unsigned int InputSize, bool IsSigned, + roundingMode RM) { + return getIEEE().convertFromZeroExtendedInteger(Input, InputSize, IsSigned, + RM); + } + opStatus convertFromString(StringRef, roundingMode); + APInt bitcastToAPInt() const { return getIEEE().bitcastToAPInt(); } + double convertToDouble() const { return getIEEE().convertToDouble(); } + float convertToFloat() const { return getIEEE().convertToFloat(); } + + bool operator==(const APFloat &) const = delete; + + cmpResult compare(const APFloat &RHS) const { + return getIEEE().compare(RHS.getIEEE()); + } + + bool bitwiseIsEqual(const APFloat &RHS) const { + return getIEEE().bitwiseIsEqual(RHS.getIEEE()); + } + + unsigned int convertToHexString(char *DST, unsigned int HexDigits, + bool UpperCase, roundingMode RM) const { + return getIEEE().convertToHexString(DST, HexDigits, UpperCase, RM); + } + + bool isZero() const { return getCategory() == fcZero; } + bool isInfinity() const { return getCategory() == fcInfinity; } + bool isNaN() const { return getCategory() == fcNaN; } + + bool isNegative() const { return getIEEE().isNegative(); } + bool isDenormal() const { return getIEEE().isDenormal(); } + bool isSignaling() const { return getIEEE().isSignaling(); } + + bool isNormal() const { return !isDenormal() && isFiniteNonZero(); } + bool isFinite() const { return !isNaN() && !isInfinity(); } + + fltCategory getCategory() const { return getIEEE().getCategory(); } + const fltSemantics &getSemantics() const { return *U.semantics; } + bool isNonZero() const { return !isZero(); } + bool isFiniteNonZero() const { return isFinite() && !isZero(); } + bool isPosZero() const { return isZero() && !isNegative(); } + bool isNegZero() const { return isZero() && isNegative(); } + bool isSmallest() const { return getIEEE().isSmallest(); } + bool isLargest() const { return getIEEE().isLargest(); } + bool isInteger() const { return getIEEE().isInteger(); } + + APFloat &operator=(const APFloat &RHS) = default; + APFloat &operator=(APFloat &&RHS) = default; + + void toString(SmallVectorImpl &Str, unsigned FormatPrecision = 0, + unsigned FormatMaxPadding = 3) const { + return getIEEE().toString(Str, FormatPrecision, FormatMaxPadding); + } + + void print(raw_ostream &) const; + void dump() const; + + bool getExactInverse(APFloat *inv) const { + return getIEEE().getExactInverse(inv ? &inv->getIEEE() : nullptr); + } + + // This is for internal test only. + // TODO: Remove it after the PPCDoubleDouble transition. + const APFloat &getSecondFloat() const { + assert(&getSemantics() == &PPCDoubleDouble()); + return U.Double.getSecond(); + } + + friend hash_code hash_value(const APFloat &Arg); + friend int ilogb(const APFloat &Arg) { return ilogb(Arg.getIEEE()); } + friend APFloat scalbn(APFloat X, int Exp, roundingMode RM); + friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM); + friend IEEEFloat; + friend DoubleAPFloat; +}; + /// See friend declarations above. /// /// These additional declarations are required in order to compile LLVM with IBM /// xlC compiler. hash_code hash_value(const APFloat &Arg); -int ilogb(const APFloat &Arg); -APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode); +inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) { + return APFloat(scalbn(X.getIEEE(), Exp, RM), X.getSemantics()); +} /// \brief Equivalent of C standard library function. /// /// While the C standard says Exp is an unspecified value for infinity and nan, /// this returns INT_MAX for infinities, and INT_MIN for NaNs. -APFloat frexp(const APFloat &Val, int &Exp, APFloat::roundingMode RM); - +inline APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM) { + return APFloat(frexp(X.getIEEE(), Exp, RM), X.getSemantics()); +} /// \brief Returns the absolute value of the argument. inline APFloat abs(APFloat X) { X.clearSign(); diff --git a/contrib/llvm/include/llvm/ADT/APInt.h b/contrib/llvm/include/llvm/ADT/APInt.h index d77d1c7ca93f..2c0713da256c 100644 --- a/contrib/llvm/include/llvm/ADT/APInt.h +++ b/contrib/llvm/include/llvm/ADT/APInt.h @@ -40,6 +40,10 @@ const unsigned int host_char_bit = 8; const unsigned int integerPartWidth = host_char_bit * static_cast(sizeof(integerPart)); +class APInt; + +inline APInt operator-(APInt); + //===----------------------------------------------------------------------===// // APInt Class //===----------------------------------------------------------------------===// @@ -70,7 +74,7 @@ const unsigned int integerPartWidth = /// * In general, the class tries to follow the style of computation that LLVM /// uses in its IR. This simplifies its use for LLVM. /// -class APInt { +class LLVM_NODISCARD APInt { unsigned BitWidth; ///< The number of bits in this APInt. /// This union is used to store the integer value. When the @@ -620,18 +624,6 @@ public: return Result; } - /// \brief Unary negation operator - /// - /// Negates *this using two's complement logic. - /// - /// \returns An APInt value representing the negation of *this. - APInt operator-() const { - APInt Result(*this); - Result.flipAllBits(); - ++Result; - return Result; - } - /// \brief Logical negation operator. /// /// Performs logical negation operation on this APInt. @@ -750,6 +742,7 @@ public: /// /// \returns *this APInt &operator+=(const APInt &RHS); + APInt &operator+=(uint64_t RHS); /// \brief Subtraction assignment operator. /// @@ -757,6 +750,7 @@ public: /// /// \returns *this APInt &operator-=(const APInt &RHS); + APInt &operator-=(uint64_t RHS); /// \brief Left-shift assignment function. /// @@ -783,9 +777,7 @@ public: return APInt(getBitWidth(), VAL & RHS.VAL); return AndSlowCase(RHS); } - APInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APInt &RHS) const { - return this->operator&(RHS); - } + APInt And(const APInt &RHS) const { return this->operator&(RHS); } /// \brief Bitwise OR operator. /// @@ -805,9 +797,7 @@ public: /// calling operator|. /// /// \returns An APInt value representing the bitwise OR of *this and RHS. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APInt &RHS) const { - return this->operator|(RHS); - } + APInt Or(const APInt &RHS) const { return this->operator|(RHS); } /// \brief Bitwise XOR operator. /// @@ -827,27 +817,13 @@ public: /// through the usage of operator^. /// /// \returns An APInt value representing the bitwise XOR of *this and RHS. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APInt &RHS) const { - return this->operator^(RHS); - } + APInt Xor(const APInt &RHS) const { return this->operator^(RHS); } /// \brief Multiplication operator. /// /// Multiplies this APInt by RHS and returns the result. APInt operator*(const APInt &RHS) const; - /// \brief Addition operator. - /// - /// Adds RHS to this APInt and returns the result. - APInt operator+(const APInt &RHS) const; - APInt operator+(uint64_t RHS) const; - - /// \brief Subtraction operator. - /// - /// Subtracts RHS from this APInt and returns the result. - APInt operator-(const APInt &RHS) const; - APInt operator-(uint64_t RHS) const; - /// \brief Left logical shift operator. /// /// Shifts this APInt left by \p Bits and returns the result. @@ -861,17 +837,17 @@ public: /// \brief Arithmetic right-shift function. /// /// Arithmetic right-shift this APInt by shiftAmt. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT ashr(unsigned shiftAmt) const; + APInt ashr(unsigned shiftAmt) const; /// \brief Logical right-shift function. /// /// Logical right-shift this APInt by shiftAmt. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT lshr(unsigned shiftAmt) const; + APInt lshr(unsigned shiftAmt) const; /// \brief Left-shift function. /// /// Left-shift this APInt by shiftAmt. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT shl(unsigned shiftAmt) const { + APInt shl(unsigned shiftAmt) const { assert(shiftAmt <= BitWidth && "Invalid shift amount"); if (isSingleWord()) { if (shiftAmt >= BitWidth) @@ -882,31 +858,31 @@ public: } /// \brief Rotate left by rotateAmt. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotl(unsigned rotateAmt) const; + APInt rotl(unsigned rotateAmt) const; /// \brief Rotate right by rotateAmt. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotr(unsigned rotateAmt) const; + APInt rotr(unsigned rotateAmt) const; /// \brief Arithmetic right-shift function. /// /// Arithmetic right-shift this APInt by shiftAmt. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT ashr(const APInt &shiftAmt) const; + APInt ashr(const APInt &shiftAmt) const; /// \brief Logical right-shift function. /// /// Logical right-shift this APInt by shiftAmt. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT lshr(const APInt &shiftAmt) const; + APInt lshr(const APInt &shiftAmt) const; /// \brief Left-shift function. /// /// Left-shift this APInt by shiftAmt. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT shl(const APInt &shiftAmt) const; + APInt shl(const APInt &shiftAmt) const; /// \brief Rotate left by rotateAmt. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotl(const APInt &rotateAmt) const; + APInt rotl(const APInt &rotateAmt) const; /// \brief Rotate right by rotateAmt. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotr(const APInt &rotateAmt) const; + APInt rotr(const APInt &rotateAmt) const; /// \brief Unsigned division operation. /// @@ -914,12 +890,12 @@ public: /// RHS are treated as unsigned quantities for purposes of this division. /// /// \returns a new APInt value containing the division result - APInt LLVM_ATTRIBUTE_UNUSED_RESULT udiv(const APInt &RHS) const; + APInt udiv(const APInt &RHS) const; /// \brief Signed division function for APInt. /// /// Signed divide this APInt by APInt RHS. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT sdiv(const APInt &RHS) const; + APInt sdiv(const APInt &RHS) const; /// \brief Unsigned remainder operation. /// @@ -930,12 +906,12 @@ public: /// is *this. /// /// \returns a new APInt value containing the remainder result - APInt LLVM_ATTRIBUTE_UNUSED_RESULT urem(const APInt &RHS) const; + APInt urem(const APInt &RHS) const; /// \brief Function for signed remainder operation. /// /// Signed remainder operation on APInt. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT srem(const APInt &RHS) const; + APInt srem(const APInt &RHS) const; /// \brief Dual division/remainder interface. /// @@ -1178,7 +1154,7 @@ 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. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(unsigned width) const; + APInt trunc(unsigned width) const; /// \brief Sign extend to a new width. /// @@ -1186,38 +1162,38 @@ public: /// 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. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT sext(unsigned width) const; + APInt sext(unsigned width) const; /// \brief Zero extend to a new width. /// /// 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. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT zext(unsigned width) const; + APInt zext(unsigned width) const; /// \brief Sign extend or truncate to width /// /// 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. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT sextOrTrunc(unsigned width) const; + APInt sextOrTrunc(unsigned width) const; /// \brief Zero extend or truncate to width /// /// 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. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT zextOrTrunc(unsigned width) const; + APInt zextOrTrunc(unsigned width) const; /// \brief Sign extend or truncate to width /// /// Make this APInt have the bit width given by \p width. The value is sign /// extended, or left alone to make it that width. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT sextOrSelf(unsigned width) const; + APInt sextOrSelf(unsigned width) const; /// \brief Zero extend or truncate to width /// /// Make this APInt have the bit width given by \p width. The value is zero /// extended, or left alone to make it that width. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT zextOrSelf(unsigned width) const; + APInt zextOrSelf(unsigned width) const; /// @} /// \name Bit Manipulation Operators @@ -1454,11 +1430,11 @@ public: std::string toString(unsigned Radix, bool Signed) const; /// \returns a byte-swapped representation of this APInt Value. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT byteSwap() const; + APInt byteSwap() const; /// \returns the value with the bit representation reversed of this APInt /// Value. - APInt LLVM_ATTRIBUTE_UNUSED_RESULT reverseBits() const; + APInt reverseBits() const; /// \brief Converts this APInt to a double value. double roundToDouble(bool isSigned) const; @@ -1501,7 +1477,7 @@ public: /// /// The conversion does not do a translation from double to integer, it just /// re-interprets the bits of the double. - static APInt LLVM_ATTRIBUTE_UNUSED_RESULT doubleToBits(double V) { + static APInt doubleToBits(double V) { union { uint64_t I; double D; @@ -1514,7 +1490,7 @@ public: /// /// The conversion does not do a translation from float to integer, it just /// re-interprets the bits of the float. - static APInt LLVM_ATTRIBUTE_UNUSED_RESULT floatToBits(float V) { + static APInt floatToBits(float V) { union { unsigned I; float F; @@ -1532,7 +1508,9 @@ public: /// \returns the ceil log base 2 of this APInt. unsigned ceilLogBase2() const { - return BitWidth - (*this - 1).countLeadingZeros(); + APInt temp(*this); + --temp; + return BitWidth - temp.countLeadingZeros(); } /// \returns the nearest log base 2 of this APInt. Ties round up. @@ -1573,12 +1551,12 @@ public: } /// \brief Compute the square root - APInt LLVM_ATTRIBUTE_UNUSED_RESULT sqrt() const; + APInt sqrt() const; /// \brief Get the absolute value; /// /// If *this is < 0 then return -(*this), otherwise *this; - APInt LLVM_ATTRIBUTE_UNUSED_RESULT abs() const { + APInt abs() const { if (isNegative()) return -(*this); return *this; @@ -1750,6 +1728,55 @@ inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) { return OS; } +inline APInt operator-(APInt v) { + v.flipAllBits(); + ++v; + return v; +} + +inline APInt operator+(APInt a, const APInt &b) { + a += b; + return a; +} + +inline APInt operator+(const APInt &a, APInt &&b) { + b += a; + return std::move(b); +} + +inline APInt operator+(APInt a, uint64_t RHS) { + a += RHS; + return a; +} + +inline APInt operator+(uint64_t LHS, APInt b) { + b += LHS; + return b; +} + +inline APInt operator-(APInt a, const APInt &b) { + a -= b; + return a; +} + +inline APInt operator-(const APInt &a, APInt &&b) { + b = -std::move(b); + b += a; + return std::move(b); +} + +inline APInt operator-(APInt a, uint64_t RHS) { + a -= RHS; + return a; +} + +inline APInt operator-(uint64_t LHS, APInt b) { + b = -std::move(b); + b += LHS; + return b; +} + + namespace APIntOps { /// \brief Determine the smaller of two APInts considered to be signed. diff --git a/contrib/llvm/include/llvm/ADT/APSInt.h b/contrib/llvm/include/llvm/ADT/APSInt.h index a6552d0a2f36..813b3686d6b1 100644 --- a/contrib/llvm/include/llvm/ADT/APSInt.h +++ b/contrib/llvm/include/llvm/ADT/APSInt.h @@ -19,7 +19,7 @@ namespace llvm { -class APSInt : public APInt { +class LLVM_NODISCARD APSInt : public APInt { bool IsUnsigned; public: @@ -78,22 +78,22 @@ public: return isSigned() ? getSExtValue() : getZExtValue(); } - APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const { + APSInt trunc(uint32_t width) const { return APSInt(APInt::trunc(width), IsUnsigned); } - APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extend(uint32_t width) const { + APSInt extend(uint32_t width) const { if (IsUnsigned) return APSInt(zext(width), IsUnsigned); else return APSInt(sext(width), IsUnsigned); } - APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extOrTrunc(uint32_t width) const { - if (IsUnsigned) - return APSInt(zextOrTrunc(width), IsUnsigned); - else - return APSInt(sextOrTrunc(width), IsUnsigned); + APSInt extOrTrunc(uint32_t width) const { + if (IsUnsigned) + return APSInt(zextOrTrunc(width), IsUnsigned); + else + return APSInt(sextOrTrunc(width), IsUnsigned); } const APSInt &operator%=(const APSInt &RHS) { @@ -235,25 +235,19 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return APSInt(static_cast(*this) & RHS, IsUnsigned); } - APSInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APSInt& RHS) const { - return this->operator&(RHS); - } + APSInt And(const APSInt &RHS) const { return this->operator&(RHS); } APSInt operator|(const APSInt& RHS) const { assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return APSInt(static_cast(*this) | RHS, IsUnsigned); } - APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APSInt& RHS) const { - return this->operator|(RHS); - } + APSInt Or(const APSInt &RHS) const { return this->operator|(RHS); } APSInt operator^(const APSInt &RHS) const { assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return APSInt(static_cast(*this) ^ RHS, IsUnsigned); } - APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APSInt& RHS) const { - return this->operator^(RHS); - } + APSInt Xor(const APSInt &RHS) const { return this->operator^(RHS); } APSInt operator*(const APSInt& RHS) const { assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); diff --git a/contrib/llvm/include/llvm/ADT/AllocatorList.h b/contrib/llvm/include/llvm/ADT/AllocatorList.h new file mode 100644 index 000000000000..05a549f96ec7 --- /dev/null +++ b/contrib/llvm/include/llvm/ADT/AllocatorList.h @@ -0,0 +1,226 @@ +//===- llvm/ADT/AllocatorList.h - Custom allocator list ---------*- 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_ALLOCATORLIST_H +#define LLVM_ADT_ALLOCATORLIST_H + +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/simple_ilist.h" +#include "llvm/Support/Allocator.h" +#include + +namespace llvm { + +/// A linked-list with a custom, local allocator. +/// +/// Expose a std::list-like interface that owns and uses a custom LLVM-style +/// allocator (e.g., BumpPtrAllocator), leveraging \a simple_ilist for the +/// implementation details. +/// +/// Because this list owns the allocator, calling \a splice() with a different +/// list isn't generally safe. As such, \a splice has been left out of the +/// interface entirely. +template class AllocatorList : AllocatorT { + struct Node : ilist_node { + Node(Node &&) = delete; + Node(const Node &) = delete; + Node &operator=(Node &&) = delete; + Node &operator=(const Node &) = delete; + + Node(T &&V) : V(std::move(V)) {} + Node(const T &V) : V(V) {} + template Node(Ts &&... Vs) : V(std::forward(Vs)...) {} + T V; + }; + + typedef simple_ilist list_type; + list_type List; + + AllocatorT &getAlloc() { return *this; } + const AllocatorT &getAlloc() const { return *this; } + + template Node *create(ArgTs &&... Args) { + return new (getAlloc()) Node(std::forward(Args)...); + } + + struct Cloner { + AllocatorList &AL; + Cloner(AllocatorList &AL) : AL(AL) {} + Node *operator()(const Node &N) const { return AL.create(N.V); } + }; + + struct Disposer { + AllocatorList &AL; + Disposer(AllocatorList &AL) : AL(AL) {} + void operator()(Node *N) const { + N->~Node(); + AL.getAlloc().Deallocate(N); + } + }; + +public: + typedef T value_type; + typedef T *pointer; + typedef T &reference; + typedef const T *const_pointer; + typedef const T &const_reference; + typedef typename list_type::size_type size_type; + typedef typename list_type::difference_type difference_type; + +private: + template + class IteratorImpl + : public iterator_adaptor_base, + IteratorBase, + std::bidirectional_iterator_tag, ValueT> { + template + friend class IteratorImpl; + friend AllocatorList; + + typedef iterator_adaptor_base, + IteratorBase, std::bidirectional_iterator_tag, + ValueT> + base_type; + + public: + typedef ValueT value_type; + typedef ValueT *pointer; + typedef ValueT &reference; + + IteratorImpl() = default; + IteratorImpl(const IteratorImpl &) = default; + IteratorImpl &operator=(const IteratorImpl &) = default; + ~IteratorImpl() = default; + + explicit IteratorImpl(const IteratorBase &I) : base_type(I) {} + + template + IteratorImpl(const IteratorImpl &X, + typename std::enable_if::value>::type * = nullptr) + : base_type(X.wrapped()) {} + + reference operator*() const { return base_type::wrapped()->V; } + pointer operator->() const { return &operator*(); } + + friend bool operator==(const IteratorImpl &L, const IteratorImpl &R) { + return L.wrapped() == R.wrapped(); + } + friend bool operator!=(const IteratorImpl &L, const IteratorImpl &R) { + return !(L == R); + } + }; + +public: + typedef IteratorImpl iterator; + typedef IteratorImpl + reverse_iterator; + typedef IteratorImpl + const_iterator; + typedef IteratorImpl + const_reverse_iterator; + + AllocatorList() = default; + AllocatorList(AllocatorList &&X) + : AllocatorT(std::move(X.getAlloc())), List(std::move(X.List)) {} + AllocatorList(const AllocatorList &X) { + List.cloneFrom(X.List, Cloner(*this), Disposer(*this)); + } + AllocatorList &operator=(AllocatorList &&X) { + clear(); // Dispose of current nodes explicitly. + List = std::move(X.List); + getAlloc() = std::move(X.getAlloc()); + return *this; + } + AllocatorList &operator=(const AllocatorList &X) { + List.cloneFrom(X.List, Cloner(*this), Disposer(*this)); + return *this; + } + ~AllocatorList() { clear(); } + + void swap(AllocatorList &RHS) { + List.swap(RHS.List); + std::swap(getAlloc(), RHS.getAlloc()); + } + + bool empty() { return List.empty(); } + size_t size() { return List.size(); } + + iterator begin() { return iterator(List.begin()); } + iterator end() { return iterator(List.end()); } + const_iterator begin() const { return const_iterator(List.begin()); } + const_iterator end() const { return const_iterator(List.end()); } + reverse_iterator rbegin() { return reverse_iterator(List.rbegin()); } + reverse_iterator rend() { return reverse_iterator(List.rend()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(List.rbegin()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(List.rend()); + } + + T &back() { return List.back().V; } + T &front() { return List.front().V; } + const T &back() const { return List.back().V; } + const T &front() const { return List.front().V; } + + template iterator emplace(iterator I, Ts &&... Vs) { + return iterator(List.insert(I.wrapped(), *create(std::forward(Vs)...))); + } + + iterator insert(iterator I, T &&V) { + return iterator(List.insert(I.wrapped(), *create(std::move(V)))); + } + iterator insert(iterator I, const T &V) { + return iterator(List.insert(I.wrapped(), *create(V))); + } + + template + void insert(iterator I, Iterator First, Iterator Last) { + for (; First != Last; ++First) + List.insert(I.wrapped(), *create(*First)); + } + + iterator erase(iterator I) { + return iterator(List.eraseAndDispose(I.wrapped(), Disposer(*this))); + } + + iterator erase(iterator First, iterator Last) { + return iterator( + List.eraseAndDispose(First.wrapped(), Last.wrapped(), Disposer(*this))); + } + + void clear() { List.clearAndDispose(Disposer(*this)); } + void pop_back() { List.eraseAndDispose(--List.end(), Disposer(*this)); } + void pop_front() { List.eraseAndDispose(List.begin(), Disposer(*this)); } + void push_back(T &&V) { insert(end(), std::move(V)); } + void push_front(T &&V) { insert(begin(), std::move(V)); } + void push_back(const T &V) { insert(end(), V); } + void push_front(const T &V) { insert(begin(), V); } + template void emplace_back(Ts &&... Vs) { + emplace(end(), std::forward(Vs)...); + } + template void emplace_front(Ts &&... Vs) { + emplace(begin(), std::forward(Vs)...); + } + + /// Reset the underlying allocator. + /// + /// \pre \c empty() + void resetAlloc() { + assert(empty() && "Cannot reset allocator if not empty"); + getAlloc().Reset(); + } +}; + +template using BumpPtrList = AllocatorList; + +} // end namespace llvm + +#endif // LLVM_ADT_ALLOCATORLIST_H diff --git a/contrib/llvm/include/llvm/ADT/ArrayRef.h b/contrib/llvm/include/llvm/ADT/ArrayRef.h index 95a1e62ef005..b3fe31f4a806 100644 --- a/contrib/llvm/include/llvm/ADT/ArrayRef.h +++ b/contrib/llvm/include/llvm/ADT/ArrayRef.h @@ -12,7 +12,9 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/None.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include #include namespace llvm { @@ -28,7 +30,7 @@ namespace llvm { /// This is intended to be trivially copyable, so it should be passed by /// value. template - class ArrayRef { + class LLVM_NODISCARD ArrayRef { public: typedef const T *iterator; typedef const T *const_iterator; @@ -78,10 +80,14 @@ namespace llvm { /*implicit*/ ArrayRef(const std::vector &Vec) : Data(Vec.data()), Length(Vec.size()) {} + /// Construct an ArrayRef from a std::array + template + /*implicit*/ constexpr ArrayRef(const std::array &Arr) + : Data(Arr.data()), Length(N) {} + /// Construct an ArrayRef from a C array. template - /*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N]) - : Data(Arr), Length(N) {} + /*implicit*/ constexpr ArrayRef(const T (&Arr)[N]) : Data(Arr), Length(N) {} /// Construct an ArrayRef from a std::initializer_list. /*implicit*/ ArrayRef(const std::initializer_list &Vec) @@ -160,12 +166,6 @@ namespace llvm { return std::equal(begin(), end(), RHS.begin()); } - /// slice(n) - Chop off the first N elements of the array. - ArrayRef slice(size_t N) const { - assert(N <= size() && "Invalid specifier"); - return ArrayRef(data()+N, size()-N); - } - /// slice(n, m) - Chop off the first N elements of the array, and keep M /// elements in the array. ArrayRef slice(size_t N, size_t M) const { @@ -173,6 +173,9 @@ namespace llvm { return ArrayRef(data()+N, M); } + /// slice(n) - Chop off the first N elements of the array. + ArrayRef slice(size_t N) const { return slice(N, size() - N); } + /// \brief Drop the first \p N elements of the array. ArrayRef drop_front(size_t N = 1) const { assert(size() >= N && "Dropping more elements than exist"); @@ -185,6 +188,44 @@ namespace llvm { return slice(0, size() - N); } + /// \brief Return a copy of *this with the first N elements satisfying the + /// given predicate removed. + template ArrayRef drop_while(PredicateT Pred) const { + return ArrayRef(find_if_not(*this, Pred), end()); + } + + /// \brief Return a copy of *this with the first N elements not satisfying + /// the given predicate removed. + template ArrayRef drop_until(PredicateT Pred) const { + return ArrayRef(find_if(*this, Pred), end()); + } + + /// \brief Return a copy of *this with only the first \p N elements. + ArrayRef take_front(size_t N = 1) const { + if (N >= size()) + return *this; + return drop_back(size() - N); + } + + /// \brief Return a copy of *this with only the last \p N elements. + ArrayRef take_back(size_t N = 1) const { + if (N >= size()) + return *this; + return drop_front(size() - N); + } + + /// \brief Return the first N elements of this Array that satisfy the given + /// predicate. + template ArrayRef take_while(PredicateT Pred) const { + return ArrayRef(begin(), find_if_not(*this, Pred)); + } + + /// \brief Return the first N elements of this Array that don't satisfy the + /// given predicate. + template ArrayRef take_until(PredicateT Pred) const { + return ArrayRef(begin(), find_if(*this, Pred)); + } + /// @} /// @name Operator Overloads /// @{ @@ -193,6 +234,22 @@ namespace llvm { return Data[Index]; } + /// Disallow accidental assignment from a temporary. + /// + /// The declaration here is extra complicated so that "arrayRef = {}" + /// continues to select the move assignment operator. + template + typename std::enable_if::value, ArrayRef>::type & + operator=(U &&Temporary) = delete; + + /// Disallow accidental assignment from a temporary. + /// + /// The declaration here is extra complicated so that "arrayRef = {}" + /// continues to select the move assignment operator. + template + typename std::enable_if::value, ArrayRef>::type & + operator=(std::initializer_list) = delete; + /// @} /// @name Expensive Operations /// @{ @@ -223,7 +280,7 @@ namespace llvm { /// This is intended to be trivially copyable, so it should be passed by /// value. template - class MutableArrayRef : public ArrayRef { + class LLVM_NODISCARD MutableArrayRef : public ArrayRef { public: typedef T *iterator; @@ -253,10 +310,14 @@ namespace llvm { /*implicit*/ MutableArrayRef(std::vector &Vec) : ArrayRef(Vec) {} + /// Construct an ArrayRef from a std::array + template + /*implicit*/ constexpr MutableArrayRef(std::array &Arr) + : ArrayRef(Arr) {} + /// Construct an MutableArrayRef from a C array. template - /*implicit*/ LLVM_CONSTEXPR MutableArrayRef(T (&Arr)[N]) - : ArrayRef(Arr) {} + /*implicit*/ constexpr MutableArrayRef(T (&Arr)[N]) : ArrayRef(Arr) {} T *data() const { return const_cast(ArrayRef::data()); } @@ -278,17 +339,16 @@ namespace llvm { return data()[this->size()-1]; } - /// slice(n) - Chop off the first N elements of the array. - MutableArrayRef slice(size_t N) const { - assert(N <= this->size() && "Invalid specifier"); - return MutableArrayRef(data()+N, this->size()-N); - } - /// slice(n, m) - Chop off the first N elements of the array, and keep M /// elements in the array. MutableArrayRef slice(size_t N, size_t M) const { - assert(N+M <= this->size() && "Invalid specifier"); - return MutableArrayRef(data()+N, M); + assert(N + M <= this->size() && "Invalid specifier"); + return MutableArrayRef(this->data() + N, M); + } + + /// slice(n) - Chop off the first N elements of the array. + MutableArrayRef slice(size_t N) const { + return slice(N, this->size() - N); } /// \brief Drop the first \p N elements of the array. @@ -302,6 +362,48 @@ namespace llvm { return slice(0, this->size() - N); } + /// \brief Return a copy of *this with the first N elements satisfying the + /// given predicate removed. + template + MutableArrayRef drop_while(PredicateT Pred) const { + return MutableArrayRef(find_if_not(*this, Pred), end()); + } + + /// \brief Return a copy of *this with the first N elements not satisfying + /// the given predicate removed. + template + MutableArrayRef drop_until(PredicateT Pred) const { + return MutableArrayRef(find_if(*this, Pred), end()); + } + + /// \brief Return a copy of *this with only the first \p N elements. + MutableArrayRef take_front(size_t N = 1) const { + if (N >= this->size()) + return *this; + return drop_back(this->size() - N); + } + + /// \brief Return a copy of *this with only the last \p N elements. + MutableArrayRef take_back(size_t N = 1) const { + if (N >= this->size()) + return *this; + return drop_front(this->size() - N); + } + + /// \brief Return the first N elements of this Array that satisfy the given + /// predicate. + template + MutableArrayRef take_while(PredicateT Pred) const { + return MutableArrayRef(begin(), find_if_not(*this, Pred)); + } + + /// \brief Return the first N elements of this Array that don't satisfy the + /// given predicate. + template + MutableArrayRef take_until(PredicateT Pred) const { + return MutableArrayRef(begin(), find_if(*this, Pred)); + } + /// @} /// @name Operator Overloads /// @{ @@ -311,6 +413,25 @@ namespace llvm { } }; + /// This is a MutableArrayRef that owns its array. + template class OwningArrayRef : public MutableArrayRef { + public: + OwningArrayRef() {} + OwningArrayRef(size_t Size) : MutableArrayRef(new T[Size], Size) {} + OwningArrayRef(ArrayRef Data) + : MutableArrayRef(new T[Data.size()], Data.size()) { + std::copy(Data.begin(), Data.end(), this->begin()); + } + OwningArrayRef(OwningArrayRef &&Other) { *this = Other; } + OwningArrayRef &operator=(OwningArrayRef &&Other) { + delete[] this->data(); + this->MutableArrayRef::operator=(Other); + Other.MutableArrayRef::operator=(MutableArrayRef()); + return *this; + } + ~OwningArrayRef() { delete[] this->data(); } + }; + /// @name ArrayRef Convenience constructors /// @{ diff --git a/contrib/llvm/include/llvm/ADT/BitVector.h b/contrib/llvm/include/llvm/ADT/BitVector.h index 661437126d48..cf3756d0d9c1 100644 --- a/contrib/llvm/include/llvm/ADT/BitVector.h +++ b/contrib/llvm/include/llvm/ADT/BitVector.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace llvm { @@ -45,14 +46,13 @@ public: BitWord *WordRef; unsigned BitPos; - reference(); // Undefined - public: reference(BitVector &b, unsigned Idx) { WordRef = &b.Bits[Idx / BITWORD_SIZE]; BitPos = Idx % BITWORD_SIZE; } + reference() = delete; reference(const reference&) = default; reference &operator=(reference t) { diff --git a/contrib/llvm/include/llvm/ADT/CachedHashString.h b/contrib/llvm/include/llvm/ADT/CachedHashString.h new file mode 100644 index 000000000000..a56a6213a073 --- /dev/null +++ b/contrib/llvm/include/llvm/ADT/CachedHashString.h @@ -0,0 +1,184 @@ +//===- llvm/ADT/CachedHashString.h - Prehashed string/StringRef -*- 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 CachedHashString and CachedHashStringRef. These are owning +// and not-owning string types that store their hash in addition to their string +// data. +// +// Unlike std::string, CachedHashString can be used in DenseSet/DenseMap +// (because, unlike std::string, CachedHashString lets us have empty and +// tombstone values). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_CACHED_HASH_STRING_H +#define LLVM_ADT_CACHED_HASH_STRING_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +/// A container which contains a StringRef plus a precomputed hash. +class CachedHashStringRef { + const char *P; + uint32_t Size; + uint32_t Hash; + +public: + // Explicit because hashing a string isn't free. + explicit CachedHashStringRef(StringRef S) + : CachedHashStringRef(S, DenseMapInfo::getHashValue(S)) {} + + CachedHashStringRef(StringRef S, uint32_t Hash) + : P(S.data()), Size(S.size()), Hash(Hash) { + assert(S.size() <= std::numeric_limits::max()); + } + + StringRef val() const { return StringRef(P, Size); } + uint32_t size() const { return Size; } + uint32_t hash() const { return Hash; } +}; + +template <> struct DenseMapInfo { + static CachedHashStringRef getEmptyKey() { + return CachedHashStringRef(DenseMapInfo::getEmptyKey(), 0); + } + static CachedHashStringRef getTombstoneKey() { + return CachedHashStringRef(DenseMapInfo::getTombstoneKey(), 1); + } + static unsigned getHashValue(const CachedHashStringRef &S) { + assert(!isEqual(S, getEmptyKey()) && "Cannot hash the empty key!"); + assert(!isEqual(S, getTombstoneKey()) && "Cannot hash the tombstone key!"); + return S.hash(); + } + static bool isEqual(const CachedHashStringRef &LHS, + const CachedHashStringRef &RHS) { + return LHS.hash() == RHS.hash() && + DenseMapInfo::isEqual(LHS.val(), RHS.val()); + } +}; + +/// A container which contains a string, which it owns, plus a precomputed hash. +/// +/// We do not null-terminate the string. +class CachedHashString { + friend struct DenseMapInfo; + + char *P; + uint32_t Size; + uint32_t Hash; + + static char *getEmptyKeyPtr() { return DenseMapInfo::getEmptyKey(); } + static char *getTombstoneKeyPtr() { + return DenseMapInfo::getTombstoneKey(); + } + + bool isEmptyOrTombstone() const { + return P == getEmptyKeyPtr() || P == getTombstoneKeyPtr(); + } + + struct ConstructEmptyOrTombstoneTy {}; + + CachedHashString(ConstructEmptyOrTombstoneTy, char *EmptyOrTombstonePtr) + : P(EmptyOrTombstonePtr), Size(0), Hash(0) { + assert(isEmptyOrTombstone()); + } + + // TODO: Use small-string optimization to avoid allocating. + +public: + explicit CachedHashString(const char *S) : CachedHashString(StringRef(S)) {} + + // Explicit because copying and hashing a string isn't free. + explicit CachedHashString(StringRef S) + : CachedHashString(S, DenseMapInfo::getHashValue(S)) {} + + CachedHashString(StringRef S, uint32_t Hash) + : P(new char[S.size()]), Size(S.size()), Hash(Hash) { + memcpy(P, S.data(), S.size()); + } + + // Ideally this class would not be copyable. But SetVector requires copyable + // keys, and we want this to be usable there. + CachedHashString(const CachedHashString &Other) + : Size(Other.Size), Hash(Other.Hash) { + if (Other.isEmptyOrTombstone()) { + P = Other.P; + } else { + P = new char[Size]; + memcpy(P, Other.P, Size); + } + } + + CachedHashString &operator=(CachedHashString Other) { + swap(*this, Other); + return *this; + } + + CachedHashString(CachedHashString &&Other) noexcept + : P(Other.P), Size(Other.Size), Hash(Other.Hash) { + Other.P = getEmptyKeyPtr(); + } + + ~CachedHashString() { + if (!isEmptyOrTombstone()) + delete[] P; + } + + StringRef val() const { return StringRef(P, Size); } + uint32_t size() const { return Size; } + uint32_t hash() const { return Hash; } + + operator StringRef() const { return val(); } + operator CachedHashStringRef() const { + return CachedHashStringRef(val(), Hash); + } + + friend void swap(CachedHashString &LHS, CachedHashString &RHS) { + using std::swap; + swap(LHS.P, RHS.P); + swap(LHS.Size, RHS.Size); + swap(LHS.Hash, RHS.Hash); + } +}; + +template <> struct DenseMapInfo { + static CachedHashString getEmptyKey() { + return CachedHashString(CachedHashString::ConstructEmptyOrTombstoneTy(), + CachedHashString::getEmptyKeyPtr()); + } + static CachedHashString getTombstoneKey() { + return CachedHashString(CachedHashString::ConstructEmptyOrTombstoneTy(), + CachedHashString::getTombstoneKeyPtr()); + } + static unsigned getHashValue(const CachedHashString &S) { + assert(!isEqual(S, getEmptyKey()) && "Cannot hash the empty key!"); + assert(!isEqual(S, getTombstoneKey()) && "Cannot hash the tombstone key!"); + return S.hash(); + } + static bool isEqual(const CachedHashString &LHS, + const CachedHashString &RHS) { + if (LHS.hash() != RHS.hash()) + return false; + if (LHS.P == CachedHashString::getEmptyKeyPtr()) + return RHS.P == CachedHashString::getEmptyKeyPtr(); + if (LHS.P == CachedHashString::getTombstoneKeyPtr()) + return RHS.P == CachedHashString::getTombstoneKeyPtr(); + + // This is safe because if RHS.P is the empty or tombstone key, it will have + // length 0, so we'll never dereference its pointer. + return LHS.val() == RHS.val(); + } +}; + +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/ADT/DAGDeltaAlgorithm.h b/contrib/llvm/include/llvm/ADT/DAGDeltaAlgorithm.h index 3dd862c8b220..5ea0fe872868 100644 --- a/contrib/llvm/include/llvm/ADT/DAGDeltaAlgorithm.h +++ b/contrib/llvm/include/llvm/ADT/DAGDeltaAlgorithm.h @@ -10,6 +10,7 @@ #define LLVM_ADT_DAGDELTAALGORITHM_H #include +#include #include namespace llvm { @@ -37,6 +38,7 @@ namespace llvm { /// should satisfy. class DAGDeltaAlgorithm { virtual void anchor(); + public: typedef unsigned change_ty; typedef std::pair edge_ty; @@ -46,7 +48,7 @@ public: typedef std::vector changesetlist_ty; public: - virtual ~DAGDeltaAlgorithm() {} + virtual ~DAGDeltaAlgorithm() = default; /// Run - Minimize the DAG formed by the \p Changes vertices and the /// \p Dependencies edges by executing \see ExecuteOneTest() on subsets of @@ -74,4 +76,4 @@ public: } // end namespace llvm -#endif +#endif // LLVM_ADT_DAGDELTAALGORITHM_H diff --git a/contrib/llvm/include/llvm/ADT/DenseMap.h b/contrib/llvm/include/llvm/ADT/DenseMap.h index 917c086beba3..0b4b09d4b733 100644 --- a/contrib/llvm/include/llvm/ADT/DenseMap.h +++ b/contrib/llvm/include/llvm/ADT/DenseMap.h @@ -19,20 +19,20 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/PointerLikeTypeTraits.h" #include "llvm/Support/type_traits.h" #include #include -#include #include #include #include +#include #include #include namespace llvm { namespace detail { + // We extend a pair to allow users to override the bucket type with their own // implementation without requiring two members. template @@ -42,7 +42,8 @@ struct DenseMapPair : public std::pair { ValueT &getSecond() { return std::pair::second; } const ValueT &getSecond() const { return std::pair::second; } }; -} + +} // end namespace detail template < typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo, @@ -76,7 +77,7 @@ public: return const_iterator(getBucketsEnd(), getBucketsEnd(), *this, true); } - bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { + LLVM_NODISCARD bool empty() const { return getNumEntries() == 0; } unsigned size() const { return getNumEntries(); } @@ -169,30 +170,45 @@ public: // If the key is already in the map, it returns false and doesn't update the // value. std::pair insert(const std::pair &KV) { - BucketT *TheBucket; - if (LookupBucketFor(KV.first, TheBucket)) - return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), - false); // Already in map. - - // Otherwise, insert the new element. - TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket); - return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), - true); + return try_emplace(KV.first, KV.second); } // Inserts key,value pair into the map if the key isn't already in the map. // If the key is already in the map, it returns false and doesn't update the // value. std::pair insert(std::pair &&KV) { + return try_emplace(std::move(KV.first), std::move(KV.second)); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // The value is constructed in-place if the key is not in the map, otherwise + // it is not moved. + template + std::pair try_emplace(KeyT &&Key, Ts &&... Args) { BucketT *TheBucket; - if (LookupBucketFor(KV.first, TheBucket)) + if (LookupBucketFor(Key, TheBucket)) return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), false); // Already in map. // Otherwise, insert the new element. - TheBucket = InsertIntoBucket(std::move(KV.first), - std::move(KV.second), - TheBucket); + TheBucket = + InsertIntoBucket(TheBucket, std::move(Key), std::forward(Args)...); + return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), + true); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // The value is constructed in-place if the key is not in the map, otherwise + // it is not moved. + template + std::pair try_emplace(const KeyT &Key, Ts &&... Args) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), + false); // Already in map. + + // Otherwise, insert the new element. + TheBucket = InsertIntoBucket(TheBucket, Key, std::forward(Args)...); return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), true); } @@ -211,8 +227,8 @@ public: false); // Already in map. // Otherwise, insert the new element. - TheBucket = InsertIntoBucket(std::move(KV.first), std::move(KV.second), Val, - TheBucket); + TheBucket = InsertIntoBucketWithLookup(TheBucket, std::move(KV.first), + std::move(KV.second), Val); return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true), true); } @@ -224,7 +240,6 @@ public: insert(*I); } - bool erase(const KeyT &Val) { BucketT *TheBucket; if (!LookupBucketFor(Val, TheBucket)) @@ -249,7 +264,7 @@ public: if (LookupBucketFor(Key, TheBucket)) return *TheBucket; - return *InsertIntoBucket(Key, ValueT(), TheBucket); + return *InsertIntoBucket(TheBucket, Key); } ValueT &operator[](const KeyT &Key) { @@ -261,7 +276,7 @@ public: if (LookupBucketFor(Key, TheBucket)) return *TheBucket; - return *InsertIntoBucket(std::move(Key), ValueT(), TheBucket); + return *InsertIntoBucket(TheBucket, std::move(Key)); } ValueT &operator[](KeyT &&Key) { @@ -429,36 +444,19 @@ private: static_cast(this)->shrink_and_clear(); } - - BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value, - BucketT *TheBucket) { + template + BucketT *InsertIntoBucket(BucketT *TheBucket, KeyArg &&Key, + ValueArgs &&... Values) { TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket); - TheBucket->getFirst() = Key; - ::new (&TheBucket->getSecond()) ValueT(Value); - return TheBucket; - } - - BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value, - BucketT *TheBucket) { - TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket); - - TheBucket->getFirst() = Key; - ::new (&TheBucket->getSecond()) ValueT(std::move(Value)); - return TheBucket; - } - - BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) { - TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket); - - TheBucket->getFirst() = std::move(Key); - ::new (&TheBucket->getSecond()) ValueT(std::move(Value)); + TheBucket->getFirst() = std::forward(Key); + ::new (&TheBucket->getSecond()) ValueT(std::forward(Values)...); return TheBucket; } template - BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, LookupKeyT &Lookup, - BucketT *TheBucket) { + BucketT *InsertIntoBucketWithLookup(BucketT *TheBucket, KeyT &&Key, + ValueT &&Value, LookupKeyT &Lookup) { TheBucket = InsertIntoBucketImpl(Key, Lookup, TheBucket); TheBucket->getFirst() = std::move(Key); @@ -530,7 +528,7 @@ private: unsigned BucketNo = getHashValue(Val) & (NumBuckets-1); unsigned ProbeAmt = 1; - while (1) { + while (true) { const BucketT *ThisBucket = BucketsPtr + BucketNo; // Found Val's bucket? If so, return it. if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) { @@ -744,6 +742,8 @@ class SmallDenseMap // simplicity of referring to them. typedef DenseMapBase BaseT; friend class DenseMapBase; + static_assert(isPowerOf2_64(InlineBuckets), + "InlineBuckets must be a power of 2."); unsigned Small : 1; unsigned NumEntries : 31; @@ -968,7 +968,8 @@ private: return NumEntries; } void setNumEntries(unsigned Num) { - assert(Num < INT_MAX && "Cannot support more than INT_MAX entries"); + // NumEntries is hardcoded to be 31 bits wide. + assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries"); NumEntries = Num; } @@ -1042,8 +1043,10 @@ public: typedef value_type *pointer; typedef value_type &reference; typedef std::forward_iterator_tag iterator_category; + private: pointer Ptr, End; + public: DenseMapIterator() : Ptr(nullptr), End(nullptr) {} @@ -1117,4 +1120,4 @@ capacity_in_bytes(const DenseMap &X) { } // end namespace llvm -#endif +#endif // LLVM_ADT_DENSEMAP_H diff --git a/contrib/llvm/include/llvm/ADT/DenseMapInfo.h b/contrib/llvm/include/llvm/ADT/DenseMapInfo.h index 18c692e0cbcc..a844ebcccf5b 100644 --- a/contrib/llvm/include/llvm/ADT/DenseMapInfo.h +++ b/contrib/llvm/include/llvm/ADT/DenseMapInfo.h @@ -30,36 +30,6 @@ struct DenseMapInfo { //static bool isEqual(const T &LHS, const T &RHS); }; -template struct CachedHash { - CachedHash(T Val) : Val(std::move(Val)) { - Hash = DenseMapInfo::getHashValue(Val); - } - CachedHash(T Val, unsigned Hash) : Val(std::move(Val)), Hash(Hash) {} - T Val; - unsigned Hash; -}; - -// Provide DenseMapInfo for all CachedHash. -template struct DenseMapInfo> { - static CachedHash getEmptyKey() { - T N = DenseMapInfo::getEmptyKey(); - return {N, 0}; - } - static CachedHash getTombstoneKey() { - T N = DenseMapInfo::getTombstoneKey(); - return {N, 0}; - } - static unsigned getHashValue(CachedHash Val) { - assert(!isEqual(Val, getEmptyKey()) && "Cannot hash the empty key!"); - assert(!isEqual(Val, getTombstoneKey()) && - "Cannot hash the tombstone key!"); - return Val.Hash; - } - static bool isEqual(CachedHash A, CachedHash B) { - return DenseMapInfo::isEqual(A.Val, B.Val); - } -}; - // Provide DenseMapInfo for all pointers. template struct DenseMapInfo { diff --git a/contrib/llvm/include/llvm/ADT/DenseSet.h b/contrib/llvm/include/llvm/ADT/DenseSet.h index 3724a09623f3..b25d3b7cba6f 100644 --- a/contrib/llvm/include/llvm/ADT/DenseSet.h +++ b/contrib/llvm/include/llvm/ADT/DenseSet.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines the DenseSet class. +// This file defines the DenseSet and SmallDenseSet classes. // //===----------------------------------------------------------------------===// @@ -15,6 +15,7 @@ #define LLVM_ADT_DENSESET_H #include "llvm/ADT/DenseMap.h" +#include namespace llvm { @@ -32,13 +33,18 @@ public: DenseSetEmpty &getSecond() { return *this; } const DenseSetEmpty &getSecond() const { return *this; } }; -} -/// DenseSet - This implements a dense probed hash-table based set. -template > -class DenseSet { - typedef DenseMap> MapTy; +/// Base class for DenseSet and DenseSmallSet. +/// +/// MapTy should be either +/// +/// DenseMap> +/// +/// or the equivalent SmallDenseMap type. ValueInfoT must implement the +/// DenseMapInfo "concept". +template +class DenseSetImpl { static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT), "DenseMap buckets unexpectedly large!"); MapTy TheMap; @@ -48,7 +54,12 @@ public: typedef ValueT value_type; typedef unsigned size_type; - explicit DenseSet(unsigned NumInitBuckets = 0) : TheMap(NumInitBuckets) {} + explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {} + + DenseSetImpl(std::initializer_list Elems) + : DenseSetImpl(Elems.size()) { + insert(Elems.begin(), Elems.end()); + } bool empty() const { return TheMap.empty(); } size_type size() const { return TheMap.size(); } @@ -58,6 +69,10 @@ public: /// the Size of the set. void resize(size_t Size) { TheMap.resize(Size); } + /// Grow the DenseSet so that it can contain at least \p NumEntries items + /// before resizing again. + void reserve(size_t Size) { TheMap.reserve(Size); } + void clear() { TheMap.clear(); } @@ -71,15 +86,13 @@ public: return TheMap.erase(V); } - void swap(DenseSet& RHS) { - TheMap.swap(RHS.TheMap); - } + void swap(DenseSetImpl &RHS) { TheMap.swap(RHS.TheMap); } // Iterators. class Iterator { typename MapTy::iterator I; - friend class DenseSet; + friend class DenseSetImpl; public: typedef typename MapTy::iterator::difference_type difference_type; @@ -131,6 +144,9 @@ public: const_iterator end() const { return ConstIterator(TheMap.end()); } iterator find(const ValueT &V) { return Iterator(TheMap.find(V)); } + const_iterator find(const ValueT &V) const { + return ConstIterator(TheMap.find(V)); + } /// Alternative version of find() which allows a different, and possibly less /// expensive, key type. @@ -151,7 +167,12 @@ public: std::pair insert(const ValueT &V) { detail::DenseSetEmpty Empty; - return TheMap.insert(std::make_pair(V, Empty)); + return TheMap.try_emplace(V, Empty); + } + + std::pair insert(ValueT &&V) { + detail::DenseSetEmpty Empty; + return TheMap.try_emplace(std::move(V), Empty); } /// Alternative version of insert that uses a different (and possibly less @@ -159,12 +180,11 @@ public: template std::pair insert_as(const ValueT &V, const LookupKeyT &LookupKey) { - return insert_as(ValueT(V), LookupKey); + return TheMap.insert_as({V, detail::DenseSetEmpty()}, LookupKey); } template std::pair insert_as(ValueT &&V, const LookupKeyT &LookupKey) { - detail::DenseSetEmpty Empty; - return TheMap.insert_as(std::make_pair(std::move(V), Empty), LookupKey); + return TheMap.insert_as({std::move(V), detail::DenseSetEmpty()}, LookupKey); } // Range insertion of values. @@ -175,6 +195,42 @@ public: } }; +} // namespace detail + +/// Implements a dense probed hash-table based set. +template > +class DenseSet : public detail::DenseSetImpl< + ValueT, DenseMap>, + ValueInfoT> { + using BaseT = + detail::DenseSetImpl>, + ValueInfoT>; + +public: + using BaseT::BaseT; +}; + +/// Implements a dense probed hash-table based set with some number of buckets +/// stored inline. +template > +class SmallDenseSet + : public detail::DenseSetImpl< + ValueT, SmallDenseMap>, + ValueInfoT> { + using BaseT = detail::DenseSetImpl< + ValueT, SmallDenseMap>, + ValueInfoT>; + +public: + using BaseT::BaseT; +}; + } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h b/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h index c9317b8539b3..c54573204588 100644 --- a/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h +++ b/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h @@ -34,10 +34,13 @@ #define LLVM_ADT_DEPTHFIRSTITERATOR_H #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/iterator_range.h" +#include #include +#include #include namespace llvm { @@ -55,44 +58,56 @@ class df_iterator_storage { public: df_iterator_storage(SetType &VSet) : Visited(VSet) {} df_iterator_storage(const df_iterator_storage &S) : Visited(S.Visited) {} + SetType &Visited; }; -// Generic Depth First Iterator -template::NodeType*, 8>, - bool ExtStorage = false, class GT = GraphTraits > -class df_iterator : public std::iterator, - public df_iterator_storage { - typedef std::iterator super; +// The visited stated for the iteration is a simple set augmented with +// one more method, completed, which is invoked when all children of a +// node have been processed. It is intended to distinguish of back and +// cross edges in the spanning tree but is not used in the common case. +template +struct df_iterator_default_set : public SmallPtrSet { + typedef SmallPtrSet BaseSet; + typedef typename BaseSet::iterator iterator; + std::pair insert(NodeRef N) { return BaseSet::insert(N) ; } + template + void insert(IterT Begin, IterT End) { BaseSet::insert(Begin,End); } - typedef typename GT::NodeType NodeType; + void completed(NodeRef) { } +}; + +// Generic Depth First Iterator +template ::NodeRef>, + bool ExtStorage = false, class GT = GraphTraits> +class df_iterator + : public std::iterator, + public df_iterator_storage { + typedef std::iterator super; + + typedef typename GT::NodeRef NodeRef; typedef typename GT::ChildIteratorType ChildItTy; - typedef PointerIntPair PointerIntTy; + + // First element is node reference, second is the 'next child' to visit. + // The second child is initialized lazily to pick up graph changes during the + // DFS. + typedef std::pair> StackElement; // VisitStack - Used to maintain the ordering. Top = current block - // First element is node pointer, second is the 'next child' to visit - // if the int in PointerIntTy is 0, the 'next child' to visit is invalid - std::vector> VisitStack; + std::vector VisitStack; private: - inline df_iterator(NodeType *Node) { + inline df_iterator(NodeRef Node) { this->Visited.insert(Node); - VisitStack.push_back( - std::make_pair(PointerIntTy(Node, 0), GT::child_begin(Node))); + VisitStack.push_back(StackElement(Node, None)); } - inline df_iterator() { - // End is when stack is empty - } - inline df_iterator(NodeType *Node, SetType &S) - : df_iterator_storage(S) { - if (!S.count(Node)) { - VisitStack.push_back( - std::make_pair(PointerIntTy(Node, 0), GT::child_begin(Node))); - this->Visited.insert(Node); - } + inline df_iterator() = default; // End is when stack is empty + inline df_iterator(NodeRef Node, SetType &S) + : df_iterator_storage(S) { + if (this->Visited.insert(Node).second) + VisitStack.push_back(StackElement(Node, None)); } inline df_iterator(SetType &S) : df_iterator_storage(S) { @@ -101,26 +116,26 @@ private: inline void toNext() { do { - std::pair &Top = VisitStack.back(); - NodeType *Node = Top.first.getPointer(); - ChildItTy &It = Top.second; - if (!Top.first.getInt()) { - // now retrieve the real begin of the children before we dive in - It = GT::child_begin(Node); - Top.first.setInt(1); - } + NodeRef Node = VisitStack.back().first; + Optional &Opt = VisitStack.back().second; - while (It != GT::child_end(Node)) { - NodeType *Next = *It++; + if (!Opt) + Opt.emplace(GT::child_begin(Node)); + + // Notice that we directly mutate *Opt here, so that + // VisitStack.back().second actually gets updated as the iterator + // increases. + while (*Opt != GT::child_end(Node)) { + NodeRef Next = *(*Opt)++; // Has our next sibling been visited? - if (Next && this->Visited.insert(Next).second) { + if (this->Visited.insert(Next).second) { // No, do it now. - VisitStack.push_back( - std::make_pair(PointerIntTy(Next, 0), GT::child_begin(Next))); + VisitStack.push_back(StackElement(Next, None)); return; } } - + this->Visited.completed(Node); + // Oops, ran out of successors... go up a level on the stack. VisitStack.pop_back(); } while (!VisitStack.empty()); @@ -146,13 +161,13 @@ public: } bool operator!=(const df_iterator &x) const { return !(*this == x); } - pointer operator*() const { return VisitStack.back().first.getPointer(); } + const NodeRef &operator*() const { return VisitStack.back().first; } // This is a nonstandard operator-> that dereferences the pointer an extra // time... so that you can actually call methods ON the Node, because // the contained type is a pointer. This allows BBIt->getTerminator() f.e. // - NodeType *operator->() const { return **this; } + NodeRef operator->() const { return **this; } df_iterator &operator++() { // Preincrement toNext(); @@ -180,7 +195,7 @@ public: // specified node. This is public, and will probably be used to iterate over // nodes that a depth first iteration did not find: ie unreachable nodes. // - bool nodeVisited(NodeType *Node) const { + bool nodeVisited(NodeRef Node) const { return this->Visited.count(Node) != 0; } @@ -190,9 +205,7 @@ public: /// getPath - Return the n'th node in the path from the entry node to the /// current node. - NodeType *getPath(unsigned n) const { - return VisitStack[n].first.getPointer(); - } + NodeRef getPath(unsigned n) const { return VisitStack[n].first; } }; // Provide global constructors that automatically figure out correct types... @@ -214,7 +227,7 @@ iterator_range> depth_first(const T& G) { } // Provide global definitions of external depth first iterators... -template ::NodeType*> > +template ::NodeRef>> struct df_ext_iterator : public df_iterator { df_ext_iterator(const df_iterator &V) : df_iterator(V) {} @@ -238,7 +251,8 @@ iterator_range> depth_first_ext(const T& G, // Provide global definitions of inverse depth first iterators... template ::NodeType*, 8>, + class SetTy = + df_iterator_default_set::NodeRef>, bool External = false> struct idf_iterator : public df_iterator, SetTy, External> { idf_iterator(const df_iterator, SetTy, External> &V) @@ -262,7 +276,7 @@ iterator_range> inverse_depth_first(const T& G) { } // Provide global definitions of external inverse depth first iterators... -template ::NodeType*> > +template ::NodeRef>> struct idf_ext_iterator : public idf_iterator { idf_ext_iterator(const idf_iterator &V) : idf_iterator(V) {} @@ -286,6 +300,6 @@ iterator_range> inverse_depth_first_ext(const T& G, return make_range(idf_ext_begin(G, S), idf_ext_end(G, S)); } -} // End llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_ADT_DEPTHFIRSTITERATOR_H diff --git a/contrib/llvm/include/llvm/ADT/EpochTracker.h b/contrib/llvm/include/llvm/ADT/EpochTracker.h index 582d58179d13..db39ba4e0c50 100644 --- a/contrib/llvm/include/llvm/ADT/EpochTracker.h +++ b/contrib/llvm/include/llvm/ADT/EpochTracker.h @@ -16,28 +16,14 @@ #ifndef LLVM_ADT_EPOCH_TRACKER_H #define LLVM_ADT_EPOCH_TRACKER_H +#include "llvm/Config/abi-breaking.h" #include "llvm/Config/llvm-config.h" #include namespace llvm { -#ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS - -class DebugEpochBase { -public: - void incrementEpoch() {} - - class HandleBase { - public: - HandleBase() = default; - explicit HandleBase(const DebugEpochBase *) {} - bool isHandleInSync() const { return true; } - const void *getEpochAddress() const { return nullptr; } - }; -}; - -#else +#if LLVM_ENABLE_ABI_BREAKING_CHECKS /// \brief A base class for data structure classes wishing to make iterators /// ("handles") pointing into themselves fail-fast. When building without @@ -92,6 +78,21 @@ public: }; }; +#else + +class DebugEpochBase { +public: + void incrementEpoch() {} + + class HandleBase { + public: + HandleBase() = default; + explicit HandleBase(const DebugEpochBase *) {} + bool isHandleInSync() const { return true; } + const void *getEpochAddress() const { return nullptr; } + }; +}; + #endif // LLVM_ENABLE_ABI_BREAKING_CHECKS } // namespace llvm diff --git a/contrib/llvm/include/llvm/ADT/EquivalenceClasses.h b/contrib/llvm/include/llvm/ADT/EquivalenceClasses.h index d6a26f88e67d..8fcac178ffc9 100644 --- a/contrib/llvm/include/llvm/ADT/EquivalenceClasses.h +++ b/contrib/llvm/include/llvm/ADT/EquivalenceClasses.h @@ -15,9 +15,10 @@ #ifndef LLVM_ADT_EQUIVALENCECLASSES_H #define LLVM_ADT_EQUIVALENCECLASSES_H -#include "llvm/Support/DataTypes.h" #include #include +#include +#include #include namespace llvm { @@ -70,6 +71,7 @@ class EquivalenceClasses { friend class EquivalenceClasses; mutable const ECValue *Leader, *Next; ElemTy Data; + // ECValue ctor - Start out with EndOfList pointing to this node, Next is // Null, isLeader = true. ECValue(const ElemTy &Elt) @@ -81,6 +83,7 @@ class EquivalenceClasses { // Path compression. return Leader = Leader->getLeader(); } + const ECValue *getEndOfList() const { assert(isLeader() && "Cannot get the end of a list for a non-leader!"); return Leader; @@ -90,6 +93,7 @@ class EquivalenceClasses { assert(getNext() == nullptr && "Already has a next pointer!"); Next = (const ECValue*)((intptr_t)NewNext | (intptr_t)isLeader()); } + public: ECValue(const ECValue &RHS) : Leader(this), Next((ECValue*)(intptr_t)1), Data(RHS.Data) { @@ -115,7 +119,7 @@ class EquivalenceClasses { std::set TheMapping; public: - EquivalenceClasses() {} + EquivalenceClasses() = default; EquivalenceClasses(const EquivalenceClasses &RHS) { operator=(RHS); } @@ -187,7 +191,6 @@ public: return NC; } - //===--------------------------------------------------------------------===// // Mutation methods @@ -210,7 +213,6 @@ public: return findLeader(TheMapping.find(V)); } - /// union - Merge the two equivalence sets for the specified values, inserting /// them if they do not already exist in the equivalence set. member_iterator unionSets(const ElemTy &V1, const ElemTy &V2) { @@ -243,12 +245,13 @@ public: const ElemTy, ptrdiff_t> super; const ECValue *Node; friend class EquivalenceClasses; + public: typedef size_t size_type; typedef typename super::pointer pointer; typedef typename super::reference reference; - explicit member_iterator() {} + explicit member_iterator() = default; explicit member_iterator(const ECValue *N) : Node(N) {} reference operator*() const { @@ -278,6 +281,6 @@ public: }; }; -} // End llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_ADT_EQUIVALENCECLASSES_H diff --git a/contrib/llvm/include/llvm/ADT/FoldingSet.h b/contrib/llvm/include/llvm/ADT/FoldingSet.h index f16258af4ae2..dab18297dd3b 100644 --- a/contrib/llvm/include/llvm/ADT/FoldingSet.h +++ b/contrib/llvm/include/llvm/ADT/FoldingSet.h @@ -19,8 +19,13 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator.h" #include "llvm/Support/Allocator.h" +#include +#include +#include +#include namespace llvm { + /// This folding set used for two purposes: /// 1. Given information about a node we want to create, look up the unique /// instance of the node in the set. If the node already exists, return @@ -184,6 +189,7 @@ public: /// EltCount-th node won't cause a rebucket operation. reserve is permitted /// to allocate more space than requested by EltCount. void reserve(unsigned EltCount); + /// capacity - Returns the number of nodes permitted in the folding set /// before a rebucket operation is performed. unsigned capacity() { @@ -200,14 +206,17 @@ private: /// NewBucketCount must be a power of two, and must be greater than the old /// bucket count. void GrowBucketCount(unsigned NewBucketCount); + protected: /// GetNodeProfile - Instantiations of the FoldingSet template implement /// this function to gather data bits for the given node. virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const = 0; + /// NodeEquals - Instantiations of the FoldingSet template implement /// this function to compare the given node with the given ID. virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash, FoldingSetNodeID &TempID) const=0; + /// ComputeNodeHash - Instantiations of the FoldingSet template implement /// this function to compute a hash value for the given node. virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const = 0; @@ -215,8 +224,6 @@ protected: //===----------------------------------------------------------------------===// -template struct FoldingSetTrait; - /// DefaultFoldingSetTrait - This class provides default implementations /// for FoldingSetTrait implementations. /// @@ -252,8 +259,6 @@ template struct DefaultFoldingSetTrait { template struct FoldingSetTrait : public DefaultFoldingSetTrait {}; -template struct ContextualFoldingSetTrait; - /// DefaultContextualFoldingSetTrait - Like DefaultFoldingSetTrait, but /// for ContextualFoldingSets. template @@ -261,6 +266,7 @@ struct DefaultContextualFoldingSetTrait { static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) { X.Profile(ID, Context); } + static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash, FoldingSetNodeID &TempID, Ctx Context); static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID, @@ -279,11 +285,11 @@ template struct ContextualFoldingSetTrait /// is often much larger than necessary, and the possibility of heap /// allocation means it requires a non-trivial destructor call. class FoldingSetNodeIDRef { - const unsigned *Data; - size_t Size; + const unsigned *Data = nullptr; + size_t Size = 0; public: - FoldingSetNodeIDRef() : Data(nullptr), Size(0) {} + FoldingSetNodeIDRef() = default; FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {} /// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef, @@ -313,7 +319,7 @@ class FoldingSetNodeID { SmallVector Bits; public: - FoldingSetNodeID() {} + FoldingSetNodeID() = default; FoldingSetNodeID(FoldingSetNodeIDRef Ref) : Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {} @@ -418,6 +424,7 @@ private: T *TN = static_cast(N); FoldingSetTrait::Profile(*TN, ID); } + /// NodeEquals - Instantiations may optionally provide a way to compare a /// node with a specified ID. bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash, @@ -425,6 +432,7 @@ private: T *TN = static_cast(N); return FoldingSetTrait::Equals(*TN, ID, IDHash, TempID); } + /// ComputeNodeHash - Instantiations may optionally provide a way to compute a /// hash value directly from a node. unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const override { @@ -483,7 +491,7 @@ public: /// /// T must be a subclass of FoldingSetNode and implement a Profile /// function with signature -/// void Profile(llvm::FoldingSetNodeID &, Ctx); +/// void Profile(FoldingSetNodeID &, Ctx); template class ContextualFoldingSet final : public FoldingSetImpl { // Unfortunately, this can't derive from FoldingSet because the @@ -501,12 +509,14 @@ private: T *TN = static_cast(N); ContextualFoldingSetTrait::Profile(*TN, ID, Context); } + bool NodeEquals(FoldingSetImpl::Node *N, const FoldingSetNodeID &ID, unsigned IDHash, FoldingSetNodeID &TempID) const override { T *TN = static_cast(N); return ContextualFoldingSetTrait::Equals(*TN, ID, IDHash, TempID, Context); } + unsigned ComputeNodeHash(FoldingSetImpl::Node *N, FoldingSetNodeID &TempID) const override { T *TN = static_cast(N); @@ -558,7 +568,7 @@ public: /// to provide the interface of FoldingSet but with deterministic iteration /// order based on the insertion order. T must be a subclass of FoldingSetNode /// and implement a Profile function. -template > +template > class FoldingSetVector { FoldingSet Set; VectorT Vector; @@ -623,7 +633,9 @@ public: class FoldingSetIteratorImpl { protected: FoldingSetNode *NodePtr; + FoldingSetIteratorImpl(void **Bucket); + void advance(); public: @@ -754,11 +766,12 @@ template struct FoldingSetTrait { template struct FoldingSetTrait> { static inline void Profile(const std::pair &P, - llvm::FoldingSetNodeID &ID) { + FoldingSetNodeID &ID) { ID.Add(P.first); ID.Add(P.second); } }; -} // End of namespace llvm. -#endif +} // end namespace llvm + +#endif // LLVM_ADT_FOLDINGSET_H diff --git a/contrib/llvm/include/llvm/ADT/GraphTraits.h b/contrib/llvm/include/llvm/ADT/GraphTraits.h index eb67b7c83659..29bbcb010eee 100644 --- a/contrib/llvm/include/llvm/ADT/GraphTraits.h +++ b/contrib/llvm/include/llvm/ADT/GraphTraits.h @@ -27,14 +27,10 @@ template struct GraphTraits { // Elements to provide: - // NOTICE: We are in a transition from migration interfaces that require - // NodeType *, to NodeRef. NodeRef is required to be cheap to copy, but does - // not have to be a raw pointer. In the transition, user should define - // NodeType, and NodeRef = NodeType *. - // - // typedef NodeType - Type of Node in the graph - // typedef NodeRef - NodeType * - // typedef ChildIteratorType - Type used to iterate over children in graph + // typedef NodeRef - Type of Node token in the graph, which should + // be cheap to copy. + // typedef ChildIteratorType - Type used to iterate over children in graph, + // dereference to a NodeRef. // static NodeRef getEntryNode(const GraphType &) // Return the entry node of the graph @@ -45,7 +41,7 @@ struct GraphTraits { // node list for the specified node. // - // typedef ...iterator nodes_iterator; + // typedef ...iterator nodes_iterator; - dereference to a NodeRef // static nodes_iterator nodes_begin(GraphType *G) // static nodes_iterator nodes_end (GraphType *G) // nodes_iterator/begin/end - Allow iteration over all nodes in the graph @@ -88,23 +84,7 @@ struct Inverse { // Provide a partial specialization of GraphTraits so that the inverse of an // inverse falls back to the original graph. -template -struct GraphTraits > > { - typedef typename GraphTraits::NodeType NodeType; - typedef typename GraphTraits::ChildIteratorType ChildIteratorType; - - static NodeType *getEntryNode(Inverse > *G) { - return GraphTraits::getEntryNode(G->Graph.Graph); - } - - static ChildIteratorType child_begin(NodeType* N) { - return GraphTraits::child_begin(N); - } - - static ChildIteratorType child_end(NodeType* N) { - return GraphTraits::child_end(N); - } -}; +template struct GraphTraits>> : GraphTraits {}; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/ADT/ImmutableList.h b/contrib/llvm/include/llvm/ADT/ImmutableList.h index a1d26bd97045..e5f51bafe995 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableList.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableList.h @@ -16,8 +16,9 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/DataTypes.h" #include +#include +#include namespace llvm { @@ -25,18 +26,18 @@ template class ImmutableListFactory; template class ImmutableListImpl : public FoldingSetNode { + friend class ImmutableListFactory; + T Head; const ImmutableListImpl* Tail; ImmutableListImpl(const T& head, const ImmutableListImpl* tail = nullptr) : Head(head), Tail(tail) {} - friend class ImmutableListFactory; - - void operator=(const ImmutableListImpl&) = delete; - ImmutableListImpl(const ImmutableListImpl&) = delete; - public: + ImmutableListImpl(const ImmutableListImpl &) = delete; + ImmutableListImpl &operator=(const ImmutableListImpl &) = delete; + const T& getHead() const { return Head; } const ImmutableListImpl* getTail() const { return Tail; } @@ -79,15 +80,17 @@ public: } class iterator { - const ImmutableListImpl* L; + const ImmutableListImpl* L = nullptr; + public: - iterator() : L(nullptr) {} + iterator() = default; iterator(ImmutableList l) : L(l.getInternalPointer()) {} iterator& operator++() { L = L->getTail(); return *this; } bool operator==(const iterator& I) const { return L == I.L; } bool operator!=(const iterator& I) const { return L != I.L; } const value_type& operator*() const { return L->getHead(); } + ImmutableList getList() const { return L; } }; @@ -121,7 +124,7 @@ public: /// getHead - Returns the head of the list. const T& getHead() { - assert (!isEmpty() && "Cannot get the head of an empty list."); + assert(!isEmpty() && "Cannot get the head of an empty list."); return X->getHead(); } @@ -145,7 +148,7 @@ class ImmutableListFactory { uintptr_t Allocator; bool ownsAllocator() const { - return Allocator & 0x1 ? false : true; + return (Allocator & 0x1) == 0; } BumpPtrAllocator& getAllocator() const { @@ -203,18 +206,21 @@ public: //===----------------------------------------------------------------------===// template struct DenseMapInfo; -template struct DenseMapInfo > { +template struct DenseMapInfo> { static inline ImmutableList getEmptyKey() { return reinterpret_cast*>(-1); } + static inline ImmutableList getTombstoneKey() { return reinterpret_cast*>(-2); } + static unsigned getHashValue(ImmutableList X) { uintptr_t PtrVal = reinterpret_cast(X.getInternalPointer()); return (unsigned((uintptr_t)PtrVal) >> 4) ^ (unsigned((uintptr_t)PtrVal) >> 9); } + static bool isEqual(ImmutableList X1, ImmutableList X2) { return X1 == X2; } @@ -222,8 +228,8 @@ template struct DenseMapInfo > { template struct isPodLike; template -struct isPodLike > { static const bool value = true; }; +struct isPodLike> { static const bool value = true; }; -} // end llvm namespace +} // end namespace llvm #endif // LLVM_ADT_IMMUTABLELIST_H diff --git a/contrib/llvm/include/llvm/ADT/ImmutableMap.h b/contrib/llvm/include/llvm/ADT/ImmutableMap.h index 7480cd73da61..f197d407ba3b 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableMap.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableMap.h @@ -14,7 +14,10 @@ #ifndef LLVM_ADT_IMMUTABLEMAP_H #define LLVM_ADT_IMMUTABLEMAP_H +#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableSet.h" +#include "llvm/Support/Allocator.h" +#include namespace llvm { @@ -56,7 +59,7 @@ struct ImutKeyValueInfo { }; template > + typename ValInfo = ImutKeyValueInfo> class ImmutableMap { public: typedef typename ValInfo::value_type value_type; @@ -106,6 +109,9 @@ public: Factory(BumpPtrAllocator &Alloc, bool canonicalize = true) : F(Alloc), Canonicalize(canonicalize) {} + Factory(const Factory &) = delete; + Factory &operator=(const Factory &) = delete; + ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); } ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D) { @@ -121,10 +127,6 @@ public: typename TreeTy::Factory *getTreeFactory() const { return const_cast(&F); } - - private: - Factory(const Factory& RHS) = delete; - void operator=(const Factory& RHS) = delete; }; bool contains(key_type_ref K) const { @@ -203,9 +205,10 @@ public: //===--------------------------------------------------===// class iterator : public ImutAVLValueIterator { + friend class ImmutableMap; + iterator() = default; explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {} - friend class ImmutableMap; public: key_type_ref getKey() const { return (*this)->first; } @@ -248,7 +251,7 @@ public: // NOTE: This will possibly become the new implementation of ImmutableMap some day. template > +typename ValInfo = ImutKeyValueInfo> class ImmutableMapRef { public: typedef typename ValInfo::value_type value_type; @@ -362,9 +365,10 @@ public: //===--------------------------------------------------===// class iterator : public ImutAVLValueIterator { + friend class ImmutableMapRef; + iterator() = default; explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {} - friend class ImmutableMapRef; public: key_type_ref getKey() const { return (*this)->first; } diff --git a/contrib/llvm/include/llvm/ADT/ImmutableSet.h b/contrib/llvm/include/llvm/ADT/ImmutableSet.h index 87026f019fec..0724a28306a0 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableSet.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableSet.h @@ -16,12 +16,16 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include #include #include +#include +#include +#include namespace llvm { @@ -329,11 +333,13 @@ private: public: void retain() { ++refCount; } + void release() { assert(refCount > 0); if (--refCount == 0) destroy(); } + void destroy() { if (left) left->release(); @@ -375,7 +381,7 @@ class ImutAVLFactory { std::vector freeNodes; bool ownsAllocator() const { - return Allocator & 0x1 ? false : true; + return (Allocator & 0x1) == 0; } BumpPtrAllocator& getAllocator() const { @@ -414,7 +420,6 @@ public: TreeTy* getEmptyTree() const { return nullptr; } protected: - //===--------------------------------------------------===// // A bunch of quick helper functions used for reasoning // about the properties of trees and their children. @@ -649,13 +654,14 @@ class ImutAVLTreeGenericIterator : public std::iterator> { SmallVector stack; + public: enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3, Flags=0x3 }; typedef ImutAVLTree TreeTy; - ImutAVLTreeGenericIterator() {} + ImutAVLTreeGenericIterator() = default; ImutAVLTreeGenericIterator(const TreeTy *Root) { if (Root) stack.push_back(reinterpret_cast(Root)); } @@ -671,7 +677,6 @@ public: return stack.back() & Flags; } - bool atEnd() const { return stack.empty(); } bool atBeginning() const { @@ -881,7 +886,6 @@ struct ImutProfileInfo { } }; - /// Generic profile trait for pointer types. We treat pointers as /// references to unique objects. template @@ -901,7 +905,6 @@ struct ImutProfileInfo { // for element profiling. //===----------------------------------------------------------------------===// - /// ImutContainerInfo - Generic definition of comparison operations for /// elements of immutable containers that defaults to using /// std::equal_to<> and std::less<> to perform comparison of elements. @@ -954,7 +957,7 @@ struct ImutContainerInfo : public ImutProfileInfo { // Immutable Set //===----------------------------------------------------------------------===// -template > +template > class ImmutableSet { public: typedef typename ValInfo::value_type value_type; @@ -972,9 +975,11 @@ public: 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(); } @@ -983,6 +988,7 @@ public: } return *this; } + ~ImmutableSet() { if (Root) { Root->release(); } } @@ -998,6 +1004,9 @@ public: Factory(BumpPtrAllocator& Alloc, bool canonicalize = true) : F(Alloc), Canonicalize(canonicalize) {} + Factory(const Factory& RHS) = delete; + void operator=(const Factory& RHS) = delete; + /// getEmptySet - Returns an immutable set that contains no elements. ImmutableSet getEmptySet() { return ImmutableSet(F.getEmptyTree()); @@ -1032,10 +1041,6 @@ public: typename TreeTy::Factory *getTreeFactory() const { return const_cast(&F); } - - private: - Factory(const Factory& RHS) = delete; - void operator=(const Factory& RHS) = delete; }; friend class Factory; @@ -1104,7 +1109,7 @@ public: }; // NOTE: This may some day replace the current ImmutableSet. -template > +template > class ImmutableSetRef { public: typedef typename ValInfo::value_type value_type; @@ -1126,11 +1131,13 @@ public: Factory(F) { if (Root) { Root->retain(); } } + ImmutableSetRef(const ImmutableSetRef &X) : Root(X.Root), Factory(X.Factory) { if (Root) { Root->retain(); } } + ImmutableSetRef &operator=(const ImmutableSetRef &X) { if (Root != X.Root) { if (X.Root) { X.Root->retain(); } @@ -1215,4 +1222,4 @@ public: } // end namespace llvm -#endif +#endif // LLVM_ADT_IMMUTABLESET_H diff --git a/contrib/llvm/include/llvm/ADT/IntervalMap.h b/contrib/llvm/include/llvm/ADT/IntervalMap.h index f8843b2a4e50..430b9671bd1d 100644 --- a/contrib/llvm/include/llvm/ADT/IntervalMap.h +++ b/contrib/llvm/include/llvm/ADT/IntervalMap.h @@ -104,11 +104,14 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/RecyclingAllocator.h" +#include +#include #include +#include +#include namespace llvm { - //===----------------------------------------------------------------------===// //--- Key traits ---// //===----------------------------------------------------------------------===// @@ -131,7 +134,6 @@ namespace llvm { template 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) { @@ -150,11 +152,15 @@ struct IntervalMapInfo { return a+1 == b; } + /// nonEmpty - Return true if [a;b] is non-empty. + /// This is a <= b for a closed interval, a < b for [a;b) half-open intervals. + static inline bool nonEmpty(const T &a, const T &b) { + return a <= b; + } }; template struct IntervalMapHalfOpenInfo { - /// startLess - Return true if x is not in [a;b). static inline bool startLess(const T &x, const T &a) { return x < a; @@ -170,19 +176,18 @@ struct IntervalMapHalfOpenInfo { return a == b; } + /// nonEmpty - Return true if [a;b) is non-empty. + static inline bool nonEmpty(const T &a, const T &b) { + return a < b; + } }; /// IntervalMapImpl - Namespace used for IntervalMap implementation details. /// It should be considered private to the implementation. namespace IntervalMapImpl { -// Forward declarations. -template class LeafNode; -template class BranchNode; - typedef std::pair IdxPair; - //===----------------------------------------------------------------------===// //--- IntervalMapImpl::NodeBase ---// //===----------------------------------------------------------------------===// @@ -406,7 +411,6 @@ IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity, const unsigned *CurSize, unsigned NewSize[], unsigned Position, bool Grow); - //===----------------------------------------------------------------------===// //--- IntervalMapImpl::NodeSizer ---// //===----------------------------------------------------------------------===// @@ -459,10 +463,8 @@ struct NodeSizer { /// different kinds of maps. typedef RecyclingAllocator Allocator; - }; - //===----------------------------------------------------------------------===// //--- IntervalMapImpl::NodeRef ---// //===----------------------------------------------------------------------===// @@ -494,7 +496,7 @@ class NodeRef { public: /// NodeRef - Create a null ref. - NodeRef() {} + NodeRef() = default; /// operator bool - Detect a null ref. explicit operator bool() const { return pip.getOpaqueValue(); } @@ -674,7 +676,6 @@ insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y) { return Size + 1; } - //===----------------------------------------------------------------------===// //--- IntervalMapImpl::BranchNode ---// //===----------------------------------------------------------------------===// @@ -919,8 +920,7 @@ public: } }; -} // namespace IntervalMapImpl - +} // end namespace IntervalMapImpl //===----------------------------------------------------------------------===// //--- IntervalMap ----// @@ -928,7 +928,7 @@ public: template ::LeafSize, - typename Traits = IntervalMapInfo > + typename Traits = IntervalMapInfo> class IntervalMap { typedef IntervalMapImpl::NodeSizer Sizer; typedef IntervalMapImpl::LeafNode Leaf; @@ -995,6 +995,7 @@ private: assert(!branched() && "Cannot acces leaf data in branched root"); return dataAs(); } + RootBranchData &rootBranchData() const { assert(branched() && "Cannot access branch data in non-branched root"); return dataAs(); @@ -1003,6 +1004,7 @@ private: assert(branched() && "Cannot access branch data in non-branched root"); return dataAs(); } + const RootBranch &rootBranch() const { return rootBranchData().node; } RootBranch &rootBranch() { return rootBranchData().node; } KeyT rootBranchStart() const { return rootBranchData().start; } @@ -1041,7 +1043,7 @@ private: public: explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) { - assert((uintptr_t(data.buffer) & (alignOf() - 1)) == 0 && + assert((uintptr_t(data.buffer) & (alignof(RootLeaf) - 1)) == 0 && "Insufficient alignment"); new(&rootLeaf()) RootLeaf(); } @@ -1149,7 +1151,6 @@ treeSafeLookup(KeyT x, ValT NotFound) const { return NR.get().safeLookup(x, NotFound); } - // branchRoot - Switch from a leaf root to a branched root. // Return the new (root offset, node offset) corresponding to Position. template @@ -1284,6 +1285,7 @@ clear() { template class IntervalMap::const_iterator : public std::iterator { + protected: friend class IntervalMap; @@ -1436,7 +1438,6 @@ public: path.leafOffset() = map->rootLeaf().findFrom(path.leafOffset(), map->rootSize, x); } - }; /// pathFillFind - Complete path by searching for x. @@ -1523,7 +1524,7 @@ class IntervalMap::iterator : public const_iterator { public: /// iterator - Create null iterator. - iterator() {} + iterator() = default; /// setStart - Move the start of the current interval. /// This may cause coalescing with the previous interval. @@ -1589,7 +1590,6 @@ public: operator--(); return tmp; } - }; /// canCoalesceLeft - Can the current interval coalesce to the left after @@ -1669,7 +1669,7 @@ iterator::setNodeStop(unsigned Level, KeyT Stop) { template void IntervalMap:: iterator::setStart(KeyT a) { - assert(Traits::stopLess(a, this->stop()) && "Cannot move start beyond stop"); + assert(Traits::nonEmpty(a, this->stop()) && "Cannot move start beyond stop"); KeyT &CurStart = this->unsafeStart(); if (!Traits::startLess(a, CurStart) || !canCoalesceLeft(a, this->value())) { CurStart = a; @@ -1685,7 +1685,7 @@ iterator::setStart(KeyT a) { template void IntervalMap:: iterator::setStop(KeyT b) { - assert(Traits::stopLess(this->start(), b) && "Cannot move stop beyond start"); + assert(Traits::nonEmpty(this->start(), b) && "Cannot move stop beyond start"); if (Traits::startLess(b, this->stop()) || !canCoalesceRight(b, this->value())) { setStopUnchecked(b); @@ -1790,7 +1790,6 @@ iterator::insert(KeyT a, KeyT b, ValT y) { treeInsert(a, b, y); } - template void IntervalMap:: iterator::treeInsert(KeyT a, KeyT b, ValT y) { @@ -2151,6 +2150,6 @@ public: } }; -} // namespace llvm +} // end namespace llvm -#endif +#endif // LLVM_ADT_INTERVALMAP_H diff --git a/contrib/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h b/contrib/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h index 8057ec10be00..559fb40773aa 100644 --- a/contrib/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/contrib/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -7,14 +7,49 @@ // //===----------------------------------------------------------------------===// // -// This file defines IntrusiveRefCntPtr, a template class that -// implements a "smart" pointer for objects that maintain their own -// internal reference count, and RefCountedBase/RefCountedBaseVPTR, two -// generic base classes for objects that wish to have their lifetimes -// managed using reference counting. +// This file defines the RefCountedBase, ThreadSafeRefCountedBase, and +// IntrusiveRefCntPtr classes. // -// IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added -// LLVM-style casting. +// IntrusiveRefCntPtr is a smart pointer to an object which maintains a +// reference count. (ThreadSafe)RefCountedBase is a mixin class that adds a +// refcount member variable and methods for updating the refcount. An object +// that inherits from (ThreadSafe)RefCountedBase deletes itself when its +// refcount hits zero. +// +// For example: +// +// class MyClass : public RefCountedBase {}; +// +// void foo() { +// // Objects that inherit from RefCountedBase should always be instantiated +// // on the heap, never on the stack. +// IntrusiveRefCntPtr Ptr1(new MyClass()); +// +// // Copying an IntrusiveRefCntPtr increases the pointee's refcount by 1. +// IntrusiveRefCntPtr Ptr2(Ptr1); +// +// // Constructing an IntrusiveRefCntPtr has no effect on the object's +// // refcount. After a move, the moved-from pointer is null. +// IntrusiveRefCntPtr Ptr3(std::move(Ptr1)); +// assert(Ptr1 == nullptr); +// +// // Clearing an IntrusiveRefCntPtr decreases the pointee's refcount by 1. +// Ptr2.reset(); +// +// // The object deletes itself when we return from the function, because +// // Ptr3's destructor decrements its refcount to 0. +// } +// +// You can use IntrusiveRefCntPtr with isa(), dyn_cast(), etc.: +// +// IntrusiveRefCntPtr Ptr(new MyClass()); +// OtherClass *Other = dyn_cast(Ptr); // Ptr.get() not required +// +// IntrusiveRefCntPtr works with any class that +// +// - inherits from (ThreadSafe)RefCountedBase, +// - has Retain() and Release() methods, or +// - specializes IntrusiveRefCntPtrInfo. // //===----------------------------------------------------------------------===// @@ -27,261 +62,207 @@ namespace llvm { - template - class IntrusiveRefCntPtr; - -//===----------------------------------------------------------------------===// -/// RefCountedBase - A generic base class for objects that wish to -/// have their lifetimes managed using reference counts. Classes -/// subclass RefCountedBase to obtain such functionality, and are -/// typically handled with IntrusiveRefCntPtr "smart pointers" (see below) -/// which automatically handle the management of reference counts. -/// Objects that subclass RefCountedBase should not be allocated on -/// the stack, as invoking "delete" (which is called when the -/// reference count hits 0) on such objects is an error. -//===----------------------------------------------------------------------===// - template - class RefCountedBase { - mutable unsigned ref_cnt; - - public: - RefCountedBase() : ref_cnt(0) {} - RefCountedBase(const RefCountedBase &) : ref_cnt(0) {} - - void Retain() const { ++ref_cnt; } - void Release() const { - assert (ref_cnt > 0 && "Reference count is already zero."); - if (--ref_cnt == 0) delete static_cast(this); - } - }; - -//===----------------------------------------------------------------------===// -/// RefCountedBaseVPTR - A class that has the same function as -/// RefCountedBase, but with a virtual destructor. Should be used -/// instead of RefCountedBase for classes that already have virtual -/// methods to enforce dynamic allocation via 'new'. Classes that -/// inherit from RefCountedBaseVPTR can't be allocated on stack - -/// attempting to do this will produce a compile error. -//===----------------------------------------------------------------------===// - class RefCountedBaseVPTR { - mutable unsigned ref_cnt; - virtual void anchor(); - - protected: - RefCountedBaseVPTR() : ref_cnt(0) {} - RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {} - - virtual ~RefCountedBaseVPTR() {} - - void Retain() const { ++ref_cnt; } - void Release() const { - assert (ref_cnt > 0 && "Reference count is already zero."); - if (--ref_cnt == 0) delete this; - } - - template - friend struct IntrusiveRefCntPtrInfo; - }; - - - template struct IntrusiveRefCntPtrInfo { - static void retain(T *obj) { obj->Retain(); } - static void release(T *obj) { obj->Release(); } - }; - -/// \brief A thread-safe version of \c llvm::RefCountedBase. +/// A CRTP mixin class that adds reference counting to a type. /// -/// A generic base class for objects that wish to have their lifetimes managed -/// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to -/// obtain such functionality, and are typically handled with -/// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the -/// management of reference counts. -template -class ThreadSafeRefCountedBase { +/// The lifetime of an object which inherits from RefCountedBase is managed by +/// calls to Release() and Retain(), which increment and decrement the object's +/// refcount, respectively. When a Release() call decrements the refcount to 0, +/// the object deletes itself. +/// +/// Objects that inherit from RefCountedBase should always be allocated with +/// operator new. +template class RefCountedBase { + mutable unsigned RefCount = 0; + +public: + RefCountedBase() = default; + RefCountedBase(const RefCountedBase &) : RefCount(0) {} + + void Retain() const { ++RefCount; } + void Release() const { + assert(RefCount > 0 && "Reference count is already zero."); + if (--RefCount == 0) + delete static_cast(this); + } +}; + +/// A thread-safe version of \c RefCountedBase. +template class ThreadSafeRefCountedBase { mutable std::atomic RefCount; protected: ThreadSafeRefCountedBase() : RefCount(0) {} public: - void Retain() const { ++RefCount; } + void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); } void Release() const { - int NewRefCount = --RefCount; + int NewRefCount = RefCount.fetch_sub(1, std::memory_order_acq_rel) - 1; assert(NewRefCount >= 0 && "Reference count was already zero."); if (NewRefCount == 0) - delete static_cast(this); + delete static_cast(this); } }; -//===----------------------------------------------------------------------===// -/// IntrusiveRefCntPtr - A template class that implements a "smart pointer" -/// that assumes the wrapped object has a reference count associated -/// with it that can be managed via calls to -/// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers -/// manage reference counts via the RAII idiom: upon creation of -/// smart pointer the reference count of the wrapped object is -/// incremented and upon destruction of the smart pointer the -/// reference count is decremented. This class also safely handles -/// wrapping NULL pointers. +/// Class you can specialize to provide custom retain/release functionality for +/// a type. /// -/// Reference counting is implemented via calls to -/// Obj->Retain()/Obj->Release(). Release() is required to destroy -/// the object when the reference count reaches zero. Inheriting from -/// RefCountedBase/RefCountedBaseVPTR takes care of this -/// automatically. -//===----------------------------------------------------------------------===// - template - class IntrusiveRefCntPtr { - T* Obj; +/// Usually specializing this class is not necessary, as IntrusiveRefCntPtr +/// works with any type which defines Retain() and Release() functions -- you +/// can define those functions yourself if RefCountedBase doesn't work for you. +/// +/// One case when you might want to specialize this type is if you have +/// - Foo.h defines type Foo and includes Bar.h, and +/// - Bar.h uses IntrusiveRefCntPtr in inline functions. +/// +/// Because Foo.h includes Bar.h, Bar.h can't include Foo.h in order to pull in +/// the declaration of Foo. Without the declaration of Foo, normally Bar.h +/// wouldn't be able to use IntrusiveRefCntPtr, which wants to call +/// T::Retain and T::Release. +/// +/// To resolve this, Bar.h could include a third header, FooFwd.h, which +/// forward-declares Foo and specializes IntrusiveRefCntPtrInfo. Then +/// Bar.h could use IntrusiveRefCntPtr, although it still couldn't call any +/// functions on Foo itself, because Foo would be an incomplete type. +template struct IntrusiveRefCntPtrInfo { + static void retain(T *obj) { obj->Retain(); } + static void release(T *obj) { obj->Release(); } +}; - public: - typedef T element_type; +/// A smart pointer to a reference-counted object that inherits from +/// RefCountedBase or ThreadSafeRefCountedBase. +/// +/// This class increments its pointee's reference count when it is created, and +/// decrements its refcount when it's destroyed (or is changed to point to a +/// different object). +template class IntrusiveRefCntPtr { + T *Obj = nullptr; - explicit IntrusiveRefCntPtr() : Obj(nullptr) {} +public: + typedef T element_type; - IntrusiveRefCntPtr(T* obj) : Obj(obj) { - retain(); - } + explicit IntrusiveRefCntPtr() = default; + IntrusiveRefCntPtr(T *obj) : Obj(obj) { retain(); } + IntrusiveRefCntPtr(const IntrusiveRefCntPtr &S) : Obj(S.Obj) { retain(); } + IntrusiveRefCntPtr(IntrusiveRefCntPtr &&S) : Obj(S.Obj) { S.Obj = nullptr; } - IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { - retain(); - } - - IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { - S.Obj = nullptr; - } - - template - IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.get()) { - S.Obj = nullptr; - } - - template - IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) - : Obj(S.get()) { - retain(); - } - - IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) { - swap(S); - return *this; - } - - ~IntrusiveRefCntPtr() { release(); } - - T& operator*() const { return *Obj; } - - T* operator->() const { return Obj; } - - T* get() const { return Obj; } - - explicit operator bool() const { return Obj; } - - void swap(IntrusiveRefCntPtr& other) { - T* tmp = other.Obj; - other.Obj = Obj; - Obj = tmp; - } - - void reset() { - release(); - Obj = nullptr; - } - - void resetWithoutRelease() { - Obj = nullptr; - } - - private: - void retain() { if (Obj) IntrusiveRefCntPtrInfo::retain(Obj); } - void release() { if (Obj) IntrusiveRefCntPtrInfo::release(Obj); } - - template - friend class IntrusiveRefCntPtr; - }; - - template - inline bool operator==(const IntrusiveRefCntPtr& A, - const IntrusiveRefCntPtr& B) - { - return A.get() == B.get(); + template + IntrusiveRefCntPtr(IntrusiveRefCntPtr &&S) : Obj(S.get()) { + S.Obj = nullptr; } - template - inline bool operator!=(const IntrusiveRefCntPtr& A, - const IntrusiveRefCntPtr& B) - { - return A.get() != B.get(); + template + IntrusiveRefCntPtr(const IntrusiveRefCntPtr &S) : Obj(S.get()) { + retain(); } - template - inline bool operator==(const IntrusiveRefCntPtr& A, - U* B) - { - return A.get() == B; + IntrusiveRefCntPtr &operator=(IntrusiveRefCntPtr S) { + swap(S); + return *this; } - template - inline bool operator!=(const IntrusiveRefCntPtr& A, - U* B) - { - return A.get() != B; + ~IntrusiveRefCntPtr() { release(); } + + T &operator*() const { return *Obj; } + T *operator->() const { return Obj; } + T *get() const { return Obj; } + explicit operator bool() const { return Obj; } + + void swap(IntrusiveRefCntPtr &other) { + T *tmp = other.Obj; + other.Obj = Obj; + Obj = tmp; } - template - inline bool operator==(T* A, - const IntrusiveRefCntPtr& B) - { - return A == B.get(); + void reset() { + release(); + Obj = nullptr; } - template - inline bool operator!=(T* A, - const IntrusiveRefCntPtr& B) - { - return A != B.get(); + void resetWithoutRelease() { Obj = nullptr; } + +private: + void retain() { + if (Obj) + IntrusiveRefCntPtrInfo::retain(Obj); + } + void release() { + if (Obj) + IntrusiveRefCntPtrInfo::release(Obj); } - template - bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr &B) { - return !B; + template friend class IntrusiveRefCntPtr; +}; + +template +inline bool operator==(const IntrusiveRefCntPtr &A, + const IntrusiveRefCntPtr &B) { + return A.get() == B.get(); +} + +template +inline bool operator!=(const IntrusiveRefCntPtr &A, + const IntrusiveRefCntPtr &B) { + return A.get() != B.get(); +} + +template +inline bool operator==(const IntrusiveRefCntPtr &A, U *B) { + return A.get() == B; +} + +template +inline bool operator!=(const IntrusiveRefCntPtr &A, U *B) { + return A.get() != B; +} + +template +inline bool operator==(T *A, const IntrusiveRefCntPtr &B) { + return A == B.get(); +} + +template +inline bool operator!=(T *A, const IntrusiveRefCntPtr &B) { + return A != B.get(); +} + +template +bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr &B) { + return !B; +} + +template +bool operator==(const IntrusiveRefCntPtr &A, std::nullptr_t B) { + return B == A; +} + +template +bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr &B) { + return !(A == B); +} + +template +bool operator!=(const IntrusiveRefCntPtr &A, std::nullptr_t B) { + return !(A == B); +} + +// Make IntrusiveRefCntPtr work with dyn_cast, isa, and the other idioms from +// Casting.h. +template struct simplify_type; + +template struct simplify_type> { + typedef T *SimpleType; + static SimpleType getSimplifiedValue(IntrusiveRefCntPtr &Val) { + return Val.get(); } +}; - template - bool operator==(const IntrusiveRefCntPtr &A, std::nullptr_t B) { - return B == A; +template struct simplify_type> { + typedef /*const*/ T *SimpleType; + static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr &Val) { + return Val.get(); } - - template - bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr &B) { - return !(A == B); - } - - template - bool operator!=(const IntrusiveRefCntPtr &A, std::nullptr_t B) { - return !(A == B); - } - -//===----------------------------------------------------------------------===// -// LLVM-style downcasting support for IntrusiveRefCntPtr objects -//===----------------------------------------------------------------------===// - - template struct simplify_type; - - template struct simplify_type > { - typedef T* SimpleType; - static SimpleType getSimplifiedValue(IntrusiveRefCntPtr& Val) { - return Val.get(); - } - }; - - template struct simplify_type > { - typedef /*const*/ T* SimpleType; - static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr& Val) { - return Val.get(); - } - }; +}; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/ADT/MapVector.h b/contrib/llvm/include/llvm/ADT/MapVector.h index f19a50b7ba84..ac1885758cb9 100644 --- a/contrib/llvm/include/llvm/ADT/MapVector.h +++ b/contrib/llvm/include/llvm/ADT/MapVector.h @@ -30,6 +30,7 @@ template, typename VectorType = std::vector > > class MapVector { + typedef typename VectorType::value_type value_type; typedef typename VectorType::size_type size_type; MapType Map; @@ -41,6 +42,12 @@ public: typedef typename VectorType::reverse_iterator reverse_iterator; typedef typename VectorType::const_reverse_iterator const_reverse_iterator; + /// Clear the MapVector and return the underlying vector. + VectorType takeVector() { + Map.clear(); + return std::move(Vector); + } + size_type size() const { return Vector.size(); } iterator begin() { return Vector.begin(); } @@ -83,7 +90,10 @@ public: return Vector[I].second; } + // Returns a copy of the value. Only allowed if ValueT is copyable. ValueT lookup(const KeyT &Key) const { + static_assert(std::is_copy_constructible::value, + "Cannot call lookup() if ValueT is not copyable."); typename MapType::const_iterator Pos = Map.find(Key); return Pos == Map.end()? ValueT() : Vector[Pos->second].second; } @@ -100,6 +110,19 @@ public: return std::make_pair(begin() + I, false); } + std::pair insert(std::pair &&KV) { + // Copy KV.first into the map, then move it into the vector. + std::pair Pair = std::make_pair(KV.first, 0); + std::pair Result = Map.insert(Pair); + unsigned &I = Result.first->second; + if (Result.second) { + Vector.push_back(std::move(KV)); + I = Vector.size() - 1; + return std::make_pair(std::prev(end()), true); + } + return std::make_pair(begin() + I, false); + } + size_type count(const KeyT &Key) const { typename MapType::const_iterator Pos = Map.find(Key); return Pos == Map.end()? 0 : 1; diff --git a/contrib/llvm/include/llvm/ADT/Optional.h b/contrib/llvm/include/llvm/ADT/Optional.h index d9acaf6d23b0..701872c9f63f 100644 --- a/contrib/llvm/include/llvm/ADT/Optional.h +++ b/contrib/llvm/include/llvm/ADT/Optional.h @@ -129,7 +129,7 @@ public: T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } template - LLVM_CONSTEXPR T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION { + constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION { return hasValue() ? getValue() : std::forward(value); } @@ -150,18 +150,43 @@ template struct isPodLike > { static const bool value = isPodLike::value; }; -/// \brief Poison comparison between two \c Optional objects. Clients needs to -/// explicitly compare the underlying values and account for empty \c Optional -/// objects. -/// -/// This routine will never be defined. It returns \c void to help diagnose -/// errors at compile time. -template -void operator==(const Optional &X, const Optional &Y); +template +bool operator==(const Optional &X, const Optional &Y) { + if (X && Y) + return *X == *Y; + return X.hasValue() == Y.hasValue(); +} + +template +bool operator!=(const Optional &X, const Optional &Y) { + return !(X == Y); +} + +template +bool operator<(const Optional &X, const Optional &Y) { + if (X && Y) + return *X < *Y; + return X.hasValue() < Y.hasValue(); +} + +template +bool operator<=(const Optional &X, const Optional &Y) { + return !(Y < X); +} + +template +bool operator>(const Optional &X, const Optional &Y) { + return Y < X; +} + +template +bool operator>=(const Optional &X, const Optional &Y) { + return !(X < Y); +} template bool operator==(const Optional &X, NoneType) { - return !X.hasValue(); + return !X; } template @@ -178,50 +203,86 @@ template bool operator!=(NoneType, const Optional &X) { return X != None; } -/// \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 -void operator!=(const Optional &X, const Optional &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 -void operator<(const Optional &X, const Optional &Y); +template bool operator<(const Optional &X, NoneType) { + return false; +} -/// \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 -void operator<=(const Optional &X, const Optional &Y); +template bool operator<(NoneType, const Optional &X) { + return X.hasValue(); +} -/// \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 -void operator>=(const Optional &X, const Optional &Y); +template bool operator<=(const Optional &X, NoneType) { + return !(None < X); +} -/// \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 -void operator>(const Optional &X, const Optional &Y); +template bool operator<=(NoneType, const Optional &X) { + return !(X < None); +} + +template bool operator>(const Optional &X, NoneType) { + return None < X; +} + +template bool operator>(NoneType, const Optional &X) { + return X < None; +} + +template bool operator>=(const Optional &X, NoneType) { + return None <= X; +} + +template bool operator>=(NoneType, const Optional &X) { + return X <= None; +} + +template bool operator==(const Optional &X, const T &Y) { + return X && *X == Y; +} + +template bool operator==(const T &X, const Optional &Y) { + return Y && X == *Y; +} + +template bool operator!=(const Optional &X, const T &Y) { + return !(X == Y); +} + +template bool operator!=(const T &X, const Optional &Y) { + return !(X == Y); +} + +template bool operator<(const Optional &X, const T &Y) { + return !X || *X < Y; +} + +template bool operator<(const T &X, const Optional &Y) { + return Y && X < *Y; +} + +template bool operator<=(const Optional &X, const T &Y) { + return !(Y < X); +} + +template bool operator<=(const T &X, const Optional &Y) { + return !(Y < X); +} + +template bool operator>(const Optional &X, const T &Y) { + return Y < X; +} + +template bool operator>(const T &X, const Optional &Y) { + return Y < X; +} + +template bool operator>=(const Optional &X, const T &Y) { + return !(X < Y); +} + +template bool operator>=(const T &X, const Optional &Y) { + return !(X < Y); +} } // end llvm namespace diff --git a/contrib/llvm/include/llvm/ADT/PackedVector.h b/contrib/llvm/include/llvm/ADT/PackedVector.h index 09267173fd77..8f925f1ff5cb 100644 --- a/contrib/llvm/include/llvm/ADT/PackedVector.h +++ b/contrib/llvm/include/llvm/ADT/PackedVector.h @@ -15,6 +15,7 @@ #define LLVM_ADT_PACKEDVECTOR_H #include "llvm/ADT/BitVector.h" +#include #include namespace llvm { @@ -83,14 +84,15 @@ public: PackedVector &Vec; const unsigned Idx; - reference(); // Undefined public: + reference() = delete; reference(PackedVector &vec, unsigned idx) : Vec(vec), Idx(idx) {} reference &operator=(T val) { Vec.setValue(Vec.Bits, Idx, val); return *this; } + operator T() const { return Vec.getValue(Vec.Bits, Idx); } @@ -144,6 +146,6 @@ public: // Leave BitNum=0 undefined. template class PackedVector; -} // end llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_ADT_PACKEDVECTOR_H diff --git a/contrib/llvm/include/llvm/ADT/PointerSumType.h b/contrib/llvm/include/llvm/ADT/PointerSumType.h index 6b8618fc5a17..005b1c645c93 100644 --- a/contrib/llvm/include/llvm/ADT/PointerSumType.h +++ b/contrib/llvm/include/llvm/ADT/PointerSumType.h @@ -54,7 +54,7 @@ struct PointerSumTypeHelper; /// /// It also default constructs to a zero tag with a null pointer, whatever that /// would be. This means that the zero value for the tag type is significant -/// and may be desireable to set to a state that is particularly desirable to +/// and may be desirable to set to a state that is particularly desirable to /// default construct. /// /// There is no support for constructing or accessing with a dynamic tag as diff --git a/contrib/llvm/include/llvm/ADT/PointerUnion.h b/contrib/llvm/include/llvm/ADT/PointerUnion.h index 6b3fe5749ad5..a8ac18645f3a 100644 --- a/contrib/llvm/include/llvm/ADT/PointerUnion.h +++ b/contrib/llvm/include/llvm/ADT/PointerUnion.h @@ -17,7 +17,10 @@ #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/Support/Compiler.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include +#include +#include namespace llvm { @@ -57,6 +60,7 @@ template class PointerUnionUIntTraits { public: static inline void *getAsVoidPointer(void *P) { return P; } static inline void *getFromVoidPointer(void *P) { return P; } + enum { PT1BitsAv = (int)(PointerLikeTypeTraits::NumLowBitsAvailable), PT2BitsAv = (int)(PointerLikeTypeTraits::NumLowBitsAvailable), @@ -97,7 +101,7 @@ private: template struct UNION_DOESNT_CONTAIN_TYPE {}; public: - PointerUnion() {} + PointerUnion() = default; PointerUnion(PT1 V) : Val(const_cast( @@ -208,6 +212,7 @@ public: static inline void *getAsVoidPointer(const PointerUnion &P) { return P.getOpaqueValue(); } + static inline PointerUnion getFromVoidPointer(void *P) { return PointerUnion::getFromOpaqueValue(P); } @@ -249,7 +254,7 @@ private: }; public: - PointerUnion3() {} + PointerUnion3() = default; PointerUnion3(PT1 V) { Val = InnerUnion(V); } PointerUnion3(PT2 V) { Val = InnerUnion(V); } @@ -328,6 +333,7 @@ public: static inline void *getAsVoidPointer(const PointerUnion3 &P) { return P.getOpaqueValue(); } + static inline PointerUnion3 getFromVoidPointer(void *P) { return PointerUnion3::getFromOpaqueValue(P); } @@ -352,7 +358,7 @@ private: ValTy Val; public: - PointerUnion4() {} + PointerUnion4() = default; PointerUnion4(PT1 V) { Val = InnerUnion1(V); } PointerUnion4(PT2 V) { Val = InnerUnion1(V); } @@ -435,6 +441,7 @@ public: getAsVoidPointer(const PointerUnion4 &P) { return P.getOpaqueValue(); } + static inline PointerUnion4 getFromVoidPointer(void *P) { return PointerUnion4::getFromOpaqueValue(P); } @@ -469,6 +476,6 @@ template struct DenseMapInfo> { } }; -} +} // end namespace llvm -#endif +#endif // LLVM_ADT_POINTERUNION_H diff --git a/contrib/llvm/include/llvm/ADT/PostOrderIterator.h b/contrib/llvm/include/llvm/ADT/PostOrderIterator.h index 0cc504b5c39e..e519b5c07964 100644 --- a/contrib/llvm/include/llvm/ADT/PostOrderIterator.h +++ b/contrib/llvm/include/llvm/ADT/PostOrderIterator.h @@ -17,9 +17,12 @@ #define LLVM_ADT_POSTORDERITERATOR_H #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallPtrSet.h" +#include #include +#include #include namespace llvm { @@ -54,22 +57,23 @@ namespace llvm { template class po_iterator_storage { SetType Visited; + public: // Return true if edge destination should be visited. - template - bool insertEdge(NodeType *From, NodeType *To) { + template + bool insertEdge(Optional From, NodeRef To) { return Visited.insert(To).second; } // Called after all children of BB have been visited. - template - void finishPostorder(NodeType *BB) {} + template void finishPostorder(NodeRef BB) {} }; /// Specialization of po_iterator_storage that references an external set. template class po_iterator_storage { SetType &Visited; + public: po_iterator_storage(SetType &VSet) : Visited(VSet) {} po_iterator_storage(const po_iterator_storage &S) : Visited(S.Visited) {} @@ -77,51 +81,50 @@ public: // Return true if edge destination should be visited, called with From = 0 for // the root node. // Graph edges can be pruned by specializing this function. - template bool insertEdge(NodeType *From, NodeType *To) { + template bool insertEdge(Optional From, NodeRef To) { return Visited.insert(To).second; } // Called after all children of BB have been visited. - template - void finishPostorder(NodeType *BB) {} + template void finishPostorder(NodeRef BB) {} }; -template::NodeType*, 8>, - bool ExtStorage = false, - class GT = GraphTraits > -class po_iterator : public std::iterator, - public po_iterator_storage { - typedef std::iterator super; - typedef typename GT::NodeType NodeType; +template ::NodeRef, 8>, + bool ExtStorage = false, class GT = GraphTraits> +class po_iterator + : public std::iterator, + public po_iterator_storage { + typedef std::iterator super; + typedef typename GT::NodeRef NodeRef; typedef typename GT::ChildIteratorType ChildItTy; // VisitStack - Used to maintain the ordering. Top = current block // First element is basic block pointer, second is the 'next child' to visit - std::vector > VisitStack; + std::vector> VisitStack; void traverseChild() { while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) { - NodeType *BB = *VisitStack.back().second++; - if (this->insertEdge(VisitStack.back().first, BB)) { + NodeRef BB = *VisitStack.back().second++; + if (this->insertEdge(Optional(VisitStack.back().first), BB)) { // If the block is not visited... VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); } } } - po_iterator(NodeType *BB) { - this->insertEdge((NodeType*)nullptr, BB); + po_iterator(NodeRef BB) { + this->insertEdge(Optional(), BB); VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); traverseChild(); } - po_iterator() {} // End is when stack is empty. - po_iterator(NodeType *BB, SetType &S) + po_iterator() = default; // End is when stack is empty. + + po_iterator(NodeRef BB, SetType &S) : po_iterator_storage(S) { - if (this->insertEdge((NodeType*)nullptr, BB)) { + if (this->insertEdge(Optional(), BB)) { VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); traverseChild(); } @@ -130,6 +133,7 @@ class po_iterator : public std::iterator(S) { } // End is when stack is empty. + public: typedef typename super::pointer pointer; @@ -149,13 +153,13 @@ public: } bool operator!=(const po_iterator &x) const { return !(*this == x); } - pointer operator*() const { return VisitStack.back().first; } + const NodeRef &operator*() const { return VisitStack.back().first; } // This is a nonstandard operator-> that dereferences the pointer an extra // time... so that you can actually call methods ON the BasicBlock, because // the contained type is a pointer. This allows BBIt->getTerminator() f.e. // - NodeType *operator->() const { return **this; } + NodeRef operator->() const { return **this; } po_iterator &operator++() { // Preincrement this->finishPostorder(VisitStack.back().first); @@ -184,7 +188,7 @@ template iterator_range> post_order(const T &G) { } // Provide global definitions of external postorder iterators... -template::NodeType*> > +template ::NodeRef>> struct po_ext_iterator : public po_iterator { po_ext_iterator(const po_iterator &V) : po_iterator(V) {} @@ -206,10 +210,9 @@ iterator_range> post_order_ext(const T &G, SetType & } // Provide global definitions of inverse post order iterators... -template ::NodeType*>, +template ::NodeRef>, bool External = false> -struct ipo_iterator : public po_iterator, SetType, External > { +struct ipo_iterator : public po_iterator, SetType, External> { ipo_iterator(const po_iterator, SetType, External> &V) : po_iterator, SetType, External> (V) {} }; @@ -230,8 +233,7 @@ iterator_range> inverse_post_order(const T &G) { } // Provide global definitions of external inverse postorder iterators... -template ::NodeType*> > +template ::NodeRef>> struct ipo_ext_iterator : public ipo_iterator { ipo_ext_iterator(const ipo_iterator &V) : ipo_iterator(V) {} @@ -278,15 +280,17 @@ inverse_post_order_ext(const T &G, SetType &S) { // } // -template > +template> class ReversePostOrderTraversal { - typedef typename GT::NodeType NodeType; - std::vector Blocks; // Block list in normal PO order - void Initialize(NodeType *BB) { + typedef typename GT::NodeRef NodeRef; + std::vector Blocks; // Block list in normal PO order + + void Initialize(NodeRef BB) { std::copy(po_begin(BB), po_end(BB), std::back_inserter(Blocks)); } + public: - typedef typename std::vector::reverse_iterator rpo_iterator; + typedef typename std::vector::reverse_iterator rpo_iterator; ReversePostOrderTraversal(GraphT G) { Initialize(GT::getEntryNode(G)); } @@ -295,6 +299,6 @@ public: rpo_iterator end() { return Blocks.rend(); } }; -} // End llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_ADT_POSTORDERITERATOR_H diff --git a/contrib/llvm/include/llvm/ADT/PriorityQueue.h b/contrib/llvm/include/llvm/ADT/PriorityQueue.h index 827d0b346e59..8ba871e25304 100644 --- a/contrib/llvm/include/llvm/ADT/PriorityQueue.h +++ b/contrib/llvm/include/llvm/ADT/PriorityQueue.h @@ -46,8 +46,7 @@ public: /// void erase_one(const T &t) { // Linear-search to find the element. - typename Sequence::size_type i = - std::find(this->c.begin(), this->c.end(), t) - this->c.begin(); + typename Sequence::size_type i = find(this->c, t) - this->c.begin(); // Logarithmic-time heap bubble-up. while (i != 0) { diff --git a/contrib/llvm/include/llvm/ADT/PriorityWorklist.h b/contrib/llvm/include/llvm/ADT/PriorityWorklist.h index 00549b88fd02..c0b4709e98f8 100644 --- a/contrib/llvm/include/llvm/ADT/PriorityWorklist.h +++ b/contrib/llvm/include/llvm/ADT/PriorityWorklist.h @@ -17,10 +17,12 @@ #define LLVM_ADT_PRIORITYWORKLIST_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Compiler.h" #include #include -#include +#include #include namespace llvm { @@ -59,7 +61,7 @@ public: typedef typename MapT::size_type size_type; /// Construct an empty PriorityWorklist - PriorityWorklist() {} + PriorityWorklist() = default; /// Determine if the PriorityWorklist is empty or not. bool empty() const { @@ -115,7 +117,7 @@ public: } while (!V.empty() && V.back() == T()); } - T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { + LLVM_NODISCARD T pop_back_val() { T Ret = back(); pop_back(); return Ret; @@ -147,7 +149,7 @@ public: /// write it: /// /// \code - /// V.erase(std::remove_if(V.begin(), V.end(), P), V.end()); + /// V.erase(remove_if(V, P), V.end()); /// \endcode /// /// However, PriorityWorklist doesn't expose non-const iterators, making any @@ -156,8 +158,8 @@ public: /// \returns true if any element is removed. template bool erase_if(UnaryPredicate P) { - typename VectorT::iterator E = std::remove_if( - V.begin(), V.end(), TestAndEraseFromMap(P, M)); + typename VectorT::iterator E = + remove_if(V, TestAndEraseFromMap(P, M)); if (E == V.end()) return false; for (auto I = V.begin(); I != E; ++I) @@ -216,9 +218,9 @@ class SmallPriorityWorklist : public PriorityWorklist, SmallDenseMap> { public: - SmallPriorityWorklist() {} + SmallPriorityWorklist() = default; }; -} +} // end namespace llvm -#endif +#endif // LLVM_ADT_PRIORITYWORKLIST_H diff --git a/contrib/llvm/include/llvm/ADT/SCCIterator.h b/contrib/llvm/include/llvm/ADT/SCCIterator.h index e89345c0f348..9a8a7b168fce 100644 --- a/contrib/llvm/include/llvm/ADT/SCCIterator.h +++ b/contrib/llvm/include/llvm/ADT/SCCIterator.h @@ -26,6 +26,9 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/iterator.h" +#include +#include +#include #include namespace llvm { @@ -93,7 +96,7 @@ class scc_iterator : public iterator_facade_base< } /// End is when the DFS stack is empty. - scc_iterator() {} + scc_iterator() = default; public: static scc_iterator begin(const GraphT &G) { @@ -230,15 +233,15 @@ template scc_iterator scc_end(const T &G) { } /// \brief Construct the begin iterator for a deduced graph type T's Inverse. -template scc_iterator > scc_begin(const Inverse &G) { - return scc_iterator >::begin(G); +template scc_iterator> scc_begin(const Inverse &G) { + return scc_iterator>::begin(G); } /// \brief Construct the end iterator for a deduced graph type T's Inverse. -template scc_iterator > scc_end(const Inverse &G) { - return scc_iterator >::end(G); +template scc_iterator> scc_end(const Inverse &G) { + return scc_iterator>::end(G); } -} // End llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_ADT_SCCITERATOR_H diff --git a/contrib/llvm/include/llvm/ADT/STLExtras.h b/contrib/llvm/include/llvm/ADT/STLExtras.h index 00b796f63818..ec121e0d55cd 100644 --- a/contrib/llvm/include/llvm/ADT/STLExtras.h +++ b/contrib/llvm/include/llvm/ADT/STLExtras.h @@ -24,18 +24,25 @@ #include #include #include +#include #include // for std::pair #include "llvm/ADT/Optional.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" namespace llvm { + +// Only used by compiler if both template types are the same. Useful when +// using SFINAE to test for the existence of member functions. +template struct SameType; + namespace detail { template -using IterOfRange = decltype(std::begin(std::declval())); +using IterOfRange = decltype(std::begin(std::declval())); } // End detail namespace @@ -208,11 +215,24 @@ inline mapped_iterator map_iterator(const ItTy &I, FuncTy F) { return mapped_iterator(I, F); } -/// \brief Metafunction to determine if type T has a member called rbegin(). -template struct has_rbegin { - template static char(&f(const U &, decltype(&U::rbegin)))[1]; - static char(&f(...))[2]; - const static bool value = sizeof(f(std::declval(), nullptr)) == 1; +/// Helper to determine if type T has a member called rbegin(). +template class has_rbegin_impl { + typedef char yes[1]; + typedef char no[2]; + + template + static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr); + + template + static no& test(...); + +public: + static const bool value = sizeof(test(nullptr)) == sizeof(yes); +}; + +/// Metafunction to determine if T& or T has a member called rbegin(). +template +struct has_rbegin : has_rbegin_impl::type> { }; // Returns an iterator_range over the given container which iterates in reverse. @@ -327,6 +347,240 @@ make_filter_range(RangeT &&Range, PredicateT Pred) { FilterIteratorT(std::end(std::forward(Range)))); } +// forward declarations required by zip_shortest/zip_first +template +bool all_of(R &&range, UnaryPredicate P); + +template struct index_sequence; + +template struct index_sequence_for; + +namespace detail { +template class zip_first { +public: + typedef std::input_iterator_tag iterator_category; + typedef std::tuple())...> value_type; + std::tuple iterators; + +private: + template value_type deres(index_sequence) { + return value_type(*std::get(iterators)...); + } + + template decltype(iterators) tup_inc(index_sequence) { + return std::tuple(std::next(std::get(iterators))...); + } + +public: + value_type operator*() { return deres(index_sequence_for{}); } + + void operator++() { iterators = tup_inc(index_sequence_for{}); } + + bool operator!=(const zip_first &other) const { + return std::get<0>(iterators) != std::get<0>(other.iterators); + } + zip_first(Iters &&... ts) : iterators(std::forward(ts)...) {} +}; + +template class zip_shortest : public zip_first { + template + bool test(const zip_first &other, index_sequence) const { + return all_of(std::initializer_list{std::get(this->iterators) != + std::get(other.iterators)...}, + identity{}); + } + +public: + bool operator!=(const zip_first &other) const { + return test(other, index_sequence_for{}); + } + zip_shortest(Iters &&... ts) + : zip_first(std::forward(ts)...) {} +}; + +template